Skip to content

feat: dashboard edits#267

Merged
gusfcarvalho merged 2 commits into
mainfrom
gc-feat-dashboard-suggestions-edit
Jun 18, 2026
Merged

feat: dashboard edits#267
gusfcarvalho merged 2 commits into
mainfrom
gc-feat-dashboard-suggestions-edit

Conversation

@gusfcarvalho

@gusfcarvalho gusfcarvalho commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Edit suggestion groups: update titles, filter labels, and member controls.
    • Generate filter merge suggestions via new generalization workflow.
    • Refine evidence selection using dynamic label conditions.
    • Display suggestion edits, differences, and generalization details.

Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@gusfcarvalho, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 50 minutes and 44 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ff5323fc-a7fb-43b0-b76b-20ea3db2e87a

📥 Commits

Reviewing files that changed from the base of the PR and between 5ba89d7 and ad3b5ce.

📒 Files selected for processing (3)
  • src/views/dashboard/SuggestionsView.vue
  • src/views/dashboard/partials/SuggestionEditDialog.vue
  • src/views/dashboard/partials/SuggestionScopeDialog.vue
📝 Walkthrough

Walkthrough

Adds label-condition-based evidence scoping, suggestion group editing, and filter-merge generalization to the dashboard suggestions feature. New types, endpoint helpers, and utility functions are defined in dashboard-suggestions.ts; a LabelConditionBuilder component and SuggestionEditDialog are introduced; SuggestionScopeDialog is reworked to use conditions/constraints instead of label sets; useDashboardSuggestions exposes new API; and SuggestionsView wires everything together.

Changes

Dashboard Suggestion Editing, Filter Generalization, and Label Condition Builder

Layer / File(s) Summary
Data contracts, endpoint helpers, and utility functions
src/views/dashboard/partials/dashboard-suggestions.ts
Adds DashboardSuggestionLabelKey, LabelConditionRow, DashboardSuggestionConstraints, LabelChip, GroupEditDiff types; extends DashboardSuggestion with edit/audit/generalization fields; adds buildLabelFilter, buildControlKey, computeGroupEditDiff, and new endpoint builders for generalization, label keys/values, and edit-group.
LabelConditionBuilder component
src/views/dashboard/partials/LabelConditionBuilder.vue
New Vue component rendering key/value condition rows with client-side key autocomplete, server-side async value fetch, and add/remove row controls.
SuggestionScopeDialog: conditions and constraints rework
src/views/dashboard/partials/SuggestionScopeDialog.vue
Replaces label-set multi-select with LabelConditionBuilder for evidence selection; adds scopePreset, mandatory, and excluded label constraint builders; updates selectedScope/selectedConstraints/fetchPreview payload logic; switches prop from labelSets to labelKeys.
SuggestionEditDialog component
src/views/dashboard/partials/SuggestionEditDialog.vue
New modal SFC for editing a suggestion group: title, dynamic label rows, membership checkboxes, add-controls multi-select, canSave gating, state-init watcher, and save emit with EditDashboardSuggestionGroupPayload.
useDashboardSuggestions composable expansion
src/composables/useDashboardSuggestions.ts
Adds useDataApi hooks and async functions for refreshLabelKeys, generalizeSuggestions, and editSuggestionGroup; extends camelcaseStopPaths to preserve originalProposedFilterLabelSet; expands returned API with new flags and functions.
SuggestionsView wiring and UI
src/views/dashboard/SuggestionsView.vue
Adds "Suggest filter merges" button, diff-driven pending-group headers via diffFor/labelChipClass, label-chip rows, Edit button, Added/Removed-controls badges, SuggestionEditDialog integration, catalog-qualified controlOptions, filterLabelsObject grouping, and suggestFilterMerges/openEditDialog/saveGroupEdit handlers.
Tests
src/views/dashboard/partials/__tests__/dashboard-suggestions.spec.ts, ...LabelConditionBuilder.spec.ts, ...SuggestionEditDialog.spec.ts, ...SuggestionScopeDialog.spec.ts, src/views/dashboard/__tests__/SuggestionsView.spec.ts
Adds test suites for buildLabelFilter, computeGroupEditDiff, LabelConditionBuilder, SuggestionEditDialog, and updates SuggestionScopeDialog and SuggestionsView tests to align with new types, mocks, stubs, and catalog-qualified control key format.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SuggestionsView
  participant SuggestionScopeDialog
  participant SuggestionEditDialog
  participant useDashboardSuggestions
  participant BackendAPI

  rect rgba(100, 149, 237, 0.5)
    Note over User,BackendAPI: Filter Merge Generalization
    User->>SuggestionsView: clicks "Suggest filter merges"
    SuggestionsView->>useDashboardSuggestions: generalizeSuggestions()
    useDashboardSuggestions->>BackendAPI: POST generalize endpoint
    BackendAPI-->>useDashboardSuggestions: { candidates, inserted }
    useDashboardSuggestions->>BackendAPI: refreshPendingSuggestions()
    SuggestionsView->>SuggestionsView: show toast (inserted/candidates counts)
  end

  rect rgba(144, 238, 144, 0.5)
    Note over User,BackendAPI: Suggestion Group Editing
    User->>SuggestionsView: clicks Edit on pending group
    SuggestionsView->>SuggestionEditDialog: openEditDialog(group)
    User->>SuggestionEditDialog: edits title, label rows, controls
    SuggestionEditDialog-->>SuggestionsView: emits save(EditDashboardSuggestionGroupPayload)
    SuggestionsView->>useDashboardSuggestions: editSuggestionGroup(payload)
    useDashboardSuggestions->>BackendAPI: POST edit-group endpoint
    useDashboardSuggestions->>BackendAPI: refreshPendingSuggestions()
  end

  rect rgba(255, 200, 100, 0.5)
    Note over User,BackendAPI: Generate with Label Conditions
    User->>SuggestionsView: opens SuggestionScopeDialog
    SuggestionsView->>useDashboardSuggestions: refreshLabelKeys()
    useDashboardSuggestions->>BackendAPI: GET label-keys endpoint
    User->>SuggestionScopeDialog: enters conditions and constraints
    SuggestionScopeDialog->>BackendAPI: POST preview with scope + constraints
    User->>SuggestionScopeDialog: clicks Generate
    SuggestionScopeDialog-->>SuggestionsView: emits generate(scope, constraints)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • compliance-framework/ui#265: Modifies useDashboardSuggestions and SuggestionsView around camelcaseStopPaths preservation for proposed filter label sets and pending-group grouping/reasoning logic, which this PR directly extends.

Poem

🐇 Hippity-hop, the labels align,
Key-value rows in a builder divine!
Edit a group, merge filters with flair,
Chips marked added or removed with care.
The rabbit diffs chips and toasts with glee —
Suggestions now smarter than they used to be! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: dashboard edits' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changes in the changeset. Consider a more specific title that highlights the primary feature, such as 'feat: add suggestion group editing and generalization workflow' or 'feat: dashboard suggestions editing with label conditions'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/views/dashboard/partials/dashboard-suggestions.ts`:
- Around line 183-187: The condition in the baselineRow find method currently
excludes empty objects as valid baselines because of the Object.keys length
check. An empty object {} should be treated as a valid baseline rather than "no
baseline". Remove the length check on
Object.keys(s.originalProposedFilterLabelSet) and simply verify that
originalProposedFilterLabelSet exists (is not undefined or null). Apply the same
fix to the similar code block at lines 211-213 that has the same pattern.

In `@src/views/dashboard/partials/SuggestionEditDialog.vue`:
- Around line 253-257: The addControlKeys mapping in the submit() method
unconditionally re-qualifies control IDs using buildControlKey(), but
addControlIds may already contain catalog-qualified keys from SuggestionsView.
This double qualification breaks the API contract. Check whether each controlId
in addControlIds.value is already a qualified key before processing it. If it's
already qualified, use it directly in the returned array. If it's not qualified,
then call buildControlKey() with the catalog ID and control ID to qualify it.
This ensures you don't emit invalid re-qualified control keys.

In `@src/views/dashboard/SuggestionsView.vue`:
- Around line 1040-1047: The saveGroupEdit function catches errors and only sets
scopeCeilingError.value, which is scoped to SuggestionScopeDialog, causing edit
failures to become silent in the edit dialog path. In addition to extracting the
error message and setting scopeCeilingError.value, also set an error state
variable that is connected to the edit dialog display (such as an editError or
similar variable) so that users receive visible feedback when the group edit
save operation fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 97f1dd49-4f9b-4ada-a8d9-62b0002e8bfc

📥 Commits

Reviewing files that changed from the base of the PR and between 23c26f1 and 5ba89d7.

📒 Files selected for processing (11)
  • src/composables/useDashboardSuggestions.ts
  • src/views/dashboard/SuggestionsView.vue
  • src/views/dashboard/__tests__/SuggestionsView.spec.ts
  • src/views/dashboard/partials/LabelConditionBuilder.vue
  • src/views/dashboard/partials/SuggestionEditDialog.vue
  • src/views/dashboard/partials/SuggestionScopeDialog.vue
  • src/views/dashboard/partials/__tests__/LabelConditionBuilder.spec.ts
  • src/views/dashboard/partials/__tests__/SuggestionEditDialog.spec.ts
  • src/views/dashboard/partials/__tests__/SuggestionScopeDialog.spec.ts
  • src/views/dashboard/partials/__tests__/dashboard-suggestions.spec.ts
  • src/views/dashboard/partials/dashboard-suggestions.ts

