| 1 | <template> |
| 2 | <div> |
| 3 | <CardEntity hoverable :embedded> |
| 4 | <template #headerMain> |
| 5 | <div class="flex items-center gap-2"> |
| 6 | <Icon :name="UserIcon" :size="14" /> |
| 7 | {{ input.creator_user_id }} |
| 8 | </div> |
| 9 | </template> |
| 10 | <template #headerExtra>{{ formatDateTime(input.created_at) }}</template> |
| 11 | <template #default> |
| 12 | <div class="flex flex-col gap-1"> |
| 13 | {{ input.title }} |
| 14 | <p> |
| 15 | {{ input.name }} |
| 16 | </p> |
| 17 | </div> |
| 18 | </template> |
| 19 | <template #footerMain> |
| 20 | <div class="flex flex-wrap items-center gap-3"> |
| 21 | <Badge :type="input.global ? 'active' : 'muted'"> |
| 22 | <template #iconRight> |
| 23 | <Icon :name="input.global ? GlobalIcon : DisabledIcon" :size="14" /> |
| 24 | </template> |
| 25 | <template #label>Global</template> |
| 26 | </Badge> |
| 27 | <n-tooltip trigger="hover" :disabled="!isRunning"> |
| 28 | <template #trigger> |
| 29 | <Badge :type="isRunning ? 'active' : 'muted'" :hint-cursor="isRunning"> |
| 30 | <template #iconRight> |
| 31 | <Icon :name="isRunning ? TimeIcon : DisabledIcon" :size="14" /> |
| 32 | </template> |
| 33 | <template #label>Running</template> |
| 34 | </Badge> |
| 35 | </template> |
| 36 | {{ formatDateTime(input.started_at) }} |
| 37 | </n-tooltip> |
| 38 | </div> |
| 39 | </template> |
| 40 | <template #footerExtra> |
| 41 | <div class="flex flex-wrap items-center justify-end gap-3"> |
| 42 | <n-button size="small" @click.stop="showDetails = true"> |
| 43 | <template #icon> |
| 44 | <Icon :name="InfoIcon" /> |
| 45 | </template> |
| 46 | Details |
| 47 | </n-button> |
| 48 | <n-button v-if="isRunning" :loading type="warning" size="small" secondary @click="stop()"> |
| 49 | <template #icon> |
| 50 | <Icon :name="StopIcon" /> |
| 51 | </template> |
| 52 | Stop input |
| 53 | </n-button> |
| 54 | <n-button v-else :loading type="success" secondary size="small" @click="start()"> |
| 55 | <template #icon> |
| 56 | <Icon :name="StartIcon" /> |
| 57 | </template> |
| 58 | Start input |
| 59 | </n-button> |
| 60 | </div> |
| 61 | </template> |
| 62 | </CardEntity> |
| 63 | |
| 64 | <n-modal |
| 65 | v-model:show="showDetails" |
| 66 | preset="card" |
| 67 | content-class="p-0!" |
| 68 | :style="{ maxWidth: 'min(600px, 90vw)', overflow: 'hidden' }" |
| 69 | :title="input.title" |
| 70 | :bordered="false" |
| 71 | segmented |
| 72 | > |
| 73 | <n-tabs type="line" animated :tabs-padding="24"> |
| 74 | <n-tab-pane name="info" tab="Info" display-directive="show:lazy"> |
| 75 | <div class="p-6 pt-3"> |
| 76 | <div class="mb-2"> |
| 77 | Id : |
| 78 | <code>{{ input.id }}</code> |
| 79 | </div> |
| 80 | <div class="mb-2"> |
| 81 | Node : |
| 82 | <code>{{ input.node }}</code> |
| 83 | </div> |
| 84 | <div class="mb-2"> |
| 85 | Type : |
| 86 | <code>{{ input.type }}</code> |
| 87 | </div> |
| 88 | <div class="mb-2"> |
| 89 | Content pack : |
| 90 | <code>{{ input.content_pack || "-" }}</code> |
| 91 | </div> |
| 92 | <div class="mb-2">Static fields :</div> |
| 93 | <SimpleJsonViewer |
| 94 | class="vuesjv-override" |
| 95 | :model-value="input.static_fields" |
| 96 | :initial-expanded-depth="1" |
| 97 | /> |
| 98 | </div> |
| 99 | </n-tab-pane> |
| 100 | <n-tab-pane name="attributes" tab="Attributes" display-directive="show:lazy"> |
| 101 | <div class="p-6 pt-3"> |
| 102 | <SimpleJsonViewer |
| 103 | class="vuesjv-override" |
| 104 | :model-value="input.attributes" |
| 105 | :initial-expanded-depth="1" |
| 106 | /> |
| 107 | </div> |
| 108 | </n-tab-pane> |
| 109 | </n-tabs> |
| 110 | </n-modal> |
| 111 | </div> |
| 112 | </template> |
| 113 | |
| 114 | <script setup lang="ts"> |
| 115 | import type { InputExtended } from "@/types/graylog/inputs.d" |
| 116 | import { NButton, NModal, NTabPane, NTabs, NTooltip, useMessage } from "naive-ui" |
| 117 | import { computed, ref } from "vue" |
| 118 | import { SimpleJsonViewer } from "vue-sjv" |
| 119 | import Api from "@/api" |
| 120 | import Badge from "@/components/common/Badge.vue" |
| 121 | import CardEntity from "@/components/common/cards/CardEntity.vue" |
| 122 | import Icon from "@/components/common/Icon.vue" |
| 123 | import { useSettingsStore } from "@/stores/settings" |
| 124 | import { formatDate } from "@/utils/format" |
| 125 | import "@/assets/scss/overrides/vuesjv-override.scss" |
| 126 | |
| 127 | const { input, embedded } = defineProps<{ input: InputExtended; embedded?: boolean }>() |
| 128 | |
| 129 | const emit = defineEmits<{ |
| 130 | (e: "updated"): void |
| 131 | }>() |
| 132 | |
| 133 | const UserIcon = "carbon:user" |
| 134 | const InfoIcon = "carbon:information" |
| 135 | const DisabledIcon = "carbon:subtract" |
| 136 | const TimeIcon = "carbon:time" |
| 137 | const GlobalIcon = "ph:globe-light" |
| 138 | const StopIcon = "carbon:stop" |
| 139 | const StartIcon = "carbon:play" |
| 140 | |
| 141 | const message = useMessage() |
| 142 | const loading = ref(false) |
| 143 | const showDetails = ref(false) |
| 144 | const isRunning = computed(() => input?.state === "RUNNING") |
| 145 | const dFormats = useSettingsStore().dateFormat |
| 146 | |
| 147 | function formatDateTime(timestamp: string): string { |
| 148 | return formatDate(timestamp, dFormats.datetimesec).toString() |
| 149 | } |
| 150 | |
| 151 | function stop() { |
| 152 | loading.value = true |
| 153 | |
| 154 | Api.graylog |
| 155 | .stopInput(input.id) |
| 156 | .then(res => { |
| 157 | if (res.data.success) { |
| 158 | emit("updated") |
| 159 | message.success(res.data?.message || "Successfully stopped input.") |
| 160 | } else { |
| 161 | message.warning(res.data?.message || "An error occurred. Please try again later.") |
| 162 | } |
| 163 | }) |
| 164 | .catch(err => { |
| 165 | message.error(err.response?.data?.message || "An error occurred. Please try again later.") |
| 166 | }) |
| 167 | .finally(() => { |
| 168 | loading.value = false |
| 169 | }) |
| 170 | } |
| 171 | |
| 172 | function start() { |
| 173 | loading.value = true |
| 174 | |
| 175 | Api.graylog |
| 176 | .startInput(input.id) |
| 177 | .then(res => { |
| 178 | if (res.data.success) { |
| 179 | emit("updated") |
| 180 | message.success(res.data?.message || "Successfully started input.") |
| 181 | } else { |
| 182 | message.warning(res.data?.message || "An error occurred. Please try again later.") |
| 183 | } |
| 184 | }) |
| 185 | .catch(err => { |
| 186 | message.error(err.response?.data?.message || "An error occurred. Please try again later.") |
| 187 | }) |
| 188 | .finally(() => { |
| 189 | loading.value = false |
| 190 | }) |
| 191 | } |
| 192 | </script> |