Skip to content

Commit 1e4082c

Browse files
authored
Merge pull request #2929 from appwrite/feat-blocked-projects
Feat blocked projects
2 parents 2f102ff + 06adf0a commit 1e4082c

File tree

10 files changed

+363
-164
lines changed

10 files changed

+363
-164
lines changed

bun.lock

Lines changed: 75 additions & 71 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@
2828
"@faker-js/faker": "^9.9.0",
2929
"@plausible-analytics/tracker": "^0.4.4",
3030
"@popperjs/core": "^2.11.8",
31-
"@sentry/sveltekit": "^8.38.0",
31+
"@sentry/sveltekit": "^8.55.1",
3232
"@stripe/stripe-js": "^3.5.0",
33-
"@threlte/core": "^8.3.1",
34-
"@threlte/extras": "^9.7.1",
35-
"ai": "^6.0.67",
36-
"analytics": "^0.8.16",
33+
"@threlte/core": "^8.5.2",
34+
"@threlte/extras": "^9.13.0",
35+
"ai": "^6.0.138",
36+
"analytics": "^0.8.19",
3737
"cron-parser": "^4.9.0",
38-
"dayjs": "^1.11.13",
38+
"dayjs": "^1.11.20",
3939
"deep-equal": "^2.2.3",
4040
"echarts": "^5.6.0",
4141
"flatted": "^3.4.2",
4242
"ignore": "^6.0.2",
43-
"nanoid": "^5.1.5",
43+
"nanoid": "^5.1.7",
4444
"nanotar": "^0.1.1",
4545
"pretty-bytes": "^6.1.1",
4646
"remarkable": "^2.0.1",
@@ -49,49 +49,50 @@
4949
"tippy.js": "^6.3.7"
5050
},
5151
"devDependencies": {
52-
"@eslint/compat": "^1.3.1",
53-
"@eslint/js": "^9.31.0",
52+
"@eslint/compat": "^1.4.1",
53+
"@eslint/js": "^9.39.4",
5454
"@melt-ui/pp": "^0.3.2",
55-
"@melt-ui/svelte": "^0.86.5",
56-
"@playwright/test": "^1.55.1",
57-
"@sveltejs/adapter-static": "^3.0.8",
58-
"@sveltejs/kit": "^2.49.5",
59-
"@sveltejs/vite-plugin-svelte": "^5.0.3",
60-
"@testing-library/dom": "^10.4.0",
61-
"@testing-library/jest-dom": "^6.6.3",
62-
"@testing-library/svelte": "^5.2.8",
55+
"@melt-ui/svelte": "^0.86.6",
56+
"@playwright/test": "^1.58.2",
57+
"@sveltejs/adapter-static": "^3.0.10",
58+
"@sveltejs/kit": "^2.55.0",
59+
"@sveltejs/vite-plugin-svelte": "^5.1.1",
60+
"@testing-library/dom": "^10.4.1",
61+
"@testing-library/jest-dom": "^6.9.1",
62+
"@testing-library/svelte": "^5.3.1",
6363
"@testing-library/user-event": "^14.6.1",
6464
"@types/deep-equal": "^1.0.4",
6565
"@types/remarkable": "^2.0.8",
6666
"@types/three": "^0.182.0",
67-
"@typescript-eslint/eslint-plugin": "^8.28.0",
68-
"@typescript-eslint/parser": "^8.28.0",
67+
"@typescript-eslint/eslint-plugin": "^8.57.2",
68+
"@typescript-eslint/parser": "^8.57.2",
6969
"@vitest/ui": "^3.2.4",
70-
"color": "^5.0.0",
71-
"eslint": "^9.31.0",
72-
"eslint-config-prettier": "^10.1.0",
73-
"eslint-plugin-svelte": "^3.3.3",
74-
"globals": "^16.0.0",
70+
"color": "^5.0.3",
71+
"eslint": "^9.39.4",
72+
"eslint-config-prettier": "^10.1.8",
73+
"eslint-plugin-svelte": "^3.16.0",
74+
"globals": "^16.5.0",
7575
"jsdom": "^26.1.0",
7676
"kleur": "^4.1.5",
77-
"prettier": "^3.5.3",
78-
"prettier-plugin-svelte": "^3.3.3",
79-
"sass": "^1.86.0",
80-
"svelte": "^5.25.3",
81-
"svelte-check": "^4.1.5",
77+
"prettier": "^3.8.1",
78+
"prettier-plugin-svelte": "^3.5.1",
79+
"sass": "^1.98.0",
80+
"svelte": "^5.55.0",
81+
"svelte-check": "^4.4.5",
8282
"svelte-preprocess": "^6.0.3",
83-
"svelte-sequential-preprocessor": "^2.0.2",
84-
"tldts": "^7.0.7",
83+
"svelte-sequential-preprocessor": "^2.0.3",
84+
"tldts": "^7.0.27",
8585
"tslib": "^2.8.1",
86-
"typescript": "^5.8.2",
87-
"typescript-eslint": "^8.30.1",
88-
"vite": "^7.0.6",
86+
"typescript": "^5.9.3",
87+
"typescript-eslint": "^8.57.2",
88+
"vite": "^7.3.1",
8989
"vitest": "^3.2.4"
9090
},
9191
"overrides": {
9292
"vite": "npm:rolldown-vite@latest",
9393
"minimatch": "10.2.3",
9494
"immutable": "^5.1.5",
95-
"flatted": "^3.4.2"
95+
"flatted": "^3.4.2",
96+
"picomatch": "^2.3.2"
9697
}
9798
}

