Skip to content

feat: implement new dialog and remove old one#1161

Merged
riderx merged 8 commits into
mainfrom
new-dialog
Jun 25, 2025
Merged

feat: implement new dialog and remove old one#1161
riderx merged 8 commits into
mainfrom
new-dialog

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Jun 24, 2025

Summary

Test plan

Screenshots

Checklist

  • My code follows the code style of this project and passes bun run lint-backend && bun run lint.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • My change has adequate E2E test coverage.
  • I have tested my code manually, and I have provided steps how to reproduce my tests

Summary by CodeRabbit

  • New Features

    • Expanded and improved localization for multiple languages, adding new translations and refining existing UI messages, prompts, and error notifications.
    • Enhanced user invitation flow with support for inviting users without existing accounts, including captcha verification.
  • Refactor

    • Unified and modernized dialog/modal management across the app, replacing the previous dialog system with a new, centralized dialog store for consistent user experience.
    • Updated dialog UI to support dynamic content, input fields, and improved button roles and styles.
    • Streamlined channel and bundle management dialogs, adding search/filter capabilities and multi-step confirmation flows.
  • Bug Fixes

    • Improved error handling and user feedback in dialogs, especially for deletion, channel management, and API key operations.
    • Fixed minor UI inconsistencies in dialog buttons and input validation.
  • Chores

    • Removed deprecated dialog-related components and legacy dialog logic.
    • Updated test coverage to verify cascading deletion of related channel data.
    • Added new admin statistics queue for backend processing.
  • Style

    • Refined button styles and dialog layouts for better clarity and accessibility.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 24, 2025

Walkthrough

This update migrates all dialog and modal management across the application from a legacy display store (useDisplayStore) to a new, centralized dialog store (useDialogV2Store). Numerous Vue components and pages are refactored to use this new dialog API, with improved input handling, button roles, and UI rendering via Teleport. Several obsolete dialog components are deleted, and dialog-related state is removed from the display store. Localization files are extensively updated and expanded across all supported languages.

Changes

