forked from Qortal/Q-Manager
384 lines
11 KiB
JavaScript
384 lines
11 KiB
JavaScript
import React, { useState } from "react";
|
|
import {
|
|
Box,
|
|
ButtonBase,
|
|
CircularProgress,
|
|
MenuItem,
|
|
Select,
|
|
Typography,
|
|
styled,
|
|
} from "@mui/material";
|
|
import { DisplayCode } from "../components/DisplayCode";
|
|
import { DisplayCodeResponse } from "../components/DisplayCodeResponse";
|
|
import ShortUniqueId from "short-unique-id";
|
|
|
|
import Button from "../components/Button";
|
|
import { useDropzone } from "react-dropzone";
|
|
import { privateServices, services } from "../constants";
|
|
import { fileToBase64 } from "../utils";
|
|
import toast from 'react-hot-toast';
|
|
import { openToast } from "../components/openToast";
|
|
|
|
const uid = new ShortUniqueId({ length: 10 });
|
|
|
|
export const Label = styled("label")(
|
|
({ theme }) => `
|
|
font-family: 'IBM Plex Sans', sans-serif;
|
|
font-size: 14px;
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
font-weight: 400;
|
|
`
|
|
);
|
|
|
|
export const PUBLISH_QDN_RESOURCE = ({ addNodeByPath, myName, mode, existingFile, updateByPath , groups, selectedGroup}) => {
|
|
const [requestData, setRequestData] = useState({
|
|
service: existingFile?.service || mode === 'private' ? "DOCUMENT_PRIVATE" : "DOCUMENT"
|
|
});
|
|
|
|
const { getRootProps, getInputProps } = useDropzone({
|
|
maxFiles: 1,
|
|
onDrop: async (acceptedFiles) => {
|
|
const fileSelected = acceptedFiles[0];
|
|
if (fileSelected) {
|
|
setFile(fileSelected);
|
|
}
|
|
},
|
|
});
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [file, setFile] = useState(null);
|
|
|
|
|
|
|
|
|
|
const executeQortalRequestGroup = async () => {
|
|
const promise = (async () => {
|
|
try {
|
|
if (!file) throw new Error('Please select a file')
|
|
if(!selectedGroup) throw new Error('Please select a group')
|
|
const findGroup = groups?.find((group)=> group.groupId === selectedGroup)
|
|
if(!findGroup) throw new Error('Cannot find group')
|
|
setIsLoading(true);
|
|
|
|
const fileExtension = file?.name?.includes(".") ? file.name.split(".").pop() : "";
|
|
const fileTitle =
|
|
file?.name
|
|
?.split(".")
|
|
.slice(0, -1)
|
|
.join(".")
|
|
.replace(/ /g, "_")
|
|
.slice(0, 20) || "Untitled";
|
|
const filename = fileExtension ? `${fileTitle}.${fileExtension}` : fileTitle;
|
|
|
|
|
|
const constructedIdentifier = existingFile?.identifier || `grp-q-manager-858-${uid.rnd()}`;
|
|
const base64File = await fileToBase64(file);
|
|
const encryptedData = await qortalRequest({
|
|
action: "ENCRYPT_QORTAL_GROUP_DATA",
|
|
data64: base64File,
|
|
groupId: selectedGroup
|
|
});
|
|
|
|
if(!encryptedData) throw new Error('Unable to encrypt data')
|
|
|
|
let account = await qortalRequest({
|
|
action: "PUBLISH_QDN_RESOURCE",
|
|
service: existingFile?.service || requestData?.service,
|
|
identifier: constructedIdentifier,
|
|
data64: encryptedData,
|
|
externalEncrypt: true,
|
|
|
|
});
|
|
|
|
if (account?.identifier) {
|
|
if (!!existingFile) {
|
|
updateByPath({
|
|
...existingFile,
|
|
mimeType: file?.type,
|
|
});
|
|
setFile("");
|
|
return true; // Success
|
|
}
|
|
|
|
addNodeByPath(
|
|
undefined,
|
|
{
|
|
type: "file",
|
|
name: filename,
|
|
mimeType: file?.type,
|
|
qortalName: myName,
|
|
identifier: constructedIdentifier,
|
|
service: requestData?.service,
|
|
group: selectedGroup,
|
|
groupName: findGroup?.groupName
|
|
},
|
|
undefined
|
|
);
|
|
|
|
|
|
return true; // Success
|
|
} else {
|
|
throw new Error("Unable to publish the file");
|
|
}
|
|
} catch (error) {
|
|
console.error("Error:", error);
|
|
throw error; // Ensure the error is propagated to the toast
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
})();
|
|
|
|
await openToast(promise, {
|
|
loading: "Publishing the file...",
|
|
success: "File published successfully!",
|
|
error: (err) => `Failed to publish: ${err?.error || err?.message || "An unknown error occurred"}`,
|
|
});
|
|
};
|
|
|
|
|
|
const executeQortalRequestPrivate = async () => {
|
|
const promise = (async () => {
|
|
try {
|
|
if (!file) return;
|
|
setIsLoading(true);
|
|
|
|
const fileExtension = file?.name?.includes(".") ? file.name.split(".").pop() : "";
|
|
const fileTitle =
|
|
file?.name
|
|
?.split(".")
|
|
.slice(0, -1)
|
|
.join(".")
|
|
.replace(/ /g, "_")
|
|
.slice(0, 20) || "Untitled";
|
|
const filename = fileExtension ? `${fileTitle}.${fileExtension}` : fileTitle;
|
|
|
|
|
|
const constructedIdentifier = existingFile?.identifier || `p-q-manager-858-${uid.rnd()}`;
|
|
const base64File = await fileToBase64(file);
|
|
const encryptedData = await qortalRequest({
|
|
action: "ENCRYPT_DATA_WITH_SHARING_KEY",
|
|
data64: base64File,
|
|
});
|
|
|
|
if(!encryptedData) throw new Error('Unable to encrypt data')
|
|
|
|
let account = await qortalRequest({
|
|
action: "PUBLISH_QDN_RESOURCE",
|
|
service: existingFile?.service || requestData?.service,
|
|
identifier: constructedIdentifier,
|
|
data64: encryptedData,
|
|
});
|
|
|
|
if (account?.identifier) {
|
|
if (!!existingFile) {
|
|
updateByPath({
|
|
...existingFile,
|
|
mimeType: file?.type,
|
|
});
|
|
setFile("");
|
|
return true; // Success
|
|
}
|
|
|
|
addNodeByPath(
|
|
undefined,
|
|
{
|
|
type: "file",
|
|
name: filename,
|
|
mimeType: file?.type,
|
|
qortalName: myName,
|
|
identifier: constructedIdentifier,
|
|
service: requestData?.service,
|
|
},
|
|
undefined
|
|
);
|
|
|
|
|
|
return true; // Success
|
|
} else {
|
|
throw new Error("Unable to publish the file");
|
|
}
|
|
} catch (error) {
|
|
console.error("Error:", error);
|
|
throw error; // Ensure the error is propagated to the toast
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
})();
|
|
|
|
await openToast(promise, {
|
|
loading: "Publishing the file...",
|
|
success: "File published successfully!",
|
|
error: (err) => `Failed to publish: ${err?.error || err?.message || "An unknown error occurred"}`,
|
|
});
|
|
};
|
|
const executeQortalRequest = async () => {
|
|
try {
|
|
setIsLoading(true);
|
|
|
|
const promise = (async () => {
|
|
const fileExtension = file?.name?.includes(".")
|
|
? file.name.split(".").pop()
|
|
: "";
|
|
const fileTitle =
|
|
file?.name
|
|
?.split(".")
|
|
.slice(0, -1)
|
|
.join(".")
|
|
.replace(/ /g, "_")
|
|
.slice(0, 20) || "Untitled";
|
|
const filename = fileExtension
|
|
? `${fileTitle}.${fileExtension}`
|
|
: fileTitle;
|
|
|
|
const constructedIdentifier =
|
|
existingFile?.identifier || `q-manager-858-${uid.rnd()}`;
|
|
const account = await qortalRequest({
|
|
action: "PUBLISH_QDN_RESOURCE",
|
|
service: existingFile?.service || requestData?.service,
|
|
identifier: constructedIdentifier,
|
|
file,
|
|
filename,
|
|
});
|
|
|
|
if (account?.identifier) {
|
|
if (!!existingFile) {
|
|
updateByPath({
|
|
...existingFile,
|
|
mimeType: file?.type,
|
|
});
|
|
setFile("");
|
|
return;
|
|
}
|
|
|
|
addNodeByPath(
|
|
undefined,
|
|
{
|
|
type: "file",
|
|
name: filename,
|
|
mimeType: file?.type,
|
|
qortalName: myName,
|
|
identifier: constructedIdentifier,
|
|
service: requestData?.service,
|
|
},
|
|
undefined
|
|
);
|
|
|
|
if(!existingFile){
|
|
setFile(null)
|
|
}
|
|
return;
|
|
} else {
|
|
throw new Error("Unable to publish the file");
|
|
}
|
|
})();
|
|
|
|
await openToast(promise, {
|
|
loading: "Publishing the file...",
|
|
success: "File published successfully!",
|
|
error: (err) => `Failed to publish: ${err.error || err.message || err}`,
|
|
});
|
|
} catch (error) {
|
|
console.error("Error during publishing:", error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
padding: "10px",
|
|
}}
|
|
>
|
|
<div
|
|
className="card"
|
|
style={{
|
|
background: "rgba(0, 0, 0, 0.1)",
|
|
}}
|
|
>
|
|
<div className="message-row">
|
|
|
|
|
|
<Label>Service</Label>
|
|
<Select
|
|
disabled={!!existingFile}
|
|
size="small"
|
|
labelId="label-select-category"
|
|
id="id-select-category"
|
|
value={requestData?.service}
|
|
displayEmpty
|
|
onChange={(e) =>
|
|
setRequestData((prev) => {
|
|
return {
|
|
...prev,
|
|
service: e.target.value,
|
|
};
|
|
})
|
|
}
|
|
sx={{
|
|
width: "300px",
|
|
}}
|
|
MenuProps={{
|
|
PaperProps: {
|
|
sx: {
|
|
backgroundColor: "#333333", // Background of the dropdown
|
|
color: "#ffffff", // Text color
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
<MenuItem value={0}>
|
|
<em>No service selected</em>
|
|
</MenuItem>
|
|
{(mode === 'private' ? privateServices : services)?.map((service) => {
|
|
return (
|
|
<MenuItem key={service.name} value={service.name}>
|
|
{`${service.name} - max ${service.sizeLabel}`}
|
|
</MenuItem>
|
|
);
|
|
})}
|
|
</Select>
|
|
<button
|
|
{...getRootProps()}
|
|
style={{
|
|
width: "150px",
|
|
}}
|
|
>
|
|
<input {...getInputProps()} />
|
|
Select file
|
|
</button>
|
|
<Typography>{file?.name}</Typography>
|
|
{file && (
|
|
<Button
|
|
name="Remove file"
|
|
bgColor="pink"
|
|
|
|
onClick={() => {
|
|
setFile(null);
|
|
}}
|
|
>
|
|
Remove file
|
|
</Button>
|
|
)}
|
|
|
|
<Button
|
|
name={!!existingFile ? "Edit Publish" :"Publish"}
|
|
bgColor="#309ed1"
|
|
onClick={()=> {
|
|
if(mode ==='group'){
|
|
executeQortalRequestGroup()
|
|
}
|
|
else if(mode === 'private'){
|
|
executeQortalRequestPrivate()
|
|
} else {
|
|
executeQortalRequest()
|
|
}
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|