Skip to content

Commit f9e1aa1

Browse files
authored
Merge branch 'appwrite:main' into fix-PRO-1949-env-format-platform-creation
2 parents d7de9e8 + 22ee0fc commit f9e1aa1

File tree

8 files changed

+146
-65
lines changed

8 files changed

+146
-65
lines changed

src/lib/components/billing/planSelection.svelte

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
bind:group={billingPlan}
2525
disabled={anyOrgFree || !selfService}
2626
value={BillingPlan.FREE}
27-
tooltipShow={anyOrgFree}
2827
title={tierFree.name}
29-
tooltipText="You are limited to 1 Free organization per account.">
28+
tooltipShow={anyOrgFree}
29+
tooltipText="You are limited to 1 Free organization per account."
30+
tooltipWidth="100%">
3031
<svelte:fragment slot="action">
3132
{#if $organization?.billingPlan === BillingPlan.FREE && !isNewOrg}
3233
<Badge variant="secondary" size="xs" content="Current plan" />

src/lib/components/labelCard.svelte

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script lang="ts">
2-
import { Card, Tooltip } from '@appwrite.io/pink-svelte';
3-
import type { HTMLAttributes } from 'svelte/elements';
4-
import type { BaseCardProps } from './card.svelte';
52
import type { ComponentType } from 'svelte';
3+
import type { BaseCardProps } from './card.svelte';
4+
import type { HTMLAttributes } from 'svelte/elements';
5+
import { Card, Tooltip } from '@appwrite.io/pink-svelte';
66
77
type Props = BaseCardProps &
88
HTMLAttributes<HTMLInputElement> & {
@@ -22,8 +22,10 @@
2222
2323
export let group: string;
2424
export let value: string;
25-
export let tooltipText: string = null;
25+
2626
export let tooltipShow = false;
27+
export let tooltipText: string = null;
28+
export let tooltipWidth: string = undefined;
2729
2830
// Pink v2
2931
export let icon: Props['icon'] = undefined;
@@ -42,25 +44,27 @@
4244
let slotTitle: HTMLSpanElement;
4345
</script>
4446

45-
<Tooltip disabled={!tooltipText || !tooltipShow}>
46-
<Card.Selector
47-
{name}
48-
{src}
49-
{alt}
50-
{icon}
51-
{padding}
52-
{imageRadius}
53-
{variant}
54-
{value}
55-
{radius}
56-
{disabled}
57-
title={title ?? slotTitle?.innerText}
58-
bind:group>
59-
{#if $$slots.default}
60-
<slot />
61-
{/if}
62-
<slot name="action" slot="action" />
63-
</Card.Selector>
47+
<Tooltip maxWidth={tooltipWidth} disabled={!tooltipText || !tooltipShow}>
48+
<div style:cursor={disabled ? 'pointer' : ''}>
49+
<Card.Selector
50+
{name}
51+
{src}
52+
{alt}
53+
{icon}
54+
{padding}
55+
{imageRadius}
56+
{variant}
57+
{value}
58+
{radius}
59+
{disabled}
60+
title={title ?? slotTitle?.innerText}
61+
bind:group>
62+
{#if $$slots.default}
63+
<slot />
64+
{/if}
65+
<slot name="action" slot="action" />
66+
</Card.Selector>
67+
</div>
6468
<span slot="tooltip">{tooltipText}</span>
6569
</Tooltip>
6670

src/lib/components/permissions/permissions.svelte

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
import { writable } from 'svelte/store';
1717
import Actions from './actions.svelte';
1818
import Row from './row.svelte';
19-
import { Icon, Selector, Table } from '@appwrite.io/pink-svelte';
19+
import { Icon, Layout, Selector, Table, Typography } from '@appwrite.io/pink-svelte';
2020
import { IconPlus, IconX } from '@appwrite.io/pink-icons-svelte';
2121
import type { PinkColumn } from '$lib/helpers/types';
22+
import { Card } from '$lib/components';
2223
2324
export let withCreate = false;
2425
export let hideOnClick = false;
@@ -206,28 +207,24 @@
206207
</Actions>
207208
</div>
208209
{:else}
209-
<article class="card u-grid u-cross-center u-width-full-line dashed">
210-
<div class="u-flex u-cross-center u-flex-vertical u-main-center u-flex">
211-
<div class="common-section">
212-
<Actions
213-
bind:showLabel
214-
bind:showCustom
215-
bind:showTeam
216-
bind:showUser
217-
{groups}
218-
{hideOnClick}
219-
on:create={create}
220-
let:toggle>
221-
<Button compact icon on:click={toggle}>
222-
<Icon icon={IconPlus} size="s" />
223-
</Button>
224-
</Actions>
225-
</div>
226-
<div class="common-section">
227-
<span class="text"> Add a role to get started </span>
228-
</div>
229-
</div>
230-
</article>
210+
<Card variant="secondary">
211+
<Layout.Stack direction="column" alignItems="center" gap="xl">
212+
<Actions
213+
bind:showLabel
214+
bind:showCustom
215+
bind:showTeam
216+
bind:showUser
217+
{groups}
218+
{hideOnClick}
219+
on:create={create}
220+
let:toggle>
221+
<Button secondary icon on:click={toggle}>
222+
<Icon icon={IconPlus} size="s" />
223+
</Button>
224+
</Actions>
225+
<Typography.Text>Add a role to get started</Typography.Text>
226+
</Layout.Stack>
227+
</Card>
231228
{/if}
232229

233230
<style lang="scss">

src/lib/components/sidebar.svelte

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@
8181
{ name: 'Storage', icon: IconFolder, slug: 'storage', category: 'build' },
8282
{ name: 'Sites', icon: IconGlobeAlt, slug: 'sites', category: 'deploy', badge: 'New' }
8383
];
84+
85+
const isSelected = (service: string): boolean => {
86+
return page.route.id?.includes(service);
87+
};
8488
</script>
8589

8690
<div
@@ -145,7 +149,7 @@
145149
<a
146150
href={`/console/project-${project.region}-${project.$id}/overview/platforms`}
147151
class="link"
148-
class:active={page.url.pathname.includes('overview')}
152+
class:active={isSelected('overview')}
149153
on:click={() => {
150154
trackEvent(Click.MenuOverviewClick);
151155
sideBarIsOpen = false;
@@ -175,7 +179,7 @@
175179
<a
176180
href={`/console/project-${project.region}-${project.$id}/${projectOption.slug}`}
177181
class="link"
178-
class:active={page.url.pathname.includes(projectOption.slug)}
182+
class:active={isSelected(projectOption.slug)}
179183
on:click={() => {
180184
trackEvent(`click_menu_${projectOption.slug}`);
181185
sideBarIsOpen = false;
@@ -206,7 +210,7 @@
206210
<a
207211
href={`/console/project-${project.region}-${project.$id}/${projectOption.slug}`}
208212
class="link"
209-
class:active={page.url.pathname.includes(projectOption.slug)}
213+
class:active={isSelected(projectOption.slug)}
210214
on:click={() => {
211215
trackEvent(`click_menu_${projectOption.slug}`);
212216
sideBarIsOpen = false;
@@ -299,8 +303,7 @@
299303
on:click={() => {
300304
trackEvent('click_menu_settings');
301305
}}
302-
class:active={page.url.pathname.includes('/settings') &&
303-
!page.url.pathname.includes('sites')}
306+
class:active={isSelected('/settings') && !isSelected('sites')}
304307
><span class="link-icon"><Icon icon={IconCog} size="s" /></span><span
305308
class:no-text={state === 'icons'}
306309
class:has-text={state === 'open'}

src/lib/helpers/waitlist.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { sdk } from '$lib/stores/sdk';
2+
import { type Account } from '$lib/stores/user';
3+
4+
export const joinWaitlistSites = (user: Account) => {
5+
const prefs = user.prefs;
6+
const newPrefs = {
7+
...prefs,
8+
joinWaitlistSites: true
9+
};
10+
11+
sdk.forConsole.account.updatePrefs(newPrefs);
12+
13+
if (sessionStorage) {
14+
sessionStorage.setItem('joinWaitlistSites', 'true');
15+
}
16+
};
17+
18+
export const isOnWaitlistSites = (user: Account): boolean => {
19+
const prefs = user.prefs;
20+
const joinedInPrefs = 'joinWaitlistSites' in prefs;
21+
22+
let joinedInSession = false;
23+
if (sessionStorage) {
24+
joinedInSession = sessionStorage.getItem('joinWaitlistSites') === 'true';
25+
}
26+
27+
return joinedInSession || joinedInPrefs;
28+
};

src/lib/stores/billing.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,8 @@ export async function checkForUsageLimit(org: Organization) {
357357
const members = org.total;
358358
const plan = get(currentPlan);
359359
const membersOverflow =
360-
members > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0;
360+
// nested null checks needed: GitHub Education plan have empty addons.
361+
members > plan.addons.seats?.limit ? members - (plan.addons.seats?.limit || members) : 0;
361362

362363
if (resources.some((r) => r.value >= 100) || membersOverflow > 0) {
363364
readOnly.set(true);

src/routes/(console)/project-[region]-[project]/+layout.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,20 @@ export const load: LayoutLoad = async ({ params, depends, parent }) => {
2222
(org) => org.$id === project.teamId
2323
);
2424

25-
const [org, regionalConsoleVariables, rolesResult] = await Promise.all([
25+
const includedInBasePlans = plansInfo.has(organization.billingPlan);
26+
27+
const [org, regionalConsoleVariables, rolesResult, organizationPlan] = await Promise.all([
2628
!organization
2729
? (sdk.forConsole.teams.get(project.teamId) as Promise<Organization>)
2830
: organization,
2931
sdk.forConsoleIn(project.region).console.variables(),
3032
isCloud ? sdk.forConsole.billing.getRoles(project.teamId) : null,
33+
34+
// fetch if not available in `plansInfo`
35+
includedInBasePlans
36+
? plansInfo.get(organization.billingPlan)
37+
: sdk.forConsole.billing.getOrganizationPlan(organization.$id),
38+
3139
loadAvailableRegions(project.teamId)
3240
]);
3341

@@ -49,13 +57,18 @@ export const load: LayoutLoad = async ({ params, depends, parent }) => {
4957
loadFailedInvoices(project.teamId);
5058
}
5159

60+
if (!includedInBasePlans) {
61+
// save the custom plan to `plansInfo` cache.
62+
plansInfo.set(organization.billingPlan, organizationPlan);
63+
}
64+
5265
return {
5366
project,
5467
organization,
5568
regionalConsoleVariables,
5669
roles,
5770
scopes,
58-
currentPlan: plansInfo.get(organization.billingPlan)
71+
currentPlan: organizationPlan
5972
};
6073
};
6174

src/routes/(console)/project-[region]-[project]/sites/+page.svelte

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@
2929
import { Dependencies } from '$lib/constants';
3030
import { sdk } from '$lib/stores/sdk';
3131
import { isSmallViewport } from '$lib/stores/viewport';
32+
import { addNotification } from '$lib/stores/notifications';
33+
import { isOnWaitlistSites, joinWaitlistSites } from '$lib/helpers/waitlist';
34+
import { user } from '$lib/stores/user';
3235
3336
export let data;
3437
3538
let show = false;
39+
let isOnWaitlist = isOnWaitlistSites($user);
3640
3741
$: $registerCommands([
3842
{
@@ -68,6 +72,17 @@
6872
? EmptyLightMobile
6973
: EmptyLight;
7074
$: imgClass = $isSmallViewport ? 'mobile' : 'desktop';
75+
76+
function addToWaitlist() {
77+
joinWaitlistSites($user);
78+
addNotification({
79+
type: 'success',
80+
title: 'Waitlist joined',
81+
message: "We'll let you know as soon as Appwrite Sites is ready for you."
82+
});
83+
84+
isOnWaitlist = true;
85+
}
7186
</script>
7287

7388
<Container>
@@ -120,18 +135,37 @@
120135
<img src={imgSrc} alt="create" aria-hidden="true" height="242" class={imgClass} />
121136

122137
<Layout.Stack>
123-
<Layout.Stack gap="m" alignItems="center">
138+
{#if isOnWaitlist}
124139
<Typography.Title size="s" align="center" color="--fgcolor-neutral-primary">
125-
Appwrite Sites is in high demand
140+
You've successfully joined the Sites waitlist
126141
</Typography.Title>
127142

128-
<div style:max-width="600px">
129-
<Typography.Text align="center" color="--fgcolor-neutral-secondary">
130-
To ensure a smooth experience for everyone, we’re rolling out access
131-
gradually.
132-
</Typography.Text>
133-
</div>
134-
</Layout.Stack>
143+
<Typography.Text align="center" color="--fgcolor-neutral-secondary">
144+
We can't wait for you to try out Sites on Cloud. You will get access
145+
soon.
146+
</Typography.Text>
147+
{:else}
148+
<Layout.Stack gap="m" alignItems="center">
149+
<Typography.Title
150+
size="s"
151+
align="center"
152+
color="--fgcolor-neutral-primary">
153+
Appwrite Sites is in high demand
154+
</Typography.Title>
155+
156+
<div style:max-width="600px">
157+
<Typography.Text align="center" color="--fgcolor-neutral-secondary">
158+
To ensure a smooth experience for everyone, we’re rolling out
159+
access gradually. Join the waitlist and be one of the first to
160+
deploy with Sites.
161+
</Typography.Text>
162+
</div>
163+
164+
<div style:margin-block-start="1rem">
165+
<Button on:click={addToWaitlist}>Join waitlist</Button>
166+
</div>
167+
</Layout.Stack>
168+
{/if}
135169
</Layout.Stack>
136170
</Layout.Stack>
137171
</Card.Base>

0 commit comments

Comments
 (0)