-
-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'incident-management' of https://github.com/socfortress/…
…CoPilot into incident-management
- Loading branch information
Showing
11 changed files
with
354 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
frontend/src/components/incidentManagement/alerts/AlertCreateCaseButton.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<template> | ||
<n-button secondary type="primary" @click="createCase()" :loading="creating"> | ||
<template #icon><Icon :name="DangerIcon" /></template> | ||
Create case | ||
</n-button> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ref, toRefs } from "vue" | ||
import { NButton, useMessage } from "naive-ui" | ||
import Icon from "@/components/common/Icon.vue" | ||
import Api from "@/api" | ||
import type { Alert } from "@/types/incidentManagement/alerts.d" | ||
const props = defineProps<{ alert: Alert }>() | ||
const { alert } = toRefs(props) | ||
const emit = defineEmits<{ | ||
(e: "updated", value: Alert): void | ||
}>() | ||
const DangerIcon = "majesticons:exclamation-line" | ||
const message = useMessage() | ||
const creating = ref(false) | ||
function updateAlert(updatedAlert: Alert) { | ||
emit("updated", updatedAlert) | ||
} | ||
function createCase() { | ||
creating.value = true | ||
Api.incidentManagement | ||
.createCase(alert.value.id) | ||
.then(res => { | ||
if (res.data.success) { | ||
updateAlert({ | ||
...alert.value, | ||
linked_cases: [ | ||
{ | ||
id: res.data.case_alert_link.case_id, | ||
case_name: "", | ||
case_description: "", | ||
case_creation_time: new Date(), | ||
assigned_to: null, | ||
case_status: null | ||
} | ||
] | ||
}) | ||
message.success(res.data?.message || "Case created successfully") | ||
} else { | ||
message.warning(res.data?.message || "An error occurred. Please try again later.") | ||
} | ||
}) | ||
.catch(err => { | ||
message.error(err.response?.data?.message || "An error occurred. Please try again later.") | ||
}) | ||
.finally(() => { | ||
creating.value = false | ||
}) | ||
} | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
frontend/src/components/incidentManagement/alerts/AlertLinkedCases.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<template> | ||
<code | ||
class="cursor-pointer text-primary-color" | ||
v-for="linkedCase of linkedCases" | ||
:key="linkedCase.id" | ||
@click="gotoIncidentManagementCases(linkedCase.id)" | ||
> | ||
#{{ linkedCase.id }} | ||
<Icon :name="LinkIcon" :size="14" class="top-0.5 relative" /> | ||
</code> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { computed, toRefs } from "vue" | ||
import Icon from "@/components/common/Icon.vue" | ||
import { useGoto } from "@/composables/useGoto" | ||
import type { Alert } from "@/types/incidentManagement/alerts.d" | ||
const props = defineProps<{ alert: Alert }>() | ||
const { alert } = toRefs(props) | ||
const LinkIcon = "carbon:launch" | ||
const { gotoIncidentManagementCases } = useGoto() | ||
const linkedCases = computed(() => alert.value.linked_cases) | ||
</script> |
165 changes: 165 additions & 0 deletions
165
frontend/src/components/incidentManagement/alerts/AlertMergeCaseButton.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
<template> | ||
<n-button secondary @click="openDialog()" :loading="merging"> | ||
<template #icon><Icon :name="MergeIcon" /></template> | ||
Merge into Case | ||
</n-button> | ||
|
||
<n-modal | ||
v-model:show="showMergeBox" | ||
display-directive="show" | ||
preset="card" | ||
title="Select the case you want to merge it with" | ||
:style="{ maxWidth: 'min(850px, 90vw)', minHeight: 'min(540px, 90vh)', maxHeight: '80vh' }" | ||
content-class="overflow-hidden flex flex-col !px-2" | ||
segmented | ||
> | ||
<n-spin | ||
:show="loadingCases" | ||
class="grow overflow-hidden flex flex-col" | ||
content-class="grow overflow-hidden flex flex-col" | ||
> | ||
<n-scrollbar class="grow flex flex-col" content-class="grow" trigger="none"> | ||
<div class="flex flex-col gap-2 px-5 py-2"> | ||
<template v-if="linkableCases.length"> | ||
<CaseItem | ||
v-for="item of linkableCases" | ||
:key="item.id" | ||
:caseData="item" | ||
compact | ||
embedded | ||
@click="toggleSelectedCase(item)" | ||
:class="{ active: selectedCase?.id === item.id }" | ||
/> | ||
</template> | ||
<template v-else> | ||
<n-empty description="No items found" class="justify-center h-48" v-if="!loadingCases" /> | ||
</template> | ||
</div> | ||
</n-scrollbar> | ||
</n-spin> | ||
<template #footer> | ||
<div class="flex justify-end"> | ||
<n-button type="success" :disabled="!selectedCase" :loading="merging" @click="linkCase()"> | ||
<template #icon><Icon :name="MergeIcon" /></template> | ||
Confirm Merge {{ selectedCase ? `with Case #${selectedCase.id}` : "" }} | ||
</n-button> | ||
</div> | ||
</template> | ||
</n-modal> | ||
</template> | ||
<script setup lang="ts"> | ||
import { inject, ref, toRefs, watch, type Ref } from "vue" | ||
import { NButton, NModal, NSpin, NEmpty, NScrollbar, useMessage } from "naive-ui" | ||
import Icon from "@/components/common/Icon.vue" | ||
import CaseItem from "../cases/CaseItem.vue" | ||
import _orderBy from "lodash/orderBy" | ||
import Api from "@/api" | ||
import type { Alert } from "@/types/incidentManagement/alerts.d" | ||
import type { Case } from "@/types/incidentManagement/cases.d" | ||
const props = defineProps<{ alert: Alert }>() | ||
const { alert } = toRefs(props) | ||
const emit = defineEmits<{ | ||
(e: "updated", value: Alert): void | ||
}>() | ||
const MergeIcon = "carbon:ibm-cloud-direct-link-1-connect" | ||
const message = useMessage() | ||
const merging = ref(false) | ||
const showMergeBox = ref(false) | ||
const loadingCases = ref(false) | ||
const linkableCases = inject<Ref<Case[]>>("linkable-cases", ref([])) | ||
const selectedCase = ref<Case | null>(null) | ||
watch(showMergeBox, val => { | ||
if (val && !linkableCases.value.length) { | ||
getCasesList() | ||
} | ||
}) | ||
function updateAlert(updatedAlert: Alert) { | ||
emit("updated", updatedAlert) | ||
} | ||
function openDialog() { | ||
showMergeBox.value = true | ||
} | ||
function closeDialog() { | ||
showMergeBox.value = false | ||
} | ||
function toggleSelectedCase(caseEntity: Case) { | ||
if (selectedCase.value?.id === caseEntity.id) { | ||
selectedCase.value = null | ||
} else { | ||
selectedCase.value = caseEntity | ||
} | ||
} | ||
function getCasesList() { | ||
loadingCases.value = true | ||
Api.incidentManagement | ||
.getCasesList() | ||
.then(res => { | ||
if (res.data.success) { | ||
linkableCases.value = _orderBy(res.data?.cases || [], ["id"], ["desc"]) | ||
} else { | ||
message.warning(res.data?.message || "An error occurred. Please try again later.") | ||
} | ||
}) | ||
.catch(err => { | ||
message.error(err.response?.data?.message || "An error occurred. Please try again later.") | ||
}) | ||
.finally(() => { | ||
loadingCases.value = false | ||
}) | ||
} | ||
function linkCase() { | ||
if (selectedCase.value?.id) { | ||
merging.value = true | ||
Api.incidentManagement | ||
.linkCase(alert.value.id, selectedCase.value.id) | ||
.then(res => { | ||
if (res.data.success) { | ||
closeDialog() | ||
updateAlert({ | ||
...alert.value, | ||
linked_cases: [ | ||
{ | ||
id: res.data.case_alert_link.case_id, | ||
case_name: "", | ||
case_description: "", | ||
case_creation_time: new Date(), | ||
assigned_to: null, | ||
case_status: null | ||
} | ||
] | ||
}) | ||
message.success(res.data?.message || "Case linked successfully") | ||
} else { | ||
message.warning(res.data?.message || "An error occurred. Please try again later.") | ||
} | ||
}) | ||
.catch(err => { | ||
message.error(err.response?.data?.message || "An error occurred. Please try again later.") | ||
}) | ||
.finally(() => { | ||
merging.value = false | ||
}) | ||
} | ||
} | ||
</script> | ||
<style lang="scss" scoped> | ||
.active { | ||
box-shadow: 0px 0px 0px 2px var(--success-color) !important; | ||
} | ||
</style> |
Oops, something went wrong.