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>