diff --git a/package.json b/package.json index 10a6e426..539df196 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,8 @@ "@openshift/dynamic-plugin-sdk-webpack": "~1.0.0", "@patternfly/react-core": "5.1.1", "@patternfly/react-table": "^5.1.1", + "@patternfly/react-icons": "5.2.1", + "@patternfly/react-topology": "5.2.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^12.0.0", "@testing-library/react-hooks": "^8.0.1", diff --git a/src/console-models/NodeNetworkStateModel.ts b/src/console-models/NodeNetworkStateModel.ts index da362d14..a68c1042 100644 --- a/src/console-models/NodeNetworkStateModel.ts +++ b/src/console-models/NodeNetworkStateModel.ts @@ -2,7 +2,7 @@ import { K8sModel } from '@openshift-console/dynamic-plugin-sdk/lib/api/common-t import { modelToGroupVersionKind, modelToRef } from './modelUtils'; -const NodeNetworkStateModel: K8sModel = { +export const NodeNetworkStateModel: K8sModel = { label: 'NodeNetworkState', labelPlural: 'NodeNetworkStates', apiVersion: 'v1beta1', @@ -17,5 +17,3 @@ const NodeNetworkStateModel: K8sModel = { export const NodeNetworkStateModelGroupVersionKind = modelToGroupVersionKind(NodeNetworkStateModel); export const NodeNetworkStateModelRef = modelToRef(NodeNetworkStateModel); - -export default NodeNetworkStateModel; diff --git a/src/utils/components/DetailItem/DetailItem.scss b/src/utils/components/DetailItem/DetailItem.scss new file mode 100644 index 00000000..5bb3d0bd --- /dev/null +++ b/src/utils/components/DetailItem/DetailItem.scss @@ -0,0 +1,17 @@ +.description-item__title { + justify-content: space-between; + flex: 1; +} + +.margin-top { + margin-top: var(--pf-v5-global--spacer--md); +} + +.DescriptionItemHeader { + &--list-term { + .pf-c-description-list__text { + align-items: center; + display: inline-flex; + } + } +} diff --git a/src/utils/components/DetailItem/DetailItem.tsx b/src/utils/components/DetailItem/DetailItem.tsx new file mode 100644 index 00000000..131029d3 --- /dev/null +++ b/src/utils/components/DetailItem/DetailItem.tsx @@ -0,0 +1,116 @@ +import React, { FC, ReactNode } from 'react'; + +import { + Button, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTermHelpText, + Flex, + FlexItem, +} from '@patternfly/react-core'; +import { PencilAltIcon } from '@patternfly/react-icons'; +import { useNMStateTranslation } from '@utils/hooks/useNMStateTranslation'; + +import { DetailItemHeader } from './DetailItemHeader'; +import EditButtonWithTooltip from './EditButtonWithTooltip'; + +import './DetailItem.scss'; + +type DetailItemProps = { + bodyContent?: ReactNode; + breadcrumb?: string; + className?: string; + 'data-test-id'?: string; + descriptionData: any; + descriptionHeader?: ReactNode; + editOnTitleJustify?: boolean; + isDisabled?: boolean; + isEdit?: boolean; + isPopover?: boolean; + label?: ReactNode; + messageOnDisabled?: string; + moreInfoURL?: string; + onEditClick?: () => void; + showEditOnTitle?: boolean; +}; + +const DetailItem: FC = ({ + bodyContent, + breadcrumb, + className, + 'data-test-id': testId, + descriptionData, + descriptionHeader, + editOnTitleJustify = false, + isDisabled, + isEdit, + isPopover, + label, + messageOnDisabled, + moreInfoURL, + onEditClick, + showEditOnTitle, +}) => { + const { t } = useNMStateTranslation(); + const NotAvailable = {t('Not available')}; + + const description = ( + + {descriptionData ?? NotAvailable} + + ); + + return ( + + + + {(bodyContent || breadcrumb || descriptionHeader || label || moreInfoURL) && ( + + + + )} + {isEdit && showEditOnTitle && ( + + + + )} + + + + + {isEdit && !showEditOnTitle ? description : descriptionData} + + + ); +}; + +export default DetailItem; diff --git a/src/utils/components/DetailItem/DetailItemHeader.tsx b/src/utils/components/DetailItem/DetailItemHeader.tsx new file mode 100644 index 00000000..6ad253d4 --- /dev/null +++ b/src/utils/components/DetailItem/DetailItemHeader.tsx @@ -0,0 +1,74 @@ +import React, { FC, ReactNode } from 'react'; + +import { + Breadcrumb, + BreadcrumbItem, + DescriptionListTerm, + DescriptionListTermHelpTextButton, + Popover, +} from '@patternfly/react-core'; +import { useNMStateTranslation } from '@utils/hooks/useNMStateTranslation'; + +import './DetailItem.scss'; + +type DetailItemHeaderProps = { + bodyContent: ReactNode; + breadcrumb?: string; + descriptionHeader: ReactNode; + isPopover: boolean; + label?: ReactNode; + maxWidth?: string; + moreInfoURL?: string; +}; + +export const DetailItemHeader: FC = ({ + bodyContent, + breadcrumb, + descriptionHeader, + isPopover, + label, + maxWidth, + moreInfoURL, +}) => { + const { t } = useNMStateTranslation(); + + if (isPopover && bodyContent) { + return ( + + {bodyContent} + {moreInfoURL && ( + <> + {t('More info: ')} + {moreInfoURL} + + )} + {breadcrumb && ( +
+ + {breadcrumb.split('.').map((item) => ( + {item} + ))} + +
+ )} + + } + hasAutoWidth + headerContent={descriptionHeader} + maxWidth={maxWidth || '30rem'} + > + + {descriptionHeader} + +
+ ); + } + + return ( + + {descriptionHeader} {label} + + ); +}; diff --git a/src/utils/components/DetailItem/EditButtonWithTooltip.tsx b/src/utils/components/DetailItem/EditButtonWithTooltip.tsx new file mode 100644 index 00000000..9433c112 --- /dev/null +++ b/src/utils/components/DetailItem/EditButtonWithTooltip.tsx @@ -0,0 +1,51 @@ +import React, { FC, PropsWithChildren, ReactNode, SyntheticEvent } from 'react'; + +import { Button, Flex, Tooltip } from '@patternfly/react-core'; +import { PencilAltIcon } from '@patternfly/react-icons'; + +type EditButtonWithTooltipProps = PropsWithChildren<{ + isEditable: boolean; + onEditClick: () => void; + testId: string; + tooltipContent?: ReactNode; +}>; + +const EditButtonWithTooltip: FC = ({ + children, + isEditable, + onEditClick, + testId, + tooltipContent, +}) => { + const EditButton = () => ( + + ); + + if (!isEditable && tooltipContent) { + return ( + + + + + + ); + } + + return ; +}; + +export default EditButtonWithTooltip; diff --git a/src/utils/components/DetailItem/OwnerDetailItem.tsx b/src/utils/components/DetailItem/OwnerDetailItem.tsx new file mode 100644 index 00000000..ac1f6168 --- /dev/null +++ b/src/utils/components/DetailItem/OwnerDetailItem.tsx @@ -0,0 +1,60 @@ +import React, { FC } from 'react'; +import { Trans } from 'react-i18next'; + +import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk'; +import { + Breadcrumb, + BreadcrumbItem, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTermHelpText, + DescriptionListTermHelpTextButton, + Popover, +} from '@patternfly/react-core'; +import { useNMStateTranslation } from '@utils/hooks/useNMStateTranslation'; + +import OwnerReferences from '../OwnerReferences/OwnerReferences'; + +type OwnerDetailsItemProps = { + obj: K8sResourceCommon; +}; + +const OwnerDetailsItem: FC = ({ obj }) => { + const { t } = useNMStateTranslation(); + + return ( + + + +
+ List of objects depended by this object. If ALL objects in the list have been + deleted, this object will be garbage collected. If this object is managed by a + controller, then an entry in this list will point to this controller, with the + controller field set to true. There cannot be more than one managing controller. +
+ + {{ kind: obj?.kind }} + metadata + ownerReferences + + + } + hasAutoWidth + headerContent={t('Owner')} + maxWidth="30rem" + > + + {t('Owner')} + +
+
+ + + +
+ ); +}; + +export default OwnerDetailsItem; diff --git a/src/utils/components/MetadataLabels/MetadataLabels.scss b/src/utils/components/MetadataLabels/MetadataLabels.scss new file mode 100644 index 00000000..f7289556 --- /dev/null +++ b/src/utils/components/MetadataLabels/MetadataLabels.scss @@ -0,0 +1,8 @@ +.metadata-labels-group { + padding-top: var(--pf-c-label-group--m-category--PaddingTop); + padding-right: var(--pf-c-label-group--m-category--PaddingRight); + padding-bottom: var(--pf-c-label-group--m-category--PaddingBottom); + padding-left: var(--pf-c-label-group--m-category--PaddingLeft); + border: var(--pf-c-label-group--m-category--BorderWidth) solid + var(--pf-c-label-group--m-category--BorderColor); +} diff --git a/src/utils/components/MetadataLabels/MetadataLabels.tsx b/src/utils/components/MetadataLabels/MetadataLabels.tsx new file mode 100644 index 00000000..c5e1f244 --- /dev/null +++ b/src/utils/components/MetadataLabels/MetadataLabels.tsx @@ -0,0 +1,38 @@ +import React, { FC } from 'react'; +import { Link } from 'react-router-dom-v5-compat'; +import { modelToRef } from 'src/console-models/modelUtils'; + +import { K8sModel } from '@openshift-console/dynamic-plugin-sdk'; +import { Label, LabelGroup } from '@patternfly/react-core'; + +import './MetadataLabels.scss'; + +type MetadataLabelsProps = { + labels?: { [key: string]: string }; + model: K8sModel; +}; + +const MetadataLabels: FC = ({ labels, model }) => { + const modelRef = modelToRef(model); + + return ( + + {Object.keys(labels || {})?.map((key) => { + const labelText = labels?.[key] ? `${key}=${labels?.[key]}` : key; + + return ( + + ); + })} + + ); +}; + +export default MetadataLabels; diff --git a/src/utils/components/OwnerReferences/OwnerReferences.tsx b/src/utils/components/OwnerReferences/OwnerReferences.tsx new file mode 100644 index 00000000..56a14683 --- /dev/null +++ b/src/utils/components/OwnerReferences/OwnerReferences.tsx @@ -0,0 +1,36 @@ +import React, { FC } from 'react'; + +import { + getGroupVersionKindForResource, + K8sResourceCommon, + OwnerReference, + ResourceLink, +} from '@openshift-console/dynamic-plugin-sdk'; +import { isEmpty } from '@utils/helpers'; +import { useNMStateTranslation } from '@utils/hooks/useNMStateTranslation'; + +type OwnerReferencesProps = { + obj: K8sResourceCommon; +}; + +const OwnerReferences: FC = ({ obj }) => { + const { t } = useNMStateTranslation(); + const ownerReferences = (obj?.metadata?.ownerReferences || [])?.map( + (ownerRef: OwnerReference) => ( + + ), + ); + + return !isEmpty(ownerReferences) ? ( +
{ownerReferences}
+ ) : ( + {t('No owner')} + ); +}; + +export default OwnerReferences; diff --git a/src/views/states/details/StateDetailsPage.tsx b/src/views/states/details/StateDetailsPage.tsx new file mode 100644 index 00000000..605da01e --- /dev/null +++ b/src/views/states/details/StateDetailsPage.tsx @@ -0,0 +1,77 @@ +import React, { FC } from 'react'; + +import { NodeNetworkStateModel, NodeNetworkStateModelGroupVersionKind } from '@models'; +import { + ResourceIcon, + Timestamp, + useAnnotationsModal, + useLabelsModal, +} from '@openshift-console/dynamic-plugin-sdk'; +import { + DescriptionList, + Divider, + PageSection, + PageSectionVariants, + Title, +} from '@patternfly/react-core'; +import { V1beta1NodeNetworkState } from '@types'; +import DetailItem from '@utils/components/DetailItem/DetailItem'; +import OwnerDetailsItem from '@utils/components/DetailItem/OwnerDetailItem'; +import MetadataLabels from '@utils/components/MetadataLabels/MetadataLabels'; +import { useNMStateTranslation } from '@utils/hooks/useNMStateTranslation'; + +type StateDetailsPageProps = { + nns: V1beta1NodeNetworkState; +}; + +const StateDetailsPage: FC = ({ nns }) => { + const { t } = useNMStateTranslation(); + const launchLabelsModal = useLabelsModal(nns); + const launchAnnotationsModal = useAnnotationsModal(nns); + + if (!nns) return null; + + const annotationsCount = Object.keys(nns?.metadata?.annotations || {}).length; + const annotationsText = t('{{annotationsCount}} Annotations', { + annotationsCount, + }); + + return ( + <> + + <span className="co-resource-item__resource-name"> + <ResourceIcon groupVersionKind={NodeNetworkStateModelGroupVersionKind} /> + <span className="co-resource-item__resource-name">{nns?.metadata?.name} </span> + </span> + + + + + + + } + descriptionHeader={t('Labels')} + isEdit + onEditClick={launchLabelsModal} + showEditOnTitle + /> + + } + descriptionHeader={t('Created at')} + /> + + + + + ); +}; + +export default StateDetailsPage; diff --git a/src/views/states/list/StatesList.tsx b/src/views/states/list/StatesList.tsx index 7f1ba26f..a92e9288 100644 --- a/src/views/states/list/StatesList.tsx +++ b/src/views/states/list/StatesList.tsx @@ -1,11 +1,12 @@ -import React, { FC, useState } from 'react'; +import React, { FC, useCallback, useState } from 'react'; +import { useNavigate } from 'react-router-dom-v5-compat'; +import { useNMStateTranslation } from 'src/utils/hooks/useNMStateTranslation'; + import { + NodeNetworkStateModel, NodeNetworkStateModelGroupVersionKind, NodeNetworkStateModelRef, -} from 'src/console-models'; -import NodeNetworkStateModel from 'src/console-models/NodeNetworkStateModel'; -import { useNMStateTranslation } from 'src/utils/hooks/useNMStateTranslation'; - +} from '@models'; import { ListPageBody, ListPageFilter, @@ -13,7 +14,8 @@ import { useK8sWatchResource, useListPageFilter, } from '@openshift-console/dynamic-plugin-sdk'; -import { Button, Flex, Pagination } from '@patternfly/react-core'; +import { Button, Flex, Icon, Pagination } from '@patternfly/react-core'; +import { TopologyIcon } from '@patternfly/react-icons'; import { Table, TableGridBreakpoint, Th, Thead, Tr } from '@patternfly/react-table'; import { V1beta1NodeNetworkState } from '@types'; import usePagination from '@utils/hooks/usePagination/usePagination'; @@ -33,7 +35,17 @@ import './states-list.scss'; const StatesList: FC = () => { const { t } = useNMStateTranslation(); - const { selectedInterfaceName, selectedStateName, selectedInterfaceType } = useDrawerInterface(); + const navigate = useNavigate(); + const { + selectedInterfaceName, + selectedStateName, + selectedInterfaceType, + setSelectedInterfaceName, + } = useDrawerInterface(); + + const onClose = useCallback(() => { + setSelectedInterfaceName(); + }, []); const [expandAll, setExpandAll] = useState(false); @@ -62,10 +74,15 @@ const StatesList: FC = () => { const { sortedStates, nameSortParams } = useSortStates(filteredData); const paginatedData = sortedStates.slice(pagination?.startIndex, pagination?.endIndex + 1); - return ( <> - + + +
@@ -144,7 +161,7 @@ const StatesList: FC = () => { )} - + ); }; diff --git a/src/views/states/list/components/InterfaceDrawer/InterfaceDrawer.tsx b/src/views/states/list/components/InterfaceDrawer/InterfaceDrawer.tsx index fcc56901..706a0830 100644 --- a/src/views/states/list/components/InterfaceDrawer/InterfaceDrawer.tsx +++ b/src/views/states/list/components/InterfaceDrawer/InterfaceDrawer.tsx @@ -1,25 +1,21 @@ -import React, { FC, useCallback } from 'react'; +import React, { FC } from 'react'; import { Modal, Title } from '@patternfly/react-core'; import { NodeNetworkConfigurationInterface } from '@types'; import { useNMStateTranslation } from '@utils/hooks/useNMStateTranslation'; -import useDrawerInterface from '../../hooks/useDrawerInterface'; - import { InterfaceDrawerTabId, InterfaceDrawerTabProps } from './constants'; import InterfaceDrawerDetailsTab from './InterfaceDrawerDetailsTab'; import InterfaceDrawerYAMLFooter from './InterfaceDrawerFooter'; import InterfaceDrawerYAMLTab from './InterfaceDrawerYAMLTab'; -const InterfaceDrawer: FC<{ selectedInterface: NodeNetworkConfigurationInterface }> = ({ - selectedInterface, -}) => { - const { t } = useNMStateTranslation(); - const { setSelectedInterfaceName } = useDrawerInterface(); +type InterfaceDrawerProps = { + selectedInterface: NodeNetworkConfigurationInterface; + onClose: () => void; +}; - const onClose = useCallback(() => { - setSelectedInterfaceName(); - }, []); +const InterfaceDrawer: FC = ({ selectedInterface, onClose }) => { + const { t } = useNMStateTranslation(); const Tabs: InterfaceDrawerTabProps[] = [ { diff --git a/src/views/states/list/constants.ts b/src/views/states/list/constants.ts index 6733a216..a494f377 100644 --- a/src/views/states/list/constants.ts +++ b/src/views/states/list/constants.ts @@ -1,5 +1,4 @@ -import NodeNetworkStateModel from 'src/console-models/NodeNetworkStateModel'; - +import { NodeNetworkStateModel } from '@models'; import { getResourceUrl } from '@utils/helpers'; export const baseListUrl = getResourceUrl({ model: NodeNetworkStateModel }); diff --git a/src/views/states/manifest.ts b/src/views/states/manifest.ts index 8d6a2f43..3507c66e 100644 --- a/src/views/states/manifest.ts +++ b/src/views/states/manifest.ts @@ -1,20 +1,15 @@ import type { EncodedExtension } from '@openshift/dynamic-plugin-sdk'; import type { - ExtensionK8sModel, ResourceClusterNavItem, ResourceListPage, + RoutePage, } from '@openshift-console/dynamic-plugin-sdk'; -import NodeNetworkStateModel from '../../console-models/NodeNetworkStateModel'; - -const StateExtensionModel: ExtensionK8sModel = { - group: NodeNetworkStateModel.apiGroup as string, - kind: NodeNetworkStateModel.kind, - version: NodeNetworkStateModel.apiVersion, -}; +import { NodeNetworkStateModelGroupVersionKind } from '../../console-models'; export const StateExposedModules = { StatesList: './views/states/list/StatesList', + Topology: './views/states/topology/Topology', }; export const StateExtensions: EncodedExtension[] = [ @@ -25,7 +20,7 @@ export const StateExtensions: EncodedExtension[] = [ perspective: 'admin', name: '%plugin__nmstate-console-plugin~NodeNetworkState%', section: 'networking', - model: StateExtensionModel, + model: NodeNetworkStateModelGroupVersionKind, dataAttributes: { 'data-quickstart-id': 'qs-nav-state-list', 'data-test-id': 'state-nav-list', @@ -36,8 +31,17 @@ export const StateExtensions: EncodedExtension[] = [ type: 'console.page/resource/list', properties: { perspective: 'admin', - model: StateExtensionModel, + model: NodeNetworkStateModelGroupVersionKind, component: { $codeRef: 'StatesList' }, }, } as EncodedExtension, + { + type: 'console.page/route', + properties: { + path: ['nmstate-topology'], + component: { + $codeRef: 'Topology', + }, + }, + } as EncodedExtension, ]; diff --git a/src/views/states/topology/Topology.tsx b/src/views/states/topology/Topology.tsx new file mode 100644 index 00000000..b46ce6db --- /dev/null +++ b/src/views/states/topology/Topology.tsx @@ -0,0 +1,134 @@ +import React, { FC, useEffect, useMemo, useState } from 'react'; +import { useNavigate } from 'react-router-dom-v5-compat'; + +import { NodeNetworkStateModelGroupVersionKind, NodeNetworkStateModelRef } from '@models'; +import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; +import { Button, Divider, Icon, Title, ToolbarItem } from '@patternfly/react-core'; +import { ListIcon } from '@patternfly/react-icons'; +import { + action, + createTopologyControlButtons, + defaultControlButtonsOptions, + SELECTION_EVENT, + TopologyControlBar, + TopologySideBar, + TopologyView, + Visualization, + VisualizationProvider, + VisualizationSurface, +} from '@patternfly/react-topology'; +import { V1beta1NodeNetworkState } from '@types'; + +import StateDetailsPage from '../details/StateDetailsPage'; +import InterfaceDrawerDetailsTab from '../list/components/InterfaceDrawer/InterfaceDrawerDetailsTab'; + +import { componentFactory, layoutFactory } from './utils/factory'; +import { transformDataToTopologyModel } from './utils/utils'; + +const Topology: FC = () => { + const navigate = useNavigate(); + const [selectedIds, setSelectedIds] = useState([]); + const [visualization, setVisualization] = useState(null); + + const [data, loaded, error] = useK8sWatchResource({ + groupVersionKind: NodeNetworkStateModelGroupVersionKind, + isList: true, + namespaced: false, + }); + + const { selectedState, selectedInterface } = useMemo(() => { + if (selectedIds.length === 0) return { selectedState: null, selectedInterface: null }; + + const [selectedNNSName, selectedInterfaceName] = selectedIds[0].split('~'); + const selectedState = data?.find((state) => state.metadata.name === selectedNNSName); + const selectedInterface = selectedState?.status?.currentState?.interfaces?.find( + (iface) => iface.name === selectedInterfaceName, + ); + + return { selectedState, selectedInterface }; + }, [selectedIds, data]); + + useEffect(() => { + if (loaded && !error) { + const topologyModel = transformDataToTopologyModel(data); + + if (!visualization) { + const newVisualization = new Visualization(); + newVisualization.registerLayoutFactory(layoutFactory); + newVisualization.registerComponentFactory(componentFactory); + newVisualization.addEventListener(SELECTION_EVENT, setSelectedIds); + newVisualization.fromModel(topologyModel); + setVisualization(newVisualization); + } else { + visualization.fromModel(topologyModel); + } + } + }, [data, loaded, error]); + + const topologySideBar = ( + 0} onClose={() => setSelectedIds([])}> +
+ {!selectedInterface ? ( + + ) : ( + <> + {selectedInterface?.name} + + + + )} +
+
+ ); + + const topologyToolBar = ( + <> + node filter + + + + + ); + + return ( + { + visualization.getGraph().scaleBy(4 / 3); + }), + zoomOutCallback: action(() => { + visualization.getGraph().scaleBy(0.75); + }), + fitToScreenCallback: action(() => { + visualization.getGraph().fit(80); + }), + resetViewCallback: action(() => { + visualization.getGraph().reset(); + visualization.getGraph().layout(); + }), + legend: false, + })} + /> + } + > + + + + + ); +}; + +export default Topology; diff --git a/src/views/states/topology/components/CustomGroup.tsx b/src/views/states/topology/components/CustomGroup.tsx new file mode 100644 index 00000000..d010245d --- /dev/null +++ b/src/views/states/topology/components/CustomGroup.tsx @@ -0,0 +1,17 @@ +import React, { FC } from 'react'; + +import { DefaultGroup, Node } from '@patternfly/react-topology'; + +type CustomGroupProps = { + element: Node; +} & any; + +const CustomGroup: FC = ({ element, ...rest }) => { + const data = element.getData(); + + return ( + + ); +}; + +export default CustomGroup; diff --git a/src/views/states/topology/components/CustomNode.tsx b/src/views/states/topology/components/CustomNode.tsx new file mode 100644 index 00000000..13b23142 --- /dev/null +++ b/src/views/states/topology/components/CustomNode.tsx @@ -0,0 +1,42 @@ +import React, { FC } from 'react'; + +import { + DefaultNode, + Node, + WithDndDropProps, + WithDragNodeProps, + WithSelectionProps, +} from '@patternfly/react-topology'; + +import { ICON_SIZE } from '../utils/constants'; + +type CustomNodeProps = { + element: Node; +} & WithSelectionProps & + WithDragNodeProps & + WithDndDropProps; + +const CustomNode: FC = ({ element, onSelect, selected }) => { + const data = element.getData(); + const Icon = data.icon; + const { width, height } = element.getBounds(); + + const xCenter = (width - ICON_SIZE) / 2; + const yCenter = (height - ICON_SIZE) / 2; + + return ( + + + + + + ); +}; + +export default CustomNode; diff --git a/src/views/states/topology/utils/constants.ts b/src/views/states/topology/utils/constants.ts new file mode 100644 index 00000000..b3175e2c --- /dev/null +++ b/src/views/states/topology/utils/constants.ts @@ -0,0 +1,4 @@ +export const NODE_DIAMETER = 35; +export const CONNECTOR_TARGET_DROP = 'connector-target-drop'; +export const GROUP = 'group'; +export const ICON_SIZE = 15; diff --git a/src/views/states/topology/utils/factory.ts b/src/views/states/topology/utils/factory.ts new file mode 100644 index 00000000..e49f9669 --- /dev/null +++ b/src/views/states/topology/utils/factory.ts @@ -0,0 +1,80 @@ +import { + ColaLayout, + ComponentFactory, + DefaultEdge, + DragObjectWithType, + Edge, + Graph, + GraphComponent, + graphDropTargetSpec, + GraphElement, + groupDropTargetSpec, + Layout, + LayoutFactory, + ModelKind, + Node, + nodeDragSourceSpec, + nodeDropTargetSpec, + withDndDrop, + withDragNode, + withPanZoom, + withSelection, + withTargetDrag, +} from '@patternfly/react-topology'; + +import CustomGroup from '../components/CustomGroup'; +import CustomNode from '../components/CustomNode'; + +import { CONNECTOR_TARGET_DROP, GROUP } from './constants'; + +export const layoutFactory: LayoutFactory = (type: string, graph: Graph): Layout | undefined => + new ColaLayout(graph); + +export const componentFactory: ComponentFactory = (kind: ModelKind, type: string): any => { + switch (type) { + case GROUP: + return withDndDrop(groupDropTargetSpec)( + withDragNode(nodeDragSourceSpec(GROUP))(withSelection()(CustomGroup)), + ); + default: + switch (kind) { + case ModelKind.graph: + return withDndDrop(graphDropTargetSpec())(withPanZoom()(GraphComponent)); + case ModelKind.node: + return withDndDrop(nodeDropTargetSpec([CONNECTOR_TARGET_DROP]))( + withDragNode(nodeDragSourceSpec(ModelKind.node, true, true))( + withSelection()(CustomNode), + ), + ); + case ModelKind.edge: + return withTargetDrag< + DragObjectWithType, + Node, + { dragging?: boolean }, + { + element: GraphElement; + } + >({ + item: { type: CONNECTOR_TARGET_DROP }, + begin: (monitor, props) => { + props.element.raise(); + return props.element; + }, + drag: (event, monitor, props) => { + (props.element as Edge).setEndPoint(event.x, event.y); + }, + end: (dropResult, monitor, props) => { + if (monitor.didDrop() && dropResult && props) { + (props.element as Edge).setTarget(dropResult); + } + (props.element as Edge).setEndPoint(); + }, + collect: (monitor) => ({ + dragging: monitor.isDragging(), + }), + })(DefaultEdge); + default: + return undefined; + } + } +}; diff --git a/src/views/states/topology/utils/utils.ts b/src/views/states/topology/utils/utils.ts new file mode 100644 index 00000000..37a34e62 --- /dev/null +++ b/src/views/states/topology/utils/utils.ts @@ -0,0 +1,66 @@ +import { NetworkIcon } from '@patternfly/react-icons'; +import { Model, ModelKind, NodeModel, NodeShape, NodeStatus } from '@patternfly/react-topology'; +import { NodeNetworkConfigurationInterface, V1beta1NodeNetworkState } from '@types'; + +import { GROUP, NODE_DIAMETER } from './constants'; + +export const getStatus = (iface: NodeNetworkConfigurationInterface) => { + const status = iface.state.toLowerCase(); + if (status === 'up') return NodeStatus.success; + if (status === 'down') return NodeStatus.danger; + if (status === 'absent') return NodeStatus.warning; + return NodeStatus.default; +}; + +export const transformDataToTopologyModel = (data: V1beta1NodeNetworkState[]): Model => { + const nodes = data + .map((nodeState) => { + const nnsName = nodeState.metadata.name; + + const childNodes: NodeModel[] = nodeState.status.currentState.interfaces.map( + (iface: NodeNetworkConfigurationInterface) => ({ + id: `${nnsName}~${iface.name}`, + type: ModelKind.node, + label: iface.name, + width: NODE_DIAMETER, + height: NODE_DIAMETER, + shape: NodeShape.ellipse, + status: getStatus(iface), + data: { + badge: 'I', // Which kind should be each one? + icon: NetworkIcon, + }, + parent: nnsName, + }), + ); + + const groupNode: NodeModel = { + id: nnsName, + type: GROUP, + label: nnsName, + group: true, + children: childNodes.map((child) => child.id), + style: { + padding: 40, + }, + data: { + badge: 'NNS', + }, + }; + + return [groupNode, ...childNodes]; + }) + .flat(); + + const edges: any[] = []; + + return { + nodes, + edges, + graph: { + id: 'nns-topology', + type: ModelKind.graph, + layout: 'Cola', + }, + }; +}; diff --git a/tsconfig.json b/tsconfig.json index 2d0f1312..62ce955d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,8 @@ "paths": { "@images/*": ["images/*"], "@types": ["src/nmstate-types/index.ts"], - "@utils/*": ["src/utils/*"] + "@utils/*": ["src/utils/*"], + "@models": ["src/console-models/index.ts"] } }, "include": ["src", "pkg", "src/custom.d.ts"], diff --git a/yarn.lock b/yarn.lock index f33686cb..58ad2757 100644 --- a/yarn.lock +++ b/yarn.lock @@ -269,6 +269,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.2.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" + integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.22.15", "@babel/template@^7.24.0", "@babel/template@^7.3.3": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" @@ -797,6 +804,18 @@ react-dropzone "^14.2.3" tslib "^2.5.0" +"@patternfly/react-core@^5.1.1": + version "5.3.4" + resolved "https://registry.yarnpkg.com/@patternfly/react-core/-/react-core-5.3.4.tgz#84f85d3528655134cf0bcdb096f82777f0dd69b6" + integrity sha512-zr2yeilIoFp8MFOo0vNgI8XuM+P2466zHvy4smyRNRH2/but2WObqx7Wu4ftd/eBMYdNqmTeuXe6JeqqRqnPMQ== + dependencies: + "@patternfly/react-icons" "^5.3.2" + "@patternfly/react-styles" "^5.3.1" + "@patternfly/react-tokens" "^5.3.1" + focus-trap "7.5.2" + react-dropzone "^14.2.3" + tslib "^2.5.0" + "@patternfly/react-core@^5.2.3": version "5.2.3" resolved "https://registry.yarnpkg.com/@patternfly/react-core/-/react-core-5.2.3.tgz#21d8168f1cccc2315162b7b1aca14a436cfa0101" @@ -809,16 +828,26 @@ react-dropzone "^14.2.3" tslib "^2.5.0" -"@patternfly/react-icons@^5.1.1", "@patternfly/react-icons@^5.2.1": +"@patternfly/react-icons@5.2.1", "@patternfly/react-icons@^5.1.1", "@patternfly/react-icons@^5.2.1": version "5.2.1" resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-5.2.1.tgz#c29e9fbecd13c33e772abe6089e31bb86b1ab2a8" integrity sha512-aeJ0X+U2NDe8UmI5eQiT0iuR/wmUq97UkDtx3HoZcpRb9T6eUBfysllxjRqHS8rOOspdU8OWq+CUhQ/E2ZDibg== +"@patternfly/react-icons@^5.3.2": + version "5.3.2" + resolved "https://registry.yarnpkg.com/@patternfly/react-icons/-/react-icons-5.3.2.tgz#f594ed67b0d39f486ea0f0367de058d4bd056605" + integrity sha512-GEygYbl0H4zD8nZuTQy2dayKIrV2bMMeWKSOEZ16Y3EYNgYVUOUnN+J0naAEuEGH39Xb1DE9n+XUbE1PC4CxPA== + "@patternfly/react-styles@^5.1.1", "@patternfly/react-styles@^5.2.1": version "5.2.1" resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-5.2.1.tgz#a6f8c750bd65572702ea94c0a6b58f6c0d4361fb" integrity sha512-GT96hzI1QenBhq6Pfc51kxnj9aVLjL1zSLukKZXcYVe0HPOy0BFm90bT1Fo4e/z7V9cDYw4SqSX1XLc3O4jsTw== +"@patternfly/react-styles@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@patternfly/react-styles/-/react-styles-5.3.1.tgz#4bc42f98c48e117df5d956ee3f551d0f57ef1b35" + integrity sha512-H6uBoFH3bJjD6PP75qZ4k+2TtF59vxf9sIVerPpwrGJcRgBZbvbMZCniSC3+S2LQ8DgXLnDvieq78jJzHz0hiA== + "@patternfly/react-table@^5.1.1": version "5.2.4" resolved "https://registry.yarnpkg.com/@patternfly/react-table/-/react-table-5.2.4.tgz#39d7435d40bfe8b2b2d3ee33c94d4137cea0da9c" @@ -836,6 +865,34 @@ resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-5.2.1.tgz#fca7decaa7039dcd93fd215f3f533eff9d070b22" integrity sha512-8GYz/jnJTGAWUJt5eRAW5dtyiHPKETeFJBPGHaUQnvi/t1ZAkoy8i4Kd/RlHsDC7ktiu813SKCmlzwBwldAHKg== +"@patternfly/react-tokens@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@patternfly/react-tokens/-/react-tokens-5.3.1.tgz#b0f840ee3ee3bcf72b5fbf35dc3fd5559666744d" + integrity sha512-VYK0uVP2/2RJ7ZshJCCLeq0Boih5I1bv+9Z/Bg6h12dCkLs85XsxAX9Ve+BGIo5DF54/mzcRHE1RKYap4ISXuw== + +"@patternfly/react-topology@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@patternfly/react-topology/-/react-topology-5.2.0.tgz#09df2807af75af172ef5291513f1f27235c7d41e" + integrity sha512-+kZJSbD6Pb1bTriNzLRiddfSbEBxyiNGSreiV6zOyPwfRizqbFPsOYyRuEocduzLqj0/wT3PM5Ml6JSp8Rw2TQ== + dependencies: + "@patternfly/react-core" "^5.1.1" + "@patternfly/react-icons" "^5.1.1" + "@patternfly/react-styles" "^5.1.1" + "@types/d3" "^7.4.0" + "@types/d3-force" "^1.2.1" + "@types/dagre" "0.7.42" + "@types/react-measure" "^2.0.6" + d3 "^7.8.0" + dagre "0.8.2" + lodash "^4.17.19" + mobx "^6.9.0" + mobx-react "^7.6.0" + point-in-svg-path "^1.0.1" + popper.js "^1.16.1" + react-measure "^2.3.0" + tslib "^2.0.0" + webcola "3.4.0" + "@remix-run/router@1.15.3": version "1.15.3" resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.3.tgz#d2509048d69dbb72d5389a14945339f1430b2d3c" @@ -1009,6 +1066,226 @@ dependencies: "@types/node" "*" +"@types/d3-array@*": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + +"@types/d3-axis@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795" + integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c" + integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d" + integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-contour@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231" + integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1" + integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw== + +"@types/d3-dispatch@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7" + integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ== + +"@types/d3-drag@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02" + integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17" + integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g== + +"@types/d3-ease@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-fetch@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980" + integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.10.tgz#6dc8fc6e1f35704f3b057090beeeb7ac674bff1a" + integrity sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw== + +"@types/d3-force@^1.2.1": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-1.2.7.tgz#b066d91ac3b8f19c35a60b49e89e99f60187460a" + integrity sha512-zySqZfnxn67RVEGWzpD9dQA0AbNIp4Rj0qGvAuUdUNfGLrwuGCbEGAGze5hEdNaHJKQT2gTqr6j+qAzncm11ew== + +"@types/d3-format@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90" + integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g== + +"@types/d3-geo@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b" + integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg== + +"@types/d3-interpolate@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a" + integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ== + +"@types/d3-polygon@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c" + integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA== + +"@types/d3-quadtree@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f" + integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg== + +"@types/d3-random@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb" + integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ== + +"@types/d3-scale-chromatic@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644" + integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw== + +"@types/d3-scale@*": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.10.tgz#98cdcf986d0986de6912b5892e7c015a95ca27fe" + integrity sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg== + +"@types/d3-shape@*": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72" + integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2" + integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg== + +"@types/d3-time@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" + integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + +"@types/d3-timer@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== + +"@types/d3-transition@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.8.tgz#677707f5eed5b24c66a1918cde05963021351a8f" + integrity sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b" + integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.4.0": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2" + integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww== + 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/dagre@0.7.42": + version "0.7.42" + resolved "https://registry.yarnpkg.com/@types/dagre/-/dagre-0.7.42.tgz#2b0cd7678d5fc273df7816a88b8b34016e3a5d85" + integrity sha512-knVdi1Ul8xYgJ0wdhQ+/2YGJFKJFa/5srcPII9zvOs4KhsHfpnFrSTQXATYmjslglxRMif3Lg+wEZ0beag+94A== + "@types/eslint-scope@^3.7.3": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" @@ -1050,6 +1327,11 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/geojson@*": + version "7946.0.14" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" + integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== + "@types/graceful-fs@^4.1.3": version "4.1.9" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" @@ -1211,6 +1493,13 @@ dependencies: "@types/react" "^17" +"@types/react-measure@^2.0.6": + version "2.0.12" + resolved "https://registry.yarnpkg.com/@types/react-measure/-/react-measure-2.0.12.tgz#e8ba05057357b9529aa4115064fe7ea77549f54c" + integrity sha512-Y6V11CH6bU7RhqrIdENPwEUZlPXhfXNGylMNnGwq5TAEs2wDoBA3kSVVM/EQ8u72sz5r9ja+7W8M8PIVcS841Q== + dependencies: + "@types/react" "*" + "@types/react-router-dom@^5.3.2": version "5.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" @@ -2453,6 +2742,11 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@7, commander@^7.0.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.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -2463,11 +2757,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: - 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@~9.4.1: version "9.4.1" resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" @@ -2712,6 +3001,293 @@ cypress@11: untildify "^4.0.0" yauzl "^2.10.0" +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "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-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-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-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, d3-dispatch@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.6.tgz#00d37bcee4dd8cd97729dd893a0ac29caaba5d58" + integrity sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA== + +"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@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== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +d3-drag@^1.0.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.5.tgz#2537f451acd39d31406677b7dc77c82f7d988f70" + integrity sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w== + dependencies: + d3-dispatch "1" + d3-selection "1" + +"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@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-geo@3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d" + integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q== + 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== + dependencies: + d3-color "1 - 3" + +d3-path@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +"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-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@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +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== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +d3-selection@1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.2.tgz#dcaa49522c0dbf32d6c1858afc26b6094555bc5c" + integrity sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg== + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +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-shape@^1.3.5: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +"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== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.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-timer@^1.0.5: + version "1.0.10" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5" + integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== + +"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== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.8.0: + version "7.9.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d" + integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA== + 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" + +dagre@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.2.tgz#755b79f4d5499d63cf74c3368fb08add93eceafe" + integrity sha512-TEOOGZOkCOgCG7AoUIq64sJ3d21SMv8tyoqteLpX+UsUsS9Qw8iap4hhogXY4oB3r0bbZuAjO0atAilgCmsE0Q== + dependencies: + graphlib "^2.1.5" + lodash "^4.17.4" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -2860,6 +3436,13 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delaunator@5: + version "5.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== + dependencies: + robust-predicates "^3.0.2" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -3919,6 +4502,11 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-node-dimensions@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz#fb7b4bb57060fb4247dd51c9d690dfbec56b0823" + integrity sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ== + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -4080,6 +4668,13 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphlib@^2.1.5: + version "2.1.8" + resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + gulp-sort@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/gulp-sort/-/gulp-sort-2.0.0.tgz#c6762a2f1f0de0a3fc595a21599d3fac8dba1aca" @@ -4382,7 +4977,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@0.6.3: +iconv-lite@0.6, 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== @@ -4477,6 +5072,11 @@ internal-slot@^1.0.4, internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" @@ -5580,7 +6180,7 @@ lodash.once@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5757,6 +6357,23 @@ mktemp@~0.4.0: resolved "https://registry.yarnpkg.com/mktemp/-/mktemp-0.4.0.tgz#6d0515611c8a8c84e484aa2000129b98e981ff0b" integrity sha512-IXnMcJ6ZyTuhRmJSjzvHSRhlVPiN9Jwc6e59V0bEJ0ba6OBeX2L0E+mRN1QseeOF4mM+F1Rit6Nh7o+rl2Yn/A== +mobx-react-lite@^3.4.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.3.tgz#3a4c22c30bfaa8b1b2aa48d12b2ba811c0947ab7" + integrity sha512-NkJREyFTSUXR772Qaai51BnE1voWx56LOL80xG7qkZr6vo8vEaLF3sz1JNUVh+rxmUzxYaqOhfuxTfqUh0FXUg== + +mobx-react@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-7.6.0.tgz#ebf0456728a9bd2e5c24fdcf9b36e285a222a7d6" + integrity sha512-+HQUNuh7AoQ9ZnU6c4rvbiVVl+wEkb9WqYsVDzGLng+Dqj1XntHu79PvEWKtSMoMj67vFp/ZPXcElosuJO8ckA== + dependencies: + mobx-react-lite "^3.4.0" + +mobx@^6.9.0: + version "6.13.1" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.13.1.tgz#76c41aa675199f75b84a257e4bec8ff839e33259" + integrity sha512-ekLRxgjWJr8hVxj9ZKuClPwM/iHckx3euIJ3Np7zLVNtqJvfbbq7l370W/98C8EabdQ1pB5Jd3BbDWxJPNnaOg== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6185,6 +6802,16 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +point-in-svg-path@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/point-in-svg-path/-/point-in-svg-path-1.0.2.tgz#e7b25370e96f58a858c34882ffb57d41b7a574bf" + integrity sha512-+Smsf7B9e7eRFHIwpN+4rE8inF2APbFWeywPfUgbeh02xdJSkbTz6Pqdt7A36wVCR+CnLbaNkRnBjgOpF5RMVQ== + +popper.js@^1.16.1: + version "1.16.1" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" + integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== + portfinder@^1.0.28: version "1.0.32" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" @@ -6494,6 +7121,16 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-measure@^2.3.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/react-measure/-/react-measure-2.5.2.tgz#4ffc410e8b9cb836d9455a9ff18fc1f0fca67f89" + integrity sha512-M+rpbTLWJ3FD6FXvYV6YEGvQ5tMayQ3fGrZhRPHrE9bVlBYfDCLuDcgNttYfk8IqfOI03jz6cbpqMRTUclQnaA== + dependencies: + "@babel/runtime" "^7.2.0" + get-node-dimensions "^1.2.1" + prop-types "^15.6.2" + resize-observer-polyfill "^1.5.0" + react-redux@7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736" @@ -6715,6 +7352,11 @@ reselect@4.x: resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== +resize-observer-polyfill@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -6804,6 +7446,11 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +robust-predicates@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + rsvp@^4.8.2: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -6821,6 +7468,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.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" @@ -7664,6 +8316,11 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.0.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + tslib@^2.1.0, tslib@^2.4.0, tslib@^2.5.0: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" @@ -8062,6 +8719,16 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +webcola@3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/webcola/-/webcola-3.4.0.tgz#490d26ae98e5b5109478b94a846a62ff6831a99d" + integrity sha512-4BiLXjXw3SJHo3Xd+rF+7fyClT6n7I+AR6TkBqyQ4kTsePSAMDLRCXY1f3B/kXJeP9tYn4G1TblxTO+jAt0gaw== + dependencies: + d3-dispatch "^1.0.3" + d3-drag "^1.0.4" + d3-shape "^1.3.5" + d3-timer "^1.0.5" + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"