You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by hb...@apache.org on 2022/12/29 05:33:26 UTC

[age-viewer] branch main updated: filter/search table (#85)

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 b2bacc7  filter/search table (#85)
b2bacc7 is described below

commit b2bacc78cd374a175c43f5f2a45121613721cb76
Author: MJinH <97...@users.noreply.github.com>
AuthorDate: Wed Dec 28 21:33:20 2022 -0800

    filter/search table (#85)
    
    Co-authored-by: moon19960501@gmail.com <we...@gmail.com>
---
 .../cypherresult/components/GraphFilterModal.jsx   |  4 +-
 .../presentations/CypherResultCytoscape.jsx        |  3 +-
 .../presentations/CypherResultTable.jsx            | 58 ++++++++++++++++------
 .../src/components/cytoscape/CypherResultTab.jsx   |  6 ++-
 frontend/src/components/frame/Frame.jsx            |  7 +--
 .../frame/presentations/CypherGraphResultFrame.jsx | 12 ++++-
 frontend/src/static/style.css                      |  2 +-
 7 files changed, 69 insertions(+), 23 deletions(-)

diff --git a/frontend/src/components/cypherresult/components/GraphFilterModal.jsx b/frontend/src/components/cypherresult/components/GraphFilterModal.jsx
index bb0b916..bee47d7 100644
--- a/frontend/src/components/cypherresult/components/GraphFilterModal.jsx
+++ b/frontend/src/components/cypherresult/components/GraphFilterModal.jsx
@@ -38,6 +38,7 @@ const GraphFilterModal = ({
   onSubmit,
   properties,
   globalFilter,
+  isTable,
 }) => {
   const [propertyElements, setPropertyElements] = useState([]);
   const [filterList, setFilterList] = useState([
@@ -154,7 +155,7 @@ const GraphFilterModal = ({
     );
   }, [propertyElements, filterList]);
   return (
-    <Modal title="Filter on Graph" visible={visible} onOk={onOk} onCancel={() => setVisible(false)} width={800}>
+    <Modal title={isTable ? 'Filter Data in Table' : 'Filter on Graph'} visible={visible} onOk={onOk} onCancel={() => setVisible(false)} width={800}>
       {
         filterElements
       }
@@ -171,6 +172,7 @@ GraphFilterModal.propTypes = {
     property: PropTypes.string,
   })).isRequired,
   globalFilter: PropTypes.bool.isRequired,
+  isTable: PropTypes.bool.isRequired,
 };
 
 export default GraphFilterModal;
diff --git a/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx b/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx
index 7799276..049a86e 100644
--- a/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx
+++ b/frontend/src/components/cypherresult/presentations/CypherResultCytoscape.jsx
@@ -368,7 +368,7 @@ const CypherResultCytoscape = forwardRef((props, ref) => {
           isReloading={isReloading}
           legendData={legendData}
         />
-        <CypherResultTab refKey={props.refKey} currentTab="graph" />
+        <CypherResultTab refKey={props.refKey} setIsTable={props.setIsTable} currentTab="graph" />
       </div>
       <CypherResultCytoscapeChart
         onElementsMouseover={getFooterData}
@@ -421,6 +421,7 @@ CypherResultCytoscape.propTypes = {
   refKey: PropTypes.string.isRequired,
   setChartLegend: PropTypes.func.isRequired,
   graph: PropTypes.string.isRequired,
+  setIsTable: PropTypes.func.isRequired,
 };
 
 export default CypherResultCytoscape;
diff --git a/frontend/src/components/cypherresult/presentations/CypherResultTable.jsx b/frontend/src/components/cypherresult/presentations/CypherResultTable.jsx
index 6014ab7..f687ff7 100644
--- a/frontend/src/components/cypherresult/presentations/CypherResultTable.jsx
+++ b/frontend/src/components/cypherresult/presentations/CypherResultTable.jsx
@@ -46,18 +46,45 @@ const CypherResultTable = ({ data, ...props }) => {
     });
     setLocalColumns(columnsForFTable);
 
-    setLocalRows(data.rows.map((item) => {
-      const newItem = {
-        ...item,
-      };
-      if (hasKey) {
-        newItem[randKeyName] = newItem.key;
-        delete newItem.key;
-      }
-      newItem.key = uuid();
-      return newItem;
-    }));
-  }, []);
+    if (props.filterTable?.length > 0) {
+      const newItem = [];
+      data.rows.forEach((item) => {
+        props.filterTable.forEach((filter) => {
+          if ((filter.property.label === item.r.label
+            && item.r.properties[filter.property.property].includes(filter.keyword))
+            || (filter.property.label === item.v.label
+              && item.v.properties[filter.property.property].includes(filter.keyword))
+            || (filter.property.label === item.v2.label
+              && item.v2.properties[filter.property.property].includes(filter.keyword))) {
+            newItem.push(item);
+          }
+        });
+      });
+      setLocalRows(newItem.map((item) => {
+        const filteredItem = {
+          ...item,
+        };
+        if (hasKey) {
+          newItem[randKeyName] = newItem.key;
+          delete newItem.key;
+        }
+        filteredItem.key = uuid();
+        return filteredItem;
+      }));
+    } else {
+      setLocalRows(data.rows.map((item) => {
+        const newItem = {
+          ...item,
+        };
+        if (hasKey) {
+          newItem[randKeyName] = newItem.key;
+          delete newItem.key;
+        }
+        newItem.key = uuid();
+        return newItem;
+      }));
+    }
+  }, [props.filterTable]);
 
   if (data.command && data.command.toUpperCase().match('(GRAPH|COPY|UPDATE).*')) {
     return (
@@ -75,7 +102,7 @@ const CypherResultTable = ({ data, ...props }) => {
     return <div style={{ margin: '25px' }}><span style={{ whiteSpace: 'pre-line' }}>Query not entered!</span></div>;
   }
 
-  const { refKey } = props;
+  const { refKey, setIsTable } = props;
   return (
     <div className="legend-area">
       <div className="contianer-frame-tab">
@@ -83,7 +110,7 @@ const CypherResultTable = ({ data, ...props }) => {
           <div className="d-flex nodeLegend">Node:</div>
           <div className="d-flex edgeLegend">Edge:</div>
         </div>
-        <CypherResultTab refKey={refKey} currentTab="table" />
+        <CypherResultTab refKey={refKey} setIsTable={setIsTable} currentTab="table" />
       </div>
       <Table columns={localColumns} dataSource={localRows} />
     </div>
@@ -102,6 +129,9 @@ CypherResultTable.propTypes = {
     statusText: PropTypes.string,
   }).isRequired,
   refKey: PropTypes.string.isRequired,
+  setIsTable: PropTypes.func.isRequired,
+  // eslint-disable-next-line react/forbid-prop-types
+  filterTable: PropTypes.any.isRequired,
 };
 
 export default CypherResultTable;
diff --git a/frontend/src/components/cytoscape/CypherResultTab.jsx b/frontend/src/components/cytoscape/CypherResultTab.jsx
index 5c2a142..6c2eda0 100644
--- a/frontend/src/components/cytoscape/CypherResultTab.jsx
+++ b/frontend/src/components/cytoscape/CypherResultTab.jsx
@@ -30,6 +30,7 @@ class CypherResultTab extends Component {
     this.state = {};
     this.refKey = props.refKey;
     this.currentTab = props.currentTab;
+    this.setIsTable = props.setIsTable;
   }
 
   render() {
@@ -52,7 +53,7 @@ class CypherResultTab extends Component {
           className="btn"
           type="button"
           style={{ width: '50%', fontSize: '14px', color: this.currentTab === 'graph' ? '#142B80' : '#495057' }}
-          onClick={() => activeTab(this.refKey, 'graph')}
+          onClick={() => { activeTab(this.refKey, 'graph'); this.setIsTable(false); }}
         >
           <IconGraph />
           <br />
@@ -70,7 +71,7 @@ class CypherResultTab extends Component {
           className="btn"
           type="button"
           style={{ width: '50%', fontSize: '14px', color: this.currentTab === 'table' ? '#142B80' : '#495057' }}
-          onClick={() => activeTab(this.refKey, 'table')}
+          onClick={() => { activeTab(this.refKey, 'table'); this.setIsTable(true); }}
         >
           <FontAwesomeIcon icon={faTable} style={{ fontSize: '25px' }} />
           <br />
@@ -84,6 +85,7 @@ class CypherResultTab extends Component {
 CypherResultTab.propTypes = {
   refKey: PropTypes.string.isRequired,
   currentTab: PropTypes.string.isRequired,
+  setIsTable: PropTypes.func.isRequired,
 };
 
 export default CypherResultTab;
diff --git a/frontend/src/components/frame/Frame.jsx b/frontend/src/components/frame/Frame.jsx
index 969c2fd..fab3b99 100644
--- a/frontend/src/components/frame/Frame.jsx
+++ b/frontend/src/components/frame/Frame.jsx
@@ -37,7 +37,7 @@ const Frame = ({
   reqString, children, refKey,
   onSearch, onSearchCancel, onRefresh,
   onThick, thicnessMenu,
-  bodyNoPadding,
+  bodyNoPadding, isTable,
 }) => {
   const dispatch = useDispatch();
   const [isFullScreen, setFullScreen] = useState(false);
@@ -78,7 +78,7 @@ const Frame = ({
 
         </div>
         <div className={styles.ButtonArea}>
-          {onThick ? (
+          {!isTable && onThick ? (
             <Popover placement="bottomLeft" content={thicnessMenu} trigger="click">
               <Button
                 size="large"
@@ -146,7 +146,7 @@ const Frame = ({
             />
           </Button>
           {
-            onRefresh ? (
+            !isTable && onRefresh ? (
               <Button
                 size="large"
                 type="link"
@@ -228,6 +228,7 @@ Frame.propTypes = {
   onSearchCancel: PropTypes.func,
   onRefresh: PropTypes.func,
   bodyNoPadding: PropTypes.bool,
+  isTable: PropTypes.bool.isRequired,
 };
 
 export default Frame;
diff --git a/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx b/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
index 93cf0ac..7d3c783 100644
--- a/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
+++ b/frontend/src/components/frame/presentations/CypherGraphResultFrame.jsx
@@ -42,11 +42,13 @@ const CypherResultFrame = ({
   const [thicknessModalVisible, setThicknessModalVisible] = useState(false);
 
   const [filterProperties, setFilterProperties] = useState([]);
+  const [filterTable, setFilterTable] = useState(null);
   const [edgeProperties, setEdgeProperties] = useState([]);
   const [globalFilter, setGlobalFilter] = useState(null);
   const [globalThickness, setGlobalThickness] = useState(null);
 
   const [chartLegend, setChartLegend] = useState({ edgeLegend: {}, nodeLegend: {} });
+  const [isTable, setIsTable] = useState(false);
 
   useEffect(() => {
     if (chartAreaRef.current && filterModalVisible) {
@@ -77,10 +79,13 @@ const CypherResultFrame = ({
 
   useEffect(() => {
     if (!chartAreaRef.current) return;
-    if (globalFilter) {
+    if (globalFilter && !isTable) {
       chartAreaRef.current.applyFilterOnCytoscapeElements(globalFilter);
+    } else if (globalFilter && isTable) {
+      setFilterTable(globalFilter);
     } else {
       chartAreaRef.current.resetFilterOnCytoscapeElements();
+      setFilterTable();
     }
   }, [globalFilter]);
 
@@ -177,6 +182,7 @@ const CypherResultFrame = ({
         reqString={reqString}
         isPinned={isPinned}
         refKey={refKey}
+        isTable={isTable}
       >
         {
           queryComplete?.complete
@@ -188,11 +194,14 @@ const CypherResultFrame = ({
                     ref={chartAreaRef}
                     refKey={refKey}
                     setChartLegend={setChartLegend}
+                    setIsTable={setIsTable}
                   />
                 </div>
                 <div style={{ height: '100%', width: '100%' }} id={`${refKey}-table`} className="deselected-frame-tab">
                   <CypherResultTableContainer
                     refKey={refKey}
+                    filterTable={filterTable}
+                    setIsTable={setIsTable}
                   />
                 </div>
               </div>
@@ -214,6 +223,7 @@ const CypherResultFrame = ({
         setVisible={setFilterModalVisible}
         properties={filterProperties}
         globalFilter={globalFilter}
+        isTable={isTable}
       />
     </>
 
diff --git a/frontend/src/static/style.css b/frontend/src/static/style.css
index 41e61e5..8d5ad43 100644
--- a/frontend/src/static/style.css
+++ b/frontend/src/static/style.css
@@ -277,7 +277,7 @@ a[data-toggle="collapse"] {
 }
 
 .legend-area {
-    width: 80%;
+    width: 100%;
 }
 
 .legend-button-area {