Skip to content

feat(tempgroups): add user-organizable temperature tabs#2434

Open
Ragilo wants to merge 3 commits intomainsail-crew:developfrom
Ragilo:feat/temperature-groups
Open

feat(tempgroups): add user-organizable temperature tabs#2434
Ragilo wants to merge 3 commits intomainsail-crew:developfrom
Ragilo:feat/temperature-groups

Conversation

@Ragilo
Copy link
Copy Markdown
Contributor

@Ragilo Ragilo commented Feb 9, 2026

Summary

Adds ability to organize temperature sensors into custom groups (tabs), addressing the issue of cluttered temperature panels with many sensors.

  • Create, edit, and delete temperature groups via Settings → Temp Groups
  • Drag & drop to reorder groups and sensors within groups
  • Optional "All" tab showing all sensors (default behavior preserved)
  • Custom display names for sensors (solves issue with non-renamable sensors like Cartographer)
  • Per-group chart visibility toggle
  • Graph Y-axis scales appropriately for filtered sensor range
  • Full backwards compatibility - no tabs shown without configured groups

Screenshots

image image image image

Test plan

  • Create a new temperature group
  • Add sensors to the group
  • Verify only grouped sensors appear in the tab
  • Verify graph filters correctly for the active tab
  • Test drag & drop reordering of groups and sensors
  • Test custom display names for sensors
  • Verify "Show All tab" toggle works
  • Verify settings persist after browser reload
  • Test on mobile (responsive tabs)

Closes #2376

Adds ability to organize temperature sensors into custom groups (tabs).
Each tab shows its own sensor list and filtered temperature graph.

Features:
- Create, edit, and delete temperature groups
- Drag & drop to reorder groups and sensors within groups
- Optional "All" tab showing all sensors (like before)
- Custom display names for sensors (solves Cartographer naming issue)
- Per-group chart visibility toggle
- Graph Y-axis scales appropriately for filtered sensors
- Full backwards compatibility (no tabs shown without groups)

Closes mainsail-crew#2376

Signed-off-by: Christopher Hesse <christopher.hesse@alphaflow.gmbh>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 9, 2026

📝 Walkthrough

Walkthrough

Adds a new "tempgroups" feature: settings UI for creating/reordering sensor groups, a namespaced Vuex tempgroups module to persist groups and active selection, and UI changes that render tabbed temperature panels filtering lists and charts by the active group.

Changes

Cohort / File(s) Summary
Temperature panel UI
src/components/panels/TemperaturePanel.vue, src/components/panels/Temperature/TemperaturePanelTabs.vue, src/components/panels/Temperature/TemperaturePanelList.vue, src/components/charts/TempChart.vue
Add tabbed temp-groups UI. New TemperaturePanelTabs manages active group in store; TemperaturePanel passes a sensorFilter to children; TemperaturePanelList and TempChart accept/consume sensorFilter and expose filtered getters.
Settings UI
src/components/TheSettingsMenu.vue, src/components/settings/SettingsTempgroupsTab.vue, src/components/settings/SettingsTempgroupsTabEdit.vue
Register new SettingsTempgroupsTab in settings menu and add full group-management UI (list, drag reorder, create/edit modal, sensor assignment, per-group options).
Vuex: tempgroups module
src/store/gui/tempgroups/types.ts, src/store/gui/tempgroups/index.ts, src/store/gui/tempgroups/getters.ts, src/store/gui/tempgroups/actions.ts, src/store/gui/tempgroups/mutations.ts, src/store/gui/index.ts, src/store/gui/types.ts
New namespaced Vuex module with types, state, getters (sorted groups, active filter, ungrouped sensors), actions (CRUD, reorder, persist, socket sync), and mutations; registered under gui.
Localization
src/locales/en.json
Add English translation keys for tempgroups UI (tab labels, settings, dialogs, group/sensor messages).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Tabs as TemperaturePanelTabs
    participant Store as Vuex Store
    participant Panel as TemperaturePanel
    participant List as TemperaturePanelList
    participant Chart as TempChart

    User->>Tabs: select group tab
    Tabs->>Store: dispatch setActiveGroup(groupId)
    Store->>Store: update activeGroupId

    Panel->>Store: read getActiveSensorFilter()
    Panel->>List: pass sensorFilter
    Panel->>Chart: pass sensorFilter

    List->>List: compute filtered lists
    List->>User: render filtered sensor list

    Chart->>Chart: compute filteredSeries from sensorFilter
    Chart->>User: render filtered chart
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped through code with whiskers bright,

