| 1 | <template> |
| 2 | <div> |
| 3 | <CardEntity :loading :embedded hoverable clickable @click.stop="openDetails()"> |
| 4 | <template #headerMain>#{{ query.id }}</template> |
| 5 | <template #headerExtra> |
| 6 | <div class="flex items-center gap-2"> |
| 7 | <span>{{ query.active ? "Active" : "Inactive" }}</span> |
| 8 | <Icon v-if="query.active" :name="EnabledIcon" :size="14" class="text-success" /> |
| 9 | <Icon v-else :name="DisabledIcon" :size="14" class="text-secondary" /> |
| 10 | </div> |
| 11 | </template> |
| 12 | <template #default> |
| 13 | {{ query.rule_name }} |
| 14 | </template> |
| 15 | <template #footerMain> |
| 16 | <div class="flex flex-wrap items-center gap-3"> |
| 17 | <QueryTimeIntervalForm |
| 18 | v-slot="{ loading: loadingTimeInterval, togglePopup: toggleTimeIntervalPopup }" |
| 19 | :query |
| 20 | @updated="updateQuery($event)" |
| 21 | > |
| 22 | <Badge type="splitted" bright point-cursor @click.stop="toggleTimeIntervalPopup()"> |
| 23 | <template #iconLeft> |
| 24 | <n-spin |
| 25 | :size="12" |
| 26 | :show="loadingTimeInterval" |
| 27 | content-class="flex flex-col justify-center" |
| 28 | > |
| 29 | <Icon :name="TimeIntervalIcon" /> |
| 30 | </n-spin> |
| 31 | </template> |
| 32 | <template #label>Time Interval</template> |
| 33 | <template #value> |
| 34 | <div class="flex items-center gap-2"> |
| 35 | {{ query.time_interval || "n/d" }} |
| 36 | <Icon :name="EditIcon" :size="13" /> |
| 37 | </div> |
| 38 | </template> |
| 39 | </Badge> |
| 40 | </QueryTimeIntervalForm> |
| 41 | |
| 42 | <Badge type="splitted" bright fluid class="hidden! sm:flex!"> |
| 43 | <template #iconLeft> |
| 44 | <Icon :name="TimeIcon" /> |
| 45 | </template> |
| 46 | <template #label>Last execution time</template> |
| 47 | <template #value> |
| 48 | <div class="flex items-center gap-2"> |
| 49 | {{ |
| 50 | query.last_execution_time |
| 51 | ? formatDate(query.last_execution_time, dFormats.datetimesec) |
| 52 | : "n/d" |
| 53 | }} |
| 54 | </div> |
| 55 | </template> |
| 56 | </Badge> |
| 57 | </div> |
| 58 | </template> |
| 59 | |
| 60 | <template #footerExtra> |
| 61 | <QueryDeleteOne |
| 62 | v-slot="{ loading: loadingDelete, togglePopup: toggleDeletePopup }" |
| 63 | :query |
| 64 | @deleted="emit('deleted', query)" |
| 65 | > |
| 66 | <n-button quaternary size="tiny" :loading="loadingDelete" @click.stop="toggleDeletePopup()"> |
| 67 | Delete |
| 68 | </n-button> |
| 69 | </QueryDeleteOne> |
| 70 | </template> |
| 71 | </CardEntity> |
| 72 | |
| 73 | <n-modal |
| 74 | v-model:show="showDetails" |
| 75 | :style="{ maxWidth: 'min(850px, 90vw)', minHeight: 'min(480px, 90vh)', overflow: 'hidden' }" |
| 76 | display-directive="show" |
| 77 | > |
| 78 | <n-card |
| 79 | content-class="flex flex-col p-0!" |
| 80 | :title="`#${query.id}`" |
| 81 | closable |
| 82 | :bordered="false" |
| 83 | segmented |
| 84 | role="modal" |
| 85 | @close="closeDetails()" |
| 86 | > |
| 87 | <QueryDetails :query @deleted="emitDelete(query)" @updated="updateQuery($event)" /> |
| 88 | </n-card> |
| 89 | </n-modal> |
| 90 | </div> |
| 91 | </template> |
| 92 | |
| 93 | <script setup lang="ts"> |
| 94 | import type { SigmaQuery } from "@/types/sigma.d" |
| 95 | import { NButton, NCard, NModal, NSpin } from "naive-ui" |
| 96 | import { ref, toRefs } from "vue" |
| 97 | import Badge from "@/components/common/Badge.vue" |
| 98 | import CardEntity from "@/components/common/cards/CardEntity.vue" |
| 99 | import Icon from "@/components/common/Icon.vue" |
| 100 | import { useSettingsStore } from "@/stores/settings" |
| 101 | import { formatDate } from "@/utils/format" |
| 102 | import QueryDeleteOne from "./actionsProviders/QueryDeleteOne.vue" |
| 103 | import QueryTimeIntervalForm from "./actionsProviders/QueryTimeIntervalForm.vue" |
| 104 | import QueryDetails from "./QueryDetails.vue" |
| 105 | |
| 106 | const props = defineProps<{ |
| 107 | query: SigmaQuery |
| 108 | embedded?: boolean |
| 109 | }>() |
| 110 | |
| 111 | const emit = defineEmits<{ |
| 112 | (e: "deleted", value: SigmaQuery): void |
| 113 | (e: "updated", value: SigmaQuery): void |
| 114 | }>() |
| 115 | |
| 116 | const { query, embedded } = toRefs(props) |
| 117 | |
| 118 | const TimeIcon = "carbon:time" |
| 119 | const EditIcon = "uil:edit-alt" |
| 120 | const EnabledIcon = "carbon:circle-solid" |
| 121 | const DisabledIcon = "carbon:subtract-alt" |
| 122 | const TimeIntervalIcon = "material-symbols:autoplay" |
| 123 | |
| 124 | const loading = ref(false) |
| 125 | const showDetails = ref(false) |
| 126 | const dFormats = useSettingsStore().dateFormat |
| 127 | |
| 128 | function updateQuery(updatedQuery: SigmaQuery) { |
| 129 | emit("updated", updatedQuery) |
| 130 | } |
| 131 | |
| 132 | function emitDelete(updatedQuery: SigmaQuery) { |
| 133 | closeDetails() |
| 134 | emit("deleted", updatedQuery) |
| 135 | } |
| 136 | |
| 137 | function openDetails() { |
| 138 | showDetails.value = true |
| 139 | } |
| 140 | |
| 141 | function closeDetails() { |
| 142 | showDetails.value = false |
| 143 | } |
| 144 | </script> |