Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/dispatch/static/dispatch/src/signal/InstanceEntityPopover.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<div>
<v-menu v-model="menu" origin="overlap">
<template #activator="{ props }">
<v-chip v-bind="props">
{{ value.length }} <v-icon class="pl-2">mdi-cube-outline</v-icon>
</v-chip>
</template>
<v-card v-if="value.length > 0" max-width="600px" class="pb-4">
<v-list-dark v-bind="props">
<v-list-item>
<v-list-item-title>Entities</v-list-item-title>
<template #append>
<v-btn icon variant="text" @click="menu = false">
<v-icon>mdi-close-circle</v-icon>
</v-btn>
</template>
</v-list-item>
<v-list-item v-for="entity in value" :key="`${entity.entity_type.name}-${entity.value}`">
<h5>{{ entity.entity_type.name }}</h5>
{{ entity.value }}
</v-list-item>
</v-list-dark>
</v-card>
</v-menu>
</div>
</template>

<script>
export default {
name: "InstanceEntityPopover",

data: () => ({
menu: false,
}),

setup() {},

props: {
value: {
type: Object,
default: function () {
return {}
},
},
},
}
</script>
170 changes: 98 additions & 72 deletions src/dispatch/static/dispatch/src/signal/TableInstance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,77 +8,77 @@
<table-filter-dialog />
</v-col>
</v-row>
<v-row no-gutters>
<v-col>
<v-card variant="flat">
<!-- <v-card-title> -->
<!-- <v-text-field -->
<!-- v-model="q" -->
<!-- append-icon="search" -->
<!-- label="Search" -->
<!-- single-line -->
<!-- hide-details -->
<!-- clearable -->
<!-- /> -->
<!-- </v-card-title> -->
<v-data-table-server
:headers="headers"
:items="items"
:items-length="total || 0"
v-model:page="page"
v-model:items-per-page="itemsPerPage"
:footer-props="{
'items-per-page-options': [10, 25, 50, 100],
}"
v-model:sort-by="sortBy"
v-model:sort-desc="descending"
:loading="loading"
loading-text="Loading... Please wait"
>
<template #item.case="{ value }">
<case-popover v-if="value" :value="value" />
</template>
<template #item.signal="{ value }">
<signal-popover :value="value" />
</template>
<template #item.signal.project.display_name="{ item, value }">
<v-chip size="small" :color="item.signal.project.color">
{{ value }}
</v-chip>
</template>
<template #item.filter_action="{ value }">
<v-chip
size="small"
:color="
{
snooze: 'blue-accent-4',
deduplicate: 'blue-accent-2',
}[value]
"
>
{{
{
snooze: "Snoozed",
deduplicate: "Duplicate",
}[value] || "Not Filtered"
}}
</v-chip>
</template>
<template #item.created_at="{ value }">
<v-tooltip location="bottom">
<template #activator="{ props }">
<span v-bind="props">{{ formatRelativeDate(value) }}</span>
</template>
<span>{{ formatDate(value) }}</span>
</v-tooltip>
</template>
<template #item.data-table-actions="{ item }">
<raw-signal-viewer :value="item.raw" />
</template>
</v-data-table-server>
</v-card>
</v-col>
</v-row>
<v-data-table-server
:headers="headers"
:items="items"
:items-length="total || 0"
v-model:page="page"
v-model:items-per-page="itemsPerPage"
:footer-props="{
'items-per-page-options': [10, 25, 50, 100],
}"
v-model:sort-by="sortBy"
v-model:sort-desc="descending"
:loading="loading"
loading-text="Loading... Please wait"
>
<template #item.case="{ value }">
<case-popover v-if="value" :value="value" />
</template>
<template #item.signal="{ value }">
<signal-popover :value="value" />
</template>
<template #item.entities="{ value }">
<instance-entity-popover :value="value" />
</template>
<template #item.signal.filters="{ value }">
<span
v-if="
this.getSnoozes(value) === 0 && this.getSnoozes(value, (count_expired = true)) === 0
"
>
No Snoozes Created
</span>
<span v-else>
<v-chip>{{ this.getSnoozes(value) }} Active</v-chip>
<v-chip>{{ this.getSnoozes(value, (count_expired = true)) }} Expired</v-chip>
</span>
</template>
<template #item.signal.project.display_name="{ item, value }">
<v-chip size="small" :color="item.signal.project.color">
{{ value }}
</v-chip>
</template>
<template #item.filter_action="{ value }">
<v-chip
size="small"
:color="
{
snooze: 'blue-accent-4',
deduplicate: 'orange-darken-2',
}[value] || 'green-darken-1'
"
>
{{
{
snooze: "Snoozed",
deduplicate: "Duplicate",
}[value] || "Not Filtered"
}}
</v-chip>
</template>
<template #item.created_at="{ value }">
<v-tooltip location="bottom">
<template #activator="{ props }">
<span v-bind="props">{{ formatRelativeDate(value) }}</span>
</template>
<span>{{ formatDate(value) }}</span>
</v-tooltip>
</template>
<template #item.data-table-actions="{ item }">
<raw-signal-viewer :value="item.raw" />
</template>
</v-data-table-server>
</v-container>
</template>

Expand All @@ -92,6 +92,7 @@ import RawSignalViewer from "@/signal/RawSignalViewer.vue"
import RouterUtils from "@/router/utils"
import SignalPopover from "@/signal/SignalPopover.vue"
import TableFilterDialog from "@/signal/TableFilterDialog.vue"
import InstanceEntityPopover from "@/signal/InstanceEntityPopover.vue"

export default {
name: "SignalInstanceTable",
Expand All @@ -101,14 +102,18 @@ export default {
RawSignalViewer,
SignalPopover,
TableFilterDialog,
InstanceEntityPopover,
},

data() {
return {
activeView: "triggers",
headers: [
{ title: "Case", value: "case", sortable: false },
{ title: "Status", value: "filter_action", sortable: true },
{ title: "Signal Definition", value: "signal", sortable: false },
{ title: "Filter Action", value: "filter_action", sortable: true },
{ title: "Entities", value: "entities", sortable: true },
{ title: "Snoozes", value: "signal.filters", sortable: false },
{ title: "Project", value: "signal.project.display_name", sortable: true },
{ title: "Created At", value: "created_at" },
{ title: "", value: "data-table-actions", sortable: false, align: "end" },
Expand Down Expand Up @@ -149,6 +154,27 @@ export default {

methods: {
...mapActions("signal", ["getAllInstances"]),

/**
* Count the snooze filters for a given signal definition. Counts all
* active snoozes by default, with the option to count expired snoozes instead.
* @param signal_filters: The definition's filters.
* @param count_expired: If true, count expired snoozes instead of active ones.
*/
getSnoozes(signal_filters, count_expired = false) {
let snoozes = 0
for (let filter of signal_filters) {
if (filter.action === "snooze") {
let filter_is_expired = filter.expiration && new Date() >= new Date(filter.expiration)
if (!count_expired && !filter_is_expired) {
snoozes++
} else if (count_expired && filter_is_expired) {
Comment thread
whitdog47 marked this conversation as resolved.
snoozes++
}
}
}
return snoozes
},
},

created() {
Expand Down
Loading