Skip to content

Curves MinMax control extended menu migration to Vue#919

Merged
haslinghuis merged 8 commits into
betaflight:masterfrom
demvlad:extended_minmax_ctrl_menu
May 27, 2026
Merged

Curves MinMax control extended menu migration to Vue#919
haslinghuis merged 8 commits into
betaflight:masterfrom
demvlad:extended_minmax_ctrl_menu

Conversation

@demvlad

@demvlad demvlad commented May 22, 2026

Copy link
Copy Markdown
Contributor

The extended MinMax control menu at the charts config dialog box.
Press Shift+Right mouse click at the min-max input fields to show it.

ExtendedMenu

Summary by CodeRabbit

  • Refactor

    • Context menu rebuilt to be state-driven, tracking modifier keys and per-curve checkbox state so menu content and labels update dynamically; dialog now receives current graph context.
  • New Features

    • Shift-held extended menu shows checkbox submenus for batch operations (min/max, scaling, centering, zoom, full-range).
    • Bulk actions can be scoped to checked curves and honor interval/window selections.
  • Bug Fixes

    • Multiple bulk-action flows corrected.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bac0ea99-f7ef-4047-854c-22a7502fedff

📥 Commits

Reviewing files that changed from the base of the PR and between 6980cd2 and c826778.

📒 Files selected for processing (2)
  • src/App.vue
  • src/components/GraphConfigDialog.vue

Walkthrough

GraphConfigDialog.vue now accepts a grapher prop; context-menu logic was refactored from imperative mutation to state-driven computed menus with a shift-key extended menu offering per-field checkboxes and checkbox-scoped bulk min/max actions.

Changes

Context Menu State-Driven Refactor

Layer / File(s) Summary
Prop and template wiring, menu state foundation
src/components/GraphConfigDialog.vue, src/App.vue
Adds grapher prop and binds :grapher="graphStore.graph"; establishes menu state foundation used by computed menus.
Simple computed menu and current-field label
src/components/GraphConfigDialog.vue
Adds simpleMenuItems for non-shift menus and computes current-field submenu header from friendlyName(currentState.value.field?.name ?? "").
Menu state (currentState) and default resets
src/components/GraphConfigDialog.vue
Introduces currentState (graph, field, shiftKey, isFieldChecked) and refactors setMinMaxToDefault to accept setCheckedOnly to reset only checked fields when scoped.
Scoped bulk min/max helpers
src/components/GraphConfigDialog.vue
Refactors bulk setters (setMinMaxLikeThis, setMinMaxOneScale, setMinMaxCentered, setMinMaxZoom, full-range/interval helpers) to accept setCheckedOnly and apply updates only to checkbox-selected curves; interval/window computations use props.grapher.
Extended/checkboxed menu and context handler
src/components/GraphConfigDialog.vue
Adds getFieldsCheckboxedSubmenu() and extendedMenuItems with nested checkboxes; menuItems switches by currentState.shiftKey; onContextMenu initializes currentState and isFieldChecked so extended actions route to scoped helpers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • betaflight/blackbox-log-viewer#918: Modifies the same min/max context-menu implementation in GraphConfigDialog.vue; this PR builds on related menu/state scaffolding changes.

Suggested reviewers

  • haslinghuis
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description provides a brief explanation and includes a screenshot demonstrating the feature, but does not follow the repository's PR template with required considerations and guidelines. Provide additional context such as motivation for the change, any testing performed, and clarify the status of the incomplete 'Full range' submenu items mentioned in PR objectives.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: migrating the extended MinMax control menu to Vue, which aligns with the refactoring of GraphConfigDialog to use a state-driven context-menu system with new bulk min/max helpers.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

🤖 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/components/GraphConfigDialog.vue`:
- Around line 851-863: getFieldsCheckboxedSubmenu currently dereferences
currentState.value.graph.fields and can throw if state isn't seeded; update the
function to early-return an empty array (or safe fallback) when
currentState.value, currentState.value.graph, or currentState.value.graph.fields
is falsy, and ensure you read isFieldChecked safely (fallback to an array) and
guard index access when setting currentState.value.isFieldChecked[index]; this
keeps getFieldsCheckboxedSubmenu from throwing before onContextMenu initializes
state while preserving the existing mapping behavior.
- Around line 865-1084: The extendedMenuItems handlers are no-ops (they only
call e.preventDefault()) so batch Min/Max and Zoom actions never run; update
each actionable onSelect in the extendedMenuItems computed (the "SET", "At the
all/window/markers time", "ZOOM IN/OUT", "SET CURVES TO DEFAULT", etc.) to call
the existing batch helper applyToCheckedFields(...) and pass the appropriate
operation (e.g., invoke the same logic used by setMinMaxSelectedCentered,
setMinMaxSelectedZoom, setMinMaxSelectedDefault but applied per-field) and
ensure applyToCheckedFields uses isFieldChecked to scope updates to checked
fields; keep using friendlyName(currentState.value.field?.name...), zoom, and
getFieldsCheckboxedSubmenu() as needed and remove the empty e.preventDefault()
placeholders or call preventDefault then invoke applyToCheckedFields for the
action.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c58fb2ec-c148-45a5-b17d-4e2dde57e141

📥 Commits

Reviewing files that changed from the base of the PR and between af5e516 and a8a38cc.

📒 Files selected for processing (1)
  • src/components/GraphConfigDialog.vue

Comment thread src/components/GraphConfigDialog.vue
@demvlad demvlad marked this pull request as draft May 22, 2026 14:32
@demvlad demvlad marked this pull request as ready for review May 23, 2026 20:15

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
src/components/GraphConfigDialog.vue (1)

1006-1022: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Wrong function called for batch zoom operations.

setMinMaxSelectedZoom at line 728 only accepts one argument (zoom) and operates on the single selected field. The second argument true is silently ignored, so these batch operations effectively zoom only the right-clicked field instead of all checked fields.

Should call setMinMaxZoom(zoom, setCheckedOnly) which is the batch-aware version.

🐛 Proposed fix
         [
           {
             label: "ZOOM IN",
             onSelect(e) {
-              setMinMaxSelectedZoom(1 / zoom, true);
+              setMinMaxZoom(1 / zoom, true);
               e.preventDefault();
             },
           },
           {
             label: "ZOOM OUT",
             onSelect(e) {
-              setMinMaxSelectedZoom(zoom, true);
+              setMinMaxZoom(zoom, true);
               e.preventDefault();
             },
           },
         ],
🤖 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/components/GraphConfigDialog.vue` around lines 1006 - 1022, The context
menu handlers for "ZOOM IN"/"ZOOM OUT" call setMinMaxSelectedZoom(…, true) but
that function only accepts one argument and affects a single selected field;
replace those calls with the batch-aware setMinMaxZoom(zoom, true) so the second
argument (setCheckedOnly) is honored and the operation applies to all checked
fields; update the onSelect functions in the menu item objects (the ones labeled
"ZOOM IN" and "ZOOM OUT") to call setMinMaxZoom with the same zoom value and
preserve the e.preventDefault() behavior.
🧹 Nitpick comments (1)
src/components/GraphConfigDialog.vue (1)

654-679: ⚡ Quick win

Extract repeated field-check condition to reduce complexity.

SonarCloud flags cognitive complexity of 20 (limit 15). The same condition appears multiple times across this and other setter functions.

♻️ Suggested helper extraction
+function shouldApplyToField(index, setCheckedOnly) {
+  return (!setCheckedOnly || !currentState.value.isFieldChecked) || currentState.value.isFieldChecked[index];
+}
+
 function setMinMaxOneScale(setCheckedOnly) {
   let max = -Number.MAX_VALUE;
   let min = Number.MAX_VALUE;

   if (currentState.value.graph?.fields) {
     for (const [index, field] of currentState.value.graph.fields.entries()) {
-      if ((!setCheckedOnly || !currentState.value.isFieldChecked) || currentState.value.isFieldChecked[index]) {
+      if (shouldApplyToField(index, setCheckedOnly)) {
         const mm = field?.curve?.MinMax;
         // ...
       }
     }

Then apply the same pattern to setMinMaxCentered, setMinMaxZoom, setMinMaxToFullRangeDuringAllTime, etc.

🤖 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/components/GraphConfigDialog.vue` around lines 654 - 679, Refactor the
repeated field-check logic in setMinMaxOneScale by extracting a helper (e.g.,
shouldProcessField(index, setCheckedOnly)) that encapsulates the condition using
currentState.value.isFieldChecked and the setCheckedOnly flag, then replace the
duplicated checks in both loops inside setMinMaxOneScale with calls to that
helper; apply the same extraction and replacement in the similar functions
setMinMaxCentered, setMinMaxZoom, setMinMaxToFullRangeDuringAllTime, etc., to
reduce cognitive complexity and centralize the field-checked decision.
🤖 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/components/GraphConfigDialog.vue`:
- Around line 865-882: In getFieldsCheckboxedSubmenu, guard access to
currentState.value.isFieldChecked and use the local fields variable: use the
local const fields for mapping (fields.map(...)) and for each index check that
currentState.value.isFieldChecked is an array (and optionally has an entry at
index) before reading or assigning; if it's null/undefined, treat checked as
false and initialize or set the entry on update (e.g., ensure onUpdateChecked
writes into an array after creating it if needed). This prevents null
dereference when the computed runs before onContextMenu seeds state and keeps
the code consistent by using the local fields variable instead of
currentState.value.graph.fields.

---

Outside diff comments:
In `@src/components/GraphConfigDialog.vue`:
- Around line 1006-1022: The context menu handlers for "ZOOM IN"/"ZOOM OUT" call
setMinMaxSelectedZoom(…, true) but that function only accepts one argument and
affects a single selected field; replace those calls with the batch-aware
setMinMaxZoom(zoom, true) so the second argument (setCheckedOnly) is honored and
the operation applies to all checked fields; update the onSelect functions in
the menu item objects (the ones labeled "ZOOM IN" and "ZOOM OUT") to call
setMinMaxZoom with the same zoom value and preserve the e.preventDefault()
behavior.

---

Nitpick comments:
In `@src/components/GraphConfigDialog.vue`:
- Around line 654-679: Refactor the repeated field-check logic in
setMinMaxOneScale by extracting a helper (e.g., shouldProcessField(index,
setCheckedOnly)) that encapsulates the condition using
currentState.value.isFieldChecked and the setCheckedOnly flag, then replace the
duplicated checks in both loops inside setMinMaxOneScale with calls to that
helper; apply the same extraction and replacement in the similar functions
setMinMaxCentered, setMinMaxZoom, setMinMaxToFullRangeDuringAllTime, etc., to
reduce cognitive complexity and centralize the field-checked decision.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1f252311-7301-4572-af2f-4fe40dad79d8

📥 Commits

Reviewing files that changed from the base of the PR and between a8a38cc and 2743af1.

📒 Files selected for processing (1)
  • src/components/GraphConfigDialog.vue

Comment thread src/components/GraphConfigDialog.vue
@demvlad

demvlad commented May 23, 2026

Copy link
Copy Markdown
Contributor Author

These "Full range" submenu items do not work til:

  • "At the window time"
  • "At the markers time"
    They will be resolved next time.

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 23, 2026

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

Caution

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

⚠️ Outside diff range comments (1)
src/components/GraphConfigDialog.vue (1)

1007-1018: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the batch zoom helper here.

Line 728’s setMinMaxSelectedZoom only updates currentState.value.field, so these Shift-mode “SELECT CURVES” actions still zoom a single curve and ignore the checkbox selection. Call setMinMaxZoom(..., true) instead.

🔧 Proposed fix
          {
            label: "ZOOM IN",
            onSelect(e) {
-              setMinMaxSelectedZoom(1 / zoom, true);
+              setMinMaxZoom(1 / zoom, true);
              e.preventDefault();
            },
          },
          {
            label: "ZOOM OUT",
            onSelect(e) {
-              setMinMaxSelectedZoom(zoom, true);
+              setMinMaxZoom(zoom, true);
              e.preventDefault();
            },
          },
🤖 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/components/GraphConfigDialog.vue` around lines 1007 - 1018, The
Shift-mode zoom actions labeled "ZOOM IN" and "ZOOM OUT" are calling
setMinMaxSelectedZoom which only updates currentState.value.field and thus
ignores the checkbox-selected curves; replace those calls with the batch helper
setMinMaxZoom(..., true) (preserving the same zoom value and the
e.preventDefault() behavior) so the actions operate on all selected curves
instead of a single curve.
🤖 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.

Outside diff comments:
In `@src/components/GraphConfigDialog.vue`:
- Around line 1007-1018: The Shift-mode zoom actions labeled "ZOOM IN" and "ZOOM
OUT" are calling setMinMaxSelectedZoom which only updates
currentState.value.field and thus ignores the checkbox-selected curves; replace
those calls with the batch helper setMinMaxZoom(..., true) (preserving the same
zoom value and the e.preventDefault() behavior) so the actions operate on all
selected curves instead of a single curve.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bf40bf30-1e74-4418-b42f-b5d5c6cb8422

📥 Commits

Reviewing files that changed from the base of the PR and between 2743af1 and 7db8e66.

📒 Files selected for processing (1)
  • src/components/GraphConfigDialog.vue

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 23, 2026
@demvlad demvlad changed the title Extended MinMax control menu migration to Vue (Draft) Extended MinMax control menu migration to Vue May 23, 2026
@demvlad demvlad changed the title Extended MinMax control menu migration to Vue Curves MinMax control extended menu migration to Vue May 24, 2026
@demvlad

demvlad commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

@haslinghuis
Perhaps, the all MinMax contol functions are restored.

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

Caution

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

⚠️ Outside diff range comments (2)
src/components/GraphConfigDialog.vue (1)

1038-1049: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the batch Zoom helper in the Shift menu.

These handlers sit under the checked-curves submenu, but they still call the single-field helper. Shift → Zoom therefore updates only the clicked curve instead of the checked set.

🛠️ Proposed fix
           {
             label: "ZOOM IN",
             onSelect(e) {
-              setMinMaxSelectedZoom(1 / zoom, true);
+              setMinMaxZoom(1 / zoom, true);
               e.preventDefault();
             },
           },
           {
             label: "ZOOM OUT",
             onSelect(e) {
-              setMinMaxSelectedZoom(zoom, true);
+              setMinMaxZoom(zoom, true);
               e.preventDefault();
             },
           },
🤖 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/components/GraphConfigDialog.vue` around lines 1038 - 1049, The ZOOM
IN/OUT handlers under the checked-curves submenu are calling the single-curve
helper setMinMaxSelectedZoom(…, true) with zoom, so Shift→Zoom only affects the
clicked curve; replace those calls with the batch Zoom helper that applies to
the checked set (the project’s batch helper for checked curves—e.g.,
setMinMaxSelectedZoomForChecked or setMinMaxSelectedZoomBatch) and pass the same
arguments (1/zoom, true) for ZOOM IN and (zoom, true) for ZOOM OUT, keeping the
existing e.preventDefault() behavior so the action updates all checked curves
instead of just the clicked one.
src/App.vue (1)

99-104: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove the trailing comma from the :grapher prop binding in src/App.vue

<GraphConfigDialog ... :grapher="graphStore.graph", @save="..."> contains a trailing comma after the attribute value, which makes the Vue SFC template invalid and will fail to compile.

🛠️ Proposed fix
-        :grapher="graphStore.graph",
+        :grapher="graphStore.graph"
🤖 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/App.vue` around lines 99 - 104, Summary: Remove the stray trailing comma
after the :grapher prop in the GraphConfigDialog component usage to fix the
invalid Vue template. Fix: edit the GraphConfigDialog JSX/Template invocation
(the line with :grapher="graphStore.graph",) in src/App.vue and remove the comma
so it reads :grapher="graphStore.graph" and ensure the next attribute
(`@save`="onGraphConfigSave") remains on the same element; verify the template
compiles and run linter/formatter to keep spacing consistent.
🤖 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.

Outside diff comments:
In `@src/App.vue`:
- Around line 99-104: Summary: Remove the stray trailing comma after the
:grapher prop in the GraphConfigDialog component usage to fix the invalid Vue
template. Fix: edit the GraphConfigDialog JSX/Template invocation (the line with
:grapher="graphStore.graph",) in src/App.vue and remove the comma so it reads
:grapher="graphStore.graph" and ensure the next attribute
(`@save`="onGraphConfigSave") remains on the same element; verify the template
compiles and run linter/formatter to keep spacing consistent.

In `@src/components/GraphConfigDialog.vue`:
- Around line 1038-1049: The ZOOM IN/OUT handlers under the checked-curves
submenu are calling the single-curve helper setMinMaxSelectedZoom(…, true) with
zoom, so Shift→Zoom only affects the clicked curve; replace those calls with the
batch Zoom helper that applies to the checked set (the project’s batch helper
for checked curves—e.g., setMinMaxSelectedZoomForChecked or
setMinMaxSelectedZoomBatch) and pass the same arguments (1/zoom, true) for ZOOM
IN and (zoom, true) for ZOOM OUT, keeping the existing e.preventDefault()
behavior so the action updates all checked curves instead of just the clicked
one.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bf231762-5120-4087-92f6-9717d1c3c4be

📥 Commits

Reviewing files that changed from the base of the PR and between 7db8e66 and 6980cd2.

📒 Files selected for processing (2)
  • src/App.vue
  • src/components/GraphConfigDialog.vue

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 26, 2026
@haslinghuis

Copy link
Copy Markdown
Member

Can do the sonar issues after - or you could include them here

@demvlad

demvlad commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

Can do the sonar issues after - or you could include them here

Will look now.

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 26, 2026
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
11.0% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@github-actions

Copy link
Copy Markdown

Preview URL: https://pr919.betaflight-blackbox.pages.dev

@demvlad

demvlad commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

Can do the sonar issues after - or you could include them here

Done.

@haslinghuis haslinghuis requested a review from nerdCopter May 26, 2026 18:36
@haslinghuis haslinghuis merged commit b3307e5 into betaflight:master May 27, 2026
7 of 8 checks passed
@demvlad demvlad deleted the extended_minmax_ctrl_menu branch May 27, 2026 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants