@cryptotaxi247 / CoPilot / commits / f7bd2a96

559 copilot asset information screen for non wazuh alerts (#560)

* refactor: enhance AlertAsset component structure and improve readability * linit clean

taylor_socfortress committed Dec 15, 2025 at 09:22 UTC f7bd2a9649d830ad2ae93f44836d187186396de6
1 file changed +42 -38
frontend/src/components/incidentManagement/alerts/AlertAsset.vue
+42 -38
@@ -135,7 +135,7 @@
135 </div>
136 </div>
137 </n-tab-pane>
138 - <n-tab-pane name="Artifact Collection" tab="Artifact Collection" display-directive="show:lazy">
138 + <n-tab-pane v-if="isWazuhSource" name="Artifact Collection" tab="Artifact Collection" display-directive="show:lazy">
139 <div class="p-7 pt-2">
140 <ArtifactsCollect
141 :hostname="asset.asset_name"
@@ -146,19 +146,19 @@
146 />
147 </div>
148 </n-tab-pane>
149 - <n-tab-pane name="Alert Timeline" tab="Alert Timeline" display-directive="show:lazy">
149 + <n-tab-pane v-if="isWazuhSource" name="Alert Timeline" tab="Alert Timeline" display-directive="show:lazy">
150 <div class="p-7 pt-2">
151 <AlertDetailTimeline :asset />
152 </div>
153 </n-tab-pane>
154 - <n-tab-pane name="File Collection" tab="File Collection" display-directive="show:lazy">
154 + <n-tab-pane v-if="isWazuhSource" name="File Collection" tab="File Collection" display-directive="show:lazy">
155 <div class="p-7 pt-2">
156 <FileCollectionForm v-if="asset.agent_id" :agent-id="asset.agent_id" />
157
158 <n-empty v-else description="No agent associated with this asset" class="h-40" />
159 </div>
160 </n-tab-pane>
161 - <n-tab-pane name="Data Store" tab="Data Store" display-directive="show:lazy">
161 + <n-tab-pane v-if="isWazuhSource" name="Data Store" tab="Data Store" display-directive="show:lazy">
162 <div class="p-7 pt-2">
163 <AgentDataStoreTabCompact v-if="asset.agent_id" :agent-id="asset.agent_id" />
164 <n-empty v-else description="No agent associated with this asset" class="h-40" />
@@ -172,7 +172,7 @@
172 <script setup lang="ts">
173 import type { AlertAsset, AlertContext } from "@/types/incidentManagement/alerts.d"
174 import _truncate from "lodash/truncate"
175 -import { NCard, NDivider, NModal, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
175 +import { NCard, NDivider, NEmpty, NModal, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
176 import { computed, defineAsyncComponent, ref, watch } from "vue"
177 import Api from "@/api"
178 import Badge from "@/components/common/Badge.vue"
@@ -187,22 +187,22 @@ const AlertDetailTimeline = defineAsyncComponent(() => import("./AlertDetailTime
187 // const ArtifactRecommendation = defineAsyncComponent(() => import("@/components/artifacts/ArtifactRecommendation.vue"))
188 const AIAnalystButton = defineAsyncComponent(() => import("@/components/threatIntel/AIAnalystButton.vue"))
189 const AIWazuhExclusionRuleButton = defineAsyncComponent(
190 - () => import("@/components/threatIntel/AIWazuhExclusionRuleButton.vue")
190 + () => import("@/components/threatIntel/AIWazuhExclusionRuleButton.vue")
191 )
192 const AIVelociraptorArtifactRecommendationButton = defineAsyncComponent(
193 - () => import("@/components/threatIntel/AIVelociraptorArtifactRecommendationButton.vue")
193 + () => import("@/components/threatIntel/AIVelociraptorArtifactRecommendationButton.vue")
194 )
195 const ThreatIntelProcessEvaluationProvider = defineAsyncComponent(
196 - () => import("@/components/threatIntel/ThreatIntelProcessEvaluationProvider.vue")
196 + () => import("@/components/threatIntel/ThreatIntelProcessEvaluationProvider.vue")
197 )
198 const ArtifactsCollect = defineAsyncComponent(() => import("@/components/artifacts/ArtifactsCollect.vue"))
199 const CodeSource = defineAsyncComponent(() => import("@/components/common/CodeSource.vue"))
200 const LicenseFeatureCheck = defineAsyncComponent(() => import("@/components/license/LicenseFeatureCheck.vue"))
201 const AgentDataStoreTabCompact = defineAsyncComponent(
202 - () => import("@/components/agents/dataStore/AgentDataStoreTabCompact.vue")
202 + () => import("@/components/agents/dataStore/AgentDataStoreTabCompact.vue")
203 )
204 const FileCollectionForm = defineAsyncComponent(
205 - () => import("@/components/agents/fileCollection/FileCollectionForm.vue")
205 + () => import("@/components/agents/fileCollection/FileCollectionForm.vue")
206 )
207
208 const ViewIcon = "iconoir:eye-solid"
@@ -219,44 +219,48 @@ const isInvestigationAvailable = computed(() => processNameList.value.length)
219 const licenseChecked = ref(false)
220 const licenseResponse = ref(false)
221
222 +const isWazuhSource = computed(() => {
223 + return alertContext.value?.source?.toLowerCase() === 'wazuh'
224 +})
225 +
226 watch(showDetails, val => {
223 - if (val && !alertContext.value) {
224 - getAlertContext(asset.alert_context_id)
225 - }
227 + if (val && !alertContext.value) {
228 + getAlertContext(asset.alert_context_id)
229 + }
230 })
231
232 function getAlertContext(alertContextId: number) {
229 - loading.value = true
233 + loading.value = true
234
231 - Api.incidentManagement.alerts
232 - .getAlertContext(alertContextId)
233 - .then(res => {
234 - if (res.data.success) {
235 - alertContext.value = res.data?.alert_context || null
236 - } else {
237 - message.warning(res.data?.message || "An error occurred. Please try again later.")
238 - }
239 - })
240 - .catch(err => {
241 - message.error(err.response?.data?.message || "An error occurred. Please try again later.")
242 - })
243 - .finally(() => {
244 - loading.value = false
245 - })
235 + Api.incidentManagement.alerts
236 + .getAlertContext(alertContextId)
237 + .then(res => {
238 + if (res.data.success) {
239 + alertContext.value = res.data?.alert_context || null
240 + } else {
241 + message.warning(res.data?.message || "An error occurred. Please try again later.")
242 + }
243 + })
244 + .catch(err => {
245 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
246 + })
247 + .finally(() => {
248 + loading.value = false
249 + })
250 }
251 </script>
252
253 <style lang="scss" scoped>
254 .alert-assets-badge {
251 - color: var(--primary-color);
252 - line-height: 1;
253 - cursor: pointer;
255 + color: var(--primary-color);
256 + line-height: 1;
257 + cursor: pointer;
258
255 - code {
256 - display: flex;
257 - align-items: center;
258 - gap: 7px;
259 - padding: 2px 5px;
260 - }
259 + code {
260 + display: flex;
261 + align-items: center;
262 + gap: 7px;
263 + padding: 2px 5px;
264 + }
265 }
266 </style>