@budibase/frontend-core 2.27.5 → 2.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@budibase/frontend-core",
3
- "version": "2.27.5",
3
+ "version": "2.28.0",
4
4
  "description": "Budibase frontend core libraries used in builder and client",
5
5
  "author": "Budibase",
6
6
  "license": "MPL-2.0",
7
7
  "svelte": "src/index.js",
8
8
  "dependencies": {
9
- "@budibase/bbui": "2.27.5",
10
- "@budibase/shared-core": "2.27.5",
11
- "@budibase/types": "2.27.5",
9
+ "@budibase/bbui": "2.28.0",
10
+ "@budibase/shared-core": "2.28.0",
11
+ "@budibase/types": "2.28.0",
12
12
  "dayjs": "^1.10.8",
13
13
  "lodash": "4.17.21",
14
14
  "shortid": "2.2.15",
15
15
  "socket.io-client": "^4.6.1"
16
16
  },
17
- "gitHead": "e4db515ecf2c0a19cd188cf4d646946e903717b1"
17
+ "gitHead": "29042fd20f80b9098471b86e2c578bc751a84e3d"
18
18
  }
package/src/api/user.js CHANGED
@@ -234,6 +234,16 @@ export const buildUserEndpoints = API => ({
234
234
  })
235
235
  },
236
236
 
237
+ /**
238
+ * Removes multiple user invites from Redis cache
239
+ */
240
+ removeUserInvites: async inviteCodes => {
241
+ return await API.post({
242
+ url: "/api/global/users/multi/invite/delete",
243
+ body: inviteCodes,
244
+ })
245
+ },
246
+
237
247
  /**
238
248
  * Accepts an invite to join the platform and creates a user.
239
249
  * @param inviteCode the invite code sent in the email
@@ -33,7 +33,8 @@
33
33
  column.schema.autocolumn ||
34
34
  column.schema.disabled ||
35
35
  column.schema.type === "formula" ||
36
- (!$config.canEditRows && !row._isNewRow)
36
+ (!$config.canEditRows && !row._isNewRow) ||
37
+ column.schema.readonly
37
38
 
38
39
  // Register this cell API if the row is focused
39
40
  $: {
@@ -1,49 +1,98 @@
1
1
  <script>
2
2
  import { getContext } from "svelte"
3
- import { ActionButton, Popover, Icon } from "@budibase/bbui"
3
+ import { ActionButton, Popover, Icon, notifications } from "@budibase/bbui"
4
4
  import { getColumnIcon } from "../lib/utils"
5
5
  import ToggleActionButtonGroup from "./ToggleActionButtonGroup.svelte"
6
+ import { helpers } from "@budibase/shared-core"
7
+
8
+ export let allowViewReadonlyColumns = false
6
9
 
7
10
  const { columns, datasource, stickyColumn, dispatch } = getContext("grid")
8
11
 
9
12
  let open = false
10
13
  let anchor
11
14
 
12
- $: anyHidden = $columns.some(col => !col.visible)
13
- $: text = getText($columns)
15
+ $: allColumns = $stickyColumn ? [$stickyColumn, ...$columns] : $columns
16
+
17
+ $: restrictedColumns = allColumns.filter(col => !col.visible || col.readonly)
18
+ $: anyRestricted = restrictedColumns.length
19
+ $: text = anyRestricted ? `Columns (${anyRestricted} restricted)` : "Columns"
14
20
 
15
21
  const toggleColumn = async (column, permission) => {
16
22
  const visible = permission !== PERMISSION_OPTIONS.HIDDEN
23
+ const readonly = permission === PERMISSION_OPTIONS.READONLY
17
24
 
18
- datasource.actions.addSchemaMutation(column.name, { visible })
19
- await datasource.actions.saveSchemaMutations()
25
+ await datasource.actions.addSchemaMutation(column.name, {
26
+ visible,
27
+ readonly,
28
+ })
29
+ try {
30
+ await datasource.actions.saveSchemaMutations()
31
+ } catch (e) {
32
+ notifications.error(e.message)
33
+ } finally {
34
+ await datasource.actions.resetSchemaMutations()
35
+ await datasource.actions.refreshDefinition()
36
+ }
20
37
  dispatch(visible ? "show-column" : "hide-column")
21
38
  }
22
39
 
23
- const getText = columns => {
24
- const hidden = columns.filter(col => !col.visible).length
25
- return hidden ? `Columns (${hidden} restricted)` : "Columns"
26
- }
27
-
28
40
  const PERMISSION_OPTIONS = {
29
41
  WRITABLE: "writable",
42
+ READONLY: "readonly",
30
43
  HIDDEN: "hidden",
31
44
  }
32
45
 
33
- const options = [
34
- { icon: "Edit", value: PERMISSION_OPTIONS.WRITABLE, tooltip: "Writable" },
35
- {
46
+ $: displayColumns = allColumns.map(c => {
47
+ const isRequired = helpers.schema.isRequired(c.schema.constraints)
48
+ const isDisplayColumn = $stickyColumn === c
49
+
50
+ const requiredTooltip = isRequired && "Required columns must be writable"
51
+
52
+ const editEnabled =
53
+ !isRequired ||
54
+ columnToPermissionOptions(c) !== PERMISSION_OPTIONS.WRITABLE
55
+ const options = [
56
+ {
57
+ icon: "Edit",
58
+ value: PERMISSION_OPTIONS.WRITABLE,
59
+ tooltip: (!editEnabled && requiredTooltip) || "Writable",
60
+ disabled: !editEnabled,
61
+ },
62
+ ]
63
+ if ($datasource.type === "viewV2") {
64
+ options.push({
65
+ icon: "Visibility",
66
+ value: PERMISSION_OPTIONS.READONLY,
67
+ tooltip: allowViewReadonlyColumns
68
+ ? requiredTooltip || "Read only"
69
+ : "Read only (premium feature)",
70
+ disabled: !allowViewReadonlyColumns || isRequired,
71
+ })
72
+ }
73
+
74
+ options.push({
36
75
  icon: "VisibilityOff",
37
76
  value: PERMISSION_OPTIONS.HIDDEN,
38
- tooltip: "Hidden",
39
- },
40
- ]
77
+ disabled: isDisplayColumn || isRequired,
78
+ tooltip:
79
+ (isDisplayColumn && "Display column cannot be hidden") ||
80
+ requiredTooltip ||
81
+ "Hidden",
82
+ })
83
+
84
+ return { ...c, options }
85
+ })
41
86
 
42
87
  function columnToPermissionOptions(column) {
43
- if (!column.visible) {
88
+ if (!column.schema.visible) {
44
89
  return PERMISSION_OPTIONS.HIDDEN
45
90
  }
46
91
 
92
+ if (column.schema.readonly) {
93
+ return PERMISSION_OPTIONS.READONLY
94
+ }
95
+
47
96
  return PERMISSION_OPTIONS.WRITABLE
48
97
  }
49
98
  </script>
@@ -54,7 +103,7 @@
54
103
  quiet
55
104
  size="M"
56
105
  on:click={() => (open = !open)}
57
- selected={open || anyHidden}
106
+ selected={open || anyRestricted}
58
107
  disabled={!$columns.length}
59
108
  >
60
109
  {text}
@@ -64,19 +113,7 @@
64
113
  <Popover bind:open {anchor} align="left">
65
114
  <div class="content">
66
115
  <div class="columns">
67
- {#if $stickyColumn}
68
- <div class="column">
69
- <Icon size="S" name={getColumnIcon($stickyColumn)} />
70
- {$stickyColumn.label}
71
- </div>
72
-
73
- <ToggleActionButtonGroup
74
- disabled
75
- value={PERMISSION_OPTIONS.WRITABLE}
76
- {options}
77
- />
78
- {/if}
79
- {#each $columns as column}
116
+ {#each displayColumns as column}
80
117
  <div class="column">
81
118
  <Icon size="S" name={getColumnIcon(column)} />
82
119
  {column.label}
@@ -84,7 +121,7 @@
84
121
  <ToggleActionButtonGroup
85
122
  on:click={e => toggleColumn(column, e.detail)}
86
123
  value={columnToPermissionOptions(column)}
87
- {options}
124
+ options={column.options}
88
125
  />
89
126
  {/each}
90
127
  </div>
@@ -7,7 +7,6 @@
7
7
 
8
8
  export let value
9
9
  export let options
10
- export let disabled
11
10
  </script>
12
11
 
13
12
  <div class="permissionPicker">
@@ -15,7 +14,7 @@
15
14
  <AbsTooltip text={option.tooltip} type={TooltipType.Info}>
16
15
  <ActionButton
17
16
  on:click={() => dispatch("click", option.value)}
18
- {disabled}
17
+ disabled={option.disabled}
19
18
  size="S"
20
19
  icon={option.icon}
21
20
  quiet
@@ -57,6 +57,7 @@
57
57
  export let buttons = null
58
58
  export let darkMode
59
59
  export let isCloud = null
60
+ export let allowViewReadonlyColumns = false
60
61
 
61
62
  // Unique identifier for DOM nodes inside this instance
62
63
  const gridID = `grid-${Math.random().toString().slice(2)}`
@@ -153,7 +154,7 @@
153
154
  <div class="controls-left">
154
155
  <slot name="filter" />
155
156
  <SortButton />
156
- <ColumnsSettingButton />
157
+ <ColumnsSettingButton {allowViewReadonlyColumns} />
157
158
  <SizeButton />
158
159
  <slot name="controls" />
159
160
  </div>
@@ -146,6 +146,7 @@ export const initialise = context => {
146
146
  schema: fieldSchema,
147
147
  width: fieldSchema.width || oldColumn?.width || DefaultColumnWidth,
148
148
  visible: fieldSchema.visible ?? true,
149
+ readonly: fieldSchema.readonly,
149
150
  order: fieldSchema.order ?? oldColumn?.order,
150
151
  primaryDisplay: field === primaryDisplay,
151
152
  }
@@ -204,6 +204,10 @@ export const createActions = context => {
204
204
  ...$definition,
205
205
  schema: newSchema,
206
206
  })
207
+ resetSchemaMutations()
208
+ }
209
+
210
+ const resetSchemaMutations = () => {
207
211
  schemaMutations.set({})
208
212
  }
209
213
 
@@ -253,6 +257,7 @@ export const createActions = context => {
253
257
  addSchemaMutation,
254
258
  addSchemaMutations,
255
259
  saveSchemaMutations,
260
+ resetSchemaMutations,
256
261
  },
257
262
  },
258
263
  }