Update handling of basic and admin edges
This commit is contained in:
parent
2099ee8baf
commit
354b5041c7
|
@ -20,7 +20,7 @@
|
||||||
export let target
|
export let target
|
||||||
|
|
||||||
const flow = useSvelteFlow()
|
const flow = useSvelteFlow()
|
||||||
const { updateRole, selectedNodes } = getContext("flow")
|
const { deleteEdge, selectedNodes } = getContext("flow")
|
||||||
|
|
||||||
let iconHovered = false
|
let iconHovered = false
|
||||||
let edgeHovered = false
|
let edgeHovered = false
|
||||||
|
@ -53,13 +53,6 @@
|
||||||
return classes
|
return classes
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteEdge = async () => {
|
|
||||||
flow.deleteElements({
|
|
||||||
edges: [{ id }],
|
|
||||||
})
|
|
||||||
await updateRole(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onEdgeMouseOver = () => {
|
const onEdgeMouseOver = () => {
|
||||||
edgeHovered = true
|
edgeHovered = true
|
||||||
}
|
}
|
||||||
|
@ -92,7 +85,7 @@
|
||||||
style:transform="translate(-50%, -50%) translate({labelX}px,{labelY}px)"
|
style:transform="translate(-50%, -50%) translate({labelX}px,{labelY}px)"
|
||||||
class="edge-label nodrag nopan"
|
class="edge-label nodrag nopan"
|
||||||
class:active
|
class:active
|
||||||
on:click={deleteEdge}
|
on:click={() => deleteEdge(id)}
|
||||||
on:mouseover={() => (iconHovered = true)}
|
on:mouseover={() => (iconHovered = true)}
|
||||||
on:mouseout={() => (iconHovered = false)}
|
on:mouseout={() => (iconHovered = false)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -31,26 +31,33 @@
|
||||||
$: handleExternalRoleChanges($roles)
|
$: handleExternalRoleChanges($roles)
|
||||||
|
|
||||||
// Converts a role doc into a node structure
|
// Converts a role doc into a node structure
|
||||||
const roleToNode = role => ({
|
const roleToNode = role => {
|
||||||
id: role._id,
|
const custom = !role._id.match(/[A-Z]+/)
|
||||||
sourcePosition: Position.Right,
|
|
||||||
targetPosition: Position.Left,
|
return {
|
||||||
type: "role",
|
id: role._id,
|
||||||
position: { x: 0, y: 0 },
|
sourcePosition: Position.Right,
|
||||||
data: {
|
targetPosition: Position.Left,
|
||||||
...role.uiMetadata,
|
type: "role",
|
||||||
custom: !role._id.match(/[A-Z]+/),
|
position: { x: 0, y: 0 },
|
||||||
},
|
data: {
|
||||||
})
|
...role.uiMetadata,
|
||||||
|
custom,
|
||||||
|
},
|
||||||
|
deletable: custom,
|
||||||
|
draggable: custom,
|
||||||
|
connectable: custom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Converts a node structure back into a role doc
|
// Converts a node structure back into a role doc
|
||||||
const nodeToRole = node => {
|
const nodeToRole = node => {
|
||||||
const role = $roles.find(x => x._id === node.id)
|
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
|
// TODO save inherits array
|
||||||
return {
|
return {
|
||||||
...role,
|
...role,
|
||||||
// inherits,
|
inherits,
|
||||||
uiMetadata: {
|
uiMetadata: {
|
||||||
displayName: node.data.displayName,
|
displayName: node.data.displayName,
|
||||||
color: node.data.color,
|
color: node.data.color,
|
||||||
|
@ -63,7 +70,11 @@
|
||||||
const rolesToLayout = roles => {
|
const rolesToLayout = roles => {
|
||||||
let nodes = []
|
let nodes = []
|
||||||
let edges = []
|
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
|
// Add node for this role
|
||||||
nodes.push(roleToNode(role))
|
nodes.push(roleToNode(role))
|
||||||
|
|
||||||
|
@ -138,7 +149,6 @@
|
||||||
description: "Custom role",
|
description: "Custom role",
|
||||||
},
|
},
|
||||||
permissionId: "write",
|
permissionId: "write",
|
||||||
inherits: Roles.BASIC,
|
|
||||||
})
|
})
|
||||||
await tick()
|
await tick()
|
||||||
selectNode(roleId)
|
selectNode(roleId)
|
||||||
|
@ -148,7 +158,7 @@
|
||||||
const updateRole = async (roleId, metadata) => {
|
const updateRole = async (roleId, metadata) => {
|
||||||
// Don't update builtins
|
// Don't update builtins
|
||||||
const node = $nodes.find(x => x.id === roleId)
|
const node = $nodes.find(x => x.id === roleId)
|
||||||
if (!node || !node.data.custom) {
|
if (!node) {
|
||||||
return
|
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
|
// Saves a new connection
|
||||||
const onConnect = async connection => {
|
const onConnect = async connection => {
|
||||||
await updateRole(connection.target)
|
await updateRole(connection.target)
|
||||||
|
@ -183,6 +202,7 @@
|
||||||
createRole,
|
createRole,
|
||||||
updateRole,
|
updateRole,
|
||||||
deleteRole,
|
deleteRole,
|
||||||
|
deleteEdge,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
export let data
|
export let data
|
||||||
export let id
|
export let id
|
||||||
export let selected
|
export let selected
|
||||||
|
export let isConnectable
|
||||||
|
|
||||||
const { dragging, updateRole, deleteRole } = getContext("flow")
|
const { dragging, updateRole, deleteRole } = getContext("flow")
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@
|
||||||
$: nameError = validateName(tempDisplayName, $roles)
|
$: nameError = validateName(tempDisplayName, $roles)
|
||||||
$: descriptionError = validateDescription(tempDescription)
|
$: descriptionError = validateDescription(tempDescription)
|
||||||
$: invalid = nameError || descriptionError
|
$: invalid = nameError || descriptionError
|
||||||
$: targetClasses = `target${$dragging ? "" : " hidden"}`
|
$: targetClasses = `target${!$dragging ? " hidden" : ""}`
|
||||||
|
|
||||||
const validateName = (name, roles) => {
|
const validateName = (name, roles) => {
|
||||||
if (!name?.length) {
|
if (!name?.length) {
|
||||||
|
@ -91,15 +92,13 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if id !== Roles.BASIC}
|
{#if isConnectable}
|
||||||
<Handle
|
<Handle
|
||||||
type="target"
|
type="target"
|
||||||
position={Position.Left}
|
position={Position.Left}
|
||||||
class={targetClasses}
|
class={targetClasses}
|
||||||
isConnectable={$dragging}
|
isConnectable={$dragging}
|
||||||
/>
|
/>
|
||||||
{/if}
|
|
||||||
{#if id !== Roles.ADMIN}
|
|
||||||
<Handle type="source" position={Position.Right} />
|
<Handle type="source" position={Position.Right} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const dagreLayout = ({ nodes, edges }) => {
|
||||||
dagreGraph.setDefaultEdgeLabel(() => ({}))
|
dagreGraph.setDefaultEdgeLabel(() => ({}))
|
||||||
dagreGraph.setGraph({
|
dagreGraph.setGraph({
|
||||||
rankdir: "LR",
|
rankdir: "LR",
|
||||||
ranksep: GridResolution * 8,
|
ranksep: GridResolution * 4,
|
||||||
nodesep: GridResolution * 2,
|
nodesep: GridResolution * 2,
|
||||||
})
|
})
|
||||||
nodes.forEach(node => {
|
nodes.forEach(node => {
|
||||||
|
@ -19,6 +19,26 @@ export const dagreLayout = ({ nodes, edges }) => {
|
||||||
edges.forEach(edge => {
|
edges.forEach(edge => {
|
||||||
dagreGraph.setEdge(edge.source, edge.target)
|
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)
|
dagre.layout(dagreGraph)
|
||||||
nodes.forEach(node => {
|
nodes.forEach(node => {
|
||||||
const pos = dagreGraph.node(node.id)
|
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
|
// Adds additional edges as needed to the flow structure to ensure compatibility with BB role logic
|
||||||
const sanitiseLayout = ({ nodes, edges }) => {
|
const sanitiseLayout = ({ nodes, edges }) => {
|
||||||
let additions = []
|
// Remove any inheritance of basic and admin since this is implied
|
||||||
|
edges = edges.filter(
|
||||||
for (let node of nodes) {
|
edge => edge.source !== Roles.BASIC && edge.target !== Roles.ADMIN
|
||||||
// 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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nodes,
|
nodes,
|
||||||
edges: [...edges, ...additions],
|
edges,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue