Skip to content

Commit

Permalink
Merge pull request #5590 from cloudforet-io/feature-project-alert-man…
Browse files Browse the repository at this point in the history
…ager

feat: apply qa issue
  • Loading branch information
skdud4659 authored Jan 22, 2025
2 parents a83cce5 + 34a7d50 commit a1c967b
Show file tree
Hide file tree
Showing 28 changed files with 531 additions and 264 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ const stopPairInit = watch(() => props.pairs, (pairs) => {
width: 15rem;
}
.value {
@apply inline-block font-bold;
@apply inline-block font-bold pl-2;
width: 20rem;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ const handleSelectDropdown = (type: 'start' | 'end', value: number) => {
}
};
const areDayArraysEqual = (selectedDayButton: DayType[], compareDays: DayType[]) => {
if (selectedDayButton.length !== compareDays.length) return false;
const selectedDaySet = new Set(selectedDayButton);
return compareDays.every((day) => selectedDaySet.has(day));
};
watch([() => state.selectedRadioIdx, () => state.selectedDayButton, () => state.start, () => state.end], ([selectedRadioIdx]) => {
emit('update-form', {
Expand All @@ -130,6 +136,16 @@ watch([() => state.selectedRadioIdx, () => state.selectedDayButton, () => state.
});
}, { immediate: true });
watch(() => state.selectedDayButton, (selectedDayButton) => {
const weekDays = ['MON', 'TUE', 'WED', 'THU', 'FRI'] as DayType[];
const everyDay = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'] as DayType[];
if (areDayArraysEqual(selectedDayButton, weekDays)) {
state.selectedRadioIdx = 0;
} else if (areDayArraysEqual(selectedDayButton, everyDay)) {
state.selectedRadioIdx = 1;
}
}, { immediate: true });
onMounted(() => {
if (props.scheduleForm) {
initScheduleForm();
Expand Down
114 changes: 87 additions & 27 deletions apps/web/src/common/pages/AlertPublicDetailPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import {
import type { TabItem } from '@cloudforet/mirinae/types/navigation/tabs/tab/type';
import { iso8601Formatter } from '@cloudforet/utils';
import type { AlertModel } from '@/schema/alert-manager/alert/model';
import { ALERT_STATE, ALERT_URGENCY } from '@/schema/monitoring/alert/constants';
import type { AlertModel } from '@/schema/monitoring/alert/model';
import type { AlertModelV1 } from '@/schema/monitoring/alert/model';
import { i18n, setI18nLocale } from '@/translations';
import { ERROR_ROUTE } from '@/router/constant';
Expand All @@ -31,45 +32,75 @@ import { AUTH_ROUTE } from '@/services/auth/routes/route-constant';
const router = useRouter();
interface Props {
alertUrl?: string;
language?: string;
alertUrl?: string;
language?: string;
}
const props = defineProps<Props>();
interface PublicAlertModelV1 extends AlertModelV1 {
project_name: string;
domain_settings: {
timezone: string;
language: string;
};
}
interface PublicAlertModel extends AlertModel {
project_name: string;
domain_settings: {
timezone: string;
language: string;
};
service_name: string;
domain_settings: {
timezone: string;
language: string;
}
}
const state = reactive({
loading: true,
alertData: {} as Partial<PublicAlertModel>,
alertVersion: '',
alertData: {} as Partial<PublicAlertModelV1> & Partial<PublicAlertModel>,
alertId: '',
duration: computed(() => calculateTime(state.alertData?.created_at)),
timezone: computed(() => state.alertData?.domain_settings?.timezone ?? 'UTC'),
language: computed(() => state.alertData?.domain_settings?.language ?? 'en'),
});
const tableState = reactive({
fields: computed(() => [
{ name: 'description', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.DESC'), disableCopy: true },
{ name: 'rule', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.RULE'), disableCopy: true },
{ name: 'severity', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.SEVERITY'), disableCopy: true },
{ name: 'escalation_policy_id', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.ESCALATION_POLICY'), disableCopy: true },
{ name: 'project_id', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.PROJECT'), disableCopy: true },
{ name: 'triggered_by', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.TRIGGERED_BY'), disableCopy: true },
{ name: 'account', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.ACCOUNT_ID'), disableCopy: true },
{ name: 'resources', label: i18n.t('MONITORING.ALERT.DETAIL.DETAILS.RESOURCE'), disableCopy: true },
{ name: 'responder', label: i18n.t('MONITORING.ALERT.DETAIL.DETAILS.RESPONDER'), disableCopy: true },
{ name: 'created_at', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.CREATED'), disableCopy: true },
{ name: 'acknowledged_at', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.ACKNOWLEDGED'), disableCopy: true },
{ name: 'resolved_at', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.RESOLVED'), disableCopy: true },
]),
escalationPolicyName: '',
fields: computed(() => {
let fieldPerVersion;
if (state.alertVersion === 'v1') {
fieldPerVersion = [
{ name: 'project_id', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.PROJECT'), disableCopy: true },
{ name: 'account', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.ACCOUNT_ID'), disableCopy: true },
{ name: 'responder', label: i18n.t('MONITORING.ALERT.DETAIL.DETAILS.RESPONDER'), disableCopy: true },
];
} else {
fieldPerVersion = [
{ name: 'service_id', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.SERVICE'), disableCopy: true },
{ name: 'triggered_type', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.TRIGGERED_TYPE'), disableCopy: true },
{ name: 'acknowledged_by', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.ACKNOWLEDGED_BY'), disableCopy: true },
{ name: 'resolved_by', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.RESOLVED_BY'), disableCopy: true },
{ name: 'webhook_id', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.WEBHOOK'), disableCopy: true },
];
}
return [
{ name: 'description', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.DESC'), disableCopy: true },
{ name: 'rule', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.RULE'), disableCopy: true },
{ name: 'severity', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.SEVERITY'), disableCopy: true },
{ name: 'escalation_policy_id', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.ESCALATION_POLICY'), disableCopy: true },
{ name: 'triggered_by', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.TRIGGERED_BY'), disableCopy: true },
{ name: 'resources', label: i18n.t('MONITORING.ALERT.DETAIL.DETAILS.RESOURCE'), disableCopy: true },
{ name: 'created_at', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.CREATED'), disableCopy: true },
{ name: 'acknowledged_at', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.ACKNOWLEDGED'), disableCopy: true },
{ name: 'resolved_at', label: i18n.t('MONITORING.ALERT.DETAIL.INFO.RESOLVED'), disableCopy: true },
...fieldPerVersion,
];
}),
escalationPolicyName: computed(() => {
if (state.alertVersion === 'v2') {
return state.alertData.escalation_policy_name;
}
return '';
}),
webhooks: {},
alertStateList: computed(() => ([
{ name: ALERT_STATE.TRIGGERED, label: i18n.t('MONITORING.ALERT.DETAIL.HEADER.TRIGGERED') },
Expand Down Expand Up @@ -106,6 +137,12 @@ const fetchData = async () => {
try {
const response = await axios.get(alertFetchUrl as string);
state.alertData = response?.data;
if (Object.keys(state.alertData).includes('version')
&& state.alertData.version === 'v2') {
state.alertVersion = 'v2';
} else if (!Object.keys(state.alertData).includes('version')) {
state.alertVersion = 'v1';
}
} catch (e) {
console.error(e);
await router.push({ name: ERROR_ROUTE.EXPIRED_LINK._NAME });
Expand Down Expand Up @@ -159,7 +196,9 @@ const handleRouteToSignInWithRedirectPath = () => {
@click-back-button="router.go(-1)"
>
<template #title-right-extra>
<span class="alert-number">#{{ state.alertData?.alert_number }}</span>
<span v-if="state.alertVersion === 'v1'"
class="alert-number"
>#{{ state.alertData?.alert_number }}</span>
</template>
</p-heading>
<section class="detail-contents-wrapper">
Expand All @@ -168,11 +207,16 @@ const handleRouteToSignInWithRedirectPath = () => {
<p-pane-layout class="alert-detail-summary">
<p class="content-wrapper">
<span class="title">{{ $t('MONITORING.ALERT.DETAIL.HEADER.STATE') }}</span>
<template v-if="state.alertData?.state !== ALERT_STATE.ERROR">
<template v-if="state.alertVersion === 'v1' && state.alertData?.state !== ALERT_STATE.ERROR">
<span :class="{'text-alert': state.alertData.state === ALERT_STATE.TRIGGERED}">
{{ tableState.alertStateList.find(d => d.name === state.alertData?.state)?.label }}
</span>
</template>
<template v-else-if="state.alertVersion === 'v2' && state.alertData?.status !== ALERT_STATE.ERROR">
<span :class="{'text-alert': state.alertData.status === ALERT_STATE.TRIGGERED}">
{{ tableState.alertStateList.find(d => d.name === state.alertData?.status)?.label }}
</span>
</template>
<template v-else>
<p-badge style-type="alert"
badge-type="solid"
Expand Down Expand Up @@ -202,7 +246,9 @@ const handleRouteToSignInWithRedirectPath = () => {
{{ tableState.alertUrgencyList.find(d => d.name === state.alertData?.urgency)?.label }}
</span>
</p>
<p class="content-wrapper">
<p v-if="state.alertVersion === 'v1'"
class="content-wrapper"
>
<span class="title">{{ $t('MONITORING.ALERT.DETAIL.HEADER.ASSIGNED_TO') }}</span>
<span v-if="state.alertData?.assignee"
class="email"
Expand Down Expand Up @@ -285,6 +331,20 @@ const handleRouteToSignInWithRedirectPath = () => {
<span v-if="state.alertData.resolved_at"> {{ iso8601Formatter(state.alertData.resolved_at, state.timezone) }}</span>
<span v-else>--</span>
</template>
<template #data-service_id>
<p class="content-wrapper">
<span class="service">
{{ state.alertData?.service_name ?? state.alertData?.service_id }}
</span>
</p>
</template>
<template #data-triggered_type>
<p-badge badge-type="solid-outline"
style-type="indigo500"
>
{{ state.alertData.triggered_type }}
</p-badge>
</template>
<template #data-additional_info="{value}">
<span v-if="Object.keys(value)?.length === 0">
--
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/schema/monitoring/alert/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {
AlertResource, AlertSeverity, AlertState, AlertUrgency,
} from '@/schema/monitoring/alert/type';

export interface AlertModel {
export interface AlertModelV1 {
alert_number: number;
alert_id: string;
title: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, reactive } from 'vue';
import { useRouter } from 'vue-router/composables';
import { useRoute, useRouter } from 'vue-router/composables';
import { SpaceConnector } from '@cloudforet/core-lib/space-connector';
import { PButtonModal } from '@cloudforet/mirinae';
Expand Down Expand Up @@ -33,6 +33,7 @@ const storeState = reactive({
alertInfo: computed<AlertModel>(() => alertDetailPageState.alertInfo),
});
const router = useRouter();
const route = useRoute();
const { getProperRouteLocation } = useProperRouteLocation();
Expand All @@ -53,7 +54,12 @@ const handleConfirm = async () => {
await SpaceConnector.clientV2.alertManager.alert.delete<AlertDeleteParameters>({
alert_id: storeState.alertInfo.alert_id,
});
await router.push(getProperRouteLocation({ name: ALERT_MANAGER_ROUTE.ALERTS._NAME }));
const serviceId = route.params?.serviceId;
if (serviceId) {
await router.go(-1);
} else {
await router.push(getProperRouteLocation({ name: ALERT_MANAGER_ROUTE.ALERTS._NAME }));
}
showSuccessMessage(i18n.t('ALERT_MANAGER.ALERTS.ALT_S_DELETE'), '');
} catch (e) {
ErrorHandler.handleError(e, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ const state = reactive({
alertUrgency: 'HIGH',
duration: computed<string>(() => (
storeState.alertInfo.status === ALERT_STATUS.RESOLVED
? calculateTime(storeState.alertInfo?.resolved_at, storeState.timezone)
: calculateTime(storeState.alertInfo?.created_at, storeState.timezone)
? calculateTime(storeState.alertInfo?.resolved_at, storeState.timezone) || '0m'
: calculateTime(storeState.alertInfo?.created_at, storeState.timezone) || '0m'
)),
alertStateList: computed<SelectDropdownMenuItem[]>(() => ([
{ name: ALERT_STATUS.TRIGGERED, label: i18n.t('ALERT_MANAGER.ALERTS.TRIGGERED') },
Expand All @@ -57,6 +57,8 @@ const state = reactive({
])),
});
const getEscalationInfo = (id: string) => storeState.escalationPolicy[id]?.label || '';
const handleChangeAlertState = async (alertState: AlertStatusType) => {
await alertDetailPageStore.updateAlertDetail({
alert_id: storeState.alertInfo.alert_id,
Expand Down Expand Up @@ -132,7 +134,7 @@ watch(() => alertDetailPageState.alertInfo, (alertInfo) => {
</div>
<div class="content-wrapper">
<span class="title">{{ $t('ALERT_MANAGER.ESCALATION_POLICY.TITLE') }}</span>
<p-link :text="storeState.escalationPolicy[storeState.alertInfo.escalation_policy_id].label"
<p-link :text="getEscalationInfo(storeState.alertInfo.escalation_policy_id)"
action-icon="internal-link"
new-tab
:to="getProperRouteLocation({
Expand All @@ -146,6 +148,7 @@ watch(() => alertDetailPageState.alertInfo, (alertInfo) => {
},
})"
highlight
size="md"
class="leading-8"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const storeState = reactive({
selectedServiceId: computed<string>(() => alertPageState.selectedServiceId),
selectedStatus: computed<string>(() => alertPageState.selectedStatus),
selectedUrgency: computed<string>(() => alertPageState.selectedUrgency),
selectedSearchFilter: computed<string|undefined>(() => alertPageState.selectedSearchFilter),
selectedSearchFilter: computed<string[]|undefined>(() => alertPageState.selectedSearchFilter),
});
const state = reactive({
menuItems: computed<MenuItem[]>(() => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,8 @@ watch(() => storeState.serviceId, async (serviceId) => {
</template>
<template #col-duration-format="{ item }">
<span>{{ item.status === ALERT_STATUS.RESOLVED
? calculateTime(item?.resolved_at, storeState.timezone)
: calculateTime(item?.created_at, storeState.timezone) }}</span>
? calculateTime(item?.resolved_at, storeState.timezone) || '0m'
: calculateTime(item?.created_at, storeState.timezone) || '0m' }}</span>
</template>
</p-toolbox-table>
<custom-field-modal :visible="state.visibleCustomFieldModal"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const state = reactive({
alerts: storeState.service.alerts.TOTAL.HIGH + storeState.service.alerts.TOTAL.LOW,
webhook: storeState.service.webhooks?.length || 0,
})),
noData: computed<boolean>(() => state.data.alerts === 0 && state.data.webhook === 0),
});
const handleConfirm = async () => {
state.loading = true;
Expand All @@ -66,7 +67,7 @@ const handleClose = () => {

<template>
<p-button-modal class="service-detail-delete-modal"
:header-title="$t('ALERT_MANAGER.SERVICE.MODAL_DELETE_TITLE')"
:header-title="!state.noData ? $t('ALERT_MANAGER.SERVICE.MODAL_DELETE_TITLE') : $t('ALERT_MANAGER.SERVICE.MODAL_DELETE_NO_DATA')"
size="sm"
theme-color="alert"
:fade="true"
Expand All @@ -77,10 +78,13 @@ const handleClose = () => {
@cancel="handleClose"
@close="handleClose"
>
<template #body>
<template v-if="!state.noData"
#body
>
<div class="flex flex-col gap-2 pt-4 pb-2">
<span>{{ $t('ALERT_MANAGER.SERVICE.MODAL_DELETE_DESC') }}</span>
<p-definition-table :fields="state.fields"
<p-definition-table v-if="!state.noData"
:fields="state.fields"
:data="state.data"
:skeleton-rows="2"
class="definition-table"
Expand All @@ -89,6 +93,11 @@ const handleClose = () => {
/>
</div>
</template>
<template v-if="state.noData"
#confirm-button
>
{{ $t('COMMON.BUTTONS.DELETE') }}
</template>
</p-button-modal>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ watch(() => tabState.activeTab, (activeTab) => {
mode: activeTab !== SERVICE_DETAIL_TABS.SETTINGS ? undefined : route.query?.mode,
webhookId: activeTab !== SERVICE_DETAIL_TABS.SETTINGS ? undefined : route.query?.webhookId,
eventRuleId: activeTab !== SERVICE_DETAIL_TABS.SETTINGS ? undefined : route.query?.eventRuleId,
escalationPolicyId: activeTab !== SERVICE_DETAIL_TABS.SETTINGS ? undefined : route.query?.escalationPolicyId,
});
});
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,10 @@ watch(() => storeState.serviceInfo.service_id, (service_id) => {
>
<p-text-button style-type="highlight"
class="ml-auto mr-auto"
size="sm"
@click="handleRouteAlertsTab"
>
{{ $t('ALERT_MANAGER.SERVICE.VIEW_ALL_OPEN_ALERTS') }}
{{ $t('ALERT_MANAGER.SERVICE.VIEW_ALL') }}
</p-text-button>
</td>
</template>
Expand Down
Loading

0 comments on commit a1c967b

Please sign in to comment.