fix(dashboard): correct user/team prefs deletion and binding issues

This commit is contained in:
Your Name
2026-01-07 19:48:48 +05:30
parent 5939091827
commit e87d80dd2d
2 changed files with 94 additions and 56 deletions
@@ -12,31 +12,45 @@
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { page } from '$app/state';
type PrefRow = { id: string; key: string; value: string };
$: if (prefs) {
if (JSON.stringify(prefs) !== JSON.stringify(Object.entries($team.prefs))) {
if (!!prefs[prefs.length - 1][0] && !!prefs[prefs.length - 1][1]) {
arePrefsDisabled = false;
} else {
arePrefsDisabled = true;
}
} else {
arePrefsDisabled = true;
}
const normalize = (entries: [string, string][] | PrefRow[]) =>
entries
.map(item => Array.isArray(item) ? item : [item.key, item.value])
.filter(([k, v]: [string, string]) => k.trim() && v.trim())
.sort(([a]: [string, string], [b]: [string, string]) => a.localeCompare(b));
const currentNormalized = normalize(prefs);
const originalNormalized = normalize(Object.entries($team.prefs as Record<string, string>));
arePrefsDisabled = JSON.stringify(currentNormalized) === JSON.stringify(originalNormalized);
}
let prefs: [string, string][] = null;
let prefs: PrefRow[] = null;
let arePrefsDisabled = true;
let nextId = 0;
function createPrefRow(key = '', value = ''): PrefRow {
return { id: `pref-${nextId++}`, key, value };
}
onMount(async () => {
prefs = Object.entries($team.prefs as Record<string, string>);
if (!prefs?.length) {
prefs.push(['', '']);
}
const entries = Object.entries($team.prefs as Record<string, string>);
prefs = entries.length > 0
? entries.map(([key, value]) => createPrefRow(key, value))
: [createPrefRow()];
});
async function updatePrefs() {
try {
let updatedPrefs = Object.fromEntries(prefs);
const sanitizedPrefs = prefs.filter(
pref => pref.key.trim() !== '' && pref.value.trim() !== ''
);
const updatedPrefs = sanitizedPrefs.length === 0
? {}
: Object.fromEntries(sanitizedPrefs.map(pref => [pref.key, pref.value]));
await sdk
.forProject(page.params.region, page.params.project)
@@ -66,32 +80,36 @@
they can easily be shared across members.
<svelte:fragment slot="aside">
{#if prefs}
{#each prefs as [key, value], index}
{#each prefs as pref, index (pref.id)}
<Layout.Stack direction="row" alignItems="flex-end">
<InputText
id={`key-${index}`}
bind:value={key}
value={pref.key}
on:input={(e) => {
prefs[index].key = e.target.value;
prefs = [...prefs];
}}
placeholder="Enter key"
label={index === 0 ? 'Key' : undefined}
required />
<Layout.Stack direction="row" alignItems="flex-end" gap="xs">
<InputText
id={`value-${index}`}
bind:value
value={pref.value}
on:input={(e) => {
prefs[index].value = e.target.value;
prefs = [...prefs];
}}
placeholder="Enter value"
label={index === 0 ? 'Value' : undefined}
required />
<Button
icon
compact
disabled={(!key || !value) && index === 0}
disabled={(!pref.key || !pref.value) && index === 0}
on:click={() => {
if (index === 0 && prefs?.length === 1) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
prefs.splice(index, 1);
prefs = [...prefs];
}}>
<span class="icon-x" aria-hidden="true"></span>
</Button>
@@ -103,14 +121,13 @@
<Button
secondary
disabled={prefs?.length &&
prefs[prefs.length - 1][0] &&
prefs[prefs.length - 1][1]
prefs[prefs.length - 1].key &&
prefs[prefs.length - 1].value
? false
: true}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
if (prefs[prefs.length - 1].key && prefs[prefs.length - 1].value) {
prefs = [...prefs, createPrefRow()];
}
}}>
<Icon icon={IconPlus} slot="start" size="s" />
@@ -12,27 +12,45 @@
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { page } from '$app/state';
type PrefRow = { id: string; key: string; value: string };
$: if (prefs) {
if (JSON.stringify(prefs) !== JSON.stringify(Object.entries($user.prefs))) {
arePrefsDisabled = false;
} else {
arePrefsDisabled = true;
}
const normalize = (entries: [string, string][] | PrefRow[]) =>
entries
.map(item => Array.isArray(item) ? item : [item.key, item.value])
.filter(([k, v]: [string, string]) => k.trim() && v.trim())
.sort(([a]: [string, string], [b]: [string, string]) => a.localeCompare(b));
const currentNormalized = normalize(prefs);
const originalNormalized = normalize(Object.entries($user.prefs));
arePrefsDisabled = JSON.stringify(currentNormalized) === JSON.stringify(originalNormalized);
}
let prefs: [string, string][] = null;
let prefs: PrefRow[] = null;
let arePrefsDisabled = true;
let nextId = 0;
function createPrefRow(key = '', value = ''): PrefRow {
return { id: `pref-${nextId++}`, key, value };
}
onMount(async () => {
prefs = Object.entries($user.prefs);
if (!prefs?.length) {
prefs.push(['', '']);
}
const entries = Object.entries($user.prefs);
prefs = entries.length > 0
? entries.map(([key, value]) => createPrefRow(key, value))
: [createPrefRow()];
});
async function updatePrefs() {
try {
let updatedPrefs = Object.fromEntries(prefs);
const sanitizedPrefs = prefs.filter(
pref => pref.key.trim() !== '' && pref.value.trim() !== ''
);
const updatedPrefs = sanitizedPrefs.length === 0
? {}
: Object.fromEntries(sanitizedPrefs.map(pref => [pref.key, pref.value]));
await sdk
.forProject(page.params.region, page.params.project)
@@ -61,32 +79,36 @@
Add custom user preferences to share them across devices and sessions.
<svelte:fragment slot="aside">
{#if prefs}
{#each prefs as [key, value], index}
{#each prefs as pref, index (pref.id)}
<Layout.Stack direction="row" alignItems="flex-end">
<InputText
id={`key-${index}`}
bind:value={key}
value={pref.key}
on:input={(e) => {
prefs[index].key = e.target.value;
prefs = [...prefs];
}}
placeholder="Enter key"
label={index === 0 ? 'Key' : undefined}
required />
<Layout.Stack direction="row" alignItems="flex-end" gap="xs">
<InputText
id={`value-${index}`}
bind:value
value={pref.value}
on:input={(e) => {
prefs[index].value = e.target.value;
prefs = [...prefs];
}}
placeholder="Enter value"
label={index === 0 ? 'Value' : undefined}
required />
<Button
icon
compact
disabled={(!key || !value) && index === 0}
disabled={(!pref.key || !pref.value) && index === 0}
on:click={() => {
if (index === 0 && prefs?.length === 1) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
prefs.splice(index, 1);
prefs = [...prefs];
}}>
<span class="icon-x" aria-hidden="true"></span>
</Button>
@@ -98,14 +120,13 @@
<Button
secondary
disabled={prefs?.length &&
prefs[prefs.length - 1][0] &&
prefs[prefs.length - 1][1]
prefs[prefs.length - 1].key &&
prefs[prefs.length - 1].value
? false
: true}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
if (prefs[prefs.length - 1].key && prefs[prefs.length - 1].value) {
prefs = [...prefs, createPrefRow()];
}
}}>
<Icon icon={IconPlus} slot="start" size="s" />