mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'main' into spreadsheet
This commit is contained in:
@@ -7,8 +7,8 @@
|
||||
import { LabelCard } from '..';
|
||||
|
||||
export let billingPlan: Tier;
|
||||
export let anyOrgFree = false;
|
||||
export let isNewOrg = false;
|
||||
export let anyOrgFree = false;
|
||||
export let selfService = true;
|
||||
|
||||
$: freePlan = $plansInfo.get(BillingPlan.FREE);
|
||||
@@ -22,12 +22,9 @@
|
||||
<LabelCard
|
||||
name="plan"
|
||||
bind:group={billingPlan}
|
||||
disabled={anyOrgFree || !selfService}
|
||||
disabled={!selfService}
|
||||
value={BillingPlan.FREE}
|
||||
title={tierFree.name}
|
||||
tooltipShow={anyOrgFree}
|
||||
tooltipText="You are limited to 1 Free organization per account."
|
||||
tooltipWidth="100%">
|
||||
title={tierFree.name}>
|
||||
<svelte:fragment slot="action">
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE && !isNewOrg}
|
||||
<Badge variant="secondary" size="xs" content="Current plan" />
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
import type { PageData } from './$types';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { onMount } from 'svelte';
|
||||
import { Badge, Layout, Table, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Badge, Layout, Table, Typography, Icon } from '@appwrite.io/pink-svelte';
|
||||
import { IconGlobeAlt } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -92,9 +93,9 @@
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'client' },
|
||||
{ id: 'location', width: 120 },
|
||||
{ id: 'ip', width: 120 },
|
||||
{ id: 'actions', width: 70 }
|
||||
{ id: 'location', width: 200 },
|
||||
{ id: 'ip', width: 200 },
|
||||
{ id: 'actions', width: 100 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="client" {root}>Client</Table.Header.Cell>
|
||||
@@ -114,13 +115,9 @@
|
||||
height="20"
|
||||
width="20"
|
||||
src={getBrowser(session.clientCode).toString()}
|
||||
style="--p-text-size: 1.25rem"
|
||||
alt={session.clientName} />
|
||||
{:else}
|
||||
<span
|
||||
class="icon-globe-alt"
|
||||
style="--p-text-size: 1.25rem"
|
||||
aria-hidden="true"></span>
|
||||
<Icon icon={IconGlobeAlt} size="s" />
|
||||
{/if}
|
||||
</div>
|
||||
<Trim>
|
||||
|
||||
@@ -150,8 +150,7 @@
|
||||
await goto(previousPage);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
isHtml: true,
|
||||
message: `<b>${$organization.name}</b> plan has been successfully updated.`
|
||||
message: `${$organization.name} plan has been successfully updated.`
|
||||
});
|
||||
|
||||
trackEvent(Submit.OrganizationDowngrade, {
|
||||
@@ -264,7 +263,9 @@
|
||||
|
||||
$: isUpgrade = $plansInfo.get(selectedPlan).order > $currentPlan?.order;
|
||||
$: isDowngrade = $plansInfo.get(selectedPlan).order < $currentPlan?.order;
|
||||
$: isButtonDisabled = $organization?.billingPlan === selectedPlan;
|
||||
$: isButtonDisabled =
|
||||
$organization?.billingPlan === selectedPlan ||
|
||||
(isDowngrade && selectedPlan === BillingPlan.FREE && data.hasFreeOrgs);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -297,8 +298,21 @@
|
||||
selfService={data.selfService}
|
||||
anyOrgFree={data.hasFreeOrgs} />
|
||||
|
||||
{#if isDowngrade && selectedPlan === BillingPlan.FREE && data.hasFreeOrgs}
|
||||
<Alert.Inline
|
||||
status="warning"
|
||||
title="You can only have one free organization per account">
|
||||
To downgrade this organization, first migrate or delete one of your
|
||||
existing paid organizations.
|
||||
<Button
|
||||
compact
|
||||
href="https://appwrite.io/docs/advanced/migrations/cloud"
|
||||
>Migration guide</Button>
|
||||
</Alert.Inline>
|
||||
{/if}
|
||||
|
||||
{#if isDowngrade}
|
||||
{#if selectedPlan === BillingPlan.FREE}
|
||||
{#if selectedPlan === BillingPlan.FREE && !data.hasFreeOrgs}
|
||||
<PlanExcess tier={BillingPlan.FREE} />
|
||||
{:else if selectedPlan === BillingPlan.PRO && data.organization.billingPlan === BillingPlan.SCALE && collaborators?.length > 0}
|
||||
{@const extraMembers = collaborators?.length ?? 0}
|
||||
@@ -364,7 +378,7 @@
|
||||
id="members" />
|
||||
</Fieldset>
|
||||
{/if}
|
||||
{#if isDowngrade && selectedPlan === BillingPlan.FREE}
|
||||
{#if isDowngrade && selectedPlan === BillingPlan.FREE && !data.hasFreeOrgs}
|
||||
<Fieldset legend="Feedback">
|
||||
<Layout.Stack gap="xl">
|
||||
<InputSelect
|
||||
@@ -395,7 +409,7 @@
|
||||
bind:billingBudget
|
||||
organizationId={data.organization.$id} />
|
||||
{:else if data.organization.billingPlan !== BillingPlan.CUSTOM}
|
||||
<PlanComparisonBox downgrade={isDowngrade} />
|
||||
<PlanComparisonBox downgrade={data.hasFreeOrgs ? false : isDowngrade} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="footer">
|
||||
|
||||
+74
-78
@@ -1,18 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { EmptySearch } from '$lib/components';
|
||||
import { Badge } from '@appwrite.io/pink-svelte';
|
||||
import { EmptySearch, Trim } from '$lib/components';
|
||||
import { Badge, Layout, Table, Typography, Icon } from '@appwrite.io/pink-svelte';
|
||||
import { IconGlobeAlt } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableCellHead,
|
||||
TableCellText,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
TableScroll
|
||||
} from '$lib/elements/table';
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types';
|
||||
import { Container, ContainerHeader } from '$lib/layout';
|
||||
import { Container } from '$lib/layout';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Browser } from '@appwrite.io/console';
|
||||
import DeleteAllSessions from '../deleteAllSessions.svelte';
|
||||
@@ -33,77 +25,81 @@
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<ContainerHeader title="Sessions">
|
||||
<Layout.Stack direction="row" justifyContent="space-between">
|
||||
<Typography.Title>Sessions</Typography.Title>
|
||||
{#if data.sessions.total}
|
||||
<Button secondary on:click={() => (showDeleteAll = true)}>
|
||||
<span class="text">Delete All</span>
|
||||
</Button>
|
||||
<Button secondary on:click={() => (showDeleteAll = true)}>Sign out all sessions</Button>
|
||||
{/if}
|
||||
</ContainerHeader>
|
||||
</Layout.Stack>
|
||||
|
||||
{#if data.sessions.total}
|
||||
<TableScroll>
|
||||
<TableHeader>
|
||||
<TableCellHead width={140}>Browser and device</TableCellHead>
|
||||
<TableCellHead width={140}>Session</TableCellHead>
|
||||
<TableCellHead width={140}>Location</TableCellHead>
|
||||
<TableCellHead width={140}>IP</TableCellHead>
|
||||
<TableCellHead width={30} />
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each data.sessions.sessions as session}
|
||||
{@const browser = getBrowser(session.clientCode)}
|
||||
<TableRow>
|
||||
<TableCell title="Client">
|
||||
<div class="u-flex u-gap-12 u-cross-center">
|
||||
<div class="avatar">
|
||||
{#if browser}
|
||||
<img
|
||||
height="20"
|
||||
width="20"
|
||||
src={getBrowser(session.clientCode).toString()}
|
||||
style="--p-text-size: 1.25rem"
|
||||
alt={session.clientName} />
|
||||
{:else}
|
||||
<span
|
||||
class="icon-globe-alt"
|
||||
style="--p-text-size: 1.25rem"
|
||||
aria-hidden="true">
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="text">
|
||||
{session.clientName}
|
||||
{session.clientVersion} on {session.osName}
|
||||
{session.osVersion}
|
||||
</p>
|
||||
{#if session.current}
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type="success"
|
||||
content="current session" />
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'client' },
|
||||
{ id: 'location', width: 200 },
|
||||
{ id: 'ip', width: 200 },
|
||||
{ id: 'actions', width: 100 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="client" {root}>Client</Table.Header.Cell>
|
||||
<Table.Header.Cell column="location" {root}>Location</Table.Header.Cell>
|
||||
<Table.Header.Cell column="ip" {root}>IP</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root} />
|
||||
</svelte:fragment>
|
||||
{#each data.sessions.sessions as session}
|
||||
{@const browser = getBrowser(session.clientCode)}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="client" {root}>
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<div class="avatar is-size-small">
|
||||
{#if browser}
|
||||
<img
|
||||
height="20"
|
||||
width="20"
|
||||
src={getBrowser(session.clientCode).toString()}
|
||||
alt={session.clientName} />
|
||||
{:else}
|
||||
<Icon icon={IconGlobeAlt} size="s" />
|
||||
{/if}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
<TableCellText title="Session">{session.clientType}</TableCellText>
|
||||
<TableCellText title="Location">{session.countryName}</TableCellText>
|
||||
<TableCellText title="IP">{session.ip}</TableCellText>
|
||||
<TableCell>
|
||||
<Button
|
||||
text
|
||||
icon
|
||||
ariaLabel="Delete item"
|
||||
on:click={() => {
|
||||
selectedSessionId = session.$id;
|
||||
showDelete = true;
|
||||
}}>
|
||||
<span class="icon-trash" aria-hidden="true"></span>
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</TableScroll>
|
||||
<Trim>
|
||||
{session.clientName}
|
||||
{session.clientVersion} on {session.osName}
|
||||
{session.osVersion}
|
||||
</Trim>
|
||||
{#if session.current}
|
||||
<Badge
|
||||
type="success"
|
||||
variant="secondary"
|
||||
content="current session" />
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell column="location" {root}>
|
||||
{#if session.countryCode !== '--'}
|
||||
{session.countryName}
|
||||
{:else}
|
||||
Unknown
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="ip" {root}>
|
||||
{session.ip}
|
||||
</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<Button
|
||||
size="xs"
|
||||
secondary
|
||||
on:click={() => {
|
||||
selectedSessionId = session.$id;
|
||||
showDelete = true;
|
||||
}}>
|
||||
Sign out
|
||||
</Button>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{:else}
|
||||
<EmptySearch>
|
||||
<div class="u-flex u-flex-vertical u-cross-center u-gap-24">
|
||||
|
||||
Reference in New Issue
Block a user