Comment on lines +183 to +187
const baselineRow = suggestions.find(
(s) =>
s.originalProposedFilterLabelSet &&
Object.keys(s.originalProposedFilterLabelSet).length > 0,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle empty AI baselines as valid baselines in diff computation

originalProposedFilterLabelSet: {} is currently treated as “no baseline” because of the length check, so edited labels render as unchanged instead of added.

Suggested patch
-  const baselineRow = suggestions.find(
-    (s) =>
-      s.originalProposedFilterLabelSet &&
-      Object.keys(s.originalProposedFilterLabelSet).length > 0,
-  );
-  const baseline = baselineRow?.originalProposedFilterLabelSet;
+  const baseline = suggestions.find(
+    (s) => s.originalProposedFilterLabelSet !== undefined,
+  )?.originalProposedFilterLabelSet;
+  const hasBaseline = baseline !== undefined;
@@
-    ...(baseline ? Object.keys(baseline) : []),
+    ...(hasBaseline ? Object.keys(baseline) : []),
@@
-    if (!baseline) {
+    if (!hasBaseline) {
       labelChips.push({ text: `${key}=${current}`, kind: 'unchanged' });

Also applies to: 211-213

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/views/dashboard/partials/dashboard-suggestions.ts` around lines 183 -
187, The condition in the baselineRow find method currently excludes empty
objects as valid baselines because of the Object.keys length check. An empty
object {} should be treated as a valid baseline rather than "no baseline".
Remove the length check on Object.keys(s.originalProposedFilterLabelSet) and
simply verify that originalProposedFilterLabelSet exists (is not undefined or
null). Apply the same fix to the similar code block at lines 211-213 that has
the same pattern.

Comment on lines +253 to +257
const addControlKeys = addControlIds.value.map((controlId) => {
const catalogId =
props.resolveCatalogId?.(controlId) || groupCatalogId.value;
return buildControlKey(catalogId, controlId);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid re-qualifying control keys in edit payload

addControlIds may already contain catalog-qualified keys from SuggestionsView (optionValue = controlOptions.value), but submit() always runs buildControlKey(...) again. This can emit invalid addControlKeys and break the API contract.

Suggested patch
-  const addControlKeys = addControlIds.value.map((controlId) => {
-    const catalogId =
-      props.resolveCatalogId?.(controlId) || groupCatalogId.value;
-    return buildControlKey(catalogId, controlId);
-  });
+  const addControlKeys = addControlIds.value.map((controlKeyOrId) => {
+    if (controlKeyOrId.includes(':')) {
+      return controlKeyOrId;
+    }
+    const catalogId =
+      props.resolveCatalogId?.(controlKeyOrId) || groupCatalogId.value;
+    return catalogId
+      ? buildControlKey(catalogId, controlKeyOrId)
+      : controlKeyOrId;
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const addControlKeys = addControlIds.value.map((controlId) => {
const catalogId =
props.resolveCatalogId?.(controlId) || groupCatalogId.value;
return buildControlKey(catalogId, controlId);
});
const addControlKeys = addControlIds.value.map((controlKeyOrId) => {
if (controlKeyOrId.includes(':')) {
return controlKeyOrId;
}
const catalogId =
props.resolveCatalogId?.(controlKeyOrId) || groupCatalogId.value;
return catalogId
? buildControlKey(catalogId, controlKeyOrId)
: controlKeyOrId;
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/views/dashboard/partials/SuggestionEditDialog.vue` around lines 253 -
257, The addControlKeys mapping in the submit() method unconditionally
re-qualifies control IDs using buildControlKey(), but addControlIds may already
contain catalog-qualified keys from SuggestionsView. This double qualification
breaks the API contract. Check whether each controlId in addControlIds.value is
already a qualified key before processing it. If it's already qualified, use it
directly in the returned array. If it's not qualified, then call
buildControlKey() with the catalog ID and control ID to qualify it. This ensures
you don't emit invalid re-qualified control keys.

Comment thread src/views/dashboard/SuggestionsView.vue
Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>
@gusfcarvalho gusfcarvalho enabled auto-merge (squash) June 18, 2026 12:35
@gusfcarvalho gusfcarvalho merged commit 22defbe into main Jun 18, 2026
3 checks passed
@gusfcarvalho gusfcarvalho deleted the gc-feat-dashboard-suggestions-edit branch June 18, 2026 12:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant