Skip to content

Commit 05640ca

Browse files
authored
Merge pull request #2327 from appwrite/fix-SER-320-Bug-select-more-users
2 parents a13a400 + e31f1a6 commit 05640ca

2 files changed

Lines changed: 62 additions & 53 deletions

File tree

src/lib/components/paginationInline.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
{:else}
6767
<Layout.Stack direction="row" inline>
6868
<Button.Button
69+
type="button"
6970
size="s"
7071
variant="compact"
7172
on:click={prev}
@@ -75,6 +76,7 @@
7576
</Button.Button>
7677

7778
<Button.Button
79+
type="button"
7880
size="s"
7981
variant="compact"
8082
on:click={next}

src/routes/(console)/project-[region]-[project]/messaging/userTargetsModal.svelte

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
let totalResults = 0;
2222
let userResultsById: Record<string, Models.User<Record<string, unknown>>> = {}; // use a hash map so we can quickly look up a user by id
2323
let selected: Record<string, Models.Target> = {};
24-
let selectedSize = 0;
25-
let selectedUsers = 0;
26-
let hasSelection = false;
2724
2825
function reset() {
2926
offset = 0;
@@ -38,6 +35,7 @@
3835
3936
async function request() {
4037
if (!show) return;
38+
4139
const queries = [Query.limit(5), Query.offset(offset)];
4240
4341
if (providerType === MessagingProviderType.Email) {
@@ -52,44 +50,43 @@
5250
});
5351
5452
totalResults = response.total;
55-
userResultsById = {};
56-
response.users.forEach((user) => {
57-
if (providerType !== null) {
58-
user.targets = user.targets.filter(
59-
(target) => target.providerType === providerType
60-
);
61-
}
62-
userResultsById = {
63-
...userResultsById,
64-
[user.$id]: user
65-
};
66-
});
53+
54+
userResultsById = Object.fromEntries(
55+
response.users.map((user) => {
56+
const filteredUser =
57+
providerType !== null
58+
? {
59+
...user,
60+
targets: user.targets.filter(
61+
(target) => target.providerType === providerType
62+
)
63+
}
64+
: user;
65+
return [user.$id, filteredUser];
66+
})
67+
);
6768
}
6869
69-
function onUserSelection(event: CustomEvent<boolean>, userId: string) {
70+
function onUserSelection(event: CustomEvent<boolean | 'indeterminate'>, userId: string) {
7071
const user = userResultsById[userId];
72+
const shouldSelect = event.detail === 'indeterminate' || event.detail === true;
7173
72-
if (event.detail) {
73-
user.targets.forEach((target) => {
74-
selected = {
75-
...selected,
76-
[target.$id]: target
77-
};
78-
});
79-
} else {
80-
user.targets.forEach((target) => {
81-
const { [target.$id]: _, ...rest } = selected;
82-
selected = rest;
83-
});
84-
}
74+
const updatedSelected = { ...selected };
75+
76+
user.targets.forEach((target) => {
77+
if (shouldSelect) {
78+
updatedSelected[target.$id] = target;
79+
} else {
80+
delete updatedSelected[target.$id];
81+
}
82+
});
83+
84+
selected = updatedSelected;
8585
}
8686
8787
function onTargetSelection(event: CustomEvent<boolean>, target: Models.Target) {
8888
if (event.detail) {
89-
selected = {
90-
...selected,
91-
[target.$id]: target
92-
};
89+
selected = { ...selected, [target.$id]: target };
9390
} else {
9491
const { [target.$id]: _, ...rest } = selected;
9592
selected = rest;
@@ -107,19 +104,35 @@
107104
request();
108105
}
109106
110-
$: {
111-
selectedSize = 0;
112-
const users = new Set();
113-
for (const s in selected) {
114-
const target = selected[s];
115-
users.add(target.userId);
116-
selectedSize++;
117-
}
118-
selectedUsers = users.size;
119-
}
120-
107+
$: selectedTargets = Object.values(selected);
108+
$: selectedSize = selectedTargets.length;
109+
$: selectedUsers = new Set(selectedTargets.map((target) => target.userId)).size;
121110
$: hasSelection = selectedSize > 0;
122111
112+
$: parentStates = Object.fromEntries(
113+
Object.entries(userResultsById).map(([userId, user]) => {
114+
const selectedCount = user.targets.filter((target) => selected[target.$id]).length;
115+
const totalCount = user.targets.length;
116+
117+
let state: boolean | 'indeterminate';
118+
if (selectedCount === 0) {
119+
state = false;
120+
} else if (selectedCount === totalCount) {
121+
state = true;
122+
} else {
123+
state = 'indeterminate';
124+
}
125+
126+
return [userId, state];
127+
})
128+
);
129+
130+
$: targetSelectionStates = Object.fromEntries(
131+
Object.values(userResultsById)
132+
.flatMap((user) => user.targets)
133+
.map((target) => [target.$id, !!selected[target.$id]])
134+
);
135+
123136
$: if (show) {
124137
selected = targetsById;
125138
}
@@ -140,25 +153,19 @@
140153
).length}
141154
<Accordion
142155
selectable
143-
title={user.name
144-
? user.name
145-
: user.email
146-
? user.email
147-
: user.phone
148-
? user.phone
149-
: userId}
156+
title={user.name || user.email || user.phone || userId}
150157
badge={user.targets.length === 0
151158
? '0 targets'
152159
: `${selectedCount}/${user.targets.length} targets`}
153160
disabled={!user.targets.length}
154-
checked={selectedCount > 0 && selectedCount === user.targets.length}
161+
checked={parentStates[userId]}
155162
on:change={(event) => onUserSelection(event, userId)}>
156163
{#each user.targets as target}
157164
<Layout.Stack direction="row">
158165
<Selector.Checkbox
159166
id={target.$id}
160167
size="s"
161-
checked={!!selected[target.$id]}
168+
checked={targetSelectionStates[target.$id] || false}
162169
on:change={(event) => onTargetSelection(event, target)}>
163170
</Selector.Checkbox>
164171
<div class="u-inline-flex u-gap-8">

0 commit comments

Comments
 (0)