{data.taskType ? renderTaskType() : null}
{data.text}
@@ -321,61 +261,126 @@ export const ReactFlowCustomTaskNode = ({ data }: any) => {
* and any edge handles.
* @param props.data data property of ReactFlowGraphNodeData
*/
-export const ReactFlowCustomSubworkflowNode = ({ data }: any) => {
- const { dag } = data;
- const backgroundStyle = getRFBackground().nested;
+export const ReactFlowSubWorkflowContainer = ({ data }: any) => {
+ const BREAD_FONT_SIZE = '9px';
+ const BREAD_COLOR_ACTIVE = '#8B37FF';
+ const BREAD_COLOR_INACTIVE = '#000';
const borderStyle = getNestedContainerStyle(data.nodeExecutionStatus);
- const { estimatedDimensions } = setReactFlowGraphLayout(dag, 'LR', true);
- const graphContainer = getNestedGraphContainerStyle(estimatedDimensions);
- return (
- <>
- {renderDefaultHandles(
- data.scopedId,
- getGraphHandleStyle('source'),
- getGraphHandleStyle('target')
- )}
-
- >
- );
-};
-/**
- * Custom component renders Branch nodes as indepdenet flow
- * and any edge handles.
- * @param props.data data property of ReactFlowGraphNodeData
- */
-export const ReactFlowCustomBranchNode = ({ data }: any) => {
- const { dag } = data;
- console.log('@ReactFlowCustomBranchNode: data', data);
- const backgroundStyle = getRFBackground().nested;
- const borderStyle = getNestedContainerStyle(data.nodeExecutionStatus);
- const { estimatedDimensions } = setReactFlowGraphLayout(dag, 'LR', true);
- const graphContainer = getNestedGraphContainerStyle(estimatedDimensions);
+ const handleNestedViewClick = e => {
+ const index = e.target.id.substr(
+ e.target.id.indexOf('_') + 1,
+ e.target.id.length
+ );
+ data.onRemoveNestedView(data.scopedId, index);
+ };
+
+ const handleRootClick = () => {
+ data.onRemoveNestedView(data.scopedId, -1);
+ };
+
+ const currentNestedDepth = data.currentNestedView?.length || 0;
+
+ const BreadElement = ({ nestedView, index }) => {
+ const liStyles: React.CSSProperties = {
+ cursor: 'pointer',
+ fontSize: BREAD_FONT_SIZE,
+ color: BREAD_COLOR_ACTIVE
+ };
+
+ const liStyleInactive: React.CSSProperties = { ...liStyles };
+ liStyleInactive['color'] = BREAD_COLOR_INACTIVE;
+
+ const beforeStyle: React.CSSProperties = {
+ cursor: 'pointer',
+ color: BREAD_COLOR_ACTIVE,
+ padding: '0 .2rem',
+ fontSize: BREAD_FONT_SIZE
+ };
+ const onClick =
+ currentNestedDepth > index + 1 ? handleNestedViewClick : undefined;
+ return (
+
+ {index == 0 ? {'>'} : null}
+ {nestedView}
+ {index < currentNestedDepth - 1 ? (
+ {'>'}
+ ) : null}
+
+ );
+ };
+
+ const BorderElement = props => {
+ return
{props.children}
;
+ };
+
+ const BorderContainer = props => {
+ let output = BorderElement(props);
+ for (let i = 0; i < currentNestedDepth; i++) {
+ output =
{output};
+ }
+ return output;
+ };
+
+ const renderBreadCrumb = () => {
+ const breadContainerStyle: React.CSSProperties = {
+ position: 'absolute',
+ display: 'flex',
+ width: '100%',
+ marginTop: '-1rem'
+ };
+ const olStyles: React.CSSProperties = {
+ margin: 0,
+ padding: 0,
+ display: 'flex',
+ listStyle: 'none',
+ listStyleImage: 'none',
+ minWidth: '1rem'
+ };
+ const headerStyle: React.CSSProperties = {
+ color: BREAD_COLOR_ACTIVE,
+ fontSize: BREAD_FONT_SIZE,
+ margin: 0,
+ padding: 0
+ };
+
+ const rootClick = currentNestedDepth > 0 ? handleRootClick : undefined;
+ return (
+
+
+
+ {data.currentNestedView?.map((nestedView, i) => {
+ return (
+
+ );
+ })}
+
+
+ );
+ };
return (
<>
- {renderDefaultHandles(
- data.scopedId,
- getGraphHandleStyle('source'),
- getGraphHandleStyle('target')
- )}
-
+ {renderBreadCrumb()}
+
+ {renderDefaultHandles(
+ data.scopedId,
+ getGraphHandleStyle('source'),
+ getGraphHandleStyle('target')
+ )}
+
>
);
};
diff --git a/src/components/flytegraph/ReactFlow/transformDAGToReactFlowV2.tsx b/src/components/flytegraph/ReactFlow/transformDAGToReactFlowV2.tsx
new file mode 100644
index 0000000000..ecb54a6e07
--- /dev/null
+++ b/src/components/flytegraph/ReactFlow/transformDAGToReactFlowV2.tsx
@@ -0,0 +1,397 @@
+import { dEdge, dNode, dTypes } from 'models/Graph/types';
+import { ReactFlowGraphConfig } from './utils';
+import { Edge, Node, Position } from 'react-flow-renderer';
+import { NodeExecutionPhase } from 'models/Execution/enums';
+import { ConvertDagProps } from './types';
+import { createDebugLogger } from '../utils';
+
+interface rfNode extends Node {
+ isRootParentNode?: boolean;
+}
+
+interface rfEdge extends Edge {
+ parent?: string;
+}
+
+interface ReactFlowGraph {
+ nodes: any;
+ edges: any;
+}
+
+const debug = createDebugLogger('@TransformerDAGToReactFlow');
+
+export interface ReactFlowGraphMapping {
+ root: ReactFlowGraph;
+ rootParentMap: {
+ [key: string]: {
+ [key: string]: ReactFlowGraph;
+ };
+ };
+}
+
+export const buildCustomNodeName = (type: dTypes) => {
+ return `${ReactFlowGraphConfig.customNodePrefix}_${dTypes[type]}`;
+};
+
+export const nodeHasChildren = (node: dNode) => {
+ return node.nodes.length > 0;
+};
+
+export const isStartOrEndEdge = edge => {
+ return edge.sourceId == 'start-node' || edge.targetId == 'end-node';
+};
+
+interface BuildDataProps {
+ node: dNode;
+ nodeExecutionsById: any;
+ onNodeSelectionChanged: any;
+ onAddNestedView: any;
+ onRemoveNestedView: any;
+ rootParentNode: dNode;
+ currentNestedView: string[];
+}
+export const buildReactFlowDataProps = (props: BuildDataProps) => {
+ const {
+ node,
+ nodeExecutionsById,
+ onNodeSelectionChanged,
+ onAddNestedView,
+ onRemoveNestedView,
+ rootParentNode,
+ currentNestedView
+ } = props;
+
+ const taskType = node.value?.template ? node.value.template.type : null;
+ const displayName = node.name;
+ const mapNodeExecutionStatus = () => {
+ if (nodeExecutionsById) {
+ if (nodeExecutionsById[node.scopedId]) {
+ return nodeExecutionsById[node.scopedId].closure
+ .phase as NodeExecutionPhase;
+ } else {
+ return NodeExecutionPhase.SKIPPED;
+ }
+ } else {
+ return NodeExecutionPhase.UNDEFINED;
+ }
+ };
+ const nodeExecutionStatus = mapNodeExecutionStatus();
+
+ const dataProps = {
+ nodeExecutionStatus: nodeExecutionStatus,
+ text: displayName,
+ handles: [],
+ nodeType: node.type,
+ scopedId: node.scopedId,
+ taskType: taskType,
+ onNodeSelectionChanged: () => {
+ if (onNodeSelectionChanged) {
+ onNodeSelectionChanged([node.scopedId]);
+ }
+ },
+ onAddNestedView: () => {
+ onAddNestedView({
+ parent: rootParentNode.scopedId,
+ view: node.scopedId
+ });
+ },
+ onRemoveNestedView
+ };
+
+ for (const rootParentId in currentNestedView) {
+ if (node.scopedId == rootParentId) {
+ dataProps['currentNestedView'] = currentNestedView[rootParentId];
+ }
+ }
+
+ return dataProps;
+};
+
+interface BuildNodeProps {
+ node: dNode;
+ dataProps: any;
+ rootParentNode?: dNode;
+ parentNode?: dNode;
+ typeOverride?: dTypes;
+}
+export const buildReactFlowNode = ({
+ node,
+ dataProps,
+ rootParentNode,
+ parentNode,
+ typeOverride
+}: BuildNodeProps): rfNode => {
+ const output: rfNode = {
+ id: node.scopedId,
+ type: buildCustomNodeName(typeOverride || node.type),
+ data: { text: node.scopedId },
+ position: { x: 0, y: 0 },
+ style: {},
+ sourcePosition: Position.Right,
+ targetPosition: Position.Left
+ };
+ if (rootParentNode) {
+ output['parentNode'] = rootParentNode.scopedId;
+ } else if (parentNode) {
+ output['parentNode'] = parentNode.scopedId;
+ }
+
+ if (output.parentNode == node.scopedId) {
+ delete output.parentNode;
+ }
+
+ output['data'] = buildReactFlowDataProps({
+ ...dataProps,
+ node,
+ rootParentNode
+ });
+ return output;
+};
+interface BuildEdgeProps {
+ edge: dEdge;
+ rootParentNode?: dNode;
+ parentNode?: dNode;
+}
+export const buildReactFlowEdge = ({
+ edge,
+ rootParentNode
+}: BuildEdgeProps): rfEdge => {
+ const output = {
+ id: `${edge.sourceId}->${edge.targetId}`,
+ source: edge.sourceId,
+ target: edge.targetId,
+ arrowHeadType: ReactFlowGraphConfig.arrowHeadType,
+ type: ReactFlowGraphConfig.edgeType
+ } as rfEdge;
+
+ if (rootParentNode) {
+ output['parent'] = rootParentNode.scopedId;
+ output['zIndex'] = 1;
+ }
+
+ return output;
+};
+
+export const edgesToArray = edges => {
+ return Object.values(edges);
+};
+
+export const nodesToArray = nodes => {
+ return Object.values(nodes);
+};
+
+export const buildGraphMapping = (props): ReactFlowGraphMapping => {
+ const dag: dNode = props.root;
+ const {
+ nodeExecutionsById,
+ onNodeSelectionChanged,
+ onAddNestedView,
+ onRemoveNestedView,
+ currentNestedView,
+ isStaticGraph
+ } = props;
+ const nodeDataProps = {
+ nodeExecutionsById,
+ onNodeSelectionChanged,
+ onAddNestedView,
+ onRemoveNestedView,
+ currentNestedView
+ };
+ const root: ReactFlowGraph = {
+ nodes: {},
+ edges: {}
+ };
+ const rootParentMap = {};
+
+ interface ParseProps {
+ nodeDataProps: any;
+ contextNode: dNode;
+ contextParent?: dNode;
+ rootParentNode?: dNode;
+ }
+ const parse = (props: ParseProps) => {
+ const {
+ contextNode,
+ contextParent,
+ rootParentNode,
+ nodeDataProps
+ } = props;
+ let context: ReactFlowGraph | null = null;
+ contextNode.nodes.map((node: dNode) => {
+ /* Case: node has children => recurse */
+ if (nodeHasChildren(node)) {
+ if (rootParentNode) {
+ parse({
+ contextNode: node,
+ contextParent: node,
+ rootParentNode: rootParentNode,
+ nodeDataProps: nodeDataProps
+ });
+ } else {
+ parse({
+ contextNode: node,
+ contextParent: node,
+ rootParentNode: node,
+ nodeDataProps: nodeDataProps
+ });
+ }
+ }
+
+ if (rootParentNode) {
+ const rootParentId = rootParentNode.scopedId;
+ const contextParentId = contextParent?.scopedId;
+ rootParentMap[rootParentId] = rootParentMap[rootParentId] || {};
+ rootParentMap[rootParentId][contextParentId] = rootParentMap[
+ rootParentId
+ ][contextParentId] || {
+ nodes: {},
+ edges: {}
+ };
+ context = rootParentMap[rootParentId][
+ contextParentId
+ ] as ReactFlowGraph;
+ const reactFlowNode = buildReactFlowNode({
+ node: node,
+ dataProps: nodeDataProps,
+ rootParentNode: rootParentNode,
+ parentNode: contextParent,
+ typeOverride:
+ isStaticGraph == true ? dTypes.staticNode : undefined
+ });
+ context.nodes[reactFlowNode.id] = reactFlowNode;
+ } else {
+ const reactFlowNode = buildReactFlowNode({
+ node: node,
+ dataProps: nodeDataProps,
+ typeOverride:
+ isStaticGraph == true ? dTypes.staticNode : undefined
+ });
+ root.nodes[reactFlowNode.id] = reactFlowNode;
+ }
+ });
+ contextNode.edges.map((edge: dEdge) => {
+ const reactFlowEdge = buildReactFlowEdge({ edge, rootParentNode });
+ if (rootParentNode && context) {
+ context.edges[reactFlowEdge.id] = reactFlowEdge;
+ } else {
+ root.edges[reactFlowEdge.id] = reactFlowEdge;
+ }
+ });
+ };
+
+ parse({ contextNode: dag, nodeDataProps: nodeDataProps });
+
+ return {
+ root,
+ rootParentMap
+ };
+};
+
+export interface RenderGraphProps {
+ graphMapping: any;
+ currentNestedView?: any[];
+ maxRenderDepth?: number;
+ isStaticGraph?: boolean;
+}
+export const renderGraph = ({
+ graphMapping,
+ currentNestedView,
+ maxRenderDepth = 0,
+ isStaticGraph = false
+}) => {
+ debug('\t graphMapping:', graphMapping);
+ debug('\t currentNestedView:', currentNestedView);
+ if (maxRenderDepth > 0 && !isStaticGraph) {
+ const nestedChildGraphs: ReactFlowGraph = {
+ nodes: {},
+ edges: {}
+ };
+ const nestedContent: string[] = [];
+
+ /**
+ * Compute which nested content will be populated into a subworkflow container.
+ *
+ * Function returns array of id's. These id's are then matched to rootParentMap
+ * values for determining which nodes to show
+ *
+ * Note: currentNestedView is a mapping where
+ * k: rootParentId
+ * v: array of nested depth with last value as current view
+ */
+ for (const nestedParentId in graphMapping.rootParentMap) {
+ const rootParent = currentNestedView[nestedParentId];
+ if (rootParent) {
+ const currentView = rootParent[rootParent.length - 1];
+ nestedContent.push(currentView);
+ } else {
+ nestedContent.push(nestedParentId);
+ }
+ }
+
+ for (const rootParentId in graphMapping.rootParentMap) {
+ const parentMapContext = graphMapping.rootParentMap[rootParentId];
+ for (let i = 0; i < nestedContent.length; i++) {
+ const nestedChildGraphId = nestedContent[i];
+ if (parentMapContext[nestedChildGraphId]) {
+ nestedChildGraphs.nodes = {
+ ...nestedChildGraphs.nodes,
+ ...parentMapContext[nestedChildGraphId].nodes
+ };
+ nestedChildGraphs.edges = {
+ ...nestedChildGraphs.edges,
+ ...parentMapContext[nestedChildGraphId].edges
+ };
+ }
+ }
+ for (const parentKey in graphMapping.root.nodes) {
+ const parentNode = graphMapping.root.nodes[parentKey];
+ if (parentNode.id == rootParentId) {
+ parentNode['isRootParentNode'] = true;
+ parentNode['style'] = {};
+ }
+ }
+ /**
+ * @TODO refactor this; we need this step but can prob be done better
+ * The issue is that somehow/somewhere root-level nodes are being added
+ * to these nestedGraphs and if the appear in the output they break
+ * reactFlow because a node can have a self-referencing "parentNode"
+ *
+ * eg. { id: "n0", parentNode: "n0"} will break
+ *
+ */
+ for (const nodeId in nestedChildGraphs.nodes) {
+ const node = nestedChildGraphs.nodes[nodeId];
+ for (const rootId in graphMapping.rootParentMap) {
+ if (node.id == rootId) {
+ delete nestedChildGraphs.nodes[nodeId];
+ } else {
+ if (node.type == 'FlyteNode_subworkflow') {
+ node.type = 'FlyteNode_nestedMaxDepth';
+ }
+ }
+ }
+ }
+ }
+ const output = { ...graphMapping.root };
+ output.nodes = { ...output.nodes, ...nestedChildGraphs.nodes };
+ output.edges = { ...output.edges, ...nestedChildGraphs.edges };
+ output.nodes = nodesToArray(output.nodes);
+ output.edges = edgesToArray(output.edges);
+ return output;
+ } else {
+ const output = { ...graphMapping.root };
+ output.nodes = nodesToArray(output.nodes);
+ output.edges = edgesToArray(output.edges);
+ return output;
+ }
+};
+
+export const ConvertFlyteDagToReactFlows = (props: ConvertDagProps) => {
+ const graphMapping: ReactFlowGraphMapping = buildGraphMapping(props);
+ return renderGraph({
+ graphMapping: graphMapping,
+ currentNestedView: props.currentNestedView,
+ maxRenderDepth: props.maxRenderDepth,
+ isStaticGraph: props.isStaticGraph
+ });
+};
diff --git a/src/components/flytegraph/ReactFlow/transformerDAGToReactFlow.tsx b/src/components/flytegraph/ReactFlow/transformerDAGToReactFlow.tsx
deleted file mode 100644
index a693853b0f..0000000000
--- a/src/components/flytegraph/ReactFlow/transformerDAGToReactFlow.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { dEdge, dTypes } from 'models/Graph/types';
-import { ReactFlowGraphConfig } from './utils';
-import { Edge, Elements, Node, Position } from 'react-flow-renderer';
-import { NodeExecutionPhase } from 'models/Execution/enums';
-import { BuildRFNodeProps, ConvertDagProps, DagToFRProps } from './types';
-
-export const buildCustomNodeName = (type: dTypes) => {
- return `${ReactFlowGraphConfig.customNodePrefix}_${dTypes[type]}`;
-};
-
-export const buildReactFlowEdge = (edge: dEdge): Edge => {
- return {
- id: `[${edge.sourceId}]->[${edge.targetId}]`,
- source: edge.sourceId,
- target: edge.targetId,
- sourceHandle: 'left-handle',
- arrowHeadType: ReactFlowGraphConfig.arrowHeadType,
- type: ReactFlowGraphConfig.edgeType
- } as Edge;
-};
-
-export const buildReactFlowNode = (props: BuildRFNodeProps): Node => {
- const {
- dNode,
- dag,
- nodeExecutionsById,
- typeOverride,
- onNodeSelectionChanged
- } = props;
-
- const type = typeOverride ? typeOverride : dNode.type;
- const taskType = dNode?.value?.template ? dNode.value.template.type : null;
- const displayName = dNode.name;
-
- const mapNodeExecutionStatus = () => {
- if (nodeExecutionsById) {
- if (nodeExecutionsById[dNode.scopedId]) {
- return nodeExecutionsById[dNode.scopedId].closure
- .phase as NodeExecutionPhase;
- } else {
- return NodeExecutionPhase.SKIPPED;
- }
- } else {
- return NodeExecutionPhase.UNDEFINED;
- }
- };
- const nodeExecutionStatus = mapNodeExecutionStatus();
-
- const dataProps = {
- nodeExecutionStatus: nodeExecutionStatus,
- text: displayName,
- handles: [],
- nodeType: type,
- scopedId: dNode.scopedId,
- dag: dag,
- taskType: taskType,
- onNodeSelectionChanged: () => {
- if (onNodeSelectionChanged) {
- onNodeSelectionChanged([dNode.scopedId]);
- }
- }
- };
-
- return {
- id: dNode.scopedId,
- type: buildCustomNodeName(type),
- data: dataProps,
- position: { x: 0, y: 0 },
- sourcePosition: Position.Right,
- targetPosition: Position.Left
- } as Node;
-};
-
-export const nodeMapToArr = map => {
- const output: any[] = [];
- for (const k in map) {
- output.push(map[k]);
- }
- return output;
-};
-
-export const dagToReactFlow = (props: DagToFRProps) => {
- const {
- root,
- nodeExecutionsById,
- currentDepth,
- onNodeSelectionChanged,
- maxRenderDepth,
- isStaticGraph
- } = props;
-
- const nodes: any = {};
- const edges: any = {};
-
- root.nodes?.map(dNode => {
- /* Base props to build RF Node */
- const buildNodeProps = {
- dNode: dNode,
- dag: [],
- nodeExecutionsById: nodeExecutionsById,
- typeOverride: null,
- onNodeSelectionChanged: onNodeSelectionChanged,
- isStaticGraph: isStaticGraph
- } as BuildRFNodeProps;
- if (dNode.nodes?.length > 0 && currentDepth <= maxRenderDepth) {
- /* Note: currentDepth will be replaced once nested toggle */
- if (currentDepth == maxRenderDepth) {
- buildNodeProps.typeOverride = isStaticGraph
- ? dTypes.staticNestedNode
- : dTypes.nestedMaxDepth;
- } else {
- const nestedDagProps: DagToFRProps = {
- root: dNode,
- nodeExecutionsById: nodeExecutionsById,
- currentDepth: currentDepth + 1,
- onNodeSelectionChanged: onNodeSelectionChanged,
- maxRenderDepth: maxRenderDepth,
- isStaticGraph: isStaticGraph
- };
- buildNodeProps.dag = dagToReactFlow(nestedDagProps);
- buildNodeProps.typeOverride = isStaticGraph
- ? dTypes.staticNode
- : null;
- }
- } else {
- buildNodeProps.typeOverride = isStaticGraph
- ? dTypes.staticNode
- : null;
- }
- /* Build and add node to map */
- nodes[dNode.id] = buildReactFlowNode(buildNodeProps);
- });
- root.edges?.map(edge => {
- const rfEdge = buildReactFlowEdge(edge);
- edges[rfEdge.id] = rfEdge;
- });
- const output = nodeMapToArr(nodes).concat(nodeMapToArr(edges));
- return output;
-};
-
-export const ConvertFlyteDagToReactFlows = (
- props: ConvertDagProps
-): Elements => {
- const dagProps = { ...props, currentDepth: 0 } as DagToFRProps;
- const rfJson = dagToReactFlow(dagProps);
- return rfJson;
-};
diff --git a/src/components/flytegraph/ReactFlow/types.ts b/src/components/flytegraph/ReactFlow/types.ts
index 49412edcf8..7d99e7a9fd 100644
--- a/src/components/flytegraph/ReactFlow/types.ts
+++ b/src/components/flytegraph/ReactFlow/types.ts
@@ -1,12 +1,14 @@
import { NodeExecutionsById } from 'models/Execution/types';
import { dNode, dTypes } from 'models/Graph/types';
-import { Elements, HandleProps } from 'react-flow-renderer';
+import { HandleProps } from 'react-flow-renderer';
export interface RFWrapperProps {
- rfGraphJson: Elements;
+ rfGraphJson: any;
backgroundStyle: RFBackgroundProps;
- type: RFGraphTypes;
+ type?: RFGraphTypes;
+ currentNestedView?: any;
onNodeSelectionChanged?: any;
+ nodeExecutionsById?: any;
version?: string;
}
@@ -22,9 +24,9 @@ export enum RFGraphTypes {
}
export interface LayoutRCProps {
- setElements: any;
- setLayout: any;
- hasLayout: boolean;
+ setPositionedElements: any;
+ graphData: any;
+ nodeExecutionsById: any;
}
/* React Flow params and styles (background is styles) */
@@ -40,6 +42,9 @@ export interface BuildRFNodeProps {
nodeExecutionsById: any;
typeOverride: dTypes | null;
onNodeSelectionChanged: any;
+ onAddNestedView?: any;
+ onRemoveNestedView?: any;
+ currentNestedView?: any;
isStaticGraph: boolean;
}
@@ -47,12 +52,16 @@ export interface ConvertDagProps {
root: dNode;
nodeExecutionsById: any;
onNodeSelectionChanged: any;
+ onRemoveNestedView?: any;
+ onAddNestedView?: any;
+ currentNestedView?: any;
maxRenderDepth: number;
- isStaticGraph: boolean;
+ isStaticGraph?: boolean;
}
-export interface DagToFRProps extends ConvertDagProps {
+export interface DagToReactFlowProps extends ConvertDagProps {
currentDepth: number;
+ parents: any;
}
export interface RFCustomData {
@@ -64,4 +73,6 @@ export interface RFCustomData {
dag: any;
taskType?: dTypes;
onNodeSelectionChanged?: any;
+ onAddNestedView: any;
+ onRemoveNestedView: any;
}
diff --git a/src/components/flytegraph/ReactFlow/utils.tsx b/src/components/flytegraph/ReactFlow/utils.tsx
index 01d017c9fb..e9b34e25a7 100644
--- a/src/components/flytegraph/ReactFlow/utils.tsx
+++ b/src/components/flytegraph/ReactFlow/utils.tsx
@@ -1,7 +1,6 @@
import { NodeExecutionPhase } from 'models/Execution/enums';
import { dTypes } from 'models/Graph/types';
import { CSSProperties } from 'react';
-import { Elements, isNode, Position } from 'react-flow-renderer';
import { RFBackgroundProps } from './types';
const dagre = require('dagre');
@@ -10,6 +9,7 @@ export const COLOR_EXECUTED = '#2892f4';
export const COLOR_NOT_EXECUTED = '#c6c6c6';
export const COLOR_TASK_TYPE = '#666666';
export const COLOR_GRAPH_BACKGROUND = '#666666';
+export const GRAPH_PADDING_FACTOR = 50;
export const DISPLAY_NAME_START = 'start';
export const DISPLAY_NAME_END = 'end';
@@ -22,6 +22,17 @@ export const ReactFlowGraphConfig = {
edgeType: 'default'
};
+/**
+ * Function replaces all retry values with '0' to be used a key between static/runtime
+ * values.
+ * @param id NodeExcution nodeId.
+ * @returns nodeId with all retry values replaces with '0'
+ */
+export const retriesToZero = (id: string): string => {
+ const output = id.replace(/(-[0-9]-)/g, '-0-');
+ return output;
+};
+
export const getGraphHandleStyle = (
handleType: string,
type?: dTypes
@@ -133,7 +144,10 @@ export const getNestedContainerStyle = nodeExecutionStatus => {
const style = {
border: `1px dashed ${getStatusColor(nodeExecutionStatus)}`,
borderRadius: '8px',
- background: 'rgba(255,255,255,.9)'
+ background: 'rgba(255,255,255,.9)',
+ width: '100%',
+ height: '100%',
+ padding: '.25rem'
} as React.CSSProperties;
return style;
};
@@ -154,7 +168,9 @@ export const getGraphNodeStyle = (
minWidth: '.5rem',
minHeight: '.5rem',
height: 'auto',
- width: 'auto'
+ width: 'auto',
+ zIndex: 100000,
+ position: 'relative'
};
const nestedPoint = {
@@ -237,43 +253,87 @@ export const getRFBackground = () => {
border: '1px solid #444',
backgroundColor: 'rgba(255,255,255,1)'
},
- gridColor: '#ccc',
- gridSpacing: 20
+ gridColor: 'none'
} as RFBackgroundProps,
nested: {
- gridColor: 'none',
- gridSpacing: 1
+ gridColor: 'none'
} as RFBackgroundProps,
static: {
background: {
border: 'none',
backgroundColor: 'rgb(255,255,255)'
},
- gridColor: 'none',
- gridSpacing: 20
+ gridColor: 'none'
} as RFBackgroundProps
};
};
+export interface PositionProps {
+ nodes: any;
+ edges: any;
+ parentMap?: any;
+ direction?: string;
+}
+
/**
- * Uses dagree/graphlib to compute graph layout
- * @see https://github.com/dagrejs/dagre/wiki
- * @param elements Graph elements (nodes/edges) in JSON format
- * @param direction Direction to render graph
+ * Computes positions for provided nodes
+ * @param PositionProps
* @returns
*/
-export const setReactFlowGraphLayout = (
- elements: Elements,
- direction: string,
- estimate = false
-) => {
+export const computeChildNodePositions = ({
+ nodes,
+ edges,
+ direction = 'LR'
+}: PositionProps) => {
const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));
- const isHorizontal = direction === 'LR';
-
- const ESTIMATE_HEIGHT = 25;
- const ESTIMATE_WIDTH_FACTOR = 6;
+ dagreGraph.setGraph({
+ rankdir: direction,
+ edgesep: 60,
+ nodesep: 30,
+ ranker: 'longest-path',
+ acyclicer: 'greedy'
+ });
+ nodes.map(n => {
+ dagreGraph.setNode(n.id, n.dimensions);
+ });
+ edges.map(e => {
+ dagreGraph.setEdge(e.source, e.target);
+ });
+ dagre.layout(dagreGraph);
+ const dimensions = {
+ width: dagreGraph.graph().width,
+ height: dagreGraph.graph().height
+ };
+ const graph = nodes.map(el => {
+ const node = dagreGraph.node(el.id);
+ const x = node.x - node.width / 2;
+ const y = node.y - node.height / 2;
+ return {
+ ...el,
+ position: {
+ x: x,
+ y: y
+ }
+ };
+ });
+ return { graph, dimensions };
+};
+/**
+ * Computes positions for root-level nodes in a graph by filtering out
+ * all children (nodes that have parents).
+ * @param PositionProps
+ * @returns
+ */
+export const computeRootNodePositions = ({
+ nodes,
+ edges,
+ parentMap,
+ direction = 'LR'
+}: PositionProps) => {
+ const dagreGraph = new dagre.graphlib.Graph();
+ dagreGraph.setDefaultEdgeLabel(() => ({}));
dagreGraph.setGraph({
rankdir: direction,
edgesep: 60,
@@ -282,69 +342,189 @@ export const setReactFlowGraphLayout = (
acyclicer: 'greedy'
});
- /**
- * Note: this waits/assumes rendered dimensions from ReactFlow as .__rf
- */
- elements.forEach(el => {
- if (isNode(el)) {
- const nodeWidth = estimate
- ? el.data.text.length * ESTIMATE_WIDTH_FACTOR
- : el.__rf.width;
- const nodeHeight = estimate ? ESTIMATE_HEIGHT : el.__rf.height;
- dagreGraph.setNode(el.id, { width: nodeWidth, height: nodeHeight });
- } else {
- dagreGraph.setEdge(el.source, el.target);
+ /* Filter all children from creating dagree nodes */
+ nodes.map(n => {
+ if (n.isRootParentNode) {
+ dagreGraph.setNode(n.id, {
+ width: parentMap[n.id].childGraphDimensions.width,
+ height: parentMap[n.id].childGraphDimensions.height
+ });
+ } else if (!n.parentNode) {
+ dagreGraph.setNode(n.id, n.dimensions);
}
});
+ /* Filter all children from creating dagree edges */
+ edges.map(e => {
+ if (!e.parent) {
+ dagreGraph.setEdge(e.source, e.target);
+ }
+ });
+
+ /* Compute graph posistions for root-level nodes */
dagre.layout(dagreGraph);
- const graphWidth = dagreGraph.graph().width;
- const graphHeight = dagreGraph.graph().height;
- if (estimate) {
- return {
- estimatedDimensions: {
- width: graphWidth,
- height: graphHeight
+ const dimensions = {
+ width: dagreGraph.graph().width,
+ height: dagreGraph.graph().height
+ };
+
+ /* Merge dagre positions to rf elements*/
+ const graph = nodes.map(el => {
+ const node = dagreGraph.node(el.id);
+ if (node) {
+ const x = node.x - node.width / 2;
+ const y = node.y - node.height / 2;
+ if (parentMap && el.isRootParentNode) {
+ el.style = parentMap[el.id].childGraphDimensions;
}
- };
- } else {
- return {
- graph: elements.map(el => {
- if (isNode(el)) {
- el.targetPosition = isHorizontal
- ? Position.Left
- : Position.Top;
- el.sourcePosition = isHorizontal
- ? Position.Right
- : Position.Bottom;
- const nodeWidth = estimate
- ? el.data.text.length * ESTIMATE_WIDTH_FACTOR
- : el.__rf.width;
- const nodeHeight = estimate
- ? ESTIMATE_HEIGHT
- : el.__rf.height;
- const nodeWithPosition = dagreGraph.node(el.id);
-
- /** Keep both position and .__rf.position in sync */
- const x = nodeWithPosition.x - nodeWidth / 2;
- const y = nodeWithPosition.y - nodeHeight / 2;
- el.position = {
- x: x,
- y: y
- };
- el.__rf.position = {
- x: x,
- y: y
+ return {
+ ...el,
+ position: {
+ x: x,
+ y: y
+ }
+ };
+ } else if (parentMap) {
+ /* Case: Overwrite children positions with computed values */
+ const parent = parentMap[el.parentNode];
+ for (let i = 0; i < parent.nodes.length; i++) {
+ const node = parent.nodes[i];
+ if (node.id == el.id) {
+ return {
+ ...el,
+ position: { ...node.position }
};
}
- return el;
- }),
- dimensions: {
- width: graphWidth,
- height: graphHeight
}
+ }
+ });
+ return { graph, dimensions };
+};
+
+/**
+ * Returns positioned nodes and edges.
+ *
+ * Note: Handles nesting by first "rendering" all child graphs to calculate their rendered
+ * dimensions and setting those values as the dimentions (width/height) for parent/container.
+ * Once those dimensions have been set (for parent/container nodes) we can set root-level node
+ * positions.
+ *
+ * @param nodes
+ * @param edges
+ * @param currentNestedView
+ * @param direction
+ * @returns Array of ReactFlow nodes
+ */
+export const getPositionedNodes = (
+ nodes,
+ edges,
+ currentNestedView,
+ direction = 'LR'
+) => {
+ const parentMap = {};
+ /* (1) Collect all child graphs in parentMap */
+ nodes.forEach(node => {
+ if (node.isRootParentNode) {
+ parentMap[node.id] = {
+ nodes: [],
+ edges: [],
+ childGraphDimensions: {
+ width: 0,
+ height: 0
+ },
+ self: node
+ };
+ }
+ if (node.parentNode) {
+ if (parentMap[node.parentNode]) {
+ if (parentMap[node.parentNode].nodes) {
+ parentMap[node.parentNode].nodes.push(node);
+ } else {
+ parentMap[node.parentNode].nodes = [node];
+ }
+ }
+ }
+ });
+ edges.forEach(edge => {
+ if (edge.parent) {
+ if (parentMap[edge.parent]) {
+ if (parentMap[edge.parent].edges) {
+ parentMap[edge.parent].edges.push(edge);
+ } else {
+ parentMap[edge.parent].edges = [edge];
+ }
+ }
+ }
+ });
+
+ /* (2) Compute child graph positiions/dimensions */
+ for (const parentId in parentMap) {
+ const children = parentMap[parentId];
+ const childGraph = computeChildNodePositions({
+ nodes: children.nodes,
+ edges: children.edges,
+ direction: direction
+ });
+ let nestedDepth = 1;
+ if (
+ currentNestedView &&
+ currentNestedView[parentId] &&
+ currentNestedView[parentId].length > 0
+ ) {
+ nestedDepth = currentNestedView[parentId].length;
+ }
+ const borderPadding = GRAPH_PADDING_FACTOR * nestedDepth;
+ const width = childGraph.dimensions.width + borderPadding;
+ const height = childGraph.dimensions.height + borderPadding;
+
+ parentMap[parentId].childGraphDimensions = {
+ width: width,
+ height: height
};
+ const relativePosNodes = childGraph.graph.map(node => {
+ const position = node.position;
+ position.y = position.y + GRAPH_PADDING_FACTOR / 2;
+ position.x = position.x + GRAPH_PADDING_FACTOR / 2;
+ return {
+ ...node,
+ position
+ };
+ });
+ parentMap[parentId].nodes = relativePosNodes;
+ parentMap[parentId].self.dimensions.width = width;
+ parentMap[parentId].self.dimensions.height = height;
}
+ /* (3) Compute positions of root-level nodes */
+ const { graph, dimensions } = computeRootNodePositions({
+ nodes: nodes,
+ edges: edges,
+ direction: direction,
+ parentMap: parentMap
+ });
+ return graph;
};
-export default setReactFlowGraphLayout;
+export const ReactFlowIdHash = (nodes, edges) => {
+ const key = Math.floor(Math.random() * 10000).toString();
+ const properties = ['id', 'source', 'target', 'parent', 'parentNode'];
+ const hashGraph = nodes.map(node => {
+ const updates = {};
+ properties.forEach(prop => {
+ if (node[prop]) {
+ updates[prop] = `${key}-${node[prop]}`;
+ }
+ });
+ return { ...node, ...updates };
+ });
+
+ const hashEdges = edges.map(edge => {
+ const updates = {};
+ properties.forEach(prop => {
+ if (edge[prop]) {
+ updates[prop] = `${key}-${edge[prop]}`;
+ }
+ });
+ return { ...edge, ...updates };
+ });
+ return { hashGraph, hashEdges };
+};
diff --git a/src/models/Common/constants.ts b/src/models/Common/constants.ts
index fbd8b3c218..0fab59b181 100644
--- a/src/models/Common/constants.ts
+++ b/src/models/Common/constants.ts
@@ -9,6 +9,7 @@ export const endpointPrefixes = {
launchPlan: '/launch_plans',
namedEntity: '/named_entities',
nodeExecution: '/node_executions',
+ dynamicWorkflowExecution: '/data/node_executions',
project: '/projects',
relaunchExecution: '/executions/relaunch',
recoverExecution: '/executions/recover',
diff --git a/src/models/Execution/api.ts b/src/models/Execution/api.ts
index 8778719928..450c280404 100644
--- a/src/models/Execution/api.ts
+++ b/src/models/Execution/api.ts
@@ -256,7 +256,8 @@ export const getNodeExecution = (
config
);
-/** Fetches data URLs for a NodeExecution */
+/** Fetches data URLs for a NodeExecution (used when fetching Dynamicworkflows
+ * from nodeExeecutions at runtime) */
export const getNodeExecutionData = (
id: NodeExecutionIdentifier,
config?: RequestConfig
diff --git a/src/models/Execution/types.ts b/src/models/Execution/types.ts
index a78b3561fb..0720008618 100644
--- a/src/models/Execution/types.ts
+++ b/src/models/Execution/types.ts
@@ -1,5 +1,6 @@
import { Admin, Core, Protobuf } from 'flyteidl';
import { Identifier, LiteralMap, LiteralMapBlob, TaskLog, UrlBlob } from 'models/Common/types';
+import { CompiledWorkflow } from 'models/Workflow/types';
import { ExecutionMode, NodeExecutionPhase, TaskExecutionPhase, WorkflowExecutionPhase } from './enums';
export type WorkflowExecutionIdentifier = RequiredNonNullable
;
@@ -126,4 +127,5 @@ export interface ExecutionData {
outputs: UrlBlob;
fullInputs: LiteralMap | null;
fullOutputs: LiteralMap | null;
+ dynamicWorkflow?: CompiledWorkflow;
}
diff --git a/src/models/Graph/types.ts b/src/models/Graph/types.ts
index 307f6cf6a9..fbc5fcdd26 100644
--- a/src/models/Graph/types.ts
+++ b/src/models/Graph/types.ts
@@ -34,6 +34,7 @@ export enum dTypes {
* @targetId dNode.id
*/
export interface dEdge {
+ id: string;
sourceId: string;
targetId: string;
}
diff --git a/src/server.tsx b/src/server.tsx
index 8b25f66b24..7555ac704d 100644
--- a/src/server.tsx
+++ b/src/server.tsx
@@ -7,59 +7,48 @@ import { Helmet } from 'react-helmet';
import { processEnv } from '../env';
interface Stats {
- publicPath: string;
- assets: Array<{ name: string }>;
+ publicPath: string;
+ assets: Array<{ name: string }>;
}
interface ServerRendererArguments {
- clientStats: Stats;
- fileSystem: MemoryFileSystem;
- currentDirectory: string;
+ clientStats: Stats;
+ fileSystem: MemoryFileSystem;
+ currentDirectory: string;
}
/**
* Universal render function in development mode
*/
-export default function serverRenderer({
- fileSystem,
- currentDirectory
-}: ServerRendererArguments) {
- const env = process.env.NODE_ENV || 'development';
- const isDev = env === 'development';
- const isProd = env === 'production';
- let html = '';
- if (isProd) {
- html = fs
- .readFileSync(path.join(currentDirectory, 'dist/index.html'))
- .toString();
+export default function serverRenderer({ fileSystem, currentDirectory }: ServerRendererArguments) {
+ const env = process.env.NODE_ENV || 'development';
+ const isDev = env === 'development';
+ const isProd = env === 'production';
+ let html = '';
+ if (isProd) {
+ html = fs.readFileSync(path.join(currentDirectory, 'dist/index.html')).toString();
+ }
+
+ return (_req: express.Request, res: express.Response) => {
+ if (isDev) {
+ const indexPath = path.join(currentDirectory, 'dist', 'index.html');
+ html = fileSystem.readFileSync(indexPath).toString();
}
- return (_req: express.Request, res: express.Response) => {
- if (isDev) {
- const indexPath = path.join(currentDirectory, 'dist', 'index.html');
- html = fileSystem.readFileSync(indexPath).toString();
- }
-
- if (html === '') {
- throw new ReferenceError('Could not find index.html to render');
- }
+ if (html === '') {
+ throw new ReferenceError('Could not find index.html to render');
+ }
- // populate the app content...
- const $ = cheerio.load(html);
+ // populate the app content...
+ const $ = cheerio.load(html);
- // populate Helmet content
- const helmet = Helmet.renderStatic();
- $('head').append(
- $.parseHTML(
- `${helmet.title.toString()} ${helmet.meta.toString()} ${helmet.link.toString()}`
- )
- );
+ // populate Helmet content
+ const helmet = Helmet.renderStatic();
+ $('head').append($.parseHTML(`${helmet.title.toString()} ${helmet.meta.toString()} ${helmet.link.toString()}`));
- // Populate process.env into window.env
- $('head').append(
- $(``)
- );
+ // Populate process.env into window.env
+ $('head').append($(``));
- res.status(200).send($.html());
- };
+ res.status(200).send($.html());
+ };
}
diff --git a/yarn.lock b/yarn.lock
index 64efbbe647..2b8f3a622b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1346,7 +1346,7 @@
core-js-pure "^3.0.0"
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.14.8", "@babel/runtime@^7.16.7", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.6":
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.14.8", "@babel/runtime@^7.16.5", "@babel/runtime@^7.16.7", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.6":
version "7.17.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
@@ -1360,13 +1360,6 @@
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.14.6":
- version "7.14.6"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
- integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
- dependencies:
- regenerator-runtime "^0.13.4"
-
"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.3.3":
version "7.12.7"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc"
@@ -3831,109 +3824,109 @@
integrity sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==
"@types/d3-array@*":
- version "2.12.1"
- resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-2.12.1.tgz#bee6857b812f1ecfd5e6832fd67f617b667dd024"
- integrity sha512-kVHqB3kfLpU0WYEmx5Y2hi3LRhUGIEIQXFdGazNNWQhyhzHx8xrgLtpAOKYzpfS3a+GjFMdKsI82QUH4q5dACQ==
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.2.tgz#71c35bca8366a40d1b8fce9279afa4a77fb0065d"
+ integrity sha512-5mjGjz6XOXKOCdTajXTZ/pMsg236RdiwKPrRPWAEf/2S/+PzwY+LLYShUpeysWaMvsdS7LArh6GdUefoxpchsQ==
"@types/d3-axis@*":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-2.1.0.tgz#5314adec80e4303d4eb02d23bdb5b8c600f6ee2c"
- integrity sha512-6ekm+D+EG/LVT3oiwwU9wsm0+SBAQpxSSOsZq92fp+tnpaa19YMHpj8sRZQAeksSBcqNWzEMjuRPXR9s38YFaw==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.1.tgz#6afc20744fa5cc0cbc3e2bd367b140a79ed3e7a8"
+ integrity sha512-zji/iIbdd49g9WN0aIsGcwcTBUkgLsCSwB+uH+LPVDAiKWENMtI3cJEWt+7/YYwelMoZmbBfzA3qCdrZ2XFNnw==
dependencies:
"@types/d3-selection" "*"
"@types/d3-brush@*":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-2.1.0.tgz#c51ad1ab93887b23be7637d2100540f1df0dac00"
- integrity sha512-rLQqxQeXWF4ArXi81GlV8HBNwJw9EDpz0jcWvvzv548EDE4tXrayBTOHYi/8Q4FZ/Df8PGXFzxpAVQmJMjOtvQ==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.1.tgz#ae5f17ce391935ca88b29000e60ee20452c6357c"
+ integrity sha512-B532DozsiTuQMHu2YChdZU0qsFJSio3Q6jmBYGYNp3gMDzBmuFFgPt9qKA4VYuLZMp4qc6eX7IUFUEsvHiXZAw==
dependencies:
"@types/d3-selection" "*"
"@types/d3-chord@*":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-2.0.1.tgz#45c72b28c9686eb4b02c8a1bb0fe174723053890"
- integrity sha512-mqGww8qDtGZRnDsFizzobAVizd85hgaYNEri095ZI7/aYtW7hxa9a20enwuoVTWm0YqdCtLPoyV9ZPYgfyaTZw==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.1.tgz#54c8856c19c8e4ab36a53f73ba737de4768ad248"
+ integrity sha512-eQfcxIHrg7V++W8Qxn6QkqBNBokyhdWSAS73AbkbMzvLQmVVBviknoz2SRS/ZJdIOmhcmmdCRE/NFOm28Z1AMw==
"@types/d3-color@*":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-2.0.1.tgz#570ea7f8b853461301804efa52bd790a640a26db"
- integrity sha512-u7LTCL7RnaavFSmob2rIAJLNwu50i6gFwY9cHFr80BrQURYQBRkJ+Yv47nA3Fm7FeRhdWTiVTeqvSeOuMAOzBQ==
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.0.2.tgz#53f2d6325f66ee79afd707c05ac849e8ae0edbb0"
+ integrity sha512-WVx6zBiz4sWlboCy7TCgjeyHpNjMsoF36yaagny1uXfbadc9f+5BeBf7U+lRmQqY3EHbGQpP8UdW8AC+cywSwQ==
"@types/d3-contour@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-2.0.0.tgz#6e079f281b29a8df3fcbd3ec193f2cf1d0b4a584"
- integrity sha512-PS9UO6zBQqwHXsocbpdzZFONgK1oRUgWtjjh/iz2vM06KaXLInLiKZ9e3OLBRerc1cU2uJYpO+8zOnb6frvCGQ==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.1.tgz#9ff4e2fd2a3910de9c5097270a7da8a6ef240017"
+ integrity sha512-C3zfBrhHZvrpAAK3YXqLWVAGo87A4SvJ83Q/zVJ8rFWJdKejUnDYaWZPkA8K84kb2vDA/g90LTQAz7etXcgoQQ==
dependencies:
"@types/d3-array" "*"
"@types/geojson" "*"
"@types/d3-delaunay@*":
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-5.3.0.tgz#416169bb5c67a510c87b55d092a404fcab49def3"
- integrity sha512-gJYcGxLu0xDZPccbUe32OUpeaNtd1Lz0NYJtko6ZLMyG2euF4pBzrsQXms67LHZCDFzzszw+dMhSL/QAML3bXw==
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.0.tgz#c09953ac7e5460997f693d2d7bf3522e0d4a88e6"
+ integrity sha512-iGm7ZaGLq11RK3e69VeMM6Oqj2SjKUB9Qhcyd1zIcqn2uE8w9GFB445yCY46NOQO3ByaNyktX1DK+Etz7ZaX+w==
"@types/d3-dispatch@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-2.0.0.tgz#1f8803041b73b81f2c751e026b7bb63dd5f24ce0"
- integrity sha512-Sh0KW6z/d7uxssD7K4s4uCSzlEG/+SP+U47q098NVdOfFvUKNTvKAIV4XqjxsUuhE/854ARAREHOxkr9gQOCyg==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.1.tgz#a1b18ae5fa055a6734cb3bd3cbc6260ef19676e3"
+ integrity sha512-NhxMn3bAkqhjoxabVJWKryhnZXXYYVQxaBnbANu0O94+O/nX9qSjrA1P1jbAQJxJf+VC72TxDX/YJcKue5bRqw==
"@types/d3-drag@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-2.0.0.tgz#ef66acc422576fbe10b8bd66af45a9fb8525199a"
- integrity sha512-VaUJPjbMnDn02tcRqsHLRAX5VjcRIzCjBfeXTLGe6QjMn5JccB5Cz4ztMRXMJfkbC45ovgJFWuj6DHvWMX1thA==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.1.tgz#fb1e3d5cceeee4d913caa59dedf55c94cb66e80f"
+ integrity sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==
dependencies:
"@types/d3-selection" "*"
"@types/d3-dsv@*":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-2.0.1.tgz#44ce09b025cf365d27cbe11fc13cd10954369627"
- integrity sha512-wovgiG9Mgkr/SZ/m/c0m+RwrIT4ozsuCWeLxJyoObDWsie2DeQT4wzMdHZPR9Ya5oZLQT3w3uSl0NehG0+0dCA==
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.0.tgz#f3c61fb117bd493ec0e814856feb804a14cfc311"
+ integrity sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==
"@types/d3-ease@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-2.0.0.tgz#798cbd9908d26cfe9f1a295a3a75164da9a3666e"
- integrity sha512-6aZrTyX5LG+ptofVHf+gTsThLRY1nhLotJjgY4drYqk1OkJMu2UvuoZRlPw2fffjRHeYepue3/fxTufqKKmvsA==
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.0.tgz#c29926f8b596f9dadaeca062a32a45365681eae0"
+ integrity sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==
"@types/d3-fetch@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-2.0.0.tgz#580846256ed0011b36a08ebb36924e0dff70e27e"
- integrity sha512-WnLepGtxepFfXRdPI8I5FTgNiHn9p4vMTTqaNCzJJfAswXx0rOY2jjeolzEU063em3iJmGZ+U79InnEeFOrCRw==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.1.tgz#f9fa88b81aa2eea5814f11aec82ecfddbd0b8fe0"
+ integrity sha512-toZJNOwrOIqz7Oh6Q7l2zkaNfXkfR7mFSJvGvlD/Ciq/+SQ39d5gynHJZ/0fjt83ec3WL7+u3ssqIijQtBISsw==
dependencies:
"@types/d3-dsv" "*"
"@types/d3-force@*":
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-2.1.1.tgz#a18b6f029d056eb0f8f84a09471e6228e4469b14"
- integrity sha512-3r+CQv2K/uDTAVg0DGxsbBjV02vgOxb8RhPIv3gd6cp3pdPAZ7wEXpDjUZSoqycAQLSDOxG/AZ54Vx6YXZSbmQ==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.3.tgz#76cb20d04ae798afede1ea6e41750763ff5a9c82"
+ integrity sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==
"@types/d3-format@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-2.0.0.tgz#607d261cb268f0a027f100575491031539a40ee6"
- integrity sha512-uagdkftxnGkO4pZw5jEYOM5ZnZOEsh7z8j11Qxk85UkB2RzfUUxRl7R9VvvJZHwKn8l+x+rpS77Nusq7FkFmIg==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.1.tgz#194f1317a499edd7e58766f96735bdc0216bb89d"
+ integrity sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==
"@types/d3-geo@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-2.0.0.tgz#6f179512343c2d30e06acde190abfacf44b2d264"
- integrity sha512-DHHgYXW36lnAEQMYU2udKVOxxljHrn2EdOINeSC9jWCAXwOnGn7A19B8sNsHqgpu4F7O2bSD7//cqBXD3W0Deg==
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.0.2.tgz#e7ec5f484c159b2c404c42d260e6d99d99f45d9a"
+ integrity sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ==
dependencies:
"@types/geojson" "*"
"@types/d3-hierarchy@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz#92079d9dbcec1dfe2736fb050a8bf916e5850a1c"
- integrity sha512-YxdskUvwzqggpnSnDQj4KVkicgjpkgXn/g/9M9iGsiToLS3nG6Ytjo1FoYhYVAAElV/fJBGVL3cQ9Hb7tcv+lw==
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.0.2.tgz#ca63f2f4da15b8f129c5b7dffd71d904cba6aca2"
+ integrity sha512-+krnrWOZ+aQB6v+E+jEkmkAx9HvsNAD+1LCD0vlBY3t+HwjKnsBFbpVLx6WWzDzCIuiTWdAxXMEnGnVXpB09qQ==
"@types/d3-interpolate@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-2.0.0.tgz#325029216dc722c1c68c33ccda759f1209d35823"
- integrity sha512-Wt1v2zTlEN8dSx8hhx6MoOhWQgTkz0Ukj7owAEIOF2QtI0e219paFX9rf/SLOr/UExWb1TcUzatU8zWwFby6gg==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc"
+ integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==
dependencies:
"@types/d3-color" "*"
"@types/d3-path@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-2.0.0.tgz#dcc7f5ecadf52b0c0c39f6c1def3733195e4b199"
- integrity sha512-tXcR/9OtDdeCIsyl6eTNHC3XOAOdyc6ceF3QGBXOd9jTcK+ex/ecr00p9L9362e/op3UEPpxrToi1FHrtTSj7Q==
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.0.tgz#939e3a784ae4f80b1fde8098b91af1776ff1312b"
+ integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==
"@types/d3-path@^1":
version "1.0.9"
@@ -3941,43 +3934,43 @@
integrity sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==
"@types/d3-polygon@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-2.0.0.tgz#8b1df0a1358016e62c4961b01e8dc8e5ab4c64e5"
- integrity sha512-fISnMd8ePED1G4aa4V974Jmt+ajHSgPoxMa2D0ULxMybpx0Vw4WEzhQEaMIrL3hM8HVRcKTx669I+dTy/4PhAw==
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.0.tgz#5200a3fa793d7736fa104285fa19b0dbc2424b93"
+ integrity sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==
"@types/d3-quadtree@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-2.0.0.tgz#b17e953dc061e083966075bba0d3a9a259812150"
- integrity sha512-YZuJuGBnijD0H+98xMJD4oZXgv/umPXy5deu3IimYTPGH3Kr8Th6iQUff0/6S80oNBD7KtOuIHwHUCymUiRoeQ==
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz#433112a178eb7df123aab2ce11c67f51cafe8ff5"
+ integrity sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==
"@types/d3-random@*":
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-2.2.0.tgz#fc44cabb966917459490b758f31f5359adeabe5b"
- integrity sha512-Hjfj9m68NmYZzushzEG7etPvKH/nj9b9s9+qtkNG3/dbRBjQZQg1XS6nRuHJcCASTjxXlyXZnKu2gDxyQIIu9A==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.1.tgz#5c8d42b36cd4c80b92e5626a252f994ca6bfc953"
+ integrity sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==
"@types/d3-scale-chromatic@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz#8d4a6f07cbbf2a9f2a4bec9c9476c27ed76a96ea"
- integrity sha512-Y62+2clOwZoKua84Ha0xU77w7lePiaBoTjXugT4l8Rd5LAk+Mn/ZDtrgs087a+B5uJ3jYUHHtKw5nuEzp0WBHw==
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#103124777e8cdec85b20b51fd3397c682ee1e954"
+ integrity sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==
"@types/d3-scale@*":
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-3.3.0.tgz#7ab91db0186bac0f24834ceb33f970e829f2fba1"
- integrity sha512-rJj4nh/71Rw5bZgTF5cA5rW60WT3x8RbivEsScgQ66sqFnYZRmuyKSayyo7JiP+c9KJJiQhY9JXBmY16FZa3+g==
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69"
+ integrity sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA==
dependencies:
"@types/d3-time" "*"
"@types/d3-selection@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-2.0.0.tgz#59df94a8e47ed1050a337d4ffb4d4d213aa590a8"
- integrity sha512-EF0lWZ4tg7oDFg4YQFlbOU3936e3a9UmoQ2IXlBy1+cv2c2Pv7knhKUzGlH5Hq2sF/KeDTH1amiRPey2rrLMQA==
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.2.tgz#23e48a285b24063630bbe312cc0cfe2276de4a59"
+ integrity sha512-d29EDd0iUBrRoKhPndhDY6U/PYxOWqgIZwKTooy2UkBfU7TNZNpRho0yLWPxlatQrFWk2mnTu71IZQ4+LRgKlQ==
"@types/d3-shape@*":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-2.1.0.tgz#cc7bbc9fc2c25f092bd457887a3224a21a55ca55"
- integrity sha512-xTMEs8eITRksXclcVxMHIONRdyjj2TjDIwO4XFOPTVBNK9/oC4ZOhUbvTz1IpcsEsS/mClwuulP+OoawSAbSGA==
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.0.2.tgz#4b1ca4ddaac294e76b712429726d40365cd1e8ca"
+ integrity sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw==
dependencies:
- "@types/d3-path" "^1"
+ "@types/d3-path" "*"
"@types/d3-shape@^1.2.6":
version "1.3.5"
@@ -3987,39 +3980,39 @@
"@types/d3-path" "^1"
"@types/d3-time-format@*":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-3.0.0.tgz#913e984362a59792dc8d8b122dd17625991eade2"
- integrity sha512-UpLg1mn/8PLyjr+J/JwdQJM/GzysMvv2CS8y+WYAL5K0+wbvXv/pPSLEfdNaprCZsGcXTxPsFMy8QtkYv9ueew==
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.0.tgz#ee7b6e798f8deb2d9640675f8811d0253aaa1946"
+ integrity sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==
"@types/d3-time@*":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-2.1.0.tgz#95708e5c92b199959806fd2116eeb3dfa0e9661c"
- integrity sha512-qVCiT93utxN0cawScyQuNx8H82vBvZXSClZfgOu3l3dRRlRO6FjKEZlaPgXG9XUFjIAOsA4kAJY101vobHeJLQ==
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819"
+ integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==
"@types/d3-timer@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-2.0.0.tgz#9901bb02af38798764674df17d66b07329705632"
- integrity sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg==
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.0.tgz#e2505f1c21ec08bda8915238e397fb71d2fc54ce"
+ integrity sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==
"@types/d3-transition@*":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-2.0.0.tgz#6f073f0b567c13b7a3dcd1d54214c89f48c5a873"
- integrity sha512-UJDzI98utcZQUJt3uIit/Ho0/eBIANzrWJrTmi4+TaKIyWL2iCu7ShP0o4QajCskhyjOA7C8+4CE3b1YirTzEQ==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.1.tgz#c9a96125567173d6163a6985b874f79154f4cc3d"
+ integrity sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g==
dependencies:
"@types/d3-selection" "*"
"@types/d3-zoom@*":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-2.0.1.tgz#6f0d993042124947314053c937784e24d8b003cf"
- integrity sha512-FuiGLfaHmp84b9wsj0dG03E/aJl5k98OLnJ2/5p7bQOHEpWqR+z5WCoWYMAbdGxaca7VNd9tCT5i6AJnpauNTQ==
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.1.tgz#4bfc7e29625c4f79df38e2c36de52ec3e9faf826"
+ integrity sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==
dependencies:
"@types/d3-interpolate" "*"
"@types/d3-selection" "*"
-"@types/d3@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.0.0.tgz#d102ec6ea5741e51a1ff7b8228850db0665ccd27"
- integrity sha512-7rMMuS5unvbvFCJXAkQXIxWTo2OUlmVXN5q7sfQFesuVICY55PSP6hhbUhWjTTNpfTTB3iLALsIYDFe7KUNABw==
+"@types/d3@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.1.0.tgz#8f32a7e7f434d8f920c8b1ebdfed55e18c033720"
+ integrity sha512-gYWvgeGjEl+zmF8c+U1RNIKqe7sfQwIXeLXO5Os72TjDjCEtgpvGBvZ8dXlAuSS1m6B90Y1Uo6Bm36OGR/OtCA==
dependencies:
"@types/d3-array" "*"
"@types/d3-axis" "*"
@@ -4082,9 +4075,9 @@
"@types/serve-static" "*"
"@types/geojson@*":
- version "7946.0.7"
- resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad"
- integrity sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==
+ version "7946.0.8"
+ resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca"
+ integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==
"@types/glob@*", "@types/glob@^7.1.1":
version "7.2.0"
@@ -4113,14 +4106,6 @@
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934"
integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==
-"@types/hoist-non-react-statics@^3.3.0":
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
- integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
- dependencies:
- "@types/react" "*"
- hoist-non-react-statics "^3.3.0"
-
"@types/html-minifier-terser@^5.0.0":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57"
@@ -4380,16 +4365,6 @@
dependencies:
"@types/react" "*"
-"@types/react-redux@^7.1.16":
- version "7.1.16"
- resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.16.tgz#0fbd04c2500c12105494c83d4a3e45c084e3cb21"
- integrity sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==
- dependencies:
- "@types/hoist-non-react-statics" "^3.3.0"
- "@types/react" "*"
- hoist-non-react-statics "^3.3.0"
- redux "^4.0.0"
-
"@types/react-responsive@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/react-responsive/-/react-responsive-3.0.3.tgz#a31b599c7cfe4135c5cc2f45d0b71df64803b23f"
@@ -6787,7 +6762,7 @@ cloneable-readable@^1.0.0:
process-nextick-args "^2.0.0"
readable-stream "^2.3.5"
-clsx@^1.0.2, clsx@^1.0.4, clsx@^1.1.0:
+clsx@^1.0.2, clsx@^1.0.4, clsx@^1.1.0, clsx@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
@@ -13109,7 +13084,7 @@ lodash@4.17.15:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
-lodash@^4.15.0, lodash@^4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
+lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -15857,6 +15832,14 @@ react-draggable@^4.4.3:
classnames "^2.2.5"
prop-types "^15.6.0"
+react-draggable@^4.4.4:
+ version "4.4.4"
+ resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.4.tgz#5b26d9996be63d32d285a426f41055de87e59b2f"
+ integrity sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==
+ dependencies:
+ clsx "^1.1.1"
+ prop-types "^15.6.0"
+
react-element-to-jsx-string@^14.3.4:
version "14.3.4"
resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz#709125bc72f06800b68f9f4db485f2c7d31218a8"
@@ -15876,21 +15859,18 @@ react-fast-compare@^3.0.1, react-fast-compare@^3.2.0:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
-react-flow-renderer@^9.6.3:
- version "9.6.3"
- resolved "https://registry.yarnpkg.com/react-flow-renderer/-/react-flow-renderer-9.6.3.tgz#3dc4bf941a5fa5691057248aec838746238a3f9c"
- integrity sha512-/2J1Lil8eOq3G0spVJPTIyhVUfnzDyV/JGRQC7DEFzwqzjL+qTj+ssyCblSxCSidxx1Q7zaza+ghnuMTr4E8QA==
+react-flow-renderer@10.0.0-next.30:
+ version "10.0.0-next.30"
+ resolved "https://registry.yarnpkg.com/react-flow-renderer/-/react-flow-renderer-10.0.0-next.30.tgz#eb105270da2cc1c67362b12845760c5530312317"
+ integrity sha512-ZBaI0ti2g1TTKjeN0O2JHNQUD9sT5l6AMGTaPtuWOLJZRx0xUBbOmBR4HL936Gq1BzbiZv09OWZnf2qEyfC7yw==
dependencies:
- "@babel/runtime" "^7.14.6"
- "@types/d3" "^7.0.0"
- "@types/react-redux" "^7.1.16"
+ "@babel/runtime" "^7.16.5"
+ "@types/d3" "^7.1.0"
classcat "^5.0.3"
d3-selection "^3.0.0"
d3-zoom "^3.0.0"
- fast-deep-equal "^3.1.3"
- react-draggable "^4.4.3"
- react-redux "^7.2.4"
- redux "^4.1.0"
+ react-draggable "^4.4.4"
+ zustand "^3.6.7"
react-ga4@^1.4.1:
version "1.4.1"
@@ -16014,18 +15994,6 @@ react-query@^3.3.0:
"@babel/runtime" "^7.5.5"
match-sorter "^6.0.2"
-react-redux@^7.2.4:
- version "7.2.4"
- resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225"
- integrity sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA==
- dependencies:
- "@babel/runtime" "^7.12.1"
- "@types/react-redux" "^7.1.16"
- hoist-non-react-statics "^3.3.2"
- loose-envify "^1.4.0"
- prop-types "^15.7.2"
- react-is "^16.13.1"
-
react-refresh@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
@@ -16358,13 +16326,6 @@ redeyed@~2.1.0:
dependencies:
esprima "~4.0.0"
-redux@^4.0.0, redux@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4"
- integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==
- dependencies:
- "@babel/runtime" "^7.9.2"
-
refractor@^3.1.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a"
@@ -19971,6 +19932,11 @@ yocto-queue@^0.1.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+zustand@^3.6.7:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.1.tgz#7388f0a7175a6c2fd9a2880b383a4bf6cdf6b7c6"
+ integrity sha512-wHBCZlKj+bg03/hP+Tzv24YhnqqP8MCeN9ECPDXoF01062SIbnfl3j9O0znkDw1lNTY0a8WN3F///a0UhhaEqg==
+
zwitch@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"