mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Add user labels to user list and detail pages
This commit is contained in:
@@ -118,6 +118,7 @@ export enum Submit {
|
||||
UserCreate = 'submit_user_create',
|
||||
UserDelete = 'submit_user_delete',
|
||||
UserUpdateEmail = 'submit_user_update_email',
|
||||
UserUpdateLabels = 'submit_user_update_labels',
|
||||
UserUpdateName = 'submit_user_update_name',
|
||||
UserUpdatePassword = 'submit_user_update_password',
|
||||
UserUpdatePhone = 'submit_user_update_phone',
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
// TODO: Remove this when the console SDK is updated
|
||||
const users = data.users.users.map((user) => {
|
||||
const labels: string[] = [];
|
||||
return { labels, ...user };
|
||||
});
|
||||
|
||||
let showCreate = false;
|
||||
const projectId = $page.params.project;
|
||||
async function userCreated(event: CustomEvent<Models.User<Record<string, unknown>>>) {
|
||||
@@ -49,10 +55,11 @@
|
||||
<TableCellHead onlyDesktop>Identifiers</TableCellHead>
|
||||
<TableCellHead onlyDesktop width={130}>Status</TableCellHead>
|
||||
<TableCellHead onlyDesktop width={100}>ID</TableCellHead>
|
||||
<TableCellHead onlyDesktop width={100}>Labels</TableCellHead>
|
||||
<TableCellHead onlyDesktop>Joined</TableCellHead>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each data.users.users as user}
|
||||
{#each users as user}
|
||||
<TableRowLink
|
||||
href={`${base}/console/project-${projectId}/auth/user-${user.$id}`}>
|
||||
<TableCell title="Name">
|
||||
@@ -102,6 +109,9 @@
|
||||
</Pill>
|
||||
</Copy>
|
||||
</TableCell>
|
||||
<TableCellText onlyDesktop title="Labels">
|
||||
{user.labels.join(', ')}
|
||||
</TableCellText>
|
||||
<TableCellText onlyDesktop title="Joined">
|
||||
{toLocaleDateTime(user.registration)}
|
||||
</TableCellText>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import DangerZone from './dangerZone.svelte';
|
||||
import UpdateEmail from './updateEmail.svelte';
|
||||
import UpdateLabels from './updateLabels.svelte';
|
||||
import UpdateName from './updateName.svelte';
|
||||
import UpdatePassword from './updatePassword.svelte';
|
||||
import UpdatePhone from './updatePhone.svelte';
|
||||
@@ -15,6 +16,7 @@
|
||||
<UpdateEmail />
|
||||
<UpdatePhone />
|
||||
<UpdatePassword />
|
||||
<UpdateLabels />
|
||||
<UpdatePrefs />
|
||||
<DangerZone />
|
||||
</Container>
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { CardGrid, Heading } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button, Form, Helper, InputTags } from '$lib/elements/forms';
|
||||
import { symmetricDifference } from '$lib/helpers/array';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { user } from './store';
|
||||
import { Pill } from '$lib/elements';
|
||||
|
||||
const alphaNumericRegExp = /^[a-zA-Z0-9]+$/;
|
||||
let suggestedLabels = ['admin', 'premium', 'mvp'];
|
||||
let labels: string[] = [];
|
||||
let error = '';
|
||||
|
||||
onMount(async () => {
|
||||
// TODO: Remove type cast when console SDK is updated
|
||||
labels = [...($user as unknown as { labels: string[] }).labels];
|
||||
});
|
||||
|
||||
async function updateLabels() {
|
||||
try {
|
||||
// TODO: Use SDK method when console SDK is updated
|
||||
// await sdk.forProject.users.updateLabels($user.$id, labels);
|
||||
const path = `/users/${$user.$id}/labels`;
|
||||
await sdk.forProject.client.call(
|
||||
'PUT',
|
||||
new URL(sdk.forConsole.client.config.endpoint + path),
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
{
|
||||
labels: labels
|
||||
}
|
||||
);
|
||||
await invalidate(Dependencies.USER);
|
||||
isDisabled = true;
|
||||
|
||||
addNotification({
|
||||
message: 'User labels have been updated',
|
||||
type: 'success'
|
||||
});
|
||||
trackEvent(Submit.UserUpdateLabels);
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
message: error.message,
|
||||
type: 'error'
|
||||
});
|
||||
trackError(error, Submit.UserUpdateLabels);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove type cast when console SDK is updated
|
||||
$: isDisabled =
|
||||
!!error ||
|
||||
!symmetricDifference(labels, ($user as unknown as { labels: string[] }).labels).length;
|
||||
$: if (labels) {
|
||||
const invalidLabels = [];
|
||||
|
||||
labels.forEach((label) => {
|
||||
if (!alphaNumericRegExp.test(label)) {
|
||||
invalidLabels.push(label);
|
||||
}
|
||||
});
|
||||
|
||||
if (invalidLabels.length) {
|
||||
error = `Invalid labels: ${invalidLabels.join(', ')}`;
|
||||
} else {
|
||||
error = '';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Form onSubmit={updateLabels}>
|
||||
<CardGrid>
|
||||
<Heading tag="h6" size="7">Labels</Heading>
|
||||
<p class="text">
|
||||
Categorize and manage your users based on specific criteria by assigning them
|
||||
customizable labels. New label-based roles will be assigned.
|
||||
</p>
|
||||
<svelte:fragment slot="aside">
|
||||
<ul class="common-section">
|
||||
<InputTags
|
||||
id="user-labels"
|
||||
label="Labels"
|
||||
placeholder="Select or tyype user labels"
|
||||
bind:tags={labels} />
|
||||
<li>
|
||||
<Helper type={error ? 'warning' : 'neutral'}
|
||||
>{error ? error : 'Only alphanumeric characters are allowed'}</Helper>
|
||||
</li>
|
||||
<li class="u-flex u-gap-12 u-margin-block-start-8">
|
||||
{#each suggestedLabels as suggestedLabel}
|
||||
<Pill
|
||||
selected={labels.includes(suggestedLabel)}
|
||||
button
|
||||
on:click={() => {
|
||||
if (!labels.includes(suggestedLabel)) {
|
||||
labels = [...labels, suggestedLabel];
|
||||
} else {
|
||||
labels = labels.filter((e) => e !== suggestedLabel);
|
||||
}
|
||||
}}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
{suggestedLabel}
|
||||
</Pill>
|
||||
{/each}
|
||||
</li>
|
||||
</ul>
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button disabled={isDisabled} submit>Update</Button>
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
</Form>
|
||||
Reference in New Issue
Block a user