Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: apply API at service detail header (edit / delete) #5211

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading