josdejong / jsoneditor

A web-based tool to view, edit, format, and validate JSON
http://jsoneditoronline.org
Apache License 2.0
11.23k stars 2.02k forks source link

How to highlight changes in two panels displaying original and edited JSON files in a React TypeScript app with JSONEditor integration? #1588

Closed nastja4 closed 1 month ago

nastja4 commented 1 month ago

Hello. I am a beginner in IT and currently working on a React app where I need to implement functionality that allows users to see highlighted differences in JSON configurations. The application uses two panels: one displaying the original JSON content and another for editing. I have integrated JSONEditor instances into the React DOM using 'useRef'. I am considering using the 'deep-diff' library to track changes between the original and modified JSON, but I am unsure how to effectively apply these differences to highlight changes within the JSONEditor instances. Could someone please help me outline an approach or provide examples of how to achieve this? Specific Challenges:

  1. How to apply the results from 'deep-diff' to dynamically highlight changes in JSONEditor?
  2. Is there a recommended way to visually represent these differences in the JSONEditor interface using React? Any guidance or suggestions would be greatly appreciated!

Here's a snippet of how I'm currently setting up the JSONEditors:

import React, { useState, useEffect, useRef } from "react";
import JSONEditor from "jsoneditor";
import "jsoneditor/dist/jsoneditor.css";
import axios from "axios"; 
import diff from "deep-diff";

const Settings = () => {
  const [jsonContent, setJsonContent] = useState({});
  const [initialJsonContent, setInitialJsonContent] = useState({});
  const viewEditorRef = useRef<HTMLDivElement | null>(null);
  const editEditorRef = useRef<HTMLDivElement | null>(null);
  const viewEditorInstance = useRef<JSONEditor | null>(null);
  const editEditorInstance = useRef<JSONEditor | null>(null);

  // Initialization of JSONEditors
  useEffect(() => {
    if (viewEditorRef.current) {
      viewEditorInstance.current = new JSONEditor(viewEditorRef.current, { mode: "view" });
    }
    if (editEditorRef.current) {
      editEditorInstance.current = new JSONEditor(editEditorRef.current, { mode: "tree" });
    }

    return () => {
      viewEditorInstance.current?.destroy();
      editEditorInstance.current?.destroy();
    };
  }, []);

  // Update editors with jsonContent
  useEffect(() => {
    viewEditorInstance.current?.set(jsonContent);
    editEditorInstance.current?.set(jsonContent);
    viewEditorInstance.current?.expandAll();
    editEditorInstance.current?.expandAll();
  }, [jsonContent]);

  const handleFileLoaded = (fileContent: string, fileName?: string) => {
    if (fileContent === "" && fileName === "") {
      setJsonContent({});
      setInitialJsonContent({});
    } else {
      const json = JSON.parse(fileContent);
      setJsonContent(json);
      setInitialJsonContent(json);
    }
  };

  const showDifferences = () => {
    const originalJson = initialJsonContent;
    const modifiedJson = editEditorInstance.current?.get();
    const diffs = diff(originalJson, modifiedJson);
    // Process and display `differences` appropriately
  };

  return (
    <div>
      <div ref={viewEditorRef} className="ref-container"></div>
      <div ref={editEditorRef} className="ref-container"></div>
      <button onClick={showDifferences}>Show Differences</button>
    </div>
  );
};

export default Settings;
josdejong commented 1 month ago

You can give the nodes a specific class name when they are removed, updated, or added.

See this example: https://github.com/josdejong/jsoneditor/blob/develop/examples/20_custom_css_style_for_nodes.html