src/lib/commandCenter/commandCenter.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@
4646
{
4747
callback: toggleCommandCenter,
4848
keys: ['k'],
49-
ctrl: true,
50-
forceEnable: true
49+
ctrl: true
5150
},
5251
{
5352
label: 'Toggle debug overlay',

src/lib/components/navbar.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import { beforeNavigate } from '$app/navigation';
5050
import { page } from '$app/state';
5151
import type { Models } from '@appwrite.io/console';
52+
import { isProjectBlocked as getIsProjectBlocked } from '$lib/helpers/project';
5253
5354
let showSupport = false;
5455
@@ -108,6 +109,7 @@
108109
}
109110
110111
$: currentOrg = organizations.find((org) => org.isSelected);
112+
$: isProjectBlocked = getIsProjectBlocked(currentProject);
111113
112114
beforeNavigate(() => (showAccountMenu = false));
113115
</script>
@@ -137,7 +139,7 @@
137139
size="xs"
138140
variant="secondary"
139141
href={`${base}/project-${currentProject.region}-${currentProject.$id}/get-started`}
140-
>Connect</Button.Anchor>
142+
disabled={isProjectBlocked}>Connect</Button.Anchor>
141143
</div>
142144
{/if}
143145
</div>
@@ -201,6 +203,7 @@
201203
<Button.Button
202204
variant="text"
203205
aria-label="Toggle Command Center"
206+
disabled={isProjectBlocked}
204207
on:click={toggleCommandCenter}
205208
icon>
206209
<Icon icon={IconSearch} />

src/lib/helpers/project.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { page } from '$app/state';
22
import { get } from 'svelte/store';
33
import { sdk } from '$lib/stores/sdk';
44
import { projectRegion } from '$routes/(console)/project-[region]-[project]/store';
5+
import type { Models } from '@appwrite.io/console';
56

