Remove concept of selected access role and refactor logic around assigning roles to new screens

This commit is contained in:
Andrew Kingston 2022-05-11 08:47:24 +01:00
parent e5f48fedd1
commit 914a94b695
8 changed files with 101 additions and 61 deletions

View File

@ -59,7 +59,5 @@ export const mainLayout = derived(store, $store => {
) )
}) })
export const selectedAccessRole = writable("BASIC")
// For compatibility // For compatibility
export const currentAsset = selectedScreen export const currentAsset = selectedScreen

View File

@ -1,12 +1,6 @@
import { get, writable } from "svelte/store" import { get, writable } from "svelte/store"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { import { currentAsset, mainLayout, selectedComponent } from "builderStore"
currentAsset,
mainLayout,
selectedComponent,
selectedAccessRole,
store,
} from "builderStore"
import { import {
datasources, datasources,
integrations, integrations,
@ -197,10 +191,6 @@ export const getFrontendStore = () => {
screens.find(screen => screen._id === screenId) || screens[0] screens.find(screen => screen._id === screenId) || screens[0]
if (!screen) return state if (!screen) return state
// Update role to the screen's role setting so that it will always
// be visible
selectedAccessRole.set(screen.routing.roleId)
state.currentFrontEndType = FrontendTypes.SCREEN state.currentFrontEndType = FrontendTypes.SCREEN
state.selectedScreenId = screen._id state.selectedScreenId = screen._id
state.currentView = "detail" state.currentView = "detail"

View File

@ -1,5 +1,5 @@
<script> <script>
import { store, selectedAccessRole } from "builderStore" import { store } from "builderStore"
import PathTree from "./PathTree.svelte" import PathTree from "./PathTree.svelte"
let routes = {} let routes = {}

View File

@ -11,6 +11,7 @@
bind:value bind:value
on:change on:change
options={$roles} options={$roles}
placeholder={null}
getOptionLabel={role => role.name} getOptionLabel={role => role.name}
getOptionValue={role => role._id} getOptionValue={role => role._id}
getOptionColour={role => RoleUtils.getRoleColour(role._id)} getOptionColour={role => RoleUtils.getRoleColour(role._id)}

View File

@ -1,20 +1,18 @@
<script> <script>
import { ModalContent, Input } from "@budibase/bbui" import { ModalContent, Input } from "@budibase/bbui"
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
import { store, selectedAccessRole } from "builderStore"
import { get } from "svelte/store" import { get } from "svelte/store"
import { store } from "builderStore"
export let onConfirm export let onConfirm
export let onCancel export let onCancel
export let screenUrl export let screenUrl
export let screenName export let screenRole
export let confirmText = "Continue" export let confirmText = "Continue"
let routeError
let touched = false
let screenAccessRole = $selectedAccessRole + ""
const appPrefix = "/app" const appPrefix = "/app"
let touched = false
let error
$: appUrl = screenUrl $: appUrl = screenUrl
? `${window.location.origin}${appPrefix}${screenUrl}` ? `${window.location.origin}${appPrefix}${screenUrl}`
@ -27,41 +25,42 @@
touched = true touched = true
screenUrl = sanitizeUrl(screenUrl) screenUrl = sanitizeUrl(screenUrl)
if (routeExists(screenUrl)) { if (routeExists(screenUrl)) {
routeError = "This URL is already taken for this access role" error = "This URL is already taken for this access role"
} else { } else {
routeError = null error = null
} }
} }
const routeExists = url => { const routeExists = url => {
const roleId = get(selectedAccessRole) || "BASIC" if (!screenRole) {
return false
}
return get(store).screens.some( return get(store).screens.some(
screen => screen =>
screen.routing.route.toLowerCase() === url.toLowerCase() && screen.routing.route.toLowerCase() === url.toLowerCase() &&
screen.routing.roleId === roleId screen.routing.roleId === screenRole
) )
} }
const confirmScreenDetails = async () => { const confirmScreenDetails = async () => {
await onConfirm({ await onConfirm({
screenUrl, screenUrl,
screenName,
}) })
} }
</script> </script>
<ModalContent <ModalContent
size="M" size="M"
title={"Enter details"} title={"Screen details"}
{confirmText} {confirmText}
onConfirm={confirmScreenDetails} onConfirm={confirmScreenDetails}
{onCancel} {onCancel}
cancelText={"Back"} cancelText={"Back"}
disabled={!screenAccessRole || !screenUrl || routeError || !touched} disabled={!screenUrl || error || !touched}
> >
<Input <Input
label="Enter a URL for the new screen" label="Enter a URL for the new screen"
error={routeError} {error}
bind:value={screenUrl} bind:value={screenUrl}
on:change={routeChanged} on:change={routeChanged}
/> />

View File

@ -84,8 +84,8 @@
<Modal bind:this={screenDetailsModal}> <Modal bind:this={screenDetailsModal}>
<ScreenDetailsModal <ScreenDetailsModal
onConfirm={createDuplicateScreen} onConfirm={createDuplicateScreen}
screenName={screen?.props._instanceName}
screenUrl={screen?.routing.route} screenUrl={screen?.routing.route}
screenRole={screen?.routing.roleId}
confirmText="Duplicate" confirmText="Duplicate"
/> />
</Modal> </Modal>

View File

@ -0,0 +1,66 @@
<script>
import { Select, ModalContent } from "@budibase/bbui"
import analytics, { Events } from "analytics"
import { RoleUtils } from "@budibase/frontend-core"
import { roles } from "stores/backend"
import { get } from "svelte/store"
import { store } from "builderStore"
import { onMount } from "svelte"
export let onConfirm
export let onCancel
export let screenUrl
export let screenAccessRole
let error
const onChangeRole = e => {
const roleId = e.detail
analytics.captureEvent(Events.SCREEN.CREATE_ROLE_UPDATED, {
screenAccessRole: roleId,
})
if (routeExists(screenUrl, roleId)) {
error = "This URL is already taken for this access role"
} else {
error = null
}
}
const routeExists = (url, role) => {
if (!url || !role) {
return false
}
return get(store).screens.some(
screen =>
screen.routing.route.toLowerCase() === url.toLowerCase() &&
screen.routing.roleId === role
)
}
onMount(() => {
// Validate the initial role
onChangeRole({ detail: screenAccessRole })
})
</script>
<ModalContent
title={"Create CRUD Screens"}
confirmText={"Done"}
cancelText={"Back"}
{onConfirm}
{onCancel}
disabled={!!error}
>
Select which level of access you want your screens to have
<Select
bind:value={screenAccessRole}
on:change={onChangeRole}
label="Access"
{error}
getOptionLabel={role => role.name}
getOptionValue={role => role._id}
getOptionColour={role => RoleUtils.getRoleColour(role._id)}
options={$roles}
placeholder={null}
/>
</ModalContent>

View File

@ -2,13 +2,15 @@
import ScreenDetailsModal from "./ScreenDetailsModal.svelte" import ScreenDetailsModal from "./ScreenDetailsModal.svelte"
import NewScreenModal from "./NewScreenModal.svelte" import NewScreenModal from "./NewScreenModal.svelte"
import DatasourceModal from "./DatasourceModal.svelte" import DatasourceModal from "./DatasourceModal.svelte"
import ScreenRoleModal from "./ScreenRoleModal.svelte"
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
import { Modal, ModalContent, Select, notifications } from "@budibase/bbui" import { Modal, notifications } from "@budibase/bbui"
import { store, selectedAccessRole } from "builderStore" import { store } from "builderStore"
import analytics, { Events } from "analytics" import analytics, { Events } from "analytics"
import { get } from "svelte/store" import { get } from "svelte/store"
import getTemplates from "builderStore/store/screenTemplates" import getTemplates from "builderStore/store/screenTemplates"
import { tables, roles } from "stores/backend" import { tables } from "stores/backend"
import { Roles } from "constants/backend"
let pendingScreen let pendingScreen
@ -19,10 +21,9 @@
let screenAccessRoleModal let screenAccessRoleModal
// Cache variables for workflow // Cache variables for workflow
let screenAccessRole = $selectedAccessRole + "" let screenAccessRole = Roles.BASIC
let selectedTemplates = null let selectedTemplates = null
let blankScreenUrl = null let blankScreenUrl = null
let screenMode = null let screenMode = null
// External handler to show the screen wizard // External handler to show the screen wizard
@ -30,10 +31,9 @@
selectedTemplates = null selectedTemplates = null
blankScreenUrl = null blankScreenUrl = null
screenMode = null screenMode = null
newScreenModal.show()
// Reset state when showing modal again
pendingScreen = null pendingScreen = null
screenAccessRole = Roles.BASIC
newScreenModal.show()
} }
// Creates an array of screens, checking and sanitising their URLs // Creates an array of screens, checking and sanitising their URLs
@ -58,9 +58,11 @@
screen.routing.route = sanitizeUrl(screen.routing.route) screen.routing.route = sanitizeUrl(screen.routing.route)
// Use the currently selected role // Use the currently selected role
if (!screenAccessRole) {
console.log("NO ROLE")
return
}
screen.routing.roleId = screenAccessRole screen.routing.roleId = screenAccessRole
? screenAccessRole
: get(selectedAccessRole) || "BASIC"
// Create the screen // Create the screen
await store.actions.screens.save(screen) await store.actions.screens.save(screen)
@ -90,7 +92,7 @@
// Checks if any screens exist in the store with the given route and // Checks if any screens exist in the store with the given route and
// currently selected role // currently selected role
const hasExistingUrl = url => { const hasExistingUrl = url => {
const roleId = get(selectedAccessRole) || "BASIC" const roleId = screenAccessRole
const screens = get(store).screens.filter(s => s.routing.roleId === roleId) const screens = get(store).screens.filter(s => s.routing.roleId === roleId)
return !!screens.find(s => s.routing?.route === url) return !!screens.find(s => s.routing?.route === url)
} }
@ -115,7 +117,7 @@
const confirmScreenSelection = async mode => { const confirmScreenSelection = async mode => {
screenMode = mode screenMode = mode
if (mode == "autoCreate") { if (mode === "autoCreate") {
datasourceModal.show() datasourceModal.show()
} else { } else {
let templates = getTemplates($store, $tables.list) let templates = getTemplates($store, $tables.list)
@ -198,28 +200,12 @@
</Modal> </Modal>
<Modal bind:this={screenAccessRoleModal}> <Modal bind:this={screenAccessRoleModal}>
<ModalContent <ScreenRoleModal
title={"Create CRUD Screens"}
confirmText={"Done"}
cancelText={"Back"}
onConfirm={confirmScreenCreation} onConfirm={confirmScreenCreation}
onCancel={roleSelectBack} onCancel={roleSelectBack}
> bind:screenAccessRole
Select which level of access you want your screens to have screenUrl={blankScreenUrl}
<Select
bind:value={screenAccessRole}
on:change={() => {
analytics.captureEvent(Events.SCREEN.CREATE_ROLE_UPDATED, {
screenAccessRole,
})
}}
label="Access"
getOptionLabel={role => role.name}
getOptionValue={role => role._id}
getOptionColor={role => role.color}
options={$roles}
/> />
</ModalContent>
</Modal> </Modal>
<Modal bind:this={screenDetailsModal}> <Modal bind:this={screenDetailsModal}>