Refactor spatial input components to use nullable properties and default spatial data

This commit is contained in:
ArnabChatterjee20k
2025-09-06 14:01:56 +05:30
parent 0a03c56d8c
commit 8a5eca914c
9 changed files with 139 additions and 94 deletions
+8 -14
View File
@@ -4,36 +4,30 @@
import Button from './button.svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
let defaultValues: number[][] = [
[0, 0],
[0, 0]
];
export let values: number[][];
export let showDefaults;
export let nullable: boolean;
export let onAddPoint: () => void;
export let onDeletePoint: () => void = undefined;
let required = true;
$: required = showDefaults;
$: required = nullable;
$: disableDeletePoints = !values || values.length <= 2;
</script>
<Layout.Stack>
<Layout.Stack alignItems="flex-start">
<Layout.Stack>
{#each values || defaultValues as value}
{#each values as value}
<InputPoint
showDefaults={required}
nullable={required}
values={value}
deletePoints={true}
disableDelete={disableDeletePoints}
{onDeletePoint} />
{/each}
</Layout.Stack>
<Layout.Stack direction="row" gap="s" style="margin-top: 8px;">
<Button compact on:click={onAddPoint}>
<Icon icon={IconPlus} size="s" /> Add coordinate
</Button>
</Layout.Stack>
<Button compact on:click={onAddPoint} disabled={nullable}>
<Icon icon={IconPlus} size="s" /> Add coordinate
</Button>
</Layout.Stack>
+5 -5
View File
@@ -4,9 +4,9 @@
import Button from './button.svelte';
import { IconX } from '@appwrite.io/pink-icons-svelte';
let defaultValues: number[] = [0, 0];
let nullableSkeletonShape: number[] = [0, 0];
export let values: number[];
export let showDefaults;
export let nullable = false;
export let deletePoints = false;
export let onDeletePoint: () => void = undefined;
export let disableDelete = false;
@@ -14,8 +14,8 @@
<Layout.Stack>
<Layout.Stack direction="row" gap="s">
{#if showDefaults}
{#each defaultValues as _, index}
{#if nullable}
{#each nullableSkeletonShape as _, index}
<InputNumber id={`default-${index}`} placeholder="Enter value" disabled={true} />
{/each}
{:else}
@@ -28,7 +28,7 @@
{/each}
{/if}
{#if deletePoints}
<Button secondary disabled={showDefaults || disableDelete} on:click={onDeletePoint}>
<Button secondary disabled={nullable || disableDelete} on:click={onDeletePoint}>
<Icon icon={IconX} size="s" />
</Button>
{/if}
@@ -0,0 +1,29 @@
<script lang="ts">
import { Icon, Layout } from '@appwrite.io/pink-svelte';
import Button from './button.svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import type { NestedNumberArray } from '$lib/helpers/types';
import InputLine from './inputLine.svelte';
export let values: NestedNumberArray;
export let nullable;
export let onAddPoint: () => void;
export let onAddLine: () => void;
export let onDeletePoint: () => void = undefined;
let required = true;
$: required = nullable;
</script>
<Layout.Stack>
{#each values as value}
<InputLine values={value as number[][]} {onAddPoint} nullable={required} {onDeletePoint} />
{/each}
<Layout.Stack direction="row" gap="s" style="margin-top: 8px;">
<Button compact on:click={onAddLine}>
<Icon icon={IconPlus} size="s" /> Add line
</Button>
</Layout.Stack>
</Layout.Stack>
@@ -35,33 +35,26 @@
</script>
<script lang="ts">
const defaultData = getDefaultSpatialData('linestring') as number[][];
export let data: Partial<Models.ColumnLine> = {
required: false,
default: [
[0, 0],
[0, 0]
]
default: defaultData
};
import { createConservative } from '$lib/helpers/stores';
import { Selector, Layout, Typography } from '@appwrite.io/pink-svelte';
import { InputLine } from '$lib/elements/forms';
import { getDefaultSpatialData } from '../store';
let savedDefault = data.default;
let showDefaultPointDummyData = false;
// let showDefaultPointDummyData = false;
function handleDefaultState(hideDefault: boolean) {
if (hideDefault) {
savedDefault = data.default ?? [
[0, 0],
[0, 0]
];
savedDefault = data.default;
data.default = null;
} else {
data.default = savedDefault ?? [
[0, 0],
[0, 0]
];
data.default = savedDefault ?? defaultData;
}
}
@@ -101,8 +94,8 @@
<Typography.Caption variant="400">Optional</Typography.Caption>
</Layout.Stack>
<InputLine
values={data.default as number[][]}
values={data.default || defaultData}
onAddPoint={pushCoordinate}
showDefaults={showDefaultPointDummyData}
nullable={showDefaultPointDummyData}
onDeletePoint={deleteCoordinate} />
</Layout.Stack>
@@ -36,24 +36,26 @@
<script lang="ts">
import { InputPoint } from '$lib/elements/forms';
import { getDefaultSpatialData } from '../store';
import { createConservative } from '$lib/helpers/stores';
import { Selector, Typography, Layout } from '@appwrite.io/pink-svelte';
const defaultData = getDefaultSpatialData('point') as number[];
export let data: Partial<Models.ColumnPoint> = {
required: false,
default: [0, 0]
default: defaultData
};
import { createConservative } from '$lib/helpers/stores';
import { Selector, Typography, Layout } from '@appwrite.io/pink-svelte';
let savedDefault = data.default;
let showDefaultPointDummyData = false;
function handleDefaultState(hideDefault: boolean) {
if (hideDefault) {
savedDefault = data.default ?? [0, 0];
savedDefault = data.default ?? defaultData;
data.default = null;
} else {
data.default = savedDefault ?? [0, 0];
data.default = savedDefault ?? defaultData;
}
}
@@ -84,5 +86,5 @@
<Typography.Text variant="m-600">Default</Typography.Text>
<Typography.Caption variant="400">Optional</Typography.Caption>
</Layout.Stack>
<InputPoint values={data.default as number[]} showDefaults={showDefaultPointDummyData} />
<InputPoint values={data.default} nullable={showDefaultPointDummyData} />
</Layout.Stack>
@@ -7,82 +7,71 @@
databaseId: string,
tableId: string,
key: string,
data: Partial<Models.ColumnBoolean>
data: Partial<Models.ColumnPoint>
) {
await sdk.forProject(page.params.region, page.params.project).tablesDB.createBooleanColumn({
await sdk.forProject(page.params.region, page.params.project).tablesDB.createPolygonColumn({
databaseId,
tableId,
key,
required: data.required,
xdefault: data.default,
array: data.array
xdefault: data?.default
});
}
export async function updatePolygon(
databaseId: string,
tableId: string,
data: Partial<Models.ColumnBoolean>,
data: Partial<Models.ColumnPoint>,
originalKey?: string
) {
await sdk.forProject(page.params.region, page.params.project).tablesDB.updateBooleanColumn({
await sdk.forProject(page.params.region, page.params.project).tablesDB.updatePolygonColumn({
databaseId,
tableId,
key: originalKey,
required: data.required,
xdefault: data.default,
xdefault: data?.default,
newKey: data.key !== originalKey ? data.key : undefined
});
}
</script>
<script lang="ts">
import { InputSelect } from '$lib/elements/forms';
import { createConservative } from '$lib/helpers/stores';
import { Selector, Typography, Layout } from '@appwrite.io/pink-svelte';
import InputPolygon from '$lib/elements/forms/inputPolygon.svelte';
import { getDefaultSpatialData } from '../store';
export let editing = false;
export let data: Partial<Models.ColumnBoolean> = {
const defaultData = getDefaultSpatialData('polygon');
export let data: Partial<Models.ColumnPoint> = {
required: false,
array: false,
default: null
default: defaultData
};
import { createConservative } from '$lib/helpers/stores';
import { Selector } from '@appwrite.io/pink-svelte';
let savedDefault = data.default;
let showDefaultPointDummyData = false;
function handleDefaultState(hideDefault: boolean) {
if (hideDefault) {
savedDefault = data.default;
data.default = null;
} else {
data.default = savedDefault;
data.default = savedDefault ?? defaultData;
}
}
const {
stores: { required, array },
stores: { required },
listen
} = createConservative<Partial<Models.ColumnBoolean>>({
} = createConservative<Partial<Models.ColumnPoint>>({
required: false,
array: false,
...data
});
$: listen(data);
$: handleDefaultState($required || $array);
$: handleDefaultState($required);
$: showDefaultPointDummyData = $required ? true : false;
</script>
<InputSelect
id="default"
label="Default value"
placeholder="Select a value"
disabled={data.required || data.array}
options={[
{ label: 'NULL', value: null },
{ label: 'True', value: true },
{ label: 'False', value: false }
]}
bind:value={data.default} />
<Selector.Checkbox
size="s"
id="required"
@@ -90,10 +79,15 @@
bind:checked={data.required}
disabled={data.array}
description="Indicate whether this column is required" />
<Selector.Checkbox
size="s"
id="array"
label="Array"
bind:checked={data.array}
disabled={data.required || editing}
description="Indicate whether this column is an array. Defaults to an empty array." />
<Layout.Stack>
<Layout.Stack direction="row" alignItems="center" gap="s">
<Typography.Text variant="m-600">Default</Typography.Text>
<Typography.Caption variant="400">Optional</Typography.Caption>
</Layout.Stack>
<InputPolygon
values={data.default || defaultData}
nullable={showDefaultPointDummyData}
onAddLine={() => {}}
onAddPoint={() => {}} />
</Layout.Stack>
@@ -2,18 +2,17 @@
import { InputLine } from '$lib/elements/forms';
import type { Models } from '@appwrite.io/console';
import { Layout, Typography } from '@appwrite.io/pink-svelte';
import { getDefaultSpatialData } from '../../../store';
export let id: string;
export let label: string;
export let value: number[][] | null = null;
export let value: number[][];
export let limited: boolean = false;
export let column: Models.ColumnInteger;
const defaultShape = [
[0, 0],
[0, 0]
];
export let column: Models.ColumnLine;
const defaultData = getDefaultSpatialData('linestring') as number[][];
function onAddPoint() {
value = [...(value || defaultShape), [0, 0]];
value = [...(value || defaultData), getDefaultSpatialData('point') as number[]];
}
function onDeletePoint() {
@@ -21,15 +20,19 @@
}
$: nullable = !limited ? !column.required : false;
$: value = nullable ? null : defaultData;
$: console.log({ name: column.key, column, nullable });
</script>
<Layout.Stack>
<Layout.Stack direction="row" alignItems="center" gap="s">
<Typography.Text variant="m-600">{label}</Typography.Text>
<Typography.Text variant="m-500">{label}</Typography.Text>
{#if nullable}
<Typography.Caption variant="400">optional</Typography.Caption>
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary"
>optional</Typography.Text>
{/if}
</Layout.Stack>
<InputLine values={value} showDefaults={false} {onAddPoint} {onDeletePoint} />
<InputLine values={value || defaultData} {nullable} {onAddPoint} {onDeletePoint} />
</Layout.Stack>
@@ -2,6 +2,7 @@
import { InputPoint } from '$lib/elements/forms';
import type { Models } from '@appwrite.io/console';
import { Layout, Typography } from '@appwrite.io/pink-svelte';
import { getDefaultSpatialData } from '../../../store';
export let id: string;
export let label: string;
@@ -10,14 +11,17 @@
export let column: Models.ColumnInteger;
$: nullable = !limited ? !column.required : false;
$: value = nullable ? null : (getDefaultSpatialData('point') as number[]);
</script>
<Layout.Stack>
<Layout.Stack direction="row" alignItems="center" gap="s">
<Typography.Text variant="m-600">{label}</Typography.Text>
<Typography.Text variant="m-500">{label}</Typography.Text>
{#if nullable}
<Typography.Caption variant="400">optional</Typography.Caption>
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary"
>optional</Typography.Text>
{/if}
</Layout.Stack>
<InputPoint values={value || [0, 0]} showDefaults={false} />
<InputPoint values={value} {nullable} />
</Layout.Stack>
@@ -1,5 +1,5 @@
import { page } from '$app/stores';
import type { Column } from '$lib/helpers/types';
import type { Column, ColumnType } from '$lib/helpers/types';
import type { Models } from '@appwrite.io/console';
import { derived, writable } from 'svelte/store';
import type { SortDirection } from '$lib/components';
@@ -191,3 +191,29 @@ export const PROHIBITED_ROW_KEYS = [
];
export const sheetHeightStore = writable('74.5vh');
export const getDefaultSpatialData = (
type: Extract<ColumnType, 'point' | 'linestring' | 'polygon'>
) => {
if (type === 'point') return [0, 0];
else if (type === 'linestring')
return [
[0, 0],
[0, 0]
];
else if (type === 'polygon')
return [
[
[0, 0],
[0, 0],
[0, 0],
[0, 0]
],
[
[0, 0],
[0, 0],
[0, 0],
[0, 0]
]
];
};