fix table for users

This commit is contained in:
Torsten Dittmann
2022-05-20 16:01:06 +02:00
parent 91ba8df026
commit 3f144db22e
7 changed files with 142 additions and 66 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
<article class="card">
<article class="card common-section">
<slot />
</article>
+1 -1
View File
@@ -48,7 +48,7 @@
aria-label="Close Modal"
title="Close Modal"
on:click={closeModal}>
<span class="icon-cancel" aria-hidden="true" />
<span class="icon-x" aria-hidden="true" />
</button>
</header>
<div class="modal-content">
+6
View File
@@ -7,3 +7,9 @@
<slot />
</span>
</th>
<style>
th {
text-transform: uppercase;
}
</style>
+13
View File
@@ -4,3 +4,16 @@ export const toLocaleDate = (timestamp: number) => {
return date.toLocaleDateString('en', options);
};
export const toLocaleDateTime = (timestamp: number) => {
const date = new Date(timestamp * 1000);
const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric'
};
return date.toLocaleDateString('en', options);
};
@@ -17,7 +17,7 @@
import type { Models } from 'src/sdk';
import { goto } from '$app/navigation';
import { Pill } from '$lib/elements';
import { toLocaleDate } from '$lib/helpers/date';
import { toLocaleDateTime } from '$lib/helpers/date';
import { Container } from '$lib/layout';
import { base } from '$app/paths';
import { usersList } from './store';
@@ -26,13 +26,14 @@
let showCreate = false;
let search = '';
let offset: number = null;
const limit = 5;
const limit = 5;
const project = $page.params.project;
const getAvatar = (name: string) => sdkForProject.avatars.getInitials(name, 30, 30).toString();
const userCreated = async (event: CustomEvent<Models.User<Record<string, unknown>>>) => {
await goto(`${base}/console/${project}/users/user/${event.detail.$id}`);
};
$: usersList.load(search, limit, offset);
$: if (search) offset = 0;
$: {
@@ -65,7 +66,8 @@
<TableCellHead width={30} />
<TableCellHead>Name</TableCellHead>
<TableCellHead>E-Mail</TableCellHead>
<TableCellHead>Status</TableCellHead>
<TableCellHead width={100}>Status</TableCellHead>
<TableCellHead width={100}>ID</TableCellHead>
<TableCellHead>Joined</TableCellHead>
</TableHeader>
<TableBody>
@@ -88,12 +90,19 @@
</TableCellLink>
<TableCellText title="E-Mail">{user.email}</TableCellText>
<TableCellText title="Status">
<Pill success={user.emailVerification}>
{user.emailVerification ? 'Verified' : 'Unverified'}
</Pill>
{#if user.status}
<Pill success={user.emailVerification}>
{user.emailVerification ? 'Verified' : 'Unverified'}
</Pill>
{:else}
<Pill danger>Blocked</Pill>
{/if}
</TableCellText>
<TableCellText title="ID">
<Pill>User ID <i class="icon-duplicate" /></Pill>
</TableCellText>
<TableCellText title="Joined">
{toLocaleDate(user.registration)}
{toLocaleDateTime(user.registration)}
</TableCellText>
</TableRow>
{/each}
+39 -2
View File
@@ -8,7 +8,12 @@ export type UsersList = {
response?: Models.UserList<Record<string, unknown>>;
};
function createUserStore() {
export type TeamsList = {
loading: boolean;
response?: Models.TeamList;
};
function createUsersListStore() {
const { subscribe, set } = writable<UsersList>({
loading: true,
response: browser ? JSON.parse(sessionStorage.getItem('users')) : null
@@ -38,8 +43,40 @@ function createUserStore() {
};
}
export const usersList = createUserStore();
function createTeamsListStore() {
const { subscribe, set } = writable<TeamsList>({
loading: true,
response: browser ? JSON.parse(sessionStorage.getItem('teams')) : null
});
return {
subscribe,
set,
load: async (search: string, limit: number, offset: number) => {
try {
const response = await sdkForProject.teams.list(
search,
limit,
offset,
undefined,
undefined,
'DESC'
);
set({
loading: false,
response
});
} catch (error) {
//TODO: take care what happens here
}
}
};
}
export const usersList = createUsersListStore();
export const teamsList = createTeamsListStore();
if (browser) {
usersList.subscribe((n) => sessionStorage?.setItem('users', JSON.stringify(n.response ?? '')));
teamsList.subscribe((n) => sessionStorage?.setItem('teams', JSON.stringify(n.response ?? '')));
}
+66 -55
View File
@@ -11,14 +11,16 @@
TableCellText,
TableCell
} from '$lib/elements/table';
import { Button, InputSearch } from '$lib/elements/forms';
import { Button } from '$lib/elements/forms';
import { Empty, Pagination } from '$lib/components';
import Create from './_createTeam.svelte';
import { goto } from '$app/navigation';
import type { Models } from 'src/sdk';
import { toLocaleDate } from '$lib/helpers/date';
import { Container } from '$lib/layout';
import { base } from '$app/paths';
import { teamsList } from './store';
import { onMount } from 'svelte';
import type { Models } from 'src/sdk';
let search = '';
let showCreate = false;
@@ -30,68 +32,77 @@
const teamCreated = async (event: CustomEvent<Models.Team>) => {
await goto(`${base}/console/${project}/users/team/${event.detail.$id}`);
};
$: request = sdkForProject.teams.list(search, limit, offset);
$: teamsList.load(search, limit, offset);
$: if (search) offset = 0;
$: {
//TODO: refactor this into something maintainable without the use of goto
if (offset !== null) {
$page.url.searchParams.set('offset', offset.toString());
goto(`?${$page.url.searchParams.toString()}`);
}
}
onMount(() => {
offset = +$page.url.searchParams.get('offset') ?? 0;
});
</script>
<Container>
<div class="u-flex u-space-between common-section">
<InputSearch bind:value={search} />
<div class="u-flex u-gap-12 common-section u-main-space-between">
<div class="input-text-wrapper u-stretch" style="max-width: 500px">
<input type="search" class="input-text" bind:value={search} />
<span class="icon-search" aria-hidden="true" />
</div>
<Button on:click={() => (showCreate = true)}>
<span class="icon-plus" aria-hidden="true" /> <span class="text">Create Team</span>
</Button>
</div>
{#if $teamsList?.response?.total}
<Table>
<TableHeader>
<TableCellHead width={30} />
<TableCellHead>Name</TableCellHead>
<TableCellHead>Members</TableCellHead>
<TableCellHead>Created</TableCellHead>
</TableHeader>
<TableBody>
{#each $teamsList.response.teams as team}
<TableRow>
<TableCell onlyDesktop>
<div class="image">
<img
class="avatar"
width="30"
height="30"
src={getAvatar(team.name)}
alt={team.name} />
</div>
</TableCell>
<TableCellLink
title="ID"
href={`${base}/console/${project}/users/teams/${team.$id}`}>
{team.name}
</TableCellLink>
<TableCellText title="Members">{team.total}</TableCellText>
<TableCellText title="Members"
>{toLocaleDate(team.dateCreated)}</TableCellText>
</TableRow>
{/each}
</TableBody>
</Table>
{#await request}
<div aria-busy="true" />
{:then response}
{#if response.total}
<Table>
<TableHeader>
<TableCellHead width={30} />
<TableCellHead>Name</TableCellHead>
<TableCellHead>Members</TableCellHead>
<TableCellHead>Created</TableCellHead>
</TableHeader>
<TableBody>
{#each response.teams as team}
<TableRow>
<TableCell onlyDesktop>
<div class="image">
<img
class="avatar"
width="30"
height="30"
src={getAvatar(team.name)}
alt={team.name} />
</div>
</TableCell>
<TableCellLink
title="ID"
href={`${base}/console/${project}/users/teams/${team.$id}`}>
{team.name}
</TableCellLink>
<TableCellText title="Members">{team.total}</TableCellText>
<TableCellText title="Members"
>{toLocaleDate(team.dateCreated)}</TableCellText>
</TableRow>
{/each}
</TableBody>
</Table>
<Pagination {limit} bind:offset sum={response.total} />
{:else if search}
<Empty>
<svelte:fragment slot="header"
>No results found for <b>{search}</b></svelte:fragment>
</Empty>
{:else}
<Empty>
<svelte:fragment slot="header">No Teams Found</svelte:fragment>
Create your first team to get started.
</Empty>
{/if}
{/await}
<Pagination {limit} bind:offset sum={$teamsList.response.total} />
{:else if search}
<Empty>
<svelte:fragment slot="header">No results found for <b>{search}</b></svelte:fragment>
</Empty>
{:else}
<Empty>
<svelte:fragment slot="header">No Teams Found</svelte:fragment>
Create your first team to get started.
</Empty>
{/if}
</Container>
<Create bind:showCreate on:created={teamCreated} />