Ensure 'table' type settings are migrated and handled properly. Allow deleting rows from views
This commit is contained in:
parent
b6e675e3ff
commit
c78fcb2ba6
|
@ -1,12 +1,20 @@
|
|||
<script>
|
||||
import { Select, Label, Checkbox, Input, Body } from "@budibase/bbui"
|
||||
import { tables } from "stores/backend"
|
||||
import { tables as tablesStore, viewsV2 } from "stores/backend"
|
||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||
|
||||
export let parameters
|
||||
export let bindings = []
|
||||
|
||||
$: tableOptions = $tables.list || []
|
||||
$: tables = $tablesStore.list.map(table => ({
|
||||
label: table.name,
|
||||
resourceId: table._id,
|
||||
}))
|
||||
$: views = $viewsV2.list.map(view => ({
|
||||
label: view.name,
|
||||
resourceId: view.id,
|
||||
}))
|
||||
$: options = [...(tables || []), ...(views || [])]
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
|
@ -15,9 +23,9 @@
|
|||
<Label>Table</Label>
|
||||
<Select
|
||||
bind:value={parameters.tableId}
|
||||
options={tableOptions}
|
||||
getOptionLabel={table => table.name}
|
||||
getOptionValue={table => table._id}
|
||||
{options}
|
||||
getOptionLabel={x => x.label}
|
||||
getOptionValue={x => x.resourceId}
|
||||
/>
|
||||
|
||||
<Label small>Row IDs</Label>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { Select } from "@budibase/bbui"
|
||||
import { createEventDispatcher, onMount } from "svelte"
|
||||
import { tables as tablesStore } from "stores/backend"
|
||||
import { tables as tablesStore, viewsV2 } from "stores/backend"
|
||||
|
||||
export let value
|
||||
|
||||
|
@ -11,36 +11,28 @@
|
|||
...table,
|
||||
type: "table",
|
||||
label: table.name,
|
||||
key: table._id,
|
||||
resourceId: table._id,
|
||||
}))
|
||||
$: views = $viewsV2.list.map(view => ({
|
||||
...view,
|
||||
type: "viewV2",
|
||||
label: view.name,
|
||||
resourceId: view.id,
|
||||
}))
|
||||
$: views = $tablesStore.list.reduce(
|
||||
(acc, table) => [
|
||||
...acc,
|
||||
...Object.values(table.views || {})
|
||||
.filter(view => view.version === 2)
|
||||
.map(view => ({
|
||||
...view,
|
||||
type: "viewV2",
|
||||
label: view.name,
|
||||
key: view.id,
|
||||
})),
|
||||
],
|
||||
[]
|
||||
)
|
||||
$: options = [...(tables || []), ...(views || [])]
|
||||
|
||||
const onChange = e => {
|
||||
dispatch(
|
||||
"change",
|
||||
options.find(x => x.key === e.detail)
|
||||
options.find(x => x.resourceId === e.detail)
|
||||
)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// Migrate old values before "key" existed
|
||||
if (value && !value.key) {
|
||||
const view = views.find(x => x.key === value.id)
|
||||
const table = tables.find(x => x.key === value._id)
|
||||
// Migrate old values before "resourceId" existed
|
||||
if (value && !value.resourceId) {
|
||||
const view = views.find(x => x.resourceId === value.id)
|
||||
const table = tables.find(x => x.resourceId === value._id)
|
||||
dispatch("change", view || table)
|
||||
}
|
||||
})
|
||||
|
@ -48,8 +40,8 @@
|
|||
|
||||
<Select
|
||||
on:change={onChange}
|
||||
value={value?.key}
|
||||
value={value?.resourceId}
|
||||
{options}
|
||||
getOptionValue={x => x.key}
|
||||
getOptionValue={x => x.resourceId}
|
||||
getOptionLabel={x => x.label}
|
||||
/>
|
||||
|
|
|
@ -272,12 +272,36 @@
|
|||
return missing
|
||||
})
|
||||
|
||||
// Run any migrations
|
||||
runMigrations(instance, settingsDefinition)
|
||||
|
||||
// Force an initial enrichment of the new settings
|
||||
enrichComponentSettings(get(context), settingsDefinitionMap, {
|
||||
force: true,
|
||||
})
|
||||
}
|
||||
|
||||
const runMigrations = (instance, settingsDefinition) => {
|
||||
settingsDefinition.forEach(setting => {
|
||||
// Migrate "table" settings to ensure they have a type and resource ID
|
||||
if (setting.type === "table") {
|
||||
const val = instance[setting.key]
|
||||
if (val) {
|
||||
if (!val.type) {
|
||||
val.type = "table"
|
||||
}
|
||||
if (!val.resourceId) {
|
||||
if (val.type === "viewV2") {
|
||||
val.resourceId = val.id || val.tableId
|
||||
} else {
|
||||
val.resourceId = val.tableId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getSettingsDefinitionMap = settingsDefinition => {
|
||||
let map = {}
|
||||
settingsDefinition?.forEach(setting => {
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
|
||||
$: formattedFields = convertOldFieldFormat(fields)
|
||||
$: fieldsOrDefault = getDefaultFields(formattedFields, schema)
|
||||
|
||||
$: fetchSchema(dataSource)
|
||||
$: dataProvider = `{{ literal ${safe(providerId)} }}`
|
||||
$: filter = [
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"##eventHandlerType": "Save Row",
|
||||
parameters: {
|
||||
providerId: formId,
|
||||
tableId: dataSource?.tableId,
|
||||
tableId: dataSource?.resourceId,
|
||||
notificationOverride,
|
||||
},
|
||||
},
|
||||
|
@ -80,7 +80,7 @@
|
|||
"##eventHandlerType": "Delete Row",
|
||||
parameters: {
|
||||
confirm: true,
|
||||
tableId: dataSource?.tableId,
|
||||
tableId: dataSource?.resourceId,
|
||||
rowId: `{{ ${safe(repeaterId)}.${safe("_id")} }}`,
|
||||
revId: `{{ ${safe(repeaterId)}.${safe("_rev")} }}`,
|
||||
notificationOverride,
|
||||
|
|
|
@ -35,7 +35,7 @@ export const buildRowEndpoints = API => ({
|
|||
* @param suppressErrors whether or not to suppress error notifications
|
||||
*/
|
||||
patchRow: async (row, suppressErrors = false) => {
|
||||
if (!row?.tableId) {
|
||||
if (!row?.tableId && !row?._viewId) {
|
||||
return
|
||||
}
|
||||
return await API.patch({
|
||||
|
@ -47,7 +47,7 @@ export const buildRowEndpoints = API => ({
|
|||
|
||||
/**
|
||||
* Deletes a row from a table.
|
||||
* @param tableId the ID of the table to delete from
|
||||
* @param tableId the ID of the table or view to delete from
|
||||
* @param rowId the ID of the row to delete
|
||||
* @param revId the rev of the row to delete
|
||||
*/
|
||||
|
@ -66,10 +66,13 @@ export const buildRowEndpoints = API => ({
|
|||
|
||||
/**
|
||||
* Deletes multiple rows from a table.
|
||||
* @param tableId the table ID to delete the rows from
|
||||
* @param tableId the table or view ID to delete the rows from
|
||||
* @param rows the array of rows to delete
|
||||
*/
|
||||
deleteRows: async ({ tableId, rows }) => {
|
||||
rows?.forEach(row => {
|
||||
delete row?._viewId
|
||||
})
|
||||
return await API.delete({
|
||||
url: `/api/${tableId}/rows`,
|
||||
body: {
|
||||
|
|
|
@ -69,52 +69,4 @@ export const buildViewV2Endpoints = API => ({
|
|||
delete: async viewId => {
|
||||
return await API.delete({ url: `/api/v2/views/${viewId}` })
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a row from a view
|
||||
* @param row the row to create
|
||||
* @param suppressErrors whether or not to suppress error notifications
|
||||
*/
|
||||
createRow: async (row, suppressErrors = false) => {
|
||||
if (!row?._viewId || !row?.tableId) {
|
||||
return
|
||||
}
|
||||
return await API.post({
|
||||
url: `/api/v2/views/${row._viewId}/rows`,
|
||||
body: row,
|
||||
suppressErrors,
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Updates an existing row through a view
|
||||
* @param row the row to update
|
||||
* @param suppressErrors whether or not to suppress error notifications
|
||||
*/
|
||||
updateRow: async (row, suppressErrors = false) => {
|
||||
if (!row?._viewId || !row?.tableId || !row?._id) {
|
||||
return
|
||||
}
|
||||
return await API.patch({
|
||||
url: `/api/v2/views/${row._viewId}/rows/${row._id}`,
|
||||
body: row,
|
||||
suppressErrors,
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Deletes multiple rows from a table through a view
|
||||
* @param viewId the table ID to delete the rows from
|
||||
* @param rows the array of rows to delete
|
||||
*/
|
||||
deleteRows: async ({ viewId, rows }) => {
|
||||
// Ensure we delete _viewId from rows as otherwise this throws a 500
|
||||
rows?.forEach(row => {
|
||||
delete row?._viewId
|
||||
})
|
||||
return await API.delete({
|
||||
url: `/api/v2/views/${viewId}/rows`,
|
||||
body: {
|
||||
rows,
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue