From 12498fb711031ff2e2c0b43016e689fcd81b4613 Mon Sep 17 00:00:00 2001 From: fraxken Date: Mon, 4 Dec 2023 20:50:36 +0100 Subject: [PATCH] feat: lock/unlock network & highlight multipleNodes --- i18n/english.js | 3 +- i18n/french.js | 3 +- public/components/locker/locker.css | 49 ++++++ public/components/locker/locker.js | 58 +++++++ .../views/home/maintainers/maintainers.js | 20 ++- public/components/views/network/network.css | 9 ++ public/components/views/settings/settings.js | 3 +- public/font/fontello/config.json | 14 +- public/font/fontello/fontello.css | 16 +- public/font/fontello/fontello.eot | Bin 21796 -> 22176 bytes public/font/fontello/fontello.svg | 6 +- public/font/fontello/fontello.ttf | Bin 21628 -> 22008 bytes public/font/fontello/fontello.woff | Bin 13656 -> 13876 bytes public/font/fontello/fontello.woff2 | Bin 11388 -> 11568 bytes public/main.css | 1 + public/main.js | 3 + views/index.html | 12 +- workspaces/vis-network/src/constants.js | 19 ++- workspaces/vis-network/src/network.js | 142 ++++++++++++++++++ 19 files changed, 338 insertions(+), 20 deletions(-) create mode 100644 public/components/locker/locker.css create mode 100644 public/components/locker/locker.js diff --git a/i18n/english.js b/i18n/english.js index e9a84124..9380a79f 100644 --- a/i18n/english.js +++ b/i18n/english.js @@ -34,7 +34,8 @@ const ui = { title: "Shortcuts", blockquote: "Click on hotkey to update", goto: "Goto", - openCloseWiki: "Open/Close wiki" + openCloseWiki: "Open/Close wiki", + lock: "Lock/Unlock network" } } }; diff --git a/i18n/french.js b/i18n/french.js index 7b09de9c..d4a9c28a 100644 --- a/i18n/french.js +++ b/i18n/french.js @@ -34,7 +34,8 @@ const ui = { title: "Raccourcis", blockquote: "Cliquer sur le raccourci clavier pour mettre à jour", goto: "Ouvrir", - openCloseWiki: "Ouverture/Fermeture du wiki" + openCloseWiki: "Ouverture/Fermeture du wiki", + lock: "Verrouiller/Déverrouiller le réseau" } } }; diff --git a/public/components/locker/locker.css b/public/components/locker/locker.css new file mode 100644 index 00000000..c6c7059b --- /dev/null +++ b/public/components/locker/locker.css @@ -0,0 +1,49 @@ +#network-locker { + position: absolute; + bottom: 10px; + right: 10px; + z-index: 30; + display: flex; + height: 30px; + border-radius: 4px; + align-items: center; + box-sizing: border-box; + overflow: hidden; + background-color: var(--primary); + transition: 0.3s all linear; + cursor: pointer; +} + +#network-locker:not(.enabled) { + background-color: var(--primary); +} + +#network-locker.enabled { + background-color: #af2222; +} + +#network-locker>i { + height: inherit; + padding: 0 5px; + display: flex; + align-items: center; + border-radius: 4px; + margin-right: 10px; + transition: 0.3s all linear; +} + +#network-locker>i:not(.enabled) { + background-color: var(--primary-lighter); +} + +#network-locker>i.enabled { + background-color: #cb3d3d; +} + +#network-locker>p { + font-family: "mononoki"; + padding-right: 10px; + display: flex; + align-items: center; + height: inherit; +} diff --git a/public/components/locker/locker.js b/public/components/locker/locker.js new file mode 100644 index 00000000..437f67f1 --- /dev/null +++ b/public/components/locker/locker.js @@ -0,0 +1,58 @@ + +export class Locker { + constructor(nsn) { + this.dom = document.getElementById("network-locker"); + this.networkView = document.getElementById("network--view"); + this.nsn = nsn; + this.unlock(); + + document.addEventListener("keydown", (event) => { + const hotkeys = JSON.parse(localStorage.getItem("hotkeys")); + switch (event.key.toUpperCase()) { + case hotkeys.lock: { + this.auto(); + break; + } + } + }); + this.dom.addEventListener("click", () => { + this.auto(); + }); + + this.nsn.network.on("highlight_done", () => { + this.unlock(); + }); + } + + auto() { + this[this.locked ? "unlock" : "lock"](); + } + + lock() { + this.dom.classList.add("enabled"); + this.dom.querySelector("p").textContent = "LOCKED"; + this.networkView.classList.add("locked"); + + const iconElement = this.dom.querySelector("i"); + iconElement.classList.remove("icon-lock-open"); + iconElement.classList.add("icon-lock"); + iconElement.classList.add("enabled"); + + this.nsn.lock(); + this.locked = true; + } + + unlock() { + this.dom.classList.remove("enabled"); + this.dom.querySelector("p").textContent = "UNLOCKED"; + this.networkView.classList.remove("locked"); + + const iconElement = this.dom.querySelector("i"); + iconElement.classList.remove("icon-lock"); + iconElement.classList.remove("enabled"); + iconElement.classList.add("icon-lock-open"); + + this.nsn.unlock(); + this.locked = false; + } +} diff --git a/public/components/views/home/maintainers/maintainers.js b/public/components/views/home/maintainers/maintainers.js index d75b8d86..e34b29c1 100644 --- a/public/components/views/home/maintainers/maintainers.js +++ b/public/components/views/home/maintainers/maintainers.js @@ -115,10 +115,26 @@ export class PopupMaintainer { linkElement.style.display = "none"; } - const focusGlobElement = clone.querySelector(".icon-globe-alt-outline"); - focusGlobElement.addEventListener("click", () => { + const globeElement = clone.querySelector(".icon-globe-alt-outline"); + const packagesList = [...this.data.packages] + .map((spec) => { + const { name, version } = utils.parseNpmSpec(spec); + + return `${name}@${version}`; + }); + + globeElement.addEventListener("click", () => { + this.nsn.highlightMultipleNodes( + this.nsn.findNodeIds(new Set(packagesList)) + ); + if (!window.locker.locked) { + window.locker.lock(); + } window.popup.close(); window.navigation.setNavByName("network--view"); + const { name, version } = utils.parseNpmSpec(packagesList[0]); + + setTimeout(() => this.nsn.focusNodeByNameAndVersion(name, version), 25); }); this.generatePackagesList(clone); diff --git a/public/components/views/network/network.css b/public/components/views/network/network.css index b6f234e8..47301ff1 100644 --- a/public/components/views/network/network.css +++ b/public/components/views/network/network.css @@ -1,5 +1,14 @@ #network--view { z-index: 10; + transition: 0.3s all linear; +} + +#network--view:not(.locked) { + box-shadow: -2px -2px 10px #6d29b5b8 inset; +} + +#network--view.locked { + box-shadow: -2px -2px 10px #b52929b8 inset; } #network-loader { diff --git a/public/components/views/settings/settings.js b/public/components/views/settings/settings.js index 2d1653d6..4a891e8a 100644 --- a/public/components/views/settings/settings.js +++ b/public/components/views/settings/settings.js @@ -11,7 +11,8 @@ const kDefaultHotKeys = { home: "H", network: "N", settings: "S", - wiki: "W" + wiki: "W", + lock: "L" }; export class Settings { diff --git a/public/font/fontello/config.json b/public/font/fontello/config.json index 6cc350b7..823fe534 100644 --- a/public/font/fontello/config.json +++ b/public/font/fontello/config.json @@ -329,6 +329,18 @@ "css": "globe-alt", "code": 59430, "src": "typicons" + }, + { + "uid": "c1f1975c885aa9f3dad7810c53b82074", + "css": "lock", + "code": 59431, + "src": "fontawesome" + }, + { + "uid": "05376be04a27d5a46e855a233d6e8508", + "css": "lock-open", + "code": 61758, + "src": "fontawesome" } ] -} +} \ No newline at end of file diff --git a/public/font/fontello/fontello.css b/public/font/fontello/fontello.css index d36f7cca..d8467a08 100644 --- a/public/font/fontello/fontello.css +++ b/public/font/fontello/fontello.css @@ -1,11 +1,11 @@ @font-face { font-family: 'fontello'; - src: url('./fontello.eot?8115607'); - src: url('./fontello.eot?8115607#iefix') format('embedded-opentype'), - url('./fontello.woff2?8115607') format('woff2'), - url('./fontello.woff?8115607') format('woff'), - url('./fontello.ttf?8115607') format('truetype'), - url('./fontello.svg?8115607#fontello') format('svg'); + src: url('./fontello.eot?84631897'); + src: url('./fontello.eot?84631897#iefix') format('embedded-opentype'), + url('./fontello.woff2?84631897') format('woff2'), + url('./fontello.woff?84631897') format('woff'), + url('./fontello.ttf?84631897') format('truetype'), + url('./fontello.svg?84631897#fontello') format('svg'); font-weight: normal; font-style: normal; } @@ -15,7 +15,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../../font/fontello.svg?8115607#fontello') format('svg'); + src: url('../font/fontello.svg?84631897#fontello') format('svg'); } } */ @@ -92,6 +92,7 @@ .icon-code:before { content: '\e824'; } /* '' */ .icon-globe-alt-outline:before { content: '\e825'; } /* '' */ .icon-globe-alt:before { content: '\e826'; } /* '' */ +.icon-lock:before { content: '\e827'; } /* '' */ .icon-info-circled:before { content: '\f085'; } /* '' */ .icon-info-circled-alt:before { content: '\f086'; } /* '' */ .icon-docs:before { content: '\f0c5'; } /* '' */ @@ -100,6 +101,7 @@ .icon-terminal:before { content: '\f120'; } /* '' */ .icon-fork:before { content: '\f126'; } /* '' */ .icon-unlink:before { content: '\f127'; } /* '' */ +.icon-lock-open:before { content: '\f13e'; } /* '' */ .icon-minus-squared:before { content: '\f146'; } /* '' */ .icon-minus-squared-alt:before { content: '\f147'; } /* '' */ .icon-doc-inv:before { content: '\f15b'; } /* '' */ diff --git a/public/font/fontello/fontello.eot b/public/font/fontello/fontello.eot index 55262e7e21ae70d0bf48ca9bc4097946e8c386ff..c36e21a3ef6a9f1119945015dd326d861c2686ce 100644 GIT binary patch delta 1073 zcmZ9LZERCj9LAsjxi4ivy3TF4qwU6}gBCYHSi5euu+=$7B9Z_WB7)Jfmrm)+g)L<4 z!!}_+B8E6`gMJ~Y3Gl(h#CVhW1s6jG@q__rbMMu!sqhV{g+sujgL7&`Uc7t#(p>!F^p^nb1MtCMCTWz4uRme`Eg=6gcxqhd zI$yivd~=Q%sm!r$k0;sleCOI!a?Iemi+wlis#N;)Ncg}fe*x+&5SL!%J5@UiNnYv1H`N#{alCb`j_=u>Zn1Ic!YL$L4{9N6i8qp-FR@a$SB9KMnFh zs`j?9uIBlE$SCoEkGCLUZ82CnU%FK)mR8DoIauy73!<5N%o}18?|^vLM@YYDS!7|@ z&3qzqjxO*kAk{n}t(Y^CV&-JErjogGbz4*NuQXi@0u`_sD4nyx%dF>Z(8hYp2JNgx z8*E`+vB6fLtlMB4YrqDtu=3g!u${HX20K^>s_X$exU<^^A=V={;L|8yut6v5WgA3T zzq3IXt7XF*QXQ$bX#qTYEY3=6;J|vc#e<3@K!PAbVF}G@(&$^oGZL}g5?}n^Ekuf7w&ZdB- zKr{n2dY7|CMJu&BRIQylH244WwUDDhZ6|+#^ZQkIqu5(b z_ur748)`Q?wQBrpEpCqaBBhnei_boEYML{aNW?5_Ihs&>m#*Jke7|<*1Jp`<+`v8a zw}pSzO!szC)V$hT5aNv47x!1>So}nAvT;${uHAMYb^p|)H!ZHa>CrszdKSFGJLLV_ z*X_Ge{mi4*Kk*u((C2;g6tceWdy{xE(VvwmO0QZ*|9hm!{Kp+Pm)_XBx~9_Gnlpy8 Nre|P}H8k*}^EvY?3c>&Y delta 717 zcmX|;Ur19?9LK+BTT@G%4>j9W>sqFpnboRIFl=VFQ3Qq>gj7y*yNK6aQo>|tQaZ2~ z?U)1=Oz=Cg(@{Z$*ABW(>gI1=I(W-thH`?)Be5W0K~53KjC!ZBvw2DOW1$ z(D3`vrR+ErHmI=HAL|LLJBD8Yr*aE4H9V}bN5$*?|7Q?@T`%$NYZld_vUDS(H(EIv0nkb?poC3kLe4Diw*Apk{lPJrX&7Xq9h>jJuXOz5nawv~Bi-R0LD zC;z}y5Neib$!_ y*3!pi^5%c>>sL<~Fy`e-^Ahvwd(WI>%+LE;2K2R-D~vY=FYpJ!^ZJkA+oJ!9M9~QV diff --git a/public/font/fontello/fontello.svg b/public/font/fontello/fontello.svg index fb0eb317..70eba5a5 100644 --- a/public/font/fontello/fontello.svg +++ b/public/font/fontello/fontello.svg @@ -1,7 +1,7 @@ -Copyright (C) 2022 by original authors @ fontello.com +Copyright (C) 2023 by original authors @ fontello.com @@ -84,6 +84,8 @@ + + @@ -100,6 +102,8 @@ + + diff --git a/public/font/fontello/fontello.ttf b/public/font/fontello/fontello.ttf index 1a038a364596c0b0c77c0f9eb0942c2cae092571..3d8dc1ed8138efa57d2806d8f704cd06f8722f8a 100644 GIT binary patch delta 1056 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

