Cache roles in store and add role selector for screens

This commit is contained in:
Andrew Kingston 2020-12-09 15:35:57 +00:00
parent 74d7316e2f
commit b842a2addc
8 changed files with 70 additions and 92 deletions

View File

@ -6,6 +6,7 @@ const INITIAL_BACKEND_UI_STATE = {
tables: [],
views: [],
users: [],
roles: [],
selectedDatabase: {},
selectedTable: {},
draftTable: {},
@ -177,6 +178,26 @@ export const getBackendUiStore = () => {
return state
}),
},
roles: {
fetch: async () => {
const response = await api.get("/api/roles")
const roles = await response.json()
store.update(state => {
state.roles = roles
return state
})
},
delete: async role => {
const response = await api.delete(`/api/roles/${role._id}/${role._rev}`)
await store.actions.roles.fetch()
return response
},
save: async role => {
const response = await api.post("/api/roles", role)
await store.actions.roles.fetch()
return response
},
},
}
return store

View File

@ -1,42 +1,10 @@
<!-- Module scoped cache of saved role options -->
<script context="module">
import builderApi from "builderStore/api"
let cachedRoles
async function getRoles(force = false) {
if (cachedRoles && !force) {
return await cachedRoles
}
cachedRoles = new Promise(resolve => {
builderApi
.get("/api/roles")
.then(response => response.json())
.then(resolve)
})
return await cachedRoles
}
</script>
<script>
import { backendUiStore } from "builderStore"
export let roleId
let roleName
$: getRole()
async function getRole() {
// Try to find a matching role
let roles = await getRoles()
let role = roles.find(role => role._id === roleId)
// If we didn't find a matching role, try updating the cached results
if (!role) {
let roles = await getRoles(true)
let role = roles.find(role => role._id === roleId)
}
role = roles.find(role => role._id === roleId)
roleName = role?.name ?? "Unknown role"
}
$: role = $backendUiStore.roles.find(role => role._id === roleId)
$: roleName = role?.name ?? "Unknown role"
</script>
<div>{roleName}</div>

View File

