Skip to content

feat(web): redesign settings - #1905

Merged
tinsever merged 4 commits into
mainfrom
feat/settings-redesign
Oct 3, 2026
Merged

tinsever merged 4 commits into
mainfrom
feat/settings-redesign

Conversation

@tinsever

@tinsever tinsever commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

What changed?

People kept telling us the settings page felt off. Switching tabs swapped out the whole sidebar, and the big headings didn't match the rest of the app.

Settings now work like a mode of the app. The app sidebar is replaced by a settings sidebar with the same width and frame, grouped into account, workspace, projects and administration. Each project opens its own pages right in the sidebar, so the project dropdown is gone. Esc takes you back to the workspace unless an overlay is open or focus is within a form or on an editable field. On mobile the navigation opens as a sheet.

All pages now share one page header and the same section and card styles. The integrations page is a list with each service's logo, and connected ones show their repository or channel. Their status loads for all workspace members, matching the API read permissions. Pending reads show a loading state, and failed initial reads offer a retry without presenting the service as disconnected. Cached status survives a failed background refresh, and nullable activity flags are shown as paused. Preferences got a visual theme picker and a board or list toggle.

There are seven new translation keys, added to every locale.

Related issue

None.

How did you check it?

Tests cover the navigation model, breadcrumbs, the Esc behaviour, integration status reads, loading and failure states, retry, and keeping open settings panels mounted after a background status failure. Lint, typecheck, the web test suite and the i18n check pass. I also clicked through the settings pages on desktop and mobile, in light and dark mode.

Settings now use one sidebar in the same frame as the app instead of
tabs that each swapped in their own sidebar. Projects expand in place,
Esc goes back to the workspace, and every page shares the same header
and section styles. The integrations page lists each service with its
logo and connection status.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-03T15:18:10.895017Z 5bbe6df Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Redesign settings navigation and unify settings pages

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Replaces tab-specific sidebars with one app-framed settings sidebar and expandable project
 navigation.
• Standardizes page styling, adds visual preferences, and shows permission-gated integration status.
• Adds translations and tests for navigation, breadcrumbs, Escape behavior, and integration status.
Diagram

graph TD
  Route["Settings Route"] --> Shell["Settings Shell"] --> Sidebar["Unified Sidebar"] --> Nav["Navigation Model"]
  Shell --> Pages["Settings Pages"] --> Integrations["Integration List"] --> Queries["Permission Gated Queries"]
  Shell --> Escape["Escape Handling"]
  Pages --> Preferences["Visual Preferences"]
Loading
High-Level Assessment

A single shell and data-driven navigation model address the sidebar inconsistency without changing route URLs. Reusing integration query keys and shared page components is preferable to maintaining parallel settings layouts or duplicate status fetching.

Files changed (97) +2183 / -1241

Enhancement (40) +1440 / -252
theme-picker.tsxAdd visual theme selector +65/-0

Add visual theme selector

• Offers light, dark, and system choices as accessible radio options with previews.

apps/web/src/components/account/theme-picker.tsx

theme-preview-window.tsxAdd theme preview illustration +61/-0

Add theme preview illustration

• Draws a fixed-palette miniature app frame for each theme option.

apps/web/src/components/account/theme-preview-window.tsx

discord-icon.tsxAdd Discord service logo +16/-0

Add Discord service logo

• Provides a local SVG brand icon for integration rows.

apps/web/src/components/icons/discord-icon.tsx

gitea-icon.tsxAdd Gitea service logo +16/-0

Add Gitea service logo

• Provides a local SVG brand icon for integration rows.

apps/web/src/components/icons/gitea-icon.tsx

mattermost-icon.tsxAdd Mattermost service logo +16/-0

Add Mattermost service logo

• Provides a local SVG brand icon for integration rows.

apps/web/src/components/icons/mattermost-icon.tsx

slack-icon.tsxAdd multicolor Slack service logo +26/-0

Add multicolor Slack service logo

• Provides the four-color Slack SVG mark for integration rows.

apps/web/src/components/icons/slack-icon.tsx

telegram-icon.tsxAdd Telegram service logo +16/-0

Add Telegram service logo

• Provides a local SVG brand icon for integration rows.

apps/web/src/components/icons/telegram-icon.tsx

get-integration-status.tsDerive display statuses for integrations +37/-0

Derive display statuses for integrations

• Converts configuration and activation data into status and formatted detail.

apps/web/src/components/project/integrations/get-integration-status.ts

integration-definitions.tsxDefine the integration catalog +114/-0

Define the integration catalog

• Associates each service with its category, logo, text, and settings component.

apps/web/src/components/project/integrations/integration-definitions.tsx

integration-row.tsxAdd expandable integration list row +79/-0

Add expandable integration list row

• Shows logo, status, repository or channel detail, and a configuration panel.

apps/web/src/components/project/integrations/integration-row.tsx

integration-status-badge.tsxAdd integration connection badge +37/-0

Add integration connection badge

• Displays connected or paused state while omitting badges for disconnected services.

apps/web/src/components/project/integrations/integration-status-badge.tsx

integrations-group.tsxGroup integration list rows +37/-0

Group integration list rows

• Renders a titled card containing integration rows and their statuses.

apps/web/src/components/project/integrations/integrations-group.tsx

use-integration-statuses.tsAggregate permission-gated integration statuses +76/-0

Aggregate permission-gated integration statuses

• Reuses existing integration queries and maps their responses into list status and detail.

apps/web/src/components/project/integrations/use-integration-statuses.ts

build-settings-nav.tsBuild unified settings navigation +151/-0

Build unified settings navigation

