From b1df97a4c33effd5ca7bbbbe7d3da11202c0cced Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 20 Jun 2025 18:47:23 +0530 Subject: [PATCH] svelte5: cleanups, improvements (#1966) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update: cleanups, improvements. * fix: protocol usage. * update: load failed invoice as non-blocking. * address comments, make stuff faster! * fix: missing type on org loads. * fix: connect button shown on org. page. * fix: error check. * update: comment, just ocd things. * update: flip `localStorage` check after `browser` check. * update: comment. * perf: parallelize fetch for faster loads [↓49%] * update: compute things later. * update: don't rely on dependency or reload if scope doesn't allow. * update: simplify. * update: do not load credits if the organization plan does not support it. * update: just some cleaning. * address comments for promise handling. * address comments; remove: unused api calls!!! * address comments; * address comment. * misc. * cleaner endpoint creation. * fix: required to optional. * update: url to quick load. * address comments. * update: load payments on ui. * update: load non-urgent calls on UI. * fix: unnecessary runs of root layout. * reduce: calls to countries, locale api. * reduce: calls to countries, locale api in org settings. * update: simplify api calls and data passing. * address comments. * remove: id from `UsageProjectInfo`. * update: make api call only when needed. * fix: text. * fix: endpoint flag design <> verified by design. * fix: `inline` inner stack so project name has enough space. * fix: tests. * update: improve orgs loading? * update: misc. * remove: todo. * updates: more billing cleanups. * misc. * misc. * fix: tests and a warning. * address comment. * fix: merge leftover issues. * fix: tab selection on overview. * fix: issues with user store on main project layout. * remove: `selectedTab` store. * fix: account menu regression. * fix: reactive logic. use `svelte5` syntax. * Remove trailing comma in invalidate array * remove: unused method. * updates: misc optimizations. * fix: lint. * update: changes after merge. * update: modal size for credits and show loader. * update: misc and PR freeze! * update: use a default credit card icon if one isn't supported by the API. * fix: project loading state as per updated org ID. LAST FIX. * address comments. --------- Co-authored-by: Torsten Dittmann --- package.json | 2 +- pnpm-lock.yaml | 19 +- .../billing/selectPaymentMethod.svelte | 2 +- .../billing/validateCreditModal.svelte | 4 +- .../bottom-sheet/SheetMenuBlock.svelte | 2 +- src/lib/components/breadcrumbs.svelte | 200 +++++++++--------- src/lib/components/columnSelector.svelte | 4 +- src/lib/components/confirm.svelte | 2 + src/lib/components/copy.svelte | 8 +- .../components/creditCardBrandImage.svelte | 16 +- src/lib/components/id.svelte | 26 +-- src/lib/components/modal.svelte | 3 +- src/lib/components/navbar.svelte | 26 ++- src/lib/components/regionEndpoint.svelte | 55 ++--- src/lib/components/sidebar.svelte | 2 +- src/lib/elements/forms/button.svelte | 7 +- src/lib/helpers/onboarding.ts | 13 +- src/lib/layout/shell.svelte | 18 +- src/lib/sdk/billing.ts | 18 ++ src/lib/stores/billing.ts | 36 +++- src/lib/stores/git.ts | 6 +- src/routes/(console)/+layout.svelte | 35 +-- src/routes/(console)/+layout.ts | 89 ++++---- .../(console)/account/payments/+page.svelte | 5 +- .../(console)/account/payments/+page.ts | 11 +- .../account/payments/addressModal.svelte | 5 +- .../account/payments/billingAddress.svelte | 17 +- .../account/payments/editAddressModal.svelte | 13 +- .../(console)/create-organization/+page.ts | 1 + .../+layout.svelte | 3 +- .../organization-[organization]/+layout.ts | 55 +++-- .../organization-[organization]/+page.svelte | 7 +- .../organization-[organization]/+page.ts | 10 +- .../billing/+page.svelte | 18 +- .../billing/+page.ts | 42 ++-- .../billing/availableCredit.svelte | 28 ++- .../billing/billingAddress.svelte | 23 +- .../billing/paymentHistory.svelte | 39 +++- .../billing/paymentMethods.svelte | 17 +- .../billing/planSummary.svelte | 5 +- .../billing/replaceCard.svelte | 7 +- .../change-plan/+page.svelte | 115 ++++++---- .../change-plan/+page.ts | 42 +--- .../createMember.svelte | 8 +- .../createProjectCloud.svelte | 63 +++--- .../deleteMember.svelte | 6 +- .../organization-[organization]/header.svelte | 98 +++++---- .../settings/+page.svelte | 8 +- .../settings/+page.ts | 7 +- .../settings/BAA.svelte | 6 +- .../settings/BAAModal.svelte | 10 +- .../settings/Soc2.svelte | 5 +- .../settings/Soc2Modal.svelte | 10 +- .../settings/deleteOrganizationModal.svelte | 5 +- .../organization-[organization]/store.ts | 2 + .../usage/[[invoice]]/+page.svelte | 37 ++-- .../usage/[[invoice]]/+page.ts | 72 ++++--- .../usage/[[invoice]]/ProjectBreakdown.svelte | 14 +- .../project-[region]-[project]/+layout.ts | 67 +++--- .../project-[region]-[project]/+page.ts | 14 +- .../functions/templates/+page.ts | 35 ++- .../templates/template-[template]/+page.ts | 3 +- .../overview/+layout.svelte | 2 +- .../overview/+page.ts | 8 +- .../overview/dev-keys/+page.ts | 5 +- .../overview/header.svelte | 39 ++-- .../overview/keys/+page.ts | 3 - .../overview/platforms/+page.svelte | 6 +- .../overview/platforms/+page.ts | 5 +- .../overview/platforms/wizard/store.ts | 37 ---- .../overview/store.ts | 2 - .../settings/updateInstallations.svelte | 6 +- .../sites/create-site/templates/+page.svelte | 4 +- .../sites/create-site/templates/+page.ts | 69 +++--- .../project-[region]-[project]/store.ts | 7 +- src/routes/(console)/store.ts | 10 +- 76 files changed, 908 insertions(+), 821 deletions(-) diff --git a/package.json b/package.json index a5f75727f..219891efb 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@ai-sdk/svelte": "^1.1.24", - "@appwrite.io/console": "^1.9.0", + "@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5", "@appwrite.io/pink-icons": "0.25.0", "@appwrite.io/pink-icons-svelte": "^2.0.0-RC.1", "@appwrite.io/pink-legacy": "^1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9fd6d1195..f62d185a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^1.1.24 version: 1.1.24(svelte@5.25.3)(zod@3.24.3) '@appwrite.io/console': - specifier: ^1.9.0 - version: 1.9.0 + specifier: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5 + version: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5 '@appwrite.io/pink-icons': specifier: 0.25.0 version: 0.25.0 @@ -257,8 +257,9 @@ packages: '@analytics/type-utils@0.6.2': resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==} - '@appwrite.io/console@1.9.0': - resolution: {integrity: sha512-g8+zfdBF8mz7tRUER4CGVe5FHWQVLp8TlY/UOGCZ2TgUF1qnpNu/DhiQgph8uF+QZ9jDKCLAAZlP5//9t7ckWA==} + '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5': + resolution: {tarball: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5} + version: 1.9.0 '@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@973fff20fff9995eff19c3f9c270cb676d2dde12': resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@973fff20fff9995eff19c3f9c270cb676d2dde12} @@ -1348,8 +1349,8 @@ packages: '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} - '@types/react@18.3.23': - resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==} + '@types/react@18.3.22': + resolution: {integrity: sha512-vUhG0YmQZ7kL/tmKLrD3g5zXbXXreZXB3pmROW8bg3CnLnpjkRVwUlLne7Ufa2r9yJ8+/6B73RzhAek5TBKh2Q==} '@types/remarkable@2.0.8': resolution: {integrity: sha512-eKXqPZfpQl1kOADjdKchHrp2gwn9qMnGXhH/AtZe0UrklzhGJkawJo/Y/D0AlWcdWoWamFNIum8+/nkAISQVGg==} @@ -3643,7 +3644,7 @@ snapshots: '@analytics/type-utils@0.6.2': {} - '@appwrite.io/console@1.9.0': {} + '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5': {} '@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@973fff20fff9995eff19c3f9c270cb676d2dde12(svelte@5.25.3)': dependencies: @@ -4807,7 +4808,7 @@ snapshots: '@types/prop-types@15.7.14': {} - '@types/react@18.3.23': + '@types/react@18.3.22': dependencies: '@types/prop-types': 15.7.14 csstype: 3.1.3 @@ -6768,7 +6769,7 @@ snapshots: svelte-motion@0.12.2(svelte@5.25.3): dependencies: - '@types/react': 18.3.23 + '@types/react': 18.3.22 framesync: 6.1.2 popmotion: 11.0.5 style-value-types: 5.1.2 diff --git a/src/lib/components/billing/selectPaymentMethod.svelte b/src/lib/components/billing/selectPaymentMethod.svelte index 7dfe14a2e..9a7265c8b 100644 --- a/src/lib/components/billing/selectPaymentMethod.svelte +++ b/src/lib/components/billing/selectPaymentMethod.svelte @@ -11,9 +11,9 @@ import { invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; - export let methods: PaymentList; export let value: string; export let taxId = ''; + export let methods: PaymentList; let showTaxId = false; let showPaymentModal = false; diff --git a/src/lib/components/billing/validateCreditModal.svelte b/src/lib/components/billing/validateCreditModal.svelte index b2c3f6190..e73ea2949 100644 --- a/src/lib/components/billing/validateCreditModal.svelte +++ b/src/lib/components/billing/validateCreditModal.svelte @@ -48,7 +48,7 @@ } - + Credits will be applied automatically to your next invoice. @@ -62,6 +62,6 @@ - + diff --git a/src/lib/components/bottom-sheet/SheetMenuBlock.svelte b/src/lib/components/bottom-sheet/SheetMenuBlock.svelte index a8d65c4be..6bc3d2cab 100644 --- a/src/lib/components/bottom-sheet/SheetMenuBlock.svelte +++ b/src/lib/components/bottom-sheet/SheetMenuBlock.svelte @@ -11,7 +11,7 @@ {#if menu?.title} {menu.title} {/if} - + {#each menu.items as menuItem} {#if menuItem.href} import { createMenubar, melt } from '@melt-ui/svelte'; - import { Badge, Icon, type SheetMenu, ActionMenu, Card } from '@appwrite.io/pink-svelte'; + import { + Badge, + Icon, + type SheetMenu, + Layout, + ActionMenu, + Card, + Skeleton + } from '@appwrite.io/pink-svelte'; import { IconChevronDown, IconChevronRight, @@ -14,20 +22,13 @@ import { base } from '$app/paths'; import { currentPlan, newOrgModal } from '$lib/stores/organization'; import { Click, trackEvent } from '$lib/actions/analytics'; - import { page } from '$app/stores'; + import type { Models } from '@appwrite.io/console'; - type Project = { - name: string; - $id: string; - isSelected: boolean; - region: string; - }; type Organization = { name: string; $id: string; tierName: string; isSelected: boolean; - projects: Array; }; const { @@ -62,13 +63,15 @@ } } = createMenu(); + let isLoadingProjects = true; + 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); - $: selectedOrg = organizations.find((organization) => organization.isSelected); - $: selectedProject = $page.data.project; - - let organisationBottomSheetOpen = false; let projectsBottomSheetOpen = false; + let organisationBottomSheetOpen = false; function createOrg() { trackEvent(Click.OrganizationClickCreate, { source: 'breadcrumbs' }); @@ -96,85 +99,76 @@ } }; - $: organizationsBottomSheet = !selectedOrg - ? switchOrganization - : ({ - top: { - items: [ - { - name: 'Organization overview', - href: `${base}/organization-${selectedOrg?.$id}` - } - ] - }, - bottom: - organizations.length > 1 - ? { - items: [ - { - name: 'Switch organization', - trailingIcon: IconChevronRight, - subMenu: switchOrganization - } - ] - } - : { - items: [ - { - name: 'Create organization', - leadingIcon: IconPlus, - onClick: createOrg - } - ] - } - } satisfies SheetMenu); + async function createProjectsBottomSheet(organization: Organization): Promise { + isLoadingProjects = true; + loadedProjects = await projects; + isLoadingProjects = false; - $: projectsBottomSheet = { - top: - selectedOrg?.projects.length > 1 - ? { - title: 'Switch project', - items: !selectedOrg - ? [] - : selectedOrg?.projects - .map((project, index) => { - if (index < 4) { - return { - name: project.name, - href: `${base}/project-${project.region}-${project.$id}/overview` - }; - } else if (index === 4) { - return { - name: 'All projects', - href: `${base}/organization-${selectedOrg?.$id}` - }; - } - return null; - }) - .filter((project) => project !== null) - } - : { + const createProjectItem = { + name: 'Create project', + trailingIcon: IconPlus, + href: `${base}/organization-${organization?.$id}?create-project` + }; + + if (loadedProjects.total > 1 && selectedOrg) { + const projectLinks = loadedProjects.projects.slice(0, 4).map((project) => ({ + name: project.name, + href: `${base}/project-${project.region}-${project.$id}/overview/platforms` + })); + + if (loadedProjects.projects.length > 4) { + projectLinks.push({ + name: 'All projects', + href: `${base}/organization-${selectedOrg.$id}` + }); + } + + return { + top: { title: 'Switch project', items: projectLinks }, + bottom: { items: [createProjectItem] } + }; + } + + return { + top: { items: [createProjectItem] }, + bottom: { items: [createProjectItem] } + }; + } + + function createOrganizationBottomSheet(organization: Organization) { + return !organization + ? switchOrganization + : ({ + top: { items: [ { - name: 'Create project', - trailingIcon: IconPlus, - href: `${base}/organization-${selectedOrg?.$id}?create-project` + name: 'Organization overview', + href: `${base}/organization-${organization?.$id}` } ] }, - bottom: - selectedOrg?.projects.length > 1 - ? { - items: [ - { - name: 'Create project', - trailingIcon: IconPlus, - href: `${base}/organization-${selectedOrg?.$id}?create-project` - } - ] - } - : undefined - } satisfies SheetMenu; + bottom: + organizations.length > 1 + ? { + items: [ + { + name: 'Switch organization', + trailingIcon: IconChevronRight, + subMenu: switchOrganization + } + ] + } + : { + items: [ + { + name: 'Create organization', + leadingIcon: IconPlus, + onClick: createOrg + } + ] + } + } satisfies SheetMenu); + } function onResize() { if ((organisationBottomSheetOpen || projectsBottomSheetOpen) && !$isSmallViewport) { @@ -183,6 +177,12 @@ } } + $: selectedOrg = organizations.find((org) => org.isSelected); + + $: projectsBottomSheet = createProjectsBottomSheet(selectedOrg); + + $: organizationsBottomSheet = createOrganizationBottomSheet(selectedOrg); + $: correctPlanName = // the plan names are hardcoded in some cases and are not available locally, // so we rely on the plan's source of truth - `$currentPlan` @@ -191,7 +191,7 @@ ? $currentPlan.name : selectedOrg?.tierName; // fallback - $: derivedKey = `${selectedOrg?.$id}-${selectedProject?.$id}`; + $: derivedKey = `${selectedOrg?.$id}-${currentProject?.$id}`; @@ -220,7 +220,7 @@ organisationBottomSheetOpen = true; }} aria-label="Open organizations tab"> - {selectedOrg?.name ?? 'Organization'} @@ -302,7 +302,7 @@ - {#if selectedOrg && selectedProject} + {#if selectedOrg && currentProject} / {#if !$isSmallViewport} {:else} @@ -319,20 +319,28 @@ class="trigger" on:click={() => (projectsBottomSheetOpen = true)} aria-label="Open projects tab"> - {selectedProject.name} + {currentProject.name} {/if}