Add empty state node to role editor
This commit is contained in:
parent
303f400139
commit
a342aa3c31
|
@ -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">
|
||||
|
|
|
@ -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>
|
|
@ -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 }}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue