Skip to content

Commit

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

feat: apply alert manager v2
  • Loading branch information
skdud4659 authored Jan 9, 2025
2 parents b03c42a + fa0a009 commit 6df4b59
Show file tree
Hide file tree
Showing 701 changed files with 74,361 additions and 4,464 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<script lang="ts" setup>
import {
computed, reactive, ref, watch,
} from 'vue';
import {
PFieldGroup, PRadioGroup, PRadio,
} from '@cloudforet/mirinae';
import type { MenuItem } from '@cloudforet/mirinae/types/inputs/context-menu/type';
import { i18n } from '@/translations';
import UserSelectDropdown from '@/common/modules/user/UserSelectDropdown.vue';
import { useNotificationChannelCreateFormStore } from '@/services/iam/store/notification-channel-create-form-store';
const notificationChannelCreateFormStore = useNotificationChannelCreateFormStore();
const notificationChannelCreateFormState = notificationChannelCreateFormStore.state;
const USER_MODE = {
ALL_MEMBER: 'ALL_MEMBER',
USER_GROUP: 'USER_GROUP',
USER: 'USER',
};
const SHOW_TYPE = {
USER_LIST: 'userList',
USER_GROUP_LIST: 'userGroupList',
};
const showType = ref<string>();
const selectedIds = ref<any>([]);
const state = reactive({
userMode: computed<MenuItem[]>(() => [{
label: i18n.t('IAM.USER_GROUP.MODAL.CREATE_CHANNEL.DESC.USER_MODE.ALL_MEMBERS'),
name: USER_MODE.ALL_MEMBER,
}, {
label: i18n.t('IAM.USER_GROUP.MODAL.CREATE_CHANNEL.DESC.USER_MODE.USER_GROUP'),
name: USER_MODE.USER_GROUP,
}, {
label: i18n.t('IAM.USER_GROUP.MODAL.CREATE_CHANNEL.DESC.USER_MODE.SPECIFIC_USER'),
name: USER_MODE.USER,
}]),
selectedUserModeIdx: 0,
});
/* Component */
const handleChange = (idx: number) => {
state.selectedUserModeIdx = idx;
};
const handleSelectedIds = (value) => {
selectedIds.value = value;
};
/* Watcher */
watch(() => state.userMode[state.selectedUserModeIdx], (nv_userMode) => {
showType.value = nv_userMode?.name === USER_MODE.USER_GROUP ? SHOW_TYPE.USER_GROUP_LIST : SHOW_TYPE.USER_LIST;
}, { deep: true, immediate: true });
watch(() => state.selectedUserModeIdx, async (nv_selectedIdx, ov_selectedIdx) => {
if (nv_selectedIdx !== ov_selectedIdx) {
selectedIds.value = [];
}
});
watch(() => state.selectedUserModeIdx, (nv_selected_idx) => {
if (nv_selected_idx === 0) {
notificationChannelCreateFormState.userInfo.type = 'ALL_MEMBER';
} else if (nv_selected_idx === 1) {
notificationChannelCreateFormState.userInfo.type = 'USER_GROUP';
} else {
notificationChannelCreateFormState.userInfo.type = 'USER';
}
});
watch([() => notificationChannelCreateFormState.userInfo.type, () => notificationChannelCreateFormState.userInfo.value], () => {
// TODO: Retrieving a list of existing users
// if (nv_user_info_type) {
// if (nv_user_info_type !== 'ALL_MEMBER') {
// state.selectedUserModeIdx = nv_user_info_type === 'USER_GROUP' ? 1 : 2;
//
// selectedIds.value = {
// type: nv_user_info_type,
// value: nv_user_info_value,
// };
// } else {
// state.selectedUserModeIdx = 0;
// }
// }
}, { immediate: true, deep: true });
watch(selectedIds, (nv_selected_ids) => {
const result: string[] = [];
nv_selected_ids.forEach((id) => {
result.push(id.value);
});
notificationChannelCreateFormState.userInfo.value = result;
}, { immediate: true });
</script>

