update: cleanups, improvements.

This commit is contained in:
Darshan
2025-06-02 13:47:53 +05:30
parent d5e00ffd83
commit 2a50e11485
7 changed files with 123 additions and 82 deletions
+59 -5
View File
@@ -4,8 +4,8 @@
import Footer from '$lib/layout/footer.svelte';
import Shell from '$lib/layout/shell.svelte';
import { app } from '$lib/stores/app';
import { newOrgModal, organization, type Organization } from '$lib/stores/organization';
import { database, checkForDatabaseBackupPolicies } from '$lib/stores/database';
import { newOrgModal, organization, type Organization } from '$lib/stores/organization';
import { wizard } from '$lib/stores/wizard';
import { afterUpdate, onMount } from 'svelte';
import { loading } from '$routes/store';
@@ -36,7 +36,7 @@
import { stripe } from '$lib/stores/stripe';
import MobileSupportModal from './wizard/support/mobileSupportModal.svelte';
import { showSupportModal } from './wizard/support/store';
import { activeHeaderAlert, consoleVariables } from './store';
import { activeHeaderAlert, consoleVariables, version } from './store';
import { headerAlert } from '$lib/stores/headerAlert';
import { UsageRates } from '$lib/components/billing';
import { base } from '$app/paths';
@@ -54,6 +54,10 @@
} from '@appwrite.io/pink-icons-svelte';
import type { LayoutData } from './$types';
import type { NavbarProject } from '$lib/components/navbar.svelte';
import { sdk } from '$lib/stores/sdk';
import { type Models, Query } from '@appwrite.io/console';
export let data: LayoutData;
function kebabToSentenceCase(str: string) {
return str
@@ -62,11 +66,56 @@
.join(' ');
}
const isAssistantEnabled = $consoleVariables?._APP_ASSISTANT_ENABLED === true;
let loadingVersion = false;
let loadingConsoleVars = false;
let loadingProjectsForShell = false;
export let data: LayoutData;
function loadConsoleVariables() {
if (!$version && !loadingVersion) {
const { endpoint, project } = sdk.forConsole.client.config;
$: loadedProjects = data.projects.map((project) => {
loadingVersion = true;
fetch(`${endpoint}/health/version`, {
headers: { 'X-Appwrite-Project': project }
})
.then((res) => res.json().catch(() => null))
.then((data) => version.set(data?.version))
.finally(() => (loadingVersion = false));
}
if (!$consoleVariables && !loadingConsoleVars) {
loadingConsoleVars = true;
sdk.forConsole.console
.variables()
.then((vars) => consoleVariables.set(vars))
.finally(() => (loadingConsoleVars = false));
}
}
let latestProjects: Models.Project[] = [];
function loadProjectsForShell() {
if (latestProjects.length || loadingProjectsForShell) return;
loadingProjectsForShell = true;
sdk.forConsole.projects
.list([
Query.equal('teamId', data.currentOrgId),
Query.limit(5),
Query.orderDesc('$updatedAt')
])
.then((res) => {
latestProjects = res.projects ?? [];
for (const project of latestProjects) {
project.region ??= 'default';
}
})
.finally(() => (loadingProjectsForShell = false));
}
$: isAssistantEnabled = $consoleVariables?._APP_ASSISTANT_ENABLED === true;
$: loadedProjects = latestProjects.map((project) => {
return {
name: project?.name,
$id: project.$id,
@@ -262,6 +311,11 @@
rank: -1
}
]);
loadProjectsForShell();
loadConsoleVariables();
onMount(async () => {
loading.set(false);
if (!localStorage.getItem('feedbackElapsed')) {
+35 -53
View File
@@ -1,71 +1,53 @@
import { Dependencies } from '$lib/constants';
import type { Plan } from '$lib/sdk/billing';
import type { Tier } from '$lib/stores/billing';
import { sdk } from '$lib/stores/sdk';
import { isCloud } from '$lib/system';
import type { LayoutLoad } from './$types';
import { Query, type Models } from '@appwrite.io/console';
import { Dependencies } from '$lib/constants';
import type { Tier } from '$lib/stores/billing';
import type { Plan, PlanList } from '$lib/sdk/billing';
export const load: LayoutLoad = async ({ params, fetch, depends, parent }) => {
export const load: LayoutLoad = async ({ params, depends, parent }) => {
await parent();
depends(Dependencies.RUNTIMES);
depends(Dependencies.CONSOLE_VARIABLES);
depends(Dependencies.ORGANIZATION);
const prefs = await sdk.forConsole.account.getPrefs();
const [preferences, plansArray, organizations] = await loadPromises();
const { endpoint, project } = sdk.forConsole.client.config;
const versionPromise = fetch(`${endpoint}/health/version`, {
headers: {
'X-Appwrite-Project': project
}
}).then((response) => response.json() as { version?: string });
const plansInfo = toPlanMap(plansArray);
const variablesPromise = sdk.forConsole.console.variables();
const [data, variables] = await Promise.all([versionPromise, variablesPromise]);
let plansInfo = new Map<Tier, Plan>();
if (isCloud) {
const plansArray = await sdk.forConsole.billing.getPlansInfo();
plansInfo = plansArray.plans.reduce((map, plan) => {
map.set(plan.$id as Tier, plan);
return map;
}, new Map<Tier, Plan>());
}
const organizations = !isCloud
? await sdk.forConsole.teams.list()
: await sdk.forConsole.billing.listOrganization();
let projects: Models.Project[] = [];
let currentOrgId = params.organization ? params.organization : prefs.organization;
if (!currentOrgId && organizations.teams.length > 0) {
currentOrgId = organizations.teams[0].$id;
}
if (currentOrgId) {
const orgProjects = await sdk.forConsole.projects.list([
Query.equal('teamId', currentOrgId),
Query.limit(5),
Query.orderDesc('$updatedAt')
]);
projects = orgProjects.projects.length > 0 ? orgProjects.projects : [];
}
// set `default` if no region!
for (const project of projects) {
project.region ??= 'default';
}
const currentOrgId =
params.organization ??
preferences.organization ??
(organizations.teams.length > 0 ? organizations.teams[0].$id : undefined);
return {
consoleVariables: variables,
version: data?.version ?? null,
plansInfo,
roles: [],
scopes: [],
projects: projects,
currentProjectId: params.project ?? '',
organizations: organizations
preferences,
currentOrgId,
organizations,
currentProjectId: params.project ?? ''
};
};
async function loadPromises() {
return Promise.all([
sdk.forConsole.account.getPrefs(),
isCloud ? sdk.forConsole.billing.getPlansInfo() : Promise.resolve(null),
isCloud ? sdk.forConsole.billing.listOrganization() : sdk.forConsole.teams.list()
]);
}
function toPlanMap(plansArray: PlanList | null): Map<Tier, Plan> {
const map = new Map<Tier, Plan>();
if (!plansArray?.plans.length) return map;
const plans = plansArray.plans;
for (let i = 0; i < plans.length; i++) {
const plan = plans[i];
map.set(plan.$id as Tier, plan);
}
return map;
}
@@ -10,12 +10,13 @@ import { headerAlert } from '$lib/stores/headerAlert';
import ProjectsAtRisk from '$lib/components/billing/alerts/projectsAtRisk.svelte';
import { get } from 'svelte/store';
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 }) => {
export const load: LayoutLoad = async ({ params, depends, parent }) => {
const { preferences: prefs } = await parent();
depends(Dependencies.ORGANIZATION);
depends(Dependencies.MEMBERS);
depends(Dependencies.PAYMENT_METHODS);
@@ -41,20 +42,18 @@ export const load: LayoutLoad = async ({ params, depends }) => {
}
}
}
const prefs = await sdk.forConsole.account.getPrefs();
if (prefs.organization !== params.organization) {
const newPrefs = { ...prefs, organization: params.organization };
sdk.forConsole.account.updatePrefs(newPrefs);
void sdk.forConsole.account.updatePrefs(newPrefs);
}
const [organization, members] = await Promise.all([
sdk.forConsole.teams.get(params.organization) as Promise<Organization>,
sdk.forConsole.teams.get(params.organization),
sdk.forConsole.teams.listMemberships(params.organization),
preferences.loadTeamPrefs(params.organization)
preferences.loadTeamPrefs(params.organization),
loadAvailableRegions(params.organization)
]);
await loadAvailableRegions(params.organization);
return {
header: Header,
breadcrumbs: Breadcrumbs,
@@ -65,9 +64,8 @@ export const load: LayoutLoad = async ({ params, depends }) => {
scopes
};
} catch (e) {
const prefs = await sdk.forConsole.account.getPrefs();
const newPrefs = { ...prefs, organization: null };
sdk.forConsole.account.updatePrefs(newPrefs);
void sdk.forConsole.account.updatePrefs(newPrefs);
error(e.code, e.message);
}
};
@@ -155,7 +155,8 @@
{@const platforms = filterPlatforms(
project.platforms.map((platform) => getPlatformInfo(platform.type))
)}
<GridItem1 href={`${base}/project-${project.region}-${project.$id}`}>
<GridItem1
href={`${base}/project-${project.region}-${project.$id}/overview/platforms`}>
<svelte:fragment slot="eyebrow">
{project?.platforms?.length ? project?.platforms?.length : 'No'} apps
</svelte:fragment>
@@ -11,16 +11,18 @@ 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';
import type { Organization } from '$lib/stores/organization';
import { roles as rolesStore, scopes as scopesStore } from '$lib/stores/roles';
import { organization as orgStore, type Organization } from '$lib/stores/organization';
export const load: LayoutLoad = async ({ params, depends }) => {
depends(Dependencies.PROJECT);
let currentPlan: Plan = null;
const orgFromStore: Organization = get(orgStore);
try {
const project = await sdk.forConsole.projects.get(params.project);
const [organization, prefs, regionalConsoleVariables, _] = await Promise.all([
sdk.forConsole.teams.get(project.teamId) as Promise<Organization>,
orgFromStore ? Promise.resolve(orgFromStore) : sdk.forConsole.teams.get(project.teamId),
sdk.forConsole.account.getPrefs(),
sdk.forConsoleIn(project.region).console.variables(),
loadAvailableRegions(project.teamId)
@@ -32,11 +34,18 @@ export const load: LayoutLoad = async ({ params, depends }) => {
});
}
await preferences.loadTeamPrefs(project.teamId);
// get values from saved stores if available!
const [rolesStoreValue, scopesStoreValue] = [get(rolesStore), get(scopesStore)];
const areBothAvailable = !!(rolesStoreValue.length && scopesStoreValue.length);
let roles = isCloud ? [] : defaultRoles;
let scopes = isCloud ? [] : defaultScopes;
if (isCloud) {
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(project.teamId);
const res = await sdk.forConsole.billing.getRoles(project.teamId);
const res = areBothAvailable
? { roles: rolesStoreValue, scopes: scopesStoreValue }
: await sdk.forConsole.billing.getRoles(project.teamId);
roles = res.roles;
scopes = res.scopes;
if (scopes.includes('billing.read')) {
@@ -5,9 +5,8 @@ import type { PageLoad } from './$types';
import { selectedTab } from './store';
export const load: PageLoad = async ({ params }) => {
if (get(selectedTab) === 'keys') {
redirect(302, `${base}/project-${params.region}-${params.project}/overview/keys`);
} else {
redirect(302, `${base}/project-${params.region}-${params.project}/overview/platforms`);
}
const tab = get(selectedTab);
const subroute = ['keys', 'dev-keys'].includes(tab) ? tab : 'platforms';
redirect(302, `${base}/project-${params.region}-${params.project}/overview/${subroute}`);
};
+3 -5
View File
@@ -4,11 +4,9 @@ import type { Organization } from '$lib/stores/organization';
import type { Models } from '@appwrite.io/console';
import { derived, writable } from 'svelte/store';
export const version = derived(page, ($page) => $page.data.version as string | null);
export const consoleVariables = derived(
page,
($page) => $page.data.consoleVariables as Models.ConsoleVariables
);
export const version = writable<string | null>(null);
export const consoleVariables = writable<Models.ConsoleVariables | undefined>(undefined);
export const protocol = derived(page, ($page) =>
($page.data.consoleVariables as Models.ConsoleVariables)?._APP_OPTIONS_FORCE_HTTPS === 'enabled'
? 'https://'