mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'main' of github.com:appwrite/console into feat-databases-v2
This commit is contained in:
Generated
+4
-5
@@ -6,10 +6,9 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@appwrite/console",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@analytics/google-analytics": "^1.0.5",
|
||||
"@appwrite.io/pink": "^0.0.6-rc.3",
|
||||
"@appwrite.io/pink": "^0.0.6-rc.4",
|
||||
"@appwrite.io/pink-icons": "^0.0.6-rc.3",
|
||||
"@aw-labs/appwrite-console": "^13.1.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
@@ -149,9 +148,9 @@
|
||||
"integrity": "sha512-1Yw7u/COtxx06BfwlI+kVhsa/upKYzmCNrT4c8QDeCY2KMYlnijkUjtHiPU08HxyTIVB5j6d75O0YWVIHwQS8g=="
|
||||
},
|
||||
"node_modules/@appwrite.io/pink": {
|
||||
"version": "0.0.6-rc.3",
|
||||
"resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.0.6-rc.3.tgz",
|
||||
"integrity": "sha512-oeRwchmRdHjspYJFipc6k/oWOOdaD7TKFwJ1weZMJMF2/GmQ44zCYo2qJhN2tPRb73Wje2dTvnkV6MH/Rxg7vw==",
|
||||
"version": "0.0.6-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.0.6-rc.4.tgz",
|
||||
"integrity": "sha512-vSBq0wB4lQMM8vRPCh0B2M8aWIdrFQSf14X58y8DVjj0djg/gwQ51pwxLojXAol7rwFNhh73NSqTuRC4y+BpxA==",
|
||||
"dependencies": {
|
||||
"@appwrite.io/pink-icons": "*",
|
||||
"normalize.css": "^8.0.1",
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"name": "@appwrite/console",
|
||||
"version": "0.0.1",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
@@ -20,8 +19,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@analytics/google-analytics": "^1.0.5",
|
||||
"@appwrite.io/pink": "^0.0.6-rc.3",
|
||||
"@appwrite.io/pink-icons": "^0.0.6-rc.3",
|
||||
"@appwrite.io/pink": "^0.0.6-rc.4",
|
||||
"@aw-labs/appwrite-console": "^13.1.0",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@sentry/svelte": "^7.44.2",
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
class:common-section={!isTile}
|
||||
class:is-border-dashed={isDashed}
|
||||
class:is-danger={danger}
|
||||
class:is-allowed-focus={href}
|
||||
on:click
|
||||
on:keyup={clickOnEnter}
|
||||
{href}>
|
||||
|
||||
@@ -49,3 +49,4 @@ export { default as Output } from './output.svelte';
|
||||
export { default as ViewSelector } from './viewSelector.svelte';
|
||||
export { default as LabelCard } from './labelCard.svelte';
|
||||
export { default as CustomPagination } from './customPagination.svelte';
|
||||
export { default as Limit } from './limit.svelte';
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { page as pageStore } from '$app/stores';
|
||||
import { InputSelect } from '$lib/elements/forms';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
|
||||
export let sum: number;
|
||||
export let limit: number;
|
||||
export let name: string;
|
||||
|
||||
const options = [
|
||||
{ label: '6', value: 6 },
|
||||
{ label: '12', value: 12 },
|
||||
{ label: '24', value: 24 },
|
||||
{ label: '48', value: 48 },
|
||||
{ label: '96', value: 96 }
|
||||
];
|
||||
|
||||
async function limitChange() {
|
||||
const url = new URL($pageStore.url);
|
||||
const previousLimit = Number(url.searchParams.get('limit'));
|
||||
url.searchParams.set('limit', limit.toString());
|
||||
preferences.setLimit(limit);
|
||||
|
||||
if (url.searchParams.has('page')) {
|
||||
const page = Number(url.searchParams.get('page'));
|
||||
const newPage = Math.floor(((page - 1) * previousLimit) / limit);
|
||||
url.searchParams.set('page', newPage.toString());
|
||||
}
|
||||
|
||||
await goto(url.toString());
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="u-flex u-gap-12 u-cross-center">
|
||||
<InputSelect
|
||||
id="rows"
|
||||
label="Rows per page"
|
||||
showLabel={false}
|
||||
{options}
|
||||
bind:value={limit}
|
||||
on:change={limitChange} />
|
||||
<p class="text">{name} per page. Total results: {sum}</p>
|
||||
</div>
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page as pageStore } from '$app/stores';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
|
||||
export let sum: number;
|
||||
export let limit: number;
|
||||
export let offset: number;
|
||||
export let path: string;
|
||||
export let hidePages = false;
|
||||
|
||||
$: totalPages = Math.ceil(sum / limit);
|
||||
@@ -27,68 +27,87 @@
|
||||
...(end < total - 1 ? ['...', total] : end < total ? [total] : [])
|
||||
];
|
||||
}
|
||||
|
||||
function getLink(page: number): string {
|
||||
const url = new URL($pageStore.url);
|
||||
if (page === 1) {
|
||||
url.searchParams.delete('page');
|
||||
} else {
|
||||
url.searchParams.set('page', page.toString());
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if totalPages > 1}
|
||||
{@const search = $page.url.search}
|
||||
<nav class="pagination">
|
||||
<a
|
||||
class:is-disabled={currentPage <= 1}
|
||||
class="button is-text"
|
||||
aria-label="prev page"
|
||||
href={`${path}/${currentPage - 1}${search}`}>
|
||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||
<span class="text">Prev</span>
|
||||
</a>
|
||||
{#if !hidePages}
|
||||
<ol class="pagination-list is-only-desktop">
|
||||
{#each pages as page}
|
||||
{#if typeof page === 'number'}
|
||||
<li class="pagination-item">
|
||||
<a
|
||||
href={`${path}/${page}${search}`}
|
||||
class="button"
|
||||
class:is-disabled={currentPage === page}
|
||||
class:is-text={currentPage !== page}
|
||||
aria-label="page">
|
||||
<span class="text">{page}</span>
|
||||
</a>
|
||||
</li>
|
||||
{:else}
|
||||
<li class="li is-text">
|
||||
<span class="icon">...</span>
|
||||
</li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ol>
|
||||
{/if}
|
||||
<a
|
||||
class:is-disabled={currentPage === totalPages}
|
||||
class="button is-text"
|
||||
href={`${path}/${currentPage + 1}${search}`}
|
||||
aria-label="next page">
|
||||
<span class="text">Next</span>
|
||||
<span class="icon-cheveron-right" aria-hidden="true" />
|
||||
</a>
|
||||
</nav>
|
||||
{#key $pageStore.url}
|
||||
<nav class="pagination">
|
||||
{#if currentPage <= 1}
|
||||
<Button disabled text ariaLabel="prev page">
|
||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||
<span class="text">Prev</span>
|
||||
</Button>
|
||||
{:else}
|
||||
<Button text ariaLabel="prev page" href={getLink(currentPage - 1)}>
|
||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||
<span class="text">Prev</span>
|
||||
</Button>
|
||||
{/if}
|
||||
{#if !hidePages}
|
||||
<ol class="pagination-list is-only-desktop">
|
||||
{#each pages as page}
|
||||
{#if typeof page === 'number'}
|
||||
<li class="pagination-item">
|
||||
{#if currentPage === page}
|
||||
<Button ariaLabel="page" disabled>
|
||||
<span class="text">{page}</span>
|
||||
</Button>
|
||||
{:else}
|
||||
<Button text ariaLabel="page" href={getLink(page)}>
|
||||
<span class="text">{page}</span>
|
||||
</Button>
|
||||
{/if}
|
||||
</li>
|
||||
{:else}
|
||||
<li class="li is-text">
|
||||
<span class="icon">...</span>
|
||||
</li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ol>
|
||||
{/if}
|
||||
{#if currentPage >= totalPages}
|
||||
<Button disabled text ariaLabel="next page">
|
||||
<span class="text">Next</span>
|
||||
<span class="icon-cheveron-right" aria-hidden="true" />
|
||||
</Button>
|
||||
{:else}
|
||||
<Button text ariaLabel="next page" href={getLink(currentPage + 1)}>
|
||||
<span class="text">Next</span>
|
||||
<span class="icon-cheveron-right" aria-hidden="true" />
|
||||
</Button>
|
||||
{/if}
|
||||
</nav>
|
||||
{/key}
|
||||
{:else}
|
||||
<nav class="pagination">
|
||||
<button type="button" class="button is-text is-disabled" aria-label="prev page">
|
||||
<Button text disabled ariaLabel="prev page">
|
||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||
<span class="text">Prev</span>
|
||||
</button>
|
||||
</Button>
|
||||
{#if !hidePages}
|
||||
<ol class="pagination-list is-only-desktop">
|
||||
<li class="pagination-item">
|
||||
<button type="button" class="button is-disabled" aria-label="page">
|
||||
<Button disabled ariaLabel="page">
|
||||
<span class="text">1</span>
|
||||
</button>
|
||||
</Button>
|
||||
</li>
|
||||
</ol>
|
||||
{/if}
|
||||
<button type="button" class="button is-text is-disabled" aria-label="next page">
|
||||
<Button text disabled ariaLabel="next page">
|
||||
<span class="text">Next</span>
|
||||
<span class="icon-cheveron-right" aria-hidden="true" />
|
||||
</button>
|
||||
</Button>
|
||||
</nav>
|
||||
{/if}
|
||||
|
||||
@@ -29,23 +29,28 @@
|
||||
}
|
||||
});
|
||||
|
||||
$: valueChange(search);
|
||||
$: valueChange(search ?? '');
|
||||
|
||||
function valueChange(value: string) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(async () => {
|
||||
timer = setTimeout(() => {
|
||||
const url = new URL($page.url);
|
||||
if (url.search === value) {
|
||||
const previous = url.searchParams.get('search') ?? '';
|
||||
|
||||
if (previous === value) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Reset to first page if search changes.
|
||||
*/
|
||||
|
||||
if ($page.data.page > 1) {
|
||||
url.pathname = url.pathname.replace(new RegExp(`/${$page.data.page}*$`), '/');
|
||||
url.searchParams.delete('page');
|
||||
}
|
||||
|
||||
if (value === '') {
|
||||
url.searchParams.delete('search');
|
||||
} else {
|
||||
url.searchParams.set('search', value);
|
||||
}
|
||||
|
||||
url.search = value;
|
||||
trackEvent('search');
|
||||
goto(url, { keepFocus: true });
|
||||
}, debounce);
|
||||
|
||||
@@ -1,34 +1,68 @@
|
||||
<script lang="ts">
|
||||
import { Button, InputChoice } from '$lib/elements/forms';
|
||||
import { DropList } from '.';
|
||||
import { prefs } from '$lib/stores/user';
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import type { Writable } from 'svelte/store';
|
||||
|
||||
type Column = {
|
||||
<script context="module" lang="ts">
|
||||
export type Column = {
|
||||
id: string;
|
||||
title: string;
|
||||
show: boolean;
|
||||
width?: number;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { Button, InputChoice } from '$lib/elements/forms';
|
||||
import { DropList } from '.';
|
||||
import { page } from '$app/stores';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import { onMount } from 'svelte';
|
||||
import { View } from '$lib/helpers/load';
|
||||
|
||||
export let columns: Writable<Column[]>;
|
||||
export let showToggle = true;
|
||||
const pathname = $page.url.pathname;
|
||||
export let view: View;
|
||||
export let isCustomCollection = false;
|
||||
export let hideView = false;
|
||||
export let hideColumns = false;
|
||||
|
||||
let showSelectColumns = false;
|
||||
|
||||
onMount(() => {
|
||||
updateColumns();
|
||||
onMount(async () => {
|
||||
if (isCustomCollection) {
|
||||
const prefs = preferences.getCustomCollectionColumns($page.params.collection);
|
||||
columns.set(
|
||||
$columns.map((column) => {
|
||||
column.show = prefs?.includes(column.id) ?? true;
|
||||
return column;
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const prefs = preferences.get($page.route);
|
||||
|
||||
columns.set(
|
||||
$columns.map((column) => {
|
||||
column.show = prefs.columns?.includes(column.id) ?? true;
|
||||
return column;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return columns.subscribe((ctx) => {
|
||||
const columns = ctx.filter((n) => n.show).map((n) => n.id);
|
||||
|
||||
if (isCustomCollection) {
|
||||
preferences.setCustomCollectionColumns(columns);
|
||||
} else {
|
||||
preferences.setColumns(columns);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function updateColumns() {
|
||||
if ($prefs?.[pathname]) {
|
||||
$columns.forEach((column, i) => {
|
||||
column.show = $prefs[pathname][i];
|
||||
});
|
||||
$columns = $columns;
|
||||
}
|
||||
function getViewLink(view: View): string {
|
||||
const url = new URL($page.url);
|
||||
url.searchParams.set('view', view);
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
function updateViewPreferences(view: View) {
|
||||
preferences.setView(view);
|
||||
}
|
||||
|
||||
$: selectedColumnsNumber = $columns.reduce((acc, column) => {
|
||||
@@ -37,19 +71,14 @@
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
columns.subscribe((columns) => {
|
||||
const columnsArray = columns.map((column) => column.show);
|
||||
prefs.updatePrefs({ ...$prefs, [pathname]: columnsArray });
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if $columns?.length}
|
||||
{#if $prefs?.preferredView === 'list'}
|
||||
{#if !hideColumns && view === View.Table}
|
||||
{#if $columns?.length}
|
||||
<DropList bind:show={showSelectColumns} scrollable={true}>
|
||||
<Button secondary on:click={() => (showSelectColumns = true)}>
|
||||
<Button secondary on:click={() => (showSelectColumns = !showSelectColumns)}>
|
||||
<span
|
||||
class="icon-view-boards u-opacity-50 "
|
||||
class="icon-view-boards u-opacity-50"
|
||||
aria-hidden="true"
|
||||
aria-label="columns" />
|
||||
<span class="text">Columns</span>
|
||||
@@ -68,29 +97,33 @@
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if showToggle}
|
||||
{#if !hideView}
|
||||
<div class="toggle-button">
|
||||
<ul class="toggle-button-list">
|
||||
<li class="toggle-button-item">
|
||||
<button
|
||||
class="toggle-button-element"
|
||||
aria-label="List View"
|
||||
type="button"
|
||||
class:is-selected={$prefs.preferredView === 'list'}
|
||||
on:click={() => prefs.updatePrefs({ ...$prefs, preferredView: 'list' })}>
|
||||
<span class="icon-view-list" aria-hidden="true" />
|
||||
</button>
|
||||
</li>
|
||||
<li class="toggle-button-item">
|
||||
<button
|
||||
class="toggle-button-element"
|
||||
aria-label="Grid View"
|
||||
type="button"
|
||||
class:is-selected={$prefs.preferredView === 'grid'}
|
||||
on:click={() => prefs.updatePrefs({ ...$prefs, preferredView: 'grid' })}>
|
||||
<span class="icon-view-grid" aria-hidden="true" />
|
||||
</button>
|
||||
</li>
|
||||
{#key $page.url}
|
||||
<li class="toggle-button-item">
|
||||
<a
|
||||
href={getViewLink(View.Table)}
|
||||
on:click={() => updateViewPreferences(View.Table)}
|
||||
class="toggle-button-element"
|
||||
aria-label="List View"
|
||||
type="button"
|
||||
class:is-selected={view === View.Table}>
|
||||
<span class="icon-view-list" aria-hidden="true" />
|
||||
</a>
|
||||
</li>
|
||||
<li class="toggle-button-item">
|
||||
<a
|
||||
href={getViewLink(View.Grid)}
|
||||
on:click={() => updateViewPreferences(View.Grid)}
|
||||
class="toggle-button-element"
|
||||
aria-label="Grid View"
|
||||
type="button"
|
||||
class:is-selected={view === View.Grid}>
|
||||
<span class="icon-view-grid" aria-hidden="true" />
|
||||
</a>
|
||||
</li>
|
||||
{/key}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
+27
-16
@@ -1,24 +1,35 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import type { Page } from '@sveltejs/kit';
|
||||
|
||||
export function pageToOffset(page: number, limit: number): number {
|
||||
return page ? page * limit - limit : 0;
|
||||
}
|
||||
|
||||
export async function redirectOnOffsetOverflow(
|
||||
offset: number,
|
||||
page: number,
|
||||
total: number,
|
||||
project: string,
|
||||
path: string,
|
||||
search: string
|
||||
) {
|
||||
if (offset > total) {
|
||||
if (page <= 2) {
|
||||
await goto(`/console/project-${project}/${path}?${search}`);
|
||||
} else {
|
||||
await goto(`/console/project-${project}/${path}/${page - 1}?${search}`);
|
||||
}
|
||||
}
|
||||
export function getPage(url: URL): number {
|
||||
return Number(url.searchParams.get('page'));
|
||||
}
|
||||
|
||||
export function getLimit(url: URL, route: Page['route'], fallback: number): number {
|
||||
return Number(url.searchParams.get('limit') ?? preferences.get(route).limit ?? fallback);
|
||||
}
|
||||
|
||||
export enum View {
|
||||
Table = 'table',
|
||||
Grid = 'grid'
|
||||
}
|
||||
|
||||
export function getView(url: URL, route: Page['route'], fallback: View): View {
|
||||
return (url.searchParams.get('view') ?? preferences.get(route).view) === View.Grid
|
||||
? View.Grid
|
||||
: View.Table ?? fallback;
|
||||
}
|
||||
|
||||
export function getColumns(route: Page['route'], fallback: string[]): string[] {
|
||||
return preferences.get(route).columns ?? fallback;
|
||||
}
|
||||
|
||||
export function getSearch(url: URL): string | undefined {
|
||||
return url.searchParams.get('search') ?? undefined;
|
||||
}
|
||||
|
||||
type TabElement = { href: string; title: string; hasChildren?: boolean };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { AvatarInitials, EmptySearch, Pagination, Trim } from '$lib/components';
|
||||
import { AvatarInitials, EmptySearch, Limit, Pagination, Trim } from '$lib/components';
|
||||
import {
|
||||
TableBody,
|
||||
TableHeader,
|
||||
@@ -11,12 +11,11 @@
|
||||
} from '$lib/elements/table';
|
||||
import { Container } from '$lib/layout';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
|
||||
export let logs: Models.LogList;
|
||||
export let path: string;
|
||||
export let offset = 0;
|
||||
export let limit = 0;
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -66,8 +65,8 @@
|
||||
</TableBody>
|
||||
</TableScroll>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {logs.total}</p>
|
||||
<Pagination limit={PAGE_LIMIT} {path} {offset} sum={logs.total} />
|
||||
<Limit {limit} sum={logs.total} name="Logs" />
|
||||
<Pagination {limit} {offset} sum={logs.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<EmptySearch>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import { browser } from '$app/environment';
|
||||
import { page } from '$app/stores';
|
||||
import type { View } from '$lib/helpers/load';
|
||||
import type { Page } from '@sveltejs/kit';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { sdk } from './sdk';
|
||||
|
||||
type Preferences = {
|
||||
limit?: number;
|
||||
view?: View;
|
||||
columns?: string[];
|
||||
};
|
||||
|
||||
type PreferencesStore = {
|
||||
[key: string]: {
|
||||
[key: string]: Preferences;
|
||||
collections?: {
|
||||
[key: string]: Preferences['columns'];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
function createPreferences() {
|
||||
const { subscribe, set, update } = writable<PreferencesStore>({});
|
||||
if (browser) {
|
||||
set(JSON.parse(globalThis.localStorage.getItem('preferences') ?? '{}'));
|
||||
}
|
||||
return {
|
||||
subscribe,
|
||||
get: (route: Page['route']): Preferences => {
|
||||
let preferences: PreferencesStore;
|
||||
subscribe((n) => (preferences = n))();
|
||||
|
||||
return (
|
||||
preferences[sdk.forProject.client.config.project]?.[route.id] ?? {
|
||||
limit: null,
|
||||
view: null,
|
||||
columns: null
|
||||
}
|
||||
);
|
||||
},
|
||||
getCustomCollectionColumns: (collectionId: string): Preferences['columns'] => {
|
||||
let preferences: PreferencesStore;
|
||||
subscribe((n) => (preferences = n))();
|
||||
|
||||
return (
|
||||
preferences[sdk.forProject.client.config.project]?.collections?.[collectionId] ??
|
||||
null
|
||||
);
|
||||
},
|
||||
setLimit: (limit: Preferences['limit']) =>
|
||||
update((n) => {
|
||||
const path = get(page).route.id;
|
||||
const project = sdk.forProject.client.config.project;
|
||||
if (!n[project]?.[path]) {
|
||||
n[project] ??= {};
|
||||
n[project][path] ??= {};
|
||||
}
|
||||
|
||||
n[project][path].limit = limit;
|
||||
|
||||
return n;
|
||||
}),
|
||||
setView: (view: Preferences['view']) =>
|
||||
update((n) => {
|
||||
const path = get(page).route.id;
|
||||
const project = sdk.forProject.client.config.project;
|
||||
if (!n[project]?.[path]) {
|
||||
n[project] ??= {};
|
||||
n[project][path] ??= {};
|
||||
}
|
||||
|
||||
n[project][path].view = view;
|
||||
|
||||
return n;
|
||||
}),
|
||||
setColumns: (columns: Preferences['columns']) =>
|
||||
update((n) => {
|
||||
const path = get(page).route.id;
|
||||
const project = sdk.forProject.client.config.project;
|
||||
if (!n[project]?.[path]) {
|
||||
n[project] ??= {};
|
||||
n[project][path] ??= {};
|
||||
}
|
||||
|
||||
n[project][path].columns = columns;
|
||||
|
||||
return n;
|
||||
}),
|
||||
setCustomCollectionColumns: (columns: Preferences['columns']) =>
|
||||
update((n) => {
|
||||
const current = get(page);
|
||||
const project = sdk.forProject.client.config.project;
|
||||
const collection = current.params.collection;
|
||||
if (!n[project]?.collections?.[collection]) {
|
||||
n[project] ??= {};
|
||||
n[project].collections ??= {};
|
||||
}
|
||||
|
||||
n[project].collections[collection] = columns;
|
||||
|
||||
return n;
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
export const preferences = createPreferences();
|
||||
|
||||
if (browser) {
|
||||
preferences.subscribe((n) => globalThis.localStorage.setItem('preferences', JSON.stringify(n)));
|
||||
}
|
||||
+1
-2
@@ -3,7 +3,6 @@
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
const path = '/console/account/activity';
|
||||
</script>
|
||||
|
||||
<Activity {path} logs={data.logs} offset={data.offset} />
|
||||
<Activity {...data} />
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
logs: await sdk.forConsole.account.listLogs([Query.offset(offset), Query.limit(limit)])
|
||||
};
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
|
||||
return {
|
||||
offset,
|
||||
logs: await sdk.forConsole.account.listLogs([Query.offset(offset), Query.limit(PAGE_LIMIT)])
|
||||
};
|
||||
};
|
||||
+5
-9
@@ -6,13 +6,13 @@
|
||||
Pagination,
|
||||
AvatarGroup,
|
||||
CardContainer,
|
||||
Heading
|
||||
Heading,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import CreateOrganization from '../../../createOrganization.svelte';
|
||||
import CreateOrganization from '../../createOrganization.svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
@@ -67,12 +67,8 @@
|
||||
</Empty>
|
||||
{/if}
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.organizations.total}</p>
|
||||
<Pagination
|
||||
limit={CARD_LIMIT}
|
||||
path="/console/account/organizations"
|
||||
offset={data.offset}
|
||||
sum={data.organizations.total} />
|
||||
<Limit limit={data.limit} sum={data.organizations.total} name="Organizations" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.organizations.total} />
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
+7
-5
@@ -1,18 +1,20 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, CARD_LIMIT);
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
organizations: await sdk.forConsole.teams.list([
|
||||
Query.offset(offset),
|
||||
Query.limit(CARD_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
};
|
||||
-1
@@ -124,6 +124,5 @@
|
||||
{/if}
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.sessions.total}</p>
|
||||
<!-- <Pagination limit={PAGE_LIMIT} offset={data.offset} sum={data.sessions.total} /> -->
|
||||
</div>
|
||||
</Container>
|
||||
+5
-10
@@ -1,13 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { GridItem1, Heading, Empty, CardContainer, Pagination } from '$lib/components';
|
||||
import { GridItem1, Heading, Empty, CardContainer, Pagination, Limit } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import CreateProject from '../createProject.svelte';
|
||||
import CreateOrganization from '../../createOrganization.svelte';
|
||||
import CreateProject from './createProject.svelte';
|
||||
import CreateOrganization from '../createOrganization.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
export let data: PageData;
|
||||
@@ -96,12 +95,8 @@
|
||||
</Empty>
|
||||
{/if}
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.projects.total}</p>
|
||||
<Pagination
|
||||
path={`/console/organization-${$page.params.organization}`}
|
||||
limit={CARD_LIMIT}
|
||||
offset={data.offset}
|
||||
sum={data.projects.total} />
|
||||
<Limit limit={data.limit} sum={data.projects.total} name="Projects" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.projects.total} />
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
+7
-5
@@ -1,18 +1,20 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, CARD_LIMIT);
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
projects: await sdk.forConsole.projects.list([
|
||||
Query.offset(offset),
|
||||
Query.limit(CARD_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.equal('teamId', params.organization),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
+5
-9
@@ -2,8 +2,8 @@
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { AvatarInitials, Heading, Pagination } from '$lib/components';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { AvatarInitials, Heading, Limit, Pagination } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
@@ -21,7 +21,7 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
import Delete from '../../deleteMember.svelte';
|
||||
import Delete from '../deleteMember.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -111,12 +111,8 @@
|
||||
</TableBody>
|
||||
</TableScroll>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.organizationMembers.total}</p>
|
||||
<Pagination
|
||||
offset={data.offset}
|
||||
limit={PAGE_LIMIT}
|
||||
path={`/console/organization-${$page.params.organization}/members`}
|
||||
sum={data.members.total} />
|
||||
<Limit limit={data.limit} sum={data.members.total} name="Members" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.members.total} />
|
||||
</div>
|
||||
{/if}
|
||||
</Container>
|
||||
+7
-5
@@ -1,17 +1,19 @@
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
export const load: PageLoad = async ({ url, params, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
organizationMembers: await sdk.forConsole.teams.listMemberships(params.organization, [
|
||||
Query.limit(PAGE_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.offset(offset)
|
||||
])
|
||||
};
|
||||
@@ -6,5 +6,5 @@
|
||||
|
||||
<Container>
|
||||
<Heading size="1" tag="h3">{$page.status}</Heading>
|
||||
<Heading size="3" tag="h4">{$page.error.message}</Heading>
|
||||
<p class="body-text-2 u-margin-block-start-4">{$page.error.message}</p>
|
||||
</Container>
|
||||
|
||||
+7
-11
@@ -6,7 +6,8 @@
|
||||
Pagination,
|
||||
Copy,
|
||||
SearchQuery,
|
||||
AvatarInitials
|
||||
AvatarInitials,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
@@ -23,8 +24,7 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { goto } from '$app/navigation';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import Create from '../createUser.svelte';
|
||||
import Create from './createUser.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
|
||||
let showCreate = false;
|
||||
const projectId = $page.params.project;
|
||||
const userCreated = async (event: CustomEvent<Models.User<Record<string, unknown>>>) => {
|
||||
async function userCreated(event: CustomEvent<Models.User<Record<string, unknown>>>) {
|
||||
await goto(`${base}/console/project-${projectId}/auth/user-${event.detail.$id}`);
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -111,12 +111,8 @@
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.users.total}</p>
|
||||
<Pagination
|
||||
offset={data.offset}
|
||||
limit={PAGE_LIMIT}
|
||||
sum={data.users.total}
|
||||
path={`/console/project-${projectId}/auth`} />
|
||||
<Limit limit={data.limit} sum={data.users.total} name="Users" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.users.total} />
|
||||
</div>
|
||||
{:else if data.search}
|
||||
<EmptySearch>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
search,
|
||||
page,
|
||||
users: await sdk.forProject.users.list(
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
search
|
||||
)
|
||||
};
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, url }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
const search = url.search.slice(1) ?? undefined;
|
||||
|
||||
return {
|
||||
offset,
|
||||
search,
|
||||
page,
|
||||
users: await sdk.forProject.users.list(
|
||||
[Query.limit(PAGE_LIMIT), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
search
|
||||
)
|
||||
};
|
||||
};
|
||||
@@ -1,14 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Modal, CopyInput, Alert } from '$lib/components';
|
||||
import { Button, InputText, InputTextarea, InputSwitch, FormList } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Alert, CopyInput, Modal } from '$lib/components';
|
||||
import { Button, FormList, InputSwitch, InputText, InputTextarea } from '$lib/elements/forms';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { updateOAuth } from './updateOAuth';
|
||||
|
||||
const projectId = $page.params.project;
|
||||
|
||||
export let provider: Provider;
|
||||
|
||||
@@ -17,6 +16,7 @@
|
||||
let keyID: string = null;
|
||||
let teamID: string = null;
|
||||
let p8: string = null;
|
||||
let error: string;
|
||||
|
||||
onMount(() => {
|
||||
appId ??= provider.appId;
|
||||
@@ -24,33 +24,13 @@
|
||||
if (provider.secret) ({ keyID, teamID, p8 } = JSON.parse(provider.secret));
|
||||
});
|
||||
|
||||
let error: string;
|
||||
|
||||
const projectId = $page.params.project;
|
||||
const update = async () => {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been ${
|
||||
provider.enabled ? 'enabled' : 'disabled'
|
||||
}`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
const result = await updateOAuth({ projectId, provider, secret, appId, enabled });
|
||||
|
||||
if (result.status === 'error') {
|
||||
error = result.message;
|
||||
} else {
|
||||
provider = null;
|
||||
invalidate(Dependencies.PROJECT);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Modal, CopyInput, Alert } from '$lib/components';
|
||||
import { Button, InputPassword, InputText, InputSwitch, FormList } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Alert, CopyInput, Modal } from '$lib/components';
|
||||
import { Button, FormList, InputPassword, InputSwitch, InputText } from '$lib/elements/forms';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { updateOAuth } from './updateOAuth';
|
||||
|
||||
export let provider: Provider;
|
||||
|
||||
@@ -26,29 +23,12 @@
|
||||
|
||||
const projectId = $page.params.project;
|
||||
const update = async () => {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been ${
|
||||
provider.enabled ? 'enabled' : 'disabled'
|
||||
}`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
const result = await updateOAuth({ projectId, provider, secret, appId, enabled });
|
||||
|
||||
if (result.status === 'error') {
|
||||
error = result.message;
|
||||
} else {
|
||||
provider = null;
|
||||
invalidate(Dependencies.PROJECT);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Modal, CopyInput, Alert } from '$lib/components';
|
||||
import { Button, InputPassword, InputText, InputSwitch, FormList } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Alert, CopyInput, Modal } from '$lib/components';
|
||||
import { Button, FormList, InputPassword, InputSwitch, InputText } from '$lib/elements/forms';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { updateOAuth } from './updateOAuth';
|
||||
|
||||
export let provider: Provider;
|
||||
|
||||
@@ -26,29 +23,12 @@
|
||||
|
||||
const projectId = $page.params.project;
|
||||
const update = async () => {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been ${
|
||||
provider.enabled ? 'enabled' : 'disabled'
|
||||
}`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
const result = await updateOAuth({ projectId, provider, secret, appId, enabled });
|
||||
|
||||
if (result.status === 'error') {
|
||||
error = result.message;
|
||||
} else {
|
||||
provider = null;
|
||||
invalidate(Dependencies.PROJECT);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Modal, CopyInput, Alert } from '$lib/components';
|
||||
import { Button, InputPassword, InputText, InputSwitch, FormList } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Alert, CopyInput, Modal } from '$lib/components';
|
||||
import { Button, FormList, InputPassword, InputSwitch, InputText } from '$lib/elements/forms';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { updateOAuth } from './updateOAuth';
|
||||
|
||||
export let provider: Provider;
|
||||
|
||||
@@ -26,29 +23,12 @@
|
||||
|
||||
const projectId = $page.params.project;
|
||||
const update = async () => {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been ${
|
||||
provider.enabled ? 'enabled' : 'disabled'
|
||||
}`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
const result = await updateOAuth({ projectId, provider, secret, appId, enabled });
|
||||
|
||||
if (result.status === 'error') {
|
||||
error = result.message;
|
||||
} else {
|
||||
provider = null;
|
||||
invalidate(Dependencies.PROJECT);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Modal, CopyInput, Alert } from '$lib/components';
|
||||
import { Button, InputPassword, InputText, InputSwitch, FormList } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Alert, CopyInput, Modal } from '$lib/components';
|
||||
import { Button, FormList, InputPassword, InputSwitch, InputText } from '$lib/elements/forms';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { updateOAuth } from './updateOAuth';
|
||||
|
||||
export let provider: Provider;
|
||||
|
||||
@@ -27,29 +24,12 @@
|
||||
let error: string;
|
||||
|
||||
const update = async () => {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been ${
|
||||
provider.enabled ? 'enabled' : 'disabled'
|
||||
}`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
const result = await updateOAuth({ projectId, provider, secret, appId, enabled });
|
||||
|
||||
if (result.status === 'error') {
|
||||
error = result.message;
|
||||
} else {
|
||||
provider = null;
|
||||
invalidate(Dependencies.PROJECT);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Modal, CopyInput, Alert } from '$lib/components';
|
||||
import { Button, InputPassword, InputText, InputSwitch, FormList } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Alert, CopyInput, Modal } from '$lib/components';
|
||||
import { Button, FormList, InputPassword, InputSwitch, InputText } from '$lib/elements/forms';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { updateOAuth } from './updateOAuth';
|
||||
|
||||
export let provider: Provider;
|
||||
|
||||
@@ -27,29 +24,12 @@
|
||||
const projectId = $page.params.project;
|
||||
|
||||
const update = async () => {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been ${
|
||||
provider.enabled ? 'enabled' : 'disabled'
|
||||
}`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
const result = await updateOAuth({ projectId, provider, secret, appId, enabled });
|
||||
|
||||
if (result.status === 'error') {
|
||||
error = result.message;
|
||||
} else {
|
||||
provider = null;
|
||||
invalidate(Dependencies.PROJECT);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Modal, CopyInput, Alert } from '$lib/components';
|
||||
import { Button, InputPassword, InputText, InputSwitch, FormList } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Alert, CopyInput, Modal } from '$lib/components';
|
||||
import { Button, FormList, InputPassword, InputSwitch, InputText } from '$lib/elements/forms';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { updateOAuth } from './updateOAuth';
|
||||
|
||||
const projectId = $page.params.project;
|
||||
|
||||
export let provider: Provider;
|
||||
|
||||
@@ -17,42 +16,23 @@
|
||||
let clientSecret: string = null;
|
||||
let oktaDomain: string = null;
|
||||
let authorizationServerId: string = null;
|
||||
let error: string;
|
||||
|
||||
onMount(() => {
|
||||
appId ??= provider.appId;
|
||||
enabled ??= provider.enabled;
|
||||
if (provider.secret)
|
||||
if (provider.secret) {
|
||||
({ clientSecret, oktaDomain, authorizationServerId } = JSON.parse(provider.secret));
|
||||
}
|
||||
});
|
||||
|
||||
let error: string;
|
||||
|
||||
const projectId = $page.params.project;
|
||||
|
||||
const update = async () => {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been ${
|
||||
provider.enabled ? 'enabled' : 'disabled'
|
||||
}`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
const result = await updateOAuth({ projectId, provider, secret, appId, enabled });
|
||||
|
||||
if (result.status === 'error') {
|
||||
error = result.message;
|
||||
} else {
|
||||
provider = null;
|
||||
invalidate(Dependencies.PROJECT);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,9 +25,7 @@
|
||||
await sdk.forConsole.projects.updateAuthStatus(projectId, box.method, box.value);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${box.label} authentication has been ${
|
||||
box.value ? 'enabled' : 'disabled'
|
||||
}`
|
||||
message: `${box.label} authentication has been updated`
|
||||
});
|
||||
trackEvent(Submit.AuthStatusUpdate, {
|
||||
method: box.method,
|
||||
|
||||
+11
-9
@@ -10,15 +10,21 @@
|
||||
TableCell
|
||||
} from '$lib/elements/table';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, EmptySearch, AvatarInitials, Pagination, SearchQuery } from '$lib/components';
|
||||
import Create from '../../createTeam.svelte';
|
||||
import {
|
||||
Empty,
|
||||
EmptySearch,
|
||||
AvatarInitials,
|
||||
Pagination,
|
||||
SearchQuery,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import Create from '../createTeam.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -63,12 +69,8 @@
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.teams.total}</p>
|
||||
<Pagination
|
||||
limit={PAGE_LIMIT}
|
||||
path={`/console/project-${$page.params.project}/auth/teams`}
|
||||
offset={data.offset}
|
||||
sum={data.teams.total} />
|
||||
<Limit limit={data.limit} sum={data.teams.total} name="Teams" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.teams.total} />
|
||||
</div>
|
||||
{:else if data.search}
|
||||
<EmptySearch>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
search,
|
||||
page,
|
||||
teams: await sdk.forProject.teams.list(
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
search
|
||||
)
|
||||
};
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, url }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
const search = url.search.slice(1) ?? undefined;
|
||||
|
||||
return {
|
||||
offset,
|
||||
search,
|
||||
page,
|
||||
teams: await sdk.forProject.teams.list(
|
||||
[Query.limit(PAGE_LIMIT), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
search
|
||||
)
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { Activity } from '$lib/layout';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<Activity {...data} />
|
||||
+7
-5
@@ -1,17 +1,19 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
logs: await sdk.forProject.teams.listLogs(params.team, [
|
||||
Query.limit(PAGE_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.offset(offset)
|
||||
])
|
||||
};
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { page } from '$app/stores';
|
||||
import { Activity } from '$lib/layout';
|
||||
|
||||
export let data: PageData;
|
||||
const path = `/console/project-${$page.params.project}/auth/teams/team-${$page.params.team}/activity`;
|
||||
</script>
|
||||
|
||||
<Activity {path} logs={data.logs} offset={data.offset} />
|
||||
+13
-10
@@ -1,6 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Empty, EmptySearch, AvatarInitials, Pagination, SearchQuery } from '$lib/components';
|
||||
import {
|
||||
Empty,
|
||||
EmptySearch,
|
||||
AvatarInitials,
|
||||
Pagination,
|
||||
SearchQuery,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import {
|
||||
Table,
|
||||
TableHeader,
|
||||
@@ -17,9 +24,9 @@
|
||||
import { base } from '$app/paths';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import type { PageData } from './$types';
|
||||
import CreateMember from '../../createMembership.svelte';
|
||||
import DeleteMembership from '../../deleteMembership.svelte';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import CreateMember from '../createMembership.svelte';
|
||||
import DeleteMembership from '../deleteMembership.svelte';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
export let data: PageData;
|
||||
@@ -81,12 +88,8 @@
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.memberships.total}</p>
|
||||
<Pagination
|
||||
limit={PAGE_LIMIT}
|
||||
path={`/console/project-${$page.params.project}/auth/teams/team-${$page.params.team}/members`}
|
||||
offset={data.offset}
|
||||
sum={data.memberships.total} />
|
||||
<Limit limit={data.limit} sum={data.memberships.total} name="Memberships" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.memberships.total} />
|
||||
</div>
|
||||
{:else if data.search}
|
||||
<EmptySearch>
|
||||
+8
-6
@@ -1,22 +1,24 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url }) => {
|
||||
export const load: PageLoad = async ({ params, depends, url, route }) => {
|
||||
depends(Dependencies.MEMBERSHIPS);
|
||||
const teamId = params.team;
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
const search = url.search.slice(1) ?? undefined;
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
search,
|
||||
limit,
|
||||
memberships: await sdk.forProject.teams.listMemberships(
|
||||
teamId,
|
||||
[Query.limit(PAGE_LIMIT), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
search
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
type Args = {
|
||||
projectId: string;
|
||||
provider: Provider;
|
||||
appId: string;
|
||||
secret: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
type Return = {
|
||||
status: 'success' | 'error';
|
||||
message?: string;
|
||||
};
|
||||
|
||||
export async function updateOAuth({
|
||||
projectId,
|
||||
provider,
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
}: Args): Promise<Return> {
|
||||
try {
|
||||
await sdk.forConsole.projects.updateOAuth2(
|
||||
projectId,
|
||||
provider.name.toLowerCase(),
|
||||
appId,
|
||||
secret,
|
||||
enabled
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${provider.name} authentication has been updated`
|
||||
});
|
||||
trackEvent(Submit.ProviderUpdate, {
|
||||
provider,
|
||||
enabled
|
||||
});
|
||||
invalidate(Dependencies.PROJECT);
|
||||
|
||||
return { status: 'success' };
|
||||
} catch (e) {
|
||||
trackError(e, Submit.ProviderUpdate);
|
||||
return { status: 'error', message: e.message };
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const { period } = params;
|
||||
const response = await sdk.forProject.users.getUsage(period ?? '30d');
|
||||
return {
|
||||
count: response.usersCount as unknown as Models.Metric[],
|
||||
created: response.usersCreate as unknown as Models.Metric[],
|
||||
read: response.usersRead as unknown as Models.Metric[],
|
||||
updated: response.usersUpdate as unknown as Models.Metric[],
|
||||
deleted: response.usersDelete as unknown as Models.Metric[]
|
||||
};
|
||||
try {
|
||||
const response = await sdk.forProject.users.getUsage(period ?? '30d');
|
||||
return {
|
||||
count: response.usersCount as unknown as Models.Metric[],
|
||||
created: response.usersCreate as unknown as Models.Metric[],
|
||||
read: response.usersRead as unknown as Models.Metric[],
|
||||
updated: response.usersUpdate as unknown as Models.Metric[],
|
||||
deleted: response.usersDelete as unknown as Models.Metric[]
|
||||
};
|
||||
} catch (e) {
|
||||
throw error(e.code, e.message);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { Activity } from '$lib/layout';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<Activity logs={data.logs} offset={data.offset} />
|
||||
+7
-6
@@ -1,17 +1,18 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
logs: await sdk.forProject.users.listLogs(params.user, [
|
||||
Query.limit(PAGE_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.offset(offset)
|
||||
])
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { page } from '$app/stores';
|
||||
import { Activity } from '$lib/layout';
|
||||
|
||||
export let data: PageData;
|
||||
const path = `/console/project-${$page.params.project}/auth/user-${$page.params.user}/activity`;
|
||||
</script>
|
||||
|
||||
<Activity {path} logs={data.logs} offset={data.offset} />
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
} from '$lib/elements/table';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import DeleteMembership from '../../deleteMembership.svelte';
|
||||
import DeleteMembership from '../deleteMembership.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
+2
-2
@@ -13,8 +13,8 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import DeleteAllSessions from '../../deleteAllSessions.svelte';
|
||||
import DeleteSessions from '../../deleteSession.svelte';
|
||||
import DeleteAllSessions from '../deleteAllSessions.svelte';
|
||||
import DeleteSessions from '../deleteSession.svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
+1
@@ -4,6 +4,7 @@ import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.SESSIONS);
|
||||
|
||||
return {
|
||||
sessions: await sdk.forProject.users.listSessions(params.user)
|
||||
};
|
||||
+16
-19
@@ -1,42 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { goto, invalidate } from '$app/navigation';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, Heading, ViewSelector } from '$lib/components';
|
||||
import { Empty, Heading, Pagination, Limit, ViewSelector } from '$lib/components';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import Create from '../create.svelte';
|
||||
import Create from './create.svelte';
|
||||
import Grid from './grid.svelte';
|
||||
import Table from './table.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
import GridView from './gridView.svelte';
|
||||
import TableView from './tableView.svelte';
|
||||
import { prefs } from '$lib/stores/user';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { columns } from './store';
|
||||
|
||||
export let data: PageData;
|
||||
const project = $page.params.project;
|
||||
|
||||
let showCreate = false;
|
||||
const project = $page.params.project;
|
||||
|
||||
async function handleCreate(event: CustomEvent<Models.Database>) {
|
||||
showCreate = false;
|
||||
await goto(`${base}/console/project-${project}/databases/database-${event.detail.$id}`);
|
||||
}
|
||||
|
||||
prefs.subscribe((prefs) => {
|
||||
if (prefs?.preferredView) {
|
||||
invalidate(Dependencies.DATABASES);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<div class="u-flex common-section u-main-space-between">
|
||||
<div class="u-flex u-gap-12 common-section u-main-space-between">
|
||||
<Heading tag="h2" size="5">Databases</Heading>
|
||||
|
||||
<div class="u-flex u-gap-16">
|
||||
<ViewSelector {columns} />
|
||||
<ViewSelector view={data.view} {columns} />
|
||||
|
||||
<Button on:click={() => (showCreate = true)} event="create_database">
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
@@ -46,11 +38,16 @@
|
||||
</div>
|
||||
|
||||
{#if data.databases.total}
|
||||
{#if $prefs?.preferredView === 'list'}
|
||||
<TableView {data} {columns} />
|
||||
{#if data.view === 'grid'}
|
||||
<Grid {data} />
|
||||
{:else}
|
||||
<GridView {data} bind:showCreate />
|
||||
<Table {data} />
|
||||
{/if}
|
||||
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<Limit limit={data.limit} sum={data.databases.total} name="Databases" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.databases.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<Empty
|
||||
single
|
||||
@@ -0,0 +1,23 @@
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import { getLimit, getPage, getView, pageToOffset, View } from '$lib/helpers/load';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const view = getView(url, route, View.Grid);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
view,
|
||||
databases: await sdk.forProject.databases.list([
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
};
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { pageToOffset, redirectOnOffsetOverflow } from '$lib/helpers/load';
|
||||
import { CARD_LIMIT, Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { get } from 'svelte/store';
|
||||
import { prefs } from '$lib/stores/user';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url }) => {
|
||||
depends(Dependencies.DATABASES);
|
||||
|
||||
const customPrefs = get(prefs);
|
||||
const page = Number(params.page);
|
||||
const limit = customPrefs?.pageLimit
|
||||
? customPrefs.pageLimit
|
||||
: customPrefs?.preferredView === 'list'
|
||||
? PAGE_LIMIT
|
||||
: CARD_LIMIT;
|
||||
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
const databases = await sdk.forProject.databases.list([
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
]);
|
||||
|
||||
await redirectOnOffsetOverflow(
|
||||
offset,
|
||||
page,
|
||||
databases.total,
|
||||
params.project,
|
||||
'databases',
|
||||
url.search
|
||||
);
|
||||
|
||||
return {
|
||||
offset,
|
||||
databases
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
import { Empty, Heading, Limit, Pagination, ViewSelector } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import { columns, showCreate } from './store';
|
||||
import Table from './table.svelte';
|
||||
import Grid from './grid.svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<div class="u-flex u-gap-12 common-section u-main-space-between">
|
||||
<Heading tag="h2" size="5">Collections</Heading>
|
||||
<div class="u-flex u-gap-16">
|
||||
<ViewSelector view={data.view} {columns} />
|
||||
|
||||
<Button on:click={() => ($showCreate = true)} event="create_collection">
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create collection</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if data.collections.total}
|
||||
{#if data.view === 'grid'}
|
||||
<Grid {data} />
|
||||
{:else}
|
||||
<Table {data} />
|
||||
{/if}
|
||||
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<Limit limit={data.limit} sum={data.collections.total} name="Collections" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.collections.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<Empty
|
||||
single
|
||||
href="https://appwrite.io/docs/databases#collection"
|
||||
target="collection"
|
||||
on:click={() => ($showCreate = true)} />
|
||||
{/if}
|
||||
</Container>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getLimit, getPage, getView, pageToOffset, View } from '$lib/helpers/load';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const view = getView(url, route, View.Grid);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
view,
|
||||
collections: await sdk.forProject.databases.listCollections(params.database, [
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
};
|
||||
};
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, Heading, ViewSelector } from '$lib/components';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import type { PageData } from './$types';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import Create from '../createCollection.svelte';
|
||||
import GridView from './gridView.svelte';
|
||||
import TableView from './tableView.svelte';
|
||||
import { prefs } from '$lib/stores/user';
|
||||
import { columns } from './store';
|
||||
|
||||
export let data: PageData;
|
||||
let showCreate = false;
|
||||
|
||||
const project = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
|
||||
async function handleCreate(event: CustomEvent<Models.Collection>) {
|
||||
showCreate = false;
|
||||
await goto(
|
||||
`${base}/console/project-${project}/databases/database-${databaseId}/collection-${event.detail.$id}`
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<div class="u-flex common-section u-main-space-between">
|
||||
<Heading tag="h2" size="5">Collections</Heading>
|
||||
|
||||
<div class="u-flex u-gap-16">
|
||||
<ViewSelector {columns} />
|
||||
|
||||
<Button on:click={() => (showCreate = true)} event="create_collection">
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create collection</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if data.collections.total}
|
||||
{#if $prefs?.preferredView === 'list'}
|
||||
<TableView {data} {columns} />
|
||||
{:else}
|
||||
<GridView {data} bind:showCreate />
|
||||
{/if}
|
||||
{:else}
|
||||
<Empty
|
||||
single
|
||||
href="https://appwrite.io/docs/databases#collection"
|
||||
target="collection"
|
||||
on:click={() => (showCreate = true)} />
|
||||
{/if}
|
||||
</Container>
|
||||
|
||||
<Create bind:showCreate on:created={handleCreate} />
|
||||
@@ -1,41 +0,0 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { pageToOffset, redirectOnOffsetOverflow } from '$lib/helpers/load';
|
||||
import { CARD_LIMIT, Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { get } from 'svelte/store';
|
||||
import { prefs } from '$lib/stores/user';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url }) => {
|
||||
depends(Dependencies.DATABASE);
|
||||
const page = Number(params.page);
|
||||
|
||||
const customPrefs = get(prefs);
|
||||
|
||||
const limit = customPrefs?.pageLimit
|
||||
? customPrefs.pageLimit
|
||||
: customPrefs?.preferredView === 'list'
|
||||
? PAGE_LIMIT
|
||||
: CARD_LIMIT;
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
const collections = await sdk.forProject.databases.listCollections(params.database, [
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
]);
|
||||
|
||||
await redirectOnOffsetOverflow(
|
||||
offset,
|
||||
page,
|
||||
collections.total,
|
||||
params.project,
|
||||
`databases/database-${params.database}`,
|
||||
url.search
|
||||
);
|
||||
|
||||
return {
|
||||
offset,
|
||||
collections
|
||||
};
|
||||
};
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
<script lang="ts">
|
||||
import { Empty, Heading, Pagination, Limit, ViewSelector } from '$lib/components';
|
||||
import { Container } from '$lib/layout';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import Create from './createDocument.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { collection, columns } from './store';
|
||||
import CreateAttribute from './createAttribute.svelte';
|
||||
import Table from './table.svelte';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let showCreateAttribute = false;
|
||||
|
||||
$: selected = preferences.getCustomCollectionColumns($page.params.collection);
|
||||
$: columns.set(
|
||||
$collection.attributes.map((attribute) => ({
|
||||
id: attribute.key,
|
||||
title: attribute.key,
|
||||
type: attribute.type,
|
||||
show: selected?.includes(attribute.key) ?? true
|
||||
}))
|
||||
);
|
||||
|
||||
function openWizard() {
|
||||
wizard.start(Create);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<div class="u-flex u-gap-12 common-section u-main-space-between">
|
||||
<Heading tag="h2" size="5">Documents</Heading>
|
||||
<div class="u-flex u-gap-16">
|
||||
<ViewSelector view={data.view} {columns} hideView isCustomCollection />
|
||||
<Button
|
||||
disabled={!$collection?.attributes?.length}
|
||||
on:click={openWizard}
|
||||
event="create_document">
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create document</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $collection?.attributes?.length}
|
||||
{#if data.documents.total}
|
||||
<Table {data} />
|
||||
|
||||
<div class="u-flex common-section u-main-space-between">
|
||||
<Limit limit={data.limit} sum={data.documents.total} name="Documents" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.documents.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<Empty
|
||||
single
|
||||
href="https://appwrite.io/docs/databases#create-documents"
|
||||
target="document"
|
||||
on:click={openWizard} />
|
||||
{/if}
|
||||
{:else}
|
||||
<Empty
|
||||
single
|
||||
href="https://appwrite.io/docs/databases#attributes"
|
||||
target="attribute"
|
||||
on:click={() => (showCreateAttribute = true)} />
|
||||
{/if}
|
||||
</Container>
|
||||
|
||||
<CreateAttribute bind:showCreate={showCreateAttribute} />
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { getLimit, getPage, getView, pageToOffset, View } from '$lib/helpers/load';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url, route }) => {
|
||||
depends(Dependencies.DOCUMENTS);
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const view = getView(url, route, View.Grid);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
view,
|
||||
documents: await sdk.forProject.databases.listDocuments(
|
||||
params.database,
|
||||
params.collection,
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('$createdAt')]
|
||||
)
|
||||
};
|
||||
};
|
||||
-217
@@ -1,217 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
TableScroll,
|
||||
TableRowLink,
|
||||
TableBody,
|
||||
TableHeader,
|
||||
TableCellHead,
|
||||
TableCell
|
||||
} from '$lib/elements/table';
|
||||
import { Empty, Copy, Heading, ViewSelector, CustomPagination } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Container } from '$lib/layout';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { base } from '$app/paths';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import Create from '../createDocument.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { collection } from '../store';
|
||||
import { page } from '$app/stores';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import CreateAttribute from '../createAttribute.svelte';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import { columns } from './store';
|
||||
import { onMount } from 'svelte';
|
||||
import RelationshipsModal from './relationshipsModal.svelte';
|
||||
import CreateAttributeDropdown from '../attributes/createAttributeDropdown.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
const projectId = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
let showCreateAttribute = false;
|
||||
let showRelationships = false;
|
||||
let selectedRelationship: string[] = null;
|
||||
let showCreateDropdown = false;
|
||||
let selectedAttribute: string = null;
|
||||
|
||||
function openWizard() {
|
||||
wizard.start(Create);
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
columns.set([
|
||||
...$collection.attributes.map((attribute) => ({
|
||||
id: attribute.key,
|
||||
title: attribute.key,
|
||||
type: attribute.type,
|
||||
show: true
|
||||
}))
|
||||
]);
|
||||
});
|
||||
|
||||
function formatArray(array: unknown[]) {
|
||||
if (array.length === 0) return '[ ]';
|
||||
|
||||
let formattedFields: string[] = [];
|
||||
for (const item of array) {
|
||||
if (typeof item === 'string') {
|
||||
formattedFields.push(`"${item}"`);
|
||||
} else {
|
||||
formattedFields.push(`${item}`);
|
||||
}
|
||||
}
|
||||
|
||||
return `[${formattedFields.join(', ')}]`;
|
||||
}
|
||||
|
||||
function formatColumn(column: unknown) {
|
||||
let formattedColumn: string;
|
||||
|
||||
if (typeof column === 'string') {
|
||||
formattedColumn = column;
|
||||
} else if (Array.isArray(column)) {
|
||||
formattedColumn = formatArray(column);
|
||||
} else if (column === null) {
|
||||
formattedColumn = 'n/a';
|
||||
} else {
|
||||
formattedColumn = `${column}`;
|
||||
}
|
||||
|
||||
return {
|
||||
value:
|
||||
formattedColumn.length > 20
|
||||
? `${formattedColumn.slice(0, 20)}...`
|
||||
: formattedColumn,
|
||||
truncated: formattedColumn.length > 20,
|
||||
whole: formattedColumn
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<div class="u-flex u-gap-12 common-section u-main-space-between">
|
||||
<Heading tag="h2" size="5">Documents</Heading>
|
||||
<div class="u-flex u-gap-16">
|
||||
<ViewSelector showToggle={false} {columns} />
|
||||
<Button
|
||||
disabled={!$collection?.attributes?.length}
|
||||
on:click={openWizard}
|
||||
event="create_document">
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create document</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if $collection?.attributes?.length}
|
||||
{#if data.documents.total}
|
||||
<TableScroll isSticky>
|
||||
<TableHeader>
|
||||
<TableCellHead width={200} eyebrow={false}>Document ID</TableCellHead>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<TableCellHead eyebrow={false}>{column.title}</TableCellHead>
|
||||
{/if}
|
||||
{/each}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each data.documents.documents as document}
|
||||
<TableRowLink
|
||||
href={`${base}/console/project-${projectId}/databases/database-${databaseId}/collection-${$collection.$id}/document-${document.$id}`}>
|
||||
<TableCell width={230}>
|
||||
<Copy value={document.$id}>
|
||||
<Pill button trim>
|
||||
<span class="icon-duplicate" aria-hidden="true" />
|
||||
<span class="text">{document.$id}</span>
|
||||
</Pill>
|
||||
</Copy>
|
||||
</TableCell>
|
||||
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
{#if column.type === 'relationship'}
|
||||
{#if column.direction === 'one'}
|
||||
<TableCell title={column.title}>
|
||||
{document[column.id]}
|
||||
</TableCell>
|
||||
{:else}
|
||||
<TableCell>
|
||||
{@const itemsNum = column?.data?.lenght}
|
||||
<Button
|
||||
on:click={() => {
|
||||
showRelationships = true;
|
||||
selectedRelationship = document;
|
||||
}}
|
||||
disabled={!itemsNum}>
|
||||
Items <span class="inline-tag">{itemsNum}</span>
|
||||
</Button>
|
||||
</TableCell>
|
||||
{/if}
|
||||
{:else}
|
||||
{@const formatted = formatColumn(document[column.id])}
|
||||
<TableCell>
|
||||
<div
|
||||
use:tooltip={{
|
||||
content: formatted.whole,
|
||||
disabled: !formatted.truncated
|
||||
}}>
|
||||
{formatted.value}
|
||||
</div>
|
||||
</TableCell>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</TableRowLink>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</TableScroll>
|
||||
|
||||
<CustomPagination
|
||||
limit={PAGE_LIMIT}
|
||||
name="Documents"
|
||||
path={`/console/project-${$page.params.project}/databases/database-${$page.params.database}/collection-${$page.params.collection}`}
|
||||
offset={data.offset}
|
||||
total={data.documents.total}
|
||||
dependencies={[Dependencies.DOCUMENTS]} />
|
||||
{:else}
|
||||
<Empty
|
||||
single
|
||||
href="https://appwrite.io/docs/databases#create-documents"
|
||||
target="document"
|
||||
on:click={openWizard} />
|
||||
{/if}
|
||||
{:else}
|
||||
<Empty single target="attribute" on:click={() => (showCreateDropdown = true)}>
|
||||
<div class="u-text-center">
|
||||
<Heading size="7" tag="h2">Create your first attribute to get started.</Heading>
|
||||
<p class="body-text-2 u-margin-block-start-4">
|
||||
Need a hand? Check out our documentation.
|
||||
</p>
|
||||
</div>
|
||||
<div class="u-flex u-gap-16 u-main-center">
|
||||
<Button
|
||||
external
|
||||
href="https://appwrite.io/docs/databases#attributes"
|
||||
text
|
||||
event="empty_documentation"
|
||||
ariaLabel={`create {target}`}>Documentation</Button>
|
||||
<CreateAttributeDropdown
|
||||
bind:showCreateDropdown
|
||||
bind:showCreate={showCreateAttribute}
|
||||
bind:selectedOption={selectedAttribute}>
|
||||
<Button
|
||||
secondary
|
||||
event="create_attribute"
|
||||
on:click={() => {
|
||||
showCreateDropdown = !showCreateDropdown;
|
||||
}}>
|
||||
Create attribute
|
||||
</Button>
|
||||
</CreateAttributeDropdown>
|
||||
</div>
|
||||
</Empty>
|
||||
{/if}
|
||||
</Container>
|
||||
|
||||
<CreateAttribute bind:showCreate={showCreateAttribute} bind:selectedOption={selectedAttribute} />
|
||||
<RelationshipsModal bind:show={showRelationships} {selectedRelationship} />
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.DOCUMENTS);
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
|
||||
return {
|
||||
offset,
|
||||
documents: await sdk.forProject.databases.listDocuments(
|
||||
params.database,
|
||||
params.collection,
|
||||
[Query.limit(PAGE_LIMIT), Query.offset(offset), Query.orderDesc('$createdAt')]
|
||||
)
|
||||
};
|
||||
};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { Activity } from '$lib/layout';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<Activity {...data} />
|
||||
+7
-5
@@ -1,19 +1,21 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
logs: await sdk.forProject.databases.listCollectionLogs(
|
||||
params.database,
|
||||
params.collection,
|
||||
[Query.limit(PAGE_LIMIT), Query.offset(offset)]
|
||||
[Query.limit(limit), Query.offset(offset)]
|
||||
)
|
||||
};
|
||||
};
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Activity } from '$lib/layout';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
const path = `/console/project-${$page.params.project}/databases/database-${$page.params.database}/collection-${$page.params.collection}/activity`;
|
||||
</script>
|
||||
|
||||
<Activity {path} logs={data.logs} offset={data.offset} />
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { Activity } from '$lib/layout';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<Activity {...data} />
|
||||
+7
-5
@@ -1,20 +1,22 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
logs: await sdk.forProject.databases.listDocumentLogs(
|
||||
params.database,
|
||||
params.collection,
|
||||
params.document,
|
||||
[Query.limit(PAGE_LIMIT), Query.offset(offset)]
|
||||
[Query.limit(limit), Query.offset(offset)]
|
||||
)
|
||||
};
|
||||
};
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { page } from '$app/stores';
|
||||
import { Activity } from '$lib/layout';
|
||||
|
||||
export let data: PageData;
|
||||
const path = `/console/project-${$page.params.project}/databases/database-${$page.params.database}/collection-${$page.params.collection}/document-${$page.params.document}/activity`;
|
||||
</script>
|
||||
|
||||
<Activity {path} logs={data.logs} offset={data.offset} />
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import type { Column } from '$lib/components/viewSelector.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { derived } from 'svelte/store';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
|
||||
export type Attributes =
|
||||
| Models.AttributeBoolean
|
||||
@@ -22,3 +23,4 @@ export const attributes = derived(
|
||||
($page) => $page.data.collection.attributes as Attributes[]
|
||||
);
|
||||
export const indexes = derived(page, ($page) => $page.data.collection.indexes as Models.Index[]);
|
||||
export const columns = writable<Column[]>([]);
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { showCreate } from '../store';
|
||||
import type { PageData } from './[[page]]/$types';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
$: data = $page.data as PageData;
|
||||
$: project = $page.params.project;
|
||||
@@ -31,7 +31,7 @@
|
||||
{#if data?.allCollections?.total}
|
||||
<ul class="drop-list">
|
||||
{#each sortedCollections as collection}
|
||||
{@const href = `${base}/console/project-${project}/databases/database-${databaseId}/collection-${collection.$id}/documents`}
|
||||
{@const href = `${base}/console/project-${project}/databases/database-${databaseId}/collection-${collection.$id}`}
|
||||
{@const isSelected = collectionId === collection.$id}
|
||||
<li class="drop-list-item">
|
||||
<a class="drop-button" class:is-selected={isSelected} {href}>
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import { Copy } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import {
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableCellHead,
|
||||
TableHeader,
|
||||
TableRowLink,
|
||||
TableScroll
|
||||
} from '$lib/elements/table';
|
||||
import type { PageData } from './$types';
|
||||
import { collection, columns } from './store';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
const projectId = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
|
||||
function formatArray(array: unknown[]) {
|
||||
if (array.length === 0) return '[ ]';
|
||||
|
||||
let formattedFields: string[] = [];
|
||||
for (const item of array) {
|
||||
if (typeof item === 'string') {
|
||||
formattedFields.push(`"${item}"`);
|
||||
} else {
|
||||
formattedFields.push(`${item}`);
|
||||
}
|
||||
}
|
||||
|
||||
return `[${formattedFields.join(', ')}]`;
|
||||
}
|
||||
|
||||
function formatColumn(column: unknown) {
|
||||
let formattedColumn: string;
|
||||
|
||||
if (typeof column === 'string') {
|
||||
formattedColumn = column;
|
||||
} else if (Array.isArray(column)) {
|
||||
formattedColumn = formatArray(column);
|
||||
} else if (column === null) {
|
||||
formattedColumn = 'n/a';
|
||||
} else {
|
||||
formattedColumn = `${column}`;
|
||||
}
|
||||
|
||||
return {
|
||||
value:
|
||||
formattedColumn.length > 20
|
||||
? `${formattedColumn.slice(0, 20)}...`
|
||||
: formattedColumn,
|
||||
truncated: formattedColumn.length > 20,
|
||||
whole: formattedColumn
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<TableScroll isSticky>
|
||||
<TableHeader>
|
||||
<TableCellHead width={100} eyebrow={false}>Document ID</TableCellHead>
|
||||
{#each $columns.filter((n) => n.show) as column}
|
||||
{#if column.show}
|
||||
<TableCellHead eyebrow={false}>{column.title}</TableCellHead>
|
||||
{/if}
|
||||
{/each}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each data.documents.documents as document}
|
||||
<TableRowLink
|
||||
href={`${base}/console/project-${projectId}/databases/database-${databaseId}/collection-${$collection.$id}/document-${document.$id}`}>
|
||||
<TableCell>
|
||||
<Copy value={document.$id}>
|
||||
<Pill button trim>
|
||||
<span class="icon-duplicate" aria-hidden="true" />
|
||||
<span class="text">{document.$id}</span>
|
||||
</Pill>
|
||||
</Copy>
|
||||
</TableCell>
|
||||
{#each $columns.filter((n) => n.show) as column}
|
||||
{@const formatted = formatColumn(document[column.id])}
|
||||
<TableCell>
|
||||
<div
|
||||
use:tooltip={{
|
||||
content: formatted.whole,
|
||||
disabled: !formatted.truncated
|
||||
}}>
|
||||
{formatted.value}
|
||||
</div>
|
||||
</TableCell>
|
||||
{/each}
|
||||
</TableRowLink>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</TableScroll>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { CardContainer, Copy, GridItem1 } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import type { PageData } from './$types';
|
||||
export let data: PageData;
|
||||
export let showCreate = false;
|
||||
const projectId = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
</script>
|
||||
|
||||
<CardContainer
|
||||
total={data.collections.total}
|
||||
on:click={() => (showCreate = true)}
|
||||
event="collection">
|
||||
{#each data.collections.collections as collection}
|
||||
<GridItem1
|
||||
href={`${base}/console/project-${projectId}/databases/database-${databaseId}/collection-${collection.$id}`}>
|
||||
<svelte:fragment slot="title">{collection.name}</svelte:fragment>
|
||||
<svelte:fragment slot="status">
|
||||
{#if !collection.enabled}
|
||||
<Pill>disabled</Pill>
|
||||
{/if}</svelte:fragment>
|
||||
|
||||
<Copy value={collection.$id}>
|
||||
<Pill button><i class="icon-duplicate" />Collection ID</Pill>
|
||||
</Copy>
|
||||
</GridItem1>
|
||||
{/each}
|
||||
</CardContainer>
|
||||
@@ -1,6 +1,14 @@
|
||||
import { page } from '$app/stores';
|
||||
import type { Column } from '$lib/components/viewSelector.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
|
||||
export const database = derived(page, ($page) => $page.data.database as Models.Database);
|
||||
export const showCreate = writable(false);
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Database ID', show: true, width: 50 },
|
||||
{ id: 'name', title: 'Name', show: true, width: 120 },
|
||||
{ id: '$createdAt', title: 'Created', show: true, width: 120 },
|
||||
{ id: '$updatedAt', title: 'Updated', show: true, width: 120 }
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Copy } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableCellHead,
|
||||
TableCellText,
|
||||
TableHeader,
|
||||
TableRowLink
|
||||
} from '$lib/elements/table';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import type { PageData } from './$types';
|
||||
import { columns } from './store';
|
||||
|
||||
export let data: PageData;
|
||||
const projectId = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
</script>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<TableCellHead width={column.width}>{column.title}</TableCellHead>
|
||||
{/if}
|
||||
{/each}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each data.collections.collections as collection}
|
||||
<TableRowLink
|
||||
href={`${base}/console/project-${projectId}/databases/database-${databaseId}/collection-${collection.$id}`}>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<TableCell title={column.title}>
|
||||
<Copy value={collection.$id}>
|
||||
<Pill button trim>
|
||||
<span class="icon-duplicate" aria-hidden="true" />
|
||||
<span class="text u-trim">{collection.$id}</span>
|
||||
</Pill>
|
||||
</Copy>
|
||||
</TableCell>
|
||||
{/key}
|
||||
{:else if column.id === 'name'}
|
||||
<TableCellText title={column.title}>
|
||||
{collection.name}
|
||||
</TableCellText>
|
||||
{:else}
|
||||
<TableCellText title={column.title}>
|
||||
{toLocaleDateTime(collection[column.id])}
|
||||
</TableCellText>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</TableRowLink>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</Table>
|
||||
@@ -0,0 +1,25 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { CardContainer, Copy, GridItem1 } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import type { PageData } from './$types';
|
||||
export let data: PageData;
|
||||
export let showCreate = false;
|
||||
const project = $page.params.project;
|
||||
</script>
|
||||
|
||||
<CardContainer total={data.databases.total} on:click={() => (showCreate = true)} event="database">
|
||||
{#each data.databases.databases as database}
|
||||
<GridItem1 href={`${base}/console/project-${project}/databases/database-${database.$id}`}>
|
||||
<svelte:fragment slot="title">{database.name}</svelte:fragment>
|
||||
|
||||
<Copy value={database.$id}>
|
||||
<Pill button><i class="icon-duplicate" />Database ID</Pill>
|
||||
</Copy>
|
||||
</GridItem1>
|
||||
{/each}
|
||||
<svelte:fragment slot="empty">
|
||||
<p>Create a new database</p>
|
||||
</svelte:fragment>
|
||||
</CardContainer>
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { Column } from '$lib/components/viewSelector.svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'Database ID', show: true, width: 50 },
|
||||
{ id: 'name', title: 'Name', show: true, width: 120 },
|
||||
{ id: '$createdAt', title: 'Created', show: true, width: 120 },
|
||||
{ id: '$updatedAt', title: 'Updated', show: true, width: 120 }
|
||||
]);
|
||||
@@ -0,0 +1,62 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Copy } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableCellHead,
|
||||
TableCellText,
|
||||
TableHeader,
|
||||
TableRowLink
|
||||
} from '$lib/elements/table';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import type { PageData } from './$types';
|
||||
import { columns } from './store';
|
||||
|
||||
export let data: PageData;
|
||||
const projectId = $page.params.project;
|
||||
</script>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
<TableCellHead width={column.width}>{column.title}</TableCellHead>
|
||||
{/if}
|
||||
{/each}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each data.databases.databases as database}
|
||||
<TableRowLink
|
||||
href={`${base}/console/project-${projectId}/databases/database-${database.$id}`}>
|
||||
{#each $columns as column}
|
||||
{#if column.show}
|
||||
{#if column.id === '$id'}
|
||||
{#key $columns}
|
||||
<TableCell title={column.title}>
|
||||
<Copy value={database.$id}>
|
||||
<Pill button trim>
|
||||
<span class="icon-duplicate" aria-hidden="true" />
|
||||
<span class="text u-trim">{database.$id}</span>
|
||||
</Pill>
|
||||
</Copy>
|
||||
</TableCell>
|
||||
{/key}
|
||||
{:else if column.id === 'name'}
|
||||
<TableCellText title={column.title}>
|
||||
{database.name}
|
||||
</TableCellText>
|
||||
{:else}
|
||||
<TableCellText title={column.title}>
|
||||
{toLocaleDateTime(database[column.id])}
|
||||
</TableCellText>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</TableRowLink>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</Table>
|
||||
@@ -1,16 +1,20 @@
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const { period } = params;
|
||||
const response = await sdk.forProject.databases.getUsage(period ?? '30d');
|
||||
|
||||
return {
|
||||
count: response.databasesCount as unknown as Models.Metric[],
|
||||
created: response.databasesCreate as unknown as Models.Metric[],
|
||||
read: response.databasesRead as unknown as Models.Metric[],
|
||||
updated: response.databasesUpdate as unknown as Models.Metric[],
|
||||
deleted: response.databasesDelete as unknown as Models.Metric[]
|
||||
};
|
||||
try {
|
||||
const response = await sdk.forProject.databases.getUsage(period ?? '30d');
|
||||
return {
|
||||
count: response.databasesCount as unknown as Models.Metric[],
|
||||
created: response.databasesCreate as unknown as Models.Metric[],
|
||||
read: response.databasesRead as unknown as Models.Metric[],
|
||||
updated: response.databasesUpdate as unknown as Models.Metric[],
|
||||
deleted: response.databasesDelete as unknown as Models.Metric[]
|
||||
};
|
||||
} catch (e) {
|
||||
throw error(e.code, e.message);
|
||||
}
|
||||
};
|
||||
|
||||
+12
-9
@@ -1,7 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, CardContainer, Copy, GridItem1, Heading, Pagination } from '$lib/components';
|
||||
import {
|
||||
Empty,
|
||||
CardContainer,
|
||||
Copy,
|
||||
GridItem1,
|
||||
Heading,
|
||||
Pagination,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
@@ -10,9 +18,8 @@
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { beforeNavigate } from '$app/navigation';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import Create from '../createFunction.svelte';
|
||||
import Create from './createFunction.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -82,12 +89,8 @@
|
||||
</svelte:fragment>
|
||||
</CardContainer>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.functions.total}</p>
|
||||
<Pagination
|
||||
limit={CARD_LIMIT}
|
||||
path={`/console/project-${$page.params.project}/functions`}
|
||||
offset={data.offset}
|
||||
sum={data.functions.total} />
|
||||
<Limit limit={data.limit} sum={data.functions.total} name="Functions" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.functions.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<Empty
|
||||
+7
-5
@@ -1,18 +1,20 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { CARD_LIMIT, Dependencies } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends }) => {
|
||||
export const load: PageLoad = async ({ url, depends, route }) => {
|
||||
depends(Dependencies.FUNCTIONS);
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, CARD_LIMIT);
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
functions: await sdk.forProject.functions.list([
|
||||
Query.limit(CARD_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
+10
-13
@@ -9,7 +9,8 @@
|
||||
Empty,
|
||||
Status,
|
||||
Heading,
|
||||
Pagination
|
||||
Pagination,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import {
|
||||
TableHeader,
|
||||
@@ -20,7 +21,7 @@
|
||||
TableCellText,
|
||||
TableScroll
|
||||
} from '$lib/elements/table';
|
||||
import { execute, func } from '../store';
|
||||
import { execute, func } from './store';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { app } from '$lib/stores/app';
|
||||
@@ -28,15 +29,14 @@
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { log } from '$lib/stores/logs';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
import Delete from '../delete.svelte';
|
||||
import Create from '../create.svelte';
|
||||
import Activate from '../activate.svelte';
|
||||
import Delete from './delete.svelte';
|
||||
import Create from './create.svelte';
|
||||
import Activate from './activate.svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { page } from '$app/stores';
|
||||
import Output from '$lib/components/output.svelte';
|
||||
import { calculateTime } from '$lib/helpers/timeConversion';
|
||||
import { timer } from '$lib/actions/timer';
|
||||
@@ -279,13 +279,10 @@
|
||||
href="https://appwrite.io/docs/functions#createFunction"
|
||||
on:click={() => (showCreate = true)} />
|
||||
{/if}
|
||||
{@const sum = data.deployments.total ? data.deployments.total - 1 : 0}
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.deployments.total ? data.deployments.total - 1 : 0}</p>
|
||||
<Pagination
|
||||
limit={PAGE_LIMIT}
|
||||
path={`/console/project-${$page.params.project}/functions/function-${$page.params.function}`}
|
||||
offset={data.offset}
|
||||
sum={data.deployments.total ? data.deployments.total - 1 : 0} />
|
||||
<Limit limit={data.limit} {sum} name="Deployments" />
|
||||
<Pagination limit={data.limit} offset={data.offset} {sum} />
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
+7
-5
@@ -1,18 +1,20 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends }) => {
|
||||
export const load: PageLoad = async ({ params, depends, url, route }) => {
|
||||
depends(Dependencies.DEPLOYMENTS);
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
deployments: await sdk.forProject.functions.listDeployments(params.function, [
|
||||
Query.limit(PAGE_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
+6
-11
@@ -1,8 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { Copy, EmptySearch, Heading, Pagination, Status } from '$lib/components';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { Copy, EmptySearch, Heading, Limit, Pagination, Status } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
@@ -20,8 +19,8 @@
|
||||
import { log } from '$lib/stores/logs';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { func } from '../../store';
|
||||
import CreateDeployment from '../../create.svelte';
|
||||
import { func } from '../store';
|
||||
import CreateDeployment from '../create.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
@@ -105,12 +104,8 @@
|
||||
</TableBody>
|
||||
</TableScroll>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.executions.total}</p>
|
||||
<Pagination
|
||||
limit={PAGE_LIMIT}
|
||||
path={`/console/project-${$page.params.project}/functions/function-${$page.params.function}/executions`}
|
||||
offset={data.offset}
|
||||
sum={data.executions.total} />
|
||||
<Limit limit={data.limit} sum={data.executions.total} name="Executions" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.executions.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<EmptySearch>
|
||||
+7
-5
@@ -1,18 +1,20 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends }) => {
|
||||
export const load: PageLoad = async ({ params, depends, url, route }) => {
|
||||
depends(Dependencies.EXECUTIONS);
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
executions: await sdk.forProject.functions.listExecutions(params.function, [
|
||||
Query.limit(PAGE_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
+13
-8
@@ -1,15 +1,20 @@
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const response = await sdk.forProject.functions.getFunctionUsage(
|
||||
params.function,
|
||||
params.period ?? '30d'
|
||||
);
|
||||
try {
|
||||
const response = await sdk.forProject.functions.getFunctionUsage(
|
||||
params.function,
|
||||
params.period ?? '30d'
|
||||
);
|
||||
|
||||
return {
|
||||
count: response.executionsTotal as unknown as Models.Metric[],
|
||||
errors: response.executionsFailure as unknown as Models.Metric[]
|
||||
};
|
||||
return {
|
||||
count: response.executionsTotal as unknown as Models.Metric[],
|
||||
errors: response.buildsFailure as unknown as Models.Metric[]
|
||||
};
|
||||
} catch (e) {
|
||||
throw error(e.code, e.message);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Alert, Code } from '$lib/components';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { Mode, MODE } from '$lib/system';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
const { endpoint, project } = sdk.forProject.client.config;
|
||||
@@ -10,6 +11,8 @@ let client = Client()
|
||||
.setEndpoint("${endpoint}")
|
||||
.setProject("${project}")
|
||||
.setSelfSigned(status: true) // For self signed certificates, only use for development`;
|
||||
|
||||
let showAlert = true;
|
||||
</script>
|
||||
|
||||
<WizardStep>
|
||||
@@ -25,13 +28,18 @@ let client = Client()
|
||||
Before sending any API calls to your new Appwrite project, make sure your device or emulator
|
||||
has network access to your Appwrite project's hostname or IP address.
|
||||
</p>
|
||||
<div class="common-section">
|
||||
<Alert type="info">
|
||||
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
|
||||
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
|
||||
you should use the private IP of the device running your Appwrite project as the hostname
|
||||
of the endpoint instead of localhost. You can also use a service like ngrok to proxy the
|
||||
Appwrite server.
|
||||
</Alert>
|
||||
</div>
|
||||
{#if showAlert}
|
||||
<div class="common-section">
|
||||
<Alert
|
||||
type="info"
|
||||
dismissible={MODE === Mode.CLOUD}
|
||||
on:dismiss={() => (showAlert = false)}>
|
||||
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
|
||||
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
|
||||
you should use the private IP of the device running your Appwrite project as the hostname
|
||||
of the endpoint instead of localhost. You can also use a service like ngrok to proxy
|
||||
the Appwrite server.
|
||||
</Alert>
|
||||
</div>
|
||||
{/if}
|
||||
</WizardStep>
|
||||
|
||||
+17
-9
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Alert, Code } from '$lib/components';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { Mode, MODE } from '$lib/system';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
const { endpoint, project } = sdk.forProject.client.config;
|
||||
@@ -11,6 +12,8 @@ client
|
||||
.setEndpoint('${endpoint}')
|
||||
.setProject('${project}')
|
||||
.setSelfSigned(status: true); // For self signed certificates, only use for development`;
|
||||
|
||||
let showAlert = true;
|
||||
</script>
|
||||
|
||||
<WizardStep>
|
||||
@@ -26,13 +29,18 @@ client
|
||||
Before sending any API calls to your new Appwrite project, make sure your device or emulator
|
||||
has network access to your Appwrite project's hostname or IP address.
|
||||
</p>
|
||||
<div class="common-section">
|
||||
<Alert type="info">
|
||||
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
|
||||
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
|
||||
you should use the private IP of the device running your Appwrite project as the hostname
|
||||
of the endpoint instead of localhost. You can also use a service like ngrok to proxy the
|
||||
Appwrite server.
|
||||
</Alert>
|
||||
</div>
|
||||
{#if showAlert}
|
||||
<div class="common-section">
|
||||
<Alert
|
||||
type="info"
|
||||
dismissible={MODE === Mode.CLOUD}
|
||||
on:dismiss={() => (showAlert = false)}>
|
||||
<svelte:fragment slot="title">For self-hosted solutions</svelte:fragment>
|
||||
When connecting to a locally hosted Appwrite project from an emulator or a mobile device,
|
||||
you should use the private IP of the device running your Appwrite project as the hostname
|
||||
of the endpoint instead of localhost. You can also use a service like ngrok to proxy
|
||||
the Appwrite server.
|
||||
</Alert>
|
||||
</div>
|
||||
{/if}
|
||||
</WizardStep>
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
import Create from '../create.svelte';
|
||||
import Delete from '../delete.svelte';
|
||||
import Create from './create.svelte';
|
||||
import Delete from './delete.svelte';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
|
||||
export let data: PageData;
|
||||
+13
-9
@@ -2,17 +2,25 @@
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, Pagination, Copy, GridItem1, CardContainer, Heading } from '$lib/components';
|
||||
import {
|
||||
Empty,
|
||||
Pagination,
|
||||
Copy,
|
||||
GridItem1,
|
||||
CardContainer,
|
||||
Heading,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import Create from '../create.svelte';
|
||||
import Create from './create.svelte';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import type { PageData } from './$types';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let showCreate = false;
|
||||
|
||||
const project = $page.params.project;
|
||||
@@ -83,12 +91,8 @@
|
||||
</CardContainer>
|
||||
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.buckets.total}</p>
|
||||
<Pagination
|
||||
limit={CARD_LIMIT}
|
||||
path={`/console/project-${$page.params.project}/storage`}
|
||||
offset={data.offset}
|
||||
sum={data.buckets.total} />
|
||||
<Limit limit={data.limit} sum={data.buckets.total} name="Buckets" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.buckets.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<Empty
|
||||
+7
-5
@@ -1,17 +1,19 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, CARD_LIMIT);
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
buckets: await sdk.forProject.storage.listBuckets([
|
||||
Query.limit(CARD_LIMIT),
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
+7
-10
@@ -11,10 +11,11 @@
|
||||
DropList,
|
||||
DropListItem,
|
||||
DropListLink,
|
||||
SearchQuery
|
||||
SearchQuery,
|
||||
Limit
|
||||
} from '$lib/components';
|
||||
import Create from '../create.svelte';
|
||||
import Delete from '../deleteFile.svelte';
|
||||
import Create from './create.svelte';
|
||||
import Delete from './deleteFile.svelte';
|
||||
import {
|
||||
Table,
|
||||
TableHeader,
|
||||
@@ -34,7 +35,7 @@
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import type { PageData } from './$types';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
|
||||
export let data: PageData;
|
||||
@@ -184,12 +185,8 @@
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {data.files.total}</p>
|
||||
<Pagination
|
||||
limit={PAGE_LIMIT}
|
||||
path={`/console/project-${$page.params.project}/storage/bucket-${$page.params.bucket}`}
|
||||
offset={data.offset}
|
||||
sum={data.files.total} />
|
||||
<Limit limit={data.limit} sum={data.files.total} name="Files" />
|
||||
<Pagination limit={data.limit} offset={data.offset} sum={data.files.total} />
|
||||
</div>
|
||||
{:else if data.search}
|
||||
<EmptySearch>
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url, route }) => {
|
||||
depends(Dependencies.FILES);
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
search,
|
||||
files: await sdk.forProject.storage.listFiles(
|
||||
params.bucket,
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
search
|
||||
)
|
||||
};
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { pageToOffset } from '$lib/helpers/load';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url }) => {
|
||||
depends(Dependencies.FILES);
|
||||
const page = Number(params.page);
|
||||
const offset = pageToOffset(page, PAGE_LIMIT);
|
||||
const search = url.search.slice(1) ?? undefined;
|
||||
|
||||
return {
|
||||
offset,
|
||||
search,
|
||||
files: await sdk.forProject.storage.listFiles(
|
||||
params.bucket,
|
||||
[Query.limit(PAGE_LIMIT), Query.offset(offset), Query.orderDesc('$createdAt')],
|
||||
search
|
||||
)
|
||||
};
|
||||
};
|
||||
@@ -1,15 +1,20 @@
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const response = await sdk.forProject.storage.getUsage(params.period ?? '30d');
|
||||
try {
|
||||
const response = await sdk.forProject.storage.getUsage(params.period ?? '30d');
|
||||
|
||||
return {
|
||||
count: response.bucketsCount as unknown as Models.Metric[],
|
||||
created: response.bucketsCreate as unknown as Models.Metric[],
|
||||
read: response.bucketsRead as unknown as Models.Metric[],
|
||||
updated: response.bucketsUpdate as unknown as Models.Metric[],
|
||||
deleted: response.bucketsDelete as unknown as Models.Metric[]
|
||||
};
|
||||
return {
|
||||
count: response.bucketsCount as unknown as Models.Metric[],
|
||||
created: response.bucketsCreate as unknown as Models.Metric[],
|
||||
read: response.bucketsRead as unknown as Models.Metric[],
|
||||
updated: response.bucketsUpdate as unknown as Models.Metric[],
|
||||
deleted: response.bucketsDelete as unknown as Models.Metric[]
|
||||
};
|
||||
} catch (e) {
|
||||
throw error(e.code, e.message);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user