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&&} - + {fields.map((field,i)=>)} {{fields.map((col,i)=>)}{SubmitBoxes()}} className="submitbutton"/>} + (f)=>{setSubmitVal({field:col.name,value:f});}}/>})}} {data.map((dat)=> - {fields.map((col,i)=>{fields.map((col,i)=>)})}
{ + {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"/>{field.name}
{{setSubmitVal({field:col.name,value:f});}}/>}
{SubmitBoxes()}} className="submitbutton"/>
{axios.delete(p.BACKENDURL+p.path,{data:{id:dat.id,pass:p.password}}).then(()=>{setUpdate(true)}).catch((err)=>{alert(err.response.data)})}}/> + 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}
+ }}> Restore
} 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 {p.children} + 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}

    - {setCl(Number(f.currentTarget.value))}}> - {Object.keys(classList).map((c)=>)} + {Object.keys(classList).map((c)=>)}

    @@ -189,19 +189,19 @@ function SkillTreeEditor(p) { gridDimensionsX={dimensionX} gridDimensionsY={dimensionY} gridSizeX={gridSizeX} gridSizeY={gridSizeY} gridPaddingX={gridPaddingX} gridPaddingY={gridPaddingY} skillLines={skillLines} halflineheight={halflineheight} /> - {renderedInputs.map((control)=>control)} + {renderedInputs.map((control,i)=>{control})}


    - {setLineColor(f.currentTarget.value)}}/>
    - {setLineWidth(f.currentTarget.value)}}/>
    - {setDimensionX(f.currentTarget.value)}}/>
    - {setDimensionY(f.currentTarget.value)}}/>
    - {setHalfLineHeight(f.currentTarget.value)}}/>
    - {setGridSizeX(f.currentTarget.value)}}/>
    - {setGridSizeY(f.currentTarget.value)}}/>
    - {setGridPaddingX(f.currentTarget.value)}}/>
    - {setGridPaddingY(f.currentTarget.value)}}/>
    + {setLineColor(f.currentTarget.value)}}/>
    + {setLineWidth(f.currentTarget.value)}}/>
    + {setDimensionX(f.currentTarget.value)}}/>
    + {setDimensionY(f.currentTarget.value)}}/>
    + {setHalfLineHeight(f.currentTarget.value)}}/>
    + {setGridSizeX(f.currentTarget.value)}}/>
    + {setGridSizeY(f.currentTarget.value)}}/>
    + {setGridPaddingX(f.currentTarget.value)}}/>
    + {setGridPaddingY(f.currentTarget.value)}}/>
    } 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.defaultValue==='□'&&} 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