mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge commit '93754b342accbdb6db066c33b2addea7b9e92d67' into feat-v2-regions
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ export function getOrganizationIdFromUrl(pathname: string) {
|
||||
|
||||
export function getProjectIdFromUrl(pathname: string) {
|
||||
// TODO: use base path from svelte here
|
||||
const regex = /\/console\/project-([^/]+)(\/.*)?/;
|
||||
const regex = /\/console\/project-(?:[a-z]{2,3}-)?([^/]+)(\/.*)?/;
|
||||
const match = pathname.match(regex);
|
||||
|
||||
if (match) {
|
||||
|
||||
@@ -8,12 +8,12 @@ test('upgrade - free tier', async ({ page }) => {
|
||||
await createFreeProject(page);
|
||||
await test.step('upgrade project', async () => {
|
||||
await page.getByRole('link', { name: 'Upgrade', exact: true }).click();
|
||||
await page.waitForURL('./organization-**/change-plan');
|
||||
await page.waitForURL(/\/organization-[^/]+\/change-plan/);
|
||||
await page.locator('input[value="tier-1"]').click();
|
||||
await page.getByRole('button', { name: 'add' }).first().click();
|
||||
await enterCreditCard(page);
|
||||
// skip members
|
||||
await page.getByRole('button', { name: 'change plan' }).click();
|
||||
await page.waitForURL('**/console/project-*/overview/platforms');
|
||||
await page.waitForURL(/\/console\/project-(?:[a-z0-9]+-)?([^/]+)\/overview\/platforms/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,18 +13,18 @@ export async function createFreeProject(page: Page): Promise<Metadata> {
|
||||
await page.locator('id=name').fill('test org');
|
||||
await page.locator('id=plan').selectOption('tier-0');
|
||||
await page.getByRole('button', { name: 'get started' }).click();
|
||||
await page.waitForURL('./organization-**');
|
||||
await page.waitForURL(/\/organization-[^/]+/);
|
||||
return getOrganizationIdFromUrl(page.url());
|
||||
});
|
||||
|
||||
const projectId = await test.step('create project', async () => {
|
||||
await page.waitForURL('./organization-**');
|
||||
await page.waitForURL(/\/organization-[^/]+/);
|
||||
await page.getByRole('button', { name: 'create project' }).first().click();
|
||||
await page.locator('id=name').fill('test project');
|
||||
await page.getByRole('button', { name: 'next' }).click();
|
||||
await page.locator('label').filter({ hasText: 'Frankfurt' }).click();
|
||||
await page.getByRole('button', { name: 'create' }).click();
|
||||
await page.waitForURL('./project-**/overview/platforms');
|
||||
await page.waitForURL(/\/project-(?:[a-z0-9]+-)?([^/]+)\/overview\/platforms/);
|
||||
expect(page.url()).toContain('/console/project-');
|
||||
|
||||
return getProjectIdFromUrl(page.url());
|
||||
|
||||
@@ -32,24 +32,24 @@ export async function createProProject(page: Page): Promise<Metadata> {
|
||||
await page.locator('id=name').fill('test org');
|
||||
await page.locator('id=plan').selectOption('tier-1');
|
||||
await page.getByRole('button', { name: 'get started' }).click();
|
||||
await page.waitForURL('./create-organization**');
|
||||
await page.waitForURL(/\/create-organization.*/);
|
||||
await page.getByRole('button', { name: 'add' }).first().click();
|
||||
await enterCreditCard(page);
|
||||
// skip members
|
||||
await page.getByRole('button', { name: 'create organization' }).click();
|
||||
await page.waitForURL('./organization-**');
|
||||
await page.waitForURL(/\/organization-[^/]+/);
|
||||
|
||||
return getOrganizationIdFromUrl(page.url());
|
||||
});
|
||||
|
||||
const projectId = await test.step('create project', async () => {
|
||||
await page.waitForURL('./organization-**');
|
||||
await page.waitForURL(/\/organization-[^/]+/);
|
||||
await page.getByRole('button', { name: 'create project' }).first().click();
|
||||
await page.getByPlaceholder('project name').fill('test project');
|
||||
await page.getByRole('button', { name: 'next' }).click();
|
||||
await page.locator('label').filter({ hasText: 'frankfurt' }).click();
|
||||
await page.getByRole('button', { name: 'create' }).click();
|
||||
await page.waitForURL('./project-**/overview/platforms');
|
||||
await page.waitForURL(/\/project-(?:[a-z0-9]+-)?([^/]+)\/overview\/platforms/);
|
||||
expect(page.url()).toContain('/project-');
|
||||
|
||||
return getProjectIdFromUrl(page.url());
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
"@stripe/stripe-js": "^3.5.0",
|
||||
"ai": "^2.2.37",
|
||||
"analytics": "^0.8.16",
|
||||
"@ai-sdk/svelte": "^1.1.22",
|
||||
"@ai-sdk/svelte": "^1.1.24",
|
||||
"cron-parser": "^4.9.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"deep-equal": "^2.2.3",
|
||||
|
||||
Generated
+19
-19
@@ -9,8 +9,8 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@ai-sdk/svelte':
|
||||
specifier: ^1.1.22
|
||||
version: 1.1.22(svelte@4.2.19)(zod@3.24.2)
|
||||
specifier: ^1.1.24
|
||||
version: 1.1.24(svelte@4.2.19)(zod@3.24.2)
|
||||
'@appwrite.io/console':
|
||||
specifier: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@e2f082e
|
||||
version: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@e2f082e
|
||||
@@ -195,8 +195,8 @@ packages:
|
||||
'@adobe/css-tools@4.4.2':
|
||||
resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==}
|
||||
|
||||
'@ai-sdk/provider-utils@2.1.11':
|
||||
resolution: {integrity: sha512-lMnXA5KaRJidzW7gQmlo/SnX6D+AKk5GxHFcQtOaGOSJNmu/qcNZc1rGaO7K5qW52OvCLXtnWudR4cc/FvMpVQ==}
|
||||
'@ai-sdk/provider-utils@2.1.13':
|
||||
resolution: {integrity: sha512-kLjqsfOdONr6DGcGEntFYM1niXz1H05vyZNf9OAzK+KKKc64izyP4/q/9HX7W4+6g8hm6BnmKxu8vkr6FSOqDg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
@@ -204,12 +204,12 @@ packages:
|
||||
zod:
|
||||
optional: true
|
||||
|
||||
'@ai-sdk/provider@1.0.10':
|
||||
resolution: {integrity: sha512-pco8Zl9U0xwXI+nCLc0woMtxbvjU8hRmGTseAUiPHFLYAAL8trRPCukg69IDeinOvIeo1SmXxAIdWWPZOLb4Cg==}
|
||||
'@ai-sdk/provider@1.0.11':
|
||||
resolution: {integrity: sha512-CPyImHGiT3svyfmvPvAFTianZzWFtm0qK82XjwlQIA1C3IQ2iku/PMQXi7aFyrX0TyMh3VTkJPB03tjU2VXVrw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@ai-sdk/svelte@1.1.22':
|
||||
resolution: {integrity: sha512-xtJjvEPHD8GDB1iODvsRLKplZ9CVUN/gT4U+nttuEvjV42qoPXKkrWwjTLEdWKnwTnoHuuI8mnQMje6RhFWtpA==}
|
||||
'@ai-sdk/svelte@1.1.24':
|
||||
resolution: {integrity: sha512-nlSSd4FirQyM10MQb9vCzF3e/R4id0od0/cKtB1JdtcIvT4ZaJzyltIK3Q72ceOjEbHXSGbucW6gVyExBzHCLQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
svelte: ^3.0.0 || ^4.0.0 || ^5.0.0
|
||||
@@ -217,8 +217,8 @@ packages:
|
||||
svelte:
|
||||
optional: true
|
||||
|
||||
'@ai-sdk/ui-utils@1.1.17':
|
||||
resolution: {integrity: sha512-fCnp/wntZGqPf6tiCmhuQoSDLSBhXoI5DU2JX4As96EO870+jliE6ozvYUwYOZC6Ta2OKAjjWPcSP7HeHX0b+g==}
|
||||
'@ai-sdk/ui-utils@1.1.19':
|
||||
resolution: {integrity: sha512-rDHy2uxlPMt3jjS9L6mBrsfhEInZ5BVoWevmD13fsAt2s/XWy2OwwKmgmUQkdLlY4mn/eyeYAfDGK8+5CbOAgg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
@@ -3529,32 +3529,32 @@ snapshots:
|
||||
|
||||
'@adobe/css-tools@4.4.2': {}
|
||||
|
||||
'@ai-sdk/provider-utils@2.1.11(zod@3.24.2)':
|
||||
'@ai-sdk/provider-utils@2.1.13(zod@3.24.2)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.0.10
|
||||
'@ai-sdk/provider': 1.0.11
|
||||
eventsource-parser: 3.0.0
|
||||
nanoid: 3.3.9
|
||||
secure-json-parse: 2.7.0
|
||||
optionalDependencies:
|
||||
zod: 3.24.2
|
||||
|
||||
'@ai-sdk/provider@1.0.10':
|
||||
'@ai-sdk/provider@1.0.11':
|
||||
dependencies:
|
||||
json-schema: 0.4.0
|
||||
|
||||
'@ai-sdk/svelte@1.1.22(svelte@4.2.19)(zod@3.24.2)':
|
||||
'@ai-sdk/svelte@1.1.24(svelte@4.2.19)(zod@3.24.2)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider-utils': 2.1.11(zod@3.24.2)
|
||||
'@ai-sdk/ui-utils': 1.1.17(zod@3.24.2)
|
||||
'@ai-sdk/provider-utils': 2.1.13(zod@3.24.2)
|
||||
'@ai-sdk/ui-utils': 1.1.19(zod@3.24.2)
|
||||
optionalDependencies:
|
||||
svelte: 4.2.19
|
||||
transitivePeerDependencies:
|
||||
- zod
|
||||
|
||||
'@ai-sdk/ui-utils@1.1.17(zod@3.24.2)':
|
||||
'@ai-sdk/ui-utils@1.1.19(zod@3.24.2)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.0.10
|
||||
'@ai-sdk/provider-utils': 2.1.11(zod@3.24.2)
|
||||
'@ai-sdk/provider': 1.0.11
|
||||
'@ai-sdk/provider-utils': 2.1.13(zod@3.24.2)
|
||||
zod-to-json-schema: 3.24.3(zod@3.24.2)
|
||||
optionalDependencies:
|
||||
zod: 3.24.2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { initCreateAttribute } from '$routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/+layout.svelte';
|
||||
import { attributeOptions } from '$routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/attributes/store';
|
||||
import { initCreateAttribute } from '$routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/+layout.svelte';
|
||||
import { attributeOptions } from '$routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/store';
|
||||
import Template from './template.svelte';
|
||||
|
||||
let search = '';
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { providers } from '$routes/(console)/project-[project]/messaging/providers/store';
|
||||
import { providers } from '$routes/(console)/project-[region]-[project]/messaging/providers/store';
|
||||
import {
|
||||
messageParams,
|
||||
providerType,
|
||||
targetsById
|
||||
} from '$routes/(console)/project-[project]/messaging/wizard/store';
|
||||
} from '$routes/(console)/project-[region]-[project]/messaging/wizard/store';
|
||||
import { MessagingProviderType } from '@appwrite.io/console';
|
||||
import Template from './template.svelte';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import Create from '$routes/(console)/project-[project]/messaging/create.svelte';
|
||||
import { topicsById } from '$routes/(console)/project-[project]/messaging/store';
|
||||
import Create from '$routes/(console)/project-[region]-[project]/messaging/create.svelte';
|
||||
import { topicsById } from '$routes/(console)/project-[region]-[project]/messaging/store';
|
||||
|
||||
let search = '';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import {
|
||||
Platform,
|
||||
addPlatform
|
||||
} from '$routes/(console)/project-[project]/overview/platforms/+page.svelte';
|
||||
} from '$routes/(console)/project-[region]-[project]/overview/platforms/+page.svelte';
|
||||
import Template from './template.svelte';
|
||||
import { IconAndroid, IconApple, IconCode, IconFlutter } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
|
||||
@@ -14,12 +14,13 @@ import {
|
||||
IconPuzzle,
|
||||
IconSearch
|
||||
} from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
const getBucketCommand = (bucket: Models.Bucket, projectId: string) => {
|
||||
const getBucketCommand = (bucket: Models.Bucket, region: string, projectId: string) => {
|
||||
return {
|
||||
label: `${bucket.name}`,
|
||||
callback() {
|
||||
goto(`${base}/project-${projectId}/storage/bucket-${bucket.$id}`);
|
||||
goto(`${base}/project-${region}-${projectId}/storage/bucket-${bucket.$id}`);
|
||||
},
|
||||
group: 'buckets',
|
||||
icon: IconFolder
|
||||
@@ -27,19 +28,24 @@ const getBucketCommand = (bucket: Models.Bucket, projectId: string) => {
|
||||
};
|
||||
|
||||
export const bucketSearcher = (async (query: string) => {
|
||||
const { buckets } = await sdk.forProject.storage.listBuckets([Query.orderDesc('$createdAt')]);
|
||||
|
||||
const $project = get(project);
|
||||
const region = page.params.region;
|
||||
const { buckets } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.storage.listBuckets([Query.orderDesc('$createdAt')]);
|
||||
|
||||
const filtered = buckets.filter((bucket) => bucket.name.includes(query));
|
||||
|
||||
if (filtered.length === 1) {
|
||||
const bucket = filtered[0];
|
||||
return [
|
||||
getBucketCommand(bucket, $project.$id),
|
||||
getBucketCommand(bucket, region, $project.$id),
|
||||
{
|
||||
label: 'Find files',
|
||||
async callback() {
|
||||
await goto(`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}`);
|
||||
await goto(
|
||||
`${base}/project-${$project.region}-${$project.$id}/storage/bucket-${bucket.$id}`
|
||||
);
|
||||
addSubPanel(FilesPanel);
|
||||
},
|
||||
group: 'buckets',
|
||||
@@ -51,7 +57,7 @@ export const bucketSearcher = (async (query: string) => {
|
||||
label: 'Permissions',
|
||||
async callback() {
|
||||
await goto(
|
||||
`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#permissions`
|
||||
`${base}/project-${$project.region}-${$project.$id}/storage/bucket-${bucket.$id}/settings#permissions`
|
||||
);
|
||||
scrollBy({ top: -100 });
|
||||
},
|
||||
@@ -63,7 +69,7 @@ export const bucketSearcher = (async (query: string) => {
|
||||
label: 'Extensions',
|
||||
async callback() {
|
||||
await goto(
|
||||
`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#extensions`
|
||||
`${base}/project-${$project.region}-${$project.$id}/storage/bucket-${bucket.$id}/settings#extensions`
|
||||
);
|
||||
},
|
||||
group: 'buckets',
|
||||
@@ -74,7 +80,7 @@ export const bucketSearcher = (async (query: string) => {
|
||||
label: 'File Security',
|
||||
async callback() {
|
||||
await goto(
|
||||
`${base}/project-${$project.$id}/storage/bucket-${bucket.$id}/settings#file-security`
|
||||
`${base}/project-${$project.region}-${$project.$id}/storage/bucket-${bucket.$id}/settings#file-security`
|
||||
);
|
||||
scrollBy({ top: -100 });
|
||||
},
|
||||
@@ -85,5 +91,5 @@ export const bucketSearcher = (async (query: string) => {
|
||||
];
|
||||
}
|
||||
|
||||
return filtered.map((bucket) => getBucketCommand(bucket, $project.$id));
|
||||
return filtered.map((bucket) => getBucketCommand(bucket, $project.region, $project.$id));
|
||||
}) satisfies Searcher;
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { database } from '$routes/(console)/project-[region]-[project]/databases/database-[database]/store';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export const collectionsSearcher = (async (query: string) => {
|
||||
const databaseId = get(database).$id;
|
||||
const { collections } = await sdk.forProject.databases.listCollections(databaseId);
|
||||
const { collections } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.databases.listCollections(databaseId);
|
||||
|
||||
const projectId = get(project).$id;
|
||||
return collections
|
||||
.filter((col) => col.name.toLowerCase().includes(query.toLowerCase()))
|
||||
.map(
|
||||
@@ -20,7 +21,7 @@ export const collectionsSearcher = (async (query: string) => {
|
||||
label: col.name,
|
||||
callback: () => {
|
||||
goto(
|
||||
`${base}/project-${projectId}/databases/database-${databaseId}/collection-${col.$id}`
|
||||
`${base}/project-${page.params.region}-${page.params.project}/databases/database-${databaseId}/collection-${col.$id}`
|
||||
);
|
||||
}
|
||||
}) as const
|
||||
|
||||
@@ -5,9 +5,12 @@ import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
import { IconDatabase } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export const dbSearcher = (async (query: string) => {
|
||||
const { databases } = await sdk.forProject.databases.list();
|
||||
const { databases } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.databases.list();
|
||||
|
||||
return databases
|
||||
.filter((db) => db.name.toLowerCase().includes(query.toLowerCase()))
|
||||
@@ -17,7 +20,9 @@ export const dbSearcher = (async (query: string) => {
|
||||
group: 'databases',
|
||||
label: db.name,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${get(project).$id}/databases/database-${db.$id}`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/databases/database-${db.$id}`
|
||||
);
|
||||
},
|
||||
icon: IconDatabase
|
||||
}) as const
|
||||
|
||||
@@ -7,21 +7,22 @@ import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { base } from '$app/paths';
|
||||
import { IconDocument } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export const fileSearcher = (async (query: string) => {
|
||||
const $bucket = get(bucket);
|
||||
const $project = get(project);
|
||||
|
||||
const { files } = await sdk.forProject.storage.listFiles(
|
||||
$bucket.$id,
|
||||
[Query.orderDesc('')],
|
||||
query || undefined
|
||||
);
|
||||
const { files } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.storage.listFiles($bucket.$id, [Query.orderDesc('')], query || undefined);
|
||||
|
||||
return files.map((file) => ({
|
||||
label: file.name,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/storage/bucket-${$bucket.$id}/file-${file.$id}`);
|
||||
goto(
|
||||
`${base}/project-${$project.region}-${$project.$id}/storage/bucket-${$bucket.$id}/file-${file.$id}`
|
||||
);
|
||||
},
|
||||
icon: IconDocument,
|
||||
group: 'files'
|
||||
|
||||
@@ -9,11 +9,11 @@ import { showCreateDeployment } from '$routes/(console)/project-[region]-[projec
|
||||
import { base } from '$app/paths';
|
||||
import { IconLightningBolt, IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
const getFunctionCommand = (fn: Models.Function, projectId: string) => {
|
||||
const getFunctionCommand = (fn: Models.Function, region: string, projectId: string) => {
|
||||
return {
|
||||
label: fn.name,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/functions/function-${fn.$id}`);
|
||||
goto(`${base}/project-${region}-${projectId}/functions/function-${fn.$id}`);
|
||||
},
|
||||
group: 'functions',
|
||||
icon: IconLightningBolt
|
||||
@@ -21,23 +21,27 @@ const getFunctionCommand = (fn: Models.Function, projectId: string) => {
|
||||
};
|
||||
|
||||
export const functionsSearcher = (async (query: string) => {
|
||||
const { functions } = await sdk.forProject.functions.list();
|
||||
|
||||
const $page = get(page);
|
||||
const projectId = get(project).$id;
|
||||
const { functions } = await sdk
|
||||
.forProject($page.params.region, $page.params.project)
|
||||
.functions.list();
|
||||
|
||||
const filtered = functions.filter((fn) => fn.name.toLowerCase().includes(query.toLowerCase()));
|
||||
|
||||
if (filtered.length === 1) {
|
||||
const func = filtered[0];
|
||||
return [
|
||||
getFunctionCommand(func, projectId),
|
||||
getFunctionCommand(func, $page.params.region, projectId),
|
||||
{
|
||||
label: 'Create deployment',
|
||||
nested: true,
|
||||
async callback() {
|
||||
const $page = get(page);
|
||||
if (!$page.url.pathname.endsWith(func.$id)) {
|
||||
await goto(`${base}/project-${projectId}/functions/function-${func.$id}`);
|
||||
await goto(
|
||||
`${base}/project-${$page.params.region}-${projectId}/functions/function-${func.$id}`
|
||||
);
|
||||
}
|
||||
showCreateDeployment.set(true);
|
||||
},
|
||||
@@ -48,7 +52,9 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to deployments',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}`);
|
||||
goto(
|
||||
`${base}/project-${$page.params.region}-${projectId}/functions/function-${func.$id}`
|
||||
);
|
||||
},
|
||||
group: 'functions'
|
||||
},
|
||||
@@ -56,7 +62,9 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to usage',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}/usage`);
|
||||
goto(
|
||||
`${base}/project-${$page.params.region}-${projectId}/functions/function-${func.$id}/usage`
|
||||
);
|
||||
},
|
||||
group: 'functions'
|
||||
},
|
||||
@@ -64,7 +72,9 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to executions',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}/executions`);
|
||||
goto(
|
||||
`${base}/project-${$page.params.region}-${projectId}/functions/function-${func.$id}/executions`
|
||||
);
|
||||
},
|
||||
group: 'functions'
|
||||
},
|
||||
@@ -72,12 +82,14 @@ export const functionsSearcher = (async (query: string) => {
|
||||
label: 'Go to settings',
|
||||
nested: true,
|
||||
callback() {
|
||||
goto(`${base}/project-${projectId}/functions/function-${func.$id}/settings`);
|
||||
goto(
|
||||
`${base}/project-${$page.params.region}-${projectId}/functions/function-${func.$id}/settings`
|
||||
);
|
||||
},
|
||||
group: 'functions'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
return filtered.map((fn) => getFunctionCommand(fn, projectId));
|
||||
return filtered.map((fn) => getFunctionCommand(fn, $page.params.region, projectId));
|
||||
}) satisfies Searcher;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import { type Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { MessagingProviderType, type Models } from '@appwrite.io/console';
|
||||
import { base } from '$app/paths';
|
||||
import { IconAnnotation, IconDeviceMobile, IconMail } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
const getLabel = (message: Models.Message) => {
|
||||
switch (message.providerType) {
|
||||
@@ -34,9 +33,9 @@ const getIcon = (message: Models.Message) => {
|
||||
};
|
||||
|
||||
export const messagesSearcher = (async (query: string) => {
|
||||
const { messages } = await sdk.forProject.messaging.listMessages([], query || undefined);
|
||||
|
||||
const projectId = get(project).$id;
|
||||
const { messages } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.messaging.listMessages([], query || undefined);
|
||||
|
||||
return messages
|
||||
.filter((message) => getLabel(message).toLowerCase().includes(query.toLowerCase()))
|
||||
@@ -46,7 +45,9 @@ export const messagesSearcher = (async (query: string) => {
|
||||
group: 'messages',
|
||||
label: getLabel(message),
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/messaging/message-${message.$id}`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/messaging/message-${message.$id}`
|
||||
);
|
||||
},
|
||||
icon: getIcon(message)
|
||||
}) as const
|
||||
|
||||
@@ -18,7 +18,7 @@ export const projectsSearcher = (async (query: string) => {
|
||||
return {
|
||||
label: project.name,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${project.$id}`);
|
||||
goto(`${base}/project-${project.region}-${project.$id}`);
|
||||
},
|
||||
group: 'projects'
|
||||
} as const;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getProviderDisplayNameAndIcon } from '$routes/(console)/project-[project]/messaging/provider.svelte';
|
||||
import { getProviderDisplayNameAndIcon } from '$routes/(console)/project-[region]-[project]/messaging/provider.svelte';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
|
||||
const getIcon = (provider: string) => {
|
||||
const { icon } = getProviderDisplayNameAndIcon(provider);
|
||||
@@ -12,9 +11,9 @@ const getIcon = (provider: string) => {
|
||||
};
|
||||
|
||||
export const providersSearcher = (async (query: string) => {
|
||||
const { providers } = await sdk.forProject.messaging.listProviders([], query || undefined);
|
||||
|
||||
const projectId = get(project).$id;
|
||||
const { providers } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.messaging.listProviders([], query || undefined);
|
||||
|
||||
return providers
|
||||
.filter((provider) => provider.name.toLowerCase().includes(query.toLowerCase()))
|
||||
@@ -25,7 +24,7 @@ export const providersSearcher = (async (query: string) => {
|
||||
label: provider.name,
|
||||
callback: () => {
|
||||
goto(
|
||||
`${base}/project-${projectId}/messaging/providers/provider-${provider.$id}`
|
||||
`${base}/project-${page.params.region}-${page.params.project}/messaging/providers/provider-${provider.$id}`
|
||||
);
|
||||
},
|
||||
image: getIcon(provider.provider)
|
||||
|
||||
@@ -1,33 +1,35 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Command, Searcher } from '../commands';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { base } from '$app/paths';
|
||||
import { IconUserCircle } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
const getTeamCommand = (team: Models.Team<Models.Preferences>, projectId: string) =>
|
||||
const getTeamCommand = (team: Models.Team<Models.Preferences>, region: string, projectId: string) =>
|
||||
({
|
||||
label: team.name,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/auth/teams/team-${team.$id}`);
|
||||
goto(`${base}/project-${region}-${projectId}/auth/teams/team-${team.$id}`);
|
||||
},
|
||||
group: 'teams',
|
||||
icon: IconUserCircle
|
||||
}) satisfies Command;
|
||||
|
||||
export const teamSearcher = (async (query: string) => {
|
||||
const { teams } = await sdk.forProject.teams.list([], query);
|
||||
const projectId = get(project).$id;
|
||||
const { teams } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.teams.list([], query);
|
||||
|
||||
if (teams.length === 1) {
|
||||
return [
|
||||
getTeamCommand(teams[0], projectId),
|
||||
getTeamCommand(teams[0], page.params.region, page.params.project),
|
||||
{
|
||||
label: 'Go to members',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/auth/teams/team-${teams[0].$id}/members`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/auth/teams/team-${teams[0].$id}/members`
|
||||
);
|
||||
},
|
||||
group: 'teams',
|
||||
nested: true
|
||||
@@ -36,12 +38,14 @@ export const teamSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to activity',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/auth/teams/team-${teams[0].$id}/activity`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/auth/teams/team-${teams[0].$id}/activity`
|
||||
);
|
||||
},
|
||||
group: 'teams',
|
||||
nested: true
|
||||
}
|
||||
];
|
||||
}
|
||||
return teams.map((team) => getTeamCommand(team, projectId));
|
||||
return teams.map((team) => getTeamCommand(team, page.params.region, page.params.project));
|
||||
}) satisfies Searcher;
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Searcher } from '../commands';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { base } from '$app/paths';
|
||||
import { IconChevronRight } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export const topicsSearcher = (async (query: string) => {
|
||||
const { topics } = await sdk.forProject.messaging.listTopics([], query || undefined);
|
||||
|
||||
const projectId = get(project).$id;
|
||||
const { topics } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.messaging.listTopics([], query || undefined);
|
||||
|
||||
return topics
|
||||
.filter((topic) => topic.name.toLowerCase().includes(query.toLowerCase()))
|
||||
@@ -19,7 +18,9 @@ export const topicsSearcher = (async (query: string) => {
|
||||
group: 'topics',
|
||||
label: topic.name,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/messaging/topics/topic-${topic.$id}`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/messaging/topics/topic-${topic.$id}`
|
||||
);
|
||||
},
|
||||
icon: IconChevronRight // TODO: @itznotabug - 'send' no replacement yet.
|
||||
}) as const
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { project } from '$routes/(console)/project-[region]-[project]/store';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Command, Searcher } from '../commands';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { promptDeleteUser } from '$routes/(console)/project-[project]/auth/user-[user]/dangerZone.svelte';
|
||||
import { promptDeleteUser } from '$routes/(console)/project-[region]-[project]/auth/user-[user]/dangerZone.svelte';
|
||||
import { base } from '$app/paths';
|
||||
import { IconTrash, IconUserCircle } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
const getUserCommand = (user: Models.User<Models.Preferences>, projectId: string) =>
|
||||
const getUserCommand = (user: Models.User<Models.Preferences>, region: string, projectId: string) =>
|
||||
({
|
||||
label: user.name,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/auth/user-${user.$id}`);
|
||||
goto(`${base}/project-${region}-${projectId}/auth/user-${user.$id}`);
|
||||
},
|
||||
group: 'users',
|
||||
icon: IconUserCircle
|
||||
}) satisfies Command;
|
||||
|
||||
export const userSearcher = (async (query: string) => {
|
||||
const { users } = await sdk.forProject.users.list([], query || undefined);
|
||||
const projectId = get(project).$id;
|
||||
const { users } = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.users.list([], query || undefined);
|
||||
|
||||
if (users.length === 1) {
|
||||
return [
|
||||
getUserCommand(users[0], projectId),
|
||||
getUserCommand(users[0], page.params.region, page.params.project),
|
||||
{
|
||||
label: 'Delete user',
|
||||
callback: () => {
|
||||
@@ -37,7 +37,9 @@ export const userSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to activity',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/auth/user-${users[0].$id}/activity`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/auth/user-${users[0].$id}/activity`
|
||||
);
|
||||
},
|
||||
group: 'users',
|
||||
nested: true
|
||||
@@ -45,7 +47,9 @@ export const userSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to sessions',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/auth/user-${users[0].$id}/sessions`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/auth/user-${users[0].$id}/sessions`
|
||||
);
|
||||
},
|
||||
group: 'users',
|
||||
nested: true
|
||||
@@ -53,12 +57,14 @@ export const userSearcher = (async (query: string) => {
|
||||
{
|
||||
label: 'Go to memberships',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${projectId}/auth/user-${users[0].$id}/memberships`);
|
||||
goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/auth/user-${users[0].$id}/memberships`
|
||||
);
|
||||
},
|
||||
group: 'users',
|
||||
nested: true
|
||||
}
|
||||
];
|
||||
}
|
||||
return users.map((user) => getUserCommand(user, projectId));
|
||||
return users.map((user) => getUserCommand(user, page.params.region, page.params.project));
|
||||
}) satisfies Searcher;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { realtime } from '$lib/stores/sdk';
|
||||
import { type Payload } from '@appwrite.io/console';
|
||||
import { onMount } from 'svelte';
|
||||
import { isCloud, isSelfHosted } from '$lib/system';
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
function showRestoreNotification(newDatabaseId: string, newDatabaseName: string) {
|
||||
if (newDatabaseId && newDatabaseName && lastDatabaseRestorationId !== newDatabaseId) {
|
||||
const region = page.params.region;
|
||||
const project = page.params.project;
|
||||
lastDatabaseRestorationId = newDatabaseId;
|
||||
|
||||
@@ -45,7 +46,9 @@
|
||||
{
|
||||
name: 'View restored data',
|
||||
method: () => {
|
||||
goto(`${base}/project-${project}/databases/database-${newDatabaseId}`);
|
||||
goto(
|
||||
`${base}/project-${region}-${project}/databases/database-${newDatabaseId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -123,16 +126,18 @@
|
||||
// fast path: don't subscribe if org is on a free plan or is self-hosted.
|
||||
if (isSelfHosted || (isCloud && $organization.billingPlan === BillingPlan.FREE)) return;
|
||||
|
||||
return sdk.forConsole.client.subscribe('console', (response) => {
|
||||
if (!response.channels.includes(`projects.${getProjectId()}`)) return;
|
||||
return realtime
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.subscribe('console', (response) => {
|
||||
if (!response.channels.includes(`projects.${getProjectId()}`)) return;
|
||||
|
||||
if (
|
||||
response.events.includes('archives.*') ||
|
||||
response.events.includes('restorations.*')
|
||||
) {
|
||||
updateOrAddItem(response.payload);
|
||||
}
|
||||
});
|
||||
if (
|
||||
response.events.includes('archives.*') ||
|
||||
response.events.includes('restorations.*')
|
||||
) {
|
||||
updateOrAddItem(response.payload);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
export let event: string = null;
|
||||
export let eventContext = 'click_id_tag';
|
||||
export let tooltipDisabled = false;
|
||||
export let copyText: string = 'Click to copy';
|
||||
|
||||
let content = 'Click to copy';
|
||||
let content = copyText;
|
||||
|
||||
async function handleClick() {
|
||||
const success = await copy(value);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
function getCreditCardImage(brand: string, width = 46, height = 32) {
|
||||
if (!isValueOfStringEnum(CreditCard, brand)) return '';
|
||||
return sdk.forConsole.avatars.getCreditCard(brand, width, height).toString();
|
||||
return sdk.forConsole.avatars.getCreditCard(brand, width, height);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -49,20 +49,21 @@
|
||||
|
||||
function getPreview(bucketId: string, fileId: string, size: number = 64) {
|
||||
return (
|
||||
sdk.forProject.storage.getFilePreview(bucketId, fileId, size, size).toString() +
|
||||
'&mode=admin'
|
||||
sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.storage.getFilePreview(bucketId, fileId, size, size)
|
||||
.toString() + '&mode=admin'
|
||||
);
|
||||
}
|
||||
|
||||
async function uploadFile() {
|
||||
try {
|
||||
uploading = true;
|
||||
const file = await sdk.forProject.storage.createFile(
|
||||
selectedBucket,
|
||||
ID.unique(),
|
||||
fileSelector.files[0],
|
||||
[Permission.read(Role.any())]
|
||||
);
|
||||
const file = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.storage.createFile(selectedBucket, ID.unique(), fileSelector.files[0], [
|
||||
Permission.read(Role.any())
|
||||
]);
|
||||
search.set($search === null ? '' : null);
|
||||
selectFile(file);
|
||||
} catch (e) {
|
||||
@@ -110,7 +111,9 @@
|
||||
let buckets: Promise<Models.BucketList> = loadBuckets();
|
||||
|
||||
async function loadBuckets() {
|
||||
const response = await sdk.forProject.storage.listBuckets();
|
||||
const response = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.storage.listBuckets();
|
||||
const bucket = response.buckets[0] ?? null;
|
||||
if (bucket) {
|
||||
currentBucket = bucket;
|
||||
@@ -122,8 +125,9 @@
|
||||
|
||||
$: files =
|
||||
currentBucket &&
|
||||
sdk.forProject.storage
|
||||
.listFiles(
|
||||
sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.storage.listFiles(
|
||||
currentBucket.$id,
|
||||
[Query.startsWith('mimeType', mimeTypeQuery), Query.orderDesc('$createdAt')],
|
||||
$search || undefined
|
||||
@@ -218,6 +222,9 @@
|
||||
<span class="icon-upload" aria-hidden="true"></span>
|
||||
<span>Upload</span>
|
||||
{/if}
|
||||
======= external href={`${base}/project-${page.params.region}-${page.params.project}/storage`}>
|
||||
Create bucket >>>>>>>
|
||||
93754b342accbdb6db066c33b2addea7b9e92d67
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
@@ -355,7 +362,7 @@
|
||||
slot="actions"
|
||||
secondary
|
||||
external
|
||||
href={`${base}/project-${page.params.project}/storage`}>
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/storage`}>
|
||||
Create bucket
|
||||
</Button>
|
||||
</Empty>
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Icon, Tag } from '@appwrite.io/pink-svelte';
|
||||
import { Copy } from '.';
|
||||
import { IconDuplicate } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let value: string;
|
||||
export let event: string = null;
|
||||
|
||||
function truncateText(node: HTMLElement) {
|
||||
<script context="module" lang="ts">
|
||||
export function truncateText(node: HTMLElement) {
|
||||
const MAX_TRIES = 100;
|
||||
let originalText = node.textContent;
|
||||
function checkOverflow() {
|
||||
@@ -48,6 +41,15 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { Icon, Tag } from '@appwrite.io/pink-svelte';
|
||||
import { Copy } from '.';
|
||||
import { IconDuplicate } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let value: string;
|
||||
export let event: string = null;
|
||||
</script>
|
||||
|
||||
<Copy {value} {event}>
|
||||
<Tag size="xs" variant="code">
|
||||
<Icon icon={IconDuplicate} size="s" slot="start" />
|
||||
|
||||
@@ -82,3 +82,4 @@ export { default as BottomSheet } from './bottom-sheet/index';
|
||||
export { default as Confirm } from './confirm.svelte';
|
||||
export { default as UsageCard } from './usageCard.svelte';
|
||||
export { default as ViewToggle } from './viewToggle.svelte';
|
||||
export { default as RegionEndpoint } from './regionEndpoint.svelte';
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
const url = new URL(pageStore.url);
|
||||
const previousLimit = Number(url.searchParams.get('limit'));
|
||||
url.searchParams.set('limit', limit.toString());
|
||||
preferences.setLimit(limit);
|
||||
preferences.setLimit($pageStore.params.project, $pageStore.route, limit);
|
||||
|
||||
if (url.searchParams.has('page')) {
|
||||
const page = Number(url.searchParams.get('page'));
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts" context="module">
|
||||
import { page } from '$app/stores';
|
||||
import { parseIfString } from '$lib/helpers/object';
|
||||
import { getProjectId } from '$lib/helpers/project';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { realtime } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { onMount } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
@@ -49,13 +50,15 @@
|
||||
})();
|
||||
|
||||
onMount(() => {
|
||||
return sdk.forConsole.client.subscribe<Models.Migration>(['console'], async (response) => {
|
||||
if (!response.channels.includes(`projects.${getProjectId()}`)) return;
|
||||
if (response.events.includes('migrations.*')) {
|
||||
if (response.payload.source === 'Backup') return;
|
||||
migration = response.payload;
|
||||
}
|
||||
});
|
||||
return realtime
|
||||
.forProject($page.params.region, $page.params.project)
|
||||
.subscribe<Models.Migration>(['console'], async (response) => {
|
||||
if (!response.channels.includes(`projects.${getProjectId()}`)) return;
|
||||
if (response.events.includes('migrations.*')) {
|
||||
if (response.payload.source === 'Backup') return;
|
||||
migration = response.payload;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
export let show = false;
|
||||
export let size: 'small' | 'big' | 'huge' = null;
|
||||
export let closable = true;
|
||||
export let closeByEscape = true;
|
||||
export let headerDivider = true;
|
||||
export let style = '';
|
||||
|
||||
@@ -48,7 +49,7 @@
|
||||
}
|
||||
|
||||
function handleKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
if (event.key === 'Escape' && closeByEscape) {
|
||||
event.preventDefault();
|
||||
trackEvent(Click.ModalCloseClick, {
|
||||
from: 'escape'
|
||||
|
||||
@@ -27,10 +27,16 @@
|
||||
const role = permission.split(':')[0];
|
||||
const id = permission.split(':')[1].split('/')[0];
|
||||
if (role === 'user') {
|
||||
return await sdk.forProject.users.get(id);
|
||||
const user = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.users.get(id);
|
||||
return user;
|
||||
}
|
||||
if (role === 'team') {
|
||||
return await sdk.forProject.teams.get(id);
|
||||
const team = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.teams.get(id);
|
||||
return team;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -82,7 +88,7 @@
|
||||
{/if}
|
||||
<div>
|
||||
<Button.Anchor
|
||||
href={`${base}/project-${page.params.project}/auth/user-${data?.$id}`}
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/auth/user-${data?.$id}`}
|
||||
size="xs"
|
||||
target="_blank"
|
||||
variant="secondary">
|
||||
@@ -94,7 +100,7 @@
|
||||
<Typography.Text>Members: {data?.total}</Typography.Text>
|
||||
<div>
|
||||
<Button.Anchor
|
||||
href={`${base}/project-${page.params.project}/auth/teams/team-${data?.$id}`}
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/auth/teams/team-${data?.$id}`}
|
||||
size="s"
|
||||
target="_blank"
|
||||
variant="secondary">
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
Table,
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export let show: boolean;
|
||||
export let groups: Writable<Map<string, Permission>>;
|
||||
@@ -40,10 +41,9 @@
|
||||
|
||||
async function request() {
|
||||
if (!show) return;
|
||||
results = await sdk.forProject.teams.list(
|
||||
[Query.limit(5), Query.offset(offset)],
|
||||
search || undefined
|
||||
);
|
||||
results = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.teams.list([Query.limit(5), Query.offset(offset)], search || undefined);
|
||||
}
|
||||
|
||||
function onSelection(role: string) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import { IconAnonymous, IconMinusSm } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export let show: boolean;
|
||||
export let groups: Writable<Map<string, Permission>>;
|
||||
@@ -43,10 +44,9 @@
|
||||
|
||||
async function request() {
|
||||
if (!show) return;
|
||||
results = await sdk.forProject.users.list(
|
||||
[Query.limit(5), Query.offset(offset)],
|
||||
search || undefined
|
||||
);
|
||||
results = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.users.list([Query.limit(5), Query.offset(offset)], search || undefined);
|
||||
}
|
||||
|
||||
function onSelection(role: string) {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<script lang="ts">
|
||||
import { Copy } from '.';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Flag } from '@appwrite.io/console';
|
||||
import { truncateText } from '$lib/components/id.svelte';
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types';
|
||||
import { getProjectEndpoint } from '$lib/helpers/project';
|
||||
import { projectRegion } from '$routes/(console)/project-[region]-[project]/store';
|
||||
|
||||
$: flagSrc =
|
||||
$projectRegion && isValueOfStringEnum(Flag, $projectRegion.flag)
|
||||
? sdk.forConsole.avatars.getFlag($projectRegion.flag, 30, 20, 100)
|
||||
: '';
|
||||
</script>
|
||||
|
||||
<Copy value={getProjectEndpoint()} appendTo="parent" copyText="Copy endpoint">
|
||||
<div
|
||||
class="flex u-gap-8 u-cross-center interactive-text-output is-buttons-on-top u-text-center"
|
||||
style:min-inline-size="0"
|
||||
style:display="inline-flex">
|
||||
<span
|
||||
style:white-space="nowrap"
|
||||
class="text u-line-height-1-5"
|
||||
style:overflow="hidden"
|
||||
style:word-break="break-all"
|
||||
use:truncateText
|
||||
style:font-family="unset">
|
||||
{$projectRegion?.name}
|
||||
</span>
|
||||
|
||||
{#if flagSrc}
|
||||
<img
|
||||
style="border-radius: 2.5px"
|
||||
src={flagSrc}
|
||||
alt={$projectRegion?.name}
|
||||
width={16}
|
||||
height={12} />
|
||||
{/if}
|
||||
</div>
|
||||
</Copy>
|
||||
@@ -3,6 +3,14 @@ export const CARD_LIMIT = 6; // default card limit
|
||||
export const INTERVAL = 5 * 60000; // default interval to check for feedback
|
||||
export const NEW_DEV_PRO_UPGRADE_COUPON = 'appw50';
|
||||
|
||||
export const REGION_FRA = 'fra';
|
||||
export const REGION_SYD = 'syd';
|
||||
export const REGION_NYC = 'nyc';
|
||||
|
||||
export const SUBDOMAIN_FRA = 'fra.';
|
||||
export const SUBDOMAIN_SYD = 'syd.';
|
||||
export const SUBDOMAIN_NYC = 'nyc.';
|
||||
|
||||
export enum Dependencies {
|
||||
FACTORS = 'dependency:factors',
|
||||
IDENTITIES = 'dependency:identities',
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Flag } from '@appwrite.io/console';
|
||||
|
||||
export let flag: string;
|
||||
export let name: string = flag;
|
||||
export let width = 40;
|
||||
|
||||
+11
-4
@@ -9,8 +9,15 @@ export function getPage(url: URL): number {
|
||||
return Number(url.searchParams.get('page'));
|
||||
}
|
||||
|
||||
export function getLimit(url: URL, route: Page['route'], fallback: number): number {
|
||||
return Number(url.searchParams.get('limit') ?? preferences.get(route).limit ?? fallback);
|
||||
export function getLimit(
|
||||
projectId: string,
|
||||
url: URL,
|
||||
route: Page['route'],
|
||||
fallback: number
|
||||
): number {
|
||||
return Number(
|
||||
url.searchParams.get('limit') ?? preferences.get(projectId, route).limit ?? fallback
|
||||
);
|
||||
}
|
||||
|
||||
export enum View {
|
||||
@@ -28,8 +35,8 @@ export function getView(url: URL, route: Page['route'], fallback: View, overwrit
|
||||
: (overwrite ?? View.Table ?? fallback);
|
||||
}
|
||||
|
||||
export function getColumns(route: Page['route'], fallback: string[]): string[] {
|
||||
return preferences.get(route).columns ?? fallback;
|
||||
export function getColumns(projectId: string, route: Page['route'], fallback: string[]): string[] {
|
||||
return preferences.get(projectId, route).columns ?? fallback;
|
||||
}
|
||||
|
||||
export function getSearch(url: URL): string | undefined {
|
||||
|
||||
@@ -1,6 +1,44 @@
|
||||
export function getProjectId() {
|
||||
import { page } from '$app/stores';
|
||||
import { get } from 'svelte/store';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { projectRegion } from '$routes/(console)/project-[region]-[project]/store';
|
||||
|
||||
/**
|
||||
* Returns the current project ID.
|
||||
*
|
||||
* The function first checks for a `project` parameter in the Svelte `$page` store.
|
||||
* If not found, it extracts the project ID from the pathname.
|
||||
*
|
||||
* Supports:
|
||||
* - Legacy structure: `/project-{projectID}/`
|
||||
* - Multi-region structure: `/project-{region}-{projectID}/`
|
||||
*
|
||||
* Example:
|
||||
* - `/project-console/` → `console`
|
||||
* - `/project-fra-console/` → `console`
|
||||
* - `/project-nyc-console/` → `console`
|
||||
*/
|
||||
export function getProjectId(): string | null {
|
||||
// safety check!
|
||||
const projectFromParams = get(page)?.params?.project;
|
||||
if (projectFromParams) {
|
||||
return projectFromParams;
|
||||
}
|
||||
|
||||
const pathname = window.location.pathname + '/';
|
||||
const projectMatch = pathname.match(/\/project-(.*?)\//);
|
||||
const projectMatch = pathname.match(/\/project-(?:[a-z]{2,3}-)?([^/]+)/);
|
||||
|
||||
return projectMatch?.[1] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the correct API endpoint for the project based on the current project region.
|
||||
*
|
||||
* @returns {string} The project-specific API endpoint.
|
||||
*/
|
||||
export function getProjectEndpoint(): string {
|
||||
const currentProjectRegion = get(projectRegion);
|
||||
const { protocol, hostname, href } = new URL(sdk.forConsole.client.config.endpoint);
|
||||
|
||||
return currentProjectRegion ? `${protocol}//${currentProjectRegion.$id}.${hostname}/v1` : href;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
</Layout.Stack>
|
||||
|
||||
<style>
|
||||
header {
|
||||
margin-block-end: 1.25rem;
|
||||
}
|
||||
|
||||
.hide-divider {
|
||||
padding-block-end: 0;
|
||||
border-block-end: none;
|
||||
|
||||
@@ -7,15 +7,16 @@
|
||||
import Step1 from './wizard/step1.svelte';
|
||||
import Step2 from './wizard/step2.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { page } from '$app/stores';
|
||||
import { realtime } from '$lib/stores/sdk';
|
||||
|
||||
onMount(() => {
|
||||
domain.set({ $id: '', domain: '' });
|
||||
|
||||
return sdk.forConsole.client.subscribe<Models.ProxyRule>('console', (data) =>
|
||||
domain.set(data.payload)
|
||||
);
|
||||
return realtime
|
||||
.forProject($page.params.region, $page.params.region)
|
||||
.subscribe<Models.ProxyRule>('console', (data) => domain.set(data.payload));
|
||||
});
|
||||
|
||||
async function onFinish() {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import type { Dependencies } from '$lib/constants';
|
||||
import Confirm from '$lib/components/confirm.svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export let showDelete = false;
|
||||
export let selectedDomain: Models.ProxyRule;
|
||||
@@ -27,7 +28,9 @@
|
||||
|
||||
async function deleteDomain() {
|
||||
try {
|
||||
await sdk.forProject.proxy.deleteRule(selectedDomain.$id);
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.proxy.deleteRule(selectedDomain.$id);
|
||||
await invalidate(dependency);
|
||||
showDelete = false;
|
||||
addNotification({
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Table } from '@appwrite.io/pink-svelte';
|
||||
import { domain } from './store';
|
||||
import { getProjectEndpoint } from '$lib/helpers/project';
|
||||
|
||||
const target = window?.location.hostname ?? '';
|
||||
$: parts = $domain.domain.split('.');
|
||||
$: registerable = [parts[parts.length - 2], parts[parts.length - 1]].join('.');
|
||||
$: cnameValue = $domain.domain.replace('.' + registerable, '');
|
||||
|
||||
$: target = new URL(getProjectEndpoint()).hostname;
|
||||
</script>
|
||||
|
||||
<Table.Root
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { Card, Icon, Layout, Link, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { IconExclamationCircle } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
let retrying = false;
|
||||
export let showTitle = true;
|
||||
@@ -21,7 +22,9 @@
|
||||
async function retry() {
|
||||
try {
|
||||
retrying = true;
|
||||
domain = await sdk.forProject.proxy.updateRuleVerification(domain.$id);
|
||||
domain = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.proxy.updateRuleVerification(domain.$id);
|
||||
invalidate(Dependencies.FUNCTION_DOMAINS);
|
||||
addNotification({
|
||||
message:
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { domain } from './store';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import { Alert } from '@appwrite.io/pink-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
let error = null;
|
||||
const isDomainsEnabled = $consoleVariables?._APP_DOMAIN_ENABLED === true;
|
||||
@@ -15,11 +16,14 @@
|
||||
async function createDomain() {
|
||||
try {
|
||||
if ($domain.$id) {
|
||||
await sdk.forProject.proxy.deleteRule($domain.$id);
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.proxy.deleteRule($domain.$id);
|
||||
}
|
||||
|
||||
// TODO: move to new api methods
|
||||
$domain = await sdk.forProject.proxy.createFunctionRule($domain.domain, $func.$id);
|
||||
$domain = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.proxy.createFunctionRule($domain.domain, $func.$id);
|
||||
|
||||
trackEvent(Submit.DomainCreate);
|
||||
} catch (e) {
|
||||
|
||||
@@ -1277,9 +1277,11 @@ export class Billing {
|
||||
);
|
||||
}
|
||||
|
||||
async listRegions(): Promise<RegionList> {
|
||||
async listRegions(teamId: string): Promise<RegionList> {
|
||||
const path = `/console/regions`;
|
||||
const params = {};
|
||||
const params = {
|
||||
teamId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'GET',
|
||||
|
||||
@@ -325,7 +325,7 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
const members = org.total;
|
||||
const plan = get(plansInfo)?.get(org.billingPlan);
|
||||
const membersOverflow =
|
||||
members - 1 > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0;
|
||||
members > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0;
|
||||
|
||||
if (resources.some((r) => r.value >= 100) || membersOverflow > 0) {
|
||||
readOnly.set(true);
|
||||
|
||||
@@ -14,7 +14,11 @@ export const backupsBannerId = 'banner:databaseBackups';
|
||||
|
||||
export const showPolicyAlert = writable<boolean>(false);
|
||||
|
||||
export async function checkForDatabaseBackupPolicies(database: Models.Database) {
|
||||
export async function checkForDatabaseBackupPolicies(
|
||||
region: string,
|
||||
projectId: string,
|
||||
database: Models.Database
|
||||
) {
|
||||
// fast path: return if user dismissed the banner
|
||||
if (!shouldShowNotification(backupsBannerId)) return;
|
||||
|
||||
@@ -23,10 +27,9 @@ export async function checkForDatabaseBackupPolicies(database: Models.Database)
|
||||
|
||||
if (isCloud && backupsEnabled) {
|
||||
try {
|
||||
const policies = await sdk.forProject.backups.listPolicies([
|
||||
Query.limit(1),
|
||||
Query.equal('resourceId', database.$id)
|
||||
]);
|
||||
const policies = await sdk
|
||||
.forProject(region, projectId)
|
||||
.backups.listPolicies([Query.limit(1), Query.equal('resourceId', database.$id)]);
|
||||
|
||||
total = policies.total;
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { Component } from 'svelte';
|
||||
import Apple from '$routes/(console)/project-[project]/auth/(providers)/appleOAuth.svelte';
|
||||
import Auth0 from '$routes/(console)/project-[project]/auth/(providers)/auth0OAuth.svelte';
|
||||
import Authentik from '$routes/(console)/project-[project]/auth/(providers)/authentikOAuth.svelte';
|
||||
import GitLab from '$routes/(console)/project-[project]/auth/(providers)/gitlabOAuth.svelte';
|
||||
import Google from '$routes/(console)/project-[project]/auth/(providers)/googleOAuth.svelte';
|
||||
import Main from '$routes/(console)/project-[project]/auth/(providers)/mainOAuth.svelte';
|
||||
import Microsoft from '$routes/(console)/project-[project]/auth/(providers)/microsoftOAuth.svelte';
|
||||
import Oidc from '$routes/(console)/project-[project]/auth/(providers)/oidcOAuth.svelte';
|
||||
import Okta from '$routes/(console)/project-[project]/auth/(providers)/oktaOAuth.svelte';
|
||||
import Apple from '$routes/(console)/project-[region]-[project]/auth/(providers)/appleOAuth.svelte';
|
||||
import Auth0 from '$routes/(console)/project-[region]-[project]/auth/(providers)/auth0OAuth.svelte';
|
||||
import Authentik from '$routes/(console)/project-[region]-[project]/auth/(providers)/authentikOAuth.svelte';
|
||||
import GitLab from '$routes/(console)/project-[region]-[project]/auth/(providers)/gitlabOAuth.svelte';
|
||||
import Google from '$routes/(console)/project-[region]-[project]/auth/(providers)/googleOAuth.svelte';
|
||||
import Main from '$routes/(console)/project-[region]-[project]/auth/(providers)/mainOAuth.svelte';
|
||||
import Microsoft from '$routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte';
|
||||
import Oidc from '$routes/(console)/project-[region]-[project]/auth/(providers)/oidcOAuth.svelte';
|
||||
import Okta from '$routes/(console)/project-[region]-[project]/auth/(providers)/oktaOAuth.svelte';
|
||||
|
||||
export type Provider = {
|
||||
name: string;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { page } from '$app/stores';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import type { Tier } from './billing';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import type { Plan, RegionList } from '$lib/sdk/billing';
|
||||
|
||||
export type OrganizationError = {
|
||||
status: number;
|
||||
@@ -60,3 +60,5 @@ export const organizationList = derived(
|
||||
export const organization = derived(page, ($page) => $page.data?.organization as Organization);
|
||||
export const currentPlan = derived(page, ($page) => $page.data?.currentPlan as Plan);
|
||||
export const members = derived(page, ($page) => $page.data.members as Models.MembershipList);
|
||||
|
||||
export const regions = writable<RegionList | undefined>(undefined);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { browser } from '$app/environment';
|
||||
import { page } from '$app/stores';
|
||||
import type { View } from '$lib/helpers/load';
|
||||
import type { Page } from '@sveltejs/kit';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { sdk } from './sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { organization } from './organization';
|
||||
import { page } from '$app/state';
|
||||
|
||||
type Preferences = {
|
||||
limit?: number;
|
||||
@@ -47,7 +47,7 @@ function createPreferences() {
|
||||
set,
|
||||
update,
|
||||
get: (route?: Page['route']): Preferences => {
|
||||
const parsedRoute = route ?? get(page).route;
|
||||
const parsedRoute = route ?? page.route;
|
||||
return (
|
||||
preferences?.[parsedRoute.id] ?? {
|
||||
limit: null,
|
||||
@@ -62,7 +62,7 @@ function createPreferences() {
|
||||
},
|
||||
setLimit: (limit: Preferences['limit']) =>
|
||||
update((n) => {
|
||||
const path = get(page).route.id;
|
||||
const path = page.route.id;
|
||||
|
||||
if (!n?.[path]) {
|
||||
n ??= {};
|
||||
@@ -73,9 +73,9 @@ function createPreferences() {
|
||||
|
||||
return n;
|
||||
}),
|
||||
setView: (view: Preferences['view']) =>
|
||||
setView: (projectId: string, route: Page['route'], view: Preferences['view']) =>
|
||||
update((n) => {
|
||||
const path = get(page).route.id;
|
||||
const path = page.route.id;
|
||||
|
||||
if (!n?.[path]) {
|
||||
n ??= {};
|
||||
@@ -86,9 +86,9 @@ function createPreferences() {
|
||||
|
||||
return n;
|
||||
}),
|
||||
setColumns: (columns: Preferences['columns']) =>
|
||||
setColumns: (projectId: string, route: Page['route'], columns: Preferences['columns']) =>
|
||||
update((n) => {
|
||||
const path = get(page).route.id;
|
||||
const path = page.route.id;
|
||||
|
||||
if (!n?.[path]) {
|
||||
n ??= {};
|
||||
@@ -99,9 +99,13 @@ function createPreferences() {
|
||||
|
||||
return n;
|
||||
}),
|
||||
setCustomCollectionColumns: (columns: Preferences['columns']) =>
|
||||
setCustomCollectionColumns: (
|
||||
projectId: string,
|
||||
route: Page['route'],
|
||||
columns: Preferences['columns']
|
||||
) =>
|
||||
update((n) => {
|
||||
const current = get(page);
|
||||
const current = page;
|
||||
|
||||
const collection = current.params.collection;
|
||||
if (!n?.collections?.[collection]) {
|
||||
|
||||
+59
-12
@@ -1,4 +1,3 @@
|
||||
import { getProjectId } from '$lib/helpers/project';
|
||||
import { VARS } from '$lib/system';
|
||||
import {
|
||||
Account,
|
||||
@@ -26,21 +25,52 @@ import { Billing } from '../sdk/billing';
|
||||
import { Backups } from '../sdk/backups';
|
||||
import { Domains } from '$lib/sdk/domains';
|
||||
import { Sources } from '$lib/sdk/sources';
|
||||
import {
|
||||
REGION_FRA,
|
||||
REGION_NYC,
|
||||
REGION_SYD,
|
||||
SUBDOMAIN_FRA,
|
||||
SUBDOMAIN_NYC,
|
||||
SUBDOMAIN_SYD
|
||||
} from '$lib/constants';
|
||||
import { building } from '$app/environment';
|
||||
import { getProjectId } from '$lib/helpers/project';
|
||||
|
||||
export function getApiEndpoint(): string {
|
||||
if (VARS.APPWRITE_ENDPOINT) return VARS.APPWRITE_ENDPOINT;
|
||||
return globalThis?.location?.origin + '/v1';
|
||||
export function getApiEndpoint(region?: string): string {
|
||||
if (building) return '';
|
||||
const url = new URL(
|
||||
VARS.APPWRITE_ENDPOINT ? VARS.APPWRITE_ENDPOINT : globalThis?.location?.toString()
|
||||
);
|
||||
const protocol = url.protocol;
|
||||
const hostname = url.hostname;
|
||||
const subdomain = getSubdomain(region);
|
||||
|
||||
return `${protocol}//${subdomain}${hostname}/v1`;
|
||||
}
|
||||
|
||||
const getSubdomain = (region?: string) => {
|
||||
switch (region) {
|
||||
case REGION_FRA:
|
||||
return SUBDOMAIN_FRA;
|
||||
case REGION_SYD:
|
||||
return SUBDOMAIN_SYD;
|
||||
case REGION_NYC:
|
||||
return SUBDOMAIN_NYC;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
const endpoint = getApiEndpoint();
|
||||
|
||||
const clientConsole = new Client();
|
||||
const clientProject = new Client();
|
||||
const clientRealtime = new Client();
|
||||
|
||||
if (!building) {
|
||||
clientConsole.setEndpoint(endpoint).setProject('console');
|
||||
clientProject.setEndpoint(endpoint).setMode('admin');
|
||||
clientRealtime.setEndpoint(endpoint).setProject('console');
|
||||
}
|
||||
|
||||
const sdkForProject = {
|
||||
@@ -64,12 +94,22 @@ const sdkForProject = {
|
||||
sites: new Sites(clientProject)
|
||||
};
|
||||
|
||||
export const getSdkForProject = (projectId: string) => {
|
||||
if (projectId && projectId !== clientProject.config.project) {
|
||||
clientProject.setProject(projectId);
|
||||
}
|
||||
export const realtime = {
|
||||
forProject(region: string, _projectId: string) {
|
||||
const endpoint = getApiEndpoint(region);
|
||||
if (endpoint !== clientRealtime.config.endpoint) {
|
||||
clientRealtime.setEndpoint(endpoint);
|
||||
|
||||
return sdkForProject;
|
||||
/**
|
||||
* Workaround: the SDK doesn't update the realtime in `setEndpoint`.
|
||||
* Until that's fixed, we manually set the realtime endpoint like this:
|
||||
*/
|
||||
clientRealtime.setEndpointRealtime(
|
||||
endpoint.replace('https://', 'wss://').replace('http://', 'ws://')
|
||||
);
|
||||
}
|
||||
return clientRealtime;
|
||||
}
|
||||
};
|
||||
|
||||
export const sdk = {
|
||||
@@ -91,9 +131,16 @@ export const sdk = {
|
||||
sites: new Sites(clientConsole),
|
||||
domains: new Domains(clientConsole)
|
||||
},
|
||||
get forProject() {
|
||||
const projectId = getProjectId();
|
||||
return getSdkForProject(projectId);
|
||||
forProject(region: string, projectId: string) {
|
||||
const endpoint = getApiEndpoint(region);
|
||||
if (endpoint !== clientProject.config.endpoint) {
|
||||
clientProject.setEndpoint(endpoint);
|
||||
}
|
||||
if (projectId !== clientProject.config.project) {
|
||||
clientProject.setProject(projectId);
|
||||
}
|
||||
|
||||
return sdkForProject;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+31
-21
@@ -1,6 +1,8 @@
|
||||
import { type Models, Sites, Storage } from '@appwrite.io/console';
|
||||
import { Client, type Models, Sites, Storage } from '@appwrite.io/console';
|
||||
import { writable } from 'svelte/store';
|
||||
import { createAdminClient } from '$lib/stores/sdk';
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
import { page } from '$app/state';
|
||||
|
||||
type UploaderFile = {
|
||||
$id: string;
|
||||
@@ -17,12 +19,18 @@ export type Uploader = {
|
||||
files: UploaderFile[];
|
||||
};
|
||||
|
||||
const temporaryStorage = () => {
|
||||
return new Storage(createAdminClient());
|
||||
const temporaryStorage = (region: string, projectId: string) => {
|
||||
const clientProject = new Client().setMode('admin');
|
||||
const endpoint = getApiEndpoint(region);
|
||||
clientProject.setEndpoint(endpoint).setProject(projectId);
|
||||
return new Storage(clientProject);
|
||||
};
|
||||
|
||||
const temporarySites = () => {
|
||||
return new Sites(createAdminClient());
|
||||
const temporarySites = (region: string, projectId: string) => {
|
||||
const clientProject = new Client().setMode('admin');
|
||||
const endpoint = getApiEndpoint(region);
|
||||
clientProject.setEndpoint(endpoint).setProject(projectId);
|
||||
return new Sites(clientProject);
|
||||
};
|
||||
|
||||
const createUploader = () => {
|
||||
@@ -64,7 +72,14 @@ const createUploader = () => {
|
||||
isCollapsed: false,
|
||||
files: []
|
||||
}),
|
||||
uploadFile: async (bucketId: string, id: string, file: File, permissions: string[]) => {
|
||||
uploadFile: async (
|
||||
region: string,
|
||||
projectId: string,
|
||||
bucketId: string,
|
||||
id: string,
|
||||
file: File,
|
||||
permissions: string[]
|
||||
) => {
|
||||
const newFile: UploaderFile = {
|
||||
$id: id,
|
||||
resourceId: bucketId,
|
||||
@@ -79,7 +94,7 @@ const createUploader = () => {
|
||||
n.files.unshift(newFile);
|
||||
return n;
|
||||
});
|
||||
const uploadedFile = await temporaryStorage().createFile(
|
||||
const uploadedFile = await temporaryStorage(region, projectId).createFile(
|
||||
bucketId,
|
||||
id ?? 'unique()',
|
||||
file,
|
||||
@@ -111,20 +126,15 @@ const createUploader = () => {
|
||||
n.files.unshift(newDeployment);
|
||||
return n;
|
||||
});
|
||||
const uploadedFile = await temporarySites().createDeployment(
|
||||
siteId,
|
||||
code,
|
||||
true,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
(p) => {
|
||||
newDeployment.$id = p.$id;
|
||||
newDeployment.progress = p.progress;
|
||||
newDeployment.status = p.progress === 100 ? 'success' : 'pending';
|
||||
updateFile(p.$id, newDeployment);
|
||||
}
|
||||
);
|
||||
const uploadedFile = await temporarySites(
|
||||
page.params.region,
|
||||
page.params.project
|
||||
).createDeployment(siteId, code, true, undefined, undefined, undefined, (p) => {
|
||||
newDeployment.$id = p.$id;
|
||||
newDeployment.progress = p.progress;
|
||||
newDeployment.status = p.progress === 100 ? 'success' : 'pending';
|
||||
updateFile(p.$id, newDeployment);
|
||||
});
|
||||
newDeployment.$id = uploadedFile.$id;
|
||||
newDeployment.progress = 100;
|
||||
newDeployment.status = 'success';
|
||||
|
||||
@@ -17,6 +17,6 @@ export function openMigrationWizard() {
|
||||
});
|
||||
}
|
||||
|
||||
export const selectedProject = writable(null);
|
||||
export const selectedProject = writable<string>(null);
|
||||
|
||||
export const provider = createMigrationProviderStore();
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
import { Alert, Box, EyebrowHeading } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { deepMap } from '$lib/helpers/object';
|
||||
import type { WritableValue } from '$lib/helpers/types';
|
||||
import { type getSdkForProject } from '$lib/stores/sdk';
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import {
|
||||
createMigrationFormStore,
|
||||
createMigrationProviderStore,
|
||||
@@ -16,10 +12,12 @@
|
||||
} from '$lib/stores/migration';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import type { sdk } from '$lib/stores/sdk';
|
||||
import type { WritableValue } from '$lib/helpers/types';
|
||||
|
||||
export let formData: ReturnType<typeof createMigrationFormStore>;
|
||||
export let provider: ReturnType<typeof createMigrationProviderStore>;
|
||||
export let projectSdk: ReturnType<typeof getSdkForProject>;
|
||||
export let projectSdk: ReturnType<typeof sdk.forProject>;
|
||||
|
||||
type ValueOf<T> = T[keyof T];
|
||||
type FormData = WritableValue<typeof formData>;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { getSdkForProject } from '$lib/stores/sdk';
|
||||
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { formData, provider, selectedProject } from '.';
|
||||
import ResourceForm from './resource-form.svelte';
|
||||
</script>
|
||||
@@ -18,5 +17,5 @@
|
||||
Learn about which resources are supported</a
|
||||
>.
|
||||
</svelte:fragment>
|
||||
<ResourceForm {provider} {formData} projectSdk={getSdkForProject($selectedProject)} />
|
||||
<ResourceForm {provider} {formData} projectSdk={sdk.forProject('fra1', $selectedProject)} />
|
||||
</WizardStep>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
|
||||
import Wizard from '$lib/layout/wizardWithSteps.svelte';
|
||||
import { migrationFormToResources } from '$lib/stores/migration';
|
||||
import { getSdkForProject } from '$lib/stores/sdk';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { formData, provider, selectedProject } from '.';
|
||||
@@ -11,6 +10,7 @@
|
||||
import Step2 from './step2.svelte';
|
||||
import { requestedMigration } from '$routes/store';
|
||||
import { base } from '$app/paths';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
const onExit = () => {
|
||||
formData.reset();
|
||||
@@ -21,12 +21,14 @@
|
||||
if ($provider.provider !== 'appwrite') return;
|
||||
const resources = migrationFormToResources($formData, $provider.provider);
|
||||
|
||||
await getSdkForProject($selectedProject).migrations.createAppwriteMigration(
|
||||
resources,
|
||||
$provider.endpoint,
|
||||
$provider.projectID,
|
||||
$provider.apiKey
|
||||
);
|
||||
await sdk
|
||||
.forProject('fra1', $selectedProject)
|
||||
.migrations.createAppwriteMigration(
|
||||
resources,
|
||||
$provider.endpoint,
|
||||
$provider.projectID,
|
||||
$provider.apiKey
|
||||
);
|
||||
|
||||
await invalidateAll();
|
||||
wizard.hide();
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
import { addSubPanel } from '$lib/commandCenter/subPanels';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { openMigrationWizard } from './(migration-wizard)';
|
||||
import { project } from './project-[project]/store';
|
||||
import { project } from './project-[region]-[project]/store';
|
||||
import { feedback } from '$lib/stores/feedback';
|
||||
import { hasStripePublicKey, isCloud, VARS } from '$lib/system';
|
||||
import { stripe } from '$lib/stores/stripe';
|
||||
@@ -171,7 +171,9 @@
|
||||
({
|
||||
label: kebabToSentenceCase(heading),
|
||||
async callback() {
|
||||
await goto(`${base}/project-${$project.$id}/auth/security#${heading}`);
|
||||
await goto(
|
||||
`${base}/project-${$project.region}-${$project.$id}/auth/security#${heading}`
|
||||
);
|
||||
scrollBy({ top: -100 });
|
||||
},
|
||||
disabled: !$project?.$id,
|
||||
@@ -185,7 +187,7 @@
|
||||
|
||||
keys: isOnSettingsLayout ? ['g', 'o'] : undefined,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/settings`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/settings`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && page.url.pathname.endsWith('settings')),
|
||||
@@ -197,7 +199,7 @@
|
||||
|
||||
keys: isOnSettingsLayout ? ['g', 'd'] : undefined,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/settings/domains`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/settings/domains`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && page.url.pathname.includes('domains')),
|
||||
@@ -208,7 +210,7 @@
|
||||
label: 'Go to webhooks',
|
||||
keys: isOnSettingsLayout ? ['g', 'w'] : undefined,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/settings/webhooks`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/settings/webhooks`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && page.url.pathname.includes('webhooks')),
|
||||
@@ -220,7 +222,7 @@
|
||||
label: 'Go to migrations',
|
||||
keys: isOnSettingsLayout ? ['g', 'm'] : undefined,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/settings/migrations`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/settings/migrations`);
|
||||
},
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && page.url.pathname.includes('migrations')),
|
||||
@@ -232,7 +234,7 @@
|
||||
label: 'Go to SMTP settings',
|
||||
keys: isOnSettingsLayout ? ['g', 's'] : undefined,
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/settings/smtp`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/settings/smtp`);
|
||||
},
|
||||
disabled: !$project?.$id || (isOnSettingsLayout && page.url.pathname.includes('smtp')),
|
||||
group: isOnSettingsLayout ? 'navigation' : 'settings',
|
||||
@@ -287,9 +289,9 @@
|
||||
}
|
||||
|
||||
database.subscribe(async (database) => {
|
||||
if (!database) return;
|
||||
if (!database || !$page.params.region || !$page.params.project) return;
|
||||
// the component checks `isCloud` internally.
|
||||
await checkForDatabaseBackupPolicies(database);
|
||||
await checkForDatabaseBackupPolicies($page.params.region, $page.params.project, database);
|
||||
});
|
||||
|
||||
let currentOrganizationId = null;
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const limit = getLimit('console', url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { isCloud } from '$lib/system';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const limit = getLimit('console', url, route, CARD_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
const queries = [Query.offset(offset), Query.limit(limit), Query.orderDesc('')];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { Modal } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
@@ -27,8 +28,10 @@
|
||||
let error: string = null;
|
||||
|
||||
onMount(async () => {
|
||||
const countryList = await sdk.forProject.locale.listCountries();
|
||||
const locale = await sdk.forProject.locale.get();
|
||||
const countryList = await sdk
|
||||
.forProject($page.params.region, $page.params.project)
|
||||
.locale.listCountries();
|
||||
const locale = await sdk.forProject($page.params.region, $page.params.project).locale.get();
|
||||
if (locale.countryCode) {
|
||||
country = locale.countryCode;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
Tag,
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
let show = false;
|
||||
let showEdit = false;
|
||||
@@ -37,7 +38,9 @@
|
||||
let countryList: Models.CountryList;
|
||||
|
||||
onMount(async () => {
|
||||
countryList = await sdk.forProject.locale.listCountries();
|
||||
countryList = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.locale.listCountries();
|
||||
});
|
||||
|
||||
$: orgList = $organizationList.teams as unknown as Organization[];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { Modal } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
@@ -21,7 +22,13 @@
|
||||
];
|
||||
|
||||
onMount(async () => {
|
||||
const countryList = await sdk.forProject.locale.listCountries();
|
||||
const countryList = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.locale.listCountries();
|
||||
const locale = await sdk.forProject(page.params.region, page.params.project).locale.get();
|
||||
if (locale.countryCode) {
|
||||
selectedAddress.country = locale.countryCode;
|
||||
}
|
||||
options = countryList.countries.map((country) => {
|
||||
return {
|
||||
value: country.code,
|
||||
@@ -62,11 +69,13 @@
|
||||
* which really shouldn't happen, but here we are, playing it safe!
|
||||
*/
|
||||
$: if (show && !selectedAddress.country) {
|
||||
sdk.forProject.locale.get().then((locale) => {
|
||||
if (locale.countryCode) {
|
||||
selectedAddress.country = locale.countryCode;
|
||||
}
|
||||
});
|
||||
sdk.forProject(page.params.region, page.params.project)
|
||||
.locale.get()
|
||||
.then((locale) => {
|
||||
if (locale.countryCode) {
|
||||
selectedAddress.country = locale.countryCode;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
function getBrowser(clientCode: string) {
|
||||
const code = clientCode.toLowerCase();
|
||||
if (!isValueOfStringEnum(Browser, code)) return '';
|
||||
return sdk.forProject.avatars.getBrowser(code, 40, 40);
|
||||
|
||||
return sdk.forConsole.avatars.getBrowser(code, 40, 40);
|
||||
}
|
||||
|
||||
function logoutSessionId(sessionId: string) {
|
||||
|
||||
@@ -21,7 +21,7 @@ if (isCloud) {
|
||||
importance: 8,
|
||||
cta: {
|
||||
text: 'Try now',
|
||||
link: ({ project }) => `${base}/project-${project.$id}/databases`
|
||||
link: ({ project }) => `${base}/project-${project.region}-${project.$id}/databases`
|
||||
},
|
||||
learnMore: {
|
||||
text: 'Learn more',
|
||||
|
||||
@@ -13,6 +13,7 @@ import { preferences } from '$lib/stores/preferences';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import { defaultRoles, defaultScopes } from '$lib/constants';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import { loadAvailableRegions } from '$routes/(console)/regions';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.ORGANIZATION);
|
||||
@@ -52,6 +53,8 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
preferences.loadTeamPrefs(params.organization)
|
||||
]);
|
||||
|
||||
await loadAvailableRegions(params.organization);
|
||||
|
||||
return {
|
||||
header: Header,
|
||||
breadcrumbs: Breadcrumbs,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import { loading } from '$routes/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { ID, Region } from '@appwrite.io/console';
|
||||
import { openImportWizard } from '../project-[project]/settings/migrations/(import)';
|
||||
import { openImportWizard } from '../project-[region]-[project]/settings/migrations/(import)';
|
||||
import { readOnly } from '$lib/stores/billing';
|
||||
import { onMount, type ComponentType } from 'svelte';
|
||||
import { canWriteProjects } from '$lib/stores/roles';
|
||||
@@ -122,17 +122,16 @@
|
||||
trackEvent(Submit.ProjectCreate, {
|
||||
teamId: page.params.organization
|
||||
});
|
||||
await goto(`${base}/project-${project.$id}/settings/migrations`);
|
||||
await goto(`${base}/project-${project.region}-${project.$id}/settings/migrations`);
|
||||
openImportWizard();
|
||||
loading.set(false);
|
||||
} catch (e) {
|
||||
trackError(e, Submit.ProjectCreate);
|
||||
}
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
if (isCloud) {
|
||||
const regions = await sdk.forConsole.billing.listRegions();
|
||||
if (isCloud && $organization.$id) {
|
||||
const regions = await sdk.forConsole.billing.listRegions($organization.$id);
|
||||
regionsStore.set(regions);
|
||||
checkPricingRefAndRedirect(page.url.searchParams);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export const load: PageLoad = async ({ params, url, route, depends, parent }) =>
|
||||
const { scopes } = await parent();
|
||||
depends(Dependencies.ORGANIZATION);
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, CARD_LIMIT);
|
||||
const limit = getLimit('console', url, route, CARD_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
if (!scopes.includes('projects.read') && scopes.includes('billing.read')) {
|
||||
return redirect(301, `/console/organization-${params.organization}/billing`);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { base } from '$app/paths';
|
||||
import { Alert, Badge, Card, Layout, Skeleton } from '@appwrite.io/pink-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export let show = false;
|
||||
let loading = true;
|
||||
@@ -43,11 +44,13 @@
|
||||
: null
|
||||
: null;
|
||||
|
||||
const locale = await sdk.forProject.locale.get();
|
||||
const locale = await sdk.forProject(page.params.region, page.params.project).locale.get();
|
||||
if (locale?.countryCode) {
|
||||
country = locale.countryCode;
|
||||
}
|
||||
const countryList = await sdk.forProject.locale.listCountries();
|
||||
const countryList = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.locale.listCountries();
|
||||
options = countryList.countries.map((country) => {
|
||||
return {
|
||||
value: country.code,
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
type: 'success',
|
||||
message: `${name} has been created`
|
||||
});
|
||||
await goto(`${base}/project-${project.$id}`);
|
||||
await goto(`${base}/project-${project.region}-${project.$id}`);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.ProjectCreate);
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
message: `${$createProject.name} has been created`
|
||||
});
|
||||
await onFinish();
|
||||
await goto(`${base}/project-${project.$id}`);
|
||||
await goto(`${base}/project-${project.region}-${project.$id}`);
|
||||
} catch (e) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
|
||||
@@ -9,7 +9,7 @@ export const load: PageLoad = async ({ url, params, route, depends }) => {
|
||||
depends(Dependencies.MEMBERS);
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const limit = getLimit('console', url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
let error: string;
|
||||
|
||||
onMount(async () => {
|
||||
const countryList = await sdk.forProject.locale.listCountries();
|
||||
const locale = await sdk.forProject.locale.get();
|
||||
/* use console sdk as project is not always available here. */
|
||||
const locale = await sdk.forConsole.locale.get();
|
||||
const countryList = await sdk.forConsole.locale.listCountries();
|
||||
|
||||
if (locale.countryCode) {
|
||||
country = locale.countryCode;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,10 @@
|
||||
let error: string;
|
||||
|
||||
onMount(async () => {
|
||||
const countryList = await sdk.forProject.locale.listCountries();
|
||||
const locale = await sdk.forProject.locale.get();
|
||||
/* use console sdk as project is not always available here. */
|
||||
const locale = await sdk.forConsole.locale.get();
|
||||
const countryList = await sdk.forConsole.locale.listCountries();
|
||||
|
||||
if (locale.countryCode) {
|
||||
country = locale.countryCode;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export const load: PageLoad = async ({ params, parent }) => {
|
||||
sdk.forConsole.billing.getOrganizationPlan(org.$id)
|
||||
]);
|
||||
|
||||
const projectNames: { [key: string]: Models.Project } = {};
|
||||
const projects: { [key: string]: Models.Project } = {};
|
||||
if (usage?.projects?.length > 0) {
|
||||
// in batches of 100 (the max number of values in a query)
|
||||
const requests = [];
|
||||
@@ -75,17 +75,17 @@ export const load: PageLoad = async ({ params, parent }) => {
|
||||
const responses = await Promise.all(requests);
|
||||
for (const response of responses) {
|
||||
for (const project of response.projects) {
|
||||
projectNames[project.$id] = project;
|
||||
projects[project.$id] = project;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
organizationUsage: usage,
|
||||
projectNames,
|
||||
plan,
|
||||
invoices,
|
||||
projects,
|
||||
currentInvoice,
|
||||
organizationMembers,
|
||||
plan
|
||||
organizationUsage: usage
|
||||
};
|
||||
};
|
||||
|
||||
+10
-3
@@ -37,7 +37,12 @@
|
||||
}
|
||||
|
||||
function getProjectUsageLink(projectId: string): string {
|
||||
return `${base}/project-${projectId}/settings/usage`;
|
||||
const region = data.projects[projectId]?.region ?? 'fra';
|
||||
return `${base}/project-${region}-${projectId}/settings/usage`;
|
||||
}
|
||||
|
||||
function getProjectName(projectId: string): string {
|
||||
return data.projects[projectId]?.name ?? 'Unknown';
|
||||
}
|
||||
|
||||
function groupByProject(
|
||||
@@ -53,12 +58,14 @@
|
||||
}> {
|
||||
const data = [];
|
||||
for (const project of projects) {
|
||||
const projectId = project.projectId;
|
||||
|
||||
if (metric) {
|
||||
const usage = project[metric];
|
||||
if (!usage) continue;
|
||||
|
||||
data.push({
|
||||
projectId: project.projectId,
|
||||
projectId,
|
||||
usage: usage ?? 0,
|
||||
estimate: estimate ? project[estimate] : undefined
|
||||
});
|
||||
@@ -68,7 +75,7 @@
|
||||
|
||||
if (reads || writes) {
|
||||
data.push({
|
||||
projectId: project.projectId,
|
||||
projectId,
|
||||
databasesReads: reads,
|
||||
databasesWrites: writes
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { BackupRestoreBox, MigrationBox, UploadBox } from '$lib/components';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { realtime } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { project, stats } from './store';
|
||||
|
||||
@@ -26,20 +26,22 @@
|
||||
} from '$lib/stores/roles';
|
||||
|
||||
onMount(() => {
|
||||
return sdk.forConsole.client.subscribe(['project', 'console'], (response) => {
|
||||
if (response.events.includes('stats.connections')) {
|
||||
for (const [projectId, value] of Object.entries(response.payload)) {
|
||||
stats.add(projectId, [new Date(response.timestamp).toISOString(), value]);
|
||||
return realtime
|
||||
.forProject($page.params.region, $page.params.project)
|
||||
.subscribe(['project', 'console'], (response) => {
|
||||
if (response.events.includes('stats.connections')) {
|
||||
for (const [projectId, value] of Object.entries(response.payload)) {
|
||||
stats.add(projectId, [new Date(response.timestamp).toISOString(), value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$: $registerCommands([
|
||||
{
|
||||
label: 'Go to Auth',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/auth`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/auth`);
|
||||
},
|
||||
keys: ['g', 'a'],
|
||||
group: 'navigation'
|
||||
@@ -47,7 +49,7 @@
|
||||
{
|
||||
label: 'Go to Databases',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/databases`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/databases`);
|
||||
},
|
||||
keys: ['g', 'd'],
|
||||
group: 'navigation',
|
||||
@@ -56,7 +58,7 @@
|
||||
{
|
||||
label: 'Go to Functions',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/functions`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/functions`);
|
||||
},
|
||||
keys: ['g', 'f'],
|
||||
group: 'navigation',
|
||||
@@ -65,7 +67,7 @@
|
||||
{
|
||||
label: 'Go to Messaging',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/messaging`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/messaging`);
|
||||
},
|
||||
keys: ['g', 'm'],
|
||||
disabled: page.url.pathname.endsWith('messaging') || !$canSeeMessages,
|
||||
@@ -74,7 +76,7 @@
|
||||
{
|
||||
label: 'Go to Storage',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/storage`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/storage`);
|
||||
},
|
||||
keys: ['g', 's'],
|
||||
group: 'navigation',
|
||||
@@ -83,7 +85,7 @@
|
||||
{
|
||||
label: 'Go to Settings',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}/settings`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/settings`);
|
||||
},
|
||||
keys: ['g', 'e'],
|
||||
group: 'navigation',
|
||||
@@ -101,7 +103,7 @@
|
||||
{
|
||||
label: 'Go to Overview',
|
||||
callback: () => {
|
||||
goto(`${base}/project-${$project.$id}`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}`);
|
||||
},
|
||||
keys: ['g', 'o'],
|
||||
group: 'navigation'
|
||||
|
||||
@@ -11,6 +11,7 @@ import type { Plan } from '$lib/sdk/billing';
|
||||
import { get } from 'svelte/store';
|
||||
import { headerAlert } from '$lib/stores/headerAlert';
|
||||
import PaymentFailed from '$lib/components/billing/alerts/paymentFailed.svelte';
|
||||
import { loadAvailableRegions } from '$routes/(console)/regions';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.PROJECT);
|
||||
@@ -18,9 +19,10 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
|
||||
try {
|
||||
const project = await sdk.forConsole.projects.get(params.project);
|
||||
const [organization, prefs] = await Promise.all([
|
||||
const [organization, prefs, _] = await Promise.all([
|
||||
sdk.forConsole.teams.get(project.teamId) as Promise<Organization>,
|
||||
sdk.forConsole.account.getPrefs()
|
||||
sdk.forConsole.account.getPrefs(),
|
||||
loadAvailableRegions(project.teamId)
|
||||
]);
|
||||
if (prefs?.organization !== project.teamId) {
|
||||
sdk.forConsole.account.updatePrefs({
|
||||
|
||||
@@ -5,7 +5,7 @@ import { hasOnboardingDismissed } from '$lib/helpers/onboarding';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
if (hasOnboardingDismissed(params.project)) {
|
||||
redirect(302, `${base}/project-${params.project}/overview`);
|
||||
redirect(302, `${base}/project-${params.region}-${params.project}/overview`);
|
||||
}
|
||||
redirect(302, `${base}/project-${params.project}/get-started`);
|
||||
redirect(302, `${base}/project-${params.region}-${params.project}/get-started`);
|
||||
};
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
import { Link, Alert } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
|
||||
export let provider: Models.AuthProvider;
|
||||
export let show = false;
|
||||
|
||||
let appId: string = null;
|
||||
let enabled: boolean = null;
|
||||
let clientSecret: string = null;
|
||||
let auth0Domain: string = null;
|
||||
let error: string;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
label: 'Create user',
|
||||
callback: async () => {
|
||||
if (!page.url.pathname.endsWith('auth')) {
|
||||
await goto(`${base}/project-${$project.$id}/auth`);
|
||||
await goto(`${base}/project-${$project.region}-${$project.$id}/auth`);
|
||||
}
|
||||
showCreateUser.set(true);
|
||||
},
|
||||
@@ -31,7 +31,7 @@
|
||||
label: 'Create team',
|
||||
callback: async () => {
|
||||
if (!page.url.pathname.endsWith('teams')) {
|
||||
await goto(`${base}/project-${$project.$id}/auth/teams`);
|
||||
await goto(`${base}/project-${$project.region}-${$project.$id}/auth/teams`);
|
||||
}
|
||||
showCreateTeam.set(true);
|
||||
},
|
||||
@@ -46,7 +46,7 @@
|
||||
label: 'Go to teams',
|
||||
keys: ['g', 't'],
|
||||
callback() {
|
||||
goto(`${base}/project-${$project.$id}/auth/teams`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/auth/teams`);
|
||||
},
|
||||
group: 'navigation',
|
||||
rank: 1,
|
||||
@@ -56,7 +56,7 @@
|
||||
label: 'Go to usage',
|
||||
keys: ['g', 'u'],
|
||||
callback() {
|
||||
goto(`${base}/project-${$project.$id}/auth/usage`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/auth/usage`);
|
||||
},
|
||||
group: 'navigation',
|
||||
rank: 1,
|
||||
@@ -66,7 +66,7 @@
|
||||
label: 'Go to security',
|
||||
keys: ['g', 'e'],
|
||||
callback() {
|
||||
goto(`${base}/project-${$project.$id}/auth/security`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/auth/security`);
|
||||
},
|
||||
group: 'navigation',
|
||||
rank: 1,
|
||||
@@ -76,7 +76,7 @@
|
||||
label: 'Go to settings',
|
||||
keys: ['g', 's'],
|
||||
callback() {
|
||||
goto(`${base}/project-${$project.$id}/auth/settings`);
|
||||
goto(`${base}/project-${$project.region}-${$project.$id}/auth/settings`);
|
||||
},
|
||||
group: 'navigation',
|
||||
rank: 1,
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { writable } from 'svelte/store';
|
||||
import type { PageData } from './$types';
|
||||
import Create from './createUser.svelte';
|
||||
import { Badge, Icon, Table, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Tag } from '@appwrite.io/pink-svelte';
|
||||
@@ -29,9 +28,8 @@
|
||||
import ViewSelector from '$lib/components/viewSelector.svelte';
|
||||
import { View } from '$lib/helpers/load';
|
||||
|
||||
export let data: PageData;
|
||||
export let data;
|
||||
|
||||
const projectId = page.params.project;
|
||||
const columns = writable<Column[]>([
|
||||
{ id: '$id', title: 'User ID', type: 'string', width: 200 },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 260 } },
|
||||
@@ -49,7 +47,9 @@
|
||||
]);
|
||||
|
||||
async function userCreated(event: CustomEvent<Models.User<Record<string, unknown>>>) {
|
||||
await goto(`${base}/project-${projectId}/auth/user-${event.detail.$id}`);
|
||||
await goto(
|
||||
`${base}/project-${page.params.region}-${page.params.project}/auth/user-${event.detail.$id}`
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -75,7 +75,9 @@
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
{#each data.users.users as user}
|
||||
<Table.Row.Link href={`${base}/project-${projectId}/auth/user-${user.$id}`} {root}>
|
||||
<Table.Row.Link
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/auth/user-${user.$id}`}
|
||||
{root}>
|
||||
{#each $columns as { id } (id)}
|
||||
<Table.Cell column={id} {root}>
|
||||
{#if id === '$id'}
|
||||
@@ -160,8 +162,10 @@
|
||||
total={data.users.total} />
|
||||
{:else if data.search}
|
||||
<EmptySearch target="users" hidePagination>
|
||||
<Button href={`${base}/project-${projectId}/auth`} size="s" secondary
|
||||
>Clear Search</Button>
|
||||
<Button
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/auth`}
|
||||
size="s"
|
||||
secondary>Clear Search</Button>
|
||||
</EmptySearch>
|
||||
{:else}
|
||||
<Empty
|
||||
|
||||
@@ -5,10 +5,10 @@ import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
import { showCreateUser } from './+page.svelte';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
export const load: PageLoad = async ({ url, route, params }) => {
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const limit = getLimit(params.project, url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
if (typeof url.searchParams.get('create') === 'string') {
|
||||
@@ -20,9 +20,8 @@ export const load: PageLoad = async ({ url, route }) => {
|
||||
limit,
|
||||
search,
|
||||
page,
|
||||
users: await sdk.forProject.users.list(
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('')],
|
||||
search
|
||||
)
|
||||
users: await sdk
|
||||
.forProject(params.region, params.project)
|
||||
.users.list([Query.limit(limit), Query.offset(offset), Query.orderDesc('')], search)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
title: $organization?.name
|
||||
},
|
||||
{
|
||||
href: `${base}/project-${$project?.$id}`,
|
||||
href: `${base}/project-${$project.region}-${$project?.$id}`,
|
||||
title: $project?.name
|
||||
},
|
||||
{
|
||||
href: `${base}/project-${$project?.$id}/auth`,
|
||||
href: `${base}/project-${$project.region}-${$project?.$id}/auth`,
|
||||
title: 'Auth'
|
||||
}
|
||||
];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { Modal, CustomId } from '$lib/components';
|
||||
import { InputText, Button } from '$lib/elements/forms';
|
||||
@@ -18,7 +19,9 @@
|
||||
|
||||
const create = async () => {
|
||||
try {
|
||||
const team = await sdk.forProject.teams.create(id ?? ID.unique(), name);
|
||||
const team = await sdk
|
||||
.forProject($page.params.region, $page.params.project)
|
||||
.teams.create(id ?? ID.unique(), name);
|
||||
name = '';
|
||||
showCreate = false;
|
||||
showCustomId = false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { Modal, CustomId } from '$lib/components';
|
||||
import { Button, InputPassword, InputEmail, InputText, InputPhone } from '$lib/elements/forms';
|
||||
@@ -19,13 +20,15 @@
|
||||
|
||||
const create = async () => {
|
||||
try {
|
||||
const user = await sdk.forProject.users.create(
|
||||
id ?? ID.unique(),
|
||||
mail || undefined,
|
||||
phone || undefined,
|
||||
pass || undefined,
|
||||
name || undefined
|
||||
);
|
||||
const user = await sdk
|
||||
.forProject($page.params.region, $page.params.project)
|
||||
.users.create(
|
||||
id ?? ID.unique(),
|
||||
mail || undefined,
|
||||
phone || undefined,
|
||||
pass || undefined,
|
||||
name || undefined
|
||||
);
|
||||
mail = pass = name = '';
|
||||
showCreate = false;
|
||||
showDropdown = false;
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
import { canWriteProjects } from '$lib/stores/roles';
|
||||
import { Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
const path = `${base}/project-${projectId}/auth`;
|
||||
const path = `${base}/project-${page.params.region}-${page.params.project}/auth`;
|
||||
const tabs = [
|
||||
{
|
||||
href: path,
|
||||
|
||||
@@ -17,14 +17,13 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import type { PageData } from './$types';
|
||||
import { writable } from 'svelte/store';
|
||||
import { canWriteTeams } from '$lib/stores/roles';
|
||||
import { Icon, Layout, Table } from '@appwrite.io/pink-svelte';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import DualTimeView from '$lib/components/dualTimeView.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
export let data;
|
||||
|
||||
const project = page.params.project;
|
||||
const teamCreated = async (event: CustomEvent<Models.Team<Record<string, unknown>>>) => {
|
||||
@@ -79,7 +78,10 @@
|
||||
total={data.teams.total} />
|
||||
{:else if data.search}
|
||||
<EmptySearch target="teams" search={data.search} hidePagination={data.teams.total === 0}>
|
||||
<Button secondary size="s" href={`${base}/project-${page.params.project}/auth/teams`}>
|
||||
<Button
|
||||
secondary
|
||||
size="s"
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/auth/teams`}>
|
||||
Clear Search
|
||||
</Button>
|
||||
</EmptySearch>
|
||||
|
||||
@@ -4,10 +4,10 @@ import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ url, route }) => {
|
||||
export const load: PageLoad = async ({ url, route, params }) => {
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const limit = getLimit(params.project, url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
@@ -15,9 +15,8 @@ export const load: PageLoad = async ({ url, route }) => {
|
||||
limit,
|
||||
search,
|
||||
page,
|
||||
teams: await sdk.forProject.teams.list(
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('')],
|
||||
search
|
||||
)
|
||||
teams: await sdk
|
||||
.forProject(params.region, params.project)
|
||||
.teams.list([Query.limit(limit), Query.offset(offset), Query.orderDesc('')], search)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
return {
|
||||
header: Header,
|
||||
breadcrumbs: Breadcrumbs,
|
||||
team: await sdk.forProject.teams.get(params.team)
|
||||
team: await sdk.forProject(params.region, params.project).teams.get(params.team)
|
||||
};
|
||||
} catch (e) {
|
||||
error(e.code, e.message);
|
||||
|
||||
+7
-5
@@ -6,15 +6,17 @@ import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, url, route }) => {
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const limit = getLimit(params.project, url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
logs: await sdk.forProject.teams.listLogs(params.team, [
|
||||
Query.limit(limit),
|
||||
Query.offset(offset)
|
||||
])
|
||||
logs: await sdk
|
||||
.forProject(params.region, params.project)
|
||||
.databases.listDocumentLogs(params.database, params.collection, params.document, [
|
||||
Query.limit(limit),
|
||||
Query.offset(offset)
|
||||
])
|
||||
};
|
||||
};
|
||||
|
||||
+4
-3
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import { Breadcrumbs } from '$lib/layout';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { project } from '../../../store';
|
||||
@@ -11,15 +12,15 @@
|
||||
title: $organization?.name
|
||||
},
|
||||
{
|
||||
href: `${base}/project-${$project.$id}`,
|
||||
href: `${base}/project-${$page.params.region}-${$page.params.project}`,
|
||||
title: $project?.name
|
||||
},
|
||||
{
|
||||
href: `${base}/project-${$project?.$id}/auth`,
|
||||
href: `${base}/project-${$page.params.region}-${$page.params.project}/auth`,
|
||||
title: 'Auth'
|
||||
},
|
||||
{
|
||||
href: `${base}/project-${$project?.$id}/auth/teams/team-${$team?.$id}`,
|
||||
href: `${base}/project-${$page.params.region}-${$page.params.project}/auth/teams/team-${$team?.$id}`,
|
||||
title: $team?.name
|
||||
}
|
||||
];
|
||||
|
||||
+11
-9
@@ -19,15 +19,17 @@
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
const user = await sdk.forProject.teams.createMembership(
|
||||
teamId,
|
||||
roles,
|
||||
email || undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
`${page.url.origin}${base}/invite`,
|
||||
name || undefined
|
||||
);
|
||||
const user = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.teams.createMembership(
|
||||
teamId,
|
||||
roles,
|
||||
email || undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
`${page.url.origin}${base}/invite`,
|
||||
name || undefined
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${name ? name : email} created successfully`
|
||||
|
||||
+4
-5
@@ -18,15 +18,14 @@
|
||||
|
||||
async function deleteMembership() {
|
||||
try {
|
||||
await sdk.forProject.teams.deleteMembership(
|
||||
selectedMembership.teamId,
|
||||
selectedMembership.$id
|
||||
);
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.teams.deleteMembership(selectedMembership.teamId, selectedMembership.$id);
|
||||
showDelete = false;
|
||||
dispatch('deleted');
|
||||
trackEvent(Submit.MemberDelete);
|
||||
await goto(
|
||||
`${base}/project-${page.params.project}/auth/teams/team-${selectedMembership.teamId}/members`
|
||||
`${base}/project-${page.params.region}-${page.params.project}/auth/teams/team-${selectedMembership.teamId}/members`
|
||||
);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
|
||||
+2
-2
@@ -15,10 +15,10 @@
|
||||
|
||||
async function deleteTeam() {
|
||||
try {
|
||||
await sdk.forProject.teams.delete(team.$id);
|
||||
await sdk.forProject(page.params.region, page.params.project).teams.delete(team.$id);
|
||||
showDelete = false;
|
||||
trackEvent(Submit.TeamDelete);
|
||||
await goto(`${base}/project-${page.params.project}/auth/teams`);
|
||||
await goto(`${base}/project-${page.params.region}-${page.params.project}/auth/teams`);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
trackError(e, Submit.TeamDelete);
|
||||
|
||||
+3
-4
@@ -6,9 +6,7 @@
|
||||
import { Cover, CoverTitle } from '$lib/layout';
|
||||
import { team } from './store';
|
||||
|
||||
const projectId = page.params.project;
|
||||
const teamId = page.params.team;
|
||||
const path = `${base}/project-${projectId}/auth/teams/team-${teamId}`;
|
||||
const path = `${base}/project-${page.params.region}-${page.params.project}/auth/teams/team-${page.params.team}`;
|
||||
const tabs = [
|
||||
{
|
||||
href: path,
|
||||
@@ -32,7 +30,8 @@
|
||||
|
||||
<Cover>
|
||||
<svelte:fragment slot="header">
|
||||
<CoverTitle href={`${base}/project-${projectId}/auth/teams`}>
|
||||
<CoverTitle
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/auth/teams`}>
|
||||
{$team?.name}
|
||||
</CoverTitle>
|
||||
<Id value={$team?.$id} event="team">{$team?.$id}</Id>
|
||||
|
||||
+8
-6
@@ -10,17 +10,19 @@ export const load: PageLoad = async ({ params, depends, url, route }) => {
|
||||
const teamId = params.team;
|
||||
const page = getPage(url);
|
||||
const search = getSearch(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
const limit = getLimit(params.project, url, route, PAGE_LIMIT);
|
||||
const offset = pageToOffset(page, limit);
|
||||
|
||||
return {
|
||||
offset,
|
||||
search,
|
||||
limit,
|
||||
memberships: await sdk.forProject.teams.listMemberships(
|
||||
teamId,
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('')],
|
||||
search
|
||||
)
|
||||
memberships: await sdk
|
||||
.forProject(params.region, params.project)
|
||||
.teams.listMemberships(
|
||||
teamId,
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('')],
|
||||
search
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -18,7 +18,9 @@
|
||||
|
||||
async function updateName() {
|
||||
try {
|
||||
await sdk.forProject.teams.updateName(page.params.team, teamName);
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.teams.updateName(page.params.team, teamName);
|
||||
await invalidate(Dependencies.TEAM);
|
||||
addNotification({
|
||||
message: 'Name has been updated',
|
||||
|
||||
+4
-1
@@ -10,6 +10,7 @@
|
||||
import { team } from './store';
|
||||
import { Icon, Layout } from '@appwrite.io/pink-svelte';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
$: if (prefs) {
|
||||
if (JSON.stringify(prefs) !== JSON.stringify(Object.entries($team.prefs))) {
|
||||
@@ -37,7 +38,9 @@
|
||||
try {
|
||||
let updatedPrefs = Object.fromEntries(prefs);
|
||||
|
||||
await sdk.forProject.teams.updatePrefs($team.$id, updatedPrefs);
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.teams.updatePrefs($team.$id, updatedPrefs);
|
||||
await invalidate(Dependencies.TEAM);
|
||||
arePrefsDisabled = true;
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@
|
||||
EmailTemplateType,
|
||||
EmailTemplateLocale
|
||||
} from '@appwrite.io/console';
|
||||
import { Accordion, Layout, Alert, Badge, Link, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Accordion, Alert, Layout, Link, Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
let emailOpen = null;
|
||||
let emailOpen = 'verification';
|
||||
$: emailVerificationOpen = emailOpen === 'verification';
|
||||
$: emailMagicSessionOpen = emailOpen === 'magicSession';
|
||||
$: emailOtpSessionOpen = emailOpen === 'otpSession';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
export const load = async () => {
|
||||
const codes = await sdk.forProject.locale.listCodes();
|
||||
export const load = async ({ params }) => {
|
||||
const codes = await sdk.forProject(params.region, params.project).locale.listCodes();
|
||||
return {
|
||||
localeCodes: codes.localeCodes
|
||||
};
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import { Container, Usage } from '$lib/layout';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
export let data;
|
||||
$: total = data.usersTotal;
|
||||
$: count = data.users;
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<Usage
|
||||
path={`${base}/project-${page.params.project}/auth/usage`}
|
||||
path={`${base}/project-${page.params.region}-${page.params.project}/auth/usage`}
|
||||
countMetadata={{
|
||||
legend: 'Users',
|
||||
title: 'Registered users'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user