Conversation
Console (appwrite/console)Project ID: Tip Dynamic API keys are generated automatically for each function execution |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds project-blocking detection and applies it across UI. New helper Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR adds a "blocked project" state to the Appwrite Console: when a project has active Key changes:
Issues found:
Confidence Score: 3/5Not safe to merge as-is: keyboard users can fully bypass the blocked-project gate The feature direction and visual design are solid, but both interaction-blocking mechanisms (sidebar in shell.svelte, content area in +layout.svelte) use CSS/ARIA guards that don't stop keyboard navigation. This is a functional gap in the blocking UX — a determined user can Tab past the overlay and use the project normally. Swapping src/routes/(console)/project-[region]-[project]/+layout.svelte and src/lib/layout/shell.svelte both need the Important Files Changed
Reviews (1): Last reviewed commit: "fix layout issues" | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/routes/(console)/project-[region]-[project]/+layout.svelte (1)
34-34: Use an alias for the new SVG import.
./blocked-lock.svgis the only new relative import here. Please switch it to a$routesor$libalias so this file stays aligned with the repo import convention.♻️ Suggested change
- import BlockedLock from './blocked-lock.svg'; + import BlockedLock from '$routes/(console)/project-[region]-[project]/blocked-lock.svg';As per coding guidelines "Use $lib, $routes, and $themes path aliases for imports".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte at line 34, The SVG import uses a relative path; replace the relative import "import BlockedLock from './blocked-lock.svg';" with the project path alias (e.g., import from $routes or $lib) so it follows repo conventions; update the import to reference the route/lib alias that contains blocked-lock.svg (keeping the symbol name BlockedLock) and ensure any build/tsconfig alias mappings remain valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/layout/shell.svelte`:
- Line 183: The sidebar wrapper toggles isProjectBlocked but only disables
pointer events; make the wrapper fully non-interactive when isProjectBlocked is
true by applying the inert attribute and aria-hidden="true" on the same
container that currently gets the is-blocked class (so browsers and assistive
tech ignore it), and for extra safety ensure interactive elements inside
Sidebar/SideNavigation respect focus changes (remove or set tabindex to -1 when
isProjectBlocked is true and restore when false). Update the occurrences that
compute/use isProjectBlocked (the wrapper around Sidebar/SideNavigation and the
other two similar blocks) so the inert and aria-hidden toggles are applied
wherever the is-blocked behavior is used.
In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte:
- Around line 37-41: The overlay flag isProjectBlocked currently only controls
visibility but not the command/search registrations; update the code that
registers command-center entries and searchers (the blocks that add keybindings,
register commands or call wizard.start(SupportWizard) or similar project
navigation handlers) so they are skipped when isProjectBlocked is true — i.e.,
wrap or guard those registration calls with if (!isProjectBlocked) { ... } or
return early from the registration functions so Cmd/Ctrl+K and other
navigation/search handlers are not active while the project is blocked.
- Around line 129-130: The content wrapper currently uses
aria-hidden={isProjectBlocked} but remains keyboard-focusable; add
inert={isProjectBlocked} to the <div class="project-layout__content"> (the
element that also has aria-hidden) so its subtree is removed from the tab order
when isProjectBlocked is true; apply the same change to the other content
wrapper instance that uses aria-hidden (the second project-layout__content block
around the <slot />) so blocked content becomes truly inert for keyboard users.
- Around line 135-149: The overlay's absolute positioning centers the dialog
against the full slotted page height (project-layout__overlay /
project-layout__dialog), causing it to be off-screen on long routes; change the
overlay to be viewport-anchored (e.g., position: fixed; inset: 0) or wrap the
dialog in a viewport-sized/sticky container so the lock/message stays centered
in the user's viewport, update relevant styles for project-layout__overlay and
project-layout__dialog and ensure the Contact support Button and contactSupport
handler behavior remain unchanged.
---
Nitpick comments:
In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte:
- Line 34: The SVG import uses a relative path; replace the relative import
"import BlockedLock from './blocked-lock.svg';" with the project path alias
(e.g., import from $routes or $lib) so it follows repo conventions; update the
import to reference the route/lib alias that contains blocked-lock.svg (keeping
the symbol name BlockedLock) and ensure any build/tsconfig alias mappings remain
valid.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7c2f0b81-dee9-4c9c-91f1-785f82ce08f3
⛔ Files ignored due to path filters (1)
src/routes/(console)/project-[region]-[project]/blocked-lock.svgis excluded by!**/*.svg
📒 Files selected for processing (3)
src/lib/components/navbar.sveltesrc/lib/layout/shell.sveltesrc/routes/(console)/project-[region]-[project]/+layout.svelte
| $: isProjectBlocked = data.project?.status !== 'paused' && !!data.project?.blocks?.length; | ||
|
|
||
| function contactSupport() { | ||
| wizard.start(SupportWizard); | ||
| } |
There was a problem hiding this comment.
Blocked mode still leaves command-center entries active.
isProjectBlocked only drives the overlay. The layout still registers project navigation commands and searchers below, so Cmd/Ctrl+K remains a live path into blocked project areas. Gate those registrations with this flag too.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte around lines
37 - 41, The overlay flag isProjectBlocked currently only controls visibility
but not the command/search registrations; update the code that registers
command-center entries and searchers (the blocks that add keybindings, register
commands or call wizard.start(SupportWizard) or similar project navigation
handlers) so they are skipped when isProjectBlocked is true — i.e., wrap or
guard those registration calls with if (!isProjectBlocked) { ... } or return
early from the registration functions so Cmd/Ctrl+K and other navigation/search
handlers are not active while the project is blocked.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/routes/`(console)/project-[region]-[project]/+error.svelte:
- Around line 14-18: The reactive computation for allOrgsHavePremiumSupport and
hasPremiumSupport reads billingPlanDetails unsafely and treats an empty
organization list as premium; modify the logic in the reactive blocks
(allOrgsHavePremiumSupport, hasPremiumSupport) to guard access by checking
isCloud (or defensively using optional access) and ensure the .every check only
runs when $organizationList.teams has items — e.g., only evaluate
team.billingPlanDetails?.premiumSupport when isCloud is true and when
teams.length>0, and fall back to false otherwise so missing/partial payloads or
empty lists do not throw or incorrectly report premium support.
- Around line 44-47: The error title currently checks 'status' in page.error
(which is always false) so replace that check to use the SvelteKit-provided
page.status; update the Typography.Title expression that currently references
page.error to instead render page.status (e.g. use page.status ?? 'Invalid
Argument' or a ternary checking page.status) so the actual HTTP status code is
shown; modify the expression near Typography.Title in +error.svelte and remove
the 'status' in page.error conditional.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 16d530a4-67bf-4656-9a92-f8029f7a18bb
📒 Files selected for processing (1)
src/routes/(console)/project-[region]-[project]/+error.svelte
| <Typography.Title size="s" align="center"> | ||
| {'status' in page.error | ||
| ? page.error.status || 'Invalid Argument' | ||
| : 'Invalid Argument'} |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In SvelteKit +error.svelte, is the HTTP status exposed on $app/state's page.statuswhilepage.error only contains the error payload/body?
💡 Result:
Yes, in SvelteKit +error.svelte, the HTTP status is exposed on $app/state's page.status, while page.error contains only the error payload/body (typically { message: string } or extended App.Error object without the status code).
Citations:
- 1: https://svelte.dev/docs/kit/$app-state
- 2: https://svelte.dev/docs/kit/errors
- 3: https://svelte.dev/tutorial/kit/error-pages
- 4: Error is not handled correctly sveltejs/kit#14016
- 5: https://www.tutorialspoint.com/svelte/sveltekit-states.htm
- 6: Add
statusanderrorto page store sveltejs/kit#3096
Use page.status to display the HTTP error status.
In SvelteKit error routes, the HTTP status is exposed on page.status while page.error contains only the error payload. The current code checks for status in page.error, which never exists, so all error pages will display "Invalid Argument" instead of the actual HTTP status code.
Suggested fix
- {'status' in page.error
- ? page.error.status || 'Invalid Argument'
- : 'Invalid Argument'}
+ {page.status || 'Invalid Argument'}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Typography.Title size="s" align="center"> | |
| {'status' in page.error | |
| ? page.error.status || 'Invalid Argument' | |
| : 'Invalid Argument'} | |
| <Typography.Title size="s" align="center"> | |
| {page.status || 'Invalid Argument'} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/routes/`(console)/project-[region]-[project]/+error.svelte around lines
44 - 47, The error title currently checks 'status' in page.error (which is
always false) so replace that check to use the SvelteKit-provided page.status;
update the Typography.Title expression that currently references page.error to
instead render page.status (e.g. use page.status ?? 'Invalid Argument' or a
ternary checking page.status) so the actual HTTP status code is shown; modify
the expression near Typography.Title in +error.svelte and remove the 'status' in
page.error conditional.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte:
- Around line 204-216: The overlay (.project-layout__overlay) is currently under
the progress tray (.layout-level-progress-bars) because its z-index is 5 while
the tray is 100; increase the overlay z-index to be higher than the tray (e.g.,
>100) or add a blocked-state modifier that hides/disables
.layout-level-progress-bars when the overlay is active; update the CSS rules for
.project-layout__overlay (or add a .is-blocked modifier) so the overlay visually
and interactively sits above the progress tray and blocks its controls.
- Around line 42-45: The reactive derivations allOrgsHavePremiumSupport and
hasPremiumSupport access cloud-only billingPlanDetails on every render and will
throw on self-hosted; guard these behind the isCloud flag and use defensive
optional chaining on $organizationList and team objects. Update the
allOrgsHavePremiumSupport expression (and any use of $organizationList) to first
check isCloud and that $organizationList?.teams is an array, e.g., short-circuit
to false when not cloud, and change the team access to optional chain into
billingPlanDetails?.premiumSupport; likewise compute hasPremiumSupport as
isCloud ? ($currentPlan?.premiumSupport ?? allOrgsHavePremiumSupport) : false so
self-hosted renders never dereference billingPlanDetails.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5dfbd2e0-4194-49ee-bab0-d6462370abb8
📒 Files selected for processing (1)
src/routes/(console)/project-[region]-[project]/+layout.svelte
There was a problem hiding this comment.
♻️ Duplicate comments (3)
src/routes/(console)/project-[region]-[project]/+layout.svelte (3)
206-218:⚠️ Potential issue | 🟡 MinorOverlay z-index is below the progress tray.
project-layout__overlayusesz-index: 5(line 209), but.layout-level-progress-barsusesz-index: 100(line 248). Active upload/export/backup boxes will render above the blocked overlay, potentially exposing reachable controls.🔧 Proposed fix
.project-layout__overlay { position: fixed; inset: 48px 0 0 0; - z-index: 5; + z-index: 101; display: flex;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte around lines 206 - 218, Overlay (.project-layout__overlay) has z-index: 5 which is lower than .layout-level-progress-bars (z-index: 100), allowing progress boxes to sit above the blocked overlay; update the overlay's stacking so it sits above the progress tray by increasing its z-index to be greater than .layout-level-progress-bars (or use a shared stacking variable/constant) and ensure pointer-events remain enabled so underlying controls stay blocked; modify the .project-layout__overlay rule to use the new higher z-index value (or variable) so it consistently overlays .layout-level-progress-bars.
61-134:⚠️ Potential issue | 🟠 MajorCommand center navigation remains active when project is blocked.
The
registerCommandsandregisterSearcherscalls (lines 61-134) don't checkisProjectBlocked. Users can still navigate to blocked project areas via Cmd/Ctrl+K even though the overlay is shown.🔧 Proposed fix — disable commands when blocked
$: $registerCommands([ { label: 'Go to Auth', callback: () => { goto(`${base}/project-${$project.region}-${$project.$id}/auth`); }, keys: ['g', 'a'], - group: 'navigation' + group: 'navigation', + disabled: isProjectBlocked }, { label: 'Go to Databases', callback: () => { goto(`${base}/project-${$project.region}-${$project.$id}/databases`); }, keys: ['g', 'd'], group: 'navigation', - disabled: !$canSeeDatabases + disabled: !$canSeeDatabases || isProjectBlocked }, // ... apply same pattern to all commandsAlso guard the searchers:
- $registerSearchers(userSearcher, teamSearcher, dbSearcher, functionsSearcher, bucketSearcher); + if (!isProjectBlocked) { + $registerSearchers(userSearcher, teamSearcher, dbSearcher, functionsSearcher, bucketSearcher); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte around lines 61 - 134, The command and search registrations ($registerCommands and $registerSearchers) are executed even when isProjectBlocked is true, allowing navigation via Cmd/Ctrl+K into blocked areas; change the code to early-guard these calls by checking isProjectBlocked and either skip registering commands/searchers or mark all commands disabled when isProjectBlocked is true (update each command object used in $registerCommands to set disabled: true when isProjectBlocked, and avoid calling $registerSearchers or pass an empty list when blocked) so the command center and searchers are inert for blocked projects; touch the block that builds the array passed to $registerCommands and the call to $registerSearchers to implement this guard.
42-45:⚠️ Potential issue | 🔴 CriticalGuard
billingPlanDetailsaccess for self-hosted deployments.
billingPlanDetailsis cloud-only. This code will throw on self-hosted instances because$organizationList.teamsis accessed unconditionally, andbillingPlanDetails.premiumSupportis dereferenced without optional chaining.🔧 Proposed fix
- $: allOrgsHavePremiumSupport = $organizationList.teams.every( - (team) => (team as Models.Organization).billingPlanDetails.premiumSupport - ); - $: hasPremiumSupport = $currentPlan?.premiumSupport ?? allOrgsHavePremiumSupport ?? false; + $: allOrgsHavePremiumSupport = + isCloud && + ($organizationList?.teams?.length ?? 0) > 0 && + $organizationList.teams.every( + (team) => (team as Models.Organization).billingPlanDetails?.premiumSupport + ); + $: hasPremiumSupport = + isCloud && ($currentPlan?.premiumSupport ?? allOrgsHavePremiumSupport ?? false);Based on learnings:
billingPlanDetailsis cloud-only in the Appwrite Console, so Svelte components should guard that access withisCloudor defensive optional chaining.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte around lines 42 - 45, The current reactive statements allOrgsHavePremiumSupport and hasPremiumSupport dereference billingPlanDetails on every team which is cloud-only and will throw on self-hosted; update the logic in the reactive block for allOrgsHavePremiumSupport to defensively check that $organizationList?.teams exists and each team has billingPlanDetails (use optional chaining like team?.billingPlanDetails?.premiumSupport or guard with an isCloud flag) and then compute hasPremiumSupport as $currentPlan?.premiumSupport ?? allOrgsHavePremiumSupport ?? false so that self-hosted deployments never access billingPlanDetails unguarded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/routes/`(console)/project-[region]-[project]/+layout.svelte:
- Around line 206-218: Overlay (.project-layout__overlay) has z-index: 5 which
is lower than .layout-level-progress-bars (z-index: 100), allowing progress
boxes to sit above the blocked overlay; update the overlay's stacking so it sits
above the progress tray by increasing its z-index to be greater than
.layout-level-progress-bars (or use a shared stacking variable/constant) and
ensure pointer-events remain enabled so underlying controls stay blocked; modify
the .project-layout__overlay rule to use the new higher z-index value (or
variable) so it consistently overlays .layout-level-progress-bars.
- Around line 61-134: The command and search registrations ($registerCommands
and $registerSearchers) are executed even when isProjectBlocked is true,
allowing navigation via Cmd/Ctrl+K into blocked areas; change the code to
early-guard these calls by checking isProjectBlocked and either skip registering
commands/searchers or mark all commands disabled when isProjectBlocked is true
(update each command object used in $registerCommands to set disabled: true when
isProjectBlocked, and avoid calling $registerSearchers or pass an empty list
when blocked) so the command center and searchers are inert for blocked
projects; touch the block that builds the array passed to $registerCommands and
the call to $registerSearchers to implement this guard.
- Around line 42-45: The current reactive statements allOrgsHavePremiumSupport
and hasPremiumSupport dereference billingPlanDetails on every team which is
cloud-only and will throw on self-hosted; update the logic in the reactive block
for allOrgsHavePremiumSupport to defensively check that $organizationList?.teams
exists and each team has billingPlanDetails (use optional chaining like
team?.billingPlanDetails?.premiumSupport or guard with an isCloud flag) and then
compute hasPremiumSupport as $currentPlan?.premiumSupport ??
allOrgsHavePremiumSupport ?? false so that self-hosted deployments never access
billingPlanDetails unguarded.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3e3adaed-65ee-4333-acf1-f1d4b53b9fc9
📒 Files selected for processing (1)
src/routes/(console)/project-[region]-[project]/+layout.svelte

What does this PR do?
Test Plan
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)
Related PRs and Issues
(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)
Have you read the Contributing Guidelines on issues?
(Write your answer here.)
Summary by CodeRabbit
New Features
Chores