fix circular dependencies frontend

This commit is contained in:
Ruben Fiszel
2023-10-23 15:08:31 +02:00
parent 75c30b0ce1
commit f9c75c95ce
20 changed files with 178 additions and 395 deletions
@@ -7,7 +7,8 @@
DraftService,
type PathScript,
ScriptService,
Script
Script,
type HubScriptKind
} from '$lib/gen'
import { initHistory, push, redo, undo } from '$lib/history'
import {
@@ -413,7 +414,7 @@
$copilotModulesStore[idx].hubCompletions = scripts as {
path: string
summary: string
kind: string
kind: HubScriptKind
app: string
ask_id: number
}[]
@@ -129,7 +129,7 @@
</div>
{#if copilotModule.source === 'hub' && copilotModule.selectedCompletion && copilotModule.selectedCompletion?.kind !== 'script'}
<Badge color="gray" baseClass="border"
>{capitalize(copilotModule.selectedCompletion.kind)}</Badge
>{capitalize(copilotModule.selectedCompletion.kind.toString())}</Badge
>
{/if}
@@ -254,7 +254,9 @@
</div>
</div>
{#if item.kind !== 'script'}
<Badge color="gray" baseClass="border">{capitalize(item.kind)}</Badge>
<Badge color="gray" baseClass="border"
>{capitalize(item.kind.toString())}</Badge
>
{/if}
</button>
</li>
+3 -3
View File
@@ -1,4 +1,4 @@
import type { Script, FlowModule } from '$lib/gen'
import type { Script, FlowModule, HubScriptKind } from '$lib/gen'
import { addResourceTypes, deltaCodeCompletion, getNonStreamingCompletion } from './lib'
import type { Writable } from 'svelte/store'
import type Editor from '../Editor.svelte'
@@ -15,7 +15,7 @@ export type FlowCopilotModule = {
hubCompletions: {
path: string
summary: string
kind: string
kind: HubScriptKind,
app: string
ask_id: number
}[]
@@ -23,7 +23,7 @@ export type FlowCopilotModule = {
| {
path: string
summary: string
kind: string
kind: HubScriptKind
app: string
ask_id: number
}
@@ -5,10 +5,10 @@
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
import { APP_TO_ICON_COMPONENT } from '$lib/components/icons'
import ListFilters from '$lib/components/home/ListFilters.svelte'
import { IntegrationService, ScriptService } from '$lib/gen'
import { IntegrationService, ScriptService, type HubScriptKind } from '$lib/gen'
import { Loader2 } from 'lucide-svelte'
export let kind: 'script' | 'trigger' | 'approval' | 'failure' = 'script'
export let kind: HubScriptKind & string = 'script'
export let filter = ''
export let syncQuery = false
@@ -25,7 +25,7 @@
version_id: number
ask_id: number
app: string
kind: typeof kind
kind: HubScriptKind
}[] = []
let allApps: string[] = []
@@ -89,7 +89,7 @@
id: number
ask_id: number
app: string
kind: typeof kind
kind: HubScriptKind
}) => ({
...x,
path: `hub/${x.version_id}/${x.app}/${x.summary.toLowerCase().replaceAll(/\s+/g, '_')}`,
@@ -1,136 +0,0 @@
import type { EdgeType, NodeType, ResizeNodeType, StoreType } from '../../store/types/types'
import type { CollapsibleType } from '../types/types'
import { get } from 'svelte/store'
import type { AnchorType } from '../../edges/types/types'
import { getAnchorById } from '../../edges/controllers/util'
import { getAnchors } from '../../edges/controllers/util'
// Given a nodeId, find ids of all connecting target nodes
function findTargets(store: StoreType, nodeId: string): string[] {
// get source anchors on the node
const anchors = getAnchors(store, {
nodeId: nodeId,
sourceOrTarget: 'source'
})
// get target anchors on other node, and record the node id
const targetNodeIds: string[] = []
for (const anchor of anchors) {
const targetAnchorId = anchor.getOtherAnchorId()
const targetAnchor = getAnchorById(store, targetAnchorId)
targetNodeIds.push(targetAnchor.nodeId)
}
return targetNodeIds
}
// traverses tree and increments hideCount
function traverseAndIncrement(
store: StoreType,
nodeId: string,
operation: 'increment' | 'decrement'
) {
const collapsibles = get(store.collapsibleStore)
recursiveTraverse(nodeId)
store.collapsibleStore.set(collapsibles)
function recursiveTraverse(nId: string) {
for (const collapsible of collapsibles) {
if (collapsible.nodeId === nId) {
if (operation === 'increment') collapsible.hideCount++
else collapsible.hideCount--
const targetIds = findTargets(store, nId)
for (const targetId of targetIds) {
recursiveTraverse(targetId)
}
}
}
}
}
function collapse(store: StoreType, nodeId: string) {
const targetNodeIds = findTargets(store, nodeId)
for (const targetNodeId of targetNodeIds) traverseAndIncrement(store, targetNodeId, 'increment')
}
function expand(store: StoreType, nodeId: string) {
const targetNodeIds = findTargets(store, nodeId)
for (const targetNodeId of targetNodeIds) traverseAndIncrement(store, targetNodeId, 'decrement')
}
export function toggleExpandAndCollapse(store: StoreType, nodeId: string) {
const collapsibles = getCollapsibles(store, { nodeId: nodeId })
if (collapsibles.length === 0) return // when the collapsible feature is disabled, there will be no collapbsible objects
if (collapsibles.length > 1) throw 'there should only be one collapsible object per node'
const collapsible = collapsibles[0]
if (collapsible.state === 'expanded') collapse(store, nodeId)
else expand(store, nodeId)
store.collapsibleStore.update((arr) => {
for (const c of arr) if (c.id === collapsible.id) c.toggleState()
return [...arr]
})
}
export function getCollapsibles(store: StoreType, filter?: { [key: string]: any }) {
let collapsibles = Object.values(get(store.collapsibleStore))
// filter the array of anchors for elements that match filter
// Example: if filter = {sourceOrTarget: 'source', positionX: 35} then we will
//return all anchors with sourceOrTarget = source AND poxitionX = 35
if (filter !== undefined) {
collapsibles = collapsibles.filter((collapsible) => {
for (let filterKey in filter) {
const filterValue = filter[filterKey]
if (collapsible[filterKey as keyof CollapsibleType] !== filterValue) return false
}
return true
})
}
// return list of anchors
return collapsibles
}
/*
This function is responsible for filtering nodes should be displayed based on Collapsible.
It also filters node-associated elements such as anchors, edges, etc. so that when you collapse a node, the
edges also hide.
There is a better way to implement this with foreign keys; when collapsing a node, you would also collapse any rows with a foreign key
linking to that node (like a cascading delete in SQL, but with hiding instead of deleting)
*/
export function filterByCollapsible(
store: StoreType,
nodes: NodeType[],
resizeNodes: ResizeNodeType[],
anchors: AnchorType[],
edges: EdgeType[]
) {
// filter nodes for the collapsible nodes feature
const filteredNodes = nodes.filter((node) => {
const nodeId = node.id
const collapssibleObj = get(store.collapsibleStore).find((e) => e.nodeId === nodeId)
if (collapssibleObj === undefined) return true
return collapssibleObj.isHidden() === false
})
const filteredNodeIds = filteredNodes.map((e) => e.id)
// filter resizeNodes
const filteredResizeNodes = resizeNodes.filter((resizeNode) =>
filteredNodeIds.includes(resizeNode.nodeId)
)
const filteredAnchors = anchors.filter((selfAnchor) => {
const otherAnchorId = selfAnchor.getOtherAnchorId()
const otherAnchor = get(store.anchorsStore)[otherAnchorId]
if (filteredNodeIds.includes(selfAnchor.nodeId) && filteredNodeIds.includes(otherAnchor.nodeId))
return true
return false
})
const filteredEdgeIds = new Set(filteredAnchors.map((e) => e.edgeId))
const filteredEdges = edges.filter((edge) => filteredEdgeIds.has(edge.id))
return {
filteredNodes,
filteredResizeNodes,
filteredAnchors,
filteredEdges
}
}
@@ -1,26 +0,0 @@
/**
* This model implements functionality for nodes to expand and collapse their children
*/
import type { CollapsibleType } from '../types/types';
/** Class that implements collapsible/expandable functionality for Node objects
* @param {string} id Unique string that serves as a primary key
* @param {string} nodeId Foreign key to a Node Object
*/
export class Collapsible implements CollapsibleType {
constructor(
public id: string,
public nodeId: string,
public hideCount: number,
public state: 'expanded' | 'collapsed'
) {}
isHidden() {
return this.hideCount > 0;
}
toggleState() {
this.state = this.state === 'expanded' ? 'collapsed' : 'expanded';
}
}
@@ -1,8 +0,0 @@
export interface CollapsibleType {
id: string;
nodeId: string;
hideCount: number;
state: 'expanded' | 'collapsed';
isHidden: Function;
toggleState: Function;
}
@@ -3,30 +3,16 @@ This file contains "middleware" functions that sanitize user input (UserNodeType
maintain consistency between previous
*/
import { get } from 'svelte/store';
import {
bottomCb,
leftCb,
rightCb,
topCb,
} from '../../edges/controllers/anchorCbUser';
import type { StoreType } from '../../store/types/types';
import type { UserEdgeType, UserNodeType } from '../../types/types';
/**
* sanitizeCanvasOptions will sanitize the canvas level options so that incompatible features will not be run simulataneously
* @param store The array of nodes that have a UserNodeType
* @returns void. The store is modified directly
*/
export function sanitizeCanvasOptions(store: StoreType) {
enforceCollapsibleCompatibility(store);
}
function enforceCollapsibleCompatibility(store: StoreType) {
if (get(store.collapsibleOption)) {
store.nodeCreate.set(false);
}
}
/**
* sanitizeUserNodesAndEdges will sanitize the data initially passed in to Svelvet component. For example, the node that user specified have an integar as its id but to instantiate a Node and be compatible with uuid we will need to convert the integar id to a string.
@@ -9,7 +9,7 @@
import Node from '../../nodes/views/Node.svelte'
import { determineD3Instance } from '../..//d3/controllers/d3'
import { findStore } from '../../store/controllers/storeApi'
import { findStore } from '../../store/models/store'
import { Expand, Minus, Plus } from 'lucide-svelte'
import Toggle from '$lib/components/Toggle.svelte'
@@ -8,7 +8,7 @@
} from '../../store/controllers/storeApi'
import { afterUpdate, onMount, getContext } from 'svelte'
import GraphView from './GraphView.svelte'
import { sanitizeCanvasOptions, sanitizeUserNodesAndEdges } from '../controllers/middleware'
import { sanitizeUserNodesAndEdges } from '../controllers/middleware'
import { SVELVET_CONTEXT_KEY, type SvelvetSettingsContext } from '../models'
const settings = getContext<SvelvetSettingsContext | undefined>(SVELVET_CONTEXT_KEY)
@@ -24,7 +24,6 @@
export let snapTo: number = 30
export let nodeCreate: boolean = false
export let boundary = false
export let collapsible = false
export let locked: boolean = false // if true, node movement is disabled
export let editable: boolean = false
export let highlightEdges: boolean = true
@@ -58,13 +57,10 @@
store.options.set(optionsObj) //
store.nodeCreate.set(nodeCreate)
store.boundary.set(boundary)
store.collapsibleOption.set(collapsible)
store.lockedOption.set(locked)
store.editableOption.set(editable)
store.highlightEdgesOption.set(highlightEdges)
// make sure that all canvas options are compatible
sanitizeCanvasOptions(store)
// set node/edge related stores
populateSvelvetStoreFromUserInput(canvasId, userNodes, userEdges)
error = ''
@@ -92,13 +88,10 @@
store.options.set(optionsObj) //
store.nodeCreate.set(nodeCreate)
store.boundary.set(boundary)
store.collapsibleOption.set(collapsible)
store.lockedOption.set(locked)
store.editableOption.set(editable)
store.highlightEdgesOption.set(highlightEdges)
// make sure that all canvas options are compatible
sanitizeCanvasOptions(store)
// set node/edge related stores
populateSvelvetStoreFromUserInput(canvasId, userNodes, userEdges)
error = ''
@@ -1,4 +1,4 @@
import { findStore } from '../../store/controllers/storeApi'
import { findStore } from '../../store/models/store'
import type { UserEdgeType } from '../../types/types'
import type { EdgeType } from '../../store/types/types'
@@ -1,5 +1,5 @@
<script lang="ts">
import { findStore } from '../../../store/controllers/storeApi'
import { findStore } from '../../../store/models/store'
import { getEdgeById } from '../../../edges/controllers/util'
import EdgeText from '../Edges/EdgeText.svelte'
import { get } from 'svelte/store'
@@ -3,7 +3,7 @@
const Position = { Left: 'left', Right: 'right', Top: 'top', Bottom: 'bottom' }
import { findStore } from '../../../store/controllers/storeApi'
import { findStore } from '../../../store/models/store'
import { getAnchorFromEdge } from '../../../edges/controllers/util'
function calculateControlOffset(distance, curvature) {
@@ -1,176 +1,157 @@
<script>
import BaseEdge from './BaseEdge.svelte';
import { getCenter } from './utils';
import BaseEdge from './BaseEdge.svelte'
import { getCenter } from './utils'
const Position = {};
Position['Left'] = 'left';
Position['Right'] = 'right';
Position['Top'] = 'top';
Position['Bottom'] = 'bottom';
// These are some helper methods for drawing the round corners
// The name indicates the direction of the path. "bottomLeftCorner" goes
// from bottom to the left and "leftBottomCorner" goes from left to the bottom.
// We have to consider the direction of the paths because of the animated lines.
const bottomLeftCorner = (x, y, size) =>
`L ${x},${y - size}Q ${x},${y} ${x + size},${y}`;
const leftBottomCorner = (x, y, size) =>
`L ${x + size},${y}Q ${x},${y} ${x},${y - size}`;
const bottomRightCorner = (x, y, size) =>
`L ${x},${y - size}Q ${x},${y} ${x - size},${y}`;
const rightBottomCorner = (x, y, size) =>
`L ${x - size},${y}Q ${x},${y} ${x},${y - size}`;
const leftTopCorner = (x, y, size) =>
`L ${x + size},${y}Q ${x},${y} ${x},${y + size}`;
const topLeftCorner = (x, y, size) =>
`L ${x},${y + size}Q ${x},${y} ${x + size},${y}`;
const topRightCorner = (x, y, size) =>
`L ${x},${y + size}Q ${x},${y} ${x - size},${y}`;
const rightTopCorner = (x, y, size) =>
`L ${x - size},${y}Q ${x},${y} ${x},${y + size}`;
// returns string to pass into edge 'path' svg d attribute (where to be drawn)
export function getSmoothStepPath({
sourceX,
sourceY,
sourcePosition = Position.Bottom,
targetX,
targetY,
targetPosition = Position.Top,
borderRadius = 5,
centerX,
centerY,
}) {
const [_centerX, _centerY, offsetX, offsetY] = getCenter({
sourceX,
sourceY,
targetX,
targetY,
});
const cornerWidth = Math.min(borderRadius, Math.abs(targetX - sourceX));
const cornerHeight = Math.min(borderRadius, Math.abs(targetY - sourceY));
const cornerSize = Math.min(cornerWidth, cornerHeight, offsetX, offsetY);
const leftAndRight = [Position.Left, Position.Right];
const cX = typeof centerX !== 'undefined' ? centerX : _centerX;
const cY = typeof centerY !== 'undefined' ? centerY : _centerY;
let firstCornerPath = null;
let secondCornerPath = null;
// for non-mixed edge top/bottom
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? bottomLeftCorner(sourceX, cY, cornerSize)
: topLeftCorner(sourceX, cY, cornerSize);
secondCornerPath =
sourceY <= targetY
? rightTopCorner(targetX, cY, cornerSize)
: rightBottomCorner(targetX, cY, cornerSize);
} else {
firstCornerPath =
sourceY < targetY
? bottomRightCorner(sourceX, cY, cornerSize)
: topRightCorner(sourceX, cY, cornerSize);
secondCornerPath =
sourceY < targetY
? leftTopCorner(targetX, cY, cornerSize)
: leftBottomCorner(targetX, cY, cornerSize);
}
// for non-mixed edge left/right
if (
leftAndRight.includes(sourcePosition) &&
leftAndRight.includes(targetPosition)
) {
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? rightTopCorner(cX, sourceY, cornerSize)
: rightBottomCorner(cX, sourceY, cornerSize);
secondCornerPath =
sourceY <= targetY
? bottomLeftCorner(cX, targetY, cornerSize)
: topLeftCorner(cX, targetY, cornerSize);
} else if (
(sourcePosition === Position.Right &&
targetPosition === Position.Left) ||
(sourcePosition === Position.Left &&
targetPosition === Position.Right) ||
(sourcePosition === Position.Left && targetPosition === Position.Left)
) {
// and sourceX > targetX
firstCornerPath =
sourceY <= targetY
? leftTopCorner(cX, sourceY, cornerSize)
: leftBottomCorner(cX, sourceY, cornerSize);
secondCornerPath =
sourceY <= targetY
? bottomRightCorner(cX, targetY, cornerSize)
: topRightCorner(cX, targetY, cornerSize);
}
// for mixed edges (top/bottom to left/right) OR (left/right to top/bottom)
} else if (
leftAndRight.includes(sourcePosition) &&
!leftAndRight.includes(targetPosition)
) {
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? rightTopCorner(targetX, sourceY, cornerSize)
: rightBottomCorner(targetX, sourceY, cornerSize);
} else {
firstCornerPath =
sourceY <= targetY
? leftTopCorner(targetX, sourceY, cornerSize)
: leftBottomCorner(targetX, sourceY, cornerSize);
}
secondCornerPath = '';
} else if (
!leftAndRight.includes(sourcePosition) &&
leftAndRight.includes(targetPosition)
) {
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? bottomLeftCorner(sourceX, targetY, cornerSize)
: topLeftCorner(sourceX, targetY, cornerSize);
} else {
firstCornerPath =
sourceY <= targetY
? bottomRightCorner(sourceX, targetY, cornerSize)
: topRightCorner(sourceX, targetY, cornerSize);
}
secondCornerPath = '';
}
return `M ${sourceX},${sourceY}${firstCornerPath}${secondCornerPath}L ${targetX},${targetY}`;
}
export let edge;
export let borderRadius = 5;
export let canvasId;
const Position = {}
Position['Left'] = 'left'
Position['Right'] = 'right'
Position['Top'] = 'top'
Position['Bottom'] = 'bottom'
// These are some helper methods for drawing the round corners
// The name indicates the direction of the path. "bottomLeftCorner" goes
// from bottom to the left and "leftBottomCorner" goes from left to the bottom.
// We have to consider the direction of the paths because of the animated lines.
const bottomLeftCorner = (x, y, size) => `L ${x},${y - size}Q ${x},${y} ${x + size},${y}`
const leftBottomCorner = (x, y, size) => `L ${x + size},${y}Q ${x},${y} ${x},${y - size}`
const bottomRightCorner = (x, y, size) => `L ${x},${y - size}Q ${x},${y} ${x - size},${y}`
const rightBottomCorner = (x, y, size) => `L ${x - size},${y}Q ${x},${y} ${x},${y - size}`
const leftTopCorner = (x, y, size) => `L ${x + size},${y}Q ${x},${y} ${x},${y + size}`
const topLeftCorner = (x, y, size) => `L ${x},${y + size}Q ${x},${y} ${x + size},${y}`
const topRightCorner = (x, y, size) => `L ${x},${y + size}Q ${x},${y} ${x - size},${y}`
const rightTopCorner = (x, y, size) => `L ${x - size},${y}Q ${x},${y} ${x},${y + size}`
// returns string to pass into edge 'path' svg d attribute (where to be drawn)
export function getSmoothStepPath({
sourceX,
sourceY,
sourcePosition = Position.Bottom,
targetX,
targetY,
targetPosition = Position.Top,
borderRadius = 5,
centerX,
centerY
}) {
const [_centerX, _centerY, offsetX, offsetY] = getCenter({
sourceX,
sourceY,
targetX,
targetY
})
const cornerWidth = Math.min(borderRadius, Math.abs(targetX - sourceX))
const cornerHeight = Math.min(borderRadius, Math.abs(targetY - sourceY))
const cornerSize = Math.min(cornerWidth, cornerHeight, offsetX, offsetY)
const leftAndRight = [Position.Left, Position.Right]
const cX = typeof centerX !== 'undefined' ? centerX : _centerX
const cY = typeof centerY !== 'undefined' ? centerY : _centerY
let firstCornerPath = null
let secondCornerPath = null
// for non-mixed edge top/bottom
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? bottomLeftCorner(sourceX, cY, cornerSize)
: topLeftCorner(sourceX, cY, cornerSize)
secondCornerPath =
sourceY <= targetY
? rightTopCorner(targetX, cY, cornerSize)
: rightBottomCorner(targetX, cY, cornerSize)
} else {
firstCornerPath =
sourceY < targetY
? bottomRightCorner(sourceX, cY, cornerSize)
: topRightCorner(sourceX, cY, cornerSize)
secondCornerPath =
sourceY < targetY
? leftTopCorner(targetX, cY, cornerSize)
: leftBottomCorner(targetX, cY, cornerSize)
}
// for non-mixed edge left/right
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? rightTopCorner(cX, sourceY, cornerSize)
: rightBottomCorner(cX, sourceY, cornerSize)
secondCornerPath =
sourceY <= targetY
? bottomLeftCorner(cX, targetY, cornerSize)
: topLeftCorner(cX, targetY, cornerSize)
} else if (
(sourcePosition === Position.Right && targetPosition === Position.Left) ||
(sourcePosition === Position.Left && targetPosition === Position.Right) ||
(sourcePosition === Position.Left && targetPosition === Position.Left)
) {
// and sourceX > targetX
firstCornerPath =
sourceY <= targetY
? leftTopCorner(cX, sourceY, cornerSize)
: leftBottomCorner(cX, sourceY, cornerSize)
secondCornerPath =
sourceY <= targetY
? bottomRightCorner(cX, targetY, cornerSize)
: topRightCorner(cX, targetY, cornerSize)
}
// for mixed edges (top/bottom to left/right) OR (left/right to top/bottom)
} else if (leftAndRight.includes(sourcePosition) && !leftAndRight.includes(targetPosition)) {
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? rightTopCorner(targetX, sourceY, cornerSize)
: rightBottomCorner(targetX, sourceY, cornerSize)
} else {
firstCornerPath =
sourceY <= targetY
? leftTopCorner(targetX, sourceY, cornerSize)
: leftBottomCorner(targetX, sourceY, cornerSize)
}
secondCornerPath = ''
} else if (!leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
if (sourceX <= targetX) {
firstCornerPath =
sourceY <= targetY
? bottomLeftCorner(sourceX, targetY, cornerSize)
: topLeftCorner(sourceX, targetY, cornerSize)
} else {
firstCornerPath =
sourceY <= targetY
? bottomRightCorner(sourceX, targetY, cornerSize)
: topRightCorner(sourceX, targetY, cornerSize)
}
secondCornerPath = ''
}
return `M ${sourceX},${sourceY}${firstCornerPath}${secondCornerPath}L ${targetX},${targetY}`
}
export let edge
export let borderRadius = 5
export let canvasId
import { findStore } from '../../../store/controllers/storeApi';
import { getAnchorFromEdge } from '../../../edges/controllers/util';
import { findStore } from '../../../store/models/store'
import { getAnchorFromEdge } from '../../../edges/controllers/util'
let params;
$: {
const store = findStore(canvasId);
const sourceAnchor = getAnchorFromEdge(store, edge.id, 'source');
const targetAnchor = getAnchorFromEdge(store, edge.id, 'target');
const mapAngle = { 0: 'right', 90: 'top', 180: 'left', 270: 'bottom' };
params = {
sourceX: edge.sourceX,
sourceY: edge.sourceY,
targetX: edge.targetX,
targetY: edge.targetY,
sourcePosition: mapAngle[sourceAnchor.angle],
targetPosition: mapAngle[targetAnchor.angle],
borderRadius: borderRadius,
};
}
$: [centerX, centerY] = getCenter(params);
$: path = getSmoothStepPath(params);
$: baseEdgeProps = {
...edge,
path: path,
centerX: centerX,
centerY: centerY,
};
let params
$: {
const store = findStore(canvasId)
const sourceAnchor = getAnchorFromEdge(store, edge.id, 'source')
const targetAnchor = getAnchorFromEdge(store, edge.id, 'target')
const mapAngle = { 0: 'right', 90: 'top', 180: 'left', 270: 'bottom' }
params = {
sourceX: edge.sourceX,
sourceY: edge.sourceY,
targetX: edge.targetX,
targetY: edge.targetY,
sourcePosition: mapAngle[sourceAnchor.angle],
targetPosition: mapAngle[targetAnchor.angle],
borderRadius: borderRadius
}
}
$: [centerX, centerY] = getCenter(params)
$: path = getSmoothStepPath(params)
$: baseEdgeProps = {
...edge,
path: path,
centerX: centerX,
centerY: centerY
}
</script>
<BaseEdge {baseEdgeProps} {canvasId} />
@@ -1,7 +1,7 @@
<script lang="ts">
import { afterUpdate } from 'svelte'
import { findStore } from '../../store/controllers/storeApi'
import { findStore } from '../../store/models/store'
import type { NodeType } from '../../store/types/types'
import { forceCssHeightAndWidth } from '../../customCss/controllers/getCss'
@@ -30,22 +30,13 @@ populateSvelvetStoreFromUserInput(canvasId, nodes, edges)
- edges: same as nodes, this is an array of objects containing edge info THAT IS DIFFERENT FROM THE EDGE CLASS.
- Returns: store
*/
import { stores } from '../models/store'
import { findStore, stores } from '../models/store'
import { writable } from 'svelte/store'
import type { StoreType } from '../types/types'
import type { UserNodeType, UserEdgeType } from '../../types/types'
import { populateAnchorsStore, populateNodesStore, populateEdgesStore } from './util'
/**
* findStore is going to return the target Svelvet store with the canvasId provided as argument.
* There can be multiple Svelvet canvases on the same page, and each has their own store with a unique canvasId.
* @param canvasId The canvasId of a Svelvet component
* @returns The store of a Svelvet component that matches the canvasId
*/
export function findStore(canvasId: string): StoreType {
return stores[canvasId]
}
/**
* createStoreEmpty will initialize a new Svelvet store with a unique canvasId.
@@ -79,8 +70,6 @@ export function createStoreEmpty(canvasId: string): StoreType {
nodeCreate: writable(false), // this option sets whether the "nodeEdit" feature is enabled
boundary: writable(false),
edgeEditModal: writable(null), // this is used for edgeEditModal feature. When an edge is right clicked, store.edgeEditModal is set to the edgeId string. This causes a modal to be rendered
collapsibleStore: writable([]), // this is used for the collaspsible node feature. If the feature is enabled, store.collapsible will be populated with Collapsible objects which will track whether the node should be displayed or not
collapsibleOption: writable(false),
lockedOption: writable(false),
editableOption: writable(false), // true if you want nodes/edges to be editable. See feature editEdges
d3ZoomParameters: writable({}), // this stores d3 parameters x, y, and zoom. This isn't used for anything other than giving users a way to access d3 zoom parameters if they want to build on top of Svelvet
@@ -1,4 +1,4 @@
import { findStore } from './storeApi';
import { findStore } from '../models/store';
import { get } from 'svelte/store';
export function getD3PositionX(canvasId) {
const store = findStore(canvasId);
@@ -1,5 +1,9 @@
import type { StoreType } from '../types/types';
export function findStore(canvasId: string): StoreType {
return stores[canvasId]
}
/**
`store` is a dictionary of Svelvet stores.
* The reason why we have multiple Svelvet stores is to handle multiple canvases on the same page.
@@ -1,4 +1,3 @@
import type { CollapsibleType } from '../../collapsible/types/types'
import type { Writable } from 'svelte/store'
import type { AnchorType } from '../../edges/types/types'
@@ -35,8 +34,6 @@ export interface StoreType {
nodeCreate: Writable<boolean> // this option sets whether the "nodeEdit" feature is enabled
boundary: Writable<boolean | PositionType>
edgeEditModal: Writable<null | string> // this options is used to place the edgeEdit modal when an edge is right-clicked. null is no modal, positionType if modal should be placed at position defined by postionType.x, positionType.y
collapsibleStore: Writable<CollapsibleType[]>
collapsibleOption: Writable<boolean>
lockedOption: Writable<boolean>
editableOption: Writable<boolean>
d3ZoomParameters: Writable<{
@@ -40,7 +40,7 @@ export interface UserEdgeType {
offset?: number
}
import { findStore } from '../store/controllers/storeApi'
import { findStore } from '../store/models/store'
import { get } from 'svelte/store'
export function getD3PositionX(canvasId: string) {
const store = findStore(canvasId)