I grouped the temps to tidy sight,
Drag, name, and sort each sensor crew,
Tabs now filter charts true-blue,
A little rabbit cheers — hooray! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main feature: adding user-organizable temperature tabs, which is the primary objective of this changeset.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining features implemented, test coverage, and linking to the closed issue.
Linked Issues check ✅ Passed The PR fully addresses #2376 requirements: multiple temperature tabs, create/edit/delete groups, drag-and-drop reordering, custom sensor names, per-group chart visibility, and backwards compatibility.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing temperature group functionality. No unrelated modifications to other features or systems were introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Copy Markdown

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

🤖 Fix all issues with AI agents
In `@src/components/settings/SettingsTempgroupsTabEdit.vue`:
- Around line 200-212: The debounced updater dispatches invalid names because
updateGroupNameDebounced(newVal: string) is called unconditionally from the
groupName setter; change updateGroupNameDebounced to perform the same validation
checks as the component's rules (e.g., non-empty, uniqueness against existing
temp groups, and any length/format checks) before calling this.$store.dispatch,
and also ensure it returns early if validation fails or if newVal ===
this.localGroupName; reference the groupName setter, updateGroupNameDebounced,
this.localGroupName and the component's validation rules when implementing the
guard.

In `@src/store/gui/tempgroups/actions.ts`:
- Around line 73-82: addSensorToGroup currently creates a GuiTempgroupSensor
with pos: 0 which causes duplicate positions; instead, read the group's existing
sensors from the action context (use the destructured state or state.groups /
groupStore equivalent) to compute the next position as (max existing sensor.pos
+ 1) or 0 if none, set sensor.pos to that computed nextPos before calling
commit('addSensorToGroup', { id, sensor }) and then dispatch('groupUpload', id);
reference the addSensorToGroup action, GuiTempgroupSensor shape, the
'addSensorToGroup' mutation and dispatch to 'groupUpload' when making the
change.
🧹 Nitpick comments (10)
src/store/gui/tempgroups/actions.ts (2)

54-55: await on a synchronous Vuex commit is misleading.

commit is synchronous in Vuex and does not return a Promise. The await on line 54 is a no-op and suggests asynchrony that doesn't exist. Only the dispatch on line 55 is actually async.

Suggested fix
-    await commit('groupStore', { id, values: group })
-    await dispatch('groupUpload', id)
+    commit('groupStore', { id, values: group })
+    await dispatch('groupUpload', id)

107-112: Group reorder triggers N individual socket calls.

reorderGroups dispatches groupUpload for each group, causing one socket emit per group. This works but is chatty. Not a problem for a handful of groups, but worth noting if the number could grow.

src/locales/en.json (1)

1385-1408: Overlapping locale keys between Settings.TempgroupsTab and Tempgroups.

Several keys are duplicated across these two sections with inconsistent casing (e.g., "Available Sensors" vs "Available sensors", "add group" vs "Add Group"). While having separate sections for settings vs. panel context is a valid pattern in this codebase, consider aligning the casing for shared concepts to maintain consistency, or consolidating keys that are truly identical.

Also applies to: 1609-1623

src/store/gui/tempgroups/types.ts (1)

9-22: Inconsistent naming: position in GuiTempgroup vs pos in GuiTempgroupSensor.

Both fields serve the same purpose (ordering), but use different names. Consider aligning them (e.g., both position or both pos) for consistency.