<template>
<p-field-group :label="$t('IAM.USER_GROUP.MODAL.CREATE_CHANNEL.DESC.USER_MODE.TITLE')"
required
>
<p-radio-group>
<p-radio v-for="(mode, idx) in state.userMode"
:key="`${mode.name}-${idx}`"
v-model="state.selectedUserModeIdx"
:value="idx"
@handle="handleChange"
>
{{ mode.label }}
</p-radio>
</p-radio-group>
<user-select-dropdown class="mt-2"
:show-user-list="showType === SHOW_TYPE.USER_LIST"
:show-user-group-list="showType === SHOW_TYPE.USER_GROUP_LIST"
:disabled="state.userMode[state.selectedUserModeIdx].name === USER_MODE.ALL_MEMBER"
appearance-type="stack"
selection-type="multiple"
:selected-ids="selectedIds"
@update:selected-ids="handleSelectedIds"
/>
</p-field-group>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<script lang="ts" setup>
import {
computed, onMounted, reactive, watch,
} from 'vue';
import { range, zipObject } from 'lodash';
import {
PFieldGroup, PRadioGroup, PRadio, PI, PSelectButton, PSelectDropdown,
} from '@cloudforet/mirinae';
import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/types/controls/dropdown/select-dropdown/type';
import type { ServiceChannelScheduleType } from '@/schema/alert-manager/service-channel/type';
import { i18n } from '@/translations';
import { useUserStore } from '@/store/user/user-store';
import type {
ScheduleDayButtonType,
ScheduleRadioType,
DayType,
ScheduleSettingFormType,
ScheduleFormDayType,
} from '@/common/components/schedule-setting-form/schedule-setting-form';
import { blue } from '@/styles/colors';
interface Props {
scheduleForm?: ScheduleSettingFormType;
}
const props = withDefaults(defineProps<Props>(), {
scheduleForm: undefined,
});
const userStore = useUserStore();
const userState = userStore.state;
const emit = defineEmits<{(e: 'update-form', form: ScheduleSettingFormType): void; }>();
const storeState = reactive({
timezone: computed(() => userState.timezone || 'UTC'),
});
const state = reactive({
scheduleTypeList: computed<ScheduleRadioType[]>(() => [
{ name: 'WEEK_DAY', label: i18n.t('COMMON.SCHEDULE_SETTING.WEEKDAYS') },
{ name: 'ALL_DAY', label: i18n.t('COMMON.SCHEDULE_SETTING.EVERYDAY') },
{ name: 'CUSTOM', label: i18n.t('COMMON.SCHEDULE_SETTING.CUSTOM') },
]),
selectedRadioIdx: 0,
days: computed<ScheduleDayButtonType[]>(() => [
{ name: 'MON', label: i18n.t('COMMON.SCHEDULE_SETTING.MON') },
{ name: 'TUE', label: i18n.t('COMMON.SCHEDULE_SETTING.TUE') },
{ name: 'WED', label: i18n.t('COMMON.SCHEDULE_SETTING.WED') },
{ name: 'THU', label: i18n.t('COMMON.SCHEDULE_SETTING.THU') },
{ name: 'FRI', label: i18n.t('COMMON.SCHEDULE_SETTING.FRI') },
{ name: 'SAT', label: i18n.t('COMMON.SCHEDULE_SETTING.SAT') },
{ name: 'SUN', label: i18n.t('COMMON.SCHEDULE_SETTING.SUN') },
]),
selectedDayButton: ['MON', 'TUE', 'WED', 'THU', 'FRI'] as DayType[],
start: 0,
end: 24,
startHourTimeList: computed<SelectDropdownMenuItem[]>(() => range(0, state.end).map((h) => ({
label: `${h.toString().padStart(2, '0')}:00`,
name: h.toString(),
}))),
endHourTimeList: computed<SelectDropdownMenuItem[]>(() => range(Number(state.start) + 1, 25).map((h) => ({
label: `${h.toString().padStart(2, '0')}:00`,
name: h.toString(),
}))),
scheduleDayForm: computed<Record<DayType, ScheduleFormDayType>>(() => {
const refinedDays = state.days.map((day) => ({
is_scheduled: state.selectedDayButton.includes(day.name),
start: state.start,
end: state.end,
}));
return zipObject(state.days.map((i) => i.name), refinedDays) as Record<DayType, ScheduleFormDayType>;
}),
});
const initScheduleForm = () => {
if (!props.scheduleForm) return;
state.selectedRadioIdx = state.scheduleTypeList.findIndex((item) => item.name === props.scheduleForm?.SCHEDULE_TYPE) || 0;
let filteredSchedule: string[] = [];
if (state.selectedRadioIdx === 0) {
filteredSchedule = state.days.slice(0, 5).map((day) => day.name);
} else if (state.selectedRadioIdx === 1) {
filteredSchedule = state.days.map((day) => day.name);
} else {
filteredSchedule = state.days.filter((day) => {
if (!props.scheduleForm) return [];
const schedule = props.scheduleForm[day.name];
return schedule?.is_scheduled;
}).map((i) => i.name);
}
state.selectedDayButton = filteredSchedule;
state.start = props.scheduleForm[filteredSchedule[0]]?.start || 0;
state.end = props.scheduleForm[filteredSchedule[0]]?.end || 24;
};
const handleSelectScheduleType = (type: ServiceChannelScheduleType) => {
if (type === 'WEEK_DAY') {
state.selectedDayButton = state.days.slice(0, 5).map((day) => day.name);
} else if (type === 'ALL_DAY') {
state.selectedDayButton = state.days.map((day) => day.name);
} else {
state.selectedDayButton = [];
}
};
const handleSelectDayButton = (value: DayType[]) => {
state.selectedRadioIdx = 2;
state.selectedDayButton = value;
};
const handleSelectDropdown = (type: 'start' | 'end', value: number) => {
if (type === 'start') {
state.start = value || 0;
} else {
state.end = value || 0;
}
};
watch([() => state.selectedRadioIdx, () => state.selectedDayButton, () => state.start, () => state.end], ([selectedRadioIdx]) => {
emit('update-form', {
SCHEDULE_TYPE: state.scheduleTypeList[selectedRadioIdx].name,
TIMEZONE: storeState.timezone,
...state.scheduleDayForm,
});
}, { immediate: true });
onMounted(() => {
if (props.scheduleForm) {
initScheduleForm();
}
});
</script>

<template>
<div class="schedule-setting-form flex flex-col">
<p-field-group :label="$t('COMMON.SCHEDULE_SETTING.SCHEDULE_SETTING')"
required
>
<p-radio-group direction="horizontal">
<p-radio v-for="(item, index) in state.scheduleTypeList"
:key="`schedule-setting-${index}`"
v-model="state.selectedRadioIdx"
:value="index"
@change="handleSelectScheduleType(item.name)"
>
{{ item.label }}
</p-radio>
</p-radio-group>
<div class="flex gap-1 py-2 px-0.5">
<p-i name="ic_info-circle"
:color="blue[600]"
width="0.875rem"
height="0.875rem"
/>
<p class="text-xs text-blue-600">
{{ $t('COMMON.SCHEDULE_SETTING.INFO') }}
</p>
</div>
<div class="w-full overflow py-4 flex flex-wrap gap-2">
<p-select-button v-for="(item, index) in state.days"
:key="`schedule-days-${index}`"
v-model="state.selectedDayButton"
multi-selectable
:value="item.name"
@change="handleSelectDayButton"
>
{{ item.label }}
</p-select-button>
</div>
<div class="flex items-center gap-2">
<p-select-dropdown :menu="state.startHourTimeList"
:selected="state.start"
:placeholder="state.startHourTimeList[state.start].label"
@select="handleSelectDropdown('start', $event)"
/>
<span>{{ $t('COMMON.SCHEDULE_SETTING.TO') }}</span>
<p-select-dropdown :menu="state.endHourTimeList"
:selected="state.end"
:placeholder="state.endHourTimeList[state.end - state.start - 1].label"
@select="handleSelectDropdown('end', $event)"
/>
</div>
</p-field-group>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { TranslateResult } from 'vue-i18n';

export type ScheduleType = 'ALL_DAY' | 'WEEK_DAY' | 'WEEKEND' | 'CUSTOM';
export type DayType = 'MON' | 'TUE' | 'WED' | 'THU' | 'FRI' | 'SAT' | 'SUN';

export type ScheduleRadioType = {
name: ScheduleType;
label: TranslateResult;
};
export type ScheduleDayButtonType = {
name: DayType;
label: TranslateResult;
};

type ScheduleFormType = {
SCHEDULE_TYPE: ScheduleType;
};
export type ScheduleFormDayType = {
is_scheduled: boolean;
start: number;
end: number;
};

export type ScheduleSettingFormType = ScheduleFormType & Partial<Record<DayType, ScheduleFormDayType>> & {
TIMEZONE: string;
};
Loading

0 comments on commit 6df4b59

Please sign in to comment.