@budibase/frontend-core 2.9.38 → 2.9.39-alpha.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 +4 -4
- package/src/api/groups.js +22 -0
- package/src/api/index.js +2 -0
- package/src/api/permissions.js +23 -0
- package/src/api/rows.js +22 -3
- package/src/api/user.js +27 -4
- package/src/api/viewsV2.js +72 -0
- package/src/components/grid/cells/DataCell.svelte +8 -3
- package/src/components/grid/cells/GutterCell.svelte +4 -4
- package/src/components/grid/cells/HeaderCell.svelte +3 -3
- package/src/components/grid/controls/HideColumnsButton.svelte +10 -7
- package/src/components/grid/controls/SizeButton.svelte +10 -4
- package/src/components/grid/controls/SortButton.svelte +12 -34
- package/src/components/grid/layout/Grid.svelte +22 -17
- package/src/components/grid/layout/GridBody.svelte +2 -2
- package/src/components/grid/layout/HeaderRow.svelte +3 -4
- package/src/components/grid/layout/NewColumnButton.svelte +3 -2
- package/src/components/grid/layout/NewRow.svelte +6 -6
- package/src/components/grid/layout/StickyColumn.svelte +2 -2
- package/src/components/grid/lib/websocket.js +18 -12
- package/src/components/grid/overlays/KeyboardManager.svelte +12 -11
- package/src/components/grid/overlays/MenuOverlay.svelte +3 -6
- package/src/components/grid/stores/clipboard.js +1 -1
- package/src/components/grid/stores/columns.js +39 -99
- package/src/components/grid/stores/config.js +33 -6
- package/src/components/grid/stores/datasource.js +131 -0
- package/src/components/grid/stores/filter.js +2 -2
- package/src/components/grid/stores/index.js +14 -3
- package/src/components/grid/stores/menu.js +1 -1
- package/src/components/grid/stores/pagination.js +3 -4
- package/src/components/grid/stores/reorder.js +1 -1
- package/src/components/grid/stores/resize.js +1 -1
- package/src/components/grid/stores/rows.js +61 -101
- package/src/components/grid/stores/sort.js +29 -6
- package/src/components/grid/stores/table.js +129 -0
- package/src/components/grid/stores/ui.js +24 -36
- package/src/components/grid/stores/users.js +8 -1
- package/src/components/grid/stores/viewV2.js +212 -0
- package/src/components/grid/stores/viewport.js +4 -4
- package/src/constants.js +21 -13
- package/src/fetch/DataFetch.js +35 -24
- package/src/fetch/QueryFetch.js +4 -0
- package/src/fetch/ViewV2Fetch.js +65 -0
- package/src/fetch/fetchData.js +2 -0
- package/src/utils/roles.js +5 -3
|
@@ -14,7 +14,7 @@ export const createStores = context => {
|
|
|
14
14
|
const focusedCellAPI = writable(null)
|
|
15
15
|
const selectedRows = writable({})
|
|
16
16
|
const hoveredRowId = writable(null)
|
|
17
|
-
const rowHeight = writable(props.fixedRowHeight || DefaultRowHeight)
|
|
17
|
+
const rowHeight = writable(get(props).fixedRowHeight || DefaultRowHeight)
|
|
18
18
|
const previousFocusedRowId = writable(null)
|
|
19
19
|
const gridFocused = writable(false)
|
|
20
20
|
const isDragging = writable(false)
|
|
@@ -61,23 +61,13 @@ export const createStores = context => {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
export const deriveStores = context => {
|
|
64
|
-
const {
|
|
65
|
-
|
|
66
|
-
selectedRows,
|
|
67
|
-
hoveredRowId,
|
|
68
|
-
enrichedRows,
|
|
69
|
-
rowLookupMap,
|
|
70
|
-
rowHeight,
|
|
71
|
-
stickyColumn,
|
|
72
|
-
width,
|
|
73
|
-
hasNonAutoColumn,
|
|
74
|
-
config,
|
|
75
|
-
} = context
|
|
64
|
+
const { focusedCellId, rows, rowLookupMap, rowHeight, stickyColumn, width } =
|
|
65
|
+
context
|
|
76
66
|
|
|
77
67
|
// Derive the row that contains the selected cell
|
|
78
68
|
const focusedRow = derived(
|
|
79
|
-
[focusedCellId, rowLookupMap,
|
|
80
|
-
([$focusedCellId, $rowLookupMap, $
|
|
69
|
+
[focusedCellId, rowLookupMap, rows],
|
|
70
|
+
([$focusedCellId, $rowLookupMap, $rows]) => {
|
|
81
71
|
const rowId = $focusedCellId?.split("-")[0]
|
|
82
72
|
|
|
83
73
|
// Edge case for new rows
|
|
@@ -87,18 +77,11 @@ export const deriveStores = context => {
|
|
|
87
77
|
|
|
88
78
|
// All normal rows
|
|
89
79
|
const index = $rowLookupMap[rowId]
|
|
90
|
-
return $
|
|
80
|
+
return $rows[index]
|
|
91
81
|
},
|
|
92
82
|
null
|
|
93
83
|
)
|
|
94
84
|
|
|
95
|
-
// Callback when leaving the grid, deselecting all focussed or selected items
|
|
96
|
-
const blur = () => {
|
|
97
|
-
focusedCellId.set(null)
|
|
98
|
-
selectedRows.set({})
|
|
99
|
-
hoveredRowId.set(null)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
85
|
// Derive the amount of content lines to show in cells depending on row height
|
|
103
86
|
const contentLines = derived(rowHeight, $rowHeight => {
|
|
104
87
|
if ($rowHeight >= LargeRowHeight) {
|
|
@@ -114,19 +97,24 @@ export const deriveStores = context => {
|
|
|
114
97
|
return ($stickyColumn?.width || 0) + $width + GutterWidth < 1100
|
|
115
98
|
})
|
|
116
99
|
|
|
117
|
-
// Derive if we're able to add rows
|
|
118
|
-
const canAddRows = derived(
|
|
119
|
-
[config, hasNonAutoColumn],
|
|
120
|
-
([$config, $hasNonAutoColumn]) => {
|
|
121
|
-
return $config.allowAddRows && $hasNonAutoColumn
|
|
122
|
-
}
|
|
123
|
-
)
|
|
124
|
-
|
|
125
100
|
return {
|
|
126
|
-
canAddRows,
|
|
127
101
|
focusedRow,
|
|
128
102
|
contentLines,
|
|
129
103
|
compact,
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const createActions = context => {
|
|
108
|
+
const { focusedCellId, selectedRows, hoveredRowId } = context
|
|
109
|
+
|
|
110
|
+
// Callback when leaving the grid, deselecting all focussed or selected items
|
|
111
|
+
const blur = () => {
|
|
112
|
+
focusedCellId.set(null)
|
|
113
|
+
selectedRows.set({})
|
|
114
|
+
hoveredRowId.set(null)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
130
118
|
ui: {
|
|
131
119
|
actions: {
|
|
132
120
|
blur,
|
|
@@ -143,7 +131,7 @@ export const initialise = context => {
|
|
|
143
131
|
focusedCellId,
|
|
144
132
|
selectedRows,
|
|
145
133
|
hoveredRowId,
|
|
146
|
-
|
|
134
|
+
definition,
|
|
147
135
|
rowHeight,
|
|
148
136
|
fixedRowHeight,
|
|
149
137
|
} = context
|
|
@@ -199,9 +187,9 @@ export const initialise = context => {
|
|
|
199
187
|
})
|
|
200
188
|
|
|
201
189
|
// Pull row height from table as long as we don't have a fixed height
|
|
202
|
-
|
|
190
|
+
definition.subscribe($definition => {
|
|
203
191
|
if (!get(fixedRowHeight)) {
|
|
204
|
-
rowHeight.set($
|
|
192
|
+
rowHeight.set($definition?.rowHeight || DefaultRowHeight)
|
|
205
193
|
}
|
|
206
194
|
})
|
|
207
195
|
|
|
@@ -210,7 +198,7 @@ export const initialise = context => {
|
|
|
210
198
|
if (height) {
|
|
211
199
|
rowHeight.set(height)
|
|
212
200
|
} else {
|
|
213
|
-
rowHeight.set(get(
|
|
201
|
+
rowHeight.set(get(definition)?.rowHeight || DefaultRowHeight)
|
|
214
202
|
}
|
|
215
203
|
})
|
|
216
204
|
}
|
|
@@ -39,6 +39,14 @@ export const deriveStores = context => {
|
|
|
39
39
|
}
|
|
40
40
|
)
|
|
41
41
|
|
|
42
|
+
return {
|
|
43
|
+
selectedCellMap,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const createActions = context => {
|
|
48
|
+
const { users } = context
|
|
49
|
+
|
|
42
50
|
const updateUser = user => {
|
|
43
51
|
const $users = get(users)
|
|
44
52
|
if (!$users.some(x => x.sessionId === user.sessionId)) {
|
|
@@ -66,6 +74,5 @@ export const deriveStores = context => {
|
|
|
66
74
|
removeUser,
|
|
67
75
|
},
|
|
68
76
|
},
|
|
69
|
-
selectedCellMap,
|
|
70
77
|
}
|
|
71
78
|
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { get } from "svelte/store"
|
|
2
|
+
|
|
3
|
+
const SuppressErrors = true
|
|
4
|
+
|
|
5
|
+
export const createActions = context => {
|
|
6
|
+
const { definition, API, datasource, columns, stickyColumn } = context
|
|
7
|
+
|
|
8
|
+
const refreshDefinition = async () => {
|
|
9
|
+
const $datasource = get(datasource)
|
|
10
|
+
if (!$datasource) {
|
|
11
|
+
definition.set(null)
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
const table = await API.fetchTableDefinition($datasource.tableId)
|
|
15
|
+
const view = Object.values(table?.views || {}).find(
|
|
16
|
+
view => view.id === $datasource.id
|
|
17
|
+
)
|
|
18
|
+
definition.set(view)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const saveDefinition = async newDefinition => {
|
|
22
|
+
await API.viewV2.update(newDefinition)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const saveRow = async row => {
|
|
26
|
+
const $datasource = get(datasource)
|
|
27
|
+
row.tableId = $datasource?.tableId
|
|
28
|
+
row._viewId = $datasource?.id
|
|
29
|
+
return {
|
|
30
|
+
...(await API.saveRow(row, SuppressErrors)),
|
|
31
|
+
_viewId: row._viewId,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const deleteRows = async rows => {
|
|
36
|
+
await API.deleteRows({
|
|
37
|
+
tableId: get(datasource).id,
|
|
38
|
+
rows,
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const getRow = () => {
|
|
43
|
+
throw "Views don't support fetching individual rows"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const isDatasourceValid = datasource => {
|
|
47
|
+
return (
|
|
48
|
+
datasource?.type === "viewV2" && datasource?.id && datasource?.tableId
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const canUseColumn = name => {
|
|
53
|
+
const $columns = get(columns)
|
|
54
|
+
const $sticky = get(stickyColumn)
|
|
55
|
+
return (
|
|
56
|
+
$columns.some(col => col.name === name && col.visible) ||
|
|
57
|
+
$sticky?.name === name
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
viewV2: {
|
|
63
|
+
actions: {
|
|
64
|
+
refreshDefinition,
|
|
65
|
+
saveDefinition,
|
|
66
|
+
addRow: saveRow,
|
|
67
|
+
updateRow: saveRow,
|
|
68
|
+
deleteRows,
|
|
69
|
+
getRow,
|
|
70
|
+
isDatasourceValid,
|
|
71
|
+
canUseColumn,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const initialise = context => {
|
|
78
|
+
const {
|
|
79
|
+
definition,
|
|
80
|
+
datasource,
|
|
81
|
+
sort,
|
|
82
|
+
rows,
|
|
83
|
+
filter,
|
|
84
|
+
subscribe,
|
|
85
|
+
viewV2,
|
|
86
|
+
initialFilter,
|
|
87
|
+
initialSortColumn,
|
|
88
|
+
initialSortOrder,
|
|
89
|
+
config,
|
|
90
|
+
fetch,
|
|
91
|
+
} = context
|
|
92
|
+
|
|
93
|
+
// Keep a list of subscriptions so that we can clear them when the datasource
|
|
94
|
+
// config changes
|
|
95
|
+
let unsubscribers = []
|
|
96
|
+
|
|
97
|
+
// Observe datasource changes and apply logic for view V2 datasources
|
|
98
|
+
datasource.subscribe($datasource => {
|
|
99
|
+
// Clear previous subscriptions
|
|
100
|
+
unsubscribers?.forEach(unsubscribe => unsubscribe())
|
|
101
|
+
unsubscribers = []
|
|
102
|
+
if (!viewV2.actions.isDatasourceValid($datasource)) {
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Reset state for new view
|
|
107
|
+
filter.set(get(initialFilter))
|
|
108
|
+
sort.set({
|
|
109
|
+
column: get(initialSortColumn),
|
|
110
|
+
order: get(initialSortOrder) || "ascending",
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Keep sort and filter state in line with the view definition
|
|
114
|
+
unsubscribers.push(
|
|
115
|
+
definition.subscribe($definition => {
|
|
116
|
+
if ($definition?.id !== $datasource.id) {
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
// Only override sorting if we don't have an initial sort column
|
|
120
|
+
if (!get(initialSortColumn)) {
|
|
121
|
+
sort.set({
|
|
122
|
+
column: $definition.sort?.field,
|
|
123
|
+
order: $definition.sort?.order || "ascending",
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
// Only override filter state if we don't have an initial filter
|
|
127
|
+
if (!get(initialFilter)) {
|
|
128
|
+
filter.set($definition.query)
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
// When sorting changes, ensure view definition is kept up to date
|
|
134
|
+
unsubscribers.push(
|
|
135
|
+
sort.subscribe(async $sort => {
|
|
136
|
+
// If we can mutate schema then update the view definition
|
|
137
|
+
if (get(config).canSaveSchema) {
|
|
138
|
+
// Ensure we're updating the correct view
|
|
139
|
+
const $view = get(definition)
|
|
140
|
+
if ($view?.id !== $datasource.id) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
if (
|
|
144
|
+
$sort?.column !== $view.sort?.field ||
|
|
145
|
+
$sort?.order !== $view.sort?.order
|
|
146
|
+
) {
|
|
147
|
+
await datasource.actions.saveDefinition({
|
|
148
|
+
...$view,
|
|
149
|
+
sort: {
|
|
150
|
+
field: $sort.column,
|
|
151
|
+
order: $sort.order || "ascending",
|
|
152
|
+
},
|
|
153
|
+
})
|
|
154
|
+
await rows.actions.refreshData()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Otherwise just update the fetch
|
|
158
|
+
else {
|
|
159
|
+
// Ensure we're updating the correct fetch
|
|
160
|
+
const $fetch = get(fetch)
|
|
161
|
+
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
$fetch.update({
|
|
165
|
+
sortOrder: $sort.order || "ascending",
|
|
166
|
+
sortColumn: $sort.column,
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
// When filters change, ensure view definition is kept up to date
|
|
173
|
+
unsubscribers?.push(
|
|
174
|
+
filter.subscribe(async $filter => {
|
|
175
|
+
// If we can mutate schema then update the view definition
|
|
176
|
+
if (get(config).canSaveSchema) {
|
|
177
|
+
// Ensure we're updating the correct view
|
|
178
|
+
const $view = get(definition)
|
|
179
|
+
if ($view?.id !== $datasource.id) {
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
if (JSON.stringify($filter) !== JSON.stringify($view.query)) {
|
|
183
|
+
await datasource.actions.saveDefinition({
|
|
184
|
+
...$view,
|
|
185
|
+
query: $filter,
|
|
186
|
+
})
|
|
187
|
+
await rows.actions.refreshData()
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Otherwise just update the fetch
|
|
191
|
+
else {
|
|
192
|
+
// Ensure we're updating the correct fetch
|
|
193
|
+
const $fetch = get(fetch)
|
|
194
|
+
if ($fetch?.options?.datasource?.tableId !== $datasource.tableId) {
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
$fetch.update({
|
|
198
|
+
filter: $filter,
|
|
199
|
+
})
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
// When hidden we show columns, we need to refresh data in order to fetch
|
|
205
|
+
// values for those columns
|
|
206
|
+
unsubscribers.push(
|
|
207
|
+
subscribe("show-column", async () => {
|
|
208
|
+
await rows.actions.refreshData()
|
|
209
|
+
})
|
|
210
|
+
)
|
|
211
|
+
})
|
|
212
|
+
}
|
|
@@ -10,7 +10,7 @@ export const deriveStores = context => {
|
|
|
10
10
|
const {
|
|
11
11
|
rowHeight,
|
|
12
12
|
visibleColumns,
|
|
13
|
-
|
|
13
|
+
rows,
|
|
14
14
|
scrollTop,
|
|
15
15
|
scrollLeft,
|
|
16
16
|
width,
|
|
@@ -35,9 +35,9 @@ export const deriveStores = context => {
|
|
|
35
35
|
0
|
|
36
36
|
)
|
|
37
37
|
const renderedRows = derived(
|
|
38
|
-
[
|
|
39
|
-
([$
|
|
40
|
-
return $
|
|
38
|
+
[rows, scrolledRowCount, visualRowCapacity],
|
|
39
|
+
([$rows, $scrolledRowCount, $visualRowCapacity]) => {
|
|
40
|
+
return $rows.slice(
|
|
41
41
|
$scrolledRowCount,
|
|
42
42
|
$scrolledRowCount + $visualRowCapacity
|
|
43
43
|
)
|
package/src/constants.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Operator options for lucene queries
|
|
3
3
|
*/
|
|
4
4
|
export { OperatorOptions, SqlNumberTypeRangeMap } from "@budibase/shared-core"
|
|
5
|
+
export { Feature as Features } from "@budibase/types"
|
|
5
6
|
|
|
6
7
|
// Cookie names
|
|
7
8
|
export const Cookies = {
|
|
@@ -22,12 +23,29 @@ export const BudibaseRoles = {
|
|
|
22
23
|
Admin: "admin",
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
export const
|
|
26
|
-
{ label: "App User", value: BudibaseRoles.AppUser },
|
|
26
|
+
export const BudibaseRoleOptionsOld = [
|
|
27
27
|
{ label: "Developer", value: BudibaseRoles.Developer },
|
|
28
|
+
{ label: "Member", value: BudibaseRoles.AppUser },
|
|
29
|
+
{ label: "Admin", value: BudibaseRoles.Admin },
|
|
30
|
+
]
|
|
31
|
+
export const BudibaseRoleOptions = [
|
|
32
|
+
{ label: "Member", value: BudibaseRoles.AppUser },
|
|
28
33
|
{ label: "Admin", value: BudibaseRoles.Admin },
|
|
29
34
|
]
|
|
30
35
|
|
|
36
|
+
export const BudibaseRoleOptionsNew = [
|
|
37
|
+
{
|
|
38
|
+
label: "Admin",
|
|
39
|
+
value: "admin",
|
|
40
|
+
subtitle: "Has full access to all apps and settings in your account",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: "Member",
|
|
44
|
+
value: "appUser",
|
|
45
|
+
subtitle: "Can only view apps they have access to",
|
|
46
|
+
},
|
|
47
|
+
]
|
|
48
|
+
|
|
31
49
|
export const BuilderRoleDescriptions = [
|
|
32
50
|
{
|
|
33
51
|
value: BudibaseRoles.AppUser,
|
|
@@ -62,17 +80,6 @@ export const PlanType = {
|
|
|
62
80
|
*/
|
|
63
81
|
export const ApiVersion = "1"
|
|
64
82
|
|
|
65
|
-
export const Features = {
|
|
66
|
-
USER_GROUPS: "userGroups",
|
|
67
|
-
BACKUPS: "appBackups",
|
|
68
|
-
ENVIRONMENT_VARIABLES: "environmentVariables",
|
|
69
|
-
AUDIT_LOGS: "auditLogs",
|
|
70
|
-
ENFORCEABLE_SSO: "enforceableSSO",
|
|
71
|
-
BRANDING: "branding",
|
|
72
|
-
SCIM: "scim",
|
|
73
|
-
SYNC_AUTOMATIONS: "syncAutomations",
|
|
74
|
-
}
|
|
75
|
-
|
|
76
83
|
// Role IDs
|
|
77
84
|
export const Roles = {
|
|
78
85
|
ADMIN: "ADMIN",
|
|
@@ -80,6 +87,7 @@ export const Roles = {
|
|
|
80
87
|
BASIC: "BASIC",
|
|
81
88
|
PUBLIC: "PUBLIC",
|
|
82
89
|
BUILDER: "BUILDER",
|
|
90
|
+
CREATOR: "CREATOR",
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
export const Themes = [
|
package/src/fetch/DataFetch.js
CHANGED
|
@@ -110,14 +110,27 @@ export default class DataFetch {
|
|
|
110
110
|
return this.derivedStore.subscribe
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Gets the default sort column for this datasource
|
|
115
|
+
*/
|
|
116
|
+
getDefaultSortColumn(definition, schema) {
|
|
117
|
+
if (definition?.primaryDisplay && schema[definition.primaryDisplay]) {
|
|
118
|
+
return definition.primaryDisplay
|
|
119
|
+
} else {
|
|
120
|
+
return Object.keys(schema)[0]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
113
124
|
/**
|
|
114
125
|
* Fetches a fresh set of data from the server, resetting pagination
|
|
115
126
|
*/
|
|
116
127
|
async getInitialData() {
|
|
117
128
|
const { datasource, filter, paginate } = this.options
|
|
118
129
|
|
|
119
|
-
// Fetch datasource definition and
|
|
130
|
+
// Fetch datasource definition and extract sort properties if configured
|
|
120
131
|
const definition = await this.getDefinition(datasource)
|
|
132
|
+
|
|
133
|
+
// Determine feature flags
|
|
121
134
|
const features = this.determineFeatureFlags(definition)
|
|
122
135
|
this.features = {
|
|
123
136
|
supportsSearch: !!features?.supportsSearch,
|
|
@@ -132,32 +145,32 @@ export default class DataFetch {
|
|
|
132
145
|
return
|
|
133
146
|
}
|
|
134
147
|
|
|
135
|
-
// If
|
|
136
|
-
if (!this.options.
|
|
137
|
-
this.options.
|
|
148
|
+
// If an invalid sort column is specified, delete it
|
|
149
|
+
if (this.options.sortColumn && !schema[this.options.sortColumn]) {
|
|
150
|
+
this.options.sortColumn = null
|
|
138
151
|
}
|
|
139
152
|
|
|
140
|
-
// If no sort column,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (!sortValid) {
|
|
144
|
-
let newSortColumn
|
|
145
|
-
if (definition?.primaryDisplay && schema[definition.primaryDisplay]) {
|
|
146
|
-
newSortColumn = definition.primaryDisplay
|
|
147
|
-
} else {
|
|
148
|
-
newSortColumn = Object.keys(schema)[0]
|
|
149
|
-
}
|
|
150
|
-
this.options.sortColumn = newSortColumn
|
|
153
|
+
// If no sort column, get the default column for this datasource
|
|
154
|
+
if (!this.options.sortColumn) {
|
|
155
|
+
this.options.sortColumn = this.getDefaultSortColumn(definition, schema)
|
|
151
156
|
}
|
|
152
|
-
const { sortOrder, sortColumn } = this.options
|
|
153
157
|
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
if (sortColumn) {
|
|
157
|
-
|
|
158
|
-
sortType =
|
|
158
|
+
// If we don't have a sort column specified then just ensure we don't set
|
|
159
|
+
// any sorting params
|
|
160
|
+
if (!this.options.sortColumn) {
|
|
161
|
+
this.options.sortOrder = "ascending"
|
|
162
|
+
this.options.sortType = null
|
|
163
|
+
} else {
|
|
164
|
+
// Otherwise determine what sort type to use base on sort column
|
|
165
|
+
const type = schema?.[this.options.sortColumn]?.type
|
|
166
|
+
this.options.sortType =
|
|
167
|
+
type === "number" || type === "bigint" ? "number" : "string"
|
|
168
|
+
|
|
169
|
+
// If no sort order, default to ascending
|
|
170
|
+
if (!this.options.sortOrder) {
|
|
171
|
+
this.options.sortOrder = "ascending"
|
|
172
|
+
}
|
|
159
173
|
}
|
|
160
|
-
this.options.sortType = sortType
|
|
161
174
|
|
|
162
175
|
// Build the lucene query
|
|
163
176
|
let query = this.options.query
|
|
@@ -174,8 +187,6 @@ export default class DataFetch {
|
|
|
174
187
|
loading: true,
|
|
175
188
|
cursors: [],
|
|
176
189
|
cursor: null,
|
|
177
|
-
sortOrder,
|
|
178
|
-
sortColumn,
|
|
179
190
|
}))
|
|
180
191
|
|
|
181
192
|
// Actually fetch data
|
package/src/fetch/QueryFetch.js
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import DataFetch from "./DataFetch.js"
|
|
2
|
+
import { get } from "svelte/store"
|
|
3
|
+
|
|
4
|
+
export default class ViewV2Fetch extends DataFetch {
|
|
5
|
+
determineFeatureFlags() {
|
|
6
|
+
return {
|
|
7
|
+
supportsSearch: true,
|
|
8
|
+
supportsSort: true,
|
|
9
|
+
supportsPagination: true,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getSchema(datasource, definition) {
|
|
14
|
+
return definition?.schema
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async getDefinition(datasource) {
|
|
18
|
+
if (!datasource?.id) {
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const res = await this.API.viewV2.fetchDefinition(datasource.id)
|
|
23
|
+
return res?.data
|
|
24
|
+
} catch (error) {
|
|
25
|
+
this.store.update(state => ({
|
|
26
|
+
...state,
|
|
27
|
+
error,
|
|
28
|
+
}))
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getDefaultSortColumn() {
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async getData() {
|
|
38
|
+
const { datasource, limit, sortColumn, sortOrder, sortType, paginate } =
|
|
39
|
+
this.options
|
|
40
|
+
const { cursor, query } = get(this.store)
|
|
41
|
+
try {
|
|
42
|
+
const res = await this.API.viewV2.fetch({
|
|
43
|
+
viewId: datasource.id,
|
|
44
|
+
query,
|
|
45
|
+
paginate,
|
|
46
|
+
limit,
|
|
47
|
+
bookmark: cursor,
|
|
48
|
+
sort: sortColumn,
|
|
49
|
+
sortOrder: sortOrder?.toLowerCase(),
|
|
50
|
+
sortType,
|
|
51
|
+
})
|
|
52
|
+
return {
|
|
53
|
+
rows: res?.rows || [],
|
|
54
|
+
hasNextPage: res?.hasNextPage || false,
|
|
55
|
+
cursor: res?.bookmark || null,
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return {
|
|
59
|
+
rows: [],
|
|
60
|
+
hasNextPage: false,
|
|
61
|
+
error,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/fetch/fetchData.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import TableFetch from "./TableFetch.js"
|
|
2
2
|
import ViewFetch from "./ViewFetch.js"
|
|
3
|
+
import ViewV2Fetch from "./ViewV2Fetch.js"
|
|
3
4
|
import QueryFetch from "./QueryFetch.js"
|
|
4
5
|
import RelationshipFetch from "./RelationshipFetch.js"
|
|
5
6
|
import NestedProviderFetch from "./NestedProviderFetch.js"
|
|
@@ -11,6 +12,7 @@ import GroupUserFetch from "./GroupUserFetch.js"
|
|
|
11
12
|
const DataFetchMap = {
|
|
12
13
|
table: TableFetch,
|
|
13
14
|
view: ViewFetch,
|
|
15
|
+
viewV2: ViewV2Fetch,
|
|
14
16
|
query: QueryFetch,
|
|
15
17
|
link: RelationshipFetch,
|
|
16
18
|
user: UserFetch,
|
package/src/utils/roles.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { Roles } from "../constants"
|
|
2
2
|
|
|
3
3
|
const RolePriorities = {
|
|
4
|
-
[Roles.ADMIN]:
|
|
4
|
+
[Roles.ADMIN]: 5,
|
|
5
|
+
[Roles.CREATOR]: 4,
|
|
5
6
|
[Roles.POWER]: 3,
|
|
6
7
|
[Roles.BASIC]: 2,
|
|
7
8
|
[Roles.PUBLIC]: 1,
|
|
8
9
|
}
|
|
9
10
|
const RoleColours = {
|
|
10
11
|
[Roles.ADMIN]: "var(--spectrum-global-color-static-red-400)",
|
|
12
|
+
[Roles.CREATOR]: "var(--spectrum-global-color-static-magenta-600)",
|
|
11
13
|
[Roles.POWER]: "var(--spectrum-global-color-static-orange-400)",
|
|
12
14
|
[Roles.BASIC]: "var(--spectrum-global-color-static-green-400)",
|
|
13
15
|
[Roles.PUBLIC]: "var(--spectrum-global-color-static-blue-400)",
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
export const getRolePriority =
|
|
17
|
-
return RolePriorities[
|
|
18
|
+
export const getRolePriority = role => {
|
|
19
|
+
return RolePriorities[role] ?? 0
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export const getRoleColour = roleId => {
|