mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
add basic notifications
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import type { Notification } from '../notifications';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let type: Notification['type'] = 'info';
|
||||
export let dismissible = true;
|
||||
</script>
|
||||
|
||||
<article class={type} role="alert" transition:fade>
|
||||
<div class="text">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
{#if dismissible}
|
||||
<button class="close" on:click={() => dispatch('dismiss')}> x </button>
|
||||
{/if}
|
||||
</article>
|
||||
|
||||
<style lang="scss">
|
||||
article {
|
||||
color: white;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 0.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 auto 0.5rem auto;
|
||||
width: 20rem;
|
||||
}
|
||||
.error {
|
||||
background: IndianRed;
|
||||
}
|
||||
.success {
|
||||
background: MediumSeaGreen;
|
||||
}
|
||||
.info {
|
||||
background: SkyBlue;
|
||||
}
|
||||
.text {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
button {
|
||||
color: white;
|
||||
background: transparent;
|
||||
border: 0 none;
|
||||
padding: 0;
|
||||
margin: 0 0 0 auto;
|
||||
line-height: 1;
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,34 @@
|
||||
<script lang="ts">
|
||||
import Notification from './notification.svelte';
|
||||
|
||||
import { dismissToast, toasts } from '../notifications';
|
||||
</script>
|
||||
|
||||
{#if $toasts}
|
||||
<section>
|
||||
{#each $toasts as toast (toast.id)}
|
||||
<Notification
|
||||
type={toast.type}
|
||||
dismissible={toast.dismissible}
|
||||
on:dismiss={() => dismissToast(toast.id)}
|
||||
>
|
||||
{toast.message}
|
||||
</Notification>
|
||||
{/each}
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
section {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
z-index: 1000;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,31 @@
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export type Notification = {
|
||||
id: number;
|
||||
type: 'success' | 'error' | 'info';
|
||||
dismissible: boolean;
|
||||
timeout: number;
|
||||
message: string;
|
||||
};
|
||||
|
||||
let counter = 0;
|
||||
|
||||
export const toasts = writable<Notification[]>([]);
|
||||
|
||||
export const dismissToast = (id: number) => {
|
||||
toasts.update((all) => all.filter((t) => t.id !== id));
|
||||
};
|
||||
|
||||
export const addToast = (notification: Omit<Notification, 'id'>) => {
|
||||
const defaults = {
|
||||
id: counter++,
|
||||
type: 'info',
|
||||
dismissible: true,
|
||||
timeout: 3000
|
||||
};
|
||||
|
||||
const n = { ...defaults, ...notification };
|
||||
toasts.update((all) => [n, ...all]);
|
||||
|
||||
if (n.timeout) setTimeout(() => dismissToast(n.id), n.timeout);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import Notifications from '$lib/layout/notifications.svelte';
|
||||
import { sdkForConsole } from '$lib/stores/sdk';
|
||||
import { user } from '$lib/stores/user';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -20,6 +21,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<Notifications />
|
||||
<main class="container">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<h1>Overview</h1>
|
||||
<article class="overview">
|
||||
<p><img src={getAvatar(user.name)} alt={user.name} class="avatar" /></p>
|
||||
<p class="id" data-tooltip="Click to copy.">{user.$id}</p>
|
||||
<p>{user.$id}</p>
|
||||
<p>Member since {user.registration}</p>
|
||||
<p>{user.emailVerification ? 'Verified' : 'Unverified'}</p>
|
||||
<p>{user.email}</p>
|
||||
@@ -54,10 +54,6 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.id {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Pagination, Table, TableCell, TableHeader, TableBody, TableRow } from '$lib/components';
|
||||
import {
|
||||
Pagination,
|
||||
Table,
|
||||
TableCell,
|
||||
TableHeader,
|
||||
TableBody,
|
||||
TableRow,
|
||||
Button
|
||||
} from '$lib/components';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
|
||||
const getSessions = () => sdkForProject.users.getSessions($page.params.user);
|
||||
|
||||
const deleteSession = async (id: string) => {
|
||||
try {
|
||||
await sdkForProject.users.deleteSession($page.params.user, id);
|
||||
request = getSessions();
|
||||
} catch (error) {
|
||||
alert(error.message);
|
||||
}
|
||||
};
|
||||
const deleteAllSessions = async () => {
|
||||
try {
|
||||
if (confirm('You really want to delete all sessions?')) {
|
||||
await sdkForProject.users.deleteSessions($page.params.user);
|
||||
}
|
||||
} catch (error) {
|
||||
alert(error.message);
|
||||
}
|
||||
};
|
||||
let offset = 0;
|
||||
const limit = 25;
|
||||
|
||||
@@ -19,6 +43,7 @@
|
||||
<TableCell>Country</TableCell>
|
||||
<TableCell>OS</TableCell>
|
||||
<TableCell>IP</TableCell>
|
||||
<TableCell />
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each response.sessions as session}
|
||||
@@ -26,10 +51,12 @@
|
||||
<TableCell>{session.countryName}</TableCell>
|
||||
<TableCell>{session.osName}</TableCell>
|
||||
<TableCell>{session.ip}</TableCell>
|
||||
<TableCell><Button on:click={() => deleteSession(session.$id)}>Logout</Button></TableCell>
|
||||
</TableRow>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
<Pagination {limit} bind:offset sum={response.sum} on:change={() => (request = getSessions())} />
|
||||
<Button on:click={deleteAllSessions}>Logout from all sessions</Button>
|
||||
{/await}
|
||||
|
||||
Reference in New Issue
Block a user