This commit is contained in:
Aykut Saraç 2022-02-15 17:01:44 +03:00
parent c093575700
commit 1286dbba13
3 changed files with 147 additions and 142 deletions

View File

@ -3,10 +3,7 @@ import Link from "next/link";
import styled from "styled-components"; import styled from "styled-components";
import { useLocalStorage } from "usehooks-ts"; import { useLocalStorage } from "usehooks-ts";
import { FaFileImport } from "react-icons/fa"; import { FaFileImport } from "react-icons/fa";
import { import { MdUnfoldMore, MdUnfoldLess } from "react-icons/md";
MdUnfoldMore,
MdUnfoldLess,
} from "react-icons/md";
import { import {
AiFillHome, AiFillHome,
AiOutlineClear, AiOutlineClear,
@ -25,6 +22,7 @@ import {
import { getNextLayout } from "src/containers/LiveEditor/helpers"; import { getNextLayout } from "src/containers/LiveEditor/helpers";
import { StorageConfig } from "src/typings/global"; import { StorageConfig } from "src/typings/global";
import { CanvasDirection } from "reaflow"; import { CanvasDirection } from "reaflow";
import { useLoading } from "src/hooks/useLoading";
const StyledSidebar = styled.div` const StyledSidebar = styled.div`
display: flex; display: flex;
@ -110,6 +108,8 @@ function getLayoutIcon(layout: CanvasDirection) {
export const Sidebar: React.FC<{ export const Sidebar: React.FC<{
setJson: React.Dispatch<React.SetStateAction<string>>; setJson: React.Dispatch<React.SetStateAction<string>>;
}> = ({ setJson }) => { }> = ({ setJson }) => {
const pageLoaded = useLoading();
const [jsonFile, setJsonFile] = React.useState<File | null>(null); const [jsonFile, setJsonFile] = React.useState<File | null>(null);
const [config, setConfig] = useLocalStorage<StorageConfig>("config", { const [config, setConfig] = useLocalStorage<StorageConfig>("config", {
layout: "LEFT", layout: "LEFT",
@ -117,7 +117,6 @@ export const Sidebar: React.FC<{
controls: true, controls: true,
}); });
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) setJsonFile(e.target.files?.item(0)); if (e.target.files) setJsonFile(e.target.files?.item(0));
}; };
@ -140,89 +139,92 @@ export const Sidebar: React.FC<{
} }
}, [jsonFile, setJson]); }, [jsonFile, setJson]);
return ( if (pageLoaded)
<StyledSidebar> return (
<StyledTopWrapper> <StyledSidebar>
<Link passHref href="/"> <StyledTopWrapper>
<StyledElement as="a"> <Link passHref href="/">
<StyledLogo> <StyledElement as="a">
<StyledText>J</StyledText> <StyledLogo>
<StyledText secondary>V</StyledText> <StyledText>J</StyledText>
</StyledLogo> <StyledText secondary>V</StyledText>
</StyledLogo>
</StyledElement>
</Link>
<StyledElement title="Home">
<Link href="/">
<a>
<AiFillHome />
</a>
</Link>
</StyledElement>
<StyledElement
as="a"
onClick={() => {
setJson("[]");
localStorage.removeItem("json");
}}
title="Clear JSON"
>
<AiOutlineClear />
</StyledElement>
<StyledElement
as="a"
onClick={() =>
setConfig((c) => ({
...c,
layout: getNextLayout(c.layout),
}))
}
title="Change Layout"
>
{getLayoutIcon(config.layout)}
</StyledElement>
<StyledElement
title="Toggle Controls"
as="a"
onClick={() => toggle("controls")}
>
{config.controls ? <AiFillControl /> : <AiOutlineControl />}
</StyledElement> </StyledElement>
</Link>
<StyledElement title="Home">
<Link href="/">
<a>
<AiFillHome />
</a>
</Link>
</StyledElement>
<StyledElement
as="a"
onClick={() => {
setJson("[]");
localStorage.removeItem("json");
}}
title="Clear JSON"
>
<AiOutlineClear />
</StyledElement>
<StyledElement
as="a"
onClick={() =>
setConfig((c) => ({
...c,
layout: getNextLayout(c.layout),
}))
}
title="Change Layout"
>
{getLayoutIcon(config.layout)}
</StyledElement>
<StyledElement
title="Toggle Controls"
as="a"
onClick={() => toggle("controls")}
>
{config.controls ? <AiFillControl /> : <AiOutlineControl />}
</StyledElement>
<StyledElement <StyledElement
as="a" as="a"
title="Toggle Expand/Collapse" title="Toggle Expand/Collapse"
onClick={() => toggle("expand")} onClick={() => toggle("expand")}
> >
{config.expand ? <MdUnfoldMore /> : <MdUnfoldLess />} {config.expand ? <MdUnfoldMore /> : <MdUnfoldLess />}
</StyledElement> </StyledElement>
<StyledElement as="a" title="Import JSON File"> <StyledElement as="a" title="Import JSON File">
<StyledImportFile> <StyledImportFile>
<input <input
key={jsonFile?.name} key={jsonFile?.name}
onChange={handleFileChange} onChange={handleFileChange}
type="file" type="file"
accept="application/JSON" accept="application/JSON"
/> />
<FaFileImport /> <FaFileImport />
</StyledImportFile> </StyledImportFile>
</StyledElement> </StyledElement>
</StyledTopWrapper> </StyledTopWrapper>
<StyledBottomWrapper> <StyledBottomWrapper>
<StyledElement> <StyledElement>
<Link href="https://twitter.com/aykutsarach"> <Link href="https://twitter.com/aykutsarach">
<a rel="me" target="_blank"> <a rel="me" target="_blank">
<AiOutlineTwitter /> <AiOutlineTwitter />
</a> </a>
</Link> </Link>
</StyledElement> </StyledElement>
<StyledElement> <StyledElement>
<Link href="https://github.com/AykutSarac/jsonvisio.com"> <Link href="https://github.com/AykutSarac/jsonvisio.com">
<a rel="me" target="_blank"> <a rel="me" target="_blank">
<AiFillGithub /> <AiFillGithub />
</a> </a>
</Link> </Link>
</StyledElement> </StyledElement>
</StyledBottomWrapper> </StyledBottomWrapper>
</StyledSidebar> </StyledSidebar>
); );
return null;
}; };

View File

@ -18,6 +18,7 @@ import {
AiOutlineFullscreen, AiOutlineFullscreen,
AiFillSave, AiFillSave,
} from "react-icons/ai"; } from "react-icons/ai";
import { useLoading } from "src/hooks/useLoading";
const StyledLiveEditor = styled.div` const StyledLiveEditor = styled.div`
position: relative; position: relative;
@ -47,6 +48,8 @@ export const LiveEditor: React.FC<{
json: string; json: string;
setJson: React.Dispatch<React.SetStateAction<string>>; setJson: React.Dispatch<React.SetStateAction<string>>;
}> = ({ json }) => { }> = ({ json }) => {
const pageLoaded = useLoading();
const canvasRef = React.useRef<CanvasRef | null>(null); const canvasRef = React.useRef<CanvasRef | null>(null);
const wrapperRef = React.useRef<ReactZoomPanPinchRef | null>(null); const wrapperRef = React.useRef<ReactZoomPanPinchRef | null>(null);
const [config] = useLocalStorage<StorageConfig>("config", { const [config] = useLocalStorage<StorageConfig>("config", {
@ -87,55 +90,58 @@ export const LiveEditor: React.FC<{
} }
}; };
return ( if (pageLoaded)
<StyledLiveEditor> return (
<StyledEditorWrapper> <StyledLiveEditor>
<TransformWrapper <StyledEditorWrapper>
maxScale={2} <TransformWrapper
minScale={0.4} maxScale={2}
initialScale={0.8} minScale={0.4}
ref={wrapperRef} initialScale={0.8}
limitToBounds={false} ref={wrapperRef}
wheel={{ limitToBounds={false}
step: 0.4, wheel={{
}} step: 0.4,
> }}
<TransformComponent> >
<Canvas <TransformComponent>
ref={canvasRef} <Canvas
nodes={nodes} ref={canvasRef}
edges={edges} nodes={nodes}
layoutOptions={{ edges={edges}
"elk.direction": config.layout, layoutOptions={{
}} "elk.direction": config.layout,
maxWidth={20000} }}
maxHeight={20000} maxWidth={20000}
center={false} maxHeight={20000}
zoomable={false} center={false}
fit zoomable={false}
readonly fit
animated readonly
node={CustomNode} animated
/> node={CustomNode}
</TransformComponent> />
</TransformWrapper> </TransformComponent>
</StyledEditorWrapper> </TransformWrapper>
{config.controls && ( </StyledEditorWrapper>
<StyledControls> {config.controls && (
<Button onClick={() => zoomIn(0.5)}> <StyledControls>
<AiOutlineZoomIn size={24} /> <Button onClick={() => zoomIn(0.5)}>
</Button> <AiOutlineZoomIn size={24} />
<Button onClick={() => zoomOut(0.4)}> </Button>
<AiOutlineZoomOut size={24} /> <Button onClick={() => zoomOut(0.4)}>
</Button> <AiOutlineZoomOut size={24} />
<Button onClick={() => wrapperRef.current?.resetTransform()}> </Button>
<AiOutlineFullscreen size={24} /> <Button onClick={() => wrapperRef.current?.resetTransform()}>
</Button> <AiOutlineFullscreen size={24} />
<Button onClick={() => localStorage.setItem("json", json)}> </Button>
<AiFillSave size={24} /> <Button onClick={() => localStorage.setItem("json", json)}>
</Button> <AiFillSave size={24} />
</StyledControls> </Button>
)} </StyledControls>
</StyledLiveEditor> )}
); </StyledLiveEditor>
);
return null;
}; };

View File

@ -11,7 +11,6 @@ import { useLoading } from "src/hooks/useLoading";
function AykutSarac({ Component, pageProps }: AppProps) { function AykutSarac({ Component, pageProps }: AppProps) {
const router = useRouter(); const router = useRouter();
const data = useLoading();
const [pageLoading, setPageLoading] = React.useState<boolean>(false); const [pageLoading, setPageLoading] = React.useState<boolean>(false);
React.useEffect(() => { React.useEffect(() => {
@ -38,8 +37,6 @@ function AykutSarac({ Component, pageProps }: AppProps) {
</ThemeProvider> </ThemeProvider>
); );
if (!data) return null;
return ( return (
<ThemeProvider theme={darkTheme}> <ThemeProvider theme={darkTheme}>
<GlobalStyle /> <GlobalStyle />