diff --git a/application/frontend/src/App.tsx b/application/frontend/src/App.tsx index e372d844f..1913e46a9 100755 --- a/application/frontend/src/App.tsx +++ b/application/frontend/src/App.tsx @@ -6,6 +6,7 @@ import { QueryClient, QueryClientProvider } from 'react-query'; import { BrowserRouter } from 'react-router-dom'; import { GlobalFilterState, filterContext } from './hooks/applyFilters'; +import { DataProvider } from './providers/DataProvider'; import { MainContentArea } from './scaffolding'; const queryClient = new QueryClient(); @@ -14,10 +15,12 @@ const App = () => (
- - - - + + + + + +
diff --git a/application/frontend/src/const.ts b/application/frontend/src/const.ts index 8022b9138..3dd4890c7 100644 --- a/application/frontend/src/const.ts +++ b/application/frontend/src/const.ts @@ -1,3 +1,5 @@ +export const TWO_DAYS_MILLISECONDS = 1.728e8; + export const TYPE_IS_PART_OF = 'Is Part Of'; export const TYPE_LINKED_TO = 'Linked To'; export const TYPE_LINKED_FROM = 'Linked From'; @@ -37,5 +39,6 @@ export const GRAPH = '/graph'; export const DEEPLINK = '/deeplink'; export const BROWSEROOT = '/root_cres'; export const GAP_ANALYSIS = '/map_analysis'; +export const EXPLORER = '/explorer'; export const GA_STRONG_UPPER_LIMIT = 2; // remember to change this in the Python code too diff --git a/application/frontend/src/hooks/useWindowDimensions.tsx b/application/frontend/src/hooks/useWindowDimensions.tsx new file mode 100644 index 000000000..acfe312cb --- /dev/null +++ b/application/frontend/src/hooks/useWindowDimensions.tsx @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react'; + +function getWindowDimensions() { + const { innerWidth: width, innerHeight: height } = window; + return { + width, + height, + }; +} + +export default function useWindowDimensions() { + const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions()); + + useEffect(() => { + function handleResize() { + setWindowDimensions(getWindowDimensions()); + } + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + return windowDimensions; +} diff --git a/application/frontend/src/pages/Explorer/explorer.scss b/application/frontend/src/pages/Explorer/explorer.scss new file mode 100644 index 000000000..5b0182330 --- /dev/null +++ b/application/frontend/src/pages/Explorer/explorer.scss @@ -0,0 +1,109 @@ +#explorer-content { + font-family: Vollkorn, Ubuntu, Optima, Segoe, Segoe UI, Candara, Calibri, Arial, sans-serif; + margin: 40px; + text-align: left; +} + +#explorer-content>.group { + border-top: 1px dotted lightgrey; + border-left: 6px solid lightgrey; + margin: 4px; + margin-left: 46px; + padding: 5px; + vertical-align: top; + background-color: rgba(200, 200, 200, 0.2); +} + +#explorer-content>.doc-id { + display: inline-block; + border-radius: 6px; + margin: 3px; + padding: 3px; + background-color: #f8f8f8; + vertical-align: top; + font-size: 90%; +} + +#explorer-content>.tag { + display: inline-block; + border: 1px solid lightgrey; + border-radius: 6px; + margin: 3px; + padding: 3px; + background-color: #f8f8f8; + vertical-align: top; + font-size: 90%; + max-width: 80px; + white-space: nowrap; + overflow: hidden; +} + +#explorer-content>a { + text-decoration: none; +} + +#explorer-content>.icon { + width: 140px; + height: 140px; + object-fit: cover; + border-radius: 4px; + margin-top: 26px; + margin-bottom: 20px; + filter: grayscale(100%); +} + +#explorer-content>::placeholder { + color: lightgrey; + opacity: 1; +} + +#explorer-content>:-ms-input-placeholder { + color: lightgrey; +} + +#explorer-content>::-ms-input-placeholder { + color: lightgrey; +} + + +#explorer-content>div { + vertical-align: top; +} + +#explorer-content>content { + margin-left: -20px; +} + +#explorer-content>h1 { + font-size: 50px; + margin-bottom: 5px; + margin-left: 16px; +} + +#explorer-content>img { + vertical-align: middle; + height: 80px; +} + +b { + padding-top: 20px; + padding-left: 12px; +} +p{ + color: grey; margin-left: 26px; +} +#explorer-wrapper{ + margin-left: 24px; margin-top: 20px; margin-bottom: 20px; color: grey; +} + +#filter{ + font-size: 16px; height: 32px; width: 320px; margin-bottom: 10px; +} +#search-summary{ + display: inline-block; vertical-align: middle; +} +#graphs{font-size: 80%; color: grey;} + +.highlight{ + background-color: yellow; +} \ No newline at end of file diff --git a/application/frontend/src/pages/Explorer/explorer.tsx b/application/frontend/src/pages/Explorer/explorer.tsx new file mode 100644 index 000000000..ed41ae260 --- /dev/null +++ b/application/frontend/src/pages/Explorer/explorer.tsx @@ -0,0 +1,153 @@ +import './explorer.scss'; + +import React, { useEffect, useState } from 'react'; +import { Link } from 'react-router-dom'; +import { Label, List } from 'semantic-ui-react'; + +import { LoadingAndErrorIndicator } from '../../components/LoadingAndErrorIndicator'; +import { useDataStore } from '../../providers/DataProvider'; +import { LinkedTreeDocument, TreeDocument } from '../../types'; + +export const Explorer = () => { + const { dataLoading, dataTree } = useDataStore(); + const [filter, setFilter] = useState(''); + const [filteredTree, setFilteredTree] = useState(); + + const applyHighlight = (text, term) => { + if (!term) return text; + var index = text.toLowerCase().indexOf(term); + if (index >= 0) { + return ( + <> + {text.substring(0, index)} + {text.substring(index, index + term.length)} + {text.substring(index + term.length)} + + ); + } + return text; + }; + + const filterFunc = (doc: TreeDocument, term: string) => + doc.displayName && doc.displayName.toLowerCase().includes(term); + const recursiveFilter = (doc: TreeDocument, term: string) => { + if (doc.links) { + const filteredLinks: LinkedTreeDocument[] = []; + doc.links.forEach((x) => { + const docu = recursiveFilter(x.document, term); + if (docu) { + filteredLinks.push({ ltype: x.ltype, document: docu }); + } + }); + doc.links = filteredLinks; + } + if (filterFunc(doc, term) || doc.links?.length) { + return doc; + } + return null; + }; + + useEffect(() => { + if (dataTree.length) { + const treeCopy = structuredClone(dataTree); + const filTree: TreeDocument[] = []; + treeCopy + .map((x) => recursiveFilter(x, filter)) + .forEach((x) => { + if (x) { + filTree.push(x); + } + }); + setFilteredTree(filTree); + } + }, [filter, dataTree, setFilteredTree]); + + function processNode(item) { + if (!item) { + return <>; + } + const contains = item.links.filter((x) => x.ltype === 'Contains'); + const linkedTo = item.links.filter((x) => x.ltype === 'Linked To'); + return ( + + + + + {applyHighlight(item.displayName, filter)} + + {linkedTo.length > 0 && ( + + + {[...new Set(linkedTo.map((x: LinkedTreeDocument) => x.document.name))] + .sort() + .map((x: string) => ( + + + + ))} + + + )} + {contains.length > 0 && ( + {contains.map((child) => processNode(child.document))} + )} + + + ); + } + function update(event) { + setFilter(event.target.value.toLowerCase()); + } + + return ( + <> +
+

+ Explorer +

+

+ A visual explorer of Open Common Requirement Enumerations (CREs). Originally created by:{' '} + + Zeljko Obrenovic + + . +

+ +
+
+ +
+
+ +
+ + + {filteredTree?.map((item) => { + return processNode(item); + })} + +
+ + ); +}; diff --git a/application/frontend/src/pages/Explorer/visuals/circles/circles.scss b/application/frontend/src/pages/Explorer/visuals/circles/circles.scss new file mode 100644 index 000000000..50d6c9aba --- /dev/null +++ b/application/frontend/src/pages/Explorer/visuals/circles/circles.scss @@ -0,0 +1,32 @@ + +.node { + cursor: pointer; +} + +.node:hover { + stroke: #000; + stroke-width: 1.5px; +} + +.node--leaf { + fill: white; +} + +.label { + font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif; + text-anchor: middle; + text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff; +} + +.label, +.node--root, +.node--leaf { + pointer-events: none; +} + +.ui.button.screen-size-button { + position: absolute; + right: 0; + margin: 0; + background-color: transparent; +} \ No newline at end of file diff --git a/application/frontend/src/pages/Explorer/visuals/circles/circles.tsx b/application/frontend/src/pages/Explorer/visuals/circles/circles.tsx new file mode 100644 index 000000000..10ae9d202 --- /dev/null +++ b/application/frontend/src/pages/Explorer/visuals/circles/circles.tsx @@ -0,0 +1,170 @@ +import './circles.scss'; + +import { LoadingAndErrorIndicator } from 'application/frontend/src/components/LoadingAndErrorIndicator'; +import useWindowDimensions from 'application/frontend/src/hooks/useWindowDimensions'; +import { useDataStore } from 'application/frontend/src/providers/DataProvider'; +import * as d3 from 'd3'; +import React, { useEffect, useState } from 'react'; +import { Button, Icon } from 'semantic-ui-react'; + +export const ExplorerCircles = () => { + const { height, width } = useWindowDimensions(); + const [useFullScreen, setUseFullScreen] = useState(false); + const { dataLoading, dataTree } = useDataStore(); + + useEffect(() => { + var svg = d3.select('svg'); + svg.selectAll('*').remove(); + var margin = 20, + diameter = +svg.attr('width'), + g = svg.append('g').attr('transform', 'translate(' + diameter / 2 + ',' + diameter / 2 + ')'); + + var color = d3 + .scaleLinear([-1, 5], ['hsl(152,80%,80%)', 'hsl(228,30%,40%)']) + .interpolate(d3.interpolateHcl); + + var pack = d3 + .pack() + .size([diameter - margin, diameter - margin]) + .padding(2); + + const populateChildren = (node) => { + node.children = []; + if (node.links) { + node.children = node.links.filter((x) => x.document && x.ltype !== 'Related').map((x) => x.document); + } + node.children.forEach((x) => populateChildren(x)); + node.children.forEach((x) => { + if (x.children.length === 0) x.size = 1; + }); + }; + + const dataTreeClone = structuredClone(dataTree); + dataTreeClone.forEach((node) => populateChildren(node)); + + let root: any = { + displayName: 'cluster', + children: dataTreeClone, + }; + + root = d3 + .hierarchy(root) + .sum(function (d: any) { + return d.size; + }) + .sort(function (a: any, b: any) { + return b.value - a.value; + }); + + var focus: any = root, + nodes = pack(root).descendants(), + view; + + var circle = g + .selectAll('circle') + .data(nodes) + .enter() + .append('circle') + .attr('class', function (d) { + return d.parent ? (d.children ? 'node' : 'node node--leaf') : 'node node--root'; + }) + .style('fill', function (d: any) { + return d.children ? color(d.depth) : d.data.color ? d.data.color : null; + }) + .on('click', function (event, d: any) { + if (focus !== d) zoom(event, d), event.stopPropagation(); + }); + + var text = g + .selectAll('text') + .data(nodes) + .enter() + .append('text') + .attr('class', 'label') + .style('fill-opacity', function (d: any) { + return d.parent === root ? 1 : 0; + }) + .style('display', function (d: any) { + return d.parent === root ? 'inline' : 'none'; + }) + .text(function (d: any) { + let name = + d.data.displayName.length > 33 ? d.data.displayName.substr(0, 33) + '...' : d.data.displayName; + if (d.data.children && d.data.children.length > 0) name += ' (' + d.data.children.length + ')'; + return name; + }); + + var node = g.selectAll('circle,text'); + + svg.style('background', color(-1)).on('click', function (event) { + zoom(event, root); + }); + + zoomTo([root.x, root.y, root.r * 2 + margin]); + + function zoom(event: any, d: any) { + var focus0 = focus; + focus = d; + + var transition = d3 + .transition() + .duration(event.altKey ? 7500 : 750) + .tween('zoom', function (d) { + var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]); + return function (t) { + zoomTo(i(t)); + }; + }); + + transition + .selectAll('text') + .filter(function (d: any) { + const el = this as HTMLElement; + return (d && d.parent === focus) || el.style.display === 'inline'; + }) + .style('fill-opacity', function (d: any) { + return d && d.parent === focus ? 1 : 0; + }) + .on('start', function (d: any) { + const el = this as HTMLElement; + if (d && d.parent === focus) el.style.display = 'inline'; + }) + .on('end', function (d: any) { + const el = this as HTMLElement; + if (d && d.parent !== focus) el.style.display = 'none'; + }); + } + + function zoomTo(v) { + var k = diameter / v[2]; + view = v; + node.attr('transform', function (d: any) { + return 'translate(' + (d.x - v[0]) * k + ',' + (d.y - v[1]) * k + ')'; + }); + circle.attr('r', function (d) { + return d.r * k; + }); + } + }, [useFullScreen]); + const defaultSize = width > height ? height - 100 : width; + const size = useFullScreen ? width : defaultSize; + return ( +
+ +
+
+ +
+ + + +
+
+ ); +}; diff --git a/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.scss b/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.scss new file mode 100644 index 000000000..aa94cbbb4 --- /dev/null +++ b/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.scss @@ -0,0 +1,3 @@ +body { + margin: 0; +} \ No newline at end of file diff --git a/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.tsx b/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.tsx new file mode 100644 index 000000000..ee3134bc1 --- /dev/null +++ b/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.tsx @@ -0,0 +1,146 @@ +import './forceGraph.scss'; + +import { LoadingAndErrorIndicator } from 'application/frontend/src/components/LoadingAndErrorIndicator'; +import { useDataStore } from 'application/frontend/src/providers/DataProvider'; +import { LinkedTreeDocument } from 'application/frontend/src/types'; +import React, { useEffect, useState } from 'react'; +import ForceGraph3D from 'react-force-graph-3d'; +import { Checkbox, Form } from 'semantic-ui-react'; + +export const ExplorerForceGraph = () => { + const [graphData, setGraphData] = useState(); + const [ignoreTypes, setIgnoreTypes] = useState(['same']); + const [maxCount, setMaxCount] = useState(0); + const [maxNodeSize, setMaxNodeSize] = useState(0); + const { dataLoading, dataTree, getStoreKey, dataStore } = useDataStore(); + useEffect(() => { + const gData: any = { + nodes: [], + links: [], + }; + + const populateGraphData = (node) => { + let filteredLinks = []; + if (node.links) { + filteredLinks = node.links.filter((x) => x.document && !ignoreTypes.includes(x.ltype.toLowerCase())); + } + filteredLinks.forEach((x: LinkedTreeDocument) => { + gData.links.push({ + source: getStoreKey(node), + target: getStoreKey(x.document), + count: x.ltype === 'Contains' ? 2 : 1, + type: x.ltype, + }); + populateGraphData(x.document); + }); + }; + dataTree.forEach((x) => populateGraphData(x)); + + const nodesMap = {}; + const addNode = function (name) { + if (!nodesMap[name]) { + const storedDoc = dataStore[name]; + nodesMap[name] = { + id: name, + size: 1, + name: storedDoc ? storedDoc.displayName : name, + doctype: storedDoc ? storedDoc.doctype : 'Unknown', + }; + gData.nodes.push(nodesMap[name]); + } else { + nodesMap[name].size += 1; + } + }; + gData.links.forEach((link) => { + addNode(link.source); + addNode(link.target); + }); + + setMaxNodeSize(gData.nodes.map((n) => n.size).reduce((a, b) => Math.max(a, b))); + setMaxCount(gData.links.map((l) => l.count).reduce((a, b) => Math.max(a, b))); + + gData.links = gData.links.map((l) => { + return { source: l.target, target: l.source, count: l.count, type: l.type }; + }); + setGraphData(gData); + }, [ignoreTypes]); + + const getLinkColor = (ltype) => { + switch (ltype.toLowerCase()) { + case 'related': + return 'skyblue'; + case 'linked to': + return 'gray'; + case 'same': + return 'red'; + default: + return 'white'; + } + }; + + const getNodeColor = (doctype) => { + switch (doctype.toLowerCase()) { + case 'cre': + return ''; + case 'standard': + return 'orange'; + case 'tool': + return 'lightgreen'; + case 'linked to': + return 'red'; + default: + return 'purple'; + } + }; + + const toggleLinks = (name) => { + const ignoreTypesClone = structuredClone(ignoreTypes); + if (ignoreTypesClone.includes(name)) { + const index = ignoreTypesClone.indexOf(name); + ignoreTypesClone.splice(index, 1); + setIgnoreTypes(ignoreTypesClone); + } else { + ignoreTypesClone.push(name); + setIgnoreTypes(ignoreTypesClone); + } + }; + + return ( +
+ + + toggleLinks('contains')} + /> + {' | '} + toggleLinks('related')} + /> + {' | '} + toggleLinks('linked to')} + /> + {' | '} + toggleLinks('same')} /> + + {graphData && ( + Math.max((20 * n.size) / maxNodeSize, 0.001)} + nodeLabel={(n) => n.name + ' (' + n.size + ')'} + nodeColor={(n: any) => getNodeColor(n.doctype)} + linkOpacity={0.5} + linkColor={(l) => getLinkColor(l.type)} + linkWidth={(d) => 4} + /> + )} +
+ ); +}; diff --git a/application/frontend/src/providers/DataProvider.tsx b/application/frontend/src/providers/DataProvider.tsx new file mode 100644 index 000000000..db43868f8 --- /dev/null +++ b/application/frontend/src/providers/DataProvider.tsx @@ -0,0 +1,142 @@ +import axios from 'axios'; +import React, { createContext, useContext, useEffect, useState } from 'react'; +import { useQuery } from 'react-query'; + +import { TWO_DAYS_MILLISECONDS } from '../const'; +import { useEnvironment } from '../hooks/useEnvironment'; +import { Document, TreeDocument } from '../types'; +import { getLocalStorageObject, setLocalStorageObject } from '../utils'; +import { getDocumentDisplayName, getInternalUrl } from '../utils/document'; + +const DATA_STORE_KEY = 'data-store', + DATA_TREE_KEY = 'record-tree'; + +type DataContextValues = { + dataLoading: boolean; + dataStore: Record; + dataTree: TreeDocument[]; + getStoreKey; +}; + +export const DataContext = createContext(null); + +export const DataProvider = ({ children }: { children: React.ReactNode }) => { + const { apiUrl } = useEnvironment(); + const [dataLoading, setDataLoading] = useState(false); + const [dataStore, setDataStore] = useState>( + getLocalStorageObject(DATA_STORE_KEY) || {} + ); + const [dataTree, setDataTree] = useState(getLocalStorageObject(DATA_TREE_KEY) || []); + + const getStoreKey = (doc: Document): string => { + if (doc.doctype === 'CRE') return doc.id; + return `${doc.name}-${doc.sectionID}`; + }; + + const buildTree = (doc: Document, keyPath: string[] = []): TreeDocument => { + const selfKey = getStoreKey(doc); + keyPath.push(selfKey); + if (selfKey === '567-755') { + console.log('BLA'); + } + const storedDoc = structuredClone(dataStore[selfKey]); + storedDoc.links = storedDoc.links + .filter( + (x) => + x.document && !keyPath.includes(getStoreKey(x.document)) && getStoreKey(x.document) in dataStore + ) + .map((x) => ({ ltype: x.ltype, document: buildTree(x.document, keyPath) })); + return storedDoc; + }; + + const getTreeQuery = useQuery( + 'root_cres', + async () => { + if (!dataTree.length && Object.keys(dataStore).length) { + setDataLoading(true); + try { + const result = await axios.get(`${apiUrl}/root_cres`); + const treeData = result.data.data.map((x) => buildTree(x)); + setLocalStorageObject(DATA_TREE_KEY, treeData, TWO_DAYS_MILLISECONDS); + setDataTree(treeData); + } catch (error) { + console.error(error); + } + } + }, + { + retry: false, + enabled: false, + onSettled: () => { + setDataLoading(false); + }, + } + ); + + const getStoreQuery = useQuery( + 'everything', + async () => { + if (!Object.keys(dataStore).length) { + try { + setDataLoading(true); + const result = await axios.get(`${apiUrl}/everything`); + const data = result.data.data; + if (data) { + let store = {}; + data.forEach((x) => { + store[getStoreKey(x)] = { + links: [], + displayName: getDocumentDisplayName(x), + url: getInternalUrl(x), + ...x, + }; + }); + setLocalStorageObject(DATA_STORE_KEY, store, TWO_DAYS_MILLISECONDS); + setDataStore(store); + } + } catch (error) { + console.error(error); + } + } + }, + { + retry: false, + enabled: false, + onSettled: () => { + setDataLoading(false); + }, + } + ); + useEffect(() => { + setDataLoading(true); + getStoreQuery.refetch(); + }, [dataTree]); + + useEffect(() => { + setDataLoading(true); + getTreeQuery.refetch(); + }, [dataStore, setDataStore]); + + return ( + + {children} + + ); +}; + +export const useDataStore = () => { + const dataContext = useContext(DataContext); + + if (!dataContext) { + throw new Error('useDataStore must be used within a DataProvider'); + } + + return dataContext; +}; diff --git a/application/frontend/src/routes.tsx b/application/frontend/src/routes.tsx index 548c2d7a3..c7a1431fe 100644 --- a/application/frontend/src/routes.tsx +++ b/application/frontend/src/routes.tsx @@ -4,6 +4,7 @@ import { BROWSEROOT, CRE, DEEPLINK, + EXPLORER, GAP_ANALYSIS, GRAPH, INDEX, @@ -16,6 +17,9 @@ import { CommonRequirementEnumeration, Graph, Search, Standard } from './pages'; import { BrowseRootCres } from './pages/BrowseRootCres/browseRootCres'; import { Chatbot } from './pages/chatbot/chatbot'; import { Deeplink } from './pages/Deeplink/Deeplink'; +import { Explorer } from './pages/Explorer/explorer'; +import { ExplorerCircles } from './pages/Explorer/visuals/circles/circles'; +import { ExplorerForceGraph } from './pages/Explorer/visuals/force-graph/forceGraph'; import { GapAnalysis } from './pages/GapAnalysis/GapAnalysis'; import { MembershipRequired } from './pages/MembershipRequired/MembershipRequired'; import { SearchName } from './pages/Search/SearchName'; @@ -125,4 +129,22 @@ export const ROUTES: IRoute[] = [ showHeader: true, showFilter: false, }, + { + path: `${EXPLORER}/circles`, + component: ExplorerCircles, + showHeader: true, + showFilter: false, + }, + { + path: `${EXPLORER}/force_graph`, + component: ExplorerForceGraph, + showHeader: true, + showFilter: false, + }, + { + path: `${EXPLORER}`, + component: Explorer, + showHeader: true, + showFilter: false, + }, ]; diff --git a/application/frontend/src/scaffolding/Header/Header.tsx b/application/frontend/src/scaffolding/Header/Header.tsx index 362c0176d..362673684 100644 --- a/application/frontend/src/scaffolding/Header/Header.tsx +++ b/application/frontend/src/scaffolding/Header/Header.tsx @@ -21,6 +21,10 @@ const getLinks = (): { to: string; name: string }[] => [ to: `/map_analysis`, name: 'Map analysis', }, + { + to: `/explorer`, + name: 'Explorer', + }, ]; export const Header = () => { diff --git a/application/frontend/src/types.ts b/application/frontend/src/types.ts index a3c905b35..3b050b633 100644 --- a/application/frontend/src/types.ts +++ b/application/frontend/src/types.ts @@ -38,6 +38,18 @@ export interface GapAnalysisPathStart { extra: number; weakLinks: Record; } + +export interface TreeDocument extends Document { + displayName: string; + url: string; + links: LinkedTreeDocument[]; +} + +export interface LinkedTreeDocument { + document: TreeDocument; + ltype: string; +} + export interface PaginatedResponse { standards: Document[]; total_pages: number; diff --git a/application/frontend/src/utils/index.ts b/application/frontend/src/utils/index.ts index 24d98c1da..76fe64f5c 100644 --- a/application/frontend/src/utils/index.ts +++ b/application/frontend/src/utils/index.ts @@ -1 +1,27 @@ export { groupLinksByType as groupLinksByType, LinksByType, getDocumentDisplayName } from './document'; + +export const getLocalStorageObject = (key) => { + const itemStr = localStorage.getItem(key); + if (!itemStr) { + return null; + } + + const item = JSON.parse(itemStr); + const now = new Date(); + + if (now.getTime() > item.expiry) { + localStorage.removeItem(key); + return null; + } + return item.value; +}; + +export const setLocalStorageObject = (key, value, ttl) => { + const now = new Date(); + + const item = { + value: value, + expiry: now.getTime() + ttl, + }; + localStorage.setItem(key, JSON.stringify(item)); +}; diff --git a/package.json b/package.json index 18438f74b..3b66e89fd 100755 --- a/package.json +++ b/package.json @@ -42,9 +42,11 @@ "dependencies": { "@artsy/fresnel": "^1.4.0", "@react-oauth/google": "^0.11.0", + "@types/d3": "^7.4.2", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", "awesome-typescript-loader": "5.2.1", "axios": "^0.21.4", + "d3": "^7.8.5", "d3-dag": "^0.6.3", "date-fns": "^2.16.1", "del-cli": "^3.0.1", @@ -71,6 +73,7 @@ "react-flow": "^1.0.3", "react-flow-renderer": "^9.7.4", "react-force-graph-2d": "^1.23.2", + "react-force-graph-3d": "^1.24.0", "react-hot-toast": "^1.0.0", "react-query": "^3.15.2", "react-router-dom": "5.2.0", diff --git a/yarn.lock b/yarn.lock index 2d21f25e9..f6b98c247 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,17 @@ # yarn lockfile v1 +"3d-force-graph@^1.73": + version "1.73.0" + resolved "https://registry.yarnpkg.com/3d-force-graph/-/3d-force-graph-1.73.0.tgz#aa1117766f55459d88b3048afd70701d52a60c9e" + integrity sha512-fMuZxQRIx6pVnn/JiB/0VnM0VD6uRpku1TkXMXYbnzKiMziPYQnaKobQ/QAqSskrQGJA9RUaale0ux4lOsCnOw== + dependencies: + accessor-fn "1" + kapsule "1" + three ">=0.118 <1" + three-forcegraph "1" + three-render-objects "^1.29" + "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -1047,6 +1058,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.17.8": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" + integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.3.1": version "7.21.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" @@ -2242,6 +2260,11 @@ resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-18.6.4.tgz#40a3d0a93647124872dec8e0fd1bd5926695b6ca" integrity sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ== +"@tweenjs/tween.js@18 - 21": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-21.0.0.tgz#73f993c2d1de37b78b4c1246163e20bc6ae3b75e" + integrity sha512-qVfOiFh0U8ZSkLgA6tf7kj2MciqRbSCWaJZRwftVO7UbtVDNsZAXpWXqvCDtIefvjC83UJB+vHTDOGm5ibXjEA== + "@types/aria-query@^4.2.0": version "4.2.2" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" @@ -2310,6 +2333,216 @@ dependencies: "@types/node" "*" +"@types/d3-array@*": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.0.tgz#603b85d0072962bdecaf8391f60eea465c8dc282" + integrity sha512-tjU8juPSfhMnu6mJZPOCVVGba4rZoE0tjHDPb81PYwA8CzbaFscGjgkUM7juUJu6iWA1cCVWNEVwxZ5HN9Jj8Q== + +"@types/d3-axis@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.5.tgz#39e2f355da2cde9a8e8bb71907cdf6f4005f6a7b" + integrity sha512-ufDAV3SQzju+uB3Jlty7SUb/jMigjpIlvDDcSGvGmmO6OT/sNO93UE0dRzwWOZeBLzrLSA0CQM4bf3iq1std3A== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.5.tgz#94d869e11d7d28dee7e68eee080fa8aa0b9371ca" + integrity sha512-JROQXZNq1X6QdWstESDUv1VilwZ2hBCQnWB91yal+5yZvYwGQvYsGCjrkHGfKK/8/AcX1JnERmpQzdDDuLRUsA== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.5.tgz#528f22907c3b6deaa0151babcafa04adaf573c48" + integrity sha512-rs26AIhJjtc+XLR4YQU8IjPTLOlDVO4PR1y+pVFYEHzKh2tE5tYz3MF4QV6iz7HboXQEaYpJQt8dH9uUkne8yA== + +"@types/d3-color@*": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.2.tgz#7939eed011a908287cd1bcfd11580c17b2ac7f8a" + integrity sha512-At+Ski7dL8Bs58E8g8vPcFJc8tGcaC12Z4m07+p41+DRqnZQcAlp3NfYjLrhNYv+zEyQitU1CUxXNjqUyf+c0g== + +"@types/d3-contour@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.5.tgz#3a94c5441847ddb787988c5328e9b407500300c3" + integrity sha512-wLvjwdOQVd1NL1IcW90CCt1VtpeZ3V20p/OTXlkT8uAiprrJnq2PNNnRNe1QCez4U9aMU29Z14zpJQVLW1+Lcg== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.3.tgz#e306ff57327265418acb3bc9eaec1174a2d26371" + integrity sha512-+Lf5NPKZ4JBC9tbudVkKceQXRxU3jJs0el9aKQvinMtdnFSOG84eVXyhCNgIFuXNQO3iIcYs7sgzN359FEOZnQ== + +"@types/d3-dispatch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.5.tgz#918f37deaf74485371fa0ab21365ecb415258d89" + integrity sha512-hxvq2kc+9hydVppo21JCGfcM0tLTh1DXnG3MLN0KlxsNZJH4bsdl1iXDuWtXFpWWlBrCMwSqlnoLPDxNAZU3Bg== + +"@types/d3-drag@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.5.tgz#4f599a9b99fb6b2c88b7517e06c1f79a6acebf04" + integrity sha512-arHyAGvO0NEGGPCU2jTb31TlXeSxwty1bIxr5wOFOCVqVjgriXloLWXoRp39Oa0Y/qXxcAVMIonAWLrtLxUZAQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.5.tgz#c12df56be81d0b457d167842fa87276d0d6eb880" + integrity sha512-73WZR3QFOaSRVz9iOrebTbTnbo7xjcgS/i0Cq5zy0jMXPO3v/JbkTD3Zqii1eYE6v4EJ78g5VP407rm+p8fdlA== + +"@types/d3-ease@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.1.tgz#ef386d2f28602dba82206888047f97f7f7f7558a" + integrity sha512-VZofjpEt8HWv3nxUAosj5o/+4JflnJ7Bbv07k17VO3T2WRuzGdZeookfaF60iVh5RdhVG49LE5w6LIshVUC6rg== + +"@types/d3-fetch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.5.tgz#0bec3763a04d199ad8bce2756b6f6818ee188b32" + integrity sha512-Rc8pb6H0RRLpAV2hEXduykUgcDUOhjSLTLmCIeo6ejzgs4SaITh/EteMb3p5Env3Hqjsqw0fCksyqopHHzMkMg== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.7.tgz#8b7e0cb02351e29382e53430bc3ccd5202da337c" + integrity sha512-rsok4CEvPLyVWRPsFiBhanJc3up03H/EARVz4d8soPh8drv82YMuAckYy4yv8g4/81JwCng5U5/o9aj9d0T6bQ== + +"@types/d3-format@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.3.tgz#1edd7fb3f7c207c7ed0e0a95a9f329a57e76bd02" + integrity sha512-kxuLXSAEJykTeL/EI3tUiEfGqru7PRdqEy099YBnqFl+fF167UVSB4+wntlZv86ZdoYf0DHjsRHnTIm8kcH7qw== + +"@types/d3-geo@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.0.6.tgz#138821c463c67551e1cc13729f0211986c5c3cce" + integrity sha512-wblAES3b+C3hvp4VakwECEKtHquT/xc6K4HOna95LM1j1fd7s7WmU4V+JMQZfKhNCMkV2vWD+ZUgY2Uj6gqfuA== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.5.tgz#307666c5aea5de800b843f54f3c1d3f81c334285" + integrity sha512-DEcBUj1IL3WyPLDlh4m2nsNXnMLITXM5Vwcu4G85yJHtf2cVGPBjgky3L11WBnT+ayHKf06Tchk5mY1eGmd4WQ== + +"@types/d3-interpolate@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.3.tgz#e10c06c4bf11bd770ed56184a0d76cd516ff4ded" + integrity sha512-6OZ2EIB4lLj+8cUY7I/Cgn9Q+hLdA4DjJHYOQDiHL0SzqS1K9DL5xIOVBSIHgF+tiuO9MU1D36qvdIvRDRPh+Q== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.1.tgz#6171c9e388904014764661a37613e3c4ab8df22d" + integrity sha512-blRhp7ki7pVznM8k6lk5iUU9paDbVRVq+/xpf0RRgSJn5gr6SE7RcFtxooYGMBOc1RZiGyqRpVdu5AD0z0ooMA== + +"@types/d3-polygon@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.1.tgz#0aed3e82757054e31b2ba6c4ef535b554684a20f" + integrity sha512-nrcWPk7B9qs6xnpq60Cls44zm9eDmFAv65qi/N/emh/oftnG6uYz49aIS0mdFaGeJxVN8H3pHneMuZMV8EwFdw== + +"@types/d3-quadtree@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.4.tgz#2047d35258b10c76dd29348e71c1d6fad9f4258b" + integrity sha512-B725MopFDIOQ6njFbeOxIEf42HVO2Xv+FmcxQISdOKErvLbFqWz3Riu+OWujUYoogreqqyHBHcGGL/JzzXQYsw== + +"@types/d3-random@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.2.tgz#a48e02aac62417b5325ec0e5a63a8c3783ad75fc" + integrity sha512-8QhsqkKs6mymAZMrg3ZFXPxKA34rdgp3ZrtB8o6mhFsKAd1gOvR1gocWnca+kmXypQdwgnzKm9gZE2Uw8NjjKw== + +"@types/d3-scale-chromatic@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.1.tgz#646c8cf9ce869fd316a5180bb7f862efa4e74123" + integrity sha512-Ob7OrwiTeQXY/WBBbRHGZBOn6rH1h7y3jjpTSKYqDEeqFjktql6k2XSgNwLrLDmAsXhEn8P9NHDY4VTuo0ZY1w== + +"@types/d3-scale@*": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.6.tgz#9d221949f37b90b52696ec99f9b1e972d55fe10d" + integrity sha512-lo3oMLSiqsQUovv8j15X4BNEDOsnHuGjeVg7GRbAuB2PUa1prK5BNSOu6xixgNf3nqxPl4I1BqJWrPvFGlQoGQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.8.tgz#9423511db3ed00a55aad4217ac8d546db5d8e5f5" + integrity sha512-pxCZUfQyedq/DIlPXIR5wE1mIH37omOdx1yxRudL3KZ4AC+156jMjOv1z5RVlGq62f8WX2kyO0hTVgEx627QFg== + +"@types/d3-shape@*": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.4.tgz#748a256d5e499cdfb3e48beca9c557f3ea0ff15c" + integrity sha512-M2/xsWPsjaZc5ifMKp1EBp0gqJG0eO/zlldJNOC85Y/5DGsBQ49gDkRJ2h5GY7ZVD6KUumvZWsylSbvTaJTqKg== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.2.tgz#8b1c74e3f8f1bb2927d94de9bc18a85369898070" + integrity sha512-wr08C1Gh77qaN8JIkrn5Rz/bdt5M9bdEqFmEOcYhUSq2t2sHvLTBfb4XAtGB3D4hm0ubj50NXWWXoXyp5tPXDg== + +"@types/d3-time@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.2.tgz#f4425b2ebcb04495a7b2390da03633ef1a8adbe5" + integrity sha512-kbdRXTmUgNfw5OTE3KZnFQn6XdIc4QGroN5UixgdrXATmYsdlPQS6pEut9tVlIojtzuFD4txs/L+Rq41AHtLpg== + +"@types/d3-timer@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.1.tgz#8dac23292df0e559a3aa459d8efca78a734c3fbe" + integrity sha512-GGTvzKccVEhxmRfJEB6zhY9ieT4UhGVUIQaBzFpUO9OXy2ycAlnPCSJLzmGGgqt3KVjqN3QCQB4g1rsZnHsWhg== + +"@types/d3-transition@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.6.tgz#141684ef8046f4dc5da2d5b015c497513eba541c" + integrity sha512-K0To23B5UxNwFtKORnS5JoNYvw/DnknU5MzhHIS9czJ/lTqFFDeU6w9lArOdoTl0cZFNdNrMJSFCbRCEHccH2w== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.6.tgz#deb4fca8a020e8b7b0e04d636d35f2ab3da1d431" + integrity sha512-dGZQaXEu7aNcCL71LPpjB58IjoQNM9oDPfQuMUJ7N/fbkcIWGX2PnmUWO1jPJ+RLbZBpRUggJUX8twKRvo2hKQ== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.4.2": + version "7.4.2" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.2.tgz#2e9ccbec794b40e1ccac2dad2ba0642bf25b9a10" + integrity sha512-Y4g2Yb30ZJmmtqAJTqMRaqXwRawfvpdpVmyEYEcyGNhrQI/Zvkq3k7yE1tdN07aFSmNBfvmegMQ9Fe2qy9ZMhw== + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-fetch" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" + "@types/eslint-scope@^3.7.3": version "3.7.4" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" @@ -2360,6 +2593,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/geojson@*": + version "7946.0.12" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.12.tgz#0307536218d32e6b970bccd1d148b9c4e5b6f10d" + integrity sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA== + "@types/glob@^7.1.1": version "7.2.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" @@ -5283,6 +5521,11 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== +commander@7, commander@^7.0.0, commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@^2.19.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -5293,11 +5536,6 @@ commander@^5.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -commander@^7.0.0, commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" @@ -5775,6 +6013,13 @@ cwd@^0.10.0: dependencies: internmap "1 - 2" +"d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + d3-array@^2.11.0: version "2.12.1" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" @@ -5782,16 +6027,46 @@ d3-array@^2.11.0: dependencies: internmap "^1.0.0" +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + d3-binarytree@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/d3-binarytree/-/d3-binarytree-0.2.2.tgz#2b3421a4ac41ddaf3ebd2584f96f8e68ecb7c444" integrity sha512-TmgSEKWO4lSjX26Rk77hbTdiF3TQ1v5LqL+cmSz6/5RiSxmq6+e6qHE6X/KwrsIESekhEReH63X5yM8dvXaT7A== -"d3-color@1 - 3": +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: version "3.1.0" resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== +d3-contour@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" + integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== + dependencies: + d3-array "^3.2.0" + d3-dag@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/d3-dag/-/d3-dag-0.6.3.tgz#8fc297d6ff0b35fd8c5f250ff8b09c8371b16dee" @@ -5802,12 +6077,19 @@ d3-dag@^0.6.3: javascript-lp-solver "0.4.24" quadprog "^1.6.1" -"d3-dispatch@1 - 3": +d3-delaunay@6: + version "6.0.4" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== -"d3-drag@2 - 3": +"d3-drag@2 - 3", d3-drag@3: version "3.0.0" resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== @@ -5815,11 +6097,27 @@ d3-dag@^0.6.3: d3-dispatch "1 - 3" d3-selection "3" -"d3-ease@1 - 3": +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + "d3-force-3d@2 - 3": version "3.0.3" resolved "https://registry.yarnpkg.com/d3-force-3d/-/d3-force-3d-3.0.3.tgz#ddd0b9120837ef3cd6ffdad668d99d1992483af2" @@ -5831,12 +6129,33 @@ d3-dag@^0.6.3: d3-quadtree "1 - 3" d3-timer "1 - 3" -"d3-format@1 - 3": +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: version "3.1.0" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== -"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3": +d3-geo@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.0.tgz#74fd54e1f4cebd5185ac2039217a98d39b0a4c0e" + integrity sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== @@ -5848,12 +6167,27 @@ d3-octree@^0.2.0: resolved "https://registry.yarnpkg.com/d3-octree/-/d3-octree-0.2.2.tgz#24c513d809252d14fd3b0bf7eb5af321c30bd69b" integrity sha512-ysk9uSPAhZVb0Gq4GXzghl/Yqxu80dHrq55I53qaIMdGB65+0UfO84sr4Fci2JHumcgh6H4WE0r8LwxPagkE+g== -"d3-quadtree@1 - 3": +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== -"d3-scale-chromatic@1 - 3": +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +"d3-scale-chromatic@1 - 3", d3-scale-chromatic@3: version "3.0.0" resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a" integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g== @@ -5861,7 +6195,7 @@ d3-octree@^0.2.0: d3-color "1 - 3" d3-interpolate "1 - 3" -"d3-scale@1 - 4": +"d3-scale@1 - 4", d3-scale@4: version "4.0.2" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== @@ -5877,7 +6211,14 @@ d3-octree@^0.2.0: resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== -"d3-time-format@2 - 4": +d3-shape@3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +"d3-time-format@2 - 4", d3-time-format@4: version "4.1.0" resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== @@ -5891,12 +6232,19 @@ d3-octree@^0.2.0: dependencies: d3-array "2 - 3" -"d3-timer@1 - 3": +d3-time@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== -"d3-transition@2 - 3": +"d3-transition@2 - 3", d3-transition@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== @@ -5907,7 +6255,7 @@ d3-octree@^0.2.0: d3-interpolate "1 - 3" d3-timer "1 - 3" -"d3-zoom@2 - 3", d3-zoom@^3.0.0: +"d3-zoom@2 - 3", d3-zoom@3, d3-zoom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== @@ -5923,6 +6271,42 @@ d3@^3.5.17: resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8" integrity sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg== +d3@^7.8.5: + version "7.8.5" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.8.5.tgz#fde4b760d4486cdb6f0cc8e2cbff318af844635c" + integrity sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "4" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" @@ -5951,6 +6335,13 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-joint@1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/data-joint/-/data-joint-1.3.1.tgz#d134950322c90f531e81bbbe8454277549031466" + integrity sha512-tMK0m4OVGqiA3zkn8JmO6YAqD8UwJqIAx4AAwFl1SKTtKAqcXePuT+n2aayiX9uITtlN3DFtKKTOxJRUc2+HvQ== + dependencies: + index-array-by "^1.4.0" + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -6143,6 +6534,13 @@ del@^5.1.0: rimraf "^3.0.0" slash "^3.0.0" +delaunator@5: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" + integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + dependencies: + robust-predicates "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -8599,7 +8997,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.2, iconv-lite@^0.6.3: +iconv-lite@0.6, iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -8756,6 +9154,11 @@ index-array-by@1: resolved "https://registry.yarnpkg.com/index-array-by/-/index-array-by-1.3.3.tgz#6881ae680a44af2c344db5e18eac6c5dc1ccea47" integrity sha512-dpqV1sX+hx4s0RqAT97ypk9xzcAXJ0XK27p3bTgPy8bjbJAX6Kf7RU3pPXgmg9hhO7f5/WxO354v2f/A0/fz3Q== +index-array-by@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/index-array-by/-/index-array-by-1.4.1.tgz#425f26cf0c744a47ebadf47366692e52043cf17b" + integrity sha512-Zu6THdrxQdyTuT2uA5FjUoBEsFHPzHcPIj18FszN6yXKHxSfGcR4TPLabfuT//E25q1Igyx9xta2WMvD/x9P/g== + indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" @@ -9450,6 +9853,11 @@ jerrypick@^1.0.5: resolved "https://registry.yarnpkg.com/jerrypick/-/jerrypick-1.0.5.tgz#808a2a53acd332b1d972a097c510c5d28fb8e3e2" integrity sha512-95dIyL2QXqevDDJ70rmiqKLsTi+riZftLQo708tSFR/O5pQOf6VscDhjnN8mkNQwqnQmGhw+6dfZ5d4bmH/yww== +jerrypick@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/jerrypick/-/jerrypick-1.1.1.tgz#db0b15841a53cfe492de2db9544eecf8de73203c" + integrity sha512-XTtedPYEyVp4t6hJrXuRKr/jHj8SC4z+4K0b396PMkov6muL+i8IIamJIvZWe3jUspgIJak0P+BaWKawMYNBLg== + jest-changed-files@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" @@ -10569,6 +10977,13 @@ just-extend@^4.0.2: resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== +kapsule@1: + version "1.14.5" + resolved "https://registry.yarnpkg.com/kapsule/-/kapsule-1.14.5.tgz#c0bc7c1d4c693ee2647182e5b4ffbf95a4d65f72" + integrity sha512-H0iSpTynUzZw3tgraDmReprpFRmH5oP5GPmaNsurSwLx2H5iCpOMIkp5q+sfhB4Tz/UJd1E1IbEE9Z6ksnJ6RA== + dependencies: + lodash-es "4" + kapsule@^1.13: version "1.13.8" resolved "https://registry.yarnpkg.com/kapsule/-/kapsule-1.13.8.tgz#1f43f8111b1b78d13e45daeff35dbef1e81114c2" @@ -10888,7 +11303,7 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash-es@^4.17.21: +lodash-es@4, lodash-es@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== @@ -11611,6 +12026,37 @@ next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== +ngraph.events@^1.0.0, ngraph.events@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ngraph.events/-/ngraph.events-1.2.2.tgz#3ceb92d676a04a4e7ce60a09fa8e17a4f0346d7f" + integrity sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ== + +ngraph.forcelayout@3: + version "3.3.1" + resolved "https://registry.yarnpkg.com/ngraph.forcelayout/-/ngraph.forcelayout-3.3.1.tgz#981e1baee5e0593c490bc27219169f9cedfa4f8b" + integrity sha512-MKBuEh1wujyQHFTW57y5vd/uuEOK0XfXYxm3lC7kktjJLRdt/KEKEknyOlc6tjXflqBKEuYBBcu7Ax5VY+S6aw== + dependencies: + ngraph.events "^1.0.0" + ngraph.merge "^1.0.0" + ngraph.random "^1.0.0" + +ngraph.graph@20: + version "20.0.1" + resolved "https://registry.yarnpkg.com/ngraph.graph/-/ngraph.graph-20.0.1.tgz#579470d1d805583239704dc913e2095540aaf371" + integrity sha512-VFsQ+EMkT+7lcJO1QP8Ik3w64WbHJl27Q53EO9hiFU9CRyxJ8HfcXtfWz/U8okuoYKDctbciL6pX3vG5dt1rYA== + dependencies: + ngraph.events "^1.2.1" + +ngraph.merge@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ngraph.merge/-/ngraph.merge-1.0.0.tgz#d763cdfa48b1bbd4270ea246f06c9c8ff5d3477c" + integrity sha512-5J8YjGITUJeapsomtTALYsw7rFveYkM+lBj3QiYZ79EymQcuri65Nw3knQtFxQBU1r5iOaVRXrSwMENUPK62Vg== + +ngraph.random@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ngraph.random/-/ngraph.random-1.1.0.tgz#5345c4bb63865c85d98ee6f13eab1395d8545a90" + integrity sha512-h25UdUN/g8U7y29TzQtRm/GvGr70lK37yQPvPKXXuVfs7gCm82WipYFZcksQfeKumtOemAzBIcT7lzzyK/edLw== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -12583,6 +13029,13 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +polished@4: + version "4.2.2" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1" + integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ== + dependencies: + "@babel/runtime" "^7.17.8" + portfinder@^1.0.26: version "1.0.32" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" @@ -13362,7 +13815,7 @@ promzard@^0.3.0: dependencies: read "1" -prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.0, prop-types@^15.7.2, prop-types@^15.8, prop-types@^15.8.1: +prop-types@15, prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.0, prop-types@^15.7.2, prop-types@^15.8, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -13681,6 +14134,15 @@ react-force-graph-2d@^1.23.2: prop-types "^15.8" react-kapsule "^2.2" +react-force-graph-3d@^1.24.0: + version "1.24.0" + resolved "https://registry.yarnpkg.com/react-force-graph-3d/-/react-force-graph-3d-1.24.0.tgz#560a0c6835dc0ec09696481237b4eb3e7fe14e14" + integrity sha512-EyfiIqhs6L6q5OvUQFUtcbn9EGMPaG5nesX12gsQZ6tf8DvOR4haBY3Vj+C7afIqUl5579Ac6yhPIeolgsV7pA== + dependencies: + "3d-force-graph" "^1.73" + prop-types "15" + react-kapsule "2" + react-hot-toast@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-1.0.2.tgz#162f020ba7c0b20f2f25bb7738458c435e84107c" @@ -13702,6 +14164,14 @@ react-is@^17.0.0, react-is@^17.0.1, react-is@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" +react-kapsule@2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/react-kapsule/-/react-kapsule-2.4.0.tgz#50d296ed2872a6db89f2de176eebb1a4ce2cccb8" + integrity sha512-w4Yv9CgWdj8kWGQEPNWFGJJ08dYEZHZpiaFR/DgZjCMBNqv9wus2Gy1qvHVJmJbzvAZbq6jdvFC+NYzEqAlNhQ== + dependencies: + fromentries "^1.3.2" + jerrypick "^1.1.1" + react-kapsule@^2.2: version "2.2.5" resolved "https://registry.yarnpkg.com/react-kapsule/-/react-kapsule-2.2.5.tgz#f65e747818e49150215c0678cf7fa1b6bf7543fe" @@ -14055,6 +14525,11 @@ regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7, regenerator-runtime@^0 resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw== +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" @@ -14366,6 +14841,11 @@ ripemd160@0.2.0: resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce" integrity sha512-JJsJ74Mw4sUDDisXGDnNNyN9xWmt5HcH6Kwvb/0m/IvTKjnLAtZfzeoLdpxk44AxQZki54oCCd+Kt0nPQ2AF2g== +robust-predicates@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + rollup-plugin-terser@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" @@ -14403,6 +14883,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + rxjs@^7.5.4: version "7.5.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" @@ -15616,6 +16101,37 @@ text-table@^0.2.0, text-table@~0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +three-forcegraph@1: + version "1.41.10" + resolved "https://registry.yarnpkg.com/three-forcegraph/-/three-forcegraph-1.41.10.tgz#a162263b5c5db957c88cb496baff057f12bb26ef" + integrity sha512-XrrH0HzlWQiY5A30RMtlu+SpAM/LOoHMyaQouCFgavTSLrSsP4UIUP3eWrfJ0be1xDPuMGt3iofSYjgu4UT2NA== + dependencies: + accessor-fn "1" + d3-array "1 - 3" + d3-force-3d "2 - 3" + d3-scale "1 - 4" + d3-scale-chromatic "1 - 3" + data-joint "1" + kapsule "1" + ngraph.forcelayout "3" + ngraph.graph "20" + tinycolor2 "1" + +three-render-objects@^1.29: + version "1.29.0" + resolved "https://registry.yarnpkg.com/three-render-objects/-/three-render-objects-1.29.0.tgz#fb9769e62784f02682d7d26626dda4fec2655deb" + integrity sha512-HzVjL12KG2ko5VoU3aO/qFbtVu5Md5SN8dSzjGS7uNeTmYSAdQQZmg+R6zgctmvUrEjA78vO6ZGAC9y/9o/H2A== + dependencies: + "@tweenjs/tween.js" "18 - 21" + accessor-fn "1" + kapsule "1" + polished "4" + +"three@>=0.118 <1": + version "0.158.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.158.0.tgz#03ddd5b60ce9c31be8fb69f27a6d9efd49908ac3" + integrity sha512-TALj4EOpdDPF1henk2Q+s17K61uEAAWQ7TJB68nr7FKxqwyDr3msOt5IWdbGm4TaWKjrtWS8DJJWe9JnvsWOhQ== + throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -15658,6 +16174,11 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tinycolor2@1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" + integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== + tinycolor2@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"