Merge branch 'main' of https://github.com/appwrite/console into 1.5.x

This commit is contained in:
Torsten Dittmann
2024-03-08 10:01:23 +01:00
15 changed files with 111 additions and 26 deletions
+3
View File
@@ -3,7 +3,10 @@
<head>
<meta charset="utf-8" />
<meta name="description" content="" />
<link rel="icon" type="image/svg+xml" href="/logos/appwrite-icon.svg" />
<link rel="mask-icon" type="image/png" href="/logos/appwrite-icon.png" />
<link
rel="preload"
href="/fonts/inter/inter-v8-latin-600.woff2"
@@ -0,0 +1,25 @@
<script lang="ts">
import { page } from '$app/stores';
import { BillingPlan } from '$lib/constants';
import { Button } from '$lib/elements/forms';
import { HeaderAlert } from '$lib/layout';
import { orgMissingPaymentMethod } from '$routes/console/store';
</script>
{#if ($orgMissingPaymentMethod.billingPlan === BillingPlan.PRO || $orgMissingPaymentMethod.billingPlan === BillingPlan.SCALE) && !$orgMissingPaymentMethod.paymentMethodId && !$orgMissingPaymentMethod.backupPaymentMethodId && !$page.url.pathname.includes('/console/account')}
<HeaderAlert
type="error"
title={`Payment method required for ${$orgMissingPaymentMethod.name}`}>
<svelte:fragment>
Add a payment method to {$orgMissingPaymentMethod.name} to avoid service interruptions to
your projects.
</svelte:fragment>
<svelte:fragment slot="buttons">
<Button
secondary
href={`/console/organization-${$orgMissingPaymentMethod.$id}/billing`}>
Add payment method
</Button>
</svelte:fragment>
</HeaderAlert>
{/if}
+1 -1
View File
@@ -24,7 +24,7 @@
{#if single}
<article class="card u-grid u-cross-center u-width-full-line common-section">
<div
class="u-flex u-flex-vertical u-cross-center u-gap-24 u-width-full-line u-overflow-hidden">
class="u-flex u-flex-vertical u-cross-center u-gap-24 u-width-full-line u-overflow-hidden u-padding-block-8">
{#if !noMedia}
<button
type="button"
+4 -3
View File
@@ -4,6 +4,7 @@
import { page } from '$app/stores';
import { log } from '$lib/stores/logs';
import { wizard } from '$lib/stores/wizard';
import { activeHeaderAlert } from '$routes/console/store';
export let isOpen = false;
export let showSideNavigation = false;
@@ -47,9 +48,9 @@
class:grid-with-side={showSideNavigation}
class:is-open={isOpen}
class:u-hide={$wizard.show || $log.show || $wizard.cover}
class:is-fixed-layout={$$slots.alert}>
{#if $$slots.alert}
<slot name="alert" />
class:is-fixed-layout={$activeHeaderAlert?.show}>
{#if $activeHeaderAlert?.show}
<svelte:component this={$activeHeaderAlert.component} />
{/if}
<header class="main-header u-padding-inline-end-0">
<button
+18 -2
View File
@@ -1,5 +1,5 @@
import type { Client, Models } from '@appwrite.io/console';
import type { Organization } from '../stores/organization';
import type { Client, Models, Query } from '@appwrite.io/console';
import type { Organization, OrganizationList } from '../stores/organization';
import type { PaymentMethod } from '@stripe/stripe-js';
import type { Tier } from '$lib/stores/billing';
@@ -274,6 +274,22 @@ export class Billing {
this.client = client;
}
async listOrganization(queries: Query[] = []): Promise<OrganizationList> {
const path = `/organizations`;
const params = {
queries
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
'GET',
uri,
{
'content-type': 'application/json'
},
params
);
}
async createOrganization(
organizationId: string,
name: string,
+19 -1
View File
@@ -11,9 +11,10 @@ import PaymentAuthRequired from '$lib/components/billing/alerts/paymentAuthRequi
import { addNotification, notifications } from './notifications';
import { goto } from '$app/navigation';
import { base } from '$app/paths';
import { activeHeaderAlert } from '$routes/console/store';
import { activeHeaderAlert, orgMissingPaymentMethod } from '$routes/console/store';
import MarkedForDeletion from '$lib/components/billing/alerts/markedForDeletion.svelte';
import { BillingPlan } from '$lib/constants';
import MissingPaymentMethod from '$lib/components/billing/alerts/missingPaymentMethod.svelte';
export type Tier = 'tier-0' | 'tier-1' | 'tier-2';
@@ -265,3 +266,20 @@ export function checkForMarkedForDeletion(org: Organization) {
});
}
}
export async function checkForMissingPaymentMethod() {
const orgs = await sdk.forConsole.billing.listOrganization([
Query.notEqual('billingPlan', BillingPlan.STARTER),
Query.isNull('paymentMethodId'),
Query.isNull('backupPaymentMethodId')
]);
if (orgs?.total) {
orgMissingPaymentMethod.set(orgs.teams[0]);
headerAlert.add({
id: 'missingPaymentMethod',
component: MissingPaymentMethod,
show: true,
importance: 8
});
}
}
+5
View File
@@ -22,6 +22,11 @@ export type Organization = Models.Team<Record<string, unknown>> & {
billingPlanDowngrade?: string;
};
export type OrganizationList = {
teams: Organization[];
total: number;
};
export type BillingLimits = {
bandwidth: number;
documents: number;
+6 -1
View File
@@ -19,7 +19,12 @@ export async function initializeStripe() {
isStripeInitialized.set(true);
const methods = await sdk.forConsole.billing.listPaymentMethods();
clientSecret = methods.paymentMethods[0]?.clientSecret;
// Get the client secret from empty payment method if available
clientSecret = methods.paymentMethods?.filter(
(method) => !!method?.clientSecret && !method?.providerMethodId
)[0]?.clientSecret;
// If there is no payment method, create an empty one and get the client secret
if (!clientSecret) {
paymentMethod = await sdk.forConsole.billing.createPaymentMethod();
+3 -6
View File
@@ -19,7 +19,8 @@
checkPaymentAuthorizationRequired,
calculateTrialDay,
paymentExpired,
checkForMarkedForDeletion
checkForMarkedForDeletion,
checkForMissingPaymentMethod
} from '$lib/stores/billing';
import { goto } from '$app/navigation';
import { CommandCenter, registerCommands, registerSearchers } from '$lib/commandCenter';
@@ -236,6 +237,7 @@
if (isCloud && hasStripePublicKey) {
$stripe = await loadStripe(VARS.STRIPE_PUBLIC_KEY);
await checkForMissingPaymentMethod();
}
});
@@ -288,11 +290,6 @@
!$page.url.pathname.includes('/console/account') &&
!$page.url.pathname.includes('/console/card') &&
!$page.url.pathname.includes('/console/onboarding')}>
<svelte:fragment slot="alert">
{#if $activeHeaderAlert?.show}
<svelte:component this={$activeHeaderAlert.component} />
{/if}
</svelte:fragment>
<Header slot="header" />
<SideNavigation slot="side" bind:isOpen />
<slot />
@@ -20,7 +20,7 @@ export const load: LayoutLoad = async ({ params, depends }) => {
if (isCloud) {
await failedInvoice.load(params.organization);
if (!get(failedInvoice)) {
if (get(failedInvoice)) {
headerAlert.add({
show: true,
component: ProjectsAtRisk,
@@ -18,15 +18,18 @@
let name: string;
let showCustomId = false;
let error: string;
let disabled: boolean = false;
async function create() {
try {
disabled = true;
const project = await sdk.forConsole.projects.create(
id ?? ID.unique(),
name,
teamId,
Region.Default
);
show = false;
dispatch('created', project);
trackEvent(Submit.ProjectCreate, {
customId: !!id,
@@ -40,6 +43,7 @@
} catch (e) {
error = e.message;
trackError(e, Submit.ProjectCreate);
disabled = false;
}
}
</script>
@@ -61,6 +65,6 @@
</FormList>
<svelte:fragment slot="footer">
<Button secondary on:click={() => (show = false)}>Cancel</Button>
<Button submit>Create</Button>
<Button submit {disabled}>Create</Button>
</svelte:fragment>
</Modal>
@@ -58,9 +58,9 @@
</Button>
</div>
{:else}
<ul class="u-grid u-gap-8">
<ul class="u-grid u-gap-4">
{#each [...formValues[attribute.key].keys()] as index}
<li class="form-item is-multiple">
<li class="form-item is-multiple u-gap-8">
<div class="form-item-part u-stretch">
<Attribute
{attribute}
@@ -24,6 +24,7 @@
import { wizard } from '$lib/stores/wizard';
import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
import { SMTPSecure } from '@appwrite.io/console';
import InputSelect from '$lib/elements/forms/inputSelect.svelte';
let enabled = false;
let senderName: string;
@@ -33,7 +34,13 @@
let port: number;
let username: string;
let password: string;
let secure = false;
let secure: string;
const options = [
{ value: 'tls', label: 'TLS' },
{ value: 'ssl', label: 'SSL' },
{ value: '', label: 'None' }
];
onMount(() => {
enabled = $project.smtpEnabled ?? false;
@@ -44,7 +51,7 @@
port = $project.smtpPort;
username = $project.smtpUsername;
password = $project.smtpPassword;
secure = $project.smtpSecure === 'tls';
secure = $project.smtpSecure === 'tls' ? 'tls' : $project.smtpSecure === 'ssl' ? 'ssl' : '';
});
async function updateSmtp() {
@@ -98,7 +105,7 @@
port: $project.smtpPort,
username: $project.smtpUsername,
password: $project.smtpPassword,
secure: $project.smtpSecure === 'tls'
secure: $project.smtpSecure
}
);
@@ -110,7 +117,7 @@
port = undefined;
username = undefined;
password = undefined;
secure = false;
secure = undefined;
}
</script>
@@ -190,10 +197,12 @@
label="Password"
bind:value={password}
placeholder="Enter password" />
<InputChoice bind:value={secure} id="tls" label="TLS secure protocol">
Enable if TLS is supported on your SMTP server.
</InputChoice>
<InputSelect
id="tls"
label="Secure protocol"
placeholder="Select protocol"
bind:value={secure}
{options} />
{/if}
</FormList>
{/if}
+2
View File
@@ -1,5 +1,6 @@
import { page } from '$app/stores';
import type { HeaderAlert } from '$lib/stores/headerAlert';
import type { Organization } from '$lib/stores/organization';
import type { Models } from '@appwrite.io/console';
import { derived, writable } from 'svelte/store';
@@ -10,3 +11,4 @@ export const consoleVariables = derived(
);
export const activeHeaderAlert = writable<HeaderAlert>(null);
export const orgMissingPaymentMethod = writable<Organization>(null);
Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B