mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge pull request #2352 from appwrite/accordions-for-relations
This commit is contained in:
+2
-2
@@ -24,9 +24,9 @@
|
||||
"@ai-sdk/svelte": "^1.1.24",
|
||||
"@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@6031134",
|
||||
"@appwrite.io/pink-icons": "0.25.0",
|
||||
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@2cf27e0",
|
||||
"@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0",
|
||||
"@appwrite.io/pink-legacy": "^1.0.3",
|
||||
"@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@fb8b1ed",
|
||||
"@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0",
|
||||
"@faker-js/faker": "^9.9.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@sentry/sveltekit": "^8.38.0",
|
||||
|
||||
Generated
+10
-10
@@ -18,14 +18,14 @@ importers:
|
||||
specifier: 0.25.0
|
||||
version: 0.25.0
|
||||
'@appwrite.io/pink-icons-svelte':
|
||||
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@2cf27e0
|
||||
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@2cf27e0(svelte@5.25.3)
|
||||
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0
|
||||
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0(svelte@5.25.3)
|
||||
'@appwrite.io/pink-legacy':
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
'@appwrite.io/pink-svelte':
|
||||
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@fb8b1ed
|
||||
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@fb8b1ed(svelte@5.25.3)
|
||||
specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0
|
||||
version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0(svelte@5.25.3)
|
||||
'@faker-js/faker':
|
||||
specifier: ^9.9.0
|
||||
version: 9.9.0
|
||||
@@ -269,8 +269,8 @@ packages:
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@2cf27e0':
|
||||
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@2cf27e0}
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0':
|
||||
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0}
|
||||
version: 2.0.0-RC.1
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0
|
||||
@@ -284,8 +284,8 @@ packages:
|
||||
'@appwrite.io/pink-legacy@1.0.3':
|
||||
resolution: {integrity: sha512-GGde5fmPhs+s6/3aFeMPc/kKADG/gTFkYQSy6oBN8pK0y0XNCLrZZgBv+EBbdhwdtqVEWXa0X85Mv9w7jcIlwQ==}
|
||||
|
||||
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@fb8b1ed':
|
||||
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@fb8b1ed}
|
||||
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0':
|
||||
resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0}
|
||||
version: 2.0.0-RC.2
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0
|
||||
@@ -3706,7 +3706,7 @@ snapshots:
|
||||
dependencies:
|
||||
svelte: 5.25.3
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@2cf27e0(svelte@5.25.3)':
|
||||
'@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@d8326d0(svelte@5.25.3)':
|
||||
dependencies:
|
||||
svelte: 5.25.3
|
||||
|
||||
@@ -3719,7 +3719,7 @@ snapshots:
|
||||
'@appwrite.io/pink-icons': 1.0.0
|
||||
the-new-css-reset: 1.11.3
|
||||
|
||||
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@fb8b1ed(svelte@5.25.3)':
|
||||
'@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@d8326d0(svelte@5.25.3)':
|
||||
dependencies:
|
||||
'@appwrite.io/pink-icons-svelte': 2.0.0-RC.1(svelte@5.25.3)
|
||||
'@floating-ui/dom': 1.6.13
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string = undefined;
|
||||
export let id: string;
|
||||
@@ -16,6 +17,7 @@
|
||||
export let step: number | 'any' = 0.001;
|
||||
export let min: string = undefined;
|
||||
export let max: string = undefined;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
|
||||
@@ -49,6 +51,7 @@
|
||||
{readonly}
|
||||
{min}
|
||||
{max}
|
||||
{leadingIcon}
|
||||
type="date"
|
||||
autofocus={autofocus || undefined}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { type ComponentType, onMount } from 'svelte';
|
||||
import { Input, Layout, Selector } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let id: string;
|
||||
@@ -13,6 +13,7 @@
|
||||
export let autocomplete = false;
|
||||
export let step: number | 'any' = 0.001;
|
||||
export let type: 'date' | 'time' | 'datetime-local' = 'date';
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
let element: HTMLInputElement;
|
||||
@@ -54,6 +55,7 @@
|
||||
{step}
|
||||
{type}
|
||||
helper={error}
|
||||
{leadingIcon}
|
||||
on:change={onChange}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}>
|
||||
{#if nullable}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string = null;
|
||||
export let id: string;
|
||||
@@ -13,6 +14,7 @@
|
||||
export let autofocus = false;
|
||||
export let autocomplete = false;
|
||||
export let maxlength: number | undefined = undefined;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
// https://www.geeksforgeeks.org/how-to-validate-a-domain-name-using-regular-expression/
|
||||
const pattern = String.raw`(?!-)[A-Za-z0-9\-]+([\-\.]{1}[a-z0-9]+)*\.[A-Za-z]{2,18}`;
|
||||
@@ -50,6 +52,7 @@
|
||||
{nullable}
|
||||
{pattern}
|
||||
{maxlength}
|
||||
{leadingIcon}
|
||||
on:input
|
||||
on:invalid={handleInvalid}
|
||||
type="text"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string = null;
|
||||
export let id: string;
|
||||
@@ -12,6 +13,7 @@
|
||||
export let readonly = false;
|
||||
export let autofocus = false;
|
||||
export let autocomplete = false;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
|
||||
@@ -42,6 +44,7 @@
|
||||
{required}
|
||||
{readonly}
|
||||
{label}
|
||||
{leadingIcon}
|
||||
{nullable}
|
||||
on:input
|
||||
on:invalid={handleInvalid}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let value = '';
|
||||
export let autofocus = true;
|
||||
export let required = false;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error = false;
|
||||
const pattern = String.raw`^[a-zA-Z0-9][a-zA-Z0-9._\-]*$`;
|
||||
@@ -26,6 +28,7 @@
|
||||
{pattern}
|
||||
{autofocus}
|
||||
{required}
|
||||
{leadingIcon}
|
||||
id="id"
|
||||
placeholder="Enter ID"
|
||||
maxlength={36}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string = null;
|
||||
export let id: string;
|
||||
@@ -15,6 +16,7 @@
|
||||
export let max: number = null;
|
||||
export let step: number | 'any' = 1;
|
||||
export let helper: string = undefined;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
|
||||
@@ -56,6 +58,7 @@
|
||||
{label}
|
||||
{step}
|
||||
{nullable}
|
||||
{leadingIcon}
|
||||
bind:value
|
||||
autofocus={autofocus || undefined}
|
||||
helper={error || helper}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { type ComponentType, onMount } from 'svelte';
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let label: string = undefined;
|
||||
@@ -15,6 +15,7 @@
|
||||
export let maxlength: number = null;
|
||||
export let autofocus = false;
|
||||
export let autocomplete = false;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let element: HTMLInputElement;
|
||||
let error: string;
|
||||
@@ -60,6 +61,7 @@
|
||||
{label}
|
||||
{pattern}
|
||||
{readonly}
|
||||
{leadingIcon}
|
||||
autofocus={autofocus || undefined}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}
|
||||
helper={error}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -12,6 +13,7 @@
|
||||
export let autocomplete = false;
|
||||
export let minlength = 8;
|
||||
export let maxlength: number = null;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
|
||||
@@ -42,6 +44,7 @@
|
||||
{minlength}
|
||||
{maxlength}
|
||||
{placeholder}
|
||||
{leadingIcon}
|
||||
state={error ? 'error' : 'default'}
|
||||
autofocus={autofocus || undefined}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string = null;
|
||||
export let id: string;
|
||||
@@ -14,6 +15,7 @@
|
||||
export let minlength: number = null;
|
||||
export let maxlength: number = 15;
|
||||
export let nullable = false;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
const pattern = String.raw`^\+[1-9]\d{1,14}$`;
|
||||
|
||||
@@ -55,6 +57,7 @@
|
||||
{label}
|
||||
{nullable}
|
||||
{pattern}
|
||||
{leadingIcon}
|
||||
on:input
|
||||
on:invalid={handleInvalid}
|
||||
type="text"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let value = '';
|
||||
export let autofocus = true;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error = false;
|
||||
|
||||
@@ -25,6 +27,7 @@
|
||||
<Input.Text
|
||||
{pattern}
|
||||
{autofocus}
|
||||
{leadingIcon}
|
||||
id="id"
|
||||
placeholder="Enter ID"
|
||||
maxlength={36}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { IconX, IconSearch } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Input, Icon } from '@appwrite.io/pink-svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { type ComponentType, createEventDispatcher } from 'svelte';
|
||||
import { onDestroy } from 'svelte';
|
||||
|
||||
export let value = '';
|
||||
@@ -11,6 +11,7 @@
|
||||
export let disabled = false;
|
||||
export let autofocus = false;
|
||||
export let label: string = '';
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let element: HTMLInputElement;
|
||||
@@ -48,6 +49,7 @@
|
||||
{required}
|
||||
{autofocus}
|
||||
{label}
|
||||
{leadingIcon}
|
||||
bind:value
|
||||
on:input={valueChange}>
|
||||
<svelte:fragment slot="start">
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { ComponentType } from 'svelte';
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string = '';
|
||||
export let value = '';
|
||||
export let placeholder = '';
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
</script>
|
||||
|
||||
<Input.Password {id} {label} {value} {placeholder} readonly />
|
||||
<Input.Password {id} {label} {value} {placeholder} {leadingIcon} readonly />
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
leadingHtml?: string;
|
||||
badge?: string;
|
||||
}[];
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let element: HTMLSelectElement;
|
||||
let error: string;
|
||||
@@ -56,6 +57,7 @@
|
||||
{placeholder}
|
||||
{disabled}
|
||||
{autofocus}
|
||||
{leadingIcon}
|
||||
helper={error ?? helper}
|
||||
{required}
|
||||
state={error ? 'error' : 'default'}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -9,6 +10,7 @@
|
||||
export let disabled = false;
|
||||
export let helper: string | undefined = undefined;
|
||||
export let pattern: string | undefined = undefined;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let value = '';
|
||||
let error: string;
|
||||
@@ -37,6 +39,7 @@
|
||||
{disabled}
|
||||
{pattern}
|
||||
{required}
|
||||
{leadingIcon}
|
||||
bind:value={tags}
|
||||
helper={error || helper}
|
||||
on:invalid={handleInvalid}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string = undefined;
|
||||
export let id: string;
|
||||
@@ -16,6 +17,7 @@
|
||||
export let autofocus = false;
|
||||
export let autocomplete = false;
|
||||
export let maxlength: number = null;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
export let error: string = null;
|
||||
|
||||
@@ -54,6 +56,7 @@
|
||||
{nullable}
|
||||
{readonly}
|
||||
{pattern}
|
||||
{leadingIcon}
|
||||
autofocus={autofocus || undefined}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}
|
||||
helper={error || helper}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label = '';
|
||||
export let id: string;
|
||||
@@ -15,6 +16,7 @@
|
||||
export let maxlength: number = null;
|
||||
export let rows = 3;
|
||||
export let helper: string = '';
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
|
||||
@@ -43,6 +45,7 @@
|
||||
{label}
|
||||
{nullable}
|
||||
{rows}
|
||||
{leadingIcon}
|
||||
autofocus={autofocus || undefined}
|
||||
helper={error || helper}
|
||||
state={error ? 'error' : 'default'}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string = undefined;
|
||||
export let id: string;
|
||||
@@ -16,6 +17,7 @@
|
||||
export let step: number | 'any' = 0.001;
|
||||
export let min: string = undefined;
|
||||
export let max: string = undefined;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
|
||||
@@ -49,6 +51,7 @@
|
||||
{readonly}
|
||||
{min}
|
||||
{max}
|
||||
{leadingIcon}
|
||||
type="time"
|
||||
autofocus={autofocus || undefined}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let label: string;
|
||||
export let id: string;
|
||||
@@ -13,6 +14,7 @@
|
||||
export let autofocus = false;
|
||||
export let autocomplete = false;
|
||||
export let maxlength: number = null;
|
||||
export let leadingIcon: ComponentType | undefined = undefined;
|
||||
|
||||
let error: string;
|
||||
|
||||
@@ -46,6 +48,7 @@
|
||||
{maxlength}
|
||||
{label}
|
||||
{nullable}
|
||||
{leadingIcon}
|
||||
type="url"
|
||||
autofocus={autofocus || undefined}
|
||||
autocomplete={autocomplete ? 'on' : 'off'}
|
||||
|
||||
+1
-3
@@ -41,9 +41,7 @@
|
||||
tables: []
|
||||
});
|
||||
|
||||
const sortedTables = $derived.by(() =>
|
||||
tables?.tables?.slice().sort((a, b) => a.name.localeCompare(b.name))
|
||||
);
|
||||
const sortedTables = $derived.by(() => tables?.tables);
|
||||
|
||||
const selectedTable = $derived.by(() =>
|
||||
sortedTables?.find((table: Models.Table) => table.$id === tableId)
|
||||
|
||||
+4
-1
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { InputSelect } from '$lib/elements/forms';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconToggle } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -29,4 +30,6 @@
|
||||
{optionalText}
|
||||
autofocus={limited}
|
||||
placeholder="Select a value"
|
||||
required={column.required} />
|
||||
required={column.required}
|
||||
leadingIcon={!limited ? IconToggle : undefined}>
|
||||
</InputSelect>
|
||||
|
||||
+11
-2
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { InputDateTime } from '$lib/elements/forms';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { InputDateTime } from '$lib/elements/forms';
|
||||
import { IconCalendar } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -16,4 +17,12 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<InputDateTime {id} {label} {type} bind:value {nullable} {autofocus} required={column.required} />
|
||||
<InputDateTime
|
||||
{id}
|
||||
{label}
|
||||
{type}
|
||||
bind:value
|
||||
{nullable}
|
||||
{autofocus}
|
||||
required={column.required}
|
||||
leadingIcon={!limited ? IconCalendar : undefined} />
|
||||
|
||||
+5
-3
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import InputEmail from '$lib/elements/forms/inputEmail.svelte';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconMail } from '@appwrite.io/pink-icons-svelte';
|
||||
import InputEmail from '$lib/elements/forms/inputEmail.svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -18,5 +19,6 @@
|
||||
bind:value
|
||||
{nullable}
|
||||
{autofocus}
|
||||
placeholder="Enter URL"
|
||||
required={column.required} />
|
||||
placeholder="name@example.com"
|
||||
required={column.required}
|
||||
leadingIcon={!limited ? IconMail : undefined} />
|
||||
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { InputSelect } from '$lib/elements/forms';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconList } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -50,5 +51,6 @@
|
||||
{optionalText}
|
||||
autofocus={limited}
|
||||
required={column.required}
|
||||
placeholder="Select a value" />
|
||||
placeholder="Select a value"
|
||||
leadingIcon={!limited ? IconList : undefined} />
|
||||
{/if}
|
||||
|
||||
+3
-1
@@ -2,6 +2,7 @@
|
||||
import { InputNumber } from '$lib/elements/forms';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { isWithinSafeRange } from '$lib/helpers/numbers';
|
||||
import { IconHashtag } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -30,4 +31,5 @@
|
||||
min={column.min}
|
||||
max={column.max}
|
||||
required={column.required}
|
||||
step={column.type === 'double' ? 'any' : 1} />
|
||||
step={column.type === 'double' ? 'any' : 1}
|
||||
leadingIcon={!limited ? IconHashtag : undefined} />
|
||||
|
||||
+16
-6
@@ -6,7 +6,7 @@
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
import { type ComponentType, onMount } from 'svelte';
|
||||
import { isRelationshipToMany } from '../../store';
|
||||
import { IconPlus, IconX } from '@appwrite.io/pink-icons-svelte';
|
||||
import { IconPlus, IconRelationship, IconX } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Icon, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
type SelectOption = {
|
||||
@@ -201,6 +201,8 @@
|
||||
{#if !limited}
|
||||
<Layout.Stack direction="row" alignContent="space-between">
|
||||
<Layout.Stack gap="xxs" direction="row" alignItems="center">
|
||||
<Icon icon={IconRelationship} size="s" color="--fgcolor-neutral-weak" />
|
||||
|
||||
<Typography.Text variant="m-500">{label}</Typography.Text>
|
||||
<Typography.Text variant="m-400" color="--fgcolor-neutral-tertiary">
|
||||
{optionalText}
|
||||
@@ -229,7 +231,8 @@
|
||||
on:change={() => {
|
||||
if (!relatedList[0]) relatedList = [''];
|
||||
updateRelatedList();
|
||||
}} />
|
||||
}}
|
||||
leadingIcon={!limited ? IconRelationship : undefined} />
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
|
||||
@@ -245,7 +248,9 @@
|
||||
options={getAvailableOptions(actualIndex)}
|
||||
bind:value={relatedList[actualIndex]}
|
||||
placeholder={`Select ${column.key}`}
|
||||
on:change={updateRelatedList} />
|
||||
on:change={updateRelatedList}
|
||||
leadingIcon={!limited ? IconRelationship : undefined} />
|
||||
|
||||
{#if !limited}
|
||||
{#if relatedList[actualIndex]}
|
||||
<div style:padding-block-start="0.5rem">
|
||||
@@ -271,7 +276,9 @@
|
||||
required
|
||||
options={getAvailableOptions(i)}
|
||||
bind:value={item}
|
||||
on:change={updateRelatedList} />
|
||||
on:change={updateRelatedList}
|
||||
leadingIcon={!limited ? IconRelationship : undefined} />
|
||||
|
||||
<div style:padding-block-start="0.5rem">
|
||||
<Button
|
||||
icon
|
||||
@@ -297,7 +304,9 @@
|
||||
placeholder={`Select ${column.key}`}
|
||||
bind:value={newItemValue}
|
||||
options={getAvailableOptions()}
|
||||
on:change={addNewItem} />
|
||||
on:change={addNewItem}
|
||||
leadingIcon={!limited ? IconRelationship : undefined} />
|
||||
|
||||
<div style:padding-block-start="0.5rem">
|
||||
<Button icon extraCompact on:click={cancelAddItem}>
|
||||
<Icon icon={IconX} size="s" />
|
||||
@@ -333,7 +342,8 @@
|
||||
} else {
|
||||
value = rowList.rows.find((row) => row.$id === singleRel);
|
||||
}
|
||||
}} />
|
||||
}}
|
||||
leadingIcon={!limited ? IconRelationship : undefined} />
|
||||
|
||||
{#if !limited && singleRel}
|
||||
<div style:padding-block-start="2.25rem">
|
||||
|
||||
+5
-2
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Layout, Link } from '@appwrite.io/pink-svelte';
|
||||
import { IconText } from '@appwrite.io/pink-icons-svelte';
|
||||
import { InputText, InputTextarea } from '$lib/elements/forms';
|
||||
|
||||
let {
|
||||
@@ -132,7 +133,8 @@
|
||||
{autofocus}
|
||||
bind:value={stringValue}
|
||||
required={column.required}
|
||||
placeholder={getPlaceholder()}>
|
||||
placeholder={getPlaceholder()}
|
||||
leadingIcon={!limited ? IconText : undefined}>
|
||||
<Layout.Stack direction="column" alignItems="flex-start" slot="end">
|
||||
{#if array}
|
||||
<Link.Button on:click size="s" variant="quiet">Advanced edit</Link.Button>
|
||||
@@ -148,5 +150,6 @@
|
||||
{maxlength}
|
||||
bind:value={stringValue}
|
||||
placeholder="Enter string"
|
||||
required={column.required} />
|
||||
required={column.required}
|
||||
leadingIcon={!limited ? IconText : undefined} />
|
||||
{/if}
|
||||
|
||||
+4
-2
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import InputURL from '$lib/elements/forms/inputURL.svelte';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import InputURL from '$lib/elements/forms/inputURL.svelte';
|
||||
import { IconLink } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let id: string;
|
||||
export let label: string;
|
||||
@@ -19,4 +20,5 @@
|
||||
{nullable}
|
||||
{autofocus}
|
||||
placeholder="Enter URL"
|
||||
required={column.required} />
|
||||
required={column.required}
|
||||
leadingIcon={!limited ? IconLink : undefined} />
|
||||
|
||||
+53
-20
@@ -11,8 +11,9 @@
|
||||
import { type Columns, PROHIBITED_ROW_KEYS } from '../store';
|
||||
import ColumnItem from './columns/columnItem.svelte';
|
||||
import { buildWildcardColumnsQuery, isRelationship, isRelationshipToMany } from './store';
|
||||
import { Divider, Layout, Skeleton, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Accordion, Layout, Skeleton } from '@appwrite.io/pink-svelte';
|
||||
import { deepClone } from '$lib/helpers/object';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
|
||||
const databaseId = page.params.database;
|
||||
|
||||
@@ -192,6 +193,7 @@
|
||||
const relatedIds = currentColumn.map((doc: string | Record<string, unknown>) =>
|
||||
typeof doc === 'string' ? doc : doc.$id
|
||||
);
|
||||
|
||||
return !symmetricDifference(workIds, relatedIds).length;
|
||||
} else {
|
||||
const workId = typeof workColumn === 'string' ? workColumn : workColumn?.$id;
|
||||
@@ -312,6 +314,20 @@
|
||||
};
|
||||
}
|
||||
|
||||
function getAccordionTitle(row: Models.Row): string {
|
||||
const names = preferences.getDisplayNames(row.$tableId).filter((name) => name !== '$id');
|
||||
|
||||
const values = names
|
||||
.map((name) => row?.[name])
|
||||
.filter((value) => value != null && typeof value === 'string' && value !== '');
|
||||
|
||||
if (!values.length) {
|
||||
return row.$id;
|
||||
}
|
||||
|
||||
return `${values.join(' | ')} (...${row.$id.slice(-5)})`;
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (rows && tableId) {
|
||||
loadRelatedRow().then(() => {
|
||||
@@ -322,16 +338,26 @@
|
||||
</script>
|
||||
|
||||
{#if loading}
|
||||
<div style:margin-block="" style:margin-inline-end="2.25rem">
|
||||
<div style:margin-inline-end="2.25rem">
|
||||
<Skeleton variant="line" height={40} width="auto" />
|
||||
</div>
|
||||
{:else if relatedTable?.columns?.length && fetchedRows.length}
|
||||
<!-- we should not show current table column items in this view -->
|
||||
{@const twoWayKeys = new Set(
|
||||
relatedTable.columns
|
||||
.filter((column: Models.ColumnRelationship) => column.twoWay)
|
||||
.map((c) => c.key)
|
||||
)}
|
||||
|
||||
<!-- render the filtered ones -->
|
||||
{@const columnsToRender = relatedTable.columns.filter((c) => !twoWayKeys.has(c.key))}
|
||||
|
||||
<div bind:this={columnFormWrapper}>
|
||||
{#if fetchedRows.length === 1}
|
||||
{@const workStore = getStore(fetchedRows[0].$id)}
|
||||
{#if workStore}
|
||||
<Layout.Stack direction="column" gap="l">
|
||||
{#each relatedTable.columns as column}
|
||||
{#each columnsToRender as column}
|
||||
{@const label = column.key}
|
||||
<ColumnItem
|
||||
{column}
|
||||
@@ -344,28 +370,35 @@
|
||||
{/if}
|
||||
{:else}
|
||||
<Layout.Stack direction="column" gap="m" class="column-item-stack">
|
||||
<Typography.Text variant="l-400">{relatedTable.name}</Typography.Text>
|
||||
<Layout.Stack direction="column" gap="l" class="column-item-stack">
|
||||
<Layout.Stack direction="column" gap="xs" class="column-item-stack">
|
||||
{#each fetchedRows as row, index (row.$id)}
|
||||
{@const workStore = getStore(row.$id)}
|
||||
{#if workStore}
|
||||
{#each relatedTable.columns as column}
|
||||
{@const label = column.key}
|
||||
<ColumnItem
|
||||
{column}
|
||||
{label}
|
||||
editing
|
||||
formValues={workStore}
|
||||
onUpdateFormValues={handleFormUpdate(row.$id)} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
{#if index < fetchedRows.length - 1}
|
||||
<Divider />
|
||||
{/if}
|
||||
<Accordion
|
||||
title={getAccordionTitle(row)}
|
||||
hideDivider={index >= fetchedRows.length - 1}>
|
||||
{#if workStore}
|
||||
<Layout.Stack direction="column" gap="m">
|
||||
{#each columnsToRender as column}
|
||||
{@const label = column.key}
|
||||
<ColumnItem
|
||||
{column}
|
||||
{label}
|
||||
editing
|
||||
formValues={workStore}
|
||||
onUpdateFormValues={handleFormUpdate(row.$id)} />
|
||||
{/each}
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Accordion>
|
||||
{/each}
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
:global(.column-item-stack .divider) {
|
||||
margin-inline-start: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
+14
-6
@@ -40,7 +40,8 @@
|
||||
spreadsheetRenderKey,
|
||||
expandTabs,
|
||||
databaseRelatedRowSheetOptions,
|
||||
rowPermissionSheet
|
||||
rowPermissionSheet,
|
||||
type Columns
|
||||
} from './store';
|
||||
import type { Column, ColumnType } from '$lib/helpers/types';
|
||||
import {
|
||||
@@ -465,9 +466,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
function openSideSheetForRelationsToMany(tableId: string, rows: string | Models.Row[]) {
|
||||
$databaseRelatedRowSheetOptions.tableId = tableId;
|
||||
function openSideSheetForRelationsToMany(rows: string | Models.Row[], column?: Columns) {
|
||||
const relatedCol = column as Models.ColumnRelationship;
|
||||
$databaseRelatedRowSheetOptions.rows = rows;
|
||||
$databaseRelatedRowSheetOptions.tableId = relatedCol.relatedTable;
|
||||
|
||||
$databaseRelatedRowSheetOptions.show = true;
|
||||
}
|
||||
|
||||
@@ -950,11 +953,16 @@
|
||||
{/if}
|
||||
|
||||
<svelte:fragment slot="cell-editor" let:close>
|
||||
{@const isRelatedToMany = isRelationshipToMany(rowColumn)}
|
||||
{@const hasItems = isRelatedToMany
|
||||
? row[columnId]?.length
|
||||
: false}
|
||||
|
||||
<EditRowCell
|
||||
{row}
|
||||
column={rowColumn}
|
||||
onRowStructureUpdate={updateRowContents}
|
||||
noInlineEdit={isRelationshipToMany(rowColumn)}
|
||||
noInlineEdit={isRelatedToMany && hasItems}
|
||||
onChange={(row) => paginatedRows.update(index, row)}
|
||||
onRevert={(row) => paginatedRows.update(index, row)}
|
||||
openSideSheet={() => {
|
||||
@@ -962,8 +970,8 @@
|
||||
|
||||
if (isRelationshipToMany(rowColumn)) {
|
||||
openSideSheetForRelationsToMany(
|
||||
columnId,
|
||||
row[columnId]
|
||||
row[columnId],
|
||||
rowColumn
|
||||
);
|
||||
} else {
|
||||
onSelectSheetOption('update', null, 'row', row);
|
||||
|
||||
Reference in New Issue
Block a user