mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
update: cleanups, improvements.
This commit is contained in:
@@ -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')) {
|
||||
|
||||
@@ -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}`);
|
||||
};
|
||||
|
||||
@@ -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://'
|
||||
|
||||
Reference in New Issue
Block a user