Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update field type #2170

Merged
merged 4 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<CirclePlusIcon class="mr-2 size-4" />
{$LL.base.createBase()}
</Button>
<Button on:click={() => toggleModal(IMPORT_TEMPLATE_MODAL)} {...$$restProps}>
<Button class="w-48" on:click={() => toggleModal(IMPORT_TEMPLATE_MODAL)} {...$$restProps}>
<PackageIcon class="mr-2 size-4" />
{$LL.base.importFromTemplate()}
</Button>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
import { getTable } from "$lib/store/table.store"
import { trpc } from "$lib/trpc/client"
import { createMutation, useQueryClient } from "@tanstack/svelte-query"
import { createFieldDTO, type FieldType } from "@undb/table"
import { createDefaultFieldDTO, createFieldDTO, type FieldType } from "@undb/table"
import { toast } from "svelte-sonner"
import { derived } from "svelte/store"
import { defaults, superForm } from "sveltekit-superforms"
import { zodClient } from "sveltekit-superforms/adapters"
import FieldOptions from "../field-options/field-options.svelte"
import FieldTypePicker from "../field-picker/field-type-picker.svelte"
import { createDefaultField } from "./create-default-field"
import { LL } from "@undb/i18n/client"
import { BetweenVerticalStartIcon, LoaderCircleIcon } from "lucide-svelte"

Expand Down Expand Up @@ -41,43 +40,33 @@
})),
)

const form = superForm(
defaults(
{
type: "string",
name: $table.schema.getNextFieldName($LL.table.fieldTypes.string()),
display: false,
constraint: {},
},
zodClient(createFieldDTO),
),
{
SPA: true,
dataType: "json",
validators: zodClient(createFieldDTO),
resetForm: false,
invalidateAll: false,
onSubmit(input) {
validateForm({ update: true })
},
onUpdate(event) {
if (!event.form.valid) {
console.log(event.form.data, event.form.errors)
return
}

$createFieldMutation.mutate({
tableId: $table.id.value,
field: event.form.data,
})
},
const defaultValue = createDefaultFieldDTO($table, "string", $LL)
const form = superForm(defaults(defaultValue, zodClient(createFieldDTO)), {
SPA: true,
dataType: "json",
validators: zodClient(createFieldDTO),
resetForm: false,
invalidateAll: false,
onSubmit(input) {
validateForm({ update: true })
},
)
onUpdate(event) {
if (!event.form.valid) {
console.log(event.form.data, event.form.errors)
return
}

$createFieldMutation.mutate({
tableId: $table.id.value,
field: event.form.data,
})
},
})

const { allErrors, enhance, form: formData, reset, validateForm } = form

function updateType(type: FieldType) {
$formData = createDefaultField($table, type, $LL.table.fieldTypes[type](), name)
$formData = createDefaultFieldDTO($table, type, $LL)
}

function onTypeChange(type: FieldType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import autoAnimate from "@formkit/auto-animate"
import { onMount } from "svelte"
import { isEqual } from "radash"
import { ssrExportAllKey } from "vite/runtime"
import { LL } from "@undb/i18n/client"

export let constraint: IReferenceFieldConstraint | undefined = {
required: false,
Expand Down Expand Up @@ -64,35 +64,39 @@
<div class="space-y-1">
<Label class="text-muted-foreground flex items-center text-xs font-normal">
<ExternalLinkIcon class="mr-2 h-3 w-3" />
Foreign table
{$LL.table.field.reference.foreignTable()}
</Label>
<ForeignTablePicker disabled bind:value={option.foreignTableId} class="text-xs" />
</div>
{/if}
{#if constraint}
<div class="grid grid-cols-2 gap-2">
<div class="space-y-1">
<Label for="min" class="text-xs font-normal">Min items</Label>
<Label for="min" class="text-xs font-normal">
{$LL.table.field.reference.min()}
</Label>
<NumberInput
{disabled}
id="min"
min={0}
max={constraint.max}
step={1}
bind:value={constraint.min}
placeholder="Min items..."
placeholder={$LL.table.field.reference.minPlaceholder()}
class="bg-background text-xs"
/>
</div>
<div class="space-y-1">
<Label for="max" class="text-xs font-normal">Max items</Label>
<Label for="max" class="text-xs font-normal">
{$LL.table.field.reference.max()}
</Label>
<NumberInput
{disabled}
id="max"
min={constraint.min || 0}
step={1}
bind:value={constraint.max}
placeholder="Max items..."
placeholder={$LL.table.field.reference.maxPlaceholder()}
class="bg-background text-xs"
/>
</div>
Expand All @@ -103,7 +107,9 @@
</div>
<div class="flex items-center space-x-2">
<Checkbox {disabled} id="required" bind:checked={constraint.required} />
<Label for="required" class="text-xs font-normal">Mark as required field.</Label>
<Label for="required" class="text-xs font-normal">
{$LL.table.field.defaultValue.markAsRequired()}
</Label>
</div>
{/if}

Expand All @@ -120,7 +126,9 @@
}
}}
/>
<Label for="condition" class="text-xs font-normal">Limit record selection to condition.</Label>
<Label for="condition" class="text-xs font-normal">
{$LL.table.field.reference.limitRecordSelectionToCondition()}
</Label>
</div>

<div use:autoAnimate>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@
const deleteField = createMutation({
mutationFn: trpc.table.field.delete.mutate,
async onSuccess() {
toast.success("Delete field success")
toast.success($LL.table.field.deleted())
await invalidate(`undb:table:${$table.id.value}`)
await client.invalidateQueries({ queryKey: ["records", $table.id.value] })
open = false
deleteAlertOpen = false
},
onError(error, variables, context) {
toast.error("Delete field failed")
toast.error($LL.table.field.deleteFailed())
},
})

Expand Down Expand Up @@ -184,7 +184,7 @@
<AlertDialog.Title class="flex items-center">
<TrashIcon class="mr-2 h-4 w-4" />
<div class="flex items-center gap-2">
{$LL.table.field.delete()}
{$LL.table.field.delete()}

<span
data-field-id={field.id.value}
Expand Down Expand Up @@ -297,7 +297,7 @@
}}
>
<TrashIcon class="mr-2 h-4 w-4" />
{$LL.table.field.delete()}
{$LL.table.field.delete()}
</AlertDialog.Action>
</AlertDialog.Footer>
</AlertDialog.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@
import { getTable } from "$lib/store/table.store"
import { trpc } from "$lib/trpc/client"
import { createMutation, useQueryClient } from "@tanstack/svelte-query"
import { getIsSystemFieldType, updateFieldDTO, type Field, type FieldValue, type IUpdateFieldDTO } from "@undb/table"
import {
createUpdateFieldDTO,
getIsFieldChangeTypeDisabled,
getIsSystemFieldType,
updateFieldDTO,
type Field,
type FieldValue,
type IUpdateFieldDTO,
} from "@undb/table"
import { toast } from "svelte-sonner"
import { derived } from "svelte/store"
import { Option } from "@undb/domain"
Expand All @@ -19,21 +27,27 @@
import { cn } from "$lib/utils"
import { LoaderCircleIcon, PencilIcon } from "lucide-svelte"
import { LL } from "@undb/i18n/client"
import { getIsFieldCanCastTo } from "@undb/table"

const table = getTable()

export let field: Field

export let onSuccess: () => void = () => {}

let type = field.type
let updatedType = field.type

$: isTypeChanged = type !== updatedType

const client = useQueryClient()
const updateFieldMutation = createMutation(
derived([table], ([$table]) => ({
mutationKey: ["table", $table.id.value, "updateField"],
mutationFn: trpc.table.field.update.mutate,
async onSuccess() {
onSuccess()
toast.success("Update field success")
toast.success($LL.table.field.updated())
await invalidate(`undb:table:${$table.id.value}`)
await client.invalidateQueries({ queryKey: ["records", $table.id.value] })
reset()
Expand All @@ -44,41 +58,45 @@
})),
)

function getDefaultValue(): IUpdateFieldDTO {
function getDefaultValue(field: Field): IUpdateFieldDTO {
console.log(field.constraint)
return {
id: field.id.value,
type: field.type,
name: field.name.value,
display: !!field.display,
defaultValue: (field.defaultValue as Option<FieldValue>)?.unwrapUnchecked()?.value as any,
constraint: field.constraint.unwrapUnchecked()?.value,
option: field.option.unwrapUnchecked(),
defaultValue: (field.defaultValue as Option<FieldValue>)?.into(undefined)?.value as any,
constraint: field.constraint?.unwrapUnchecked()?.value ?? {},
option: field.option?.unwrapUnchecked() ?? {},
}
}

const form = superForm<IUpdateFieldDTO>(defaults<IUpdateFieldDTO>(getDefaultValue(), zodClient(updateFieldDTO)), {
SPA: true,
dataType: "json",
validators: zodClient(updateFieldDTO),
resetForm: false,
invalidateAll: false,
onSubmit(input) {
validateForm({ update: true })
},
async onUpdate(event) {
if (!event.form.valid) {
console.log(event.form.errors, event.form.data)
return
}
const data = event.form.data
const field = FieldFactory.fromJSON(data).toJSON()
const form = superForm<IUpdateFieldDTO>(
defaults<IUpdateFieldDTO>(getDefaultValue(field), zodClient(updateFieldDTO)),
{
SPA: true,
dataType: "json",
validators: zodClient(updateFieldDTO),
resetForm: false,
invalidateAll: false,
onSubmit(input) {
validateForm({ update: true })
},
async onUpdate(event) {
if (!event.form.valid) {
console.log(event.form.errors, event.form.data)
return
}
const data = event.form.data
const field = FieldFactory.fromJSON(data).toJSON()

await $updateFieldMutation.mutateAsync({
tableId: $table.id.value,
field,
})
await $updateFieldMutation.mutateAsync({
tableId: $table.id.value,
field,
})
},
},
})
)

const { enhance, form: formData, reset, validateForm } = form
</script>
Expand All @@ -87,7 +105,21 @@
<div class="flex h-8 items-center gap-2">
<Form.Field {form} name="type" class="h-full">
<Form.Control let:attrs>
<FieldTypePicker {...attrs} bind:value={$formData.type} tabIndex={-1} class="h-full" disabled />
<FieldTypePicker
sameWidth={false}
{...attrs}
value={$formData.type}
tabIndex={-1}
class="h-full"
filter={(field) => getIsFieldCanCastTo($formData.type, field)}
disabled={getIsFieldChangeTypeDisabled($formData.type)}
onValueChange={(value) => {
form.reset()
$formData.type = value
updatedType = value
$formData = createUpdateFieldDTO($table, field, value)
}}
/>
</Form.Control>
<Form.Description />
<Form.FieldErrors />
Expand All @@ -102,6 +134,10 @@
</Form.Field>
</div>

{#if isTypeChanged}
<div class="text-xs text-yellow-600">{$LL.table.field.typeChanged()}</div>
{/if}

<div use:autoAnimate>
{#if !getIsSystemFieldType($formData.type)}
<Form.Field {form} name="constraint">
Expand Down
Loading