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>
|
<script>
|
||||||
import { Select, Label, Checkbox, Input, Body } from "@budibase/bbui"
|
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"
|
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||||
|
|
||||||
export let parameters
|
export let parameters
|
||||||
export let bindings = []
|
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>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -15,9 +23,9 @@
|
||||||
<Label>Table</Label>
|
<Label>Table</Label>
|
||||||
<Select
|
<Select
|
||||||
bind:value={parameters.tableId}
|
bind:value={parameters.tableId}
|
||||||
options={tableOptions}
|
{options}
|
||||||
getOptionLabel={table => table.name}
|
getOptionLabel={x => x.label}
|
||||||
getOptionValue={table => table._id}
|
getOptionValue={x => x.resourceId}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Label small>Row IDs</Label>
|
<Label small>Row IDs</Label>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { Select } from "@budibase/bbui"
|
import { Select } from "@budibase/bbui"
|
||||||
import { createEventDispatcher, onMount } from "svelte"
|
import { createEventDispatcher, onMount } from "svelte"
|
||||||
import { tables as tablesStore } from "stores/backend"
|
import { tables as tablesStore, viewsV2 } from "stores/backend"
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
|
|
||||||
|
@ -11,36 +11,28 @@
|
||||||
...table,
|
...table,
|
||||||
type: "table",
|
type: "table",
|
||||||
label: table.name,
|
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 || [])]
|
$: options = [...(tables || []), ...(views || [])]
|
||||||
|
|
||||||
const onChange = e => {
|
const onChange = e => {
|
||||||
dispatch(
|
dispatch(
|
||||||
"change",
|
"change",
|
||||||
options.find(x => x.key === e.detail)
|
options.find(x => x.resourceId === e.detail)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Migrate old values before "key" existed
|
// Migrate old values before "resourceId" existed
|
||||||
if (value && !value.key) {
|
if (value && !value.resourceId) {
|
||||||
const view = views.find(x => x.key === value.id)
|
const view = views.find(x => x.resourceId === value.id)
|
||||||
const table = tables.find(x => x.key === value._id)
|
const table = tables.find(x => x.resourceId === value._id)
|
||||||
dispatch("change", view || table)
|
dispatch("change", view || table)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -48,8 +40,8 @@
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
on:change={onChange}
|
on:change={onChange}
|
||||||
value={value?.key}
|
value={value?.resourceId}
|
||||||
{options}
|
{options}
|
||||||
getOptionValue={x => x.key}
|
getOptionValue={x => x.resourceId}
|
||||||
getOptionLabel={x => x.label}
|
getOptionLabel={x => x.label}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -272,12 +272,36 @@
|
||||||
return missing
|
return missing
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Run any migrations
|
||||||
|
runMigrations(instance, settingsDefinition)
|
||||||
|
|
||||||
// Force an initial enrichment of the new settings
|
// Force an initial enrichment of the new settings
|
||||||
enrichComponentSettings(get(context), settingsDefinitionMap, {
|
enrichComponentSettings(get(context), settingsDefinitionMap, {
|
||||||
force: true,
|
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 => {
|
const getSettingsDefinitionMap = settingsDefinition => {
|
||||||
let map = {}
|
let map = {}
|
||||||
settingsDefinition?.forEach(setting => {
|
settingsDefinition?.forEach(setting => {
|
||||||
|
|
|
@ -56,7 +56,6 @@
|
||||||
|
|
||||||
$: formattedFields = convertOldFieldFormat(fields)
|
$: formattedFields = convertOldFieldFormat(fields)
|
||||||
$: fieldsOrDefault = getDefaultFields(formattedFields, schema)
|
$: fieldsOrDefault = getDefaultFields(formattedFields, schema)
|
||||||
|
|
||||||
$: fetchSchema(dataSource)
|
$: fetchSchema(dataSource)
|
||||||
$: dataProvider = `{{ literal ${safe(providerId)} }}`
|
$: dataProvider = `{{ literal ${safe(providerId)} }}`
|
||||||
$: filter = [
|
$: filter = [
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
"##eventHandlerType": "Save Row",
|
"##eventHandlerType": "Save Row",
|
||||||
parameters: {
|
parameters: {
|
||||||
providerId: formId,
|
providerId: formId,
|
||||||
tableId: dataSource?.tableId,
|
tableId: dataSource?.resourceId,
|
||||||
notificationOverride,
|
notificationOverride,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
"##eventHandlerType": "Delete Row",
|
"##eventHandlerType": "Delete Row",
|
||||||
parameters: {
|
parameters: {
|
||||||
confirm: true,
|
confirm: true,
|
||||||
tableId: dataSource?.tableId,
|
tableId: dataSource?.resourceId,
|
||||||
rowId: `{{ ${safe(repeaterId)}.${safe("_id")} }}`,
|
rowId: `{{ ${safe(repeaterId)}.${safe("_id")} }}`,
|
||||||
revId: `{{ ${safe(repeaterId)}.${safe("_rev")} }}`,
|
revId: `{{ ${safe(repeaterId)}.${safe("_rev")} }}`,
|
||||||
notificationOverride,
|
notificationOverride,
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const buildRowEndpoints = API => ({
|
||||||
* @param suppressErrors whether or not to suppress error notifications
|
* @param suppressErrors whether or not to suppress error notifications
|
||||||
*/
|
*/
|
||||||
patchRow: async (row, suppressErrors = false) => {
|
patchRow: async (row, suppressErrors = false) => {
|
||||||
if (!row?.tableId) {
|
if (!row?.tableId && !row?._viewId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return await API.patch({
|
return await API.patch({
|
||||||
|
@ -47,7 +47,7 @@ export const buildRowEndpoints = API => ({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a row from a table.
|
* 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 rowId the ID of the row to delete
|
||||||
* @param revId the rev 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.
|
* 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
|
* @param rows the array of rows to delete
|
||||||
*/
|
*/
|
||||||
deleteRows: async ({ tableId, rows }) => {
|
deleteRows: async ({ tableId, rows }) => {
|
||||||
|
rows?.forEach(row => {
|
||||||
|
delete row?._viewId
|
||||||
|
})
|
||||||
return await API.delete({
|
return await API.delete({
|
||||||
url: `/api/${tableId}/rows`,
|
url: `/api/${tableId}/rows`,
|
||||||
body: {
|
body: {
|
||||||
|
|
|
@ -69,52 +69,4 @@ export const buildViewV2Endpoints = API => ({
|
||||||
delete: async viewId => {
|
delete: async viewId => {
|
||||||
return await API.delete({ url: `/api/v2/views/${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