mirror of
https://github.com/AykutSarac/jsoncrack.com.git
synced 2025-01-20 05:12:54 +08:00
update icons & options
This commit is contained in:
parent
c71832525e
commit
0539e0b72f
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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};
|
||||||
|
@ -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
|
||||||
|
@ -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 />
|
||||||
|
@ -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);
|
|
||||||
|
|
||||||
if (settings.autoformat) {
|
|
||||||
setValue(JSON.stringify(parsedJson, null, 2));
|
|
||||||
} else {
|
|
||||||
setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({ type: ConfigActionType.SET_JSON, payload: value });
|
|
||||||
}
|
|
||||||
|
|
||||||
setError((err) => ({ ...err, message: "" }));
|
setError((err) => ({ ...err, message: "" }));
|
||||||
} catch (jsonError: any) {
|
return dispatch({ type: ConfigActionType.SET_JSON, payload: "[]" });
|
||||||
setError((err) => ({ ...err, message: jsonError.message }));
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
settings.autoformat ? 1200 : 1800
|
parseJson(value);
|
||||||
);
|
dispatch({ type: ConfigActionType.SET_JSON, payload: value });
|
||||||
|
setError((err) => ({ ...err, message: "" }));
|
||||||
|
} catch (jsonError: any) {
|
||||||
|
setError((err) => ({ ...err, message: jsonError.message }));
|
||||||
|
}
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
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)}
|
||||||
/>
|
/>
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user