modify import from url implementation

This commit is contained in:
AykutSarac 2022-05-07 15:57:00 +03:00
parent cc77dde5dd
commit 7be8e3dbee
5 changed files with 155 additions and 45 deletions

View File

@ -4,8 +4,6 @@ import Link from "next/link";
import styled from "styled-components";
import { CanvasDirection } from "reaflow";
import { TiFlowMerge } from "react-icons/ti";
import { BsList } from "react-icons/bs";
import { MdUploadFile } from "react-icons/md";
import { RiPatreonFill } from "react-icons/ri";
import { CgArrowsMergeAltH, CgArrowsShrinkH } from "react-icons/cg";
import {
@ -14,23 +12,22 @@ import {
AiOutlineTwitter,
AiOutlineSave,
AiOutlineFileAdd,
AiOutlineLink,
} from "react-icons/ai";
import { Tooltip } from "src/components/Tooltip";
import { Modal } from "src/components/Modal/index";
import { ConfigActionType } from "src/reducer/reducer";
import { useConfig } from "src/hocs/config";
import { useRouter } from "next/router";
import { ImportModal } from "src/containers/ImportModal";
const StyledSidebar = styled.div`
display: flex;
justify-content: space-between;
flex-direction: column;
align-items: center;
width: 36px;
width: fit-content;
background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
padding: 8px;
padding: 4px;
border-right: 1px solid ${({ theme }) => theme.BACKGROUND_MODIFIER_ACCENT};
`;
@ -39,18 +36,22 @@ const StyledElement = styled.div`
justify-content: center;
text-align: center;
font-size: 28px;
font-weight: 700;
font-weight: 600;
width: 100%;
color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
cursor: pointer;
&:hover :is(a, svg) {
color: ${({ theme }) => theme.INTERACTIVE_HOVER};
svg {
padding: 8px;
vertical-align: middle;
}
svg {
padding: 8px 0;
vertical-align: middle;
a {
display: flex;
}
&:hover :is(a, svg) {
color: ${({ theme }) => theme.INTERACTIVE_HOVER};
}
`;
@ -92,14 +93,6 @@ const StyledLogo = styled.div`
color: ${({ theme }) => theme.FULL_WHITE};
`;
const StyledImportFile = styled.label`
cursor: pointer;
input[type="file"] {
display: none;
}
`;
function rotateLayout(layout: CanvasDirection) {
if (layout === "LEFT") return 90;
if (layout === "UP") return 180;
@ -111,16 +104,12 @@ export const Sidebar: React.FC = () => {
const { json, settings, dispatch } = useConfig();
const router = useRouter();
const [jsonFile, setJsonFile] = React.useState<File | null>(null);
const [visible, setVisible] = React.useState(false);
const [modalVisible, setModalVisible] = React.useState(false);
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) setJsonFile(e.target.files?.item(0));
};
const handleImportJSONFromURL = () => {
setVisible(true);
};
const handleClear = () => {
dispatch({ type: ConfigActionType.SET_JSON, payload: "{}" });
localStorage.removeItem("json");
@ -154,7 +143,7 @@ export const Sidebar: React.FC = () => {
return (
<StyledSidebar>
<StyledTopWrapper>
<Modal visible={visible} setVisible={setVisible} />
<ImportModal visible={modalVisible} setVisible={setModalVisible} />
<Link passHref href="/">
<StyledElement onClick={() => router.push("/")}>
<StyledLogo>
@ -164,21 +153,8 @@ export const Sidebar: React.FC = () => {
</StyledElement>
</Link>
<Tooltip title="Import File">
<StyledElement>
<StyledImportFile>
<input
key={jsonFile?.name}
onChange={handleFileChange}
type="file"
accept="application/JSON"
/>
<AiOutlineFileAdd />
</StyledImportFile>
</StyledElement>
</Tooltip>
<Tooltip title="Fetch JSON from URL">
<StyledElement onClick={handleImportJSONFromURL}>
<AiOutlineLink />
<StyledElement onClick={() => setModalVisible(true)}>
<AiOutlineFileAdd />
</StyledElement>
</Tooltip>
<Tooltip title="Rotate Layout">

View File

@ -8,7 +8,7 @@ import {
import { FiDownload } from "react-icons/fi";
import { HiOutlineSun, HiOutlineMoon } from "react-icons/hi";
import { MdCenterFocusWeak } from "react-icons/md";
import { Input } from "src/components/Input";
import { SearchInput } from "src/containers/SearchInput";
import { useConfig } from "src/hocs/config";
import { ConfigActionType } from "src/reducer/reducer";
import styled from "styled-components";
@ -68,7 +68,7 @@ export const Tools: React.FC = () => {
<StyledToolElement aria-label="switch theme" onClick={toggleTheme}>
{settings.lightmode ? <HiOutlineMoon /> : <HiOutlineSun />}
</StyledToolElement>
<Input />
<SearchInput />
<StyledToolElement aria-label="save" onClick={exportAsImage}>
<FiDownload />
</StyledToolElement>

View File

@ -0,0 +1,134 @@
import React from "react";
import styled from "styled-components";
import toast from "react-hot-toast";
import { useConfig } from "src/hocs/config";
import { ConfigActionType } from "src/reducer/reducer";
import { Modal } from "src/components/Modal";
import { Button } from "src/components/Button";
import { AiOutlineUpload } from "react-icons/ai";
const StyledInput = styled.input`
background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
outline: none;
border: none;
border-radius: 5px;
padding: 6px 8px;
width: 100%;
margin-bottom: 10px;
`;
const StyledModalContent = styled(Modal.Content)`
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
`;
const StyledUploadWrapper = styled.label`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: ${({ theme }) => theme.BACKGROUND_SECONDARY};
border: 2px dashed ${({ theme }) => theme.BACKGROUND_TERTIARY};
border-radius: 5px;
width: 100%;
padding: 16px;
cursor: pointer;
input[type="file"] {
display: none;
}
`;
const StyledFileName = styled.span`
color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
`;
const StyledUploadMessage = styled.h3`
color: ${({ theme }) => theme.INTERACTIVE_ACTIVE};
margin-bottom: 0;
`;
export const ImportModal = ({ visible, setVisible }) => {
const { dispatch } = useConfig();
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 handleImportFile = () => {
if (url) {
setJsonFile(null);
return fetch(url)
.then((res) => res.json())
.then((json) => {
dispatch({
type: ConfigActionType.SET_JSON,
payload: JSON.stringify(json),
});
setVisible(false);
})
.catch(() => toast.error("Failed to fetch JSON!"));
}
if (jsonFile) {
const reader = new FileReader();
reader.readAsText(jsonFile, "UTF-8");
reader.onload = function (data) {
dispatch({
type: ConfigActionType.SET_JSON,
payload: data.target?.result as string,
});
};
}
};
React.useEffect(() => {
return () => {
setJsonFile(null);
setURL("");
};
}, [visible]);
return (
<Modal visible={visible} setVisible={setVisible}>
<Modal.Header>Select An Import Method</Modal.Header>
<StyledModalContent>
<StyledInput
value={url}
onChange={(e) => setURL(e.target.value)}
type="url"
placeholder="URL of JSON to fetch"
/>
<StyledUploadWrapper>
<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>
</StyledModalContent>
<Modal.Controls setVisible={setVisible}>
<Button
status="SECONDARY"
onClick={handleImportFile}
disabled={!(jsonFile || url)}
>
Import
</Button>
</Modal.Controls>
</Modal>
);
};

View File

@ -51,7 +51,7 @@ const StyledSearchButton = styled.button`
}
`;
export const Input: React.FC = () => {
export const SearchInput: React.FC = () => {
const [content, setContent, skip] = useFocusNode();
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {

View File

@ -3,12 +3,12 @@ import { Button } from "src/components/Button";
import { Container } from "src/components/Container";
import { Navbar } from "src/components/Navbar";
import { Image } from "src/components/Image";
import styled from "styled-components";
import { AiFillGithub } from "react-icons/ai";
import { Footer } from "src/components/Footer";
import Head from "next/head";
import { Producthunt } from "src/components/Producthunt";
import { useRouter } from "next/router";
import styled from "styled-components";
const StyledHome = styled.div`
padding: 24px;