From 5748f572f95f6b392747c55593e8f01d0269b438 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:03:43 +0000 Subject: [PATCH 01/59] chore(deps): bump dompurify from 3.2.3 to 3.2.4 Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.2.3 to 3.2.4. - [Release notes](https://github.com/cure53/DOMPurify/releases) - [Commits](https://github.com/cure53/DOMPurify/compare/3.2.3...3.2.4) --- updated-dependencies: - dependency-name: dompurify dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- apps/web/package.json | 2 +- package-lock.json | 25 +++++++++++++------------ packages/mirinae/package.json | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 700cf7930c..e1972a5a82 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -53,7 +53,7 @@ "currency.js": "^2.0.4", "dayjs": "^1.11.7", "diff-match-patch": "^1.0.5", - "dompurify": "^3.2.3", + "dompurify": "^3.2.4", "echarts": "^5.5.0", "ejs": "^3.1.10", "hangul-js": "^0.2.6", diff --git a/package-lock.json b/package-lock.json index d38d3fdf65..6c5f69bf29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -150,7 +150,7 @@ "currency.js": "^2.0.4", "dayjs": "^1.11.7", "diff-match-patch": "^1.0.5", - "dompurify": "^3.2.3", + "dompurify": "^3.2.4", "echarts": "^5.5.0", "ejs": "^3.1.10", "hangul-js": "^0.2.6", @@ -14839,9 +14839,10 @@ } }, "node_modules/dompurify": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz", - "integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", + "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", + "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -33952,7 +33953,7 @@ "@typescript-eslint/parser": "^5.41.0", "eslint": "8.22.0", "eslint-config-airbnb": "^19.0.4", - "eslint-config-turbo": "latest", + "eslint-config-turbo": "*", "eslint-import-resolver-typescript": "^2.7.1", "eslint-plugin-import": "^2.26.0", "eslint-plugin-mdx": "^1.17.1", @@ -33997,7 +33998,7 @@ "commander": "^10.0.1", "core-js": "^3.29.1", "dayjs": "^1.10.7", - "dompurify": "^3.2.3", + "dompurify": "^3.2.4", "dragselect": "^1.15.1", "ejs": "^3.1.10", "filepond": "^4.30.3", @@ -36597,7 +36598,7 @@ "concurrently": "^7.6.0", "core-js": "^3.29.1", "dayjs": "^1.10.7", - "dompurify": "^3.2.3", + "dompurify": "^3.2.4", "dragselect": "^1.15.1", "ejs": "^3.1.10", "eslint-config-custom": "*", @@ -45206,9 +45207,9 @@ } }, "dompurify": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz", - "integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", + "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", "requires": { "@types/trusted-types": "^2.0.7" } @@ -46002,7 +46003,7 @@ "@typescript-eslint/parser": "^5.41.0", "eslint": "8.22.0", "eslint-config-airbnb": "^19.0.4", - "eslint-config-turbo": "latest", + "eslint-config-turbo": "*", "eslint-import-resolver-typescript": "^2.7.1", "eslint-plugin-import": "^2.26.0", "eslint-plugin-mdx": "^1.17.1", @@ -59353,7 +59354,7 @@ "currency.js": "^2.0.4", "dayjs": "^1.11.7", "diff-match-patch": "^1.0.5", - "dompurify": "^3.2.3", + "dompurify": "^3.2.4", "dotenv": "^16.0.3", "echarts": "^5.5.0", "ejs": "^3.1.10", diff --git a/packages/mirinae/package.json b/packages/mirinae/package.json index 9bb8383655..bbbf861bc4 100644 --- a/packages/mirinae/package.json +++ b/packages/mirinae/package.json @@ -70,7 +70,7 @@ "commander": "^10.0.1", "core-js": "^3.29.1", "dayjs": "^1.10.7", - "dompurify": "^3.2.3", + "dompurify": "^3.2.4", "dragselect": "^1.15.1", "ejs": "^3.1.10", "filepond": "^4.30.3", From 2a67f577e07fca951ddb03a5d3f3586c4a9c2bd3 Mon Sep 17 00:00:00 2001 From: WANJIN Date: Tue, 25 Feb 2025 18:49:43 +0900 Subject: [PATCH 02/59] chore(workflow): improve random reviewer assignment logic (#5647) Signed-off-by: Wanjin Noh --- .../pull_request_random_reviewer_assignment.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pull_request_random_reviewer_assignment.yaml b/.github/workflows/pull_request_random_reviewer_assignment.yaml index 25f16efca6..7325bd6f08 100644 --- a/.github/workflows/pull_request_random_reviewer_assignment.yaml +++ b/.github/workflows/pull_request_random_reviewer_assignment.yaml @@ -19,8 +19,7 @@ jobs: runs-on: ubuntu-latest env: - GROUP1: '["WANZARGEN", "sulmoJ", "skdud4659", "piggggggggy"]' - GROUP2: '["kkdy21", "seungyeoneeee", "Hansoo-mzc"]' + REVIEWERS: '["WANZARGEN", "seungyeoneeee", "skdud4659", "piggggggggy"]' steps: - uses: actions/checkout@v3 @@ -30,12 +29,13 @@ jobs: uses: actions/github-script@v6 with: script: | - const group1 = JSON.parse(process.env.GROUP1).filter(user => user !== context.payload.pull_request.user.login); - const group2 = JSON.parse(process.env.GROUP2).filter(user => user !== context.payload.pull_request.user.login); - console.log('group1:', group1, 'group2:', group2); + const reviewers = JSON.parse(process.env.REVIEWERS).filter(user => user !== context.payload.pull_request.user.login); + console.log('available reviewers:', reviewers); - const randomReviewer1 = group1[Math.floor(Math.random() * group1.length)]; - const randomReviewer2 = group2[Math.floor(Math.random() * group2.length)]; + // Shuffle array and pick first two reviewers + const shuffled = reviewers.sort(() => 0.5 - Math.random()); + const randomReviewer1 = shuffled[0]; + const randomReviewer2 = shuffled[1]; console.log('randomReviewer1:', randomReviewer1, 'randomReviewer2:', randomReviewer2); core.setOutput('randomReviewer1', randomReviewer1); From a991c87fc65ef0f5a3ffd42ca3cbec40b6805530 Mon Sep 17 00:00:00 2001 From: Yongtae Park Date: Mon, 24 Feb 2025 18:17:40 +0900 Subject: [PATCH 03/59] chore: edit api query key name Signed-off-by: samuel.park --- .../schema/api-verbs/add.ts | 17 +++++++++++++ .../schema/api-verbs/delete.ts | 3 +++ .../schema/api-verbs/get.ts | 3 +++ .../schema/api-verbs/list.ts | 11 +++++++++ .../schema/api-verbs/load.ts | 15 ++++++++++++ .../schema/api-verbs/transform.ts | 18 ++++++++++++++ .../schema/api-verbs/update.ts | 14 +++++++++++ .../WidgetFormDataTableCardAddContents.vue | 4 ++-- ...dgetFormDataTableCardTransformContents.vue | 4 ++-- .../widgets/_components/WidgetFormOverlay.vue | 4 ++-- .../_components/WidgetFormOverlayStep2.vue | 6 ++--- .../WidgetFormOverlayStep2WidgetForm.vue | 4 ++-- .../_composables/use-widget-form-query.ts | 24 +++++++++---------- .../DashboardLabelsButton.vue | 2 +- .../DashboardManageVariableImportModal.vue | 2 +- .../DashboardManageVariableOverlay.vue | 2 +- .../DashboardNameEditModal.vue | 2 +- .../DashboardRefreshDropdown.vue | 2 +- .../DashboardReorderSidebar.vue | 2 +- .../DashboardToolsetDateDropdown.vue | 2 +- .../DashboardVariablesFormModal.vue | 2 +- .../DashboardVariablesMoreButton.vue | 2 +- .../DashboardWidgetContainerV2.vue | 2 +- .../composables/use-dashboard-detail-query.ts | 24 +++++++++---------- .../dashboards/pages/DashboardDetailPage.vue | 2 +- 25 files changed, 127 insertions(+), 46 deletions(-) create mode 100644 apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/add.ts create mode 100644 apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/delete.ts create mode 100644 apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/get.ts create mode 100644 apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/list.ts create mode 100644 apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/load.ts create mode 100644 apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/transform.ts create mode 100644 apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/update.ts diff --git a/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/add.ts b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/add.ts new file mode 100644 index 0000000000..b58c7c4d6b --- /dev/null +++ b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/add.ts @@ -0,0 +1,17 @@ +import type { Tags } from '@/api-clients/_common/schema/model'; +import type { DashboardVars } from '@/api-clients/dashboard/_types/dashboard-type'; + +import type { + DataTableOptions, DataTableSourceType, +} from '@/common/modules/widgets/types/widget-model'; + + + +export interface DataTableAddParameters { + widget_id: string; + name?: string; + source_type: DataTableSourceType; + options?: DataTableOptions; + tags?: Tags; + vars?: DashboardVars; +} diff --git a/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/delete.ts b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/delete.ts new file mode 100644 index 0000000000..9e29a7bc5c --- /dev/null +++ b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/delete.ts @@ -0,0 +1,3 @@ +export interface DataTableDeleteParameters { + data_table_id: string; +} diff --git a/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/get.ts b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/get.ts new file mode 100644 index 0000000000..ee75f6f558 --- /dev/null +++ b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/get.ts @@ -0,0 +1,3 @@ +export interface DataTableGetParameters { + data_table_id: string; +} diff --git a/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/list.ts b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/list.ts new file mode 100644 index 0000000000..de0f6003ef --- /dev/null +++ b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/list.ts @@ -0,0 +1,11 @@ +import type { DataTableSourceType, DataTableOperator, DataTableDataType } from '@/common/modules/widgets/types/widget-model'; + +export interface DataTableListParameters { + widget_id: string; + query?: Record; + data_table_id?: string; + name?: string; + data_type?: DataTableDataType + source_type?: DataTableSourceType; + operator?: DataTableOperator; +} diff --git a/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/load.ts b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/load.ts new file mode 100644 index 0000000000..defac8b27b --- /dev/null +++ b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/load.ts @@ -0,0 +1,15 @@ +import type { Page } from '@/api-clients/_common/schema/type'; +import type { DashboardVars } from '@/api-clients/dashboard/_types/dashboard-type'; +import type { Granularity } from '@/api-clients/dashboard/_types/widget-type'; + + + +export interface DataTableLoadParameters { + data_table_id: string; + granularity: Granularity; + start?: string; + end?: string; + sort?: any[]; + page?: Page; + vars?: DashboardVars; +} diff --git a/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/transform.ts b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/transform.ts new file mode 100644 index 0000000000..4e18967e73 --- /dev/null +++ b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/transform.ts @@ -0,0 +1,18 @@ +import type { Tags } from '@/api-clients/_common/schema/model'; +import type { DashboardVars } from '@/api-clients/dashboard/_types/dashboard-type'; + +import type { + DataTableOperator, + DataTableOptions, +} from '@/common/modules/widgets/types/widget-model'; + + + +export interface DataTableTransformParameters { + widget_id: string; + name?: string; + operator: DataTableOperator; + options?: DataTableOptions; + tags?: Tags; + vars?: DashboardVars; +} diff --git a/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/update.ts b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/update.ts new file mode 100644 index 0000000000..9641db8bbc --- /dev/null +++ b/apps/web/src/api-clients/dashboard/private-data-table/schema/api-verbs/update.ts @@ -0,0 +1,14 @@ +import type { Tags } from '@/api-clients/_common/schema/model'; +import type { DashboardVars } from '@/api-clients/dashboard/_types/dashboard-type'; + +import type { DataTableOptions } from '@/common/modules/widgets/types/widget-model'; + + + +export interface DataTableUpdateParameters { + data_table_id: string; + name?: string; + options?: DataTableOptions; + tags?: Tags; + vars?: DashboardVars; +} diff --git a/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardAddContents.vue b/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardAddContents.vue index c5e799ca6f..179d9bfcda 100644 --- a/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardAddContents.vue +++ b/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardAddContents.vue @@ -287,8 +287,8 @@ const { mutateAsync: updateWidget } = useMutation({ mutationFn: fetcher.updateWidgetFn, onSuccess: (data) => { const widgetQueryKey = widgetGenerateState.widgetId?.startsWith('private') - ? keys.privateWidgetQueryKey - : keys.publicWidgetQueryKey; + ? keys.privateWidgetGetQueryKey + : keys.publicWidgetGetQueryKey; queryClient.setQueryData(widgetQueryKey.value, () => data); }, onError: (e) => { diff --git a/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardTransformContents.vue b/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardTransformContents.vue index b09b60dd80..a350204ac1 100644 --- a/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardTransformContents.vue +++ b/apps/web/src/common/modules/widgets/_components/WidgetFormDataTableCardTransformContents.vue @@ -249,8 +249,8 @@ const { mutateAsync: updateWidget } = useMutation({ mutationFn: fetcher.updateWidgetFn, onSuccess: (data) => { const widgetQueryKey = widgetGenerateState.widgetId?.startsWith('private') - ? keys.privateWidgetQueryKey - : keys.publicWidgetQueryKey; + ? keys.privateWidgetGetQueryKey + : keys.publicWidgetGetQueryKey; queryClient.setQueryData(widgetQueryKey.value, () => data); }, onError: (e) => { diff --git a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlay.vue b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlay.vue index 97a9170ab7..097984aa25 100644 --- a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlay.vue +++ b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlay.vue @@ -111,8 +111,8 @@ const { mutateAsync: updateWidget } = useMutation({ mutationFn: fetcher.updateWidgetFn, onSuccess: (data) => { const widgetQueryKey = widgetGenerateState.widgetId?.startsWith('private') - ? keys.privateWidgetQueryKey - : keys.publicWidgetQueryKey; + ? keys.privateWidgetGetQueryKey + : keys.publicWidgetGetQueryKey; queryClient.setQueryData(widgetQueryKey.value, () => data); }, onError: (e) => { diff --git a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue index ed048df910..6cefefc8b9 100644 --- a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue +++ b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue @@ -149,8 +149,8 @@ const { mutateAsync: updateWidgetMutate } = useMutation({ mutationFn: wigetFetcher.updateWidgetFn, onSuccess: (data) => { const widgetQueryKey = state.isPrivate - ? widgetKeys.privateWidgetQueryKey - : widgetKeys.publicWidgetQueryKey; + ? widgetKeys.privateWidgetQueryGetKey + : widgetKeys.publicWidgetQueryGetKey; queryClient.setQueryData(widgetQueryKey.value, () => data); }, onError: (e) => { @@ -202,7 +202,7 @@ const { mutate: updateDashboard } = useMutation( { mutationFn: fetcher.updateDashboardFn, onSuccess: (data) => { - const dashboardQueryKey = state.isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = state.isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; // queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); queryClient.setQueryData(dashboardQueryKey.value, () => data); }, diff --git a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2WidgetForm.vue b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2WidgetForm.vue index 761041aa00..512d8c4747 100644 --- a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2WidgetForm.vue +++ b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2WidgetForm.vue @@ -114,8 +114,8 @@ const { mutateAsync: updateWidget } = useMutation({ mutationFn: fetcher.updateWidgetFn, onSuccess: (data) => { const widgetQueryKey = widgetGenerateState.widgetId?.startsWith('private') - ? keys.privateWidgetQueryKey - : keys.publicWidgetQueryKey; + ? keys.privateWidgetGetQueryKey + : keys.publicWidgetGteQueryKey; queryClient.setQueryData(widgetQueryKey.value, () => data); }, onError: (e) => { diff --git a/apps/web/src/common/modules/widgets/_composables/use-widget-form-query.ts b/apps/web/src/common/modules/widgets/_composables/use-widget-form-query.ts index 80070fb3fb..4c5bac911e 100644 --- a/apps/web/src/common/modules/widgets/_composables/use-widget-form-query.ts +++ b/apps/web/src/common/modules/widgets/_composables/use-widget-form-query.ts @@ -29,8 +29,8 @@ interface UseWidgetFormQueryReturn { dataTableListLoading: ComputedRef; widgetLoading: ComputedRef; keys: { - publicWidgetQueryKey: ComputedRef; - privateWidgetQueryKey: ComputedRef; + publicWidgetGetQueryKey: ComputedRef; + privateWidgetGetQueryKey: ComputedRef; publicWidgetLoadQueryKey: ComputedRef; privateWidgetLoadQueryKey: ComputedRef; publicWidgetLoadSumQueryKey: ComputedRef; @@ -59,13 +59,13 @@ export const useWidgetFormQuery = ({ }: UseWidgetFormQueryOptions): UseWidgetFormQueryReturn => { const { publicWidgetAPI, - publicWidgetQueryKey, + publicWidgetGetQueryKey, publicWidgetLoadQueryKey, publicWidgetLoadSumQueryKey, } = usePublicWidgetApi(); const { privateWidgetAPI, - privateWidgetQueryKey, + privateWidgetGetQueryKey, privateWidgetLoadQueryKey, privateWidgetLoadSumQueryKey, } = usePrivateWidgetApi(); @@ -84,12 +84,12 @@ export const useWidgetFormQuery = ({ const isPrivate = computed(() => !!widgetId?.value?.startsWith('private')); /* Query Keys */ - const _publicWidgetQueryKey = computed(() => [ - ...publicWidgetQueryKey.value, + const _publicWidgetGetQueryKey = computed(() => [ + ...publicWidgetGetQueryKey.value, widgetId?.value, ]); - const _privateWidgetQueryKey = computed(() => [ - ...privateWidgetQueryKey.value, + const _privateWidgetGetQueryKey = computed(() => [ + ...privateWidgetGetQueryKey.value, widgetId?.value, ]); const _publicDataTableListQueryKey = computed(() => [ @@ -103,7 +103,7 @@ export const useWidgetFormQuery = ({ /* Querys */ const publicWidgetQuery = useScopedQuery({ - queryKey: _publicWidgetQueryKey, + queryKey: _publicWidgetGetQueryKey, queryFn: () => publicWidgetAPI.get({ widget_id: widgetId?.value as string, }), @@ -111,7 +111,7 @@ export const useWidgetFormQuery = ({ staleTime: STALE_TIME, }, ['DOMAIN', 'WORKSPACE']); const privateWidgetQuery = useScopedQuery({ - queryKey: _privateWidgetQueryKey, + queryKey: _privateWidgetGetQueryKey, queryFn: () => privateWidgetAPI.get({ widget_id: widgetId?.value as string, }), @@ -175,8 +175,8 @@ export const useWidgetFormQuery = ({ privateDataTableAPI, }, keys: { - publicWidgetQueryKey: _publicWidgetQueryKey, - privateWidgetQueryKey: _privateWidgetQueryKey, + publicWidgetGetQueryKey: _publicWidgetGetQueryKey, + privateWidgetGetQueryKey: _privateWidgetGetQueryKey, publicDataTableListQueryKey: _publicDataTableListQueryKey, privateDataTableListQueryKey: _privateDataTableListQueryKey, publicWidgetLoadQueryKey: computed(() => publicWidgetLoadQueryKey.value), diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardLabelsButton.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardLabelsButton.vue index 9a49fc420f..3e0a637895 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardLabelsButton.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardLabelsButton.vue @@ -56,7 +56,7 @@ const { mutate } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); }, onError: (e) => { diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableImportModal.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableImportModal.vue index 5b7a35b2eb..015e796ff9 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableImportModal.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableImportModal.vue @@ -100,7 +100,7 @@ const { mutate } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); showSuccessMessage(i18n.t('DASHBOARDS.DETAIL.VARIABLES.ALT_S_UPDATE_DASHBOARD_VARS_SCHEMA'), ''); }, diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableOverlay.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableOverlay.vue index a663dfd361..140e020d26 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableOverlay.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardManageVariableOverlay.vue @@ -187,7 +187,7 @@ const { mutate } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: DashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.setQueryData(dashboardQueryKey.value, (oldDashboard) => { if (!oldDashboard) return oldDashboard; return { diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardNameEditModal.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardNameEditModal.vue index 7a11e2ef74..085f0e4e73 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardNameEditModal.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardNameEditModal.vue @@ -100,7 +100,7 @@ const { mutate, isPending: loading } = useMutation( const dashboardListQueryKey = isPrivate ? keys.privateDashboardListQueryKey : keys.publicDashboardListQueryKey; queryClient.invalidateQueries({ queryKey: dashboardListQueryKey.value }); if (state.isDetailPage) { - const dashboardQueryKey = isPrivate ? dashboardDetailKeys.privateDashboardQueryKey : dashboardDetailKeys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? dashboardDetailKeys.privateDashboardGetQueryKey : dashboardDetailKeys.publicDashboardGetQueryKey; queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); } }, diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardRefreshDropdown.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardRefreshDropdown.vue index eb8fde3eab..6ae95754cb 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardRefreshDropdown.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardRefreshDropdown.vue @@ -119,7 +119,7 @@ const { mutate } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); }, }, diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardReorderSidebar.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardReorderSidebar.vue index 31ba786689..b85dad62a9 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardReorderSidebar.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardReorderSidebar.vue @@ -75,7 +75,7 @@ const { mutate: updateDashboard } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); }, onSettled: () => { diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardToolsetDateDropdown.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardToolsetDateDropdown.vue index 3d9da1bd02..4f01e9ae5e 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardToolsetDateDropdown.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardToolsetDateDropdown.vue @@ -162,7 +162,7 @@ const { mutate } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); }, }, diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesFormModal.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesFormModal.vue index f0d832c6c1..8185722b9a 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesFormModal.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesFormModal.vue @@ -216,7 +216,7 @@ const { mutate, isPending: loading } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.setQueryData(dashboardQueryKey.value, (oldDashboard) => { if (!oldDashboard) return oldDashboard; return { diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesMoreButton.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesMoreButton.vue index 9191dc8ea8..6f2679a0b9 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesMoreButton.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardVariablesMoreButton.vue @@ -125,7 +125,7 @@ const { mutate, isPending: loading } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: DashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.setQueryData(dashboardQueryKey.value, (oldDashboard) => { if (!oldDashboard) return oldDashboard; return { diff --git a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardWidgetContainerV2.vue b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardWidgetContainerV2.vue index 51cf6d5366..4d320db71e 100644 --- a/apps/web/src/services/dashboards/components/dashboard-detail/DashboardWidgetContainerV2.vue +++ b/apps/web/src/services/dashboards/components/dashboard-detail/DashboardWidgetContainerV2.vue @@ -187,7 +187,7 @@ const { mutateAsync: updateDashboard } = useMutation( mutationFn: fetcher.updateDashboardFn, onSuccess: async (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; await queryClient.invalidateQueries({ queryKey: dashboardQueryKey.value }); }, }, diff --git a/apps/web/src/services/dashboards/composables/use-dashboard-detail-query.ts b/apps/web/src/services/dashboards/composables/use-dashboard-detail-query.ts index fb35f870d5..9049e25f79 100644 --- a/apps/web/src/services/dashboards/composables/use-dashboard-detail-query.ts +++ b/apps/web/src/services/dashboards/composables/use-dashboard-detail-query.ts @@ -33,8 +33,8 @@ interface UseDashboardDetailQueryReturn { isLoading: ComputedRef; isError: ComputedRef; keys: { - publicDashboardQueryKey: ComputedRef; - privateDashboardQueryKey: ComputedRef; + publicDashboardGetQueryKey: ComputedRef; + privateDashboardGetQueryKey: ComputedRef; publicWidgetListQueryKey: ComputedRef; privateWidgetListQueryKey: ComputedRef; }; @@ -54,8 +54,8 @@ interface UseDashboardDetailQueryReturn { export const useDashboardDetailQuery = ({ dashboardId, }: UseDashboardDetailQueryOptions): UseDashboardDetailQueryReturn => { - const { publicDashboardAPI, publicDashboardQueryKey } = usePublicDashboardApi(); - const { privateDashboardAPI, privateDashboardQueryKey } = usePrivateDashboardApi(); + const { publicDashboardAPI, publicDashboardGetQueryKey } = usePublicDashboardApi(); + const { privateDashboardAPI, privateDashboardGetQueryKey } = usePrivateDashboardApi(); const { publicWidgetAPI, publicWidgetListQueryKey } = usePublicWidgetApi(); const { privateWidgetAPI, privateWidgetListQueryKey } = usePrivateWidgetApi(); const queryClient = useQueryClient(); @@ -63,12 +63,12 @@ export const useDashboardDetailQuery = ({ const isPrivate = computed(() => !!dashboardId.value?.startsWith('private')); /* Query Keys */ - const _publicDashboardQueryKey = computed(() => [ - ...publicDashboardQueryKey.value, + const _publicDashboardGetQueryKey = computed(() => [ + ...publicDashboardGetQueryKey.value, dashboardId.value, ]); - const _privateDashboardQueryKey = computed(() => [ - ...privateDashboardQueryKey.value, + const _privateDashboardGetQueryKey = computed(() => [ + ...privateDashboardGetQueryKey.value, dashboardId.value, ]); const _publicWidgetListQueryKey = computed(() => [ @@ -82,7 +82,7 @@ export const useDashboardDetailQuery = ({ /* Querys */ const publicDashboardQuery = useScopedQuery({ - queryKey: _publicDashboardQueryKey, + queryKey: _publicDashboardGetQueryKey, queryFn: () => publicDashboardAPI.get({ dashboard_id: dashboardId.value as string, }), @@ -90,7 +90,7 @@ export const useDashboardDetailQuery = ({ staleTime: STALE_TIME, }, ['DOMAIN', 'WORKSPACE']); const privateDashboardQuery = useScopedQuery({ - queryKey: _privateDashboardQueryKey, + queryKey: _privateDashboardGetQueryKey, queryFn: () => privateDashboardAPI.get({ dashboard_id: dashboardId.value as string, }), @@ -156,8 +156,8 @@ export const useDashboardDetailQuery = ({ privateWidgetAPI, }, keys: { - publicDashboardQueryKey: _publicDashboardQueryKey, - privateDashboardQueryKey: _privateDashboardQueryKey, + publicDashboardGetQueryKey: _publicDashboardGetQueryKey, + privateDashboardGetQueryKey: _privateDashboardGetQueryKey, publicWidgetListQueryKey: _publicWidgetListQueryKey, privateWidgetListQueryKey: _privateWidgetListQueryKey, }, diff --git a/apps/web/src/services/dashboards/pages/DashboardDetailPage.vue b/apps/web/src/services/dashboards/pages/DashboardDetailPage.vue index 66abaf0094..05b4473349 100644 --- a/apps/web/src/services/dashboards/pages/DashboardDetailPage.vue +++ b/apps/web/src/services/dashboards/pages/DashboardDetailPage.vue @@ -101,7 +101,7 @@ const { mutate: updateDashboard, isPending: dashboardUpdateLoading } = useMutati mutationFn: fetcher.updateDashboardFn, onSuccess: (_dashboard: PublicDashboardModel|PrivateDashboardModel) => { const isPrivate = _dashboard.dashboard_id.startsWith('private'); - const dashboardQueryKey = isPrivate ? keys.privateDashboardQueryKey : keys.publicDashboardQueryKey; + const dashboardQueryKey = isPrivate ? keys.privateDashboardGetQueryKey : keys.publicDashboardGetQueryKey; queryClient.setQueryData(dashboardQueryKey.value, (oldDashboard) => { if (!oldDashboard) return _dashboard; return { From 9df428aede73e5f078cb57dd5b9cc2757f457a4a Mon Sep 17 00:00:00 2001 From: Yongtae Park Date: Thu, 27 Feb 2025 14:48:38 +0900 Subject: [PATCH 04/59] feat(use-api-query-key): refactor use-api-query-key composable Signed-off-by: samuel.park --- .../_common/composables/use-api-query-key.ts | 59 ++++++ .../_common/composables/use-query-key.ts | 41 ---- .../api-clients/_common/constants/api-doc.ts | 199 ++++++++++++++++++ .../_common/types/query-key-type.ts | 9 + 4 files changed, 267 insertions(+), 41 deletions(-) create mode 100644 apps/web/src/api-clients/_common/composables/use-api-query-key.ts delete mode 100644 apps/web/src/api-clients/_common/composables/use-query-key.ts create mode 100644 apps/web/src/api-clients/_common/constants/api-doc.ts create mode 100644 apps/web/src/api-clients/_common/types/query-key-type.ts diff --git a/apps/web/src/api-clients/_common/composables/use-api-query-key.ts b/apps/web/src/api-clients/_common/composables/use-api-query-key.ts new file mode 100644 index 0000000000..697ff885e4 --- /dev/null +++ b/apps/web/src/api-clients/_common/composables/use-api-query-key.ts @@ -0,0 +1,59 @@ +import type { ComputedRef } from 'vue'; +import { computed, reactive } from 'vue'; + + +import type { QueryKey } from '@tanstack/vue-query'; + +import type { + ResourceName, ServiceName, Verb, +} from '@/api-clients/_common/types/query-key-type'; + + +import { useAppContextStore } from '@/store/app-context/app-context-store'; +import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; + +/** + * Generates a computed query key for API requests, incorporating global parameters. + * + * @param service - The service name, representing the API service scope (e.g., 'dashboard'). + * @param resource - The resource name, specifying the target API resource (e.g., 'public-data-table'). + * @param verb - The API action verb, defining the type of request (e.g., 'get', 'list', 'update'). + * @param additionalGlobalParams - Optional additional global parameters (e.g., workspace ID, admin mode). + * @returns A computed reference to the query key array, structured as `[service, resource, verb, { globalParams }]`. + * + * ### Example Usage: + * ```ts + * const queryKey = useAPIQueryKey('dashboard', 'public-data-table', 'get'); + * ``` + * The generated query key ensures: + * - **Type safety**: Prevents invalid API calls by enforcing a valid `service/resource/verb` combination. + * - **Auto-completion**: Provides intelligent suggestions based on predefined API structure. + * - **Cache management**: Enables precise cache invalidation and data synchronization. + */ + +interface GlobalQueryParams { + workspaceId?: string; + isAdminMode?: boolean; +} +export const useAPIQueryKey = , V extends Verb>( + service: S, + resource: R, + verb: V, + additionalGlobalParams?: Partial, +): ComputedRef => { + const appContextStore = useAppContextStore(); + const userWorkspaceStore = useUserWorkspaceStore(); + + const _state = reactive({ + currentWorkdpaceId: computed(() => userWorkspaceStore.getters.currentWorkspaceId), + isAdminMode: computed(() => appContextStore.getters.isAdminMode), + }); + + const globalQueryParams = reactive({ + workspaceId: _state.currentWorkdpaceId, + isAdminMode: _state.isAdminMode, + ...additionalGlobalParams, + }); + + return computed(() => [service, resource, verb, { ...globalQueryParams }]); +}; diff --git a/apps/web/src/api-clients/_common/composables/use-query-key.ts b/apps/web/src/api-clients/_common/composables/use-query-key.ts deleted file mode 100644 index f5ab16645c..0000000000 --- a/apps/web/src/api-clients/_common/composables/use-query-key.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { ComputedRef } from 'vue'; -import { computed, reactive } from 'vue'; - - -import type { QueryKey } from '@tanstack/vue-query'; - -import { useAppContextStore } from '@/store/app-context/app-context-store'; -import { useUserWorkspaceStore } from '@/store/app-context/workspace/user-workspace-store'; - -/** - * Generates a computed query key for API requests, incorporating global parameters. - * - * @param primaryQueryKey - The primary key for the api query (e.g., 'private-dashboard/get'). It follows the `{api-resource-name}/{api-verb}` convention. - * @param additionalGlobalParams - Optional additional global parameters to include in the api query key. - * @returns A computed reference to the query key array. - */ - -interface GlobalQueryParams { - workspaceId?: string; - isAdminMode?: boolean; -} -export const useAPIQueryKey = ( - primaryQueryKey: string, - additionalGlobalParams?: Partial, -): ComputedRef => { - const appContextStore = useAppContextStore(); - const userWorkspaceStore = useUserWorkspaceStore(); - - const _state = reactive({ - currentWorkdpaceId: computed(() => userWorkspaceStore.getters.currentWorkspaceId), - isAdminMode: computed(() => appContextStore.getters.isAdminMode), - }); - - const globalQueryParams = reactive({ - workspaceId: _state.currentWorkdpaceId, - isAdminMode: _state.isAdminMode, - ...additionalGlobalParams, - }); - - return computed(() => [primaryQueryKey, { ...globalQueryParams }]); -}; diff --git a/apps/web/src/api-clients/_common/constants/api-doc.ts b/apps/web/src/api-clients/_common/constants/api-doc.ts new file mode 100644 index 0000000000..7e615b336b --- /dev/null +++ b/apps/web/src/api-clients/_common/constants/api-doc.ts @@ -0,0 +1,199 @@ +/** + * 🚀 AUTO-GENERATED API DOCUMENTATION + * + * This file is **automatically generated** by the API documentation script. + * **DO NOT** modify this file manually, as changes will be overwritten. + * + * ## Purpose: + * - Provides a structured mapping of API endpoints based on the directory structure. + * - Used for **query key generation**, **caching strategies**, and **API reference**. + * - Helps maintain consistency and prevents hardcoded API keys. + * + * ## How It Works: + * - The script scans the `api-clients/{service-name}/{resource-name}/schema/api-verbs/` directory. + * - Extracts `{service-name}`, `{resource-name}`, and `{verb}.ts` files. + * - Generates a structured **API_DOC** constant. + * + * ## Regenerate: + * If you need to update this file, run: + * + * ```sh + * npm run api-doc + * ``` + * + * 🚨 Any manual modifications will be lost on regeneration! + */ + +export const API_DOC = { + 'cost-analysis': { + budget: [ + 'create', + 'delete', + 'get', + 'list', + 'set-notification', + 'update', + ], + 'budget-usage': [ + 'analyze', + 'list', + ], + cost: [ + 'analyze', + 'stat', + ], + 'cost-query-set': [ + 'create', + 'delete', + 'list', + 'update', + ], + 'cost-report': [ + 'get-url', + 'get', + 'list', + 'send', + ], + 'cost-report-config': [ + 'list', + 'update-recipients', + 'update', + ], + 'cost-report-data': [ + 'analyze', + 'list', + ], + 'data-source': [ + 'get', + 'list', + 'sync', + 'update-permissions', + ], + 'data-source-account': [ + 'analyze', + 'list', + 'reset', + 'update', + ], + job: [ + 'cancel', + 'list', + ], + 'unified-cost': [ + 'analyze', + 'get', + 'list', + 'stat', + ], + }, + dashboard: { + 'private-dashboard': [ + 'change-folder', + 'create', + 'delete', + 'get', + 'list', + 'update', + ], + 'private-data-table': [ + 'add', + 'delete', + 'get', + 'list', + 'load', + 'transform', + 'update', + ], + 'private-folder': [ + 'create', + 'delete', + 'get', + 'list', + 'update', + ], + 'private-widget': [ + 'create', + 'delete', + 'get', + 'list', + 'load-sum', + 'load', + 'update', + ], + 'public-dashboard': [ + 'change-folder', + 'create', + 'delete', + 'get', + 'list', + 'share', + 'unshare', + 'update', + ], + 'public-data-table': [ + 'add', + 'delete', + 'get', + 'list', + 'load', + 'transform', + 'update', + ], + 'public-folder': [ + 'create', + 'delete', + 'get', + 'list', + 'share', + 'unshare', + 'update', + ], + 'public-widget': [ + 'create', + 'delete', + 'get', + 'list', + 'load-sum', + 'load', + 'update', + ], + }, + opsflow: { + comment: [ + 'create', + 'delete', + 'get', + 'list', + 'update', + ], + event: [ + 'list', + ], + task: [ + 'change-assignee', + 'change-status', + 'create', + 'delete', + 'get', + 'list', + 'update-description', + 'update', + ], + 'task-category': [ + 'create', + 'delete', + 'get', + 'list', + 'update', + ], + 'task-type': [ + 'create', + 'delete', + 'get', + 'list', + 'update-fields', + 'update', + ], + }, +} as const; +export type APIDoc = typeof API_DOC; diff --git a/apps/web/src/api-clients/_common/types/query-key-type.ts b/apps/web/src/api-clients/_common/types/query-key-type.ts new file mode 100644 index 0000000000..b8430ca461 --- /dev/null +++ b/apps/web/src/api-clients/_common/types/query-key-type.ts @@ -0,0 +1,9 @@ +import type { API_DOC } from '@/api-clients/_common/constants/api-doc'; + + +/** + * Extracts all possible keys for `{service-name}`, `{resource-name}`, and `{verb}` + */ +export type ServiceName = keyof typeof API_DOC; +export type ResourceName = keyof (typeof API_DOC)[S]; +export type Verb> = Extract<(typeof API_DOC)[S][R], string[]>[number] | string; From bd5d8ccbe8ee940d1eed2991a7ac52bdd7310d26 Mon Sep 17 00:00:00 2001 From: Yongtae Park Date: Thu, 27 Feb 2025 14:49:13 +0900 Subject: [PATCH 05/59] feat(api-doc): create api-doc generating cli Signed-off-by: samuel.park --- apps/web/cli/api-doc-gen.js | 78 +++++++++++++++++++++++++++++++++++++ apps/web/package.json | 3 +- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 apps/web/cli/api-doc-gen.js diff --git a/apps/web/cli/api-doc-gen.js b/apps/web/cli/api-doc-gen.js new file mode 100644 index 0000000000..ffe1e79572 --- /dev/null +++ b/apps/web/cli/api-doc-gen.js @@ -0,0 +1,78 @@ +import fs from 'fs'; +import path from 'path'; + +const API_DIR = './src/api-clients'; +const OUTPUT_PATH = './src/api-clients/_common/constants/api-doc.ts'; + + +const generateAPIDocumentation = (basePath) => { + const result = {}; + + const traverse = (dirPath) => { + const parts = dirPath.split(path.sep).slice(-5); + if (parts.length !== 5) return; + if (parts[3] !== 'api-verbs' || parts[1] === '_common') return; + + const [serviceName, resourceName, , , verb] = parts; + + if (!result[serviceName]) result[serviceName] = {}; + if (!result[serviceName][resourceName]) result[serviceName][resourceName] = []; + + result[serviceName][resourceName].push(verb.replace('.ts', '')); + }; + + const walk = (currentPath) => { + const files = fs.readdirSync(currentPath); + + files.forEach((file) => { + const fullPath = path.join(currentPath, file); + + const stat = fs.statSync(fullPath); + + if (stat.isDirectory()) { + walk(fullPath); + } else if (file.endsWith('.ts')) { + traverse(fullPath); + } + }); + }; + + walk(basePath); + return result; +}; + +const API_DOC = generateAPIDocumentation(API_DIR); + +const tsContent = `/** + * 🚀 AUTO-GENERATED API DOCUMENTATION + * + * This file is **automatically generated** by the API documentation script. + * **DO NOT** modify this file manually, as changes will be overwritten. + * + * ## Purpose: + * - Provides a structured mapping of API endpoints based on the directory structure. + * - Used for **query key generation**, **caching strategies**, and **API reference**. + * - Helps maintain consistency and prevents hardcoded API keys. + * + * ## How It Works: + * - The script scans the \`api-clients/{service-name}/{resource-name}/schema/api-verbs/\` directory. + * - Extracts \`{service-name}\`, \`{resource-name}\`, and \`{verb}.ts\` files. + * - Generates a structured **API_DOC** constant. + * + * ## Regenerate: + * If you need to update this file, run: + * + * \`\`\`sh + * npm run api-doc + * \`\`\` + * + * 🚨 Any manual modifications will be lost on regeneration! + */ + +export const API_DOC = ${JSON.stringify(API_DOC, null, 4)} as const; +export type APIDoc = typeof API_DOC; +`; +fs.writeFileSync(OUTPUT_PATH, tsContent); + + +console.log('✅ API Keys generated successfully!'); diff --git a/apps/web/package.json b/apps/web/package.json index c6faa28f47..62392f31fe 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -17,7 +17,8 @@ "eslint:fix": "eslint --fix --ext .js,.vue,.ts .", "stylelint:fix": "stylelint --fix \"src/**/*.{css,vue,pcss,scss}\"", "format": "npm run eslint:fix && npm run stylelint:fix", - "postcss": "node build/reset-css.js" + "postcss": "node build/reset-css.js", + "api-doc": "node ./cli/api-doc-gen.js && npx eslint ./src/api-clients/_common/constants/api-doc.ts --fix" }, "main": "dist/cloudforet-component.common.js", "dependencies": { From c359634d2c3a060ef51242f4656037527545944d Mon Sep 17 00:00:00 2001 From: Yongtae Park Date: Thu, 27 Feb 2025 14:49:51 +0900 Subject: [PATCH 06/59] feat(api-composable): apply changed use-query-key hook Signed-off-by: samuel.park --- .../composables/use-private-dashboard-api.ts | 10 +++++----- .../composables/use-private-data-table-api.ts | 12 ++++++------ .../composables/use-private-folder-api.ts | 10 +++++----- .../composables/use-private-widget-api.ts | 14 +++++++------- .../composables/use-public-dashboard-api.ts | 10 +++++----- .../composables/use-public-data-table-api.ts | 12 ++++++------ .../composables/use-public-folder-api.ts | 10 +++++----- .../composables/use-public-widget-api.ts | 14 +++++++------- 8 files changed, 46 insertions(+), 46 deletions(-) diff --git a/apps/web/src/api-clients/dashboard/private-dashboard/composables/use-private-dashboard-api.ts b/apps/web/src/api-clients/dashboard/private-dashboard/composables/use-private-dashboard-api.ts index e6be21d1f7..94168b16fa 100644 --- a/apps/web/src/api-clients/dashboard/private-dashboard/composables/use-private-dashboard-api.ts +++ b/apps/web/src/api-clients/dashboard/private-dashboard/composables/use-private-dashboard-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { PrivateDashboardChangeFolderParameters } from '@/api-clients/dashboard/private-dashboard/schema/api-verbs/change-folder'; import type { PrivateDashboardCreateParameters } from '@/api-clients/dashboard/private-dashboard/schema/api-verbs/create'; @@ -15,7 +15,7 @@ import type { PrivateDashboardUpdateParameters } from '@/api-clients/dashboard/p import type { PrivateDashboardModel } from '@/api-clients/dashboard/private-dashboard/schema/model'; interface UsePrivateDashboardApiReturn { - privateDashboardQueryKey: ComputedRef; + privateDashboardGetQueryKey: ComputedRef; privateDashboardListQueryKey: ComputedRef; privateDashboardAPI: { create: (params: PrivateDashboardCreateParameters) => Promise; @@ -29,8 +29,8 @@ interface UsePrivateDashboardApiReturn { export const usePrivateDashboardApi = (): UsePrivateDashboardApiReturn => { - const privateDashboardQueryKey = useAPIQueryKey('private-dashboard/get'); - const privateDashboardListQueryKey = useAPIQueryKey('private-dashboard/list'); + const privateDashboardGetQueryKey = useAPIQueryKey('dashboard', 'private-dashboard', 'get'); + const privateDashboardListQueryKey = useAPIQueryKey('dashboard', 'private-dashboard', 'list'); const actions = { async create(params: PrivateDashboardCreateParameters) { @@ -54,7 +54,7 @@ export const usePrivateDashboardApi = (): UsePrivateDashboardApiReturn => { }; return { - privateDashboardQueryKey, + privateDashboardGetQueryKey, privateDashboardListQueryKey, privateDashboardAPI: actions, }; diff --git a/apps/web/src/api-clients/dashboard/private-data-table/composables/use-private-data-table-api.ts b/apps/web/src/api-clients/dashboard/private-data-table/composables/use-private-data-table-api.ts index 69dc86ea2b..280c5e58fa 100644 --- a/apps/web/src/api-clients/dashboard/private-data-table/composables/use-private-data-table-api.ts +++ b/apps/web/src/api-clients/dashboard/private-data-table/composables/use-private-data-table-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { DataTableLoadResponse } from '@/api-clients/dashboard/_types/widget-type'; import type { PrivateDataTableModel } from '@/api-clients/dashboard/private-data-table/schema/model'; @@ -17,7 +17,7 @@ import type { DataTableTransformParameters } from '@/api-clients/dashboard/publi import type { DataTableUpdateParameters } from '@/api-clients/dashboard/public-data-table/schema/api-verbs/update'; interface UsePrivateDataTableApiReturn { - privateDataTableQueryKey: ComputedRef; + privateDataTableGetQueryKey: ComputedRef; privateDataTableListQueryKey: ComputedRef; privateDataTableLoadQueryKey: ComputedRef; privateDataTableAPI: { @@ -32,9 +32,9 @@ interface UsePrivateDataTableApiReturn { } export const usePrivateDataTableApi = (): UsePrivateDataTableApiReturn => { - const privateDataTableQueryKey = useAPIQueryKey('private-data-table/get'); - const privateDataTableListQueryKey = useAPIQueryKey('private-data-table/list'); - const privateDataTableLoadQueryKey = useAPIQueryKey('private-data-table/load'); + const privateDataTableGetQueryKey = useAPIQueryKey('dashboard', 'private-data-table', 'get'); + const privateDataTableListQueryKey = useAPIQueryKey('dashboard', 'private-dashboard', 'list'); + const privateDataTableLoadQueryKey = useAPIQueryKey('dashboard', 'private-dashboard', 'list'); const action = { async add(params: DataTableAddParameters) { @@ -61,7 +61,7 @@ export const usePrivateDataTableApi = (): UsePrivateDataTableApiReturn => { }; return { - privateDataTableQueryKey, + privateDataTableGetQueryKey, privateDataTableListQueryKey, privateDataTableLoadQueryKey, privateDataTableAPI: action, diff --git a/apps/web/src/api-clients/dashboard/private-folder/composables/use-private-folder-api.ts b/apps/web/src/api-clients/dashboard/private-folder/composables/use-private-folder-api.ts index bd61398f37..20401b6f12 100644 --- a/apps/web/src/api-clients/dashboard/private-folder/composables/use-private-folder-api.ts +++ b/apps/web/src/api-clients/dashboard/private-folder/composables/use-private-folder-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { PrivateFolderCreateParameters } from '@/api-clients/dashboard/private-folder/schema/api-verbs/create'; import type { PrivateFolderDeleteParameters } from '@/api-clients/dashboard/private-folder/schema/api-verbs/delete'; @@ -14,7 +14,7 @@ import type { PrivateFolderUpdateParameters } from '@/api-clients/dashboard/priv import type { PrivateFolderModel } from '@/api-clients/dashboard/private-folder/schema/model'; interface UsePrivateFolderApiReturn { - privateFolderQueryKey: ComputedRef; + privateFolderGetQueryKey: ComputedRef; privateFolderListQueryKey: ComputedRef; privateFolderAPI: { create: (params: PrivateFolderCreateParameters) => Promise; @@ -26,8 +26,8 @@ interface UsePrivateFolderApiReturn { } export const usePrivateFolderApi = (): UsePrivateFolderApiReturn => { - const privateFolderQueryKey = useAPIQueryKey('private-folder/get'); - const privateFolderListQueryKey = useAPIQueryKey('private-folder/list'); + const privateFolderGetQueryKey = useAPIQueryKey('dashboard', 'private-folder', 'get'); + const privateFolderListQueryKey = useAPIQueryKey('dashboard', 'private-folder', 'list'); const action = { async create(params: PrivateFolderCreateParameters) { @@ -48,7 +48,7 @@ export const usePrivateFolderApi = (): UsePrivateFolderApiReturn => { }; return { - privateFolderQueryKey, + privateFolderGetQueryKey, privateFolderListQueryKey, privateFolderAPI: action, }; diff --git a/apps/web/src/api-clients/dashboard/private-widget/composables/use-private-widget-api.ts b/apps/web/src/api-clients/dashboard/private-widget/composables/use-private-widget-api.ts index 354c0c7d76..abb13242b3 100644 --- a/apps/web/src/api-clients/dashboard/private-widget/composables/use-private-widget-api.ts +++ b/apps/web/src/api-clients/dashboard/private-widget/composables/use-private-widget-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { WidgetLoadResponse } from '@/api-clients/dashboard/_types/widget-type'; import type { PrivateWidgetCreateParameters } from '@/api-clients/dashboard/private-widget/schema/api-verbs/create'; @@ -17,7 +17,7 @@ import type { PrivateWidgetUpdateParameters } from '@/api-clients/dashboard/priv import type { PrivateWidgetModel } from '@/api-clients/dashboard/private-widget/schema/model'; interface UsePrivateWidgetApiReturn { - privateWidgetQueryKey: ComputedRef; + privateWidgetGetQueryKey: ComputedRef; privateWidgetListQueryKey: ComputedRef; privateWidgetLoadQueryKey: ComputedRef; privateWidgetLoadSumQueryKey: ComputedRef; @@ -33,10 +33,10 @@ interface UsePrivateWidgetApiReturn { } export const usePrivateWidgetApi = (): UsePrivateWidgetApiReturn => { - const privateWidgetQueryKey = useAPIQueryKey('private-widget/get'); - const privateWidgetListQueryKey = useAPIQueryKey('private-widget/list'); - const privateWidgetLoadQueryKey = useAPIQueryKey('private-widget/load'); - const privateWidgetLoadSumQueryKey = useAPIQueryKey('private-widget/load-sum'); + const privateWidgetGetQueryKey = useAPIQueryKey('dashboard', 'private-widget', 'get'); + const privateWidgetListQueryKey = useAPIQueryKey('dashboard', 'private-widget', 'list'); + const privateWidgetLoadQueryKey = useAPIQueryKey('dashboard', 'private-widget', 'load'); + const privateWidgetLoadSumQueryKey = useAPIQueryKey('dashboard', 'private-widget', 'load-sum'); const action = { async create(params: PrivateWidgetCreateParameters) { @@ -63,7 +63,7 @@ export const usePrivateWidgetApi = (): UsePrivateWidgetApiReturn => { }; return { - privateWidgetQueryKey, + privateWidgetGetQueryKey, privateWidgetListQueryKey, privateWidgetLoadQueryKey, privateWidgetLoadSumQueryKey, diff --git a/apps/web/src/api-clients/dashboard/public-dashboard/composables/use-public-dashboard-api.ts b/apps/web/src/api-clients/dashboard/public-dashboard/composables/use-public-dashboard-api.ts index 9a04d3f2e5..e2969a6483 100644 --- a/apps/web/src/api-clients/dashboard/public-dashboard/composables/use-public-dashboard-api.ts +++ b/apps/web/src/api-clients/dashboard/public-dashboard/composables/use-public-dashboard-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { PublicDashboardChangeFolderParameters } from '@/api-clients/dashboard/public-dashboard/schema/api-verbs/change-folder'; import type { PublicDashboardCreateParameters } from '@/api-clients/dashboard/public-dashboard/schema/api-verbs/create'; @@ -17,7 +17,7 @@ import type { PublicDashboardUpdateParameters } from '@/api-clients/dashboard/pu import type { PublicDashboardModel } from '@/api-clients/dashboard/public-dashboard/schema/model'; interface UsePublicDashboardApiReturn { - publicDashboardQueryKey: ComputedRef; + publicDashboardGetQueryKey: ComputedRef; publicDashboardListQueryKey: ComputedRef; publicDashboardAPI: { create: (params: PublicDashboardCreateParameters) => Promise; @@ -32,8 +32,8 @@ interface UsePublicDashboardApiReturn { } export const usePublicDashboardApi = (): UsePublicDashboardApiReturn => { - const publicDashboardQueryKey = useAPIQueryKey('public-dashboard/get'); - const publicDashboardListQueryKey = useAPIQueryKey('public-dashboard/list'); + const publicDashboardGetQueryKey = useAPIQueryKey('dashboard', 'public-dashboard', 'get'); + const publicDashboardListQueryKey = useAPIQueryKey('dashboard', 'public-dashboard', 'list'); const actions = { async create(params: PublicDashboardCreateParameters) { @@ -63,7 +63,7 @@ export const usePublicDashboardApi = (): UsePublicDashboardApiReturn => { }; return { - publicDashboardQueryKey, + publicDashboardGetQueryKey, publicDashboardListQueryKey, publicDashboardAPI: actions, }; diff --git a/apps/web/src/api-clients/dashboard/public-data-table/composables/use-public-data-table-api.ts b/apps/web/src/api-clients/dashboard/public-data-table/composables/use-public-data-table-api.ts index b40aa342a5..dcf0879a22 100644 --- a/apps/web/src/api-clients/dashboard/public-data-table/composables/use-public-data-table-api.ts +++ b/apps/web/src/api-clients/dashboard/public-data-table/composables/use-public-data-table-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { DataTableLoadResponse } from '@/api-clients/dashboard/_types/widget-type'; import type { DataTableAddParameters } from '@/api-clients/dashboard/public-data-table/schema/api-verbs/add'; @@ -18,7 +18,7 @@ import type { PublicDataTableModel } from '@/api-clients/dashboard/public-data-t interface UsePublicDataTableApiReturn { - publicDataTableQueryKey: ComputedRef; + publicDataTableGetQueryKey: ComputedRef; publicDataTableListQueryKey: ComputedRef; publicDataTableLoadQueryKey: ComputedRef; publicDataTableAPI: { @@ -33,9 +33,9 @@ interface UsePublicDataTableApiReturn { } export const usePublicDataTableApi = (): UsePublicDataTableApiReturn => { - const publicDataTableQueryKey = useAPIQueryKey('public-data-table/get'); - const publicDataTableListQueryKey = useAPIQueryKey('public-data-table/list'); - const publicDataTableLoadQueryKey = useAPIQueryKey('public-data-table/load'); + const publicDataTableGetQueryKey = useAPIQueryKey('dashboard', 'public-data-table', 'get'); + const publicDataTableListQueryKey = useAPIQueryKey('dashboard', 'public-data-table', 'list'); + const publicDataTableLoadQueryKey = useAPIQueryKey('dashboard', 'public-data-table', 'load'); const action = { async add(params: DataTableAddParameters) { @@ -62,7 +62,7 @@ export const usePublicDataTableApi = (): UsePublicDataTableApiReturn => { }; return { - publicDataTableQueryKey, + publicDataTableGetQueryKey, publicDataTableListQueryKey, publicDataTableLoadQueryKey, publicDataTableAPI: action, diff --git a/apps/web/src/api-clients/dashboard/public-folder/composables/use-public-folder-api.ts b/apps/web/src/api-clients/dashboard/public-folder/composables/use-public-folder-api.ts index 73b3878793..998f523b29 100644 --- a/apps/web/src/api-clients/dashboard/public-folder/composables/use-public-folder-api.ts +++ b/apps/web/src/api-clients/dashboard/public-folder/composables/use-public-folder-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { PublicFolderCreateParameters } from '@/api-clients/dashboard/public-folder/schema/api-verbs/create'; import type { PublicFolderDeleteParameters } from '@/api-clients/dashboard/public-folder/schema/api-verbs/delete'; @@ -16,7 +16,7 @@ import type { PublicFolderUpdateParameters } from '@/api-clients/dashboard/publi import type { PublicFolderModel } from '@/api-clients/dashboard/public-folder/schema/model'; interface UsePublicFolderApiReturn { - publicFolderQueryKey: ComputedRef; + publicFolderGetQueryKey: ComputedRef; publicFolderListQueryKey: ComputedRef; publicFolderAPI: { create: (params: PublicFolderCreateParameters) => Promise; @@ -30,8 +30,8 @@ interface UsePublicFolderApiReturn { } export const usePublicFolderApi = (): UsePublicFolderApiReturn => { - const publicFolderQueryKey = useAPIQueryKey('public-folder/get'); - const publicFolderListQueryKey = useAPIQueryKey('public-folder/list'); + const publicFolderGetQueryKey = useAPIQueryKey('dashboard', 'public-folder', 'get'); + const publicFolderListQueryKey = useAPIQueryKey('dashboard', 'public-folder', 'list'); const action = { async create(params: PublicFolderCreateParameters) { @@ -58,7 +58,7 @@ export const usePublicFolderApi = (): UsePublicFolderApiReturn => { }; return { - publicFolderQueryKey, + publicFolderGetQueryKey, publicFolderListQueryKey, publicFolderAPI: action, }; diff --git a/apps/web/src/api-clients/dashboard/public-widget/composables/use-public-widget-api.ts b/apps/web/src/api-clients/dashboard/public-widget/composables/use-public-widget-api.ts index c30613da9f..36c10f204a 100644 --- a/apps/web/src/api-clients/dashboard/public-widget/composables/use-public-widget-api.ts +++ b/apps/web/src/api-clients/dashboard/public-widget/composables/use-public-widget-api.ts @@ -4,7 +4,7 @@ import type { QueryKey } from '@tanstack/vue-query'; import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; -import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-api-query-key'; import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; import type { WidgetLoadResponse } from '@/api-clients/dashboard/_types/widget-type'; import type { PublicWidgetCreateParameters } from '@/api-clients/dashboard/public-widget/schema/api-verbs/create'; @@ -17,7 +17,7 @@ import type { PublicWidgetUpdateParameters } from '@/api-clients/dashboard/publi import type { PublicWidgetModel } from '@/api-clients/dashboard/public-widget/schema/model'; interface UsePublicWidgetApiReturn { - publicWidgetQueryKey: ComputedRef; + publicWidgetGetQueryKey: ComputedRef; publicWidgetListQueryKey: ComputedRef; publicWidgetLoadQueryKey: ComputedRef; publicWidgetLoadSumQueryKey: ComputedRef; @@ -33,10 +33,10 @@ interface UsePublicWidgetApiReturn { } export const usePublicWidgetApi = (): UsePublicWidgetApiReturn => { - const publicWidgetQueryKey = useAPIQueryKey('public-widget/get'); - const publicWidgetListQueryKey = useAPIQueryKey('public-widget/list'); - const publicWidgetLoadQueryKey = useAPIQueryKey('public-widget/load'); - const publicWidgetLoadSumQueryKey = useAPIQueryKey('public-widget/load-sum'); + const publicWidgetGetQueryKey = useAPIQueryKey('dashboard', 'public-widget', 'get'); + const publicWidgetListQueryKey = useAPIQueryKey('dashboard', 'public-widget', 'list'); + const publicWidgetLoadQueryKey = useAPIQueryKey('dashboard', 'public-widget', 'load'); + const publicWidgetLoadSumQueryKey = useAPIQueryKey('dashboard', 'public-widget', 'load-sum'); const action = { async create(params: PublicWidgetCreateParameters) { @@ -63,7 +63,7 @@ export const usePublicWidgetApi = (): UsePublicWidgetApiReturn => { }; return { - publicWidgetQueryKey, + publicWidgetGetQueryKey, publicWidgetListQueryKey, publicWidgetLoadQueryKey, publicWidgetLoadSumQueryKey, From e26b7fb2d4b4173faab38508a81b74f616c20842 Mon Sep 17 00:00:00 2001 From: Yongtae Park Date: Tue, 4 Mar 2025 10:10:57 +0900 Subject: [PATCH 07/59] chore(query-key): solve query key bug (typo) Signed-off-by: samuel.park --- .../modules/widgets/_components/WidgetFormOverlayStep2.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue index 6cefefc8b9..0a1c87d0ab 100644 --- a/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue +++ b/apps/web/src/common/modules/widgets/_components/WidgetFormOverlayStep2.vue @@ -149,8 +149,8 @@ const { mutateAsync: updateWidgetMutate } = useMutation({ mutationFn: wigetFetcher.updateWidgetFn, onSuccess: (data) => { const widgetQueryKey = state.isPrivate - ? widgetKeys.privateWidgetQueryGetKey - : widgetKeys.publicWidgetQueryGetKey; + ? widgetKeys.privateWidgetGetQueryKey + : widgetKeys.publicWidgetGetQueryKey; queryClient.setQueryData(widgetQueryKey.value, () => data); }, onError: (e) => { From c516621ebe40b10223c422e933a615241b3393c6 Mon Sep 17 00:00:00 2001 From: mzc-eeheg <166787584+mzc-eeheg@users.noreply.github.com> Date: Wed, 5 Mar 2025 00:21:01 +0900 Subject: [PATCH 08/59] chore(ci): update Slack webhook URL in Make Helm Chart Signed-off-by: mzc-eeheg <166787584+mzc-eeheg@users.noreply.github.com> --- .github/workflows/dispatch_make_helm_chart.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dispatch_make_helm_chart.yaml b/.github/workflows/dispatch_make_helm_chart.yaml index e42c0a8e87..5fa9262b2d 100644 --- a/.github/workflows/dispatch_make_helm_chart.yaml +++ b/.github/workflows/dispatch_make_helm_chart.yaml @@ -5,7 +5,7 @@ on: types: [make_helm_chart] env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_GITHUB_HELM_CHART_WEBHOOK_URL }} jobs: helm_cloudforet: @@ -75,4 +75,4 @@ jobs: with: status: ${{job.status}} fields: repo,message,commit,author,action,eventName,ref,workflow,job,took - author_name: Github Action Slack \ No newline at end of file + author_name: Github Action Slack From 0ea6ccdb1f5a35da6cf245df4592d3ded048f297 Mon Sep 17 00:00:00 2001 From: WANJIN Date: Wed, 5 Mar 2025 16:43:58 +0900 Subject: [PATCH 09/59] feat(opsflow): fix v1 minor bugs and refactor to use vue query for task apis (#5674) * feat(link): add line height prop to link component Signed-off-by: Wanjin Noh * fix(text-editor): add white-space pre-wrap to code blocks Signed-off-by: Wanjin Noh * fix(board-task): add line height classes to task name field Signed-off-by: Wanjin Noh * refactor(ops-flow): update import paths for task-related schemas Signed-off-by: Wanjin Noh * feat(ops-flow): add category and task type descriptions to task creation form Signed-off-by: Wanjin Noh * feat(task-fields): add text field options and improve field configuration Signed-off-by: Wanjin Noh * feat(opsflow): add composable API clients for task, task category, and task type Signed-off-by: Wanjin Noh * refactor(board-task): migrate to vue-query and improve task list loading Signed-off-by: Wanjin Noh * refactor(task-detail): migrate to vue-query and improve task loading mechanism Signed-off-by: Wanjin Noh * refactor(task-assign): update task API import and method signature Signed-off-by: Wanjin Noh * refactor(ops-flow): remove unused imports and task loading logic from landing page Signed-off-by: Wanjin Noh * refactor(task-content-form): update task API import and status change method Signed-off-by: Wanjin Noh * refactor(task-type-delete): migrate to vue-query for associated tasks loading Signed-off-by: Wanjin Noh * refactor(task-category-delete): add use-associated-tasks-query Signed-off-by: Wanjin Noh * fix(collapsible-panel): update display style for text clamping to inline-box Signed-off-by: Wanjin Noh * refactor(task-category-delete): optimize workspace-based task filtering Signed-off-by: Wanjin Noh * refactor(task-create): migrate to vue-query for task creation with improved error handling Signed-off-by: Wanjin Noh * refactor(task-detail): migrate task update to vue-query and remove deprecated task API composable This commit: - Removes the deprecated `use-task-api.ts` composable - Migrates task update logic to use vue-query mutation in TaskDetailPage - Simplifies task content form store by removing direct task creation/update methods - Adds loading and success state handling for task updates Signed-off-by: Wanjin Noh --------- Signed-off-by: Wanjin Noh --- .../opsflow/_types/task-field-type.ts | 3 +- .../composables/use-task-category-api.ts | 55 +++++++ .../composables/use-task-type-api.ts | 60 ++++++++ .../opsflow/task/composables/use-task-api.ts | 70 +++++++++ .../components/editor/text-editor-nodes.pcss | 1 + .../components/BoardTaskNameField.vue | 2 + .../ops-flow/components/BoardTaskTable.vue | 110 +++++++------- .../ops-flow/components/TaskAssignModal.vue | 11 +- .../components/TaskCategoryDeleteModal.vue | 78 ++++++---- .../components/TaskContentBaseForm.vue | 102 +++++++------ .../components/TaskStatusDeleteModal.vue | 2 +- .../components/TaskStatusDraggableItem.vue | 2 +- .../ops-flow/components/TaskStatusList.vue | 3 +- .../components/TaskStatusSetDefaultModal.vue | 2 +- .../components/TaskTypeDeleteModal.vue | 49 +++--- .../ops-flow/components/TaskTypeForm.vue | 9 +- .../composables/use-associated-tasks-query.ts | 52 +++++++ .../ops-flow/composables/use-task-api.ts | 66 --------- .../composables/use-task-status-field.ts | 2 +- .../composables/use-task-type-field.ts | 3 +- .../constants/task-status-label-constant.ts | 2 +- .../ops-flow/pages/OpsFlowLandingPage.vue | 19 +-- .../ops-flow/pages/TaskCreatePage.vue | 51 +++++-- .../ops-flow/pages/TaskDetailPage.vue | 139 ++++++++++++------ .../stores/admin/task-category-page-store.ts | 44 +----- .../admin/task-management-page-store.ts | 44 ------ .../ops-flow/stores/board-page-store.ts | 4 +- .../stores/task-content-form-store.ts | 52 +------ .../TaskFieldGenerator.vue | 40 ++--- .../TaskFieldGeneratorHeader.vue | 2 +- .../TaskFieldsConfiguration.vue | 19 +-- .../composables/use-task-field-generator.ts | 2 +- .../use-task-fields-configuration.ts | 2 +- .../DropdownOptionsGenerator.vue | 4 +- .../ParagraphOptionsGenerator.vue | 7 +- .../TextOptionsGenerator.vue | 45 ++++++ .../stores/use-task-field-metadata-store.ts | 2 +- .../types/mutable-task-field-type.ts | 2 +- .../types/options-generator-type.ts | 3 +- .../types/task-field-dropdown-enum-type.ts | 2 +- .../types/task-field-type-metadata-type.ts | 2 +- .../task-fields-form/TaskFieldsForm.vue | 2 +- .../composables/use-task-field-validation.ts | 2 +- .../field-templates/AssetTaskField.vue | 2 +- .../field-templates/DateTaskField.vue | 2 +- .../field-templates/DropdownTaskField.vue | 2 +- .../field-templates/LabelsTaskField.vue | 2 +- .../field-templates/ParagraphTaskField.vue | 2 +- .../field-templates/ProjectTaskField.vue | 2 +- .../ServiceAccountTaskField.vue | 2 +- .../field-templates/TextTaskField.vue | 4 +- .../field-templates/UnknownTaskField.vue | 2 +- .../field-templates/UserTaskField.vue | 2 +- .../types/task-field-form-type.ts | 2 +- .../composables/use-text-clamper.ts | 4 +- .../mirinae/src/navigation/link/PLink.mdx | 6 + .../src/navigation/link/PLink.stories.ts | 15 ++ .../mirinae/src/navigation/link/PLink.vue | 6 +- .../src/navigation/link/story-helper.ts | 16 ++ 59 files changed, 749 insertions(+), 495 deletions(-) create mode 100644 apps/web/src/services/ops-flow/composables/use-associated-tasks-query.ts delete mode 100644 apps/web/src/services/ops-flow/composables/use-task-api.ts create mode 100644 apps/web/src/services/ops-flow/task-fields-configuration/options-generator-templates/TextOptionsGenerator.vue diff --git a/apps/web/src/api-clients/opsflow/_types/task-field-type.ts b/apps/web/src/api-clients/opsflow/_types/task-field-type.ts index 1cb2a8e12a..ee7c81085b 100644 --- a/apps/web/src/api-clients/opsflow/_types/task-field-type.ts +++ b/apps/web/src/api-clients/opsflow/_types/task-field-type.ts @@ -17,7 +17,8 @@ export interface TaskFieldOptions { // union of all task field options } /* task field options by type */ -interface TextTaskFieldOptions { +export interface TextTaskFieldOptions { + description?: string; example?: string; max_length?: number; } diff --git a/apps/web/src/api-clients/opsflow/task-category/composables/use-task-category-api.ts b/apps/web/src/api-clients/opsflow/task-category/composables/use-task-category-api.ts index e69de29bb2..0ddeca22a7 100644 --- a/apps/web/src/api-clients/opsflow/task-category/composables/use-task-category-api.ts +++ b/apps/web/src/api-clients/opsflow/task-category/composables/use-task-category-api.ts @@ -0,0 +1,55 @@ +import type { ComputedRef } from 'vue'; + +import type { QueryKey } from '@tanstack/vue-query'; + +import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; + +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; +import type { TaskCategoryCreateParameters } from '@/api-clients/opsflow/task-category/schema/api-verbs/create'; +import type { TaskCategoryDeleteParameters } from '@/api-clients/opsflow/task-category/schema/api-verbs/delete'; +import type { TaskCategoryGetParameters } from '@/api-clients/opsflow/task-category/schema/api-verbs/get'; +import type { TaskCategoryListParameters } from '@/api-clients/opsflow/task-category/schema/api-verbs/list'; +import type { TaskCategoryUpdateParameters } from '@/api-clients/opsflow/task-category/schema/api-verbs/update'; +import type { TaskCategoryModel } from '@/api-clients/opsflow/task-category/schema/model'; + +interface UseTaskCategoryApiReturn { + taskCategoryQueryKey: ComputedRef; + taskCategoryListQueryKey: ComputedRef; + taskCategoryAPI: { + create: (params: TaskCategoryCreateParameters) => Promise; + update: (params: TaskCategoryUpdateParameters) => Promise; + delete: (params: TaskCategoryDeleteParameters) => Promise; + get: (params: TaskCategoryGetParameters) => Promise; + list: (params: TaskCategoryListParameters) => Promise>; + } +} + +export const useTaskCategoryApi = (): UseTaskCategoryApiReturn => { + const taskCategoryQueryKey = useAPIQueryKey('opsflow/task-category/get'); + const taskCategoryListQueryKey = useAPIQueryKey('opsflow/task-category/list'); + + const actions = { + async create(params: TaskCategoryCreateParameters) { + return SpaceConnector.clientV2.opsflow.taskCategory.create(params); + }, + async update(params: TaskCategoryUpdateParameters) { + return SpaceConnector.clientV2.opsflow.taskCategory.update(params); + }, + async delete(params: TaskCategoryDeleteParameters) { + return SpaceConnector.clientV2.opsflow.taskCategory.delete(params); + }, + async get(params: TaskCategoryGetParameters) { + return SpaceConnector.clientV2.opsflow.taskCategory.get(params); + }, + async list(params: TaskCategoryListParameters) { + return SpaceConnector.clientV2.opsflow.taskCategory.list>(params); + }, + }; + + return { + taskCategoryQueryKey, + taskCategoryListQueryKey, + taskCategoryAPI: actions, + }; +}; diff --git a/apps/web/src/api-clients/opsflow/task-type/composables/use-task-type-api.ts b/apps/web/src/api-clients/opsflow/task-type/composables/use-task-type-api.ts index e69de29bb2..e0bf5089b4 100644 --- a/apps/web/src/api-clients/opsflow/task-type/composables/use-task-type-api.ts +++ b/apps/web/src/api-clients/opsflow/task-type/composables/use-task-type-api.ts @@ -0,0 +1,60 @@ +import type { ComputedRef } from 'vue'; + +import type { QueryKey } from '@tanstack/vue-query'; + +import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; + +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; +import type { TaskTypeCreateParameters } from '@/api-clients/opsflow/task-type/schema/api-verbs/create'; +import type { TaskTypeDeleteParameters } from '@/api-clients/opsflow/task-type/schema/api-verbs/delete'; +import type { TaskTypeGetParameters } from '@/api-clients/opsflow/task-type/schema/api-verbs/get'; +import type { TaskTypeListParameters } from '@/api-clients/opsflow/task-type/schema/api-verbs/list'; +import type { TaskTypeUpdateParameters } from '@/api-clients/opsflow/task-type/schema/api-verbs/update'; +import type { TaskTypeUpdateFieldsParameters } from '@/api-clients/opsflow/task-type/schema/api-verbs/update-fields'; +import type { TaskTypeModel } from '@/api-clients/opsflow/task-type/schema/model'; + +interface UseTaskTypeApiReturn { + taskTypeQueryKey: ComputedRef; + taskTypeListQueryKey: ComputedRef; + taskTypeAPI: { + create: (params: TaskTypeCreateParameters) => Promise; + update: (params: TaskTypeUpdateParameters) => Promise; + delete: (params: TaskTypeDeleteParameters) => Promise; + get: (params: TaskTypeGetParameters) => Promise; + list: (params: TaskTypeListParameters) => Promise>; + updateFields: (params: TaskTypeUpdateFieldsParameters) => Promise; + } +} + +export const useTaskTypeApi = (): UseTaskTypeApiReturn => { + const taskTypeQueryKey = useAPIQueryKey('opsflow/task-type/get'); + const taskTypeListQueryKey = useAPIQueryKey('opsflow/task-type/list'); + + const actions = { + async create(params: TaskTypeCreateParameters) { + return SpaceConnector.clientV2.opsflow.taskType.create(params); + }, + async update(params: TaskTypeUpdateParameters) { + return SpaceConnector.clientV2.opsflow.taskType.update(params); + }, + async delete(params: TaskTypeDeleteParameters) { + return SpaceConnector.clientV2.opsflow.taskType.delete(params); + }, + async get(params: TaskTypeGetParameters) { + return SpaceConnector.clientV2.opsflow.taskType.get(params); + }, + async list(params: TaskTypeListParameters) { + return SpaceConnector.clientV2.opsflow.taskType.list>(params); + }, + async updateFields(params: TaskTypeUpdateFieldsParameters) { + return SpaceConnector.clientV2.opsflow.taskType.updateFields(params); + }, + }; + + return { + taskTypeQueryKey, + taskTypeListQueryKey, + taskTypeAPI: actions, + }; +}; diff --git a/apps/web/src/api-clients/opsflow/task/composables/use-task-api.ts b/apps/web/src/api-clients/opsflow/task/composables/use-task-api.ts index e69de29bb2..e60c0f83de 100644 --- a/apps/web/src/api-clients/opsflow/task/composables/use-task-api.ts +++ b/apps/web/src/api-clients/opsflow/task/composables/use-task-api.ts @@ -0,0 +1,70 @@ +import type { ComputedRef } from 'vue'; + +import type { QueryKey } from '@tanstack/vue-query'; + +import { SpaceConnector } from '@cloudforet/core-lib/space-connector'; + +import { useAPIQueryKey } from '@/api-clients/_common/composables/use-query-key'; +import type { ListResponse } from '@/api-clients/_common/schema/api-verbs/list'; +import type { TaskChangeAssigneeParameters } from '@/api-clients/opsflow/task/schema/api-verbs/change-assignee'; +import type { TaskChangeStatusParameters } from '@/api-clients/opsflow/task/schema/api-verbs/change-status'; +import type { TaskCreateParameters } from '@/api-clients/opsflow/task/schema/api-verbs/create'; +import type { TaskDeleteParameters } from '@/api-clients/opsflow/task/schema/api-verbs/delete'; +import type { TaskGetParameters } from '@/api-clients/opsflow/task/schema/api-verbs/get'; +import type { TaskListParameters } from '@/api-clients/opsflow/task/schema/api-verbs/list'; +import type { TaskUpdateParameters } from '@/api-clients/opsflow/task/schema/api-verbs/update'; +import type { TaskUpdateDescriptionParameters } from '@/api-clients/opsflow/task/schema/api-verbs/update-description'; +import type { TaskModel } from '@/api-clients/opsflow/task/schema/model'; + +interface UseTaskApiReturn { + taskQueryKey: ComputedRef; + taskListQueryKey: ComputedRef; + taskAPI: { + create: (params: TaskCreateParameters) => Promise; + update: (params: TaskUpdateParameters) => Promise; + delete: (params: TaskDeleteParameters) => Promise; + get: (params: TaskGetParameters) => Promise; + list: (params: TaskListParameters) => Promise>; + changeAssignee: (params: TaskChangeAssigneeParameters) => Promise; + changeStatus: (params: TaskChangeStatusParameters) => Promise; + updateDescription: (params: TaskUpdateDescriptionParameters) => Promise; + } +} + +export const useTaskApi = (): UseTaskApiReturn => { + const taskQueryKey = useAPIQueryKey('opsflow/task/get'); + const taskListQueryKey = useAPIQueryKey('opsflow/task/list'); + + const actions = { + async create(params: TaskCreateParameters) { + return SpaceConnector.clientV2.opsflow.task.create(params); + }, + async update(params: TaskUpdateParameters) { + return SpaceConnector.clientV2.opsflow.task.update(params); + }, + async delete(params: TaskDeleteParameters) { + return SpaceConnector.clientV2.opsflow.task.delete(params); + }, + async get(params: TaskGetParameters) { + return SpaceConnector.clientV2.opsflow.task.get(params); + }, + async list(params: TaskListParameters) { + return SpaceConnector.clientV2.opsflow.task.list>(params); + }, + async changeAssignee(params: TaskChangeAssigneeParameters) { + return SpaceConnector.clientV2.opsflow.task.changeAssignee(params); + }, + async changeStatus(params: TaskChangeStatusParameters) { + return SpaceConnector.clientV2.opsflow.task.changeStatus(params); + }, + async updateDescription(params: TaskUpdateDescriptionParameters) { + return SpaceConnector.clientV2.opsflow.task.updateDescription(params); + }, + }; + + return { + taskQueryKey, + taskListQueryKey, + taskAPI: actions, + }; +}; diff --git a/apps/web/src/common/components/editor/text-editor-nodes.pcss b/apps/web/src/common/components/editor/text-editor-nodes.pcss index 8602905579..a39d91c52a 100644 --- a/apps/web/src/common/components/editor/text-editor-nodes.pcss +++ b/apps/web/src/common/components/editor/text-editor-nodes.pcss @@ -157,6 +157,7 @@ @apply bg-gray-100 rounded-lg; margin-top: 0.75rem; padding: 0.5rem 1rem; + white-space: pre-wrap; > code { font-family: $font-code; font-size: 0.875rem; diff --git a/apps/web/src/services/ops-flow/components/BoardTaskNameField.vue b/apps/web/src/services/ops-flow/components/BoardTaskNameField.vue index 125cbdc1ed..5a7a2d92e4 100644 --- a/apps/web/src/services/ops-flow/components/BoardTaskNameField.vue +++ b/apps/web/src/services/ops-flow/components/BoardTaskNameField.vue @@ -25,9 +25,11 @@ const props = defineProps<{ taskId: props.taskId, }, }" + class="leading-lg" :highlight="!props.linkNewTab" :action-icon="props.linkNewTab ? 'internal-link' : 'none'" :new-tab="props.linkNewTab" + line-height="1.25" /> diff --git a/apps/web/src/services/ops-flow/components/BoardTaskTable.vue b/apps/web/src/services/ops-flow/components/BoardTaskTable.vue index b16db8fe1b..c0be3b96cd 100644 --- a/apps/web/src/services/ops-flow/components/BoardTaskTable.vue +++ b/apps/web/src/services/ops-flow/components/BoardTaskTable.vue @@ -1,10 +1,14 @@ @@ -85,25 +105,23 @@ onBeforeUnmount(() => { theme-color="alert" :header-title="headerTitle" :size="deletable ? 'sm' : 'md'" - :loading="loading" - :loading-backdrop="taskManagementPageState.loadingAssociatedTasksToCategory" + :is-loading="isDeleting" + :loading-backdrop="isLoading" @confirm="handleConfirm" @close="handleCloseOrCancel" @cancel="handleCloseOrCancel" @closed="handleClosed" > diff --git a/apps/web/src/services/ops-flow/components/TaskContentBaseForm.vue b/apps/web/src/services/ops-flow/components/TaskContentBaseForm.vue index 898a900faa..7d346da2b5 100644 --- a/apps/web/src/services/ops-flow/components/TaskContentBaseForm.vue +++ b/apps/web/src/services/ops-flow/components/TaskContentBaseForm.vue @@ -10,6 +10,7 @@ import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/types/controls/ import type { TaskCategoryModel } from '@/api-clients/opsflow/task-category/schema/model'; import type { TaskTypeModel } from '@/api-clients/opsflow/task-type/schema/model'; +import { useTaskApi } from '@/api-clients/opsflow/task/composables/use-task-api'; import type { TaskModel } from '@/api-clients/opsflow/task/schema/model'; import type { TaskStatusType } from '@/api-clients/opsflow/task/schema/type'; import { i18n } from '@/translations'; @@ -23,7 +24,6 @@ import ErrorHandler from '@/common/composables/error/errorHandler'; import { useFormValidator } from '@/common/composables/form-validator'; import { useCategoryField } from '@/services/ops-flow/composables/use-category-field'; -import { useTaskAPI } from '@/services/ops-flow/composables/use-task-api'; import { useTaskStatusField } from '@/services/ops-flow/composables/use-task-status-field'; import { useTaskTypeField } from '@/services/ops-flow/composables/use-task-type-field'; import { TASK_STATUS_LABELS } from '@/services/ops-flow/constants/task-status-label-constant'; @@ -71,6 +71,10 @@ const handleUpdateSelectedCategory = (items: SelectDropdownMenuItem[]) => { } initRelatedFieldsByCategorySelection(category); }; +const taskCategoryDesciprion = computed(() => { + if (!taskContentFormGetters.currentCategory) return ''; + return taskContentFormGetters.currentCategory.description; +}); /* task type */ const { @@ -96,9 +100,13 @@ const handleUpdateSelectedTaskType = async (items: SelectDropdownMenuItem[]) => initRelatedFieldsByTaskTypeSelection(category, taskType); } }; +const taskTypeDescription = computed(() => { + if (!taskContentFormState.currentTaskType) return ''; + return taskContentFormState.currentTaskType.description; +}); /* status */ -const taskAPI = useTaskAPI(); +const { taskAPI } = useTaskApi(); const { selectedStatusItems, taskStatusValidator, @@ -114,7 +122,10 @@ const changeStatus = async (statusId: string) => { if (!taskContentFormState.originTask) { throw new Error('Origin task is not defined'); } - await taskAPI.changeStatus(taskContentFormState.originTask.task_id, statusId); + await taskAPI.changeStatus({ + task_id: taskContentFormState.originTask.task_id, + status_id: statusId, + }); showSuccessMessage(i18n.t('OPSFLOW.ALT_S_UPDATE_TARGET', { target: i18n.t('OPSFLOW.STATUS') }), ''); } catch (e) { ErrorHandler.handleRequestError(e, i18n.t('OPSFLOW.ALT_E_UPDATE_TARGET', { target: i18n.t('OPSFLOW.STATUS') })); @@ -272,50 +283,57 @@ createModeInitWatchStop = watch([() => taskContentFormState.currentCategoryId, (