mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
feat: create sibling route for organizations
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
export let icon: string = null;
|
||||
</script>
|
||||
|
||||
<li class="drop-list-item">
|
||||
<li class="drop-list-item" on:click>
|
||||
<a {href} class="drop-button">
|
||||
<span class="text"><slot /></span>
|
||||
{#if icon}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<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';
|
||||
@@ -9,9 +10,11 @@
|
||||
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 '../../routes/console/store';
|
||||
import { onMount } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import {
|
||||
organizationList,
|
||||
organization,
|
||||
newOrgModal
|
||||
} from '../../routes/console/organization-[organization]/store';
|
||||
|
||||
let showDropdown = false;
|
||||
|
||||
@@ -23,7 +26,9 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<a class="logo" href={`${base}/console`}>
|
||||
<a
|
||||
class="logo"
|
||||
href={$organization ? `${base}/console/organization-${$organization.$id}` : `${base}/console`}>
|
||||
<img src={AppwriteLogo} width="132" height="34" alt="Appwrite" />
|
||||
</a>
|
||||
|
||||
@@ -67,12 +72,11 @@
|
||||
</button>
|
||||
<svelte:fragment slot="list">
|
||||
{#each $organizationList.teams as org}
|
||||
<DropListItem
|
||||
<DropListLink
|
||||
href={`${base}/console/organization-${org.$id}`}
|
||||
on:click={() => {
|
||||
showDropdown = false;
|
||||
goto(`/console`);
|
||||
organization.set(org);
|
||||
}}>{org.name}</DropListItem>
|
||||
}}>{org.name}</DropListLink>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="other">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { navigating, page } from '$app/stores';
|
||||
import { tabs, title, backButton, copyData, titleDropdown } from '$lib/stores/layout';
|
||||
import { Cover } from '.';
|
||||
import { Copy, DropList, DropListItem, AvatarGroup } from '$lib/components';
|
||||
import { Copy, DropList, DropListItem, DropListLink, AvatarGroup } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
@@ -10,8 +10,9 @@
|
||||
memberList,
|
||||
newOrgModal,
|
||||
newMemberModal
|
||||
} from '../../routes/console/store';
|
||||
} from '../../routes/console/organization-[organization]/store';
|
||||
import { sdkForConsole } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export let isOpen = false;
|
||||
export let showSideNavigation = false;
|
||||
@@ -123,15 +124,13 @@
|
||||
</button>
|
||||
<svelte:fragment slot="list">
|
||||
{#each $titleDropdown as org}
|
||||
<DropListItem
|
||||
<DropListLink
|
||||
href={`${base}/console/organization-${org.$id}`}
|
||||
on:click={() => {
|
||||
showDropdown = false;
|
||||
if (org.$id !== $organization.$id) {
|
||||
organization.load(org.$id);
|
||||
}
|
||||
}}>
|
||||
{org.name}
|
||||
</DropListItem>
|
||||
</DropListLink>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="other">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { collection } from './databases/database/[database]/collection/[collection]/store';
|
||||
import { UploadBox } from '$lib/components';
|
||||
import { project } from './store';
|
||||
import { organization } from '../store';
|
||||
import { organization } from '../organization-[organization]/store';
|
||||
import { onMount } from 'svelte';
|
||||
import { afterNavigate } from '$app/navigation';
|
||||
import { updateLayout } from '$lib/stores/layout';
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Shell from '$lib/layout/shell.svelte';
|
||||
import Header from '$lib/layout/header.svelte';
|
||||
import { updateLayout } from '$lib/stores/layout';
|
||||
import { onMount } from 'svelte';
|
||||
import { afterNavigate } from '$app/navigation';
|
||||
import {
|
||||
organizationList,
|
||||
organization,
|
||||
memberList,
|
||||
newOrgModal,
|
||||
newMemberModal
|
||||
} from './store';
|
||||
import CreateMember from './_createMember.svelte';
|
||||
import Create from './_createOrganization.svelte';
|
||||
|
||||
onMount(handle);
|
||||
afterNavigate(handle);
|
||||
|
||||
async function handle(event = null) {
|
||||
await organizationList.load();
|
||||
if ($organizationList?.total) {
|
||||
if (!$organization) {
|
||||
await organization.load($organizationList.teams[0].$id);
|
||||
await memberList.load($organization.$id, '', 100, 0);
|
||||
}
|
||||
updateLayout({
|
||||
navigate: event,
|
||||
title: $organization?.name ?? `${$organizationList.teams[0].name}`,
|
||||
titleDropdown: $organizationList.teams,
|
||||
level: 0,
|
||||
customBase: '',
|
||||
breadcrumbs: {
|
||||
title: `${$organization.name}`,
|
||||
href: 'console'
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
href: 'console',
|
||||
title: 'Projects'
|
||||
},
|
||||
{
|
||||
href: 'console/members',
|
||||
title: 'Members'
|
||||
},
|
||||
{
|
||||
href: 'console/settings',
|
||||
title: 'Settings'
|
||||
}
|
||||
]
|
||||
});
|
||||
} else {
|
||||
$newOrgModal = true;
|
||||
closable = false;
|
||||
}
|
||||
}
|
||||
|
||||
let closable = true;
|
||||
|
||||
organization.subscribe((org) => {
|
||||
handle();
|
||||
if (org?.$id) {
|
||||
memberList.load(org.$id, '', 100, 0);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Appwrite - Console</title>
|
||||
</svelte:head>
|
||||
|
||||
<Shell>
|
||||
<svelte:fragment slot="header">
|
||||
<Header />
|
||||
</svelte:fragment>
|
||||
{#if $organization}
|
||||
<slot />
|
||||
{/if}
|
||||
<footer class="main-footer" />
|
||||
</Shell>
|
||||
|
||||
<Create bind:show={$newOrgModal} {closable} />
|
||||
<CreateMember bind:showCreate={$newMemberModal} />
|
||||
@@ -3,26 +3,64 @@
|
||||
import SideNavigation from '$lib/layout/navigation.svelte';
|
||||
import Header from '$lib/layout/header.svelte';
|
||||
import { updateLayout } from '$lib/stores/layout';
|
||||
import { organization, newOrgModal } from './store';
|
||||
import {
|
||||
organization,
|
||||
organizationList,
|
||||
newOrgModal
|
||||
} from './organization-[organization]/store';
|
||||
import Create from './_createOrganization.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { afterNavigate, goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let closable = true;
|
||||
|
||||
updateLayout({
|
||||
title: $organization.name ?? 'Projects',
|
||||
title: $organization?.name ?? 'Projects',
|
||||
level: 0
|
||||
});
|
||||
|
||||
onMount(async () => {
|
||||
if ($page.url.pathname === '/console') {
|
||||
await pageLoad();
|
||||
}
|
||||
});
|
||||
|
||||
afterNavigate(async () => {
|
||||
if ($page.url.pathname === '/console') {
|
||||
await pageLoad();
|
||||
}
|
||||
});
|
||||
|
||||
const pageLoad = async () => {
|
||||
if (!$organization) {
|
||||
await organizationList.load();
|
||||
if ($organizationList?.total) {
|
||||
await organization.load($organizationList.teams[0].$id);
|
||||
await goto(`/console/organization-${$organization.$id}`);
|
||||
} else {
|
||||
closable = false;
|
||||
newOrgModal.set(true);
|
||||
}
|
||||
} else {
|
||||
await goto(`/console/organization-${$organization.$id}`);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<Shell showSideNavigation>
|
||||
<Shell showSideNavigation={!$page?.params.organization}>
|
||||
<svelte:fragment slot="header">
|
||||
<Header />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="side">
|
||||
<SideNavigation />
|
||||
{#if !$page?.params.organization}
|
||||
<SideNavigation />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<slot />
|
||||
<footer class="main-footer" />
|
||||
</Shell>
|
||||
|
||||
{#if $newOrgModal}
|
||||
<Create bind:show={$newOrgModal} />
|
||||
<Create bind:show={$newOrgModal} {closable} />
|
||||
{/if}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdkForConsole } from '$lib/stores/sdk';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { organization, organizationList } from './store';
|
||||
import { organization, organizationList } from './organization-[organization]/store';
|
||||
import { titleDropdown } from '$lib/stores/layout';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<p>loading</p>
|
||||
@@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
import { updateLayout } from '$lib/stores/layout';
|
||||
import { onMount } from 'svelte';
|
||||
import { afterNavigate } from '$app/navigation';
|
||||
import {
|
||||
organizationList,
|
||||
organization,
|
||||
memberList,
|
||||
newOrgModal,
|
||||
newMemberModal
|
||||
} from './store';
|
||||
import CreateMember from './_createMember.svelte';
|
||||
import Create from '../_createOrganization.svelte';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
$: org = $page.params.organization;
|
||||
$: path = `console/organization-${org}`;
|
||||
|
||||
onMount(handle);
|
||||
afterNavigate(handle);
|
||||
|
||||
async function handle(event = null) {
|
||||
if ($organization.$id !== org) {
|
||||
await organization.load(org);
|
||||
await memberList.load(org, '', 100, 0);
|
||||
}
|
||||
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'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Appwrite - Console</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if $organization}
|
||||
<slot />
|
||||
{/if}
|
||||
|
||||
<Create bind:show={$newOrgModal} />
|
||||
<CreateMember bind:showCreate={$newMemberModal} />
|
||||
+9
-16
@@ -6,22 +6,22 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import CreateOrganization from './_createOrganization.svelte';
|
||||
import CreateOrganization from '../_createOrganization.svelte';
|
||||
import CreateProject from './_createProject.svelte';
|
||||
import { organization, projectList } from './store';
|
||||
import { projectList } from './store';
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
let projects: Models.Project[] = [];
|
||||
$: org = $page.params.organization;
|
||||
|
||||
onMount(async () => {
|
||||
await projectList.load();
|
||||
|
||||
projects = $projectList.projects.filter((n) => n.teamId === $organization.$id);
|
||||
projects = $projectList?.projects.filter((n) => n.teamId === org);
|
||||
});
|
||||
|
||||
let showCreate = false;
|
||||
let addOrganization = false;
|
||||
let currentOrganization = $organization?.$id;
|
||||
let offset = 0;
|
||||
const limit = 5;
|
||||
|
||||
@@ -53,11 +53,7 @@
|
||||
return { name, icon };
|
||||
};
|
||||
|
||||
$: if (currentOrganization !== $organization?.$id) {
|
||||
currentOrganization = $organization.$id;
|
||||
projectList.load();
|
||||
projects = $projectList.projects.filter((a) => a.teamId === $organization.$id);
|
||||
}
|
||||
$: projects = $projectList?.projects.filter((a) => a.teamId === org);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -136,15 +132,12 @@
|
||||
</div>
|
||||
</Empty>
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {projects.length}</p>
|
||||
<Pagination {limit} bind:offset sum={projects.length} />
|
||||
<p class="text">Total results: {projects?.length}</p>
|
||||
<Pagination {limit} bind:offset sum={projects?.length} />
|
||||
</div>
|
||||
{/if}
|
||||
</Container>
|
||||
|
||||
<CreateOrganization bind:show={addOrganization} />
|
||||
|
||||
<CreateProject
|
||||
bind:show={showCreate}
|
||||
bind:teamId={currentOrganization}
|
||||
on:created={projectCreated} />
|
||||
<CreateProject bind:show={showCreate} teamId={org} on:created={projectCreated} />
|
||||
@@ -0,0 +1,84 @@
|
||||
import { sdkForConsole } from '$lib/stores/sdk';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { writable } from 'svelte/store';
|
||||
import { browser } from '$app/env';
|
||||
|
||||
function createOrganizationList() {
|
||||
const { subscribe, set } = writable<Models.TeamList>(
|
||||
browser ? JSON.parse(sessionStorage.getItem('organizationList')) : null
|
||||
);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set,
|
||||
load: async () => {
|
||||
const response = await sdkForConsole.teams.list();
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
}
|
||||
function createOrganization() {
|
||||
const { subscribe, set } = writable<Models.Team>(
|
||||
browser ? JSON.parse(sessionStorage.getItem('organization')) : null
|
||||
);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set,
|
||||
load: async (teamId: string) => {
|
||||
const response = await sdkForConsole.teams.get(teamId);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createProjectList() {
|
||||
const { subscribe, set } = writable<Models.ProjectList>(
|
||||
browser ? JSON.parse(sessionStorage.getItem('projectList')) : null
|
||||
);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set,
|
||||
load: async () => {
|
||||
const response = await sdkForConsole.projects.list();
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createMemberList() {
|
||||
const { subscribe, set } = writable<Models.MembershipList>(
|
||||
browser ? JSON.parse(sessionStorage.getItem('memberList')) : null
|
||||
);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set,
|
||||
load: async (teamId: string, search: string, limit: number, offset: number) => {
|
||||
const response = await sdkForConsole.teams.getMemberships(
|
||||
teamId,
|
||||
search,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const organizationList = createOrganizationList();
|
||||
export const organization = createOrganization();
|
||||
export const projectList = createProjectList();
|
||||
export const memberList = createMemberList();
|
||||
export const newOrgModal = writable<boolean>(false);
|
||||
export const newMemberModal = writable<boolean>(false);
|
||||
|
||||
if (browser) {
|
||||
organizationList.subscribe((n) =>
|
||||
sessionStorage?.setItem('organizationList', JSON.stringify(n ?? ''))
|
||||
);
|
||||
organization.subscribe((n) => sessionStorage?.setItem('organization', JSON.stringify(n ?? '')));
|
||||
projectList.subscribe((n) => sessionStorage?.setItem('projectList', JSON.stringify(n ?? '')));
|
||||
memberList.subscribe((n) => sessionStorage?.setItem('memberList', JSON.stringify(n ?? '')));
|
||||
}
|
||||
Reference in New Issue
Block a user