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 toast from "react-hot-toast";
|
||||
import Link from "next/link";
|
||||
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 {
|
||||
MdUnfoldMore,
|
||||
MdUnfoldLess,
|
||||
MdAutoFixHigh,
|
||||
MdOutlineAutoFixOff,
|
||||
} from "react-icons/md";
|
||||
import {
|
||||
AiFillHome,
|
||||
AiFillDelete,
|
||||
AiOutlineDelete,
|
||||
AiFillGithub,
|
||||
AiOutlineTwitter,
|
||||
AiOutlineSave,
|
||||
AiOutlineFileAdd,
|
||||
} from "react-icons/ai";
|
||||
import {
|
||||
CgArrowLongDownE,
|
||||
CgArrowLongLeftE,
|
||||
CgArrowLongRightE,
|
||||
CgArrowLongUpE,
|
||||
} from "react-icons/cg";
|
||||
|
||||
import { CanvasDirection } from "reaflow";
|
||||
import toast from "react-hot-toast";
|
||||
import { Tooltip } from "../Tooltip";
|
||||
import { Tooltip } from "src/components/Tooltip";
|
||||
import { ConfigActionType } from "src/reducer/reducer";
|
||||
import { useConfig } from "src/hocs/config";
|
||||
import { useRouter } from "next/router";
|
||||
@ -33,7 +26,7 @@ const StyledSidebar = styled.div`
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 42px;
|
||||
width: 36px;
|
||||
background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
|
||||
padding: 8px;
|
||||
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};
|
||||
`;
|
||||
|
||||
const StyledFlowIcon = styled(TiFlowMerge)<{ rotate: number }>`
|
||||
transform: rotate(${({ rotate }) => `${rotate}deg`});
|
||||
`;
|
||||
|
||||
const StyledTopWrapper = styled.nav`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -101,15 +98,15 @@ const StyledImportFile = styled.label`
|
||||
}
|
||||
`;
|
||||
|
||||
function getLayoutIcon(layout: CanvasDirection) {
|
||||
if (layout === "LEFT") return <CgArrowLongLeftE />;
|
||||
if (layout === "UP") return <CgArrowLongUpE />;
|
||||
if (layout === "RIGHT") return <CgArrowLongRightE />;
|
||||
return <CgArrowLongDownE />;
|
||||
function rotateLayout(layout: CanvasDirection) {
|
||||
if (layout === "LEFT") return 90;
|
||||
if (layout === "UP") return 180;
|
||||
if (layout === "RIGHT") return 270;
|
||||
return 360;
|
||||
}
|
||||
|
||||
export const Sidebar: React.FC = () => {
|
||||
const { settings, dispatch } = useConfig();
|
||||
const { json, settings, dispatch } = useConfig();
|
||||
const router = useRouter();
|
||||
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.`);
|
||||
};
|
||||
|
||||
const toggleAutoFormat = () => {
|
||||
dispatch({ type: ConfigActionType.TOGGLE_AUTOFORMAT });
|
||||
toast(
|
||||
`Auto format has been ${settings.autoformat ? "disabled." : "enabled."}`
|
||||
);
|
||||
const handleSave = () => {
|
||||
localStorage.setItem("json", json);
|
||||
toast.success("Saved JSON successfully!");
|
||||
};
|
||||
|
||||
const toggleExpandCollapse = () => {
|
||||
@ -160,36 +155,6 @@ export const Sidebar: React.FC = () => {
|
||||
</StyledLogo>
|
||||
</StyledElement>
|
||||
</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">
|
||||
<StyledElement>
|
||||
<StyledImportFile>
|
||||
@ -199,10 +164,35 @@ export const Sidebar: React.FC = () => {
|
||||
type="file"
|
||||
accept="application/JSON"
|
||||
/>
|
||||
<FaFileImport />
|
||||
<AiOutlineFileAdd />
|
||||
</StyledImportFile>
|
||||
</StyledElement>
|
||||
</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>
|
||||
<StyledBottomWrapper>
|
||||
<StyledElement>
|
||||
@ -219,6 +209,13 @@ export const Sidebar: React.FC = () => {
|
||||
</a>
|
||||
</Link>
|
||||
</StyledElement>
|
||||
<StyledElement>
|
||||
<Link href="https://www.patreon.com/aykutsarac">
|
||||
<a aria-label="Patreon" rel="me" target="_blank">
|
||||
<RiPatreonFill />
|
||||
</a>
|
||||
</Link>
|
||||
</StyledElement>
|
||||
</StyledBottomWrapper>
|
||||
</StyledSidebar>
|
||||
);
|
||||
|
@ -15,7 +15,7 @@ const StyledTooltip = styled.div<{ visible: boolean }>`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: translate(calc(100% + 15px), 25%);
|
||||
transform: translate(calc(100% + 15px), 20%);
|
||||
z-index: 5;
|
||||
background: ${({ theme }) => theme.BACKGROUND_PRIMARY};
|
||||
color: ${({ theme }) => theme.TEXT_NORMAL};
|
||||
|
@ -36,7 +36,6 @@ export const defaultJson = {
|
||||
export const defaultConfig: StorageConfig = {
|
||||
layout: "RIGHT",
|
||||
expand: true,
|
||||
autoformat: true,
|
||||
hideEditor: false,
|
||||
zoomPanPinch: null,
|
||||
lightmode: false
|
||||
|
@ -2,10 +2,10 @@ import React from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import {
|
||||
AiOutlineFullscreen,
|
||||
AiOutlineSave,
|
||||
AiOutlineMinus,
|
||||
AiOutlinePlus,
|
||||
} from "react-icons/ai";
|
||||
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";
|
||||
@ -42,10 +42,6 @@ const StyledToolElement = styled.button`
|
||||
|
||||
export const Tools: React.FC = () => {
|
||||
const { json, settings, dispatch } = useConfig();
|
||||
const handleSave = () => {
|
||||
localStorage.setItem("json", json);
|
||||
toast.success("Saved JSON successfully!");
|
||||
};
|
||||
|
||||
const zoomIn = () => dispatch({ type: ConfigActionType.ZOOM_IN });
|
||||
|
||||
@ -66,8 +62,13 @@ export const Tools: React.FC = () => {
|
||||
{settings.lightmode ? <HiOutlineMoon /> : <HiOutlineSun />}
|
||||
</StyledToolElement>
|
||||
<Input />
|
||||
<StyledToolElement aria-label="save" onClick={handleSave}>
|
||||
<AiOutlineSave />
|
||||
<StyledToolElement
|
||||
aria-label="save"
|
||||
onClick={() => {
|
||||
// export as png
|
||||
}}
|
||||
>
|
||||
<FiDownload />
|
||||
</StyledToolElement>
|
||||
<StyledToolElement aria-label="center canvas" onClick={centerView}>
|
||||
<MdCenterFocusWeak />
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import Editor from "@monaco-editor/react";
|
||||
import parseJson from "parse-json";
|
||||
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 { useConfig } from "src/hocs/config";
|
||||
import { Loading } from "src/components/Loading";
|
||||
@ -16,6 +16,7 @@ const StyledEditorWrapper = styled.div`
|
||||
`;
|
||||
|
||||
const editorOptions = {
|
||||
formatOnPaste: true,
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
@ -35,36 +36,24 @@ export const JsonEditor: React.FC = () => {
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (settings.autoformat) {
|
||||
return setValue(JSON.stringify(JSON.parse(json), null, 2));
|
||||
}
|
||||
|
||||
setValue(json);
|
||||
}, [settings.autoformat, json]);
|
||||
setValue(JSON.stringify(JSON.parse(json), null, 2));
|
||||
}, [json]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const formatTimer = setTimeout(
|
||||
() => {
|
||||
try {
|
||||
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 });
|
||||
}
|
||||
|
||||
const formatTimer = setTimeout(() => {
|
||||
try {
|
||||
if (!value) {
|
||||
setError((err) => ({ ...err, message: "" }));
|
||||
} catch (jsonError: any) {
|
||||
setError((err) => ({ ...err, message: jsonError.message }));
|
||||
return dispatch({ type: ConfigActionType.SET_JSON, payload: "[]" });
|
||||
}
|
||||
},
|
||||
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);
|
||||
}, [value, dispatch]);
|
||||
@ -76,8 +65,8 @@ export const JsonEditor: React.FC = () => {
|
||||
height="100%"
|
||||
defaultLanguage="json"
|
||||
value={value}
|
||||
options={editorOptions}
|
||||
theme={editorTheme}
|
||||
options={editorOptions}
|
||||
loading={<Loading message="Loading Editor..." />}
|
||||
onChange={(value) => setValue(value as string)}
|
||||
/>
|
||||
|
@ -6,7 +6,6 @@ export enum ConfigActionType {
|
||||
SET_CONFIG,
|
||||
TOGGLE_LAYOUT,
|
||||
TOGGLE_EXPAND,
|
||||
TOGGLE_AUTOFORMAT,
|
||||
TOGGLE_DOCK,
|
||||
TOGGLE_THEME,
|
||||
ZOOM_IN,
|
||||
@ -70,15 +69,6 @@ export const useConfigReducer: React.Reducer<AppConfig, ReducerAction> = (
|
||||
);
|
||||
return state;
|
||||
|
||||
case ConfigActionType.TOGGLE_AUTOFORMAT:
|
||||
return {
|
||||
...state,
|
||||
settings: {
|
||||
...state.settings,
|
||||
autoformat: !state.settings.autoformat,
|
||||
},
|
||||
};
|
||||
|
||||
case ConfigActionType.TOGGLE_DOCK:
|
||||
return {
|
||||
...state,
|
||||
|
@ -5,7 +5,6 @@ import { CanvasDirection } from "reaflow";
|
||||
export interface StorageConfig {
|
||||
layout: CanvasDirection;
|
||||
expand: boolean;
|
||||
autoformat: boolean;
|
||||
hideEditor: boolean;
|
||||
zoomPanPinch: ReactZoomPanPinchRef | null;
|
||||
lightmode: boolean;
|
||||
|
Loading…
x
Reference in New Issue
Block a user