mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-10-31 11:29:20 +08:00 
			
		
		
		
	Fix: Filtering works with group monitors (again) (#3685)
* Fix: Group monitors use nested filtering * Chore: Fix lint
This commit is contained in:
		| @@ -51,11 +51,12 @@ | ||||
|                 v-for="(item, index) in sortedMonitorList" | ||||
|                 :key="index" | ||||
|                 :monitor="item" | ||||
|                 :showPathName="filtersActive" | ||||
|                 :isSelectMode="selectMode" | ||||
|                 :isSelected="isSelected" | ||||
|                 :select="select" | ||||
|                 :deselect="deselect" | ||||
|                 :filter-func="filterFunc" | ||||
|                 :sort-func="sortFunc" | ||||
|             /> | ||||
|         </div> | ||||
|     </div> | ||||
| @@ -126,75 +127,16 @@ export default { | ||||
|             let result = Object.values(this.$root.monitorList); | ||||
|  | ||||
|             result = result.filter(monitor => { | ||||
|                 // filter by search text | ||||
|                 // finds monitor name, tag name or tag value | ||||
|                 let searchTextMatch = true; | ||||
|                 if (this.searchText !== "") { | ||||
|                     const loweredSearchText = this.searchText.toLowerCase(); | ||||
|                     searchTextMatch = | ||||
|                         monitor.name.toLowerCase().includes(loweredSearchText) | ||||
|                         || monitor.tags.find(tag => tag.name.toLowerCase().includes(loweredSearchText) | ||||
|                             || tag.value?.toLowerCase().includes(loweredSearchText)); | ||||
|                 // The root list does not show children | ||||
|                 if (monitor.parent !== null) { | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 // filter by status | ||||
|                 let statusMatch = true; | ||||
|                 if (this.filterState.status != null && this.filterState.status.length > 0) { | ||||
|                     if (monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[monitor.id]) { | ||||
|                         monitor.status = this.$root.lastHeartbeatList[monitor.id].status; | ||||
|                     } | ||||
|                     statusMatch = this.filterState.status.includes(monitor.status); | ||||
|                 } | ||||
|  | ||||
|                 // filter by active | ||||
|                 let activeMatch = true; | ||||
|                 if (this.filterState.active != null && this.filterState.active.length > 0) { | ||||
|                     activeMatch = this.filterState.active.includes(monitor.active); | ||||
|                 } | ||||
|  | ||||
|                 // filter by tags | ||||
|                 let tagsMatch = true; | ||||
|                 if (this.filterState.tags != null && this.filterState.tags.length > 0) { | ||||
|                     tagsMatch = monitor.tags.map(tag => tag.tag_id) // convert to array of tag IDs | ||||
|                         .filter(monitorTagId => this.filterState.tags.includes(monitorTagId)) // perform Array Intersaction between filter and monitor's tags | ||||
|                         .length > 0; | ||||
|                 } | ||||
|  | ||||
|                 // Hide children if not filtering | ||||
|                 let showChild = true; | ||||
|                 if (this.filterState.status == null && this.filterState.active == null && this.filterState.tags == null && this.searchText === "") { | ||||
|                     if (monitor.parent !== null) { | ||||
|                         showChild = false; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 return searchTextMatch && statusMatch && activeMatch && tagsMatch && showChild; | ||||
|                 return true; | ||||
|             }); | ||||
|  | ||||
|             // Filter result by active state, weight and alphabetical | ||||
|             result.sort((m1, m2) => { | ||||
|                 if (m1.active !== m2.active) { | ||||
|                     if (m1.active === false) { | ||||
|                         return 1; | ||||
|                     } | ||||
|             result = result.filter(this.filterFunc); | ||||
|  | ||||
|                     if (m2.active === false) { | ||||
|                         return -1; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (m1.weight !== m2.weight) { | ||||
|                     if (m1.weight > m2.weight) { | ||||
|                         return -1; | ||||
|                     } | ||||
|  | ||||
|                     if (m1.weight < m2.weight) { | ||||
|                         return 1; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 return m1.name.localeCompare(m2.name); | ||||
|             }); | ||||
|             result.sort(this.sortFunc); | ||||
|  | ||||
|             return result; | ||||
|         }, | ||||
| @@ -361,6 +303,85 @@ export default { | ||||
|  | ||||
|             this.cancelSelectMode(); | ||||
|         }, | ||||
|         /** | ||||
|          * Whether a monitor should be displayed based on the filters | ||||
|          * @param {object} monitor Monitor to check | ||||
|          * @returns {boolean} Should the monitor be displayed | ||||
|          */ | ||||
|         filterFunc(monitor) { | ||||
|             // Group monitors bypass filter if at least 1 of children matched | ||||
|             if (monitor.type === "group") { | ||||
|                 const children = Object.values(this.$root.monitorList).filter(m => m.parent === monitor.id); | ||||
|                 if (children.some((child, index, children) => this.filterFunc(child))) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // filter by search text | ||||
|             // finds monitor name, tag name or tag value | ||||
|             let searchTextMatch = true; | ||||
|             if (this.searchText !== "") { | ||||
|                 const loweredSearchText = this.searchText.toLowerCase(); | ||||
|                 searchTextMatch = | ||||
|                     monitor.name.toLowerCase().includes(loweredSearchText) | ||||
|                     || monitor.tags.find(tag => tag.name.toLowerCase().includes(loweredSearchText) | ||||
|                         || tag.value?.toLowerCase().includes(loweredSearchText)); | ||||
|             } | ||||
|  | ||||
|             // filter by status | ||||
|             let statusMatch = true; | ||||
|             if (this.filterState.status != null && this.filterState.status.length > 0) { | ||||
|                 if (monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[monitor.id]) { | ||||
|                     monitor.status = this.$root.lastHeartbeatList[monitor.id].status; | ||||
|                 } | ||||
|                 statusMatch = this.filterState.status.includes(monitor.status); | ||||
|             } | ||||
|  | ||||
|             // filter by active | ||||
|             let activeMatch = true; | ||||
|             if (this.filterState.active != null && this.filterState.active.length > 0) { | ||||
|                 activeMatch = this.filterState.active.includes(monitor.active); | ||||
|             } | ||||
|  | ||||
|             // filter by tags | ||||
|             let tagsMatch = true; | ||||
|             if (this.filterState.tags != null && this.filterState.tags.length > 0) { | ||||
|                 tagsMatch = monitor.tags.map(tag => tag.tag_id) // convert to array of tag IDs | ||||
|                     .filter(monitorTagId => this.filterState.tags.includes(monitorTagId)) // perform Array Intersaction between filter and monitor's tags | ||||
|                     .length > 0; | ||||
|             } | ||||
|  | ||||
|             return searchTextMatch && statusMatch && activeMatch && tagsMatch; | ||||
|         }, | ||||
|         /** | ||||
|          * Function used in Array.sort to order monitors in a list. | ||||
|          * @param {*} m1 monitor 1 | ||||
|          * @param {*} m2 monitor 2 | ||||
|          * @returns {number} -1, 0 or 1 | ||||
|          */ | ||||
|         sortFunc(m1, m2) { | ||||
|             if (m1.active !== m2.active) { | ||||
|                 if (m1.active === false) { | ||||
|                     return 1; | ||||
|                 } | ||||
|  | ||||
|                 if (m2.active === false) { | ||||
|                     return -1; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (m1.weight !== m2.weight) { | ||||
|                 if (m1.weight > m2.weight) { | ||||
|                     return -1; | ||||
|                 } | ||||
|  | ||||
|                 if (m1.weight < m2.weight) { | ||||
|                     return 1; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return m1.name.localeCompare(m2.name); | ||||
|         } | ||||
|     }, | ||||
| }; | ||||
| </script> | ||||
| @@ -458,5 +479,4 @@ export default { | ||||
|     align-items: center; | ||||
|     gap: 10px; | ||||
| } | ||||
|  | ||||
| </style> | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|                             <span v-if="hasChildren" class="collapse-padding" @click.prevent="changeCollapsed"> | ||||
|                                 <font-awesome-icon icon="chevron-down" class="animated" :class="{ collapsed: isCollapsed}" /> | ||||
|                             </span> | ||||
|                             {{ monitorName }} | ||||
|                             {{ monitor.name }} | ||||
|                         </div> | ||||
|                         <div v-if="monitor.tags.length > 0" class="tags"> | ||||
|                             <Tag v-for="tag in monitor.tags" :key="tag" :item="tag" :size="'sm'" /> | ||||
| @@ -44,7 +44,6 @@ | ||||
|                 <MonitorListItem | ||||
|                     v-for="(item, index) in sortedChildMonitorList" | ||||
|                     :key="index" :monitor="item" | ||||
|                     :showPathName="showPathName" | ||||
|                     :isSelectMode="isSelectMode" | ||||
|                     :isSelected="isSelected" | ||||
|                     :select="select" | ||||
| @@ -75,11 +74,6 @@ export default { | ||||
|             type: Object, | ||||
|             default: null, | ||||
|         }, | ||||
|         /** Should the monitor name show it's parent */ | ||||
|         showPathName: { | ||||
|             type: Boolean, | ||||
|             default: false, | ||||
|         }, | ||||
|         /** If the user is in select mode */ | ||||
|         isSelectMode: { | ||||
|             type: Boolean, | ||||
| @@ -105,6 +99,16 @@ export default { | ||||
|             type: Function, | ||||
|             default: () => {} | ||||
|         }, | ||||
|         /** Function to filter child monitors */ | ||||
|         filterFunc: { | ||||
|             type: Function, | ||||
|             default: () => {} | ||||
|         }, | ||||
|         /** Function to sort child monitors */ | ||||
|         sortFunc: { | ||||
|             type: Function, | ||||
|             default: () => {}, | ||||
|         } | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
| @@ -115,32 +119,13 @@ export default { | ||||
|         sortedChildMonitorList() { | ||||
|             let result = Object.values(this.$root.monitorList); | ||||
|  | ||||
|             // Get children | ||||
|             result = result.filter(childMonitor => childMonitor.parent === this.monitor.id); | ||||
|  | ||||
|             result.sort((m1, m2) => { | ||||
|             // Run filter on children | ||||
|             result = result.filter(this.filterFunc); | ||||
|  | ||||
|                 if (m1.active !== m2.active) { | ||||
|                     if (m1.active === 0) { | ||||
|                         return 1; | ||||
|                     } | ||||
|  | ||||
|                     if (m2.active === 0) { | ||||
|                         return -1; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (m1.weight !== m2.weight) { | ||||
|                     if (m1.weight > m2.weight) { | ||||
|                         return -1; | ||||
|                     } | ||||
|  | ||||
|                     if (m1.weight < m2.weight) { | ||||
|                         return 1; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 return m1.name.localeCompare(m2.name); | ||||
|             }); | ||||
|             result.sort(this.sortFunc); | ||||
|  | ||||
|             return result; | ||||
|         }, | ||||
| @@ -152,13 +137,6 @@ export default { | ||||
|                 marginLeft: `${31 * this.depth}px`, | ||||
|             }; | ||||
|         }, | ||||
|         monitorName() { | ||||
|             if (this.showPathName) { | ||||
|                 return this.monitor.pathName; | ||||
|             } else { | ||||
|                 return this.monitor.name; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     watch: { | ||||
|         isSelectMode() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user