main
vue 110 lines 3.05 KB
Raw
1 <template>
2 <div class="available-reports-list">
3 <div class="header mb-3 flex items-center justify-end gap-2">
4 <div class="info flex grow gap-5">
5 <n-popover overlap placement="bottom-start">
6 <template #trigger>
7 <div class="bg-default rounded-lg">
8 <n-button size="small" class="cursor-help!">
9 <template #icon>
10 <Icon :name="InfoIcon" />
11 </template>
12 </n-button>
13 </div>
14 </template>
15 <div class="flex flex-col gap-2">
16 <div class="box">
17 Total reports:
18 <code>{{ totalReports }}</code>
19 </div>
20 </div>
21 </n-popover>
22 </div>
23 <div class="actions flex items-center gap-2">
24 <n-button size="small" type="primary" @click="showForm = true">
25 <template #icon>
26 <Icon :name="NewReportIcon" :size="15" />
27 </template>
28 Create new Report
29 </n-button>
30 </div>
31 </div>
32 <n-spin :show="loading" class="min-h-32">
33 <template v-if="reportsList.length">
34 <div class="list grid-auto-fill-250 grid gap-4">
35 <AvailableReportsItem
36 v-for="report of reportsList"
37 :key="report"
38 :report
39 class="item-appear item-appear-bottom item-appear-005"
40 @deleted="getReports()"
41 />
42 </div>
43 </template>
44 <template v-else>
45 <n-empty v-if="!loading" description="No items found" class="h-48 justify-center" />
46 </template>
47 </n-spin>
48
49 <n-modal
50 v-model:show="showForm"
51 display-directive="show"
52 preset="card"
53 :style="{ maxWidth: 'min(600px, 90vw)', minHeight: 'min(270px, 90vh)', overflow: 'hidden' }"
54 title="Generate Report"
55 :bordered="false"
56 segmented
57 >
58 <CreationReportForm @submitted="getReports()" @mounted="formCTX = $event" />
59 </n-modal>
60 </div>
61 </template>
62
63 <script setup lang="ts">
64 import type { ScoutSuiteReport } from "@/types/cloudSecurityAssessment.d"
65 import { NButton, NEmpty, NModal, NPopover, NSpin, useMessage } from "naive-ui"
66 import { computed, onBeforeMount, ref, watch } from "vue"
67 import Api from "@/api"
68 import Icon from "@/components/common/Icon.vue"
69 import AvailableReportsItem from "./AvailableReportsItem.vue"
70 import CreationReportForm from "./CreationReportForm.vue"
71
72 const InfoIcon = "carbon:information"
73 const NewReportIcon = "carbon:fetch-upload-cloud"
74 const message = useMessage()
75 const showForm = ref(false)
76 const loading = ref(false)
77 const reportsList = ref<ScoutSuiteReport[]>([])
78 const totalReports = computed(() => reportsList.value.length)
79 const formCTX = ref<{ reset: () => void } | null>(null)
80
81 function getReports() {
82 loading.value = true
83
84 Api.cloudSecurityAssessment
85 .getAvailableScoutSuiteReports()
86 .then(res => {
87 if (res.data.success) {
88 reportsList.value = res.data?.available_reports || []
89 } else {
90 message.warning(res.data?.message || "An error occurred. Please try again later.")
91 }
92 })
93 .catch(err => {
94 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
95 })
96 .finally(() => {
97 loading.value = false
98 })
99 }
100
101 watch(showForm, val => {
102 if (val) {
103 formCTX.value?.reset()
104 }
105 })
106
107 onBeforeMount(() => {
108 getReports()
109 })
110 </script>