Skip to content

Commit 3fcf1d8

Browse files
authored
Merge pull request #2987 from appwrite/fix-team-preferences-console
fix: render team preferences in console
2 parents 145cab7 + 8bafb89 commit 3fcf1d8

3 files changed

Lines changed: 101 additions & 26 deletions

File tree

src/lib/helpers/prefs.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,25 @@ function stringTrim(s: unknown): string {
44
return String(s ?? '').trim();
55
}
66

7+
export function stringifyPrefValue(value: unknown): string {
8+
if (typeof value === 'string') return value;
9+
if (value === null || value === undefined) return '';
10+
11+
try {
12+
return JSON.stringify(value);
13+
} catch {
14+
return String(value);
15+
}
16+
}
17+
718
export function normalizePrefs(
819
entries: [string, unknown][] | PrefRow[] | { key: unknown; value: unknown }[]
920
): [string, string][] {
1021
return entries
1122
.map((item): [string, string] =>
1223
Array.isArray(item)
13-
? [String(item[0] ?? ''), String(item[1] ?? '')]
14-
: [String(item.key ?? ''), String(item.value ?? '')]
24+
? [String(item[0] ?? ''), stringifyPrefValue(item[1])]
25+
: [String(item.key ?? ''), stringifyPrefValue(item.value)]
1526
)
1627
.filter(([k, v]) => stringTrim(k).length > 0 && stringTrim(v).length > 0)
1728
.sort(([a], [b]) => a.localeCompare(b));
@@ -21,6 +32,14 @@ export function createPrefRow(key = '', value = ''): PrefRow {
2132
return { key, value };
2233
}
2334

35+
export function createPrefRows(prefs: Record<string, unknown> | null | undefined): PrefRow[] {
36+
const entries = Object.entries(prefs ?? {});
37+
38+
return entries.length > 0
39+
? entries.map(([key, value]) => createPrefRow(String(key ?? ''), stringifyPrefValue(value)))
40+
: [createPrefRow()];
41+
}
42+
2443
export function isAddDisabled(prefs: PrefRow[] | null): boolean {
2544
return (
2645
!!prefs &&
@@ -32,3 +51,27 @@ export function isAddDisabled(prefs: PrefRow[] | null): boolean {
3251
export function sanitizePrefs(prefs: PrefRow[]) {
3352
return prefs.filter((p) => stringTrim(p.key).length > 0 && stringTrim(p.value).length > 0);
3453
}
54+
55+
export function parsePrefValue(value: string, original: unknown): unknown {
56+
const trimmed = value.trim();
57+
58+
if (typeof original === 'number') {
59+
const parsed = Number(trimmed);
60+
return Number.isNaN(parsed) ? value : parsed;
61+
}
62+
63+
if (typeof original === 'boolean') {
64+
if (trimmed === 'true') return true;
65+
if (trimmed === 'false') return false;
66+
return value;
67+
}
68+
69+
if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return value;
70+
71+
try {
72+
return JSON.parse(value);
73+
} catch {
74+
if (typeof original !== 'string' && original !== undefined) return original;
75+
return value;
76+
}
77+
}

src/routes/(console)/project-[region]-[project]/auth/teams/team-[team]/updatePrefs.svelte

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import { Button, Form, InputText } from '$lib/elements/forms';
77
import { addNotification } from '$lib/stores/notifications';
88
import { sdk } from '$lib/stores/sdk';
9-
import { onMount } from 'svelte';
109
import { team } from './store';
1110
import { Icon, Layout } from '@appwrite.io/pink-svelte';
1211
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
@@ -16,10 +15,25 @@
1615
import {
1716
normalizePrefs,
1817
createPrefRow,
18+
createPrefRows,
1919
isAddDisabled,
20+
parsePrefValue,
2021
sanitizePrefs
2122
} from '$lib/helpers/prefs';
2223
24+
$: {
25+
const originalNormalized = normalizePrefs(Object.entries($team?.prefs ?? {}));
26+
27+
if (
28+
!prefs ||
29+
(!hasUnsavedPrefsChanges && !deepEqual(lastPrefsNormalized, originalNormalized))
30+
) {
31+
prefs = createPrefRows($team?.prefs);
32+
lastPrefsNormalized = originalNormalized;
33+
hasUnsavedPrefsChanges = false;
34+
}
35+
}
36+
2337
$: if (prefs) {
2438
const currentNormalized = normalizePrefs(prefs);
2539
const originalNormalized = normalizePrefs(Object.entries($team?.prefs ?? {}));
@@ -29,16 +43,8 @@
2943
3044
let prefs: PrefRow[] = null;
3145
let arePrefsDisabled = true;
32-
33-
onMount(async () => {
34-
const entries = Object.entries($team?.prefs ?? {});
35-
prefs =
36-
entries.length > 0
37-
? entries.map(([key, value]) =>
38-
createPrefRow(String(key ?? ''), String(value ?? ''))
39-
)
40-
: [createPrefRow()];
41-
});
46+
let hasUnsavedPrefsChanges = false;
47+
let lastPrefsNormalized: [string, string][] = [];
4248
4349
async function updatePrefs() {
4450
try {
@@ -47,12 +53,18 @@
4753
const updatedPrefs =
4854
sanitizedPrefs.length === 0
4955
? {}
50-
: Object.fromEntries(sanitizedPrefs.map((pref) => [pref.key, pref.value]));
56+
: Object.fromEntries(
57+
sanitizedPrefs.map((pref) => [
58+
pref.key,
59+
parsePrefValue(pref.value, $team?.prefs?.[pref.key])
60+
])
61+
);
5162
5263
await sdk
5364
.forProject(page.params.region, page.params.project)
5465
.teams.updatePrefs({ teamId: $team.$id, prefs: updatedPrefs });
5566
await invalidate(Dependencies.TEAM);
67+
hasUnsavedPrefsChanges = false;
5668
arePrefsDisabled = true;
5769
5870
addNotification({
@@ -84,6 +96,7 @@
8496
value={pref.key}
8597
on:input={(e) => {
8698
pref.key = (e.currentTarget as HTMLInputElement).value;
99+
hasUnsavedPrefsChanges = true;
87100
prefs = [...prefs];
88101
}}
89102
placeholder="Enter key"
@@ -95,6 +108,7 @@
95108
value={pref.value}
96109
on:input={(e) => {
97110
pref.value = (e.currentTarget as HTMLInputElement).value;
111+
hasUnsavedPrefsChanges = true;
98112
prefs = [...prefs];
99113
}}
100114
placeholder="Enter value"
@@ -106,6 +120,7 @@
106120
disabled={(!pref.key || !pref.value) && index === 0}
107121
on:click={() => {
108122
prefs.splice(index, 1);
123+
hasUnsavedPrefsChanges = true;
109124
prefs = [...prefs];
110125
}}>
111126
<span class="icon-x" aria-hidden="true"></span>
@@ -120,6 +135,7 @@
120135
disabled={isAddDisabled(prefs)}
121136
on:click={() => {
122137
if (!prefs) return;
138+
hasUnsavedPrefsChanges = true;
123139
prefs = [...prefs, createPrefRow()];
124140
}}>
125141
<Icon icon={IconPlus} slot="start" size="s" />

src/routes/(console)/project-[region]-[project]/auth/user-[user]/updatePrefs.svelte

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import { Button, Form, InputText } from '$lib/elements/forms';
77
import { addNotification } from '$lib/stores/notifications';
88
import { sdk } from '$lib/stores/sdk';
9-
import { onMount } from 'svelte';
109
import { user } from './store';
1110
import { Icon, Layout } from '@appwrite.io/pink-svelte';
1211
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
@@ -16,10 +15,25 @@
1615
import {
1716
normalizePrefs,
1817
createPrefRow,
18+
createPrefRows,
1919
isAddDisabled,
20+
parsePrefValue,
2021
sanitizePrefs
2122
} from '$lib/helpers/prefs';
2223
24+
$: {
25+
const originalNormalized = normalizePrefs(Object.entries($user?.prefs ?? {}));
26+
27+
if (
28+
!prefs ||
29+
(!hasUnsavedPrefsChanges && !deepEqual(lastPrefsNormalized, originalNormalized))
30+
) {
31+
prefs = createPrefRows($user?.prefs);
32+
lastPrefsNormalized = originalNormalized;
33+
hasUnsavedPrefsChanges = false;
34+
}
35+
}
36+
2337
$: if (prefs) {
2438
const currentNormalized = normalizePrefs(prefs);
2539
const originalNormalized = normalizePrefs(Object.entries($user?.prefs ?? {}));
@@ -29,16 +43,8 @@
2943
3044
let prefs: PrefRow[] = null;
3145
let arePrefsDisabled = true;
32-
33-
onMount(async () => {
34-
const entries = Object.entries($user?.prefs ?? {});
35-
prefs =
36-
entries.length > 0
37-
? entries.map(([key, value]) =>
38-
createPrefRow(String(key ?? ''), String(value ?? ''))
39-
)
40-
: [createPrefRow()];
41-
});
46+
let hasUnsavedPrefsChanges = false;
47+
let lastPrefsNormalized: [string, string][] = [];
4248
4349
async function updatePrefs() {
4450
try {
@@ -47,12 +53,18 @@
4753
const updatedPrefs =
4854
sanitizedPrefs.length === 0
4955
? {}
50-
: Object.fromEntries(sanitizedPrefs.map((pref) => [pref.key, pref.value]));
56+
: Object.fromEntries(
57+
sanitizedPrefs.map((pref) => [
58+
pref.key,
59+
parsePrefValue(pref.value, $user?.prefs?.[pref.key])
60+
])
61+
);
5162
5263
await sdk
5364
.forProject(page.params.region, page.params.project)
5465
.users.updatePrefs({ userId: $user.$id, prefs: updatedPrefs });
5566
await invalidate(Dependencies.USER);
67+
hasUnsavedPrefsChanges = false;
5668
arePrefsDisabled = true;
5769
5870
addNotification({
@@ -83,6 +95,7 @@
8395
value={pref.key}
8496
on:input={(e) => {
8597
pref.key = (e.currentTarget as HTMLInputElement).value;
98+
hasUnsavedPrefsChanges = true;
8699
prefs = [...prefs];
87100
}}
88101
placeholder="Enter key"
@@ -94,6 +107,7 @@
94107
value={pref.value}
95108
on:input={(e) => {
96109
pref.value = (e.currentTarget as HTMLInputElement).value;
110+
hasUnsavedPrefsChanges = true;
97111
prefs = [...prefs];
98112
}}
99113
placeholder="Enter value"
@@ -105,6 +119,7 @@
105119
disabled={(!pref.key || !pref.value) && index === 0}
106120
on:click={() => {
107121
prefs.splice(index, 1);
122+
hasUnsavedPrefsChanges = true;
108123
prefs = [...prefs];
109124
}}>
110125
<span class="icon-x" aria-hidden="true"></span>
@@ -119,6 +134,7 @@
119134
disabled={isAddDisabled(prefs)}
120135
on:click={() => {
121136
if (!prefs) return;
137+
hasUnsavedPrefsChanges = true;
122138
prefs = [...prefs, createPrefRow()];
123139
}}>
124140
<Icon icon={IconPlus} slot="start" size="s" />

0 commit comments

Comments
 (0)