mirror of https://github.com/Qortal/q-share
Browse Source
Some references to Q-Tube in code replaced with Q-Share Characters allowed in Publish Titles added to constants/Misc.ts, more characters are allowed than before User Search Label now says "User's Exact Name" to communicate that users must be precise about what names they search for Search and Name Search now can perform searches by hitting enter instead of clicking on Search Button Phil's MultiplePublishAll.tsx component used Added "Other" main Category Categories are sorted by name, "Other" is always lastpull/1/head
Qortal Dev
8 months ago
6 changed files with 283 additions and 166 deletions
@ -1,136 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */ |
||||
import { |
||||
Box, |
||||
Button, |
||||
CircularProgress, |
||||
Modal, |
||||
Typography, |
||||
useTheme, |
||||
} from "@mui/material"; |
||||
import React, { useCallback, useEffect, useState, useRef } from "react"; |
||||
import { ModalBody } from "../../PublishFile/Upload-styles.tsx"; |
||||
import { CircleSVG } from "../../../assets/svgs/CircleSVG"; |
||||
import { EmptyCircleSVG } from "../../../assets/svgs/EmptyCircleSVG"; |
||||
|
||||
export const MultiplePublish = ({ publishes, isOpen, onSubmit }) => { |
||||
const theme = useTheme(); |
||||
const listOfSuccessfulPublishesRef = useRef([]) |
||||
const [listOfSuccessfulPublishes, setListOfSuccessfulPublishes] = useState< |
||||
any[] |
||||
>([]); |
||||
const [currentlyInPublish, setCurrentlyInPublish] = useState(null); |
||||
const hasStarted = useRef(false); |
||||
const publish = useCallback(async (pub: any) => { |
||||
await qortalRequest(pub); |
||||
}, []); |
||||
const [isPublishing, setIsPublishing] = useState(true) |
||||
|
||||
const handlePublish = useCallback( |
||||
async (pub: any) => { |
||||
try { |
||||
setCurrentlyInPublish(pub?.identifier); |
||||
|
||||
await publish(pub); |
||||
|
||||
setListOfSuccessfulPublishes((prev: any) => [...prev, pub?.identifier]); |
||||
listOfSuccessfulPublishesRef.current = [...listOfSuccessfulPublishesRef.current, pub?.identifier] |
||||
} catch (error) { |
||||
console.log({ error }); |
||||
await new Promise<void>((res) => { |
||||
setTimeout(() => { |
||||
res(); |
||||
}, 5000); |
||||
}); |
||||
// await handlePublish(pub);
|
||||
} |
||||
}, |
||||
[publish] |
||||
); |
||||
|
||||
const startPublish = useCallback( |
||||
async (pubs: any) => { |
||||
setIsPublishing(true) |
||||
const filterPubs = pubs.filter((pub)=> !listOfSuccessfulPublishesRef.current.includes(pub.identifier)) |
||||
for (const pub of filterPubs) { |
||||
await handlePublish(pub); |
||||
|
||||
} |
||||
|
||||
if(listOfSuccessfulPublishesRef.current.length === pubs.length){ |
||||
onSubmit() |
||||
} |
||||
setIsPublishing(false) |
||||
}, |
||||
[handlePublish, onSubmit, listOfSuccessfulPublishes, publishes] |
||||
); |
||||
|
||||
useEffect(() => { |
||||
if (publishes && !hasStarted.current) { |
||||
hasStarted.current = true; |
||||
startPublish(publishes); |
||||
} |
||||
}, [startPublish, publishes, listOfSuccessfulPublishes]); |
||||
|
||||
|
||||
return ( |
||||
<Modal |
||||
open={isOpen} |
||||
aria-labelledby="modal-title" |
||||
aria-describedby="modal-description" |
||||
> |
||||
<ModalBody |
||||
sx={{ |
||||
minHeight: "50vh", |
||||
}} |
||||
> |
||||
{publishes.map((publish: any) => { |
||||
return ( |
||||
<Box |
||||
sx={{ |
||||
display: "flex", |
||||
gap: "20px", |
||||
justifyContent: "space-between", |
||||
alignItems: "center", |
||||
}} |
||||
> |
||||
<Typography>{publish?.title}</Typography> |
||||
{publish?.identifier === currentlyInPublish ? ( |
||||
<CircularProgress |
||||
size={20} |
||||
thickness={2} |
||||
sx={{ |
||||
color: theme.palette.secondary.main, |
||||
}} |
||||
/> |
||||
) : listOfSuccessfulPublishes.includes(publish.identifier) ? ( |
||||
<CircleSVG |
||||
color={theme.palette.text.primary} |
||||
height="24px" |
||||
width="24px" |
||||
/> |
||||
) : ( |
||||
<EmptyCircleSVG |
||||
color={theme.palette.text.primary} |
||||
height="24px" |
||||
width="24px" |
||||
/> |
||||
)} |
||||
</Box> |
||||
); |
||||
})} |
||||
{!isPublishing && listOfSuccessfulPublishes.length !== publishes.length && ( |
||||
<> |
||||
<Typography sx={{ |
||||
marginTop: '20px', |
||||
fontSize: '16px' |
||||
}}>Some files were not published. Please try again. It's important that all the files get published. Maybe wait a couple minutes if the error keeps occurring</Typography> |
||||
<Button onClick={()=> { |
||||
startPublish(publishes) |
||||
}}>Try again</Button> |
||||
</> |
||||
)} |
||||
|
||||
</ModalBody> |
||||
</Modal> |
||||
); |
||||
}; |
@ -0,0 +1,211 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */ |
||||
import { |
||||
Box, |
||||
Button, |
||||
CircularProgress, |
||||
Modal, |
||||
Typography, |
||||
useTheme, |
||||
} from "@mui/material"; |
||||
import React, { useCallback, useEffect, useState, useRef } from "react"; |
||||
import { CircleSVG } from "../../../assets/svgs/CircleSVG"; |
||||
import { EmptyCircleSVG } from "../../../assets/svgs/EmptyCircleSVG"; |
||||
import { styled } from "@mui/system"; |
||||
|
||||
interface Publish { |
||||
resources: any[]; |
||||
action: string; |
||||
} |
||||
|
||||
interface MultiplePublishProps { |
||||
publishes: Publish; |
||||
isOpen: boolean; |
||||
onSubmit: ()=> void |
||||
onError: (message?: string)=> void |
||||
} |
||||
export const MultiplePublish = ({ publishes, isOpen, onSubmit, onError}: MultiplePublishProps) => { |
||||
const theme = useTheme(); |
||||
const listOfSuccessfulPublishesRef = useRef([]) |
||||
const [listOfSuccessfulPublishes, setListOfSuccessfulPublishes] = useState< |
||||
any[] |
||||
>([]); |
||||
const [listOfUnsuccessfulPublishes, setListOfUnSuccessfulPublishes] = useState< |
||||
any[] |
||||
>([]); |
||||
const [currentlyInPublish, setCurrentlyInPublish] = useState(null); |
||||
const hasStarted = useRef(false); |
||||
const publish = useCallback(async (pub: any) => { |
||||
const lengthOfResources = pub?.resources?.length |
||||
const lengthOfTimeout = lengthOfResources * 30000 |
||||
return await qortalRequestWithTimeout(pub, lengthOfTimeout); |
||||
}, []); |
||||
const [isPublishing, setIsPublishing] = useState(true) |
||||
|
||||
const handlePublish = useCallback( |
||||
async (pub: any) => { |
||||
try { |
||||
setCurrentlyInPublish(pub?.identifier); |
||||
setIsPublishing(true) |
||||
const res = await publish(pub); |
||||
|
||||
onSubmit() |
||||
setListOfUnSuccessfulPublishes([]) |
||||
|
||||
} catch (error: any) { |
||||
const unsuccessfulPublishes = error?.error?.unsuccessfulPublishes || [] |
||||
if(error?.error === 'User declined request'){ |
||||
onError() |
||||
return |
||||
} |
||||
|
||||
if(error?.error === 'The request timed out'){ |
||||
onError("The request timed out") |
||||
|
||||
return |
||||
} |
||||
|
||||
|
||||
if(unsuccessfulPublishes?.length > 0){ |
||||
setListOfUnSuccessfulPublishes(unsuccessfulPublishes) |
||||
|
||||
} |
||||
} finally { |
||||
|
||||
setIsPublishing(false) |
||||
} |
||||
}, |
||||
[publish] |
||||
); |
||||
|
||||
const retry = ()=> { |
||||
let newlistOfMultiplePublishes: any[] = []; |
||||
listOfUnsuccessfulPublishes?.forEach((item)=> { |
||||
const findPub = publishes?.resources.find((res: any)=> res?.identifier === item.identifier) |
||||
if(findPub){ |
||||
newlistOfMultiplePublishes.push(findPub) |
||||
} |
||||
}) |
||||
const multiplePublish = { |
||||
...publishes, |
||||
resources: newlistOfMultiplePublishes |
||||
}; |
||||
handlePublish(multiplePublish) |
||||
} |
||||
|
||||
const startPublish = useCallback( |
||||
async (pubs: any) => { |
||||
await handlePublish(pubs); |
||||
}, |
||||
[handlePublish, onSubmit, listOfSuccessfulPublishes, publishes] |
||||
); |
||||
|
||||
useEffect(() => { |
||||
if (publishes && !hasStarted.current) { |
||||
hasStarted.current = true; |
||||
startPublish(publishes); |
||||
} |
||||
}, [startPublish, publishes, listOfSuccessfulPublishes]); |
||||
|
||||
|
||||
return ( |
||||
<Modal |
||||
open={isOpen} |
||||
aria-labelledby="modal-title" |
||||
aria-describedby="modal-description" |
||||
> |
||||
<ModalBody |
||||
sx={{ |
||||
minHeight: "50vh", |
||||
}} |
||||
> |
||||
{publishes?.resources?.map((publish: any) => { |
||||
const unpublished = listOfUnsuccessfulPublishes.map(item => item?.identifier) |
||||
return ( |
||||
<Box |
||||
sx={{ |
||||
display: "flex", |
||||
gap: "20px", |
||||
justifyContent: "space-between", |
||||
alignItems: "center", |
||||
}} |
||||
> |
||||
<Typography>{publish?.identifier}</Typography> |
||||
{!isPublishing && hasStarted.current ? ( |
||||
<> |
||||
{!unpublished.includes(publish.identifier) ? ( |
||||
<CircleSVG |
||||
color={theme.palette.text.primary} |
||||
height="24px" |
||||
width="24px" |
||||
/> |
||||
) : ( |
||||
<EmptyCircleSVG |
||||
color={theme.palette.text.primary} |
||||
height="24px" |
||||
width="24px" |
||||
/> |
||||
)} |
||||
</> |
||||
): <CircularProgress size={16} color="secondary"/>} |
||||
|
||||
</Box> |
||||
); |
||||
})} |
||||
{!isPublishing && listOfUnsuccessfulPublishes.length > 0 && ( |
||||
<> |
||||
<Typography sx={{ |
||||
marginTop: '20px', |
||||
fontSize: '16px' |
||||
}}>Some files were not published. Please try again. It's important that all the files get published. Maybe wait a couple minutes if the error keeps occurring</Typography> |
||||
<Button variant="contained" onClick={()=> { |
||||
retry() |
||||
}}>Try again</Button> |
||||
</> |
||||
)} |
||||
|
||||
</ModalBody> |
||||
</Modal> |
||||
); |
||||
}; |
||||
|
||||
|
||||
export const ModalBody = styled(Box)(({ theme }) => ({ |
||||
position: "absolute", |
||||
backgroundColor: theme.palette.background.default, |
||||
borderRadius: "4px", |
||||
top: "50%", |
||||
left: "50%", |
||||
transform: "translate(-50%, -50%)", |
||||
width: "75%", |
||||
maxWidth: "900px", |
||||
padding: "15px 35px", |
||||
display: "flex", |
||||
flexDirection: "column", |
||||
gap: "17px", |
||||
overflowY: "auto", |
||||
maxHeight: "95vh", |
||||
boxShadow: |
||||
theme.palette.mode === "dark" |
||||
? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)" |
||||
: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px", |
||||
"&::-webkit-scrollbar-track": { |
||||
backgroundColor: theme.palette.background.paper, |
||||
}, |
||||
"&::-webkit-scrollbar-track:hover": { |
||||
backgroundColor: theme.palette.background.paper, |
||||
}, |
||||
"&::-webkit-scrollbar": { |
||||
width: "16px", |
||||
height: "10px", |
||||
backgroundColor: theme.palette.mode === "light" ? "#f6f8fa" : "#292d3e", |
||||
}, |
||||
"&::-webkit-scrollbar-thumb": { |
||||
backgroundColor: theme.palette.mode === "light" ? "#d3d9e1" : "#575757", |
||||
borderRadius: "8px", |
||||
backgroundClip: "content-box", |
||||
border: "4px solid transparent", |
||||
}, |
||||
"&::-webkit-scrollbar-thumb:hover": { |
||||
backgroundColor: theme.palette.mode === "light" ? "#b7bcc4" : "#474646", |
||||
}, |
||||
})); |
Loading…
Reference in new issue