File(s) Change Summary
.vscode/settings.json Enhanced i18n-ally VSCode settings: set source language to English and restrict frameworks to Vue.
messages/*.json Major updates and additions to localization strings for all supported languages, including new keys, improved phrasing, and consistency.
src/components/Dialog.vue, src/components/BundleLinkDialog.vue, src/components/InviteNewUserWithoutAccountDialog.vue Deleted obsolete dialog components, removing legacy modal logic.
src/components/DialogV2.vue Updated cancel button styling class from "btn btn-ghost" to "btn btn-outline".
src/stores/display.ts, src/auto-imports.d.ts Removed all dialog-related state, interfaces, and functions from the display store and global types.
src/App.vue Removed imports and usage of deleted dialog components.
src/components/dashboard/AppSetting.vue, DropdownOrganization.vue, DropdownProfile.vue, StepsApp.vue, StepsBundle.vue Refactored to use dialogStore for all dialogs, added Teleport-based input rendering, improved dialog flows.
src/components/tables/BundleTable.vue, ChannelTable.vue, HistoryTable.vue Migrated dialog flows to dialogStore, modularized confirmation dialogs, improved input and button handling.
src/pages/ApiKeys.vue Refactored API key creation and management dialogs to use dialogStore, added granular org/app selection, improved UI.
src/pages/app/p/[package].bundle.[bundle].vue, src/pages/app/p/[package].channel.[channel].vue Centralized dialog handling via dialogStore, added reactive state for channel/bundle management, improved UI and flows.
src/pages/app/p/[package].d.[device].vue, src/pages/delete_account.vue, src/pages/forgot_password.vue, src/pages/settings/Account.vue, src/pages/settings/ChangePassword.vue, src/pages/settings/organization/Members.vue, src/pages/settings/organization/Plans.vue, src/pages/settings/organization/Usage.vue, src/pages/settings/organization/index.vue Migrated all dialogs to dialogStore, improved input binding, multi-step flows, and UI consistency.
src/pages/demo_dialog.vue Added internationalization to dialog titles and buttons using vue-i18n.
src/services/stripe.ts Migrated dialog interactions to dialogStore, updated property names and button roles.
src/modules/auth.ts, supabase/functions/_backend/utils/supabase.ts, supabase/functions/_backend/utils/stripe_event.ts Minor code style/formatting changes, no logic affected.
supabase/migrations/20250530233128_base.sql Added creation of new pgmq queue 'admin_stats'.
tests/cli-channel.test.ts Added test to verify cascading deletion of channel_devices on channel deletion.

Sequence Diagram(s)

Centralized Dialog Flow (Old vs New)

sequenceDiagram
    participant User
    participant VueComponent
    participant DisplayStore
    participant DialogV2Store

    Note over User,VueComponent: Old Dialog Flow
    User->>VueComponent: Triggers dialog action
    VueComponent->>DisplayStore: Set dialogOption, showDialog = true
    User->>DisplayStore: Interacts with dialog
    DisplayStore-->>VueComponent: onDialogDismiss()

    Note over User,VueComponent: New Dialog Flow
    User->>VueComponent: Triggers dialog action
    VueComponent->>DialogV2Store: openDialog(options)
    User->>DialogV2Store: Interacts with dialog
    DialogV2Store-->>VueComponent: onDialogDismiss()
Loading

Example: Multi-step Dialog with Teleport Input

sequenceDiagram
    participant User
    participant VueComponent
    participant DialogV2Store

    User->>VueComponent: Initiates action (e.g., transfer ownership)
    VueComponent->>DialogV2Store: openDialog(step 1)
    User->>DialogV2Store: Confirms step 1
    DialogV2Store-->>VueComponent: onDialogDismiss()
    VueComponent->>DialogV2Store: openDialog(step 2, Teleport input rendered)
    User->>DialogV2Store: Fills input, confirms
    DialogV2Store-->>VueComponent: onDialogDismiss()
    VueComponent->>VueComponent: Proceeds with action based on input
Loading

Poem

A bunny hops through dialogs old and new,
With Teleport magic and buttons in view.
The store is now tidy, the logic refined,
Each language updated, all strings aligned.
From bundles to channels, the flow is a breeze—
This rabbit approves, with carrots and ease!

((\
( -.-)
o_(")(")


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b35e4f8 and 501dd81.

📒 Files selected for processing (5)
  • src/components/dashboard/AppSetting.vue (18 hunks)
  • src/components/tables/BundleTable.vue (12 hunks)
  • src/components/tables/ChannelTable.vue (8 hunks)
  • src/pages/settings/organization/Members.vue (12 hunks)
  • supabase/functions/_backend/utils/stripe_event.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • supabase/functions/_backend/utils/stripe_event.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/tables/ChannelTable.vue
  • src/components/tables/BundleTable.vue
  • src/components/dashboard/AppSetting.vue
🔇 Additional comments (5)
src/pages/settings/organization/Members.vue (5)

2-2: LGTM: Clean migration to new dialog system with proper type imports and state management.

The import changes appropriately support the new dialogV2 store migration and captcha-enabled invitation flow. The reactive state setup is comprehensive and well-organized.

Also applies to: 11-11, 17-18, 31-44


140-180: Excellent dialog system migration with improved consistency.

The migration to useDialogV2Store follows a consistent pattern throughout all dialog functions. The standardization of button roles to 'secondary' for permission selections and the structured dialog parameters improve both code maintainability and user experience.

Also applies to: 193-222, 274-284, 332-347


505-597: Well-implemented invitation flow for users without accounts.

The new invitation functionality is comprehensive with:

  • Proper form validation and user feedback
  • Loading state management preventing double submissions
  • Comprehensive error handling with user-friendly messages
  • Security considerations with captcha validation
  • Clean state management and form reset logic

The API integration using supabase.functions.invoke follows the correct pattern for calling Edge Functions.


625-723: Excellent Teleport implementation for dialog content rendering.

The template changes effectively implement the new dialog system with:

  • Clean conditional rendering preventing dialog content conflicts
  • Comprehensive form with proper accessibility (labels, semantic HTML)
  • Good UX with validation feedback, tooltips, and appropriate disabled states
  • Proper use of Teleport with defer attribute for dialog content

The form structure follows Vue best practices with reactive two-way binding and semantic HTML.


287-287: Fix captcha key reference bug.

The captchaKey.value usage is incorrect since captchaKey is already a ref (defined on line 43). This will cause a runtime error.

-    if (captchaKey.value) {
+    if (captchaKey) {

Likely an incorrect or invalid review comment.

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🧹 Nitpick comments (11)
src/modules/auth.ts (2)

40-40: Remove leftover debug statement or switch to structured logging

A commented-out console.log is typically just noise in the codebase.
Drop the line entirely or replace it with the project’s logger (e.g. logger.debug('set user', data)) behind an environment flag.

-          // console.log('set user', data)

68-72: Add error-handling for the asynchronous plan fetch

getPlans() is fired and silently ignored on failure. If the request rejects, the user store stays in an indeterminate state and the UI may render incorrectly.

-    getPlans().then((pls) => {
-      main.plans = pls
-    })
+    getPlans()
+      .then(pls => { main.plans = pls })
+      .catch(err => console.error('Failed to load plans', err))

At a minimum, log the error; ideally surface a toast/notification and consider retry/back-off logic.

messages/zh-cn.json (1)

93-96: Minor placeholder mismatch risk

The English key "available-versions" uses “bundles”, but the Chinese translation is "可用的捆绑包".
All good semantically, but double-check where this string is concatenated with counts; the plural noun “捆绑包” is correct only when a number follows.
No change required if UI already handles pluralisation.

messages/it.json (1)

16-16: Consider using "account" instead of "conto"

In Italian IT contexts, "account" is more commonly used than "conto". This would also maintain consistency with other technical terms that remain in English.

-  "account": "conto",
+  "account": "account",
src/pages/settings/Account.vue (1)

273-276: Consider adding verification code format validation

While removing spaces is good, consider validating that the code is exactly 6 digits before attempting verification.

handler: async () => {
  // User has clicked the "verify button - let's check"
  const verifyCode = mfaVerificationCode.value.replace(' ', '')
+  
+  // Validate code format
+  if (!/^\d{6}$/.test(verifyCode.trim())) {
+    toast.error(t('mfa-invalid-code'))
+    return false
+  }

  const { data: challenge, error: challengeError } = await supabase.auth.mfa.challenge({ factorId: data.id })
src/components/tables/BundleTable.vue (1)

128-145: Consider renaming didCancel function for clarity

The function name didCancel is misleading since it can return a deletion method string ('normal' or 'unsafe') when the user doesn't cancel. Consider a more descriptive name.

-async function didCancel(name: string, isPlural = false, askForMethod = true): Promise<boolean | 'normal' | 'unsafe'> {
+async function getDeletionMethodOrCancel(name: string, isPlural = false, askForMethod = true): Promise<boolean | 'normal' | 'unsafe'> {

Also update all references to this function throughout the file.

messages/fr.json (1)

100-100: Remove trailing colons from label translations for consistency.

These label translations have trailing colons which is inconsistent with other labels in the file. Labels should not include punctuation as it's typically added by the UI component.

Apply this diff to fix the inconsistency:

-  "bandwith-usage": "Utilisation de la bande passante:",
+  "bandwith-usage": "Utilisation de la bande passante",
-  "mau-usage": "Utilisation des utilisateurs actifs mensuels:",
+  "mau-usage": "Utilisation des utilisateurs actifs mensuels",
-  "storage-usage": "Utilisation du stockage:",
+  "storage-usage": "Utilisation du stockage",
-  "your-ussage": "Votre utilisation:",
+  "your-ussage": "Votre utilisation",

Also applies to: 404-404, 603-603, 688-688

src/pages/settings/organization/Members.vue (2)

43-43: Remove unnecessary reactivity for static environment variable.

The captchaKey doesn't need to be a reactive ref since import.meta.env values are static at build time.

Apply this diff to simplify:

-const captchaKey = ref(import.meta.env.VITE_CAPTCHA_KEY)
+const captchaKey = import.meta.env.VITE_CAPTCHA_KEY

Then update the template usage:

-<VueTurnstile v-if="captchaKey" ref="captchaElement" v-model="captchaToken" size="flexible" :site-key="captchaKey" />
+<VueTurnstile v-if="captchaKey" ref="captchaElement" v-model="captchaToken" size="flexible" :site-key="captchaKey" />

572-587: Enhance error handling with specific error details.

The Edge Function error handling could provide more specific error information to help diagnose issues.

Apply this diff to improve error handling:

 const { error } = await supabase.functions.invoke('private/invite_new_user_to_org', {
   body: {
     email: inviteUserEmail.value,
     org_id: inviteUserOrgId.value,
     invite_type: inviteType,
     captcha_token: captchaToken.value,
     first_name: inviteUserFirstName.value,
     last_name: inviteUserLastName.value,
   },
 })

 if (error) {
   console.error('Invitation failed:', error)
-  toast.error(t('invitation-failed', 'Invitation failed'))
+  const errorMessage = error.message || t('invitation-failed', 'Invitation failed')
+  toast.error(errorMessage)
   return false
 }
src/pages/app/p/[package].channel.[channel].vue (1)

630-632: Reduce debounce delay for better user experience.

The 500ms debounce delay might feel sluggish to users when searching for bundles.

Apply this diff to improve search responsiveness:

 const debouncedRefreshFilteredVersions = useDebounceFn(() => {
   refreshFilteredVersions()
-}, 500)
+}, 300)
src/pages/app/p/[package].bundle.[bundle].vue (1)

256-259: Enhance error handling with specific error details

Consider logging the actual error for debugging purposes.

   catch (error) {
     console.error(error)
-    toast.error(t('cannot-test-app-some'))
+    toast.error(t('cannot-test-app-some'))
+    console.error('Failed to link channel:', error)
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cde35a6 and 6e7e79d.

📒 Files selected for processing (48)
  • .vscode/settings.json (1 hunks)
  • messages/de.json (2 hunks)
  • messages/en.json (25 hunks)
  • messages/es.json (1 hunks)
  • messages/fr.json (14 hunks)
  • messages/id.json (3 hunks)
  • messages/it.json (2 hunks)
  • messages/ja.json (2 hunks)
  • messages/ko.json (2 hunks)
  • messages/pl.json (3 hunks)
  • messages/pt-br.json (1 hunks)
  • messages/ru.json (2 hunks)
  • messages/tr.json (1 hunks)
  • messages/vi.json (2 hunks)
  • messages/zh-cn.json (23 hunks)
  • src/App.vue (0 hunks)
  • src/auto-imports.d.ts (0 hunks)
  • src/components/BundleLinkDialog.vue (0 hunks)
  • src/components/Dialog.vue (0 hunks)
  • src/components/DialogV2.vue (1 hunks)
  • src/components/InviteNewUserWithoutAccountDialog.vue (0 hunks)
  • src/components/dashboard/AppSetting.vue (18 hunks)
  • src/components/dashboard/DropdownOrganization.vue (8 hunks)
  • src/components/dashboard/DropdownProfile.vue (6 hunks)
  • src/components/dashboard/StepsApp.vue (3 hunks)
  • src/components/dashboard/StepsBundle.vue (3 hunks)
  • src/components/tables/BundleTable.vue (12 hunks)
  • src/components/tables/ChannelTable.vue (8 hunks)
  • src/components/tables/HistoryTable.vue (4 hunks)
  • src/modules/auth.ts (1 hunks)
  • src/pages/ApiKeys.vue (9 hunks)
  • src/pages/app/p/[package].bundle.[bundle].vue (10 hunks)
  • src/pages/app/p/[package].channel.[channel].vue (17 hunks)
  • src/pages/app/p/[package].d.[device].vue (4 hunks)
  • src/pages/delete_account.vue (2 hunks)
  • src/pages/demo_dialog.vue (5 hunks)
  • src/pages/forgot_password.vue (3 hunks)
  • src/pages/settings/Account.vue (10 hunks)
  • src/pages/settings/ChangePassword.vue (3 hunks)
  • src/pages/settings/organization/Members.vue (13 hunks)
  • src/pages/settings/organization/Plans.vue (4 hunks)
  • src/pages/settings/organization/Usage.vue (3 hunks)
  • src/pages/settings/organization/index.vue (8 hunks)
  • src/services/stripe.ts (6 hunks)
  • src/stores/display.ts (1 hunks)
  • src/typed-router.d.ts (1 hunks)
  • tests/cli-channel.test.ts (1 hunks)
  • vitest.config.ts (1 hunks)
💤 Files with no reviewable changes (5)
  • src/auto-imports.d.ts
  • src/App.vue
  • src/components/Dialog.vue
  • src/components/BundleLinkDialog.vue
  • src/components/InviteNewUserWithoutAccountDialog.vue
🧰 Additional context used
🪛 GitHub Check: Run tests
tests/cli-channel.test.ts

[failure] 500-500: tests/cli-channel.test.ts > tests CLI channel commands > channel deletion > should delete channel and associated channel_devices
AssertionError: expected '\u001b[90m┌\u001b[39m Delete channel…' to contain 'Done ✅'

  • Expected
  • Received
  • Done ✅
  • ┌ Delete channel
  • ● Using custom supabase instance from provided options
  • ● Deleting channel com.cli_channel_5ece92a3-8637-45cd-baf9-a54e045414ae#test-channel-24b5b480 from Capgo
  • ■ Cannot delete Channel 🙀
  • │ code: 23503
  • │ details: Key is still referenced from table "channel_devices".
  • │ hint: null
  • │ message: update or delete on table "channels" violates foreign key constraint "channel_devices_channel_id_fkey" on table "channel_devices"

❯ tests/cli-channel.test.ts:500:22


[failure] 500-500: tests/cli-channel.test.ts > tests CLI channel commands > channel deletion > should delete channel and associated channel_devices
AssertionError: expected '\u001b[90m┌\u001b[39m Delete channel…' to contain 'Done ✅'

  • Expected
  • Received
  • Done ✅
  • ┌ Delete channel
  • ● Using custom supabase instance from provided options
  • ● Deleting channel com.cli_channel_5ece92a3-8637-45cd-baf9-a54e045414ae#test-channel-8a9e5835 from Capgo
  • ■ Cannot delete Channel 🙀
  • │ code: 23503
  • │ details: Key is still referenced from table "channel_devices".
  • │ hint: null
  • │ message: update or delete on table "channels" violates foreign key constraint "channel_devices_channel_id_fkey" on table "channel_devices"

❯ tests/cli-channel.test.ts:500:22


[failure] 461-461: tests/cli-channel.test.ts > tests CLI channel commands > channel deletion > should delete channel and associated channel_devices
Error: Test timed out in 20000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
❯ tests/cli-channel.test.ts:461:8

🪛 GitHub Actions: Run tests
tests/cli-channel.test.ts

[error] 461-500: Test timed out in 20000ms. The test 'should delete channel and associated channel_devices' failed due to a foreign key constraint violation preventing deletion of a channel because it is still referenced from table 'channel_devices'. Expected output to contain 'Done ✅' but received an error indicating 'Cannot delete Channel' with code 23503.

🔇 Additional comments (67)
vitest.config.ts (1)

7-12: ```shell
#!/bin/bash
set -e

Locate vitest.config.ts

CONFIG_FILE=$(fd vitest.config.ts | head -n 1)
echo "Config file path: $CONFIG_FILE"

Show the first 50 lines to inspect commented sections

echo "----- First 50 lines of $CONFIG_FILE -----"
sed -n '1,50p' "$CONFIG_FILE"

Search for commented-out reporters and coverage blocks

echo "----- Commented-out reporters -----"
rg -n "//\s*reporters" "$CONFIG_FILE" || echo "No commented-out 'reporters' found"

echo "----- Commented-out coverage -----"
rg -n "//\s*coverage" "$CONFIG_FILE" || echo "No commented-out 'coverage' found"

Search for active reporters and coverage settings

echo "----- Active reporters settings -----"
rg -n "reporters\s*:" "$CONFIG_FILE" || echo "No active 'reporters' setting found"

echo "----- Active coverage settings -----"
rg -n "coverage\s*:" "$CONFIG_FILE" || echo "No active 'coverage' setting found"


</details>
<details>
<summary>src/components/DialogV2.vue (1)</summary>

`87-93`: **Style update LGTM – confirm visual contrast of new `btn-outline`**  

Switching the “cancel” role to `btn-outline` is fine; just verify it still meets WCAG contrast in both light & dark themes. No functional concerns.

</details>
<details>
<summary>.vscode/settings.json (1)</summary>

`4-7`: **Nice i18n-ally refinement**  

Setting the source language and restricting frameworks will cut down noise from the extension – looks good.

</details>
<details>
<summary>src/typed-router.d.ts (1)</summary>

`49-49`: **LGTM! Standard route addition for Webhooks functionality.**

The new `/Webhooks` route entry follows the established patterns and is properly typed with no route parameters.

</details>
<details>
<summary>src/components/dashboard/StepsBundle.vue (3)</summary>

`9-12`: **LGTM! Proper imports for the dialog refactoring.**

The addition of `useDialogV2Store` and `useOrganizationStore` imports aligns with the new dialog management system.

---

`30-30`: **LGTM! Consistent store initialization.**

The `dialogStore` initialization follows the established pattern.

---

`95-106`: **LGTM! Proper dialog refactoring implementation.**

The dialog configuration correctly uses the new API with:
- `title` instead of `header`
- `description` instead of `message` 
- Proper `buttons` array structure
- Async dismissal handling with `await dialogStore.onDialogDismiss()`

This follows the standardized dialog pattern used across the codebase.

</details>
<details>
<summary>src/pages/settings/organization/Usage.vue (4)</summary>

`7-7`: **LGTM! Added router imports for navigation.**

The addition of `useRoute` and `useRouter` imports supports the existing navigation logic.

---

`13-13`: **LGTM! Dialog store import for refactoring.**

The `useDialogV2Store` import is correctly added for the new dialog system.

---

`25-25`: **LGTM! Proper store initialization.**

The `dialogStore` initialization follows the established pattern.

---

`172-182`: **LGTM! Correct dialog refactoring with preserved logic.**

The dialog configuration properly uses:
- `title` and `description` instead of the old keys
- Proper `buttons` array structure
- Async dismissal handling

The permission check and navigation logic is correctly preserved after the dialog refactoring.

</details>
<details>
<summary>src/pages/app/p/[package].d.[device].vue (3)</summary>

`17-17`: **LGTM! Dialog store import for refactoring.**

The `useDialogV2Store` import is correctly added for the new dialog system.

---

`35-35`: **LGTM! Proper store initialization.**

The `dialogStore` initialization follows the established pattern.

---

`232-248`: **LGTM! Correct dialog refactoring with preserved return behavior.**

The `didCancel` function correctly:
- Uses `dialogStore.openDialog()` with the new API structure
- Maintains proper `title`, `description`, and `buttons` configuration
- Returns the dismissal promise as expected by calling code
- Preserves the original function's behavior while adopting the new dialog system

</details>
<details>
<summary>src/components/tables/HistoryTable.vue (3)</summary>

`10-10`: **LGTM! Dialog store import for refactoring.**

The `useDialogV2Store` import is correctly added for the new dialog system.

---

`48-48`: **LGTM! Proper store initialization.**

The `dialogStore` initialization follows the established pattern.

---

`240-277`: **LGTM! Comprehensive dialog refactoring with enhanced button handling.**

The rollback dialog correctly implements the new dialog API with:
- Proper `title` and `description` configuration
- Well-structured `buttons` array with explicit roles (`primary` and `cancel`)
- Inline handler function for the confirm button that preserves the rollback logic
- Async dismissal handling

The permission checks and rollback functionality are correctly preserved while adopting the new dialog system.

</details>
<details>
<summary>src/pages/delete_account.vue (2)</summary>

`12-12`: **LGTM: Clean migration to new dialog store**

The migration from `useDisplayStore` to `useDialogV2Store` is implemented correctly with proper imports and initialization.




Also applies to: 16-16

---

`24-25`: **LGTM: Proper dialog API migration**

The dialog invocation correctly uses the new API pattern:
- `header` → `title` property rename
- `dialogStore.openDialog()` and `dialogStore.onDialogDismiss()` usage

This aligns with the broader refactoring effort across the codebase.




Also applies to: 84-85

</details>
<details>
<summary>src/components/dashboard/StepsApp.vue (2)</summary>

`9-9`: **LGTM: Correct store imports and initialization**

The migration includes proper imports for `useDialogV2Store` and `useOrganizationStore` with correct store initialization.




Also applies to: 12-12, 29-29

---

`91-101`: **LGTM: Proper dialog API transformation**

The dialog invocation correctly migrates to the new API:
- `header` → `title`
- `message` → `description`
- Uses `dialogStore.openDialog()` and `dialogStore.onDialogDismiss()`

The migration is consistent with the broader refactoring pattern.

</details>
<details>
<summary>src/pages/demo_dialog.vue (3)</summary>

`2-2`: **LGTM: Proper internationalization setup**

The `useI18n` import and initialization correctly enables internationalization support for the demo dialog component.




Also applies to: 7-7

---

`33-33`: **LGTM: Consistent internationalization implementation**

Dialog titles and button texts are properly internationalized using the `t()` function with appropriate translation keys:
- `'dialog-with-custom-input'`
- `'user-registration'`
- `'cancel'`
- `'register'`




Also applies to: 77-77, 81-81, 85-85

---

`170-170`: **LGTM: Improved teleport logic with optimization**

The conditional checks for teleport content correctly use translated strings for comparison. The addition of the `defer` attribute on line 170 is a good optimization for rendering performance.




Also applies to: 188-188

</details>
<details>
<summary>src/services/stripe.ts (2)</summary>

`5-5`: **LGTM: Correct dialog store migration setup**

The migration from `useDisplayStore` to `useDialogV2Store` is properly implemented with correct imports and store initialization in both functions.




Also applies to: 10-10, 40-40

---

`12-28`: **LGTM: Enhanced dialog API implementation**

Both functions correctly migrate to the new dialog API with:
- `header` → `title` property rename
- `message` → `description` property rename (in `openPortal`)
- Addition of `role: 'primary'` for better button semantics
- Proper use of `dialogStore.openDialog()` and `dialogStore.onDialogDismiss()`

The migration maintains the original functionality while improving the dialog interface consistency.




Also applies to: 54-76

</details>
<details>
<summary>messages/en.json (1)</summary>

`17-17`: **LGTM! Comprehensive localization improvements.**

The additions and updates to English localization strings properly support the new dialog system and UI improvements. The new keys cover dialogs, user management, bundle/channel operations, and error handling scenarios.



Also applies to: 78-78, 93-96, 112-121, 125-125, 178-178, 201-201, 208-210, 216-217, 220-220, 241-242, 244-248, 262-262, 269-269, 275-275, 298-300, 303-304, 320-321, 338-339, 350-350, 356-356, 391-391, 469-469, 517-517, 526-526, 534-534, 538-540, 552-552, 558-559, 567-568, 570-572, 574-575, 580-583, 586-586, 599-599, 616-616, 622-625, 629-630, 632-635, 660-662, 664-664, 668-668

</details>
<details>
<summary>src/components/dashboard/DropdownProfile.vue (4)</summary>

`9-9`: **LGTM! Proper migration to new dialog store.**

The import and initialization of `useDialogV2Store` is correctly implemented, replacing the old `useDisplayStore` approach.



Also applies to: 15-15, 28-28

---

`30-56`: **LGTM! Well-implemented dialog handling with reactive input.**

The `openLogAsDialog` function correctly:
- Resets the input value before opening the dialog
- Uses the new dialog API with proper configuration
- Handles user input through the reactive `logAsInput` variable
- Awaits dialog dismissal before proceeding

The dialog configuration properly includes title, buttons with roles, and a handler that captures the input value.

---

`113-132`: **LGTM! Consistent dialog pattern for logout confirmation.**

The logout dialog follows the same pattern as the log-as dialog, using the new dialog store API correctly with proper button configuration and handlers.

---

`183-194`: **LGTM! Proper Teleport implementation for dialog content.**

The Teleport block correctly:
- Conditionally renders based on dialog state and title
- Targets the correct dialog content container
- Uses proper Vue input binding with `v-model`
- Includes appropriate placeholder and styling
- Prevents form submission on enter key

The implementation follows Vue 3 best practices for teleporting content.

</details>
<details>
<summary>messages/pt-br.json (2)</summary>

`3-690`: **LGTM! Comprehensive Portuguese localization improvements.**

The Brazilian Portuguese translations have been significantly improved with:
- Better natural language phrasing
- Consistent terminology usage
- Proper punctuation and capitalization
- Enhanced clarity in technical terms
- Complete coverage of new UI elements

The translations appear to maintain consistency with the application's tone and style while being more natural in Portuguese.

---

`2-2`: **Verify the Portuguese schema URL.**

The schema URL has been changed to a Portuguese-specific version. Please ensure this URL is valid and properly serves the Portuguese localization schema.


```web
Does the URL https://inlang.com/schema/formato-de-mensagem-inlang exist and serve the correct Portuguese message format schema?
src/components/tables/ChannelTable.vue (4)

5-5: LGTM! Proper imports and store initialization.

The component correctly imports FormKit and migrates to the new useDialogV2Store, with proper reactive variable setup for the new channel name input.

Also applies to: 16-16, 41-41, 53-53


60-76: LGTM! Proper dialog confirmation implementation.

The didCancel function correctly uses the new dialog API with proper button configuration and role assignment. The function returns the dialog dismissal promise for proper async handling.


206-216: LGTM! Important data integrity improvement.

The addition of deleting channel_devices before deleting the channel is a crucial data integrity improvement. This prevents orphaned records and maintains referential integrity. The error handling properly aborts the operation if device deletion fails.


352-360: LGTM! Well-implemented FormKit integration with Teleport.

The Teleport implementation correctly:

  • Conditionally renders based on dialog state and title
  • Uses FormKit for consistent form styling
  • Includes proper placeholder text
  • Targets the correct dialog content container

The FormKit integration maintains consistency with the application's form styling.

src/pages/settings/organization/Plans.vue (2)

214-228: LGTM: Dialog migration implemented correctly

The migration from displayStore to dialogStore is properly implemented. The dialog options correctly use the new structure with title, description, and buttons, and the dismissal handling uses await dialogStore.onDialogDismiss().


300-308: LGTM: Usage details dialog properly migrated

The information dialog for detailed usage plan follows the new dialog pattern correctly. The button structure and dialog dismissal are properly implemented.

src/stores/display.ts (1)

1-29: LGTM: Complete dialog cleanup

The removal of all dialog-related state and functionality from the display store is clean and complete. The store now focuses solely on toast notifications, navigation, and selection state, which is appropriate given the migration to the new dialog system.

src/pages/settings/ChangePassword.vue (2)

48-71: LGTM: Proper 2FA dialog implementation

The 2FA dialog implementation correctly uses the new dialog store pattern. The error handling properly returns false to prevent dialog closure on verification failure, which provides good UX.


147-165: LGTM: Well-implemented Teleport for 2FA input

The Teleport component correctly renders the 2FA input only when the specific dialog is shown. The input includes proper attributes (maxlength, inputmode) and clear user instructions.

src/components/dashboard/DropdownOrganization.vue (2)

123-170: LGTM: Proper organization creation dialog with validation

The dialog implementation includes proper input validation that shows a user-friendly error message and prevents dialog closure when the organization name is empty. The error handling for duplicate names also correctly prevents dialog closure.


208-218: LGTM: Clean Teleport implementation for organization input

The Teleport component properly conditionally renders the organization name input field with appropriate styling and prevents form submission on Enter key press.

messages/pl.json (1)

1-691: LGTM: Comprehensive Polish localization updates

The extensive Polish localization updates appropriately support the new dialog system and UI improvements. The new translation keys for 2FA, user invitations, channel management, and error handling align well with the functionality described in the PR summary.

messages/ru.json (1)

1-690: Excellent localization improvements!

The Russian translation updates are comprehensive and well-executed. The changes demonstrate:

  • Consistent terminology usage throughout (e.g., consistently using "пакет" for bundle, "ключ API" for API key)
  • Improved grammar and natural phrasing that makes the interface more user-friendly
  • Proper schema URL localization
  • Addition of new keys supporting expanded UI features like captcha handling, user invitations, and dialog management

The translations maintain professional quality while improving clarity and user experience for Russian-speaking users.

src/pages/forgot_password.vue (4)

12-21: Good refactor to centralized dialog management.

The migration from useDisplayStore to useDialogV2Store improves dialog state management consistency across the application. The explicit mfaCode reactive variable provides better control over MFA input compared to implicit dialog input handling.


80-103: Improved MFA dialog implementation with good error handling.

The refactored MFA dialog implementation has several improvements:

  • Structured dialog options with clear title and description
  • Proper error handling that keeps the dialog open on invalid codes (return false)
  • Input sanitization with space removal for 6-digit codes
  • Consistent button roles with the new dialog system

The explicit state management and error handling patterns provide better user experience compared to the previous implementation.


235-253: Well-implemented Teleport for dialog content.

The Teleport implementation for the MFA input is well-executed:

  • Proper conditional rendering based on dialog state and title matching
  • Good UX attributes: maxlength="6", inputmode="numeric" for 6-digit codes
  • Appropriate styling and accessibility considerations
  • Proper reactive binding to mfaCode
  • Internationalized placeholder text

This pattern provides explicit control over dialog content rendering while maintaining clean separation of concerns.


1-261: Successful dialog system migration maintaining security and improving UX.

The migration from useDisplayStore to useDialogV2Store is well-executed and maintains all security considerations while improving the user experience:

  • MFA verification still uses proper validation and error handling
  • Explicit reactive state management improves code clarity
  • Dialog content rendering via Teleport provides better control
  • Consistent patterns that align with the broader codebase refactor

This change is part of a systematic improvement to dialog management across the application.

messages/es.json (1)

1-691: Excellent Spanish localization enhancements!

The Spanish translation updates demonstrate high localization quality:

  • Consistent terminology throughout (e.g., "paquete" for bundle, "clave API" for API key)
  • Natural Spanish phrasing that improves user experience
  • Proper schema URL localization for Spanish
  • Comprehensive addition of new keys supporting expanded UI features
  • Professional grammar and clarity improvements

These updates significantly enhance the Spanish user experience while maintaining translation consistency across the application.

src/pages/settings/organization/index.vue (4)

12-21: Good architectural improvements for dialog management.

The migration to useDialogV2Store and explicit deleteInput reactive variable improves the organization settings implementation:

  • Consistent dialog management patterns with the rest of the application
  • Explicit state management for destructive operations enhances security
  • Better separation of concerns between dialog presentation and business logic

45-71: Well-structured action sheet implementation.

The photo selection action sheet dialog is properly implemented:

  • Clear button hierarchy with appropriate roles (primary, secondary, cancel)
  • Proper async handling with dialogStore.onDialogDismiss()
  • Maintained functionality from the original implementation
  • Clean separation between dialog presentation and photo handling logic

173-214: Excellent security implementation for destructive organization deletion.

The organization deletion dialog demonstrates strong security practices:

  • Input validation: Requires exact organization name match to prevent accidental deletions
  • Error handling: Proper error feedback and dialog state management (return false on errors)
  • User feedback: Clear success/error messages with localized text
  • Safe navigation: Only redirects after successful deletion and state updates
  • Role-based security: Confirms user permissions before allowing deletion

The validation requiring the user to type the exact organization name is a critical safety measure for this destructive operation.


226-237: Good UX patterns for clipboard operations and dialog input.

Both implementations demonstrate good user experience practices:

Copy functionality (226-237):

  • Graceful fallback when clipboard API fails
  • User-friendly error dialog displaying the organization ID
  • Proper error logging for debugging

Deletion input Teleport (347-358):

  • Consistent conditional rendering pattern
  • Proper input attributes and styling
  • Prevention of accidental form submission with Enter key

These patterns enhance the robustness and usability of the organization settings interface.

Also applies to: 347-358

src/pages/settings/Account.vue (3)

36-110: LGTM! Dialog refactoring implemented correctly

The deleteAccount function properly uses the new dialogStore with appropriate title, button configuration, and awaits dialog dismissal.


238-307: Well-structured MFA dialog flow

The two-step MFA enablement process is cleanly implemented with proper state management and error handling. Good use of returning false from handlers to prevent dialog closure on validation failures.


533-550: Teleport implementation for MFA dialog is correct

Good use of conditional rendering based on dialog title, proper v-model binding, and enter key prevention.

src/components/tables/BundleTable.vue (2)

56-170: Excellent modularization of dialog functions

The separation of deletion workflow into distinct dialog functions (showDeletionMethodDialog, showDeleteConfirmationDialog, showUnlinkDialog) improves code readability and maintainability. Each function has a clear purpose and proper return values.


584-602: Good implementation of deletion style dialog content

The Teleport block properly renders additional context for the deletion style dialog, including recommendations and helpful documentation links.

src/pages/ApiKeys.vue (2)

282-344: Well-implemented API key creation with proper validation

The createApiKey function properly validates organization and app selections when limitations are enabled, with appropriate error messages and return values for dialog control.


577-584: Good UX logic for checkbox dependencies

The watcher correctly resets app limitations when organization limitation is disabled, maintaining logical consistency in the UI.

src/components/dashboard/AppSetting.vue (1)

333-430: Well-implemented multi-step dialog flow!

The app transfer ownership flow is excellently structured with:

  • Clear step progression
  • Proper permission checks
  • 32-day cooldown validation
  • App ID confirmation for safety
  • Good error handling throughout
src/pages/app/p/[package].bundle.[bundle].vue (3)

532-656: Well-implemented bundle deletion logic

The function has excellent error handling, permission checking, and user feedback. The channel unlinking logic before deletion is particularly well thought out.


828-1048: Excellent use of Teleport for dialog content

The teleport sections are well-organized and properly conditionally rendered based on dialog state. This is a clean implementation of the dialog system migration.


186-186: Fix reactive ref assignment

Direct assignment to ref should use .value.

-  selectedChannelForLink.value = null
+  selectedChannelForLink.value = null

Wait, I see the code already has .value. Let me re-examine... Actually, the code is correct as written.

messages/de.json (1)

1-690: High-quality German localization updates

The German translations are well-written with proper grammar and consistent terminology. The new dialog-related keys are correctly added and the schema URL is properly formatted.

Comment thread messages/id.json
@@ -1,181 +1,190 @@
{
"$schema": "https://inlang.com/schema/inlang-message-format",
"$schema": "https://inlang.com/schema/format-pesan-inlang",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

$schema URL deviates from canonical inlang schema – likely to break tooling

The value "https://inlang.com/schema/format-pesan-inlang" does not match the canonical URL (https://inlang.com/schema/inlang-message-format) used in every other locale file.
Editors / CI plugins relying on the schema will fail to validate this file.

-"$schema": "https://inlang.com/schema/format-pesan-inlang",
+"$schema": "https://inlang.com/schema/inlang-message-format",
📝 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.

Suggested change
"$schema": "https://inlang.com/schema/format-pesan-inlang",
"$schema": "https://inlang.com/schema/inlang-message-format",
🤖 Prompt for AI Agents
In messages/id.json at line 2, the $schema URL is incorrect and differs from the
canonical inlang schema URL. Replace the current value
"https://inlang.com/schema/format-pesan-inlang" with the correct canonical URL
"https://inlang.com/schema/inlang-message-format" to ensure proper validation by
editors and CI tools.

Comment thread messages/tr.json
"2fa-code": "2FA kimlik doğrulama kodu",
"2fa-disabled": "2FA devre dışı bırakıldı",
"6-characters-minimum": "Minimum 6 karakter, 1 büyük harf, 1 küçük harf, 1 özel karakter",
"$schema": "https://inlang.com/schema/inlang-message-format\n\nThis is a URL and it cannot be translated.",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

$schema contains embedded text and line-breaks – JSON schema reference becomes invalid

The schema value currently is:

"https://inlang.com/schema/inlang-message-format\n\nThis is a URL and it cannot be translated."

This concatenates the URL with explanatory text, resulting in an invalid (and multi-line) URI.
Down-stream tooling that tries to fetch the schema will choke.

-"$schema": "https://inlang.com/schema/inlang-message-format\n\nThis is a URL and it cannot be translated.",
+"$schema": "https://inlang.com/schema/inlang-message-format",
📝 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.

Suggested change
"$schema": "https://inlang.com/schema/inlang-message-format\n\nThis is a URL and it cannot be translated.",
"$schema": "https://inlang.com/schema/inlang-message-format",
🤖 Prompt for AI Agents
In messages/tr.json at line 2, the $schema value incorrectly includes
explanatory text and line breaks after the URL, making the JSON schema reference
invalid. Remove the extra text and line breaks so that $schema contains only the
valid URL string "https://inlang.com/schema/inlang-message-format" without any
additional characters or newlines.

Comment thread tests/cli-channel.test.ts
Comment on lines +461 to +518
it.concurrent('should delete channel and associated channel_devices', async () => {
const channelName = generateChannelName()
await createChannel(channelName, APPNAME)

// Get the channel ID
const { data: channelData } = await getSupabaseClient()
.from('channels')
.select('id')
.eq('name', channelName)
.eq('app_id', APPNAME)
.single()
.throwOnError()

const channelId = channelData!.id

// Create some channel_devices
const deviceIds = [randomUUID(), randomUUID(), randomUUID()]
for (const deviceId of deviceIds) {
await getSupabaseClient()
.from('channel_devices')
.insert({
channel_id: channelId,
device_id: deviceId,
app_id: APPNAME,
owner_org: ORG_ID,
})
.throwOnError()
}

// Verify channel_devices were created
const { data: devicesBefore } = await getSupabaseClient()
.from('channel_devices')
.select('*')
.eq('channel_id', channelId)
expect(devicesBefore).toHaveLength(3)

// Delete the channel
const output = await runCli(['channel', 'delete', channelName, APPNAME], APPNAME, false, undefined, true, true)
expect(output).toContain(`Deleting channel ${APPNAME}#${channelName} from Capgo`)
expect(output).toContain(`Done ✅`)

// Verify channel is deleted
const { data: channelAfter, error: channelError } = await getSupabaseClient()
.from('channels')
.select('*')
.eq('name', channelName)
.eq('app_id', APPNAME)
.single()
expect(channelError).toBeDefined()
expect(channelAfter).toBeNull()

// Verify channel_devices are also deleted
const { data: devicesAfter } = await getSupabaseClient()
.from('channel_devices')
.select('*')
.eq('channel_id', channelId)
expect(devicesAfter).toHaveLength(0)
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Verification correct

Critical Issue: Test fails due to missing cascade delete implementation in CLI

The test expects the CLI channel deletion command to automatically delete associated channel_devices entries, but the pipeline failures show foreign key constraint violations (error code 23503). The CLI implementation doesn't handle cascading deletes, causing this test to fail consistently.

The CLI channel deletion command needs to be updated to handle cascading deletes before this test can pass. Either:

  1. Update the CLI implementation to delete channel_devices entries before deleting the channel
  2. Modify the test to reflect the current CLI behavior (not recommended as cascading deletes are likely desired functionality)

🏁 Script executed:

#!/bin/bash
# Description: Check if the CLI channel delete command properly handles cascading deletes

# Search for the CLI channel deletion implementation
ast-grep --pattern $'function $_ {
  $$$
  delete $$$
  $$$
}'

# Look for any existing cascade delete logic
rg -A 10 -B 5 "channel.*delete|delete.*channel" --type ts

Length of output: 24937


Critical Issue: Test fails due to missing cascade delete implementation in CLI

The test expects the CLI channel deletion command to automatically delete associated channel_devices entries, but the pipeline failures show foreign key constraint violations (error code 23503). The CLI implementation doesn't handle cascading deletes, causing this test to fail consistently.

The CLI channel deletion command needs to be updated to handle cascading deletes before this test can pass. Either:

  1. Update the CLI implementation to delete channel_devices entries before deleting the channel
  2. Modify the test to reflect the current CLI behavior (not recommended as cascading deletes are likely desired functionality)
#!/bin/bash
# Description: Check if the CLI channel delete command properly handles cascading deletes

# Search for the CLI channel deletion implementation
ast-grep --pattern $'function $_ {
  $$$
  delete $$$
  $$$
}'

# Look for any existing cascade delete logic
rg -A 10 -B 5 "channel.*delete|delete.*channel" --type ts
🧰 Tools
🪛 GitHub Check: Run tests

[failure] 500-500: tests/cli-channel.test.ts > tests CLI channel commands > channel deletion > should delete channel and associated channel_devices
AssertionError: expected '\u001b[90m┌\u001b[39m Delete channel…' to contain 'Done ✅'

  • Expected
  • Received
  • Done ✅
  • ┌ Delete channel
  • ● Using custom supabase instance from provided options
  • ● Deleting channel com.cli_channel_5ece92a3-8637-45cd-baf9-a54e045414ae#test-channel-24b5b480 from Capgo
  • ■ Cannot delete Channel 🙀
  • │ code: 23503
  • │ details: Key is still referenced from table "channel_devices".
  • │ hint: null
  • │ message: update or delete on table "channels" violates foreign key constraint "channel_devices_channel_id_fkey" on table "channel_devices"

❯ tests/cli-channel.test.ts:500:22


[failure] 500-500: tests/cli-channel.test.ts > tests CLI channel commands > channel deletion > should delete channel and associated channel_devices
AssertionError: expected '\u001b[90m┌\u001b[39m Delete channel…' to contain 'Done ✅'

  • Expected
  • Received
  • Done ✅
  • ┌ Delete channel
  • ● Using custom supabase instance from provided options
  • ● Deleting channel com.cli_channel_5ece92a3-8637-45cd-baf9-a54e045414ae#test-channel-8a9e5835 from Capgo
  • ■ Cannot delete Channel 🙀
  • │ code: 23503
  • │ details: Key is still referenced from table "channel_devices".
  • │ hint: null
  • │ message: update or delete on table "channels" violates foreign key constraint "channel_devices_channel_id_fkey" on table "channel_devices"

❯ tests/cli-channel.test.ts:500:22


[failure] 461-461: tests/cli-channel.test.ts > tests CLI channel commands > channel deletion > should delete channel and associated channel_devices
Error: Test timed out in 20000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
❯ tests/cli-channel.test.ts:461:8

🪛 GitHub Actions: Run tests

[error] 461-500: Test timed out in 20000ms. The test 'should delete channel and associated channel_devices' failed due to a foreign key constraint violation preventing deletion of a channel because it is still referenced from table 'channel_devices'. Expected output to contain 'Done ✅' but received an error indicating 'Cannot delete Channel' with code 23503.

🤖 Prompt for AI Agents
In tests/cli-channel.test.ts around lines 461 to 518, the test fails because the
CLI channel deletion command does not handle cascading deletes of associated
channel_devices, causing foreign key constraint errors. To fix this, update the
CLI channel delete command implementation to explicitly delete all
channel_devices linked to the channel before deleting the channel itself. This
ensures the database constraints are respected and the test passes as expected.

Comment thread messages/en.json
"register-next": "Register",
"reload": "Reload",
"remove-bundle-from-channel": "Remove bundle from channel",
"remove-bundle-from-this-channel": "Remove budnle from this channel",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the typo in the localization key.

There's a typo: "budnle" should be "bundle".

-  "remove-bundle-from-this-channel": "Remove budnle from this channel",
+  "remove-bundle-from-this-channel": "Remove bundle from this channel",
📝 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.

Suggested change
"remove-bundle-from-this-channel": "Remove budnle from this channel",
"remove-bundle-from-this-channel": "Remove bundle from this channel",
🤖 Prompt for AI Agents
In messages/en.json at line 539, fix the typo in the string value by changing
"budnle" to "bundle" so the localization key reads "Remove bundle from this
channel".

Comment thread messages/en.json
"select-bundle-action-for-channel": "Select bundle action for channel",
"select-channel": "Select channel",
"select-channel-msg": "Please select the channel that you would like to use in this overwrite",
"select-channel-to-link": "Select channek to link",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the typo in the localization key.

There's a typo: "channek" should be "channel".

-  "select-channel-to-link": "Select channek to link",
+  "select-channel-to-link": "Select channel to link",
📝 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.

Suggested change
"select-channel-to-link": "Select channek to link",
"select-channel-to-link": "Select channel to link",
🤖 Prompt for AI Agents
In messages/en.json at line 574, correct the typo in the string value by
changing "channek" to "channel" so the text reads "Select channel to link".

Comment on lines +638 to +671
async function refreshFilteredVersions() {
if (!channel.value)
return

if (bundleLinkSearchVal.value && bundleLinkSearchVal.value.trim()) {
const { data, error } = await supabase.from('app_versions')
.select('*')
.eq('app_id', channel.value.app_id)
.eq('deleted', false)
.neq('id', channel.value.version.id)
.order('created_at', { ascending: false })
.like('name', `%${bundleLinkSearchVal.value.trim()}%`)
.limit(5)
if (error) {
console.error(error)
toast.error(t('error-fetching-versions'))
}
bundleLinkVersions.value = data ?? []
}
else {
const { data, error } = await supabase.from('app_versions')
.select('*')
.eq('app_id', channel.value.app_id)
.eq('deleted', false)
.neq('id', channel.value.version.id)
.order('created_at', { ascending: false })
.limit(5)
if (error) {
console.error(error)
toast.error(t('error-fetching-versions'))
}
bundleLinkVersions.value = data ?? []
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add loading state for bundle search operations.

The async search operations should show a loading indicator to provide better user feedback.

Add a loading state ref:

const isBundleSearchLoading = ref(false)

Then update the search function:

 async function refreshFilteredVersions() {
   if (!channel.value)
     return
+  
+  isBundleSearchLoading.value = true
+  try {
     if (bundleLinkSearchVal.value && bundleLinkSearchVal.value.trim()) {
       const { data, error } = await supabase.from('app_versions')
         // ... query
       if (error) {
         console.error(error)
         toast.error(t('error-fetching-versions'))
       }
       bundleLinkVersions.value = data ?? []
     }
     else {
       const { data, error } = await supabase.from('app_versions')
         // ... query
       if (error) {
         console.error(error)
         toast.error(t('error-fetching-versions'))
       }
       bundleLinkVersions.value = data ?? []
     }
+  } finally {
+    isBundleSearchLoading.value = false
+  }
 }

And update the template to show loading state:

<!-- Add after line 908 -->
<div v-if="isBundleSearchLoading" class="text-center py-4">
  <Spinner size="w-8 h-8" />
</div>
🤖 Prompt for AI Agents
In src/pages/app/p/[package].channel.[channel].vue around lines 638 to 671, the
async function refreshFilteredVersions lacks a loading state to indicate when
the bundle search is in progress. To fix this, declare a ref named
isBundleSearchLoading initialized to false, set it to true at the start of
refreshFilteredVersions, and set it back to false after the search completes or
errors. Also, update the template around line 908 to conditionally render a
loading spinner when isBundleSearchLoading is true, providing clear user
feedback during search operations.

console.error(error)
toast.error(t('cannot-test-app-some'))
else if (localDependencies.length === 0) {
toast.info('ignore-compatibility')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use translation for toast message

The toast message should use the translation function for consistency.

-      toast.info('ignore-compatibility')
+      toast.info(t('ignore-compatibility'))
📝 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.

Suggested change
toast.info('ignore-compatibility')
toast.info(t('ignore-compatibility'))
🤖 Prompt for AI Agents
In src/pages/app/p/[package].bundle.[bundle].vue at line 248, the toast message
'ignore-compatibility' is hardcoded and should use the translation function
instead. Replace the string with a call to the translation function (e.g., $t or
equivalent) passing 'ignore-compatibility' as the key to ensure the message is
localized consistently.

Comment on lines +51 to +72
watch(() => channelSearchVal.value, () => {
if (channelSearchVal.value.trim()) {
filteredChannels.value = channels.value.filter(channel =>
channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
)
}
else {
filteredChannels.value = channels.value
}
})

// Update filtered channels when channels change
watch(() => channels.value, () => {
if (channelSearchVal.value.trim()) {
filteredChannels.value = channels.value.filter(channel =>
channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
)
}
else {
filteredChannels.value = channels.value
}
}, { immediate: true })
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor duplicated channel filtering logic

The watch functions contain identical filtering logic, violating the DRY principle. Consider using a computed property instead.

Replace the two watch functions with a single computed property:

-// Watch for search changes
-watch(() => channelSearchVal.value, () => {
-  if (channelSearchVal.value.trim()) {
-    filteredChannels.value = channels.value.filter(channel =>
-      channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
-    )
-  }
-  else {
-    filteredChannels.value = channels.value
-  }
-})
-
-// Update filtered channels when channels change
-watch(() => channels.value, () => {
-  if (channelSearchVal.value.trim()) {
-    filteredChannels.value = channels.value.filter(channel =>
-      channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
-    )
-  }
-  else {
-    filteredChannels.value = channels.value
-  }
-}, { immediate: true })
+// Computed property for filtered channels
+const filteredChannels = computed(() => {
+  if (channelSearchVal.value.trim()) {
+    return channels.value.filter(channel =>
+      channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
+    )
+  }
+  return channels.value
+})

Also remove the reactive declaration on line 48:

-const filteredChannels = ref<(Database['public']['Tables']['channels']['Row'])[]>([])
📝 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.

Suggested change
watch(() => channelSearchVal.value, () => {
if (channelSearchVal.value.trim()) {
filteredChannels.value = channels.value.filter(channel =>
channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
)
}
else {
filteredChannels.value = channels.value
}
})
// Update filtered channels when channels change
watch(() => channels.value, () => {
if (channelSearchVal.value.trim()) {
filteredChannels.value = channels.value.filter(channel =>
channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
)
}
else {
filteredChannels.value = channels.value
}
}, { immediate: true })
// Remove this reactive declaration:
// - const filteredChannels = ref<(Database['public']['Tables']['channels']['Row'])[]>([])
// Add a computed property instead of two duplicated watchers:
const filteredChannels = computed(() => {
if (channelSearchVal.value.trim()) {
return channels.value.filter(channel =>
channel.name.toLowerCase().includes(channelSearchVal.value.toLowerCase()),
)
}
return channels.value
})
// (The two watch calls below have been removed)
// watch(() => channelSearchVal.value, ...) { … }
// watch(() => channels.value, …, { immediate: true }) { … }
🤖 Prompt for AI Agents
In src/pages/app/p/[package].bundle.[bundle].vue around lines 51 to 72, the
channel filtering logic is duplicated in two watch functions. Refactor by
removing these watch functions and the reactive declaration on line 48, then
create a single computed property that returns the filtered channels based on
channelSearchVal and channels. This computed property will automatically update
when either value changes, eliminating duplication and adhering to the DRY
principle.

Comment thread messages/vi.json
@@ -1,511 +1,561 @@
{
"$schema": "https://inlang.com/schema/inlang-message-format",
"$schema": "https://inlang.com/schema/dinh-dang-tin-nhan-inlang",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Keep schema URL in English

The schema URL should not be translated as it's a technical identifier that tools may depend on.

-  "$schema": "https://inlang.com/schema/dinh-dang-tin-nhan-inlang",
+  "$schema": "https://inlang.com/schema/inlang-message-format",
📝 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.

Suggested change
"$schema": "https://inlang.com/schema/dinh-dang-tin-nhan-inlang",
"$schema": "https://inlang.com/schema/inlang-message-format",
🤖 Prompt for AI Agents
In messages/vi.json at line 2, the schema URL is currently translated, which
should be avoided because it is a technical identifier. Revert the schema URL
back to the original English version
"https://inlang.com/schema/message-format-inlang" to ensure compatibility with
tools that rely on this exact URL.

Comment thread messages/ja.json
{
"$schema": "https://inlang.com/schema/inlang-message-format",
"2fa": "2FA の管理",
"$schema": "https://inlang.com/schema/inlang-message-format\n\nを日本語に翻訳します:\n\nhttps://inlang.com/schema/inlang-メッセージ形式",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix malformed schema URL

The schema URL contains Japanese text that breaks the URL format. It should remain in English.

-  "$schema": "https://inlang.com/schema/inlang-message-format\n\nを日本語に翻訳します:\n\nhttps://inlang.com/schema/inlang-メッセージ形式",
+  "$schema": "https://inlang.com/schema/inlang-message-format",
📝 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.

Suggested change
"$schema": "https://inlang.com/schema/inlang-message-format\n\nを日本語に翻訳します:\n\nhttps://inlang.com/schema/inlang-メッセージ形式",
"$schema": "https://inlang.com/schema/inlang-message-format",
🤖 Prompt for AI Agents
In messages/ja.json at line 2, the $schema URL is malformed because it includes
Japanese text, breaking the URL format. Replace the entire value with the
correct English URL "https://inlang.com/schema/inlang-message-format" without
any additional Japanese characters or line breaks.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
src/pages/ApiKeys.vue (1)

533-553: Potential duplicate selection issue in checkbox handlers.

The checkbox change handlers might add duplicate entries if called multiple times. Consider checking for existence before adding.

function handleOrgSelection(orgId: string, checked: boolean) {
  if (checked) {
-    if (!displayStore.selectedOrganizations.includes(orgId)) {
-      displayStore.selectedOrganizations.push(orgId)
-    }
+    const index = displayStore.selectedOrganizations.indexOf(orgId)
+    if (index === -1) {
+      displayStore.selectedOrganizations.push(orgId)
+    }
  }
  else {
    displayStore.selectedOrganizations = displayStore.selectedOrganizations.filter(id => id !== orgId)
  }
}
src/pages/app/p/[package].channel.[channel].vue (1)

638-671: Add loading state for bundle search operations.

The async search operations should show a loading indicator to provide better user feedback.

Add a loading state ref:

const isBundleSearchLoading = ref(false)

Then update the search function:

 async function refreshFilteredVersions() {
   if (!channel.value)
     return
+  
+  isBundleSearchLoading.value = true
+  try {
     if (bundleLinkSearchVal.value && bundleLinkSearchVal.value.trim()) {
       const { data, error } = await supabase.from('app_versions')
         // ... query
       if (error) {
         console.error(error)
         toast.error(t('error-fetching-versions'))
       }
       bundleLinkVersions.value = data ?? []
     }
     else {
       const { data, error } = await supabase.from('app_versions')
         // ... query
       if (error) {
         console.error(error)
         toast.error(t('error-fetching-versions'))
       }
       bundleLinkVersions.value = data ?? []
     }
+  } finally {
+    isBundleSearchLoading.value = false
+  }
 }
src/pages/app/p/[package].bundle.[bundle].vue (2)

51-72: Refactor duplicated channel filtering logic

This is the same duplicated filtering logic that was previously flagged. The two watch functions contain identical code and violate the DRY principle.


248-248: Use translation for toast message

The toast message 'ignore-compatibility' is still hardcoded and should use the translation function for consistency.

🧹 Nitpick comments (1)
src/pages/app/p/[package].bundle.[bundle].vue (1)

828-1048: Consider extracting dialog content to separate components

The multiple Teleport components provide rich dialog content but result in a very long template. Consider extracting these into separate dialog content components for better maintainability.

For example, create components like:

  • ChannelLinkingDialog.vue
  • ChannelActionsDialog.vue
  • BundleDeletionDialog.vue

This would improve code organization and reusability across the application.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 559af83 and b35e4f8.

📒 Files selected for processing (15)
  • src/components/dashboard/AppSetting.vue (18 hunks)
  • src/components/dashboard/StepsApp.vue (3 hunks)
  • src/components/dashboard/StepsBundle.vue (3 hunks)
  • src/components/tables/BundleTable.vue (12 hunks)
  • src/components/tables/ChannelTable.vue (8 hunks)
  • src/components/tables/HistoryTable.vue (4 hunks)
  • src/pages/ApiKeys.vue (9 hunks)
  • src/pages/app/p/[package].bundle.[bundle].vue (10 hunks)
  • src/pages/app/p/[package].channel.[channel].vue (17 hunks)
  • src/pages/app/p/[package].d.[device].vue (4 hunks)
  • src/pages/forgot_password.vue (3 hunks)
  • src/pages/settings/Account.vue (10 hunks)
  • src/pages/settings/organization/Usage.vue (3 hunks)
  • src/services/supabase.ts (1 hunks)
  • supabase/functions/_backend/utils/supabase.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/services/supabase.ts
  • supabase/functions/_backend/utils/supabase.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/components/tables/HistoryTable.vue
  • src/pages/settings/organization/Usage.vue
  • src/pages/app/p/[package].d.[device].vue
  • src/components/dashboard/StepsBundle.vue
  • src/components/dashboard/StepsApp.vue
  • src/components/tables/ChannelTable.vue
  • src/pages/forgot_password.vue
  • src/components/tables/BundleTable.vue
🔇 Additional comments (23)
src/pages/settings/Account.vue (5)

17-17: Good migration to centralized dialog store.

The import of useDialogV2Store correctly replaces the old dialog management system.


32-34: Well-structured reactive state for MFA dialog inputs.

The reactive variables for MFA verification code and QR code are properly declared and will integrate well with the new dialog system.


36-110: Dialog migration implemented correctly with proper error handling.

The deleteAccount function properly migrates to the new dialog store API with:

  • Correct button roles and handlers
  • Proper await pattern with dialogStore.onDialogDismiss()
  • Maintained error handling logic

234-307: Excellent refactoring of MFA enablement into two-step dialog flow.

The MFA setup is well-structured with:

  • Clear separation between QR code display and verification steps
  • Proper state management with reactive variables
  • Correct error handling that returns false to prevent dialog closure
  • Good cleanup of MFA enrollment on cancellation

The sequential dialog approach improves user experience by breaking down the complex MFA setup process.


533-549: Well-implemented Teleport component for MFA dialog content.

The Teleport component properly:

  • Conditionally renders based on dialog state and title
  • Handles both QR code display and verification input states
  • Uses proper v-model binding for the verification code
  • Includes appropriate styling and accessibility

The defer attribute ensures proper DOM timing.

src/pages/ApiKeys.vue (4)

13-13: Good migration to centralized dialog store.

The import and initialization of useDialogV2Store correctly replaces the old dialog management system.

Also applies to: 19-19


29-40: Well-structured reactive state for API key dialog functionality.

The reactive variables for dialog state management are properly declared:

  • newApiKeyName for name change dialogs
  • Checkbox states for organization/app limitations
  • availableApps for dynamic app selection

These will integrate well with the new dialog system.


282-344: Well-structured API key creation function with proper validation.

The createApiKey function properly:

  • Validates organization and app selections before creation
  • Returns false on validation failures to prevent dialog closure
  • Handles errors appropriately with user feedback
  • Updates the local state after successful creation

The function correctly integrates with the new dialog system's button handler pattern.


624-685: Excellent Teleport implementation for complex API key creation dialog.

The Teleport component for the "Add New Key" modal properly:

  • Conditionally renders based on dialog state and title
  • Implements nested checkbox logic for organization/app limitations
  • Uses proper v-model bindings and event handlers
  • Provides good UX with scrollable containers and clear labels

The organization-to-app filtering logic enhances usability by showing only relevant apps.

src/pages/app/p/[package].channel.[channel].vue (4)

22-22: Good migration to centralized dialog store.

The import and initialization of useDialogV2Store correctly replaces the old dialog management system.

Also applies to: 31-31


46-57: Well-structured reactive state for bundle linking functionality.

The reactive variables for bundle link dialog state are properly declared:

  • bundleLinkVersions for available versions
  • bundleLinkSearchVal for search input
  • bundleLinkSearchMode for UI state management

The computed properties enhance the component's reactivity.


592-628: Excellent implementation of bundle version selection dialog.

The openSelectVersion function properly:

  • Fetches available versions with appropriate filters
  • Initializes dialog state correctly
  • Uses the new dialog store API with proper configuration
  • Handles errors with user feedback

The function sets up the foundation for the enhanced bundle management UX.


867-1012: Outstanding Teleport implementation for bundle management dialog.

The bundle management dialog provides excellent UX with:

  • Clear current bundle indication
  • Search functionality with debounced input
  • Action cards for different operations (link, unlink, revert)
  • Proper conditional rendering based on search mode
  • Good visual hierarchy and accessibility

The implementation properly separates search results from action options, making the interface intuitive.

src/components/dashboard/AppSetting.vue (5)

15-15: Good migration to centralized dialog store.

The import and initialization of useDialogV2Store correctly replaces the old dialog management system.

Also applies to: 24-24


28-30: Well-structured reactive state for dialog inputs.

The reactive variables for dialog inputs are properly declared:

  • transferAppIdInput for app ID confirmation
  • selectedChannel and availableChannels for channel selection

These will integrate well with the Teleport components.


158-211: Excellent refactoring of channel selection into dialog-based flow.

The setDefaultChannel function properly:

  • Fetches available channels with error handling
  • Uses reactive state for channel selection
  • Implements proper validation in the dialog handler
  • Returns false on validation failure to prevent dialog closure
  • Provides user feedback on success/failure

The radio button approach via Teleport enhances UX compared to a simple dropdown.


333-430: Outstanding implementation of multi-step app transfer flow.

The transferAppOwnership function excellently implements a secure multi-step process:

  1. Initial confirmation - Warns about requirements
  2. Organization selection - Dynamic buttons for eligible organizations
  3. Final confirmation - Requires app ID input for verification

Key strengths:

  • Proper validation at each step with early returns
  • Secure app ID confirmation to prevent accidental transfers
  • Good error handling and user feedback
  • Proper integration with the new dialog system

The flow provides excellent UX while maintaining security.


573-607: Well-implemented Teleport components for dialog inputs.

Both Teleport components properly:

  • Conditionally render based on dialog state and title
  • Use appropriate input controls (text input, radio buttons)
  • Include proper styling and accessibility attributes
  • Handle user interactions correctly

The radio button implementation for channel selection provides better UX than a dropdown.

src/pages/app/p/[package].bundle.[bundle].vue (5)

106-117: Well-implemented dialog migration

The copyToast function has been properly migrated to use the new dialogStore with consistent button roles and proper async handling.


178-214: Clean channel chooser implementation

The refactored ASChannelChooser function properly handles permissions, initializes state, and uses the new dialog system consistently. The separation of concerns with handleChannelLink is well done.


216-260: Robust compatibility checking logic

The handleChannelLink function implements thorough compatibility validation with proper error handling and user confirmation flows. The fallback for compatibility checking is well handled.


532-656: Comprehensive bundle deletion workflow

The deleteBundle function implements a thorough multi-step deletion process with proper channel unlinking, permission checks, and both soft/hard deletion options. The error handling and user feedback are excellent.


717-727: Improved channel UI with settings access

The addition of settings buttons next to each linked channel provides better UX for channel management. The styling and interaction patterns are consistent.

@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit 0179d57 into main Jun 25, 2025
11 of 12 checks passed
@riderx riderx deleted the new-dialog branch June 25, 2025 13:46
@coderabbitai coderabbitai Bot mentioned this pull request Nov 7, 2025
5 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Jan 14, 2026
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant