diff --git a/packages/builder/package.json b/packages/builder/package.json index f44c2ea549..36ec099b56 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -59,12 +59,14 @@ "@codemirror/state": "^6.2.0", "@codemirror/theme-one-dark": "^6.1.2", "@codemirror/view": "^6.11.2", + "@dagrejs/dagre": "1.1.4", "@fontsource/source-sans-pro": "^5.0.3", "@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/free-brands-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", + "@xyflow/svelte": "^0.1.18", "@zerodevx/svelte-json-view": "^1.0.7", "codemirror": "^5.65.16", "dayjs": "^1.10.8", diff --git a/packages/builder/src/components/backend/DataTable/buttons/ManageAccessButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/ManageAccessButton.svelte index 7316fc79a9..5c8ccddf59 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/ManageAccessButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/ManageAccessButton.svelte @@ -15,7 +15,6 @@ import { capitalise } from "helpers" import InfoDisplay from "pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/InfoDisplay.svelte" import { Roles } from "constants/backend" - import RoleEditor from "./RoleEditor.svelte" export let resourceId @@ -197,10 +196,6 @@ on:show={() => (showPopover = false)} on:hide={() => (showPopover = true)} /> - (showPopover = false)} - on:drawerHide={() => (showPopover = true)} - /> diff --git a/packages/builder/src/components/backend/DataTable/buttons/RoleEditor.svelte b/packages/builder/src/components/backend/DataTable/buttons/RoleEditor.svelte deleted file mode 100644 index 6b7e79eabc..0000000000 --- a/packages/builder/src/components/backend/DataTable/buttons/RoleEditor.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - asdasdasd - diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte index a6078e38fb..621b8073a6 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte @@ -76,6 +76,12 @@ selectedBy={$userSelectedResourceMap[TableNames.USERS]} /> {/if} + $goto("./roles")} + /> {#each enrichedDataSources.filter(ds => ds.show) as datasource} + import { Button, Helpers, ActionButton } from "@budibase/bbui" + import { useSvelteFlow, Position } from "@xyflow/svelte" + import { getContext } from "svelte" + import { dagreLayout } from "./layout" + + const { nodes, edges } = getContext("flow") + const flow = useSvelteFlow() + + const addRole = () => { + nodes.update(state => [ + ...state, + { + id: Helpers.uuid(), + sourcePosition: Position.Right, + targetPosition: Position.Left, + type: "role", + data: { + label: "New role", + description: "Custom role", + custom: true, + }, + position: { x: 0, y: 0 }, + }, + ]) + autoLayout() + } + + const autoLayout = () => { + const layout = dagreLayout({ nodes: $nodes, edges: $edges }) + nodes.set(layout.nodes) + edges.set(layout.edges) + flow.fitView({ maxZoom: 1 }) + } + + +
+
+ + +
+ + +
+
+ +
+ + diff --git a/packages/builder/src/components/backend/RoleEditor/RoleEditor.svelte b/packages/builder/src/components/backend/RoleEditor/RoleEditor.svelte new file mode 100644 index 0000000000..0bc4bd6aef --- /dev/null +++ b/packages/builder/src/components/backend/RoleEditor/RoleEditor.svelte @@ -0,0 +1,97 @@ + + +
+
+ Manage roles +
+
Roles inherit permissions from each other.
+
+
+ console.log("on node click", event.detail.node)} + > + + + +
+ + diff --git a/packages/builder/src/components/backend/RoleEditor/RoleNode.svelte b/packages/builder/src/components/backend/RoleEditor/RoleNode.svelte new file mode 100644 index 0000000000..6261ac6dec --- /dev/null +++ b/packages/builder/src/components/backend/RoleEditor/RoleNode.svelte @@ -0,0 +1,120 @@ + + +
+
+
+
+
+ {label} +
+ {#if custom} +
+ + +
+ {/if} +
+ {#if description} +
+ {description} +
+ {/if} +
+ {#if id !== Roles.BASIC} + + {/if} + {#if id !== Roles.ADMIN} + + {/if} +
+ + diff --git a/packages/builder/src/components/backend/RoleEditor/constants.js b/packages/builder/src/components/backend/RoleEditor/constants.js new file mode 100644 index 0000000000..5c08561a23 --- /dev/null +++ b/packages/builder/src/components/backend/RoleEditor/constants.js @@ -0,0 +1,2 @@ +export const NodeWidth = 220 +export const NodeHeight = 66 diff --git a/packages/builder/src/components/backend/RoleEditor/layout.js b/packages/builder/src/components/backend/RoleEditor/layout.js new file mode 100644 index 0000000000..da24c0c4d0 --- /dev/null +++ b/packages/builder/src/components/backend/RoleEditor/layout.js @@ -0,0 +1,120 @@ +import dagre from "@dagrejs/dagre" +import { NodeWidth, NodeHeight } from "./constants" +import { Position } from "@xyflow/svelte" +import { roles } from "stores/builder" +import { Roles } from "constants/backend" +import { get } from "svelte/store" + +export const initialLayout = () => { + const builtins = [Roles.BASIC, Roles.POWER, Roles.ADMIN] + const descriptions = { + [Roles.BASIC]: "Basic user", + [Roles.POWER]: "Power user", + [Roles.ADMIN]: "Can do everything", + } + const $roles = get(roles) + const nodes = builtins + .map(roleId => { + return { + id: roleId, + sourcePosition: Position.Right, + targetPosition: Position.Left, + type: "role", + data: { + label: $roles.find(x => x._id === roleId)?.name, + description: descriptions[roleId], + }, + } + }) + .concat([ + { + id: "management", + sourcePosition: Position.Right, + targetPosition: Position.Left, + type: "role", + data: { + label: "Management", + description: "Custom role", + custom: true, + }, + }, + { + id: "approver", + sourcePosition: Position.Right, + targetPosition: Position.Left, + type: "role", + data: { + label: "Approver", + description: "Custom role", + custom: true, + }, + }, + { + id: "engineer", + sourcePosition: Position.Right, + targetPosition: Position.Left, + type: "role", + data: { + label: "Engineer", + description: "Custom role", + custom: true, + }, + }, + ]) + + let edges = [] + const link = (source, target) => { + edges.push({ + id: `${source}-${target}`, + source, + target, + animated: true, + // markerEnd: { + // type: MarkerType.ArrowClosed, + // width: 16, + // height: 16, + // }, + }) + } + + link(Roles.BASIC, "engineer") + link(Roles.BASIC, "approver") + + link("engineer", Roles.POWER) + link("approver", "management") + + link(Roles.POWER, Roles.ADMIN) + link("management", Roles.ADMIN) + + return { + nodes, + edges, + } +} + +export const dagreLayout = ({ nodes, edges }) => { + const dagreGraph = new dagre.graphlib.Graph() + dagreGraph.setDefaultEdgeLabel(() => ({})) + dagreGraph.setGraph({ + rankdir: "LR", + ranksep: 100, + nodesep: 100, + }) + nodes.forEach(node => { + dagreGraph.setNode(node.id, { width: NodeWidth, height: NodeHeight }) + }) + edges.forEach(edge => { + dagreGraph.setEdge(edge.source, edge.target) + }) + dagre.layout(dagreGraph) + nodes.forEach(node => { + const nodeWithPosition = dagreGraph.node(node.id) + node.targetPosition = Position.Left + node.sourcePosition = Position.Right + node.position = { + x: nodeWithPosition.x - NodeWidth / 2, + y: nodeWithPosition.y - NodeHeight / 2, + } + }) + return { nodes, edges } +} diff --git a/packages/builder/src/pages/builder/app/[application]/data/roles.svelte b/packages/builder/src/pages/builder/app/[application]/data/roles.svelte new file mode 100644 index 0000000000..bea482d9d2 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/data/roles.svelte @@ -0,0 +1,5 @@ + + +