• Produces account, workspace, project, and administration links from live settings context.

apps/web/src/components/settings/nav/build-settings-nav.ts

get-settings-breadcrumb.tsResolve breadcrumbs from navigation links +33/-0

Resolve breadcrumbs from navigation links

• Matches normalized paths to their section and page labels.

apps/web/src/components/settings/nav/get-settings-breadcrumb.ts

settings-nav-group.tsxRender standard sidebar groups +41/-0

Render standard sidebar groups

• Displays labeled navigation links with active-page styling.

apps/web/src/components/settings/nav/settings-nav-group.tsx

settings-nav-project.tsxExpand project pages in the sidebar +64/-0

Expand project pages in the sidebar

• Provides an expandable project item with links to its individual settings pages.

apps/web/src/components/settings/nav/settings-nav-project.tsx

settings-nav-projects.tsxRender project navigation group +42/-0

Render project navigation group

• Lists expandable project items when projects are available.

apps/web/src/components/settings/nav/settings-nav-projects.tsx

settings-sidebar-header.tsxAdd back-to-workspace sidebar control +39/-0

Add back-to-workspace sidebar control

• Displays the settings label, back action, and Escape hint.

apps/web/src/components/settings/nav/settings-sidebar-header.tsx

settings-sidebar.tsxAdd persistent settings sidebar +48/-0

Add persistent settings sidebar

• Combines all settings groups, supports sidebar shortcuts, and closes mobile navigation after route changes.

apps/web/src/components/settings/nav/settings-sidebar.tsx

should-leave-on-escape.tsGuard Escape-to-workspace navigation +39/-0

Guard Escape-to-workspace navigation

• Allows leaving settings only when no text field or open overlay owns Escape.

apps/web/src/components/settings/nav/should-leave-on-escape.ts

types.tsDefine settings navigation types +31/-0

Define settings navigation types

• Types grouped links, project sublinks, and the overall navigation model.

apps/web/src/components/settings/nav/types.ts

use-leave-settings-on-escape.tsRegister Escape-to-leave listener +16/-0

Register Escape-to-leave listener

• Hooks the Escape guard to workspace navigation in the capture phase.

apps/web/src/components/settings/nav/use-leave-settings-on-escape.ts

use-leave-settings.tsProvide leave-settings navigation action +20/-0

Provide leave-settings navigation action

• Navigates back to the active workspace when one is available.

apps/web/src/components/settings/nav/use-leave-settings.ts

use-settings-nav.tsPopulate navigation from settings data +29/-0

Populate navigation from settings data

• Builds the model from workspace, projects, billing config, translations, and admin access.

apps/web/src/components/settings/nav/use-settings-nav.ts

settings-header.tsxAdd shared sidebar and breadcrumb header +66/-0

Add shared sidebar and breadcrumb header

• Shows the sidebar trigger and current settings section/page breadcrumb.

apps/web/src/components/settings/settings-header.tsx

settings-page.tsxAdd shared settings page layout +38/-0

Add shared settings page layout

• Standardizes page width, title, description, actions, and content spacing.

apps/web/src/components/settings/settings-page.tsx

settings-section-header.tsxAdd shared section header +25/-0

Add shared section header

• Standardizes section title, description, and optional action placement.

apps/web/src/components/settings/settings-section-header.tsx

settings-shell.tsxHost settings in an app-aligned shell +45/-0

Host settings in an app-aligned shell

• Supplies the sidebar, header, content inset, and Escape handling without changing the surrounding frame.

apps/web/src/components/settings/settings-shell.tsx

use-get-discord-integration.tsMake Discord query conditionally enabled +5/-2

Make Discord query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/discord-integration/use-get-discord-integration.ts

use-get-generic-webhook-integration.tsMake webhook query conditionally enabled +5/-2

Make webhook query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/generic-webhook-integration/use-get-generic-webhook-integration.ts

use-get-gitea-integration.tsMake Gitea query conditionally enabled +5/-2

Make Gitea query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/gitea-integration/use-get-gitea-integration.ts

use-get-github-integration.tsMake GitHub query conditionally enabled +5/-2

Make GitHub query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/github-integration/use-get-github-integration.ts

use-get-gitlab-integration.tsMake GitLab query conditionally enabled +5/-2

Make GitLab query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/gitlab-integration/use-get-gitlab-integration.ts

use-get-mattermost-integration.tsMake Mattermost query conditionally enabled +5/-2

Make Mattermost query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/mattermost-integration/use-get-mattermost-integration.ts

use-get-slack-integration.tsMake Slack query conditionally enabled +5/-2

Make Slack query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/slack-integration/use-get-slack-integration.ts

use-get-telegram-integration.tsMake Telegram query conditionally enabled +5/-2

Make Telegram query conditionally enabled

• Adds an enabled option for permission-aware status fetching.

apps/web/src/hooks/queries/telegram-integration/use-get-telegram-integration.ts

use-workspace-permission.tsExpose manage-settings permission +2/-0

Expose manage-settings permission

• Adds a capability used to authorize integration status requests.

apps/web/src/hooks/use-workspace-permission.ts

preferences.tsxRedesign preferences controls +47/-94

Redesign preferences controls

• Adds visual theme options and a board/list toggle within the shared page styling.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/account/preferences.tsx

integrations.tsxShow integrations as a status list +28/-142

Show integrations as a status list

• Groups code-hosting and chat/webhook services and loads status only with settings-management permission.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/integrations.tsx

Refactor (31) +263 / -968
change-password-settings.tsxAlign password settings with shared section styling +7/-10

Align password settings with shared section styling

• Uses SettingsSectionHeader and the rounded card treatment.

