diff --git a/src/App.js b/src/App.js
index 70955ed..7f95fc2 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,7 +4,7 @@ import React, {useState,useEffect,useReducer} from 'react';
import Toggle from 'react-toggle' //Tooltip props: http://aaronshaf.github.io/react-toggle/
import Helmet from 'react-helmet'
-import {XSquareFill, PlusCircle, LifePreserver, Server, CloudUploadFill} from 'react-bootstrap-icons'
+import {TrashFill, PlusCircle, LifePreserver, Server, CloudUploadFill} from 'react-bootstrap-icons'
import { SkillTreeEditor } from './skilltree/skillTreeEditor'
@@ -57,11 +57,11 @@ function Box(p) {
}
function Table(p) {
- return
+ return
{p.children}
-
+
}
function InputBox(p) {
@@ -93,20 +93,22 @@ function InputBox(p) {
return p.data?:{keydownFunc(f)}} onChange={(f)=>{changeFunc(f)}} onBlur={(f)=>{blurFunc(f)}}/>
}
function TableEditor(p) {
const initialVals={}
+
+ const { TESTMODE } = p
function updateVals(state,update) {
if (update==='Clear') {
return initialVals
}
state[update.field]=update.value
- return state
+ return state
}
const [fields,setFields] = useState([])
@@ -116,7 +118,6 @@ function TableEditor(p) {
const [loading,setLoading] = useState(false)
const [dependencies,setDependencies] = useState([])
const [importAllowed,setImportAllowed] = useState(false)
- const [fileData,setFileData] = useState(undefined)
const [lockSubmission,setLockSubmission] = useState(false)
function patchValue(value,p,col,dat) {
@@ -143,26 +144,30 @@ function TableEditor(p) {
})
}
}
-
- useEffect(()=>{
- setUpdate(true)
- },[p.path])
- useEffect(()=>{
- var promises=[]
- parse(fileData,{columns:true,skip_empty_lines:true}).forEach((entry)=>{
- for (var col of fields) {
- if ((col.dataTypeID===23||col.dataTypeID===701||col.dataTypeID===16)&&entry[col.name]==="") {
- entry[col.name]=0
+ function SubmitDeletion() {
+ if (!lockSubmission) {
+ setLockSubmission(true)
+ var promises = []
+ for (var dat of data) {
+ if (document.getElementById("delete_"+dat.id).checked) {
+ promises.push(axios.delete(p.BACKENDURL+p.path,{data:{pass:p.password,id:dat.id}}))
}
}
- promises.push(axios.post(p.BACKENDURL+p.path,{...entry,pass:p.password}))
- })
- Promise.allSettled(promises)
- .then(()=>{
- setUpdate(true)
- })
- },[fileData,p.path,p.BACKENDURL,p.password])
+ Promise.allSettled(promises)
+ .catch((err)=>{
+ alert(err.message)
+ })
+ .then((data)=>{
+ setLockSubmission(false)
+ setUpdate(true)
+ })
+ }
+ }
+
+ useEffect(()=>{
+ setUpdate(true)
+ },[p.path,TESTMODE])
useEffect(()=>{
for (var col of fields) {
@@ -207,24 +212,36 @@ function TableEditor(p) {
{!loading?
- {importAllowed&&{
+ {importAllowed&&{
const reader = new FileReader()
reader.onload=(ev)=>{
- setFileData(ev.target.result)
+ var promises=[]
+ parse(ev.target.result,{columns:true,skip_empty_lines:true}).forEach((entry)=>{
+ for (var col of fields) {
+ if ((col.dataTypeID===23||col.dataTypeID===701||col.dataTypeID===16)&&entry[col.name]==="") {
+ entry[col.name]=0
+ }
+ }
+ promises.push(axios.post(p.BACKENDURL+p.path,{...entry,pass:p.password}))
+ })
+ Promise.allSettled(promises)
+ .then(()=>{
+ setUpdate(true)
+ })
}
reader.readAsText(f.target.files[0])
}} style={{opacity:0}} id="uploads" type="file" accept=".txt,.csv"/>}
- |
+ {SubmitDeletion()}} className="trashButton"/> |
{fields.map((field,i)=>{field.name} | )}
{ | {fields.map((col,i)=>{{setSubmitVal({field:col.name,value:f});}}/>} | )}{SubmitBoxes()}} className="submitbutton"/>
}
+ (f)=>{setSubmitVal({field:col.name,value:f});}}/>})}{SubmitBoxes()}} className="submitbutton"/> | }
{data.map((dat)=>
- {axios.delete(p.BACKENDURL+p.path,{data:{id:dat.id,pass:p.password}}).then(()=>{setUpdate(true)}).catch((err)=>{alert(err.response.data)})}}/> | {fields.map((col,i)=>
+ | | {fields.map((col,i)=>
patchValue(value,p,col,dat)} callback2={(f,value)=>{if (f.key==='Enter') {f.currentTarget.blur()} else {return 'Chill'}}} value={String(dat[col.name])}/> | )}
)}
@@ -306,13 +323,13 @@ function DatabaseEditor(p) {
Live Database
Test Database
- {databases.map((db)=>{
+ {databases.map((db,i)=>{
var label = ""
if (db.datname!=="ngsplanner"&&db.datname!=="ngsplanner2") {
var dateStr = db.datname.replace("ngsplanner","")
var date = new Date(dateStr.slice(0,4),dateStr.slice(4,6),dateStr.slice(6,8),dateStr.slice(8,10),dateStr.slice(10,12),dateStr.slice(12,14))
label=<>
{"Backup from "+date}>
- return <>{label}
} else {
- return <>>
+ return
}
})}
>
@@ -413,10 +430,10 @@ function AdminPanel(p) {
Navigation
- Testing Mode {p.setTESTMODE(f.target.checked)}}/> {p.TESTMODE?ON:OFF}
+ Testing Mode {p.setTESTMODE(f.target.checked)}}/> {p.TESTMODE?ON:OFF}
- {navigationData.map((nav)=>(nav.hr)?
:<>{nav.page}
>)}
+ {navigationData.map((nav,i)=>(nav.hr)?
:{nav.page}
)}
Database Manager
@@ -425,7 +442,7 @@ function AdminPanel(p) {
- {navigationData.map((nav)=>(nav.duplicate===undefined&&nav.hr===undefined)&&
+ {navigationData.map((nav,i)=>(nav.duplicate===undefined&&nav.hr===undefined)&&
{nav.page}
@@ -433,7 +450,7 @@ function AdminPanel(p) {
{APP_TITLE+" - Admin Panel: "+nav.page}
- {nav.render??
}
+ {nav.render??}
)}
@@ -790,8 +807,6 @@ function App() {
const [DATAID,setDATAID] = useState({GetData:()=>{}})
const [update,setUpdate] = useState(false)
- const [dataLoaded,setDataLoaded] = useState(false)
-
const [LOGGEDINUSER,setLOGGEDINUSER] = useState("")
const [LOGGEDINHASH,setLOGGEDINHASH] = useState("")
diff --git a/src/TestPanel.js b/src/TestPanel.js
index 37a1d31..0d881c5 100644
--- a/src/TestPanel.js
+++ b/src/TestPanel.js
@@ -74,7 +74,7 @@ function EditableClass(p){
function PopupWindow(p) {
- return {p.setModalOpen(false)}} shouldFocusAfterRender={true} shouldCloseOnOverlayClick={true} shouldCloseOnEsc={true} className="modal" overlayClassName="modalOverlay">
+ return {p.setModalOpen(false)}} shouldFocusAfterRender={true} shouldCloseOnOverlayClick={true} shouldCloseOnEsc={true} className="modal" overlayClassName="modalOverlay">
{p.title}
@@ -117,7 +117,7 @@ function SelectorWindow(p) {
{(p.sortItems||p.filter)&&
{p.sortItems&&}
@@ -127,7 +127,7 @@ function SelectorWindow(p) {
}
- {p.filter?itemList.filter((item)=>p.filterFunction(tabPage,item)).filter((item)=>p.searchFieldFunction(filter,item)).sort((a,b)=>p.sortOrderFunction(sortSelector,a,b)).map((item)=>p.displayFunction(item)):itemList.map((item)=>p.displayFunction(item))}
+ {p.filter?itemList.filter((item)=>p.filterFunction(tabPage,item)).filter((item)=>p.searchFieldFunction(filter,item)).sort((a,b)=>p.sortOrderFunction(sortSelector,a,b)).map((item,i)=>{p.displayFunction(item)}):itemList.map((item,i)=>{p.displayFunction(item)})}
{p.children}
@@ -230,7 +230,7 @@ function SkillTreeBoxes(p) {
return <>
{p.skillTreeSkillData&&p.skillTreeSkillData.map((skill,i)=>{
var splitter = skill.split(",")
- return splitter[0]!==""&&splitter[1]!==""&&splitter[2]!==""&&
0?"skillActive":""} boxId={i} skillPointData={p.skillPointData} setSkillPointData={p.setSkillPointData} page={p.page} cl={p.cl} maxPoints={GetHighestLevel(splitter[2])} points={p.points} setPoints={p.setPoints} GetData={p.GetData} skill={splitter.map((numb)=>Number(numb))}/>
+ return splitter[0]!==""&&splitter[1]!==""&&splitter[2]!==""&&0?"skillActive":""} boxId={i} skillPointData={p.skillPointData} setSkillPointData={p.setSkillPointData} page={p.page} cl={p.cl} maxPoints={GetHighestLevel(splitter[2])} points={p.points} setPoints={p.setPoints} GetData={p.GetData} skill={splitter.map((numb)=>Number(numb))}/>
})}
>
}
@@ -593,7 +593,7 @@ AUGMENT
- { setClassSkillTreeWindowOpen(false) }} shouldFocusAfterRender={true} shouldCloseOnOverlayClick={true} shouldCloseOnEsc={true} className="modal" overlayClassName="modalOverlay">
+ { setClassSkillTreeWindowOpen(false) }} shouldFocusAfterRender={true} shouldCloseOnOverlayClick={true} shouldCloseOnEsc={true} className="modal" overlayClassName="modalOverlay">
Class Skill Tree
@@ -647,7 +647,7 @@ AUGMENT
}
}}
displayFunction={(item)=>{
- return
{setSelectedWeapon(item);setWeaponSelectWindowOpen(false)}}>{GetSpecialWeaponName(item)}
{item[WEAPON_WEAPON].atk} {item[WEAPON_POTENTIAL_TOOLTIP].map((pot,i)=><>{(i!==0)&&
}{pot.name}: {pot.description?pot.description.split("\\n").map((it)=><>{it}
>):<>>}>)}>}>
+ return {setSelectedWeapon(item);setWeaponSelectWindowOpen(false)}}>{GetSpecialWeaponName(item)}
{item[WEAPON_WEAPON].atk} {item[WEAPON_POTENTIAL_TOOLTIP].map((pot,i)=>{(i!==0)&&
}{pot.name}: {pot.description?pot.description.split("\\n").map((it,ii)=>{it}
):})}>}>
{item[WEAPON_POTENTIAL].name}
}}
/>
diff --git a/src/skilltree/skillTree.js b/src/skilltree/skillTree.js
index 57fe430..be9ba50 100644
--- a/src/skilltree/skillTree.js
+++ b/src/skilltree/skillTree.js
@@ -36,7 +36,7 @@ function SkillTree(p) {
case "┬":context.beginPath();context.moveTo(x*p.gridSizeX+(padX)-p.gridPaddingX,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+p.gridSizeY+p.gridPaddingY);context.stroke();context.beginPath();context.moveTo(x*p.gridSizeX+(padX)+p.gridSizeX+p.gridPaddingX,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+p.gridSizeY+p.gridPaddingY);context.stroke();break;
case "┴":context.beginPath();context.moveTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)-p.gridPaddingY);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX+p.gridPaddingX,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.stroke();context.beginPath();context.moveTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)-p.gridPaddingY);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.lineTo(x*p.gridSizeX+(padX)-p.gridPaddingX,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.stroke();break;
case "┼":context.beginPath();context.moveTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)-p.gridPaddingY);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX/2,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+p.gridSizeY+p.gridPaddingY);context.moveTo(x*p.gridSizeX+(padX)-p.gridPaddingX,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.lineTo(x*p.gridSizeX+(padX)+p.gridSizeX+p.gridPaddingX,Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY)+(y%2===1?p.halflineheight:p.gridSizeY)/2);context.stroke();break;
- case "□":context.fillRect(x*p.gridSizeX+(padX), Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY), p.gridSizeX, y%2===1?p.halflineheight:p.gridSizeY);break;
+ case "□":context.clearRect(x*p.gridSizeX+(padX), Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY), p.gridSizeX, y%2===1?p.halflineheight:p.gridSizeY);context.fillRect(x*p.gridSizeX+(padX), Math.ceil(y/2)*p.gridSizeY+Math.ceil((y-1)/2)*p.halflineheight+(padY), p.gridSizeX, y%2===1?p.halflineheight:p.gridSizeY);break;
default:
}
x++
@@ -47,7 +47,7 @@ function SkillTree(p) {
return
+ height={height} ref={canvasRef} style={p.style} className={p.className}>{p.children}
}
export {SkillTree}
\ No newline at end of file
diff --git a/src/skilltree/skillTreeEditor.js b/src/skilltree/skillTreeEditor.js
index 721d060..9f36631 100644
--- a/src/skilltree/skillTreeEditor.js
+++ b/src/skilltree/skillTreeEditor.js
@@ -1,5 +1,5 @@
import { SkillTree } from "./skillTree";
-import { useEffect,useState,useMemo,useCallback } from "react";
+import React, { useEffect,useState,useMemo,useCallback } from "react";
import { SkillTreeSelector } from "./skillTreeSelector";
import axios from "axios";
@@ -174,9 +174,9 @@ function SkillTreeEditor(p) {
return <>
{loading?:<>
{message}
- >}
>
diff --git a/src/skilltree/skillTreeSelector.js b/src/skilltree/skillTreeSelector.js
index 29dce30..37429b4 100644
--- a/src/skilltree/skillTreeSelector.js
+++ b/src/skilltree/skillTreeSelector.js
@@ -13,11 +13,11 @@ function SkillTreeSelector(p) {
return <>
{p.callback(f.currentTarget.value,Number(p.x),Number(p.y))}} style={{position:"absolute",left:p.ADJUSTMENT[0]+(p.x*p.gridSizeX+p.padX+p.gridSizeX/2),top:p.ADJUSTMENT[1]+((p.y/2)*p.gridSizeY+(p.y/2-1)*p.halflineheight+p.padY+(p.y===0?p.halflineheight:p.gridSizeY)/2)}} value={p.defaultValue}>
{[' ','─','│','□','┌','└','┐','┘','┬','┴','├','┤','┼'].map((ch)=>
- )
+ )
}
{p.defaultValue==='□'&&
{p.skillCallback(p.x,p.y,f.currentTarget.value)}} value={p.skill.split(",")[2]}>
- {["",...Object.keys((skillList)).filter((skill)=>skillList[skill].class_id===p.cl)].map((skill)=>)}
+ {["",...Object.keys((skillList)).filter((skill)=>skillList[skill].class_id===p.cl)].map((skill)=>)}
}
>
diff --git a/src/style.css b/src/style.css
index 90f8afb..31eb74a 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1408,3 +1408,12 @@ dd:before {
font-family: "Segoe UI Symbol";
content: "\2B1B" !important;
}
+.trashButton{
+ color:rgba(100,50,50,1);
+ width:24px;
+ height:24px;
+}
+.trashButton:hover {
+ color:rgba(200,50,50,1);
+ border: 2px solid red;
+}
\ No newline at end of file