[Feature][UI Next] Auto layout modal (#8298)
This commit is contained in:
parent
1d6c509119
commit
78cac08532
|
|
@ -10,6 +10,7 @@
|
|||
"prettier": "prettier --write \"src/**/*.{vue,ts,tsx}\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/layout": "^0.1.31",
|
||||
"@antv/x6": "^1.29.5",
|
||||
"@vueuse/core": "^7.5.3",
|
||||
"axios": "^0.24.0",
|
||||
|
|
@ -36,7 +37,7 @@
|
|||
"@vicons/antd": "^0.11.0",
|
||||
"@vitejs/plugin-vue": "^1.10.2",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.3",
|
||||
"dart-sass": "^1.48.0",
|
||||
"dart-sass": "^1.25.0",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
lockfileVersion: 5.3
|
||||
|
||||
specifiers:
|
||||
'@antv/layout': ^0.1.31
|
||||
'@antv/x6': ^1.29.5
|
||||
'@types/node': ^16.11.19
|
||||
'@types/nprogress': ^0.2.0
|
||||
|
|
@ -57,6 +58,7 @@ specifiers:
|
|||
vue-tsc: ^0.28.10
|
||||
|
||||
dependencies:
|
||||
'@antv/layout': 0.1.31
|
||||
'@antv/x6': 1.29.5
|
||||
'@vueuse/core': 7.5.3_vue@3.2.26
|
||||
axios: 0.24.0
|
||||
|
|
@ -99,6 +101,58 @@ devDependencies:
|
|||
|
||||
packages:
|
||||
|
||||
/@antv/g-webgpu-core/0.5.6:
|
||||
resolution: {integrity: sha512-DPiH3GkAUiT0Q+LAKeImpI+IOQ/gP2w6HstYKivpFIpBPIvZ/9equM3icVrn1iDfDkZANVXQ1PppcO3xBv1ZTw==}
|
||||
dependencies:
|
||||
eventemitter3: 4.0.7
|
||||
gl-matrix: 3.4.3
|
||||
inversify: 5.1.1
|
||||
inversify-inject-decorators: 3.1.0
|
||||
probe.gl: 3.5.0
|
||||
reflect-metadata: 0.1.13
|
||||
dev: false
|
||||
|
||||
/@antv/g-webgpu-engine/0.5.6:
|
||||
resolution: {integrity: sha512-D311qYUefdEFwLayutIHqucrAY3cAGH3BdnXS37nq+0nsglrHcNP0Ab1YTinn9RihLoY3yXFTLzrYkJHJbZXDg==}
|
||||
dependencies:
|
||||
'@antv/g-webgpu-core': 0.5.6
|
||||
'@webgpu/glslang': 0.0.15
|
||||
'@webgpu/types': 0.0.31
|
||||
gl-matrix: 3.4.3
|
||||
hammerjs: 2.0.8
|
||||
inversify: 5.1.1
|
||||
inversify-inject-decorators: 3.1.0
|
||||
probe.gl: 3.5.0
|
||||
reflect-metadata: 0.1.13
|
||||
regl: 1.7.0
|
||||
dev: false
|
||||
|
||||
/@antv/g-webgpu/0.5.5:
|
||||
resolution: {integrity: sha512-TxtBniINFq1jFGEPo46xjJfrbJbUqkFd5wmsRs3tcg/7J7xoldOP1kEadpI3AJG9knMYdE92VpILw1VPd6DgzQ==}
|
||||
dependencies:
|
||||
'@antv/g-webgpu-core': 0.5.6
|
||||
'@antv/g-webgpu-engine': 0.5.6
|
||||
'@webgpu/types': 0.0.31
|
||||
gl-matrix: 3.4.3
|
||||
gl-vec2: 1.3.0
|
||||
hammerjs: 2.0.8
|
||||
inversify: 5.1.1
|
||||
inversify-inject-decorators: 3.1.0
|
||||
polyline-miter-util: 1.0.1
|
||||
polyline-normals: 2.0.2
|
||||
probe.gl: 3.5.0
|
||||
reflect-metadata: 0.1.13
|
||||
dev: false
|
||||
|
||||
/@antv/layout/0.1.31:
|
||||
resolution: {integrity: sha512-iz9i19dOJGiZr5xBWI5sfG+2K3QVMNAGOBrbjWKH2RGLvGpf2TSFySidhz0siDrcQA46cDsjLmGstezQdgeGzA==}
|
||||
dependencies:
|
||||
'@antv/g-webgpu': 0.5.5
|
||||
'@dagrejs/graphlib': 2.1.4
|
||||
d3-force: 2.1.1
|
||||
ml-matrix: 6.8.2
|
||||
dev: false
|
||||
|
||||
/@antv/x6/1.29.5:
|
||||
resolution: {integrity: sha512-U5gg40jo+UtzjdX/7QFenVZgGKOtDFDo60AMNGEvIEzGnixV+2zV0EBJ2f8We4Fp1ZVP0G2pm6uS7ajuuuLsvg==}
|
||||
dependencies:
|
||||
|
|
@ -369,6 +423,13 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/runtime/7.17.0:
|
||||
resolution: {integrity: sha512-etcO/ohMNaNA2UBdaXBBSX/3aEzFMRrVfaPv8Ptc0k+cWpWW0QFiGZ2XnVqQZI1Cf734LbPGmqBKWESfW4x/dQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
regenerator-runtime: 0.13.9
|
||||
dev: false
|
||||
|
||||
/@babel/template/7.16.7:
|
||||
resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
|
@ -420,6 +481,12 @@ packages:
|
|||
vue: 3.2.26
|
||||
dev: false
|
||||
|
||||
/@dagrejs/graphlib/2.1.4:
|
||||
resolution: {integrity: sha512-QCg9sL4uhjn468FDEsb/S9hS2xUZSrv/+dApb1Ze5VKO96pTXKNJZ6MGhIpgWkc1TVhbVGH9/7rq/Mf8/jWicw==}
|
||||
dependencies:
|
||||
lodash: 4.17.21
|
||||
dev: false
|
||||
|
||||
/@emmetio/abbreviation/2.2.2:
|
||||
resolution: {integrity: sha512-TtE/dBnkTCct8+LntkqVrwqQao6EnPAs1YN3cUgxOxTaBlesBCY37ROUAVZrRlG64GNnVShdl/b70RfAI3w5lw==}
|
||||
dependencies:
|
||||
|
|
@ -531,6 +598,25 @@ packages:
|
|||
fastq: 1.13.0
|
||||
dev: true
|
||||
|
||||
/@probe.gl/env/3.5.0:
|
||||
resolution: {integrity: sha512-YdlpZZshhyYxvWDBmZ5RIW2pTR14Pw4p9czMlt/v7F6HbFzWfAdmH7q6xVwFRYxUpQLwhWensWyv4aFysiWl4g==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.17.0
|
||||
dev: false
|
||||
|
||||
/@probe.gl/log/3.5.0:
|
||||
resolution: {integrity: sha512-nW/qz2X1xY08WU/TsmJP6/6IPNcaY5fS/vLjpC4ahJuE2Mezga4hGM/R2X5JWE/nkPc+BsC5GnAnD13rwAxS7g==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.17.0
|
||||
'@probe.gl/env': 3.5.0
|
||||
dev: false
|
||||
|
||||
/@probe.gl/stats/3.5.0:
|
||||
resolution: {integrity: sha512-IH2M+F3c8HR1DTroBARePUFG7wIewumtKA0UFqx51Z7S4hKrD60wFbpMmg0AcF4FvHAXMBoC+kYi1UKW9XbAOw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.17.0
|
||||
dev: false
|
||||
|
||||
/@rollup/pluginutils/4.1.2:
|
||||
resolution: {integrity: sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
|
|
@ -916,6 +1002,14 @@ packages:
|
|||
vue-demi: 0.12.1_vue@3.2.26
|
||||
dev: false
|
||||
|
||||
/@webgpu/glslang/0.0.15:
|
||||
resolution: {integrity: sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==}
|
||||
dev: false
|
||||
|
||||
/@webgpu/types/0.0.31:
|
||||
resolution: {integrity: sha512-cvvCMSZBT4VsRNtt0lI6XQqvOIIWw6+NRUtnPUMDVDgsI4pCZColz3qzF5QcP9wIYOHEc3jssIBse8UWONKhlQ==}
|
||||
dev: false
|
||||
|
||||
/acorn-jsx/5.3.2_acorn@8.7.0:
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
|
|
@ -1213,6 +1307,26 @@ packages:
|
|||
resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==}
|
||||
dev: false
|
||||
|
||||
/d3-dispatch/2.0.0:
|
||||
resolution: {integrity: sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==}
|
||||
dev: false
|
||||
|
||||
/d3-force/2.1.1:
|
||||
resolution: {integrity: sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==}
|
||||
dependencies:
|
||||
d3-dispatch: 2.0.0
|
||||
d3-quadtree: 2.0.0
|
||||
d3-timer: 2.0.0
|
||||
dev: false
|
||||
|
||||
/d3-quadtree/2.0.0:
|
||||
resolution: {integrity: sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw==}
|
||||
dev: false
|
||||
|
||||
/d3-timer/2.0.0:
|
||||
resolution: {integrity: sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==}
|
||||
dev: false
|
||||
|
||||
/dart-sass/1.25.0:
|
||||
resolution: {integrity: sha512-syNOAstJXAmvD3RifcDk3fiPMyYE2fY8so6w9gf2/wNlKpG0zyH+oiXubEYVOy1WAWkzOc72pbAxwx+3OU4JJA==}
|
||||
engines: {node: '>=8.9.0'}
|
||||
|
|
@ -1720,6 +1834,10 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/eventemitter3/4.0.7:
|
||||
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
|
||||
dev: false
|
||||
|
||||
/evtd/0.2.3:
|
||||
resolution: {integrity: sha512-tmiT1YUVqFjTY+BSBOAskL83xNx41iUfpvKP6Gcd/xMHjg3mnER98jXGXJyKnxCG19uPc6EhZiUC+MUyvoqCtw==}
|
||||
dev: false
|
||||
|
|
@ -1843,6 +1961,14 @@ packages:
|
|||
has: 1.0.3
|
||||
has-symbols: 1.0.2
|
||||
|
||||
/gl-matrix/3.4.3:
|
||||
resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==}
|
||||
dev: false
|
||||
|
||||
/gl-vec2/1.3.0:
|
||||
resolution: {integrity: sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A==}
|
||||
dev: false
|
||||
|
||||
/glob-parent/5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
|
|
@ -1896,6 +2022,11 @@ packages:
|
|||
resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==}
|
||||
dev: true
|
||||
|
||||
/hammerjs/2.0.8:
|
||||
resolution: {integrity: sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=}
|
||||
engines: {node: '>=0.8.0'}
|
||||
dev: false
|
||||
|
||||
/has-flag/3.0.0:
|
||||
resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=}
|
||||
engines: {node: '>=4'}
|
||||
|
|
@ -2014,6 +2145,18 @@ packages:
|
|||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
dev: true
|
||||
|
||||
/inversify-inject-decorators/3.1.0:
|
||||
resolution: {integrity: sha512-/seBlVp5bXrLQS3DpKEmlgeZL6C7Tf/QITd+IMQrbBBGuCbxb7k3hRAWu9XSreNpFzLgSboz3sClLSEmGwHphw==}
|
||||
dev: false
|
||||
|
||||
/inversify/5.1.1:
|
||||
resolution: {integrity: sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==}
|
||||
dev: false
|
||||
|
||||
/is-any-array/2.0.0:
|
||||
resolution: {integrity: sha512-WdPV58rT3aOWXvvyuBydnCq4S2BM1Yz8shKxlEpk/6x+GX202XRvXOycEFtNgnHVLoc46hpexPFx8Pz1/sMS0w==}
|
||||
dev: false
|
||||
|
||||
/is-binary-path/2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -2286,6 +2429,32 @@ packages:
|
|||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/ml-array-max/1.2.4:
|
||||
resolution: {integrity: sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ==}
|
||||
dependencies:
|
||||
is-any-array: 2.0.0
|
||||
dev: false
|
||||
|
||||
/ml-array-min/1.2.3:
|
||||
resolution: {integrity: sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q==}
|
||||
dependencies:
|
||||
is-any-array: 2.0.0
|
||||
dev: false
|
||||
|
||||
/ml-array-rescale/1.3.7:
|
||||
resolution: {integrity: sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ==}
|
||||
dependencies:
|
||||
is-any-array: 2.0.0
|
||||
ml-array-max: 1.2.4
|
||||
ml-array-min: 1.2.3
|
||||
dev: false
|
||||
|
||||
/ml-matrix/6.8.2:
|
||||
resolution: {integrity: sha512-5o2gVLFyieDSgsStEU5mqty4MZqfeytYA/gJqBSw5/Xuob0X2UrFX/k7FDh+YAwjzG/1l8nYa0oDaJ0sGs/RlA==}
|
||||
dependencies:
|
||||
ml-array-rescale: 1.3.7
|
||||
dev: false
|
||||
|
||||
/monaco-editor/0.31.1:
|
||||
resolution: {integrity: sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q==}
|
||||
dev: false
|
||||
|
|
@ -2470,6 +2639,18 @@ packages:
|
|||
vue-demi: 0.12.1_vue@3.2.26
|
||||
dev: false
|
||||
|
||||
/polyline-miter-util/1.0.1:
|
||||
resolution: {integrity: sha1-tpPyOJ6g3tNqa89ezS7OS2kX2Vc=}
|
||||
dependencies:
|
||||
gl-vec2: 1.3.0
|
||||
dev: false
|
||||
|
||||
/polyline-normals/2.0.2:
|
||||
resolution: {integrity: sha1-oXN+ddjA3MsaWR+csn8J7vS30TU=}
|
||||
dependencies:
|
||||
polyline-miter-util: 1.0.1
|
||||
dev: false
|
||||
|
||||
/postcss-filter-plugins/3.0.1:
|
||||
resolution: {integrity: sha512-tRKbW4wWBEkSSFuJtamV2wkiV9rj6Yy7P3Y13+zaynlPEEZt8EgYKn3y/RBpMeIhNmHXFlSdzofml65hD5OafA==}
|
||||
dependencies:
|
||||
|
|
@ -2555,6 +2736,15 @@ packages:
|
|||
react-is: 17.0.2
|
||||
dev: false
|
||||
|
||||
/probe.gl/3.5.0:
|
||||
resolution: {integrity: sha512-KWj8u0PNytr/rVwcQFcN7O8SK7n/ITOsUZ91l4fSX95oHhKvVCI7eadrzFUzFRlXkFfBWpMWZXFHITsHHHUctw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.17.0
|
||||
'@probe.gl/env': 3.5.0
|
||||
'@probe.gl/log': 3.5.0
|
||||
'@probe.gl/stats': 3.5.0
|
||||
dev: false
|
||||
|
||||
/progress/2.0.3:
|
||||
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
|
@ -2689,11 +2879,23 @@ packages:
|
|||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/reflect-metadata/0.1.13:
|
||||
resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==}
|
||||
dev: false
|
||||
|
||||
/regenerator-runtime/0.13.9:
|
||||
resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==}
|
||||
dev: false
|
||||
|
||||
/regexpp/3.2.0:
|
||||
resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/regl/1.7.0:
|
||||
resolution: {integrity: sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w==}
|
||||
dev: false
|
||||
|
||||
/request-light/0.5.7:
|
||||
resolution: {integrity: sha512-i/wKzvcx7Er8tZnvqSxWuNO5ZGggu2UgZAqj/RyZ0si7lBTXL7kZiI/dWxzxnQjaY7s5HEy1qK21Do4Ncr6cVw==}
|
||||
dev: true
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ const props = {
|
|||
confirmLoading: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
},
|
||||
autoFocus: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,6 +79,7 @@ const Modal = defineComponent({
|
|||
v-model={[this.show, 'show']}
|
||||
class={styles.container}
|
||||
mask-closable={false}
|
||||
auto-focus={this.autoFocus}
|
||||
>
|
||||
<NCard title={this.title}>
|
||||
{{
|
||||
|
|
|
|||
|
|
@ -482,15 +482,19 @@ const project = {
|
|||
download_log: 'Download Log'
|
||||
},
|
||||
dag: {
|
||||
createWorkflow: 'Create Workflow',
|
||||
create: 'Create Workflow',
|
||||
search: 'Search',
|
||||
download_png: 'Download PNG',
|
||||
fullscreen_open: 'Open Fullscreen',
|
||||
fullscreen_close: 'Close Fullscreen',
|
||||
workflow_version: 'Workflow Version Info',
|
||||
save: 'Save',
|
||||
close: 'Close',
|
||||
format: 'Format'
|
||||
format: 'Format',
|
||||
layout_type: 'Layout Type',
|
||||
grid_layout: 'Grid',
|
||||
dagre_layout: 'Dagre',
|
||||
rows: 'Rows',
|
||||
cols: 'Cols'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -481,15 +481,19 @@ const project = {
|
|||
download_log: '下载日志'
|
||||
},
|
||||
dag: {
|
||||
createWorkflow: '创建工作流',
|
||||
create: '创建工作流',
|
||||
search: '搜索',
|
||||
download_png: '下载工作流图片',
|
||||
fullscreen_open: '全屏',
|
||||
fullscreen_close: '退出全屏',
|
||||
workflow_version: '工作流版本信息',
|
||||
save: '保存',
|
||||
close: '关闭',
|
||||
format: '格式化'
|
||||
format: '格式化',
|
||||
layout_type: '布局类型',
|
||||
grid_layout: '网格布局',
|
||||
dagre_layout: '层次布局',
|
||||
rows: '行数',
|
||||
cols: '列数'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineComponent, PropType, ref } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import Modal from '@/components/modal'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInputNumber,
|
||||
NRadioButton,
|
||||
NRadioGroup
|
||||
} from 'naive-ui'
|
||||
import { LAYOUT_TYPE } from './use-graph-auto-layout'
|
||||
import './x6-style.scss'
|
||||
|
||||
const props = {
|
||||
visible: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
},
|
||||
formValue: {
|
||||
type: Object as PropType<Ref<any>>,
|
||||
default: ref()
|
||||
},
|
||||
formRef: {
|
||||
type: Object as PropType<Ref<any>>,
|
||||
default: ref()
|
||||
},
|
||||
submit: {
|
||||
type: Function as PropType<() => void>,
|
||||
default: () => {}
|
||||
},
|
||||
cancel: {
|
||||
type: Function as PropType<() => void>,
|
||||
default: () => {}
|
||||
}
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'dag-format-modal',
|
||||
props,
|
||||
setup(props, context) {
|
||||
const { t } = useI18n()
|
||||
const { formValue, formRef, submit, cancel } = props
|
||||
|
||||
return () => (
|
||||
<Modal
|
||||
show={props.visible}
|
||||
title={t('project.dag.format')}
|
||||
onConfirm={submit}
|
||||
onCancel={cancel}
|
||||
autoFocus={false}
|
||||
>
|
||||
<NForm
|
||||
label-width='80'
|
||||
model={formValue.value}
|
||||
rules={{}}
|
||||
size='medium'
|
||||
label-placement='left'
|
||||
ref={formRef}
|
||||
>
|
||||
<NFormItem label={t('project.dag.layout_type')} path='type'>
|
||||
<NRadioGroup
|
||||
v-model={[formValue.value.type, 'value']}
|
||||
name='radiogroup'
|
||||
>
|
||||
<NRadioButton value={LAYOUT_TYPE.GRID}>
|
||||
{t('project.dag.grid_layout')}
|
||||
</NRadioButton>
|
||||
<NRadioButton value={LAYOUT_TYPE.DAGRE}>
|
||||
{t('project.dag.dagre_layout')}
|
||||
</NRadioButton>
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
{formValue.value.type === LAYOUT_TYPE.GRID ? (
|
||||
<NFormItem label={t('project.dag.rows')} path='rows'>
|
||||
<NInputNumber v-model={[formValue.value.rows, 'value']} min={0} />
|
||||
</NFormItem>
|
||||
) : null}
|
||||
{formValue.value.type === LAYOUT_TYPE.GRID ? (
|
||||
<NFormItem label={t('project.dag.cols')} path='cols'>
|
||||
<NInputNumber v-model={[formValue.value.cols, 'value']} min={0} />
|
||||
</NFormItem>
|
||||
) : null}
|
||||
</NForm>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
import { defineComponent, ref, inject } from 'vue'
|
||||
import Styles from './dag.module.scss'
|
||||
import type { PropType, Ref } from 'vue'
|
||||
import type { Dragged } from './dag'
|
||||
import type { Dragged } from './index'
|
||||
import { useCanvasInit, useCellActive, useCanvasDrop } from './dag-hooks'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import Modal from '@/components/modal'
|
||||
import './x6-style.scss'
|
||||
|
||||
const props = {
|
||||
show: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'dag-format-modal',
|
||||
props,
|
||||
setup(props, context) {
|
||||
return () => <Modal show={props.show}></Modal>
|
||||
}
|
||||
})
|
||||
|
|
@ -21,6 +21,7 @@ import { useCellActive } from './use-cell-active'
|
|||
import { useSidebarDrag } from './use-sidebar-drag'
|
||||
import { useCanvasDrop } from './use-canvas-drop'
|
||||
import { useNodeSearch } from './use-node-search'
|
||||
import { useGraphAutoLayout } from './use-graph-auto-layout'
|
||||
|
||||
export {
|
||||
useCanvasInit,
|
||||
|
|
@ -28,5 +29,6 @@ export {
|
|||
useCellActive,
|
||||
useSidebarDrag,
|
||||
useCanvasDrop,
|
||||
useNodeSearch
|
||||
useNodeSearch,
|
||||
useGraphAutoLayout
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,9 +57,10 @@ export default defineComponent({
|
|||
onDragstart={(e) => onDragStart(e, task.type)}
|
||||
>
|
||||
<em
|
||||
class={`${Styles['sidebar-icon']} ${
|
||||
class={[
|
||||
Styles['sidebar-icon'],
|
||||
Styles['icon-' + task.type.toLocaleLowerCase()]
|
||||
}`}
|
||||
]}
|
||||
></em>
|
||||
<span>{task.alias}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineComponent, ref, inject } from 'vue'
|
||||
import { defineComponent, ref, inject, PropType } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import Styles from './dag.module.scss'
|
||||
import { NTooltip, NIcon, NButton, NSelect } from 'naive-ui'
|
||||
|
|
@ -31,11 +31,23 @@ import { useNodeSearch } from './dag-hooks'
|
|||
import { DataUri } from '@antv/x6'
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useThemeStore } from '@/store/theme/theme'
|
||||
|
||||
const props = {
|
||||
layoutToggle: {
|
||||
type: Function as PropType<(bool?: boolean) => void>,
|
||||
default: () => {}
|
||||
}
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'workflow-dag-toolbar',
|
||||
props,
|
||||
setup(props, context) {
|
||||
const { t } = useI18n()
|
||||
|
||||
const themeStore = useThemeStore()
|
||||
|
||||
const graph = inject('graph', ref())
|
||||
const router = useRouter()
|
||||
|
||||
|
|
@ -88,11 +100,8 @@ export default defineComponent({
|
|||
/**
|
||||
* Open DAG format modal
|
||||
*/
|
||||
const { openFormatModal } = inject('formatModal', {
|
||||
openFormatModal: (bool: boolean) => {}
|
||||
})
|
||||
const onFormat = () => {
|
||||
openFormatModal(true)
|
||||
props.layoutToggle(true)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -103,10 +112,13 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return () => (
|
||||
<div class={Styles.toolbar}>
|
||||
<span class={Styles['workflow-name']}>
|
||||
{t('project.workflow.create_workflow')}
|
||||
</span>
|
||||
<div
|
||||
class={[
|
||||
Styles.toolbar,
|
||||
Styles[themeStore.darkTheme ? 'toolbar-dark' : 'toolbar-light']
|
||||
]}
|
||||
>
|
||||
<span class={Styles['workflow-name']}>{t('project.dag.create')}</span>
|
||||
<div class={Styles['toolbar-right-part']}>
|
||||
{/* Search node */}
|
||||
<NTooltip
|
||||
|
|
@ -128,7 +140,7 @@ export default defineComponent({
|
|||
}}
|
||||
/>
|
||||
),
|
||||
default: () => t('project.workflow.search')
|
||||
default: () => t('project.dag.search')
|
||||
}}
|
||||
></NTooltip>
|
||||
<div
|
||||
|
|
@ -164,7 +176,7 @@ export default defineComponent({
|
|||
}}
|
||||
/>
|
||||
),
|
||||
default: () => t('project.workflow.download_png')
|
||||
default: () => t('project.dag.download_png')
|
||||
}}
|
||||
></NTooltip>
|
||||
{/* Toggle fullscreen */}
|
||||
|
|
@ -193,8 +205,8 @@ export default defineComponent({
|
|||
),
|
||||
default: () =>
|
||||
isFullscreen.value
|
||||
? t('project.workflow.fullscreen_close')
|
||||
: t('project.workflow.fullscreen_open')
|
||||
? t('project.dag.fullscreen_close')
|
||||
: t('project.dag.fullscreen_open')
|
||||
}}
|
||||
></NTooltip>
|
||||
{/* DAG Format */}
|
||||
|
|
@ -217,7 +229,7 @@ export default defineComponent({
|
|||
}}
|
||||
/>
|
||||
),
|
||||
default: () => t('project.workflow.format')
|
||||
default: () => t('project.dag.format')
|
||||
}}
|
||||
></NTooltip>
|
||||
{/* Version info */}
|
||||
|
|
@ -240,7 +252,7 @@ export default defineComponent({
|
|||
}}
|
||||
/>
|
||||
),
|
||||
default: () => t('project.workflow.workflow_version')
|
||||
default: () => t('project.workflow.version_info')
|
||||
}}
|
||||
></NTooltip>
|
||||
{/* Save workflow */}
|
||||
|
|
@ -250,11 +262,11 @@ export default defineComponent({
|
|||
secondary
|
||||
round
|
||||
>
|
||||
{t('project.workflow.save')}
|
||||
{t('project.dag.save')}
|
||||
</NButton>
|
||||
{/* Return to previous page */}
|
||||
<NButton secondary round onClick={onClose}>
|
||||
{t('project.workflow.close')}
|
||||
{t('project.dag.close')}
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -19,8 +19,14 @@ $blue: #288fff;
|
|||
$blueBg: rgba(40, 143, 255, 0.1);
|
||||
$toolbarHeight: 50px;
|
||||
|
||||
$borderDark: rgba(255, 255, 255, 0.09);
|
||||
$borderLight: rgb(239, 239, 245);
|
||||
$bgDark: rgb(24, 24, 28);
|
||||
$bgLight: #ffffff;
|
||||
|
||||
.dag {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content {
|
||||
|
|
@ -34,17 +40,25 @@ $toolbarHeight: 50px;
|
|||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
border: 1px solid var(--n-border-color);
|
||||
border-radius: 4px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dag-dark .toolbar {
|
||||
border: 1px solid $borderDark;
|
||||
}
|
||||
|
||||
.dag-light .toolbar-light {
|
||||
border: 1px solid $borderLight;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.paper {
|
||||
|
|
@ -68,7 +82,6 @@ $toolbarHeight: 50px;
|
|||
height: 32px;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
border: 1px solid var(--n-border-color);
|
||||
padding: 0 10px;
|
||||
border-radius: 4px;
|
||||
transform: translate(0, 0);
|
||||
|
|
@ -83,109 +96,122 @@ $toolbarHeight: 50px;
|
|||
background-size: 100% 100%;
|
||||
margin-right: 10px;
|
||||
&.icon-shell {
|
||||
background-image: url('@/assets/images/task-icons/shell.png');
|
||||
background-image: url("@/assets/images/task-icons/shell.png");
|
||||
}
|
||||
&.icon-sub_process {
|
||||
background-image: url('@/assets/images/task-icons/sub_process.png');
|
||||
background-image: url("@/assets/images/task-icons/sub_process.png");
|
||||
}
|
||||
&.icon-procedure {
|
||||
background-image: url('@/assets/images/task-icons/procedure.png');
|
||||
background-image: url("@/assets/images/task-icons/procedure.png");
|
||||
}
|
||||
&.icon-sql {
|
||||
background-image: url('@/assets/images/task-icons/sql.png');
|
||||
background-image: url("@/assets/images/task-icons/sql.png");
|
||||
}
|
||||
&.icon-flink {
|
||||
background-image: url('@/assets/images/task-icons/flink.png');
|
||||
background-image: url("@/assets/images/task-icons/flink.png");
|
||||
}
|
||||
&.icon-mr {
|
||||
background-image: url('@/assets/images/task-icons/mr.png');
|
||||
background-image: url("@/assets/images/task-icons/mr.png");
|
||||
}
|
||||
&.icon-python {
|
||||
background-image: url('@/assets/images/task-icons/python.png');
|
||||
background-image: url("@/assets/images/task-icons/python.png");
|
||||
}
|
||||
&.icon-dependent {
|
||||
background-image: url('@/assets/images/task-icons/dependent.png');
|
||||
background-image: url("@/assets/images/task-icons/dependent.png");
|
||||
}
|
||||
&.icon-http {
|
||||
background-image: url('@/assets/images/task-icons/http.png');
|
||||
background-image: url("@/assets/images/task-icons/http.png");
|
||||
}
|
||||
&.icon-datax {
|
||||
background-image: url('@/assets/images/task-icons/datax.png');
|
||||
background-image: url("@/assets/images/task-icons/datax.png");
|
||||
}
|
||||
&.icon-pigeon {
|
||||
background-image: url('@/assets/images/task-icons/pigeon.png');
|
||||
background-image: url("@/assets/images/task-icons/pigeon.png");
|
||||
}
|
||||
&.icon-sqoop {
|
||||
background-image: url('@/assets/images/task-icons/sqoop.png');
|
||||
background-image: url("@/assets/images/task-icons/sqoop.png");
|
||||
}
|
||||
&.icon-conditions {
|
||||
background-image: url('@/assets/images/task-icons/conditions.png');
|
||||
background-image: url("@/assets/images/task-icons/conditions.png");
|
||||
}
|
||||
&.icon-seatunnel {
|
||||
background-image: url('@/assets/images/task-icons/seatunnel.png');
|
||||
background-image: url("@/assets/images/task-icons/seatunnel.png");
|
||||
}
|
||||
&.icon-spark {
|
||||
background-image: url('@/assets/images/task-icons/spark.png');
|
||||
background-image: url("@/assets/images/task-icons/spark.png");
|
||||
}
|
||||
&.icon-switch {
|
||||
background-image: url('@/assets/images/task-icons/switch.png');
|
||||
background-image: url("@/assets/images/task-icons/switch.png");
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.sidebar-icon {
|
||||
&.icon-shell {
|
||||
background-image: url("@/assets/images/task-icons/shell_hover.png");
|
||||
}
|
||||
&.icon-sub_process {
|
||||
background-image: url("@/assets/images/task-icons/sub_process_hover.png");
|
||||
}
|
||||
&.icon-procedure {
|
||||
background-image: url("@/assets/images/task-icons/procedure_hover.png");
|
||||
}
|
||||
&.icon-sql {
|
||||
background-image: url("@/assets/images/task-icons/sql_hover.png");
|
||||
}
|
||||
&.icon-flink {
|
||||
background-image: url("@/assets/images/task-icons/flink_hover.png");
|
||||
}
|
||||
&.icon-mr {
|
||||
background-image: url("@/assets/images/task-icons/mr_hover.png");
|
||||
}
|
||||
&.icon-python {
|
||||
background-image: url("@/assets/images/task-icons/python_hover.png");
|
||||
}
|
||||
&.icon-dependent {
|
||||
background-image: url("@/assets/images/task-icons/dependent_hover.png");
|
||||
}
|
||||
&.icon-http {
|
||||
background-image: url("@/assets/images/task-icons/http_hover.png");
|
||||
}
|
||||
&.icon-datax {
|
||||
background-image: url("@/assets/images/task-icons/datax_hover.png");
|
||||
}
|
||||
&.icon-pigeon {
|
||||
background-image: url("@/assets/images/task-icons/pigeon_hover.png");
|
||||
}
|
||||
&.icon-sqoop {
|
||||
background-image: url("@/assets/images/task-icons/sqoop_hover.png");
|
||||
}
|
||||
&.icon-conditions {
|
||||
background-image: url("@/assets/images/task-icons/conditions_hover.png");
|
||||
}
|
||||
&.icon-seatunnel {
|
||||
background-image: url("@/assets/images/task-icons/seatunnel_hover.png");
|
||||
}
|
||||
&.icon-spark {
|
||||
background-image: url("@/assets/images/task-icons/spark_hover.png");
|
||||
}
|
||||
&.icon-switch {
|
||||
background-image: url("@/assets/images/task-icons/switch_hover.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dag-dark .draggable {
|
||||
border: 1px solid $borderDark;
|
||||
}
|
||||
|
||||
.dag-light .draggable {
|
||||
border: 1px solid $borderLight;
|
||||
}
|
||||
|
||||
.dag .draggable {
|
||||
&:hover {
|
||||
color: $blue;
|
||||
border: 1px dashed $blue;
|
||||
background-color: $blueBg;
|
||||
.sidebar-icon {
|
||||
&.icon-shell {
|
||||
background-image: url('@/assets/images/task-icons/shell_hover.png');
|
||||
}
|
||||
&.icon-sub_process {
|
||||
background-image: url('@/assets/images/task-icons/sub_process_hover.png');
|
||||
}
|
||||
&.icon-procedure {
|
||||
background-image: url('@/assets/images/task-icons/procedure_hover.png');
|
||||
}
|
||||
&.icon-sql {
|
||||
background-image: url('@/assets/images/task-icons/sql_hover.png');
|
||||
}
|
||||
&.icon-flink {
|
||||
background-image: url('@/assets/images/task-icons/flink_hover.png');
|
||||
}
|
||||
&.icon-mr {
|
||||
background-image: url('@/assets/images/task-icons/mr_hover.png');
|
||||
}
|
||||
&.icon-python {
|
||||
background-image: url('@/assets/images/task-icons/python_hover.png');
|
||||
}
|
||||
&.icon-dependent {
|
||||
background-image: url('@/assets/images/task-icons/dependent_hover.png');
|
||||
}
|
||||
&.icon-http {
|
||||
background-image: url('@/assets/images/task-icons/http_hover.png');
|
||||
}
|
||||
&.icon-datax {
|
||||
background-image: url('@/assets/images/task-icons/datax_hover.png');
|
||||
}
|
||||
&.icon-pigeon {
|
||||
background-image: url('@/assets/images/task-icons/pigeon_hover.png');
|
||||
}
|
||||
&.icon-sqoop {
|
||||
background-image: url('@/assets/images/task-icons/sqoop_hover.png');
|
||||
}
|
||||
&.icon-conditions {
|
||||
background-image: url('@/assets/images/task-icons/conditions_hover.png');
|
||||
}
|
||||
&.icon-seatunnel {
|
||||
background-image: url('@/assets/images/task-icons/seatunnel_hover.png');
|
||||
}
|
||||
&.icon-spark {
|
||||
background-image: url('@/assets/images/task-icons/spark_hover.png');
|
||||
}
|
||||
&.icon-switch {
|
||||
background-image: url('@/assets/images/task-icons/switch_hover.png');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ import DagToolbar from './dag-toolbar'
|
|||
import DagCanvas from './dag-canvas'
|
||||
import DagSidebar from './dag-sidebar'
|
||||
import Styles from './dag.module.scss'
|
||||
import DagFormatModal from './dag-format-modal'
|
||||
import DagAutoLayoutModal from './dag-auto-layout-modal'
|
||||
import { useGraphAutoLayout } from './dag-hooks'
|
||||
import { useThemeStore } from '@/store/theme/theme'
|
||||
import './x6-style.scss'
|
||||
|
||||
export interface Dragged {
|
||||
|
|
@ -33,6 +35,8 @@ export interface Dragged {
|
|||
export default defineComponent({
|
||||
name: 'workflow-dag',
|
||||
setup(props, context) {
|
||||
const theme = useThemeStore()
|
||||
|
||||
// Whether the graph can be operated
|
||||
const readonly = ref(false)
|
||||
provide('readonly', readonly)
|
||||
|
|
@ -53,24 +57,35 @@ export default defineComponent({
|
|||
type: ''
|
||||
})
|
||||
|
||||
// Dag format modal visible
|
||||
const formatModalVisible = ref<boolean>(false)
|
||||
const openFormatModal = (bool: boolean) => {
|
||||
formatModalVisible.value = bool
|
||||
}
|
||||
provide('formatModal', {
|
||||
openFormatModal,
|
||||
formatModalVisible
|
||||
})
|
||||
// Auto layout
|
||||
const {
|
||||
visible: layoutVisible,
|
||||
toggle: layoutToggle,
|
||||
formValue,
|
||||
formRef,
|
||||
submit,
|
||||
cancel
|
||||
} = useGraphAutoLayout({ graph })
|
||||
|
||||
return () => (
|
||||
<div class={Styles.dag}>
|
||||
<DagToolbar v-slots={toolbarSlots} />
|
||||
<div
|
||||
class={[
|
||||
Styles.dag,
|
||||
Styles[`dag-${theme.darkTheme ? 'dark' : 'light'}`]
|
||||
]}
|
||||
>
|
||||
<DagToolbar v-slots={toolbarSlots} layoutToggle={layoutToggle} />
|
||||
<div class={Styles.content}>
|
||||
<DagSidebar dragged={dragged} />
|
||||
<DagCanvas dragged={dragged} />
|
||||
</div>
|
||||
<DagFormatModal show={formatModalVisible.value} />
|
||||
<DagAutoLayoutModal
|
||||
visible={layoutVisible.value}
|
||||
submit={submit}
|
||||
cancel={cancel}
|
||||
formValue={formValue}
|
||||
formRef={formRef}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { ref, onMounted, Ref, onUnmounted } from 'vue'
|
|||
import { Graph } from '@antv/x6'
|
||||
import { NODE, EDGE, X6_NODE_NAME, X6_EDGE_NAME } from './dag-config'
|
||||
import { debounce } from 'lodash'
|
||||
import { useResizeObserver } from '@vueuse/core'
|
||||
|
||||
interface Options {
|
||||
readonly: Ref<boolean>
|
||||
|
|
@ -136,18 +137,14 @@ export function useCanvasInit(options: Options) {
|
|||
/**
|
||||
* Redraw when the page is resized
|
||||
*/
|
||||
const paperResize = debounce(() => {
|
||||
if (!container.value) return
|
||||
const w = container.value.offsetWidth
|
||||
const h = container.value.offsetHeight
|
||||
graph.value?.resize(w, h)
|
||||
const resize = debounce(() => {
|
||||
if (container.value && true) {
|
||||
const w = container.value.offsetWidth
|
||||
const h = container.value.offsetHeight
|
||||
graph.value?.resize(w, h)
|
||||
}
|
||||
}, 200)
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', paperResize)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', paperResize)
|
||||
})
|
||||
useResizeObserver(container, resize)
|
||||
|
||||
/**
|
||||
* Register custom cells
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ref, Ref } from 'vue'
|
||||
import type { Graph } from '@antv/x6'
|
||||
import { DagreLayout, GridLayout } from '@antv/layout'
|
||||
import _ from 'lodash'
|
||||
import { X6_NODE_NAME, X6_EDGE_NAME } from './dag-config'
|
||||
|
||||
interface Options {
|
||||
graph: Ref<Graph | undefined>
|
||||
}
|
||||
|
||||
interface LayoutConfig {
|
||||
cols: number
|
||||
nodesep: number
|
||||
padding: number
|
||||
ranksep: number
|
||||
rows: number
|
||||
type: LAYOUT_TYPE
|
||||
}
|
||||
|
||||
export enum LAYOUT_TYPE {
|
||||
GRID = 'grid',
|
||||
DAGRE = 'dagre'
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto layout graph
|
||||
* 1. Manage the state of auto layout popups
|
||||
* 2. Implement graph automatic layout function
|
||||
*/
|
||||
export function useGraphAutoLayout(options: Options) {
|
||||
const DEFAULT_LAYOUT_CONFIG: LayoutConfig = {
|
||||
cols: 0,
|
||||
nodesep: 50,
|
||||
padding: 50,
|
||||
ranksep: 50,
|
||||
rows: 0,
|
||||
type: LAYOUT_TYPE.DAGRE
|
||||
}
|
||||
|
||||
const { graph: graphRef } = options
|
||||
|
||||
// Auto layout config form ref
|
||||
const formRef = ref()
|
||||
|
||||
// Auto layout config form value
|
||||
const formValue = ref({
|
||||
...DEFAULT_LAYOUT_CONFIG
|
||||
})
|
||||
|
||||
// Dag format modal visible
|
||||
const visible = ref<boolean>(false)
|
||||
const toggle = (bool?: boolean) => {
|
||||
if (typeof bool === 'boolean') {
|
||||
visible.value = bool
|
||||
} else {
|
||||
visible.value = !visible.value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto layout graph
|
||||
* @param layoutConfig
|
||||
* @returns
|
||||
*/
|
||||
function format(layoutConfig: LayoutConfig) {
|
||||
if (!layoutConfig) {
|
||||
layoutConfig = DEFAULT_LAYOUT_CONFIG
|
||||
}
|
||||
const graph = graphRef?.value
|
||||
if (!graph) {
|
||||
return
|
||||
}
|
||||
|
||||
graph.cleanSelection()
|
||||
|
||||
let layoutFunc = null
|
||||
if (layoutConfig.type === LAYOUT_TYPE.DAGRE) {
|
||||
layoutFunc = new DagreLayout({
|
||||
type: LAYOUT_TYPE.DAGRE,
|
||||
rankdir: 'LR',
|
||||
align: 'UL',
|
||||
// Calculate the node spacing based on the edge label length
|
||||
ranksepFunc: (d) => {
|
||||
const edges = graph.getOutgoingEdges(d.id)
|
||||
let max = 0
|
||||
if (edges && edges.length > 0) {
|
||||
edges.forEach((edge) => {
|
||||
const edgeView = graph.findViewByCell(edge)
|
||||
const labelView = edgeView?.findAttr(
|
||||
'width',
|
||||
_.get(edgeView, ['labelSelectors', '0', 'body'], null)
|
||||
)
|
||||
const labelWidth = labelView ? +labelView : 0
|
||||
max = Math.max(max, labelWidth)
|
||||
})
|
||||
}
|
||||
return layoutConfig.ranksep + max
|
||||
},
|
||||
nodesep: layoutConfig.nodesep,
|
||||
controlPoints: true
|
||||
})
|
||||
} else if (layoutConfig.type === LAYOUT_TYPE.GRID) {
|
||||
layoutFunc = new GridLayout({
|
||||
type: LAYOUT_TYPE.GRID,
|
||||
preventOverlap: true,
|
||||
preventOverlapPadding: layoutConfig.padding,
|
||||
sortBy: '_index',
|
||||
rows: layoutConfig.rows || undefined,
|
||||
cols: layoutConfig.cols || undefined,
|
||||
nodeSize: 220
|
||||
})
|
||||
}
|
||||
const json = graph.toJSON()
|
||||
const nodes = json.cells
|
||||
.filter((cell) => cell.shape === X6_NODE_NAME)
|
||||
.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
// sort by code aesc
|
||||
_index: -(item.id as string)
|
||||
}
|
||||
})
|
||||
const edges = json.cells.filter((cell) => cell.shape === X6_EDGE_NAME)
|
||||
const newModel: any = layoutFunc?.layout({
|
||||
nodes: nodes,
|
||||
edges: edges
|
||||
} as any)
|
||||
graph.fromJSON(newModel)
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto layout modal submit
|
||||
*/
|
||||
function submit() {
|
||||
if (formRef.value) {
|
||||
formRef.value.validate((errors: unknown) => {
|
||||
if (errors) return
|
||||
format(formValue.value)
|
||||
toggle(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto layout modal cancel
|
||||
*/
|
||||
function cancel() {
|
||||
toggle(false)
|
||||
}
|
||||
|
||||
return {
|
||||
format,
|
||||
toggle,
|
||||
visible,
|
||||
formRef,
|
||||
formValue,
|
||||
cancel,
|
||||
submit
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,26 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
$borderDark: rgba(255, 255, 255, 0.09);
|
||||
$borderLight: rgb(239, 239, 245);
|
||||
$bgDark: rgb(24, 24, 28);
|
||||
$bgLight: #ffffff;
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
height: calc(100vh - 100px);
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dark {
|
||||
border: solid 1px $borderDark;
|
||||
background-color: $bgDark;
|
||||
}
|
||||
|
||||
.light {
|
||||
border: solid 1px $borderLight;
|
||||
background-color: $bgLight;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,21 +17,28 @@
|
|||
|
||||
import { defineComponent } from 'vue'
|
||||
import Dag from '../../components/dag'
|
||||
import { NCard } from 'naive-ui'
|
||||
import styles from './index.module.scss'
|
||||
import { useThemeStore } from '@/store/theme/theme'
|
||||
import Styles from './index.module.scss'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'WorkflowDefinitionCreate',
|
||||
setup() {
|
||||
const theme = useThemeStore()
|
||||
|
||||
const slots = {
|
||||
toolbarLeft: () => <span>left-operations</span>,
|
||||
toolbarRight: () => <span>right-operations</span>
|
||||
}
|
||||
|
||||
return () => (
|
||||
<NCard class={styles.container}>
|
||||
<div
|
||||
class={[
|
||||
Styles.container,
|
||||
theme.darkTheme ? Styles['dark'] : Styles['light']
|
||||
]}
|
||||
>
|
||||
<Dag v-slots={slots} />
|
||||
</NCard>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue