Merge pull request #13818 from Budibase/BUDI-8281/add-readonly-view-config

Add readonly view config
This commit is contained in:
Adria Navarro 2024-05-31 13:05:35 +02:00 committed by GitHub
commit 381d9a246b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 58 additions and 30 deletions

View File

@ -1,6 +1,6 @@
<script>
import { viewsV2 } from "stores/builder"
import { admin } from "stores/portal"
import { admin, licensing } from "stores/portal"
import { Grid } from "@budibase/frontend-core"
import { API } from "api"
import GridCreateEditRowModal from "components/backend/DataTable/modals/grid/GridCreateEditRowModal.svelte"
@ -28,6 +28,7 @@
showAvatars={false}
on:updatedatasource={handleGridViewUpdate}
isCloud={$admin.cloud}
allowViewReadonlyColumns={$licensing.isViewReadonlyColumnsEnabled}
>
<svelte:fragment slot="filter">
<GridFilterButton />

View File

@ -138,6 +138,11 @@ export const createLicensingStore = () => {
const isViewPermissionsEnabled = license.features.includes(
Constants.Features.VIEW_PERMISSIONS
)
const isViewReadonlyColumnsEnabled = license.features.includes(
Constants.Features.VIEW_READONLY_COLUMNS
)
store.update(state => {
return {
...state,
@ -157,6 +162,7 @@ export const createLicensingStore = () => {
triggerAutomationRunEnabled,
isViewPermissionsEnabled,
perAppBuildersEnabled,
isViewReadonlyColumnsEnabled,
}
})
},

View File

@ -1,49 +1,72 @@
<script>
import { getContext } from "svelte"
import { ActionButton, Popover, Icon } from "@budibase/bbui"
import { ActionButton, Popover, Icon, notifications } from "@budibase/bbui"
import { getColumnIcon } from "../lib/utils"
import ToggleActionButtonGroup from "./ToggleActionButtonGroup.svelte"
export let allowViewReadonlyColumns = false
const { columns, datasource, stickyColumn, dispatch } = getContext("grid")
let open = false
let anchor
$: anyHidden = $columns.some(col => !col.visible)
$: text = getText($columns)
$: restrictedColumns = $columns.filter(col => !col.visible || col.readonly)
$: anyRestricted = restrictedColumns.length
$: text = anyRestricted ? `Columns (${anyRestricted} restricted)` : "Columns"
const toggleColumn = async (column, permission) => {
const visible = permission !== PERMISSION_OPTIONS.HIDDEN
const readonly = permission === PERMISSION_OPTIONS.READONLY
datasource.actions.addSchemaMutation(column.name, { visible })
datasource.actions.addSchemaMutation(column.name, { visible, readonly })
try {
await datasource.actions.saveSchemaMutations()
dispatch(visible ? "show-column" : "hide-column")
} catch (e) {
notifications.error(e.message)
}
const getText = columns => {
const hidden = columns.filter(col => !col.visible).length
return hidden ? `Columns (${hidden} restricted)` : "Columns"
dispatch(visible ? "show-column" : "hide-column")
}
const PERMISSION_OPTIONS = {
WRITABLE: "writable",
READONLY: "readonly",
HIDDEN: "hidden",
}
const options = [
{ icon: "Edit", value: PERMISSION_OPTIONS.WRITABLE, tooltip: "Writable" },
{
const EDIT_OPTION = {
icon: "Edit",
value: PERMISSION_OPTIONS.WRITABLE,
tooltip: "Writable",
}
$: READONLY_OPTION = {
icon: "Visibility",
value: PERMISSION_OPTIONS.READONLY,
tooltip: allowViewReadonlyColumns
? "Read only"
: "Read only (premium feature)",
disabled: !allowViewReadonlyColumns,
}
const HIDDEN_OPTION = {
icon: "VisibilityOff",
value: PERMISSION_OPTIONS.HIDDEN,
tooltip: "Hidden",
},
]
}
$: options =
$datasource.type === "viewV2"
? [EDIT_OPTION, READONLY_OPTION, HIDDEN_OPTION]
: [EDIT_OPTION, HIDDEN_OPTION]
function columnToPermissionOptions(column) {
if (!column.visible) {
return PERMISSION_OPTIONS.HIDDEN
}
if (column.readonly) {
return PERMISSION_OPTIONS.READONLY
}
return PERMISSION_OPTIONS.WRITABLE
}
</script>
@ -54,7 +77,7 @@
quiet
size="M"
on:click={() => (open = !open)}
selected={open || anyHidden}
selected={open || anyRestricted}
disabled={!$columns.length}
>
{text}
@ -73,7 +96,7 @@
<ToggleActionButtonGroup
disabled
value={PERMISSION_OPTIONS.WRITABLE}
{options}
options={options.map(o => ({ ...o, disabled: true }))}
/>
{/if}
{#each $columns as column}

View File

@ -7,7 +7,6 @@
export let value
export let options
export let disabled
</script>
<div class="permissionPicker">
@ -15,7 +14,7 @@
<AbsTooltip text={option.tooltip} type={TooltipType.Info}>
<ActionButton
on:click={() => dispatch("click", option.value)}
{disabled}
disabled={option.disabled}
size="S"
icon={option.icon}
quiet

View File

@ -57,6 +57,7 @@
export let buttons = null
export let darkMode
export let isCloud = null
export let allowViewReadonlyColumns = false
// Unique identifier for DOM nodes inside this instance
const gridID = `grid-${Math.random().toString().slice(2)}`
@ -153,7 +154,7 @@
<div class="controls-left">
<slot name="filter" />
<SortButton />
<ColumnsSettingButton />
<ColumnsSettingButton {allowViewReadonlyColumns} />
<SizeButton />
<slot name="controls" />
</div>

View File

@ -146,6 +146,7 @@ export const initialise = context => {
schema: fieldSchema,
width: fieldSchema.width || oldColumn?.width || DefaultColumnWidth,
visible: fieldSchema.visible ?? true,
readonly: fieldSchema.readonly,
order: fieldSchema.order ?? oldColumn?.order,
primaryDisplay: field === primaryDisplay,
}

View File

@ -424,7 +424,7 @@ describe.each([
await config.api.viewV2.create(newView, {
status: 400,
body: {
message: "Readonly fields are not enabled for your tenant",
message: "Readonly fields are not enabled",
status: 400,
},
})
@ -690,7 +690,7 @@ describe.each([
await config.api.viewV2.update(view, {
status: 400,
body: {
message: "Readonly fields are not enabled for your tenant",
message: "Readonly fields are not enabled",
},
})
})

View File

@ -55,10 +55,7 @@ async function guardViewSchema(
if (viewSchema[field].readonly) {
if (!(await features.isViewReadonlyColumnsEnabled())) {
throw new HTTPError(
`Readonly fields are not enabled for your tenant`,
400
)
throw new HTTPError(`Readonly fields are not enabled`, 400)
}
if (isRequired(tableSchemaField.constraints)) {