Improve handling of permission issues and routing issues, and add an error fallback message
This commit is contained in:
parent
ee8033e88f
commit
ab4e71c1a4
|
@ -18,6 +18,8 @@
|
||||||
import SettingsBar from "./preview/SettingsBar.svelte"
|
import SettingsBar from "./preview/SettingsBar.svelte"
|
||||||
import SelectionIndicator from "./preview/SelectionIndicator.svelte"
|
import SelectionIndicator from "./preview/SelectionIndicator.svelte"
|
||||||
import HoverIndicator from "./preview/HoverIndicator.svelte"
|
import HoverIndicator from "./preview/HoverIndicator.svelte"
|
||||||
|
import { Layout, Heading, Body } from "@budibase/bbui"
|
||||||
|
import ErrorSVG from "../../../builder/assets/error.svg"
|
||||||
|
|
||||||
// Provide contexts
|
// Provide contexts
|
||||||
setContext("sdk", SDK)
|
setContext("sdk", SDK)
|
||||||
|
@ -25,6 +27,7 @@
|
||||||
setContext("context", createContextStore())
|
setContext("context", createContextStore())
|
||||||
|
|
||||||
let dataLoaded = false
|
let dataLoaded = false
|
||||||
|
let permissionError = false
|
||||||
|
|
||||||
// Load app config
|
// Load app config
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
@ -46,12 +49,21 @@
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// Redirect to home layout if no matching route
|
// Handle no matching route - this is likely a permission error
|
||||||
$: {
|
$: {
|
||||||
if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) {
|
if (dataLoaded && $routeStore.routerLoaded && !$routeStore.activeRoute) {
|
||||||
if ($authStore) {
|
if ($authStore) {
|
||||||
routeStore.actions.navigate("/")
|
// There is a logged in user, so handle them
|
||||||
|
if ($screenStore.screens.length) {
|
||||||
|
// Screens exist so navigate back to the home screen
|
||||||
|
const firstRoute = $screenStore.screens[0].routing?.route ?? "/"
|
||||||
|
routeStore.actions.navigate(firstRoute)
|
||||||
|
} else {
|
||||||
|
// No screens likely means the user has no permissions to view this app
|
||||||
|
permissionError = true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// The user is not logged in, redirect them to login
|
||||||
const returnUrl = `${window.location.pathname}${window.location.hash}`
|
const returnUrl = `${window.location.pathname}${window.location.hash}`
|
||||||
const encodedUrl = encodeURIComponent(returnUrl)
|
const encodedUrl = encodeURIComponent(returnUrl)
|
||||||
window.location = `/builder/auth/login?returnUrl=${encodedUrl}`
|
window.location = `/builder/auth/login?returnUrl=${encodedUrl}`
|
||||||
|
@ -60,36 +72,46 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if dataLoaded && $screenStore.activeLayout}
|
{#if dataLoaded}
|
||||||
<div
|
<div
|
||||||
id="spectrum-root"
|
id="spectrum-root"
|
||||||
lang="en"
|
lang="en"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
class="spectrum spectrum--medium spectrum--light"
|
class="spectrum spectrum--medium spectrum--light"
|
||||||
>
|
>
|
||||||
<Provider key="user" data={$authStore} {actions}>
|
{#if permissionError}
|
||||||
<div id="app-root">
|
<div class="error">
|
||||||
{#key $screenStore.activeLayout._id}
|
<Layout justifyItems="center" gap="S">
|
||||||
<Component instance={$screenStore.activeLayout.props} />
|
{@html ErrorSVG}
|
||||||
{/key}
|
<Heading size="L">You don't have permission to use this app</Heading>
|
||||||
|
<Body size="S">Ask your administrator to grant you access</Body>
|
||||||
|
</Layout>
|
||||||
</div>
|
</div>
|
||||||
<NotificationDisplay />
|
{:else if $screenStore.activeLayout}
|
||||||
<ConfirmationDisplay />
|
<Provider key="user" data={$authStore} {actions}>
|
||||||
<!-- Key block needs to be outside the if statement or it breaks -->
|
<div id="app-root">
|
||||||
{#key $builderStore.selectedComponentId}
|
{#key $screenStore.activeLayout._id}
|
||||||
|
<Component instance={$screenStore.activeLayout.props} />
|
||||||
|
{/key}
|
||||||
|
</div>
|
||||||
|
<NotificationDisplay />
|
||||||
|
<ConfirmationDisplay />
|
||||||
|
<!-- Key block needs to be outside the if statement or it breaks -->
|
||||||
|
{#key $builderStore.selectedComponentId}
|
||||||
|
{#if $builderStore.inBuilder}
|
||||||
|
<SettingsBar />
|
||||||
|
{/if}
|
||||||
|
{/key}
|
||||||
|
<!--
|
||||||
|
We don't want to key these by componentID as they control their own
|
||||||
|
re-mounting to avoid flashes.
|
||||||
|
-->
|
||||||
{#if $builderStore.inBuilder}
|
{#if $builderStore.inBuilder}
|
||||||
<SettingsBar />
|
<SelectionIndicator />
|
||||||
|
<HoverIndicator />
|
||||||
{/if}
|
{/if}
|
||||||
{/key}
|
</Provider>
|
||||||
<!--
|
{/if}
|
||||||
We don't want to key these by componentID as they control their own
|
|
||||||
re-mounting to avoid flashes.
|
|
||||||
-->
|
|
||||||
{#if $builderStore.inBuilder}
|
|
||||||
<SelectionIndicator />
|
|
||||||
<HoverIndicator />
|
|
||||||
{/if}
|
|
||||||
</Provider>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
@ -105,4 +127,31 @@
|
||||||
#app-root {
|
#app-root {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
z-index: 1;
|
||||||
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue