diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e84ba9c8b..a700a4add 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -99,7 +99,7 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0 with: images: appwrite/console tags: | diff --git a/package.json b/package.json index 77499856c..1b4f96e89 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,11 @@ }, "dependencies": { "@ai-sdk/svelte": "^1.1.24", - "@appwrite.io/console": "^1.10.0", + "@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2408", "@appwrite.io/pink-icons": "0.25.0", - "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@e6b154b", + "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0b77850", "@appwrite.io/pink-legacy": "^1.0.3", - "@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@e6b154b", + "@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0b77850", "@popperjs/core": "^2.11.8", "@sentry/sveltekit": "^8.38.0", "@stripe/stripe-js": "^3.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7aa3f74a5..05e7c465f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,20 +12,20 @@ importers: specifier: ^1.1.24 version: 1.1.24(svelte@5.25.3)(zod@3.24.3) '@appwrite.io/console': - specifier: ^1.10.0 - version: 1.10.0 + specifier: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2408 + version: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2408 '@appwrite.io/pink-icons': specifier: 0.25.0 version: 0.25.0 '@appwrite.io/pink-icons-svelte': - specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@e6b154b - version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@e6b154b(svelte@5.25.3) + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0b77850 + version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0b77850(svelte@5.25.3) '@appwrite.io/pink-legacy': specifier: ^1.0.3 version: 1.0.3 '@appwrite.io/pink-svelte': - specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@e6b154b - version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@e6b154b(svelte@5.25.3) + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0b77850 + version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0b77850(svelte@5.25.3) '@popperjs/core': specifier: ^2.11.8 version: 2.11.8 @@ -257,16 +257,17 @@ packages: '@analytics/type-utils@0.6.2': resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==} - '@appwrite.io/console@1.10.0': - resolution: {integrity: sha512-7ErAZgS0djmB41ZFXPTlJH5kBNvJeKv2UHOEcI6uAOyXO4UoVWlhQk0D/3oktNylwOsr/K/98EWfsUDeYbq68w==} + '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2408': + resolution: {tarball: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2408} + version: 1.10.0 '@appwrite.io/pink-icons-svelte@2.0.0-RC.1': resolution: {integrity: sha512-iLFlV55hj8mGuAbmxJGenxN5RaZMmVT4GJb9dv/MP1xBAtYibFq7JvBcxm18qV2KU8c31Rntf+Ub4GL7HwqTYg==} peerDependencies: svelte: ^4.0.0 - '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@e6b154b': - resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@e6b154b} + '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0b77850': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0b77850} version: 2.0.0-RC.1 peerDependencies: svelte: ^4.0.0 @@ -280,8 +281,8 @@ packages: '@appwrite.io/pink-legacy@1.0.3': resolution: {integrity: sha512-GGde5fmPhs+s6/3aFeMPc/kKADG/gTFkYQSy6oBN8pK0y0XNCLrZZgBv+EBbdhwdtqVEWXa0X85Mv9w7jcIlwQ==} - '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@e6b154b': - resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@e6b154b} + '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0b77850': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0b77850} version: 2.0.0-RC.2 peerDependencies: svelte: ^4.0.0 @@ -3645,13 +3646,13 @@ snapshots: '@analytics/type-utils@0.6.2': {} - '@appwrite.io/console@1.10.0': {} + '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2408': {} '@appwrite.io/pink-icons-svelte@2.0.0-RC.1(svelte@5.25.3)': dependencies: svelte: 5.25.3 - '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@e6b154b(svelte@5.25.3)': + '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@0b77850(svelte@5.25.3)': dependencies: svelte: 5.25.3 @@ -3664,7 +3665,7 @@ snapshots: '@appwrite.io/pink-icons': 1.0.0 the-new-css-reset: 1.11.3 - '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@e6b154b(svelte@5.25.3)': + '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@0b77850(svelte@5.25.3)': dependencies: '@appwrite.io/pink-icons-svelte': 2.0.0-RC.1(svelte@5.25.3) '@floating-ui/dom': 1.6.13 diff --git a/src/lib/components/billing/alerts/projectsLimit.svelte b/src/lib/components/billing/alerts/projectsLimit.svelte index cd3a0a3ee..8d7b10b33 100644 --- a/src/lib/components/billing/alerts/projectsLimit.svelte +++ b/src/lib/components/billing/alerts/projectsLimit.svelte @@ -9,17 +9,22 @@ upgradeURL } from '$lib/stores/billing'; import { currentPlan } from '$lib/stores/organization'; - import { onMount } from 'svelte'; import SelectProjectCloud from './selectProjectCloud.svelte'; import { toLocaleDate } from '$lib/helpers/date'; - let showSelectProject: boolean = $state(false); + let selectedProjects: string[] = $state([]); - onMount(() => { - selectedProjects = page.data.organization?.projects || []; + let showSelectProject: boolean = $state(false); + + const organizationId = $derived(page.data.organization?.$id); + + $effect(() => { + if (organizationId) { + selectedProjects = page.data.organization?.projects || []; + } }); - + {#if $currentPlan && $currentPlan.projects > 0 && !hideBillingHeaderRoutes.includes(page.url.pathname)} - import { type Models } from '@appwrite.io/console'; - import { Alert, Button, Table } from '@appwrite.io/pink-svelte'; + import { type Models, Query } from '@appwrite.io/console'; + import { Alert, Button, Skeleton, Table } from '@appwrite.io/pink-svelte'; import { Modal } from '$lib/components'; - import { onMount } from 'svelte'; import { sdk } from '$lib/stores/sdk'; import { addNotification } from '$lib/stores/notifications'; import { invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; import { billingProjectsLimitDate } from '$lib/stores/billing'; - import { page } from '$app/state'; import { toLocaleDate, toLocaleDateTime } from '$lib/helpers/date'; import { currentPlan } from '$lib/stores/organization'; let { showSelectProject = $bindable(false), - selectedProjects = $bindable([]) + selectedProjects = $bindable([]), + organizationId }: { showSelectProject: boolean; selectedProjects: string[]; + organizationId: string; } = $props(); - let projects = $state>([]); - let error = $state(null); + let loading = $state(false); + let projectsLoadingError = $state(null); - onMount(() => { - projects = page.data.allProjects?.projects || []; - }); + let error = $state(null); + let projects = $state>([]); let projectsToArchive = $derived( projects.filter((project) => !selectedProjects.includes(project.$id)) @@ -37,6 +36,7 @@ projects[0].teamId, selectedProjects ); + showSelectProject = false; invalidate(Dependencies.ORGANIZATION); addNotification({ @@ -67,46 +67,95 @@ return result; } + + $effect(() => { + if (!showSelectProject) return; + + const areProjectsLoaded = projects.length > 0; + const teamIdInLoadedProjects = areProjectsLoaded ? projects[0].teamId : null; + + if (organizationId != teamIdInLoadedProjects) { + loading = true; + + sdk.forConsole.projects + .list([ + Query.equal('teamId', organizationId), + Query.limit(1000) // Get all projects for organization + ]) + .then((loadedProjects) => (projects = loadedProjects.projects)) + .catch((err) => (projectsLoadingError = err.message)) + .finally(() => (loading = false)); + } + }); - + - Choose which two projects to keep. Projects over the limit will be blocked after this date. + Choose which {$currentPlan?.projects || 2} projects to keep. Projects over the limit will be + blocked after this date. - {#if error} - {error} - {/if} - - - Project Name - Created - - {#each projects as project} - - {project.name} - {toLocaleDateTime(project.$createdAt)} - - {/each} - - {#if selectedProjects.length > $currentPlan?.projects} -
- You can only select {$currentPlan?.projects} projects. Please deselect others to continue. + + {#if loading} +
+ + + Project Name + Created + + + {#each Array.from({ length: 5 }) as _} + + + + + + + + + {/each} +
- {/if} - {#if selectedProjects.length === $currentPlan?.projects} - - - {@html formatProjectsToArchive()} - will be archived. - - + {:else if projectsLoadingError} + {projectsLoadingError} + {:else} + {#if error} + {error} + {/if} + + + + Project Name + Created + + {#each projects as project} + + {project.name} + {toLocaleDateTime(project.$createdAt)} + + {/each} + + + {#if selectedProjects.length > $currentPlan?.projects} +
+ You can only select {$currentPlan?.projects} projects. Please deselect others to continue. +
+ {/if} + + {#if selectedProjects.length === $currentPlan?.projects} + + + {@html formatProjectsToArchive()} + will be archived. + + + {/if} {/if} (showSelectProject = false)} @@ -115,3 +164,13 @@ >Save + + diff --git a/src/lib/components/billing/paymentModal.svelte b/src/lib/components/billing/paymentModal.svelte index 72accfd10..92aec21a8 100644 --- a/src/lib/components/billing/paymentModal.svelte +++ b/src/lib/components/billing/paymentModal.svelte @@ -42,7 +42,7 @@ const card = await submitStripeCard(name, page?.params?.organization ?? null); if (card && Object.hasOwn(card, 'id')) { - if ((card as PaymentMethod).card.country === 'US') { + if ((card as PaymentMethod).card?.country === 'US') { paymentMethod = card as PaymentMethod; showState = true; return; diff --git a/src/lib/components/billing/planSelection.svelte b/src/lib/components/billing/planSelection.svelte index 846a887f2..900fbe3d3 100644 --- a/src/lib/components/billing/planSelection.svelte +++ b/src/lib/components/billing/planSelection.svelte @@ -9,8 +9,8 @@ import { page } from '$app/state'; export let billingPlan: Tier; - export let anyOrgFree = false; export let isNewOrg = false; + export let anyOrgFree = false; export let selfService = true; $: plans = Object.values(page.data.plans.plans) as Plan[]; diff --git a/src/lib/components/breadcrumbs.svelte b/src/lib/components/breadcrumbs.svelte index da4bfd5c0..e2ecda32f 100644 --- a/src/lib/components/breadcrumbs.svelte +++ b/src/lib/components/breadcrumbs.svelte @@ -22,7 +22,9 @@ import { base } from '$app/paths'; import { currentPlan, newOrgModal } from '$lib/stores/organization'; import { Click, trackEvent } from '$lib/actions/analytics'; - import type { Models } from '@appwrite.io/console'; + import { type Models, Query } from '@appwrite.io/console'; + import { sdk } from '$lib/stores/sdk'; + import { page } from '$app/state'; type Organization = { name: string; @@ -63,15 +65,15 @@ } } = createMenu(); - let isLoadingProjects = true; + let isLoadingProjects = false; let loadedProjects: Models.ProjectList = { total: 0, projects: [] }; export let organizations: Organization[] = []; export let currentProject: Models.Project | null = null; - export let projects: Promise = Promise.resolve(loadedProjects); let projectsBottomSheetOpen = false; let organisationBottomSheetOpen = false; + let projectsBottomSheet: Promise = null; function createOrg() { trackEvent(Click.OrganizationClickCreate, { source: 'breadcrumbs' }); @@ -99,13 +101,25 @@ } }; - async function createProjectsBottomSheet(organization: Organization): Promise { + async function createProjectsBottomSheet( + organization: Organization + ): Promise { + if (!isOnProjects) return null; + isLoadingProjects = true; + // null on non-org/project path like `onboarding`. - loadedProjects = (await projects) ?? loadedProjects; + loadedProjects = + (await sdk.forConsole.projects.list([ + Query.equal('teamId', organizationId ?? page.data.currentOrgId), + Query.limit(5), + Query.orderDesc('$updatedAt') + ])) ?? loadedProjects; + for (const project of loadedProjects.projects) { project.region ??= 'default'; } + isLoadingProjects = false; const createProjectItem = { @@ -185,8 +199,6 @@ $: selectedOrg = organizations.find((org) => org.isSelected); - $: projectsBottomSheet = createProjectsBottomSheet(selectedOrg); - $: organizationsBottomSheet = createOrganizationBottomSheet(selectedOrg); $: correctPlanName = @@ -198,6 +210,20 @@ : selectedOrg?.tierName; // fallback $: derivedKey = `${selectedOrg?.$id}-${currentProject?.$id}`; + + $: organizationId = currentProject?.teamId; + + $: isOnProjects = page.route.id.includes('project-[region]-[project]'); + + $: shouldReloadProjects = isLoadingProjects + ? false + : currentProject && loadedProjects.projects.length + ? loadedProjects.projects[0].teamId != currentProject.teamId + : !loadedProjects.projects.length; + + $: if (shouldReloadProjects) { + projectsBottomSheet = createProjectsBottomSheet(selectedOrg); + } @@ -380,7 +406,9 @@ {#await projectsBottomSheet then menu} - + {#if menu} + + {/if} {/await} {/key} diff --git a/src/lib/components/navbar.svelte b/src/lib/components/navbar.svelte index c87845b4e..51ed33e43 100644 --- a/src/lib/components/navbar.svelte +++ b/src/lib/components/navbar.svelte @@ -1,15 +1,6 @@ @@ -61,7 +74,8 @@ helper={error || helper} state={error ? 'error' : 'default'} on:invalid={handleInvalid} - on:input> + on:input={coerceToNumber} + on:change={coerceToNumber}> diff --git a/src/lib/helpers/regions.ts b/src/lib/helpers/regions.ts index 82010ee0a..ce3d4e27e 100644 --- a/src/lib/helpers/regions.ts +++ b/src/lib/helpers/regions.ts @@ -15,8 +15,15 @@ export function filterRegions(regions: Models.ConsoleRegion[]): RegionOption[] { return regions .filter((region) => region.$id !== 'default') .sort((a, b) => { - if (a.disabled && !b.disabled) return 1; - if (!a.disabled && b.disabled) return -1; + // Check if regions are truly available (not disabled and available) + const aAvailable = !a.disabled && a.available; + const bAvailable = !b.disabled && b.available; + + // Prioritize truly available regions + if (aAvailable && !bAvailable) return -1; + if (!aAvailable && bAvailable) return 1; + + // Within the same availability group, sort alphabetically return a.name.localeCompare(b.name); }) .map((region) => ({ diff --git a/src/lib/helpers/templateSource.ts b/src/lib/helpers/templateSource.ts new file mode 100644 index 000000000..d24b67e77 --- /dev/null +++ b/src/lib/helpers/templateSource.ts @@ -0,0 +1,26 @@ +import type { Models } from '@appwrite.io/console'; + +/** + * Build VCS repo URL from the template response model. + * Example (GitHub): https://github.com/appwrite/templates-for-sites + */ +export function getTemplateSourceUrl( + t: Models.TemplateSite | Models.TemplateFunction +): string | null { + const owner = t.providerOwner; + const repo = t.providerRepositoryId; + const provider = t.vcsProvider; // e.g., "github" + + if (!owner || !repo || !provider) return null; + + // Map provider → host (extend if needed) + const hostMap: Record = { + github: 'github.com', + gitlab: 'gitlab.com', + bitbucket: 'bitbucket.org' + }; + + const host = hostMap[provider.toLowerCase()] ?? provider; // fallback + + return `https://${host}/${owner}/${repo}`; +} diff --git a/src/lib/images/promos/auto-increment-dark.png b/src/lib/images/promos/auto-increment-dark.png deleted file mode 100644 index b63c3891c..000000000 Binary files a/src/lib/images/promos/auto-increment-dark.png and /dev/null differ diff --git a/src/lib/images/promos/auto-increment-light.png b/src/lib/images/promos/auto-increment-light.png deleted file mode 100644 index b2c174fc4..000000000 Binary files a/src/lib/images/promos/auto-increment-light.png and /dev/null differ diff --git a/src/lib/images/promos/timestamp-overrides-dark.png b/src/lib/images/promos/timestamp-overrides-dark.png new file mode 100644 index 000000000..569abb8e0 Binary files /dev/null and b/src/lib/images/promos/timestamp-overrides-dark.png differ diff --git a/src/lib/images/promos/timestamp-overrides-light.png b/src/lib/images/promos/timestamp-overrides-light.png new file mode 100644 index 000000000..adf0c88ec Binary files /dev/null and b/src/lib/images/promos/timestamp-overrides-light.png differ diff --git a/src/lib/layout/createProject.svelte b/src/lib/layout/createProject.svelte index 2199f0a4b..f8302245c 100644 --- a/src/lib/layout/createProject.svelte +++ b/src/lib/layout/createProject.svelte @@ -50,6 +50,30 @@ {#if showTitle} Create your project {/if} + + {#if projectsLimited} + {#if isProPlan} + + You've reached your limit of 2 projects included on the Pro plan. Each extra + project costs $15/month. + + {:else} + + Extra projects are available on paid plans for an additional fee + + + + + {/if} + {/if} + @@ -72,27 +96,6 @@ - {#if projectsLimited} - {#if isProPlan} - - You've reached your limit of 2 projects included on the Pro plan. Each extra - project costs $15/month. - - {:else} - - Extra projects are available on paid plans for an additional fee - - - - - {/if} - {/if} - {#if isCloud && regions.length > 0} @@ -23,7 +23,6 @@ direction="row" alignItems="center" gap={$isSmallViewport ? 'm' : 'l'} - inline={$isTabletViewport} justifyContent="flex-start"> ⓒ {currentYear} Appwrite. All rights reserved. @@ -54,63 +53,37 @@ - {#if isCloud && $isSmallViewport} -
- - {#if $version} - {#if isCloud} - - {/if} - - Version {$version} - - - - - {/if} - - -
- {/if} + - {#if isCloud} - {#if !$isSmallViewport} + alignItems="center" + wrap={$isSmallViewport ? 'wrap' : 'normal'}> + {#if !$isSmallViewport} + {#if isCloud} - - {#if $version} - - Version {$version} - - - - - {/if} + {/if} + + {#if $version} + + Version {$version} + + + + {/if} {/if} @@ -157,6 +130,32 @@ Cookies {/if} + {#if $isSmallViewport} + {#if $version} + + + + + Version {$version} + + {#if isCloud} + + + {/if} + {/if} + {/if}
@@ -180,7 +179,4 @@ margin-inline-end: 2rem; } } - .extra-margin { - margin-block-start: var(--space-2, 4px); - } diff --git a/src/lib/layout/shell.svelte b/src/lib/layout/shell.svelte index fb23bceac..790643c29 100644 --- a/src/lib/layout/shell.svelte +++ b/src/lib/layout/shell.svelte @@ -22,7 +22,6 @@ export let showFooter = true; export let showSideNavigation = false; export let selectedProject: Models.Project = null; - export let projects: Promise = undefined; let yOnMenuOpen: number; let showContentTransition = false; @@ -104,8 +103,6 @@ }; }), - projects: projects, - currentProject: selectedProject }; diff --git a/src/lib/layout/unauthenticated.svelte b/src/lib/layout/unauthenticated.svelte index 9d1afcb2b..b5fe495ea 100644 --- a/src/lib/layout/unauthenticated.svelte +++ b/src/lib/layout/unauthenticated.svelte @@ -10,6 +10,7 @@ import type { Campaign } from '$lib/stores/campaigns'; import { Typography, Layout, Avatar } from '@appwrite.io/pink-svelte'; import { getCampaignImageUrl } from '$routes/(public)/card/helpers'; + import { isSmallViewport } from '$lib/stores/viewport'; export const imgLight = LoginLight; export const imgDark = LoginDark; @@ -44,7 +45,7 @@
@@ -159,7 +160,6 @@
-
diff --git a/src/routes/(console)/bottomAlerts.ts b/src/routes/(console)/bottomAlerts.ts index 1fec84852..1fb9f6672 100644 --- a/src/routes/(console)/bottomAlerts.ts +++ b/src/routes/(console)/bottomAlerts.ts @@ -1,12 +1,12 @@ import { isCloud } from '$lib/system'; import { isSameDay } from '$lib/helpers/date'; import { type BottomModalAlertItem, showBottomModalAlert } from '$lib/stores/bottom-alerts'; -import AutoIncrementDark from '$lib/images/promos/auto-increment-dark.png'; -import AutoIncrementLight from '$lib/images/promos/auto-increment-light.png'; import AtomicNumericOperationsDark from '$lib/images/promos/atomic-numeric-operations-dark.png'; import AtomicNumericOperationsLight from '$lib/images/promos/atomic-numeric-operations-light.png'; import AppwriteGeneralAvailabiltyLight from '$lib/images/promos/appwrite-general-availability-light.png'; import AppwriteGeneralAvailabiltyDark from '$lib/images/promos/appwrite-general-availability-dark.png'; +import TimestampOverridesDark from '$lib/images/promos/timestamp-overrides-dark.png'; +import TimestampOverridesLight from '$lib/images/promos/timestamp-overrides-light.png'; const listOfPromotions: BottomModalAlertItem[] = []; @@ -30,21 +30,21 @@ if (isCloud) { }, show: true }; - const autoIncrementPromo: BottomModalAlertItem = { - id: 'modal:auto_increment_announcement', + const timestampOverridesPromo: BottomModalAlertItem = { + id: 'modal:timestamp_overrides_announcement', src: { - dark: AutoIncrementDark, - light: AutoIncrementLight + dark: TimestampOverridesDark, + light: TimestampOverridesLight }, - title: 'Announcing Auto-increment support', + title: 'Announcing Timestamp Overrides', message: - 'Get a built-in numeric identifier that increases predictably with every new document added.', + 'Move historical data into Appwrite without losing context or disrupting chronological accuracy.', plan: 'free', importance: 8, scope: 'project', cta: { text: 'Read announcement', - link: () => 'https://appwrite.io/blog/post/announcing-auto-increment-support', + link: () => 'https://appwrite.io/blog/post/announcing-timestamp-overrides', external: true, hideOnClick: true }, @@ -71,9 +71,9 @@ if (isCloud) { show: true }; listOfPromotions.push( + timestampOverridesPromo, appwriteGeneralAvailabiltyPromo, - atomicNumericOperationsPromo, - autoIncrementPromo + atomicNumericOperationsPromo ); } diff --git a/src/routes/(console)/organization-[organization]/+page.svelte b/src/routes/(console)/organization-[organization]/+page.svelte index a622d9523..313430fe3 100644 --- a/src/routes/(console)/organization-[organization]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/+page.svelte @@ -114,9 +114,8 @@ trackError(e, Submit.ProjectCreate); } }; - onMount(async () => { - checkPricingRefAndRedirect(page.url.searchParams); - }); + + onMount(async () => checkPricingRefAndRedirect(page.url.searchParams)); function findRegion(project: Models.Project) { return $regionsStore.regions.find((region) => region.$id === project.region); @@ -140,7 +139,10 @@ ); - +
@@ -167,7 +169,7 @@
- {#if isCloud && $currentPlan?.projects && $currentPlan?.projects > 0 && data.organization.projects.length > 0 && data.projects.total > 2 && $canWriteProjects} + {#if isCloud && $currentPlan?.projects && $currentPlan?.projects > 0 && data.organization.projects.length > 0 && data.projects.total > $currentPlan.projects && $canWriteProjects} diff --git a/src/routes/(console)/organization-[organization]/billing/replaceCard.svelte b/src/routes/(console)/organization-[organization]/billing/replaceCard.svelte index a0b17f774..a0d5de92d 100644 --- a/src/routes/(console)/organization-[organization]/billing/replaceCard.svelte +++ b/src/routes/(console)/organization-[organization]/billing/replaceCard.svelte @@ -54,7 +54,7 @@ } else { const card = await submitStripeCard(name, organization.$id); if (card && Object.hasOwn(card, 'id')) { - if ((card as PaymentMethod).card.country === 'US') { + if ((card as PaymentMethod).card?.country === 'US') { paymentMethod = card as PaymentMethod; showState = true; return; diff --git a/src/routes/(console)/organization-[organization]/billing/retryPaymentModal.svelte b/src/routes/(console)/organization-[organization]/billing/retryPaymentModal.svelte index 3a9fbfb29..7e39f10ee 100644 --- a/src/routes/(console)/organization-[organization]/billing/retryPaymentModal.svelte +++ b/src/routes/(console)/organization-[organization]/billing/retryPaymentModal.svelte @@ -66,7 +66,7 @@ } else { const card = await submitStripeCard(name, $organization.$id); if (card && Object.hasOwn(card, 'id')) { - if ((card as PaymentMethod).card.country === 'US') { + if ((card as PaymentMethod).card?.country === 'US') { paymentMethod = card as PaymentMethod; showState = true; return; diff --git a/src/routes/(console)/organization-[organization]/billing/wizard/paymentDetails.svelte b/src/routes/(console)/organization-[organization]/billing/wizard/paymentDetails.svelte index 8e1dd12da..fd27def7e 100644 --- a/src/routes/(console)/organization-[organization]/billing/wizard/paymentDetails.svelte +++ b/src/routes/(console)/organization-[organization]/billing/wizard/paymentDetails.svelte @@ -34,7 +34,7 @@ } else { const card = await submitStripeCard(name, $organization.$id); if (card && Object.hasOwn(card, 'id')) { - if ((card as PaymentMethod).card.country === 'US') { + if ((card as PaymentMethod).card?.country === 'US') { paymentMethod = card as PaymentMethod; showState = true; return; diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index f899405b0..682bf7bd8 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -150,8 +150,7 @@ await goto(previousPage); addNotification({ type: 'success', - isHtml: true, - message: `${$organization.name} plan has been successfully updated.` + message: `${$organization.name} plan has been successfully updated.` }); trackEvent(Submit.OrganizationDowngrade, { @@ -262,9 +261,11 @@ } } - $: isUpgrade = $plansInfo.get(selectedPlan)?.order > $currentPlan?.order; - $: isDowngrade = $plansInfo.get(selectedPlan)?.order < $currentPlan?.order; - $: isButtonDisabled = $organization?.billingPlan === selectedPlan; + $: isUpgrade = $plansInfo.get(selectedPlan).order > $currentPlan?.order; + $: isDowngrade = $plansInfo.get(selectedPlan).order < $currentPlan?.order; + $: isButtonDisabled = + $organization?.billingPlan === selectedPlan || + (isDowngrade && selectedPlan === BillingPlan.FREE && data.hasFreeOrgs); @@ -297,8 +298,21 @@ selfService={data.selfService} anyOrgFree={data.hasFreeOrgs} /> + {#if isDowngrade && selectedPlan === BillingPlan.FREE && data.hasFreeOrgs} + + To downgrade this organization, first migrate or delete one of your + existing paid organizations. + + + {/if} + {#if isDowngrade} - {#if selectedPlan === BillingPlan.FREE} + {#if selectedPlan === BillingPlan.FREE && !data.hasFreeOrgs} {:else if selectedPlan === BillingPlan.PRO && data.organization.billingPlan === BillingPlan.SCALE && collaborators?.length > 0} {@const extraMembers = collaborators?.length ?? 0} @@ -364,7 +378,7 @@ id="members" /> {/if} - {#if isDowngrade && selectedPlan === BillingPlan.FREE} + {#if isDowngrade && selectedPlan === BillingPlan.FREE && !data.hasFreeOrgs}
{:else if data.organization.billingPlan !== BillingPlan.CUSTOM} - + {/if} diff --git a/src/routes/(console)/organization-[organization]/createProjectCloud.svelte b/src/routes/(console)/organization-[organization]/createProjectCloud.svelte index a0236076f..408c06982 100644 --- a/src/routes/(console)/organization-[organization]/createProjectCloud.svelte +++ b/src/routes/(console)/organization-[organization]/createProjectCloud.svelte @@ -12,8 +12,8 @@ import { Dependencies } from '$lib/constants'; export let teamId: string; - export let showCreateProjectCloud: boolean; export let projects: number; + export let showCreateProjectCloud: boolean; export let regions: Array = []; let id: string = null; diff --git a/src/routes/(console)/organization-[organization]/domains/domain-[domain]/table.svelte b/src/routes/(console)/organization-[organization]/domains/domain-[domain]/table.svelte index 8fde81408..ab71bb13d 100644 --- a/src/routes/(console)/organization-[organization]/domains/domain-[domain]/table.svelte +++ b/src/routes/(console)/organization-[organization]/domains/domain-[domain]/table.svelte @@ -11,6 +11,7 @@ import { PaginationWithLimit } from '$lib/components'; import { ActionMenu, + Badge, Button, InteractiveText, Icon, @@ -79,11 +80,24 @@ {record.type} {:else if column.id === 'value'} - {@const isARecord = record.value === 'a.a.a.a'} - {#if isARecord} + {@const isARecord = record.type.toLowerCase() === 'a'} + {@const isAAAARecord = record.type.toLowerCase() === 'aaaa'} + {@const isCAARecord = record.type.toLowerCase() === 'caa'} + {#if record.lock && (isARecord || isAAAARecord)}
- Served by Appwrite + +
+ {:else if record.lock && isCAARecord} + +
+
{:else} diff --git a/src/routes/(console)/project-[region]-[project]/auth/user-[user]/sessions/+page.svelte b/src/routes/(console)/project-[region]-[project]/auth/user-[user]/sessions/+page.svelte index f39e39bca..dbea6505e 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/user-[user]/sessions/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/user-[user]/sessions/+page.svelte @@ -1,18 +1,10 @@ - + + Sessions {#if data.sessions.total} - + {/if} - +
+ {#if data.sessions.total} - - - Browser and device - Session - Location - IP - - - - {#each data.sessions.sessions as session} - {@const browser = getBrowser(session.clientCode)} - - -
-
- {#if browser} - {session.clientName} - {:else} - - {/if} -
-

- {session.clientName} - {session.clientVersion} on {session.osName} - {session.osVersion} -

- {#if session.current} - + + + Client + Location + IP + + + {#each data.sessions.sessions as session} + {@const browser = getBrowser(session.clientCode)} + + + +
+ {#if browser} + {session.clientName} + {:else} + {/if}
- - - {session.clientType} - {session.countryName} - {session.ip} - - - - - {/each} - - + + {session.clientName} + {session.clientVersion} on {session.osName} + {session.osVersion} + + {#if session.current} + + {/if} +
+
+ + {#if session.countryCode !== '--'} + {session.countryName} + {:else} + Unknown + {/if} + + + {session.ip} + + + + +
+ {/each} +
{:else}
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte index da920f4e7..f1eb3eb44 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte @@ -123,16 +123,12 @@ // Reactive statements $: collections = collectionList?.collections?.filter((n) => n.$id !== $collection.$id) ?? []; - $: if (editing) { - way = data.twoWay ? 'two' : 'one'; - } else { - if (way === 'two') { - data.twoWay = true; - if (!data.twoWayKey) { - data.twoWayKey = camelize($collection.name); - } - } else { - data.twoWay = false; + $: if (!editing && way) { + data.twoWay = way === 'two'; + if (way === 'two' && !data.twoWayKey) { + data.twoWayKey = camelize($collection.name); + } else if (way === 'one') { + data.twoWayKey = undefined; } } @@ -158,6 +154,7 @@ bind:group={way} name="one" value="one" + disabled={editing} icon={IconArrowSmRight}> One Relation attribute within this collection @@ -166,6 +163,7 @@ bind:group={way} name="two" value="two" + disabled={editing} icon={IconSwitchHorizontal}> One Relation attribute within this collection and another within the related collection @@ -178,6 +176,7 @@ placeholder="Select a collection" bind:value={data.relatedCollection} on:change={updateKeyName} + disabled={editing} options={collections?.map((n) => ({ value: n.$id, label: `${n.name} (${n.$id})` })) ?? []} /> {#if data?.relatedCollection} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte index 1d6858eac..297cb1381 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/indexes/createIndex.svelte @@ -14,8 +14,6 @@ import { type Attributes, collection, indexes } from '../store'; import { Icon, Layout } from '@appwrite.io/pink-svelte'; import { IconPlus } from '@appwrite.io/pink-icons-svelte'; - import { flags } from '$lib/flags'; - export let showCreateIndex = false; export let externalAttribute: Attributes = null; @@ -39,8 +37,6 @@ let attributeList = [{ value: '', order: '', length: null }]; - const showLengths = flags.showIndexLengths(page.data); - function generateIndexKey() { let indexKeys = $indexes.map((index) => index.key); @@ -152,7 +148,7 @@ placeholder="Select Order" /> - {#if selectedType === IndexType.Key && showLengths} + {#if selectedType === IndexType.Key} @@ -43,14 +39,12 @@ id={`value-${selectedIndex.orders[i]}`} value={selectedIndex.orders[i]} readonly /> - {#if showLengths} - - {/if} + {/each} {/if} diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/store.ts b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/store.ts index 3e36a4f57..b99f1c12b 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/store.ts +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/store.ts @@ -3,6 +3,13 @@ import { writable } from 'svelte/store'; export const columns = writable([ { id: '$id', title: 'Execution ID', type: 'string', width: { min: 200, max: 250 } }, + { + id: 'deploymentId', + title: 'Deployment ID', + type: 'string', + width: { min: 210 }, + hide: true + }, { id: 'requestPath', title: 'Path', @@ -10,7 +17,6 @@ export const columns = writable([ width: { min: 200 }, format: 'string' }, - { id: 'trigger', title: 'Trigger', diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/table.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/table.svelte index f54637771..1df28df61 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/table.svelte @@ -84,6 +84,8 @@ {#key column.id} {log.$id} {/key} + {:else if column.id === 'deploymentId'} + {log.deploymentId} {:else if column.id === '$createdAt'} {:else if column.id === 'requestPath'} diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateBuildCommand.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateBuildCommand.svelte index 91c6eff22..b119c3c87 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateBuildCommand.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateBuildCommand.svelte @@ -37,7 +37,8 @@ func.providerRepositoryId || undefined, func.providerBranch || undefined, func.providerSilentMode || undefined, - func.providerRootDirectory || undefined + func.providerRootDirectory || undefined, + func.specification || undefined ); await invalidate(Dependencies.FUNCTION); addNotification({ diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/table.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/table.svelte index d4691d150..b9d29b855 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/table.svelte @@ -227,7 +227,7 @@ - + {selectedRows.length > 1 ? 'deployments' : 'deployment'} selected diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/components/OnboardingPlatformCard.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/components/OnboardingPlatformCard.svelte index 3b3105ab6..815249835 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/components/OnboardingPlatformCard.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/components/OnboardingPlatformCard.svelte @@ -49,6 +49,10 @@ height: var(--icon-size); color: var(--icon-color); } + + & :global(img) { + inline-size: var(--icon-size) !important; + } } :global(.theme-dark) { diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte index ec30089b7..ef3305dbd 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte @@ -24,7 +24,7 @@ import ConnectionLine from './components/ConnectionLine.svelte'; import OnboardingPlatformCard from './components/OnboardingPlatformCard.svelte'; import { PlatformType } from '@appwrite.io/console'; - import { isCloud } from '$lib/system'; + import { project } from '../../store'; let showExitModal = false; let isPlatformCreated = false; @@ -35,11 +35,9 @@ const gitCloneCode = '\ngit clone https://github.com/appwrite/starter-for-android\ncd starter-for-android\n'; - const updateConfigCode = isCloud - ? `const val APPWRITE_PROJECT_ID = "${projectId}"` - : `const val APPWRITE_PROJECT_ID = "${projectId}" -const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}" - `; + const configCode = `const val APPWRITE_PROJECT_ID = "${projectId}" +const val APPWRITE_PROJECT_NAME = "${$project.name}" +const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}"`; async function createAndroidPlatform() { try { @@ -57,6 +55,12 @@ const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page. trackEvent(Submit.PlatformCreate, { type: 'android' }); + + addNotification({ + type: 'success', + message: 'Platform created.' + }); + invalidate(Dependencies.PROJECT); invalidate(Dependencies.PLATFORMS); } catch (error) { @@ -158,7 +162,7 @@ const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page. {#if isPlatformCreated} -
+
1. If you're starting a new project, you can clone our starter kit from @@ -171,14 +175,12 @@ const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.
2. Open the file and update the configuration - settings. + >2. Open the file + and update the configuration settings.
- +
{#if isPlatformCreated} -
+
1. If you're starting a new project, you can clone our starter kit from @@ -206,7 +210,7 @@ APPWRITE_PUBLIC_ENDPOINT: "${sdk.forProject(page.params.region, page.params.proj
- +
- Go to dashboard + Skip, go to dashboard {/if} diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte index 04b2831ec..bf29f22aa 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte @@ -25,7 +25,7 @@ import ConnectionLine from './components/ConnectionLine.svelte'; import OnboardingPlatformCard from './components/OnboardingPlatformCard.svelte'; import { PlatformType } from '@appwrite.io/console'; - import { isCloud } from '$lib/system'; + import { project } from '../../store'; let showExitModal = false; let isPlatformCreated = false; @@ -36,11 +36,11 @@ const gitCloneCode = '\ngit clone https://github.com/appwrite/starter-for-flutter\ncd starter-for-flutter\n'; - const updateConfigCode = isCloud - ? `static const String APPWRITE_PROJECT_ID = "${projectId}"` - : `static const String APPWRITE_PROJECT_ID = "${projectId}" -static const String APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}" - `; + const configCode = `class Environment { + static const String appwriteProjectId = '${projectId}'; + static const String appwriteProjectName = '${$project.name}'; + static const String appwritePublicEndpoint = '${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}'; +}`; export let platform: PlatformType = PlatformType.Flutterandroid; @@ -127,6 +127,11 @@ static const String APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.reg type: platform }); + addNotification({ + type: 'success', + message: 'Platform created.' + }); + invalidate(Dependencies.PROJECT); invalidate(Dependencies.PLATFORMS); } catch (error) { @@ -263,7 +268,7 @@ static const String APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.reg {#if isPlatformCreated} -
+
1. If you're starting a new project, you can clone our starter kit from @@ -276,16 +281,18 @@ static const String APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.reg
2. Open the file - and update the configuration settings. + >2. Replace + to reflect the values below:
- +
3. Run the app on a connected device or simulator, then click the 3. Run the app on a connected device or simulator using , then click the button to verify the setup. @@ -343,7 +350,7 @@ static const String APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.reg secondary disabled={isCreatingPlatform} href={location.pathname}> - Go to dashboard + Skip, go to dashboard {/if} diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte index edbd6a355..a8ef1c9fa 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte @@ -25,6 +25,7 @@ import ConnectionLine from './components/ConnectionLine.svelte'; import OnboardingPlatformCard from './components/OnboardingPlatformCard.svelte'; import { PlatformType } from '@appwrite.io/console'; + import { project } from '../../store'; let showExitModal = false; let isPlatformCreated = false; @@ -36,6 +37,7 @@ '\ngit clone https://github.com/appwrite/starter-for-react-native\ncd starter-for-react-native\n'; const updateConfigCode = `EXPO_PUBLIC_APPWRITE_PROJECT_ID=${projectId} +EXPO_PUBLIC_APPWRITE_PROJECT_NAME="${$project.name}" EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}`; export let platform: PlatformType = PlatformType.Reactnativeandroid; @@ -91,6 +93,11 @@ EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.p type: platform }); + addNotification({ + type: 'success', + message: 'Platform created.' + }); + invalidate(Dependencies.PROJECT); invalidate(Dependencies.PLATFORMS); } catch (error) { @@ -210,7 +217,7 @@ EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.p {#if isPlatformCreated} -
+
1. If you're starting a new project, you can clone our starter kit from @@ -235,7 +242,13 @@ EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.p 3. Run the app on a connected device or simulator, then click the 3. Run the app on a connected device or simulator using followed by , then click the button to verify the setup. @@ -290,7 +303,7 @@ EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.p secondary disabled={isCreatingPlatform} href={location.pathname}> - Go to dashboard + Skip, go to dashboard {/if} diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte index 14b4a0358..f686e4a59 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte @@ -128,7 +128,15 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p smallIcon: IconAngular, portNumber: 4200, runCommand: 'npm run start', - updateConfigCode: `appwriteEndpoint: '${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}',\nappwriteProjectId: '${projectId}',\nappwriteProjectName: '${$project.name}'` + updateConfigCode: `export const environment: { + appwriteEndpoint: string; + appwriteProjectId: string; + appwriteProjectName: string; +} = { + appwriteEndpoint: '${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}', + appwriteProjectId: '${projectId}', + appwriteProjectName: '${$project.name}' +};` }, { key: 'js', @@ -167,6 +175,11 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p type: platform }); + addNotification({ + type: 'success', + message: 'Platform created.' + }); + invalidate(Dependencies.PROJECT); invalidate(Dependencies.PLATFORMS); } catch (error) { @@ -273,7 +286,7 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p {#if isPlatformCreated && !isChangingFramework} -
+
1. If you're starting a new project, you can clone our starter kit from @@ -290,7 +303,7 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p {#if selectedFramework.key === 'angular'} 2. Change 2. Replace to reflect the values below: @@ -303,7 +316,10 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p
- +
(show = true)}> diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/aside.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/aside.svelte index 96294b630..7bf4186e4 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/aside.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/aside.svelte @@ -62,6 +62,7 @@
+ {/if} {#if domain && showAfter} diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte index 3685e4120..08f4f1047 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte @@ -18,23 +18,25 @@ let deployment = $state(data.deployment); onMount(() => { - return sdk.forConsole.client.subscribe( - 'console', - async (response: RealtimeResponseEvent) => { - if ( - response.events.includes( - `sites.${data.site.$id}.deployments.${data.deployment.$id}.update` - ) - ) { - deployment = response.payload; - if (response.payload.status === 'ready') { - goto( - `${base}/project-${page.params.region}-${page.params.project}/sites/create-site/finish?site=${data.site.$id}` - ); + return sdk + .forConsoleIn(page.params.region) + .client.subscribe( + 'console', + async (response: RealtimeResponseEvent) => { + if ( + response.events.includes( + `sites.${data.site.$id}.deployments.${data.deployment.$id}.update` + ) + ) { + deployment = response.payload; + if (response.payload.status === 'ready') { + goto( + `${base}/project-${page.params.region}-${page.params.project}/sites/create-site/finish?site=${data.site.$id}` + ); + } } } - } - ); + ); }); diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte index 4ad7bd998..86e81b895 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte @@ -37,6 +37,7 @@ import { connectGitHub } from '$lib/stores/git'; import { getFrameworkIcon } from '$lib/stores/sites'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import { getTemplateSourceUrl } from '$lib/helpers/templateSource'; export let data; @@ -351,6 +352,16 @@ alt={data.template.name} ratio="16/9" /> + + + {@const sourceUrl = getTemplateSourceUrl(data.template)} + {#if sourceUrl} + + {/if} + diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte index 4e5651181..cf798ba1e 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte @@ -30,18 +30,20 @@ let showCancel = $state(false); onMount(() => { - return sdk.forConsole.client.subscribe( - 'console', - async (response: RealtimeResponseEvent) => { - if ( - response.events.includes( - `sites.${page.params.site}.deployments.${page.params.deployment}.update` - ) - ) { - await invalidate(Dependencies.DEPLOYMENT); + return sdk + .forConsoleIn(page.params.region) + .client.subscribe( + 'console', + async (response: RealtimeResponseEvent) => { + if ( + response.events.includes( + `sites.${page.params.site}.deployments.${page.params.deployment}.update` + ) + ) { + await invalidate(Dependencies.DEPLOYMENT); + } } - } - ); + ); }); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/table.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/table.svelte index fc380e684..c6ebfea6f 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/table.svelte @@ -155,7 +155,7 @@ - + {selectedRows.length > 1 ? 'deployments' : 'deployment'} selected diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/store.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/store.ts index 605ad603d..44fb484a7 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/store.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/store.ts @@ -3,6 +3,13 @@ import { writable } from 'svelte/store'; export const columns = writable([ { id: '$id', title: 'Log ID', type: 'string', width: { min: 200, max: 250 } }, + { + id: 'deploymentId', + title: 'Deployment ID', + type: 'string', + width: { min: 210 }, + hide: true + }, { id: 'requestPath', title: 'Path', @@ -10,7 +17,6 @@ export const columns = writable([ width: { min: 480 }, format: 'string' }, - { id: 'requestMethod', title: 'Method', diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/table.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/table.svelte index eefe0aa0b..9aef64d84 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/table.svelte @@ -74,6 +74,8 @@ {#key column.id} {log.$id} {/key} + {:else if column.id === 'deploymentId'} + {log.deploymentId} {:else if column.id === 'requestMethod'} {log.requestMethod} diff --git a/src/routes/(public)/invite/+page.svelte b/src/routes/(public)/invite/+page.svelte index 2b44f2eb9..cf4b837c4 100644 --- a/src/routes/(public)/invite/+page.svelte +++ b/src/routes/(public)/invite/+page.svelte @@ -25,7 +25,7 @@ await sdk.forConsole.teams.updateMembershipStatus(teamId, membershipId, userId, secret); addNotification({ type: 'success', - message: 'Successfully logged in.' + message: 'Successfully joined the organization.' }); await goto(`${base}/organization-${teamId}`); trackEvent(Submit.MembershipUpdateStatus); diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index ed25aafc4..9892099a1 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -1,16 +1,16 @@ - {'status' in page.error - ? page.error.status || 'Invalid Argument' - : 'Invalid Argument'} - {page.error.message} - + + + + The page you're looking for doesn't exist. + + + diff --git a/static/css/loading.css b/static/css/loading.css index aa2b8324a..f4b292985 100644 --- a/static/css/loading.css +++ b/static/css/loading.css @@ -38,7 +38,7 @@ body { visibility: hidden; position: absolute; max-width: 100%; - bottom: 60px; + bottom: 20px; left: 50%; transform: translate(-50%, -50%); }