Merge branch 'main' of github.com:appwrite/console into billing

This commit is contained in:
Arman
2023-07-19 17:54:20 +02:00
8 changed files with 312 additions and 26 deletions
+1
View File
@@ -131,6 +131,7 @@ export enum Submit {
ProjectCreate = 'submit_project_create',
ProjectDelete = 'submit_project_delete',
ProjectUpdateName = 'submit_project_update_name',
ProjectUpdateTeam = 'submit_project_update_team',
ProjectService = 'submit_project_service',
MemberCreate = 'submit_member_create',
MemberDelete = 'submit_member_delete',
+48 -12
View File
@@ -2,20 +2,56 @@
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import { Heading } from '$lib/components';
import { onMount } from 'svelte';
onMount(async () => {
const project = $page.url.searchParams.get('project');
if (project) {
await goto(`appwrite-callback-${project}://${$page.url.search}`);
const project = $page.url.searchParams.get('project');
const link = `appwrite-callback-${project}://${$page.url.search}`;
const redirect = new Promise((resolve, reject) => {
if (!project) {
reject('no-project');
}
// this timeout is needed because goto does not
// throw an exception if the redirect does not work
setTimeout(() => reject('timeout'), 500);
// goto will resolve on successful redirect
goto(link).then(resolve);
});
</script>
<Heading tag="h1" size="1">Missing Redirect URL</Heading>
<p class="text">
Your OAuth login flow is missing a proper redirect URL. Please check the
<a class="link" href="https://appwrite.io/docs/client/account?sdk=web#createOAuth2Session"
>OAuth docs</a>
and send request for new session with a valid callback URL.
</p>
{#await redirect then}
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<Heading tag="h1" size="4">Login failed</Heading>
<p class="text">You will be automatically redirected back to your app shortly.</p>
<p class="text">
If you are not redirected, please click on the following
<a class="link" href={`appwrite-callback-${project}://${$page.url.search}`}>link</a
>.
</p>
</div>
</article>
{:catch}
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<Heading tag="h1" size="4">Missing Redirect URL</Heading>
<p class="text">
Your OAuth login flow is missing a proper redirect URL. Please check the
<a
class="link"
href="https://appwrite.io/docs/client/account?sdk=web#createOAuth2Session"
>OAuth docs</a>
and send request for new session with a valid callback URL.
</p>
</div>
</article>
{/await}
<style lang="scss">
@import '@appwrite.io/pink/src/abstract/variables/_devices.scss';
// override padding for screens bigger than mobile
@media #{$break2open} {
article.card {
padding: 2rem !important;
}
}
</style>
+48 -12
View File
@@ -2,20 +2,56 @@
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import { Heading } from '$lib/components';
import { onMount } from 'svelte';
onMount(async () => {
const project = $page.url.searchParams.get('project');
if (project) {
await goto(`appwrite-callback-${project}://${$page.url.search}`);
const project = $page.url.searchParams.get('project');
const link = `appwrite-callback-${project}://${$page.url.search}`;
const redirect = new Promise((resolve, reject) => {
if (!project) {
reject('no-project');
}
// this timeout is needed because goto does not
// throw an exception if the redirect does not work
setTimeout(() => reject('timeout'), 500);
// goto will resolve on successful redirect
goto(link).then(resolve);
});
</script>
<Heading tag="h1" size="1">Missing Redirect URL</Heading>
<p class="text">
Your OAuth login flow is missing a proper redirect URL. Please check the
<a class="link" href="https://appwrite.io/docs/client/account?sdk=web#createOAuth2Session"
>OAuth docs</a>
and send request for new session with a valid callback URL.
</p>
{#await redirect then}
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<Heading tag="h1" size="4">You're now logged in</Heading>
<p class="text">You will be automatically redirected back to your app shortly.</p>
<p class="text">
If you are not redirected, please click on the following
<a class="link" href={`appwrite-callback-${project}://${$page.url.search}`}>link</a
>.
</p>
</div>
</article>
{:catch}
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<Heading tag="h1" size="4">Missing Redirect URL</Heading>
<p class="text">
Your OAuth login flow is missing a proper redirect URL. Please check the
<a
class="link"
href="https://appwrite.io/docs/client/account?sdk=web#createOAuth2Session"
>OAuth docs</a>
and send request for new session with a valid callback URL.
</p>
</div>
</article>
{/await}
<style lang="scss">
@import '@appwrite.io/pink/src/abstract/variables/_devices.scss';
// override padding for screens bigger than mobile
@media #{$break2open} {
article.card {
padding: 2rem !important;
}
}
</style>
@@ -11,6 +11,8 @@
import { wizard } from '$lib/stores/wizard';
import { isCloud } from '$lib/system';
import { page } from '$app/stores';
import { services } from '$lib/stores/project-services';
import type { Models } from '@appwrite.io/console';
export let data: PageData;
@@ -41,6 +43,17 @@
return { name, icon };
};
function allServiceDisabled(project: Models.Project): boolean {
let disabled = true;
services.load(project);
$services.list.forEach((service) => {
if (service.value) {
disabled = false;
}
});
return disabled;
}
function filterPlatforms(platforms: { name: string; icon: string }[]) {
return platforms.filter(
(value, index, self) => index === self.findIndex((t) => t.name === value.name)
@@ -75,6 +88,11 @@
<svelte:fragment slot="title">
{project.name}
</svelte:fragment>
{#if allServiceDisabled(project)}
<p>
<span class="icon-pause" aria-hidden="true" /> All services are disabled.
</p>
{/if}
{@const platforms = filterPlatforms(
project.platforms.map((platform) => getPlatformInfo(platform.type))
)}
@@ -3,10 +3,18 @@
import { onMount } from 'svelte';
import { toLocaleDateTime } from '$lib/helpers/date';
import { addNotification } from '$lib/stores/notifications';
import { organizationList } from '$lib/stores/organization';
import { project } from '../store';
import { services, type Service } from '$lib/stores/project-services';
import { CardGrid, CopyInput, Box, Heading } from '$lib/components';
import { Button, Form, FormList, InputText, InputSwitch } from '$lib/elements/forms';
import {
Button,
Form,
FormList,
InputText,
InputSwitch,
InputSelect
} from '$lib/elements/forms';
import { Container } from '$lib/layout';
import { invalidate } from '$app/navigation';
import { Dependencies } from '$lib/constants';
@@ -14,14 +22,22 @@
import { base } from '$app/paths';
import { page } from '$app/stores';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import EnableAllServices from './enableAllServices.svelte';
import DisableAllServices from './disableAllServices.svelte';
import Transfer from './transferProject.svelte';
let name: string = null;
let teamId: string = null;
let showDelete = false;
let showTransfer = false;
const endpoint = sdk.forConsole.client.config.endpoint;
const projectId = $page.params.project;
let showDisableAll = false;
let showEnableAll = false;
onMount(async () => {
name ??= $project.name;
teamId ??= $project.teamId;
});
async function updateName() {
@@ -42,6 +58,50 @@
}
}
async function toggleAllServices(status: boolean) {
if (status && !showEnableAll) {
showEnableAll = true;
return;
}
if (!status && !showDisableAll) {
showDisableAll = true;
return;
}
try {
const path = '/projects/' + $project.$id + '/service/all';
await sdk.forConsole.client.call(
'PATCH',
new URL(sdk.forConsole.client.config.endpoint + path),
{
'content-type': 'application/json'
},
{
status: status
}
);
invalidate(Dependencies.PROJECT);
addNotification({
type: 'success',
message:
'All services for ' +
$project.name +
' has been ' +
(status ? 'enabled.' : 'disabled.')
});
trackEvent(Submit.ProjectService);
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
trackError(error, Submit.ProjectService);
} finally {
showDisableAll = false;
showEnableAll = false;
}
}
async function serviceUpdate(service: Service) {
try {
await sdk.forConsole.projects.updateServiceStatus(
@@ -120,8 +180,18 @@
services are not accessible to client SDKs but remain accessible to server SDKs.
</p>
<svelte:fragment slot="aside">
<ul class="buttons-list u-main-end">
<li class="buttons-list-item">
<Button text={true} on:click={() => toggleAllServices(true)}
>Enable all</Button>
</li>
<li class="buttons-list-item">
<Button text={true} on:click={() => toggleAllServices(false)}
>Disable all</Button>
</li>
</ul>
<FormList>
<form class="form">
<form class="form card-separator">
<ul class="form-list is-multiple">
{#each $services.list as service}
<InputSwitch
@@ -137,7 +207,30 @@
</FormList>
</svelte:fragment>
</CardGrid>
<CardGrid>
<Heading tag="h6" size="7">Transfer project</Heading>
<p class="text">Transfer your project to another organization that you own.</p>
<svelte:fragment slot="aside">
<FormList>
<InputSelect
id="organization"
label="Available organizations"
bind:value={teamId}
options={$organizationList.teams.map((team) => ({
value: team.$id,
label: team.name
}))} />
</FormList>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button
secondary
disabled={teamId === $project.teamId}
on:click={() => (showTransfer = true)}>Transfer</Button>
</svelte:fragment>
</CardGrid>
<CardGrid danger>
<div>
<Heading tag="h6" size="7">Delete Project</Heading>
@@ -163,3 +256,11 @@
</Container>
<Delete bind:showDelete />
<DisableAllServices handleDisableAll={() => toggleAllServices(false)} bind:show={showDisableAll} />
<EnableAllServices handleEnableAll={() => toggleAllServices(true)} bind:show={showEnableAll} />
{#if teamId}
<Transfer
bind:teamId
teamName={$organizationList.teams.find((t) => t.$id == teamId).name}
bind:show={showTransfer} />
{/if}
@@ -0,0 +1,19 @@
<script lang="ts">
import { Modal } from '$lib/components';
import { Button } from '$lib/elements/forms';
export let show = false;
export let handleDisableAll;
</script>
<Modal icon="exclamation" state="warning" bind:show onSubmit={handleDisableAll}>
<svelte:fragment slot="header">Disable all services</svelte:fragment>
<p class="text" data-private>
Are you sure you want to disable all services? This will disable API requests to your
project.
</p>
<svelte:fragment slot="footer">
<Button text on:click={() => (show = false)}>Cancel</Button>
<Button secondary submit>Disable All</Button>
</svelte:fragment>
</Modal>
@@ -0,0 +1,16 @@
<script lang="ts">
import { Modal } from '$lib/components';
import { Button } from '$lib/elements/forms';
export let show = false;
export let handleEnableAll;
</script>
<Modal bind:show onSubmit={handleEnableAll}>
<svelte:fragment slot="header">Enable all services</svelte:fragment>
<p class="text" data-private>All project services will be enabled.</p>
<svelte:fragment slot="footer">
<Button text on:click={() => (show = false)}>Cancel</Button>
<Button secondary submit>Enable all</Button>
</svelte:fragment>
</Modal>
@@ -0,0 +1,59 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { base } from '$app/paths';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { Modal } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { project } from '../store';
export let show = false;
export let teamName;
export let teamId;
const handleTransfer = async () => {
try {
await sdk.forConsole.client.call(
'PATCH',
new URL(
sdk.forConsole.client.config.endpoint + '/projects/' + $project.$id + '/team'
),
{
'content-type': 'application/json'
},
{
teamId: teamId
}
);
// await sdk.forConsole.projects.update($project.$id, password);
show = false;
addNotification({
type: 'success',
message: `${$project.name} has been transfered to ${teamName}`
});
trackEvent(Submit.ProjectUpdateTeam);
await goto(`${base}/console/organization-${teamId}`);
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
trackError(error, Submit.ProjectUpdateTeam);
}
};
</script>
<Modal bind:show onSubmit={handleTransfer} headerDivider={false}>
<svelte:fragment slot="header">Transfer project</svelte:fragment>
<p>Are you sure you want to transfer <b>{$project.name}</b> to <b>{teamName}</b>?</p>
<p>
Members who are not part of the destination organization must be invited to gain access to
this project.
</p>
<svelte:fragment slot="footer">
<Button text on:click={() => (show = false)}>Cancel</Button>
<Button secondary submit>Transfer</Button>
</svelte:fragment>
</Modal>