diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 397ad2eb92..4d9700e192 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,15 @@ jobs: if: ${{ !contains(github.event.pull_request.title, '[skip checker]') }} strategy: matrix: - shard: [1, 2, 3, 4] + include: + - package_name: base + package_path: packages/base + - package_name: '@actiontech/dms-kit' + package_path: packages/dms-kit + - package_name: '@actiontech/shared' + package_path: packages/shared + - package_name: sqle + package_path: packages/sqle steps: - name: Checkout repository uses: actions/checkout@v4 @@ -34,64 +42,14 @@ jobs: - name: Install dependencies uses: ./.github/actions/catch-install-pnpm - - name: Coverage test report - run: sh ./scripts/jest/run-ci.sh ${{ matrix.shard }} ${{ strategy.job-total }} + - name: Run package test suite + run: pnpm turbo run test:ci --filter=${{ matrix.package_name }} - - uses: actions/upload-artifact@v4 - with: - name: coverage-artifacts-${{ matrix.shard }} - path: coverage/ - - report: - runs-on: ubuntu-latest - if: ${{ !contains(github.event.pull_request.title, '[skip checker]') }} - needs: [test] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Get Coverage 1 - uses: actions/download-artifact@v4 - with: - name: coverage-artifacts-1 - path: coverage - - - name: Get Coverage 2 - uses: actions/download-artifact@v4 - with: - name: coverage-artifacts-2 - path: coverage - - - name: Get Coverage 3 - uses: actions/download-artifact@v4 - with: - name: coverage-artifacts-3 - path: coverage - - - name: Get Coverage 4 - uses: actions/download-artifact@v4 - with: - name: coverage-artifacts-4 - path: coverage - - - name: Install dependencies - uses: ./.github/actions/catch-install-pnpm - - - name: Merge coverage reports - run: node ./scripts/jest/merge-report-json.js - - - name: Coverage test report + - name: Coverage report uses: ArtiomTr/jest-coverage-report-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} - base-coverage-file: coverage-merged.json - coverage-file: coverage-merged.json - - - name: Delete artifact - uses: geekyeggo/delete-artifact@v5 - with: - name: | - coverage-artifacts-1 - coverage-artifacts-2 - coverage-artifacts-3 - coverage-artifacts-4 + custom-title: 'Coverage report (${{ matrix.package_name }})' + coverage-file: ${{ matrix.package_path }}/coverage/report.json + base-coverage-file: ${{ matrix.package_path }}/coverage/report.json + skip-step: all diff --git a/.gitignore b/.gitignore index 4dbb2d65dd..ebf2981337 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,8 @@ dist # testing /ce_coverage /coverage +**/coverage/** /report.json -/coverage-merged -/coverage-merged.json # production /build @@ -53,4 +52,6 @@ verdaccio ftp-data -/scripts/cli/dms-kit-publish/docs \ No newline at end of file +/scripts/cli/dms-kit-publish/docs + +*.turbo \ No newline at end of file diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 0000000000..aa9ef744a3 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,18 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "tabWidth": 2, + "semi": true, + "printWidth": 80, + "trailingComma": "none", + "arrowParens": "always", + "proseWrap": "preserve", + "useTabs": false, + "singleQuote": true, + "bracketSpacing": true, + "jsxBracketSameLine": false, + "sortPackageJson": false, + "ignorePatterns": [ + "*.snap", + "*.md" + ] +} diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000000..72db1b5f1f --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,42 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": [ + "react", + "import", + "node", + "jest", + "typescript", + "unicorn", + "oxc" + ], + "categories": { + "correctness": "warn", + "suspicious": "warn" + }, + "rules": { + "no-console": "warn", + "react-in-jsx-scope": "off", + "no-shadow": "off", + "no-shadow-restricted-names": "error", + "prefer-const": "warn", + "no-extra-boolean-cast": "off", + "no-template-curly-in-string": "warn", + "react/display-name": "off", + "import/no-anonymous-default-export": "warn" + }, + "env": { + "builtin": true + }, + "ignorePatterns": [ + "**/*.test.ts", + "**/*.test.tsx", + "**/demo/**", + "**/demos/**", + "**/dist/**", + "**/es/**", + "**/node_modules/**", + "packages/shared/lib/api/*", + "packages/**/mockApi/*", + "packages/**/testUtil/*" + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile index 58996cf147..69e5770452 100644 --- a/Makefile +++ b/Makefile @@ -38,13 +38,13 @@ docker_clean: $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app -w /usr/src/app --rm $(DOCKER_IMAGE) sh -c "git config --global --add safe.directory /usr/src/app && git clean -dfx" docker_build_ce: pull_image docker_install_node_modules - $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app --user $(UID):$(GID) -w /usr/src/app --rm $(DOCKER_IMAGE) sh -c "pnpm build" + $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app --user $(UID):$(GID) -w /usr/src/app --rm $(DOCKER_IMAGE) sh -c "pnpm --filter base build:release" docker_build_ee: pull_image docker_install_node_modules - $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app --user $(UID):$(GID) -w /usr/src/app --rm $(DOCKER_IMAGE) sh -c "pnpm build:ee" + $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app --user $(UID):$(GID) -w /usr/src/app --rm $(DOCKER_IMAGE) sh -c "pnpm --filter base build:release:ee" docker_build_demo: pull_image docker_install_node_modules - $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app --user $(UID):$(GID) -w /usr/src/app --rm $(DOCKER_IMAGE) sh -c "pnpm build:demo" + $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app --user $(UID):$(GID) -w /usr/src/app --rm $(DOCKER_IMAGE) sh -c "pnpm --filter base build:release:demo" docker_dms_kit_publish: docker_install_node_modules $(DOCKER) run -v $(MAIN_MODULE):/usr/src/app --user $(UID):$(GID) -w /usr/src/app --rm \ diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index b92397d45c..0000000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,101 +0,0 @@ -import { defineConfig, globalIgnores } from 'eslint/config'; -import globals from 'globals'; -import tseslint from 'typescript-eslint'; -import pluginReact from 'eslint-plugin-react'; -import pluginImport from 'eslint-plugin-import'; -import pluginReactHooks from 'eslint-plugin-react-hooks'; -import pluginNode from 'eslint-plugin-node'; - -export default defineConfig([ - tseslint.configs.recommended, - { - files: ['**/scripts/**/*.{js,mjs,cjs,ts,jsx,tsx}'], - plugins: { - import: pluginImport, - node: pluginNode - }, - languageOptions: { - globals: { - ...globals.node - } - }, - rules: { - '@typescript-eslint/no-unused-vars': 'warn', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-require-imports': 'warn', - '@typescript-eslint/no-empty-object-type': 'off' - } - }, - { - files: ['**/packages/**/*.{js,mjs,cjs,ts,jsx,tsx}'], - ...pluginReact.configs.flat.recommended, - plugins: { - import: pluginImport, - react: pluginReact, - 'react-hooks': pluginReactHooks - }, - languageOptions: { - ...pluginReact.configs.flat.recommended.languageOptions, - globals: { - ...globals.browser - } - }, - settings: { - react: { - pragma: 'React', - version: 'detect' - } - }, - rules: { - ...pluginReactHooks.configs.recommended.rules, - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': 'error', - 'no-shadow-restricted-names': 'error', - 'testing-library/render-result-naming-convention': 0, - 'prefer-const': 'warn', - '@typescript-eslint/no-non-null-asserted-optional-chain': 0, - '@typescript-eslint/no-non-null-assertion': 0, - 'no-extra-boolean-cast': 'off', - 'import/no-anonymous-default-export': [2, { allowNew: true }], - '@typescript-eslint/no-empty-interface': [ - 'error', - { - allowSingleExtends: true - } - ], - '@typescript-eslint/no-explicit-any': 'off', - 'react/display-name': 0, - 'react/prop-types': 'off', - 'react/require-default-props': 'off', - 'no-console': 'warn', - '@typescript-eslint/no-unused-vars': 'warn', - 'no-template-curly-in-string': 'warn', - '@typescript-eslint/no-empty-object-type': 'off', - '@typescript-eslint/no-empty-function': 'warn', - 'import/no-anonymous-default-export': 'warn' - } - }, - globalIgnores([ - 'jest.config.js', - 'eslint.config.mjs', - '**/packages/**/*.test.ts', - '**/packages/**/*.test.tsx', - '**/packages/shared/lib/api/*', - '**/packages/**/mockApi/*', - '**/packages/**/testUtil/*', - '**/packages/**/demo/*', - '**/packages/**/demos/*', - 'jest-setup.ts', - 'node_modules/*', - '**/packages/*/node_modules/*', - '**/scripts/jest/*.js', - '/**/node_modules/*', - 'dist', - 'packages/*/dist', - 'packages/*/scripts', - '# config', - 'vite.config.ts', - '.eslintrc.json', - 'es' - ]) -]); diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 6515087c59..0000000000 --- a/jest.config.js +++ /dev/null @@ -1,150 +0,0 @@ -process.env.TZ = 'Asia/Shanghai'; - -const path = require('path'); - -const { compilerOptions } = require('./tsconfig.json'); -const { pathsToModuleNameMapper } = require('ts-jest'); - -compilerOptions.paths['~/*'][0] = path.resolve(compilerOptions.paths['~/*'][0]); - -const sharedModuleNameMapper = { - '.+\\.(css|style|less|sass|scss|ttf|woff|woff2)$': 'identity-obj-proxy', - '@ant-design/plots': - '/packages/shared/lib/testUtil/mockModule/mockAntDesignPlots.jsx', - 'monaco-editor': - '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', - '@monaco-editor/react': - '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', - '@uiw/react-md-editor': - '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', - '@actiontech/(.*)': '/packages/$1', - '@react-sigma/core(.*)$': - '/packages/shared/lib/testUtil/mockModule/mockSigmaCore.tsx', - '@react-sigma/graph-search$': - '/packages/shared/lib/testUtil/mockModule/mockSigmaGraphSearch.tsx', - ...pathsToModuleNameMapper(compilerOptions.paths) -}; - -const sharedIgnorePatterns = ['/node_modules/', '/demo/', '/demos/']; - -// Naming conventions for condition-specific test files: -// *.ce.test.{ts,tsx} → CE project (ee=false, ce=true, sqle=true, dms=false) 不要强制匹配 ce.test, ce.[可选项].test.{ts,tsx} -// *.sqle.test.{ts,tsx} → EE project (ee=true, ce=false, sqle=true, dms=false) 同上 -// *.provision.test.{ts,tsx} → PROVISION project (ee=true, ce=false, sqle=false, provision=true, dms=false) 同上 -// *.test.{ts,tsx} → DMS project (ee=true, ce=false, sqle=true, provision=true, dms=true) [default] 同上 -// 实现:`.ce.` / `.sqle.` / `.provision.` 与 `.test.` 之间可有零段或多段 `.xxx.`(正则见下方 *_TEST_FILE_RE)。 -const CE_TEST_FILE_RE = '\\.ce(\\.[^./]+)*\\.test\\.[jt]sx?$'; -const SQLE_TEST_FILE_RE = '\\.sqle(\\.[^./]+)*\\.test\\.[jt]sx?$'; -const PROVISION_TEST_FILE_RE = '\\.provision(\\.[^./]+)*\\.test\\.[jt]sx?$'; - -const sharedProjectConfig = { - transform: { - '^.+\\.(ts|tsx|js|jsx)$': '/scripts/jest/custom-transform.js', - '^.+\\.(png|jpg|jpeg|css|json)$': '/scripts/jest/file-transform.js' - }, - transformIgnorePatterns: [ - '/dist/', - 'node_modules/(?!(?:.pnpm/)?(@react-sigma|.+/es))[^/]+?/(?!(es|node_modules)/)' - ], - moduleFileExtensions: ['ts', 'tsx', 'js', 'json', 'jsx', 'node'], - testEnvironment: 'jest-environment-jsdom', - resetMocks: true, - moduleNameMapper: sharedModuleNameMapper, - collectCoverageFrom: [ - 'packages/**/{src,lib}/{page,components,hooks,global,store,utils}/**/*.{ts,tsx}', - 'packages/**/src/App.tsx', - 'packages/shared/api/common/**', - '!packages/**/index.type.ts', - '!packages/**/index.enum.ts', - '!packages/sqle/src/page/SqlAnalyze/SqlAnalyze/ProcessListCom/**', - '!packages/shared/lib/hooks/usePrompt/index.tsx', - '!packages/sqle/src/page/Knowledge/Graph/components/**', - '!packages/**/demo/**', - '!packages/**/demos/**' - ], - setupFilesAfterEnv: ['/jest-setup.ts'] -}; - -module.exports = { - projects: [ - { - ...sharedProjectConfig, - displayName: 'dms', - globals: { - TEST_CONDITIONS: { - ee: true, - ce: false, - sqle: true, - provision: true, - dms: true - } - }, - // Default tests only: exclude CE / sqle / provision condition tests (dedicated projects) - testPathIgnorePatterns: [ - ...sharedIgnorePatterns, - CE_TEST_FILE_RE, - SQLE_TEST_FILE_RE, - PROVISION_TEST_FILE_RE - ] - }, - { - ...sharedProjectConfig, - displayName: 'sqle-ce', - globals: { - TEST_CONDITIONS: { - ee: false, - ce: true, - sqle: true, - provision: false, - dms: false - } - }, - testRegex: CE_TEST_FILE_RE, - testPathIgnorePatterns: sharedIgnorePatterns - }, - { - ...sharedProjectConfig, - displayName: 'sqle-ee', - globals: { - TEST_CONDITIONS: { - ee: true, - ce: false, - sqle: true, - provision: false, - dms: false - } - }, - testRegex: SQLE_TEST_FILE_RE, - // e.g. *.ce.sqle.test.* belongs to CE, not EE - testPathIgnorePatterns: [...sharedIgnorePatterns, CE_TEST_FILE_RE] - }, - { - ...sharedProjectConfig, - displayName: 'provision', - globals: { - TEST_CONDITIONS: { - ee: true, - ce: false, - sqle: false, - provision: true, - dms: false - } - }, - testRegex: PROVISION_TEST_FILE_RE, - testPathIgnorePatterns: [...sharedIgnorePatterns, CE_TEST_FILE_RE] - } - ], - reporters: [ - 'default', - [ - 'jest-slow-test-reporter', - { - numTests: 8, - outputDirectory: 'reports', - outputName: 'report.xml', - color: true, - warnSlowerThan: 6000 - } - ] - ] -}; diff --git a/package.json b/package.json index 567c18aebd..9491b360f6 100644 --- a/package.json +++ b/package.json @@ -8,22 +8,28 @@ "pnpm": ">=9.7.0" }, "scripts": { + "preview": "pnpm --filter base preview", "preinstall": "npx only-allow pnpm", - "start": "concurrently \"pnpm --filter base start\" \"pnpm --filter @actiontech/dms-kit dev\"", - "start:ee": "concurrently \"pnpm --filter base start:ee\" \"pnpm --filter @actiontech/dms-kit dev\"", - "start:demo": "concurrently \"pnpm --filter base start:demo\" \"pnpm --filter @actiontech/dms-kit dev\"", - "build": "pnpm --filter @actiontech/dms-kit build && pnpm --filter base build", - "build:ee": "pnpm --filter @actiontech/dms-kit build && pnpm --filter base build:ee", - "build:demo": "pnpm --filter @actiontech/dms-kit build && pnpm --filter base build:demo", - "prettier:w": "prettier -w packages/*/src/ packages/shared/lib/ scripts/cli/*/src", - "prettier:c": "prettier -c packages/*/src/ packages/shared/lib/ scripts/cli/*/src", - "eslint": "eslint packages/*/src/ packages/shared/lib/ scripts/cli/*/src", + "start": "turbo run start --filter=base --parallel", + "start:ee": "turbo run start:ee --filter=base --parallel", + "start:demo": "turbo run start:demo --filter=base --parallel", + "build": "turbo run build --filter=@actiontech/dms-kit && pnpm --filter base build", + "build:ee": "turbo run build --filter=@actiontech/dms-kit && pnpm --filter base build:ee", + "build:demo": "turbo run build --filter=@actiontech/dms-kit && pnpm --filter base build:demo", + "check:turbo": "turbo run check --filter='./packages/*'", + "oxfmt:w": "node ./scripts/format/oxfmt-changed.mjs", + "oxfmt:c": "node ./scripts/format/oxfmt-changed.mjs --check", + "oxfmt:w:all": "oxfmt --write \"packages/*/src/**/*\" \"packages/shared/lib/**/*\" \"scripts/cli/*/src/**/*\"", + "oxfmt:c:all": "oxfmt --check \"packages/*/src/**/*\" \"packages/shared/lib/**/*\" \"scripts/cli/*/src/**/*\"", + "oxlint": "oxlint --no-error-on-unmatched-pattern packages/base/src packages/dms-kit/src packages/shared/src packages/shared/lib packages/sqle/src scripts/cli/create-dms-page/src scripts/cli/dms-kit-publish/src packages/base/vite.config.mts", + "oxlint:turbo": "turbo run oxlint --filter='./packages/*'", "stylelint": "stylelint packages/*/{src,lib}/**/{*.less,style.ts,element.ts}", "ts-check": "tsc --noEmit", - "checker": "concurrently \"pnpm ts-check\" \"pnpm eslint\" \"pnpm stylelint\" \"pnpm prettier:c\"", - "test": "sh ./scripts/jest/run.sh", - "test:c": "sh ./scripts/jest/run-coverage.sh", - "test:ci": "sh ./scripts/jest/run-ci.sh 1 1 && node ./scripts/jest/merge-report-json.js", + "checker": "pnpm check:turbo", + "test": "pnpm --workspace-concurrency=1 --filter base --filter @actiontech/dms-kit --filter @actiontech/shared --filter sqle run test:run", + "test:c": "pnpm --workspace-concurrency=1 --filter base --filter @actiontech/dms-kit --filter @actiontech/shared --filter sqle run test:c", + "test:ci": "turbo run test:ci --filter='./packages/*'", + "test:ci:turbo": "pnpm test:ci", "test:clean": "jest --clearCache", "icon:g": "pnpm --filter @actiontech/icons icon:g", "icon:docs:g": "pnpm --filter @actiontech/icons docs:g", @@ -34,12 +40,13 @@ "api_client:g": "cross-env npm_config_registry=http://10.186.18.19:4873 pnpx @actiontech/cli api-client -y", "api_mocks:g": "cross-env npm_config_registry=http://10.186.18.19:4873 pnpx @actiontech/cli api-mocks -y", "ai-doc": "cross-env npm_config_registry=http://10.186.18.19:4873 pnpx @actiontech/cli ai-doc", - "postinstall": "pnpm --filter @actiontech/dms-kit build", + "dms-kit:build": "turbo run build --filter=@actiontech/dms-kit", "dms-kit:publish": "pnpm --filter @actiontech/cli-dms-kit-publish build && dms-kit-publish" }, "keywords": [], "author": "", "devDependencies": { + "@actiontech/tooling-config": "workspace:^", "@actiontech/cli-create-dms-page": "workspace:^", "@actiontech/cli-dms-kit-publish": "workspace:^", "@cfaester/enzyme-adapter-react-18": "^0.7.0", @@ -60,12 +67,11 @@ "@types/testing-library__jest-dom": "^5.14.5", "@typescript-eslint/eslint-plugin": "^5.30.6", "@typescript-eslint/parser": "^5.30.6", - "@vitejs/plugin-react": "^4.2.1", + "@vitejs/plugin-react": "^6", "babel-jest": "^29.7.0", "babel-preset-react-app": "^10.0.1", "blob-polyfill": "^7.0.20220408", "comment-parser": "^1.4.1", - "concurrently": "^9.1.2", "cross-env": "^7.0.3", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.2", @@ -85,6 +91,8 @@ "less": "^4.1.3", "mockdate": "^3.0.5", "msw": "^0.45.0", + "oxfmt": "^0.45.0", + "oxlint": "^1.60.0", "postcss-less": "^6.0.0", "postcss-styled-syntax": "^0.6.4", "prettier": "^2.7.1", @@ -95,11 +103,11 @@ "stylelint-prettier": "^4.0.2", "ts-jest": "27.1.5", "tsx": "^4.20.5", - "typescript": "^5.0.2", + "turbo": "^2.9.6", + "typescript": "^6", "typescript-eslint": "^8.28.0", - "vite": "^5.2.6", + "vite": "^8", "vite-plugin-conditional-compile": "1.4.3", - "vite-plugin-eslint": "^1.8.1", "vite-plugin-html": "^3.2.2" }, "dependencies": { @@ -117,6 +125,7 @@ "@mui/styles": "^5.11.16", "@mui/system": "^5.9.1", "@reduxjs/toolkit": "^1.9.3", + "@uiw/react-md-editor": "^3.23.5", "@xyflow/react": "^12.3.0", "ahooks": "^3.7.0", "antd": "^5.7.3", @@ -140,8 +149,7 @@ "react-redux": "^8.0.5", "react-router-dom": "^6.10.0", "recoil": "^0.7.4", - "sql-formatter": "^12.2.4", - "@uiw/react-md-editor": "^3.23.5" + "sql-formatter": "^12.2.4" }, "resolutions": { "headers-polyfill": "3.0.10", diff --git a/packages/base/jest.config.mjs b/packages/base/jest.config.mjs new file mode 100644 index 0000000000..c3629d79b9 --- /dev/null +++ b/packages/base/jest.config.mjs @@ -0,0 +1,19 @@ +import { createJestConfig } from '@actiontech/tooling-config/jest/create-jest-config'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +const packageRoot = path.dirname(fileURLToPath(import.meta.url)); + +export default createJestConfig({ + packageRoot, + enabledProjects: ['dms', 'sqle-ce', 'sqle-ee'], + collectCoverageFrom: [ + 'src/{page,components,hooks,global,store,utils}/**/*.{ts,tsx}', + 'src/App.tsx', + '!src/**/*.test.{ts,tsx}', + '!src/**/*.type.ts', + '!src/**/*.enum.ts', + '!src/**/demo/**', + '!src/**/demos/**' + ] +}); diff --git a/packages/base/package.json b/packages/base/package.json index b0aa6eb18f..791f7c183a 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -6,17 +6,26 @@ "start": "cross-env buildType=ce,SQLE vite --port=3020", "start:ee": "cross-env buildType=ee,SQLE vite --port=3020", "start:demo": "cross-env buildType=ce,SQLE,DEMO vite --port=3020", - "build": "node ../../scripts/getGitVersion.mjs ce && tsc && cross-env NODE_OPTIONS=--max_old_space_size=102400 buildType=ce,SQLE vite build", - "build:ee": "node ../../scripts/getGitVersion.mjs ee && tsc && cross-env NODE_OPTIONS=--max_old_space_size=102400 buildType=ee,SQLE vite build", - "build:demo": "node ../../scripts/getGitVersion.mjs trial && tsc && cross-env NODE_OPTIONS=--max_old_space_size=102400 buildType=ce,SQLE,DEMO vite build", + "build": "tsc && cross-env NODE_OPTIONS=--max_old_space_size=102400 buildType=ce,SQLE vite build", + "build:ee": "tsc && cross-env NODE_OPTIONS=--max_old_space_size=102400 buildType=ee,SQLE vite build", + "build:demo": "tsc && cross-env NODE_OPTIONS=--max_old_space_size=102400 buildType=ce,SQLE,DEMO vite build", + "build:release": "node ../../scripts/getGitVersion.mjs ce && pnpm build", + "build:release:ee": "node ../../scripts/getGitVersion.mjs ee && pnpm build:ee", + "build:release:demo": "node ../../scripts/getGitVersion.mjs trial && pnpm build:demo", "preview": "vite preview", + "oxlint": "oxlint --no-error-on-unmatched-pattern src vite.config.mts", + "typecheck": "tsc --noEmit -p tsconfig.json", + "stylelint": "stylelint \"src/**/{*.less,style.ts,element.ts}\" --allow-empty-input", + "check": "echo \"base check\"", "test": "jest --watchAll=true", - "test:c": "jest --coverage", - "test:ci": "jest --ci --watchAll=false --coverage --color --silent --testLocationInResults" + "test:c": "jest --watchAll=false --coverage --coverageDirectory=coverage", + "test:run": "jest --watchAll=false --color", + "test:ci": "jest --ci --watchAll=false --coverage --coverageDirectory=coverage --json --outputFile=coverage/report.json --color --silent --testLocationInResults" }, "dependencies": { "@actiontech/shared": "workspace:^", "@actiontech/dms-kit": "workspace:^", + "@actiontech/tooling-config": "workspace:^", "babel-preset-react-app": "^10.0.1", "sqle": "workspace:^", "@actiontech/icons": "workspace:^" diff --git a/packages/base/src/locale/en-US/dmsDataExport.ts b/packages/base/src/locale/en-US/dmsDataExport.ts index 10c6c50e3d..fba5efe8a6 100644 --- a/packages/base/src/locale/en-US/dmsDataExport.ts +++ b/packages/base/src/locale/en-US/dmsDataExport.ts @@ -56,6 +56,17 @@ export default { result: { success: 'Task created successfully', guide: 'View the newly created task' + }, + approvalProcess: { + title: 'Approval Process', + hint: 'Approval process can be modified in Project Configure > Approval Process', + stepLabel: 'Step {{number}}', + matchByPermission: 'Match by Permission', + loadFailed: 'Failed to load approval process', + stepType: { + export_review: 'Export Review', + export_execute: 'Export Execution Confirm' + } } }, batchClose: { diff --git a/packages/base/src/locale/zh-CN/dmsDataExport.ts b/packages/base/src/locale/zh-CN/dmsDataExport.ts index 28a2e382d7..1bdebc0f3a 100644 --- a/packages/base/src/locale/zh-CN/dmsDataExport.ts +++ b/packages/base/src/locale/zh-CN/dmsDataExport.ts @@ -52,6 +52,17 @@ export default { hasExceptionRule: '当前存在审核规则未被校验,请排除问题后重新触发审核', continueSubmission: '仍要创建' }, + approvalProcess: { + title: '审批流程', + hint: '审批流程可在 项目配置 > 审批流程 中修改', + stepLabel: '步骤 {{number}}', + matchByPermission: '按权限匹配', + loadFailed: '加载审批流程失败', + stepType: { + export_review: '导出审批', + export_execute: '导出执行确认' + } + }, update: { baseTitle: '工单基本信息', sourceTitle: '工单导出对象', diff --git a/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/__snapshots__/index.test.tsx.snap index d7beddeca8..b0b0df09d7 100644 --- a/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/__snapshots__/index.test.tsx.snap @@ -3,7 +3,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 1`] = `
-
@@ -22,7 +22,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 1`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 2`] = `
desc
@@ -41,7 +41,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 2`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 3`] = `
desc
@@ -133,7 +133,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 3`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 4`] = `
desc
@@ -225,7 +225,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 4`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 5`] = `
desc
@@ -317,7 +317,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 5`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 6`] = `
desc
@@ -409,7 +409,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 6`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 7`] = `
desc
@@ -501,7 +501,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 7`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 8`] = `
desc
@@ -593,7 +593,7 @@ exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 8`] exports[`test base/DataExport/Common/BasicInfoWrapper should match snapshot 9`] = `
desc
diff --git a/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/index.tsx b/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/index.tsx index 8a77c4c4ef..2b4f67084b 100644 --- a/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/index.tsx +++ b/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/index.tsx @@ -1,6 +1,6 @@ import classNames from 'classnames'; import { BasicInfoWrapperProps } from './index.type'; -import { EmptyBox } from '@actiontech/dms-kit'; +import { BasicTypographyEllipsis, EmptyBox } from '@actiontech/dms-kit'; import { DataExportStatusDictionary } from '../index.data'; import { BasicInfoStyleWrapper } from './style'; const BasicInfoWrapper: React.FC = ({ @@ -77,7 +77,11 @@ const BasicInfoWrapper: React.FC = ({
{title}
-
{desc ?? '-'}
+ ); }; diff --git a/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/style.ts b/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/style.ts index 8a1b88db18..725afceb79 100644 --- a/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/style.ts +++ b/packages/base/src/page/DataExportManagement/Common/BasicInfoWrapper/style.ts @@ -60,9 +60,11 @@ export const BasicInfoStyleWrapper = styled('div')<{ } .workflow-base-info-desc { - color: ${({ theme }) => theme.sharedTheme.uiToken.colorTextTertiary}; + color: ${({ theme }) => + theme.sharedTheme.uiToken.colorTextTertiary} !important; font-size: 14px; font-weight: 400; line-height: 22px; + max-width: 800px; } `; diff --git a/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap index 243d581774..13041bc945 100644 --- a/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap @@ -1419,7 +1419,7 @@ exports[`first should match snapshot when pageState is equal SUBMIT_WORKFLOW 1`]
desc
diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000000..2822c8ca42 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,196 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`base/DataExport/Create/ApprovalProcessPreview should render fallback error state when request fails 1`] = ` + +
+
+
+
+ + + +
+
+
+ 加载审批流程失败 +
+
+
+
+ +`; + +exports[`base/DataExport/Create/ApprovalProcessPreview should render loading state 1`] = ` + +
+
+
+
+
+ + + + + + +
+
+
+
+ 审批流程 +
+
+
+ 审批流程可在 项目配置 > 审批流程 中修改 +
+
+
+
+
+ +`; + +exports[`base/DataExport/Create/ApprovalProcessPreview should render step list when data loaded successfully 1`] = ` + +
+
+
+
+
+ 审批流程 +
+
+
+
+
+ 1 +
+
+
+
+
+ 导出审批 +
+
+ 按权限匹配 +
+
+
+
+
+
+ 2 +
+
+
+
+
+ 导出执行确认 +
+
+ 按权限匹配 +
+
+
+
+
+ 审批流程可在 项目配置 > 审批流程 中修改 +
+
+
+
+
+ +`; diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/__tests__/index.test.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/__tests__/index.test.tsx new file mode 100644 index 0000000000..17bec68920 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/__tests__/index.test.tsx @@ -0,0 +1,126 @@ +import { act, screen } from '@testing-library/react'; +import { baseSuperRender } from '../../../../../../../testUtils/superRender'; +import ApprovalProcessPreview from '..'; +import workflow from '@actiontech/shared/lib/api/sqle/service/workflow'; +import { + createSpySuccessResponse, + createSpyErrorResponse +} from '@actiontech/shared/lib/testUtil/mockApi'; +import { dataExportWorkflowTemplateData } from '@actiontech/shared/lib/testUtil/mockApi/sqle/workflowTemplate/data'; +import { cloneDeep } from 'lodash'; +import MockWorkflowTemplateApi from '@actiontech/shared/lib/testUtil/mockApi/sqle/workflowTemplate'; + +describe('base/DataExport/Create/ApprovalProcessPreview', () => { + let mockGetWorkflowTemplateApi: jest.SpyInstance; + beforeEach(() => { + jest.useFakeTimers(); + mockGetWorkflowTemplateApi = MockWorkflowTemplateApi.getWorkflowTemplate(); + }); + + afterEach(() => { + jest.useRealTimers(); + jest.clearAllMocks(); + }); + + const customRender = (projectName = 'test-project') => { + return baseSuperRender( + + ); + }; + + it('should render loading state', () => { + const { baseElement } = customRender(); + expect(baseElement).toMatchSnapshot(); + }); + + it('should render step list when data loaded successfully', async () => { + mockGetWorkflowTemplateApi.mockImplementation(() => + createSpySuccessResponse({ + data: cloneDeep(dataExportWorkflowTemplateData) + }) + ); + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + + expect(mockGetWorkflowTemplateApi).toHaveBeenCalledWith({ + project_name: 'test-project', + workflow_type: 'data_export' + }); + expect(screen.getByText('审批流程')).toBeInTheDocument(); + expect(screen.getByText('导出审批')).toBeInTheDocument(); + expect(screen.getAllByText('按权限匹配').length).toBeGreaterThanOrEqual(1); + expect(screen.getByText(/审批流程可在.*中修改/)).toBeInTheDocument(); + expect(baseElement).toMatchSnapshot(); + }); + + it('should render fallback error state when request fails', async () => { + mockGetWorkflowTemplateApi.mockImplementation(() => + createSpyErrorResponse({}) + ); + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + + expect(screen.getByText('加载审批流程失败')).toBeInTheDocument(); + expect(baseElement).toMatchSnapshot(); + }); + + it('should render correct step type names for export_review and export_execute', async () => { + const multiStepData = cloneDeep(dataExportWorkflowTemplateData); + multiStepData.workflow_step_template_list = [ + { + approved_by_authorized: true, + assignee_user_id_list: [], + execute_by_authorized: false, + number: 1, + type: 'export_review' + }, + { + approved_by_authorized: false, + assignee_user_id_list: [], + execute_by_authorized: true, + number: 2, + type: 'export_execute' + } + ]; + mockGetWorkflowTemplateApi.mockImplementation(() => + createSpySuccessResponse({ + data: cloneDeep(multiStepData) + }) + ); + customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + + expect(screen.getByText('导出审批')).toBeInTheDocument(); + expect(screen.getByText('导出执行确认')).toBeInTheDocument(); + }); + + it('should render assignee user list when not matched by permission', async () => { + const customData = cloneDeep(dataExportWorkflowTemplateData); + customData.workflow_step_template_list = [ + { + approved_by_authorized: false, + assignee_user_id_list: ['user1', 'user2'], + execute_by_authorized: false, + number: 1, + type: 'export_review' + } + ]; + mockGetWorkflowTemplateApi.mockImplementation(() => + createSpySuccessResponse({ + data: cloneDeep(customData) + }) + ); + customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + + expect(screen.getByText('user1, user2')).toBeInTheDocument(); + }); + + it('should not make API call when projectName is empty', () => { + mockGetWorkflowTemplateApi.mockImplementation(() => + createSpySuccessResponse({ data: {} }) + ); + customRender(''); + expect(mockGetWorkflowTemplateApi).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/index.data.ts b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/index.data.ts new file mode 100644 index 0000000000..3783869ad3 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/index.data.ts @@ -0,0 +1,10 @@ +import { t } from '../../../../../../locale'; + +export const stepTypeNameMap: Record = { + export_review: t( + 'dmsDataExport.create.approvalProcess.stepType.export_review' + ), + export_execute: t( + 'dmsDataExport.create.approvalProcess.stepType.export_execute' + ) +}; diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/index.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/index.tsx new file mode 100644 index 0000000000..1790abec1f --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/index.tsx @@ -0,0 +1,97 @@ +import { useTranslation } from 'react-i18next'; +import { useRequest } from 'ahooks'; +import { Spin } from 'antd'; +import { Result } from 'antd'; +import { IWorkFlowStepTemplateResV1 } from '@actiontech/shared/lib/api/sqle/service/common'; +import { ApprovalProcessPreviewStyleWrapper } from './style'; +import { getWorkflowTemplateV1WorkflowTypeEnum } from '@actiontech/shared/lib/api/sqle/service/workflow/index.enum'; +import { stepTypeNameMap } from './index.data'; +import { SqleApi } from '@actiontech/shared/lib/api'; + +interface ApprovalProcessPreviewProps { + projectName: string; +} + +const ApprovalProcessPreview: React.FC = ({ + projectName +}) => { + const { t } = useTranslation(); + + const { + data: templateData, + loading, + error + } = useRequest( + () => + SqleApi.WorkflowService.getWorkflowTemplateV1({ + project_name: projectName, + workflow_type: getWorkflowTemplateV1WorkflowTypeEnum.data_export + }).then((res) => res.data.data), + { + ready: !!projectName, + // eslint-disable-next-line @typescript-eslint/no-empty-function + onError: () => {} + } + ); + + const renderAssigneeInfo = (step: IWorkFlowStepTemplateResV1) => { + if (step.approved_by_authorized || step.execute_by_authorized) { + return t('dmsDataExport.create.approvalProcess.matchByPermission'); + } + if (step.assignee_user_id_list && step.assignee_user_id_list.length > 0) { + return step.assignee_user_id_list.join(', '); + } + return '-'; + }; + + const renderStepTypeName = (type?: string) => { + if (type) { + return stepTypeNameMap[type] ?? '-'; + } + return '-'; + }; + + if (error) { + return ( + + + + ); + } + + return ( + + +
+ {t('dmsDataExport.create.approvalProcess.title')} +
+ +
+ {templateData?.workflow_step_template_list?.map((step, index) => ( +
+
+
{step.number}
+
+
+
+
+ {renderStepTypeName(step.type)} +
+
{renderAssigneeInfo(step)}
+
+
+ ))} +
+ +
+ {t('dmsDataExport.create.approvalProcess.hint')} +
+ + + ); +}; + +export default ApprovalProcessPreview; diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/style.ts b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/style.ts new file mode 100644 index 0000000000..53aa909904 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/ApprovalProcessPreview/style.ts @@ -0,0 +1,97 @@ +import { styled } from '@mui/material/styles'; + +export const ApprovalProcessPreviewStyleWrapper = styled('div')` + padding: 24px 40px; + border-bottom: 1px solid + ${({ theme }) => theme.sharedTheme.basic.colorGrayLine}; + + .approval-process-title { + color: ${({ theme }) => theme.sharedTheme.uiToken.colorText}; + font-size: 14px; + font-weight: 600; + line-height: 22px; + margin-bottom: 16px; + } + + .approval-process-steps { + display: flex; + flex-direction: column; + gap: 0; + } + + .approval-process-step { + display: flex; + align-items: flex-start; + position: relative; + padding-left: 32px; + padding-bottom: 16px; + + &:last-child { + padding-bottom: 0; + + .step-connector { + display: none; + } + } + + .step-indicator { + position: absolute; + left: 0; + top: 0; + display: flex; + flex-direction: column; + align-items: center; + + .step-dot { + width: 24px; + height: 24px; + border-radius: 50%; + background: ${({ theme }) => theme.sharedTheme.uiToken.colorPrimary}; + color: ${({ theme }) => theme.sharedTheme.basic.colorWhite}; + font-size: 12px; + font-weight: 600; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + + .step-connector { + width: 2px; + flex: 1; + min-height: 16px; + background: ${({ theme }) => theme.sharedTheme.basic.colorGrayLine}; + margin-top: 4px; + } + } + + .step-content { + flex: 1; + padding: 4px 0 0 12px; + + .step-type-name { + color: ${({ theme }) => theme.sharedTheme.uiToken.colorText}; + font-size: 14px; + font-weight: 500; + line-height: 22px; + } + + .step-assignee { + color: ${({ theme }) => theme.sharedTheme.uiToken.colorTextSecondary}; + font-size: 13px; + line-height: 20px; + margin-top: 2px; + } + } + } + + .approval-process-hint { + margin-top: 16px; + padding-top: 12px; + border-top: 1px dashed + ${({ theme }) => theme.sharedTheme.basic.colorGrayLine}; + color: ${({ theme }) => theme.sharedTheme.uiToken.colorTextTertiary}; + font-size: 12px; + line-height: 20px; + } +`; diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap index 8662bf56c3..74c935ca0c 100644 --- a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap @@ -71,7 +71,7 @@ exports[`test base/DataExport/Create/SubmitWorkflow should match snapshot 1`] =
desc
@@ -318,7 +318,7 @@ exports[`test base/DataExport/Create/SubmitWorkflow should match snapshot 2`] =
desc
diff --git a/packages/base/src/page/DataExportManagement/Detail/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Detail/__tests__/__snapshots__/index.test.tsx.snap index be4aa71414..1d47de3e85 100644 --- a/packages/base/src/page/DataExportManagement/Detail/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/Detail/__tests__/__snapshots__/index.test.tsx.snap @@ -131,7 +131,7 @@ exports[`test base/DataExport/Detail should match snapshot 1`] = `
desc
@@ -855,7 +855,7 @@ exports[`test base/DataExport/Detail should match snapshot 1`] = `
desc
@@ -3460,7 +3460,7 @@ exports[`test base/DataExport/Detail should match snapshot 2`] = `
desc
@@ -6041,7 +6041,7 @@ exports[`test base/DataExport/Detail should match snapshot 3`] = `
desc
@@ -8622,7 +8622,7 @@ exports[`test base/DataExport/Detail should match snapshot 4`] = `
desc
@@ -11070,7 +11070,7 @@ exports[`test base/DataExport/Detail should match snapshot with reject workflow class="ant-steps ant-steps-vertical css-1epey7k" >
= ({ }) => { const { t } = useTranslation(); const { sharedTheme } = useThemeStyleData(); + + // Dynamic step number calculation based on workflow status and steps const stepNumber = useMemo(() => { - if (!workflowStatus) { + if (!workflowStatus || !workflowSteps) { return currentStepNumber; } - //本期后端没有流程模板,当前固定为:创建、审核、执行 三步,所以前端自己判断当前到第几步了 - if ( - workflowStatus === WorkflowRecordStatusEnum.wait_for_approve || - workflowStatus === WorkflowRecordStatusEnum.rejected - ) { + // Total steps: create(1) + N approval nodes + execute(1) + const totalApprovalSteps = workflowSteps.length; + + if (workflowStatus === WorkflowRecordStatusEnum.rejected) { + // Find which approval step was rejected + for (let i = 0; i < workflowSteps.length; i++) { + if (workflowSteps[i]?.state === 'rejected') { + return i + 2; // +1 for create step, +1 for 1-indexed + } + } return 2; } + + if (workflowStatus === WorkflowRecordStatusEnum.wait_for_approve) { + // Find the current step being awaited + if (currentStepNumber !== undefined && currentStepNumber !== null) { + // currentStepNumber from API represents which step we are on (1-indexed) + return (currentStepNumber as number) + 1; // +1 for create step + } + return 2; + } + if (workflowStatus === WorkflowRecordStatusEnum.wait_for_export) { - return 3; + return totalApprovalSteps + 2; // all approval done, at execute step } + if ( [ WorkflowRecordStatusEnum.exporting, @@ -48,19 +66,16 @@ const WorkflowSteps: React.FC = ({ WorkflowRecordStatusEnum.cancel ].includes(workflowStatus) ) { - return 4; + return totalApprovalSteps + 2; // at execute step } - }, [currentStepNumber, workflowStatus]); + }, [currentStepNumber, workflowStatus, workflowSteps]); + const renderTitle = useCallback( (type?: string) => { if (type === 'create') { return t('dmsDataExport.detail.record.steps.create'); } - // if (type === WorkflowStepResV2TypeEnum.update_workflow) { - // return t('dmsDataExport.detail.record.steps.update'); - // } - if (type === 'approve') { return t('dmsDataExport.detail.record.steps.approve'); } @@ -136,7 +151,7 @@ const WorkflowSteps: React.FC = ({ ] ); const renderOrderStepsItem = useCallback( - (title: string, step: any) => { + (title: string, step: WorkflowStep) => { return (
{title}
@@ -148,12 +163,14 @@ const WorkflowSteps: React.FC = ({ [renderOrderStepsItemContent] ); const renderOrderStepsItemIcon = useCallback( - (type?: string) => { + (type?: string, step?: WorkflowStep) => { if (type === 'create') { return ; } if (type === 'approve') { - const isRejected = workflowStatus === WorkflowRecordStatusEnum.rejected; + const isRejected = + workflowStatus === WorkflowRecordStatusEnum.rejected && + step?.state === 'rejected'; return ( = ({ }, [workflowStatus, sharedTheme.uiToken.colorWarning] ); + const stepsItems = useMemo(() => { if (!workflowSteps) { return []; } - // 没有流程模板,先固定这 3 步 - return [ + // Build dynamic steps: create + N approval nodes + execute + const allSteps: WorkflowStep[] = [ { type: 'create', number: 1, @@ -193,21 +211,30 @@ const WorkflowSteps: React.FC = ({ name: createUser }, operation_time: createTime - }, - { - ...workflowSteps[0], - type: 'approve', - number: 2 - }, - { - type: 'execute', - number: 3 } - ].map((v, i) => { - const isNextRejected = workflowSteps[i + 1]?.state === 'rejected'; + ]; + + // Add all approval steps from workflow_step_list + workflowSteps.forEach((step, index) => { + allSteps.push({ + ...step, + type: 'approve', + number: index + 2 + }); + }); + + // Add execute step + allSteps.push({ + type: 'execute', + number: allSteps.length + 1 + }); + + return allSteps.map((v, i) => { + const nextStep = allSteps[i + 1]; + const isNextRejected = nextStep?.state === 'rejected'; return { title: renderOrderStepsItem(renderTitle(v.type), v), - icon: renderOrderStepsItemIcon(v.type), + icon: renderOrderStepsItemIcon(v.type, v), className: classNames({ 'prev-rejected-step': isNextRejected }) diff --git a/packages/base/src/page/DataExportManagement/Detail/components/WorkflowRecordInfo/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Detail/components/WorkflowRecordInfo/__tests__/__snapshots__/index.test.tsx.snap index 98dda86dd1..479a7e6d46 100644 --- a/packages/base/src/page/DataExportManagement/Detail/components/WorkflowRecordInfo/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/Detail/components/WorkflowRecordInfo/__tests__/__snapshots__/index.test.tsx.snap @@ -321,7 +321,7 @@ exports[`test base/DataExport/Detail/WorkflowRecordInfo should match snapshot 1`
{ const { result } = renderHook(() => useInitDataWithRequest()); expect(result.current.getWorkflowLoading).toBeTruthy(); - expect(result.current.getTaskInfosLoading).toBeFalsy(); + expect(result.current.getTaskInfosLoading).toBeTruthy(); expect(getWorkflowSpy).toHaveBeenCalledTimes(1); expect(getWorkflowSpy).toHaveBeenCalledWith({ project_uid: mockProjectInfo.projectID, @@ -56,7 +56,7 @@ describe('test base/DataExport/Detail/hooks/useInitDataWithRequest', () => { }); await act(async () => jest.advanceTimersByTime(3000)); - expect(result.current.getWorkflowLoading).toBeFalsy(); + expect(result.current.getWorkflowLoading).toBeTruthy(); expect(result.current.getTaskInfosLoading).toBeTruthy(); expect(mockDataExportDetailRedux.updateWorkflowInfo).toHaveBeenCalledTimes( 1 diff --git a/packages/base/src/page/DataExportManagement/Detail/hooks/useInitDataWithRequest.ts b/packages/base/src/page/DataExportManagement/Detail/hooks/useInitDataWithRequest.ts index ba73b5f63f..e832a421b7 100644 --- a/packages/base/src/page/DataExportManagement/Detail/hooks/useInitDataWithRequest.ts +++ b/packages/base/src/page/DataExportManagement/Detail/hooks/useInitDataWithRequest.ts @@ -3,11 +3,14 @@ import DataExportWorkflows from '@actiontech/shared/lib/api/base/service/DataExp import { ResponseCode } from '@actiontech/dms-kit'; import { useCurrentProject } from '@actiontech/shared/lib/features'; import useDataExportDetailReduxManage from './index.redux'; -import { useRequest } from 'ahooks'; -import { useEffect } from 'react'; +import { useBoolean, useRequest } from 'ahooks'; +import { useEffect, useMemo } from 'react'; import eventEmitter from '../../../../utils/EventEmitter'; import EmitterKey from '../../../../data/EmitterKey'; -import { GetDataExportTaskStatusEnum } from '@actiontech/shared/lib/api/base/service/common.enum'; +import { + GetDataExportTaskStatusEnum, + WorkflowRecordStatusEnum +} from '@actiontech/shared/lib/api/base/service/common.enum'; import { useTypedParams } from '@actiontech/shared'; import { ROUTE_PATHS } from '@actiontech/dms-kit'; @@ -18,7 +21,14 @@ const useInitDataWithRequest = () => { const { updateTaskInfos, updateWorkflowInfo, updateTaskStatusNumber } = useDataExportDetailReduxManage(); - const { refresh: refreshWorkflow, loading: getWorkflowLoading } = useRequest( + const [polling, { setFalse: finishPollRequest, setTrue: startPollRequest }] = + useBoolean(); + + const { + refresh: refreshWorkflow, + loading: getWorkflowLoading, + cancel + } = useRequest( () => DataExportWorkflows.GetDataExportWorkflow({ project_uid: projectID, @@ -31,8 +41,27 @@ const useInitDataWithRequest = () => { ?.map((v) => v.task_uid ?? '') ?.join(',') ?? '' ); + + // Stop polling when no longer in exporting status + if ( + res.data.data?.workflow_record?.status !== + WorkflowRecordStatusEnum.exporting + ) { + cancel(); + finishPollRequest(); + } else { + startPollRequest(); + } } - }) + }), + { + pollingInterval: 1000, + pollingErrorRetryCount: 3, + onError: () => { + cancel(); + finishPollRequest(); + } + } ); const { loading: getTaskInfosLoading, run: batchGetDataExportTask } = @@ -82,9 +111,14 @@ const useInitDataWithRequest = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const initLoading = useMemo( + () => (polling ? false : getTaskInfosLoading || getWorkflowLoading), + [getTaskInfosLoading, getWorkflowLoading, polling] + ); + return { - getWorkflowLoading, - getTaskInfosLoading + getWorkflowLoading: initLoading, + getTaskInfosLoading: initLoading }; }; diff --git a/packages/base/src/page/DataExportManagement/List/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/List/__tests__/__snapshots__/index.test.tsx.snap index ae0534cdf7..d65b34d4ff 100644 --- a/packages/base/src/page/DataExportManagement/List/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/List/__tests__/__snapshots__/index.test.tsx.snap @@ -376,7 +376,7 @@ exports[`test base/DataExport/List render batch close button When the user is no 工单名称 描述 @@ -516,7 +516,7 @@ exports[`test base/DataExport/List render batch close button When the user is no
描述 @@ -2078,7 +2078,7 @@ exports[`test base/DataExport/List render init snapshot 2`] = ` 工单名称 描述 @@ -2247,7 +2247,7 @@ exports[`test base/DataExport/List render init snapshot 2`] = `
描述 @@ -3610,7 +3610,7 @@ exports[`test base/DataExport/List render table filter items 1`] = `
t('dmsDataExport.list.column.desc'), - className: 'ellipsis-column-width-large', + className: 'ellipsis-column-width', render: (desc, record) => desc ? ( { dataIndex: 'ldap_search_base_dn', hidden: !ldapSetting?.enable_ldap }, - { - label: t('dmsSystem.ldap.ldapSearchBaseDn'), - span: 3, - dataIndex: 'ldap_search_base_dn', - hidden: !ldapSetting?.enable_ldap - }, { label: t('dmsSystem.ldap.ldapUserNameRdnKey'), span: 3, diff --git a/packages/base/tsconfig.json b/packages/base/tsconfig.json index 740aafa02b..cc3ae8dea9 100644 --- a/packages/base/tsconfig.json +++ b/packages/base/tsconfig.json @@ -3,7 +3,10 @@ "include": ["src"], "compilerOptions": { "paths": { - "~/*": ["./src/*"] + "~/*": ["./src/*"], + "@actiontech/dms-kit": ["../dms-kit/src/index.ts"], + "@actiontech/dms-kit/es/*": ["../dms-kit/src/*"], + "@actiontech/dms-kit/*": ["../dms-kit/src/*"] }, "skipLibCheck": true } diff --git a/packages/base/vite.config.mts b/packages/base/vite.config.mts index d625f08098..7f1ef1754b 100644 --- a/packages/base/vite.config.mts +++ b/packages/base/vite.config.mts @@ -1,6 +1,5 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import eslint from 'vite-plugin-eslint'; import vitePluginConditionalCompile from 'vite-plugin-conditional-compile'; import { createHtmlPlugin } from 'vite-plugin-html'; import * as path from 'path'; @@ -50,14 +49,6 @@ export default defineConfig(() => { demo: isDemo } }), - eslint({ - exclude: [ - '**/node_modules/**', - '**/packages/**/lib/**', - '**/packages/**/es/**', - '!**/packages/**/lib/api/common/**' - ] - }), react(), createHtmlPlugin({ inject: { @@ -68,9 +59,20 @@ export default defineConfig(() => { }) ], resolve: { - alias: { - '~': path.resolve(__dirname, '../provision/src') - } + alias: [ + { + find: /^@actiontech\/dms-kit\/es\/(.*)$/, + replacement: path.resolve(__dirname, '../dms-kit/src/$1') + }, + { + find: '@actiontech/dms-kit', + replacement: path.resolve(__dirname, '../dms-kit/src') + }, + { + find: '~', + replacement: path.resolve(__dirname, '../provision/src') + } + ] }, css: { preprocessorOptions: { @@ -81,6 +83,7 @@ export default defineConfig(() => { } }, build: { + target: 'chrome80', rollupOptions: { // resolve css in js 'use client' warn onwarn(warning, warn) { @@ -91,13 +94,33 @@ export default defineConfig(() => { }, output: { minifyInternalExports: true, - manualChunks: { - 'antd.module': ['antd'], - 'react.module': ['react'], - 'lodash.module': ['lodash'], - 'antd.icon.module': ['@ant-design/icons'], - 'antd.plots': ['@ant-design/plots'], - 'actiontech.shared': ['@actiontech/shared'] + codeSplitting: { + groups: [ + { + test: /[\\/]node_modules[\\/]antd[\\/]/, + name: 'antd.module' + }, + { + test: /[\\/]node_modules[\\/]react[\\/]/, + name: 'react.module' + }, + { + test: /[\\/]node_modules[\\/]lodash[\\/]/, + name: 'lodash.module' + }, + { + test: /[\\/]node_modules[\\/]@ant-design[\\/]icons[\\/]/, + name: 'antd.icon.module' + }, + { + test: /[\\/]node_modules[\\/]@ant-design[\\/]plots[\\/]/, + name: 'antd.plots' + }, + { + test: /[\\/]node_modules[\\/]@actiontech[\\/]shared[\\/]/, + name: 'actiontech.shared' + } + ] } } } diff --git a/packages/dms-kit/jest.config.mjs b/packages/dms-kit/jest.config.mjs new file mode 100644 index 0000000000..b5af9812ef --- /dev/null +++ b/packages/dms-kit/jest.config.mjs @@ -0,0 +1,18 @@ +import { createJestConfig } from '@actiontech/tooling-config/jest/create-jest-config'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +const packageRoot = path.dirname(fileURLToPath(import.meta.url)); + +export default createJestConfig({ + packageRoot, + enabledProjects: ['dms'], + collectCoverageFrom: [ + 'src/**/*.{ts,tsx}', + '!src/**/*.test.{ts,tsx}', + '!src/**/*.type.ts', + '!src/**/*.enum.ts', + '!src/**/demo/**', + '!src/**/demos/**' + ] +}); diff --git a/packages/dms-kit/package.json b/packages/dms-kit/package.json index 311f8f1ebb..c3f0cfa395 100644 --- a/packages/dms-kit/package.json +++ b/packages/dms-kit/package.json @@ -16,12 +16,20 @@ "scripts": { "build": "father build", "dev": "father dev --incremental", + "start": "pnpm dev", + "start:ee": "pnpm dev", + "start:demo": "pnpm dev", "docs:dev": "dumi dev", "docs:build": "dumi build", "docs:preview": "dumi preview", + "oxlint": "oxlint --no-error-on-unmatched-pattern src", + "typecheck": "tsc --noEmit -p tsconfig.json", + "stylelint": "stylelint \"src/**/{*.less,style.ts,element.ts}\" --allow-empty-input", + "check": "echo \"dms-kit check\"", "test": "jest --watchAll=true", - "test:c": "jest --watchAll=false --coverage", - "test:ci": "jest --ci --watchAll=false --coverage --color --silent --testLocationInResults" + "test:c": "jest --watchAll=false --coverage --coverageDirectory=coverage", + "test:run": "jest --watchAll=false --color", + "test:ci": "jest --ci --watchAll=false --coverage --coverageDirectory=coverage --json --outputFile=coverage/report.json --color --silent --testLocationInResults" }, "dependencies": { "ahooks": "^3.7.0", @@ -54,8 +62,9 @@ "typescript": "^5.0.2" }, "devDependencies": { + "@actiontech/tooling-config": "workspace:^", "father": "^4.5.2", "dumi": "^2.3.8", "babel-plugin-import": "^1.13.8" } -} \ No newline at end of file +} diff --git a/packages/dms-kit/src/data/routePaths.ts b/packages/dms-kit/src/data/routePaths.ts index c5d8b7c504..c42f76c509 100644 --- a/packages/dms-kit/src/data/routePaths.ts +++ b/packages/dms-kit/src/data/routePaths.ts @@ -321,11 +321,13 @@ export const ROUTE_PATHS = { PROGRESS: { index: { prefix: '/sqle/project', - path: ':projectID/progress' + path: ':projectID/progress', + query: 'activeTab' }, update: { prefix: '/sqle/project/:projectID/progress', - path: 'update/:workflowName' + path: 'update/:workflowName', + query: 'workflowType' } }, WHITELIST: { diff --git a/packages/dms-kit/src/types/ambient-modules.d.ts b/packages/dms-kit/src/types/ambient-modules.d.ts new file mode 100644 index 0000000000..35306c6fc9 --- /dev/null +++ b/packages/dms-kit/src/types/ambient-modules.d.ts @@ -0,0 +1 @@ +declare module '*.css'; diff --git a/packages/dms-kit/src/utils/HighlightCode.ts b/packages/dms-kit/src/utils/HighlightCode.ts index 60e822f67a..a3d4b763ee 100644 --- a/packages/dms-kit/src/utils/HighlightCode.ts +++ b/packages/dms-kit/src/utils/HighlightCode.ts @@ -1,5 +1,7 @@ import hljs from 'highlight.js/lib/core'; import sqlCore from 'highlight.js/lib/languages/sql'; + +// oxlint-disable-next-line import/no-unassigned-import import 'highlight.js/styles/github.css'; class HighlightCode { @@ -13,5 +15,5 @@ class HighlightCode { } } -// eslint-disable-next-line import/no-anonymous-default-export +// oxlint-disable-next-line import/no-anonymous-default-export export default new HighlightCode(); diff --git a/packages/icons/package.json b/packages/icons/package.json index 48cf230afa..485090a0f4 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -9,6 +9,10 @@ "docs:build": "dumi build", "docs:preview": "dumi preview", "build": "father build", + "oxlint": "oxlint --no-error-on-unmatched-pattern src", + "typecheck": "tsc --noEmit -p tsconfig.json", + "stylelint": "stylelint \"src/**/{*.less,style.ts,element.ts}\" --allow-empty-input", + "check": "echo \"icons check\"", "icon:g": "svgr --template template/template.cjs -d src svg/ ", "docs:g": "node scripts/generate.js" }, @@ -21,4 +25,4 @@ "dumi": "^2.3.8", "father": "^4.1.0" } -} \ No newline at end of file +} diff --git a/packages/icons/tsconfig.json b/packages/icons/tsconfig.json index 6cec366d2e..574fae7d54 100644 --- a/packages/icons/tsconfig.json +++ b/packages/icons/tsconfig.json @@ -6,11 +6,10 @@ "esModuleInterop": true, "resolveJsonModule": true, "jsx": "react-jsx", - "baseUrl": "./", "paths": { - "@@/*": [".dumi/tmp/*"], - "@actiontech/icons": ["src"], - "@actiontech/icons/*": ["src/*", "*"] + "@@/*": ["./.dumi/tmp/*"], + "@actiontech/icons": ["./src"], + "@actiontech/icons/*": ["./src/*", "./*"] } }, "include": [".dumirc.ts", "src/**/*"] diff --git a/packages/shared/jest.config.mjs b/packages/shared/jest.config.mjs new file mode 100644 index 0000000000..ed7c7a116c --- /dev/null +++ b/packages/shared/jest.config.mjs @@ -0,0 +1,26 @@ +import { createJestConfig } from '@actiontech/tooling-config/jest/create-jest-config'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +const packageRoot = path.dirname(fileURLToPath(import.meta.url)); + +export default createJestConfig({ + packageRoot, + enabledProjects: ['dms', 'sqle-ce'], + collectCoverageFrom: [ + 'src/**/*.{ts,tsx}', + 'lib/**/*.{ts,tsx}', + 'api/common/**/*.{ts,tsx}', + '!src/**/*.test.{ts,tsx}', + '!lib/**/*.test.{ts,tsx}', + '!src/**/*.type.ts', + '!src/**/*.enum.ts', + '!lib/**/*.type.ts', + '!lib/**/*.enum.ts', + '!lib/hooks/usePrompt/index.tsx', + '!src/**/demo/**', + '!src/**/demos/**', + '!lib/**/demo/**', + '!lib/**/demos/**' + ] +}); diff --git a/packages/shared/lib/api/sqle/service/common.d.ts b/packages/shared/lib/api/sqle/service/common.d.ts index 993b7cdaf3..581a17455f 100644 --- a/packages/shared/lib/api/sqle/service/common.d.ts +++ b/packages/shared/lib/api/sqle/service/common.d.ts @@ -98,6 +98,7 @@ import { WorkflowStepResV1StateEnum, WorkflowStepResV1TypeEnum, WorkflowTemplateDetailResV1AllowSubmitWhenLessAuditLevelEnum, + WorkflowTemplateDetailResV1WorkflowTypeEnum, pipelineNodeBaseAuditMethodEnum, pipelineNodeBaseObjectTypeEnum, pipelineNodeBaseTypeEnum, @@ -133,6 +134,12 @@ export interface IBaseRes { message?: string; } +export interface IGlobalAccountListDataV2 { + accounts?: IGlobalAccountListItemV2[]; + + can_manage?: boolean; +} + export interface IGlobalAccountListItemV2 { account_name?: string; @@ -154,7 +161,7 @@ export interface IGlobalAccountListItemV2 { export interface IGlobalAccountListResV2 { code?: number; - data?: IGlobalAccountListItemV2[]; + data?: IGlobalAccountListDataV2; message?: string; @@ -2495,6 +2502,14 @@ export interface IGetWorkflowTasksResV1 { message?: string; } +export interface IGetWorkflowTemplateListResV1 { + code?: number; + + data?: IWorkflowTemplateDetailResV1[]; + + message?: string; +} + export interface IGetWorkflowTemplateResV1 { code?: number; @@ -4457,6 +4472,8 @@ export interface IWorkflowTemplateDetailResV1 { workflow_step_template_list?: IWorkFlowStepTemplateResV1[]; workflow_template_name?: string; + + workflow_type?: WorkflowTemplateDetailResV1WorkflowTypeEnum; } export interface ICreatePipelineResData { @@ -5098,6 +5115,8 @@ export interface IUploadInstanceAuditPlanSQLsReqV2 { } export interface IWorkflowRecordResV2 { + assignee_user_name_list?: string[]; + current_step_number?: number; executable?: boolean; diff --git a/packages/shared/lib/api/sqle/service/common.enum.ts b/packages/shared/lib/api/sqle/service/common.enum.ts index 0bdc064516..6f7e06436b 100644 --- a/packages/shared/lib/api/sqle/service/common.enum.ts +++ b/packages/shared/lib/api/sqle/service/common.enum.ts @@ -829,7 +829,11 @@ export enum UpdateWorkflowTemplateReqV1AllowSubmitWhenLessAuditLevelEnum { export enum WorkFlowStepTemplateReqV1TypeEnum { 'sql_review' = 'sql_review', - 'sql_execute' = 'sql_execute' + 'sql_execute' = 'sql_execute', + + 'export_review' = 'export_review', + + 'export_execute' = 'export_execute' } export enum WorkflowDetailResV1CurrentStepTypeEnum { @@ -940,6 +944,12 @@ export enum WorkflowTemplateDetailResV1AllowSubmitWhenLessAuditLevelEnum { 'error' = 'error' } +export enum WorkflowTemplateDetailResV1WorkflowTypeEnum { + 'workflow' = 'workflow', + + 'data_export' = 'data_export' +} + export enum pipelineNodeBaseAuditMethodEnum { 'offline' = 'offline', diff --git a/packages/shared/lib/api/sqle/service/workflow/index.d.ts b/packages/shared/lib/api/sqle/service/workflow/index.d.ts index c899fa201c..10d9f54bd8 100644 --- a/packages/shared/lib/api/sqle/service/workflow/index.d.ts +++ b/packages/shared/lib/api/sqle/service/workflow/index.d.ts @@ -5,6 +5,7 @@ import { IGetWorkflowTemplateResV1, IUpdateWorkflowTemplateReqV1, IBaseRes, + IGetWorkflowTemplateListResV1, ICreateWorkflowReqV1, IAutoCreateAndExecuteWorkflowResV1, IBatchCancelWorkflowsReqV1, @@ -42,6 +43,8 @@ import { getGlobalWorkflowsV1FilterProjectPriorityEnum, GetGlobalWorkflowStatisticsFilterStatusListEnum, GetGlobalWorkflowStatisticsFilterProjectPriorityEnum, + getWorkflowTemplateV1WorkflowTypeEnum, + updateWorkflowTemplateV1WorkflowTypeEnum, getWorkflowsV1FilterStatusEnum, autoCreateAndExecuteWorkflowV1ExecModeEnum, exportWorkflowV1FilterStatusEnum, @@ -129,6 +132,8 @@ export interface IGetGlobalWorkflowStatisticsReturn export interface IGetWorkflowTemplateV1Params { project_name: string; + + workflow_type: getWorkflowTemplateV1WorkflowTypeEnum; } export interface IGetWorkflowTemplateV1Return @@ -137,10 +142,19 @@ export interface IGetWorkflowTemplateV1Return export interface IUpdateWorkflowTemplateV1Params extends IUpdateWorkflowTemplateReqV1 { project_name: string; + + workflow_type: updateWorkflowTemplateV1WorkflowTypeEnum; } export interface IUpdateWorkflowTemplateV1Return extends IBaseRes {} +export interface IGetWorkflowTemplateListV1Params { + project_name: string; +} + +export interface IGetWorkflowTemplateListV1Return + extends IGetWorkflowTemplateListResV1 {} + export interface IGetWorkflowsV1Params { filter_subject?: string; diff --git a/packages/shared/lib/api/sqle/service/workflow/index.enum.ts b/packages/shared/lib/api/sqle/service/workflow/index.enum.ts index 6dd919cb8f..5b6b68c466 100644 --- a/packages/shared/lib/api/sqle/service/workflow/index.enum.ts +++ b/packages/shared/lib/api/sqle/service/workflow/index.enum.ts @@ -96,6 +96,18 @@ export enum GetGlobalWorkflowStatisticsFilterProjectPriorityEnum { 'low' = 'low' } +export enum getWorkflowTemplateV1WorkflowTypeEnum { + 'workflow' = 'workflow', + + 'data_export' = 'data_export' +} + +export enum updateWorkflowTemplateV1WorkflowTypeEnum { + 'workflow' = 'workflow', + + 'data_export' = 'data_export' +} + export enum getWorkflowsV1FilterStatusEnum { 'wait_for_audit' = 'wait_for_audit', diff --git a/packages/shared/lib/api/sqle/service/workflow/index.ts b/packages/shared/lib/api/sqle/service/workflow/index.ts index 13a5d63d3a..28d2f084e0 100644 --- a/packages/shared/lib/api/sqle/service/workflow/index.ts +++ b/packages/shared/lib/api/sqle/service/workflow/index.ts @@ -20,6 +20,8 @@ import { IGetWorkflowTemplateV1Return, IUpdateWorkflowTemplateV1Params, IUpdateWorkflowTemplateV1Return, + IGetWorkflowTemplateListV1Params, + IGetWorkflowTemplateListV1Return, IGetWorkflowsV1Params, IGetWorkflowsV1Return, ICreateWorkflowV1Params, @@ -174,8 +176,26 @@ class WorkflowService extends ServiceBase { const project_name = paramsData.project_name; delete paramsData.project_name; + const workflow_type = paramsData.workflow_type; + delete paramsData.workflow_type; + return this.patch( - `/v1/projects/${project_name}/workflow_template`, + `/v1/projects/${project_name}/workflow_template/${workflow_type}/`, + paramsData, + options + ); + } + + public getWorkflowTemplateListV1( + params: IGetWorkflowTemplateListV1Params, + options?: AxiosRequestConfig + ) { + const paramsData = this.cloneDeep(params); + const project_name = paramsData.project_name; + delete paramsData.project_name; + + return this.get( + `/v1/projects/${project_name}/workflow_templates`, paramsData, options ); diff --git a/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/data.ts b/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/data.ts index d7337181fc..3d6a68ec6d 100644 --- a/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/data.ts +++ b/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/data.ts @@ -1,4 +1,8 @@ -import { WorkflowTemplateDetailResV1AllowSubmitWhenLessAuditLevelEnum } from '../../../../api/sqle/service/common.enum'; +import { IWorkflowTemplateDetailResV1 } from '../../../../api/sqle/service/common'; +import { + WorkflowTemplateDetailResV1AllowSubmitWhenLessAuditLevelEnum, + WorkflowTemplateDetailResV1WorkflowTypeEnum +} from '../../../../api/sqle/service/common.enum'; export const workflowTemplateData = { allow_submit_when_less_audit_level: @@ -29,5 +33,96 @@ export const workflowTemplateData = { type: 'sql_execute' } ], - workflow_template_name: '700300-WorkflowTemplate' + workflow_template_name: '700300-WorkflowTemplate', + workflow_type: WorkflowTemplateDetailResV1WorkflowTypeEnum.workflow }; + +export const dataExportWorkflowTemplateData: IWorkflowTemplateDetailResV1 = { + desc: '', + update_time: '2024-01-15T10:30:00+08:00', + workflow_step_template_list: [ + { + approved_by_authorized: true, + assignee_user_id_list: [], + execute_by_authorized: false, + number: 1, + type: 'export_review' + }, + { + approved_by_authorized: false, + assignee_user_id_list: [], + execute_by_authorized: true, + number: 2, + type: 'export_execute' + } + ], + workflow_template_name: '700300-DataExportWorkflowTemplate', + workflow_type: WorkflowTemplateDetailResV1WorkflowTypeEnum.data_export +}; + +/** + * Steps returned from API in wrong order (sql_execute first, then sql_review by descending number). + * Used to verify that the frontend correctly extracts steps by type and sorts review steps by number. + * Expected result after processing: + * reviewSteps (sorted by number): [number:1 sql_review, number:2 sql_review] + * execStep: number:3 sql_execute + */ +export const workflowTemplateOutOfOrderData = { + ...workflowTemplateData, + workflow_step_template_list: [ + { + approved_by_authorized: false, + assignee_user_id_list: [], + execute_by_authorized: true, + number: 3, + type: 'sql_execute' + }, + { + approved_by_authorized: false, + assignee_user_id_list: ['1739544663515205632'], + desc: 'step desc', + execute_by_authorized: false, + number: 2, + type: 'sql_review' + }, + { + approved_by_authorized: true, + assignee_user_id_list: [], + execute_by_authorized: false, + number: 1, + type: 'sql_review' + } + ] +}; + +/** + * Export steps returned from API in wrong order (export_execute first). + * Expected result after processing: + * reviewSteps (sorted by number): [number:1 export_review] + * execStep: number:2 export_execute + */ +export const dataExportWorkflowTemplateOutOfOrderData: IWorkflowTemplateDetailResV1 = + { + ...dataExportWorkflowTemplateData, + workflow_step_template_list: [ + { + approved_by_authorized: false, + assignee_user_id_list: [], + execute_by_authorized: true, + number: 2, + type: 'export_execute' + }, + { + approved_by_authorized: true, + assignee_user_id_list: [], + execute_by_authorized: false, + number: 1, + type: 'export_review' + } + ] + }; + +export const workflowTemplateListData = [ + workflowTemplateData, + dataExportWorkflowTemplateData +]; diff --git a/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/index.ts b/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/index.ts index 9663d8174f..dbc452b7a7 100644 --- a/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/index.ts +++ b/packages/shared/lib/testUtil/mockApi/sqle/workflowTemplate/index.ts @@ -1,12 +1,17 @@ import workflow from '../../../../api/sqle/service/workflow'; import { MockSpyApy, createSpySuccessResponse } from '../../common'; -import { workflowTemplateData } from './data'; +import { + workflowTemplateData, + dataExportWorkflowTemplateData, + workflowTemplateListData +} from './data'; import { cloneDeep } from 'lodash'; class MockWorkflowTemplateApi implements MockSpyApy { public mockAllApi(): void { this.updateWorkflowTemplate(); this.getWorkflowTemplate(); + this.getWorkflowTemplateList(); this.cancelWorkflow(); } @@ -18,7 +23,12 @@ class MockWorkflowTemplateApi implements MockSpyApy { public getWorkflowTemplate() { const spy = jest.spyOn(workflow, 'getWorkflowTemplateV1'); - spy.mockImplementation(() => { + spy.mockImplementation((params) => { + if (params.workflow_type === 'data_export') { + return createSpySuccessResponse({ + data: cloneDeep(dataExportWorkflowTemplateData) + }); + } return createSpySuccessResponse({ data: cloneDeep(workflowTemplateData) }); @@ -26,6 +36,16 @@ class MockWorkflowTemplateApi implements MockSpyApy { return spy; } + public getWorkflowTemplateList() { + const spy = jest.spyOn(workflow, 'getWorkflowTemplateListV1'); + spy.mockImplementation(() => { + return createSpySuccessResponse({ + data: cloneDeep(workflowTemplateListData) + }); + }); + return spy; + } + public cancelWorkflow() { const spy = jest.spyOn(workflow, 'cancelWorkflowV2'); spy.mockImplementation(() => { diff --git a/packages/shared/lib/types/ambient-modules.d.ts b/packages/shared/lib/types/ambient-modules.d.ts new file mode 100644 index 0000000000..35306c6fc9 --- /dev/null +++ b/packages/shared/lib/types/ambient-modules.d.ts @@ -0,0 +1 @@ +declare module '*.css'; diff --git a/packages/shared/package.json b/packages/shared/package.json index f78ab4c849..126c435ec9 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -5,15 +5,21 @@ "license": "MIT", "scripts": { "build": "tsup", + "oxlint": "oxlint --no-error-on-unmatched-pattern src lib api", + "typecheck": "tsc --noEmit -p tsconfig.json", + "stylelint": "stylelint \"{src,lib}/**/{*.less,style.ts,element.ts}\" --allow-empty-input", + "check": "echo \"shared check\"", "test": "jest --watchAll=true", - "test:c": "jest --watchAll=false --coverage", - "test:ci": "jest --ci --watchAll=false --coverage --color --silent --testLocationInResults" + "test:c": "jest --watchAll=false --coverage --coverageDirectory=coverage", + "test:run": "jest --watchAll=false --color", + "test:ci": "jest --ci --watchAll=false --coverage --coverageDirectory=coverage --json --outputFile=coverage/report.json --color --silent --testLocationInResults" }, "dependencies": { "@actiontech/icons": "workspace:^", "@actiontech/dms-kit": "workspace:^" }, "devDependencies": { + "@actiontech/tooling-config": "workspace:^", "tsup": "^8.5.0" } -} \ No newline at end of file +} diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index ee6467a89f..123b998894 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -3,7 +3,10 @@ "include": ["./lib"], "compilerOptions": { "paths": { - "~/*": ["./src/*"] + "~/*": ["./src/*"], + "@actiontech/dms-kit": ["../dms-kit/src/index.ts"], + "@actiontech/dms-kit/es/*": ["../dms-kit/src/*"], + "@actiontech/dms-kit/*": ["../dms-kit/src/*"] } } } diff --git a/packages/sqle/jest.config.mjs b/packages/sqle/jest.config.mjs new file mode 100644 index 0000000000..06aa954798 --- /dev/null +++ b/packages/sqle/jest.config.mjs @@ -0,0 +1,21 @@ +import { createJestConfig } from '@actiontech/tooling-config/jest/create-jest-config'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; + +const packageRoot = path.dirname(fileURLToPath(import.meta.url)); + +export default createJestConfig({ + packageRoot, + enabledProjects: ['dms', 'sqle-ce', 'sqle-ee'], + collectCoverageFrom: [ + 'src/{page,components,hooks,global,store,utils}/**/*.{ts,tsx}', + 'src/App.tsx', + '!src/**/*.test.{ts,tsx}', + '!src/**/*.type.ts', + '!src/**/*.enum.ts', + '!src/page/SqlAnalyze/SqlAnalyze/ProcessListCom/**', + '!src/page/Knowledge/Graph/components/**', + '!src/**/demo/**', + '!src/**/demos/**' + ] +}); diff --git a/packages/sqle/package.json b/packages/sqle/package.json index 68dacf6a58..b7cdb976b6 100644 --- a/packages/sqle/package.json +++ b/packages/sqle/package.json @@ -23,6 +23,7 @@ "web-vitals": "^0.2.4" }, "devDependencies": { + "@actiontech/tooling-config": "workspace:^", "@types/react-grid-layout": "^1.3.2", "graphology-types": "^0.24.8", "jest-canvas-mock": "^2.2.0" @@ -30,9 +31,14 @@ "scripts": { "start": "PORT=3030 craco start", "build": "craco build", + "oxlint": "oxlint --no-error-on-unmatched-pattern src", + "typecheck": "tsc --noEmit -p tsconfig.json", + "stylelint": "stylelint \"src/**/{*.less,style.ts,element.ts}\" --allow-empty-input", + "check": "echo \"sqle check\"", "test": "jest --watchAll=true", - "test:c": "jest --watchAll=false --coverage", - "test:ci": "jest --ci --watchAll=false --coverage --color --silent --testLocationInResults", + "test:c": "jest --watchAll=false --coverage --coverageDirectory=coverage", + "test:run": "jest --watchAll=false --color", + "test:ci": "jest --ci --watchAll=false --coverage --coverageDirectory=coverage --json --outputFile=coverage/report.json --color --silent --testLocationInResults", "eject": "react-scripts eject" }, "browserslist": { diff --git a/packages/sqle/src/index.tsx b/packages/sqle/src/index.tsx index 6a1ae6db08..a15dc4bfef 100644 --- a/packages/sqle/src/index.tsx +++ b/packages/sqle/src/index.tsx @@ -6,8 +6,6 @@ import { Provider } from 'react-redux'; import store from './store'; import { BrowserRouter as Router } from 'react-router-dom'; import './locale'; -import './utils/HighlightCode'; -import './index.less'; import { initReactI18n } from './locale'; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( diff --git a/packages/sqle/src/locale/en-US/execWorkflow.ts b/packages/sqle/src/locale/en-US/execWorkflow.ts index 7fa06b17e8..dd6810a88e 100644 --- a/packages/sqle/src/locale/en-US/execWorkflow.ts +++ b/packages/sqle/src/locale/en-US/execWorkflow.ts @@ -91,6 +91,8 @@ export default { addInstanceTips: 'Please add DB instance', addInstance: 'Add DB instance', uploadType: 'Select SQL statement upload method', + uploadTypeTip: + 'The number of SQL statements that can be deployed at one time is 1000', manualInput: 'Enter SQL statement', uploadFile: 'Upload SQL file', updateMybatisFile: 'Upload Mybatis XML file', diff --git a/packages/sqle/src/locale/en-US/workflowTemplate.ts b/packages/sqle/src/locale/en-US/workflowTemplate.ts index eebcd5119d..1aaa6c1ef6 100644 --- a/packages/sqle/src/locale/en-US/workflowTemplate.ts +++ b/packages/sqle/src/locale/en-US/workflowTemplate.ts @@ -10,7 +10,15 @@ export default { table: { workflowTemplateName: 'Approval workflow template name', - desc: 'Approval workflow template description' + desc: 'Approval workflow template description', + applicableType: 'Applicable Type', + approvalNodeDesc: 'Approval Node Description', + updateTime: 'Update Time' + }, + + type: { + workflow: 'SQL Exec Workflow', + dataExport: 'Data Export' }, operator: { @@ -33,7 +41,9 @@ export default { update: { title: { - wrapper: 'Update approval workflow template' + wrapper: 'Update approval workflow template', + workflow: 'Edit Approval Process - SQL Exec Workflow', + dataExport: 'Edit Approval Process - Data Export' }, result: { title: 'Update approval workflow template successfully', @@ -66,7 +76,9 @@ export default { fourth: 'Audit tickets: the auditor can execute “pass audit” or “reject” operations in this step;', fifth: - 'Online tickets: the executor can execute “execute online” or “reject” operations in this step.' + 'Online tickets: the executor can execute “execute online” or “reject” operations in this step.', + fifthExport: + 'Export tickets: the executor can execute “execute export” or “reject” operations in this step.' } }, @@ -82,6 +94,10 @@ export default { execDesc: 'Edit the audit process. The executor can execute “execute online” or “reject” operations in this step', + exportExecTitle: 'Execute export', + exportExecDesc: + 'Edit the audit process. The executor can execute “execute export” or “reject” operations in this step', + resultTitle: 'Result', resultDesc: 'Change result' }, @@ -132,6 +148,25 @@ export default { matchExecute: 'Match members who have data source online permissions' } }, + exportExec: { + title: 'Execute export', + subTitle: + 'The executor can execute “execute export” or “reject” operations in this step', + creatorAsExecutor: + 'The executor of data export is the workflow creator by default and cannot be modified.', + executeUserType: { + specifyExecute: 'Specify executor', + matchExecute: 'Match members who have data source export permissions' + } + }, + exportReview: { + title: 'Export Review', + subTitle: 'Reviewer checks the legitimacy of the export request' + }, + exportExecute: { + title: 'Export Execution Confirm', + subTitle: 'Confirm to execute the export operation' + }, operator: { remove: 'Remove this step', moveUp: 'Move this step up', @@ -147,6 +182,10 @@ export default { 'The approval workflow template can set up to 4 audit steps, or no audit steps can be set;', rule3: 'When specifying the executor for a single step, at least one specified person needs to be added, and a maximum of three specified persons can be added.' + }, + exportRuler: { + rule1: + 'The approval process starts from the initiation of the ticket, and ends with the execution of export after passing through the set audit steps;' } }, diff --git a/packages/sqle/src/locale/zh-CN/execWorkflow.ts b/packages/sqle/src/locale/zh-CN/execWorkflow.ts index 336bce2c82..656b7fe056 100644 --- a/packages/sqle/src/locale/zh-CN/execWorkflow.ts +++ b/packages/sqle/src/locale/zh-CN/execWorkflow.ts @@ -86,6 +86,7 @@ export default { addInstanceTips: '请添加数据源', addInstance: '添加数据源', uploadType: '选择SQL语句上传方式', + uploadTypeTips: '单次上线SQL数量为1000条', manualInput: '输入SQL语句', uploadFile: '上传SQL文件', updateMybatisFile: '上传Mybatis的XML文件', diff --git a/packages/sqle/src/locale/zh-CN/workflowTemplate.ts b/packages/sqle/src/locale/zh-CN/workflowTemplate.ts index 0e7ea1c556..ca1a153c84 100644 --- a/packages/sqle/src/locale/zh-CN/workflowTemplate.ts +++ b/packages/sqle/src/locale/zh-CN/workflowTemplate.ts @@ -10,7 +10,15 @@ export default { table: { workflowTemplateName: '审批流程模板名称', - desc: '审批流程模板描述' + desc: '审批流程模板描述', + applicableType: '适用类型', + approvalNodeDesc: '审批节点描述', + updateTime: '更新时间' + }, + + type: { + workflow: '上线工单', + dataExport: '数据导出' }, operator: { @@ -32,7 +40,9 @@ export default { update: { title: { - wrapper: '更新审批流程模板' + wrapper: '更新审批流程模板', + workflow: '编辑审批流程 - 上线工单', + dataExport: '编辑审批流程 - 数据导出' }, result: { title: '更新审批流程模板成功', @@ -62,7 +72,9 @@ export default { '被驳回的工单,需要创建人更新SQL语句后重新发起,驳回记录可在 “工单进度-工单历史操作” 中查看;', third: '处于 “审核节点” 中的工单,创建人可在工单详情页随时关闭;', fourth: '审核工单:审核人在该步骤可以执行「审核通过」或「驳回」操作;', - fifth: '上线工单:执行人在该步骤可以执行「执行上线」或「驳回」操作。' + fifth: '上线工单:执行人在该步骤可以执行「执行上线」或「驳回」操作。', + fifthExport: + '导出工单:执行人在该步骤可以执行「执行导出」或「驳回」操作。' } }, @@ -77,6 +89,10 @@ export default { execTitle: '执行上线', execDesc: '编辑审核流程,执行人在该步骤可以执行「执行上线」或「驳回」操作', + exportExecTitle: '执行导出', + exportExecDesc: + '编辑审核流程,执行人在该步骤可以执行「执行导出」或「驳回」操作', + resultTitle: '结果', resultDesc: '变更结果' }, @@ -96,7 +112,7 @@ export default { rule: { descMessage: '步骤描述不能超过255个字符', userRequired: '最少需要添加一个指定人', - userMessage: '最多只能添加十个指定人' + userMessage: '最多只能添加{{max}}个指定人' } }, @@ -124,6 +140,23 @@ export default { matchExecute: '匹配拥有数据源上线权限的成员' } }, + exportExec: { + title: '执行导出', + subTitle: '执行人在该步骤可以执行 执行导出或驳回 操作', + creatorAsExecutor: '数据导出的执行人默认为工单创建者,不可修改。', + executeUserType: { + specifyExecute: '指定执行人', + matchExecute: '匹配拥有数据源导出权限的成员' + } + }, + exportReview: { + title: '导出审批', + subTitle: '审批人在该步骤审核导出请求的合理性' + }, + exportExecute: { + title: '导出执行确认', + subTitle: '确认执行导出操作' + }, operator: { remove: '移除该步骤', moveUp: '上移该步骤', @@ -136,7 +169,11 @@ export default { '审核流程自工单发起开始,通过设置的审核步骤后,最后以执行上线结束;', rule2: '审核流程模板最多可设置4个审核步骤,也可不设置审核步骤;', rule3: - '单个步骤指定执行人时,最少需要添加一个指定人,最多只能添加三个指定人。' + '单个步骤指定执行人时,最少需要添加一个指定人,最多只能添加十个指定人。' + }, + exportRuler: { + rule1: + '审核流程自工单发起开始,通过设置的审核步骤后,最后以执行导出结束;' } }, diff --git a/packages/sqle/src/page/RuleKnowledge/Common/MarkdownPreview/markdownPreviewOptions.tsx b/packages/sqle/src/page/RuleKnowledge/Common/MarkdownPreview/markdownPreviewOptions.tsx index 049c13cec9..a436268ccb 100644 --- a/packages/sqle/src/page/RuleKnowledge/Common/MarkdownPreview/markdownPreviewOptions.tsx +++ b/packages/sqle/src/page/RuleKnowledge/Common/MarkdownPreview/markdownPreviewOptions.tsx @@ -9,7 +9,15 @@ type PreviewOptions = BasicMDEditorProps['previewOptions']; export const markdownPreviewOptions: PreviewOptions = { components: { - code: ({ children, className, ...props }) => { + code: ({ + children, + className, + node + }: { + children: string; + className: string; + node: { children: Parameters[0] }; + }) => { /** * label 代码块 * Example: @@ -23,11 +31,8 @@ export const markdownPreviewOptions: PreviewOptions = { if (isArray(match) && !!match[1]) { return ; } - const code = - props.node && props.node.children - ? getCodeString(props.node.children) - : children; + node && node.children ? getCodeString(node.children) : children; /** * sql_diff 代码块 * Example: diff --git a/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/__tests__/__snapshots__/index.test.tsx.snap index 83717b0bae..93c11e263f 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/__tests__/__snapshots__/index.test.tsx.snap @@ -4,7 +4,7 @@ exports[`sqle/ExecWorkflow/BasicInfoWrapper render snap when has all params 1`]
this is a desc str
@@ -118,7 +118,7 @@ exports[`sqle/ExecWorkflow/BasicInfoWrapper render snap when has need params 1`]
-
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/index.tsx index 85be210af6..c9185530c7 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/index.tsx +++ b/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/index.tsx @@ -1,13 +1,18 @@ import classNames from 'classnames'; import { BasicInfoStyleWrapper } from './style'; import { BasicInfoWrapperProps } from './index.type'; -import { EmptyBox, BasicTag } from '@actiontech/dms-kit'; +import { + EmptyBox, + BasicTag, + BasicTypographyEllipsis +} from '@actiontech/dms-kit'; import { TypedLink } from '@actiontech/shared'; import { useTranslation } from 'react-i18next'; import { execWorkflowStatusDictionary } from '../../../../hooks/useStaticStatus/index.data'; import { Space } from 'antd'; import { useCurrentProject } from '@actiontech/shared/lib/features'; import { ROUTE_PATHS } from '@actiontech/dms-kit'; + const BasicInfoWrapper: React.FC = ({ title, desc, @@ -102,7 +107,11 @@ const BasicInfoWrapper: React.FC = ({ -
{desc ?? '-'}
+ ); }; diff --git a/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/style.ts b/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/style.ts index 35a0ee53e9..41775b6f89 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/style.ts +++ b/packages/sqle/src/page/SqlExecWorkflow/Common/BasicInfoWrapper/style.ts @@ -62,9 +62,10 @@ export const BasicInfoStyleWrapper = styled('div')<{ .workflow-base-info-desc { color: ${({ theme }) => - theme.sqleTheme.execWorkflow.common.basicInfo.descColor}; + theme.sqleTheme.execWorkflow.common.basicInfo.descColor} !important; font-size: 14px; font-weight: 400; line-height: 22px; + max-width: 800px; } `; diff --git a/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/SqlStatementFormItem/__tests__/__snapshots__/index.ce.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/SqlStatementFormItem/__tests__/__snapshots__/index.ce.test.tsx.snap index 450eb6802b..10b0a3a26f 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/SqlStatementFormItem/__tests__/__snapshots__/index.ce.test.tsx.snap +++ b/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/SqlStatementFormItem/__tests__/__snapshots__/index.ce.test.tsx.snap @@ -18,32 +18,80 @@ exports[`test SqlStatementFormItem renders SqlStatementFormItem component 1`] = class="" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
= ({ <> + {t('execWorkflow.create.form.sqlInfo.uploadType')} - + + } className="form-item-label-mb-16" /> diff --git a/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/__tests__/__snapshots__/index.ce.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/__tests__/__snapshots__/index.ce.test.tsx.snap index 81cda300f2..6fd5812f40 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/__tests__/__snapshots__/index.ce.test.tsx.snap +++ b/packages/sqle/src/page/SqlExecWorkflow/Common/SqlStatementFormController/__tests__/__snapshots__/index.ce.test.tsx.snap @@ -18,32 +18,80 @@ exports[`test SqlStatementFormController ce should match snapshot 1`] = ` class="" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
-
@@ -6666,32 +6810,80 @@ exports[`sqle/SqlExecWorkflow/Create render create rollback workflow 1`] = ` class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
test desc
@@ -8702,32 +8894,80 @@ exports[`sqle/SqlExecWorkflow/Create render create rollback workflow 2`] = ` class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
test desc
@@ -11118,32 +11358,80 @@ exports[`sqle/SqlExecWorkflow/Create should handle form submission and audit act class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
workflow desc
@@ -13737,32 +14025,80 @@ exports[`sqle/SqlExecWorkflow/Create should handle form submission and audit act class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
workflow desc
@@ -16368,32 +16704,80 @@ exports[`sqle/SqlExecWorkflow/Create should handle form submission and audit act class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
workflow desc
@@ -20808,32 +21240,80 @@ exports[`sqle/SqlExecWorkflow/Create should handle form submission and audit act class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
-
@@ -30107,32 +30779,80 @@ exports[`sqle/SqlExecWorkflow/Create should snapshot render initial workflow cre class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
desc
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Create/components/AuditResultStep/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Create/components/AuditResultStep/__tests__/__snapshots__/index.test.tsx.snap index 43f47563e8..4de1e0c167 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Create/components/AuditResultStep/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/SqlExecWorkflow/Create/components/AuditResultStep/__tests__/__snapshots__/index.test.tsx.snap @@ -72,7 +72,7 @@ exports[`test AuditResultStep render switch backup policy button 1`] = `
desc
@@ -655,7 +655,7 @@ exports[`test AuditResultStep render switch data source backup policy 1`] = `
desc
@@ -1713,7 +1713,7 @@ exports[`test AuditResultStep should match snapshot 1`] = `
desc
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Create/hooks/useAllowAuditLevel.ts b/packages/sqle/src/page/SqlExecWorkflow/Create/hooks/useAllowAuditLevel.ts index 577ffef04d..71b11ebb9e 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Create/hooks/useAllowAuditLevel.ts +++ b/packages/sqle/src/page/SqlExecWorkflow/Create/hooks/useAllowAuditLevel.ts @@ -1,5 +1,6 @@ import { WorkflowTemplateDetailResV1AllowSubmitWhenLessAuditLevelEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum'; import workflow from '@actiontech/shared/lib/api/sqle/service/workflow'; +import { getWorkflowTemplateV1WorkflowTypeEnum } from '@actiontech/shared/lib/api/sqle/service/workflow/index.enum'; import { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -32,7 +33,8 @@ export const useAllowAuditLevel = () => { ) => { const request = (projectName: string) => { return workflow.getWorkflowTemplateV1({ - project_name: projectName + project_name: projectName, + workflow_type: getWorkflowTemplateV1WorkflowTypeEnum.workflow }); }; const tips: string[] = []; diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap index 7b1100c14f..c119fd18e3 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/__tests__/__snapshots__/index.test.tsx.snap @@ -200,7 +200,7 @@ exports[`sqle/ExecWorkflow/Detail render current workflow status is wait for exe
this is a desc
@@ -951,7 +951,7 @@ exports[`sqle/ExecWorkflow/Detail render snap detail 1`] = `
-
@@ -1522,7 +1522,7 @@ exports[`sqle/ExecWorkflow/Detail render snap detail 2`] = `
this is a desc
@@ -2414,7 +2414,7 @@ exports[`sqle/ExecWorkflow/Detail render snap detail 3`] = `
this is a desc
@@ -3338,7 +3338,7 @@ exports[`sqle/ExecWorkflow/Detail render snap detail when have multiple states 1
this is a desc
diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx index 287e3a463c..26a41d681c 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx +++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/TaskResultList/SqlFileStatementOverview/index.tsx @@ -14,7 +14,7 @@ import useAuditResultFilterParams from '../../../../../Common/AuditResultFilterC import { IAuditTaskSQLResV2 } from '@actiontech/shared/lib/api/sqle/service/common'; import { AuditTaskExtraFilterMeta } from '../../index.data'; import task from '@actiontech/shared/lib/api/sqle/service/task'; -import { ResponseCode } from '@actiontech/dms-kit'; +import { FilterCustomProps, ResponseCode } from '@actiontech/dms-kit'; import { GetAuditTaskSQLsPrams } from '../../index.type'; import { BasicButton, @@ -228,7 +228,7 @@ const SqlFileStatementOverview: React.FC = () => { filterContainerMeta={filterContainerMeta} updateTableFilterInfo={updateTableFilterInfo} filterCustomProps={ - new Map([ + new Map([ [ 'audit_level', { diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx index d27310fcdf..012b012818 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx +++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/AuditExecResultPanel/index.tsx @@ -1,7 +1,10 @@ import { useTranslation } from 'react-i18next'; import { AuditExecResultPanelProps } from './index.type'; import { AuditExecResultPanelStyleWrapper } from './style'; -import { SegmentedRowStyleWrapper } from '@actiontech/dms-kit'; +import { + FilterCustomProps, + SegmentedRowStyleWrapper +} from '@actiontech/dms-kit'; import { BasicSegmented, EmptyBox } from '@actiontech/dms-kit'; import { WORKFLOW_OVERVIEW_TAB_KEY } from '../../hooks/useAuditExecResultPanelSetup'; import { @@ -35,6 +38,7 @@ import { ModalName } from '../../../../../data/ModalName'; import EmitterKey from '../../../../../data/EmitterKey'; import EventEmitter from '../../../../../utils/EventEmitter'; import useRetryExecute from './hooks/useRetryExecute'; +import { IAuditTaskSQLResV2 } from '@actiontech/shared/lib/api/sqle/service/common'; const AuditExecResultPanel: React.FC = ({ activeTabKey, @@ -180,7 +184,7 @@ const AuditExecResultPanel: React.FC = ({ filterContainerMeta={filterContainerMeta} updateTableFilterInfo={updateTableFilterInfo} filterCustomProps={ - new Map([ + new Map([ [ 'audit_level', { diff --git a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/ModifySqlStatement/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/ModifySqlStatement/__tests__/__snapshots__/index.test.tsx.snap index c565aaab7a..92dcec665b 100644 --- a/packages/sqle/src/page/SqlExecWorkflow/Detail/components/ModifySqlStatement/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/SqlExecWorkflow/Detail/components/ModifySqlStatement/__tests__/__snapshots__/index.test.tsx.snap @@ -104,32 +104,80 @@ exports[`sqle/ExecWorkflow/Detail/ModifySqlStatement render snap when click form class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
+
+ +
diff --git a/packages/sqle/src/page/SqlOptimization/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/SqlOptimization/__snapshots__/index.test.tsx.snap index 1b3987d0e0..90736772a0 100644 --- a/packages/sqle/src/page/SqlOptimization/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/SqlOptimization/__snapshots__/index.test.tsx.snap @@ -120,6 +120,7 @@ exports[`sqle/SqlOptimization should render enterprise feature display with prop >
+
+ +
diff --git a/packages/sqle/src/page/VersionManagement/Detail/components/ModifyWorkflowSql/__tests__/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/VersionManagement/Detail/components/ModifyWorkflowSql/__tests__/__snapshots__/index.test.tsx.snap index 26987a56c5..015fd498fc 100644 --- a/packages/sqle/src/page/VersionManagement/Detail/components/ModifyWorkflowSql/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/VersionManagement/Detail/components/ModifyWorkflowSql/__tests__/__snapshots__/index.test.tsx.snap @@ -101,32 +101,80 @@ exports[`sqle/VersionManagement/Detail/ModifyWorkflowSql render init snap shot 1 class="ant-form-item-no-colon" title="" > - - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- - - - - - 选择SQL语句上传方式 - +
+ + + + +
+
+ + 选择SQL语句上传方式 + +
+
+
+
+ + + +
+
+
+
- 返回审批流程模板 + 编辑审批流程 - 上线工单 @@ -692,6 +692,532 @@ exports[`page/WorkflowTemplate/UpdateWorkflowTemplate change workflow template n `; +exports[`page/WorkflowTemplate/UpdateWorkflowTemplate data_export workflow type should correctly identify export_execute as exec step when API returns steps in wrong order 1`] = ` + +