| 1 | <template> |
| 2 | <div class="pipe-details flex flex-wrap justify-between gap-1"> |
| 3 | <div class="flex w-full flex-wrap items-center justify-between gap-2"> |
| 4 | <p v-if="pipeline.description"> |
| 5 | {{ pipeline.description }} |
| 6 | </p> |
| 7 | |
| 8 | <div class="text-secondary text-right font-mono text-sm"> |
| 9 | {{ formatDate(pipeline.modified_at, dFormats.datetimesec) }} |
| 10 | </div> |
| 11 | </div> |
| 12 | </div> |
| 13 | |
| 14 | <n-scrollbar x-scrollable trigger="none" class="mt-5"> |
| 15 | <n-timeline horizontal size="large" style="width: max-content" class="mb-4"> |
| 16 | <n-timeline-item |
| 17 | v-for="stage of stages" |
| 18 | :key="stage.stage" |
| 19 | :type="stage.match === 'EITHER' ? undefined : 'info'" |
| 20 | :title="`Stage ${stage.stage}`" |
| 21 | > |
| 22 | <p class="mb-1"> |
| 23 | {{ stage.match }} |
| 24 | </p> |
| 25 | <n-popover trigger="click" style="max-height: 240px" scrollable placement="bottom"> |
| 26 | <template #trigger> |
| 27 | <n-button size="tiny"> |
| 28 | <template #icon> |
| 29 | <Icon :name="RulesIcon" :size="18" /> |
| 30 | </template> |
| 31 | Rules |
| 32 | <span class="text-secondary ml-2 font-mono">{{ stage.rules.length }}</span> |
| 33 | </n-button> |
| 34 | </template> |
| 35 | |
| 36 | <RulesSmallList :rules="stage.rules" style="margin: 0 -10px" @click="emit('clickRule', $event)" /> |
| 37 | </n-popover> |
| 38 | </n-timeline-item> |
| 39 | </n-timeline> |
| 40 | </n-scrollbar> |
| 41 | </template> |
| 42 | |
| 43 | <script setup lang="ts"> |
| 44 | // TODO-FE: refactor |
| 45 | import type { RuleExtended } from "./RulesSmallList.vue" |
| 46 | import type { PipelineFull, PipelineFullStage } from "@/types/graylog/pipelines.d" |
| 47 | import { NButton, NPopover, NScrollbar, NTimeline, NTimelineItem } from "naive-ui" |
| 48 | import { computed, toRefs } from "vue" |
| 49 | import Icon from "@/components/common/Icon.vue" |
| 50 | import { useSettingsStore } from "@/stores/settings" |
| 51 | import { formatDate } from "@/utils/format" |
| 52 | import RulesSmallList from "./RulesSmallList.vue" |
| 53 | |
| 54 | interface PipelineFullStageExt extends Omit<PipelineFullStage, "rules" | "rule_ids"> { |
| 55 | rules: RuleExtended[] |
| 56 | } |
| 57 | |
| 58 | const props = defineProps<{ pipeline: PipelineFull }>() |
| 59 | |
| 60 | const emit = defineEmits<{ |
| 61 | (e: "clickRule", value: string): void |
| 62 | }>() |
| 63 | |
| 64 | const { pipeline } = toRefs(props) |
| 65 | |
| 66 | const RulesIcon = "ic:outline-swipe-right-alt" |
| 67 | |
| 68 | const dFormats = useSettingsStore().dateFormat |
| 69 | |
| 70 | function sanitizeStage(stage: PipelineFullStage): PipelineFullStageExt { |
| 71 | const rules: RuleExtended[] = [] |
| 72 | |
| 73 | for (const i in stage.rules) { |
| 74 | rules.push({ |
| 75 | title: stage.rules[i] ?? "", |
| 76 | id: stage.rule_ids[i] ?? "" |
| 77 | }) |
| 78 | } |
| 79 | |
| 80 | const stageExt: PipelineFullStageExt = { |
| 81 | rules, |
| 82 | match: stage.match, |
| 83 | stage: stage.stage |
| 84 | } |
| 85 | |
| 86 | return stageExt |
| 87 | } |
| 88 | |
| 89 | const stages = computed<PipelineFullStageExt[]>(() => { |
| 90 | const stages: PipelineFullStageExt[] = [] |
| 91 | |
| 92 | for (const stage of pipeline.value.stages) { |
| 93 | stages.push(sanitizeStage(stage)) |
| 94 | } |
| 95 | |
| 96 | return stages |
| 97 | }) |
| 98 | </script> |