feat: new layout state management

This commit is contained in:
Torsten Dittmann
2022-10-19 17:39:20 +02:00
parent 309effa001
commit 29d91895be
55 changed files with 1165 additions and 666 deletions
+13 -42
View File
@@ -1,53 +1,24 @@
<script lang="ts" context="module">
export type Breadcrumb = {
title: string;
href?: string;
};
</script>
<script lang="ts">
import { breadcrumbs as breadcrumbsStore, level, type Breadcrumb } from '$lib/stores/layout';
$: breadcrumbs = [...$breadcrumbsStore]
.map(([level, value]) => ({ level, value }))
.sort((a, b) => (a.level > b.level ? 1 : -1))
.filter((n) => n.level <= $level);
function truncate(
breadcrumbs: {
value: Breadcrumb;
}[]
) {
/**
* Maximum of 4 Breadcrumbs, truncated from the left.
*/
if ($level > 4) {
breadcrumbs = [
{
value: {
href: null,
title: '...'
}
},
...breadcrumbs.slice(-3)
];
}
return breadcrumbs;
}
function buildHref(index: number) {
return breadcrumbs
.slice(0, index + 1)
.reduce((prev, next) => `${prev}/${next.value.href}`, '');
}
export let breadcrumbs: Breadcrumb[];
</script>
<nav class="breadcrumbs is-only-desktop" aria-label="breadcrumb">
<ol class="breadcrumbs-list">
{#each truncate(breadcrumbs) as breadcrumb, i}
{#each breadcrumbs as breadcrumb}
<li class="breadcrumbs-item">
{#if breadcrumb.value.href}
<a
href={buildHref(breadcrumbs.length > 4 ? i + breadcrumbs.length - 4 : i)}
title={breadcrumb.value.title}>
{breadcrumb.value.title}
{#if breadcrumb.href}
<a href={breadcrumb.href} title={breadcrumb.title}>
{breadcrumb.title}
</a>
{:else}
<span>{breadcrumb.value.title}</span>
<span>{breadcrumb.title}</span>
{/if}
</li>
{/each}
+5 -3
View File
@@ -1,16 +1,16 @@
<script lang="ts">
import { base } from '$app/paths';
import { onMount } from 'svelte';
import { Breadcrumbs } from '.';
import { Avatar, DropList, DropListItem, DropListLink } from '$lib/components';
import { app } from '$lib/stores/app';
import { sdkForConsole } from '$lib/stores/sdk';
import { user } from '$lib/stores/user';
import { organizationList, organization, newOrgModal } from '$lib/stores/organization';
import { breadcrumb } from '$lib/stores/layout';
import AppwriteLogo from '$lib/images/appwrite-gray-light.svg';
import LightMode from '$lib/images/mode/light-mode.svg';
import DarkMode from '$lib/images/mode/dark-mode.svg';
import SystemMode from '$lib/images/mode/system-mode.svg';
import { organizationList, organization, newOrgModal } from '$lib/stores/organization';
let showDropdown = false;
@@ -28,7 +28,9 @@
<img src={AppwriteLogo} width="132" height="34" alt="Appwrite" />
</a>
<Breadcrumbs />
{#if $breadcrumb}
<svelte:component this={$breadcrumb} />
{/if}
<div class="main-header-end">
<nav class="u-flex is-only-desktop">
+5 -131
View File
@@ -1,28 +1,6 @@
<script lang="ts">
import { navigating, page } from '$app/stores';
import { tabs, title, backButton, copyData, titleDropdown } from '$lib/stores/layout';
import { Cover } from '.';
import {
Copy,
DropList,
DropListItem,
DropListLink,
AvatarGroup,
Tabs,
Tab
} from '$lib/components';
import { Pill } from '$lib/elements';
import { Button } from '$lib/elements/forms';
import {
organization,
memberList,
newOrgModal,
newMemberModal
} from '$lib/stores/organization';
import { sdkForConsole } from '$lib/stores/sdk';
import { base } from '$app/paths';
import { user } from '$lib/stores/user';
import { goto } from '$app/navigation';
import { navigating } from '$app/stores';
import { header } from '$lib/stores/layout';
import { browser } from '$app/environment';
import { wizard } from '$lib/stores/wizard';
@@ -30,32 +8,11 @@
export let showSideNavigation = false;
let y: number;
let showDropdown = false;
navigating.subscribe(() => {
if (isOpen) isOpen = false;
});
let avatars = [];
let avatarsTotal = 0;
memberList.subscribe((value) => {
if (value?.total > 0) {
avatarsTotal = value.total;
avatars = value.memberships.map((team) => {
return {
name: team.userName,
img: sdkForConsole.avatars.getInitials(team.userName, 80, 80).toString()
};
});
}
});
const logout = async () => {
await user.logout();
await goto(`${base}/login`);
};
const toggleMenu = () => {
y = 0;
isOpen = !isOpen;
@@ -90,93 +47,10 @@
<slot name="side" />
</nav>
<section class="main-content">
<Cover>
<svelte:fragment slot="header">
{#if $backButton}
<a class="back-button" href={$backButton} aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
{/if}
{#if $titleDropdown?.length && $organization}
<DropList
bind:show={showDropdown}
position="bottom"
arrow={false}
scrollable={true}>
<button
class="button is-text u-padding-inline-0"
on:click={() => (showDropdown = !showDropdown)}>
<h1 class="heading-level-4">
<span class="text"> {$organization.name}</span>
{#if $header}
<svelte:component this={$header} />
{/if}
<span
class={`icon-cheveron-${showDropdown ? 'up' : 'down'}`}
aria-hidden="true" />
</h1>
</button>
<svelte:fragment slot="list">
{#each $titleDropdown as org}
<DropListLink
href={`${base}/console/organization-${org.$id}`}
on:click={() => {
showDropdown = false;
}}>
{org.name}
</DropListLink>
{/each}
</svelte:fragment>
<svelte:fragment slot="other">
<section class="drop-section">
<ul class="drop-list">
<DropListItem
icon="plus"
on:click={() => {
showDropdown = false;
newOrgModal.set(true);
}}>New Organization</DropListItem>
</ul>
</section></svelte:fragment>
</DropList>
<div class="u-margin-inline-start-auto">
<div class="u-flex u-gap-16">
<AvatarGroup size={40} {avatars} total={avatarsTotal} />
<Button secondary on:click={() => newMemberModal.set(true)}>
<span class="icon-plus" aria-hidden="true" />
<span class="text">Invite</span>
</Button>
</div>
</div>
{:else}
<h1 class="heading-level-4">
<span class="text">{$title ? $title : '-'}</span>
</h1>
{/if}
{#if $page.url.pathname.includes('/console/account')}
<div class="u-margin-inline-start-auto">
<Button secondary on:click={logout}>Logout</Button>
</div>
{/if}
{#if $copyData?.value}
<Copy value={$copyData.value}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
{$copyData.text}
</Pill>
</Copy>
{/if}
</svelte:fragment>
{#if $tabs.length}
<Tabs>
{#each $tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
{/if}
</Cover>
<slot />
</section>
</main>
+9 -59
View File
@@ -1,7 +1,5 @@
import { project } from '../../routes/console/project-[project]/store';
import { get, writable, readable } from 'svelte/store';
import type { Models } from '@aw-labs/appwrite-console';
import type { Navigation } from '@sveltejs/kit';
import { writable, readable, get } from 'svelte/store';
import type { SvelteComponent } from 'svelte';
export type Tab = {
href: string;
@@ -11,68 +9,20 @@ export type Tab = {
export type Breadcrumb = {
href: string;
title: string;
level?: number;
};
export type updateLayoutArguments = {
title: string;
titleDropdown?: Models.Team[];
level?: number;
tabs?: Tab[];
back?: string;
breadcrumbs?: Breadcrumb[] | Breadcrumb;
copy?: {
text: string;
value: string;
};
customBase?: string;
navigate?: Navigation;
header?: typeof SvelteComponent;
breadcrumb?: typeof SvelteComponent;
};
export const level = writable<number>();
export const title = writable<string>('');
export const titleDropdown = writable<Models.Team[]>([]);
export const backButton = writable<string>('');
export const tabs = writable<Tab[]>([]);
export const breadcrumbs = writable<Map<number, Breadcrumb>>(new Map());
export const copyData = writable({
text: '',
value: ''
});
export const header = writable<typeof SvelteComponent>();
export const breadcrumb = writable<typeof SvelteComponent>();
export function updateLayout(args: updateLayoutArguments) {
const projectId = get(project)?.$id;
const base = args?.customBase ?? projectId ? `/console/project-${projectId}` : ``;
if (args?.tabs) {
args.tabs.map((tab) => {
tab.href = `${base}/${tab.href}`;
});
}
if (args?.navigate?.to) {
const previousTabs = get(tabs);
if (previousTabs.some((t) => `${base}/${t.href}` === args.navigate.to.url.pathname)) {
return;
}
}
title.set(args.title);
titleDropdown.set(args.titleDropdown ?? []);
backButton.set(args.back ?? null);
copyData.set(args.copy ?? null);
level.set(args.level ?? null);
tabs.set(args.tabs ?? []);
if (args.breadcrumbs) {
if (!Array.isArray(args.breadcrumbs)) {
args.breadcrumbs = [args.breadcrumbs];
}
for (const breadcrumb of args.breadcrumbs) {
breadcrumbs.update((n) => n.set(breadcrumb.level ?? args.level, breadcrumb));
}
}
header.set(args.header ?? null);
breadcrumb.set(args.breadcrumb ?? null);
}
export const pageLimit = readable(12); // default page limit
export const cardLimit = readable(6); // default page limit
export const cardLimit = readable(6); // default card limit
+3 -14
View File
@@ -2,33 +2,22 @@
import Shell from '$lib/layout/shell.svelte';
import SideNavigation from '$lib/layout/navigation.svelte';
import Header from '$lib/layout/header.svelte';
import { updateLayout } from '$lib/stores/layout';
import {
organization,
organizationList,
newOrgModal,
redirectTo
} from '$lib/stores/organization';
import { organizationList, newOrgModal, redirectTo } from '$lib/stores/organization';
import Create from './_createOrganization.svelte';
import { page } from '$app/stores';
import { afterNavigate } from '$app/navigation';
import { onMount } from 'svelte';
import { wizard } from '$lib/stores/wizard';
updateLayout({
title: $organization?.name ?? '',
level: 0
});
onMount(async () => {
if ($page.url.pathname === '/console' && !$newOrgModal) {
await redirectTo();
return await redirectTo();
}
});
afterNavigate(async () => {
if ($page.url.pathname === '/console' && !$newOrgModal) {
await redirectTo();
return await redirectTo();
}
});
</script>
@@ -6,7 +6,6 @@
import { sdkForConsole } from '$lib/stores/sdk';
import { createEventDispatcher } from 'svelte';
import { organization, organizationList } from '$lib/stores/organization';
import { titleDropdown } from '$lib/stores/layout';
import { goto } from '$app/navigation';
export let show = false;
@@ -23,7 +22,6 @@
const team = await sdkForConsole.teams.create(id ?? 'unique()', name);
dispatch('created');
await organizationList.load();
titleDropdown.set($organizationList.teams);
organization.set(team);
await goto(`/console/organization-${$organization.$id}`);
addNotification({
@@ -3,7 +3,6 @@
import { onMount } from 'svelte';
import { afterNavigate } from '$app/navigation';
import {
organizationList,
organization,
memberList,
newOrgModal,
@@ -13,14 +12,15 @@
import Create from '../_createOrganization.svelte';
import { page } from '$app/stores';
import { Query } from '@aw-labs/appwrite-console';
import Header from './header.svelte';
import Breadcrumbs from './breadcrumbs.svelte';
$: organizationId = $page.params.organization;
$: path = `console/organization-${organizationId}`;
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
const promises = Promise.all([
organization.load(organizationId),
memberList.load(organizationId, [Query.limit($pageLimit)])
@@ -31,29 +31,8 @@
}
updateLayout({
navigate: event,
title: $organization?.name,
titleDropdown: $organizationList.teams,
level: 0,
customBase: '',
breadcrumbs: {
title: `${$organization.name}`,
href: path
},
tabs: [
{
href: path,
title: 'Projects'
},
{
href: `${path}/members`,
title: 'Members'
},
{
href: `${path}/settings`,
title: 'Settings'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
}
</script>
@@ -0,0 +1,13 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,104 @@
<script lang="ts">
import { base } from '$app/paths';
import { page } from '$app/stores';
import { AvatarGroup, DropList, DropListItem, DropListLink, Tab, Tabs } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { Cover } from '$lib/layout';
import {
memberList,
newMemberModal,
newOrgModal,
organization,
organizationList
} from '$lib/stores/organization';
import { sdkForConsole } from '$lib/stores/sdk';
let avatars = [];
let avatarsTotal = 0;
let showDropdown = false;
memberList.subscribe((value) => {
if (value?.total > 0) {
avatarsTotal = value.total;
avatars = value.memberships.map((team) => {
return {
name: team.userName,
img: sdkForConsole.avatars.getInitials(team.userName, 80, 80).toString()
};
});
}
});
$: organizationId = $page.params.organization;
$: path = `/console/organization-${organizationId}`;
$: tabs = [
{
href: path,
title: 'Projects'
},
{
href: `${path}/members`,
title: 'Members'
},
{
href: `${path}/settings`,
title: 'Settings'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<DropList bind:show={showDropdown} position="bottom" arrow={false} scrollable={true}>
<button
class="button is-text u-padding-inline-0"
on:click={() => (showDropdown = !showDropdown)}>
<h1 class="heading-level-4">
<span class="text"> {$organization.name}</span>
<span
class={`icon-cheveron-${showDropdown ? 'up' : 'down'}`}
aria-hidden="true" />
</h1>
</button>
<svelte:fragment slot="list">
{#each $organizationList.teams as org}
<DropListLink
href={`${base}/console/organization-${org.$id}`}
on:click={() => {
showDropdown = false;
}}>
{org.name}
</DropListLink>
{/each}
</svelte:fragment>
<svelte:fragment slot="other">
<section class="drop-section">
<ul class="drop-list">
<DropListItem
icon="plus"
on:click={() => {
showDropdown = false;
newOrgModal.set(true);
}}>New Organization</DropListItem>
</ul>
</section></svelte:fragment>
</DropList>
<div class="u-margin-inline-start-auto">
<div class="u-flex u-gap-16">
<AvatarGroup size={40} {avatars} total={avatarsTotal} />
<Button secondary on:click={() => newMemberModal.set(true)}>
<span class="icon-plus" aria-hidden="true" />
<span class="text">Invite</span>
</Button>
</div>
</div>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -5,7 +5,6 @@
import { addNotification } from '$lib/stores/notifications';
import { sdkForConsole } from '$lib/stores/sdk';
import { organization, memberList } from '$lib/stores/organization';
import { title, breadcrumbs } from '$lib/stores/layout';
import Delete from '../_deleteOrganization.svelte';
let name: string = $organization.name;
@@ -15,10 +14,6 @@
try {
await sdkForConsole.teams.update($organization.$id, name);
$organization.name = name;
title.set(name);
const breadcrumb = $breadcrumbs.get(0);
breadcrumb.title = name;
$breadcrumbs = $breadcrumbs.set($breadcrumbs.size, breadcrumb);
addNotification({
message: 'Name has been updated',
type: 'success'
@@ -8,7 +8,6 @@
import { organization } from '$lib/stores/organization';
import { onMount } from 'svelte';
import { afterNavigate } from '$app/navigation';
import { updateLayout } from '$lib/stores/layout';
import type { Models } from '@aw-labs/appwrite-console';
type Attributes =
@@ -48,7 +47,7 @@
afterNavigate(handle);
let loaded = false;
async function handle(event = null) {
async function handle() {
if (sdkForProject.client.config.project !== projectId) {
setProject(projectId);
}
@@ -62,23 +61,6 @@
await promiseOrganization;
}
}
updateLayout({
navigate: event,
title: $project.name,
level: 1,
breadcrumbs: [
{
href: 'console',
title: $organization.name,
level: 0
},
{
href: `project-${$project.$id}`,
title: $project.name
}
]
});
loaded = true;
}
</script>
@@ -2,48 +2,17 @@
import { afterNavigate } from '$app/navigation';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
const path = 'authentication';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
onMount(handle);
afterNavigate(handle);
let loaded = false;
function handle(event = null) {
function handle() {
updateLayout({
navigate: event,
title: 'Authentication',
level: 3,
breadcrumbs: {
title: 'Authentication',
href: path
},
tabs: [
{
href: path,
title: 'Users'
},
{
href: `${path}/teams`,
title: 'Teams'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/security`,
title: 'Security'
},
{
href: `${path}/settings`,
title: 'Settings'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
</script>
@@ -51,6 +20,4 @@
<title>Appwrite - Users</title>
</svelte:head>
{#if loaded}
<slot />
{/if}
<slot />
@@ -0,0 +1,22 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/authentication`,
title: 'Authentication'
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,46 @@
<script lang="ts">
import { page } from '$app/stores';
import { Tab, Tabs } from '$lib/components';
import { Cover } from '$lib/layout';
const projectId = $page.params.project;
const path = `/console/project-${projectId}/authentication`;
const tabs = [
{
href: path,
title: 'Users'
},
{
href: `${path}/teams`,
title: 'Teams'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/security`,
title: 'Security'
},
{
href: `${path}/settings`,
title: 'Settings'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<h1 class="heading-level-4">
<span class="text">Authentication</span>
</h1>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -1,18 +1,18 @@
<script lang="ts">
import { page } from '$app/stores';
import { base } from '$app/paths';
import { updateLayout } from '$lib/stores/layout';
import { team } from './store';
import { afterNavigate } from '$app/navigation';
import { onMount } from 'svelte';
import Header from './header.svelte';
import Breadcrumbs from './breadcrumbs.svelte';
const teamId = $page.params.team;
const path = `authentication/teams/${teamId}`;
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
const promise = team.load(teamId);
if ($team?.$id !== teamId) {
@@ -20,32 +20,8 @@
}
updateLayout({
navigate: event,
level: 4,
title: $team.name,
back: `${base}/console/project-${$page.params.project}/authentication/teams`,
breadcrumbs: {
title: $team.name,
href: `teams/${teamId}`
},
copy: {
text: 'Team ID',
value: teamId
},
tabs: [
{
href: path,
title: 'Overview'
},
{
href: `${path}/members`,
title: 'Members'
},
{
href: `${path}/activity`,
title: 'Activity'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
}
</script>
@@ -1,4 +1,5 @@
<script lang="ts">
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { Avatar, CardGrid, Box } from '$lib/components';
import { Container } from '$lib/layout';
@@ -7,9 +8,7 @@
import { toLocaleDateTime } from '$lib/helpers/date';
import { addNotification } from '$lib/stores/notifications';
import { team } from './store';
import { title, breadcrumbs } from '$lib/stores/layout';
import DeleteTeam from './_deleteTeam.svelte';
import { onMount } from 'svelte';
const getAvatar = (name: string) => sdkForProject.avatars.getInitials(name, 48, 48).toString();
@@ -24,10 +23,6 @@
try {
await sdkForProject.teams.update($page.params.team, teamName);
$team.name = teamName;
title.set(teamName);
const breadcrumb = $breadcrumbs.get($breadcrumbs.size);
breadcrumb.title = teamName;
$breadcrumbs = $breadcrumbs.set($breadcrumbs.size, breadcrumb);
addNotification({
message: 'Name has been updated',
type: 'success'
@@ -0,0 +1,27 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../../../store';
import { team } from './store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/authentication`,
title: 'Authentication'
},
{
href: `/console/project-${$project.$id}/authentication/user/${$team.$id}`,
title: $team.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,53 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy, Tab, Tabs } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { team } from './store';
const projectId = $page.params.project;
const teamId = $page.params.team;
const path = `/console/project-${projectId}/authentication/teams/${teamId}`;
const tabs = [
{
href: path,
title: 'Overview'
},
{
href: `${path}/members`,
title: 'Members'
},
{
href: `${path}/activity`,
title: 'Activity'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/authentication`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$team.name}</span>
</h1>
<Copy value={$team.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
Team ID
</Pill>
</Copy>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -1,18 +1,18 @@
<script lang="ts">
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
import { user } from './store';
const userId = $page.params.user;
const path = `authentication/user/${userId}`;
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
const promise = user.load(userId);
if ($user?.$id !== userId) {
@@ -20,36 +20,8 @@
}
updateLayout({
navigate: event,
title: $user.name,
level: 4,
breadcrumbs: {
title: $user.name,
href: `user/${userId}`
},
back: `${base}/console/project-${$page.params.project}/authentication`,
copy: {
text: 'User ID',
value: userId
},
tabs: [
{
href: path,
title: 'Overview'
},
{
href: `${path}/memberships`,
title: 'Memberships'
},
{
href: `${path}/sessions`,
title: 'Sessions'
},
{
href: `${path}/activity`,
title: 'Activity'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
}
</script>
@@ -17,7 +17,6 @@
import DeleteUser from './_deleteUser.svelte';
import { user } from './store';
import { onMount } from 'svelte';
import { title, breadcrumbs } from '$lib/stores/layout';
$: if (prefs) {
if (JSON.stringify(prefs) !== JSON.stringify(Object.entries($user.prefs))) {
@@ -108,10 +107,6 @@
try {
await sdkForProject.users.updateName($user.$id, userName);
$user.name = userName;
title.set(userName);
const breadcrumb = $breadcrumbs.get($breadcrumbs.size);
breadcrumb.title = userName;
$breadcrumbs = $breadcrumbs.set($breadcrumbs.size, breadcrumb);
addNotification({
message: 'Name has been updated',
type: 'success'
@@ -0,0 +1,27 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../../../store';
import { user } from './store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/authentication`,
title: 'Authentication'
},
{
href: `/console/project-${$project.$id}/authentication/user/${$user.$id}`,
title: $user.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,57 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy, Tab, Tabs } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { user } from './store';
const projectId = $page.params.project;
const userId = $page.params.user;
const path = `/console/project-${projectId}/authentication/user/${userId}`;
const tabs = [
{
href: path,
title: 'Overview'
},
{
href: `${path}/memberships`,
title: 'Memberships'
},
{
href: `${path}/sessions`,
title: 'Sessions'
},
{
href: `${path}/activity`,
title: 'Activity'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/authentication`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$user.name}</span>
</h1>
<Copy value={$user.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
User ID
</Pill>
</Copy>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -2,33 +2,17 @@
import { afterNavigate } from '$app/navigation';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
const path = 'databases';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
onMount(handle);
afterNavigate(handle);
let loaded = false;
function handle(event = null) {
function handle() {
updateLayout({
navigate: event,
title: 'Databases',
tabs: [
{
href: path,
title: 'Databases'
},
{
href: `${path}/usage`,
title: 'Usage'
}
],
level: 3,
breadcrumbs: {
href: 'databases',
title: 'Databases'
}
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
@@ -0,0 +1,22 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/databases`,
title: 'Databases'
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -1,19 +1,19 @@
<script>
import { onMount } from 'svelte';
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
import { breadcrumb, updateLayout } from '$lib/stores/layout';
import { database } from './store';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
const databaseId = $page.params.database;
const path = `databases/database/${databaseId}`;
let loaded = false;
onMount(handle);
afterNavigate(handle);
let loaded = false;
async function handle(event = null) {
const promise = database.load(databaseId);
if ($database?.$id !== databaseId) {
@@ -21,32 +21,8 @@
}
updateLayout({
navigate: event,
back: `${base}/console/project-${$page.params.project}/databases`,
copy: {
text: 'Database ID',
value: databaseId
},
title: $database.name,
level: 4,
breadcrumbs: {
href: `database/${databaseId}`,
title: $database.name
},
tabs: [
{
href: path,
title: 'Collections'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/settings`,
title: 'Settings'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
@@ -0,0 +1,27 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../../../store';
import { database } from './store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/databases`,
title: 'Databases'
},
{
href: `/console/project-${$project.$id}/databases/database/${$database.$id}`,
title: $database.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -1,62 +1,28 @@
<script lang="ts">
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
import { collection } from './store';
const databaseId = $page.params.database;
const collectionId = $page.params.collection;
const path = `databases/database/${databaseId}/collection/${collectionId}`;
let loaded = false;
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
if ($collection?.$id !== collectionId || !event) {
await collection.load(databaseId, collectionId);
let loaded = false;
async function handle() {
const promise = collection.load(databaseId, collectionId);
if ($collection?.$id !== collectionId) {
await promise;
}
updateLayout({
navigate: event,
title: $collection.name,
back: `${base}/console/project-${$page.params.project}/databases/database/${databaseId}`,
copy: {
text: 'Collection ID',
value: collectionId
},
level: 5,
breadcrumbs: {
href: `collection/${collectionId}`,
title: $collection.name
},
tabs: [
{
href: path,
title: 'Documents'
},
{
href: `${path}/attributes`,
title: 'Attributes'
},
{
href: `${path}/indexes`,
title: 'Indexes'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/settings`,
title: 'Settings'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
</script>
@@ -0,0 +1,26 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { project } from '../../../../../store';
import { database } from '../../store';
import { collection } from './store';
$: breadcrumbs = [
{
title: '...'
},
{
href: `/console/project-${$project.$id}/databases`,
title: 'Databases'
},
{
href: `/console/project-${$project.$id}/databases/database/${$database.$id}`,
title: $database.name
},
{
href: `/console/project-${$project.$id}/databases/database/${$database.$id}/collection/${$collection.$id}`,
title: $collection.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -4,42 +4,25 @@
import { doc } from './store';
import { onMount } from 'svelte';
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths';
import Header from './header.svelte';
import Breadcrumbs from './breadcrumbs.svelte';
const databaseId = $page.params.database;
const collectionId = $page.params.collection;
const documentId = $page.params.document;
const path = `databases/database/${databaseId}/collection/${collectionId}/document/${documentId}`;
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
const promise = doc.load(databaseId, collectionId, documentId);
if ($doc?.$id !== documentId) {
await promise;
}
updateLayout({
navigate: event,
title: 'Document',
copy: { text: 'Document ID', value: $doc.$id },
back: `${base}/console/project-${$page.params.project}/databases/database/${databaseId}/collection/${collectionId}`,
level: 6,
breadcrumbs: {
title: $doc.$id,
href: `document/${documentId}`
},
tabs: [
{
href: path,
title: 'Overview'
},
{
href: `${path}/activity`,
title: 'Activity'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
}
</script>
@@ -0,0 +1,27 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { project } from '../../../../../../../store';
import { database } from '../../../../store';
import { collection } from '../../store';
import { doc } from './store';
$: breadcrumbs = [
{
title: '...'
},
{
href: `/console/project-${$project.$id}/databases/database/${$database.$id}`,
title: $database.name
},
{
href: `/console/project-${$project.$id}/databases/database/${$database.$id}/collection/${$collection.$id}`,
title: $collection.name
},
{
href: `/console/project-${$project.$id}/databases/database/${$database.$id}/collection/${$collection.$id}/document/${$doc.$id}`,
title: $doc.$id
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,51 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy, Tab, Tabs } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { doc } from './store';
const projectId = $page.params.project;
const databaseId = $page.params.database;
const collectionId = $page.params.collection;
const documentId = $page.params.document;
const path = `/console/project-${projectId}/databases/database/${databaseId}/collection/${collectionId}/document/${documentId}`;
const tabs = [
{
href: path,
title: 'Overview'
},
{
href: `${path}/activity`,
title: 'Activity'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/databases/database/${databaseId}/collection/${collectionId}`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$doc.$id}</span>
</h1>
<Copy value={$doc.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
Document ID
</Pill>
</Copy>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -0,0 +1,62 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy, Tab, Tabs } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { collection } from './store';
const projectId = $page.params.project;
const databaseId = $page.params.database;
const collectionId = $page.params.collection;
const path = `/console/project-${projectId}/databases/database/${databaseId}/collection/${collectionId}`;
const tabs = [
{
href: path,
title: 'Documents'
},
{
href: `${path}/attributes`,
title: 'Attributes'
},
{
href: `${path}/indexes`,
title: 'Indexes'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/settings`,
title: 'Settings'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/databases/database/${databaseId}`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$collection.name}</span>
</h1>
<Copy value={$collection.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
Collection ID
</Pill>
</Copy>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -0,0 +1,53 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy, Tab, Tabs } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { database } from './store';
const projectId = $page.params.project;
const databaseId = $page.params.database;
const path = `/console/project-${projectId}/databases/database/${databaseId}`;
const tabs = [
{
href: path,
title: 'Collections'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/settings`,
title: 'Settings'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/databases`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$database.name}</span>
</h1>
<Copy value={$database.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
Database ID
</Pill>
</Copy>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -0,0 +1,34 @@
<script lang="ts">
import { page } from '$app/stores';
import { Tab, Tabs } from '$lib/components';
import { Cover } from '$lib/layout';
const projectId = $page.params.project;
const path = `/console/project-${projectId}/databases`;
const tabs = [
{
href: path,
title: 'Databases'
},
{
href: `${path}/usage`,
title: 'Usage'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<h1 class="heading-level-4">
<span class="text">Databases</span>
</h1>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -3,7 +3,6 @@
import { Container, type UsagePeriods } from '$lib/layout';
import { page } from '$app/stores';
import { browser } from '$app/environment';
import { tabs, title, backButton, copyData } from '$lib/stores/layout';
import { sdkForConsole } from '$lib/stores/sdk';
import { project } from '../store';
import { usage } from './store';
@@ -12,6 +11,9 @@
import { DropList, DropListItem } from '$lib/components';
import { BarChart, LineChart } from '$lib/charts';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
import { updateLayout } from '$lib/stores/layout';
import Header from './header.svelte';
import Breadcrumbs from './breadcrumbs.svelte';
$: projectId = $page.params.project;
$: path = `/console/project-${projectId}/overview`;
@@ -29,14 +31,9 @@
if ($usage) {
await promise;
}
title.set($project.name);
tabs.set([]);
backButton.set('');
copyData.set({
text: 'Project ID',
value: $project.$id
updateLayout({
header: Header,
breadcrumb: Breadcrumbs
});
}
@@ -0,0 +1,18 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,20 @@
<script lang="ts">
import { Copy } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { project } from '../store';
</script>
<Cover>
<svelte:fragment slot="header">
<h1 class="heading-level-4">
<span class="text">{$project.name}</span>
</h1>
<Copy value={$project.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
Project ID
</Pill>
</Copy>
</svelte:fragment>
</Cover>
@@ -1,6 +1,5 @@
<script lang="ts">
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { CardGrid, Secret } from '$lib/components';
import { Button, Form, FormList, InputText } from '$lib/elements/forms';
@@ -14,7 +13,9 @@
import { onMount } from 'svelte';
import { project } from '../../../store';
import Scopes from '../scopes.svelte';
import Breadcrumbs from './breadcrumbs.svelte';
import Delete from './delete.svelte';
import Header from './header.svelte';
import { key } from './store';
const projectId = $page.params.project;
@@ -30,7 +31,7 @@
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
await key.load(projectId, keyId);
name ??= $key.name;
@@ -39,26 +40,8 @@
scopes ??= $key.scopes;
updateLayout({
navigate: event,
back: `${base}/console/project-${$page.params.project}/overview/keys`,
title: $key.name,
level: 4,
copy: {
text: 'API Key Secret',
value: $key.secret
},
breadcrumbs: [
{
level: 3,
href: 'keys',
title: 'API Keys'
},
{
level: 4,
href: keyId,
title: $key.name
}
]
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
@@ -0,0 +1,27 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../../../store';
import { key } from './store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/overview/keys`,
title: 'API Keys'
},
{
href: `/console/project-${$project.$id}/overview/keys/${$key.$id}`,
title: $key.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,29 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { key } from './store';
const projectId = $page.params.project;
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/overview/keys`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$key.name}</span>
</h1>
<Copy value={$key.secret}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
API Key Secret
</Pill>
</Copy>
</svelte:fragment>
</Cover>
@@ -1,6 +1,5 @@
<script lang="ts">
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { CardGrid } from '$lib/components';
import { Button, Form, FormList, InputText } from '$lib/elements/forms';
@@ -22,6 +21,8 @@
import AppleMacOs from './appleMacOS.svelte';
import AppleWatchOs from './appleWatchOS.svelte';
import AppleTvos from './appleTvOS.svelte';
import Header from './header.svelte';
import Breadcrumbs from './breadcrumbs.svelte';
const projectId = $page.params.project;
const platformId = $page.params.platform;
@@ -46,7 +47,7 @@
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
if ($platform?.$id !== platformId) {
await platform.load(projectId, platformId);
}
@@ -54,22 +55,8 @@
name ??= $platform.name;
updateLayout({
navigate: event,
back: `${base}/console/project-${projectId}/overview/platforms`,
title: $platform.name,
level: 4,
breadcrumbs: [
{
level: 3,
href: 'platforms',
title: 'Platforms'
},
{
level: 4,
href: platformId,
title: $platform.name
}
]
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
@@ -0,0 +1,27 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../../../store';
import { platform } from './store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/overview/platforms`,
title: 'Platforms'
},
{
href: `/console/project-${$project.$id}/overview/platforms/${$platform.$id}`,
title: $platform.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,21 @@
<script lang="ts">
import { page } from '$app/stores';
import { Cover } from '$lib/layout';
import { platform } from './store';
const projectId = $page.params.project;
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/overview/platforms`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$platform.name}</span>
</h1>
</svelte:fragment>
</Cover>
@@ -2,6 +2,8 @@
import { afterNavigate } from '$app/navigation';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
const path = 'settings';
@@ -10,27 +12,8 @@
function handle(event = null) {
updateLayout({
navigate: event,
title: 'Settings',
level: 3,
breadcrumbs: {
title: 'Settings',
href: 'settings'
},
tabs: [
{
href: path,
title: 'Overview'
},
{
href: `${path}/services`,
title: 'Services'
},
{
href: `${path}/domains`,
title: 'Custom Domains'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
}
</script>
@@ -0,0 +1,22 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/settings`,
title: 'Settings'
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,38 @@
<script lang="ts">
import { page } from '$app/stores';
import { Tab, Tabs } from '$lib/components';
import { Cover } from '$lib/layout';
const projectId = $page.params.project;
const path = `/console/project-${projectId}/settings`;
const tabs = [
{
href: path,
title: 'Overview'
},
{
href: `${path}/services`,
title: 'Services'
},
{
href: `${path}/domains`,
title: 'Custom Domains'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<h1 class="heading-level-4">
<span class="text">Settings</span>
</h1>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -2,33 +2,18 @@
import { afterNavigate } from '$app/navigation';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
const path = 'storage';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
onMount(handle);
afterNavigate(handle);
let loaded = false;
async function handle(event = null) {
async function handle() {
updateLayout({
navigate: event,
title: 'Storage',
level: 3,
breadcrumbs: {
title: 'Storage',
href: 'storage'
},
tabs: [
{
href: path,
title: 'Buckets'
},
{
href: `${path}/usage`,
title: 'Usage'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
@@ -0,0 +1,22 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/storage`,
title: 'Storage'
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -1,55 +1,30 @@
<script lang="ts">
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
import { bucket } from './store';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
const projectId = $page.params.project;
const bucketId = $page.params.bucket;
const path = `storage/bucket/${bucketId}`;
let loaded = false;
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
const promise = bucket.load(bucketId);
if ($bucket?.$id !== bucketId) {
await promise;
}
updateLayout({
navigate: event,
title: $bucket.name,
level: 4,
breadcrumbs: {
title: $bucket.name,
href: `storage/bucket/${bucketId}`
},
copy: {
text: 'Bucket ID',
value: bucketId
},
back: `${base}/console/project-${projectId}/storage`,
tabs: [
{
href: path,
title: 'Files'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/settings`,
title: 'Settings'
}
]
header: Header,
breadcrumb: Breadcrumbs
});
loaded = true;
}
</script>
@@ -0,0 +1,27 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../../../store';
import { bucket } from './store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/storage`,
title: 'Storage'
},
{
href: `/console/project-${$project.$id}/storage/bucket/${$bucket.$id}`,
title: $bucket.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -1,10 +1,11 @@
<script lang="ts">
import { afterNavigate } from '$app/navigation';
import { page } from '$app/stores';
import { base } from '$app/paths';
import { file } from './store';
import { updateLayout } from '$lib/stores/layout';
import { onMount } from 'svelte';
import Header from './header.svelte';
import Breadcrumbs from './breadcrumbs.svelte';
const bucketId = $page.params.bucket;
const fileId = $page.params.file;
@@ -12,26 +13,15 @@
onMount(handle);
afterNavigate(handle);
async function handle(event = null) {
async function handle() {
const promise = file.load(bucketId, fileId);
if ($file?.$id !== fileId) {
await promise;
}
updateLayout({
navigate: event,
level: 5,
breadcrumbs: {
href: `file/${fileId}`,
title: $file.name
},
back: `${base}/console/project-${$page.params.project}/storage/bucket/${bucketId}`,
title: $file.name,
copy: {
text: 'File ID',
value: fileId
},
tabs: []
header: Header,
breadcrumb: Breadcrumbs
});
}
</script>
@@ -0,0 +1,26 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { project } from '../../../../../store';
import { bucket } from '../../store';
import { file } from './store';
$: breadcrumbs = [
{
title: '...'
},
{
href: `/console/project-${$project.$id}/storage`,
title: 'Storage'
},
{
href: `/console/project-${$project.$id}/storage/bucket/${$bucket.$id}`,
title: $bucket.name
},
{
href: `/console/project-${$project.$id}/storage/bucket/${$bucket.$id}/file/${$file.$id}`,
title: $file.name
}
];
</script>
<Breadcrumbs {breadcrumbs} />
@@ -0,0 +1,30 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { file } from './store';
const projectId = $page.params.project;
const bucketId = $page.params.bucket;
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/storage/bucket/${bucketId}`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$file.name}</span>
</h1>
<Copy value={$file.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
File ID
</Pill>
</Copy>
</svelte:fragment>
</Cover>
@@ -0,0 +1,53 @@
<script lang="ts">
import { page } from '$app/stores';
import { Copy, Tab, Tabs } from '$lib/components';
import { Pill } from '$lib/elements';
import { Cover } from '$lib/layout';
import { bucket } from './store';
const projectId = $page.params.project;
const bucketId = $page.params.bucket;
const path = `/console/project-${projectId}/storage/bucket/${bucketId}`;
const tabs = [
{
href: path,
title: 'Files'
},
{
href: `${path}/usage`,
title: 'Usage'
},
{
href: `${path}/settings`,
title: 'Settings'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<a
class="back-button"
href={`/console/project-${projectId}/storage`}
aria-label="page back">
<span class="icon-cheveron-left" aria-hidden="true" />
</a>
<h1 class="heading-level-4">
<span class="text">{$bucket.name}</span>
</h1>
<Copy value={$bucket.$id}>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
Bucket ID
</Pill>
</Copy>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>
@@ -0,0 +1,34 @@
<script lang="ts">
import { page } from '$app/stores';
import { Tab, Tabs } from '$lib/components';
import { Cover } from '$lib/layout';
const projectId = $page.params.project;
const path = `/console/project-${projectId}/storage`;
const tabs = [
{
href: path,
title: 'Buckets'
},
{
href: `${path}/usage`,
title: 'Usage'
}
];
</script>
<Cover>
<svelte:fragment slot="header">
<h1 class="heading-level-4">
<span class="text">Storage</span>
</h1>
</svelte:fragment>
<Tabs>
{#each tabs as tab}
<Tab href={tab.href} selected={$page.url.pathname === tab.href}>
{tab.title}
</Tab>
{/each}
</Tabs>
</Cover>