@ -1,18 +1,14 @@
<script>
import { onMount } from "svelte"
import { backendUiStore } from "builderStore"
import { notifier } from "builderStore/store/notifications"
import RowFieldControl from "../RowFieldControl.svelte"
import * as backendApi from "../api"
import builderApi from "builderStore/api"
import { ModalContent, Select } from "@budibase/bbui"
import ErrorsBox from "components/common/ErrorsBox.svelte"
export let row = {}
let errors = []
let roles = []
let rolesLoaded = false
$: creating = row?._id == null
$: table = row.tableId
@ -56,14 +52,6 @@
notifier.success("User saved successfully.")
backendUiStore.actions.rows.save(rowResponse)
}
const fetchRoles = async () => {
const rolesResponse = await builderApi.get("/api/roles")
roles = await rolesResponse.json()
rolesLoaded = true
}
onMount(fetchRoles)
</script>
<ModalContent
@ -80,19 +68,17 @@
bind:value={row.password} />
<!-- Defer rendering this select until roles load, otherwise the initial
selection is always undefined -->
{#if rolesLoaded}
<Select
thin
secondary
label="Role"
data-cy="roleId-select"
bind:value={row.roleId}>
<option value="">Choose an option</option>
{#each roles as role}
<option value={role._id}>{role.name}</option>
{/each}
</Select>
{/if}
<Select
thin
secondary
label="Role"
data-cy="roleId-select"
bind:value={row.roleId}>
<option value="">Choose an option</option>
{#each $backendUiStore.roles as role}
<option value={role._id}>{role.name}</option>
{/each}
</Select>
{#each customSchemaKeys as [key, meta]}
<RowFieldControl {meta} bind:value={row[key]} {creating} />
{/each}

View File

@ -4,27 +4,26 @@
import api from "builderStore/api"
import { notifier } from "builderStore/store/notifications"
import ErrorsBox from "components/common/ErrorsBox.svelte"
import { backendUiStore } from "builderStore"
let roles = []
let permissions = []
let selectedRole = {}
let errors = []
$: selectedRoleId = selectedRole._id
$: otherRoles = roles.filter(role => role._id !== selectedRoleId)
$: otherRoles = $backendUiStore.roles.filter(
role => role._id !== selectedRoleId
)
$: isCreating = selectedRoleId == null || selectedRoleId === ""
// Loads available roles and permissions from the server
const fetchRoles = async () => {
const rolesResponse = await api.get("/api/roles")
roles = await rolesResponse.json()
const fetchPermissions = async () => {
const permissionsResponse = await api.get("/api/permissions")
permissions = await permissionsResponse.json()
}
// Changes the seleced role
// Changes the selected role
const changeRole = event => {
const id = event?.target?.value
const role = roles.find(role => role._id === id)
const role = $backendUiStore.roles.find(role => role._id === id)
if (role) {
selectedRole = {
...role,
@ -61,7 +60,7 @@
}
// Save/create the role
const response = await api.post("/api/roles", selectedRole)
const response = await backendUiStore.actions.roles.save(selectedRole)
if (response.status === 200) {
notifier.success("Role saved successfully.")
} else {
@ -72,11 +71,8 @@
// Deletes the selected role
const deleteRole = async () => {
const response = await api.delete(
`/api/roles/${selectedRole._id}/${selectedRole._rev}`
)
const response = await backendUiStore.actions.roles.delete(selectedRole)
if (response.status === 200) {
await fetchRoles()
changeRole()
notifier.success("Role deleted successfully.")
} else {
@ -84,7 +80,7 @@
}
}
onMount(fetchRoles)
onMount(fetchPermissions)
</script>
<ModalContent
@ -101,7 +97,7 @@
value={selectedRoleId}
on:change={changeRole}>
<option value="">Create new role</option>
{#each roles as role}
{#each $backendUiStore.roles as role}
<option value={role._id}>{role.name}</option>
{/each}
</Select>

View File

@ -15,7 +15,6 @@
let templateIndex
let draftScreen
let createLink = true
let roles = []
let roleId = "BASIC"
$: templates = getTemplates($store, $backendUiStore.tables)
@ -30,11 +29,6 @@
}
}
const fetchRoles = async () => {
const response = await api.get("/api/roles")
roles = await response.json()
}
const templateChanged = newTemplateIndex => {
if (newTemplateIndex === undefined) return
const template = templates[newTemplateIndex]
@ -96,8 +90,6 @@
route = "/" + event.target.value
}
}
onMount(fetchRoles)
</script>
<ModalContent title="New Screen" confirmText="Create Screen" onConfirm={save}>
@ -118,12 +110,10 @@
error={routeError}
bind:value={route}
on:change={routeChanged} />
{#if roles.length}
<Select label="Access" bind:value={roleId} secondary>
{#each roles as role}
<option value={role._id}>{role.name}</option>
{/each}
</Select>
{/if}
<Select label="Access" bind:value={roleId} secondary>
{#each $backendUiStore as role}
<option value={role._id}>{role.name}</option>
{/each}
</Select>
<Toggle text="Create link in navigation bar" bind:checked={createLink} />
</ModalContent>

View File

@ -0,0 +1,15 @@
<script>
import { Select } from "@budibase/bbui"
import { backendUiStore } from "builderStore"
export let value
let roles = []
</script>
<Select bind:value extraThin secondary on:change>
<option value="">Choose an option</option>
{#each $backendUiStore.roles as role}
<option value={role._id}>{role.name}</option>
{/each}
</Select>

View File

@ -4,6 +4,7 @@
import { FrontendTypes } from "constants"
import PropertyControl from "./PropertyControl.svelte"
import LayoutSelect from "./LayoutSelect.svelte"
import RoleSelect from "./RoleSelect.svelte"
import Input from "./PropertyPanelControls/Input.svelte"
import { excludeProps } from "./propertyCategories.js"
import { store, allScreens, currentAsset } from "builderStore"
@ -36,8 +37,8 @@
const screenDefinition = [
{ key: "description", label: "Description", control: Input },
{ key: "routing.route", label: "Route", control: Input },
{ key: "routing.roleId", label: "Access", control: RoleSelect },
{ key: "layoutId", label: "Layout", control: LayoutSelect },
{ key: "routing.roleId", label: "Role", control: Input },
]
const layoutDefinition = [{ key: "title", label: "Title", control: Input }]

View File

@ -20,6 +20,7 @@
backendUiStore.actions.reset()
await store.actions.initialise(pkg)
await automationStore.actions.fetch()
await backendUiStore.actions.roles.fetch()
return pkg
} else {
throw new Error(pkg)