+
+
-
-
- {#if more}
-
- +{more}
-
- {/if}
+
+
+
+
+ {#if more}
+
+ +{more}
+
+ {/if}
+
+
+
-
diff --git a/src/lib/components/modal.svelte b/src/lib/components/modal.svelte
index 05da1e24f..8a85e526b 100644
--- a/src/lib/components/modal.svelte
+++ b/src/lib/components/modal.svelte
@@ -10,6 +10,7 @@
export let error: string = null;
export let closable = true;
+ let alert: HTMLElement;
const dispatch = createEventDispatcher();
const transitionFly: FlyParams = {
duration: 150,
@@ -48,6 +49,10 @@
document.body.classList.remove('u-overflow-hidden');
}
}
+
+ $: if (error) {
+ alert?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' });
+ }
@@ -81,14 +86,16 @@
{#if error}
-
{
- error = null;
- }}>
- {error}
-
+
+
{
+ error = null;
+ }}>
+ {error}
+
+
{/if}
diff --git a/src/lib/elements/forms/index.ts b/src/lib/elements/forms/index.ts
index 48988a2fe..7ed7d656f 100644
--- a/src/lib/elements/forms/index.ts
+++ b/src/lib/elements/forms/index.ts
@@ -15,5 +15,6 @@ export { default as InputSearch } from './inputSearch.svelte';
export { default as InputRadio } from './inputRadio.svelte';
export { default as InputSelect } from './inputSelect.svelte';
export { default as InputCheckbox } from './inputCheckbox.svelte';
+export { default as InputChoice } from './inputChoice.svelte';
export { default as InputPhone } from './inputPhone.svelte';
export { default as Helper } from './helper.svelte';
diff --git a/src/lib/elements/forms/inputChoice.svelte b/src/lib/elements/forms/inputChoice.svelte
new file mode 100644
index 000000000..be04a386a
--- /dev/null
+++ b/src/lib/elements/forms/inputChoice.svelte
@@ -0,0 +1,30 @@
+
+
+
+
+
diff --git a/src/lib/elements/table/cellText.svelte b/src/lib/elements/table/cellText.svelte
index a8a00db42..ca995e627 100644
--- a/src/lib/elements/table/cellText.svelte
+++ b/src/lib/elements/table/cellText.svelte
@@ -1,8 +1,9 @@
-
+
diff --git a/src/lib/helpers/cache.ts b/src/lib/helpers/cache.ts
new file mode 100644
index 000000000..770af75f6
--- /dev/null
+++ b/src/lib/helpers/cache.ts
@@ -0,0 +1,20 @@
+import { browser } from '$app/env';
+import { writable, type Writable } from 'svelte/store';
+
+export function cachedStore
>(
+ id: string,
+ callback: (store: Writable) => TMethods
+): TMethods & Writable {
+ const store = writable(browser ? JSON.parse(sessionStorage.getItem(id)) : null);
+
+ if (browser) {
+ store.subscribe((n) => sessionStorage?.setItem(id, JSON.stringify(n ?? '')));
+ }
+
+ return {
+ subscribe: store.subscribe,
+ set: store.set,
+ update: store.update,
+ ...callback(store)
+ };
+}
diff --git a/src/lib/layout/header.svelte b/src/lib/layout/header.svelte
index bd0dfc233..b4d0dabff 100644
--- a/src/lib/layout/header.svelte
+++ b/src/lib/layout/header.svelte
@@ -86,7 +86,9 @@
showDropdown = false;
newOrgModal.set(true);
}}>New organization
- Your Account
+ (showDropdown = false)}>Your Account
diff --git a/src/lib/layout/notifications.svelte b/src/lib/layout/notifications.svelte
index 7b019f930..202702799 100644
--- a/src/lib/layout/notifications.svelte
+++ b/src/lib/layout/notifications.svelte
@@ -4,8 +4,8 @@
{#if $notifications}
-
-
+
+
{#each $notifications as notification (notification.id)}
{
+ await user.logout();
+ await goto(`${base}/login`);
+ };
+
const onScroll = () => {
if (!tabsList) {
return;
@@ -77,9 +86,21 @@
}
};
};
+
+ const toggleMenu = () => {
+ y = 0;
+ isOpen = !isOpen;
+ if (browser) {
+ if (isOpen) {
+ document.body.classList.add('u-overflow-hidden');
+ } else {
+ document.body.classList.remove('u-overflow-hidden');
+ }
+ }
+ };
-
+
@@ -159,6 +181,12 @@
{$title}
{/if}
+ {#if $page.url.pathname.includes('/console/account')}
+
+
+
+ {/if}
+
{#if $copyData?.value}
diff --git a/src/lib/layout/unauthenticated.svelte b/src/lib/layout/unauthenticated.svelte
index 564fe2567..18a634b3f 100644
--- a/src/lib/layout/unauthenticated.svelte
+++ b/src/lib/layout/unauthenticated.svelte
@@ -3,6 +3,7 @@
import LoginLight from '$lib/images/login/login-light-mode.svg';
import LoginDark from '$lib/images/login/login-dark-mode.svg';
import { app } from '$lib/stores/app';
+ import { base } from '$app/paths';
const technologies = [
'js',
@@ -31,8 +32,9 @@
+
{#if $app.themeInUse === 'dark'}

@@ -43,16 +45,18 @@
+
Integrate with your favourite technologies
+ class="u-flex u-main-center u-flex-wrap u-gap-16 u-margin-block-start-32 u-line-height-1 u-opacity-0-5">
{#each technologies as tech}
-
-
@@ -62,7 +66,7 @@
-
+
diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts
index b6ce64a42..fa0cee9a7 100644
--- a/src/lib/stores/organization.ts
+++ b/src/lib/stores/organization.ts
@@ -1,52 +1,50 @@
import { sdkForConsole } from '$lib/stores/sdk';
import type { Models } from '@aw-labs/appwrite-console';
import { writable } from 'svelte/store';
-import { browser } from '$app/env';
import { get } from 'svelte/store';
import { base } from '$app/paths';
import { goto } from '$app/navigation';
+import { cachedStore } from '$lib/helpers/cache';
-function createOrganizationList() {
- const { subscribe, set } = writable
(
- browser ? JSON.parse(sessionStorage.getItem('organizationList')) : null
- );
+export const newOrgModal = writable(false);
+export const newMemberModal = writable(false);
+export const organizationList = cachedStore<
+ Models.TeamList,
+ {
+ load: () => Promise;
+ }
+>('organizationList', function ({ set }) {
return {
- subscribe,
- set,
load: async () => {
const response = await sdkForConsole.teams.list();
set(response);
}
};
-}
-function createOrganization() {
- const { subscribe, set } = writable(
- browser ? JSON.parse(sessionStorage.getItem('organization')) : null
- );
+});
+export const organization = cachedStore<
+ Models.Team,
+ {
+ load: (teamId: string) => Promise;
+ }
+>('organization', function ({ set }) {
return {
- subscribe,
- set,
- load: async (teamId: string) => {
+ load: async (teamId) => {
const response = await sdkForConsole.teams.get(teamId);
set(response);
- },
- deleteCache: () => {
- sessionStorage.removeItem('organization');
}
};
-}
-
-function createProjectList() {
- const { subscribe, set } = writable(
- browser ? JSON.parse(sessionStorage.getItem('projectList')) : null
- );
+});
+export const projectList = cachedStore<
+ Models.ProjectList,
+ {
+ load: (search: string, limit: number, offset: number) => Promise;
+ }
+>('projectList', function ({ set }) {
return {
- subscribe,
- set,
- load: async (search: string, limit: number, offset: number) => {
+ load: async (search, limit, offset) => {
const response = await sdkForConsole.projects.list(
search,
limit,
@@ -58,17 +56,16 @@ function createProjectList() {
set(response);
}
};
-}
-
-function createMemberList() {
- const { subscribe, set } = writable(
- browser ? JSON.parse(sessionStorage.getItem('memberList')) : null
- );
+});
+export const memberList = cachedStore<
+ Models.MembershipList,
+ {
+ load: (teamId: string, search: string, limit: number, offset: number) => Promise;
+ }
+>('memberList', function ({ set }) {
return {
- subscribe,
- set,
- load: async (teamId: string, search: string, limit: number, offset: number) => {
+ load: async (teamId, search, limit, offset) => {
const response = await sdkForConsole.teams.getMemberships(
teamId,
search,
@@ -78,23 +75,7 @@ function createMemberList() {
set(response);
}
};
-}
-
-export const organizationList = createOrganizationList();
-export const organization = createOrganization();
-export const projectList = createProjectList();
-export const memberList = createMemberList();
-export const newOrgModal = writable(false);
-export const newMemberModal = writable(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 ?? '')));
-}
+});
export const redirectTo = async () => {
let org = get(organization);
diff --git a/src/lib/stores/project-services.ts b/src/lib/stores/project-services.ts
new file mode 100644
index 000000000..6f4a8cb0d
--- /dev/null
+++ b/src/lib/stores/project-services.ts
@@ -0,0 +1,117 @@
+import { writable } from 'svelte/store';
+import type { Models } from '@aw-labs/appwrite-console';
+
+export type Service = {
+ label: string;
+ method: string;
+ value: boolean | null;
+};
+
+function createServices() {
+ const { subscribe, set } = writable({
+ list: [
+ {
+ label: 'Account',
+ method: 'account',
+ value: null
+ },
+ {
+ label: 'Avatars',
+ method: 'avatars',
+ value: null
+ },
+ {
+ label: 'Databases',
+ method: 'databases',
+ value: null
+ },
+ {
+ label: 'Functions',
+ method: 'functions',
+ value: null
+ },
+ {
+ label: 'Health',
+ method: 'health',
+ value: null
+ },
+ {
+ label: 'Locale',
+ method: 'locale',
+ value: null
+ },
+ {
+ label: 'Storage',
+ method: 'storage',
+ value: null
+ },
+ {
+ label: 'Teams',
+ method: 'teams',
+ value: null
+ },
+ {
+ label: 'Users',
+ method: 'users',
+ value: null
+ }
+ ]
+ });
+
+ return {
+ subscribe,
+ set,
+ load: (project: Models.Project) => {
+ const list = [
+ {
+ label: 'Account',
+ method: 'account',
+ value: project.serviceStatusForAccount
+ },
+ {
+ label: 'Avatars',
+ method: 'avatars',
+ value: project.serviceStatusForAvatars
+ },
+ {
+ label: 'Databases',
+ method: 'databases',
+ value: project.serviceStatusForDatabases
+ },
+ {
+ label: 'Functions',
+ method: 'functions',
+ value: project.serviceStatusForFunctions
+ },
+ {
+ label: 'Health',
+ method: 'health',
+ value: project.serviceStatusForHealth
+ },
+ {
+ label: 'Locale',
+ method: 'locale',
+ value: project.serviceStatusForLocale
+ },
+ {
+ label: 'Storage',
+ method: 'storage',
+ value: project.serviceStatusForStorage
+ },
+ {
+ label: 'Teams',
+ method: 'teams',
+ value: project.serviceStatusForTeams
+ },
+ {
+ label: 'Users',
+ method: 'users',
+ value: project.serviceStatusForUsers
+ }
+ ];
+ set({ list });
+ }
+ };
+}
+
+export const services = createServices();
diff --git a/src/lib/stores/user.ts b/src/lib/stores/user.ts
index fe9993066..12a84121b 100644
--- a/src/lib/stores/user.ts
+++ b/src/lib/stores/user.ts
@@ -10,6 +10,9 @@ function createUserStore() {
set,
fetchUser: async () => {
set(await sdkForConsole.account.get());
+ },
+ logout: async () => {
+ await sdkForConsole.account.deleteSession('current');
}
};
}
diff --git a/src/routes/__layout.svelte b/src/routes/__layout.svelte
index 71975c517..2b2f30128 100644
--- a/src/routes/__layout.svelte
+++ b/src/routes/__layout.svelte
@@ -23,6 +23,8 @@
window.GOOGLE_ANALYTICS = import.meta.env.VITE_GOOGLE_ANALYTICS?.toString() ?? false;
}
+ const acceptedRoutes = ['/login', '/register', '/recover', '/invite'];
+
onMount(async () => {
try {
if (!$user) {
@@ -33,7 +35,9 @@
await redirectTo();
}
} catch (error) {
- await goto(`${base}/login`);
+ if (acceptedRoutes.includes($page.url.pathname)) {
+ await goto(`${base}${$page.url.pathname}${$page.url.search}`);
+ } else await goto(`${base}/login`);
} finally {
loaded = true;
}
diff --git a/src/routes/console/$me.svelte b/src/routes/console/$me.svelte
deleted file mode 100644
index 732f4edb7..000000000
--- a/src/routes/console/$me.svelte
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-hey
-
-
diff --git a/src/routes/console/__layout.svelte b/src/routes/console/__layout.svelte
index 19f720775..d31f50a6b 100644
--- a/src/routes/console/__layout.svelte
+++ b/src/routes/console/__layout.svelte
@@ -36,7 +36,10 @@
Appwrite - Console
-
+
@@ -47,4 +50,6 @@
-
+{#if $newOrgModal}
+
+{/if}
diff --git a/src/routes/console/account/__layout.svelte b/src/routes/console/account/__layout.svelte
new file mode 100644
index 000000000..d6b6d2ab4
--- /dev/null
+++ b/src/routes/console/account/__layout.svelte
@@ -0,0 +1,51 @@
+
+
+
+ Appwrite - User
+
+
+
diff --git a/src/routes/console/account/_delete.svelte b/src/routes/console/account/_delete.svelte
new file mode 100644
index 000000000..f64b36636
--- /dev/null
+++ b/src/routes/console/account/_delete.svelte
@@ -0,0 +1,36 @@
+
+
+
diff --git a/src/routes/console/account/activity.svelte b/src/routes/console/account/activity.svelte
new file mode 100644
index 000000000..1fee31deb
--- /dev/null
+++ b/src/routes/console/account/activity.svelte
@@ -0,0 +1,108 @@
+
+
+
+ {#if $accountActivity?.total}
+
+
+ Date
+ Event
+ Client
+ Location
+ IP
+
+
+ {#each $accountActivity.logs as log}
+
+ {toLocaleDateTime(log.time)}
+ {log.event}
+
+
+ {#if log.clientName}
+
+
+
.toString()})
+
+
+ {log.clientName}
+ {log.clientVersion}
+ on {log.osName}
+ {log.osVersion}
+
+
+ {:else}
+
+ {/if}
+
+
+
+ {#if log.countryCode !== '--'}
+ {log.countryName}
+ {:else}
+ Unknown
+ {/if}
+
+ {log.ip}
+
+ {/each}
+
+
+ {:else}
+
+
+
+ {/if}
+
+
Total results: {$accountActivity?.total}
+
+
+
diff --git a/src/routes/console/account/index.svelte b/src/routes/console/account/index.svelte
new file mode 100644
index 000000000..df6fadaa2
--- /dev/null
+++ b/src/routes/console/account/index.svelte
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
Delete Account
+
+
+ Your account will be permanently deleted and access will be lost to any of your teams
+ and data. This action is irreversible.
+
+
+
+
+
+
+
+ {$user.name}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/console/account/organizations.svelte b/src/routes/console/account/organizations.svelte
new file mode 100644
index 000000000..3005a8d47
--- /dev/null
+++ b/src/routes/console/account/organizations.svelte
@@ -0,0 +1,110 @@
+
+
+
+
+
Organizations
+
+
+
+
+ {#if $organizationList?.teams?.length}
+ 3 ? '22rem' : '25rem'
+ };`}>
+ {#each $organizationList.teams as organization, index}
+ {@const avatarList = getMemberships(organization.$id)}
+ {#if index >= offset && index < limit + offset}
+
+ {organization?.total ? organization?.total : 'No'} projects
+
+ {organization.name}
+
+ {#await avatarList}
+
+ {:then avatars}
+
+ {/await}
+
+ {/if}
+ {/each}
+ {#if $organizationList?.total < limit + offset && ($organizationList?.total % 2 !== 0 || $organizationList?.total % 4 === 0)}
+ (addOrganization = true)}>
+
+
+
+
+
Create a new organization
+
+
+ {/if}
+
+
+
+
Total results: {$organizationList?.total}
+
+
+ {:else}
+
+
+
+
+
+
+
+
Create a new organization
+
+
+
+
+
+
Total results: {$organizationList?.total}
+
+
+ {/if}
+
+
+
diff --git a/src/routes/console/account/sessions.svelte b/src/routes/console/account/sessions.svelte
new file mode 100644
index 000000000..de4eb84ef
--- /dev/null
+++ b/src/routes/console/account/sessions.svelte
@@ -0,0 +1,125 @@
+
+
+
+
+
Sessions
+
+
+
+
+ {#if $accountSession?.total}
+
+
+ Client
+ Location
+ IP
+
+
+
+ {#each $accountSession.sessions as session}
+
+
+
+
+ {#if session.clientName}
+
+
.toString()})
+
+
+ {session.clientName}
+ {session.clientVersion}
+ on {session.osName}
+ {session.osVersion}
+
+ {:else}
+
+
Unknown
+ {/if}
+
+
+
{session.provider}
+ {#if session.current}
+
current session
+ {/if}
+
+
+
+ {#if session.countryCode !== '--'}
+ {session.countryName}
+ {:else}
+ Unknown
+ {/if}
+
+ {session.ip}
+
+
+
+
+ {/each}
+
+
+ {:else}
+
+
+
+
No sessions available
+
+
+
+
+
+
+ {/if}
+
+
Total results: {$accountSession?.total}
+
+
+
diff --git a/src/routes/console/account/store.ts b/src/routes/console/account/store.ts
new file mode 100644
index 000000000..798a4cd5d
--- /dev/null
+++ b/src/routes/console/account/store.ts
@@ -0,0 +1,30 @@
+import { cachedStore } from '$lib/helpers/cache';
+import { sdkForConsole } from '$lib/stores/sdk';
+import type { Models } from '@aw-labs/appwrite-console';
+
+export const accountSession = cachedStore<
+ Models.SessionList,
+ {
+ load: () => Promise;
+ }
+>('accountSession', function ({ set }) {
+ return {
+ load: async () => {
+ const response = await sdkForConsole.account.getSessions();
+ set(response);
+ }
+ };
+});
+export const accountActivity = cachedStore<
+ Models.LogList,
+ {
+ load: (limit: number, offset: number) => Promise;
+ }
+>('accountActivity', function ({ set }) {
+ return {
+ load: async (limit, offset) => {
+ const response = await sdkForConsole.account.getLogs(limit, offset);
+ set(response);
+ }
+ };
+});
diff --git a/src/routes/console/organization-[organization]/__layout.svelte b/src/routes/console/organization-[organization]/__layout.svelte
index 647327b21..0233e147b 100644
--- a/src/routes/console/organization-[organization]/__layout.svelte
+++ b/src/routes/console/organization-[organization]/__layout.svelte
@@ -20,7 +20,7 @@
afterNavigate(handle);
async function handle(event = null) {
- if ($organization.$id !== organizationId) {
+ if ($organization?.$id !== organizationId) {
await organization.load(organizationId);
await memberList.load(organizationId, '', 12, 0);
}
diff --git a/src/routes/console/organization-[organization]/_createMember.svelte b/src/routes/console/organization-[organization]/_createMember.svelte
index 237c167ca..b3b2f67c5 100644
--- a/src/routes/console/organization-[organization]/_createMember.svelte
+++ b/src/routes/console/organization-[organization]/_createMember.svelte
@@ -14,7 +14,7 @@
const dispatch = createEventDispatcher();
let email: string, name: string, error: string;
- const url = `${$page.url.origin}/console/`;
+ const url = `${$page.url.origin}/invite`;
const create = async () => {
try {
diff --git a/src/routes/console/organization-[organization]/_deleteMember.svelte b/src/routes/console/organization-[organization]/_deleteMember.svelte
index 215cee0a8..8a7ba31f5 100644
--- a/src/routes/console/organization-[organization]/_deleteMember.svelte
+++ b/src/routes/console/organization-[organization]/_deleteMember.svelte
@@ -1,4 +1,6 @@
+
+
diff --git a/src/routes/console/project-[project]/settings/index.svelte b/src/routes/console/project-[project]/settings/index.svelte
index d2fb3e02f..663857030 100644
--- a/src/routes/console/project-[project]/settings/index.svelte
+++ b/src/routes/console/project-[project]/settings/index.svelte
@@ -1,15 +1,34 @@
- Overview
{#if $project}
-
-
-
+
+
+
+ API Credentials
+
+ Access Appwrite services using your API Endpoint and Project ID. You can connect
+ Appwrite to your applications and server-side code by integrating a new platform
+ or
+ creating an API key.
+
+
+
+
+
+
+
+
+
+
+ Services
+ Choose services you wish to enable or disable.
+
+
+
+
+
+
+
+
+
+
Delete Project
+
+
+ The project will be permanently deleted, including all the metadata, resources and
+ stats within it. This action is irreversible.
+
+
+
+
+ {$project.name}
+
+ Last update: {toLocaleDateTime($project.$updatedAt)}
+
+
+
+
+
+
+
{/if}
+
+
diff --git a/src/routes/console/project-[project]/settings/members.svelte b/src/routes/console/project-[project]/settings/members.svelte
deleted file mode 100644
index da6770b55..000000000
--- a/src/routes/console/project-[project]/settings/members.svelte
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
- Members
- {#await request}
-
- {:then response}
- {#if response}
-
- {#each response.memberships as membership}
-
-
-
-
- {membership.userName}
-
-
- {#each membership.roles as role}
- {role}
- {/each}
- {#if !membership.confirm}
- Pending Approval
- {/if}
-
-
- {membership.userEmail}
-
-
-
-
-
- {:else}
- No sessions available.
- {/each}
-
- {/if}
- {/await}
-
diff --git a/src/routes/console/project-[project]/storage/bucket/[bucket]/file/[file]/store.ts b/src/routes/console/project-[project]/storage/bucket/[bucket]/file/[file]/store.ts
index d4e2d74eb..9f48e437e 100644
--- a/src/routes/console/project-[project]/storage/bucket/[bucket]/file/[file]/store.ts
+++ b/src/routes/console/project-[project]/storage/bucket/[bucket]/file/[file]/store.ts
@@ -1,25 +1,17 @@
import { sdkForProject } from '$lib/stores/sdk';
import type { Models } from '@aw-labs/appwrite-console';
-import { writable } from 'svelte/store';
-import { browser } from '$app/env';
-
-function createFileStore() {
- const { subscribe, set } = writable(
- browser ? JSON.parse(sessionStorage.getItem('file')) : null
- );
+import { cachedStore } from '$lib/helpers/cache';
+export const file = cachedStore<
+ Models.File,
+ {
+ load: (bucketId: string, fileId: string) => Promise;
+ }
+>('file', function ({ set }) {
return {
- subscribe,
- set,
- load: async (bucketId: string, fileId: string) => {
+ load: async (bucketId, fileId) => {
const response = await sdkForProject.storage.getFile(bucketId, fileId);
set(response);
}
};
-}
-
-export const file = createFileStore();
-
-if (browser) {
- file.subscribe((n) => sessionStorage?.setItem('file', JSON.stringify(n ?? '')));
-}
+});
diff --git a/src/routes/console/project-[project]/storage/store.ts b/src/routes/console/project-[project]/storage/store.ts
index 0418b6106..6078297c2 100644
--- a/src/routes/console/project-[project]/storage/store.ts
+++ b/src/routes/console/project-[project]/storage/store.ts
@@ -1,25 +1,17 @@
import { sdkForProject } from '$lib/stores/sdk';
import type { Models } from '@aw-labs/appwrite-console';
-import { writable } from 'svelte/store';
-import { browser } from '$app/env';
-
-function createBucketListStore() {
- const { subscribe, set } = writable(
- browser ? JSON.parse(sessionStorage.getItem('bucketList')) : null
- );
+import { cachedStore } from '$lib/helpers/cache';
+export const bucketList = cachedStore<
+ Models.BucketList,
+ {
+ load: (search: string, limit: number, offset: number) => Promise;
+ }
+>('bucketList', function ({ set }) {
return {
- subscribe,
- set,
- load: async (search: string, limit: number, offset: number) => {
+ load: async (search, limit, offset) => {
const response = await sdkForProject.storage.listBuckets(search, limit, offset);
set(response);
}
};
-}
-
-export const bucketList = createBucketListStore();
-
-if (browser) {
- bucketList.subscribe((n) => sessionStorage?.setItem('bucketList', JSON.stringify(n ?? '')));
-}
+});
diff --git a/src/routes/console/project-[project]/store.ts b/src/routes/console/project-[project]/store.ts
index 83a1a5c53..45c291faf 100644
--- a/src/routes/console/project-[project]/store.ts
+++ b/src/routes/console/project-[project]/store.ts
@@ -1,18 +1,17 @@
import { sdkForConsole } from '$lib/stores/sdk';
import type { Models } from '@aw-labs/appwrite-console';
-import { writable } from 'svelte/store';
-
-function createProject() {
- const { subscribe, set } = writable();
+import { cachedStore } from '$lib/helpers/cache';
+export const project = cachedStore<
+ Models.Project,
+ {
+ load: (projectId: string) => Promise;
+ }
+>('project', function ({ set }) {
return {
- subscribe,
- set,
load: async (projectId: string) => {
const project = await sdkForConsole.projects.get(projectId);
set(project);
}
};
-}
-
-export const project = createProject();
+});
diff --git a/src/routes/invite.svelte b/src/routes/invite.svelte
new file mode 100644
index 000000000..374ebc914
--- /dev/null
+++ b/src/routes/invite.svelte
@@ -0,0 +1,76 @@
+
+
+
+ Appwrite - Accept invite
+
+
+
+ Invite
+
+ {#if !userId || !secret || !membershipId || !teamId}
+ Invalid invite link.
+ {:else}
+ You have been invited to join a team project on Appwrite
+
+ {/if}
+
+