mirror of
https://github.com/AykutSarac/jsoncrack.com.git
synced 2025-01-27 15:22:56 +08:00
code cleanup & splitting
This commit is contained in:
parent
0ac1e9173c
commit
d16b04e35a
79
src/containers/JsonEditor/ErrorContainer.tsx
Normal file
79
src/containers/JsonEditor/ErrorContainer.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
MdExpandMore,
|
||||
MdExpandLess,
|
||||
MdReportGmailerrorred,
|
||||
} from "react-icons/md";
|
||||
|
||||
export type Error = {
|
||||
message: string;
|
||||
isExpanded: boolean;
|
||||
};
|
||||
|
||||
interface ErrorContainerProps {
|
||||
error: Error;
|
||||
setError: React.Dispatch<React.SetStateAction<Error>>;
|
||||
}
|
||||
|
||||
const StyledErrorWrapper = styled.div``;
|
||||
|
||||
const StyledErrorHeader = styled.a`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: ${({ theme }) => theme.BLACK_DARK};
|
||||
padding: 6px 12px;
|
||||
color: ${({ theme }) => theme.DANGER};
|
||||
font-size: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: ${({ theme }) => theme.DANGER};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.span`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
gap: 10px;
|
||||
`;
|
||||
|
||||
const StyledError = styled.pre`
|
||||
color: ${({ theme }) => theme.DANGER};
|
||||
border: 1px solid ${({ theme }) => theme.SILVER_DARK};
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
font-size: 12px;
|
||||
padding: 12px;
|
||||
margin: 0;
|
||||
word-wrap: break-word;
|
||||
white-space: pre-line;
|
||||
`;
|
||||
|
||||
export const ErrorContainer: React.FC<ErrorContainerProps> = ({
|
||||
error,
|
||||
setError,
|
||||
}) => {
|
||||
return (
|
||||
<StyledErrorWrapper>
|
||||
<StyledErrorHeader
|
||||
onClick={() =>
|
||||
setError((err: Error) => ({ ...err, isExpanded: !err.isExpanded }))
|
||||
}
|
||||
>
|
||||
<StyledTitle>
|
||||
<MdReportGmailerrorred size={26} /> Error
|
||||
</StyledTitle>
|
||||
{error.isExpanded ? (
|
||||
<MdExpandLess size={22} />
|
||||
) : (
|
||||
<MdExpandMore size={22} />
|
||||
)}
|
||||
</StyledErrorHeader>
|
||||
{error.isExpanded && <StyledError>{error.message}</StyledError>}
|
||||
</StyledErrorWrapper>
|
||||
);
|
||||
};
|
@ -6,11 +6,7 @@ import { useLocalStorage } from "usehooks-ts";
|
||||
import { defaultConfig } from "src/constants/data";
|
||||
import parseJson from "parse-json";
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
MdExpandMore,
|
||||
MdExpandLess,
|
||||
MdReportGmailerrorred,
|
||||
} from "react-icons/md";
|
||||
import { Error, ErrorContainer } from "./ErrorContainer";
|
||||
|
||||
const StyledEditorWrapper = styled.div`
|
||||
display: flex;
|
||||
@ -20,43 +16,6 @@ const StyledEditorWrapper = styled.div`
|
||||
user-select: none;
|
||||
`;
|
||||
|
||||
const StyledErrorWrapper = styled.div``;
|
||||
|
||||
const StyledErrorHeader = styled.a`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: ${({ theme }) => theme.BLACK_DARK};
|
||||
padding: 6px 12px;
|
||||
color: ${({ theme }) => theme.DANGER};
|
||||
font-size: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: ${({ theme }) => theme.DANGER};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.span`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
gap: 10px;
|
||||
`;
|
||||
|
||||
const StyledError = styled.pre`
|
||||
color: ${({ theme }) => theme.DANGER};
|
||||
border: 1px solid ${({ theme }) => theme.SILVER_DARK};
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
font-size: 12px;
|
||||
padding: 12px;
|
||||
margin: 0;
|
||||
word-wrap: break-word;
|
||||
white-space: pre-line;
|
||||
`;
|
||||
|
||||
const AceEditor: ComponentType<IAceEditorProps> = dynamic(
|
||||
async () => {
|
||||
const Ace = require("react-ace").default;
|
||||
@ -69,6 +28,34 @@ const AceEditor: ComponentType<IAceEditorProps> = dynamic(
|
||||
}
|
||||
);
|
||||
|
||||
function isJson(
|
||||
value: string,
|
||||
setState: React.Dispatch<React.SetStateAction<Error>>
|
||||
) {
|
||||
value = typeof value !== "string" ? JSON.stringify(value) : value;
|
||||
|
||||
try {
|
||||
value = parseJson(value);
|
||||
setState((err) => ({
|
||||
...err,
|
||||
message: "",
|
||||
}));
|
||||
} catch (e: any) {
|
||||
setState((err) => ({
|
||||
...err,
|
||||
message: e.message,
|
||||
}));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof value === "object" && value !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const JsonEditor: React.FC<{
|
||||
json: string;
|
||||
setJson: React.Dispatch<React.SetStateAction<string>>;
|
||||
@ -84,31 +71,6 @@ const JsonEditor: React.FC<{
|
||||
JSON.stringify(JSON.parse(json), null, 2)
|
||||
);
|
||||
|
||||
function isJson(value: string) {
|
||||
value = typeof value !== "string" ? JSON.stringify(value) : value;
|
||||
|
||||
try {
|
||||
value = parseJson(value);
|
||||
setError((err) => ({
|
||||
...err,
|
||||
message: "",
|
||||
}));
|
||||
} catch (e: any) {
|
||||
setError((err) => ({
|
||||
...err,
|
||||
message: e.message,
|
||||
}));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof value === "object" && value !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
const resizeObserver = new ResizeObserver((observed) => {
|
||||
const width = observed[0].contentRect.width;
|
||||
@ -133,7 +95,7 @@ const JsonEditor: React.FC<{
|
||||
|
||||
React.useEffect(() => {
|
||||
const formatTimer = setTimeout(() => {
|
||||
if (!isJson(value)) return;
|
||||
if (!isJson(value, setError)) return;
|
||||
|
||||
if (config.autoformat) {
|
||||
setValue(JSON.stringify(JSON.parse(value), null, 2));
|
||||
@ -149,26 +111,7 @@ const JsonEditor: React.FC<{
|
||||
|
||||
return (
|
||||
<StyledEditorWrapper>
|
||||
{error.message && (
|
||||
<StyledErrorWrapper>
|
||||
<StyledErrorHeader
|
||||
onClick={() =>
|
||||
setError((err) => ({ ...err, isExpanded: !err.isExpanded }))
|
||||
}
|
||||
>
|
||||
<StyledTitle>
|
||||
<MdReportGmailerrorred size={26} /> Error
|
||||
</StyledTitle>
|
||||
{error.isExpanded ? (
|
||||
<MdExpandLess size={22} />
|
||||
) : (
|
||||
<MdExpandMore size={22} />
|
||||
)}
|
||||
</StyledErrorHeader>
|
||||
{error.isExpanded && <StyledError>{error.message}</StyledError>}
|
||||
</StyledErrorWrapper>
|
||||
)}
|
||||
|
||||
{error.message && <ErrorContainer error={error} setError={setError} />}
|
||||
<AceEditor
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
|
@ -51,17 +51,16 @@ export const LiveEditor: React.FC<{
|
||||
setJson: React.Dispatch<React.SetStateAction<string>>;
|
||||
}> = ({ json }) => {
|
||||
const pageLoaded = useLoading();
|
||||
|
||||
const canvasRef = React.useRef<CanvasRef | null>(null);
|
||||
const wrapperRef = React.useRef<ReactZoomPanPinchRef | null>(null);
|
||||
const [config] = useLocalStorage<StorageConfig>("config", defaultConfig);
|
||||
|
||||
const { nodes, edges } = getEdgeNodes(json, config.expand);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (wrapperRef.current) wrapperRef.current?.resetTransform();
|
||||
}, [json, wrapperRef]);
|
||||
|
||||
const { nodes, edges } = getEdgeNodes(json, config.expand);
|
||||
|
||||
const zoomIn = (scale: number) => {
|
||||
if (
|
||||
wrapperRef.current?.state.scale &&
|
||||
|
@ -129,7 +129,6 @@ const Editor: React.FC = () => {
|
||||
|
||||
React.useEffect(() => {
|
||||
const jsonStored = localStorage.getItem("json");
|
||||
|
||||
if (jsonStored) setJson(jsonStored);
|
||||
}, []);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user