Skip to content
Open
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
29 changes: 29 additions & 0 deletions src/lib/helpers/prefs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export type PrefRow = { key: string; value: string };

export function normalizePrefs(entries: [string, string][] | PrefRow[]): [string, string][] {
return entries
.map((item): [string, string] =>
Array.isArray(item)
? [item[0], item[1]]
: [item.key, item.value]
)

.filter(([k, v]) => k.trim() && v.trim())
.sort(([a], [b]) => a.localeCompare(b));
}

export function createPrefRow(key = '', value = ''): PrefRow {
return { key, value };
}

export function isAddDisabled(prefs: PrefRow[] | null): boolean {
return (
!!prefs &&
prefs.length > 0 &&
!(prefs[prefs.length - 1].key && prefs[prefs.length - 1].value)
);
}

export function sanitizePrefs(prefs: PrefRow[]) {
return prefs.filter((p) => p.key.trim() && p.value.trim());
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,39 @@
import { Icon, Layout } from '@appwrite.io/pink-svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { page } from '$app/state';
import deepEqual from 'deep-equal';
import type { PrefRow } from '$lib/helpers/prefs';
import { normalizePrefs, createPrefRow, isAddDisabled, sanitizePrefs } from '$lib/helpers/prefs';


$: 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 currentNormalized = normalizePrefs(prefs);
const originalNormalized = normalizePrefs(
Object.entries($team.prefs as Record<string, string>)
);

arePrefsDisabled = deepEqual(currentNormalized, originalNormalized);
}

let prefs: [string, string][] = null;
let prefs: PrefRow[] = null;
let arePrefsDisabled = true;

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 = sanitizePrefs(prefs);

const updatedPrefs =
sanitizedPrefs.length === 0
? {}
: Object.fromEntries(sanitizedPrefs.map((pref) => [pref.key, pref.value]));

await sdk
.forProject(page.params.region, page.params.project)
Expand Down Expand Up @@ -66,32 +73,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 (index)}
<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 as HTMLInputElement).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 as HTMLInputElement).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>
Expand All @@ -102,16 +113,10 @@
<div>
<Button
secondary
disabled={prefs?.length &&
prefs[prefs.length - 1][0] &&
prefs[prefs.length - 1][1]
? false
: true}
disabled={isAddDisabled(prefs)}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
}
if (!prefs) return;
prefs = [...prefs, createPrefRow()];
}}>
<Icon icon={IconPlus} slot="start" size="s" />
Add preference
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,37 @@
import { Icon, Layout } from '@appwrite.io/pink-svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { page } from '$app/state';
import deepEqual from 'deep-equal';
import type { PrefRow } from '$lib/helpers/prefs';
import { normalizePrefs, createPrefRow, isAddDisabled, sanitizePrefs } from '$lib/helpers/prefs';


$: if (prefs) {
if (JSON.stringify(prefs) !== JSON.stringify(Object.entries($user.prefs))) {
arePrefsDisabled = false;
} else {
arePrefsDisabled = true;
}
const currentNormalized = normalizePrefs(prefs);
const originalNormalized = normalizePrefs(Object.entries($user.prefs));

arePrefsDisabled = deepEqual(currentNormalized, originalNormalized);
}

let prefs: [string, string][] = null;
let prefs: PrefRow[] = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Type annotation mismatch: null is not assignable to PrefRow[].

The variable is typed as PrefRow[] but initialized with null. This is a TypeScript type mismatch.

🛠️ Suggested fix
-    let prefs: PrefRow[] = null;
+    let prefs: PrefRow[] | null = null;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let prefs: PrefRow[] = null;
let prefs: PrefRow[] | null = null;
🤖 Prompt for AI Agents
In
`@src/routes/`(console)/project-[region]-[project]/auth/user-[user]/updatePrefs.svelte
at line 32, The declaration let prefs: PrefRow[] = null; causes a TypeScript
type mismatch because null is not assignable to PrefRow[]; either initialize
prefs to an empty array (e.g., set initial value to []) or broaden the type to
allow null by changing the annotation to PrefRow[] | null; update any downstream
code that checks for null accordingly (look for the prefs variable in this
module and any functions that read it) so the chosen approach is consistent
across usages.

let arePrefsDisabled = true;

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 = sanitizePrefs(prefs);

const updatedPrefs =
sanitizedPrefs.length === 0
? {}
: Object.fromEntries(sanitizedPrefs.map((pref) => [pref.key, pref.value]));

await sdk
.forProject(page.params.region, page.params.project)
Expand Down Expand Up @@ -61,32 +70,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 (index)}
<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 as HTMLInputElement).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 as HTMLInputElement).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>
Expand All @@ -97,16 +110,10 @@
<div>
<Button
secondary
disabled={prefs?.length &&
prefs[prefs.length - 1][0] &&
prefs[prefs.length - 1][1]
? false
: true}
disabled={isAddDisabled(prefs)}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
}
if (!prefs) return;
prefs = [...prefs, createPrefRow()];
}}>
<Icon icon={IconPlus} slot="start" size="s" />
Add preference
Expand Down