mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
feat: secondary sidebar in collections
This commit is contained in:
@@ -4,9 +4,18 @@
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
|
||||
$: project = $page.params.project;
|
||||
$: path = `${base}/console/project-${project}`;
|
||||
$: projectPath = `${base}/console/project-${project}`;
|
||||
|
||||
let narrow = true;
|
||||
$: secondSideNav = $page.data.secondSideNav;
|
||||
// We need to have this second variable, because we only want narrow
|
||||
// to change automatically if we change from having a second side nav to
|
||||
// not having one, not when the second side nav changes to a different value.
|
||||
$: hasSecondSideNav = !!secondSideNav;
|
||||
|
||||
let narrow = false;
|
||||
$: {
|
||||
narrow = hasSecondSideNav;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="side-nav">
|
||||
@@ -19,10 +28,10 @@
|
||||
<a
|
||||
class="drop-button"
|
||||
class:is-selected={$page.url.pathname.startsWith(
|
||||
`${path}/overview`
|
||||
`${projectPath}/overview`
|
||||
)}
|
||||
on:click={() => trackEvent('click_menu_overview')}
|
||||
href={path}>
|
||||
href={projectPath}>
|
||||
<span class="icon-chart-bar" aria-hidden="true" />
|
||||
<span class="text">Overview</span>
|
||||
</a>
|
||||
@@ -30,9 +39,11 @@
|
||||
<li class="drop-list-item">
|
||||
<a
|
||||
class="drop-button"
|
||||
class:is-selected={$page.url.pathname.startsWith(`${path}/auth`)}
|
||||
class:is-selected={$page.url.pathname.startsWith(
|
||||
`${projectPath}/auth`
|
||||
)}
|
||||
on:click={() => trackEvent('click_menu_auth')}
|
||||
href={`${path}/auth`}>
|
||||
href={`${projectPath}/auth`}>
|
||||
<span class="icon-user-group" aria-hidden="true" />
|
||||
<span class="text">Auth</span>
|
||||
</a>
|
||||
@@ -41,10 +52,10 @@
|
||||
<a
|
||||
class="drop-button"
|
||||
class:is-selected={$page.url.pathname.startsWith(
|
||||
`${path}/databases`
|
||||
`${projectPath}/databases`
|
||||
)}
|
||||
on:click={() => trackEvent('click_menu_databases')}
|
||||
href={`${path}/databases`}>
|
||||
href={`${projectPath}/databases`}>
|
||||
<span class="icon-database" aria-hidden="true" />
|
||||
<span class="text">Databases</span>
|
||||
</a>
|
||||
@@ -53,10 +64,10 @@
|
||||
<a
|
||||
class="drop-button"
|
||||
class:is-selected={$page.url.pathname.startsWith(
|
||||
`${path}/functions`
|
||||
`${projectPath}/functions`
|
||||
)}
|
||||
on:click={() => trackEvent('click_menu_functions')}
|
||||
href={`${path}/functions`}>
|
||||
href={`${projectPath}/functions`}>
|
||||
<span class="icon-lightning-bolt" aria-hidden="true" />
|
||||
<span class="text">Functions</span>
|
||||
</a>
|
||||
@@ -64,9 +75,11 @@
|
||||
<li class="drop-list-item">
|
||||
<a
|
||||
class="drop-button"
|
||||
class:is-selected={$page.url.pathname.startsWith(`${path}/storage`)}
|
||||
class:is-selected={$page.url.pathname.startsWith(
|
||||
`${projectPath}/storage`
|
||||
)}
|
||||
on:click={() => trackEvent('click_menu_storage')}
|
||||
href={`${path}/storage`}>
|
||||
href={`${projectPath}/storage`}>
|
||||
<span class="icon-folder" aria-hidden="true" />
|
||||
<span class="text">Storage</span>
|
||||
</a>
|
||||
@@ -79,72 +92,38 @@
|
||||
<section class="drop-section">
|
||||
<a
|
||||
class="drop-button"
|
||||
href={`${path}/settings`}
|
||||
href={`${projectPath}/settings`}
|
||||
on:click={() => trackEvent('click_menu_settings')}
|
||||
class:is-selected={$page.url.pathname.startsWith(`${path}/settings`)}>
|
||||
class:is-selected={$page.url.pathname.startsWith(
|
||||
`${projectPath}/settings`
|
||||
)}>
|
||||
<span class="icon-cog" aria-hidden="true" />
|
||||
<span class="text">Settings</span>
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
{/if}
|
||||
<button
|
||||
class="side-nav-button button is-small is-secondary is-not-mobile"
|
||||
aria-label="resize menu"
|
||||
on:click={() => (narrow = !narrow)}>
|
||||
<span
|
||||
class:icon-cheveron-right={narrow}
|
||||
class:icon-cheveron-left={!narrow}
|
||||
aria-hidden="true" />
|
||||
</button>
|
||||
|
||||
{#if secondSideNav}
|
||||
<button
|
||||
class="side-nav-button button is-small is-secondary is-not-mobile"
|
||||
aria-label="resize menu"
|
||||
on:click={() => (narrow = !narrow)}>
|
||||
<span
|
||||
class:icon-cheveron-right={narrow}
|
||||
class:icon-cheveron-left={!narrow}
|
||||
aria-hidden="true" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="side-nav-level-2 is-open">
|
||||
<div class="side-nav-main">
|
||||
<section class="drop-section u-flex-vertical u-gap-8">
|
||||
<button
|
||||
class="u-flex u-cross-center u-sep-block-end u-padding-block-12 is-not-desktop"
|
||||
id="aaa">
|
||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||
<span class="eyebrow-heading-3 u-margin-inline-auto">Databases</span>
|
||||
</button>
|
||||
<h5 class="eyebrow-heading-3 u-padding-block-12">Header</h5>
|
||||
<button class="button is-text is-full-width u-main-start u-padding-inline-0">
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Button</span>
|
||||
</button>
|
||||
<ul class="drop-list">
|
||||
<li class="drop-list-item">
|
||||
<a class="drop-button is-selected" href="/">
|
||||
<span class="text">Home</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="drop-list-item">
|
||||
<a class="drop-button" href="">
|
||||
<span class="text">Database</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="drop-list-item">
|
||||
<a class="drop-button" href="/settings.html">
|
||||
<span class="text">Storage</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="drop-list-item">
|
||||
<a class="drop-button" href="/users.html">
|
||||
<span class="text">Users</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="drop-list-item">
|
||||
<a class="drop-button" href="">
|
||||
<span class="text">Functions</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
{#if secondSideNav}
|
||||
<div class="side-nav-level-2 is-open">
|
||||
<div class="side-nav-main">
|
||||
<svelte:component this={secondSideNav} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Breadcrumbs from './breadcrumbs.svelte';
|
||||
import Header from './header.svelte';
|
||||
import SecondSideNav from './database-[database]/secondSideNav.svelte';
|
||||
import type { LayoutLoad } from './$types';
|
||||
|
||||
export const load: LayoutLoad = async ({ parent }) => {
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { goto, invalidate } from '$app/navigation';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import Create from './create.svelte';
|
||||
import { showCreate } from './store';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
|
||||
const project = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
|
||||
async function handleCreate(event: CustomEvent<Models.Collection>) {
|
||||
$showCreate = false;
|
||||
await invalidate(Dependencies.DATABASE);
|
||||
await goto(
|
||||
`${base}/console/project-${project}/databases/database-${databaseId}/collection-${event.detail.$id}`
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Database - Appwrite</title>
|
||||
</svelte:head>
|
||||
|
||||
<slot />
|
||||
|
||||
<Create bind:showCreate={$showCreate} on:created={handleCreate} />
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import SecondSideNav from '$routes/console/project-[project]/databases/database-[database]/secondSideNav.svelte';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import type { LayoutLoad } from './$types';
|
||||
import Breadcrumbs from './breadcrumbs.svelte';
|
||||
import Header from './header.svelte';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, parent, depends }) => {
|
||||
await parent();
|
||||
@@ -13,7 +15,11 @@ export const load: LayoutLoad = async ({ params, parent, depends }) => {
|
||||
return {
|
||||
header: Header,
|
||||
breadcrumbs: Breadcrumbs,
|
||||
database: await sdkForProject.databases.get(params.database)
|
||||
database: await sdkForProject.databases.get(params.database),
|
||||
secondSideNav: SecondSideNav,
|
||||
allCollections: await sdkForProject.databases.listCollections(params.database, [
|
||||
Query.orderDesc('$createdAt')
|
||||
])
|
||||
};
|
||||
} catch (e) {
|
||||
throw error(e.code, e.message);
|
||||
|
||||
+10
-22
@@ -1,38 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, Copy, GridItem1, CardContainer, Heading, Pagination } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { CardContainer, Copy, Empty, GridItem1, Heading, Pagination } from '$lib/components';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import { cardLimit } from '$lib/stores/layout';
|
||||
import { createPersistentPagination } from '$lib/stores/pagination';
|
||||
import { showCreate } from '../store';
|
||||
import type { PageData } from './$types';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import Create from '../create.svelte';
|
||||
import { CARD_LIMIT } from '$lib/constants';
|
||||
|
||||
export let data: PageData;
|
||||
let showCreate = false;
|
||||
|
||||
const project = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
const offset = createPersistentPagination($cardLimit);
|
||||
|
||||
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 u-gap-12 common-section u-main-space-between">
|
||||
<Heading tag="h2" size="5">Collections</Heading>
|
||||
|
||||
<Button on:click={() => (showCreate = true)} event="create_collection">
|
||||
<Button on:click={() => ($showCreate = true)} event="create_collection">
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create collection</span>
|
||||
</Button>
|
||||
@@ -43,7 +33,7 @@
|
||||
event="collection"
|
||||
total={data.collections.total}
|
||||
offset={$offset}
|
||||
on:click={() => (showCreate = true)}>
|
||||
on:click={() => ($showCreate = true)}>
|
||||
{#each data.collections.collections as collection}
|
||||
<GridItem1
|
||||
href={`${base}/console/project-${project}/databases/database-${databaseId}/collection-${collection.$id}`}>
|
||||
@@ -76,8 +66,6 @@
|
||||
single
|
||||
href="https://appwrite.io/docs/databases#collection"
|
||||
target="collection"
|
||||
on:click={() => (showCreate = true)} />
|
||||
on:click={() => ($showCreate = true)} />
|
||||
{/if}
|
||||
</Container>
|
||||
|
||||
<Create bind:showCreate on:created={handleCreate} />
|
||||
|
||||
+3
-1
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { goto, invalidate } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { Modal } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
@@ -25,6 +26,7 @@
|
||||
await goto(
|
||||
`${base}/console/project-${$page.params.project}/databases/database-${$page.params.database}`
|
||||
);
|
||||
invalidate(Dependencies.DATABASE);
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { showCreate } from './store';
|
||||
import type { PageData } from './[[page]]/$types';
|
||||
|
||||
$: data = $page.data as PageData;
|
||||
const project = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
|
||||
$: console.log(data);
|
||||
</script>
|
||||
|
||||
<section class="drop-section u-flex-vertical u-gap-8">
|
||||
<h5 class="eyebrow-heading-3 u-padding-block-12">Collections</h5>
|
||||
<button
|
||||
class="button is-text is-full-width u-main-start u-padding-inline-0"
|
||||
on:click={() => ($showCreate = true)}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create collection</span>
|
||||
</button>
|
||||
{#if data?.allCollections?.total}
|
||||
<ul class="drop-list">
|
||||
{#each data.allCollections.collections as collection}
|
||||
{@const href = `${base}/console/project-${project}/databases/database-${databaseId}/collection-${collection.$id}/documents`}
|
||||
<li class="drop-list-item">
|
||||
<a class="drop-button" {href}>
|
||||
<span class="text">{collection.name}</span>
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</section>
|
||||
@@ -1,5 +1,6 @@
|
||||
import { derived } from 'svelte/store';
|
||||
import { page } from '$app/stores';
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user