Skip to content

feat: wire workspace settings to feedback record directories#7910

Merged
pandeymangg merged 10 commits into
epic/v5from
feat/restack-pr3-workspace-directory-nav-v2
Apr 29, 2026
Merged

feat: wire workspace settings to feedback record directories#7910
pandeymangg merged 10 commits into
epic/v5from
feat/restack-pr3-workspace-directory-nav-v2

Conversation

@pandeymangg
Copy link
Copy Markdown
Contributor

Summary

Replaces #7827. Rebased onto current epic/v5 so the diff shows only PR3 + PR4 work — PR1 (#7825) and PR2 (#7826) are already on epic/v5 via squash merge.

PR4 (#7828) commits are folded in here; that PR can be closed when this lands.

What changed vs #7827

  • Dropped duplicated PR1 / PR2 commits (now on epic/v5 via squash)
  • Dropped two stray "chore: merge with epic/v5" commits
  • Cherry-picked: PR3 (b1a4277ca) + PR4 chain (bf0ad4569963f89c52)
  • Diff: 49 files (was 146)

Validation

  • pnpm i18n ✅ all keys valid
  • 248 tests pass (lib/connector, unify, workspaces/settings/lib, feedback-record-directory, hub)
  • tsc --noEmit: 61 errors, identical to epic/v5 baseline (zero new)

Test plan

  • pnpm --filter @formbricks/web test
  • pnpm i18n
  • manual smoke test workspace create/settings directory assignment + feedback records UI

Contributes to ENG-777

jobenjada and others added 8 commits April 29, 2026 13:22
Integrate feedback record directory selection into workspace settings and creation flows while updating workspace navigation components to expose the new workspace-level destinations.

Made-with: Cursor
Add hub-backed feedback record actions and UI flows under Unify so workspaces can list and manage feedback records from a dedicated drawer and table experience.

Made-with: Cursor
…fixes

- Move TSX components into components/ subfolder
- Extract types/schemas into lib/types.ts and utils into lib/utils.ts
- Remove `as unknown as` double-casts in actions.ts with explicit field mapping
- Fix IDOR: use generic "not found" error instead of AuthorizationError for
  directory mismatch, parallelize auth + directory checks in retrieve/update
- Replace `as never` casts with proper isPresetSourceType type guard and
  explicit updatePayload typing
- Remove unused directoryName interpolation param from showing_count_loaded
- Deduplicate formatSourceType across table and drawer

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…e/update

- Add utils.test.ts with 32 tests covering all exported functions:
  getValueFieldByType, toLocalDateTimeInput, toISOOrUndefined,
  getCreateDefaults, mapRecordToValues, getReadOnlyMetadataEntries,
  parseNumberValue, isPresetSourceType, formatSourceType
- Add 6 tests to hub service.test.ts for retrieveFeedbackRecord
  and updateFeedbackRecord (null client, success, error cases)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…cords

Replace .sort() with .toSorted() to avoid mutating arrays in-place
during chaining, and remove the redundant CreateFeedbackRecordResult
type alias in favor of HubFeedbackRecordResult.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 29, 2026

🚨 PR Size Warning

This PR has approximately 3021 lines of changes (2508 additions, 513 deletions across 34 files).

Large PRs (>800 lines) are significantly harder to review and increase the chance of merge conflicts. Consider splitting this into smaller, self-contained PRs.

💡 Suggestions:

  • Split by feature or module - Break down into logical, independent pieces
  • Create a sequence of PRs - Each building on the previous one
  • Branch off PR branches - Don't wait for reviews to continue dependent work

📊 What was counted:

  • ✅ Source files, stylesheets, configuration files
  • ❌ Excluded 19 files (tests, locales, locks, generated files)

📚 Guidelines:

  • Ideal: 300-500 lines per PR
  • Warning: 500-800 lines
  • Critical: 800+ lines ⚠️

If this large PR is unavoidable (e.g., migration, dependency update, major refactor), please explain in the PR description why it couldn't be split.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 29, 2026

Walkthrough

This pull request introduces a comprehensive feedback records management system. It adds server actions for creating, retrieving, and updating feedback records with authorization validation. A new FeedbackRecordFormDrawer component enables creating and editing records with configurable metadata and value types, while a refactored FeedbackRecordsTable displays records across multiple feedback record directories with pagination. Navigation updates redirect from unify/sources to unify/feedback-records and add workspace configuration for feedback sources. Workspace creation now supports selecting a feedback record directory. Feedback record directory management includes workspace-conflict validation and connector pausing logic. Hub service operations expand to support record retrieval and updates. UI components are extended to support disabled options in multi-select and React nodes in secondary navigation labels.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides context about replacement/rebase strategy and validation results, but it lacks a 'How should this be tested?' section and does not include the checklist items as specified in the template. Add a 'How should this be tested?' section with specific testing steps and fill out the required checklist items from the template (self-review, build checks, console.log removal, responsiveness testing, etc.).
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: wire workspace settings to feedback record directories' is clear, specific, and directly summarizes the main change—integrating feedback record directory management into workspace settings navigation and workflows.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/web/modules/workspaces/settings/lib/workspace.ts (1)

78-123: ⚠️ Potential issue | 🟠 Major

Make the selected-directory path atomic.

The FRD existence check, workspace.create, optional workspaceTeam.createMany, and feedbackRecordDirectoryWorkspace.create all run as separate statements. If the directory changes or the join insert fails after Line 93, this throws after the workspace has already been created, leaving a partially provisioned workspace without the requested directory link.

Wrap this branch in a single prisma.$transaction(...) or create the join via a nested write off workspace.create(...).

Possible direction
-    if (feedbackRecordDirectoryId) {
-      const feedbackDirectory = await prisma.feedbackRecordDirectory.findFirst({
-        where: {
-          id: feedbackRecordDirectoryId,
-          organizationId,
-          isArchived: false,
-        },
-        select: { id: true },
-      });
-
-      if (!feedbackDirectory) {
-        throw new InvalidInputError("FEEDBACK_RECORD_DIRECTORY_NOT_FOUND");
-      }
-    }
-
-    const workspace = await prisma.workspace.create({
-      data: {
-        config: {
-          channel: null,
-          industry: null,
-        },
-        ...data,
-        name: workspaceInput.name,
-        organizationId,
-      },
-      select: selectWorkspace,
-    });
-
-    if (teamIds) {
-      await prisma.workspaceTeam.createMany({
-        data: teamIds.map((teamId) => ({
-          workspaceId: workspace.id,
-          teamId,
-        })),
-      });
-    }
-
-    if (feedbackRecordDirectoryId) {
-      await prisma.feedbackRecordDirectoryWorkspace.create({
-        data: {
-          feedbackRecordDirectoryId,
-          workspaceId: workspace.id,
-        },
-      });
-
-      return workspace;
-    }
+    const workspace = await prisma.$transaction(async (tx) => {
+      if (feedbackRecordDirectoryId) {
+        const feedbackDirectory = await tx.feedbackRecordDirectory.findFirst({
+          where: {
+            id: feedbackRecordDirectoryId,
+            organizationId,
+            isArchived: false,
+          },
+          select: { id: true },
+        });
+
+        if (!feedbackDirectory) {
+          throw new InvalidInputError("FEEDBACK_RECORD_DIRECTORY_NOT_FOUND");
+        }
+      }
+
+      const workspace = await tx.workspace.create({
+        data: {
+          config: {
+            channel: null,
+            industry: null,
+          },
+          ...data,
+          name: workspaceInput.name,
+          organizationId,
+        },
+        select: selectWorkspace,
+      });
+
+      if (teamIds) {
+        await tx.workspaceTeam.createMany({
+          data: teamIds.map((teamId) => ({
+            workspaceId: workspace.id,
+            teamId,
+          })),
+        });
+      }
+
+      if (feedbackRecordDirectoryId) {
+        await tx.feedbackRecordDirectoryWorkspace.create({
+          data: {
+            feedbackRecordDirectoryId,
+            workspaceId: workspace.id,
+          },
+        });
+      }
+
+      return workspace;
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/modules/workspaces/settings/lib/workspace.ts` around lines 78 - 123,
The FRD existence check, workspace creation (prisma.workspace.create), optional
workspaceTeam.createMany, and feedbackRecordDirectoryWorkspace.create must be
made atomic to avoid partial state; wrap the sequence in a single
prisma.$transaction that first verifies feedbackRecordDirectory (using
feedbackRecordDirectoryId and prisma.feedbackRecordDirectory.findFirst) and then
creates the workspace plus any workspaceTeam entries and the
feedbackRecordDirectoryWorkspace join inside the same transaction, or
alternatively perform the join as a nested write within prisma.workspace.create
so the workspace and feedbackRecordDirectoryWorkspace are created together
atomically.
apps/web/modules/hub/service.ts (1)

26-30: ⚠️ Potential issue | 🟠 Major

Do not expose raw Hub error text in public results.

This copies the SDK error message straight into the result object, and the new feedback-record actions/UI surface that text with getFormattedErrorMessage(...). That leaks upstream/internal Hub responses directly to end users. Please map these failures to a small set of safe public messages and keep the raw detail only in logs. Based on learnings: "The Formbricks API changes error messages before returning them to clients to avoid leaking internal details, even though the raw error.message appears in the internal function implementation."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/modules/hub/service.ts` around lines 26 - 30, createResultFromError
currently copies raw error.message into the public result; change it to map
internal errors to a small set of safe public messages and log the raw detail
only. Specifically, in createResultFromError (and where it checks
FormbricksHub.APIError), derive a publicMessage based on err.status (e.g., 401
-> "unauthorized", 404 -> "not_found", 400 -> "invalid_request", 500+ ->
"server_error", default -> "unknown_error"), set the returned error.message to
that publicMessage and set error.detail to an empty string or the same
publicMessage, and send the raw err/message to the server log via the project
logger (or console.error) so only logs contain internal details; keep the
returned status numeric as before and use HubFeedbackRecordResult as the return
type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/app/`(app)/workspaces/[workspaceId]/components/MainNavigation.tsx:
- Around line 152-154: Replace the hardcoded label in the navigation entry (the
object with id: "ask" and name: "Ask") so it uses the i18n translator instead of
a string literal; call the file's translation function (t) for the name (e.g.,
name: t('Ask') or the appropriate key used by surrounding entries) and ensure
the component uses useTranslation()/t where other labels do—update the object
with id "ask" to reference t(...) rather than "Ask".

In
`@apps/web/app/`(app)/workspaces/[workspaceId]/unify/feedback-records/components/feedback-record-form-drawer.tsx:
- Around line 470-487: The select currently renders raw IDs from
SOURCE_TYPE_PRESET_OPTIONS and the custom option; change it to display
translated labels by mapping each option through a shared display helper (e.g.,
translateSourceType or getSourceTypeLabel) that calls t() with the appropriate
translation key, then pass the translated string as the SelectItem children
while keeping the option value as the stable ID; apply the same change for the
other select instance referenced (the block around the later SelectItems) and
ensure SOURCE_TYPE_CUSTOM_VALUE still renders its translated label via
t("workspace.unify.custom_source_type") while preserving form values and
setCustomSourceType behavior.
- Around line 130-145: Before awaiting retrieveFeedbackRecordAction in
loadRecord, clear the previous state by calling setRecord(null), reset the form
to neutral values via form.reset(defaultValues), and set source-type state back
to defaults (setSourceTypeMode(SOURCE_TYPE_CUSTOM_VALUE) and
setCustomSourceType("")), so stale data cannot render while loading; if the
fetch fails, keep the drawer closed or in an error state by invoking the
component's close handler (e.g., onClose() or setIsOpen(false)) and ensure
setIsLoadingRecord(false) is still called after handling the error.

In
`@apps/web/app/`(app)/workspaces/[workspaceId]/unify/feedback-records/components/feedback-records-table.tsx:
- Around line 313-315: The row is only clickable via the <tr>'s onClick,
excluding keyboard users; update feedback-records-table.tsx to make the edit
action keyboard-accessible by either (preferred) adding a real <button> in a
cell that calls the same edit/open-drawer handler (use the existing onClick
handler or the open/edit function and give the button a clear accessible name or
aria-label), or (minimal) make the <tr> focusable (tabIndex={0}) and add an
onKeyDown that activates the same handler on Enter/Space; ensure the handler
referenced (onClick passed to the <tr> or the component method that opens the
drawer) is reused so behavior stays consistent and preserve visual styles
(cursor/hover).
- Around line 101-128: The code currently treats an empty aggregated row set as
a failure; change the success check to detect failed requests instead: after
awaiting Promise.all(listFeedbackRecordsAction...) compute results and
successfulRecords as before, then if (results.some((r) => !r?.data)) { const
firstErrorResult = results.find((r) => !r?.data); const errorMessage =
firstErrorResult ? getFormattedErrorMessage(firstErrorResult) : undefined;
toast.error(errorMessage ??
t("workspace.unify.failed_to_load_feedback_records"), { id: toastId });
setIsRefreshing(false); return; } — this ensures you only treat the overall
refresh as failed when any request errored (using listFeedbackRecordsAction
results), while allowing successfulRecords to be empty (no rows) and still
proceed to setRecords(mergedRecords), setIsRefreshing(false) and toast.success
as before; keep using mergedRecords variable and the existing
getFormattedErrorMessage, toast, setIsRefreshing, setRecords calls.

In
`@apps/web/app/`(app)/workspaces/[workspaceId]/unify/feedback-records/lib/types.ts:
- Around line 28-31: ZMetadataEntry currently rejects empty keys too early;
relax its key rule to allow empty strings during editing (e.g., change key:
z.string().trim().min(1) to z.string().trim() or z.string().trim().min(0)) and
make the final/submit validation enforce non-empty keys by adding a refinement
or a separate submit-time schema that ensures key.length > 0 for each metadata
entry; apply the same relaxation to the other metadata-entry schema referenced
in the file (the one noted at lines 54-55) so the drawer can add blank rows
without triggering validation until submit.

In
`@apps/web/modules/ee/feedback-record-directory/components/feedback-record-directory-settings/feedback-record-directory-settings-modal.tsx`:
- Around line 173-197: The client-side pause-confirmation logic in
handleSubmitForm relies on stale local state (initialWorkspaceIds and
directory.connectors); instead, call the server to compute affected connectors
before deciding to show the confirmation UI. Change handleSubmitForm to POST a
preview request (e.g., new API endpoint or existing submitDirectory preview
mode) with the proposed data to get current affected connector count, then—based
on the server response—either setPendingSubmitData / setConnectorsToPauseCount /
setConfirmPauseDialogOpen and return, or proceed to call submitDirectory(data,
false) if no confirmation is needed; keep identifiers handleSubmitForm,
initialWorkspaceIds, directory.connectors, submitDirectory,
setPendingSubmitData, setConnectorsToPauseCount, and setConfirmPauseDialogOpen
to locate and update the code.

In
`@apps/web/modules/ee/feedback-record-directory/lib/feedback-record-directory.ts`:
- Around line 427-438: Before composing payload in
updateFeedbackRecordDirectoryAction, validate the single-active-directory
invariant by querying existing non-archived directories for the workspaces being
assigned/unarchived and rejecting the update if any workspace is already linked
to a different active FRD; use the same identifiers passed into
getArchiveUpdate(directoryId, isArchived) and
getWorkspaceAssignmentUpdate(directoryId, organizationId, workspaceIds) to find
conflicts (via getWorkspaceFeedbackRecordDirectoryAccess or a direct lookup),
and throw a clear error when a conflict exists so clients cannot bypass the
client-side preflight in feedback-record-directory-table.tsx.
- Around line 440-447: The update to prisma.feedbackRecordDirectory
(prisma.feedbackRecordDirectory.update) is committed before
pauseConnectorsInWorkspaces runs, risking a half-applied state if
connector.updateMany inside pauseConnectorsInWorkspaces fails; wrap both the
directory update and the call to pauseConnectorsInWorkspaces (or the
connector.updateMany it invokes) in a single transaction (e.g., use
prisma.$transaction) so both succeed or both roll back, or alternatively
implement compensating rollback logic that reverses the directory assignment
change if pauseConnectorsInWorkspaces fails; locate the update in
feedback-record-directory.ts and ensure pauseConnectorsInWorkspaces (or the
internal connector.updateMany) is executed within that same transactional
context.

In `@apps/web/modules/workspaces/components/create-workspace-modal/index.tsx`:
- Around line 83-115: The effect that loads teams/directories (useEffect with
inner fetchModalData) currently omits the modal open state so the auto-select
logic for feedbackRecordDirectoryId (uses getValues and setValue) doesn't run
when the modal is reopened; modify the effect to also depend on the modal open
flag (add open to the dependency array) or only call fetchModalData when open is
true so that after form.reset() the directoriesResponse.data handling will
re-run and setValue("feedbackRecordDirectoryId", ...) as needed.

---

Outside diff comments:
In `@apps/web/modules/hub/service.ts`:
- Around line 26-30: createResultFromError currently copies raw error.message
into the public result; change it to map internal errors to a small set of safe
public messages and log the raw detail only. Specifically, in
createResultFromError (and where it checks FormbricksHub.APIError), derive a
publicMessage based on err.status (e.g., 401 -> "unauthorized", 404 ->
"not_found", 400 -> "invalid_request", 500+ -> "server_error", default ->
"unknown_error"), set the returned error.message to that publicMessage and set
error.detail to an empty string or the same publicMessage, and send the raw
err/message to the server log via the project logger (or console.error) so only
logs contain internal details; keep the returned status numeric as before and
use HubFeedbackRecordResult as the return type.

In `@apps/web/modules/workspaces/settings/lib/workspace.ts`:
- Around line 78-123: The FRD existence check, workspace creation
(prisma.workspace.create), optional workspaceTeam.createMany, and
feedbackRecordDirectoryWorkspace.create must be made atomic to avoid partial
state; wrap the sequence in a single prisma.$transaction that first verifies
feedbackRecordDirectory (using feedbackRecordDirectoryId and
prisma.feedbackRecordDirectory.findFirst) and then creates the workspace plus
any workspaceTeam entries and the feedbackRecordDirectoryWorkspace join inside
the same transaction, or alternatively perform the join as a nested write within
prisma.workspace.create so the workspace and feedbackRecordDirectoryWorkspace
are created together atomically.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 93b3b6a7-27d8-45ea-b0f4-41ae5a5f13dd

📥 Commits

Reviewing files that changed from the base of the PR and between fbe2a31 and e5bc86a.

⛔ Files ignored due to path filters (16)
  • apps/web/i18n.lock is excluded by !**/*.lock
  • apps/web/locales/de-DE.json is excluded by !apps/web/locales/**
  • apps/web/locales/en-US.json is excluded by !apps/web/locales/**
  • apps/web/locales/es-ES.json is excluded by !apps/web/locales/**
  • apps/web/locales/fr-FR.json is excluded by !apps/web/locales/**
  • apps/web/locales/hu-HU.json is excluded by !apps/web/locales/**
  • apps/web/locales/ja-JP.json is excluded by !apps/web/locales/**
  • apps/web/locales/nl-NL.json is excluded by !apps/web/locales/**
  • apps/web/locales/pt-BR.json is excluded by !apps/web/locales/**
  • apps/web/locales/pt-PT.json is excluded by !apps/web/locales/**
  • apps/web/locales/ro-RO.json is excluded by !apps/web/locales/**
  • apps/web/locales/ru-RU.json is excluded by !apps/web/locales/**
  • apps/web/locales/sv-SE.json is excluded by !apps/web/locales/**
  • apps/web/locales/tr-TR.json is excluded by !apps/web/locales/**
  • apps/web/locales/zh-Hans-CN.json is excluded by !apps/web/locales/**
  • apps/web/locales/zh-Hant-TW.json is excluded by !apps/web/locales/**
📒 Files selected for processing (33)
  • apps/web/app/(app)/workspaces/[workspaceId]/actions.ts
  • apps/web/app/(app)/workspaces/[workspaceId]/components/MainNavigation.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/components/workspace-breadcrumb.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/settings/components/SettingsCard.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/components/UnifyConfigNavigation.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/actions.ts
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/components/feedback-record-form-drawer.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/components/feedback-records-page-client.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/components/feedback-records-table.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/feedback-records-table.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/lib/types.ts
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/lib/utils.test.ts
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/lib/utils.ts
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/page.tsx
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/page.tsx
  • apps/web/modules/ee/feedback-record-directory/actions.ts
  • apps/web/modules/ee/feedback-record-directory/components/feedback-record-directory-settings/feedback-record-directory-settings-modal.tsx
  • apps/web/modules/ee/feedback-record-directory/components/feedback-record-directory-table.tsx
  • apps/web/modules/ee/feedback-record-directory/components/feedback-record-directory-view.tsx
  • apps/web/modules/ee/feedback-record-directory/lib/feedback-record-directory.test.ts
  • apps/web/modules/ee/feedback-record-directory/lib/feedback-record-directory.ts
  • apps/web/modules/ee/feedback-record-directory/types/feedback-record-directory.ts
  • apps/web/modules/hub/index.ts
  • apps/web/modules/hub/service.test.ts
  • apps/web/modules/hub/service.ts
  • apps/web/modules/hub/types.ts
  • apps/web/modules/ui/components/multi-select/index.tsx
  • apps/web/modules/ui/components/secondary-navigation/index.tsx
  • apps/web/modules/workspaces/components/create-workspace-modal/index.tsx
  • apps/web/modules/workspaces/settings/actions.ts
  • apps/web/modules/workspaces/settings/components/workspace-config-navigation.tsx
  • apps/web/modules/workspaces/settings/lib/workspace.test.ts
  • apps/web/modules/workspaces/settings/lib/workspace.ts
💤 Files with no reviewable changes (1)
  • apps/web/app/(app)/workspaces/[workspaceId]/unify/feedback-records/feedback-records-table.tsx

Comment thread apps/web/modules/ee/feedback-record-directory/lib/feedback-record-directory.ts Outdated
Comment thread apps/web/modules/workspaces/components/create-workspace-modal/index.tsx Outdated
@pandeymangg pandeymangg requested a review from Dhruwang April 29, 2026 10:06
@sonarqubecloud
Copy link
Copy Markdown

@pandeymangg pandeymangg merged commit 5169dec into epic/v5 Apr 29, 2026
13 checks passed
@pandeymangg pandeymangg deleted the feat/restack-pr3-workspace-directory-nav-v2 branch April 29, 2026 10:49
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.

3 participants