Skip to content

Commit

Permalink
feat: apply notification API (enable, disable, update, delete) (#5312)
Browse files Browse the repository at this point in the history
* feat: apply notification API

Signed-off-by: NaYeong,Kim <[email protected]>

* chore: update translations

Signed-off-by: NaYeong,Kim <[email protected]>

---------

Signed-off-by: NaYeong,Kim <[email protected]>
  • Loading branch information
skdud4659 authored Dec 23, 2024
1 parent d09da98 commit fbdde5d
Show file tree
Hide file tree
Showing 14 changed files with 726 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@ import {
PFieldGroup, PRadioGroup, PRadio, PI, PSelectButton, PSelectDropdown,
} from '@cloudforet/mirinae';
import type { ServiceChannelScheduleType } from '@/schema/alert-manager/service-channel/type';
import { i18n } from '@/translations';
import type {
ScheduleDayButtonType,
ScheduleRadioType,
ScheduleType,
ScheduleDayType,
ScheduleForm,
} from '@/common/components/schedule-setting-form/schedule-setting-form';
import { blue } from '@/styles/colors';
interface Props {
scheduleForm?: ScheduleForm;
}
const props = withDefaults(defineProps<Props>(), {
scheduleForm: undefined,
});
const emit = defineEmits<{(e: 'schedule-form', form: ScheduleForm): void; }>();
Expand Down Expand Up @@ -50,7 +57,7 @@ const generateHourlyTimeArray = () => range(0, 25).map((h) => ({
name: h,
}));
const handleSelectScheduleType = (type: ScheduleType) => {
const handleSelectScheduleType = (type: ServiceChannelScheduleType) => {
if (type === 'WEEK_DAY') {
state.selectedDayButton = state.days.slice(0, 5).map((day) => day.name);
} else if (type === 'ALL_DAY') {
Expand All @@ -71,6 +78,14 @@ const handleSelectDropdown = (type: 'start' | 'end', value: number) => {
}
};
watch(() => props.scheduleForm, (scheduleForm) => {
if (scheduleForm) {
state.selectedRadioIdx = state.scheduleTypeList.findIndex((item) => item.name === props.scheduleForm?.type);
state.selectedDayButton = props.scheduleForm?.days || [];
state.start = props.scheduleForm?.start || 9;
state.end = props.scheduleForm?.end || 18;
}
}, { immediate: true });
watch([() => state.selectedRadioIdx, () => state.selectedDayButton, () => state.start, () => state.end], ([selectedRadioIdx, selectedDayButton, start, end]) => {
emit('schedule-form', {
type: state.scheduleTypeList[selectedRadioIdx].name,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { TranslateResult } from 'vue-i18n';

export type ScheduleType = 'ALL_DAY' | 'WEEK_DAY' | 'CUSTOM';
import type { ServiceChannelScheduleType } from '@/schema/alert-manager/service-channel/type';

export type ScheduleDayType = 'MON' | 'TUE' | 'WED' | 'THU' | 'FRI' | 'SAT' | 'SUN';

export type ScheduleRadioType = {
name: ScheduleType;
name: ServiceChannelScheduleType;
label: TranslateResult;
};
export type ScheduleDayButtonType = {
Expand All @@ -13,7 +14,7 @@ export type ScheduleDayButtonType = {
};

export type ScheduleForm = {
type: ScheduleType;
type: ServiceChannelScheduleType;
days: ScheduleDayType[];
start: number;
end: number;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
<script setup lang="ts">
import { computed, reactive, watch } from 'vue';
import { zipObject } from 'lodash';
import {
PFieldGroup, PLazyImg, PTextInput, PRadioGroup, PRadio, PPaneLayout,
} from '@cloudforet/mirinae';
import type { NotificationProtocolModel } from '@/schema/alert-manager/notification-protocol/model';
import type { ServiceChannelScheduleDayType } from '@/schema/alert-manager/service-channel/type';
import { i18n } from '@/translations';
import { assetUrlConverter } from '@/lib/helper/asset-helper';
import type { ScheduleDayType, ScheduleForm } from '@/common/components/schedule-setting-form/schedule-setting-form';
import type { ScheduleForm } from '@/common/components/schedule-setting-form/schedule-setting-form';
import ScheduleSettingForm from '@/common/components/schedule-setting-form/ScheduleSettingForm.vue';
import { useFormValidator } from '@/common/composables/form-validator';
import type { SelectedUserDropdownIdsType } from '@/common/modules/user/typte';
import UserSelectDropdown from '@/common/modules/user/UserSelectDropdown.vue';
import { createScheduleMap } from '@/services/alert-manager-v2/composables/form-data';
import { useServiceCreateFormStore } from '@/services/alert-manager-v2/stores/service-create-form-store';
import type { CreatedNotificationInfoType, UserRadioType } from '@/services/alert-manager-v2/types/alert-manager-type';
Expand Down Expand Up @@ -59,14 +57,7 @@ const {
invalidTexts,
} = useFormValidator({
name: '',
}, {
name(value: string) {
if (value.length >= 40) {
return i18n.t('ALERT_MANAGER.WEBHOOK.VALIDATION_NAME_MAX');
}
return '';
},
});
}, {});
const handleScheduleForm = (form: ScheduleForm) => {
state.scheduleForm = form;
Expand All @@ -75,19 +66,6 @@ const handleChangeRadio = () => {
state.selectedMemberItems = [];
};
const createScheduleMap = (scheduleForm: ScheduleForm): Record<ScheduleDayType, ServiceChannelScheduleDayType> => {
const allDays: ScheduleDayType[] = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'];
const { days, start, end } = scheduleForm;
const refinedDays = allDays.map((day) => ({
is_scheduled: days.includes(day),
start,
end,
}));
return zipObject(allDays, refinedDays) as Record<ScheduleDayType, ServiceChannelScheduleDayType>;
};
watch([() => name.value, () => state.scheduleForm, () => state.selectedRadioIdx, () => state.selectedMemberItems], ([nameVal, scheduleForm, selectedRadioIdx, selectedMemberItems]) => {
emit('change-form', {
name: nameVal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import type { NotificationProtocolModel } from '@/schema/alert-manager/notificat
import type { ServiceChannelListParameters } from '@/schema/alert-manager/service-channel/api-verbs/list';
import { SERVICE_CHANNEL_STATE } from '@/schema/alert-manager/service-channel/constants';
import type { ServiceChannelModel } from '@/schema/alert-manager/service-channel/model';
import type { WebhookModel } from '@/schema/alert-manager/webhook/model';
import { i18n as _i18n } from '@/translations';
import { useAllReferenceStore } from '@/store/reference/all-reference-store';
Expand All @@ -37,6 +36,12 @@ import ErrorHandler from '@/common/composables/error/errorHandler';
import { useProperRouteLocation } from '@/common/composables/proper-route-location';
import { useQueryTags } from '@/common/composables/query-tags';
import ServiceDetailTabsNotificationsDeleteModal
from '@/services/alert-manager-v2/components/ServiceDetailTabsNotificationsDeleteModal.vue';
import ServiceDetailTabsNotificationsTableModal
from '@/services/alert-manager-v2/components/ServiceDetailTabsNotificationsTableModal.vue';
import ServiceDetailTabsNotificationsUpdateModal
from '@/services/alert-manager-v2/components/ServiceDetailTabsNotificationsUpdateModal.vue';
import { alertManagerStateFormatter } from '@/services/alert-manager-v2/composables/refined-table-data';
import { SERVICE_TAB_HEIGHT } from '@/services/alert-manager-v2/constants/common-constant';
import {
Expand All @@ -46,7 +51,7 @@ import {
} from '@/services/alert-manager-v2/constants/notification-table-constant';
import { ALERT_MANAGER_ROUTE_V2 } from '@/services/alert-manager-v2/routes/route-constant';
import { useServiceDetailPageStore } from '@/services/alert-manager-v2/stores/service-detail-page-store';
import type { ProtocolInfo } from '@/services/alert-manager-v2/types/alert-manager-type';
import type { ProtocolInfo, NotificationsModalType } from '@/services/alert-manager-v2/types/alert-manager-type';
interface Props {
tableHeight: number;
Expand All @@ -71,25 +76,25 @@ const tableState = reactive({
actionMenu: computed<MenuItem[]>(() => ([
{
type: 'item',
name: 'enable',
name: 'ENABLE',
label: _i18n.t('ALERT_MANAGER.ENABLE'),
disabled: state.selectedItem?.state === SERVICE_CHANNEL_STATE.ENABLED,
},
{
type: 'item',
name: 'disable',
name: 'DISABLE',
label: _i18n.t('ALERT_MANAGER.DISABLED'),
disabled: state.selectedItem?.state === SERVICE_CHANNEL_STATE.DISABLED,
},
{ type: 'divider' },
{
type: 'item',
name: 'update',
name: 'UPDATE',
label: _i18n.t('ALERT_MANAGER.UPDATE'),
},
{
type: 'item',
name: 'delete',
name: 'DELETE',
label: _i18n.t('ALERT_MANAGER.DELETE'),
},
])),
Expand All @@ -106,7 +111,11 @@ const state = reactive({
items: [] as ServiceChannelModel[],
totalCount: 0,
selectIndex: undefined as number|undefined,
selectedItem: computed<WebhookModel>(() => state.items[state.selectIndex]),
selectedItem: computed<ServiceChannelModel>(() => state.items[state.selectIndex]),
});
const modalState = reactive({
visible: false,
type: undefined as NotificationsModalType|undefined,
});
const notificationsListApiQueryHelper = new ApiQueryHelper().setSort('created_at', true)
Expand All @@ -122,13 +131,19 @@ const getProtocolInfo = (id: string): ProtocolInfo => {
icon: plugin?.icon || '',
};
};
const handleCloseModal = () => {
state.selectIndex = undefined;
fetchNotificationList();
serviceDetailPageStore.setSelectedNotificationId(undefined);
};
const handleClickCreateButton = () => {
router.push(getProperRouteLocation({
name: ALERT_MANAGER_ROUTE_V2.SERVICE.DETAIL.NOTIFICATIONS.CREATE._NAME,
}));
};
const handleSelectDropdownItem = (name) => {
console.log('TODO: handleSelectDropdownItem', name);
const handleSelectDropdownItem = (name: NotificationsModalType) => {
modalState.visible = true;
modalState.type = name;
};
const handleChangeToolbox = async (options: any = {}) => {
if (options.queryTags !== undefined) queryTagHelper.setQueryTags(options.queryTags);
Expand Down Expand Up @@ -185,70 +200,89 @@ onUnmounted(() => {
</script>

<template>
<p-toolbox-table class="service-detail-tabs-notifications"
search-type="query"
selectable
sortable
exportable
:multi-select="false"
:loading="state.loading"
:total-count="state.totalCount"
:items="state.items"
:fields="tableState.fields"
:select-index="[state.selectIndex]"
:query-tags="queryTags"
:key-item-sets="NOTIFICATION_MANAGEMENT_TABLE_HANDLER.keyItemSets"
:value-handler-map="NOTIFICATION_MANAGEMENT_TABLE_HANDLER.valueHandlerMap"
:style="{height: `${props.tableHeight - SERVICE_TAB_HEIGHT}px`}"
@change="handleChangeToolbox"
@refresh="handleChangeToolbox()"
@export="handleExportExcel"
@select="handleSelectTableRow"
>
<template #toolbox-top>
<p-heading-layout class="pt-8 px-4">
<template #heading>
<p-heading heading-type="sub"
use-total-count
:total-count="state.totalCount"
:title="$t('ALERT_MANAGER.NOTIFICATIONS.TITLE')"
<div>
<p-toolbox-table class="service-detail-tabs-notifications"
search-type="query"
selectable
sortable
exportable
:multi-select="false"
:loading="state.loading"
:total-count="state.totalCount"
:items="state.items"
:fields="tableState.fields"
:select-index="[state.selectIndex]"
:query-tags="queryTags"
:key-item-sets="NOTIFICATION_MANAGEMENT_TABLE_HANDLER.keyItemSets"
:value-handler-map="NOTIFICATION_MANAGEMENT_TABLE_HANDLER.valueHandlerMap"
:style="{height: `${props.tableHeight - SERVICE_TAB_HEIGHT}px`}"
@change="handleChangeToolbox"
@refresh="handleChangeToolbox()"
@export="handleExportExcel"
@select="handleSelectTableRow"
>
<template #toolbox-top>
<p-heading-layout class="pt-8 px-4">
<template #heading>
<p-heading heading-type="sub"
use-total-count
:total-count="state.totalCount"
:title="$t('ALERT_MANAGER.NOTIFICATIONS.TITLE')"
/>
</template>
<template #extra>
<p-button style-type="primary"
icon-left="ic_plus_bold"
@click="handleClickCreateButton"
>
{{ $t('ALERT_MANAGER.CREATE') }}
</p-button>
</template>
</p-heading-layout>
</template>
<template #toolbox-left>
<p-select-dropdown :menu="tableState.actionMenu"
:disabled="!state.selectedItem"
reset-selection-on-menu-close
:placeholder="$t('ALERT_MANAGER.ACTION')"
@select="handleSelectDropdownItem"
/>
</template>
<template #col-state-format="{ value }">
<p-status
class="capitalize"
v-bind="alertManagerStateFormatter(value)"
/>
</template>
<template #col-protocol_id-format="{value}">
<div class="col-channel">
<p-lazy-img :src="assetUrlConverter(getProtocolInfo(value).icon)"
width="1rem"
height="1rem"
class="service-img"
/>
</template>
<template #extra>
<p-button style-type="primary"
icon-left="ic_plus_bold"
@click="handleClickCreateButton"
>
{{ $t('ALERT_MANAGER.CREATE') }}
</p-button>
</template>
</p-heading-layout>
</template>
<template #toolbox-left>
<p-select-dropdown :menu="tableState.actionMenu"
:disabled="!state.selectedItem"
reset-selection-on-menu-close
:placeholder="$t('ALERT_MANAGER.ACTION')"
@select="handleSelectDropdownItem"
<span>{{ getProtocolInfo(value).name }}</span>
</div>
</template>
</p-toolbox-table>
<div v-if="modalState.visible">
<service-detail-tabs-notifications-update-modal v-if="modalState.type === 'UPDATE'"
:visible.sync="modalState.visible"
:selected-item="state.selectedItem"
@close="handleCloseModal"
/>
</template>
<template #col-state-format="{ value }">
<p-status
class="capitalize"
v-bind="alertManagerStateFormatter(value)"
<service-detail-tabs-notifications-delete-modal v-else-if="modalState.type === 'DELETE'"
:visible.sync="modalState.visible"
:selected-item="state.selectedItem"
@close="handleCloseModal"
/>
</template>
<template #col-protocol_id-format="{value}">
<div class="col-channel">
<p-lazy-img :src="assetUrlConverter(getProtocolInfo(value).icon)"
width="1rem"
height="1rem"
class="service-img"
/>
<span>{{ getProtocolInfo(value).name }}</span>
</div>
</template>
</p-toolbox-table>
<service-detail-tabs-notifications-table-modal v-else
:visible.sync="modalState.visible"
:selected-item="state.selectedItem"
@close="handleCloseModal"
/>
</div>
</div>
</template>

<style scoped lang="postcss">
Expand Down
Loading

0 comments on commit fbdde5d

Please sign in to comment.