From 45f6c4197b03566895008577de964f0e5f1c80c8 Mon Sep 17 00:00:00 2001 From: wangyizhi Date: Wed, 19 Jan 2022 18:46:54 +0800 Subject: [PATCH] [Feature][UI Next] Workflow create (#8123) --- dolphinscheduler-ui-next/package.json | 1 + dolphinscheduler-ui-next/pnpm-lock.yaml | 30 ++ .../assets/images/task-icons/conditions.png | Bin 0 -> 812 bytes .../images/task-icons/conditions_hover.png | Bin 0 -> 736 bytes .../src/assets/images/task-icons/datax.png | Bin 0 -> 1122 bytes .../assets/images/task-icons/datax_hover.png | Bin 0 -> 1127 bytes .../assets/images/task-icons/dependent.png | Bin 0 -> 743 bytes .../images/task-icons/dependent_hover.png | Bin 0 -> 745 bytes .../src/assets/images/task-icons/flink.png | Bin 0 -> 1443 bytes .../assets/images/task-icons/flink_hover.png | Bin 0 -> 1348 bytes .../src/assets/images/task-icons/http.png | Bin 0 -> 707 bytes .../assets/images/task-icons/http_hover.png | Bin 0 -> 709 bytes .../src/assets/images/task-icons/mr.png | Bin 0 -> 930 bytes .../src/assets/images/task-icons/mr_hover.png | Bin 0 -> 862 bytes .../src/assets/images/task-icons/pigeon.png | Bin 0 -> 1192 bytes .../assets/images/task-icons/pigeon_hover.png | Bin 0 -> 1167 bytes .../assets/images/task-icons/procedure.png | Bin 0 -> 1555 bytes .../images/task-icons/procedure_hover.png | Bin 0 -> 1436 bytes .../src/assets/images/task-icons/python.png | Bin 0 -> 1618 bytes .../assets/images/task-icons/python_hover.png | Bin 0 -> 1233 bytes .../assets/images/task-icons/seatunnel.png | Bin 0 -> 1086 bytes .../images/task-icons/seatunnel_hover.png | Bin 0 -> 1054 bytes .../src/assets/images/task-icons/shell.png | Bin 0 -> 747 bytes .../assets/images/task-icons/shell_hover.png | Bin 0 -> 745 bytes .../src/assets/images/task-icons/spark.png | Bin 0 -> 1067 bytes .../assets/images/task-icons/spark_hover.png | Bin 0 -> 1066 bytes .../src/assets/images/task-icons/sql.png | Bin 0 -> 1317 bytes .../assets/images/task-icons/sql_hover.png | Bin 0 -> 1262 bytes .../src/assets/images/task-icons/sqoop.png | Bin 0 -> 896 bytes .../assets/images/task-icons/sqoop_hover.png | Bin 0 -> 897 bytes .../assets/images/task-icons/sub_process.png | Bin 0 -> 692 bytes .../images/task-icons/sub_process_hover.png | Bin 0 -> 693 bytes .../src/assets/images/task-icons/switch.png | Bin 0 -> 885 bytes .../assets/images/task-icons/switch_hover.png | Bin 0 -> 825 bytes .../src/locales/modules/en_US.ts | 11 + .../src/locales/modules/zh_CN.ts | 11 + .../src/router/modules/projects.ts | 16 + .../service/modules/task-definition/index.ts | 13 +- .../service/modules/task-definition/types.ts | 4 - dolphinscheduler-ui-next/src/utils/index.ts | 4 +- .../src/utils/truncate-text.ts | 51 +++ .../src/views/projects/index.tsx | 27 ++ .../src/views/projects/task/config.ts | 67 ++++ .../src/views/projects/task/task-config.tsx | 27 ++ .../views/projects/workflow/dag-canvas.tsx | 60 ++++ .../src/views/projects/workflow/dag-config.ts | 339 ++++++++++++++++++ .../src/views/projects/workflow/dag-hooks.ts | 32 ++ .../views/projects/workflow/dag-sidebar.tsx | 68 ++++ .../views/projects/workflow/dag-toolbar.tsx | 180 ++++++++++ .../views/projects/workflow/dag.module.scss | 217 +++++++++++ .../src/views/projects/workflow/dag.tsx | 67 ++++ .../src/views/projects/workflow/hook-demo.ts | 40 +++ .../projects/workflow/use-canvas-drop.ts | 70 ++++ .../projects/workflow/use-canvas-init.ts | 177 +++++++++ .../projects/workflow/use-cell-active.ts | 154 ++++++++ .../projects/workflow/use-graph-operations.ts | 157 ++++++++ .../projects/workflow/use-node-search.ts | 60 ++++ .../projects/workflow/use-sidebar-drag.ts | 48 +++ .../workflow-definition-create.module.scss | 22 ++ .../workflow/workflow-definition-create.tsx | 38 ++ .../workflow/workflow-definition-details.tsx | 27 ++ .../workflow/workflow-definition-list.tsx | 27 ++ .../workflow/workflow-instance-details.tsx | 27 ++ .../workflow/workflow-instance-list.tsx | 27 ++ .../src/views/projects/workflow/x6-style.scss | 35 ++ 65 files changed, 2123 insertions(+), 11 deletions(-) create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/conditions.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/conditions_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/datax.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/datax_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/dependent.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/dependent_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/flink.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/flink_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/http.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/http_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/mr.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/mr_hover.png create mode 100644 dolphinscheduler-ui-next/src/assets/images/task-icons/pigeon.png create mode 100644 dolphinscheduler-ui-next/src/assets/images/task-icons/pigeon_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/procedure.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/procedure_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/python.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/python_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/seatunnel.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/seatunnel_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/shell.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/shell_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/spark.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/spark_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/sql.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/sql_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/sqoop.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/sqoop_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/sub_process.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/sub_process_hover.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/switch.png create mode 100755 dolphinscheduler-ui-next/src/assets/images/task-icons/switch_hover.png create mode 100644 dolphinscheduler-ui-next/src/utils/truncate-text.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/index.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/task/config.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/task/task-config.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/dag-canvas.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/dag-config.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/dag-hooks.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/dag-sidebar.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/dag-toolbar.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/dag.module.scss create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/dag.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/hook-demo.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-drop.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-init.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/use-cell-active.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/use-graph-operations.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/use-node-search.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/use-sidebar-drag.ts create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.module.scss create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-details.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-list.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-details.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-list.tsx create mode 100644 dolphinscheduler-ui-next/src/views/projects/workflow/x6-style.scss diff --git a/dolphinscheduler-ui-next/package.json b/dolphinscheduler-ui-next/package.json index c56b683b08..941d81f91a 100644 --- a/dolphinscheduler-ui-next/package.json +++ b/dolphinscheduler-ui-next/package.json @@ -10,6 +10,7 @@ "prettier": "prettier --write \"src/**/*.{vue,ts,tsx}\"" }, "dependencies": { + "@antv/x6": "^1.29.5", "@vueuse/core": "^7.5.3", "axios": "^0.24.0", "date-fns": "^2.27.0", diff --git a/dolphinscheduler-ui-next/pnpm-lock.yaml b/dolphinscheduler-ui-next/pnpm-lock.yaml index 142dc18c5f..e446f5a95d 100644 --- a/dolphinscheduler-ui-next/pnpm-lock.yaml +++ b/dolphinscheduler-ui-next/pnpm-lock.yaml @@ -18,6 +18,7 @@ lockfileVersion: 5.3 specifiers: + '@antv/x6': ^1.29.5 '@types/node': ^16.11.19 '@types/nprogress': ^0.2.0 '@types/qs': ^6.9.7 @@ -56,6 +57,7 @@ specifiers: vue-tsc: ^0.28.10 dependencies: + '@antv/x6': 1.29.5 '@vueuse/core': 7.5.3_vue@3.2.26 axios: 0.24.0 date-fns: 2.28.0 @@ -96,6 +98,18 @@ devDependencies: vue-tsc: 0.28.10_typescript@4.5.4 packages: + + /@antv/x6/1.29.5: + resolution: {integrity: sha512-U5gg40jo+UtzjdX/7QFenVZgGKOtDFDo60AMNGEvIEzGnixV+2zV0EBJ2f8We4Fp1ZVP0G2pm6uS7ajuuuLsvg==} + dependencies: + csstype: 3.0.10 + jquery: 3.6.0 + jquery-mousewheel: 3.1.13 + lodash-es: 4.17.21 + mousetrap: 1.6.5 + utility-types: 3.10.0 + dev: false + /@babel/code-frame/7.16.7: resolution: { @@ -2792,6 +2806,14 @@ packages: engines: { node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0 } dev: false + /jquery-mousewheel/3.1.13: + resolution: {integrity: sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU=} + dev: false + + /jquery/3.6.0: + resolution: {integrity: sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==} + dev: false + /js-stringify/1.0.2: resolution: { integrity: sha1-Fzb939lyTyijaCrcYjCufk6Weds= } dev: true @@ -3064,6 +3086,9 @@ packages: { integrity: sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q== } + + /mousetrap/1.6.5: + resolution: {integrity: sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==} dev: false /ms/2.0.0: @@ -4117,6 +4142,11 @@ packages: deprecated: Please see https://github.com/lydell/urix#deprecated dev: true + /utility-types/3.10.0: + resolution: {integrity: sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==} + engines: {node: '>= 4'} + dev: false + /v8-compile-cache/2.3.0: resolution: { diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/conditions.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/conditions.png new file mode 100755 index 0000000000000000000000000000000000000000..08499643105d15b850192c22fd7640ceefe9c0b5 GIT binary patch literal 812 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9Wb+01gt!6) z|NsBLYSpU!`}fbEKY!-TnLzg3xpNmTTnJ>(n>P<42xQEeGY2RRVa%RAd)BO3$Rtn} zs2(T+B!N;8SqK+MLKtvyAOoTdO$%Hcq7tqK!i5V0#UWA<^~hYf2wX9;2t*~a-WfAy z02NH1J{`yaiXU0{WEC((!b^huf*F{YSva_Oc!fnoB_x$p)U|Z<42(@Jtn3_}-24JV zBBNpwGjsC`O3KPBDynN5J9~O3%$PZA-uxvi*R9{a^T5$#H*Vc~{Pfw&S8w0F|M2lG{`vdwU&5mJmB7Hy^mK6yk&rxl@MYNL0EX6!lMTd}M0ARsCoa@5zG9@&EFf|! zM#H@3{eLAh^TPL z3Yb?J^!b#rPgcavES0QN*MAGY-V!dmL;JbD{&Vds4!oTs|Wf5W@eUKPCWt}TDom+0OpYcX$j)c(Z}HMhAJ`{e%K z;+E38hTJb4PYRIJGM^dg8qFeJ6gM zD(+XheMjqCbKCN5z7o?-`DSN*UiWid#755t;$6GjoK^V@cOPw%zo4VFF=azjlTa(e zX&p^dS%zizmWRaOWjMIyUV)m{Q^!=EY1+bl|Dx*|6pK@zt_oy$1dLY(Pgg&ebxsLQ E0LSo^asU7T literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/conditions_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/conditions_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..a0c4551be3b1cb57770291892781f901924421e3 GIT binary patch literal 736 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(f`ybbUPaRt($ ztNv@P`tLdEzwylfdW-&B&;4&c>A&9e|Av$Q>rel$GxfjLg#UVz|Lacsuhaiud(wa1 z$^UgG{MYLLuQBnz22f-&NP)(r|JoD(Yfk#F36uhh0|kK$tw|tRO`r&n4b%cu2~^e( zLLd>K6c_=;L2RHnm;@< z`;`Rw1v4@}85mny+t@q0xcUc$hDFE3#wVnvWfl|_*EF}b zclJ-1IBE9MWy{xZ-g)x$nG26!z5Vd%^Ve_RfBgFM_wT=uOrI^l;C1(OaSX9IeRWb~ z@F53*7H5Zm#sU_RKt9KJ-cR;%wiO)x_uu~bgj7z?HN2twGWMSdxgH*EeED=?z2nV| zD!rTe1ngVZDV{$v%VOopMSrTh-u~s$>D_#ZXH8myDcdx|4Lr=;E2ac7uaS)s$u{JF zBqx~lq|BnAuE@gY)49x}4HDn0-#q*IbOl$y#o6lj{X<>}i>(bRdsW9f`&zl#8_`#f z*Lw2DS8Ps9)d=%;yxDejRQTx~(hI uG@prxoSoG*ZAVMWomrVSng#zI?q8o5J?r-OUCV%x#o+1c=d#Wzp$PySj9obZ literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/datax.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/datax.png new file mode 100755 index 0000000000000000000000000000000000000000..22519a98ece13402d382accfb5d415f6e357699c GIT binary patch literal 1122 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9WM2>P32_Aq z{s)6qt5)sbzklY;nLx(2ZQFq4qD6~<NV6rVqT{?esO=ggV2aN$BAciy~t zKn1gB&xS|=89)&r8>nE`tXV)^KsH1cNCLS)L5K*P4N(bE1C)gWh&V(sL=dP3$N-8! zxDW<}eDmfFL<+)%sDzN8KYxZW&~#y%0~Em&gcu7nf7h;E5ECFGK=Q(c3y&T>f(ydM zfrcDAb_{G7!l^*+yLay(YK|T~3YP^kfP$MhZw4|>o;(R;uU)%#$BrFWuU-YRA%Tgk zc=6)J5G@e$)2B}mWxz-QiU4B=r~nvWKm%{zzI~b@{U0!Dr{h>FR`DJUu_tEj1KXzJ?e8<<;ITG`myJ2<+yd;0kL1%yXL$Hc}bq^4)& zQco3`%UwP)}CLx+zXIdbyUne!K} zT)lez#?9Mz?%#j#=+U$1FJ8WS_4>`*x9{G)fB)g*=PzHs{rLIo&!2z){ymGn7X?g( z(>z@qLnI{69{d^K%_wu=_VrWUY5SDzovQA>-w&5h{4jgtIp@rzob>7mJ9a)RF}(0)s>*x+ zQ*M26L0fLCdLFZ2%e$r8m@D8cJLy1kXI1BE-o&J1n%PwbSG88h1p2VbEXqFO)cayj z#0#-lfh)|R>CPF`>J~{_`QDYCA#&C%!KEd2dzD`Z1kk*fLX8yaLTIVK}@XfV*c3|ZxuH{Ek7*`!y zYx90zu%5j#@1LrIEw|2g{(auKAR{MnM$o+L*S5~-6!}?M{r~v;Vw2tRX}`AlH~W_e zFPJt}{{M~b&p&MR{}WmBH8nr=?b2*Hy_j~#ia&o@P(Y-l04_G>E%DA59Sz6G;a#%HK&7)VwNsEN% lC2icGx_;4>scQfCr#^kq?9r4TWCTn^44$rjF6*2UngC>MUu^&Y literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/datax_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/datax_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..986470d99396c527b655b271dc9926b92aecb96e GIT binary patch literal 1127 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(eb-wN;vaRmzg z|Np$(5UC;j(a0+KT5|F1jkzxJH} z8dE@A!%6@3rvKNQ^j~WNNJ?)qNLFXkf9rVc!1JnW}C;Zn2D(eTS)SUER zqyN9oL@;~8e~n2XHQEzF;@T5HYBa!#fo#qG|C&G&s1j@ikf8x&gB1YH(E@V8L7>SX5{SU&KmG`n0vZKW4>Ap`9d0s6B}4=$g~W!4L)2e?^*?trOc~foKrM65 z{6F*nY8p^6L@&hH)&pP%fbD{a02SPN3-(U`f1oVXc9?ast3ihM907?3FZ-Xh>HqSJ zAOnr2z$}FrHQ~R_OpwWNGl9MXa*d|`w+F^Z|9|7D|7~ae_g?fre$D?)*Z;pPPE`iR z?u?QkzhDMNCT12^Hg-;K9$r2^egQ!tVG&U=894<-C1n*gbq!5jJ$(an3ri~-J9`I5 z7k5t|U%!Cxi0GKu_=ME-jGWxu{KDeOs=E5d#+HuG-u?*_r%azaZ^_aXt5&aBzj4#n zoxAqz-GAutkt0V=o;q{>!j-F6uivw_WZ@mSFc{bdHeR=yZ7%ueEj_7 z>$e|2fBpIM@87>&+y^y*DRH`|i(`m{eox2NV4tzX6uk$3w(y202^S00O5wwib zny7N>>XQuDqj##J)?G+5d;IoA{nT5VzioNGyY5r-b?<+syM3oUT=7<}PO{rh{?)C? zs#?<4hgE#HuMzWBw@do;YQmD@FO!yC*7HvJy|Lh|p4zrLow?$|`dqw|7AZ6xni4Gb zb-@)i&vh1FitQ486CKw|)TCU{Z8Labx_g$=ncqL>R)+Tn)N{M3CdwKtynDaA>&J45 zJ$3voN-dv$eOhdw%Xze6oneGga9r%4%5P_G&F+~h61zzEw@$IlrUfDwO#l204xbmw zBAL-r-XCqtbIPK4&L#!^3#RMDe{GX3W0lN!a(wUK-L^7!?(wv!9u#Zkd^>UXzONZ; zOipy~zF#N1{OISDT7`5WrX&f*y^A)zJNs0(nt#vJ@7I^hZwuS)KmT*lC#5gl2ff*N zlQf)lr)hg`4}3Mzb?S;5%?ToVHMV%KGUea!BwA5zw)#ea8w%bcy_24uQ}cZM=CDp( z;?jtlmM&e=sf&WHew?uXk@7v+Nf%cgT2&N2?T`CE1`*3Plbx&$)xc!L;OXk;vd$@? F2>??8O_Bfr literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/dependent.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/dependent.png new file mode 100755 index 0000000000000000000000000000000000000000..3f0b732c40e09b36d93088ad9405cce00c4aa7c5 GIT binary patch literal 743 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9Wb+01gt!6) z|NsBLZQHh0t5(gNIdjpXML=@?{P}a{%mFgy&6@{g&z(CL$N+MIg0pAOhOmL+K#^Iq zWD#DXVH|>*yMqncLYr zxOn*Z`uT^1N5#e^BEak-ar)||Oyk1=A`K6NwLEfE%eGz>i(0#A>y(JD zs9gf5e*Uj_Ij34Q{qjq89Ge7oh8x#}jLz8Zb)`5MUl zb^gOeEgq)9QnPXu6i<6Otnt!1wQr$A5vyqH;uY6~r&@{k>z>f=a67uw{L#k63zeVB z?YLY#WwGK1CP~-qO9DRkF2BEE3c zJk|M`V-nv1?P=c^uaa5x>Qtskg~{gdp3{;0ckWxX^zFxYFM{R-Ur`J*^4Y#aZ=vs# nY<~}piMv-B#il&C|DDr+b;W}NSNmrGqlCfJ)z4*}Q$iB}Is$o6 literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/dependent_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/dependent_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..4b4b8669f940a2950f18c4afc76cc6feaf64d0c8 GIT binary patch literal 745 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(eb^9A^XxB>A&Tw|Hd=_>n#G22L1oF=YSZ7lm2T>{ckw=zs}VES`+?jPWi7l`M>V8|2mWY zYfk*HJNduX6c_`j5{Q6mCj8f!^k1j{zviU>+7th4O!%)2WK8(4H4(%B$^r#}dVvfr zpc)_v)Y1=<1+szSK=lw=4WKLp0R_P-K~nutHi!Y{f^>n|KrU1ZkO33~Be)unEKCF; z3pN&6d(6Si8Nd*UED7=pW?*FJ?S5#6~)zH?_H8eA~vv+Xu@bUHY z4+)QojY~+*D=4X{t!wG%o-k$F%vtjnELpZ;SU&YhKF~s8Z-Ag}>4?Bn)_!zEbQaE+T)zI*atzFjwA8EXL;h3@a z|9|<3+pnZ;)=xdgpH@?U)AO0}=S{O&f2=+;HFPV>@;B)`p{9~y2YyYRbbOc6vn%47 z*D`s6wqGqe|GmdIec9K@eDktTTc7?usCVXYnfI4AerKE0X9T7HRm`Y4bc^HgFaJWt z11C%;NzGoVY1%~SUa z9976;+>?;GKDaeK#Mg3mjmYeKx+gXr%h%tTQJDQk{f*O{*>4z5XD*YD3BJMhY3ngj kvD0y3GtOQ9Fu#huLa5?_uJ@8Nz(`^6boFyt=akR{0BC}BSO5S3 literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/flink.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/flink.png new file mode 100755 index 0000000000000000000000000000000000000000..568efbef227d0e154749dd506a38bf0c7cf17497 GIT binary patch literal 1443 zcmZWo2{4>z82%mUA~r<3&Lk8up^j9gY@4KRyRKau$2wBPkxD`o(J4l<;)vM;Ir?z&)&pto(g}sB5i>n)n?CwpWP<{OT0|MxQLBSzkhK8Msh>VIpA9LYi zY-~c(l`F~Lq@-TG#$a5}%*x8nxxvgUD7sx-!eVpED=YccHMO;Mcj_A(o0@)TZfR+4 z|FNU9v#YD8N6`CI|D%CH(JzmOpZ+#7IyV02Uz1Z)e~ZP>r)OTw&b?e*T3TLSk*u!0 zdiDDCzi-~GufN^c+}hgSwyl0@2|tWE+1bHYTW73qJ(T%1hLa5Q@?wg!`I)Y@R5N3u z`>`V9fTIaH=0sXkQin@P2;pHqF(B9ao=#|m@bS3+@O@(XKWphTp+1WxPmbIY>iUgP za`Ln{1Es0qSL6AjCw*S=MUG3$)QmM~5Vlrl$c z3Ztmjg^LEU>Y)P-H$(Q_DZZpHPBDtY!!5-ZDu8A zhg8$FuF--Ai&loen(R=s;hu#yp2upc=Dme0zkG8Q!N) z)afuxu$e6LiK`|O=!4r~OEn_>xU6nfPeMh;+E?kGslVD`xyePkg8Wi>Eg{QO?&YH+ zemK!MNmY3iv+IwF7oF2nw@7JYl7hcei}bl{ci8fedR$)aSwZn5 zQMv{_1XurFuhFUV(q895PAL}FC4Flo7spOA%el*_$2Ki*3~M|yq0h&wv?k2}dv|N-h18!y(jz=qJX|=HrO5)3IX`Cb#ckib}bkeJ{X&p$D?H#x1s@wfZ~9&b9;gLW68PaeCIpgl(L z3kM4Vfk5PhvQW6XV4t}OoNK1+E8$|4in4D#%fNnrl z0FD#{)Bt)NpcVt4D)5mMFv|f$3}_`7aF+slDR$&819T}siUFkvJEhAo0U`zDB0!S? zY7wAFFn|;Ssu<5DSGbh|3Y3WfA_1;Yi8F-&5d&A8kpM~|AWIEm=!GQIKvImk zFg?T)1D0Z2h%vncD}qN@oq;6d`)Ex=xrYfx#wMm_Tg=~nhq%?!%G%~#+wBe{$M<$R?b_`^ zc137(h6i(x=Z9Y2dwur#`UM0A1&8csa}ID1g`vF2sOT8}k)yG3$37FpA5Tb3NPud>d3b2jJO^SKub3MI1QlG5^us_NRh%km%V8x)Ew%|BiHS=rvv*?Il9 zt{&BmzW#xmgG0ARM%8yU+Itfdx`&S@r>39$^|$`%v)Q@1=Pwo(mtMYFe*MqN>gpP6 zAox@G%~2J$+MRBVt|J#pZ+_xX6ki zvniSe`G|kgE$tG`(m!iQiyerHd)!=RwWi8C5kRNiS>fEU(=RqvoFdlr{9e|_YSm4v z9fXgGLLb3*15_qMIQso7=1GTw-MqQ_M@l~Glu&@~*stswkq7EKa&OPU_a}=l+eS66jrvNN85Vv@ZjYn5WbeWS(7tD^qc3#XWaTWI~rnBH7qEEL-^dea}cGu)dS%JZHqC{&{EeUu!I zcA-%aYvq?5JX788taKR+Po;ZnyPR~&_`c5DXZ(|CvgmCyl^*t$y(#Bshh4j~Th{dX jC5gmeGKNa#{g>b3%I_pKy+|m6FPy*$;j)^8;?DgGSbeZU literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/http.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/http.png new file mode 100755 index 0000000000000000000000000000000000000000..1d80cd08d0d8100064d838ff13b4f9470f41f84b GIT binary patch literal 707 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9WU~hNgt!6) z|NsBLfB*jZ^XIQxwQBC%xl5KTnK^UjoH=tAE?fv?%$_|P!kss7-mF=(fZ`Alph_SE zC;|i!21Fbp0wjUD;8JidL=a9w7;r7f3`{AY2pqr-gfM{Oa1k^$m{Mq3fC@4W{uTiS zL|93XUoZnB3kN4JAHR^Wh`6MRmbQ+bk%@(0SY&i^N@_-KaY<=iV^dpuXHQ@M#7UE< z&sem4-L~z!_8vNN^z69{*Kgjseecne7cXDEe)I1AhmW5=fBE|D=da&?{uZtBFariT zm#2$kh{frvmre#9au8{K__*cRf{x7#+(ZO(=eW;V+$78?uJZh^{Lx;;g_EZ3*x>cw zb^X3q?_TXYFh6Je#Vb#y)EfKMuIs;aUx9Ps=bzD=CW%{li|R%lV9R{evs~ixqSuFn zD`P(W2(-Dh$few?MQnM}?N^SQKd#?1i)E(q<-dU|n3uDGjhJuqK0Z(5%;0|Ui(mnm^#=bX;e14ZI zIH;UF;U`;ldg0@FyoWpFw(p(f`rrDijiXYC7L&&M-`v;A+V)M0|2b{PGd})FXM&Ae wj`Xe-<+)qnZ2$QC-B{zDdzRf{`By&Qep>(4UolhafZ@*I>FVdQ&MBb@0KTAa82|tP literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/http_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/http_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..31403be5e51a4cedf51927f63e41dbb66e94aa5e GIT binary patch literal 709 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(ebvj+HtxB>|G&fh|CX!%ThIM(KIy;l%>UYR{%cGDF?1&U*93B>{@0%LUu(*L&52-i%UxD8k^eMJA3;2Cr+9?ea52Y>$Yv* zwfE4Gqi4@uxPJ52?R$@&ymb{H=Cze>VFYC#hJtRdP#5ayabiT*tK?(+>bWMw;pCm z+hOi(W-oX%O?-Br-S<@EG=JY&8v^W;`1KmLXGgoZJc)C0Idy{v(&{dfF~OEceF_?^zZoj)ye-?x`NDmRUzyALL1 zTueW`sY?8A)Tu)$`LXOtC%RY}mTvvlF!gQY`iJ8B+N)+Z*KYnE#&7shIs3)=q77pI n#ouk&X}q(>XQ$zx*>;TIr24O}T&@)j40#4mS3j3^P6wpuR0(9mrGRXR z2;4M?N}vLWIS>+}1;~aN1yKVb;mUwga5hj1$b}mMVMFu+)d0mIiXq}~(|`Aal>r5TT%ZX+fGiF-8KQF9n_p(YK(8zb@(X5QWMXDzW9Q)F=H(L*6c&?|mX?uI zR8dva(K9eKHMe$faCGzV^z{vhib+UJ%`Ye^tEjB2Z)|R9?VT_gXw{r~3l=U~vTEJ> z4O{mgICSX9(G%y+UA%Pp^0n(XZ{5Cq_wK!W_a8od^z8M!51&4N{_^$v_n*Ih|Nis$ z-@jEcTJwP^Aj;FlF~s8Z(<|To4+RLYe{e1gc$Kh{M|7iB2lMtFg5U3j9krG0;(mB9 z{yp=;sZTo8j>-4jzkl!U^7rd9gBtz|Hmh(l_?=`l^PChTCR8bCtDsiEm}W57k*hSp zh9R$K`NXS9_iHac|30@!<fO;^jwy;G1r<~W74E};$6smj;Vqt zy1#|ZIidLBu|cEPkw;1!MZQ>Ri2vN^A;RJE?0dlFtA`tI$?m$nPW6Iea!!%S?993u z>KAm^%fCx6KF6=k^2%?ctM9r+cN6+`uRJon<}aNsbM=13Zn@jnSLl{TIV$9)ulHOT zBD?q4F;0<`H^*XDrY!H45>NiAcu^|ZUv9gUa%<1QrO)K+9~k6`akPm(@lI+~seQF} iSsRn#-?#s7TVLBd@iU*u$6#PoGkCiCxvXP!3-pqzN~lyq!^2X+?^QKos)S9WIG1Xte!+a21Z_$72x&O^4{Ws|UuRHC(#+3hh)BkJE{I5U# zzuu((S`+^3P5!Sv^}psskQ9*Anebn$|G(Cx|Jp#tg#X%;|LgSs*9OW0MJ9rzv?u-7 z1d9M=K`Mb#6F?e)fA%_OwBJSDXXZgt8Z*>Y3-dbdB&_c z^A;>zv}Dz~^&7VCKXB;C(G%w`Ub=kk`psLn@7}xr@X@o^?>>C`{N?NSpTBj9fB1Bq+7$O+Z19^DBeYq=o6~1Q zibMJVc^m!e{amKO8cL@QN3VJA!)&FRFx^%|%xG2b-3cyJxZj-5naNfnw_I-r^Mo_E zB{V%d48F)cUy|vNu5`GPVUmlP0Yf0$W&aR6^RF@c`mXG&NnL$r(WiXp{F`Qq-3Aut z&T2W&(RR9~WWMuhScPrIbjBU2o+n!VngySIe)LzyPsO|HDUp+AXHVVc`Hu6Z?a9^M zUX_#Foy?L8?}yGcnZLnA&CV(RfLRf5S^euJo0;z?J`P*wd}7w}XEj?rub1xJp_tFVdQ&MBb@0HHUgo&W#< literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/pigeon.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/pigeon.png new file mode 100644 index 0000000000000000000000000000000000000000..6fe21d2b1ee5f9be7f2cbccf9919a718fc860ad0 GIT binary patch literal 1192 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(ebp9}B_aRmzg z2ZL3sR_))vf9A}Y^XJb8l8Y8Cnmc#yk|j%k+@(vGE?l?}$N-7}8M9~4o;PnEPz{g- z3eK7}3n&g`0~vGX%mIo66+lQh7pMRz2vh(R2MR(IK-2?CAb^XYaUr^pW#Mc%1862t z7lgzV1d0OzP#mrX$c5MfVSuDzCO{Yvm2g40Mz}7J2ACGOEL;#-1fm5_!qq?+a1x>g z$c3mxRtAwmR)8!E(E=y?B+6a`V{~RokY6wZBNHIL{ zOIv$KPv3-zlc!9ZK6Cb*x$_n*T)KS4%GK-EZ`!hL`;MKv_Uzk#;NYRdM~|O8b^gND zYu9hwx^ws5!$*&wK70P^&D(eHKYaZ3^~cX&zyJLGH*LkkIAHR7?CIhdA|ZM9;7{l7 zLI$=E&+p#*I_r+ow3w~8jNG}GKI^hvG)b^i@M%=qqzTs))0b@B`uJ!5+uw54_t$>Z zp3nbp@7A+>AByYCe<{s5FkiM~$%@mybG9sAW1FmFRLhY%=lq5%x$Isy*fY1zSt_vF zWuw5%9cAx$OYbfYaZQaVoiH=D;VoaN@hRS{yhBOZlX?{We;(P>;(g0!F8i|IPill) z!X{bDUzoD&*&EC z%Zd4umhEGA|8n<9D)&R3qm+XEGFEB)nb3IG|IzwmYRl8po~OCrPJJNqna}z0LIXY% zo1%j$t7Xp^zGpH~*SOQX*}duDv$y@cUjjKCi#rdMUOBC?$=2ziqKPBd-wA;W-f;Jw zNnOe1eAy>a!gb0m!K|tUD;IxYRZH)!&uHD{moZ0^>v!Uf9~Se{4#vGu5}CK?ftc@o zl^5rNL>nCWHYYH!Jul}v*=*pEdy#dOk#)cY&(LM7nU?7uU##-}(32kyXOAmynDBh( z4ojmpoPaR;IWbkzLb6Mw<&;$U= CNoqg< literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/pigeon_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/pigeon_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..d9d651bf5dc7ba97346e432175afa85531357fae GIT binary patch literal 1167 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(eb?+Ne;aRmzg z|NpVNCGAhtpOf8A;SwdefTm;&M&PWrDm{lCrx zkOIw_|MjQ;*PHZTYr=ocDIk@4lR=7gCjHk2%1->R)Bj%^C_Cl9?qo2d|Gy590n`i8 zGU>ktP-NnN?a3e$K!QLv(5Q+3HGxt<5g?-<#06;qvL}Mn1C@ak07Zaouq;#=SR+Ik zP#4Ha5Tho5jRJGwW&#-?Ss>~Mn+aq<>;f}TWZ}wy<^Zh&b3qE=Y@i8XE1(8K6o3UG z<^xHHdZ2cQN{~5d+96yp2~rF;AFdv%7@{3UPP#7W28_SSB|(0{42(?7EUau?+&sMe z0)j%qBBEmA5|Yv~a`Fm_O3Es#np)br`UWPZX66=_R@OGQ&hB2`KK=oL!C?`R(Xnv} zNhukbS=qVy1;wRhef<+AO`bM;&fIwm7q48ie#6F1o40M>xogkfeftj{ zK6c{tnafwMUcY(w-u)-fp1*kc>h+tq?>>J1^6mSNpTByTbeRS*-#9Y=v6`iQ z7K_KZ{pW(k{R2fEME&R4u4wYIF8uzrC>%#uX~mugyOO%gOFDzRh2r&rtUIKKZ((QbHX{a<)Ou zk_U|&{_nh7`J!l2%CY`7rJszu^tdvOFUa_$t(+*ojq&)(7fr|9A4*=ZGcQZHeXiDa zZ|%A`?F$dQgC91lxjfW6!ylDk!0#@%H+n$<>nx2{1HT-1*5m7R1-Sw<-UaMP+_Z4X z&Ejv5*0Qe3b1v?6VhQ~=XVzjhp0gaS;u@QGpSu&iB#&iQ9oJ1YiL&|qcK_BY5T$lT*9Q zSDbR46|nHJy7{g^MVGtR8${W>dw3Rl&1rk{dv+!hVUW#cBYm?0T3`bmL;#e$S%FwA95HkOAPsa_P{NM2fKdw@!~lgui4rg! zl~@<0ZH~pB0?AvZz=jrjF4o=h8ZZbpl!H8&0qIbJj@}#;V5B41{6!dJegGIp3BYKf z5D)>jjDP{@n*kUb0Y73ih?Ot}jHVEP4U5{WfCo)sBglz7nWTNS@Ke5KxlzyJ@C3PS zAIX2LKvY!PuB`IOj-9(cRaMg) z94VBqoSd9pT&XlScTX>GpL2}!7r(s}7`33iR4+@KZd01Rr@@rX{;J5OM%F3#$>c^t`hK47NO-;}K zXl`z4Z4-CA?C$A#)hm%m|LPkU92y!P85tcLpLp|jYI^$be`e=oviXID#l@wi<>i$R zt7~g(>+2gEL_5YBoIqD+M?1Q8`!@_yf1Ife^xmE|Av5is@^Ul-%1AE0 zS#jgS%U>V4Hoqte>bzmSIu>>2-j&7vy0EI(XEQYoKAT8y7?B84rdtvfnL5f7c9z_( zfENPgmejrL-M3RBS_M?M!Y6+B#jxHanVIor;a>2o!?;a~t=kP6SnL0BmVci+( zqoZtEwQ^Y>;Z>x{sSH+kjZg6~J>JiZvrnCIDf&XEXYI=Gg5AyGre!LYV+=+UUqMl- zIdYOk>6ZEj?&a{0{!DVw=XAwH%t+Q~Y6kjhrUDHntUe%_&xYFFjVt-@ovT1tF zM$uapjd!!Q$*MRH_2(u2OF9pdMZxr|%y8fPm0H&C|wL`tcqt zS(d^brFLe1s=T~Ymzeve;q)Lqj(A#B{UwoCJU7|PHR)F)cShj9i0mO57}u^ys`rqy zze^#vr}f)LE>sZANad`Y?v@5L$;OXRfpWb?+TETz`H^RlEz zb}0wkVRZ1i_JM zrI8TP^r+~ef~s-|p;RJj#B!wg`rR2E?dczLzvq3v=l8t#kGa|2UdLsnG^7v&k)^nk zec@>We;5g2_^eq-UWCV?1mEK%q`6;f0YQXZy*>Tipa}p-10bLQxO4*RQh;j!6c%u) z1ojQ+NaO%qA#f}Qb}V$XpaZiafd2+y*yw1<0t5ycz(QRB%!>h$1#k?2Wdi~W;Gxe% zlV$~gKnHku#YP=CqM8nHEP!DGLIEluMPLFv)DUOz1ruOdz>JQL7}&-{5r{(*4>NRt zfelc=6|fxMvQUlILWhsQTc}Z-F9cx-LPy}EEWF+CfxbZV7oik?5!wLP?Nfs72X4`~ z+RH$Jt`Icu;s3gYrl5h}xvTm3E(`S@DA>C{qJe$jciit}|N=eJe9+s0=P*nOzSyfG4 zLsLsf*U-q=1cSxl31;RNmew}5b`Fk5KOwo2$!?#zQ%-nzdHV*O3JeMk4UdS7{QSbj zOVQMr*to=`%gI+$zM`dFPtUyZb#_i}Uj8jQgIT~XEGjO&eY>o@qVmq&s_L5Bdv*2q z8=G1laKHVo^-)`U$J5Sd&%1x>dC}X~KQK5nH2mwx=-BwgTLYX7Sz9 zU%Zv~t7~iP8=HS`ZEf#}5WR`;({QAakNK;qPjtOC^ov8prZ!@8JXLEO8`+KiY%(j6 zmFPyY!xdsC>e-x=wpd@{gc9lTsbYQC@k!^Vs!^KZ)3uuUuGDT1O$}vTZJosoihBG~ zl7s!5@v8LEs1nSkdcgWd-`bJZ&nCy}xU+qkrmt{=K@TRT@_nRPIb$!b{5(BPXbRj} zHZpEM^F)rU(%em^HHAnkwCO6j1=YKdS9o&^%Prh75WZeI@^Ty-C7g%gji%Ak7?0O7B#RENqq?q zuCd0<0?u93ph1KCL&p@yqgl%UZcAy{qXB_bw+~K??k5E(fdi%L92ru*+rYoQQTq^9nozu18WD&#jBA2aY zsns&!r$ff-@mJ=~;KO>o%c;4eKT;pbT1!xkx8md({RJ6MKD4P3g~OeqY4SJb zoRVTQbyCU_Let`8{Wk({@@!sWOE+tR!gZaa(@rEXD_cw0=S=R)y~8ZsF;nnk42plu miIA+db>1FqN*9UQ((FWdRPj#Ni=;gGNgxzAFLE;}JpCVqkk9D= literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/python.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/python.png new file mode 100755 index 0000000000000000000000000000000000000000..8bc4d516aa6fb6718ae9801814fdbd6dfa03d2ce GIT binary patch literal 1618 zcmZ9LeK6E{9LIllDG`xpxr&k#sg|PY+@POZOtyBJ4c%Srt?PjtXC- zA6r>Z6KBp-D62$5<@qsG7<MdG^(DC zr4EK+dcHn51KxY#*{4m0Dl&a4hnGeSgX)DB}x$)nrsHjjXm4$_c zAnNPuWilCvqM{x&3|z#{*7IhYnMm zU5*@eb#*&-{0nyv53dv6R39H-|5E`0fy^^!f`WpBL%#ktG%Sq84iEqS{Kd%2S7KtX z#U~^tagw+u9ztw|8_tecIL4-Sh1Ei{8Gz{(-@v;o*_dvGIwCmy=V|({E;G zXXobTRlmPoTKenn<(1Xde?F|OuYdgXN#UGKg)j7yFYXy=Zqfd5F(`dmzWtZ8%(4^?kMK1Q9bJ>;a)-fvZoQ%;26sC91wGG5keg6l6FSQBRIHljCO+LxV2h=fF4xQAENH6GpK{9< z78JDh7`e$QSw)1hKV_=-Fzt4h;m4kyj{RTQtLVa#`Nl=vT)Ik24>)xLy+;7*U@shiX11~f(8L#nc5gFyAT)a!O zL3-66vldF5JY`X-tXBV0I~ph3Ut~QK^sa52IHq!+c6HMuywhabYX ztdUVMCTeuSSCzsZ8zH>TFc@zm!HgUER2glT7}xbja5x*PgB-e{x!r9`ZTQ46UvC;-k44ofy`glX(ebzYOpRaRmzg z|NpA&WL{~AD}fLbPkwSWaRASM9WKtm>iG=dZW z%>;@7)dRUe#Xv65VGt3pUZ5_J`4C+|DX?`w^$;x}#X!@*S|BQcdf|dVGeLr2(?IHx z6(i|_m;jPRMqs@_6A-d+Hbe?;8juSXfoeyS1$zx>ILIit7C09oizEdx3gJ|UX)scL z@ntPwWG^ZS@(X5QWMXDvW9Q`J;pGz)5*85?mz0r}S5#6~QB&8{($>+{(>E|OHZe7` zw6S$?a&~cbbNBG{^7ird4+snj4haj7jEatljf+o6P0z^8Dkv^3udJ%BsjX{lY47an z?&9XZ(*KgRkY0K6fJ9qEdyKn!2gNKeBJ$C%$sWWHKoxgDL z(zTnn?%aL&{Pl;=U%r0({^RGb-+%u8`&?bA15BbXJY5_^BqYxs{2lFG$iV*K{H>Xt zFE@7kr+G^A~`(N>1nFSQK{qU zI}`Xt?9wjpSLR;ER@`8BWqz#oqGYq+ zA+A2hi--SSkoJsR=$Vqkz!t$e_tY7IqFoZK0tQXTu z`(cBUUO$erDSNvWC9+cWP1^Yv%y&=psG4lKUBoFe{@Y~MV`0aCK0dfo%-{R_Vv+k{ w35Ke_-GV~S9=WCZr}s(0Z)vj`AMJlIt6Qzqt&SAB3QVC4p00i_>zopr0L)@*dH?_b literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/seatunnel.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/seatunnel.png new file mode 100755 index 0000000000000000000000000000000000000000..bf2f83e206000b1ecf26a03490f84fa1d48d96bf GIT binary patch literal 1086 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9WN!}e32_Aq z{s)6qt5)sbzklY;ncKE)n?HX(kPBolTC@nrm^*jwk|j%kT%h=zIdc{+TnJ>(n>P>0 z1xf+AvuDqS$O0KaaiAKY6ofr%)+`_wNCLS)#Xts7B}5R&01Coo;o?9+2pggcq6{bq z;Q|>z02hR-gqsYJg>xYafFv9MrO*IS3Mc|6Au5qYAnG9s(8S@oNEIhiBc@~iJ}_Pf zjJ63SL4Lsuj7-cdtn3_|T--doeEb4J!Xly)QqnSV3W`c9s+wBbItIojrsh`GHnw*5 zPHyfVUfw=_{sBSZ5s@)*@yXdax%oxKC8cHM6*Udbt?gYsy^|(SpD};I!o|y0tXjKq z)3)t9cJJA{|M2k>XU?9#bmi)`8#iy=zH{&XgNKiwJbm{3#miUk-hcS?`OCNOKYsoG z^Y`D{H#0v2lh#~M7sn6@$)g8N(m$B$oysb=;laMOMrQjIs^1)uIiIy< z&8_b>*;DvZXK-ao&R#Zi<@Kh$n{D`4sQgy7fA#hFzxhY5uWC6}{e&+&@U%^N$RUN2 z(--;Gw;nmCbNy-IiqXjg0)j$HJVAzdj4{H;#K!!p-N4u$pMHd9umAIqtXdAeEkdR~Xu@*g3p{k8=m>$=aZn|RMa;jp#ald4m(EBj&s z+O$=kt~h0=F!$L+pW1-MO>YZab{&nJc`KovODbW$iQ9aivlkXL3AikkxSsN=WdfJh zra6;ud0stLFfXT7X0eLOYtHqDKUJMx5hHs+FV}B^onE+z)sszXKNGxPAJ3esJR#-M zBzKkbkFQQDI~gdeEk44ofy`glX(eb&kOJgaRmzg z|NpKP;_5B>uQm0*`6LkAp#Q(_wEx<3{%cJ6 zZ#e0{-t_-E6aH(?{BJn~3P4<- zEYJj?E{FmM8)hs}5TqC=1ylw$2OuGAKu&_O5iSH9-r}E>0gR!}k|4ie21X`k7FITP z4o)s^9zK2nK_OvLF>y&LSp`KUHFZrbZ5>@xGYd-_I|oN6XEzT|U;lu>;Lxz>xcG#` zq~w&;^t}9{;?jzmx`w8f)~>z@6DQ4_yKwQ6rRz6t-nwo3&Ru)GIWUH*Vj#`{3cDC(oY0eD(JI=PzHs|M>aq_n*K2o==U-0w$lCo-U3d5|U>R{*Lx8 zWH|oOKRS4M!2~1U6SmXC^ep*yPJPj2GVMZA(fO@T&b`-O{f*y#{PO0{wy$&kJgVFi z_v<>J+@<&zXP^K6qJB+-^`um2%JRs4*R~&e+`B5_w}`#Jm*2efZKrO1YHMArWieGb zcDYfOdSuS!{Mbr4SCJeMnYAz51X*{nFl+7N>|=T}C*5b>1?Nq_xAl#Q4w}9%-?ida;Q?b+#Kq=fz&oyqg?Qw>)vX z4f}%)Cg(zb$~OM}dbWe`DL@nw8WgTe~DWM4fOkEF( literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/shell.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/shell.png new file mode 100755 index 0000000000000000000000000000000000000000..4e40b6eb2008b68e2c5766e054812a9993380132 GIT binary patch literal 747 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9Wa|X@gt!6) z|AWE){rhLmoVjh=wnd8;ty;Be?%cUcmMj5^%%4Ah>C&Zh=F9=Ifl{+)&jyMB*$@#R z11K_U)+`_i6akVzjX*)52!snHA+m5~5Gf!D2N3l@F2pn-2?TIih&V(9lZ42kDTWKe z)#G8n^#awvl_8q|7xdc@^#B-N$t6L4!3>N{EUfI@JiL7T0)j#!V&W2V^2!>T+Ioh@ zCgxVwws!UoPA;xKzJ940S$X+I#ieBxmA#YZE?B&L)w=Z?H*Ma!bNAl;2M!-OcKpPd zvllL2y8htNlcz6Vy?y`T)*7s&PRaO{quBj46!(U_e!*JQ=rJPkIS1~ ziaZoAF{*NMF1+CASIHe1!uPS}|N94vwpU!<_U?E5yPs!g*;Zf6NqBKvW17fQr&!@7 zyQVq2b3Xp**k!mN<3wQERUL)f zyzzSuEty!nt>(~C-SirMFaLrQWfBK+wAPCM?OyZtJO@M0*J)2KHGGp`->{2=VZ(8u zx!a!qQhU21O!d0+Zk^xH*|+_3+us-V@8-Sho$oH3)%Fcc%>A){S-x9$+bn*c6dPbj OFnGH9xvXdxEk6 literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/shell_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/shell_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..b615f5532e35bf3a98783678f64f28af4d2720d7 GIT binary patch literal 745 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(eb>je0OxB>(&i5T?%*PZrXdk%=LH~qiP1dy!Og#VgT z{_9NouRHm_PXB)`AR8z?>A%Lr|2mUFvN{w0YXcdR{%cP7uQ3Uv2FTTfa3}oNp7dWE zC=S#z5u^ZQ+Qk1FKy!c$2pcF1afmFK1nLDU04W9{Afq3|1qwn`BBa2! zz-19?VCoSfU;`1xf(-|8k*r(!rJxoVUdbgve!&ckOf0PI+&sK|`~rePB4Xkaa`MU= zn%a7X#wO-g*0y%`4o)tvKE8gb8CiMxMa89M6_ve{<}O&geAT-38#isojdhY+t+M%5r-SS>O9DHTnlS8Yg-jF61)W9g_5}D>Ci$g}L3X zzW!Uo4_V#bV{rfR>jl#@*=@d7C-A1*u)Os-D}LwujhRvFcf8zWyfwb~Wh3jRJJ%v2 z|5~0`e7$9tbCL5k?JMs-3vRSO!S>VB^X|vD`_oPt*8j`)nj|(y)avK)uud;2`3Wkf z=Z@AzztNq!EhTD6ieR*w^gHd_U#t_`dqZ!0+&=Bli=UT!7G80g`Zvd(Z(rN2)gPuS Q1H*yA)78&qol`;+08kKhUjP6A literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/spark.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/spark.png new file mode 100755 index 0000000000000000000000000000000000000000..e9ff012d4dd1a3dfd6e15602f62030706fffc837 GIT binary patch literal 1067 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9WN!}e32_Aq z{s)6qt5(gNITJ{3+qP}~{P_^>qD6~aREHE4opvTy|u21GGj5TY2! zg#);0KoMj%8W&mW?K;E7z-XIL666=mz{teR%Er#Y$;HjX%P$}(BqAy%AuTH>ub`-` zrmmr>rK4|PXk=_+YGG+*ZRhCZ?BeO=(+1FymkA|z55OvI(q8N`3sk?Ub}wd=IuLo@7;g!_{p=^ zZ{EIp|MAo3FJHfX|MBzppTGZ3_NB-IlUA3fi(`m{eqj?w^jz4_=Mn&-2#-MeF zmMszW?2~craP`i+mMdc!loCF3+Sa}$KmVLmtDLp?`OLo?mw&%{D5`#o+tVwzYHqGH z(n-kZR9agk(Yi(HZENiNpRwyT(lutT<N@R|&$f0M$GT(< zcV^iehv@EK=6(2pY~`c(8ab2HXP$g4C4FO+<<#>(cSaX~+jH>i%c5?@{)tchm)i(` z*tkE^@o#~XT=A@$_Js>{6HdO@G`JMIv|+kW?iBy8Cv6gzUq6{{eaOP`qJ#WQWo>g^oRx1BW&y2o*x3R_P*9o&*e=@?S yL`S%C>2`f#kjM|%@_2GjPJm^0^y4U-e@srXRgHH&-vDEUfx*+&&t;ucLK6Tpv@2); literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/spark_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/spark_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..b0fbc560500e3082f32ece9d40be7f12089480bf GIT binary patch literal 1066 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(ebZw~MYaRmzg z|NpM-f?Z5UM5ZiFlf4%7- zDgEjHb*BE;n($w93P^$8D?R zlmBZ2wE$K2|JMP^PX4bs;lDPRp*0aC4pa=(r2!NKvVkIC6M$-f>Otg0uprO`pcPWnk?fl|WgrAcz6h4p9bVLsdc)0HwepAQG$$WGqZCf&rEVY6KYtF#&8i z$OPr(#qP-(aG7x)62)#KQJUb zGA=$bIVCMCzp$jVqO!KGzOlKry|b&gZ^Fb$Q>V|IJ#W#H<*U}M-?(|}_MLn89XNFK z)S2@aE?>QN{l?APckbT1|KRbHXRqJ9efR$3r_W!$e*6C8=kGs%|DEhhkp(8LPEQxd z5DCev2Y*KMFftr}`2LNG;IuVUR&S8K)TQFyp_h7b((F=c_db!Eq03U&Dref&Z}POA zb@OFr-P78y{x?eY1U+1pV|P`13Tw}rfR0kW#}h(2{%&}#YoEPkj~!Rq=EKI$++kBQ zILj-QV%vl#MV9}1)@`%-E!V6Ed$w3L-~DWGe$Nu7qzh^*k0zd*?w)?m@|+*5OcQTW z?DNmf^W1_zGKGt7c+2n8Wj+jt+NzLi;hg$<5OcQgxKjF64`U&_HN%cG0Dujt*5iO?(v(Q$``PDntE5J^9?yIQmKO zy{W8kp14)Yv}9`~$;q-^60F>lVzsQ{$ltu5GL2IXxw>h(Y;8Hbc9yvPZtoy=9*qMY z7ZoyVJ41M9dUsyZ2~O1t;|$dN_NyVK=4fhq!rCs?6P{Ne$4m^lo&EPfs^)^`#H&6= z#Xj|Ga$fGY6$y5*e`z&4e{Iw~-ZeHm)mnG3`&`pHb29UonRbk8amfFL_XAw28uy&z RQwAm&22WQ%mvv4FO#r3A6|evR literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/sql.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/sql.png new file mode 100755 index 0000000000000000000000000000000000000000..34154861d5a77cd6acbbfaf9b3158e54da6e64c0 GIT binary patch literal 1317 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)UVz`!IB;1l8s z6#Nect5&VrzkmPCnKOZmZQHiZpFbbS0CE>CS~Pd=+$Bqv0NFsnrAwF2nKK6>K700T zpa_t?aN)vv^X35=Kq;UIP#l>%Yt}5F2|!t(Adn4I15^MMfv|z%5H?&8$N;JV$^scc zSs)2y0~rwYKoZV?C;)QdY9I_C2?P)=VC7H+KsHbi2!OH>aUdHm2$lg6$WjnCTm-8u zTo7&)Ts=etP9iHn(*;)p5r>m-2BreI6r6!(KAJdC7NP)|L{qa=B=Qz8O{^~o@(X5Q zWMXDvWn<^ymR3 zo4;_;;w8(LuUNHu&DwSAH*VUzZRei7`}Q9=bol78<0np@K6Ccm#miT&Ub}Vs?)?W3 zA3c8Z^x4Z-uiw0V_x|IjFW(_1UV_)-+#lIdCuwB z)5mZ5KcDk8y87+j_qOam);mYV-Mx^No4-o;>@~Ju&pxkT^hdap-~7AyvZn<#N;7BF zl)bMyfAu!=K8cermL?s1vRA?V{H&)b_oRLc8*R}P{aRGi?>Bevsk7%-Zf%WR8JM>;G3yY+pi_$*i{_++uPF`qH*2K#$D0P zI@~Tmk@H0UmhX0TZ|Bddc>mJ+W*nab^U`*y(2Uwsf~60q`D|S&7gFxtS86Ky$M%Gg zRohH6rr#2tY&Pqpr?3CY`>TFJPuzzU+|##}RzE(;$nq{~dPe#3^%*y_i*Kym?Yk+h zTs2BrW92E)3%hq!*5^(7B4d`q5D{~K2D`%IoMOHS`BQ=e&+D8t2>9LFW0LUI+o+5s z_l}~-zAOI>JRXRdOD&gwnE7QwX2;ho7KWz{lf$!8)+`d%ck44ofy`glX(ebzX|XOaRmzg z|Nph{_+DHR z_N#ijhc@+0 zFq8HalQJz@zf;6>-p2l8KUQFD9iPj;P)K-ToE(<1c$l{PtVg+1H*cjyrF8 z{`XGC|DK|`H)G3p+}n3`gIQsW+>G;^1H6;B-%*uX@s!uoi~I7!i5J5+@_6dS=?5!3 z7B&*Kd3@ooy0$%Pi$4@lFUgiOB8pohZ*zV48hh6&HE6QaSx3$mQ zp~&*dO%?{H&{9K&8Rc9J7qcd8PMq}fyF+P@&yEDi6NZ&cXTNAD?f4_u>0rP2czsWz z$E#0n#d@a931!TG-)wuQxz&(iM@9U>O>1;YcBg6ZzPC8U-7ukcWy0c`-2Zo9YGqj& zZDzm0IOWsMrmHG5r7csL1!6Bel+-;LVOf(CZVlvdZ{ zqO>Wyxb%@aqsg7uyLT`ad@H!bvRtEU(TW=>d*5vQc4_;(`zHlHO#Sni|C9LsNvD`k TriD8J(=LOjtDnm{r-UW|5$b|H literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/sqoop.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/sqoop.png new file mode 100755 index 0000000000000000000000000000000000000000..2c754d365f80ebf61f3eb0df85c4ea52811bdf5e GIT binary patch literal 896 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9WZMP!gt!6) z|AWE){rhLmoVjh=w)yktuUfTg(V|5_5-0-XE?v5G&YU?w_PlxXfZ{+AAba-g*+9nJ zxpRT+S+iyVxj+)A49I{ehA<#fa5cybh!&s%h#E8oL=dPRq6I=i)PTi6mZAy5Wg!eW z30DSZK=h)S1Cd1*gp0sUMiv3G{|P;m0ft~^NswPK10xd)D?0}#HxIvnppb~Dn1rN^ zs=9`@o`IQ#wWE`>rQ(ICS{v$y1juU%hw#!IP)YUcP(f)oq#1Wy6Wafc+FK-nmFokA6^pUw)6jg`4^SxZGvfW_Emk? zTbB#@OLlj=Y4y4D>P>y0v0Gc8*GYZW?xfkPV?-ENa{r21@*w%1!GmKi?Uh#VR{y;7 zD(~yOzRE40(IHZ&nK$hHYcAwaq6fno(v2`n>YMJ+@ znJx!jtDU?pk>f7%o5Ny(MN@L07n@!FY?0!Emh&1?_xnyyeJrk44ofy`glX(eb+XeW9xB>R0m z{%cPBuQ%bp?&SYkQ~v8r_^;LfUkfNW>A&{m|JoBlq}D``AW#`lP-DV>?MeT&fXaYe zAR8z(0VD-f0F(kTfZ{*|R6pUr23Sx7EDKTwMnFN36j&Cj3?cu z7=1OKE{-7*l2;FAJ6}qWV0$1P#3QuDCrEi>QRF%0MXJv_mt0~o)D;mmom=$(zx{>H zdv7WQx8eCEcXcPSA6hNzDp@)BHK~-7M}nUr2sb#zr`GtMLvd1sclKJ zQrRNL0n;>=El3Q~alE;pg1y(Ui&rDH%lv}GQVr+GWflCr{353VK8bW+&$aP%4%zlNAZWhst+0#hR(l=4zxLz8doH(b>{+n*Rx97i+N?Lr z1q8GWmxwsexS7!2#<_OhAHiDppK^CHD;CDAzMlQGHPJ@uKf|%U_1+J4yGntP&*16m K=d#Wzp$PysZMNnB literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/sub_process.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/sub_process.png new file mode 100755 index 0000000000000000000000000000000000000000..fb12061507033a4bc5327967f61d92415d30d0a6 GIT binary patch literal 692 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8p!3-p4i=A8uq!^2X+?^QKos)S9Wb+01gt!6) z|NsBLYSpU!`}fbBITOeLlJn=!U$}4~kTHAqY#<2)bLY+ll0YtyF=x&k2xHc)SwKM` z3FHC=;angC2!MhR0MQ6!Llgr^I0L8*nGNAWL_kJ>0kQ&QDL5NV0gwv;K;4)OG(iX# zF1YsHgU!GYi7W~73ua(sW?|*z7Z4T^msD2Q(9}0HwzRUbcXD=dbN37mkBo~?OiRzm zD=aE*?&|KDI%C1&B`epgTfceB)}6cd9yoaD$gwl$&R@8E>+XXm&tANI^Y;D6&tJZN z|MBy0^iuXEKug|xx;TbdoK8-V_|kCviX2Oi#Rttxoh=NZHCB>C&H)5)rCP=hiM=dgEc1g|nhz+JOa3z1E&= z)f|VrC6{@q1o?|`*u*rfbl^J?z`U%Wi3Ll9I*OPylNgOE9J_iPouZhR zc_>^uF3WL9rr{^wkq<1-tlujLoVIV`m1DbArjVd|?m#kAnq-l|iJJ`)+g|Z3W?*61 Xav;deQY9=A=ye89S3j3^P6k44ofy`glX(eb^9A^XxB>c7MO|Hd=_Tdo3;2L1mvrhpha6aH%g$w~k9Cj8f({9mX4zxJg6T9f{3O#H9W z|6ga~f2|4sH75Pnp8Q{H;(tw`IFLQzzZOs#P$N*PA4~$30o8*Q0~tUq5Ge=)!q$KY z0!fG#APIB>SP-ZHguvp+vJgS26)=?$F2qcb31D-eT$mwHV<8p+9SIf(ssy4fma@Nq zAre^<PYyZ{^nK z2?57+b%irEb&s7nprEo=dZp&s^9K%SX}*1&%83~morVmcBDAnF+ zR5-&p!{3p|Kf&%RAJfJ^$~PuBx!mSsS#w0P!smdFGas9!w7}u8xrrhPj11L|L1xJ- SO`ZY$&fw|l=d#Wzp$PzS^gWUQ literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/switch.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/switch.png new file mode 100755 index 0000000000000000000000000000000000000000..02717ea0f9ceb15999ae72fd294eb35bbdcb1274 GIT binary patch literal 885 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(eb#|QX?xB>xGB|xyS$_2=p3I5Lp45AqD@U@_<2HQWE4B z%)rRR%FfBf&C4$!EG8}~B`qT>uc)M|uBmHaWNd0~ZDVKWlY9h9uXOrn3SB7 zmtRm=TvA)#(%RP5(>H1M+<6NYEnT)^?Yi}wcI-cJ@X(PHCr_O^bMeN_d-oqcefI3- z>o@N{eE#zF+qdsOe*OOQ_wT<=oJ)Yw&*B2EP0LUq63mw&n8Q_rCv$e*R|f`I`=<25?%*oaJn=EG>v2x;uopWX`UDT_T#{JR#dZ{^s$(xtIq%YrPGRvHx z;?JPqGU?9@q1actQ~rE@f2EthoynRbCZZbtks90 zD<;0I46~PIez#n|qxG8i=j}GHCzfWJ8&^LKpRm5C{bsbM(Hvc4Ri*pSS`L?#c~4i- dW4$^l{`STRCm9`9w*ljm!PC{xWt~$(69D~t#H#=R literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/assets/images/task-icons/switch_hover.png b/dolphinscheduler-ui-next/src/assets/images/task-icons/switch_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..0f9f0c152f0ec9d09f94a37f8c38c7573bd37e91 GIT binary patch literal 825 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P3?%12mYf5m7>k44ofy`glX(eby9fA$xB>+m z{{IhM_1|Itf6qz(t>^yNnDXCv=6}OU|Fx$6*PQuZZ_?zI1! z6G2FK@_%ih8X%hRUvtub?TP<2fb4z{TVuk1jeZbUdjd!n$ObCY1TrT6R|kqu1PN*Z z4FR&j3P1(|HG&m@#DPYEr9dJul^`}m5KIEu5M@Ad6a+R0Y8qGz$QFpd%hzw-zyI*@)0Z#bzJ34kzf~%!#+I+SNZkWQ$*pQp|u4r${eTD_^4nOstIxVqtPUAe@ ziMCZ@J`>9vPCv5QpRh!QoAK%QH!q%UHyGBQ}dTF$@bqo-FSFT>WLQ{{RR^R~JM*B$#*y{^=GU9{wU?ia;#YwP&_ aE5&!eZ5FeRKCS|cD+W(jKbLh*2~7Y$Uz<$; literal 0 HcmV?d00001 diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts index b26fd0ded5..f49adf8d9c 100644 --- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts +++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts @@ -286,6 +286,17 @@ const project = { confirm: 'Confirm', cancel: 'Cancel', delete_confirm: 'Delete?' + }, + dag: { + createWorkflow: "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' } } diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts index c5f4264b9e..517f819c07 100644 --- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts +++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts @@ -286,6 +286,17 @@ const project = { confirm: '确定', cancel: '取消', delete_confirm: '确定删除吗?' + }, + dag: { + createWorkflow: "创建工作流", + search: '搜索', + download_png: '下载工作流图片', + fullscreen_open: '全屏', + fullscreen_close: '退出全屏', + workflow_version: '工作流版本信息', + save: '保存', + close: '关闭', + format: '格式化' } } diff --git a/dolphinscheduler-ui-next/src/router/modules/projects.ts b/dolphinscheduler-ui-next/src/router/modules/projects.ts index 5fcbba2c98..56454a53fd 100644 --- a/dolphinscheduler-ui-next/src/router/modules/projects.ts +++ b/dolphinscheduler-ui-next/src/router/modules/projects.ts @@ -46,6 +46,22 @@ export default { title: '工作流监控', showSide: true } + }, + { + path: '/projects/:projectCode/workflow/definitions/create', + name: 'workflow-definition-create', + component: components['workflow-definition-create'], + meta: { + title: '创建工作流定义', + }, + }, + { + path: '/projects/:projectCode/workflow/definitions/:code', + name: 'workflow-definition-details', + component: components['workflow-definition-details'], + meta: { + title: '工作流定义详情', + }, } ] } diff --git a/dolphinscheduler-ui-next/src/service/modules/task-definition/index.ts b/dolphinscheduler-ui-next/src/service/modules/task-definition/index.ts index c2c00204cc..0770c8668b 100644 --- a/dolphinscheduler-ui-next/src/service/modules/task-definition/index.ts +++ b/dolphinscheduler-ui-next/src/service/modules/task-definition/index.ts @@ -21,7 +21,6 @@ import { ProjectCodeReq, TaskDefinitionListReq, TaskDefinitionJsonReq, - GenNumReq, CodeReq, TaskDefinitionJsonObjReq, ReleaseStateReq, @@ -51,13 +50,15 @@ export function save( } export function genTaskCodeList( - params: GenNumReq, - projectCode: ProjectCodeReq -): any { - return axios({ + num: number, + projectCode: number +) { + return axios.request({ url: `/projects/${projectCode}/task-definition/gen-task-codes`, method: 'get', - params + params: { + genNum: num + } }) } diff --git a/dolphinscheduler-ui-next/src/service/modules/task-definition/types.ts b/dolphinscheduler-ui-next/src/service/modules/task-definition/types.ts index e0d75f2964..2207e540da 100644 --- a/dolphinscheduler-ui-next/src/service/modules/task-definition/types.ts +++ b/dolphinscheduler-ui-next/src/service/modules/task-definition/types.ts @@ -37,10 +37,6 @@ interface TaskDefinitionJsonReq { taskDefinitionJson: string } -interface GenNumReq { - genNum: number -} - interface CodeReq { code: number } diff --git a/dolphinscheduler-ui-next/src/utils/index.ts b/dolphinscheduler-ui-next/src/utils/index.ts index efca1e89ce..4639c2ce1c 100644 --- a/dolphinscheduler-ui-next/src/utils/index.ts +++ b/dolphinscheduler-ui-next/src/utils/index.ts @@ -17,10 +17,12 @@ import mapping from './mapping' import regex from './regex' +import truncateText from './truncate-text' const utils = { mapping, - regex + regex, + truncateText, } export default utils diff --git a/dolphinscheduler-ui-next/src/utils/truncate-text.ts b/dolphinscheduler-ui-next/src/utils/truncate-text.ts new file mode 100644 index 0000000000..2605ac0b05 --- /dev/null +++ b/dolphinscheduler-ui-next/src/utils/truncate-text.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/** +* truncateText('ALongText', 4) => 'ALon...' +* @param {number} limit +* @param {string} text +* Each Chinese character is equal to two chars +*/ +export default function truncateText(text: string, n: number) { + const exp = /[\u4E00-\u9FA5]/ + let res = '' + let len = text.length + let chinese = text.match(new RegExp(exp, 'g')) + if (chinese) { + len += chinese.length + } + if (len > n) { + let i = 0 + let acc = 0 + while (true) { + let char = text[i] + if (exp.test(char)) { + acc += 2 + } else { + acc++ + } + if (acc > n) break + res += char + i++ + } + res += '...' + } else { + res = text + } + return res +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/index.tsx b/dolphinscheduler-ui-next/src/views/projects/index.tsx new file mode 100644 index 0000000000..e6769c4d45 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/index.tsx @@ -0,0 +1,27 @@ +/* + * 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 } from 'vue' + +export default defineComponent({ + name: "Projects", + setup() { + return () => ( +
Projects
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/task/config.ts b/dolphinscheduler-ui-next/src/views/projects/task/config.ts new file mode 100644 index 0000000000..f19efb7de6 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/task/config.ts @@ -0,0 +1,67 @@ +/* + * 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. + */ + +export const ALL_TASK_TYPES:any = { + SHELL: { + alias: 'SHELL', + }, + SUB_PROCESS: { + alias: 'SUB_PROCESS', + }, + PROCEDURE: { + alias: 'PROCEDURE', + }, + SQL: { + alias: 'SQL', + }, + SPARK: { + alias: 'SPARK', + }, + FLINK: { + alias: 'FLINK', + }, + MR: { + alias: 'MapReduce', + }, + PYTHON: { + alias: 'PYTHON', + }, + DEPENDENT: { + alias: 'DEPENDENT', + }, + HTTP: { + alias: 'HTTP', + }, + DATAX: { + alias: 'DataX', + }, + PIGEON: { + alias: 'PIGEON', + }, + SQOOP: { + alias: 'SQOOP', + }, + CONDITIONS: { + alias: 'CONDITIONS', + }, + SWITCH: { + alias: 'SWITCH', + }, + SEATUNNEL: { + alias: 'WATERDROP', + } +}; \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/task/task-config.tsx b/dolphinscheduler-ui-next/src/views/projects/task/task-config.tsx new file mode 100644 index 0000000000..3ae6873b06 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/task/task-config.tsx @@ -0,0 +1,27 @@ +/* + * 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 } from 'vue' + +export default defineComponent({ + name: "TaskConfigModal", + setup() { + return () => ( +
TaskConfigModal
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/dag-canvas.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-canvas.tsx new file mode 100644 index 0000000000..797c876e8b --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-canvas.tsx @@ -0,0 +1,60 @@ +/* + * 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, ref, inject } from 'vue' +import Styles from './dag.module.scss' +import type { PropType, Ref } from 'vue' +import type { Dragged } from './dag' +import { useCanvasInit, useGraphOperations, useCellActive, useCanvasDrop } from './dag-hooks'; +import { useRoute } from 'vue-router' + +const props = { + dragged: { + type: Object as PropType>, + default: ref({ + x: 0, + y: 0, + type: '' + }), + } +} + +export default defineComponent({ + name: "workflow-dag-canvas", + props, + setup(props, context) { + const readonly = inject('readonly', ref(false)); + const graph = inject('graph', ref()); + const route = useRoute(); + const projectCode = route.params.projectCode as string; + + const { paper, minimap, container } = useCanvasInit({ readonly, graph }); + + // Change the style on cell hover and select + useCellActive({ graph }); + + // Drop sidebar item in canvas + const { onDrop, onDragenter, onDragover, onDragleave } = useCanvasDrop({ readonly, dragged: props.dragged, graph, container, projectCode }); + + return () => ( +
+
+
+
+ ); + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/dag-config.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-config.ts new file mode 100644 index 0000000000..3f8238f6c0 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-config.ts @@ -0,0 +1,339 @@ +/* + * 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. + */ + +export const X6_NODE_NAME = 'dag-task' +export const X6_EDGE_NAME = 'dag-edge' +export const X6_PORT_OUT_NAME = 'dag-port-out' + +const EDGE_COLOR = '#999999' +const BG_BLUE = '#DFE9F7' +const BG_WHITE = '#FFFFFF' +const NODE_BORDER = '#CCCCCC' +const TITLE = '#333333' +const STROKE_BLUE = '#288FFF' +const NODE_SHADOW = 'drop-shadow(3px 3px 4px rgba(0, 0, 0, 0.2))' +const EDGE_SHADOW = 'drop-shadow(3px 3px 2px rgba(0, 0, 0, 0.2))' + +export const PORT = { + groups: { + [X6_PORT_OUT_NAME]: { + position: { + name: 'absolute', + args: { + x: 200, + y: 24 + } + }, + markup: [ + { + tagName: 'g', + selector: 'body', + children: [ + { + tagName: 'circle', + selector: 'circle-outer' + }, + { + tagName: 'text', + selector: 'plus-text' + }, + { + tagName: 'circle', + selector: 'circle-inner' + } + ] + } + ], + attrs: { + body: { + magnet: true + }, + 'plus-text': { + fontSize: 12, + fill: NODE_BORDER, + text: '+', + textAnchor: 'middle', + x: 0, + y: 3 + }, + 'circle-outer': { + stroke: NODE_BORDER, + strokeWidth: 1, + r: 6, + fill: BG_WHITE + }, + 'circle-inner': { + r: 4, + fill: 'transparent' + } + } + } + } +} + +export const PORT_HOVER = { + groups: { + [X6_PORT_OUT_NAME]: { + attrs: { + 'circle-outer': { + stroke: STROKE_BLUE, + fill: BG_BLUE, + r: 8 + }, + 'circle-inner': { + fill: STROKE_BLUE, + r: 6 + } + } + } + } +} + +export const PORT_SELECTED = { + groups: { + [X6_PORT_OUT_NAME]: { + attrs: { + 'plus-text': { + fill: STROKE_BLUE + }, + 'circle-outer': { + stroke: STROKE_BLUE, + fill: BG_WHITE + } + } + } + } +} + +export const NODE_STATUS_MARKUP = [{ + tagName: 'foreignObject', + selector: 'fo', + children: [ + { + tagName: 'body', + selector: 'fo-body', + ns: 'http://www.w3.org/1999/xhtml', + children: [{ + tagName: 'div', + selector: 'status' + }] + } + ] +}] + +export const NODE = { + width: 220, + height: 48, + markup: [ + { + tagName: 'rect', + selector: 'body', + className: 'dag-task-body' + }, + { + tagName: 'image', + selector: 'image' + }, + { + tagName: 'text', + selector: 'title' + } + ], + attrs: { + body: { + refWidth: '100%', + refHeight: '100%', + rx: 6, + ry: 6, + pointerEvents: 'visiblePainted', + fill: BG_WHITE, + stroke: NODE_BORDER, + strokeWidth: 1, + strokeDasharray: 'none', + filter: 'none' + }, + image: { + width: 30, + height: 30, + refX: 12, + refY: 9 + }, + title: { + refX: 45, + refY: 18, + fontFamily: 'Microsoft Yahei', + fontSize: 12, + fontWeight: 'bold', + fill: TITLE, + strokeWidth: 0 + }, + fo: { + refX: '46%', + refY: -25, + width: 18, + height: 18 + } + }, + ports: { + ...PORT, + items: [ + { + id: X6_PORT_OUT_NAME, + group: X6_PORT_OUT_NAME + } + ] + } +} + +export const NODE_HOVER = { + attrs: { + body: { + fill: BG_BLUE, + stroke: STROKE_BLUE, + strokeDasharray: '5,2' + }, + title: { + fill: STROKE_BLUE + } + } +} + +export const NODE_SELECTED = { + attrs: { + body: { + filter: NODE_SHADOW, + fill: BG_WHITE, + stroke: STROKE_BLUE, + strokeDasharray: '5,2', + strokeWidth: '1.5' + }, + title: { + fill: STROKE_BLUE + } + } +} + +export const EDGE = { + attrs: { + line: { + stroke: EDGE_COLOR, + strokeWidth: 1, + targetMarker: { + tagName: 'path', + fill: EDGE_COLOR, + strokeWidth: 0, + d: 'M 6 -3 0 0 6 3 Z' + }, + filter: 'none' + } + }, + connector: { + name: 'rounded' + }, + router: { + name: 'manhattan', + args: { + endDirections: ['top', 'bottom', 'left'] + } + }, + defaultLabel: { + markup: [ + { + tagName: 'rect', + selector: 'body' + }, + { + tagName: 'text', + selector: 'label' + } + ], + attrs: { + label: { + fill: EDGE_COLOR, + fontSize: 14, + textAnchor: 'middle', + textVerticalAnchor: 'middle', + pointerEvents: 'none' + }, + body: { + ref: 'label', + fill: BG_WHITE, + stroke: EDGE_COLOR, + strokeWidth: 1, + rx: 4, + ry: 4, + refWidth: '140%', + refHeight: '140%', + refX: '-20%', + refY: '-20%' + } + }, + position: { + distance: 0.5, + options: { + absoluteDistance: true, + reverseDistance: true + } + } + } +} + +export const EDGE_HOVER = { + attrs: { + line: { + stroke: STROKE_BLUE, + targetMarker: { + fill: STROKE_BLUE + } + } + }, + defaultLabel: { + attrs: { + label: { + fill: STROKE_BLUE + }, + body: { + fill: BG_WHITE, + stroke: STROKE_BLUE + } + } + } +} + +export const EDGE_SELECTED = { + attrs: { + line: { + stroke: STROKE_BLUE, + targetMarker: { + fill: STROKE_BLUE + }, + strokeWidth: 2, + filter: EDGE_SHADOW + } + }, + defaultLabel: { + attrs: { + label: { + fill: STROKE_BLUE + }, + body: { + fill: BG_WHITE, + stroke: STROKE_BLUE + } + } + } +} diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/dag-hooks.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-hooks.ts new file mode 100644 index 0000000000..0823ad34a7 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-hooks.ts @@ -0,0 +1,32 @@ +/* + * 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 { useCanvasInit } from './use-canvas-init'; +import { useGraphOperations } from './use-graph-operations'; +import { useCellActive } from './use-cell-active'; +import { useSidebarDrag } from './use-sidebar-drag'; +import { useCanvasDrop } from './use-canvas-drop'; +import { useNodeSearch } from './use-node-search'; + +export { + useCanvasInit, + useGraphOperations, + useCellActive, + useSidebarDrag, + useCanvasDrop, + useNodeSearch, +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/dag-sidebar.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-sidebar.tsx new file mode 100644 index 0000000000..c1c6b3d6fc --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-sidebar.tsx @@ -0,0 +1,68 @@ +/* + * 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 type { PropType, Ref } from 'vue'; +import type { Dragged } from './dag'; +import { defineComponent, ref, inject } from 'vue' +import { ALL_TASK_TYPES } from '../task/config'; +import { useSidebarDrag } from './dag-hooks'; +import Styles from './dag.module.scss'; + +const props = { + dragged: { + type: Object as PropType>, + default: ref({ + x: 0, + y: 0, + type: '' + }), + }, +} + +export default defineComponent({ + name: "workflow-dag-sidebar", + props, + setup(props) { + const readonly = inject('readonly', ref(false)) + const dragged = props.dragged; + const { onDragStart } = useSidebarDrag({ + readonly, + dragged + }); + const allTaskTypes = Object.keys(ALL_TASK_TYPES).map(type => ({ + type, + ...ALL_TASK_TYPES[type] + })); + + return () => ( +
+ { + allTaskTypes.map(task => ( +
onDragStart(e, task.type)} + > + + {task.alias} +
+ )) + } +
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/dag-toolbar.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-toolbar.tsx new file mode 100644 index 0000000000..599664cf54 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/dag-toolbar.tsx @@ -0,0 +1,180 @@ +/* + * 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, ref, inject } from 'vue' +import { useI18n } from 'vue-i18n' +import Styles from './dag.module.scss' +import { NTooltip, NIcon, NButton, NSelect } from 'naive-ui'; +import { SearchOutlined, DownloadOutlined, FullscreenOutlined, FullscreenExitOutlined, InfoCircleOutlined, FormatPainterOutlined } from '@vicons/antd'; +import { useNodeSearch } from './dag-hooks'; +import { DataUri } from '@antv/x6' +import { useFullscreen } from '@vueuse/core'; +import { useRouter } from 'vue-router'; + +export default defineComponent({ + name: "workflow-dag-toolbar", + setup(props, context) { + const { t } = useI18n(); + const graph = inject('graph', ref()); + const router = useRouter(); + + /** + * Node search and navigate + */ + const { + searchNode, + getAllNodes, + allNodes, + toggleSearchInput, + searchInputVisible + } = useNodeSearch({ graph }); + + /** + * Download Workflow Image + * @param {string} fileName + * @param {string} bgColor + */ + const downloadPNG = (options = { fileName: 'dag', bgColor: '#f2f3f7' }) => { + const { fileName, bgColor } = options; + graph.value?.toPNG( + (dataUri: string) => { + DataUri.downloadDataUri(dataUri, `${fileName}.png`) + }, + { + padding: { + top: 50, + right: 50, + bottom: 50, + left: 50 + }, + backgroundColor: bgColor + } + ) + } + + /** + * Toggle fullscreen + */ + const { isFullscreen, toggle } = useFullscreen(); + + + /** + * Open workflow version modal + */ + const openVersionModal = () => { + //TODO, same as the version popup in the workflow list page + } + + /** + * Open DAG format modal + */ + const openDagFormatModal = () => { + + } + + const onClose = () => { + router.go(-1) + } + + return () => ( +
+ {t("project.dag.createWorkflow")} +
+ {/* Search node */} + ( + ( + + + + ) + }} /> + ), + default: () => t('project.dag.search') + }}> + +
+ +
+ {/* Download workflow PNG */} + ( + downloadPNG()} v-slots={{ + icon: () => ( + + + + ) + }} /> + ), + default: () => t('project.dag.download_png') + }}> + + {/* Toggle fullscreen */} + ( + ( + + {isFullscreen.value ? : } + + ) + }} /> + ), + default: () => isFullscreen.value ? t('project.dag.fullscreen_close') : t('project.dag.fullscreen_open') + }}> + + {/* DAG Format */} + ( + ( + + + + ) + }} /> + ), + default: () => t('project.dag.format') + }}> + + {/* Version info */} + ( + ( + + + + ) + }} /> + ), + default: () => t('project.dag.workflow_version') + }}> + + {/* Save workflow */} + {t('project.dag.save')} + {/* Return to previous page */} + {t('project.dag.close')} +
+
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/dag.module.scss b/dolphinscheduler-ui-next/src/views/projects/workflow/dag.module.scss new file mode 100644 index 0000000000..2298363907 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/dag.module.scss @@ -0,0 +1,217 @@ +/* + * 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. + */ + +$blue: #288fff; +$blueBg: rgba(40, 143, 255, 0.1); +$toolbarHeight: 50px; + +.dag { + height: 100%; +} + +.content { + display: flex; + height: calc(100% - $toolbarHeight - 20px); + margin-top: 20px; +} + +.toolbar { + height: $toolbarHeight; + display: flex; + align-items: center; + padding: 0 20px; + border: 1px solid var(--n-border-color); + border-radius: 4px; + justify-content: space-between; +} + +.canvas { + width: 100%; + height: 100%; + position: relative; + overflow: hidden; + display: flex; +} + +.paper { + width: 100%; + height: 100%; +} + +.sidebar { + width: 190px; + height: 100%; + margin-right: 20px; +} + +.workflow-name { + font-size: 14px; +} + +.draggable { + display: flex; + width: 100%; + 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); + box-sizing: border-box; + cursor: move; + font-size: 12px; + + .sidebar-icon { + display: block; + width: 18px; + height: 18px; + background-size: 100% 100%; + margin-right: 10px; + &.icon-shell { + background-image: url("../../../assets/images/task-icons/shell.png"); + } + &.icon-sub_process { + background-image: url("../../../assets/images/task-icons/sub_process.png"); + } + &.icon-procedure { + background-image: url("../../../assets/images/task-icons/procedure.png"); + } + &.icon-sql { + background-image: url("../../../assets/images/task-icons/sql.png"); + } + &.icon-flink { + background-image: url("../../../assets/images/task-icons/flink.png"); + } + &.icon-mr { + background-image: url("../../../assets/images/task-icons/mr.png"); + } + &.icon-python { + background-image: url("../../../assets/images/task-icons/python.png"); + } + &.icon-dependent { + background-image: url("../../../assets/images/task-icons/dependent.png"); + } + &.icon-http { + background-image: url("../../../assets/images/task-icons/http.png"); + } + &.icon-datax { + background-image: url("../../../assets/images/task-icons/datax.png"); + } + &.icon-pigeon { + background-image: url("../../../assets/images/task-icons/pigeon.png"); + } + &.icon-sqoop { + background-image: url("../../../assets/images/task-icons/sqoop.png"); + } + &.icon-conditions { + background-image: url("../../../assets/images/task-icons/conditions.png"); + } + &.icon-seatunnel { + background-image: url("../../../assets/images/task-icons/seatunnel.png"); + } + &.icon-spark { + background-image: url("../../../assets/images/task-icons/spark.png"); + } + &.icon-switch { + background-image: url("../../../assets/images/task-icons/switch.png"); + } + } + + &: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"); + } + } + } +} + +.minimap { + position: absolute; + right: 0px; + bottom: 0px; + border: dashed 1px #e4e4e4; + z-index: 9; +} + +.toolbar-right-part { + display: flex; + align-items: center; + .toolbar-right-item { + margin-right: 10px; + } + .node-selector { + width: 0; + overflow: hidden; + transition: all 0.5s; + margin-right: 0; + + &.visible { + width: 200px; + margin-right: 10px; + } + } +} diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/dag.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/dag.tsx new file mode 100644 index 0000000000..2f0ce4a03d --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/dag.tsx @@ -0,0 +1,67 @@ +/* + * 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 type { Graph } from '@antv/x6'; +import { defineComponent, ref, provide } from 'vue' +import DagToolbar from './dag-toolbar'; +import DagCanvas from './dag-canvas'; +import DagSidebar from './dag-sidebar'; +import Styles from './dag.module.scss'; +import "./x6-style.scss"; + + +export interface Dragged { + x: number; + y: number; + type: string; +} + +export default defineComponent({ + name: "workflow-dag", + setup(props, context) { + + // Whether the graph can be operated + const readonly = ref(false); + provide('readonly', readonly); + + const graph = ref(); + provide('graph', graph); + + // The sidebar slots + const toolbarSlots = { + left: context.slots.toolbarLeft, + right: context.slots.toolbarRight + } + + // The element currently being dragged up + const dragged = ref({ + x: 0, + y: 0, + type: '' + }); + + return () => ( +
+ +
+ + +
+
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/hook-demo.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/hook-demo.ts new file mode 100644 index 0000000000..0e5f0e0855 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/hook-demo.ts @@ -0,0 +1,40 @@ +/* + * 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, onMounted, Ref, onUnmounted } from 'vue' + +interface Options { + // readonly: Ref; + // canvas: Ref; +} + +/** + * Canvas Init + * 1. Bind the graph to the dom + * 2. Redraw when the page is resized + * 3. Register custom graphics + */ +export function useCanvasInit(options: Options) { + + // Whether the graph can be operated + const { } = options; + + + return { + + } +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-drop.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-drop.ts new file mode 100644 index 0000000000..32fb0d0dd1 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-drop.ts @@ -0,0 +1,70 @@ +/* + * 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 type { Ref } from 'vue'; +import type { Graph } from '@antv/x6' +import type { Dragged } from './dag' +import { genTaskCodeList } from '@/service/modules/task-definition'; +import { useGraphOperations } from './dag-hooks'; + +interface Options { + readonly: Ref; + graph: Ref; + container: Ref; + dragged: Ref; + projectCode: string; +} + +/** + * Drop sidebar item in canvas + */ +export function useCanvasDrop(options: Options) { + + const { readonly, graph, container, dragged, projectCode } = options; + + const { addNode } = useGraphOperations({ graph }); + + const onDrop = (e: DragEvent) => { + e.stopPropagation(); + e.preventDefault(); + if (readonly.value) { + return; + } + if (dragged.value && graph.value && container.value && projectCode) { + const { type, x: eX, y: eY } = dragged.value; + const { x, y } = graph.value.clientToLocal(e.clientX, e.clientY); + const genNums = 1; + genTaskCodeList(genNums, Number(projectCode)) + .then((res) => { + const [code] = res + addNode(code + '', type, { x: x - eX, y: y - eY }) + // openTaskConfigModel(code, type) + }) + } + } + + const preventDefault = (e: DragEvent) => { + e.preventDefault(); + } + + return { + onDrop, + onDragenter: preventDefault, + onDragover: preventDefault, + onDragleave: preventDefault, + } +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-init.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-init.ts new file mode 100644 index 0000000000..16c4479d89 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-init.ts @@ -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 type { Node } from '@antv/x6'; +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'; + +interface Options { + readonly: Ref; + graph: Ref; +} + +/** + * Canvas Init + * 1. Bind the graph to the dom + * 2. Redraw when the page is resized + * 3. Register custom graphics + */ +export function useCanvasInit(options: Options) { + + // Whether the graph can be operated + const { readonly, graph } = options; + + const paper = ref(); // The graph mount HTMLElement + const minimap = ref(); // The minimap mount HTMLElement + const container = ref(); // The container of paper and minimap + + /** + * Graph Init, bind graph to the dom + */ + function graphInit() { + return new Graph({ + container: paper.value, + selecting: { + enabled: true, + multiple: true, + rubberband: true, + rubberEdge: true, + movable: true, + showNodeSelectionBox: false + }, + scaling: { + min: 0.2, + max: 2 + }, + mousewheel: { + enabled: true, + modifiers: ['ctrl', 'meta'] + }, + scroller: true, + grid: { + size: 10, + visible: true + }, + snapline: true, + minimap: { + enabled: true, + container: minimap.value, + scalable: false, + width: 200, + height: 120 + }, + interacting: { + edgeLabelMovable: false, + nodeMovable: !readonly.value, + magnetConnectable: !readonly.value + }, + connecting: { + // Whether multiple edges can be created between the same start node and end + allowMulti: false, + // Whether a point is allowed to connect to a blank position on the canvas + allowBlank: false, + // The start node and the end node are the same node + allowLoop: false, + // Whether an edge is allowed to link to another edge + allowEdge: false, + // Whether edges are allowed to link to nodes + allowNode: true, + // Whether to allow edge links to ports + allowPort: false, + // Whether all available ports or nodes are highlighted when you drag the edge + highlight: true, + createEdge() { + return graph.value?.createEdge({ shape: X6_EDGE_NAME }) + } + }, + highlighting: { + nodeAvailable: { + name: 'className', + args: { + className: 'available' + } + }, + magnetAvailable: { + name: 'className', + args: { + className: 'available' + } + }, + magnetAdsorbed: { + name: 'className', + args: { + className: 'adsorbed' + } + } + } + }) + } + + onMounted(() => { + graph.value = graphInit(); + // Make sure the edge starts with node, not port + graph.value.on('edge:connected', ({ isNew, edge }) => { + if (isNew) { + const sourceNode = edge.getSourceNode() as Node + edge.setSource(sourceNode) + } + }) + }) + + /** + * 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); + }, 200) + onMounted(() => { + window.addEventListener('resize', paperResize) + }) + onUnmounted(() => { + window.removeEventListener('resize', paperResize) + }) + + /** + * Register custom cells + */ + function registerCustomCells() { + Graph.unregisterNode(X6_NODE_NAME) + Graph.unregisterEdge(X6_EDGE_NAME) + Graph.registerNode(X6_NODE_NAME, { ...NODE }) + Graph.registerEdge(X6_EDGE_NAME, { ...EDGE }) + } + onMounted(() => { + registerCustomCells() + }) + + return { + graph, + paper, + minimap, + container + } +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/use-cell-active.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/use-cell-active.ts new file mode 100644 index 0000000000..341f3d0bae --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/use-cell-active.ts @@ -0,0 +1,154 @@ +/* + * 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 type { Ref } from 'vue' +import { onMounted, ref } from 'vue'; +import type { Node, Graph, Edge, Cell } from '@antv/x6' +import _ from 'lodash'; +import { + X6_PORT_OUT_NAME, + PORT_HOVER, + PORT_SELECTED, + PORT, + NODE, + NODE_HOVER, + NODE_SELECTED, + EDGE, + EDGE_SELECTED, + EDGE_HOVER +} from './dag-config'; + +interface Options { + graph: Ref +} + +/** + * Change the style on cell hover and select + */ +export function useCellActive(options: Options) { + + const { graph } = options; + const hoverCell = ref(); + + const isStatusIcon = (tagName: string) => { + if (!tagName) return false; + return tagName.toLocaleLowerCase() === 'em' || tagName.toLocaleLowerCase() === 'body' + } + + function setEdgeStyle(edge: Edge) { + const isHover = edge === hoverCell.value; + const isSelected = graph.value?.isSelected(edge) + // TODO + // const labelName = this.getEdgeLabelName ? this.getEdgeLabelName(edge) : '' + let edgeProps = null + + if (isHover) { + edgeProps = _.merge(_.cloneDeep(EDGE), EDGE_HOVER) + } else if (isSelected) { + edgeProps = _.merge(_.cloneDeep(EDGE), EDGE_SELECTED) + } else { + edgeProps = _.cloneDeep(EDGE) + } + + edge.setAttrs(edgeProps.attrs) + edge.setLabels([ + { + ..._.merge( + { + attrs: _.cloneDeep(edgeProps.defaultLabel.attrs) + }, + // { + // attrs: { label: { text: labelName } } + // } + ) + } + ]) + } + + function setNodeStyle(node: Node) { + const isHover = node === hoverCell.value + const isSelected = graph.value?.isSelected(node) + const portHover = _.cloneDeep(PORT_HOVER.groups[X6_PORT_OUT_NAME].attrs) + const portSelected = _.cloneDeep(PORT_SELECTED.groups[X6_PORT_OUT_NAME].attrs) + const portDefault = _.cloneDeep(PORT.groups[X6_PORT_OUT_NAME].attrs) + const nodeHover = _.merge(_.cloneDeep(NODE.attrs), NODE_HOVER.attrs) + const nodeSelected = _.merge(_.cloneDeep(NODE.attrs), NODE_SELECTED.attrs) + + let img = null + let nodeAttrs = null + let portAttrs = null + + if (isHover || isSelected) { + img = `/src/assets/images/task-icons/${node.data.taskType.toLocaleLowerCase()}_hover.png` + if (isHover) { + nodeAttrs = nodeHover + portAttrs = _.merge(portDefault, portHover) + } else { + nodeAttrs = nodeSelected + portAttrs = _.merge(portDefault, portSelected) + } + } else { + img = `/src/assets/images/task-icons/${node.data.taskType.toLocaleLowerCase()}.png` + nodeAttrs = NODE.attrs + portAttrs = portDefault + } + node.setAttrByPath('image/xlink:href', img) + node.setAttrs(nodeAttrs) + node.setPortProp( + X6_PORT_OUT_NAME, + 'attrs', + portAttrs + ) + } + + function updateCellStyle(cell: Cell) { + if (cell.isEdge()) { + setEdgeStyle(cell) + } else if (cell.isNode()) { + setNodeStyle(cell) + } + } + + onMounted(() => { + if (graph.value) { + // hover + graph.value.on('cell:mouseenter', (data) => { + const { cell, e } = data + if (!isStatusIcon(e.target.tagName)) { + hoverCell.value = cell + updateCellStyle(cell) + } + }) + graph.value.on('cell:mouseleave', ({ cell }) => { + hoverCell.value = undefined + updateCellStyle(cell) + }) + + // select + graph.value.on('cell:selected', ({ cell }) => { + updateCellStyle(cell) + }) + graph.value.on('cell:unselected', ({ cell }) => { + updateCellStyle(cell) + }) + } + }) + + return { + hoverCell + } +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/use-graph-operations.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/use-graph-operations.ts new file mode 100644 index 0000000000..c48eb6a214 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/use-graph-operations.ts @@ -0,0 +1,157 @@ +/* + * 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 type { Ref } from 'vue' +import type { Node, Graph, Edge } from '@antv/x6' +import { + X6_NODE_NAME, + X6_EDGE_NAME, +} from './dag-config' +import { ALL_TASK_TYPES } from '../task/config'; +import utils from '@/utils'; + +interface Options { + graph: Ref +} + +type Coordinate = { x: number; y: number; } + +/** + * Expose some graph operation methods + * @param {Options} options + */ +export function useGraphOperations(options: Options) { + + const { graph } = options; + + + /** + * Build edge metadata + * @param {string} sourceId + * @param {string} targetId + * @param {string} label + */ + function buildEdgeMetadata(sourceId: string, targetId: string, label: string = ''): Edge.Metadata { + return { + shape: X6_EDGE_NAME, + source: { + cell: sourceId + }, + target: { + cell: targetId + }, + labels: label ? [label] : undefined + } + } + + /** + * Build node metadata + * @param {string} id + * @param {string} taskType + * @param {Coordinate} coordinate Default is { x: 100, y: 100 } + */ + function buildNodeMetadata(id: string, type: string, taskName: string, coordinate: Coordinate = { x: 100, y: 100 }): Node.Metadata { + const truncation = taskName ? utils.truncateText(taskName, 18) : id; + return { + id: id, + shape: X6_NODE_NAME, + x: coordinate.x, + y: coordinate.y, + data: { + taskType: type, + taskName: taskName || id + }, + attrs: { + image: { + // Use href instead of xlink:href, you may lose the icon when downloadPNG + 'xlink:href': `/src/assets/images/task-icons/${type.toLocaleLowerCase()}.png` + }, + title: { + text: truncation + } + } + } + } + + /** + * Add a node to the graph + * @param {string} id + * @param {string} taskType + * @param {Coordinate} coordinate Default is { x: 100, y: 100 } + */ + function addNode(id: string, type: string, coordinate: Coordinate = { x: 100, y: 100 }) { + if (!ALL_TASK_TYPES[type]) { + console.warn(`taskType:${type} is invalid!`) + return + } + const node = buildNodeMetadata(id, type, '', coordinate) + graph.value?.addNode(node) + } + + /** + * Set node name by id + * @param {string} id + * @param {string} name + */ + function setNodeName(id: string, newName: string) { + const node = graph.value?.getCellById(id) + if (node) { + const truncation = utils.truncateText(newName, 18) + node.attr('title/text', truncation) + node.setData({ taskName: newName }) + } + } + + /** + * Get nodes + */ + function getNodes() { + const nodes = graph.value?.getNodes() + if (!nodes) return [] + return nodes.map((node) => { + const position = node.getPosition() + const data = node.getData() + return { + code: node.id, + position: position, + name: data.taskName, + type: data.taskType + } + }) + } + + /** + * Navigate to cell + * @param {string} code + */ + function navigateTo(code: string) { + if (!graph.value) return; + const cell = graph.value.getCellById(code) + graph.value.scrollToCell(cell, { animation: { duration: 600 } }) + graph.value.cleanSelection() + graph.value.select(cell) + }; + + return { + buildEdgeMetadata, + buildNodeMetadata, + addNode, + setNodeName, + getNodes, + navigateTo, + } +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/use-node-search.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/use-node-search.ts new file mode 100644 index 0000000000..0b26f309f1 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/use-node-search.ts @@ -0,0 +1,60 @@ +/* + * 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 type { Graph } from '@antv/x6'; +import { ref, Ref } from 'vue' +import { useGraphOperations } from './dag-hooks'; + + +interface Options { + graph: Ref; +} + +/** + * Node search and navigate + */ +export function useNodeSearch(options: Options) { + + const { graph } = options; + + const searchInputVisible = ref(false); + const allNodes = ref([]); + const toggleSearchInput = () => { + searchInputVisible.value = !searchInputVisible.value; + } + const { getNodes, navigateTo } = useGraphOperations({ graph }); + const searchNode = (val: string) => { + navigateTo(val) + } + const getAllNodes = () => { + const nodes = getNodes(); + allNodes.value = nodes.map(node => { + return { + label: node.name, + value: node.code + } + }) + } + + return { + searchNode, + getAllNodes, + allNodes, + toggleSearchInput, + searchInputVisible, + } +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/use-sidebar-drag.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/use-sidebar-drag.ts new file mode 100644 index 0000000000..b501453a25 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/use-sidebar-drag.ts @@ -0,0 +1,48 @@ +/* + * 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 type { Ref } from 'vue'; +import type { Dragged } from './dag'; + +interface Options { + readonly: Ref; + dragged: Ref; +} + +/** + * Sidebar drag + */ +export function useSidebarDrag(options: Options) { + + const { readonly, dragged } = options; + + const onDragStart = (e: DragEvent, type: string) => { + if (readonly.value) { + e.preventDefault() + return + } + dragged.value = { + x: e.offsetX, + y: e.offsetY, + type: type + } + } + + return { + onDragStart + } +} \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.module.scss b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.module.scss new file mode 100644 index 0000000000..182fdc3b05 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.module.scss @@ -0,0 +1,22 @@ +/* + * 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. + */ + +.container{ + width: 100%; + box-sizing: border-box; + height: calc(100vh - 100px); + } \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.tsx new file mode 100644 index 0000000000..eff2932110 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.tsx @@ -0,0 +1,38 @@ +/* + * 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 } from 'vue' +import Dag from './dag'; +import { NCard } from 'naive-ui'; +import styles from './workflow-definition-create.module.scss'; + +export default defineComponent({ + name: "WorkflowDefinitionCreate", + setup() { + + const slots = { + toolbarLeft: () => left-operations, + toolbarRight: () => right-operations + }; + + return () => ( + + + + ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-details.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-details.tsx new file mode 100644 index 0000000000..ea9c726e83 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-details.tsx @@ -0,0 +1,27 @@ +/* + * 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 } from 'vue' + +export default defineComponent({ + name: "WorkflowDefinitionDetails", + setup() { + return () => ( +
WorkflowDefinitionDetails
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-list.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-list.tsx new file mode 100644 index 0000000000..2878ba5ab0 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-list.tsx @@ -0,0 +1,27 @@ +/* + * 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 } from 'vue' + +export default defineComponent({ + name: "WorkflowDefinitionList", + setup() { + return () => ( +
WorkflowDefinitionList
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-details.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-details.tsx new file mode 100644 index 0000000000..137c442a87 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-details.tsx @@ -0,0 +1,27 @@ +/* + * 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 } from 'vue' + +export default defineComponent({ + name: "WorkflowInstanceDetails", + setup() { + return () => ( +
WorkflowInstanceDetails
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-list.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-list.tsx new file mode 100644 index 0000000000..619e6ca22d --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-list.tsx @@ -0,0 +1,27 @@ +/* + * 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 } from 'vue' + +export default defineComponent({ + name: "WorkflowInstanceList", + setup() { + return () => ( +
WorkflowInstanceList
+ ) + } +}) \ No newline at end of file diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/x6-style.scss b/dolphinscheduler-ui-next/src/views/projects/workflow/x6-style.scss new file mode 100644 index 0000000000..549be67ad0 --- /dev/null +++ b/dolphinscheduler-ui-next/src/views/projects/workflow/x6-style.scss @@ -0,0 +1,35 @@ +/* + * 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. + */ + + $STROKE_BLUE: #288fff; + $BG_WHITE: #ffffff; + + .x6-node[data-shape="dag-task"] { + &.available { + .dag-task-body { + stroke: $STROKE_BLUE; + stroke-width: 1; + stroke-dasharray: 5, 2; + } + &.adsorbed { + .dag-task-body { + stroke-width: 3; + } + } + } + } + \ No newline at end of file