From 3d1c5111e99b8bc4f34a5481615016f85d021338 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 9 Jun 2022 14:28:02 +0100 Subject: [PATCH] Add role setting to navigation links to allow easily customising which roles see which links --- .../_components/NavigationLinksDrawer.svelte | 4 +- .../client/src/components/ClientApp.svelte | 43 +++++++++++-------- .../client/src/components/app/Layout.svelte | 19 ++++++-- .../context/DeviceBindingsProvider.svelte | 4 +- .../context/UserBindingsProvider.svelte | 8 +--- packages/client/src/sdk.js | 2 + packages/client/src/stores/index.js | 14 ++++++ 7 files changed, 63 insertions(+), 31 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte index 4d1823108c..5ffccc5800 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/navigation/_components/NavigationLinksDrawer.svelte @@ -11,6 +11,7 @@ import { dndzone } from "svelte-dnd-action" import { generate } from "shortid" import { store } from "builderStore" + import RoleSelect from "components/design/settings/controls/RoleSelect.svelte" export let links = [] @@ -75,6 +76,7 @@ placeholder="URL" options={urlOptions} /> + .container { width: 100%; - max-width: 600px; + max-width: 800px; margin: 0 auto; } .links { diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index e5cd2fb1d2..cce8de11d4 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -59,6 +59,7 @@ $screenStore.screens, $devToolsStore.role ) + permissionError = false routeStore.actions.navigate(route) } else { // No screens likely means the user has no permissions to view this app @@ -120,17 +121,24 @@ dir="ltr" class="spectrum spectrum--medium {$themeStore.theme}" > - {#if permissionError} -
- - {@html ErrorSVG} - You don't have permission to use this app - Ask your administrator to grant you access - -
- {:else if $screenStore.activeLayout} + - + {#if permissionError} +
+ {#if isDevPreview} + + {/if} +
+ + {@html ErrorSVG} + You don't have permission to use this app + Ask your administrator to grant you access + +
+
+ {:else if $screenStore.activeLayout} @@ -198,9 +206,9 @@ -
+ {/if}
- {/if} +
{/if} @@ -248,8 +256,11 @@ overflow: hidden; } + .error-wrapper { + width: 100%; + height: 100%; + } .error { - position: absolute; width: 100%; height: 100%; display: grid; @@ -258,23 +269,19 @@ text-align: center; padding: 20px; } - .error :global(svg) { fill: var(--spectrum-global-color-gray-500); width: 80px; height: 80px; } - .error :global(h1), .error :global(p) { color: var(--spectrum-global-color-gray-800); } - .error :global(p) { font-style: italic; margin-top: -0.5em; } - .error :global(h1) { font-weight: 400; } @@ -284,12 +291,10 @@ #clip-root.preview { padding: 2px; } - #clip-root.tablet-preview { width: calc(1024px + 6px); height: calc(768px + 6px); } - #clip-root.mobile-preview { width: calc(390px + 6px); height: calc(844px + 6px); diff --git a/packages/client/src/components/app/Layout.svelte b/packages/client/src/components/app/Layout.svelte index 71ecb7d263..58b2797162 100644 --- a/packages/client/src/components/app/Layout.svelte +++ b/packages/client/src/components/app/Layout.svelte @@ -2,10 +2,12 @@ import { getContext, setContext } from "svelte" import { writable } from "svelte/store" import { Heading, Icon } from "@budibase/bbui" - import { FieldTypes } from "../../constants" + import { FieldTypes } from "constants" import active from "svelte-spa-router/active" + import { RoleUtils } from "@budibase/frontend-core" - const { routeStore, styleable, linkable, builderStore } = getContext("sdk") + const sdk = getContext("sdk") + const { routeStore, styleable, linkable, builderStore, currentRole } = sdk const component = getContext("component") const context = getContext("context") @@ -50,7 +52,7 @@ }) setContext("layout", store) - $: validLinks = links?.filter(link => link.text && link.url) || [] + $: validLinks = getValidLinks(links, $currentRole) $: typeClass = NavigationClasses[navigation] || NavigationClasses.None $: navWidthClass = WidthClasses[navWidth || width] || WidthClasses.Large $: pageWidthClass = WidthClasses[pageWidth || width] || WidthClasses.Large @@ -79,6 +81,17 @@ } } + const getValidLinks = (allLinks, role) => { + // Strip links missing required info + let validLinks = (allLinks || []).filter(link => link.text && link.url) + + // Filter to only links allowed by the current role + const priority = RoleUtils.getRolePriority(role) + return validLinks.filter(link => { + return !link.roleId || RoleUtils.getRolePriority(link.roleId) <= priority + }) + } + const isInternal = url => { return url.startsWith("/") } diff --git a/packages/client/src/components/context/DeviceBindingsProvider.svelte b/packages/client/src/components/context/DeviceBindingsProvider.svelte index cdc19c74c2..36d86645c4 100644 --- a/packages/client/src/components/context/DeviceBindingsProvider.svelte +++ b/packages/client/src/components/context/DeviceBindingsProvider.svelte @@ -21,11 +21,11 @@ } onMount(() => { - resizeObserver.observe(document.getElementById("app-root")) + resizeObserver.observe(document.getElementById("spectrum-root")) }) onDestroy(() => { - resizeObserver.unobserve(document.getElementById("app-root")) + resizeObserver.unobserve(document.getElementById("spectrum-root")) }) diff --git a/packages/client/src/components/context/UserBindingsProvider.svelte b/packages/client/src/components/context/UserBindingsProvider.svelte index f7605122ae..98769cf76a 100644 --- a/packages/client/src/components/context/UserBindingsProvider.svelte +++ b/packages/client/src/components/context/UserBindingsProvider.svelte @@ -1,6 +1,6 @@ - + diff --git a/packages/client/src/sdk.js b/packages/client/src/sdk.js index db31da7164..13190e0a4f 100644 --- a/packages/client/src/sdk.js +++ b/packages/client/src/sdk.js @@ -8,6 +8,7 @@ import { uploadStore, rowSelectionStore, componentStore, + currentRole, } from "stores" import { styleable } from "utils/styleable" import { linkable } from "utils/linkable" @@ -26,6 +27,7 @@ export default { builderStore, uploadStore, componentStore, + currentRole, styleable, linkable, getAction, diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 280a32e069..df51aa7868 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -1,3 +1,7 @@ +import { derived } from "svelte/store" +import { devToolsStore } from "./devTools.js" +import { authStore } from "./auth.js" + export { authStore } from "./auth" export { appStore } from "./app" export { notificationStore } from "./notification" @@ -13,8 +17,18 @@ export { devToolsStore } from "./devTools" export { componentStore } from "./components" export { uploadStore } from "./uploads.js" export { rowSelectionStore } from "./rowSelection.js" + // Context stores are layered and duplicated, so it is not a singleton export { createContextStore } from "./context" // Initialises an app by loading screens and routes export { initialise } from "./initialise" + +// Derive the current role of the logged-in user, which may be overridden by +// dev tools +export const currentRole = derived( + [devToolsStore, authStore], + ([$devToolsStore, $authStore]) => { + return $devToolsStore.role || $authStore?.roleId + } +)