2020-08-07 17:13:57 +02:00
|
|
|
<script>
|
2020-10-27 23:57:05 +01:00
|
|
|
import { Input, Button, TextButton, Select, Toggle } from "@budibase/bbui"
|
2020-10-24 00:55:51 +02:00
|
|
|
import { cloneDeep } from "lodash/fp"
|
|
|
|
import { backendUiStore } from "builderStore"
|
2020-11-24 15:04:14 +01:00
|
|
|
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
2020-08-07 17:13:57 +02:00
|
|
|
import { FIELDS } from "constants/backend"
|
|
|
|
import { notifier } from "builderStore/store/notifications"
|
|
|
|
import ValuesList from "components/common/ValuesList.svelte"
|
|
|
|
import DatePicker from "components/common/DatePicker.svelte"
|
2020-10-23 18:38:10 +02:00
|
|
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
2020-08-07 17:13:57 +02:00
|
|
|
|
2020-08-20 12:19:13 +02:00
|
|
|
let fieldDefinitions = cloneDeep(FIELDS)
|
|
|
|
|
2020-08-07 17:13:57 +02:00
|
|
|
export let onClosed
|
2020-08-20 12:19:13 +02:00
|
|
|
export let field = {
|
|
|
|
type: "string",
|
|
|
|
constraints: fieldDefinitions.STRING.constraints,
|
2020-10-14 20:40:01 +02:00
|
|
|
|
|
|
|
// Initial value for column name in other table for linked records
|
|
|
|
fieldName: $backendUiStore.selectedTable.name,
|
2020-08-20 12:19:13 +02:00
|
|
|
}
|
2020-08-07 17:13:57 +02:00
|
|
|
|
2020-08-10 16:34:37 +02:00
|
|
|
let originalName = field.name
|
2020-10-14 20:40:01 +02:00
|
|
|
let primaryDisplay =
|
|
|
|
$backendUiStore.selectedTable.primaryDisplay == null ||
|
|
|
|
$backendUiStore.selectedTable.primaryDisplay === field.name
|
2020-10-23 18:38:10 +02:00
|
|
|
let confirmDeleteDialog
|
2020-10-27 14:04:32 +01:00
|
|
|
let deletion
|
2020-10-23 18:38:10 +02:00
|
|
|
|
2020-10-09 19:49:23 +02:00
|
|
|
$: tableOptions = $backendUiStore.tables.filter(
|
|
|
|
table => table._id !== $backendUiStore.draftTable._id
|
2020-09-29 19:27:35 +02:00
|
|
|
)
|
2020-10-16 22:50:58 +02:00
|
|
|
$: required = !!field?.constraints?.presence || primaryDisplay
|
2020-11-25 16:30:10 +01:00
|
|
|
$: uneditable =
|
|
|
|
$backendUiStore.selectedTable?._id === TableNames.USERS &&
|
|
|
|
UNEDITABLE_USER_FIELDS.includes(field.name)
|
2020-08-07 18:41:20 +02:00
|
|
|
|
2020-08-07 17:13:57 +02:00
|
|
|
async function saveColumn() {
|
2020-08-07 18:41:20 +02:00
|
|
|
backendUiStore.update(state => {
|
2020-10-09 19:49:23 +02:00
|
|
|
backendUiStore.actions.tables.saveField({
|
2020-08-07 18:41:20 +02:00
|
|
|
originalName,
|
2020-08-11 12:23:07 +02:00
|
|
|
field,
|
2020-10-14 20:40:01 +02:00
|
|
|
primaryDisplay,
|
2020-08-07 18:41:20 +02:00
|
|
|
})
|
|
|
|
return state
|
2020-08-07 17:13:57 +02:00
|
|
|
})
|
|
|
|
onClosed()
|
|
|
|
}
|
2020-08-20 12:19:13 +02:00
|
|
|
|
2020-10-23 18:38:10 +02:00
|
|
|
function deleteColumn() {
|
|
|
|
if (field.name === $backendUiStore.selectedTable.primaryDisplay) {
|
|
|
|
notifier.danger("You cannot delete the display column")
|
|
|
|
} else {
|
|
|
|
backendUiStore.actions.tables.deleteField(field)
|
2020-10-27 14:04:32 +01:00
|
|
|
notifier.success(`Column ${field.name} deleted.`)
|
|
|
|
onClosed()
|
2020-10-23 18:38:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-20 12:19:13 +02:00
|
|
|
function handleFieldConstraints(event) {
|
|
|
|
const { type, constraints } = fieldDefinitions[
|
|
|
|
event.target.value.toUpperCase()
|
|
|
|
]
|
|
|
|
field.type = type
|
|
|
|
field.constraints = constraints
|
|
|
|
}
|
2020-10-07 11:45:26 +02:00
|
|
|
|
|
|
|
function onChangeRequired(e) {
|
|
|
|
const req = e.target.checked
|
|
|
|
field.constraints.presence = req ? { allowEmpty: false } : false
|
|
|
|
required = req
|
|
|
|
}
|
2020-10-16 22:50:58 +02:00
|
|
|
|
|
|
|
function onChangePrimaryDisplay(e) {
|
|
|
|
const isPrimary = e.target.checked
|
|
|
|
// primary display is always required
|
|
|
|
if (isPrimary) {
|
|
|
|
field.constraints.presence = { allowEmpty: false }
|
|
|
|
}
|
|
|
|
}
|
2020-10-23 18:38:10 +02:00
|
|
|
|
|
|
|
function confirmDelete() {
|
|
|
|
confirmDeleteDialog.show()
|
2020-10-27 14:04:32 +01:00
|
|
|
deletion = true
|
2020-10-24 00:55:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function hideDeleteDialog() {
|
|
|
|
confirmDeleteDialog.hide()
|
2020-10-27 14:04:32 +01:00
|
|
|
deletion = false
|
2020-10-23 18:38:10 +02:00
|
|
|
}
|
2020-08-07 17:13:57 +02:00
|
|
|
</script>
|
|
|
|
|
2020-10-27 14:04:32 +01:00
|
|
|
<div class="actions" class:hidden={deletion}>
|
2020-11-24 15:04:14 +01:00
|
|
|
<Input label="Name" thin bind:value={field.name} disabled={uneditable} />
|
2020-08-07 17:13:57 +02:00
|
|
|
|
2020-10-14 22:43:36 +02:00
|
|
|
<Select
|
|
|
|
disabled={originalName}
|
|
|
|
secondary
|
|
|
|
thin
|
|
|
|
label="Type"
|
|
|
|
on:change={handleFieldConstraints}
|
|
|
|
bind:value={field.type}>
|
|
|
|
{#each Object.values(fieldDefinitions) as field}
|
|
|
|
<option value={field.type}>{field.name}</option>
|
|
|
|
{/each}
|
|
|
|
</Select>
|
2020-08-07 17:13:57 +02:00
|
|
|
|
2020-11-24 15:04:14 +01:00
|
|
|
{#if field.type !== 'link' && !uneditable}
|
2020-10-01 12:01:06 +02:00
|
|
|
<Toggle
|
2020-10-07 11:45:26 +02:00
|
|
|
checked={required}
|
|
|
|
on:change={onChangeRequired}
|
2020-10-16 22:50:58 +02:00
|
|
|
disabled={primaryDisplay}
|
2020-10-01 12:01:06 +02:00
|
|
|
thin
|
|
|
|
text="Required" />
|
|
|
|
{/if}
|
2020-08-07 17:13:57 +02:00
|
|
|
|
2020-10-14 20:40:01 +02:00
|
|
|
{#if field.type !== 'link'}
|
|
|
|
<Toggle
|
|
|
|
bind:checked={primaryDisplay}
|
2020-10-16 22:50:58 +02:00
|
|
|
on:change={onChangePrimaryDisplay}
|
2020-10-14 20:40:01 +02:00
|
|
|
thin
|
|
|
|
text="Use as table display column" />
|
|
|
|
{/if}
|
|
|
|
|
2020-09-29 19:27:35 +02:00
|
|
|
{#if field.type === 'string'}
|
2020-09-29 14:54:04 +02:00
|
|
|
<Input
|
|
|
|
thin
|
|
|
|
type="number"
|
2020-09-25 12:35:32 +02:00
|
|
|
label="Max Length"
|
|
|
|
bind:value={field.constraints.length.maximum} />
|
2020-09-29 19:27:35 +02:00
|
|
|
{:else if field.type === 'options'}
|
|
|
|
<ValuesList
|
|
|
|
label="Options (one per line)"
|
|
|
|
bind:values={field.constraints.inclusion} />
|
|
|
|
{:else if field.type === 'datetime'}
|
2020-09-25 12:35:32 +02:00
|
|
|
<DatePicker
|
|
|
|
label="Earliest"
|
|
|
|
bind:value={field.constraints.datetime.earliest} />
|
|
|
|
<DatePicker label="Latest" bind:value={field.constraints.datetime.latest} />
|
2020-09-29 19:27:35 +02:00
|
|
|
{:else if field.type === 'number'}
|
2020-09-29 14:54:04 +02:00
|
|
|
<Input
|
|
|
|
thin
|
|
|
|
type="number"
|
2020-09-25 12:35:32 +02:00
|
|
|
label="Min Value"
|
|
|
|
bind:value={field.constraints.numericality.greaterThanOrEqualTo} />
|
2020-09-29 14:54:04 +02:00
|
|
|
<Input
|
|
|
|
thin
|
|
|
|
type="number"
|
2020-09-25 12:35:32 +02:00
|
|
|
label="Max Value"
|
|
|
|
bind:value={field.constraints.numericality.lessThanOrEqualTo} />
|
|
|
|
{:else if field.type === 'link'}
|
2020-10-09 19:49:23 +02:00
|
|
|
<Select label="Table" thin secondary bind:value={field.tableId}>
|
2020-09-29 19:27:35 +02:00
|
|
|
<option value="">Choose an option</option>
|
2020-10-09 19:49:23 +02:00
|
|
|
{#each tableOptions as table}
|
|
|
|
<option value={table._id}>{table.name}</option>
|
2020-09-29 19:27:35 +02:00
|
|
|
{/each}
|
|
|
|
</Select>
|
|
|
|
<Input
|
|
|
|
label={`Column Name in Other Table`}
|
|
|
|
thin
|
|
|
|
bind:value={field.fieldName} />
|
2020-09-25 12:35:32 +02:00
|
|
|
{/if}
|
2020-10-27 23:57:05 +01:00
|
|
|
<footer class="create-column-options">
|
2020-11-24 15:04:14 +01:00
|
|
|
{#if !uneditable && originalName}
|
2020-10-27 23:57:05 +01:00
|
|
|
<TextButton text on:click={confirmDelete}>Delete Column</TextButton>
|
2020-10-23 18:38:10 +02:00
|
|
|
{/if}
|
2020-10-27 23:57:05 +01:00
|
|
|
<Button secondary on:click={onClosed}>Cancel</Button>
|
2020-08-07 17:13:57 +02:00
|
|
|
<Button primary on:click={saveColumn}>Save Column</Button>
|
2020-10-23 18:38:10 +02:00
|
|
|
</footer>
|
2020-09-25 12:35:32 +02:00
|
|
|
</div>
|
2020-10-23 18:38:10 +02:00
|
|
|
<ConfirmDialog
|
|
|
|
bind:this={confirmDeleteDialog}
|
|
|
|
body={`Are you sure you wish to delete this column? Your data will be deleted and this action cannot be undone.`}
|
|
|
|
okText="Delete Column"
|
|
|
|
onOk={deleteColumn}
|
2020-10-24 00:55:51 +02:00
|
|
|
onCancel={hideDeleteDialog}
|
2020-10-28 17:05:19 +01:00
|
|
|
title="Confirm Deletion" />
|
2020-08-07 17:13:57 +02:00
|
|
|
|
|
|
|
<style>
|
2020-09-25 14:11:57 +02:00
|
|
|
.actions {
|
2020-08-07 17:13:57 +02:00
|
|
|
display: grid;
|
|
|
|
grid-gap: var(--spacing-xl);
|
2020-09-25 12:35:32 +02:00
|
|
|
min-width: 400px;
|
2020-08-07 17:13:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
footer {
|
2020-09-25 12:35:32 +02:00
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
|
|
|
gap: var(--spacing-m);
|
2020-08-07 17:13:57 +02:00
|
|
|
}
|
2020-10-27 14:04:32 +01:00
|
|
|
|
2020-10-27 23:57:05 +01:00
|
|
|
:global(.create-column-options button:first-child) {
|
|
|
|
margin-right: auto;
|
|
|
|
}
|
|
|
|
|
2020-10-27 14:04:32 +01:00
|
|
|
.hidden {
|
|
|
|
display: none;
|
|
|
|
}
|
2020-08-07 17:13:57 +02:00
|
|
|
</style>
|