mxx@pG6}Xlx?s9HM0J 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 delta 11487 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 i<@}4O$UVp41pXQ2TC<#+_CL; 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 diff --git a/public/main.css b/public/main.css index f0101666..02e8ac83 100644 --- a/public/main.css +++ b/public/main.css @@ -5,6 +5,7 @@ @import url("./font/roboto/roboto.css"); @import url("./font/mononoki/mononoki.css"); +@import url("./components/locker/locker.css"); @import url("./components/popup/popup.css"); @import url("./components/file-box/file-box.css"); @import url("./components/expandable/expandable.css"); diff --git a/public/main.js b/public/main.js index 67fc7cc2..f7d906c2 100644 --- a/public/main.js +++ b/public/main.js @@ -7,6 +7,7 @@ import { ViewNavigation } from "./components/navigation/navigation.js"; import { Wiki } from "./components/wiki/wiki.js"; import { SearchBar } from "./components/searchbar/searchbar.js"; import { Popup } from "./components/popup/popup.js"; +import { Locker } from "./components/locker/locker.js"; // Import Views Components import { Settings } from "./components/views/settings/settings.js"; @@ -14,6 +15,7 @@ import { HomeView } from "./components/views/home/home.js"; import { NetworkNavigation } from "./core/network-navigation.js"; document.addEventListener("DOMContentLoaded", async() => { + window.locker = null; window.popup = new Popup(); window.settings = await new Settings().fetchUserConfig(); window.navigation = new ViewNavigation(); @@ -30,6 +32,7 @@ document.addEventListener("DOMContentLoaded", async() => { // Initialize vis Network NodeSecureNetwork.networkElementId = "dependency-graph"; const nsn = new NodeSecureNetwork(secureDataSet); + window.locker = new Locker(nsn); new HomeView(secureDataSet, nsn); window.addEventListener("package-info-closed", () => { diff --git a/views/index.html b/views/index.html index 380ffc49..9107536d 100644 --- a/views/index.html +++ b/views/index.html @@ -147,8 +147,10 @@

[[=z.token('loading_nodes')]]

[[=z.token('please_wait')]]

-
- +
+
+ +

UNLOCKED

+
+ + +
@@ -311,7 +317,7 @@

[[=z.token('settings.shortcuts.title')]]

- +
diff --git a/workspaces/vis-network/src/constants.js b/workspaces/vis-network/src/constants.js index 3e8543fe..9240130f 100644 --- a/workspaces/vis-network/src/constants.js +++ b/workspaces/vis-network/src/constants.js @@ -15,6 +15,18 @@ export const COLORS = Object.freeze({ color: "#FFF" } }, + SELECTED_GROUP: { + color: "#0D47A1", + font: { + color: "#FFF" + } + }, + SELECTED_LOCK: { + color: "#1A237E", + font: { + color: "#FFF" + } + }, DEFAULT: { color: "#E3F2FD", font: { @@ -100,9 +112,10 @@ export const LABELS = Object.freeze({ } }, NONE: { - label: " ", // A space is used to simulate resetting the edge laebl + // A space is used to simulate resetting the edge laebl + label: " ", font: { - background: "Transparent", + background: "Transparent" } } -}) +}); diff --git a/workspaces/vis-network/src/network.js b/workspaces/vis-network/src/network.js index 877a5268..f6ca9341 100644 --- a/workspaces/vis-network/src/network.js +++ b/workspaces/vis-network/src/network.js @@ -69,6 +69,9 @@ export default class NodeSecureNetwork { this.secureDataSet = secureDataSet; this.highlightEnabled = false; this.isLoaded = false; + + this.locked = false; + this.lastHighlightedIds = new Set(); const { nodes, edges } = secureDataSet.build(); const theme = options.theme?.toUpperCase() ?? "LIGHT"; @@ -104,6 +107,38 @@ export default class NodeSecureNetwork { this.network.stabilize(500); } + lock() { + if (this.locked) { + return; + } + + this.locked = true; + this.network.emit("lock", this.locked); + } + + unlock() { + if (!this.locked) { + return; + } + + this.locked = false; + this.network.emit("lock", this.locked); + } + + /** + * @param {!Set} packages + * @returns {IterableIterator} + */ + * findNodeIds(packages) { + for (const [id, opt] of this.linker) { + const spec = `${opt.name}@${opt.version}`; + + if (packages.has(opt.name) || packages.has(spec)) { + yield id; + } + } + } + /** * @description Focus/move to a Node by id * @param {number} [id=0] @@ -178,6 +213,59 @@ export default class NodeSecureNetwork { this.nodes.update(updatedNodes); } + highlightMultipleNodes(nodeIds) { + if (this.locked) { + return; + } + this.network.startSimulation(); + + const allNodes = this.nodes.get({ returnType: "Object" }); + const allEdges = this.edges.get(); + + // mark all nodes as hard to read. + const nodeIdsToHighlight = new Set(nodeIds); + for (const node of Object.values(allNodes)) { + const color = nodeIdsToHighlight.has(node.id) ? + this.colors.SELECTED_GROUP : + this.colors.HARDTOREAD; + + Object.assign(node, color); + } + + for (const nodeId of nodeIdsToHighlight) { + const connectedNodes = this.network.getConnectedNodes(nodeId); + const allConnectedNodes = []; + for (let id = 0; id < connectedNodes.length; id++) { + allConnectedNodes.push(...this.network.getConnectedNodes(connectedNodes[id])); + } + + // all second degree nodes get a different color and their label back + for (let id = 0; id < allConnectedNodes.length; id++) { + const node = allNodes[allConnectedNodes[id]]; + if (nodeIdsToHighlight.has(node.id)) { + continue; + } + + Object.assign(node, this.colors.DEFAULT); + } + } + + // reset all edge labels - even if user clicks on empty space + for (let id = 0; id < allEdges.length; id++) { + Object.assign(allEdges[id], { + label: " ", + font: { + background: "Transparent" + } + }); + } + + this.lastHighlightedIds = nodeIdsToHighlight; + this.nodes.update(Object.values(allNodes)); + this.edges.update(allEdges); + this.network.stopSimulation(); + } + /** * Search for neighbours nodes of a given node * @@ -198,7 +286,58 @@ export default class NodeSecureNetwork { } } + lockedNeighbourHighlight(params) { + if (params.nodes.length === 0) { + return true; + } + + const selectedNode = params.nodes[0]; + if (!this.lastHighlightedIds.has(selectedNode)) { + return false; + } + + const allNodes = this.nodes.get({ returnType: "Object" }); + for (const node of Object.values(allNodes)) { + if (!this.lastHighlightedIds.has(node.id)) { + continue; + } + + const color = node.id === selectedNode ? + this.colors.SELECTED_LOCK : + this.colors.SELECTED_GROUP; + + Object.assign(node, color); + } + + // get the second degree nodes + const connectedNodes = this.network.getConnectedNodes(selectedNode); + const allConnectedNodes = []; + for (let id = 0; id < connectedNodes.length; id++) { + allConnectedNodes.push(...this.network.getConnectedNodes(connectedNodes[id])); + } + + // all second degree nodes get a different color and their label back + for (let id = 0; id < allConnectedNodes.length; id++) { + const node = allNodes[allConnectedNodes[id]]; + if (this.lastHighlightedIds.has(node.id)) { + continue; + } + + Object.assign(node, this.colors.DEFAULT); + } + + this.network.startSimulation(); + this.nodes.update(Object.values(allNodes)); + this.network.stopSimulation(); + + return true; + } + neighbourHighlight(params) { + if (this.locked && this.lockedNeighbourHighlight(params)) { + return; + } + const allNodes = this.nodes.get({ returnType: "Object" }); const allEdges = this.edges.get(); @@ -267,8 +406,11 @@ export default class NodeSecureNetwork { } // transform the object into an array + this.lastHighlightedIds = null; + this.locked = false; this.nodes.update(Object.values(allNodes)); this.edges.update(allEdges); this.network.stopSimulation(); + this.network.emit("highlight_done"); } }