Skip to content

Commit

Permalink
feat: apply API at service detail header (edit / delete) (#5211)
Browse files Browse the repository at this point in the history
Signed-off-by: NaYeong,Kim <[email protected]>
  • Loading branch information
skdud4659 authored Dec 11, 2024
1 parent b366de2 commit efc353b
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script setup lang="ts">
import { reactive } from 'vue';
import { useRouter } from 'vue-router/composables';
import { PButtonModal } from '@cloudforet/mirinae';
import { useProperRouteLocation } from '@/common/composables/proper-route-location';
import { useProxyValue } from '@/common/composables/proxy-state';
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';
interface Props {
visible: boolean;
}
const props = withDefaults(defineProps<Props>(), {
visible: false,
});
const serviceDetailPageStore = useServiceDetailPageStore();
const router = useRouter();
const { getProperRouteLocation } = useProperRouteLocation();
const emit = defineEmits<{(e: 'update:visible'): void; }>();
const state = reactive({
loading: false,
proxyVisible: useProxyValue('visible', props, emit),
});
const handleConfirm = () => {
state.loading = true;
try {
serviceDetailPageStore.deleteServiceDetailData();
router.push(getProperRouteLocation({ name: ALERT_MANAGER_ROUTE_V2.SERVICE._NAME }));
} finally {
state.loading = false;
handleClose();
}
};
const handleClose = () => {
state.proxyVisible = false;
};
</script>

<template>
<p-button-modal class="service-detail-delete-modal"
:header-title="$t('ALERT_MANAGER.SERVICE.MODAL_DELETE_TITLE')"
size="sm"
theme-color="alert"
:fade="true"
:backdrop="true"
:visible="state.proxyVisible"
:loading="state.loading"
@confirm="handleConfirm"
@cancel="handleClose"
@close="handleClose"
/>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<script setup lang="ts">
import { computed, onMounted, reactive } from 'vue';
import { PButtonModal, PFieldGroup, PTextInput } from '@cloudforet/mirinae';
import type { ServiceModel } from '@/schema/alert-manager/service/model';
import { i18n } from '@/translations';
import { useFormValidator } from '@/common/composables/form-validator';
import { useProxyValue } from '@/common/composables/proxy-state';
import { useServiceDetailPageStore } from '@/services/alert-manager-v2/stores/service-detail-page-store';
interface Props {
visible: boolean;
}
const props = withDefaults(defineProps<Props>(), {
visible: false,
});
const serviceDetailPageStore = useServiceDetailPageStore();
const serviceDetailPageState = serviceDetailPageStore.state;
const serviceDetailPageGetters = serviceDetailPageStore.getters;
const emit = defineEmits<{(e: 'update:visible'): void; }>();
const storeState = reactive({
serviceList: computed<ServiceModel[]>(() => serviceDetailPageState.serviceList),
serviceName: computed<string>(() => serviceDetailPageGetters.serviceInfo.name),
});
const state = reactive({
loading: false,
proxyVisible: useProxyValue('visible', props, emit),
});
const {
forms: {
name,
},
setForm,
invalidState,
invalidTexts,
isAllValid,
} = useFormValidator({
name: storeState.serviceName,
}, {
name(value: string) {
if (!value) return ' ';
const duplicatedName = storeState.serviceList?.find((item) => item.name === value);
if (duplicatedName) {
return i18n.t('ALERT_MANAGER.SERVICE.VALIDATION_NAME_UNIQUE');
}
return '';
},
});
const handleConfirm = async () => {
state.loading = true;
try {
await serviceDetailPageStore.updateServiceDetailData(name.value);
} finally {
state.loading = false;
handleClose();
}
};
const handleClose = () => {
state.proxyVisible = false;
};
onMounted(() => {
serviceDetailPageStore.fetchServiceList();
});
</script>

<template>
<p-button-modal class="service-detail-edit-modal"
:header-title="$t('ALERT_MANAGER.SERVICE.MODAL_EDIT_TITLE')"
size="sm"
:fade="true"
:backdrop="true"
:visible="state.proxyVisible"
:disabled="!isAllValid"
:loading="state.loading"
@confirm="handleConfirm"
@cancel="handleClose"
@close="handleClose"
>
<template #body>
<div class="form-contents">
<p-field-group :label="$t('ALERT_MANAGER.SERVICE.LABEL_SERVICE_NAME')"
:invalid="invalidState.name"
:invalid-text="invalidTexts.name"
class="input-form"
required
>
<p-text-input :value="name"
:invalid="invalidState.name"
class="text-input"
block
@update:value="setForm('name', $event)"
/>
</p-field-group>
</div>
</template>
</p-button-modal>
</template>
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
<script setup lang="ts">
import { computed, defineProps, reactive } from 'vue';
import { computed, reactive } from 'vue';
import { useRouter } from 'vue-router/composables';
import {
PHeading, PHeadingLayout, PSelectDropdown, PLink, PI,
} from '@cloudforet/mirinae';
import type { MenuItem } from '@cloudforet/mirinae/src/controls/context-menu/type';
import { MEMBERS_TYPE } from '@/schema/alert-manager/service/constants';
import { i18n } from '@/translations';
import { useProperRouteLocation } from '@/common/composables/proper-route-location';
import { gray } from '@/styles/colors';
interface Props {
serviceId: string;
}
import ServiceDetailDeleteModal from '@/services/alert-manager-v2/components/ServiceDetailDeleteModal.vue';
import ServiceDetailEditModal from '@/services/alert-manager-v2/components/ServiceDetailEditModal.vue';
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 { Service } from '@/services/alert-manager-v2/types/alert-manager-type';
const props = withDefaults(defineProps<Props>(), {
serviceId: '',
});
type ModalType = 'edit' | 'delete';
const serviceDetailPageStore = useServiceDetailPageStore();
const serviceDetailPageGetters = serviceDetailPageStore.getters;
const router = useRouter();
const { getProperRouteLocation } = useProperRouteLocation();
const storeState = reactive({
serviceInfo: computed<Service>(() => serviceDetailPageGetters.serviceInfo),
});
const state = reactive({
menuItems: computed<MenuItem[]>(() => [
{
Expand All @@ -32,18 +46,27 @@ const state = reactive({
},
]),
});
const modalState = reactive({
modalVisible: false,
type: '' as ModalType,
});
const handleSelectDropdownMenu = () => {
console.log('TODO: handleSelectDropdownMenu');
const handleSelectDropdownMenu = (type: ModalType) => {
modalState.modalVisible = true;
modalState.type = type;
};
const handleGoBackButton = () => {
router.push(getProperRouteLocation({ name: ALERT_MANAGER_ROUTE_V2.SERVICE._NAME }));
};
</script>

<template>
<div class="service-detail-header">
<p-heading-layout>
<template #heading>
<p-heading :title="props.serviceId"
<p-heading :title="storeState.serviceInfo.name"
show-back-button
@click-back-button="handleGoBackButton"
>
<template #title-right-extra>
<p-select-dropdown :menu="state.menuItems"
Expand All @@ -59,7 +82,7 @@ const handleSelectDropdownMenu = () => {
</p-heading>
</template>
<template #extra>
<p-link :to="undefined"
<p-link :to="getProperRouteLocation({ name: ALERT_MANAGER_ROUTE_V2.ALERTS._NAME })"
action-icon="internal-link"
new-tab
class="text-label-md"
Expand All @@ -69,41 +92,35 @@ const handleSelectDropdownMenu = () => {
</template>
</p-heading-layout>
<div class="service-info-wrapper">
<div class="info">
<div class="flex items-center text-gray-700 gap-0.5">
<p-i class="select-marker"
name="ic_member"
width="0.75rem"
height="0.75rem"
/>
<span>3</span>
<span>{{ storeState.serviceInfo.members[MEMBERS_TYPE.USER_GROUP]?.length }}</span>
<span>{{ $t('ALERT_MANAGER.SERVICE.USER_GROUP') }}</span>
</div>
<p-i name="ic_dot"
width="0.125rem"
height="0.125rem"
:color="gray[500]"
class="dot"
/>
<div class="info">
<p-i class="select-marker"
name="ic_member"
width="0.75rem"
height="0.75rem"
/>
<span>3</span>
<span> / </span>
<span>{{ storeState.serviceInfo.members[MEMBERS_TYPE.USER]?.length }}</span>
<span>{{ $t('ALERT_MANAGER.SERVICE.MEMBERS') }}</span>
</div>
<!-- TODO: apply visibility only when desc data is available-->
<p-i name="ic_dot"
<p-i v-if="storeState.serviceInfo?.description"
name="ic_dot"
width="0.125rem"
height="0.125rem"
:color="gray[500]"
class="dot"
/>
<p class="truncate">
temp desc
<p class="truncate flex-1">
{{ storeState.serviceInfo?.description }}
</p>
</div>
<service-detail-edit-modal v-if="modalState.type === 'edit'"
:visible.sync="modalState.modalVisible"
/>
<service-detail-delete-modal v-if="modalState.type === 'delete'"
:visible.sync="modalState.modalVisible"
/>
</div>
</template>

Expand All @@ -116,10 +133,6 @@ const handleSelectDropdownMenu = () => {
@apply flex items-center text-label-sm;
padding-left: 2.5rem;
gap: 0.5rem;
.info {
@apply flex items-center text-gray-700;
gap: 0.125rem;
}
}
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { defineStore } from 'pinia';

import { SpaceConnector } from '@cloudforet/core-lib/space-connector';

import type { ListResponse } from '@/schema/_common/api-verbs/list';
import type { ServiceDeleteParameters } from '@/schema/alert-manager/service/api-verbs/delete';
import type { ServiceGetParameters } from '@/schema/alert-manager/service/api-verbs/get';
import type { ServiceListParameters } from '@/schema/alert-manager/service/api-verbs/list';
import type { ServiceUpdateParameters } from '@/schema/alert-manager/service/api-verbs/update';
import { NOTIFICATION_URGENCY, RECOVERY_MODE } from '@/schema/alert-manager/service/constants';
import type { ServiceModel } from '@/schema/alert-manager/service/model';

Expand All @@ -17,13 +21,15 @@ interface ServiceFormStoreState {
loading: boolean;
currentTab: ServiceDetailTabsType;
serviceInfo: ServiceModel;
serviceList: ServiceModel[];
}

export const useServiceDetailPageStore = defineStore('page-service-detail', () => {
const state = reactive<ServiceFormStoreState>({
loading: false,
currentTab: SERVICE_DETAIL_TABS.OVERVIEW,
serviceInfo: {} as ServiceModel,
serviceList: [] as ServiceModel[],
});

const getters = reactive({
Expand Down Expand Up @@ -68,6 +74,35 @@ export const useServiceDetailPageStore = defineStore('page-service-detail', () =
state.loading = false;
}
},
async updateServiceDetailData(name: string) {
try {
state.serviceInfo = await SpaceConnector.clientV2.alertManager.service.update<ServiceUpdateParameters, ServiceModel>({
service_id: getters.serviceInfo.service_id,
name,
});
} catch (e) {
ErrorHandler.handleError(e, true);
state.serviceInfo = {} as ServiceModel;
}
},
async deleteServiceDetailData() {
try {
await SpaceConnector.clientV2.alertManager.service.delete<ServiceDeleteParameters>({
service_id: getters.serviceInfo.service_id,
});
} catch (e) {
ErrorHandler.handleError(e, true);
}
},
async fetchServiceList() {
try {
const { results } = await SpaceConnector.clientV2.alertManager.service.list<ServiceListParameters, ListResponse<ServiceModel>>();
state.serviceList = results || [];
} catch (e) {
ErrorHandler.handleError(e);
state.serviceList = [];
}
},
};

return {
Expand Down

0 comments on commit efc353b

Please sign in to comment.