From cd267e450280a08ede53ec55e304c49d707911a9 Mon Sep 17 00:00:00 2001 From: nayeongkim Date: Wed, 21 May 2025 15:33:19 +0900 Subject: [PATCH 01/33] fix: fixed time bug Signed-off-by: NaYeong,Kim --- .../components/ServiceAccountAttachedGeneralAccounts.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue b/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue index b63a64a854..2be95421b3 100644 --- a/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue +++ b/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue @@ -78,7 +78,7 @@ const state = reactive({ loading: true, syncReqLoading: false, items: [] as any, - sortBy: 'name', + sortBy: 'created_at', sortDesc: true, totalCount: 0, pageLimit: 15, @@ -377,7 +377,7 @@ watch(() => state.trustedAccountId, async (ta) => { From 7d233c1d003b38be596e877f68d25c9c11e49925 Mon Sep 17 00:00:00 2001 From: nayeongkim Date: Thu, 22 May 2025 10:48:42 +0900 Subject: [PATCH 02/33] feat: add filed at service account attached general accounts table Signed-off-by: NaYeong,Kim --- .../components/ServiceAccountAttachedGeneralAccounts.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue b/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue index 2be95421b3..e00ab12e80 100644 --- a/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue +++ b/apps/web/src/services/service-account/components/ServiceAccountAttachedGeneralAccounts.vue @@ -112,6 +112,7 @@ const state = reactive({ { name: 'state', label: 'State', sortable: false }, { name: 'workspace_id', label: 'Workspace', sortable: false }, { name: 'project_id', label: 'Project', sortable: false }, + { name: 'last_synced_at', label: 'Last Synced', sortable: false }, { name: 'created_at', label: 'Created', sortable: false }, ]; }), @@ -376,6 +377,9 @@ watch(() => state.trustedAccountId, async (ta) => { + From b7143e773258379a227b7fe84501f25af53935c0 Mon Sep 17 00:00:00 2001 From: nayeongkim Date: Wed, 28 May 2025 16:29:18 +0900 Subject: [PATCH 03/33] fix: status bar visibility bug fix Signed-off-by: NaYeong,Kim --- .../components/CollectorHistoryJobStatusChart.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/services/asset-inventory/components/CollectorHistoryJobStatusChart.vue b/apps/web/src/services/asset-inventory/components/CollectorHistoryJobStatusChart.vue index c30f7b3af9..f0b3cde813 100644 --- a/apps/web/src/services/asset-inventory/components/CollectorHistoryJobStatusChart.vue +++ b/apps/web/src/services/asset-inventory/components/CollectorHistoryJobStatusChart.vue @@ -29,13 +29,13 @@ const props = withDefaults(defineProps(), { const state = reactive({ succeededPercentage: computed(() => { - if (props.job.total_tasks > 0) { + if (props.job.total_tasks > 0 && props.job.success_tasks) { return (props.job.success_tasks / props.job.total_tasks) * 100; } return 0; }), failedPercentage: computed(() => { - if (props.job.total_tasks > 0) { + if (props.job.total_tasks > 0 && props.job.failure_tasks) { if (props.job.status === JOB_STATE.SUCCESS) { return 100 - state.succeededPercentage; } From 3d16634df4da03ee152d3b8539aa1f1317d453f2 Mon Sep 17 00:00:00 2001 From: nayeongkim Date: Wed, 28 May 2025 16:36:30 +0900 Subject: [PATCH 04/33] fix: bug fix for missing domain Signed-off-by: NaYeong,Kim --- apps/web/src/lib/site-initializer/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/lib/site-initializer/index.ts b/apps/web/src/lib/site-initializer/index.ts index e0344085b5..12b8c922fb 100644 --- a/apps/web/src/lib/site-initializer/index.ts +++ b/apps/web/src/lib/site-initializer/index.ts @@ -59,11 +59,11 @@ const initRouter = (domainId?: string) => { )?.children; const featureRoutes = globalConfigSchemaStore.state.routeSchema; - if (adminChildren) { + if (featureRoutes.adminRoutes && adminChildren) { adminChildren.push(...featureRoutes.adminRoutes); } - if (workspaceChildren) { + if (featureRoutes.routes && workspaceChildren) { workspaceChildren.push(...featureRoutes.routes); } From b2e16aa278e909162174876d32eb9cb0570c3f30 Mon Sep 17 00:00:00 2001 From: Dahyun Yu Date: Wed, 30 Apr 2025 16:43:17 +0900 Subject: [PATCH 05/33] chore: remove subpages and display all components in the parent page (#5827) Signed-off-by: yuda --- .../AdvancedSettingsCurrencyConverter.vue} | 14 ++++++++--- .../admin/AdminAdvancedSettingsPage.vue} | 11 ++++---- .../cost-explorer/routes/admin/routes.ts | 25 ++----------------- .../console-translation-2.8.babel | 21 ++++++++++++++++ packages/language-pack/en.json | 1 + packages/language-pack/ja.json | 1 + packages/language-pack/ko.json | 1 + 7 files changed, 43 insertions(+), 31 deletions(-) rename apps/web/src/services/cost-explorer/{pages/admin/AdminAdvancedSettingsCurrencyConverterPage.vue => components/AdvancedSettingsCurrencyConverter.vue} (95%) rename apps/web/src/services/cost-explorer/{components/CostAdvancedSettingsContainer.vue => pages/admin/AdminAdvancedSettingsPage.vue} (77%) diff --git a/apps/web/src/services/cost-explorer/pages/admin/AdminAdvancedSettingsCurrencyConverterPage.vue b/apps/web/src/services/cost-explorer/components/AdvancedSettingsCurrencyConverter.vue similarity index 95% rename from apps/web/src/services/cost-explorer/pages/admin/AdminAdvancedSettingsCurrencyConverterPage.vue rename to apps/web/src/services/cost-explorer/components/AdvancedSettingsCurrencyConverter.vue index 1a7892bdb9..6d2f198fef 100644 --- a/apps/web/src/services/cost-explorer/pages/admin/AdminAdvancedSettingsCurrencyConverterPage.vue +++ b/apps/web/src/services/cost-explorer/components/AdvancedSettingsCurrencyConverter.vue @@ -6,7 +6,7 @@ import { import dayjs from 'dayjs'; import { - PFieldGroup, PCheckbox, PRadioGroup, PRadio, PBadge, + PFieldGroup, PCheckbox, PRadioGroup, PRadio, PBadge, PHeading, PPaneLayout, PTextInput, PSelectDropdown, PButton, PScopedNotification, } from '@cloudforet/mirinae'; @@ -114,8 +114,12 @@ watch(() => state.originUnifiedCostConfig, (unifiedCostConfig) => { + diff --git a/apps/web/src/services/cost-explorer/pages/admin/AdminAdvancedSettingsPage.vue b/apps/web/src/services/cost-explorer/pages/admin/AdminAdvancedSettingsPage.vue index 8cacac71a3..65fdeaaf4e 100644 --- a/apps/web/src/services/cost-explorer/pages/admin/AdminAdvancedSettingsPage.vue +++ b/apps/web/src/services/cost-explorer/pages/admin/AdminAdvancedSettingsPage.vue @@ -11,9 +11,9 @@ import { i18n } from '@/translations'; import { useDomainConfigStore } from '@/store/config/domain-config-store'; +import AdvancedSettingsCostReportConfiguration from '@/services/cost-explorer/components/AdvancedSettingsCostReportConfiguration.vue'; import AdvancedSettingsCurrencyConverter from '@/services/cost-explorer/components/AdvancedSettingsCurrencyConverter.vue'; - const domainConfigStore = useDomainConfigStore(); const route = useRoute(); @@ -28,20 +28,23 @@ const state = reactive({ diff --git a/apps/web/src/services/cost-explorer/routes/admin/route-constant.ts b/apps/web/src/services/cost-explorer/routes/admin/route-constant.ts index 2592012411..c17cd1e0e3 100644 --- a/apps/web/src/services/cost-explorer/routes/admin/route-constant.ts +++ b/apps/web/src/services/cost-explorer/routes/admin/route-constant.ts @@ -23,7 +23,5 @@ export const ADMIN_COST_EXPLORER_ROUTE = { }, COST_ADVANCED_SETTINGS: { _NAME: `admin.${MENU_ID.COST_EXPLORER}.${MENU_ID.COST_ADVANCED_SETTINGS}`, - ANOMALY_DETECTION_DOMAIN_CONFIGURATION: { _NAME: `admin.${MENU_ID.COST_EXPLORER}.${MENU_ID.COST_ADVANCED_SETTINGS}.${MENU_ID.ANOMALY_DETECTION_DOMAIN_CONFIGURATION}` }, - CURRENCY_CONVERTER: { _NAME: `admin.${MENU_ID.COST_EXPLORER}.${MENU_ID.COST_ADVANCED_SETTINGS}.${MENU_ID.CURRENCY_CONVERTER}` }, }, } as const; From cd561b9339f886590c0fcde575069483f7b23dc9 Mon Sep 17 00:00:00 2001 From: Dahyun Yu Date: Fri, 9 May 2025 10:51:20 +0900 Subject: [PATCH 07/33] refactor: use VueQuery rather than SpaceConnector (#5835) * feat: add vue query and mutation of `CostReport` Signed-off-by: yuda * refactor: use VueQuery rather than SpaceConnector Signed-off-by: yuda * fix: use `select` in `useCostReportConfigQuery` Signed-off-by: yuda --------- Signed-off-by: yuda --- .../use-cost-report-update-mutation.ts | 44 +++++++++++++ .../components/CostReportSettingsModal.vue | 61 +++++++++---------- .../queries/use-cost-report-config-query.ts | 26 ++++++++ 3 files changed, 100 insertions(+), 31 deletions(-) create mode 100644 apps/web/src/api-clients/cost-analysis/cost-report-config/composables/mutations/use-cost-report-update-mutation.ts create mode 100644 apps/web/src/services/cost-explorer/composables/queries/use-cost-report-config-query.ts diff --git a/apps/web/src/api-clients/cost-analysis/cost-report-config/composables/mutations/use-cost-report-update-mutation.ts b/apps/web/src/api-clients/cost-analysis/cost-report-config/composables/mutations/use-cost-report-update-mutation.ts new file mode 100644 index 0000000000..cc605b433e --- /dev/null +++ b/apps/web/src/api-clients/cost-analysis/cost-report-config/composables/mutations/use-cost-report-update-mutation.ts @@ -0,0 +1,44 @@ +import { + useMutation, useQueryClient, +} from '@tanstack/vue-query'; + +import { useCostReportConfigApi } from '@/api-clients/cost-analysis/cost-report-config/composables/use-cost-report-config-api'; +import type { CostReportConfigUpdateParameters } from '@/api-clients/cost-analysis/cost-report-config/schema/api-verbs/update'; +import type { CostReportConfigModel } from '@/api-clients/cost-analysis/cost-report-config/schema/model'; +import { useServiceQueryKey } from '@/query/query-key/use-service-query-key'; + + +interface UseCostReportUpdateMutationOptions { + onSuccess?: (data: CostReportConfigModel, variables: CostReportConfigUpdateParameters) => void|Promise; + onError?: (error: Error, variables: CostReportConfigUpdateParameters) => void|Promise; + onSettled?: (data: CostReportConfigModel|undefined, error: Error|null, variables: CostReportConfigUpdateParameters) => void|Promise; +} + +export const useCostReportUpdateMutation = (options: UseCostReportUpdateMutationOptions) => { + const { costReportConfigAPI } = useCostReportConfigApi(); + const queryClient = useQueryClient(); + const { key: costReportConfigListQueryKey } = useServiceQueryKey('cost-analysis', 'cost-report-config', 'list'); + + const { + onSuccess, onError, onSettled, + } = options; + + const updateFn = (params: CostReportConfigUpdateParameters): Promise => { + if (!params.cost_report_config_id) throw new Error('Cost report config ID is not provided'); + return costReportConfigAPI.update(params); + }; + + return useMutation({ + mutationFn: updateFn, + onSuccess: async (data, variables) => { + queryClient.invalidateQueries({ queryKey: costReportConfigListQueryKey }); + if (onSuccess) await onSuccess(data, variables); + }, + onError: (error, variables) => { + if (onError) onError(error, variables); + }, + onSettled: (data, error, variables) => { + if (onSettled) onSettled(data, error, variables); + }, + }); +}; diff --git a/apps/web/src/services/cost-explorer/components/CostReportSettingsModal.vue b/apps/web/src/services/cost-explorer/components/CostReportSettingsModal.vue index 85cc865817..b9247b2f66 100644 --- a/apps/web/src/services/cost-explorer/components/CostReportSettingsModal.vue +++ b/apps/web/src/services/cost-explorer/components/CostReportSettingsModal.vue @@ -4,14 +4,13 @@ import { computed, reactive, watch } from 'vue'; import dayjs from 'dayjs'; import { map } from 'lodash'; -import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; import { PButtonModal, PFieldGroup, PSelectDropdown, PBadge, PTextInput, PCheckbox, PI, } from '@cloudforet/mirinae'; import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/types/controls/dropdown/select-dropdown/type'; +import { useCostReportUpdateMutation } from '@/api-clients/cost-analysis/cost-report-config/composables/mutations/use-cost-report-update-mutation'; import type { CostReportConfigUpdateParameters } from '@/api-clients/cost-analysis/cost-report-config/schema/api-verbs/update'; -import type { CostReportConfigModel } from '@/api-clients/cost-analysis/cost-report-config/schema/model'; import { i18n } from '@/translations'; import { CURRENCY, CURRENCY_SYMBOL } from '@/store/display/constant'; @@ -25,9 +24,7 @@ import ErrorHandler from '@/common/composables/error/errorHandler'; import { useFormValidator } from '@/common/composables/form-validator'; import { useProxyValue } from '@/common/composables/proxy-state'; -import { useCostReportPageStore } from '@/services/cost-explorer/stores/cost-report-page-store'; - - +import { useCostReportConfigQuery } from '@/services/cost-explorer/composables/queries/use-cost-report-config-query'; interface Props { visible: boolean; @@ -38,8 +35,8 @@ const props = withDefaults(defineProps(), { const emit = defineEmits<{(e: 'update:visible', value: boolean): void; (e: 'confirm'): void; }>(); -const costReportPageStore = useCostReportPageStore(); -const costReportPageState = costReportPageStore.state; + +const { costReportConfig } = useCostReportConfigQuery(); const state = reactive({ proxyVisible: useProxyValue('visible', props, emit), selectedCurrency: undefined as undefined|Currency, @@ -54,6 +51,7 @@ const state = reactive({ })) as SelectDropdownMenuItem[], upcomingIssueDateText: computed(() => getUpcomingIssueDate(state.enableLastDay, issueDay.value)), }); + const { forms: { issueDay }, setForm, @@ -63,7 +61,7 @@ const { } = useFormValidator({ issueDay: undefined as number | undefined, }, { - issueDay(value: number) { + issueDay(value: number | undefined) { if (state.enableLastDay) return true; if (!value) return i18n.t('BILLING.COST_MANAGEMENT.COST_REPORT.REQUIRED_FIELD'); if (value < 1) return i18n.t('BILLING.COST_MANAGEMENT.COST_REPORT.GREATER_THAN_OR_EQUAL_TO_1'); @@ -100,21 +98,14 @@ const getUpcomingIssueDate = (enableLastDay: boolean, _issueDay?: number): strin }; /* Api */ -const updateCostReportConfig = async () => { - try { - const updatedConfig = await SpaceConnector.clientV2.costAnalysis.costReportConfig.update({ - cost_report_config_id: costReportPageState.costReportConfig?.cost_report_config_id ?? '', - currency: state.selectedCurrency, - issue_day: state.enableLastDay ? undefined : Number(issueDay.value), - language: state.selectedLanguage, - is_last_day: state.enableLastDay, - }); - costReportPageStore.setCostReportConfig(updatedConfig); +const { mutate: updateCostReportConfig } = useCostReportUpdateMutation({ + onSuccess: () => { showSuccessMessage(i18n.t('BILLING.COST_MANAGEMENT.COST_REPORT.ALT_S_UPDATE_SETTINGS'), ''); - } catch (e) { - ErrorHandler.handleRequestError(e, i18n.t('BILLING.COST_MANAGEMENT.COST_REPORT.ALT_E_UPDATE_SETTINGS')); - } -}; + }, + onError: (error) => { + ErrorHandler.handleRequestError(error, i18n.t('BILLING.COST_MANAGEMENT.COST_REPORT.ALT_E_UPDATE_SETTINGS')); + }, +}); /* Event */ const handleChangeEnableLastDay = () => { @@ -123,22 +114,30 @@ const handleChangeEnableLastDay = () => { setForm('issueDay', getLastDay()); } }; -const handleSelectCurrency = (currency: Currency) => { - state.selectedCurrency = currency; +const handleSelectCurrency = (item: string | number | SelectDropdownMenuItem) => { + state.selectedCurrency = item as Currency; }; const handleConfirm = () => { - updateCostReportConfig(); + const params: CostReportConfigUpdateParameters = { + cost_report_config_id: costReportConfig.value?.cost_report_config_id ?? '', + currency: state.selectedCurrency, + language: state.selectedLanguage, + is_last_day: state.enableLastDay, + issue_day: state.enableLastDay ? undefined : Number(issueDay.value), + }; + + updateCostReportConfig(params); state.proxyVisible = false; }; /* Watcher */ watch(() => props.visible, (visible) => { - if (visible && costReportPageState.costReportConfig) { - state.selectedCurrency = costReportPageState.costReportConfig?.currency; - state.enableLastDay = costReportPageState.costReportConfig?.is_last_day; - state.selectedLanguage = costReportPageState.costReportConfig?.language; - if (!costReportPageState.costReportConfig?.is_last_day) { - setForm('issueDay', costReportPageState.costReportConfig?.issue_day); + if (visible && costReportConfig.value) { + state.selectedCurrency = costReportConfig.value?.currency; + state.enableLastDay = costReportConfig.value?.is_last_day; + state.selectedLanguage = costReportConfig.value?.language; + if (!costReportConfig.value?.is_last_day) { + setForm('issueDay', costReportConfig.value?.issue_day); } else { setForm('issueDay', getLastDay()); } diff --git a/apps/web/src/services/cost-explorer/composables/queries/use-cost-report-config-query.ts b/apps/web/src/services/cost-explorer/composables/queries/use-cost-report-config-query.ts new file mode 100644 index 0000000000..f3a1d1c3b6 --- /dev/null +++ b/apps/web/src/services/cost-explorer/composables/queries/use-cost-report-config-query.ts @@ -0,0 +1,26 @@ +import { ApiQueryHelper } from '@cloudforet/core-lib/space-connector/helper'; + +import { useCostReportConfigApi } from '@/api-clients/cost-analysis/cost-report-config/composables/use-cost-report-config-api'; +import { useScopedQuery } from '@/query/composables/use-scoped-query'; +import { useServiceQueryKey } from '@/query/query-key/use-service-query-key'; + +const costReportConfigApiHelper = new ApiQueryHelper().setSort('created_at', true); +export const useCostReportConfigQuery = () => { + const { costReportConfigAPI } = useCostReportConfigApi(); + const { key, params } = useServiceQueryKey('cost-analysis', 'cost-report-config', 'list', { + params: { + query: costReportConfigApiHelper.data, + }, + }); + const { data, isLoading, error } = useScopedQuery({ + queryKey: key, + queryFn: () => costReportConfigAPI.list(params.value), + select: (d) => d.results?.[0] ?? null, + staleTime: 1000 * 60 * 5, // 5 minutes + gcTime: 1000 * 60 * 1, // 1 minutes + }, ['WORKSPACE']); + + return { + costReportConfig: data, isLoading, error, + }; +}; From 9a16afeb54d519a2a6d1d107df39ed5e17fc2553 Mon Sep 17 00:00:00 2001 From: Dahyun Yu Date: Fri, 9 May 2025 13:53:02 +0900 Subject: [PATCH 08/33] chore: markup "cost report configuration" section (#5838) * chore: markup "cost report configuration" section Signed-off-by: yuda * feat: update costReportConfig model Signed-off-by: yuda * feat: add cost report config form handling and submission logic Signed-off-by: yuda * chore: update language Signed-off-by: yuda * chore: edit `CostReportConfigUpdateParameters` Signed-off-by: yuda * fix: add `DOMAIN` scope to `costReportConfigApiHelper` Signed-off-by: yuda * chore: delete console.log() Signed-off-by: yuda --------- Signed-off-by: yuda --- .../schema/api-verbs/list.ts | 3 + .../schema/api-verbs/update.ts | 4 + .../cost-report-config/schema/model.ts | 5 + ...dvancedSettingsCostReportConfiguration.vue | 325 +++++++++++---- .../queries/use-cost-report-config-query.ts | 2 +- .../console-translation-2.8.babel | 383 ++++++++++++++++++ packages/language-pack/en.json | 20 + packages/language-pack/ja.json | 20 + packages/language-pack/ko.json | 20 + 9 files changed, 696 insertions(+), 86 deletions(-) diff --git a/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/list.ts b/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/list.ts index 38b163aca8..f070ca1e9d 100644 --- a/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/list.ts +++ b/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/list.ts @@ -1,7 +1,10 @@ import type { Query } from '@cloudforet/core-lib/space-connector/type'; +import type { CostReportConfigStatus } from '@/api-clients/cost-analysis/cost-report-config/schema/type'; export interface CostReportConfigListParameters { query?: Query; cost_report_config_id?: string; + state?: CostReportConfigStatus; + scope?: 'WORKSPACE'|'PROJECT'; } diff --git a/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/update.ts b/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/update.ts index b7ed82087b..3013d98264 100644 --- a/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/update.ts +++ b/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/api-verbs/update.ts @@ -12,4 +12,8 @@ export interface CostReportConfigUpdateParameters { state: string; data_sources: string[]; }; + adjustment_options?: { + enabled: boolean; + period?: number; + }; } diff --git a/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/model.ts b/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/model.ts index ea49d24879..2ba5eeba57 100644 --- a/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/model.ts +++ b/apps/web/src/api-clients/cost-analysis/cost-report-config/schema/model.ts @@ -20,6 +20,11 @@ export interface CostReportConfigModel { data_sources: string[]; }; language?: LanguageCode; + scope: 'WORKSPACE'|'PROJECT'; + adjustment_options?: { + enabled: boolean; + period: number; + }; domain_id: string; created_at: string; updated_at: string; diff --git a/apps/web/src/services/cost-explorer/components/AdvancedSettingsCostReportConfiguration.vue b/apps/web/src/services/cost-explorer/components/AdvancedSettingsCostReportConfiguration.vue index 54136881d0..184e24718b 100644 --- a/apps/web/src/services/cost-explorer/components/AdvancedSettingsCostReportConfiguration.vue +++ b/apps/web/src/services/cost-explorer/components/AdvancedSettingsCostReportConfiguration.vue @@ -1,41 +1,168 @@