Add empty state node to role editor

This commit is contained in:
Andrew Kingston 2024-10-03 13:08:47 +01:00
parent 303f400139
commit a342aa3c31
No known key found for this signature in database
4 changed files with 75 additions and 12 deletions

View File

@ -7,10 +7,13 @@
const { nodes, edges, createRole } = getContext("flow")
const flow = useSvelteFlow()
const autoFit = () =>
flow.fitView({ maxZoom: MaxAutoZoom, duration: ZoomDuration })
const addRole = async () => {
await createRole()
doAutoLayout()
autoFit()
}
const doAutoLayout = () => {
@ -33,13 +36,7 @@
on:click={() => flow.zoomOut({ duration: ZoomDuration })}
/>
</div>
<Button
secondary
on:click={() =>
flow.fitView({ maxZoom: MaxAutoZoom, duration: ZoomDuration })}
>
Zoom to fit
</Button>
<Button secondary on:click={autoFit}>Zoom to fit</Button>
<Button secondary on:click={doAutoLayout}>Auto layout</Button>
</div>
<div class="control bottom-right">

View File

@ -0,0 +1,24 @@
<script>
import { NodeWidth, NodeHeight } from "./constants"
</script>
<div class="node" style={`--width:${NodeWidth}px; --height:${NodeHeight}px;`}>
Add custom roles for more granular control over permissions
</div>
<style>
.node {
border-radius: 4px;
width: var(--width);
height: var(--height);
display: grid;
place-items: center;
font-size: 16px;
text-align: center;
color: var(--spectrum-global-color-gray-800);
text-shadow: 4px 4px 10px var(--background-color),
4px -4px 10px var(--background-color),
-4px 4px 10px var(--background-color),
-4px -4px 10px var(--background-color);
}
</style>

View File

@ -10,6 +10,7 @@
} from "@xyflow/svelte"
import "@xyflow/svelte/dist/style.css"
import RoleNode from "./RoleNode.svelte"
import EmptyStateNode from "./EmptyStateNode.svelte"
import RoleEdge from "./RoleEdge.svelte"
import BracketEdge from "./BracketEdge.svelte"
import {
@ -18,6 +19,7 @@
getBasicPosition,
rolesToLayout,
nodeToRole,
getBounds,
} from "./utils"
import { setContext, tick } from "svelte"
import Controls from "./Controls.svelte"
@ -38,9 +40,7 @@
})
// Derive the bounds of all custom role nodes
const bounds = derivedMemo(nodes, $nodes => {
return getNodesBounds($nodes.filter(node => node.data.custom))
})
const bounds = derivedMemo(nodes, getBounds)
$: handleExternalRoleChanges($roles)
$: updateBuiltins($bounds)
@ -159,7 +159,7 @@
{nodes}
{edges}
snapGrid={[GridResolution, GridResolution]}
nodeTypes={{ role: RoleNode }}
nodeTypes={{ role: RoleNode, empty: EmptyStateNode }}
edgeTypes={{ role: RoleEdge, bracket: BracketEdge }}
proOptions={{ hideAttribution: true }}
fitViewOptions={{ maxZoom: MaxAutoZoom }}

View File

@ -11,6 +11,22 @@ import { Roles } from "constants/backend"
import { roles } from "stores/builder"
import { get } from "svelte/store"
// Calculates the bounds of all custom nodes
export const getBounds = nodes => {
const customNodes = nodes.filter(node => node.data.custom)
// Empty state bounds which line up with bounds after adding first node
if (!customNodes.length) {
return {
x: 0,
y: 6.5 * GridResolution,
width: 12 * GridResolution,
height: 10 * GridResolution,
}
}
return getNodesBounds(customNodes)
}
// Gets the position of the basic role
export const getBasicPosition = bounds => ({
x: bounds.x - NodeHSpacing - NodeWidth,
@ -33,6 +49,10 @@ const preProcessLayout = ({ nodes, edges }) => {
if (ignoredRoles.includes(node.id)) {
return false
}
// Filter out empty state
if (node.id === "empty") {
return false
}
return true
}),
edges: edges.filter(edge => {
@ -82,7 +102,7 @@ export const dagreLayout = ({ nodes, edges }) => {
const postProcessLayout = ({ nodes, edges }) => {
// Reposition basic and admin to bound the custom nodes
const bounds = getNodesBounds(nodes.filter(node => node.data.custom))
const bounds = getBounds(nodes)
nodes.find(x => x.id === Roles.BASIC).position = getBasicPosition(bounds)
nodes.find(x => x.id === Roles.ADMIN).position = getAdminPosition(bounds)
@ -99,6 +119,28 @@ const postProcessLayout = ({ nodes, edges }) => {
target: Roles.BASIC,
type: "bracket",
})
// Add empty state node if required
if (!nodes.filter(node => node.data.custom).length) {
nodes.push({
id: "empty",
type: "empty",
position: {
x: bounds.x + bounds.width / 2 - NodeWidth / 2,
y: bounds.y + bounds.height / 2 - NodeHeight / 2,
},
data: {},
measured: {
width: NodeWidth,
height: NodeHeight,
},
deletable: false,
draggable: false,
connectable: false,
selectable: false,
})
}
return { nodes, edges }
}