mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-27 16:54:04 +00:00
Fix: Filtering works with group monitors (again) (#3685)
* Fix: Group monitors use nested filtering * Chore: Fix lint
This commit is contained in:
parent
20a68a16f5
commit
81b84a3c53
2 changed files with 102 additions and 104 deletions
|
@ -51,11 +51,12 @@
|
||||||
v-for="(item, index) in sortedMonitorList"
|
v-for="(item, index) in sortedMonitorList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:monitor="item"
|
:monitor="item"
|
||||||
:showPathName="filtersActive"
|
|
||||||
:isSelectMode="selectMode"
|
:isSelectMode="selectMode"
|
||||||
:isSelected="isSelected"
|
:isSelected="isSelected"
|
||||||
:select="select"
|
:select="select"
|
||||||
:deselect="deselect"
|
:deselect="deselect"
|
||||||
|
:filter-func="filterFunc"
|
||||||
|
:sort-func="sortFunc"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,75 +127,16 @@ export default {
|
||||||
let result = Object.values(this.$root.monitorList);
|
let result = Object.values(this.$root.monitorList);
|
||||||
|
|
||||||
result = result.filter(monitor => {
|
result = result.filter(monitor => {
|
||||||
// filter by search text
|
// The root list does not show children
|
||||||
// finds monitor name, tag name or tag value
|
if (monitor.parent !== null) {
|
||||||
let searchTextMatch = true;
|
return false;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
// 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;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Filter result by active state, weight and alphabetical
|
result = result.filter(this.filterFunc);
|
||||||
result.sort((m1, m2) => {
|
|
||||||
if (m1.active !== m2.active) {
|
|
||||||
if (m1.active === false) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m2.active === false) {
|
result.sort(this.sortFunc);
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
@ -361,6 +303,85 @@ export default {
|
||||||
|
|
||||||
this.cancelSelectMode();
|
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>
|
</script>
|
||||||
|
@ -458,5 +479,4 @@ export default {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<span v-if="hasChildren" class="collapse-padding" @click.prevent="changeCollapsed">
|
<span v-if="hasChildren" class="collapse-padding" @click.prevent="changeCollapsed">
|
||||||
<font-awesome-icon icon="chevron-down" class="animated" :class="{ collapsed: isCollapsed}" />
|
<font-awesome-icon icon="chevron-down" class="animated" :class="{ collapsed: isCollapsed}" />
|
||||||
</span>
|
</span>
|
||||||
{{ monitorName }}
|
{{ monitor.name }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="monitor.tags.length > 0" class="tags">
|
<div v-if="monitor.tags.length > 0" class="tags">
|
||||||
<Tag v-for="tag in monitor.tags" :key="tag" :item="tag" :size="'sm'" />
|
<Tag v-for="tag in monitor.tags" :key="tag" :item="tag" :size="'sm'" />
|
||||||
|
@ -44,7 +44,6 @@
|
||||||
<MonitorListItem
|
<MonitorListItem
|
||||||
v-for="(item, index) in sortedChildMonitorList"
|
v-for="(item, index) in sortedChildMonitorList"
|
||||||
:key="index" :monitor="item"
|
:key="index" :monitor="item"
|
||||||
:showPathName="showPathName"
|
|
||||||
:isSelectMode="isSelectMode"
|
:isSelectMode="isSelectMode"
|
||||||
:isSelected="isSelected"
|
:isSelected="isSelected"
|
||||||
:select="select"
|
:select="select"
|
||||||
|
@ -75,11 +74,6 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
/** Should the monitor name show it's parent */
|
|
||||||
showPathName: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
/** If the user is in select mode */
|
/** If the user is in select mode */
|
||||||
isSelectMode: {
|
isSelectMode: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -105,6 +99,16 @@ export default {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
},
|
},
|
||||||
|
/** Function to filter child monitors */
|
||||||
|
filterFunc: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
/** Function to sort child monitors */
|
||||||
|
sortFunc: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -115,32 +119,13 @@ export default {
|
||||||
sortedChildMonitorList() {
|
sortedChildMonitorList() {
|
||||||
let result = Object.values(this.$root.monitorList);
|
let result = Object.values(this.$root.monitorList);
|
||||||
|
|
||||||
|
// Get children
|
||||||
result = result.filter(childMonitor => childMonitor.parent === this.monitor.id);
|
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) {
|
result.sort(this.sortFunc);
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
@ -152,13 +137,6 @@ export default {
|
||||||
marginLeft: `${31 * this.depth}px`,
|
marginLeft: `${31 * this.depth}px`,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
monitorName() {
|
|
||||||
if (this.showPathName) {
|
|
||||||
return this.monitor.pathName;
|
|
||||||
} else {
|
|
||||||
return this.monitor.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
isSelectMode() {
|
isSelectMode() {
|
||||||
|
|
Loading…
Reference in a new issue