diff --git a/packages/auth/src/security/roles.js b/packages/auth/src/security/roles.js index 53e1b90d73..baa8fc40dc 100644 --- a/packages/auth/src/security/roles.js +++ b/packages/auth/src/security/roles.js @@ -147,7 +147,7 @@ exports.getRole = async (appId, roleId) => { */ async function getAllUserRoles(appId, userRoleId) { if (!userRoleId) { - return [BUILTIN_IDS.PUBLIC] + return [BUILTIN_IDS.BASIC] } let currentRole = await exports.getRole(appId, userRoleId) let roles = currentRole ? [currentRole] : [] @@ -226,7 +226,7 @@ exports.getAllRoles = async appId => { dbRole => exports.getExternalRoleID(dbRole._id) === builtinRoleId )[0] if (dbBuiltin == null) { - roles.push(builtinRole) + roles.push(builtinRole || builtinRoles.BASIC) } else { // remove role and all back after combining with the builtin roles = roles.filter(role => role._id !== dbBuiltin._id) diff --git a/packages/bbui/src/Tabs/Tabs.svelte b/packages/bbui/src/Tabs/Tabs.svelte index 3e1080f2cd..77a8526a15 100644 --- a/packages/bbui/src/Tabs/Tabs.svelte +++ b/packages/bbui/src/Tabs/Tabs.svelte @@ -15,8 +15,12 @@ const dispatch = createEventDispatcher() - $: selected = $tab.title - $: selected = dispatch("select", selected) + $: { + if ($tab.title !== selected) { + selected = $tab.title + dispatch("select", selected) + } + } let top, left, width, height $: calculateIndicatorLength($tab) diff --git a/packages/builder/assets/error.svg b/packages/builder/assets/error.svg new file mode 100644 index 0000000000..4cc1d753c9 --- /dev/null +++ b/packages/builder/assets/error.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index a462167ce2..edad0fdff5 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -122,6 +122,9 @@ export const getFrontendStore = () => { save: async screen => { const creatingNewScreen = screen._id === undefined const response = await api.post(`/api/screens`, screen) + if (response.status !== 200) { + return + } screen = await response.json() await store.actions.routing.fetch() diff --git a/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte b/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte index f58b9f197f..8b7417c41f 100644 --- a/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/EditRoles.svelte @@ -10,8 +10,10 @@ let selectedRole = {} let errors = [] let builtInRoles = ["Admin", "Power", "Basic", "Public"] + // Don't allow editing of public role + $: editableRoles = $roles.filter(role => role._id !== "PUBLIC") $: selectedRoleId = selectedRole._id - $: otherRoles = $roles.filter(role => role._id !== selectedRoleId) + $: otherRoles = editableRoles.filter(role => role._id !== selectedRoleId) $: isCreating = selectedRoleId == null || selectedRoleId === "" const fetchBasePermissions = async () => { @@ -96,7 +98,7 @@ label="Role" value={selectedRoleId} on:change={changeRole} - options={$roles} + options={editableRoles} placeholder="Create new role" getOptionValue={role => role._id} getOptionLabel={role => role.name} diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 5ae4ac0ddf..12f5280b83 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -5,12 +5,16 @@ import { Screen } from "builderStore/store/screenTemplates/utils/Screen" import { FrontendTypes } from "constants" import ConfirmDialog from "components/common/ConfirmDialog.svelte" + import { ProgressCircle, Layout, Heading, Body } from "@budibase/bbui" + import ErrorSVG from "assets/error.svg?raw" let iframe let layout let screen let confirmDeleteDialog let idToDelete + let loading = true + let error // Create screen slot placeholder for use when a page is selected rather // than a screen @@ -68,11 +72,21 @@ onMount(() => { // Initialise the app when mounted iframe.contentWindow.addEventListener( - "bb-ready", + "ready", () => refreshContent(strippedJson), { once: true } ) + // Catch any app errors + iframe.contentWindow.addEventListener( + "error", + event => { + loading = false + error = event.detail || "An unknown error occurred" + }, + { once: true } + ) + // Add listener for events sent by cliebt library in preview iframe.contentWindow.addEventListener("bb-event", event => { const { type, data } = event.detail @@ -83,8 +97,10 @@ } else if (type === "delete-component" && data.id) { idToDelete = data.id confirmDeleteDialog.show() + } else if (type === "preview-loaded") { + loading = false } else { - console.log(data) + console.warning(`Client sent unknown event type: ${type}`) } }) }) @@ -99,11 +115,25 @@
+ {#if loading} +
+ +
+ {:else if error} +
+ + {@html ErrorSVG} + App preview failed to load + {error} + +
+ {/if}