update icons & options

This commit is contained in:
AykutSarac 2022-05-04 21:08:17 +03:00
parent c71832525e
commit 0539e0b72f
7 changed files with 84 additions and 109 deletions

View File

@ -1,29 +1,22 @@
import React from "react"; import React from "react";
import toast from "react-hot-toast";
import Link from "next/link"; import Link from "next/link";
import styled from "styled-components"; import styled from "styled-components";
import { FaFileImport } from "react-icons/fa"; 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 { import {
MdUnfoldMore, AiOutlineDelete,
MdUnfoldLess,
MdAutoFixHigh,
MdOutlineAutoFixOff,
} from "react-icons/md";
import {
AiFillHome,
AiFillDelete,
AiFillGithub, AiFillGithub,
AiOutlineTwitter, AiOutlineTwitter,
AiOutlineSave,
AiOutlineFileAdd,
} from "react-icons/ai"; } from "react-icons/ai";
import {
CgArrowLongDownE,
CgArrowLongLeftE,
CgArrowLongRightE,
CgArrowLongUpE,
} from "react-icons/cg";
import { CanvasDirection } from "reaflow"; import { Tooltip } from "src/components/Tooltip";
import toast from "react-hot-toast";
import { Tooltip } from "../Tooltip";
import { ConfigActionType } from "src/reducer/reducer"; import { ConfigActionType } from "src/reducer/reducer";
import { useConfig } from "src/hocs/config"; import { useConfig } from "src/hocs/config";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@ -33,7 +26,7 @@ const StyledSidebar = styled.div`
justify-content: space-between; justify-content: space-between;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
width: 42px; width: 36px;
background: ${({ theme }) => theme.BACKGROUND_TERTIARY}; background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
padding: 8px; padding: 8px;
border-right: 1px solid ${({ theme }) => theme.BACKGROUND_MODIFIER_ACCENT}; border-right: 1px solid ${({ theme }) => theme.BACKGROUND_MODIFIER_ACCENT};
@ -64,6 +57,10 @@ const StyledText = styled.span<{ secondary?: boolean }>`
secondary ? theme.INTERACTIVE_NORMAL : theme.ORANGE}; secondary ? theme.INTERACTIVE_NORMAL : theme.ORANGE};
`; `;
const StyledFlowIcon = styled(TiFlowMerge)<{ rotate: number }>`
transform: rotate(${({ rotate }) => `${rotate}deg`});
`;
const StyledTopWrapper = styled.nav` const StyledTopWrapper = styled.nav`
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -101,15 +98,15 @@ const StyledImportFile = styled.label`
} }
`; `;
function getLayoutIcon(layout: CanvasDirection) { function rotateLayout(layout: CanvasDirection) {
if (layout === "LEFT") return <CgArrowLongLeftE />; if (layout === "LEFT") return 90;
if (layout === "UP") return <CgArrowLongUpE />; if (layout === "UP") return 180;
if (layout === "RIGHT") return <CgArrowLongRightE />; if (layout === "RIGHT") return 270;
return <CgArrowLongDownE />; return 360;
} }
export const Sidebar: React.FC = () => { export const Sidebar: React.FC = () => {
const { settings, dispatch } = useConfig(); const { json, settings, dispatch } = useConfig();
const router = useRouter(); const router = useRouter();
const [jsonFile, setJsonFile] = React.useState<File | null>(null); const [jsonFile, setJsonFile] = React.useState<File | null>(null);
@ -123,11 +120,9 @@ export const Sidebar: React.FC = () => {
toast.success(`Cleared JSON and removed from memory.`); toast.success(`Cleared JSON and removed from memory.`);
}; };
const toggleAutoFormat = () => { const handleSave = () => {
dispatch({ type: ConfigActionType.TOGGLE_AUTOFORMAT }); localStorage.setItem("json", json);
toast( toast.success("Saved JSON successfully!");
`Auto format has been ${settings.autoformat ? "disabled." : "enabled."}`
);
}; };
const toggleExpandCollapse = () => { const toggleExpandCollapse = () => {
@ -160,36 +155,6 @@ export const Sidebar: React.FC = () => {
</StyledLogo> </StyledLogo>
</StyledElement> </StyledElement>
</Link> </Link>
<Tooltip title="Home">
<StyledElement onClick={() => router.push("/")}>
<AiFillHome />
</StyledElement>
</Tooltip>
<Tooltip title="Auto Format">
<StyledElement onClick={toggleAutoFormat}>
{settings.autoformat ? <MdAutoFixHigh /> : <MdOutlineAutoFixOff />}
</StyledElement>
</Tooltip>
<Tooltip title="Change Layout">
<StyledElement
onClick={() => dispatch({ type: ConfigActionType.TOGGLE_LAYOUT })}
>
{getLayoutIcon(settings.layout)}
</StyledElement>
</Tooltip>
<Tooltip title="Toggle Compact Nodes">
<StyledElement
title="Toggle Expand/Collapse"
onClick={toggleExpandCollapse}
>
{settings.expand ? <MdUnfoldMore /> : <MdUnfoldLess />}
</StyledElement>
</Tooltip>
<Tooltip title="Clear JSON">
<StyledElement onClick={handleClear}>
<AiFillDelete />
</StyledElement>
</Tooltip>
<Tooltip title="Import File"> <Tooltip title="Import File">
<StyledElement> <StyledElement>
<StyledImportFile> <StyledImportFile>
@ -199,10 +164,35 @@ export const Sidebar: React.FC = () => {
type="file" type="file"
accept="application/JSON" accept="application/JSON"
/> />
<FaFileImport /> <AiOutlineFileAdd />
</StyledImportFile> </StyledImportFile>
</StyledElement> </StyledElement>
</Tooltip> </Tooltip>
<Tooltip title="Change Layout">
<StyledElement
onClick={() => dispatch({ type: ConfigActionType.TOGGLE_LAYOUT })}
>
<StyledFlowIcon rotate={rotateLayout(settings.layout)} />
</StyledElement>
</Tooltip>
<Tooltip title={settings.expand ? "Shrink Nodes" : "Expand Nodes"}>
<StyledElement
title="Toggle Expand/Collapse"
onClick={toggleExpandCollapse}
>
{settings.expand ? <CgArrowsMergeAltH /> : <CgArrowsShrinkH />}
</StyledElement>
</Tooltip>
<Tooltip title="Clear JSON">
<StyledElement onClick={handleClear}>
<AiOutlineDelete />
</StyledElement>
</Tooltip>
<Tooltip title="Save JSON">
<StyledElement onClick={handleSave}>
<AiOutlineSave />
</StyledElement>
</Tooltip>
</StyledTopWrapper> </StyledTopWrapper>
<StyledBottomWrapper> <StyledBottomWrapper>
<StyledElement> <StyledElement>
@ -219,6 +209,13 @@ export const Sidebar: React.FC = () => {
</a> </a>
</Link> </Link>
</StyledElement> </StyledElement>
<StyledElement>
<Link href="https://www.patreon.com/aykutsarac">
<a aria-label="Patreon" rel="me" target="_blank">
<RiPatreonFill />
</a>
</Link>
</StyledElement>
</StyledBottomWrapper> </StyledBottomWrapper>
</StyledSidebar> </StyledSidebar>
); );

View File

@ -15,7 +15,7 @@ const StyledTooltip = styled.div<{ visible: boolean }>`
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
transform: translate(calc(100% + 15px), 25%); transform: translate(calc(100% + 15px), 20%);
z-index: 5; z-index: 5;
background: ${({ theme }) => theme.BACKGROUND_PRIMARY}; background: ${({ theme }) => theme.BACKGROUND_PRIMARY};
color: ${({ theme }) => theme.TEXT_NORMAL}; color: ${({ theme }) => theme.TEXT_NORMAL};

View File

@ -36,7 +36,6 @@ export const defaultJson = {
export const defaultConfig: StorageConfig = { export const defaultConfig: StorageConfig = {
layout: "RIGHT", layout: "RIGHT",
expand: true, expand: true,
autoformat: true,
hideEditor: false, hideEditor: false,
zoomPanPinch: null, zoomPanPinch: null,
lightmode: false lightmode: false

View File

@ -2,10 +2,10 @@ import React from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { import {
AiOutlineFullscreen, AiOutlineFullscreen,
AiOutlineSave,
AiOutlineMinus, AiOutlineMinus,
AiOutlinePlus, AiOutlinePlus,
} from "react-icons/ai"; } from "react-icons/ai";
import { FiDownload } from "react-icons/fi";
import { HiOutlineSun, HiOutlineMoon } from "react-icons/hi"; import { HiOutlineSun, HiOutlineMoon } from "react-icons/hi";
import { MdCenterFocusWeak } from "react-icons/md"; import { MdCenterFocusWeak } from "react-icons/md";
import { Input } from "src/components/Input"; import { Input } from "src/components/Input";
@ -42,10 +42,6 @@ const StyledToolElement = styled.button`
export const Tools: React.FC = () => { export const Tools: React.FC = () => {
const { json, settings, dispatch } = useConfig(); const { json, settings, dispatch } = useConfig();
const handleSave = () => {
localStorage.setItem("json", json);
toast.success("Saved JSON successfully!");
};
const zoomIn = () => dispatch({ type: ConfigActionType.ZOOM_IN }); const zoomIn = () => dispatch({ type: ConfigActionType.ZOOM_IN });
@ -66,8 +62,13 @@ export const Tools: React.FC = () => {
{settings.lightmode ? <HiOutlineMoon /> : <HiOutlineSun />} {settings.lightmode ? <HiOutlineMoon /> : <HiOutlineSun />}
</StyledToolElement> </StyledToolElement>
<Input /> <Input />
<StyledToolElement aria-label="save" onClick={handleSave}> <StyledToolElement
<AiOutlineSave /> aria-label="save"
onClick={() => {
// export as png
}}
>
<FiDownload />
</StyledToolElement> </StyledToolElement>
<StyledToolElement aria-label="center canvas" onClick={centerView}> <StyledToolElement aria-label="center canvas" onClick={centerView}>
<MdCenterFocusWeak /> <MdCenterFocusWeak />

View File

@ -2,7 +2,7 @@ import React from "react";
import Editor from "@monaco-editor/react"; import Editor from "@monaco-editor/react";
import parseJson from "parse-json"; import parseJson from "parse-json";
import styled from "styled-components"; import styled from "styled-components";
import { ErrorContainer } from "../../components/ErrorContainer/ErrorContainer"; import { ErrorContainer } from "src/components/ErrorContainer/ErrorContainer";
import { ConfigActionType } from "src/reducer/reducer"; import { ConfigActionType } from "src/reducer/reducer";
import { useConfig } from "src/hocs/config"; import { useConfig } from "src/hocs/config";
import { Loading } from "src/components/Loading"; import { Loading } from "src/components/Loading";
@ -16,6 +16,7 @@ const StyledEditorWrapper = styled.div`
`; `;
const editorOptions = { const editorOptions = {
formatOnPaste: true,
minimap: { minimap: {
enabled: false, enabled: false,
}, },
@ -35,36 +36,24 @@ export const JsonEditor: React.FC = () => {
); );
React.useEffect(() => { React.useEffect(() => {
if (settings.autoformat) { setValue(JSON.stringify(JSON.parse(json), null, 2));
return setValue(JSON.stringify(JSON.parse(json), null, 2)); }, [json]);
}
setValue(json);
}, [settings.autoformat, json]);
React.useEffect(() => { React.useEffect(() => {
const formatTimer = setTimeout( const formatTimer = setTimeout(() => {
() => {
try { try {
if (value) { if (!value) {
const parsedJson = parseJson(value); setError((err) => ({ ...err, message: "" }));
return dispatch({ type: ConfigActionType.SET_JSON, payload: "[]" });
if (settings.autoformat) {
setValue(JSON.stringify(parsedJson, null, 2));
} else {
setValue(value);
} }
parseJson(value);
dispatch({ type: ConfigActionType.SET_JSON, payload: value }); dispatch({ type: ConfigActionType.SET_JSON, payload: value });
}
setError((err) => ({ ...err, message: "" })); setError((err) => ({ ...err, message: "" }));
} catch (jsonError: any) { } catch (jsonError: any) {
setError((err) => ({ ...err, message: jsonError.message })); setError((err) => ({ ...err, message: jsonError.message }));
} }
}, }, 1500);
settings.autoformat ? 1200 : 1800
);
return () => clearTimeout(formatTimer); return () => clearTimeout(formatTimer);
}, [value, dispatch]); }, [value, dispatch]);
@ -76,8 +65,8 @@ export const JsonEditor: React.FC = () => {
height="100%" height="100%"
defaultLanguage="json" defaultLanguage="json"
value={value} value={value}
options={editorOptions}
theme={editorTheme} theme={editorTheme}
options={editorOptions}
loading={<Loading message="Loading Editor..." />} loading={<Loading message="Loading Editor..." />}
onChange={(value) => setValue(value as string)} onChange={(value) => setValue(value as string)}
/> />

View File

@ -6,7 +6,6 @@ export enum ConfigActionType {
SET_CONFIG, SET_CONFIG,
TOGGLE_LAYOUT, TOGGLE_LAYOUT,
TOGGLE_EXPAND, TOGGLE_EXPAND,
TOGGLE_AUTOFORMAT,
TOGGLE_DOCK, TOGGLE_DOCK,
TOGGLE_THEME, TOGGLE_THEME,
ZOOM_IN, ZOOM_IN,
@ -70,15 +69,6 @@ export const useConfigReducer: React.Reducer<AppConfig, ReducerAction> = (
); );
return state; return state;
case ConfigActionType.TOGGLE_AUTOFORMAT:
return {
...state,
settings: {
...state.settings,
autoformat: !state.settings.autoformat,
},
};
case ConfigActionType.TOGGLE_DOCK: case ConfigActionType.TOGGLE_DOCK:
return { return {
...state, ...state,

View File

@ -5,7 +5,6 @@ import { CanvasDirection } from "reaflow";
export interface StorageConfig { export interface StorageConfig {
layout: CanvasDirection; layout: CanvasDirection;
expand: boolean; expand: boolean;
autoformat: boolean;
hideEditor: boolean; hideEditor: boolean;
zoomPanPinch: ReactZoomPanPinchRef | null; zoomPanPinch: ReactZoomPanPinchRef | null;
lightmode: boolean; lightmode: boolean;