src/store/gui/tempgroups/mutations.ts (2)

62-73: Minor: shallow-copied array still mutates original sensor objects in-place.

sensors is a shallow copy of the array, but sensor[payload.option] = payload.value (Line 69) mutates the original sensor object reference before Vue.set replaces the array. While this works because Vue.set triggers reactivity on the sensors key, it's not purely immutable. Consider spreading the sensor object too for consistency with groupUpdate:

Suggested improvement
             if (sensorIndex !== -1) {
-                const sensor = sensors[sensorIndex]
-                // `@ts-ignore`
-                sensor[payload.option] = payload.value
+                sensors[sensorIndex] = {
+                    ...sensors[sensorIndex],
+                    [payload.option]: payload.value,
+                }
                 Vue.set(state.groups[payload.id], 'sensors', sensors)
             }

This also eliminates the @ts-ignore.


41-51: Minor: payload.sensor.pos is mutated on the caller's object.

Line 46 mutates payload.sensor.pos directly, which modifies the object the caller passed in. Consider creating a new sensor object instead:

Suggested improvement
         if (group) {
             const sensors = [...(group.sensors ?? [])]
             const maxPos = sensors.reduce((max, s) => Math.max(max, s.pos), -1)
-            payload.sensor.pos = maxPos + 1
-            sensors.push(payload.sensor)
+            sensors.push({ ...payload.sensor, pos: maxPos + 1 })

             Vue.set(state.groups[payload.id], 'sensors', sensors)
         }
src/components/settings/SettingsTempgroupsTab.vue (1)

134-136: Consider adding a confirmation dialog before deleting a group.

deleteGroup immediately dispatches the delete action with no user confirmation. If a group contains many carefully configured sensors, accidental deletion could be frustrating. A simple confirmation prompt would be a low-effort UX safeguard.

src/components/settings/SettingsTempgroupsTabEdit.vue (3)

173-173: searchSensors can be null at runtime due to Vuetify clearable.

When the user clicks the clear icon on a Vuetify v-text-field with clearable, the model is set to null. The type annotation says string, but the actual runtime value can be null. The guard on line 260 (!this.searchSensors) happens to cover this case, so there's no runtime crash, but the type is inaccurate.

Proposed fix
-private searchSensors: string = ''
+private searchSensors: string | null = ''

146-160: Class component structure and mixin usage look correct.

The component correctly uses @Component decorator, Mixins(BaseMixin, ThemeMixin), and @Prop with the right configuration for Vue 2 class components. One minor note: line 148 uses a relative import path ('../mixins/base') while line 149 uses an alias path ('@/components/mixins/theme'). Both work, but using the alias consistently would be slightly cleaner.


235-249: Consider using a Set for deduplication of sensors.

The allSensors computed builds a list by pushing heaters first, then conditionally adding sensors not already present. The includes check is O(n) per sensor, making this O(n²). For typical printer setups this is fine, but a Set would be both cleaner and O(n) overall.

Proposed refactor
 get allSensors(): string[] {
-    const sensors: string[] = []
-
-    const heaters = this.$store.state.printer?.heaters?.available_heaters || []
-    sensors.push(...heaters)
-
-    const tempSensors = this.$store.state.printer?.heaters?.available_sensors || []
-    tempSensors.forEach((sensor: string) => {
-        if (!sensors.includes(sensor)) {
-            sensors.push(sensor)
-        }
-    })
-
-    return sensors
+    const heaters: string[] = this.$store.state.printer?.heaters?.available_heaters || []
+    const tempSensors: string[] = this.$store.state.printer?.heaters?.available_sensors || []
+    return [...new Set([...heaters, ...tempSensors])]
 }

Comment on lines +200 to +212
set groupName(newVal: string) {
this.localGroupName = newVal
this.updateGroupNameDebounced(newVal)
}

@Debounce(250)
updateGroupNameDebounced(newVal: string) {
if (!this.groupId) return
this.$store.dispatch('gui/tempgroups/groupUpdate', {
id: this.groupId,
values: { name: newVal },
})
}
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

