D3, aria etc

This commit is contained in:
mvdbeek
2023-01-09 17:22:29 +01:00
parent fb7ebafcd2
commit bf12af5bbe
23 changed files with 950 additions and 312 deletions
+2 -1
View File
@@ -35,6 +35,7 @@
"@pinia/testing": "^0.0.14",
"@popperjs/core": "^2.11.5",
"@sentry/browser": "^6.17.4",
"@types/d3": "^7.4.0",
"@vue/runtime-dom": "^3.2.45",
"@vueuse/core": "https://github.com/mvdbeek/vueuse/releases/download/v9.3.0-useCapture/vueuse-core-v9.3.0.tgz",
"assert": "^2.0.0",
@@ -46,7 +47,7 @@
"citation-js": "^0.6.4",
"core-js": "^3.21.0",
"csv-parse": "^5.3.0",
"d3": "3",
"d3": "^7.8.0",
"d3-zoom": "^3.0.0",
"date-fns": "^2.28.0",
"date-fns-tz": "^1.3.3",
+1 -1
View File
@@ -95,7 +95,7 @@ export default {
svgElem.setAttribute("viewBox", -translateX + " 0 " + 0.5 * clientW + " " + clientH);
svgElem.setAttribute("preserveAspectRatio", "xMidYMid meet");
const tree = d3.layout.tree().size([clientH, clientW]);
const tree = d3.tree().size([clientH, clientW]);
const diagonal = d3.svg.diagonal().projection((d) => {
return [d.y, d.x];
});
@@ -0,0 +1,107 @@
<template>
<b-list-group ref="menu" id="input-choices-menu" role="menu" @keyup.down="increment" @keyup.up="decrement">
<b-list-group-item
v-for="(input, index) in allElements"
role="menu-item"
ref="menuItem"
@click="toggleConnection(input)"
@keyup.enter="toggleConnection(input)"
@focus="activeElement = index"
:tabindex="index + 1"
:active="activeElement === index">
{{ input.connected ? "Disconnect" : "Connect" }} to {{ input.inputLabel }}
</b-list-group-item>
</b-list-group>
</template>
<script lang="ts" setup>
import { useWorkflowStepStore } from "@/stores/workflowStepStore";
import { computed, nextTick, onMounted, ref, watch, type ComputedRef } from "vue";
import { type OutputTerminals, type InputTerminals, terminalFactory } from "./modules/terminals";
import { useFocusWithin } from "@/composables/useActiveElement";
const props = defineProps<{
terminal: OutputTerminals;
}>();
const menu = ref();
const { focused } = useFocusWithin(menu);
const activeElement = ref(0);
const menuItem = ref<HTMLLIElement[]>();
const emit = defineEmits<{ (e: "closeMenu", value: boolean): void }>();
onMounted(() => {
menuItem.value![0].focus();
});
watch(focused, (focused) => {
if (!focused) {
emit("closeMenu", true);
}
});
const stepStore = useWorkflowStepStore();
interface InputObject {
stepId: number;
inputName: string;
inputLabel: string;
connected: boolean;
}
function increment() {
console.log("incr");
activeElement.value += 1;
activeElement.value = Math.min(activeElement.value, menuItem.value!.length - 1);
menuItem.value![activeElement.value].focus();
}
function decrement() {
console.log("decr");
activeElement.value = Math.max(activeElement.value - 1, 0);
menuItem.value![activeElement.value].focus();
}
function terminalToInputObject(terminal: InputTerminals, connected: boolean): InputObject {
const step = stepStore.getStep(terminal.stepId);
const inputLabel = `${terminal.name} in step ${step.id + 1}: ${step.label}`;
return { stepId: step.id, inputName: terminal.name, inputLabel, connected };
}
function inputObjectToTerminal(inputObject: InputObject): InputTerminals {
const inputSource = stepStore
.getStep(inputObject.stepId)
.inputs.find((input) => input.name == inputObject.inputName)!;
return terminalFactory(inputObject.stepId, inputSource, props.terminal.datatypesMapper);
}
const validInputs: ComputedRef<InputObject[]> = computed(() => {
const inputTerminals = props.terminal.validInputTerminals();
return inputTerminals.map((inputTerminal) => terminalToInputObject(inputTerminal, false));
});
const connectedInputs: ComputedRef<InputObject[]> = computed(() => {
const inputTerminals = props.terminal.getConnectedTerminals();
return inputTerminals.map((inputTerminal) => terminalToInputObject(inputTerminal, true));
});
const allElements = computed(() => {
const allElements = [...connectedInputs.value, ...validInputs.value];
allElements.sort((elementA, elementB) => {
const stepIdSort = elementA.stepId - elementB.stepId;
if (stepIdSort === 0) {
return (elementA.inputLabel || elementA.inputName) < (elementB.inputLabel || elementB.inputName) ? -1 : 1;
}
return stepIdSort;
});
return allElements;
});
function toggleConnection(inputObject: InputObject) {
if (inputObject.connected) {
inputObjectToTerminal(inputObject).disconnect(props.terminal);
} else {
inputObjectToTerminal(inputObject).connect(props.terminal);
}
}
</script>
@@ -1,58 +1,72 @@
<template>
<g class="ribbon">
<path class="ribbon-outer" :d="line" stroke-width="6" fill="none"></path>
<path class="ribbon-inner" :d="line" stroke-width="4" fill="none"></path>
<g v-for="line in paths">
<path class="ribbon-outer" :d="line" :stroke-width="stroke.outerStroke" fill="none"></path>
<path class="ribbon-inner" :d="line" :stroke-width="stroke.innerStroke" fill="none"></path>
</g>
</g>
</template>
<script>
import { svg } from "d3";
<script lang="ts" setup>
import { line, curveBasis } from "d3";
import { computed } from "vue";
import type { TerminalPosition } from "@/stores/workflowEditorStateStore";
export default {
props: {
id: {
type: String,
required: false,
},
position: {
type: Object,
required: true,
},
},
data() {
return {
lineShift: 30,
};
},
computed: {
offsetStart() {
return 0;
},
offsetEnd() {
return 0;
},
lineData() {
const data = [
{ x: this.position.startX, y: this.position.startY + this.offsetStart },
{ x: this.position.startX + this.lineShift, y: this.position.startY + this.offsetStart },
{ x: this.position.endX - this.lineShift, y: this.position.endY + this.offsetEnd },
{ x: this.position.endX, y: this.position.endY + this.offsetEnd },
];
return data;
},
path() {
return svg
.line()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
.interpolate("basis");
},
line() {
return this.path(this.lineData);
},
},
};
const props = withDefaults(
defineProps<{
id?: string;
position: TerminalPosition;
inputIsMappedOver: boolean;
outputIsMappedOver: boolean;
}>(),
{
inputIsMappedOver: false,
outputIsMappedOver: false,
}
);
const path = line().curve(curveBasis);
const ribbonMargin = 4;
const lineShift = 30;
const stroke = computed(() => {
let innerStroke = 4;
let outerStroke = 6;
if (props.outputIsMappedOver || props.inputIsMappedOver) {
innerStroke = 1;
outerStroke = 3;
}
return { innerStroke, outerStroke };
});
const offsets = computed(() => {
const _offsets = [-2 * ribbonMargin, -ribbonMargin, 0, ribbonMargin, 2 * ribbonMargin];
let startOffsets = [0];
let endOffsets = [0];
let numOffsets = 1;
if (props.outputIsMappedOver) {
startOffsets = _offsets;
numOffsets = _offsets.length;
}
if (props.inputIsMappedOver) {
endOffsets = _offsets;
numOffsets = _offsets.length;
}
return { numOffsets, startOffsets, endOffsets };
});
const paths = computed(() => {
const lines = [...Array(offsets.value.numOffsets).keys()].map((offsetIndex) => {
const startOffset = offsets.value.startOffsets[offsetIndex] || 0;
const endOffset = offsets.value.endOffsets[offsetIndex] || 0;
return [
[props.position.startX, props.position.startY + startOffset],
[props.position.startX + lineShift, props.position.startY + startOffset],
[props.position.endX - lineShift, props.position.endY + endOffset],
[props.position.endX, props.position.endY + endOffset],
] as [number, number][];
});
return lines.map((line) => path(line)!);
});
</script>
+12 -15
View File
@@ -206,7 +206,8 @@ import { useConnectionStore } from "@/stores/workflowConnectionStore";
import Vue from "vue";
import { ConfirmDialog } from "composables/confirmDialog";
import { useWorkflowStepStore } from "stores/workflowStepStore";
import { useWorkflowStepStore } from "@/stores/workflowStepStore";
import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
import { storeToRefs } from "pinia";
import { useDatatypesMapper } from "@/composables/datatypesMapper";
@@ -257,14 +258,20 @@ export default {
const connectionsStore = useConnectionStore();
const stepStore = useWorkflowStepStore();
const { getStepIndex, steps } = storeToRefs(stepStore);
const stateStore = useWorkflowStateStore();
const { nodes, activeNode, activeNodeId } = storeToRefs(stateStore);
return {
connectionsStore,
stepStore,
steps: steps,
nodeIndex: getStepIndex,
datatypes,
activeNode,
activeNodeId,
nodes,
datatypesMapper,
datatypesMapperLoading,
stateStore,
};
},
data() {
@@ -297,9 +304,6 @@ export default {
};
},
computed: {
nodes() {
return this.$store.getters["workflowState/getNodes"];
},
showAttributes() {
return this.showInPanel == "attributes";
},
@@ -309,13 +313,6 @@ export default {
postJobActions() {
return this.activeNode.postJobActions;
},
activeNode() {
// TODO: replace usage of this with just data ?
return this.nodes[this.activeNodeId];
},
activeNodeId() {
return this.$store.getters["workflowState/getActiveNode"];
},
activeNodeName() {
return this.activeNode?.name;
},
@@ -496,7 +493,7 @@ export default {
tool_state: JSON.parse(JSON.stringify(node.tool_state)),
post_job_actions: JSON.parse(JSON.stringify(node.postJobActions)),
});
this.$store.commit("workflowState/setActiveNode", id);
this.stateStore.setActiveNode(id);
},
onInsertTool(tool_id, tool_name) {
this._insertStep(tool_id, tool_name, "tool");
@@ -569,11 +566,11 @@ export default {
},
onAttributes() {
this._ensureParametersSet();
this.$store.commit("workflowState/setActiveNode", null);
this.stateStore.setActiveNode(null);
this.showInPanel = "attributes";
},
onWorkflowTextEditor() {
this.$store.commit("workflowState/setActiveNode", null);
this.stateStore.setActiveNode(null);
this.showInPanel = "attributes";
},
onAnnotation(nodeId, newAnnotation) {
@@ -689,7 +686,7 @@ export default {
type: type,
position: defaultPosition(this.graphOffset, this.transform),
});
this.$store.commit("workflowState/setActiveNode", this.nodeIndex);
this.stateStore.setActiveNode(this.nodeIndex);
},
async _loadEditorData(data) {
const report = data.report || {};
@@ -114,6 +114,7 @@ import DraggableWrapper from "./DraggablePan";
import { ActiveOutputs } from "./modules/outputs";
import { computed, inject, reactive, ref } from "vue";
import { useElementBounding } from "@vueuse/core";
import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
Vue.use(BootstrapVue);
@@ -171,7 +172,8 @@ export default {
const position = reactive(useElementBounding(el, { windowResize: false }));
const transform = inject("transform");
const postJobActions = computed(() => props.step.post_job_actions || {});
return { el, position, transform, nodeIOKey, postJobActions };
const stateStore = useWorkflowStateStore();
return { el, position, transform, nodeIOKey, postJobActions, stateStore };
},
data() {
return {
@@ -246,7 +248,7 @@ export default {
},
},
created() {
this.$store.commit("workflowState/setNode", this);
this.stateStore.setNode(this);
this.activeOutputs = new ActiveOutputs();
this.content_id = this.contentId;
// initialize node data
@@ -257,7 +259,7 @@ export default {
}
},
beforeDestroy() {
this.$store.commit("workflowState/deleteNode", this.id);
this.stateStore.deleteNode(this.id);
},
methods: {
onMoveTo(position, event) {
@@ -28,6 +28,7 @@ import { computed } from "@vue/reactivity";
import { inject, ref, watchEffect } from "vue";
import { useTerminal } from "./composables/useTerminal";
import { DatatypesMapperModel } from "@/components/Datatypes/model";
import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
export default {
props: {
@@ -67,6 +68,7 @@ export default {
const connectedTerminals = ref([]);
watchEffect(() => (connectedTerminals.value = connectionStore.getOutputTerminalsForInputTerminal(id.value)));
const terminal = useTerminal(ref(props.stepId), ref(props.input), ref(props.datatypesMapper));
const stateStore = useWorkflowStateStore();
return {
el,
position,
@@ -77,6 +79,7 @@ export default {
iconId,
connectedTerminals,
terminal,
stateStore,
};
},
data() {
@@ -102,7 +105,6 @@ export default {
return this.input.label || this.input.name;
},
canAccept() {
// TODO: put producesAcceptableDatatype ... in datatypesMapper ?
return this.draggingConnection && this.terminal.canAccept(this.draggingConnection.terminal);
},
reason() {
@@ -130,15 +132,11 @@ export default {
},
watch: {
terminalPosition(position) {
this.$store.commit("workflowState/setInputTerminalPosition", {
stepId: this.stepId,
inputName: this.input.name,
position,
});
this.stateStore.setInputTerminalPosition(this.stepId, this.input.name, position);
},
},
beforeDestroy() {
this.$store.commit("workflowState/deleteInputTerminalPosition", {
this.stateStore.deleteInputTerminalPosition({
stepId: this.stepId,
inputName: this.input.name,
});
@@ -148,7 +146,6 @@ export default {
if (this.reason) {
this.$root.$emit("bv::show::tooltip", this.iconId);
}
console.log("dragover input", event);
},
dragLeave(event) {
this.$root.$emit("bv::hide::tooltip", this.iconId);
@@ -163,11 +160,7 @@ export default {
this.showRemove = false;
},
enter() {
if (this.hasTerminals) {
this.showRemove = true;
} else {
this.showRemove = false;
}
this.showRemove = Boolean(this.hasTerminals);
},
leave() {
this.showRemove = false;
@@ -18,12 +18,22 @@
:prevent-default="false"
:stop-propagation="true"
draggable="true"
@dragstart="dragStart"
@pan-by="onPanBy"
@start="isDragging = true"
@stop="onStopDragging"
@move="onMove">
<div class="icon prevent-zoom"></div>
<div
class="icon prevent-zoom"
tabindex="0"
@keyup.space="toggleChildComponent"
@keyup.enter="toggleChildComponent"
@keyup.esc="toggleChildComponent">
<connection-menu
ref="menu"
v-if="showChildComponent"
:terminal="terminal"
@closeMenu="closeMenu"></connection-menu>
</div>
</draggable-wrapper>
</div>
</template>
@@ -32,11 +42,14 @@
import DraggableWrapper from "./DraggablePan";
import { useCoordinatePosition } from "./composables/useCoordinatePosition";
import { useTerminal } from "./composables/useTerminal";
import { ref, computed, watch, reactive } from "vue";
import { ref, computed, watch, nextTick } from "vue";
import { DatatypesMapperModel } from "@/components/Datatypes/model";
import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
import ConnectionMenu from "@/components/Workflow/Editor/ConnectionMenu";
export default {
components: {
ConnectionMenu,
DraggableWrapper,
},
props: {
@@ -93,7 +106,35 @@ export default {
effectiveOutput.value = { ...props.output, extensions: extensions.value };
});
const terminal = useTerminal(ref(props.stepId), effectiveOutput, ref(props.datatypesMapper));
return { el, position, terminal, extensions };
function closeMenu() {
console.log("closing Menu");
showChildComponent.value = false;
}
const menu = ref(null);
const showChildComponent = ref(false);
async function toggleChildComponent() {
showChildComponent.value = !showChildComponent.value;
if (showChildComponent.value) {
await nextTick();
console.log(menu);
menu.value.$el.focus();
}
}
const stateStore = useWorkflowStateStore();
return {
el,
position,
terminal,
extensions,
stateStore,
menu,
showChildComponent,
toggleChildComponent,
closeMenu,
};
},
data() {
return {
@@ -150,11 +191,7 @@ export default {
},
watch: {
terminalPosition(position) {
this.$store.commit("workflowState/setOutputTerminalPosition", {
stepId: this.stepId,
outputName: this.output.name,
position,
});
this.stateStore.setOutputTerminalPosition(this.stepId, this.output.name, position);
},
dragPosition() {
if (this.isDragging) {
@@ -173,7 +210,7 @@ export default {
},
},
beforeDestroy() {
this.$store.commit("workflowState/deleteOutputTerminalPosition", {
this.stateStore.deleteOutputTerminalPosition({
stepId: this.stepId,
outputName: this.output.name,
});
@@ -195,9 +232,6 @@ export default {
this.dragY = 0;
this.$emit("stopDragging");
},
dragStart(e) {
console.log("dragStart", e);
},
inputDragEnter(e) {},
inputDragLeave(e) {},
onDrop(e) {},
@@ -1,40 +1,33 @@
<template>
<raw-connector v-if="position" :position="position"></raw-connector>
<raw-connector
v-if="position"
:position="position"
:output-is-mapped-over="outputIsMappedOver"
:input-is-mapped-over="inputIsMappedOver"></raw-connector>
</template>
<script>
import RawConnector from "./Connector";
<script lang="ts" setup>
import RawConnector from "@/components/Workflow/Editor/Connector.vue";
import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
import { useWorkflowStepStore } from "@/stores/workflowStepStore";
import type { Connection } from "@/stores/workflowConnectionStore";
import { computed } from "vue";
export default {
components: {
RawConnector,
},
props: {
connection: {
type: Object,
required: true,
},
},
computed: {
position() {
const outputPos = this.$store.getters["workflowState/getOutputTerminalPosition"](
this.connection.output.stepId,
this.connection.output.name
);
const inputPos = this.$store.getters["workflowState/getInputTerminalPosition"](
this.connection.input.stepId,
this.connection.input.name
);
if (inputPos && outputPos) {
return {
...inputPos,
...outputPos,
};
}
return null;
},
},
};
const props = defineProps<{
connection: Connection;
}>();
const stepStore = useWorkflowStepStore();
const outputIsMappedOver = computed(() => stepStore.stepMapOver[props.connection.output.stepId]?.isCollection);
const inputIsMappedOver = computed(() => stepStore.stepMapOver[props.connection.input.stepId]?.isCollection);
const stateStore = useWorkflowStateStore();
const position = computed(() => {
const outputPos = stateStore.getOutputTerminalPosition(
props.connection.output.stepId,
props.connection.output.name
);
const inputPos = stateStore.getInputTerminalPosition(props.connection.input.stepId, props.connection.input.name);
return { ...inputPos, ...outputPos };
});
</script>
<style></style>
@@ -1,16 +1,19 @@
<script setup>
import RawConnector from "./Connector";
import TerminalConnector from "./TerminalConnector";
<script setup lang="ts">
import RawConnector from "./Connector.vue";
import TerminalConnector from "./TerminalConnector.vue";
import { computed } from "vue";
import { useConnectionStore } from "@/stores/workflowConnectionStore";
import { storeToRefs } from "pinia";
import type { TerminalPosition } from "@/stores/workflowEditorStateStore";
import type { OutputTerminal, OutputCollectionTerminal, OutputParameterTerminal } from "./modules/terminals";
const props = defineProps({
draggingConnection: {
type: Object,
default: null,
},
});
interface DraggingConnection extends TerminalPosition {
terminal: OutputTerminal | OutputCollectionTerminal | OutputParameterTerminal;
}
const props = defineProps<{
draggingConnection?: DraggingConnection;
}>();
const connectionStore = useConnectionStore();
const { connections } = storeToRefs(connectionStore);
@@ -19,7 +22,7 @@ const dragStyle = computed(() => {
// TODO: this isn't quite right, but 6 seems to work, probably because it's the outer strokewidth
// sync up with Connector.vue ?
const strokeWidth = 6;
const dragStyle = {};
const dragStyle: { [index: string]: string } = {};
if (props.draggingConnection) {
dragStyle.left = props.draggingConnection.endX - strokeWidth + "px";
dragStyle.top = props.draggingConnection.endY - strokeWidth + "px";
@@ -31,7 +34,11 @@ const dragStyle = computed(() => {
<div>
<div v-if="draggingConnection" class="drag-terminal" :style="dragStyle" />
<svg class="canvas-svg node-area">
<raw-connector v-if="draggingConnection" :position="draggingConnection"></raw-connector>
<raw-connector
v-if="draggingConnection"
:position="draggingConnection"
:input-is-mapped-over="false"
:output-is-mapped-over="draggingConnection.terminal.mapOver?.isCollection"></raw-connector>
<terminal-connector
v-for="connection in connections"
:key="connection.id"
@@ -51,7 +51,8 @@ import { computed, reactive, ref } from "vue";
import { useElementBounding } from "@vueuse/core";
import D3Zoom from "./D3Zoom.vue";
import { provide } from "vue";
import { useScale, setScale, useActiveNodeId, setActiveNodeId } from "./composables/useWorkflowState";
import { storeToRefs } from "pinia";
import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore";
defineProps({
steps: {
@@ -77,8 +78,9 @@ const isDragging = ref(false);
provide("draggingConnection", draggingConnection);
provide("isDragging", isDragging);
provide("transform", transform);
const scale = useScale();
const activeNodeId = useActiveNodeId();
const stateStore = useWorkflowStateStore();
const { scale, activeNodeId } = storeToRefs(stateStore);
const el = ref(null);
const zoom = ref(null);
const position = reactive(useElementBounding(el, { windowResize: false, windowScroll: false }));
@@ -91,7 +93,7 @@ function onZoom(zoomLevel, panTo = null) {
if (panTo) {
onPan({ x: panTo.x - transform.x, y: panTo.y - transform.y });
}
setScale(zoomLevel);
stateStore.setScale(zoomLevel);
}
function onMoveTo(moveTo) {
zoom.value.moveTo(moveTo);
@@ -109,18 +111,18 @@ function onDragConnector(vector) {
}
function onActivate(nodeId) {
if (activeNodeId != nodeId) {
setActiveNodeId(nodeId);
stateStore.setActiveNode(nodeId);
}
}
function onDeactivate() {
setActiveNodeId(null);
stateStore.setActiveNode(null);
}
function onTransform(newTransform) {
transform.x = newTransform.x;
transform.y = newTransform.y;
transform.k = newTransform.k;
setScale(transform.k);
stateStore.setScale(transform.k);
}
const nodesStyle = computed(() => {
@@ -0,0 +1,19 @@
import type { DatatypesMapperModel } from "@/components/Datatypes/model";
import { terminalFactory } from "@/components/Workflow/Editor/modules/terminals";
import type { Step, TerminalSource } from "@/stores/workflowStepStore";
import { ref, watchEffect, type Ref } from "vue";
export function useTerminal(
stepId: Ref<Step["id"]>,
terminalSource: Ref<TerminalSource>,
datatypesMapper: Ref<DatatypesMapperModel>
): Ref<ReturnType<typeof terminalFactory>> {
const terminal = ref();
watchEffect(() => {
const newTerminal = terminalFactory(stepId.value, terminalSource.value, datatypesMapper.value);
console.log("built new terminal with datatypes mapper!", datatypesMapper.value);
newTerminal.destroyInvalidConnections();
terminal.value = newTerminal;
});
return terminal as Ref<ReturnType<typeof terminalFactory>>;
}
@@ -1,19 +0,0 @@
import store from "store";
import { computed } from "vue";
export function setScale(scale) {
store.commit("workflowState/setScale", scale);
}
export function useScale() {
const scale = computed(() => store.getters["workflowState/getScale"]);
return scale;
}
export function useActiveNodeId() {
return computed(() => store.getters["workflowState/getActiveNode"]);
}
export function setActiveNodeId(nodeId) {
store.commit("workflowState/setActiveNode", nodeId);
}
@@ -34,15 +34,6 @@ export function toSimple(workflow) {
return { steps, report, license, creator, annotation, name };
}
function _scaledNodePosition(element, canvasZoom) {
const rect = element.getBoundingClientRect();
const coords = {
left: rect.left / canvasZoom,
top: rect.top / canvasZoom,
};
return coords;
}
function _rectifyOutputs(workflow) {
// Find out if we're using workflow_outputs or not.
let using_workflow_outputs = false;
@@ -142,6 +142,12 @@ describe("canAccept", () => {
multiDataInOne.connect(collectionOut);
expect(multiDataInTwo.canAccept(collectionOut).canAccept).toBe(true);
});
it("rejects connecting output to input of same step", () => {
const dataOut = terminals["simple data"]["out_file1"] as OutputTerminal;
const dataIn = terminals["simple data"]["input"] as InputTerminal;
expect(dataIn.canAccept(dataOut).canAccept).toBe(false);
expect(dataIn.canAccept(dataOut).reason).toBe("Cannot connection output to input of same step.");
});
it("rejects paired input on multi-data input", () => {
const multiDataIn = terminals["multi data"]["f1"] as InputTerminal;
const pairedOut = terminals["paired input"]["output"] as OutputCollectionTerminal;
@@ -415,11 +421,12 @@ describe("canAccept", () => {
describe("Input terminal", () => {
let stepStore: ReturnType<typeof useWorkflowStepStore>;
let connectionStore: ReturnType<typeof useConnectionStore>;
let terminals: { [index: number]: { [index: string]: ReturnType<typeof terminalFactory> } } = {};
let terminals: { [index: number]: { [index: string]: ReturnType<typeof terminalFactory> } };
beforeEach(() => {
setActivePinia(createPinia());
stepStore = useWorkflowStepStore();
connectionStore = useConnectionStore();
terminals = {};
Object.entries(simpleSteps).map(([key, step]) => {
stepStore.addStep(step);
terminals[step.id] = {};
@@ -463,8 +470,10 @@ describe("Input terminal", () => {
const dataInputOutputTerminal = terminals[0]["output"] as OutputTerminal;
const connection = firstInputTerminal.connections[0];
expect(firstInputTerminal.canAccept(dataInputOutputTerminal).canAccept).toBe(false);
expect(dataInputOutputTerminal.validInputTerminals().length).toBe(0);
firstInputTerminal.disconnect(connection);
expect(firstInputTerminal.canAccept(dataInputOutputTerminal).canAccept).toBe(true);
expect(dataInputOutputTerminal.validInputTerminals().length).toBe(1);
connectionStore.addConnection(connection);
expect(firstInputTerminal.canAccept(dataInputOutputTerminal).canAccept).toBe(false);
});
@@ -177,6 +177,9 @@ class BaseInputTerminal extends Terminal {
}
}
canAccept(outputTerminal: BaseOutputTerminal) {
if (this.stepId == outputTerminal.stepId) {
return new ConnectionAcceptable(false, "Cannot connection output to input of same step.");
}
if (this._inputFilled()) {
return new ConnectionAcceptable(
false,
@@ -289,13 +292,17 @@ class BaseInputTerminal extends Terminal {
}
return otherCollectionType;
}
destroyInvalidConnections() {
this.connections.forEach((connection) => {
getConnectedTerminals() {
return this.connections.map((connection) => {
const outputStep = this.stepStore.getStep(connection.output.stepId);
const terminalSource = outputStep.outputs.find((output) => output.name === connection.output.name)!;
const outputTerminal = terminalFactory(outputStep.id, terminalSource, this.datatypesMapper);
if (!this.attachable(outputTerminal).canAccept) {
this.disconnect(outputTerminal);
return terminalFactory(outputStep.id, terminalSource, this.datatypesMapper);
});
}
destroyInvalidConnections() {
this.getConnectedTerminals().forEach((terminal) => {
if (!this.attachable(terminal).canAccept) {
this.disconnect(terminal);
}
});
}
@@ -503,16 +510,32 @@ class BaseOutputTerminal extends Terminal {
this.optional = attr.optional;
this.terminalType = "output";
}
destroyInvalidConnections() {
this.connections.forEach((connection) => {
getConnectedTerminals() {
return this.connections.map((connection) => {
const inputStep = this.stepStore.getStep(connection.input.stepId);
const terminalSource = inputStep.inputs.find((input) => input.name === connection.input.name)!;
const inputTerminal = terminalFactory(inputStep.id, terminalSource, this.datatypesMapper);
if (!inputTerminal.attachable(this).canAccept) {
inputTerminal.disconnect(this);
return terminalFactory(inputStep.id, terminalSource, this.datatypesMapper);
});
}
destroyInvalidConnections() {
this.getConnectedTerminals().forEach((terminal) => {
if (!terminal.attachable(this).canAccept) {
terminal.disconnect(this);
}
});
}
validInputTerminals() {
const validInputTerminals: InputTerminals[] = [];
Object.entries(this.stepStore.steps).map(([stepId, step]) => {
step.inputs?.forEach((input) => {
const inputTerminal = terminalFactory(step.id, input, this.datatypesMapper);
if (inputTerminal.canAccept(this).canAccept) {
validInputTerminals.push(inputTerminal);
}
});
});
return validInputTerminals;
}
}
export class OutputTerminal extends BaseOutputTerminal {}
@@ -549,6 +572,9 @@ export class OutputParameterTerminal extends BaseOutputTerminal {
}
}
export type OutputTerminals = OutputTerminal | OutputCollectionTerminal | OutputParameterTerminal;
export type InputTerminals = InputTerminal | InputCollectionTerminal | InputParameterTerminal;
export function producesAcceptableDatatype(
datatypesMapper: DatatypesMapperModel,
inputDatatypes: string[],
@@ -0,0 +1,56 @@
// https://github.com/vueuse/vueuse/blob/main/packages/core/_configurable.ts
import { computedWithControl } from "@vueuse/shared";
import { isClient } from "@vueuse/shared";
import { useEventListener } from "@vueuse/core";
import { unrefElement } from "@vueuse/core";
import { computed } from "vue";
import type { MaybeElementRef, UseFocusWithinReturn, ConfigurableWindow } from "@vueuse/core";
const defaultWindow = isClient ? window : undefined;
/**
* Reactive `document.activeElement`
*
* @see https://vueuse.org/useActiveElement
* @param options
*/
export function useActiveElement<T extends HTMLElement>(options: ConfigurableWindow = {}) {
const { window = defaultWindow } = options;
const activeElement = computedWithControl(
() => null,
() => window?.document.activeElement as T | null | undefined
);
if (window) {
useEventListener(
window,
"blur",
() => {
const scheduler = window.requestAnimationFrame || window.setTimeout;
scheduler(() => activeElement.trigger());
},
true
);
useEventListener(window, "focus", activeElement.trigger, true);
}
return activeElement;
}
/**
* Track if focus is contained within the target element
*
* @see https://vueuse.org/useFocusWithin
* @param target The target element to track
* @param options Focus within options
*/
export function useFocusWithin(target: MaybeElementRef, options: ConfigurableWindow = {}): UseFocusWithinReturn {
const activeElement = useActiveElement(options);
const targetElement = computed(() => unrefElement(target));
const focused = computed(() =>
targetElement.value && activeElement.value ? targetElement.value.contains(activeElement.value) : false
);
return { focused };
}
+16 -23
View File
@@ -1,6 +1,5 @@
import $ from "jquery";
import * as d3 from "d3";
import { event as currentEvent } from "d3";
function date_by_subtracting_days(date, days) {
return new Date(
@@ -126,14 +125,14 @@ export function create_chart(inp_data, name, time, title) {
}
var wdth = i * 4 + 10;
d3.select(currentEvent.target.parentElement)
d3.select(d.target.parentElement)
.select(".tool_tip")
.select("text")
.attr("transform", `translate( ${margin.left - 5}, ${height - d * zoom + margin.top + 10} )`)
.attr("visibility", "visible")
.text(d);
d3.select(currentEvent.target.parentElement)
d3.select(d.target.parentElement)
.select(".tool_tip")
.attr("width", `${wdth}px`)
.attr("height", "15px")
@@ -145,12 +144,9 @@ export function create_chart(inp_data, name, time, title) {
})
.on("mouseleave", (d) => {
// Remove tool tip
d3.select(currentEvent.target.parentElement)
.select(".tool_tip")
.select("text")
.attr("visibility", "hidden");
d3.select(d.target.parentElement).select(".tool_tip").select("text").attr("visibility", "hidden");
d3.select(currentEvent.target.parentElement)
d3.select(d.target.parentElement)
.select(".tool_tip")
.select("rect")
.attr("width", "0")
@@ -182,14 +178,14 @@ export function create_chart(inp_data, name, time, title) {
});
// Declare how high the y axis goes
var y = d3.scale.linear().range([height, 0]);
var y = d3.curveLinear().range([height, 0]);
// Create a yAxis object
var yAxis = d3.svg
.axis()
.scale(y)
.orient("left")
.tickFormat((d) => d3.round(d * d3.max(data), 0));
.tickFormat((d) => Math.round(d * d3.max(data), 0));
// Put the y axis on the chart
chart
@@ -442,13 +438,13 @@ export function create_histogram(inp_data, name, title) {
// Cereate x axis metadata
// Used for x axis, histogram creation, and bar initialization
var x = d3.scale
.linear()
var x = d3
.curveLinear()
.domain([0, d3.max(data)])
.range([0, width]);
// Generate a histogram using twenty uniformly-spaced bins.
data = d3.layout.histogram().bins(x.ticks(20))(data);
data = d3.histogram().bins(x.ticks(20))(data);
// Create an array of the sizes of the bars
var lengths = [];
@@ -466,8 +462,8 @@ export function create_histogram(inp_data, name, title) {
// Create y axis metadata
// Used for y axis and bar initialization
var y = d3.scale
.linear()
var y = d3
.curveLinear()
.domain([0, d3.max(data, (d) => d.y)])
.range([height, 0]);
@@ -542,14 +538,14 @@ export function create_histogram(inp_data, name, title) {
i++;
}
var wdth = i * 4 + 10;
d3.select(currentEvent.target.parentElement)
d3.select(d.target.parentElement)
.select(".tool_tip")
.select("text")
.attr("transform", `translate( ${margin.left - 5}, ${height - d.length * zoom + margin.top + 10} )`)
.attr("visibility", "visible")
.text(d.length);
d3.select(currentEvent.target.parentElement)
d3.select(d.target.parentElement)
.select(".tool_tip")
.attr("width", `${wdth}px`)
.attr("height", "15px")
@@ -559,14 +555,11 @@ export function create_histogram(inp_data, name, title) {
.attr("height", "15px")
.attr("fill", "#ebd9b2");
})
.on("mouseleave", () => {
.on("mouseleave", (d) => {
// Remove tool tip
d3.select(currentEvent.target.parentElement)
.select(".tool_tip")
.select("text")
.attr("visibility", "hidden");
d3.select(d.target.parentElement).select(".tool_tip").select("text").attr("visibility", "hidden");
d3.select(currentEvent.target.parentElement)
d3.select(d.target.parentElement)
.select(".tool_tip")
.select("rect")
.attr("width", "0")
-2
View File
@@ -18,7 +18,6 @@ import { invocationStore } from "./invocationStore";
import { collectionElementsStore, datasetStore, historyStore } from "./historyStore";
import { userStore, userFlagsStore } from "./userStore";
import { configStore } from "./configStore";
import { workflowStateStore } from "./workflowEditorStateStore";
import { toolStore } from "./toolStore";
import { datasetPathDestinationStore } from "./datasetPathDestinationStore";
import { datasetExtFilesStore } from "./datasetExtFilesStore";
@@ -73,7 +72,6 @@ export function createStore() {
tools: toolStore,
user: userStore,
userFlags: userFlagsStore,
workflowState: workflowStateStore,
},
};
@@ -1,82 +0,0 @@
export const state = {
inputTerminals: {},
outputTerminals: {},
connections: {},
activeNode: null,
scale: 1,
nodes: {},
};
import Vue from "vue";
const getters = {
getInputTerminalPosition: (state) => (stepId, inputName) => {
return state.inputTerminals[stepId]?.[inputName];
},
getOutputTerminalPosition: (state) => (stepId, outputName) => {
return state.outputTerminals[stepId]?.[outputName];
},
getActiveNode: (state) => {
return state.activeNode;
},
getScale: (state) => {
return state.scale;
},
getNode: (state) => (nodeId) => {
return state.nodes[nodeId];
},
getNodes: (state) => {
return state.nodes;
},
};
const actions = {};
const mutations = {
setInputTerminalPosition: (state, { stepId, inputName, position }) => {
if (!state.inputTerminals[stepId]) {
Vue.set(state.inputTerminals, stepId, { [inputName]: position });
} else {
Vue.set(state.inputTerminals[stepId], inputName, position);
}
},
setOutputTerminalPosition: (state, { stepId, outputName, position }) => {
if (!state.outputTerminals[stepId]) {
Vue.set(state.outputTerminals, stepId, { [outputName]: position });
} else {
Vue.set(state.outputTerminals[stepId], outputName, position);
}
},
deleteInputTerminalPosition: (state, { stepId, inputName }) => {
delete state.inputTerminals[stepId][inputName];
},
deleteOutputTerminalPosition: (state, { stepId, outputName }) => {
delete state.outputTerminals[stepId][outputName];
},
setConnection: (state, { source, target, connection }) => {
if (!state.connections[source]) {
state.connections[source] = { target: connection };
} else {
state.connections[source][target] = connection;
}
},
setActiveNode: (state, nodeId) => {
state.activeNode = nodeId;
},
setScale: (state, scale) => {
state.scale = scale;
},
setNode: (state, node) => {
Vue.set(state.nodes, node.id, node);
},
deleteNode: (state, nodeId) => {
delete state.nodes[nodeId];
},
};
export const workflowStateStore = {
namespaced: true,
state,
getters,
actions,
mutations,
};
@@ -0,0 +1,83 @@
import Vue from "vue";
import { defineStore } from "pinia";
export const state = {
inputTerminals: {},
outputTerminals: {},
activeNode: null,
scale: 1,
nodes: {},
};
export interface TerminalPosition {
startX: number;
endX: number;
startY: number;
endY: number;
}
interface State {
inputTerminals: { [index: number]: { [index: string]: TerminalPosition } };
outputTerminals: { [index: number]: { [index: string]: TerminalPosition } };
activeNodeId: number;
scale: number;
nodes: { [index: number]: any };
}
export const useWorkflowStateStore = defineStore("workflowStateStore", {
state: (): State => ({
inputTerminals: {},
outputTerminals: {},
activeNodeId: -1,
scale: 1,
nodes: {},
}),
getters: {
getInputTerminalPosition(state: State) {
return (stepId: number, inputName: string) => state.inputTerminals[stepId]?.[inputName];
},
getOutputTerminalPosition(state: State) {
return (stepId: number, outputName: string) => state.outputTerminals[stepId]?.[outputName];
},
getNode(state: State) {
return (nodeId: number) => state.nodes[nodeId];
},
activeNode(state: State) {
return state.nodes[state.activeNodeId];
},
},
actions: {
setInputTerminalPosition(stepId: number, inputName: string, position: TerminalPosition) {
if (!this.inputTerminals[stepId]) {
Vue.set(this.inputTerminals, stepId, { [inputName]: position });
} else {
Vue.set(this.inputTerminals[stepId], inputName, position);
}
},
setOutputTerminalPosition(stepId: number, outputName: string, position: TerminalPosition) {
if (!this.outputTerminals[stepId]) {
Vue.set(this.outputTerminals, stepId, { [outputName]: position });
} else {
Vue.set(this.outputTerminals[stepId], outputName, position);
}
},
deleteInputTerminalPosition(stepId: number, inputName: string) {
delete this.inputTerminals[stepId]?.[inputName];
},
deleteOutputTerminalPosition(stepId: number, outputName: string) {
delete this.outputTerminals[stepId]?.[outputName];
},
setActiveNode(nodeId: number) {
this.activeNodeId = nodeId;
},
setScale(scale: number) {
this.scale = scale;
},
setNode(node: any) {
Vue.set(this.nodes, node.id, node);
},
deleteNode(nodeId: number) {
delete this.nodes[nodeId];
},
},
});
+1 -1
View File
@@ -3,7 +3,7 @@
*/
import _ from "underscore";
import $ from "jquery";
import d3 from "d3";
import * as d3 from "d3";
import Backbone from "backbone";
import { getAppRoot } from "onload/loadConfig";
import util from "viz/trackster/util";
+428 -14
View File
@@ -1975,6 +1975,216 @@
resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz"
integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
"@types/d3-array@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.3.tgz#87d990bf504d14ad6b16766979d04e943c046dac"
integrity sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==
"@types/d3-axis@*":
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 "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 "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 "3.1.0"
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.0.tgz#6594da178ded6c7c3842f3cc0ac84b156f12f2d4"
integrity sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==
"@types/d3-contour@*":
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 "6.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.1.tgz#006b7bd838baec1511270cb900bf4fc377bbbf41"
integrity sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==
"@types/d3-dispatch@*":
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 "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 "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 "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 "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 "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 "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 "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 "3.1.0"
resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.0.tgz#4561bb7ace038f247e108295ef77b6a82193ac25"
integrity sha512-g+sey7qrCa3UbsQlMZZBOHROkFqx7KZKvUpRzI/tAp/8erZWpYq7FgNKvYwebi2LaEiVs1klhUfd3WCThxmmWQ==
"@types/d3-interpolate@*":
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 "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-polygon@*":
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 "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 "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 "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 "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 "3.0.3"
resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.3.tgz#57be7da68e7d9c9b29efefd8ea5a9ef1171e42ba"
integrity sha512-Mw5cf6nlW1MlefpD9zrshZ+DAWL4IQ5LnWfRheW6xwsdaWOb6IRRu2H7XPAQcyXEx1D7XQWgdoKR83ui1/HlEA==
"@types/d3-shape@*":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.0.tgz#1d87a6ddcf28285ef1e5c278ca4bdbc0658f3505"
integrity sha512-jYIYxFFA9vrJ8Hd4Se83YI6XF+gzDL1aC5DCsldai4XYYiVNdhtpGbA/GM6iyQ8ayhSp3a148LY34hy7A4TxZA==
dependencies:
"@types/d3-path" "*"
"@types/d3-time-format@*":
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 "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 "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 "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.2.tgz#393dc3e3d55009a43cc6f252e73fccab6d78a8a4"
integrity sha512-jo5o/Rf+/u6uerJ/963Dc39NI16FQzqwOc54bwvksGAdVfvDrqDpVeq95bEvPtBwLCVZutAEyAtmSyEMxN7vxQ==
dependencies:
"@types/d3-selection" "*"
"@types/d3-zoom@*":
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.4.0":
version "7.4.0"
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.0.tgz#fc5cac5b1756fc592a3cf1f3dc881bf08225f515"
integrity sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA==
dependencies:
"@types/d3-array" "*"
"@types/d3-axis" "*"
"@types/d3-brush" "*"
"@types/d3-chord" "*"
"@types/d3-color" "*"
"@types/d3-contour" "*"
"@types/d3-delaunay" "*"
"@types/d3-dispatch" "*"
"@types/d3-drag" "*"
"@types/d3-dsv" "*"
"@types/d3-ease" "*"
"@types/d3-fetch" "*"
"@types/d3-force" "*"
"@types/d3-format" "*"
"@types/d3-geo" "*"
"@types/d3-hierarchy" "*"
"@types/d3-interpolate" "*"
"@types/d3-path" "*"
"@types/d3-polygon" "*"
"@types/d3-quadtree" "*"
"@types/d3-random" "*"
"@types/d3-scale" "*"
"@types/d3-scale-chromatic" "*"
"@types/d3-selection" "*"
"@types/d3-shape" "*"
"@types/d3-time" "*"
"@types/d3-time-format" "*"
"@types/d3-timer" "*"
"@types/d3-transition" "*"
"@types/d3-zoom" "*"
"@types/eslint-scope@^3.7.3":
version "3.7.4"
resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz"
@@ -2020,6 +2230,11 @@
"@types/qs" "*"
"@types/serve-static" "*"
"@types/geojson@*":
version "7946.0.10"
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.10.tgz#6dfbf5ea17142f7f9a043809f1cd4c448cb68249"
integrity sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==
"@types/graceful-fs@^4.1.3":
version "4.1.5"
resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz"
@@ -3633,7 +3848,7 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
commander@7.2.0, commander@^7.0.0, commander@^7.2.0:
commander@7, commander@7.2.0, commander@^7.0.0, commander@^7.2.0:
version "7.2.0"
resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
@@ -4012,17 +4227,61 @@ custom-event@~1.0.0:
resolved "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz"
integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==
"d3-color@1 - 3":
"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.1"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.1.tgz#39331ea706f5709417d31bbb6ec152e0328b39b3"
integrity sha512-gUY/qeHq/yNqqoCKNq4vtpFLdoCdvyNpWoC/KNjhGbhDuQpAM9sIQQKkXSNpXa9h5KySs/gzm7R88WkUutgwWQ==
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-dispatch@1 - 3":
d3-contour@4:
version "4.0.0"
resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.0.tgz#5a1337c6da0d528479acdb5db54bc81a0ff2ec6b"
integrity sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==
dependencies:
d3-array "^3.2.0"
d3-delaunay@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92"
integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==
dependencies:
delaunator "5"
"d3-dispatch@1 - 3", d3-dispatch@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
"d3-drag@2 - 3":
"d3-drag@2 - 3", d3-drag@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
@@ -4030,29 +4289,131 @@ custom-event@~1.0.0:
d3-dispatch "1 - 3"
d3-selection "3"
"d3-ease@1 - 3":
"d3-dsv@1 - 3", d3-dsv@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73"
integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==
dependencies:
commander "7"
iconv-lite "0.6"
rw "1"
"d3-ease@1 - 3", d3-ease@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
"d3-interpolate@1 - 3":
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.0"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.0.tgz#74fd54e1f4cebd5185ac2039217a98d39b0a4c0e"
integrity sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==
dependencies:
d3-array "2.5.0 - 3"
d3-hierarchy@3:
version "3.1.2"
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6"
integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==
"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
dependencies:
d3-color "1 - 3"
"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526"
integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==
d3-polygon@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398"
integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==
"d3-quadtree@1 - 3", d3-quadtree@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f"
integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==
d3-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.0.0"
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a"
integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==
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@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-timer@1 - 3":
d3-shape@3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5"
integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==
dependencies:
d3-path "^3.1.0"
"d3-time-format@2 - 4", d3-time-format@4:
version "4.1.0"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a"
integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==
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-transition@2 - 3":
"d3-transition@2 - 3", d3-transition@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f"
integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==
@@ -4063,7 +4424,7 @@ custom-event@~1.0.0:
d3-interpolate "1 - 3"
d3-timer "1 - 3"
d3-zoom@^3.0.0:
d3-zoom@3, d3-zoom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
@@ -4074,10 +4435,41 @@ d3-zoom@^3.0.0:
d3-selection "2 - 3"
d3-transition "2 - 3"
d3@3:
version "3.5.17"
resolved "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz"
integrity sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg==
d3@^7.8.0:
version "7.8.0"
resolved "https://registry.yarnpkg.com/d3/-/d3-7.8.0.tgz#c9441f0ea9266b1003a97c2ffd53e79e9e14b1fc"
integrity sha512-a5rNemRadWkEfqnY5NsD4RdCP9vn8EIJ4I5Rl14U0uKH1SXqcNmk/h9aGaAF1O98lz6L9M0IeUcuPa9GUYbI5A==
dependencies:
d3-array "3"
d3-axis "3"
d3-brush "3"
d3-chord "3"
d3-color "3"
d3-contour "4"
d3-delaunay "6"
d3-dispatch "3"
d3-drag "3"
d3-dsv "3"
d3-ease "3"
d3-fetch "3"
d3-force "3"
d3-format "3"
d3-geo "3"
d3-hierarchy "3"
d3-interpolate "3"
d3-path "3"
d3-polygon "3"
d3-quadtree "3"
d3-random "3"
d3-scale "4"
d3-scale-chromatic "3"
d3-selection "3"
d3-shape "3"
d3-time "3"
d3-time-format "4"
d3-timer "3"
d3-transition "3"
d3-zoom "3"
d@1, d@^1.0.1:
version "1.0.1"
@@ -4254,6 +4646,13 @@ del@^6.0.0:
rimraf "^3.0.2"
slash "^3.0.0"
delaunator@5:
version "5.0.0"
resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b"
integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==
dependencies:
robust-predicates "^3.0.0"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
@@ -5858,7 +6257,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==
@@ -5966,6 +6365,11 @@ internal-slot@^1.0.3:
has "^1.0.3"
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@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz"
@@ -9168,6 +9572,11 @@ rimraf@^3.0.0, rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
robust-predicates@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a"
integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz"
@@ -9175,6 +9584,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-report-usage@^1.0.4:
version "1.0.6"
resolved "https://registry.npmjs.org/rxjs-report-usage/-/rxjs-report-usage-1.0.6.tgz"