apps/web/src/components/account/change-password-settings.tsx

notification-preferences-settings.tsxRestyle notification preference cards +3/-3

Restyle notification preference cards

• Applies the shared rounded card background and borders to notification sections.

apps/web/src/components/account/notification-preferences-settings.tsx

user-management-panel.tsxUse shared page layout for user administration +16/-25

Use shared page layout for user administration

• Replaces the custom title block and aligns panel colors with other settings pages.

apps/web/src/components/admin/user-management-panel.tsx

founding-free-card.tsxAlign founding-plan card styling +1/-1

Align founding-plan card styling

• Uses the new rounded card surface.

apps/web/src/components/billing/founding-free-card.tsx

subscription-card.tsxAlign subscription card styling +1/-1

Align subscription card styling

• Uses the new rounded card surface.

apps/web/src/components/billing/subscription-card.tsx

trial-status-card.tsxAlign trial card styling +1/-1

Align trial card styling

• Uses the new rounded card surface and border.

apps/web/src/components/billing/trial-status-card.tsx

custom-field-editor.tsxAlign custom-field empty state +1/-1

Align custom-field empty state

• Restyles the empty message as a rounded card.

apps/web/src/components/project/custom-field-editor.tsx

discord-integration-settings.tsxRestyle Discord settings panels +4/-4

Restyle Discord settings panels

• Applies the new rounded card treatment to forms and loading states.

apps/web/src/components/project/discord-integration-settings.tsx

generic-webhook-integration-settings.tsxRestyle webhook settings panels +3/-3

Restyle webhook settings panels

• Applies the new rounded card treatment to forms and loading states.

apps/web/src/components/project/generic-webhook-integration-settings.tsx

gitea-integration-settings.tsxRestyle Gitea settings panels +4/-4

Restyle Gitea settings panels

• Aligns configuration, connected, and error cards with the shared design.

apps/web/src/components/project/gitea-integration-settings.tsx

github-integration-settings.tsxRestyle GitHub settings panels +6/-6

Restyle GitHub settings panels

• Aligns configuration, connection, and loading cards with the shared design.

apps/web/src/components/project/github-integration-settings.tsx

gitlab-integration-settings.tsxRestyle GitLab settings panels +4/-4

Restyle GitLab settings panels

• Aligns configuration, connected, and error cards with the shared design.

apps/web/src/components/project/gitlab-integration-settings.tsx

mattermost-integration-settings.tsxRestyle Mattermost settings panels +4/-4

Restyle Mattermost settings panels

• Applies the new rounded card treatment to forms and loading states.

apps/web/src/components/project/mattermost-integration-settings.tsx

slack-integration-settings.tsxRestyle Slack settings panels +4/-4

Restyle Slack settings panels

• Applies the new rounded card treatment to forms and loading states.

apps/web/src/components/project/slack-integration-settings.tsx

telegram-integration-settings.tsxRestyle Telegram settings panels +4/-4

Restyle Telegram settings panels

• Applies the new rounded card treatment to forms and loading states.

apps/web/src/components/project/telegram-integration-settings.tsx

settings.tsxReplace tabbed settings layout with shared shell +5/-168

Replace tabbed settings layout with shared shell

• Moves sidebar and header behavior out of the route and into SettingsShell.

apps/web/src/routes/_layout/_authenticated/dashboard/settings.tsx

account.tsxRemove account-specific sidebar +2/-132

Remove account-specific sidebar

• Leaves the account parent route as an outlet under the unified sidebar.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/account.tsx

developer.tsxStandardize developer settings page +6/-11

Standardize developer settings page

• Uses SettingsPage for the API-key page title and content.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/account/developer.tsx

information.tsxStandardize account information page +22/-32

Standardize account information page

• Uses shared page and section headers and consistent card styling.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/account/information.tsx

notifications.tsxStandardize notifications page +6/-11

Standardize notifications page

• Wraps notification preferences in SettingsPage.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/account/notifications.tsx

security.tsxStandardize security page +6/-11

Standardize security page

• Wraps password settings in SettingsPage.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/account/security.tsx

projects.tsxRemove project dropdown sidebar +19/-189

Remove project dropdown sidebar

• Keeps first-project redirection while moving all project navigation into the unified sidebar.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects.tsx

calendar.tsxStandardize calendar settings page +6/-10

Standardize calendar settings page

• Wraps calendar feed settings in SettingsPage.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/calendar.tsx

general.tsxStandardize project general page +20/-32

Standardize project general page

• Uses shared page and section headers for project information and danger-zone controls.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/general.tsx

visibility.tsxStandardize project visibility page +13/-21

Standardize project visibility page

• Uses shared page and section headers and the new card surface.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/visibility.tsx

workflow.tsxStandardize workflow settings page +22/-38

Standardize workflow settings page

• Uses shared headers for columns, custom fields, and automation.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/workflow.tsx

workspace.tsxRemove workspace-specific sidebar +2/-118

Remove workspace-specific sidebar

• Keeps workspace routing while delegating navigation to the unified shell.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/workspace.tsx

billing.tsxStandardize billing page and sections +17/-26

Standardize billing page and sections

• Replaces billing-specific headings with shared settings page and section headers.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/workspace/billing.tsx

general.tsxStandardize workspace general page +29/-48

Standardize workspace general page

• Uses shared headers and cards for workspace information, transfer, and danger-zone sections.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/workspace/general.tsx

labels.tsxStandardize workspace labels page +6/-13

Standardize workspace labels page

• Uses the shared SettingsPage wrapper around label controls.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/workspace/labels.tsx

