Merge pull request #13818 from Budibase/BUDI-8281/add-readonly-view-config
Add readonly view config
This commit is contained in:
commit
381d9a246b
|
@ -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 />
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
})
|
||||
},
|
||||
|
|
|
@ -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 })
|
||||
await datasource.actions.saveSchemaMutations()
|
||||
datasource.actions.addSchemaMutation(column.name, { visible, readonly })
|
||||
try {
|
||||
await datasource.actions.saveSchemaMutations()
|
||||
} catch (e) {
|
||||
notifications.error(e.message)
|
||||
}
|
||||
dispatch(visible ? "show-column" : "hide-column")
|
||||
}
|
||||
|
||||
const getText = columns => {
|
||||
const hidden = columns.filter(col => !col.visible).length
|
||||
return hidden ? `Columns (${hidden} restricted)` : "Columns"
|
||||
}
|
||||
|
||||
const PERMISSION_OPTIONS = {
|
||||
WRITABLE: "writable",
|
||||
READONLY: "readonly",
|
||||
HIDDEN: "hidden",
|
||||
}
|
||||
|
||||
const options = [
|
||||
{ icon: "Edit", value: PERMISSION_OPTIONS.WRITABLE, tooltip: "Writable" },
|
||||
{
|
||||
icon: "VisibilityOff",
|
||||
value: PERMISSION_OPTIONS.HIDDEN,
|
||||
tooltip: "Hidden",
|
||||
},
|
||||
]
|
||||
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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Reference in New Issue