This is an automated email from the ASF dual-hosted git repository.

hbshin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/age-viewer.git


The following commit(s) were added to refs/heads/main by this push:
     new 605cca1  filter graph (#91)
605cca1 is described below

commit 605cca1521a9ae7136b21cd00fd4373e737fb730
Author: MJinH <[email protected]>
AuthorDate: Thu Dec 29 00:14:12 2022 -0800

    filter graph (#91)
    
    * filter graph
    
    * Update and Resolve Conflic
    
    Co-authored-by: [email protected] <[email protected]>
    Co-authored-by: Hanbyeol Shin /  David Shin / 신한별 
<[email protected]>
---
 .../presentations/CypherResultCytoscape.jsx        |   4 +
 .../cytoscape/CypherResultCytoscapeChart.jsx       | 150 ++++++++++++---------
 .../frame/presentations/CypherGraphResultFrame.jsx |  27 ++++
 3 files changed, 120 insertions(+), 61 deletions(-)

diff --git 
a/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx 
b/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx
index 982b710..0e6d05b 100644
--- 
a/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx
+++ 
b/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx
@@ -380,6 +380,8 @@ const CypherResultCytoscape = forwardRef((props, ref) => {
         addLegendData={addLegendData}
         maxDataOfGraph={maxDataOfGraph}
         graph={props.graph}
+        onAddSubmit={props.onAddSubmit}
+        onRemoveSubmit={props.onRemoveSubmit}
         openModal={props.openModal}
         addGraphHistory={props.addGraphHistory}
         addElementHistory={props.addElementHistory}
@@ -424,6 +426,8 @@ CypherResultCytoscape.propTypes = {
   refKey: PropTypes.string.isRequired,
   setChartLegend: PropTypes.func.isRequired,
   graph: PropTypes.string.isRequired,
+  onAddSubmit: PropTypes.func.isRequired,
+  onRemoveSubmit: PropTypes.func.isRequired,
   openModal: PropTypes.func.isRequired,
   addGraphHistory: PropTypes.func.isRequired,
   addElementHistory: PropTypes.func.isRequired,
diff --git a/frontend/src/components/cytoscape/CypherResultCytoscapeChart.jsx 
b/frontend/src/components/cytoscape/CypherResultCytoscapeChart.jsx
index 17c9949..6a8abcd 100644
--- a/frontend/src/components/cytoscape/CypherResultCytoscapeChart.jsx
+++ b/frontend/src/components/cytoscape/CypherResultCytoscapeChart.jsx
@@ -34,13 +34,15 @@ import {
   faEyeSlash,
   faLockOpen,
   faProjectDiagram,
-  faWindowClose,
   faTrash,
 } from '@fortawesome/free-solid-svg-icons';
+import uuid from 'react-uuid';
 import cxtmenu from '../../lib/cytoscape-cxtmenu';
 import { initLocation, seletableLayouts } from './CytoscapeLayouts';
 import { stylesheet } from './CytoscapeStyleSheet';
 import { generateCytoscapeElement } from '../../features/cypher/CypherUtil';
+import IconFilter from '../../icons/IconFilter';
+import IconSearchCancel from '../../icons/IconSearchCancel';
 import styles from '../frame/Frame.module.scss';
 
 cytoscape.use(COSEBilkent);
@@ -53,9 +55,19 @@ cytoscape.use(spread);
 cytoscape.use(cxtmenu);
 
 const CypherResultCytoscapeCharts = ({
-  elements, cytoscapeObject, setCytoscapeObject, cytoscapeLayout, 
maxDataOfGraph,
-  onElementsMouseover, addLegendData, graph, openModal,
-  addGraphHistory, addElementHistory,
+  elements,
+  cytoscapeObject,
+  setCytoscapeObject,
+  cytoscapeLayout,
+  maxDataOfGraph,
+  onElementsMouseover,
+  addLegendData,
+  graph,
+  onAddSubmit,
+  onRemoveSubmit,
+  openModal,
+  addGraphHistory,
+  addElementHistory,
 }) => {
   const [cytoscapeMenu, setCytoscapeMenu] = useState(null);
   const [initialized, setInitialized] = useState(false);
@@ -91,7 +103,11 @@ const CypherResultCytoscapeCharts = ({
         if (cytoscapeObject.nodes(':selected').size() === 1) {
           ele.neighborhood().selectify().select().unselectify();
         } else {
-          cytoscapeObject.nodes(':selected').filter(`[id != 
"${ele.id()}"]`).neighborhood().selectify()
+          cytoscapeObject
+            .nodes(':selected')
+            .filter(`[id != "${ele.id()}"]`)
+            .neighborhood()
+            .selectify()
             .select()
             .unselectify();
         }
@@ -115,7 +131,11 @@ const CypherResultCytoscapeCharts = ({
   };
 
   const addElements = (centerId, d) => {
-    const generatedData = generateCytoscapeElement(d.rows, maxDataOfGraph, 
true);
+    const generatedData = generateCytoscapeElement(
+      d.rows,
+      maxDataOfGraph,
+      true,
+    );
     if (generatedData.elements.nodes.length === 0) {
       alert('No data to extend.');
       return;
@@ -127,13 +147,19 @@ const CypherResultCytoscapeCharts = ({
     const newlyAddedEdges = cytoscapeObject.edges('.new');
     const newlyAddedTargets = newlyAddedEdges.targets();
     const newlyAddedSources = newlyAddedEdges.sources();
-    const rerenderTargets = 
newlyAddedEdges.union(newlyAddedTargets).union(newlyAddedSources);
+    const rerenderTargets = newlyAddedEdges
+      .union(newlyAddedTargets)
+      .union(newlyAddedSources);
 
-    const centerPosition = { 
...cytoscapeObject.nodes().getElementById(centerId).position() };
+    const centerPosition = {
+      ...cytoscapeObject.nodes().getElementById(centerId).position(),
+    };
     cytoscapeObject.elements().unlock();
     rerenderTargets.layout(seletableLayouts.concentric).run();
 
-    const centerMovedPosition = { 
...cytoscapeObject.nodes().getElementById(centerId).position() };
+    const centerMovedPosition = {
+      ...cytoscapeObject.nodes().getElementById(centerId).position(),
+    };
     const xGap = centerMovedPosition.x - centerPosition.x;
     const yGap = centerMovedPosition.y - centerPosition.y;
     rerenderTargets.forEach((ele) => {
@@ -156,7 +182,7 @@ const CypherResultCytoscapeCharts = ({
         commands: [
           {
             content: ReactDOMServer.renderToString(
-              (<FontAwesomeIcon icon={faLockOpen} size="lg" />),
+              <FontAwesomeIcon icon={faLockOpen} size="lg" />,
             ),
             select(ele) {
               ele.animate({ position: initLocation[ele.id()] });
@@ -164,7 +190,7 @@ const CypherResultCytoscapeCharts = ({
           },
           {
             content: ReactDOMServer.renderToString(
-              (<FontAwesomeIcon icon={faProjectDiagram} size="lg" />),
+              <FontAwesomeIcon icon={faProjectDiagram} size="lg" />,
             ),
             select(ele) {
               const elAnimate = ele.animation({
@@ -181,15 +207,16 @@ const CypherResultCytoscapeCharts = ({
                 }
               }, 1000);
 
-              fetch('/api/v1/cypher',
-                {
-                  method: 'POST',
-                  headers: {
-                    Accept: 'application/json',
-                    'Content-Type': 'application/json',
-                  },
-                  body: JSON.stringify({ cmd: `SELECT * FROM 
cypher('${graph}', $$ MATCH (S)-[R]-(T) WHERE id(S) = ${ele.id()} RETURN S, R, 
T $$) as (S agtype, R agtype, T agtype);` }),
-                })
+              fetch('/api/v1/cypher', {
+                method: 'POST',
+                headers: {
+                  Accept: 'application/json',
+                  'Content-Type': 'application/json',
+                },
+                body: JSON.stringify({
+                  cmd: `SELECT * FROM cypher('${graph}', $$ MATCH (S)-[R]-(T) 
WHERE id(S) = ${ele.id()} RETURN S, R, T $$) as (S agtype, R agtype, T 
agtype);`,
+                }),
+              })
                 .then((res) => res.json())
                 .then((data) => {
                   elAnimate.rewind().stop();
@@ -198,54 +225,47 @@ const CypherResultCytoscapeCharts = ({
                 });
             },
           },
-
           {
             content: ReactDOMServer.renderToString(
-              (<FontAwesomeIcon icon={faEyeSlash} size="lg" />),
+              <FontAwesomeIcon icon={faEyeSlash} size="lg" />,
             ),
             select(ele) {
               ele.remove();
             },
           },
-
           {
             content: ReactDOMServer.renderToString(
-              (<FontAwesomeIcon icon={faWindowClose} size="lg" />),
+              <FontAwesomeIcon icon={faTrash} size="lg" />,
             ),
-            select() {
+            select(ele) {
+              dispatch(openModal());
+              dispatch(addGraphHistory(graph));
+              dispatch(addElementHistory(ele.id()));
             },
           },
-
           {
-            content: ReactDOMServer.renderToString(
-              (<FontAwesomeIcon icon={faTrash} size="lg" />),
-            ),
+            content: ReactDOMServer.renderToString(<IconFilter size="lg" />),
             select(ele) {
-              fetch('/api/v1/cypher',
-                {
-                  method: 'POST',
-                  headers: {
-                    Accept: 'application/json',
-                    'Content-Type': 'application/json',
-                  },
-                  body: JSON.stringify({ cmd: `SELECT * FROM 
cypher('${graph}', $$ MATCH (S) WHERE id(S) = ${ele.id()} DETACH DELETE S $$) 
as (S agtype);` }),
-                })
-                .then((res) => {
-                  if (res.ok) {
-                    ele.remove();
-                  }
-                });
+              const newFilterObject = {
+                key: uuid(),
+                keyword: ele.data().properties[ele.data().caption],
+                property: {
+                  label: ele.data().label,
+                  property: ele.data().caption,
+                },
+              };
+              onAddSubmit(newFilterObject);
             },
           },
-
           {
             content: ReactDOMServer.renderToString(
-              (<FontAwesomeIcon icon={faTrash} size="lg" />),
+              <IconSearchCancel size="lg" />,
             ),
             select(ele) {
-              dispatch(openModal());
-              dispatch(addGraphHistory(graph));
-              dispatch(addElementHistory(ele.id()));
+              const keywordObject = {
+                keyword: ele.data().properties[ele.data().caption],
+              };
+              onRemoveSubmit(keywordObject);
             },
           },
         ],
@@ -284,11 +304,13 @@ const CypherResultCytoscapeCharts = ({
     }
   }, [cytoscapeObject, cytoscapeLayout]);
 
-  const cyCallback = useCallback((newCytoscapeObject) => {
-    if (cytoscapeObject) return;
-    setCytoscapeObject(newCytoscapeObject);
-  },
-  [cytoscapeObject]);
+  const cyCallback = useCallback(
+    (newCytoscapeObject) => {
+      if (cytoscapeObject) return;
+      setCytoscapeObject(newCytoscapeObject);
+    },
+    [cytoscapeObject],
+  );
 
   return (
     <CytoscapeComponent
@@ -307,14 +329,18 @@ CypherResultCytoscapeCharts.defaultProps = {
 
 CypherResultCytoscapeCharts.propTypes = {
   elements: PropTypes.shape({
-    nodes: PropTypes.arrayOf(PropTypes.shape({
-      // eslint-disable-next-line react/forbid-prop-types
-      data: PropTypes.any,
-    })),
-    edges: PropTypes.arrayOf(PropTypes.shape({
-      // eslint-disable-next-line react/forbid-prop-types
-      data: PropTypes.any,
-    })),
+    nodes: PropTypes.arrayOf(
+      PropTypes.shape({
+        // eslint-disable-next-line react/forbid-prop-types
+        data: PropTypes.any,
+      }),
+    ),
+    edges: PropTypes.arrayOf(
+      PropTypes.shape({
+        // eslint-disable-next-line react/forbid-prop-types
+        data: PropTypes.any,
+      }),
+    ),
   }).isRequired,
   // eslint-disable-next-line react/forbid-prop-types
   cytoscapeObject: PropTypes.any,
@@ -324,6 +350,8 @@ CypherResultCytoscapeCharts.propTypes = {
   onElementsMouseover: PropTypes.func.isRequired,
   addLegendData: PropTypes.func.isRequired,
   graph: PropTypes.string.isRequired,
+  onAddSubmit: PropTypes.func.isRequired,
+  onRemoveSubmit: PropTypes.func.isRequired,
   openModal: PropTypes.func.isRequired,
   addGraphHistory: PropTypes.func.isRequired,
   addElementHistory: PropTypes.func.isRequired,
diff --git 
a/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx 
b/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
index 7d3c783..99bc937 100644
--- a/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
+++ b/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
@@ -44,6 +44,8 @@ const CypherResultFrame = ({
   const [filterProperties, setFilterProperties] = useState([]);
   const [filterTable, setFilterTable] = useState(null);
   const [edgeProperties, setEdgeProperties] = useState([]);
+  const [addFilter, setAddFilter] = useState(null);
+  const [removeFilter, setRemoveFilter] = useState(null);
   const [globalFilter, setGlobalFilter] = useState(null);
   const [globalThickness, setGlobalThickness] = useState(null);
 
@@ -89,6 +91,25 @@ const CypherResultFrame = ({
     }
   }, [globalFilter]);
 
+  useEffect(() => {
+    if (addFilter) {
+      if (globalFilter) setGlobalFilter([...globalFilter, addFilter]);
+      else setGlobalFilter([addFilter]);
+    }
+  }, [addFilter]);
+
+  useEffect(() => {
+    if (removeFilter) {
+      if (globalFilter) {
+        const newFilterList = globalFilter.filter((filterItem) => (
+          filterItem.keyword !== removeFilter.keyword
+        ));
+        if (newFilterList.length > 0) setGlobalFilter(newFilterList);
+        else setGlobalFilter(null);
+      }
+    }
+  }, [removeFilter]);
+
   useEffect(() => {
     if (!chartAreaRef.current) return;
     chartAreaRef.current.applyEdgeThicknessCytoscapeElements(globalThickness);
@@ -194,6 +215,12 @@ const CypherResultFrame = ({
                     ref={chartAreaRef}
                     refKey={refKey}
                     setChartLegend={setChartLegend}
+                    onAddSubmit={(filters) => {
+                      setAddFilter(filters);
+                    }}
+                    onRemoveSubmit={(filters) => {
+                      setRemoveFilter(filters);
+                    }}
                     setIsTable={setIsTable}
                   />
                 </div>

Reply via email to