From 963728ba73e9490069877d19bab34cf5d4aed890 Mon Sep 17 00:00:00 2001 From: sulmo Date: Wed, 5 Feb 2025 11:03:53 +0900 Subject: [PATCH 01/10] chore(vercel): remove specific app option from vercel.json (#5619) ``` build(vercel): update vercel config and gitignore for deployment - Add .vercel to .gitignore to exclude Vercel-specific files - Remove build command and output directory from vercel.json ``` build(vercel): update vercel config and gitignore for deployment - Add .vercel to .gitignore to exclude Vercel-specific files - Remove build command and output directory from vercel.json Signed-off-by: sulmo --- apps/web-storybook/.gitignore | 1 + vercel.json | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/web-storybook/.gitignore b/apps/web-storybook/.gitignore index 7a7f1e3c25..b2c4fdd1ad 100755 --- a/apps/web-storybook/.gitignore +++ b/apps/web-storybook/.gitignore @@ -1,3 +1,4 @@ # Transpiled code .out storybook-static +.vercel diff --git a/vercel.json b/vercel.json index e137d8de77..6a9264870d 100644 --- a/vercel.json +++ b/vercel.json @@ -1,6 +1,4 @@ { - "buildCommand": "npm run build -- --filter=web...", - "outputDirectory": "apps/web/dist", "rewrites": [ { "source": "/(.*)", "destination": "/" } ] From ecfbe17035b1a71c99af84a26bc1c93416ab2099 Mon Sep 17 00:00:00 2001 From: sulmo Date: Wed, 5 Feb 2025 13:16:54 +0900 Subject: [PATCH 02/10] build: set unfied-storybook build config (#5620) build(storybook): update URLs and enable caching for builds - Updated Storybook URLs for mirinae and web components - Enabled caching in turbo configuration for unified-storybook build ``` Signed-off-by: sulmo --- apps/unified-storybook/.storybook/main.ts | 4 ++-- turbo.json | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/unified-storybook/.storybook/main.ts b/apps/unified-storybook/.storybook/main.ts index 9832c9d050..e1e7fce5b7 100644 --- a/apps/unified-storybook/.storybook/main.ts +++ b/apps/unified-storybook/.storybook/main.ts @@ -23,11 +23,11 @@ const config: StorybookConfig = { return { mirinae: { title: 'Mirinae Component', - url: 'https://your-production-react-storybook-url', + url: 'https://storybook.developer.spaceone.dev', }, web: { title: 'Web Component', - url: 'https://your-production-angular-storybook-url', + url: 'https://spaceone-web-storybook.vercel.app', }, }; }, diff --git a/turbo.json b/turbo.json index fb2c93a9ba..dc78e2f7e9 100644 --- a/turbo.json +++ b/turbo.json @@ -49,7 +49,15 @@ "tsconfig.json", "tailwind.config.js", "postcss.config.js", ".storybook/**/*", "!./**/__tests__/**", "!./**/*.babel", "!./**/LICENSE", "!./**/AUTHORS", "!./**/README.md", "!./**/CHANGELOG.md" ], - "cache": false + "cache": true + }, + "unified-storybook#build": { + "outputs": ["./.storybook-static/**"], + "inputs": [ + "tsconfig.json", "tailwind.config.js", "postcss.config.js", ".storybook/**/*", + "!./**/__tests__/**", "!./**/*.babel", "!./**/LICENSE", "!./**/AUTHORS", "!./**/README.md", "!./**/CHANGELOG.md" + ], + "cache": true }, "transpile": { "dependsOn": ["^transpile"], From 76c3c03240e302a6183975a15bc4944f1e4d893f Mon Sep 17 00:00:00 2001 From: sulmo Date: Thu, 6 Feb 2025 15:45:24 +0900 Subject: [PATCH 03/10] chore(build): add a GitHub Actions workflow to deploy unified-storybook (#5623) ci(github): add workflow for deploying unified storybook - Added a GitHub Actions workflow to deploy the unified storybook. - Modified output paths in turbo.json for consistency. ci(github): add workflow for deploying unified storybook - Added a GitHub Actions workflow to deploy the unified storybook. - Modified output paths in turbo.json for consistency. Signed-off-by: sulmo --- .../dispatch_deploy_unfied_storybook.yaml | 31 +++++++++++++++++++ turbo.json | 6 ++-- 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/dispatch_deploy_unfied_storybook.yaml diff --git a/.github/workflows/dispatch_deploy_unfied_storybook.yaml b/.github/workflows/dispatch_deploy_unfied_storybook.yaml new file mode 100644 index 0000000000..a8cfb7a2ca --- /dev/null +++ b/.github/workflows/dispatch_deploy_unfied_storybook.yaml @@ -0,0 +1,31 @@ +name: "[Dispatch] Deploy unified storybook" + +on: + workflow_dispatch: + +env: + TEAM_NAME: ${{ vars.VERCEL_TEAM_NAME }} + PROJECT_NAME: "unified-storybook" + VERCEL_TOKEN: ${{ secrets.VERCEL_CLOUDFORET_TOKEN }} + +jobs: + Deploy-Production: + runs-on: ubuntu-latest + steps: + - name: Checkout code and submodules + uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + + - name: Set up environment + run: sudo apt-get install jq + + - name: Install Vercel CLI + run: npm install --global vercel@latest + + - name: Checkout Vercel Target Project + run: vercel link --yes --scope=${{ env.TEAM_NAME }} --project=${{ env.PROJECT_NAME }} --token=${{ env.VERCEL_TOKEN }} + + - name: Deploy Project Artifacts to Vercel + run: vercel deploy --prod --token=${{ env.VERCEL_TOKEN }} diff --git a/turbo.json b/turbo.json index dc78e2f7e9..0a2ab38e00 100644 --- a/turbo.json +++ b/turbo.json @@ -33,7 +33,7 @@ "cache": true }, "mirinae-storybook#build": { - "outputs": ["./.storybook-static/**"], + "outputs": ["./storybook-static/**"], "inputs": [ "../../packages/mirinae/src/**", "../../packages/mirinae/postcss.config.js", "../../packages/mirinae/tailwind.config.js", "../../packages/mirinae/package.json", "tsconfig.json", "tailwind.config.js", "postcss.config.js", ".storybook/**/*", @@ -43,7 +43,7 @@ }, "web-storybook#build": { "dependsOn": ["@cloudforet/mirinae#build", "@cloudforet/mirinae#transpile", "@cloudforet/utils#build", "@cloudforet/core-lib#build"], - "outputs": ["./.storybook-static/**"], + "outputs": ["./storybook-static/**"], "inputs": [ "../web/src/common/**", "../web/postcss.config.js", "../web/tailwind.config.js", "../web/package.json", "tsconfig.json", "tailwind.config.js", "postcss.config.js", ".storybook/**/*", @@ -52,7 +52,7 @@ "cache": true }, "unified-storybook#build": { - "outputs": ["./.storybook-static/**"], + "outputs": ["./storybook-static/**"], "inputs": [ "tsconfig.json", "tailwind.config.js", "postcss.config.js", ".storybook/**/*", "!./**/__tests__/**", "!./**/*.babel", "!./**/LICENSE", "!./**/AUTHORS", "!./**/README.md", "!./**/CHANGELOG.md" From 964182a800b81288149a2fb2ccaba786c51067b0 Mon Sep 17 00:00:00 2001 From: nayeongkim Date: Fri, 7 Feb 2025 11:37:04 +0900 Subject: [PATCH 04/10] feat: add header slot at overlay layout Signed-off-by: NaYeong,Kim --- .../layouts/overlay-layout/POverlayLayout.vue | 16 +++++++++------- .../src/layouts/overlay-layout/story-helper.ts | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue b/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue index 711dbaca3d..c180c1b0c7 100644 --- a/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue +++ b/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue @@ -52,15 +52,17 @@ const handleClose = () => { 'fixed-size': props.isFixedSize, }" > -
-
-

- {{ props.title }} -

+
+
+

+ {{ props.title }} +

+
-
+ ({ }, control: 'text', }, + headerSlot: { + name: 'header', + description: 'Slot for header contents.', + table: { + type: { + summary: null, + }, + defaultValue: { + summary: null, + }, + category: 'slots', + }, + control: 'text', + }, titleRightExtraSlot: { name: 'title-right-extra', description: 'Slot for extra contents on the right side of the title.', @@ -178,6 +192,7 @@ export const getOverlayLayoutArgTypes = (): ArgTypes => ({ }, }, // default + header: { table: { disable: true } }, 'title-right-extra': { table: { disable: true } }, default: { table: { disable: true } }, footer: { table: { disable: true } }, From e7c4a70aa501a96237e9c75e55a0728f741377ca Mon Sep 17 00:00:00 2001 From: nayeongkim Date: Fri, 7 Feb 2025 12:17:35 +0900 Subject: [PATCH 05/10] chore: changed style section Signed-off-by: NaYeong,Kim --- .../src/layouts/overlay-layout/POverlayLayout.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue b/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue index c180c1b0c7..3104361d40 100644 --- a/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue +++ b/packages/mirinae/src/layouts/overlay-layout/POverlayLayout.vue @@ -52,17 +52,17 @@ const handleClose = () => { 'fixed-size': props.isFixedSize, }" > - -
+
+

{{ props.title }}

-
- + +
Date: Fri, 7 Feb 2025 13:51:10 +0900 Subject: [PATCH 06/10] ci: fix pr review labler workflow to use PAT Signed-off-by: Wanjin Noh --- .github/workflows/pull_request_review_state_labeler.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull_request_review_state_labeler.yaml b/.github/workflows/pull_request_review_state_labeler.yaml index 7e8036b829..db2a37bac5 100644 --- a/.github/workflows/pull_request_review_state_labeler.yaml +++ b/.github/workflows/pull_request_review_state_labeler.yaml @@ -18,7 +18,7 @@ jobs: id: check_self_approved uses: actions/github-script@v6 with: - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.PAT_FOR_PR_LABELER }} script: | const prNumber = context.payload.pull_request.number; const owner = context.repo.owner; @@ -36,7 +36,7 @@ jobs: if: github.event_name == 'pull_request_target' && steps.check_self_approved.outputs.isSelfApprovedPR == 'false' uses: actions/github-script@v6 with: - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.PAT_FOR_PR_LABELER }} script: | const prNumber = context.payload.pull_request.number; const owner = context.repo.owner; @@ -56,7 +56,7 @@ jobs: if: github.event_name == 'pull_request_review' && steps.check_self_approved.outputs.isSelfApprovedPR == 'false' uses: actions/github-script@v6 with: - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.PAT_FOR_PR_LABELER }} script: | const prNumber = context.payload.pull_request.number; const owner = context.repo.owner; From 5f89dbcdea40f7be1d4f8351a8e546a2583d25e9 Mon Sep 17 00:00:00 2001 From: Wanjin Noh Date: Fri, 7 Feb 2025 14:44:57 +0900 Subject: [PATCH 07/10] ci: update PR review labeler workflow token name Replaced PAT_FOR_PR_LABELER with CONSOLE_PR_PAT_TOKEN in GitHub Actions workflow Signed-off-by: Wanjin Noh --- .github/workflows/pull_request_review_state_labeler.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull_request_review_state_labeler.yaml b/.github/workflows/pull_request_review_state_labeler.yaml index db2a37bac5..caeccb1872 100644 --- a/.github/workflows/pull_request_review_state_labeler.yaml +++ b/.github/workflows/pull_request_review_state_labeler.yaml @@ -18,7 +18,7 @@ jobs: id: check_self_approved uses: actions/github-script@v6 with: - github-token: ${{ secrets.PAT_FOR_PR_LABELER }} + github-token: ${{ secrets.CONSOLE_PR_PAT_TOKEN }} script: | const prNumber = context.payload.pull_request.number; const owner = context.repo.owner; @@ -36,7 +36,7 @@ jobs: if: github.event_name == 'pull_request_target' && steps.check_self_approved.outputs.isSelfApprovedPR == 'false' uses: actions/github-script@v6 with: - github-token: ${{ secrets.PAT_FOR_PR_LABELER }} + github-token: ${{ secrets.CONSOLE_PR_PAT_TOKEN }} script: | const prNumber = context.payload.pull_request.number; const owner = context.repo.owner; @@ -56,7 +56,7 @@ jobs: if: github.event_name == 'pull_request_review' && steps.check_self_approved.outputs.isSelfApprovedPR == 'false' uses: actions/github-script@v6 with: - github-token: ${{ secrets.PAT_FOR_PR_LABELER }} + github-token: ${{ secrets.CONSOLE_PR_PAT_TOKEN }} script: | const prNumber = context.payload.pull_request.number; const owner = context.repo.owner; From 9815e35904519e2f480ad0e476c410ab146cc6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piggy=20Park=20=28=EB=B0=95=EC=9A=A9=ED=83=9C=29?= Date: Wed, 12 Feb 2025 08:39:56 +0900 Subject: [PATCH 08/10] fix(metric-explorer): solve widget metric link bug & refactor metric page (#5633) * fix(metric-explorer): solve widget metric link bug & refactor metric page Signed-off-by: samuel.park * chore(widget): small fix Signed-off-by: samuel.park --------- Signed-off-by: samuel.park --- .../widgets/_composables/use-widget-frame.ts | 12 +++--- .../ClusteredColumnChart.vue | 2 +- .../color-coded-heatmap/ColorCodedHeatmap.vue | 2 +- .../ColorCodedTableHeatmap.vue | 2 +- .../modules/widgets/_widgets/gauge/Gauge.vue | 2 +- .../widgets/_widgets/geo-map/GeoMap.vue | 2 +- .../widgets/_widgets/heatmap/Heatmap.vue | 2 +- .../widgets/_widgets/line-chart/LineChart.vue | 2 +- .../_widgets/number-card/NumberCard.vue | 2 +- .../widgets/_widgets/pie-chart/PieChart.vue | 2 +- .../_widgets/sankey-chart/SankeyChart.vue | 2 +- .../StackedColumnChart.vue | 2 +- .../StackedHorizontalBarChart.vue | 2 +- .../modules/widgets/_widgets/table/Table.vue | 2 +- .../widgets/_widgets/treemap/Treemap.vue | 2 +- .../MetricExplorerPeriodDropdown.vue | 39 ++++++++++++++++--- .../components/MetricExplorerQuerySection.vue | 2 +- .../pages/MetricExplorerDetailPage.vue | 1 + .../stores/metric-explorer-page-store.ts | 6 ++- 19 files changed, 60 insertions(+), 28 deletions(-) diff --git a/apps/web/src/common/modules/widgets/_composables/use-widget-frame.ts b/apps/web/src/common/modules/widgets/_composables/use-widget-frame.ts index 5bd66cf863..d24d672efd 100644 --- a/apps/web/src/common/modules/widgets/_composables/use-widget-frame.ts +++ b/apps/web/src/common/modules/widgets/_composables/use-widget-frame.ts @@ -25,8 +25,6 @@ import type { DateRange } from '@/common/modules/widgets/types/widget-data-type' import type { WidgetEmit, WidgetProps, WidgetSize, } from '@/common/modules/widgets/types/widget-display-type'; -import type { WidgetFieldName } from '@/common/modules/widgets/types/widget-field-type'; -import type { WidgetFieldValues } from '@/common/modules/widgets/types/widget-field-value-type'; import type { FullDataLink, WidgetFrameProps } from '@/common/modules/widgets/types/widget-frame-type'; import { ASSET_INVENTORY_ROUTE_V1 } from '@/services/asset-inventory-v1/routes/route-constant'; @@ -86,12 +84,16 @@ const getRecursiveDataTableIds = (prevValue: string[] = [], dataTable: DataTable _results = _results.concat(..._dataTables.map((d) => getRecursiveDataTableIds(prevValue, d, dataTables))); return _results; } - return prevValue.concat(dataTable.data_table_id); + + const _dataTableId = dataTable?.options?.[dataTable.operator]?.data_table_id; + const _dataTable = dataTables.find((d) => d.data_table_id === _dataTableId); + _results = _results.concat(...getRecursiveDataTableIds(prevValue, _dataTable, dataTables)); + return _results; } return prevValue.concat(dataTable.data_table_id); }; -const getFullDataLocation = (dataTable: DataTableModel, widgetOptions?: Record, dateRange?: DateRange, dashboardVars?: DashboardVars): Location|undefined => { - const _granularity = (widgetOptions?.granularity as GranularityValue).granularity || 'MONTHLY'; +const getFullDataLocation = (dataTable: DataTableModel, widgetOptions?: WidgetProps['widgetOptions'], dateRange?: DateRange, dashboardVars?: DashboardVars): Location|undefined => { + const _granularity = (widgetOptions?.granularity?.value as GranularityValue)?.granularity || 'MONTHLY'; const _groupBy: string[] = dataTable?.options?.group_by?.map((d) => d.key); const _costFilters = [ ...(dataTable?.options?.filter ?? []), diff --git a/apps/web/src/common/modules/widgets/_widgets/clustered-column-chart/ClusteredColumnChart.vue b/apps/web/src/common/modules/widgets/_widgets/clustered-column-chart/ClusteredColumnChart.vue index 554e604974..d3434610ad 100644 --- a/apps/web/src/common/modules/widgets/_widgets/clustered-column-chart/ClusteredColumnChart.vue +++ b/apps/web/src/common/modules/widgets/_widgets/clustered-column-chart/ClusteredColumnChart.vue @@ -220,7 +220,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/color-coded-heatmap/ColorCodedHeatmap.vue b/apps/web/src/common/modules/widgets/_widgets/color-coded-heatmap/ColorCodedHeatmap.vue index 8d52454a60..573ff65699 100644 --- a/apps/web/src/common/modules/widgets/_widgets/color-coded-heatmap/ColorCodedHeatmap.vue +++ b/apps/web/src/common/modules/widgets/_widgets/color-coded-heatmap/ColorCodedHeatmap.vue @@ -120,7 +120,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/color-coded-table-heatmap/ColorCodedTableHeatmap.vue b/apps/web/src/common/modules/widgets/_widgets/color-coded-table-heatmap/ColorCodedTableHeatmap.vue index 59c89af386..f675093c44 100644 --- a/apps/web/src/common/modules/widgets/_widgets/color-coded-table-heatmap/ColorCodedTableHeatmap.vue +++ b/apps/web/src/common/modules/widgets/_widgets/color-coded-table-heatmap/ColorCodedTableHeatmap.vue @@ -153,7 +153,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/gauge/Gauge.vue b/apps/web/src/common/modules/widgets/_widgets/gauge/Gauge.vue index d37eb74f3b..b672382f81 100644 --- a/apps/web/src/common/modules/widgets/_widgets/gauge/Gauge.vue +++ b/apps/web/src/common/modules/widgets/_widgets/gauge/Gauge.vue @@ -177,7 +177,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/geo-map/GeoMap.vue b/apps/web/src/common/modules/widgets/_widgets/geo-map/GeoMap.vue index ca055b2ac4..77bdabf3ba 100644 --- a/apps/web/src/common/modules/widgets/_widgets/geo-map/GeoMap.vue +++ b/apps/web/src/common/modules/widgets/_widgets/geo-map/GeoMap.vue @@ -156,7 +156,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/heatmap/Heatmap.vue b/apps/web/src/common/modules/widgets/_widgets/heatmap/Heatmap.vue index f01c01623f..24882737f1 100644 --- a/apps/web/src/common/modules/widgets/_widgets/heatmap/Heatmap.vue +++ b/apps/web/src/common/modules/widgets/_widgets/heatmap/Heatmap.vue @@ -219,7 +219,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/line-chart/LineChart.vue b/apps/web/src/common/modules/widgets/_widgets/line-chart/LineChart.vue index 55579d73ec..e91741a7d2 100644 --- a/apps/web/src/common/modules/widgets/_widgets/line-chart/LineChart.vue +++ b/apps/web/src/common/modules/widgets/_widgets/line-chart/LineChart.vue @@ -225,7 +225,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/number-card/NumberCard.vue b/apps/web/src/common/modules/widgets/_widgets/number-card/NumberCard.vue index a834b9ec2a..47a53a660f 100644 --- a/apps/web/src/common/modules/widgets/_widgets/number-card/NumberCard.vue +++ b/apps/web/src/common/modules/widgets/_widgets/number-card/NumberCard.vue @@ -221,7 +221,7 @@ const queryResults = useQueries({ ], }); -const widgetLoading = computed(() => queryResults.value?.[0].isPending || queryResults.value?.[0].isFetching); +const widgetLoading = computed(() => queryResults.value?.[0].isFetching); const previousLoading = computed(() => queryResults.value?.[1].isLoading); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); diff --git a/apps/web/src/common/modules/widgets/_widgets/pie-chart/PieChart.vue b/apps/web/src/common/modules/widgets/_widgets/pie-chart/PieChart.vue index ce0d2bd368..207206c683 100644 --- a/apps/web/src/common/modules/widgets/_widgets/pie-chart/PieChart.vue +++ b/apps/web/src/common/modules/widgets/_widgets/pie-chart/PieChart.vue @@ -236,7 +236,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/sankey-chart/SankeyChart.vue b/apps/web/src/common/modules/widgets/_widgets/sankey-chart/SankeyChart.vue index f01c1563a7..2dbdffbee8 100644 --- a/apps/web/src/common/modules/widgets/_widgets/sankey-chart/SankeyChart.vue +++ b/apps/web/src/common/modules/widgets/_widgets/sankey-chart/SankeyChart.vue @@ -178,7 +178,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/stacked-column-chart/StackedColumnChart.vue b/apps/web/src/common/modules/widgets/_widgets/stacked-column-chart/StackedColumnChart.vue index 7fda9247c1..7cbceaf272 100644 --- a/apps/web/src/common/modules/widgets/_widgets/stacked-column-chart/StackedColumnChart.vue +++ b/apps/web/src/common/modules/widgets/_widgets/stacked-column-chart/StackedColumnChart.vue @@ -218,7 +218,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/stacked-horizontal-bar-chart/StackedHorizontalBarChart.vue b/apps/web/src/common/modules/widgets/_widgets/stacked-horizontal-bar-chart/StackedHorizontalBarChart.vue index d1161bbf7c..a17c19490c 100644 --- a/apps/web/src/common/modules/widgets/_widgets/stacked-horizontal-bar-chart/StackedHorizontalBarChart.vue +++ b/apps/web/src/common/modules/widgets/_widgets/stacked-horizontal-bar-chart/StackedHorizontalBarChart.vue @@ -212,7 +212,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/common/modules/widgets/_widgets/table/Table.vue b/apps/web/src/common/modules/widgets/_widgets/table/Table.vue index 8c0d8ce544..b4b51400d7 100644 --- a/apps/web/src/common/modules/widgets/_widgets/table/Table.vue +++ b/apps/web/src/common/modules/widgets/_widgets/table/Table.vue @@ -241,7 +241,7 @@ const queryResults = useQueries({ ], }); -const widgetLoading = computed(() => queryResults.value?.[0].isFetching || queryResults.value?.[0].isPending); +const widgetLoading = computed(() => queryResults.value?.[0].isFetching); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResults.value?.[0].error?.message as string; diff --git a/apps/web/src/common/modules/widgets/_widgets/treemap/Treemap.vue b/apps/web/src/common/modules/widgets/_widgets/treemap/Treemap.vue index 5cc64689e4..762e98d215 100644 --- a/apps/web/src/common/modules/widgets/_widgets/treemap/Treemap.vue +++ b/apps/web/src/common/modules/widgets/_widgets/treemap/Treemap.vue @@ -178,7 +178,7 @@ const queryResult = useQuery({ staleTime: WIDGET_LOAD_STALE_TIME, }); -const widgetLoading = computed(() => queryResult.isFetching.value || queryResult.isPending.value); +const widgetLoading = computed(() => queryResult.isFetching.value); const errorMessage = computed(() => { if (!state.dataTable) return i18n.t('COMMON.WIDGETS.NO_DATA_TABLE_ERROR_MESSAGE'); return queryResult.error?.value?.message; diff --git a/apps/web/src/services/asset-inventory-v1/components/MetricExplorerPeriodDropdown.vue b/apps/web/src/services/asset-inventory-v1/components/MetricExplorerPeriodDropdown.vue index 90638638f2..05716e71b5 100644 --- a/apps/web/src/services/asset-inventory-v1/components/MetricExplorerPeriodDropdown.vue +++ b/apps/web/src/services/asset-inventory-v1/components/MetricExplorerPeriodDropdown.vue @@ -2,11 +2,12 @@ import { computed, reactive, watch, } from 'vue'; +import { useRoute } from 'vue-router/composables'; import dayjs from 'dayjs'; -import { isEqual, range } from 'lodash'; +import { isEmpty, isEqual, range } from 'lodash'; -import { PSelectDropdown } from '@cloudforet/mirinae'; +import { PSelectDropdown, PBadge } from '@cloudforet/mirinae'; import type { MenuItem } from '@cloudforet/mirinae/types/controls/context-menu/type'; import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/types/controls/dropdown/select-dropdown/type'; @@ -31,6 +32,8 @@ import type { const metricExplorerPageStore = useMetricExplorerPageStore(); const metricExplorerPageState = metricExplorerPageStore.state; +const route = useRoute(); + const state = reactive({ dailyPeriodMenuItems: computed(() => { const locale = i18n.locale; @@ -57,9 +60,14 @@ const state = reactive({ }, ...(range(12).map((i) => { const start = dayjs.utc().subtract(i, 'month').startOf('month'); + const end = dayjs.utc().subtract(i, 'month').endOf('month'); return { name: start.format('YYYY-MM'), label: dayjs(start).locale(locale).format('MMMM, YYYY'), + period: { + start: start.format('YYYY-MM-DD'), + end: end.format('YYYY-MM-DD'), + }, }; })), ]; @@ -108,6 +116,19 @@ const state = reactive({ }), selectedPeriod: METRIC_PERIOD_MENU.LAST_7_DAYS as MetricPeriodMenu, customDateModalVisible: false, + hasURLQuery: computed(() => !!route.query && !isEmpty(route.query)), + showPeriodBadge: computed(() => state.selectedPeriod === 'custom'), + periodBadgeText: computed(() => { + if (!metricExplorerPageState.period) return ''; + let startDateFormat = 'MMM D'; + if (metricExplorerPageState.granularity === GRANULARITY.MONTHLY) startDateFormat = 'MMM YYYY'; + const endDateFormat = metricExplorerPageState.granularity === GRANULARITY.DAILY ? 'MMM D, YYYY' : startDateFormat; + // + const start = dayjs.utc(metricExplorerPageState.period.start); + let end = dayjs.utc(metricExplorerPageState.period.end); + if (metricExplorerPageState.granularity === GRANULARITY.DAILY) end = dayjs.utc(metricExplorerPageState.period.end).endOf('month'); + return `${start.format(startDateFormat)} ~ ${end.format(endDateFormat)}`; + }), }); /* Util */ @@ -116,8 +137,8 @@ const initSelectedPeriod = () => { if (metricExplorerPageState.relativePeriod) { state.selectedPeriod = getPeriodItemNameByRelativePeriod(metricExplorerPageState.relativePeriod); } else if (metricExplorerPageState.granularity === GRANULARITY.DAILY) { - const selectedPeriodItem = state.dailyPeriodMenuItems.find((item) => isEqual(item.name, metricExplorerPageState.period)); - state.selectedPeriod = selectedPeriodItem?.name; + const selectedPeriodItem = state.dailyPeriodMenuItems.find((item) => isEqual(item?.period, metricExplorerPageState.period)); + state.selectedPeriod = selectedPeriodItem?.name || 'custom'; } else { state.selectedPeriod = 'custom'; } @@ -153,12 +174,12 @@ const handleCustomRangeModalConfirm = (start: string, end: string) => { /* Watcher */ watch(() => metricExplorerPageState.refreshMetricPeriodDropdown, (refresh) => { - if (refresh) initSelectedPeriod(); + if (refresh || state.hasURLQuery) initSelectedPeriod(); }, { immediate: true });