Update handling of basic and admin edges

This commit is contained in:
Andrew Kingston 2024-10-01 09:49:53 +01:00
parent 2099ee8baf
commit 354b5041c7
No known key found for this signature in database
4 changed files with 67 additions and 53 deletions

View File

@ -20,7 +20,7 @@
export let target
const flow = useSvelteFlow()
const { updateRole, selectedNodes } = getContext("flow")
const { deleteEdge, selectedNodes } = getContext("flow")
let iconHovered = false
let edgeHovered = false
@ -53,13 +53,6 @@
return classes
}
const deleteEdge = async () => {
flow.deleteElements({
edges: [{ id }],
})
await updateRole(target)
}
const onEdgeMouseOver = () => {
edgeHovered = true
}
@ -92,7 +85,7 @@
style:transform="translate(-50%, -50%) translate({labelX}px,{labelY}px)"
class="edge-label nodrag nopan"
class:active
on:click={deleteEdge}
on:click={() => deleteEdge(id)}
on:mouseover={() => (iconHovered = true)}
on:mouseout={() => (iconHovered = false)}
>

View File

@ -31,26 +31,33 @@
$: handleExternalRoleChanges($roles)
// Converts a role doc into a node structure
const roleToNode = role => ({
id: role._id,
sourcePosition: Position.Right,
targetPosition: Position.Left,
type: "role",
position: { x: 0, y: 0 },
data: {
...role.uiMetadata,
custom: !role._id.match(/[A-Z]+/),
},
})
const roleToNode = role => {
const custom = !role._id.match(/[A-Z]+/)
return {
id: role._id,
sourcePosition: Position.Right,
targetPosition: Position.Left,
type: "role",
position: { x: 0, y: 0 },
data: {
...role.uiMetadata,
custom,
},
deletable: custom,
draggable: custom,
connectable: custom,
}
}
// Converts a node structure back into a role doc
const nodeToRole = node => {
const role = $roles.find(x => x._id === node.id)
// const inherits = $edges.filter(x => x.target === node.id).map(x => x.source)
const inherits = $edges.filter(x => x.target === node.id).map(x => x.source)
// TODO save inherits array
return {
...role,
// inherits,
inherits,
uiMetadata: {
displayName: node.data.displayName,
color: node.data.color,
@ -63,7 +70,11 @@
const rolesToLayout = roles => {
let nodes = []
let edges = []
for (let role of roles.filter(role => role._id !== Roles.PUBLIC)) {
// Remove some builtins
const ignoredRoles = [Roles.PUBLIC, Roles.POWER]
roles = roles.filter(role => !ignoredRoles.includes(role._id))
for (let role of roles) {
// Add node for this role
nodes.push(roleToNode(role))
@ -138,7 +149,6 @@
description: "Custom role",
},
permissionId: "write",
inherits: Roles.BASIC,
})
await tick()
selectNode(roleId)
@ -148,7 +158,7 @@
const updateRole = async (roleId, metadata) => {
// Don't update builtins
const node = $nodes.find(x => x.id === roleId)
if (!node || !node.data.custom) {
if (!node) {
return
}
@ -170,6 +180,15 @@
}
}
const deleteEdge = async edgeId => {
const edge = $edges.find(x => x.id === edgeId)
if (!edge) {
return
}
edges.set($edges.filter(x => x.id !== edgeId))
await updateRole(edge.target)
}
// Saves a new connection
const onConnect = async connection => {
await updateRole(connection.target)
@ -183,6 +202,7 @@
createRole,
updateRole,
deleteRole,
deleteEdge,
})
</script>

View File

@ -17,6 +17,7 @@
export let data
export let id
export let selected
export let isConnectable
const { dragging, updateRole, deleteRole } = getContext("flow")
@ -30,7 +31,7 @@
$: nameError = validateName(tempDisplayName, $roles)
$: descriptionError = validateDescription(tempDescription)
$: invalid = nameError || descriptionError
$: targetClasses = `target${$dragging ? "" : " hidden"}`
$: targetClasses = `target${!$dragging ? " hidden" : ""}`
const validateName = (name, roles) => {
if (!name?.length) {
@ -91,15 +92,13 @@
</div>
{/if}
</div>
{#if id !== Roles.BASIC}
{#if isConnectable}
<Handle
type="target"
position={Position.Left}
class={targetClasses}
isConnectable={$dragging}
/>
{/if}
{#if id !== Roles.ADMIN}
<Handle type="source" position={Position.Right} />
{/if}
</div>

View File

@ -10,7 +10,7 @@ export const dagreLayout = ({ nodes, edges }) => {
dagreGraph.setDefaultEdgeLabel(() => ({}))
dagreGraph.setGraph({
rankdir: "LR",
ranksep: GridResolution * 8,
ranksep: GridResolution * 4,
nodesep: GridResolution * 2,
})
nodes.forEach(node => {
@ -19,6 +19,26 @@ export const dagreLayout = ({ nodes, edges }) => {
edges.forEach(edge => {
dagreGraph.setEdge(edge.source, edge.target)
})
// Add ephemeral edges for basic and admin so that we can position them properly
for (let node of nodes) {
if (
!edges.some(x => x.target === node.id) &&
node.id !== Roles.BASIC &&
node.id !== Roles.ADMIN
) {
dagreGraph.setEdge(Roles.BASIC, node.id)
}
if (
!edges.some(x => x.source === node.id) &&
node.id !== Roles.BASIC &&
node.id !== Roles.ADMIN
) {
dagreGraph.setEdge(node.id, Roles.ADMIN)
}
}
dagre.layout(dagreGraph)
nodes.forEach(node => {
const pos = dagreGraph.node(node.id)
@ -34,32 +54,14 @@ export const dagreLayout = ({ nodes, edges }) => {
// Adds additional edges as needed to the flow structure to ensure compatibility with BB role logic
const sanitiseLayout = ({ nodes, edges }) => {
let additions = []
for (let node of nodes) {
// If a node does not inherit anything, let it inherit basic
if (!edges.some(x => x.target === node.id) && node.id !== Roles.BASIC) {
additions.push({
id: Helpers.uuid(),
source: Roles.BASIC,
target: node.id,
animated: true,
})
}
// If a node is not inherited by anything, let it be inherited by admin
if (!edges.some(x => x.source === node.id) && node.id !== Roles.ADMIN) {
additions.push({
id: Helpers.uuid(),
source: node.id,
target: Roles.ADMIN,
})
}
}
// Remove any inheritance of basic and admin since this is implied
edges = edges.filter(
edge => edge.source !== Roles.BASIC && edge.target !== Roles.ADMIN
)
return {
nodes,
edges: [...edges, ...additions],
edges,
}
}