Debounced store update bypasses validation — invalid names get persisted.

The groupName setter dispatches updateGroupNameDebounced on every keystroke (after debounce), regardless of whether the rules pass. If the user clears the field or types a duplicate name, the Vuetify text field correctly shows the error, but the store is still updated with the invalid value after 250ms.

Guard the dispatch with the same checks used in the rules:

Proposed fix
 `@Debounce`(250)
 updateGroupNameDebounced(newVal: string) {
     if (!this.groupId) return
+    if (newVal === '' || this.existsGroupName(newVal)) return
     this.$store.dispatch('gui/tempgroups/groupUpdate', {
         id: this.groupId,
         values: { name: newVal },
     })
 }
📝 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
set groupName(newVal: string) {
this.localGroupName = newVal
this.updateGroupNameDebounced(newVal)
}
@Debounce(250)
updateGroupNameDebounced(newVal: string) {
if (!this.groupId) return
this.$store.dispatch('gui/tempgroups/groupUpdate', {
id: this.groupId,
values: { name: newVal },
})
}
set groupName(newVal: string) {
this.localGroupName = newVal
this.updateGroupNameDebounced(newVal)
}
`@Debounce`(250)
updateGroupNameDebounced(newVal: string) {
if (!this.groupId) return
if (newVal === '' || this.existsGroupName(newVal)) return
this.$store.dispatch('gui/tempgroups/groupUpdate', {
id: this.groupId,
values: { name: newVal },
})
}
🤖 Prompt for AI Agents
In `@src/components/settings/SettingsTempgroupsTabEdit.vue` around lines 200 -
212, The debounced updater dispatches invalid names because
updateGroupNameDebounced(newVal: string) is called unconditionally from the
groupName setter; change updateGroupNameDebounced to perform the same validation
checks as the component's rules (e.g., non-empty, uniqueness against existing
temp groups, and any length/format checks) before calling this.$store.dispatch,
and also ensure it returns early if validation fails or if newVal ===
this.localGroupName; reference the groupName setter, updateGroupNameDebounced,
this.localGroupName and the component's validation rules when implementing the
guard.

Comment on lines +73 to +82
addSensorToGroup({ commit, dispatch }, payload: { id: string; sensorName: string; displayName?: string }) {
const sensor: GuiTempgroupSensor = {
pos: 0,
name: payload.sensorName,
displayName: payload.displayName,
}

commit('addSensorToGroup', { id: payload.id, sensor })
dispatch('groupUpload', payload.id)
},
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

New sensors always get pos: 0, which may cause ambiguous ordering.

Every sensor added via addSensorToGroup gets pos: 0 regardless of how many sensors already exist in the group. If pos is used for sorting, multiple sensors will share the same position until explicitly reordered.

Consider computing the next position similarly to how groupStore computes maxPosition:

Suggested fix
 addSensorToGroup({ commit, dispatch }, payload: { id: string; sensorName: string; displayName?: string }) {
+    const group = (this as any).state.gui.tempgroups.groups[payload.id]
+    const maxPos = group?.sensors?.reduce((max: number, s: GuiTempgroupSensor) => Math.max(max, s.pos), -1) ?? -1
     const sensor: GuiTempgroupSensor = {
-        pos: 0,
+        pos: maxPos + 1,
         name: payload.sensorName,
         displayName: payload.displayName,
     }

Alternatively, you could use state from the action context:

Using destructured state
-addSensorToGroup({ commit, dispatch }, payload: { id: string; sensorName: string; displayName?: string }) {
+addSensorToGroup({ commit, dispatch, state }, payload: { id: string; sensorName: string; displayName?: string }) {
+    const existingSensors = state.groups[payload.id]?.sensors ?? []
+    const maxPos = existingSensors.reduce((max, s) => Math.max(max, s.pos), -1)
     const sensor: GuiTempgroupSensor = {
-        pos: 0,
+        pos: maxPos + 1,
         name: payload.sensorName,
         displayName: payload.displayName,
     }
📝 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
addSensorToGroup({ commit, dispatch }, payload: { id: string; sensorName: string; displayName?: string }) {
const sensor: GuiTempgroupSensor = {
pos: 0,
name: payload.sensorName,
displayName: payload.displayName,
}
commit('addSensorToGroup', { id: payload.id, sensor })
dispatch('groupUpload', payload.id)
},
addSensorToGroup({ commit, dispatch, state }, payload: { id: string; sensorName: string; displayName?: string }) {
const existingSensors = state.groups[payload.id]?.sensors ?? []
const maxPos = existingSensors.reduce((max, s) => Math.max(max, s.pos), -1)
const sensor: GuiTempgroupSensor = {
pos: maxPos + 1,
name: payload.sensorName,
displayName: payload.displayName,
}
commit('addSensorToGroup', { id: payload.id, sensor })
dispatch('groupUpload', payload.id)
},
🤖 Prompt for AI Agents
In `@src/store/gui/tempgroups/actions.ts` around lines 73 - 82, addSensorToGroup
currently creates a GuiTempgroupSensor with pos: 0 which causes duplicate
positions; instead, read the group's existing sensors from the action context
(use the destructured state or state.groups / groupStore equivalent) to compute
the next position as (max existing sensor.pos + 1) or 0 if none, set sensor.pos
to that computed nextPos before calling commit('addSensorToGroup', { id, sensor
}) and then dispatch('groupUpload', id); reference the addSensorToGroup action,
GuiTempgroupSensor shape, the 'addSensorToGroup' mutation and dispatch to
'groupUpload' when making the change.

Ragilo and others added 2 commits February 9, 2026 23:16
Adds validation to the debounced name update method to prevent
empty or duplicate names from being saved to the store.

Signed-off-by: Stefan Dej <meteyou@gmail.com>

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unnecessary await on synchronous commit call
- Use immutable pattern in mutations (spread instead of mutating payload)
- Fix TypeScript type for searchSensors (can be null from Vuetify clearable)

Signed-off-by: Stefan Dej <meteyou@gmail.com>

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown

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

🤖 Fix all issues with AI agents
In `@src/components/settings/SettingsTempgroupsTabEdit.vue`:
- Around line 184-187: The onGroupChanged watcher is overwriting the local
editing buffer (localGroupName) whenever the store's group object reference
changes; update it to only sync when the external name actually differs from the
local buffer (e.g., compare newVal?.name with this.localGroupName and return
without assigning if equal) or replace the watcher by initializing
localGroupName once from groupId (or in created/mounted) so subsequent store
mutations don't clobber in-flight edits; locate the watcher method
onGroupChanged and either add the name-equals check before setting
this.localGroupName or remove the watcher and seed localGroupName from the
groupId computed/prop on component mount.
🧹 Nitpick comments (4)
src/store/gui/tempgroups/mutations.ts (2)

75-93: removeSensorFromGroup directly mutates sensor objects in state, inconsistent with immutable pattern elsewhere.

Line 87 mutates s.pos on the original sensor references (the spread on line 78 is a shallow array copy, not a deep copy). Compare with updateSensorInGroup (line 66-69) and reorderSensorsInGroup (line 98), which both create new sensor objects via spread. Not a bug since we're inside a mutation, but for consistency with the stated intent ("Use immutable pattern in mutations"):

Suggested fix
-            sensors
-                .filter((s) => s.pos > oldPos)
-                .forEach((s) => {
-                    s.pos = s.pos - 1
-                })
+            const updatedSensors = sensors.map((s) =>
+                s.pos > oldPos ? { ...s, pos: s.pos - 1 } : s
+            )
+            sensors.splice(0, sensors.length, ...updatedSensors)

Or more simply, replace the entire block (lines 78–92) with a single immutable pipeline:

-            const sensors = [...(group.sensors ?? [])]
-            const deletedIndex = sensors.findIndex((s) => s.name === payload.sensorName)
-            if (deletedIndex !== -1) {
-                const oldPos = sensors[deletedIndex].pos
-                sensors.splice(deletedIndex, 1)
-
-                sensors
-                    .filter((s) => s.pos > oldPos)
-                    .forEach((s) => {
-                        s.pos = s.pos - 1
-                    })
-            }
-
-            Vue.set(state.groups[payload.id], 'sensors', sensors)
+            const target = (group.sensors ?? []).find((s) => s.name === payload.sensorName)
+            if (!target) return
+
+            const sensors = (group.sensors ?? [])
+                .filter((s) => s.name !== payload.sensorName)
+                .map((s) => (s.pos > target.pos ? { ...s, pos: s.pos - 1 } : { ...s }))
+
+            Vue.set(state.groups[payload.id], 'sensors', sensors)

103-109: Silent skip for unknown IDs could mask bugs.

If orderedIds contains an ID not present in state.groups, it's silently ignored. This is safe for now, but if groups are deleted concurrently (e.g., via another browser tab syncing to moonraker), the remaining groups could end up with non-contiguous or duplicate position values. Consider logging or filtering beforehand if this becomes an issue.

src/components/settings/SettingsTempgroupsTabEdit.vue (2)

270-286: existsGroupName is case-sensitive — intentional?

group.name === name means "Chamber" and "chamber" would both be allowed. If Klipper or the UI treats these as visually distinct that's fine, but it could confuse users. Worth a brief confirmation.


236-250: Use printer store getters instead of directly accessing state.

While there's no single getter that returns the combined list of heaters and sensors, the printer store exposes getAvailableHeaters and getAvailableSensors getters (at src/store/printer/getters.ts). Using these would decouple the component from the state shape and centralize the dedup logic. Alternatively, consider whether the tempgroups getUngroupedSensors getter (which already combines and deduplicates heaters + sensors) could be reused or adapted for this use case.

Comment on lines +184 to +187
@Watch('group', { immediate: true })
onGroupChanged(newVal: GuiTempgroup | null) {
this.localGroupName = newVal?.name ?? ''
}
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

onGroupChanged watcher resets localGroupName on any group mutation, discarding in-flight edits.

When the user types a new group name, localGroupName is updated and a 250ms debounce starts. If showChart (or anything else) is toggled before the debounce fires, the resulting groupUpdate dispatch replaces the store's group object → group computed returns a new reference → this watcher fires → localGroupName is overwritten with the old store name, losing the user's unsaved keystrokes.

Suggested fix — only sync when the name actually changed externally
 `@Watch`('group', { immediate: true })
 onGroupChanged(newVal: GuiTempgroup | null) {
-    this.localGroupName = newVal?.name ?? ''
+    const storeName = newVal?.name ?? ''
+    // Only overwrite localGroupName when the store name genuinely differs
+    // from what we last dispatched, to avoid clobbering in-flight edits
+    if (storeName !== this.localGroupName && storeName !== '') {
+        this.localGroupName = storeName
+    }
 }

A cleaner alternative is to drop this watcher entirely and seed localGroupName once in a @Watch('groupId', { immediate: true }) handler (or in created/mounted), so subsequent store-side mutations never interfere with the local editing buffer.

🤖 Prompt for AI Agents
In `@src/components/settings/SettingsTempgroupsTabEdit.vue` around lines 184 -
187, The onGroupChanged watcher is overwriting the local editing buffer
(localGroupName) whenever the store's group object reference changes; update it
to only sync when the external name actually differs from the local buffer
(e.g., compare newVal?.name with this.localGroupName and return without
assigning if equal) or replace the watcher by initializing localGroupName once
from groupId (or in created/mounted) so subsequent store mutations don't clobber
in-flight edits; locate the watcher method onGroupChanged and either add the
name-equals check before setting this.localGroupName or remove the watcher and
seed localGroupName from the groupId computed/prop on component mount.

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.

User organizable temperature tabs

1 participant