diff --git a/src/components/MonitorList.vue b/src/components/MonitorList.vue
index ed354e3a0..6561f5a0a 100644
--- a/src/components/MonitorList.vue
+++ b/src/components/MonitorList.vue
@@ -35,7 +35,13 @@
:aria-label="selectAll ? $t('deselectAllMonitorsAria') : $t('selectAllMonitorsAria')"
/>
-
+
@@ -100,8 +106,8 @@
m.type === "group" && m.parent === null && monitors.some((child) => child.parent === m.id)
+ );
+ },
+
+ /**
+ * Determines if all groups are collapsed.
+ * Note: collapseKey is included to force re-computation when toggleCollapseAll()
+ * updates localStorage, since Vue cannot detect localStorage changes.
+ * @returns {boolean} True if all groups are collapsed
+ */
+ allGroupsCollapsed() {
+ // collapseKey forces this computed to re-evaluate after localStorage updates
+ if (this.collapseKey < 0 || this.groupMonitors.length === 0) {
+ return true;
+ }
+
+ const storage = window.localStorage.getItem("monitorCollapsed");
+ if (storage === null) {
+ return true; // Default is collapsed
+ }
+
+ const storageObject = JSON.parse(storage);
+ return this.groupMonitors.every((group) => storageObject[`monitor_${group.id}`] !== false);
+ },
},
watch: {
searchText() {
@@ -303,6 +342,26 @@ export default {
updateFilter(newFilter) {
this.filterState = newFilter;
},
+ /**
+ * Toggle collapse state for all group monitors
+ * @returns {void}
+ */
+ toggleCollapseAll() {
+ const shouldCollapse = !this.allGroupsCollapsed;
+
+ let storageObject = {};
+ const storage = window.localStorage.getItem("monitorCollapsed");
+ if (storage !== null) {
+ storageObject = JSON.parse(storage);
+ }
+
+ this.groupMonitors.forEach((group) => {
+ storageObject[`monitor_${group.id}`] = shouldCollapse;
+ });
+
+ window.localStorage.setItem("monitorCollapsed", JSON.stringify(storageObject));
+ this.collapseKey++;
+ },
/**
* Deselect a monitor
* @param {number} id ID of monitor
@@ -731,6 +790,7 @@ export default {
.search-input {
width: 100%;
padding-right: 30px;
+ transition: none !important;
}
.monitor-item {
diff --git a/src/components/MonitorListFilter.vue b/src/components/MonitorListFilter.vue
index 1635c3353..0a5a7b91c 100644
--- a/src/components/MonitorListFilter.vue
+++ b/src/components/MonitorListFilter.vue
@@ -137,6 +137,15 @@
+