roles.tsxStandardize workspace roles page +19/-33

Standardize workspace roles page

• Uses shared page and section headers and the updated card treatment.

apps/web/src/routes/_layout/_authenticated/dashboard/settings/workspace/roles.tsx

Documentation (20) +160 / -20
az-AZ.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/az-AZ.json

de-DE.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/de-DE.json

el-GR.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/el-GR.json

en-US.jsonAdd source strings for integration list +8/-1

Add source strings for integration list

• Adds seven group, connection-status, and action labels.

i18n/en-US.json

es-ES.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/es-ES.json

fr-FR.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/fr-FR.json

hi-IN.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/hi-IN.json

id-ID.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/id-ID.json

it-IT.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/it-IT.json

ja-JP.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/ja-JP.json

ko-KR.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/ko-KR.json

mk-MK.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/mk-MK.json

nl-NL.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/nl-NL.json

pl-PL.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/pl-PL.json

pt-BR.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/pt-BR.json

ru-RU.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/ru-RU.json

tr-TR.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/tr-TR.json

uk-UA.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/uk-UA.json

vi-VN.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/vi-VN.json

zh-CN.jsonTranslate new integration UI labels +8/-1

Translate new integration UI labels

• Adds seven localized group, status, and action strings.

i18n/zh-CN.json

Other (6) +320 / -1
get-integration-status.test.tsTest integration status derivation +44/-0

Test integration status derivation

• Checks connected, paused, and disconnected states plus repository and channel formatting.

apps/web/src/components/project/integrations/get-integration-status.test.ts

build-settings-nav.test.tsTest navigation model construction +59/-0

Test navigation model construction

• Checks workspace labels, conditional billing and administration, and project links.

apps/web/src/components/settings/nav/build-settings-nav.test.ts

get-settings-breadcrumb.test.tsTest settings breadcrumb lookup +43/-0

Test settings breadcrumb lookup

• Covers account, workspace, project, and unmatched paths.

apps/web/src/components/settings/nav/get-settings-breadcrumb.test.ts

settings-nav-project.test.tsxTest expandable project navigation +68/-0

Test expandable project navigation

• Checks active-project expansion, link highlighting, and manual expansion.

apps/web/src/components/settings/nav/settings-nav-project.test.tsx

should-leave-on-escape.test.tsTest Escape navigation guard +77/-0

Test Escape navigation guard

• Covers input focus, modifier keys, dialogs, menus, hidden popups, and consumed events.

apps/web/src/components/settings/nav/should-leave-on-escape.test.ts

schema.jsonRequire new integration translation keys +29/-1

Require new integration translation keys

• Adds seven integration list strings to the schema and required-key list.

i18n/schema.json

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22472e34f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Inactive integrations appear connected ✓ Resolved
Description
getIntegrationStatus treats a configured integration as connected unless isActive is exactly
false, even though the API can return null for that field. When an existing integration has
isActive: null, the redesigned list shows a connected badge while the integration's activity
checks treat that value as inactive.
Code

apps/web/src/components/project/integrations/get-integration-status.ts[31]

+    state: isActive === false ? "paused" : "connected",
Evidence
Rule 6 requires visible current states. The new status calculation classifies null as connected; the
API contract and database allow null, while an existing integration activity check treats it as
inactive.

AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current: AGENTS.md: Keep Client Data Flows and UI States Current
apps/web/src/components/project/integrations/get-integration-status.ts[25-33]
apps/api/src/slack-integration/response.ts[14-17]
apps/api/src/database/schema.ts[913-918]
apps/api/src/gitea-integration/controllers/import-gitea-issues.ts[78-82]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Configured integrations with a null activity value are displayed as connected despite being inactive.
## Fix Focus Areas
- apps/web/src/components/project/integrations/get-integration-status.ts[30-33]
- apps/web/src/components/project/integrations/get-integration-status.test.ts[31-46]
## Recommended Fix
Show connected only when `isActive` is true, and add a test for a configured integration with `isActive: null`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Connected services appear disconnected ✓ Resolved
Description
useIntegrationStatuses treats absent query data as an unconfigured, disconnected service without
checking whether the request is loading or has failed. While a status request is pending or after it
fails, IntegrationRow presents the service as disconnected and offers “Connect” even if it is
configured.
Code

apps/web/src/components/project/integrations/use-integration-statuses.ts[R24-27]

+  const { data: github } = useGetGithubIntegration(projectId, options);
+  const { data: gitea } = useGetGiteaIntegration(projectId, options);
+  const { data: gitlab } = useGetGitlabIntegration(projectId, options);
+  const { data: slack } = useGetSlackIntegration(projectId, options);
Evidence
The hook discards query loading and error state and maps undefined data to an unconfigured status.
The GitHub fetcher can throw on an unsuccessful response, leaving no data; the row then uses the
resulting disconnected status to display “Connect” rather than a loading or error state.

AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently: AGENTS.md: Update Client Fetchers, Query Hooks, and UI States Consistently
apps/web/src/components/project/integrations/use-integration-statuses.ts[24-40]
apps/web/src/components/project/integrations/get-integration-status.ts[14-24]
apps/web/src/components/project/integrations/integration-row.tsx[31-32]
apps/web/src/components/project/integrations/integration-row.tsx[65-69]
apps/web/src/components/project/integrations/use-integration-statuses.ts[23-39]
apps/web/src/components/project/integrations/integration-row.tsx[44-69]
apps/web/src/fetchers/github-integration/get-github-integration.ts[10-18]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Pending or failed integration status requests are presented as confirmed unconfigured services.
## Fix Focus Areas
- apps/web/src/components/project/integrations/use-integration-statuses.ts[23-74]
- apps/web/src/components/project/integrations/integration-row.tsx[31-69]
## Recommended Fix
Carry each query’s loading and error state through to the integration list. Display a pending or unavailable state instead of a disconnected status or Connect action until a successful response establishes that the service is unconfigured.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Esc on a preferences dropdown leaves settings 🐞 Bug ≡ Correctness
Description
shouldLeaveOnEscape only exempts focus inside a form, an element with the switch, checkbox or
radio role, native inputs, or editable text. It does not exempt Base UI select triggers
(data-slot="select-trigger", combobox role) or toggle-group buttons. On the Preferences page, the
language and week-start dropdowns and the board/list toggle are not inside any form. After a user
picks a value, focus returns to the closed trigger, so the next Esc navigates the user back to the
workspace.
Code

apps/web/src/components/settings/nav/should-leave-on-escape.ts[R40-42]

+      target.closest(
+        'form, [role="switch"], [role="checkbox"], [role="radio"]',
+      ) ||
Evidence
The added check covers only forms, switch/checkbox/radio roles and native inputs. The Preferences
page renders a Select at lines 114 and 150 and a ToggleGroup at line 194, none of them inside a
form. The existing tests do not cover select or toggle controls.

apps/web/src/components/settings/nav/should-leave-on-escape.ts[36-50]
apps/web/src/routes/_layout/_authenticated/dashboard/settings/account/preferences.tsx[114-212]
apps/web/src/components/ui/select.tsx[71-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`shouldLeaveOnEscape` ignores Escape only when focus is in a form, in a switch/checkbox/radio, in a native input/textarea/select, or in editable text. Focused Base UI select triggers and toggle-group buttons outside a form are not covered. On the Preferences page, pressing Esc on one of them navigates the user out of settings.
## Fix Focus Areas
- apps/web/src/components/settings/nav/should-leave-on-escape.ts[37-47]
- apps/web/src/components/settings/nav/should-leave-on-escape.test.ts[42-61]
## Recommended Fix
Extend the `closest(...)` selector so it also matches these controls:
- `[role="combobox"]`
- `[data-slot="select-trigger"]`
- `[aria-pressed]`
- `[data-slot^="toggle"]`
- `[role="slider"]`
- `[role="tab"]`
Then add a test case for each of these controls.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Esc throws away unsaved settings edits ✓ Resolved
Description
shouldLeaveOnEscape only skips Esc when focus is in an INPUT, TEXTAREA, SELECT or editable
text, or when an overlay is open; it never checks whether the page has unsaved changes. With focus
on a switch, button or the page body after editing a form, Esc makes useLeaveSettingsOnEscape
navigate to the workspace and unmount the page, dropping edits in every settings form, including all
eight integration panels.
Code

apps/web/src/components/settings/nav/should-leave-on-escape.ts[R36-47]

+  const target = event.target;
+  if (
+    target instanceof HTMLElement &&
+    (target.isContentEditable ||
+      target.tagName === "INPUT" ||
+      target.tagName === "TEXTAREA" ||
+      target.tagName === "SELECT")
+  ) {
+    return false;
+  }
+
+  return !hasOpenOverlay(root);
Evidence
The capture-phase keydown listener calls onLeave (navigate to the workspace) whenever
shouldLeaveOnEscape returns true. That check only excludes text-like tags. Integration panel
toggles are Base UI Switch roots bound to react-hook-form fields that are only saved on submit, so
Esc with focus on one passes the check and unmounts the settings page with the unsaved changes.

apps/web/src/components/settings/nav/should-leave-on-escape.ts[36-47]
apps/web/src/components/settings/nav/use-leave-settings-on-escape.ts[4-15]
apps/web/src/components/settings/nav/use-leave-settings.ts[11-19]
apps/web/src/components/project/slack-integration-settings.tsx[55-66]
apps/web/src/components/ui/switch.tsx[7-16]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The global Esc handler leaves settings whenever focus is not in a text field and no overlay is open. Settings forms such as the integration panels keep unsaved state in react-hook-form, and their toggles are Base UI switches (role="switch"), not INPUT elements. Pressing Esc after flipping a toggle or tabbing past fields navigates away and loses the edits without a prompt.
## Fix Focus Areas
- apps/web/src/components/settings/nav/should-leave-on-escape.ts[36-47]
- apps/web/src/components/settings/nav/use-leave-settings-on-escape.ts[1-16]
## Recommended Fix
Do not leave on Esc when focus is inside a form or a form control. For example, return false when `target.closest('form, [role="switch"], [role="checkbox"], [role="radio"]')` matches. Alternatively, have settings forms register a dirty flag (via a context, or TanStack Router `useBlocker` keyed on `formState.isDirty`) and skip or confirm the Esc leave while it is set. Add a test with focus on a switch inside a form.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. A brief refresh error hides a connected service ✓ Resolved
Description
getIntegrationStatus returns { state: "unavailable" } whenever queryStatus === "error", before
it looks at the data that is still cached. A configured, already-loaded row whose background refetch
fails (window focus, invalidation after save) loses its Connected/Paused badge and repository or
channel, and shows "Something went wrong" with "Try again" instead of "Configure".
Code

apps/web/src/components/project/integrations/get-integration-status.ts[R26-28]

+  if (queryStatus === "pending") return { state: "loading" };
+  if (queryStatus === "error") return { state: "unavailable" };
+  if (!configured) return { state: "disconnected" };
Evidence
The error check returns before configured or detail is read. The hook passes both the query
status and the cached data. IntegrationRow derives isSetUp and the action button from state,
so a cached connected integration renders as an error with "Try again".

apps/web/src/components/project/integrations/get-integration-status.ts[20-34]
apps/web/src/components/project/integrations/use-integration-statuses.ts[28-37]
apps/web/src/components/project/integrations/integration-row.tsx[33-69]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`getIntegrationStatus` treats any query error as `unavailable`, even when the query still holds valid cached data. A failed background refetch therefore hides a connected integration.
## Fix Focus Areas
- apps/web/src/components/project/integrations/get-integration-status.ts[13-34]
- apps/web/src/components/project/integrations/use-integration-statuses.ts[28-82]
## Recommended Fix
- Add a `hasData` input to `getIntegrationStatus`, passed as `query.data !== undefined` from each call in the hook.
- Return `unavailable` only when `queryStatus === "error"` and there is no data.
- When cached data exists, compute the connected, paused or disconnected state and its detail from that data as usual.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
6. Configured integrations look disconnected to members ✓ Resolved
Description
The integrations route gates useIntegrationStatuses on canManageSettings(), so the hook returns
{} for non-managers and IntegrationRow treats every missing status as disconnected. A member
with project access but without workspace:manage_settings therefore sees “Connect” and no
repository or channel for a configured integration, even though its read endpoint and the row’s
panel can show its configuration.
Code

apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/integrations.tsx[R19-20]

+  const { canManageSettings } = useWorkspacePermission();
+  const statuses = useIntegrationStatuses(projectId, canManageSettings());
Evidence
The route passes management permission as the condition for every status query, and the disabled
hook returns an empty map that IntegrationRow converts into “disconnected” and “Connect.” The
Slack GET route requires project workspace access, while management permission is required for
mutations, demonstrating that a member can read an integration the list presents as disconnected.

apps/api/src/slack-integration/index.ts[80-103]
apps/web/src/components/project/integrations/use-integration-statuses.ts[19-35]
apps/web/src/components/project/integrations/integration-row.tsx[31-32]
apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/integrations.tsx[19-20]
apps/web/src/components/project/integrations/use-integration-statuses.ts[23-33]
apps/web/src/components/project/integrations/integration-row.tsx[65-69]
apps/api/src/slack-integration/index.ts[80-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The integrations list loads statuses only for users who can manage workspace settings, although the backend GET endpoints permit users with project workspace access to read them. As a result, non-managers see configured integrations as disconnected.
## Fix Focus Areas
- apps/web/src/routes/_layout/_authenticated/dashboard/settings/projects/$projectId/integrations.tsx[19-20]
- apps/web/src/components/project/integrations/use-integration-statuses.ts[19-35]
- apps/web/src/components/project/integrations/integration-row.tsx[31-32]
## Recommended Fix
Allow status reads independently of permission to change settings: remove the `canManageSettings()` gate and call `useIntegrationStatuses(projectId, true)`, or remove the hook’s `enabled` parameter entirely. If a status cannot be read, represent it as unknown rather than disconnected.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

7. Retrying a failed status shows no progress 🐞 Bug ☼ Reliability
Description
retry calls queries[id].refetch(), but during a refetch the query keeps status === "error" and
only fetchStatus changes, which getIntegrationStatus never sees. The row stays "unavailable"
with an enabled "Try again" button, and each extra click cancels the request in flight
(cancelRefetch defaults to true) and starts a new one.
Code

apps/web/src/components/project/integrations/use-integration-statuses.ts[R96-98]

+    retry: (id: IntegrationId) => {
+      void queries[id].refetch();
+    },
Evidence
The status mapping only reads query.status, so the row stays unavailable while a refetch runs.
The "Try again" button has no disabled or loading state.

apps/web/src/components/project/integrations/use-integration-statuses.ts[94-99]
apps/web/src/components/project/integrations/integration-row.tsx[60-69]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Retrying a failed integration status gives no visual feedback, and repeated clicks cancel and restart the request.
## Fix Focus Areas
- apps/web/src/components/project/integrations/use-integration-statuses.ts[28-99]
- apps/web/src/components/project/integrations/integration-row.tsx[60-69]
## Recommended Fix
- When a query has `fetchStatus === "fetching"`, report the `loading` state, or disable the retry button.
- Alternatively, call `refetch({ cancelRefetch: false })` so repeated clicks do not cancel the request in flight.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. An unused settings permission check is left behind 🐞 Bug ⚙ Maintainability
Description
The manageSettings capability and canManageSettings() helper, plus the { enabled } option
added to all eight integration query hooks, have no callers since the permission gate was removed.
Someone could easily wire the gate back in, which would again make configured integrations look
disconnected to members even though the API reads only require workspace membership.
Code

apps/web/src/hooks/use-workspace-permission.ts[29]

+  manageSettings: { workspace: ["manage_settings"] },
Evidence
A search of apps/web/src finds canManageSettings only at its definition, and no caller passes
enabled to any of the eight hooks.

apps/web/src/hooks/use-workspace-permission.ts[26-31]
apps/web/src/hooks/queries/github-integration/use-get-github-integration.ts[4-13]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `canManageSettings` capability and the `enabled` option on the integration query hooks are unused leftovers from the removed permission gate.
## Fix Focus Areas
- apps/web/src/hooks/use-workspace-permission.ts[29-29]
- apps/web/src/hooks/use-workspace-permission.ts[109-109]
- apps/web/src/hooks/queries/github-integration/use-get-github-integration.ts[4-12]
## Recommended Fix
- Delete `manageSettings` and `canManageSettings`.
- Revert the `{ enabled }` parameter in all eight `use-get-*-integration` hooks, keeping their original `enabled: !!projectId`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Esc stops leaving settings while a toast shows ✓ Resolved
Description
OVERLAY_SELECTOR matches any element with [data-slot$="-popup"], which includes the non-modal
toast-popup and tooltip-popup. It misses preview-card-content, which has no dialog or menu
role. As a result, Esc does nothing for several seconds after any save toast or while a tooltip is
open, and Esc on an open preview card both closes it and leaves settings.
Code

apps/web/src/components/settings/nav/should-leave-on-escape.ts[R5-10]

+const OVERLAY_SELECTOR = [
+  '[role="dialog"]',
+  '[role="alertdialog"]',
+  '[role="menu"]',
+  '[data-slot$="-popup"]',
+].join(",");
Evidence
Toast and tooltip use the data-slots toast-popup and tooltip-popup, which match the suffix
selector. Preview card uses preview-card-content, which the selector does not match.

apps/web/src/components/ui/toast.tsx[213-213]
apps/web/src/components/ui/tooltip.tsx[63-63]
apps/web/src/components/ui/preview-card.tsx[86-86]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The overlay suffix selector counts toasts and tooltips as open overlays and misses preview cards.
## Fix Focus Areas
- apps/web/src/components/settings/nav/should-leave-on-escape.ts[5-10]
## Recommended Fix
Replace `[data-slot$="-popup"]` with an explicit list: dialog-popup, alert-dialog-popup, sheet-popup, menu-popup, select-popup, combobox-popup, autocomplete-popup, popover-popup, command-dialog-popup, preview-card-content. Add a test asserting that a mounted toast-popup does not block leaving.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can copy the agent prompt from any finding and feed it to your IDE agent

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread apps/web/src/components/project/integrations/use-integration-statuses.ts Outdated
Comment thread apps/web/src/components/settings/nav/should-leave-on-escape.ts
@tinsever

tinsever commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

@codex review

@tinsever

tinsever commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

/review

Comment thread apps/web/src/components/project/integrations/get-integration-status.ts Outdated
Comment thread apps/web/src/components/project/integrations/get-integration-status.ts Outdated
Comment thread apps/web/src/hooks/use-workspace-permission.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 66ce78e

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 66ce78ee4e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@tinsever

tinsever commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

@codex review

@tinsever

tinsever commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

/review

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 8aab7ed

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 8aab7edfe1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@tinsever

tinsever commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

@codex review

@tinsever

tinsever commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

/review

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 5bbe6df

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 5bbe6df138

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@tinsever
tinsever merged commit 20837cc into main Oct 3, 2026
22 of 23 checks passed
@tinsever
tinsever deleted the feat/settings-redesign branch October 3, 2026 15:32
gabrielrinaldi pushed a commit to gabrielrinaldi/kaneo that referenced this pull request Oct 3, 2026
### Features

- **web:** redesign settings: usekaneo#1905
- **site:** link community projects from resources: [69ba99d](usekaneo@69ba99d)
- **site:** add a community projects page: [961c309](usekaneo@961c309)
- **site:** sync product preview with home, inbox and my tasks: [30ba825](usekaneo@30ba825)
- missing french translation: usekaneo#1903

### Credits

Huge thanks to @tinsever and @MonsPropre for helping!
github-actions Bot added a commit to capital-shield/kaneo that referenced this pull request Oct 3, 2026
### Features

- **web:** redesign settings: usekaneo#1905
- **site:** link community projects from resources: [69ba99d](69ba99d)
- **site:** add a community projects page: [961c309](961c309)
- **site:** sync product preview with home, inbox and my tasks: [30ba825](30ba825)
- missing french translation: usekaneo#1903
- add short task links like /acme/task/KAN-12: usekaneo#1891
- **web:** add home, inbox and my tasks pages: usekaneo#1898
- **web:** wire the task copy shortcuts: usekaneo#1897
- **web:** move task delete into the action group: usekaneo#1896
- **site:** add guides and retarget alternatives: [58f6d47](58f6d47)
- **web:** track the cloud signup funnel: [abacad7](abacad7)
- **docker:** support file-backed secrets for container deployments: usekaneo#1853
- sort labels alphabetically: usekaneo#1856
- **web:** select task ranges with shift-click: usekaneo#1838
- clickable task PR list, task link matching, and reopen completed tasks for new work: usekaneo#1864
- **mcp:** get tasks by ticket ID: usekaneo#1839
- **web:** guide cloud users through invites and plan choice during onboarding: usekaneo#1840
- rank new issue priority with Jev: [594e016](594e016)
- **web:** cloud sign-up and onboarding layout: usekaneo#1832
- gitlab integration: usekaneo#1727
- **tasks:** show subtask progress on cards and list rows: usekaneo#1703
- added project backgrounds: usekaneo#1654
- multiselect for customfield: usekaneo#1735
- **ci:** discord actions webhook: usekaneo#1792
- **ci:** adding zizmor: usekaneo#1790
- **project:** move a project to another workspace: usekaneo#1525
- duplicate a task from the card context menu: usekaneo#1609
- allow manual external resource links: usekaneo#1661
- **ci:** trufflehog implementation: usekaneo#1787
- **task:** let images be resized in the task description: usekaneo#1529
- **web:** add a change-password screen under account settings: usekaneo#1719
- **auth:** add password recovery from the login screen: usekaneo#1773
- add instance user administration panel: usekaneo#1400
- **site:** bring product preview up to date with current app: [dd855f7](dd855f7)
- **site:** refresh marketing site and interactive product previews: [90aec99](90aec99)
- **calendar:** add label-filtered project calendar feeds: usekaneo#1763

### Bug Fixes

- **web:** send subscription revenue as a property: [445b735](445b735)
- **site:** list GitLab with the git integrations: [3c01517](3c01517)
- **site:** serve favicon.ico: [e7ef050](e7ef050)
- **docs:** load the docs font from its real path: [22c7a02](22c7a02)
- **tasks:** make bulk status changes atomic: usekaneo#1873
- **integrations:** preserve rapid legitimate edits: usekaneo#1874
- **integrations:** enforce current task ownership: usekaneo#1867
- **ws:** revoke removed workspace members: usekaneo#1865
- **migrations:** record workflow migration completion: usekaneo#1872
- **auth:** enforce api key quotas and rate limits: usekaneo#1869
- **mcp:** share tools and support workspace label deletion: usekaneo#1871
- **reminders:** persist notification and claim atomically: usekaneo#1870
- **integrations:** require task update permission for imports: usekaneo#1868
- **ci:** publish npm provenance on GitHub-hosted runners: [50779a4](50779a4)
- **gitea:** reject saved tokens for changed servers: usekaneo#1866
- **ci:** pass the GitHub token to AgentScan: usekaneo#1862
- **ci:** resolve nightly warnings and errors: usekaneo#1858
- **api:** make legacy MCP HTTP requests replica independent: usekaneo#1850
- **docker:** disable wget proxy for loopback health checks: usekaneo#1841
- **billing:** resize Creem seats by subscription item id: usekaneo#1836
- **gitea:** prevent outbound comment echoes: usekaneo#1834
- **deps:** migrate Sentry SDKs together to v11 (usekaneo#1826): usekaneo#1826
- **ci:** grant nightly reusable CI scan permission: [0216067](0216067)
- **board:** allow column moves while sorting by task number: usekaneo#1816
- **auth:** backfill instance admin on legacy installations: [b7c6aee](b7c6aee)
- **admin:** harden the user administration panel: usekaneo#1805
- **admin:** allow updating your own email without changing role: [3d57439](3d57439)
- **security:** close permission and integration gaps: usekaneo#1802
- **project:** secure integrations across workspace moves: usekaneo#1801
- **editor:** preserve formatting when pasting Markdown: usekaneo#1797
- **auth:** report invitation email delivery failures: usekaneo#1798
- **gitea:** verify saved repository connections: usekaneo#1796
- **mcp:** keep OAuth requests valid outside UTC: usekaneo#1795
- **i18n:** translate calendar in remaining locales: [1d61ceb](1d61ceb)
- **ci:** zizmor findings: usekaneo#1791
- **integrations:** resolve PRs through linked issue identities: usekaneo#1739
- **auth:** prevent repeated 401s for pending invitations after session expiry: usekaneo#1715
- **auth:** gate sign-in emails to deliverable addresses: usekaneo#1758
- **web:** preserve image uploads across editor recreation: usekaneo#1738
- **reminders:** calculate deadlines from the end of the due day: usekaneo#1762
- **mcp:** support whoami with API keys: usekaneo#1748
- **web:** respect DISABLE_WORKSPACE_CREATION on the onboarding screen: usekaneo#1744
- **backlog:** prevent task remounts during list interactions: usekaneo#1734
- **auth:** prevent role changes from removing the last admin: usekaneo#1733
- **npm:** fixing GHSA-2xp9-vwfh-vxw4: usekaneo#1777
- **web:** guard tiptap setHardBreak against invalid-content schema error: [be3ffb5](be3ffb5)
- **i18n:** prevent locale module crash on stale dynamic import: usekaneo#1775
- **site:** improve search metadata and product discovery: [121183e](121183e)
- **web:** allow non-root runtime configuration writes: usekaneo#1767
- **site:** poof away preview cursor on interaction: [08dcaee](08dcaee)
- **nginx:** allow larger OAuth session headers: usekaneo#1761
- **deps:** resolve open dependabot advisories: [b8432a0](b8432a0)
- **web:** preserve comment markdown spacing: usekaneo#1521

### Performance Improvements

- **project:** stop returning tasks with project details: usekaneo#1800

### Documentation

- update sponsors: [1c51887](1c51887)
- add AI Policy badge to README: [011c8ee](011c8ee)
- update sponsors: [e45c8ac](e45c8ac)
- assign issue types from templates: [4725cfa](4725cfa)
- simplify issue and pull request templates: [cb6ce20](cb6ce20)
- adopt Human Voice AI contribution policy: [b090123](b090123)
- overhaul agents.md: [4d619aa](4d619aa)
- **readme:** highlight cloud and current features: usekaneo#1831
- update contributors and sponsors: [c200d70](c200d70)
- rebuild guides around current Kaneo workflows: usekaneo#1814
- acknowledge BrowserStack testing: [e389a68](e389a68)
- update contributors and sponsors: [fa07f10](fa07f10)
- **site:** add Blacksmith partner badge to site and README: [08a93b8](08a93b8)
- update contributors and sponsors: [8432a45](8432a45)
- **site:** refresh press kit with product screenshots: [3470b0a](3470b0a)
- update blog comparisons for current Kaneo features: [b97bf7d](b97bf7d)
- update contributors and sponsors: [6c7001c](6c7001c)

### Credits

Huge thanks to @tinsever, @MonsPropre, @andrejsshell, @tuttucodes, @druwan, @randoneering, @mazzz1y, @zaralX, @TymekV, @rdlugs, @tbringuier, @mohiuddin000, @shiminshen, @yavilavi, @thejdubb02, @yigit-serin, @OmG3r, and @zerodarkzone for helping!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant