|
import React from "react"; |
|
import { Modal, Group, Button, TextInput, Stack, Divider, ModalProps } from "@mantine/core"; |
|
import styled from "styled-components"; |
|
import toast from "react-hot-toast"; |
|
import { AiOutlineUpload } from "react-icons/ai"; |
|
import useFile from "src/store/useFile"; |
|
|
|
const StyledUploadWrapper = styled.label` |
|
display: flex; |
|
flex-direction: column; |
|
justify-content: center; |
|
align-items: center; |
|
background: ${({ theme }) => theme.GRID_BG_COLOR}; |
|
border: 2px dashed ${({ theme }) => theme.BACKGROUND_TERTIARY}; |
|
border-radius: 5px; |
|
min-height: 200px; |
|
padding: 16px; |
|
cursor: pointer; |
|
|
|
input[type="file"] { |
|
display: none; |
|
} |
|
`; |
|
|
|
const StyledFileName = styled.span` |
|
padding-top: 14px; |
|
color: ${({ theme }) => theme.INTERACTIVE_NORMAL}; |
|
`; |
|
|
|
const StyledUploadMessage = styled.h3` |
|
color: ${({ theme }) => theme.INTERACTIVE_ACTIVE}; |
|
margin-bottom: 0; |
|
`; |
|
|
|
export const ImportModal: React.FC<ModalProps> = ({ opened, onClose }) => { |
|
const setContents = useFile(state => state.setContents); |
|
const [url, setURL] = React.useState(""); |
|
const [jsonFile, setJsonFile] = React.useState<File | null>(null); |
|
|
|
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { |
|
if (e.target.files) setJsonFile(e.target.files?.item(0)); |
|
}; |
|
|
|
const handleFileDrag = (e: React.DragEvent<HTMLLabelElement>) => { |
|
e.preventDefault(); |
|
|
|
if (e.type === "drop" && e.dataTransfer.files.length) { |
|
if (e.dataTransfer.files[0].type === "application/json") { |
|
setJsonFile(e.dataTransfer.files[0]); |
|
} else { |
|
toast.error("Please upload JSON file!"); |
|
} |
|
} |
|
}; |
|
|
|
const handleImportFile = () => { |
|
if (url) { |
|
setJsonFile(null); |
|
|
|
toast.loading("Loading...", { id: "toastFetch" }); |
|
return fetch(url) |
|
.then(res => res.json()) |
|
.then(json => { |
|
setContents({ contents: JSON.stringify(json, null, 2) }); |
|
onClose(); |
|
}) |
|
.catch(() => toast.error("Failed to fetch JSON!")) |
|
.finally(() => toast.dismiss("toastFetch")); |
|
} |
|
|
|
if (jsonFile) { |
|
const reader = new FileReader(); |
|
|
|
reader.readAsText(jsonFile, "UTF-8"); |
|
reader.onload = function (data) { |
|
if (typeof data.target?.result === "string") setContents({ contents: data.target?.result }); |
|
onClose(); |
|
}; |
|
} |
|
}; |
|
|
|
return ( |
|
<Modal title="Import JSON" opened={opened} onClose={onClose} centered> |
|
<Stack py="sm"> |
|
<TextInput |
|
value={url} |
|
onChange={e => setURL(e.target.value)} |
|
type="url" |
|
placeholder="URL of JSON to fetch" |
|
data-autofocus |
|
/> |
|
<StyledUploadWrapper onDrop={handleFileDrag} onDragOver={handleFileDrag}> |
|
<input |
|
key={jsonFile?.name} |
|
onChange={handleFileChange} |
|
type="file" |
|
accept="application/JSON" |
|
/> |
|
<AiOutlineUpload size={48} /> |
|
<StyledUploadMessage>Click Here to Upload JSON</StyledUploadMessage> |
|
<StyledFileName>{jsonFile?.name ?? "None"}</StyledFileName> |
|
</StyledUploadWrapper> |
|
</Stack> |
|
<Divider my="xs" /> |
|
<Group justify="right"> |
|
<Button onClick={handleImportFile} disabled={!(jsonFile || url)}> |
|
Import |
|
</Button> |
|
</Group> |
|
</Modal> |
|
); |
|
}; |
|
|