From 5c9519ee97ed5f3a3a601f16aae2cd38391ce416 Mon Sep 17 00:00:00 2001
From: esikkala <esko.ikkala@aalto.fi>
Date: Sun, 7 Feb 2021 14:28:07 +0200
Subject: [PATCH] Add cytoscape-panzoom extension

---
 package-lock.json                             | 37 +++++++++++++++++++
 package.json                                  |  3 ++
 .../components/facet_results/Network.js       | 36 ++++++++++++++++++
 src/client/index.js                           |  6 +++
 4 files changed, 82 insertions(+)

diff --git a/package-lock.json b/package-lock.json
index 0447aa8a..2ead927e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3089,6 +3089,30 @@
       "resolved": "https://registry.npmjs.org/@formatjs/intl-utils/-/intl-utils-2.3.0.tgz",
       "integrity": "sha512-KWk80UPIzPmUg+P0rKh6TqspRw0G6eux1PuJr+zz47ftMaZ9QDwbGzHZbtzWkl5hgayM/qrKRutllRC7D/vVXQ=="
     },
+    "@fortawesome/fontawesome-common-types": {
+      "version": "0.2.34",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.34.tgz",
+      "integrity": "sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA==",
+      "dev": true
+    },
+    "@fortawesome/fontawesome-svg-core": {
+      "version": "1.2.34",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.34.tgz",
+      "integrity": "sha512-0KNN0nc5eIzaJxlv43QcDmTkDY1CqeN6J7OCGSs+fwGPdtv0yOQqRjieopBCmw+yd7uD3N2HeNL3Zm5isDleLg==",
+      "dev": true,
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "^0.2.34"
+      }
+    },
+    "@fortawesome/free-solid-svg-icons": {
+      "version": "5.15.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.2.tgz",
+      "integrity": "sha512-ZfCU+QjaFsdNZmOGmfqEWhzI3JOe37x5dF4kz9GeXvKn/sTxhqMtZ7mh3lBf76SvcYY5/GKFuyG7p1r4iWMQqw==",
+      "dev": true,
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "^0.2.34"
+      }
+    },
     "@istanbuljs/load-nyc-config": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@@ -11257,6 +11281,14 @@
         "lodash.debounce": "^4.0.8"
       }
     },
+    "cytoscape-panzoom": {
+      "version": "2.5.3",
+      "resolved": "https://registry.npmjs.org/cytoscape-panzoom/-/cytoscape-panzoom-2.5.3.tgz",
+      "integrity": "sha512-//qLOqbbFUCGddarNKHDZArItOJHgnkQ1TvxI9nV2/8aOOl/5wuEOHmra3fL/aWSjB4AYpYTG4LX7w96uWfRTQ==",
+      "requires": {
+        "jquery": "^1.4 || ^2.0 || ^3.0"
+      }
+    },
     "d": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
@@ -19591,6 +19623,11 @@
         }
       }
     },
+    "jquery": {
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
+      "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
+    },
     "js-base64": {
       "version": "2.6.4",
       "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
diff --git a/package.json b/package.json
index 4e1292ec..cd1b3c2a 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
     "axios": "^0.21.1",
     "core-js": "^3.8.1",
     "cytoscape": "^3.12.1",
+    "cytoscape-panzoom": "^2.5.3",
     "date-fns": "^2.0.0-alpha.27",
     "deck.gl": "^8.3.11",
     "dotenv": "^8.2.0",
@@ -84,6 +85,8 @@
     "@babel/plugin-transform-runtime": "^7.12.10",
     "@babel/preset-env": "^7.12.10",
     "@babel/preset-react": "^7.12.10",
+    "@fortawesome/fontawesome-svg-core": "^1.2.34",
+    "@fortawesome/free-solid-svg-icons": "^5.15.2",
     "@storybook/addon-docs": "^5.3.19",
     "@storybook/react": "^5.3.19",
     "babel-eslint": "^10.1.0",
diff --git a/src/client/components/facet_results/Network.js b/src/client/components/facet_results/Network.js
index 41a830d2..2c877776 100644
--- a/src/client/components/facet_results/Network.js
+++ b/src/client/components/facet_results/Network.js
@@ -2,9 +2,37 @@ import React from 'react'
 import PropTypes from 'prop-types'
 import history from '../../History'
 import cytoscape from 'cytoscape'
+import panzoom from 'cytoscape-panzoom'
+import 'cytoscape-panzoom/cytoscape.js-panzoom.css'
 import purple from '@material-ui/core/colors/purple'
 import CircularProgress from '@material-ui/core/CircularProgress'
 
+const zoomControlOptions = {
+  zoomFactor: 0.05, // zoom factor per zoom tick
+  zoomDelay: 45, // how many ms between zoom ticks
+  minZoom: 0.1, // min zoom level
+  maxZoom: 10, // max zoom level
+  fitPadding: 50, // padding when fitting
+  panSpeed: 10, // how many ms in between pan ticks
+  panDistance: 10, // max pan distance per tick
+  panDragAreaSize: 75, // the length of the pan drag box in which the vector for panning is calculated (bigger = finer control of pan speed and direction)
+  panMinPercentSpeed: 0.25, // the slowest speed we can pan by (as a percent of panSpeed)
+  panInactiveArea: 8, // radius of inactive area in pan drag box
+  panIndicatorMinOpacity: 0.5, // min opacity of pan indicator (the draggable nib); scales from this to 1.0
+  zoomOnly: false, // a minimal version of the ui only with zooming (useful on systems with bad mousewheel resolution)
+  fitSelector: undefined, // selector of elements to fit
+  animateOnFit: function () { // whether to animate on fit
+    return false
+  },
+  fitAnimationDuration: 1000, // duration of animation on fit
+
+  // icon class names
+  sliderHandleIcon: 'fas fa-minus',
+  zoomInIcon: 'fas fa-plus',
+  zoomOutIcon: 'fas fa-minus',
+  resetIcon: 'fas fa-expand'
+}
+
 const cyContainerStyle = {
   width: '100%',
   height: '100%'
@@ -17,6 +45,7 @@ class Network extends React.Component {
   }
 
   componentDidMount = () => {
+    console.log('did mount')
     this.props.fetchResults({
       resultClass: this.props.resultClass,
       facetClass: this.props.facetClass,
@@ -56,6 +85,13 @@ class Network extends React.Component {
     this.cy.on('mouseout', 'node', function (event) {
       document.body.style.cursor = 'default'
     })
+
+    if (this.cy.panzoom == null) {
+      // register panzoom extension
+      panzoom(cytoscape)
+    }
+    // add the panzoom control
+    this.cy.panzoom(zoomControlOptions)
   }
 
   componentDidUpdate = prevProps => {
diff --git a/src/client/index.js b/src/client/index.js
index 3f65f304..5f90fd69 100644
--- a/src/client/index.js
+++ b/src/client/index.js
@@ -10,6 +10,8 @@ import { availableLocales } from './epics/index.js'
 import { loadLocales } from './actions'
 import { defaultLocale } from './configs/sampo/GeneralConfig'
 import { updateLocaleToPathname } from './helpers/helpers'
+import { library, dom } from '@fortawesome/fontawesome-svg-core'
+import { faMinus, faPlus, faExpand } from '@fortawesome/free-solid-svg-icons'
 
 import './index.css'
 import 'react-sortable-tree/style.css'
@@ -36,6 +38,10 @@ if (Object.prototype.hasOwnProperty.call(availableLocales, localeFromUrl)) {
 }
 store.dispatch(loadLocales(locale))
 
+// https://www.pullrequest.com/blog/webpack-fontawesome-guide/
+library.add(faMinus, faPlus, faExpand)
+dom.watch()
+
 render(
   <Provider store={store}>
     <div id='app'>
-- 
GitLab