AykutSarac преди 2 години
родител
ревизия
ec14df55a8

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
public/assets/undraw_qa_engineers_dg-5-p.svg


+ 42 - 0
src/components/Graph/ErrorView.tsx

@@ -0,0 +1,42 @@
+import React from "react";
+import styled from "styled-components";
+
+const StyledErrorView = styled.div`
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+
+  img {
+    filter: drop-shadow(2px 4px 6px black);
+  }
+`;
+
+const StyledTitle = styled.h2`
+  color: ${({ theme }) => theme.TEXT_DANGER};
+`;
+
+const StyledInfo = styled.p`
+  width: 60%;
+  text-align: center;
+  color: ${({ theme }) => theme.TEXT_NORMAL};
+`;
+
+export const ErrorView = () => (
+  <StyledErrorView>
+    <img
+      src="assets/undraw_qa_engineers_dg-5-p.svg"
+      width="200"
+      height="200"
+      alt="oops"
+    />
+    <StyledTitle>JSON Crack unable to handle this file!</StyledTitle>
+    <StyledInfo>
+      We apologize for the problem you encountered, we are doing our best as Open
+      Source community to improve our service. JSON Crack is currently unable to
+      handle such a huge file.
+    </StyledInfo>
+  </StyledErrorView>
+);

+ 21 - 5
src/components/Graph/index.tsx

