feat: allow upload file by dropping on screen

This commit is contained in:
AykutSarac 2024-07-24 19:48:25 +03:00
parent 3874575a34
commit 3299a61d83
No known key found for this signature in database
5 changed files with 97 additions and 15 deletions

View File

@ -0,0 +1,60 @@
import React from "react";
import { Group, Text } from "@mantine/core";
import { Dropzone } from "@mantine/dropzone";
import toast from "react-hot-toast";
import { VscCircleSlash, VscFiles } from "react-icons/vsc";
import { FileFormat } from "src/enums/file.enum";
import useFile from "src/store/useFile";
export const FullscreenDropzone = () => {
const setContents = useFile(state => state.setContents);
return (
<Dropzone.FullScreen
maxSize={300 * 1024}
maxFiles={1}
accept={[
"application/json",
"application/x-yaml",
"text/csv",
"application/xml",
"application/toml",
]}
onReject={files => toast.error(`Unable to load file ${files[0].file.name}`)}
onDrop={async e => {
const fileContent = await e[0].text();
let fileExtension = e[0].name.split(".").pop() as FileFormat | undefined;
if (!fileExtension) fileExtension = FileFormat.JSON;
setContents({ contents: fileContent, format: fileExtension, hasChanges: false });
}}
>
<Group
justify="center"
ta="center"
align="center"
gap="xl"
h="100vh"
style={{ pointerEvents: "none" }}
>
<Dropzone.Accept>
<VscFiles size={100} />
<Text fz="h1" fw={500} mt="lg">
Upload to JSON Crack
</Text>
<Text fz="lg" c="dimmed" mt="sm">
(Max file size: 4 MB)
</Text>
</Dropzone.Accept>
<Dropzone.Reject>
<VscCircleSlash size={100} />
<Text fz="h1" fw={500} mt="lg">
Invalid file
</Text>
<Text fz="lg" c="dimmed" mt="sm">
Allowed formats are JSON, YAML, CSV, XML, TOML
</Text>
</Dropzone.Reject>
</Group>
</Dropzone.FullScreen>
);
};

View File

@ -4,6 +4,7 @@ import styled from "styled-components";
import { Allotment } from "allotment";
import "allotment/dist/style.css";
import useGraph from "src/modules/GraphView/stores/useGraph";
import { FullscreenDropzone } from "./FullscreenDropzone";
export const StyledEditor = styled(Allotment)`
position: relative !important;
@ -28,18 +29,21 @@ export const Editor = () => {
const fullscreen = useGraph(state => state.fullscreen);
return (
<StyledEditor proportionalLayout={false}>
<Allotment.Pane
preferredSize={450}
minSize={fullscreen ? 0 : 300}
maxSize={800}
visible={!fullscreen}
>
<TextEditor />
</Allotment.Pane>
<Allotment.Pane minSize={0}>
<LiveEditor />
</Allotment.Pane>
</StyledEditor>
<>
<StyledEditor proportionalLayout={false}>
<Allotment.Pane
preferredSize={450}
minSize={fullscreen ? 0 : 300}
maxSize={800}
visible={!fullscreen}
>
<TextEditor />
</Allotment.Pane>
<Allotment.Pane minSize={0}>
<LiveEditor />
</Allotment.Pane>
</StyledEditor>
<FullscreenDropzone />
</>
);
};

View File

@ -104,6 +104,17 @@ export const Navbar = () => {
>
Sign in
</Button>
<Button
component="a"
color="brightBlue"
href="/editor"
radius="md"
visibleFrom="sm"
size="md"
fw={600}
>
Start for free
</Button>
</Right>
</StyledNavbar>
</StyledNavbarWrapper>

View File

@ -3,6 +3,7 @@ import dynamic from "next/dynamic";
import Head from "next/head";
import { useRouter } from "next/router";
import { useMantineColorScheme } from "@mantine/core";
import "@mantine/dropzone/styles.css";
import styled, { ThemeProvider } from "styled-components";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { metaDescription } from "src/constants/landing";

View File

@ -14,6 +14,7 @@ type SetContents = {
contents?: string;
hasChanges?: boolean;
skipUpdate?: boolean;
format?: FileFormat;
};
type Query = string | string[] | undefined;
@ -96,9 +97,14 @@ const useFile = create<FileStates & JsonActions>()((set, get) => ({
console.warn("The content was unable to be converted, so it was cleared instead.");
}
},
setContents: async ({ contents, hasChanges = true, skipUpdate = false }) => {
setContents: async ({ contents, hasChanges = true, skipUpdate = false, format }) => {
try {
set({ ...(contents && { contents }), error: null, hasChanges });
set({
...(contents && { contents }),
error: null,
hasChanges,
format: format ?? get().format,
});
const isFetchURL = window.location.href.includes("?");
const json = await contentToJson(get().contents, get().format);