Merge branch 'cloud' of https://github.com/appwrite/console into feat-mandate-flow

This commit is contained in:
Torsten Dittmann
2024-03-10 17:11:38 +01:00
26 changed files with 178 additions and 95 deletions
+9 -9
View File
@@ -1,15 +1,15 @@
import type { Models } from '@appwrite.io/console';
import type { SvelteComponent } from 'svelte';
import { writable } from 'svelte/store';
import Apple from '../../routes/console/project-[project]/auth/appleOAuth.svelte';
import Auth0 from '../../routes/console/project-[project]/auth/auth0OAuth.svelte';
import Authentik from '../../routes/console/project-[project]/auth/authentikOAuth.svelte';
import GitLab from '../../routes/console/project-[project]/auth/gitlabOAuth.svelte';
import Google from '../../routes/console/project-[project]/auth/googleOAuth.svelte';
import Main from '../../routes/console/project-[project]/auth/mainOAuth.svelte';
import Microsoft from '../../routes/console/project-[project]/auth/microsoftOAuth.svelte';
import Oidc from '../../routes/console/project-[project]/auth/oidcOAuth.svelte';
import Okta from '../../routes/console/project-[project]/auth/oktaOAuth.svelte';
import Apple from '../../routes/console/project-[project]/auth/(providers)/appleOAuth.svelte';
import Auth0 from '../../routes/console/project-[project]/auth/(providers)/auth0OAuth.svelte';
import Authentik from '../../routes/console/project-[project]/auth/(providers)/authentikOAuth.svelte';
import GitLab from '../../routes/console/project-[project]/auth/(providers)/gitlabOAuth.svelte';
import Google from '../../routes/console/project-[project]/auth/(providers)/googleOAuth.svelte';
import Main from '../../routes/console/project-[project]/auth/(providers)/mainOAuth.svelte';
import Microsoft from '../../routes/console/project-[project]/auth/(providers)/microsoftOAuth.svelte';
import Oidc from '../../routes/console/project-[project]/auth/(providers)/oidcOAuth.svelte';
import Okta from '../../routes/console/project-[project]/auth/(providers)/oktaOAuth.svelte';
export type Provider = Models.Provider & {
key: string;
@@ -82,7 +82,7 @@
<Pill>FREE</Pill>
</div>
{/if}
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0}
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER}
<div
class="u-flex u-cross-center"
use:tooltip={{
@@ -14,6 +14,7 @@
changeOrganizationFinalAction,
changeOrganizationTier,
changeTierSteps,
feedbackDowngradeOptions,
isUpgrade
} from './wizard/cloudOrganizationChangeTier/store';
import { goto, invalidate } from '$app/navigation';
@@ -24,7 +25,7 @@
import { wizard } from '$lib/stores/wizard';
import { tierToPlan } from '$lib/stores/billing';
import { user } from '$lib/stores/user';
import { feedback } from '$lib/stores/feedback';
import { VARS } from '$lib/system';
const dispatch = createEventDispatcher();
@@ -42,12 +43,25 @@
$changeOrganizationTier.paymentMethodId,
$changeOrganizationTier.billingAddressId
);
feedback.submitFeedback(
'downgrade',
$changeOrganizationTier.feedbackMessage,
$user?.name ?? '',
$user.email
);
await fetch(`${VARS.GROWTH_ENDPOINT}/feedback/billing`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: tierToPlan($organization.billingPlan).name,
to: tierToPlan($changeOrganizationTier.billingPlan).name,
email: $user.email,
reason: feedbackDowngradeOptions.find(
(option) =>
option.value === $changeOrganizationTier.feedbackDowngradeReason
)?.label,
orgId: $organization.$id,
userId: $user.$id,
message: $changeOrganizationTier?.feedbackMessage ?? ''
})
});
addNotification({
type: 'success',
@@ -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,
'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>
@@ -94,7 +94,7 @@
{#if isCloud && $organization?.billingPlan === BillingPlan.STARTER}
<Pill>FREE</Pill>
{/if}
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0}
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER}
<div
class="u-flex u-cross-center"
use:tooltip={{
@@ -5,11 +5,12 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
const projectId = $page.params.project;
export let provider: Provider;
export let show = false;
let appId: string = null;
let enabled: boolean = null;
@@ -37,7 +38,7 @@
$: secret = keyID && teamID && p8 ? JSON.stringify({ keyID, teamID, p8 }) : provider.secret;
</script>
<Modal {error} onSubmit={update} size="big" show on:close>
<Modal {error} onSubmit={update} size="big" bind:show on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,9 +5,10 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
export let provider: Provider;
export let show = false;
let appId: string = null;
let enabled: boolean = null;
@@ -38,7 +39,7 @@
: provider.secret;
</script>
<Modal {error} size="big" show onSubmit={update} on:close>
<Modal {error} size="big" bind:show onSubmit={update} on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,9 +5,10 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
export let provider: Provider;
export let show = false;
let appId: string = null;
let enabled: boolean = null;
@@ -38,7 +39,7 @@
: provider.secret;
</script>
<Modal {error} size="big" show onSubmit={update} on:close>
<Modal {error} size="big" bind:show onSubmit={update} on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,9 +5,10 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
export let provider: Provider;
export let show = false;
let appId: string = null;
let enabled: boolean = null;
@@ -36,7 +37,7 @@
clientSecret && endpoint ? JSON.stringify({ clientSecret, endpoint }) : provider.secret;
</script>
<Modal {error} size="big" show onSubmit={update} on:close>
<Modal {error} size="big" bind:show onSubmit={update} on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,9 +5,10 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
export let provider: Provider;
export let show = false;
const projectId = $page.params.project;
@@ -34,7 +35,7 @@
};
</script>
<Modal {error} size="big" show onSubmit={update} on:close>
<Modal {error} size="big" bind:show onSubmit={update} on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,9 +5,10 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
export let provider: Provider;
export let show = false;
const projectId = $page.params.project;
@@ -34,7 +35,7 @@
};
</script>
<Modal {error} size="big" show onSubmit={update} on:close>
<Modal {error} size="big" bind:show onSubmit={update} on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,9 +5,10 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
export let provider: Provider;
export let show = false;
let appId: string = null;
let enabled: boolean = null;
@@ -37,7 +38,7 @@
clientSecret && tenantID ? JSON.stringify({ clientSecret, tenantID }) : provider.secret;
</script>
<Modal {error} onSubmit={update} size="big" show on:close>
<Modal {error} onSubmit={update} size="big" bind:show on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,11 +5,12 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
const projectId = $page.params.project;
export let provider: Provider;
export let show = false;
let appId: string = null;
let enabled: boolean = null;
@@ -60,7 +61,7 @@
: provider.secret;
</script>
<Modal {error} onSubmit={update} size="big" show on:close>
<Modal {error} onSubmit={update} size="big" bind:show on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -5,11 +5,12 @@
import type { Provider } from '$lib/stores/oauth-providers';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { updateOAuth } from './updateOAuth';
import { updateOAuth } from '../updateOAuth';
const projectId = $page.params.project;
export let provider: Provider;
export let show = false;
let appId: string = null;
let enabled: boolean = null;
@@ -42,7 +43,7 @@
: provider.secret;
</script>
<Modal {error} onSubmit={update} size="big" show on:close>
<Modal {error} onSubmit={update} size="big" bind:show on:close>
<svelte:fragment slot="title">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -14,6 +14,7 @@
import { project } from '../../store';
const projectId = $page.params.project;
let showProvider = false;
$: {
authMethods.load($project);
@@ -74,6 +75,7 @@
class="card u-flex u-flex-vertical u-cross-center u-width-full-line"
on:click={() => {
selectedProvider = provider;
showProvider = true;
trackEvent(`click_select_provider`, {
provider: provider.key.toLowerCase()
});
@@ -99,9 +101,13 @@
</Container>
{/if}
{#if selectedProvider}
{#if selectedProvider && showProvider}
<svelte:component
this={selectedProvider.component}
bind:provider={selectedProvider}
on:close={() => (selectedProvider = null)} />
bind:show={showProvider}
on:close={() => {
selectedProvider = null;
showProvider = false;
}} />
{/if}
@@ -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}
@@ -5,7 +5,7 @@
import { Dependencies } from '$lib/constants';
import { invalidate, goto } from '$app/navigation';
import { registerCommands } from '$lib/commandCenter';
import { execute, func, showCreateDeployment } from './store';
import { func, showCreateDeployment } from './store';
import { project } from '../../store';
import type { Models } from '@appwrite.io/console';
import Execute from './execute.svelte';
@@ -147,4 +147,4 @@
<slot />
<Execute selectedFunction={$execute} />
<Execute />
@@ -25,7 +25,7 @@
TableRow,
TableScroll
} from '$lib/elements/table';
import { deploymentList, execute, func, proxyRuleList } from './store';
import { deploymentList, execute, func, proxyRuleList, showFunctionExecute } from './store';
import { Container, ContainerHeader } from '$lib/layout';
import { app } from '$lib/stores/app';
import { calculateSize, humanFileSize } from '$lib/helpers/sizeConvertion';
@@ -151,7 +151,10 @@
<Button
secondary
on:click={() => ($execute = $func)}
on:click={() => {
$execute = $func;
$showFunctionExecute = true;
}}
disabled={isCloud && $readOnly && !GRACE_PERIOD_OVERRIDE}>
Execute now
</Button>
@@ -15,9 +15,7 @@
import Label from '$lib/elements/forms/label.svelte';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import type { Models } from '@appwrite.io/console';
export let selectedFunction: Models.Function = null;
import { showFunctionExecute, execute } from './store';
let path = '/';
let method = 'GET';
@@ -34,13 +32,8 @@
{ label: 'OPTIONS', value: 'OPTIONS' }
];
let show = false;
let submitting = false;
$: if (selectedFunction && !show) {
show = true;
}
const handleSubmit = async () => {
submitting = true;
try {
@@ -51,7 +44,7 @@
}
await sdk.forProject.functions.createExecution(
selectedFunction.$id,
$execute.$id,
body,
true,
path,
@@ -60,7 +53,7 @@
);
if (!$page.url?.toString()?.includes('/executions')) {
await goto(
`${base}/console/project-${$page.params.project}/functions/function-${selectedFunction.$id}/executions`
`${base}/console/project-${$page.params.project}/functions/function-${$execute.$id}/executions`
);
}
invalidate(Dependencies.EXECUTIONS);
@@ -79,8 +72,8 @@
};
function close() {
selectedFunction = null;
show = false;
$execute = null;
$showFunctionExecute = false;
}
afterNavigate(close);
@@ -89,10 +82,9 @@
<Modal
title="Execute function"
headerDivider={false}
bind:show
bind:show={$showFunctionExecute}
size="big"
onSubmit={handleSubmit}
on:close={close}
bind:error>
<p class="text">
Manually execute your function. <a
@@ -105,7 +97,7 @@
</p>
<FormList>
{#if selectedFunction?.version !== 'v3'}
{#if $execute?.version !== 'v3'}
<Alert type="info">
<svelte:fragment slot="title">
Customizable execution data now available for functions v3.0
@@ -121,11 +113,7 @@
</Button>
</svelte:fragment>
</Alert>
<InputTextarea
label="Body"
placeholder={`{ "myKey": "myValue" }`}
id="body"
bind:value={body} />
<InputTextarea label="Body" placeholder={`Hello, World!`} id="body" bind:value={body} />
{:else}
<InputText label="Path" id="path" placeholder="/" bind:value={path} required />
@@ -214,7 +202,7 @@
<InputTextarea
label="Body"
placeholder={`{ "myKey": "myValue" }`}
placeholder={`Hello, World!`}
id="body"
bind:value={body} />
</FormList>
@@ -19,19 +19,16 @@
import { log } from '$lib/stores/logs';
import { sdk } from '$lib/stores/sdk';
import { onMount } from 'svelte';
import { func } from '../store';
import { func, execute, showFunctionExecute } from '../store';
import type { Models } from '@appwrite.io/console';
import { organization } from '$lib/stores/organization';
import { getServiceLimit, showUsageRatesModal } from '$lib/stores/billing';
import { project } from '$routes/console/project-[project]/store';
import Create from '../create.svelte';
import Execute from '../execute.svelte';
import { abbreviateNumber } from '$lib/helpers/numbers';
export let data;
let selectedFunction: Models.Function = null;
onMount(() => {
return sdk.forConsole.client.subscribe('console', (response) => {
if (response.events.includes('functions.*.executions.*')) {
@@ -54,7 +51,10 @@
title="Executions"
buttonText="Execute now"
buttonEvent="execute_function"
buttonMethod={() => (selectedFunction = $func)}>
buttonMethod={() => {
$execute = $func;
$showFunctionExecute = true;
}}>
<svelte:fragment slot="tooltip" let:tier let:limit let:upgradeMethod>
<p class="u-bold">The {tier} plan has limits</p>
<ul>
@@ -169,7 +169,3 @@
</EmptySearch>
{/if}
</Container>
<!-- <CreateDeployment bind:showCreate /> -->
<Execute {selectedFunction} />
@@ -2,7 +2,7 @@
import { CardGrid, Heading, SvgIcon } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { toLocaleDateTime } from '$lib/helpers/date';
import { execute, func } from '../store';
import { execute, func, showFunctionExecute } from '../store';
</script>
<CardGrid>
@@ -26,6 +26,11 @@
</svelte:fragment>
<svelte:fragment slot="actions">
<Button secondary on:click={() => ($execute = $func)}>Execute now</Button>
<Button
secondary
on:click={() => {
$execute = $func;
$showFunctionExecute = true;
}}>Execute now</Button>
</svelte:fragment>
</CardGrid>
@@ -12,6 +12,8 @@ export const proxyRuleList = derived(
($page) => $page.data.proxyRuleList as Models.ProxyRuleList
);
export const execute: Writable<Models.Function> = writable();
export const showFunctionExecute: Writable<boolean> = writable(false);
export const repositories: Writable<{
search: string;
installationId: string;
@@ -23,6 +23,7 @@
import { organization } from '$lib/stores/organization';
import { wizard } from '$lib/stores/wizard';
import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
import InputSelect from '$lib/elements/forms/inputSelect.svelte';
let enabled = false;
let senderName: string;
@@ -32,7 +33,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;
@@ -43,7 +50,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() {
@@ -68,7 +75,7 @@
port ? port : undefined,
username ? username : undefined,
password ? password : undefined,
secure ? 'tls' : undefined
secure ? secure : undefined
);
invalidate(Dependencies.PROJECT);
@@ -97,7 +104,7 @@
port: $project.smtpPort,
username: $project.smtpUsername,
password: $project.smtpPassword,
secure: $project.smtpSecure === 'tls'
secure: $project.smtpSecure
}
);
@@ -109,7 +116,7 @@
port = undefined;
username = undefined;
password = undefined;
secure = false;
secure = undefined;
}
</script>
@@ -189,10 +196,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,7 +2,7 @@
import { Box, CreditCardBrandImage } from '$lib/components';
import { CouponInput } from '$lib/components/billing';
import { BillingPlan } from '$lib/constants';
import { FormList, InputTextarea } from '$lib/elements/forms';
import { FormList, InputSelect, InputTextarea } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
import { formatCurrency } from '$lib/helpers/numbers';
import { WizardStep } from '$lib/layout';
@@ -10,7 +10,12 @@
import { plansInfo } from '$lib/stores/billing';
import { organization } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import { changeOrganizationFinalAction, changeOrganizationTier, isUpgrade } from './store';
import {
changeOrganizationFinalAction,
changeOrganizationTier,
feedbackDowngradeOptions,
isUpgrade
} from './store';
const plan = $plansInfo.get($changeOrganizationTier.billingPlan);
const collaboratorPrice = plan?.addons.member?.price ?? 0;
@@ -28,7 +33,6 @@
status: null,
credits: null
};
let comment: string = null;
async function fetchCard() {
try {
@@ -51,16 +55,22 @@
<WizardStep>
<svelte:fragment slot="title">Confirm plan change</svelte:fragment>
<svelte:fragment slot="subtitle">
Your feedback is important to us and helps us improve the services Appwrite offer. If
there is a specific reason you chose to change your plan at this time, please let us
know.
Your feedback is important to us and helps us improve the services Appwrite offers.
Please let us know if there is a specific reason for changing your plan.
</svelte:fragment>
<FormList>
<InputSelect
id="reason"
label="What made you decide to change your plan?*"
placeholder="Select one"
required
options={feedbackDowngradeOptions}
bind:value={$changeOrganizationTier.feedbackDowngradeReason} />
<InputTextarea
id="comment"
label="Your feedback here"
placeholder="This is my reason for downgrading..."
bind:value={comment} />
placeholder="Enter feedback"
bind:value={$changeOrganizationTier.feedbackMessage} />
</FormList>
</WizardStep>
{:else}
@@ -23,6 +23,7 @@ export const changeOrganizationTier = writable<{
};
taxId?: string;
feedbackMessage?: string;
feedbackDowngradeReason?: string;
couponCode?: string;
}>({
billingPlan: BillingPlan.PRO,
@@ -32,3 +33,38 @@ export const changeOrganizationTier = writable<{
billingAddressId: null,
taxId: null
});
export const feedbackDowngradeOptions = [
{
value: 'availableFeatures',
label: "The available features don't meet my needs"
},
{
value: 'traction',
label: "My project isn't getting traction"
},
{
value: 'bugs',
label: 'I experienced bugs or unexpected outages while using the console'
},
{
value: 'starter',
label: 'The Starter plan is enough for my projects'
},
{
value: 'budget',
label: "I don't have the budget"
},
{
value: 'tryOut',
label: 'I just wanted to try it out'
},
{
value: 'alternative',
label: 'I found an alternative/competitor to meet my needs'
},
{
value: 'other',
label: 'Other'
}
];
+2 -1
View File
@@ -13,7 +13,8 @@ const config = defineConfig({
'@analytics/google-analytics',
'analytics',
'dayjs',
'dotenv'
'dotenv',
'zrender'
]
},
define: {