Add Fetch JSON from URL

Added a button in sidebar to show a modal which has inputs to type in the url of json to fetch.
This commit is contained in:
Hyunseung Lee 2022-05-06 21:32:16 +09:00
parent b3afea6f1c
commit 4bf74a4476
2 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,103 @@
import React from "react";
import styled, { DefaultTheme } from "styled-components";
import toast from "react-hot-toast";
import { useConfig } from "src/hocs/config";
import { ConfigActionType } from "src/reducer/reducer";
enum ButtonType {
PRIMARY = "PRIMARY",
SECONDARY = "BLURPLE",
DANGER = "DANGER",
SUCCESS = "SEAGREEN",
WARNING = "ORANGE",
}
function getButtonStatus(status: keyof typeof ButtonType, theme: DefaultTheme) {
return theme[ButtonType[status]];
}
const StyledModalWrapper = styled.div`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 5;
display: flex;
justify-content: center;
align-items: center;
`;
const StyledInput = styled.input`
background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
outline: none;
border: none;
border-radius: 5px;
padding: 10px;
margin: 10px 0;
display: block;
width: 100%;
`;
const StyledButton = styled.button<{ status: keyof typeof ButtonType }>`
background: ${({ status, theme }) => getButtonStatus(status, theme)};
color: #ffffff;
padding: 8px 16px;
min-width: 60px;
margin-right: 10px;
@media only screen and (max-width: 768px) {
font-size: 18px;
}
`;
export const Modal = ({ visible, setVisible }) => {
const { json, settings, dispatch } = useConfig();
const inputRef = React.useRef<HTMLInputElement | null>(null);
const fetchJSON = () => {
fetch(inputRef.current!.value)
.then((res) => res.json())
.then((json) => {
dispatch({
type: ConfigActionType.SET_JSON,
payload: JSON.stringify(json),
});
setVisible(false);
})
.catch((err) => toast.error(err.message));
};
const cancel = () => {
setVisible(false);
};
return (
visible && (
<StyledModalWrapper>
<div>
<h2>Import JSON from URL</h2>
<div>
<StyledInput
ref={inputRef}
type="url"
placeholder="URL of JSON to fetch"
/>
<StyledButton status="PRIMARY" onClick={fetchJSON}>
Import
</StyledButton>
<StyledButton status="DANGER" onClick={cancel}>
Cancel
</StyledButton>
</div>
</div>
</StyledModalWrapper>
)
);
};

View File

@ -14,9 +14,11 @@ 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";
@ -109,11 +111,16 @@ 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 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");
@ -147,6 +154,7 @@ export const Sidebar: React.FC = () => {
return (
<StyledSidebar>
<StyledTopWrapper>
<Modal visible={visible} setVisible={setVisible} />
<Link passHref href="/">
<StyledElement onClick={() => router.push("/")}>
<StyledLogo>
@ -168,6 +176,11 @@ export const Sidebar: React.FC = () => {
</StyledImportFile>
</StyledElement>
</Tooltip>
<Tooltip title="Fetch JSON from URL">
<StyledElement onClick={handleImportJSONFromURL}>
<AiOutlineLink />
</StyledElement>
</Tooltip>
<Tooltip title="Rotate Layout">
<StyledElement
onClick={() => dispatch({ type: ConfigActionType.TOGGLE_LAYOUT })}