Updated app to support fuzzy item searches and fixed bugs
This commit is contained in:
parent
4ca1b8d8af
commit
d7bb77b486
5
package-lock.json
generated
5
package-lock.json
generated
@ -6992,6 +6992,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
|
||||||
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
|
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
|
||||||
},
|
},
|
||||||
|
"fuzzysort": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-Api1mJL+Ad7W7vnDZnWq5pGaXJjyencT+iKGia2PlHUcSsSzWwIQ3S1isiMpwpavjYtGd2FzhUIhnnhOULZgDw=="
|
||||||
|
},
|
||||||
"gensync": {
|
"gensync": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.2",
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"bootstrap": "^5.0.2",
|
"bootstrap": "^5.0.2",
|
||||||
"csv-parse": "^4.16.0",
|
"csv-parse": "^4.16.0",
|
||||||
|
"fuzzysort": "^2.0.4",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-bootstrap": "^2.0.0-beta.4",
|
"react-bootstrap": "^2.0.0-beta.4",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
|||||||
176
src/App.js
176
src/App.js
@ -1,7 +1,7 @@
|
|||||||
import './App.css';
|
import './App.css';
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
|
|
||||||
import { useState,useEffect } from 'react';
|
import { useState,useEffect,Fragment } from 'react';
|
||||||
|
|
||||||
import Container from 'react-bootstrap/Container';
|
import Container from 'react-bootstrap/Container';
|
||||||
import Row from 'react-bootstrap/Row';
|
import Row from 'react-bootstrap/Row';
|
||||||
@ -14,15 +14,18 @@ import ToastContainer from 'react-bootstrap/ToastContainer'
|
|||||||
import Toast from 'react-bootstrap/Toast'
|
import Toast from 'react-bootstrap/Toast'
|
||||||
import Nav from 'react-bootstrap/Nav'
|
import Nav from 'react-bootstrap/Nav'
|
||||||
import Spinner from 'react-bootstrap/Spinner';
|
import Spinner from 'react-bootstrap/Spinner';
|
||||||
|
import Form from 'react-bootstrap/Form';
|
||||||
|
|
||||||
import { FaCheckCircle } from 'react-icons/fa';
|
import { FaCheckCircle } from 'react-icons/fa';
|
||||||
import { IoCheckmarkCircleOutline,IoCloseCircleSharp,IoAlertCircleOutline } from 'react-icons/io5';
|
import { IoCheckmarkCircleOutline,IoCloseCircleSharp,IoAlertCircleOutline } from 'react-icons/io5';
|
||||||
|
|
||||||
|
const fuzzysort = require('fuzzysort')
|
||||||
|
|
||||||
|
|
||||||
const parse = require('csv-parse/lib/sync')
|
const parse = require('csv-parse/lib/sync')
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
|
||||||
const dataSplitters = [0,128,225,363]
|
const dataSplitters = [0,190,475,670]
|
||||||
|
|
||||||
const BACKEND_URL = "https://projectdivar.com:4505"
|
const BACKEND_URL = "https://projectdivar.com:4505"
|
||||||
|
|
||||||
@ -31,6 +34,43 @@ const NOTIFICATIONTIMEOUT = 300 //In seconds
|
|||||||
const progress1 = new Audio(process.env.PUBLIC_URL+"/progress1.mp3")
|
const progress1 = new Audio(process.env.PUBLIC_URL+"/progress1.mp3")
|
||||||
const progress2 = new Audio(process.env.PUBLIC_URL+"/progress2.mp3")
|
const progress2 = new Audio(process.env.PUBLIC_URL+"/progress2.mp3")
|
||||||
|
|
||||||
|
function Item(p){
|
||||||
|
const {item,setLockout,contributor,lockout} = p
|
||||||
|
|
||||||
|
function updateItem(item,target,contributor) {
|
||||||
|
var correctedVal=Math.min(item.required,target.value);
|
||||||
|
if (correctedVal===Number(item.obtained)) {return;}
|
||||||
|
setLockout(true)
|
||||||
|
axios.post(BACKEND_URL+"/updateItem",{obtained:correctedVal,id:item.id,last_modified:new Date(),item_name:item.name,username:contributor,required:item.required,operation:correctedVal===Number(item.required)?"FINISH":correctedVal>item.obtained?"INCREASE":"SET",previous_amt:item.obtained})
|
||||||
|
.then((data)=>{
|
||||||
|
setLockout(false)
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Row className={"pb-1 pt-1 text-light"+(Number(item.obtained)===0?" notStarted":Number(item.obtained)===Number(item.required)?" completed":" inProgress")}>
|
||||||
|
<Col>
|
||||||
|
<img src={"https://xivapi.com"+item.icon} alt={item.name}/> {item.name}
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<input disabled={lockout} id={"field_"+item.id} style={{width:"5em"}} defaultValue={item.obtained} className="mt-1 bg-secondary"
|
||||||
|
onKeyDown={(k)=>{
|
||||||
|
if (k.key==='Enter') {updateItem(item,document.getElementById("field_"+item.id),contributor)}
|
||||||
|
}}
|
||||||
|
onChange={(f)=>{
|
||||||
|
if (f.currentTarget.value>=item.required) {f.currentTarget.blur()}
|
||||||
|
}} onBlur={(f)=>{updateItem(item,f.currentTarget,contributor)}} type="number" min="0" max={item.required}/> / {item.required} {item.required!==item.obtained&&<FaCheckCircle style={{color:"green"}} onClick={(f)=>{
|
||||||
|
updateItem(item,{value:item.required},contributor)
|
||||||
|
}}/>}
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<a style={{position:"relative",top:"8px"}} className="text-muted" href={"https://garlandtools.org/db/#item/"+item.itemid} target="tools">View Item Info</a>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
}
|
||||||
|
|
||||||
function ItemGroup(p) {
|
function ItemGroup(p) {
|
||||||
const { data } = p
|
const { data } = p
|
||||||
const { contributor } = p
|
const { contributor } = p
|
||||||
@ -53,42 +93,11 @@ function ItemGroup(p) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},[displayData])
|
},[displayData])
|
||||||
|
|
||||||
function updateItem(item,target,contributor) {
|
|
||||||
var correctedVal=Math.min(item.required,target.value);
|
|
||||||
if (correctedVal===Number(item.obtained)) {return;}
|
|
||||||
setLockout(true)
|
|
||||||
axios.post(BACKEND_URL+"/updateItem",{obtained:correctedVal,id:item.id,last_modified:new Date(),item_name:item.name,username:contributor,required:item.required,operation:correctedVal===Number(item.required)?"FINISH":correctedVal>item.obtained?"INCREASE":"SET",previous_amt:item.obtained})
|
|
||||||
.then((data)=>{
|
|
||||||
setLockout(false)
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Accordion.Item className="bg-dark" eventKey={p.akey}>
|
return <Accordion.Item className="bg-dark" eventKey={p.akey}>
|
||||||
<Accordion.Header className="panel-body bg-dark">{p.name}</Accordion.Header>
|
<Accordion.Header className="panel-body bg-dark">{p.name}</Accordion.Header>
|
||||||
<Accordion.Body className="panel-body">
|
<Accordion.Body className="panel-body">
|
||||||
{displayData.map((item,i,arr)=><Row key={item.id} className={"pb-1 pt-1 text-light"+(Number(item.obtained)===0?" notStarted":Number(item.obtained)===Number(item.required)?" completed":" inProgress")}>
|
{displayData.map((item,i,arr)=><Item key={item.id} item={item} setLockout={setLockout} lockout={lockout} contributor={contributor}></Item>)}
|
||||||
<Col>
|
|
||||||
<img src={"https://xivapi.com"+item.icon} alt={item.name}/> {item.name}
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<input disabled={lockout} id={"field_"+item.id} style={{width:"5em"}} defaultValue={item.obtained} className="mt-1 bg-secondary"
|
|
||||||
onKeyDown={(k)=>{
|
|
||||||
if (k.key==='Enter') {updateItem(item,document.getElementById("field_"+item.id),contributor)}
|
|
||||||
}}
|
|
||||||
onChange={(f)=>{
|
|
||||||
if (f.currentTarget.value>=item.required) {f.currentTarget.blur()}
|
|
||||||
}} onBlur={(f)=>{updateItem(item,f.currentTarget,contributor)}} type="number" min="0" max={item.required}/> / {item.required} {item.required!==item.obtained&&<FaCheckCircle style={{color:"green"}} onClick={(f)=>{
|
|
||||||
updateItem(item,{value:item.required},contributor)
|
|
||||||
}}/>}
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<a style={{position:"relative",top:"8px"}} className="text-muted" href={"https://garlandtools.org/db/#item/"+item.itemid} target="tools">View Item Info</a>
|
|
||||||
</Col>
|
|
||||||
</Row>)}
|
|
||||||
</Accordion.Body>
|
</Accordion.Body>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
}
|
}
|
||||||
@ -211,6 +220,7 @@ function ListApp(p){
|
|||||||
let currentPage=1
|
let currentPage=1
|
||||||
let recipeData=[]
|
let recipeData=[]
|
||||||
setChecking(true)
|
setChecking(true)
|
||||||
|
setGroceryList([])
|
||||||
axios.get(encodeURI(filter))
|
axios.get(encodeURI(filter))
|
||||||
.then(async(resp)=>{
|
.then(async(resp)=>{
|
||||||
let data=resp.data
|
let data=resp.data
|
||||||
@ -293,7 +303,7 @@ function ListApp(p){
|
|||||||
function Item(p){
|
function Item(p){
|
||||||
const {it} = p
|
const {it} = p
|
||||||
return it.amt>0&&<Row className="text-white">
|
return it.amt>0&&<Row className="text-white">
|
||||||
<Col><img src={"https://xivapi.com"+it.icon}></img>{it.slot?"["+Math.floor(it.slot/35+1)+"]":""} {it.name} x{it.amt} {it.hq?"(HQ)":""}</Col>
|
<Col><img src={"https://xivapi.com"+it.icon}></img>{Number.isInteger(it.slot)?"["+Math.floor(it.slot/35+1)+"]":""} {it.name} x{it.amt} {it.hq?"(HQ)":""}</Col>
|
||||||
</Row>
|
</Row>
|
||||||
}
|
}
|
||||||
function RetainerDisplay(p){
|
function RetainerDisplay(p){
|
||||||
@ -326,18 +336,21 @@ function ListApp(p){
|
|||||||
<Col xs={3}>
|
<Col xs={3}>
|
||||||
<Button onKeyDown={(k)=>{if (k.key==='Enter') {submitForm()}}} disabled={checking} onClick={()=>{submitForm()}}>{checking?<Spinner animation="border"></Spinner>:"Compose"}</Button>
|
<Button onKeyDown={(k)=>{if (k.key==='Enter') {submitForm()}}} disabled={checking} onClick={()=>{submitForm()}}>{checking?<Spinner animation="border"></Spinner>:"Compose"}</Button>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col xs={1}>
|
||||||
|
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row><span>A</span></Row>
|
<Row><span>A</span></Row>
|
||||||
{groceryList.map((list,i)=>{
|
{groceryList.map((list,i)=>{
|
||||||
if (list.length>0){
|
if (list.length>0){
|
||||||
return <>
|
return <Fragment key={i}>
|
||||||
<Row className="text-white"><Col>{(i===9)?<h4 style={{"color":"#AA0000"}}>Not Found:</h4>:<h4>From {retainerNames[i]}:</h4>}</Col></Row>
|
<Row className="text-white"><Col>{(i===9)?<h4 style={{"color":"#AA0000"}}>Not Found:</h4>:<h4>From {retainerNames[i]}:</h4>}</Col></Row>
|
||||||
<Row className="text-white"><Col>
|
<Row className="text-white"><Col>
|
||||||
<ul>
|
<ul>
|
||||||
{list.map((item,j)=><li><Item it={item} key={j}></Item></li>)}
|
{list.map((item,j)=><li key={j}><Item it={item}></Item></li>)}
|
||||||
</ul>
|
</ul>
|
||||||
</Col></Row>
|
</Col></Row>
|
||||||
</>
|
</Fragment>
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
<Row><span>Inventories</span></Row>
|
<Row><span>Inventories</span></Row>
|
||||||
@ -368,6 +381,7 @@ function App() {
|
|||||||
const [succeeded,setSucceeded] = useState(0)
|
const [succeeded,setSucceeded] = useState(0)
|
||||||
const [failed,setFailed] = useState(0)
|
const [failed,setFailed] = useState(0)
|
||||||
const [total,setTotal] = useState(0)
|
const [total,setTotal] = useState(0)
|
||||||
|
const [completeRatio,setCompleteRatio] = useState(0)
|
||||||
const [lastModified,setLastModified] = useState(new Date())
|
const [lastModified,setLastModified] = useState(new Date())
|
||||||
|
|
||||||
const [contributor,setContributor] = useState("")
|
const [contributor,setContributor] = useState("")
|
||||||
@ -377,6 +391,10 @@ function App() {
|
|||||||
|
|
||||||
const [transferItems,setTransferItems] = useState([])
|
const [transferItems,setTransferItems] = useState([])
|
||||||
|
|
||||||
|
const [matchedItems,setMatchedItems] = useState([])
|
||||||
|
|
||||||
|
const [lockout,setLockout] = useState(false)
|
||||||
|
|
||||||
function LZ(digits,numb) {
|
function LZ(digits,numb) {
|
||||||
return "0".repeat(digits-String(numb).length)+numb
|
return "0".repeat(digits-String(numb).length)+numb
|
||||||
}
|
}
|
||||||
@ -395,6 +413,12 @@ function App() {
|
|||||||
setData2(data.data.slice(dataSplitters[1],dataSplitters[2]))
|
setData2(data.data.slice(dataSplitters[1],dataSplitters[2]))
|
||||||
setData3(data.data.slice(dataSplitters[2],dataSplitters[3]))
|
setData3(data.data.slice(dataSplitters[2],dataSplitters[3]))
|
||||||
setData4(data.data.slice(dataSplitters[3],data.data.length))
|
setData4(data.data.slice(dataSplitters[3],data.data.length))
|
||||||
|
let items=0,tot=0
|
||||||
|
for (var item of data.data){
|
||||||
|
items+=item.obtained
|
||||||
|
tot+=item.required
|
||||||
|
}
|
||||||
|
setCompleteRatio(items/tot)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -410,13 +434,13 @@ function App() {
|
|||||||
var largestNotificationID = -1
|
var largestNotificationID = -1
|
||||||
var dataCheck=true
|
var dataCheck=true
|
||||||
const interval = setInterval(()=>{
|
const interval = setInterval(()=>{
|
||||||
if (dataCheck) {
|
if (dataCheck&&nav==="main") {
|
||||||
dataCheck=false
|
dataCheck=false
|
||||||
notificationLastUpdate = new Date(new Date()-(NOTIFICATIONTIMEOUT*1000))
|
notificationLastUpdate = new Date(new Date()-(NOTIFICATIONTIMEOUT*1000))
|
||||||
axios.get(BACKEND_URL+"/getNotifications?date="+encodeURIComponent(LZ(4,notificationLastUpdate.getUTCFullYear())+"-"+LZ(2,notificationLastUpdate.getUTCMonth()+1)+"-"+LZ(2,notificationLastUpdate.getUTCDate())+" "+LZ(2,notificationLastUpdate.getUTCHours())+":"+LZ(2,notificationLastUpdate.getUTCMinutes())+":"+LZ(2,notificationLastUpdate.getUTCSeconds())+"."+LZ(3,notificationLastUpdate.getUTCMilliseconds())+"+00"))
|
axios.get(BACKEND_URL+"/getNotifications?date="+encodeURIComponent(LZ(4,notificationLastUpdate.getUTCFullYear())+"-"+LZ(2,notificationLastUpdate.getUTCMonth()+1)+"-"+LZ(2,notificationLastUpdate.getUTCDate())+" "+LZ(2,notificationLastUpdate.getUTCHours())+":"+LZ(2,notificationLastUpdate.getUTCMinutes())+":"+LZ(2,notificationLastUpdate.getUTCSeconds())+"."+LZ(3,notificationLastUpdate.getUTCMilliseconds())+"+00"))
|
||||||
.then((data)=>{
|
.then((data)=>{
|
||||||
if (data.data.length>0) {
|
if (data.data.length>0) {
|
||||||
console.log("New notification array: "+JSON.stringify(data.data))
|
//console.log("New notification array: "+JSON.stringify(data.data))
|
||||||
setNotifications(data.data)
|
setNotifications(data.data)
|
||||||
var completion=false
|
var completion=false
|
||||||
var largestID = -1
|
var largestID = -1
|
||||||
@ -459,6 +483,12 @@ function App() {
|
|||||||
setData2(data.data.slice(dataSplitters[1],dataSplitters[2]))
|
setData2(data.data.slice(dataSplitters[1],dataSplitters[2]))
|
||||||
setData3(data.data.slice(dataSplitters[2],dataSplitters[3]))
|
setData3(data.data.slice(dataSplitters[2],dataSplitters[3]))
|
||||||
setData4(data.data.slice(dataSplitters[3],data.data.length))
|
setData4(data.data.slice(dataSplitters[3],data.data.length))
|
||||||
|
let items=0,tot=0
|
||||||
|
for (var item of data.data){
|
||||||
|
items+=item.obtained
|
||||||
|
tot+=item.required
|
||||||
|
}
|
||||||
|
setCompleteRatio(items/tot)
|
||||||
})
|
})
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
console.log(err.message)
|
console.log(err.message)
|
||||||
@ -521,7 +551,29 @@ function App() {
|
|||||||
console.log(d)
|
console.log(d)
|
||||||
downloadData(d,0,d.length)
|
downloadData(d,0,d.length)
|
||||||
setTotal(d.length)
|
setTotal(d.length)
|
||||||
},[fileData,failed,succeeded])
|
},[fileData])
|
||||||
|
|
||||||
|
function Importer(){
|
||||||
|
return <Row>
|
||||||
|
<Col>
|
||||||
|
{total===0?<caption><label className="buttonLabel" for="uploads">Import List</label><input onChange={(f)=>{
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload=(ev)=>{
|
||||||
|
setFileData(ev.target.result)
|
||||||
|
}
|
||||||
|
reader.readAsText(f.target.files[0])
|
||||||
|
}} style={{opacity:0}} id="uploads" type="file" accept=".txt,.csv"/></caption>:
|
||||||
|
<>
|
||||||
|
<ProgressBar>
|
||||||
|
<ProgressBar animated striped variant="success" now={Math.round(succeeded/total)*100} />
|
||||||
|
<ProgressBar animated striped variant="danger" now={Math.round(failed/total)*100} />
|
||||||
|
</ProgressBar>
|
||||||
|
<div className="text-center">{Math.round(((failed+succeeded)/total)*100)+"%"}</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className="bg-dark" fluid>
|
<Container className="bg-dark" fluid>
|
||||||
@ -545,35 +597,31 @@ function App() {
|
|||||||
nav==="main"?
|
nav==="main"?
|
||||||
data.length>0?
|
data.length>0?
|
||||||
<>
|
<>
|
||||||
|
<Row>
|
||||||
|
<ProgressBar className="bg-dark text-white">
|
||||||
|
<ProgressBar animated striped variant="success" label={`${completeRatio}%`} now={completeRatio} />
|
||||||
|
</ProgressBar>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Form>
|
||||||
|
<Form.Group className="mb-3" controlId="formBasicEmail">
|
||||||
|
<Form.Control className="bg-dark text-white" type="text" placeholder="Search Item" onChange={(f)=>{
|
||||||
|
if (f.currentTarget.value.length>2){
|
||||||
|
setMatchedItems(fuzzysort.go(f.currentTarget.value.trim().toLowerCase(), [...data,...data2,...data3,...data4], {key:'name'}))
|
||||||
|
}
|
||||||
|
}} />
|
||||||
|
{matchedItems.map((item)=><Item key={item.obj.id} item={item.obj} setLockout={setLockout} lockout={lockout} contributor={contributor}></Item>)}
|
||||||
|
</Form.Group>
|
||||||
|
</Form>
|
||||||
|
</Row>
|
||||||
<Accordion className="bg-dark" defaultActiveKey="0">
|
<Accordion className="bg-dark" defaultActiveKey="0">
|
||||||
<ItemGroup name="Gathering Items" contributor={contributor} akey="0" data={data} lastModified={lastModified} setLastModified={setLastModified} setData={setData} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
<ItemGroup name="Gathering Items" contributor={contributor} akey="0" data={data} lastModified={lastModified} setLastModified={setLastModified} setData={setData} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
||||||
<ItemGroup name="Other Items" contributor={contributor} akey="1" data={data2} lastModified={lastModified} setLastModified={setLastModified} setData={setData2} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
<ItemGroup name="Other Items" contributor={contributor} akey="1" data={data2} lastModified={lastModified} setLastModified={setLastModified} setData={setData2} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
||||||
<ItemGroup name="Pre-crafting" contributor={contributor} akey="2" data={data3} lastModified={lastModified} setLastModified={setLastModified} setData={setData3} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
<ItemGroup name="Pre-crafting" contributor={contributor} akey="2" data={data3} lastModified={lastModified} setLastModified={setLastModified} setData={setData3} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
||||||
<ItemGroup name="Crafting Items" contributor={contributor} akey="3" data={data4} lastModified={lastModified} setLastModified={setLastModified} setData={setData4} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
<ItemGroup name="Crafting Items" contributor={contributor} akey="3" data={data4} lastModified={lastModified} setLastModified={setLastModified} setData={setData4} setData1={setData} setData2={setData2} setData3={setData3} setData4={setData4}/>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</>:
|
</>:<Importer></Importer>
|
||||||
!disabled&&
|
:nav==="list"?<ListApp transferItems={transferItems}></ListApp>:
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
{total===0?<caption><label className="buttonLabel" for="uploads">Import List</label><input onChange={(f)=>{
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.onload=(ev)=>{
|
|
||||||
setFileData(ev.target.result)
|
|
||||||
}
|
|
||||||
reader.readAsText(f.target.files[0])
|
|
||||||
}} style={{opacity:0}} id="uploads" type="file" accept=".txt,.csv"/></caption>:
|
|
||||||
<>
|
|
||||||
<ProgressBar>
|
|
||||||
<ProgressBar animated striped variant="success" now={Math.round(succeeded/total)*100} />
|
|
||||||
<ProgressBar animated striped variant="danger" now={Math.round(failed/total)*100} />
|
|
||||||
</ProgressBar>
|
|
||||||
<div className="text-center">{Math.round(((failed+succeeded)/total)*100)+"%"}</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
:
|
|
||||||
nav==="list"?<ListApp transferItems={transferItems}></ListApp>:
|
|
||||||
<></>
|
<></>
|
||||||
}
|
}
|
||||||
<div style={{pointerEvents:"none",position:"fixed",top:"0px",left:"0px",width:"100%",height:"100%"}}>
|
<div style={{pointerEvents:"none",position:"fixed",top:"0px",left:"0px",width:"100%",height:"100%"}}>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user