67
/**
78
* Returns the current project ID.
@@ -42,3 +43,7 @@ export function getProjectEndpoint(): string {
4243

4344
return currentProjectRegion ? `${protocol}//${currentProjectRegion.$id}.${hostname}/v1` : href;
4445
}
46+
47+
export function isProjectBlocked(project: Models.Project | null | undefined): boolean {
48+
return project?.status !== 'paused' && !!project?.blocks?.length;
49+
}

src/lib/layout/shell.svelte

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import { BillingPlanGroup, type Models } from '@appwrite.io/console';
1919
import { getSidebarState, isInDatabasesRoute, updateSidebarState } from '$lib/helpers/sidebar';
2020
import { isTabletViewport } from '$lib/stores/viewport';
21+
import { isProjectBlocked as getIsProjectBlocked } from '$lib/helpers/project';
2122
2223
export let showHeader = true;
2324
export let showFooter = true;
@@ -180,7 +181,7 @@
180181
$: shouldRenderSidebar =
181182
!$isNewWizardStatusOpen && showSideNavigation && !$showOnboardingAnimation;
182183
$: hasSidebarSpace = shouldRenderSidebar && !$isTabletViewport && !!selectedProject;
183-
184+
$: isProjectBlocked = getIsProjectBlocked(selectedProject);
184185
$: {
185186
if ($isSidebarOpen) {
186187
yOnMenuOpen = window.scrollY;
@@ -211,20 +212,22 @@
211212
<Navbar {...navbarProps} bind:sideBarIsOpen={$isSidebarOpen} bind:showAccountMenu />
212213
{/if}
213214

214-
{#if shouldRenderSidebar}
215-
<Sidebar
216-
project={selectedProject}
217-
progressCard={getProgressCard()}
218-
avatar={navbarProps.avatar}
219-
bind:subNavigation
220-
bind:sideBarIsOpen={$isSidebarOpen}
221-
bind:showAccountMenu
222-
bind:state />
223-
{/if}
224-
225-
{#if !$showOnboardingAnimation}
226-
<SideNavigation bind:subNavigation />
227-
{/if}
215+
<div class="shell-sidebar-area" inert={isProjectBlocked || undefined}>
216+
{#if shouldRenderSidebar}
217+
<Sidebar
218+
project={selectedProject}
219+
progressCard={getProgressCard()}
220+
avatar={navbarProps.avatar}
221+
bind:subNavigation
222+
bind:sideBarIsOpen={$isSidebarOpen}
223+
bind:showAccountMenu
224+
bind:state />
225+
{/if}
226+
227+
{#if !$showOnboardingAnimation}
228+
<SideNavigation bind:subNavigation />
229+
{/if}
230+
</div>
228231

229232
<div
230233
class="content"
@@ -255,6 +258,11 @@
255258
</main>
256259

257260
<style lang="scss">
261+
.shell-sidebar-area {
262+
position: relative;
263+
z-index: 2;
264+
}
265+
258266
.content {
259267
width: 100%;
260268
Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,77 @@
11
<script lang="ts">
22
import { page } from '$app/state';
3-
import { Container } from '$lib/layout';
4-
import { Card, Link, Typography } from '@appwrite.io/pink-svelte';
3+
import { Button } from '$lib/elements/forms';
4+
import { currentPlan, organizationList } from '$lib/stores/organization';
55
import SupportWizard from '$routes/(console)/supportWizard.svelte';
6-
import { capitalize } from '$lib/helpers/string';
7-
import { currentPlan } from '$lib/stores/organization';
86
import { wizard } from '$lib/stores/wizard';
7+
import { Badge, Layout, Typography } from '@appwrite.io/pink-svelte';
8+
import type { Models } from '@appwrite.io/console';
99
10-
function getResource(id: string) {
11-
id = id.replace('/(console)/project-[region]-[project]/', '');
12-
let parts = id.split('/');
13-
const resource = parts[0];
14-
15-
return resource === 'settings' ? 'project' : resource;
10+
function contactSupport() {
11+
wizard.start(SupportWizard);
1612
}
13+
14+
$: allOrgsHavePremiumSupport = $organizationList.teams.every(
15+
(team) => (team as Models.Organization).billingPlanDetails.premiumSupport
16+
);
17+
18+
$: hasPremiumSupport = $currentPlan?.premiumSupport ?? allOrgsHavePremiumSupport ?? false;
1719
</script>
1820

19-
<Container>
20-
{#if page.error.type === 'general_resource_blocked'}
21-
{@const resource = getResource(page.route.id)}
22-
<Card.Base>
23-
<Typography.Title size="s">Your {capitalize(resource)} is paused</Typography.Title>
24-
<p class="text-red-500">
25-
We've detected unusual activity and temporarily paused your {resource}. If you
26-
believe this is a mistake or need urgent access, please contact
27-
{#if $currentPlan?.premiumSupport}
28-
<Link.Button
29-
on:click={() => {
30-
wizard.start(SupportWizard);
31-
}}>support</Link.Button
32-
>.
33-
{:else}
34-
support@appwrite.io.
35-
{/if}
36-
</p>
37-
</Card.Base>
38-
{:else}
39-
<Typography.Title size="xl"
40-
>{'status' in page.error
41-
? page.error.status || 'Invalid Argument'
42-
: 'Invalid Argument'}</Typography.Title>
21+
{#if page.error.type === 'general_resource_blocked'}
22+
<section class="resource-blocked">
23+
<div class="resource-blocked__content">
24+
<Layout.Stack gap="s" alignItems="center">
25+
<Badge type="error" variant="secondary" content="Access blocked" />
26+
<Typography.Title size="l" align="center">
27+
This resource page can&apos;t be accessed. Check your permissions or contact
28+
support for help.
29+
</Typography.Title>
30+
<div class="u-margin-block-start-16">
31+
{#if hasPremiumSupport}
32+
<Button secondary on:click={contactSupport}>Contact support</Button>
33+
{:else}
34+
<Button secondary href="mailto:support@appwrite.io">Contact support</Button>
35+
{/if}
36+
</div>
37+
</Layout.Stack>
38+
</div>
39+
</section>
40+
{:else}
41+
<section class="resource-blocked resource-blocked--default">
42+
<div class="resource-blocked__content">
43+
<Layout.Stack gap="s" alignItems="center">
44+
<Typography.Title size="s" align="center">
45+
{'status' in page.error
46+
? page.error.status || 'Invalid Argument'
47+
: 'Invalid Argument'}
48+
</Typography.Title>
49+
<p class="u-text-center">{page.error.message}</p>
50+
</Layout.Stack>
51+
</div>
52+
</section>
53+
{/if}
54+
55+
<style>
56+
.resource-blocked {
57+
min-height: calc(100vh - 48px - 2rem);
58+
display: flex;
59+
align-items: center;
60+
justify-content: center;
61+
padding: 4rem 1.5rem;
62+
text-align: center;
63+
}
64+
65+
.resource-blocked__content {
66+
width: min(100%, 33rem);
67+
max-width: 33rem;
68+
}
4369
44-
<Typography.Title>{page.error.message}</Typography.Title>
45-
{/if}
46-
</Container>
70+
.resource-blocked p {
71+
margin: 0;
72+
color: var(--fgcolor-neutral-secondary, #56565c);
73+
font-size: 1rem;
74+
line-height: 1.5;
75+
text-wrap: balance;
76+
}
77+
</style>

0 commit comments

Comments
 (0)