@@ -1,3 +1,4 @@
+// @ts-nocheck
 import React from "react";
 import {
   ReactZoomPanPinchRef,
@@ -9,6 +10,8 @@ import { CustomNode } from "src/components/CustomNode";
 import useConfig from "src/hooks/store/useConfig";
 import useGraph from "src/hooks/store/useGraph";
 import styled from "styled-components";
+import { Loading } from "../Loading";
+import { ErrorView } from "./ErrorView";
 
 interface LayoutProps {
   isWidget: boolean;
@@ -40,8 +43,10 @@ const StyledEditorWrapper = styled.div<{ isWidget: boolean }>`
 
 const GraphComponent = ({ isWidget, openModal, setSelectedNode }: LayoutProps) => {
   const setConfig = useConfig(state => state.setConfig);
+  const setGraphValue = useGraph(state => state.setGraphValue);
   const layout = useConfig(state => state.layout);
   const nodes = useGraph(state => state.nodes);
+  const loading = useGraph(state => state.loading);
   const edges = useGraph(state => state.edges);
 
   const [size, setSize] = React.useState({
@@ -64,19 +69,30 @@ const GraphComponent = ({ isWidget, openModal, setSelectedNode }: LayoutProps) =
     [setConfig]
   );
 
-  const onLayoutChange = React.useCallback((layout: ElkRoot) => {
-    if (layout.width && layout.height) {
-      setSize({ width: layout.width + 400, height: layout.height + 400 });
-    }
-  }, []);
+  const onLayoutChange = React.useCallback(
+    (layout: ElkRoot) => {
+      if (layout.width && layout.height) {
+        setSize({ width: layout.width + 400, height: layout.height + 400 });
+        requestAnimationFrame(() => {
+          setTimeout(() => {
+            setGraphValue("loading", false);
+          }, 0);
+        });
+      }
+    },
+    [setGraphValue]
+  );
 
   const onCanvasClick = React.useCallback(() => {
     const input = document.querySelector("input:focus") as HTMLInputElement;
     if (input) input.blur();
   }, []);
 
+  if (nodes.length > 5_000) return <ErrorView />;
+
   return (
     <StyledEditorWrapper isWidget={isWidget}>
+      {loading && <Loading message="Painting graph..." />}
       <TransformWrapper
         maxScale={2}
         minScale={0.5}

+ 11 - 12
src/components/Loading/index.tsx

@@ -16,6 +16,7 @@ const StyledLoading = styled.div`
   text-align: center;
   background: ${({ theme }) => theme.BLACK_DARK};
   z-index: 36;
+  pointer-events: none;
 `;
 
 const StyledLogo = styled.h2`
@@ -35,15 +36,13 @@ const StyledMessage = styled.div`
   font-weight: 500;
 `;
 
-export const Loading: React.FC<LoadingProps> = ({ message }) => {
-  return (
-    <StyledLoading>
-      <StyledLogo>
-        <StyledText>JSON</StyledText> Crack
-      </StyledLogo>
-      <StyledMessage>
-        {message ?? "Preparing the environment for you..."}
-      </StyledMessage>
-    </StyledLoading>
-  );
-};
+export const Loading: React.FC<LoadingProps> = ({ message }) => (
+  <StyledLoading>
+    <StyledLogo>
+      <StyledText>JSON</StyledText> Crack
+    </StyledLogo>
+    <StyledMessage>
+      {message ?? "Preparing the environment for you..."}
+    </StyledMessage>
+  </StyledLoading>
+);

+ 2 - 2
src/components/MonacoEditor/index.tsx

@@ -39,12 +39,12 @@ export const MonacoEditor = ({
   const lightmode = useStored(state => (state.lightmode ? "light" : "vs-dark"));
   const [value, setValue] = React.useState<string | undefined>("");
 
-
   React.useEffect(() => {
     const { nodes, edges } = parser(json, expand);
 
     setGraphValue("nodes", nodes);
     setGraphValue("edges", edges);
+    setGraphValue("loading", true);
     setValue(json);
   }, [expand, json, setGraphValue]);
 
@@ -65,7 +65,7 @@ export const MonacoEditor = ({
     }, 1200);
 
     return () => clearTimeout(formatTimer);
-  }, [value, setJson, setHasError]);
+  }, [value, setJson, setHasError, setGraphValue]);
 
   return (
     <StyledWrapper>

+ 1 - 0
src/containers/Editor/LiveEditor/index.tsx

@@ -5,6 +5,7 @@ import styled from "styled-components";
 
 const StyledLiveEditor = styled.div`
   position: relative;
+  height: 100%;
 `;
 
 const LiveEditor: React.FC = () => {

+ 8 - 13
src/hooks/store/useConfig.tsx

@@ -1,4 +1,5 @@
 import { ReactZoomPanPinchRef } from "react-zoom-pan-pinch";
+import { CanvasDirection } from "reaflow";
 import { defaultJson } from "src/constants/data";
 import create from "zustand";
 
@@ -11,25 +12,19 @@ interface ConfigActions {
   centerView: () => void;
 }
 
-export interface Config {
-  json: string;
-  cursorMode: "move" | "navigation";
-  layout: "LEFT" | "RIGHT" | "DOWN" | "UP";
-  expand: boolean;
-  hideEditor: boolean;
-  zoomPanPinch?: ReactZoomPanPinchRef;
-  performanceMode: boolean;
-}
-
-const initialStates: Config = {
+const initialStates = {
   json: defaultJson,
-  cursorMode: "move",
-  layout: "RIGHT",
+  cursorMode: "move" as "move" | "navigation",
+  layout: "RIGHT" as CanvasDirection,
   expand: true,
   hideEditor: false,
   performanceMode: true,
+  disableLoading: false,
+  zoomPanPinch: undefined as ReactZoomPanPinchRef | undefined,
 };
 
+export type Config = typeof initialStates;
+
 const useConfig = create<Config & ConfigActions>()((set, get) => ({
   ...initialStates,
   getJson: () => get().json,

+ 11 - 15
src/hooks/store/useGraph.tsx

@@ -1,14 +1,18 @@
+import { Graph } from "src/components/Graph";
 import { getChildrenEdges } from "src/utils/getChildrenEdges";
 import { getOutgoers } from "src/utils/getOutgoers";
 import create from "zustand";
 
-export interface Graph {
-  nodes: NodeData[];
-  edges: EdgeData[];
-  collapsedNodes: string[];
-  collapsedEdges: string[];
-  collapsedParents: string[];
-}
+const initialStates = {
+  loading: false,
+  nodes: [] as NodeData[],
+  edges: [] as EdgeData[],
+  collapsedNodes: [] as string[],
+  collapsedEdges: [] as string[],
+  collapsedParents: [] as string[],
+};
+
+export type Graph = typeof initialStates;
 
 interface GraphActions {
   setGraphValue: (key: keyof Graph, value: any) => void;
@@ -16,14 +20,6 @@ interface GraphActions {
   collapseNodes: (nodeId: string) => void;
 }
 
-const initialStates: Graph = {
-  nodes: [],
-  edges: [],
-  collapsedNodes: [],
-  collapsedEdges: [],
-  collapsedParents: [],
-};
-
 const useGraph = create<Graph & GraphActions>((set, get) => ({
   ...initialStates,
   setGraphValue: (key, value) =>

+ 0 - 1
src/utils/jsonParser.ts

@@ -1,4 +1,3 @@
-
 const calculateSize = (
   text: string | [string, string][],
   isParent = false,

Някои файлове не бяха показани, защото твърде много файлове са промени