Add button action for duplicating a row
This commit is contained in:
parent
00179c8a33
commit
d36daaf9b9
|
@ -0,0 +1,152 @@
|
||||||
|
<script>
|
||||||
|
import { Select, Label, Body, Checkbox, Input } from "@budibase/bbui"
|
||||||
|
import { store, currentAsset } from "builderStore"
|
||||||
|
import { tables } from "stores/backend"
|
||||||
|
import {
|
||||||
|
getContextProviderComponents,
|
||||||
|
getSchemaForDatasource,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
|
import SaveFields from "./SaveFields.svelte"
|
||||||
|
|
||||||
|
export let parameters
|
||||||
|
export let bindings = []
|
||||||
|
|
||||||
|
$: formComponents = getContextProviderComponents(
|
||||||
|
$currentAsset,
|
||||||
|
$store.selectedComponentId,
|
||||||
|
"form"
|
||||||
|
)
|
||||||
|
$: schemaComponents = getContextProviderComponents(
|
||||||
|
$currentAsset,
|
||||||
|
$store.selectedComponentId,
|
||||||
|
"schema"
|
||||||
|
)
|
||||||
|
$: providerOptions = getProviderOptions(formComponents, schemaComponents)
|
||||||
|
$: schemaFields = getSchemaFields($currentAsset, parameters?.tableId)
|
||||||
|
$: tableOptions = $tables.list || []
|
||||||
|
|
||||||
|
// Gets a context definition of a certain type from a component definition
|
||||||
|
const extractComponentContext = (component, contextType) => {
|
||||||
|
const def = store.actions.components.getDefinition(component?._component)
|
||||||
|
if (!def) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const contexts = Array.isArray(def.context) ? def.context : [def.context]
|
||||||
|
return contexts.find(context => context?.type === contextType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets options for valid context keys which provide valid data to submit
|
||||||
|
const getProviderOptions = (formComponents, schemaComponents) => {
|
||||||
|
const formContexts = formComponents.map(component => ({
|
||||||
|
component,
|
||||||
|
context: extractComponentContext(component, "form"),
|
||||||
|
}))
|
||||||
|
const schemaContexts = schemaComponents.map(component => ({
|
||||||
|
component,
|
||||||
|
context: extractComponentContext(component, "schema"),
|
||||||
|
}))
|
||||||
|
const allContexts = formContexts.concat(schemaContexts)
|
||||||
|
|
||||||
|
return allContexts.map(({ component, context }) => {
|
||||||
|
let runtimeBinding = component._id
|
||||||
|
if (context.suffix) {
|
||||||
|
runtimeBinding += `-${context.suffix}`
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
label: component._instanceName,
|
||||||
|
value: runtimeBinding,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSchemaFields = (asset, tableId) => {
|
||||||
|
const { schema } = getSchemaForDatasource(asset, { type: "table", tableId })
|
||||||
|
delete schema._id
|
||||||
|
delete schema._rev
|
||||||
|
return Object.values(schema || {})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFieldsChanged = e => {
|
||||||
|
parameters.fields = e.detail
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<Body size="S">
|
||||||
|
Choose the data source that provides the row you would like to duplicate.
|
||||||
|
<br />
|
||||||
|
You can always add or override fields manually.
|
||||||
|
</Body>
|
||||||
|
|
||||||
|
<div class="params">
|
||||||
|
<Label small>Data Source</Label>
|
||||||
|
<Select
|
||||||
|
bind:value={parameters.providerId}
|
||||||
|
options={providerOptions}
|
||||||
|
placeholder="None"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Label small>Duplicate to Table</Label>
|
||||||
|
<Select
|
||||||
|
bind:value={parameters.tableId}
|
||||||
|
options={tableOptions}
|
||||||
|
getOptionLabel={option => option.name}
|
||||||
|
getOptionValue={option => option._id}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Label small />
|
||||||
|
<Checkbox text="Require confirmation" bind:value={parameters.confirm} />
|
||||||
|
|
||||||
|
{#if parameters.confirm}
|
||||||
|
<Label small>Confirm text</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="Are you sure you want to duplicate this row?"
|
||||||
|
bind:value={parameters.confirmText}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if parameters.tableId}
|
||||||
|
<div class="fields">
|
||||||
|
<SaveFields
|
||||||
|
parameterFields={parameters.fields}
|
||||||
|
{schemaFields}
|
||||||
|
on:change={onFieldsChanged}
|
||||||
|
{bindings}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.root {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.root :global(p) {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params {
|
||||||
|
display: grid;
|
||||||
|
column-gap: var(--spacing-l);
|
||||||
|
row-gap: var(--spacing-s);
|
||||||
|
grid-template-columns: 100px 1fr;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fields {
|
||||||
|
display: grid;
|
||||||
|
column-gap: var(--spacing-l);
|
||||||
|
row-gap: var(--spacing-s);
|
||||||
|
grid-template-columns: 100px 1fr auto 1fr auto;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -13,6 +13,7 @@ import CloseScreenModal from "./CloseScreenModal.svelte"
|
||||||
import ChangeFormStep from "./ChangeFormStep.svelte"
|
import ChangeFormStep from "./ChangeFormStep.svelte"
|
||||||
import UpdateStateStep from "./UpdateState.svelte"
|
import UpdateStateStep from "./UpdateState.svelte"
|
||||||
import RefreshDataProvider from "./RefreshDataProvider.svelte"
|
import RefreshDataProvider from "./RefreshDataProvider.svelte"
|
||||||
|
import DuplicateRow from "./DuplicateRow.svelte"
|
||||||
|
|
||||||
// Defines which actions are available to configure in the front end.
|
// Defines which actions are available to configure in the front end.
|
||||||
// Unfortunately the "name" property is used as the identifier so please don't
|
// Unfortunately the "name" property is used as the identifier so please don't
|
||||||
|
@ -27,6 +28,10 @@ export const getAvailableActions = () => {
|
||||||
name: "Save Row",
|
name: "Save Row",
|
||||||
component: SaveRow,
|
component: SaveRow,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Duplicate Row",
|
||||||
|
component: DuplicateRow,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Delete Row",
|
name: "Delete Row",
|
||||||
component: DeleteRow,
|
component: DeleteRow,
|
||||||
|
|
|
@ -10,6 +10,25 @@ import { saveRow, deleteRow, executeQuery, triggerAutomation } from "api"
|
||||||
import { ActionTypes } from "constants"
|
import { ActionTypes } from "constants"
|
||||||
|
|
||||||
const saveRowHandler = async (action, context) => {
|
const saveRowHandler = async (action, context) => {
|
||||||
|
const { fields, providerId, tableId } = action.parameters
|
||||||
|
let payload
|
||||||
|
if (providerId) {
|
||||||
|
payload = context[providerId]
|
||||||
|
} else {
|
||||||
|
payload = {}
|
||||||
|
}
|
||||||
|
if (fields) {
|
||||||
|
for (let [field, value] of Object.entries(fields)) {
|
||||||
|
payload[field] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tableId) {
|
||||||
|
payload.tableId = tableId
|
||||||
|
}
|
||||||
|
await saveRow(payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
const duplicateRowHandler = async (action, context) => {
|
||||||
const { fields, providerId, tableId } = action.parameters
|
const { fields, providerId, tableId } = action.parameters
|
||||||
if (providerId) {
|
if (providerId) {
|
||||||
let draft = context[providerId]
|
let draft = context[providerId]
|
||||||
|
@ -21,6 +40,8 @@ const saveRowHandler = async (action, context) => {
|
||||||
if (tableId) {
|
if (tableId) {
|
||||||
draft.tableId = tableId
|
draft.tableId = tableId
|
||||||
}
|
}
|
||||||
|
delete draft._id
|
||||||
|
delete draft._rev
|
||||||
await saveRow(draft)
|
await saveRow(draft)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,6 +141,7 @@ const updateStateHandler = action => {
|
||||||
|
|
||||||
const handlerMap = {
|
const handlerMap = {
|
||||||
["Save Row"]: saveRowHandler,
|
["Save Row"]: saveRowHandler,
|
||||||
|
["Duplicate Row"]: duplicateRowHandler,
|
||||||
["Delete Row"]: deleteRowHandler,
|
["Delete Row"]: deleteRowHandler,
|
||||||
["Navigate To"]: navigationHandler,
|
["Navigate To"]: navigationHandler,
|
||||||
["Execute Query"]: queryExecutionHandler,
|
["Execute Query"]: queryExecutionHandler,
|
||||||
|
|
Loading…
Reference in New Issue