From 7be8e3dbee37712fb1b1a26a054478488dd24040 Mon Sep 17 00:00:00 2001 From: AykutSarac Date: Sat, 7 May 2022 15:57:00 +0300 Subject: [PATCH] modify import from url implementation --- src/components/Sidebar/index.tsx | 58 +++----- src/containers/Editor/Tools.tsx | 4 +- src/containers/ImportModal/index.tsx | 134 ++++++++++++++++++ .../SearchInput}/index.tsx | 2 +- src/pages/index.tsx | 2 +- 5 files changed, 155 insertions(+), 45 deletions(-) create mode 100644 src/containers/ImportModal/index.tsx rename src/{components/Input => containers/SearchInput}/index.tsx (97%) diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index 4aac082..11ad74c 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -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(null); - const [visible, setVisible] = React.useState(false); + const [modalVisible, setModalVisible] = React.useState(false); const handleFileChange = (e: React.ChangeEvent) => { 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 ( - + router.push("/")}> @@ -164,21 +153,8 @@ export const Sidebar: React.FC = () => { - - - - - - - - - - + setModalVisible(true)}> + diff --git a/src/containers/Editor/Tools.tsx b/src/containers/Editor/Tools.tsx index b3b23e8..7de7e86 100644 --- a/src/containers/Editor/Tools.tsx +++ b/src/containers/Editor/Tools.tsx @@ -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 = () => { {settings.lightmode ? : } - + diff --git a/src/containers/ImportModal/index.tsx b/src/containers/ImportModal/index.tsx new file mode 100644 index 0000000..ad739c8 --- /dev/null +++ b/src/containers/ImportModal/index.tsx @@ -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(null); + + const handleFileChange = (e: React.ChangeEvent) => { + 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 ( + + Select An Import Method + + setURL(e.target.value)} + type="url" + placeholder="URL of JSON to fetch" + /> + + + + Click Here to Upload JSON + {jsonFile?.name ?? "None"} + + + + + + + ); +}; diff --git a/src/components/Input/index.tsx b/src/containers/SearchInput/index.tsx similarity index 97% rename from src/components/Input/index.tsx rename to src/containers/SearchInput/index.tsx index b7c3698..18d95a3 100644 --- a/src/components/Input/index.tsx +++ b/src/containers/SearchInput/index.tsx @@ -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) => { diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 03e1521..091cf61 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -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;