@worktile/gantt 11.0.2 → 12.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/.all-contributorsrc +53 -0
  2. package/.angulardoc.json +4 -0
  3. package/.circleci/config.yml +17 -0
  4. package/.coveralls.yml +1 -0
  5. package/.docgenirc.js +64 -0
  6. package/.editorconfig +22 -0
  7. package/.prettierrc +24 -0
  8. package/.travis.yml +23 -0
  9. package/CHANGELOG.md +564 -0
  10. package/Dockerfile +4 -0
  11. package/LICENSE +21 -0
  12. package/README.md +116 -13
  13. package/angular.json +136 -0
  14. package/docs/guides/basic/components.md +54 -0
  15. package/docs/guides/basic/event.md +70 -0
  16. package/docs/guides/basic/index.md +4 -0
  17. package/docs/guides/basic/style.md +68 -0
  18. package/docs/guides/basic/type.md +70 -0
  19. package/docs/guides/basic/usage.md +189 -0
  20. package/docs/guides/index.md +5 -0
  21. package/docs/guides/intro/getting-started.md +79 -0
  22. package/docs/guides/intro/index.md +51 -0
  23. package/docs/index.md +0 -0
  24. package/example/browserslist +12 -0
  25. package/example/src/app/app-routing.module.ts +26 -0
  26. package/example/src/app/app.component.html +2 -0
  27. package/example/src/app/app.component.ts +11 -0
  28. package/example/src/app/app.module.ts +57 -0
  29. package/example/src/app/components/components.component.html +6 -0
  30. package/example/src/app/components/components.component.ts +33 -0
  31. package/example/src/app/configuration/parameters/api/zh-cn.js +350 -0
  32. package/example/src/app/configuration/parameters/doc/zh-cn.md +5 -0
  33. package/example/src/app/gantt/gantt.component.html +51 -0
  34. package/example/src/app/gantt/gantt.component.ts +119 -0
  35. package/example/src/app/gantt-advanced/component/flat.component.html +30 -0
  36. package/example/src/app/gantt-advanced/component/flat.component.ts +72 -0
  37. package/example/src/app/gantt-advanced/component/flat.scss +31 -0
  38. package/example/src/app/gantt-advanced/gantt-advanced.component.html +32 -0
  39. package/example/src/app/gantt-advanced/gantt-advanced.component.ts +34 -0
  40. package/example/src/app/gantt-advanced/mocks.ts +158 -0
  41. package/example/src/app/gantt-groups/gantt-groups.component.html +42 -0
  42. package/example/src/app/gantt-groups/gantt-groups.component.ts +62 -0
  43. package/example/src/app/gantt-range/gantt-range.component.html +66 -0
  44. package/example/src/app/gantt-range/gantt-range.component.ts +67 -0
  45. package/example/src/app/gantt-range/mocks.ts +150 -0
  46. package/example/src/app/helper.ts +38 -0
  47. package/example/src/assets/.gitkeep +0 -0
  48. package/example/src/environments/environment.prod.ts +3 -0
  49. package/example/src/environments/environment.ts +16 -0
  50. package/example/src/favicon.ico +0 -0
  51. package/example/src/index.html +13 -0
  52. package/example/src/main.ts +12 -0
  53. package/example/src/polyfills.ts +63 -0
  54. package/example/src/styles.scss +56 -0
  55. package/example/tsconfig.app.json +18 -0
  56. package/nginx.conf +17 -0
  57. package/package.json +113 -17
  58. package/packages/gantt/README.md +24 -0
  59. package/packages/gantt/karma.conf.js +46 -0
  60. package/packages/gantt/ng-package.json +7 -0
  61. package/packages/gantt/ng-package.prod.json +7 -0
  62. package/packages/gantt/package.json +16 -0
  63. package/packages/gantt/src/class/date-point.ts +14 -0
  64. package/{class/event.d.ts → packages/gantt/src/class/event.ts} +12 -6
  65. package/packages/gantt/src/class/group.ts +36 -0
  66. package/{class/index.d.ts → packages/gantt/src/class/index.ts} +0 -0
  67. package/packages/gantt/src/class/item.ts +129 -0
  68. package/packages/gantt/src/class/test/group.spec.ts +21 -0
  69. package/packages/gantt/src/class/test/item.spec.ts +102 -0
  70. package/packages/gantt/src/class/view-type.ts +7 -0
  71. package/packages/gantt/src/components/bar/bar-drag.ts +298 -0
  72. package/packages/gantt/src/components/bar/bar.component.html +17 -0
  73. package/packages/gantt/src/components/bar/bar.component.scss +169 -0
  74. package/packages/gantt/src/components/bar/bar.component.ts +109 -0
  75. package/packages/gantt/src/components/bar/test/bar.component.spec.ts +54 -0
  76. package/packages/gantt/src/components/bar/test/bar.drag.spec.ts +196 -0
  77. package/packages/gantt/src/components/calendar/calendar.component.html +52 -0
  78. package/packages/gantt/src/components/calendar/calendar.component.scss +77 -0
  79. package/packages/gantt/src/components/calendar/calendar.component.ts +100 -0
  80. package/packages/gantt/src/components/drag-backdrop/drag-backdrop.component.html +6 -0
  81. package/packages/gantt/src/components/drag-backdrop/drag-backdrop.component.scss +48 -0
  82. package/packages/gantt/src/components/drag-backdrop/drag-backdrop.component.ts +13 -0
  83. package/packages/gantt/src/components/icon/icon.component.scss +13 -0
  84. package/packages/gantt/src/components/icon/icon.component.ts +28 -0
  85. package/packages/gantt/src/components/icon/icons.ts +86 -0
  86. package/packages/gantt/src/components/links/links.component.html +19 -0
  87. package/packages/gantt/src/components/links/links.component.scss +27 -0
  88. package/packages/gantt/src/components/links/links.component.ts +263 -0
  89. package/packages/gantt/src/components/main/gantt-main.component.html +35 -0
  90. package/packages/gantt/src/components/main/gantt-main.component.ts +35 -0
  91. package/packages/gantt/src/components/range/range.component.html +8 -0
  92. package/packages/gantt/src/components/range/range.component.scss +35 -0
  93. package/packages/gantt/src/components/range/range.component.ts +27 -0
  94. package/packages/gantt/src/components/range/test/range.component.spec.ts +80 -0
  95. package/packages/gantt/src/components/table/gantt-table.component.html +105 -0
  96. package/packages/gantt/src/components/table/gantt-table.component.scss +144 -0
  97. package/packages/gantt/src/components/table/gantt-table.component.ts +166 -0
  98. package/packages/gantt/src/components/table/test/table.spec.ts +129 -0
  99. package/packages/gantt/src/gantt-abstract.ts +14 -0
  100. package/packages/gantt/src/gantt-dom.service.ts +134 -0
  101. package/packages/gantt/src/gantt-drag-container.ts +73 -0
  102. package/packages/gantt/src/gantt-item-upper.ts +50 -0
  103. package/packages/gantt/src/gantt-print.service.ts +104 -0
  104. package/packages/gantt/src/gantt-upper.ts +289 -0
  105. package/packages/gantt/src/gantt.component.html +18 -0
  106. package/packages/gantt/src/gantt.component.scss +77 -0
  107. package/packages/gantt/src/gantt.component.ts +134 -0
  108. package/packages/gantt/src/gantt.module.ts +47 -0
  109. package/packages/gantt/src/gantt.pipe.ts +31 -0
  110. package/packages/gantt/src/gantt.styles.ts +28 -0
  111. package/{public-api.d.ts → packages/gantt/src/public-api.ts} +6 -0
  112. package/packages/gantt/src/root.component.html +12 -0
  113. package/packages/gantt/src/root.component.ts +121 -0
  114. package/packages/gantt/src/styles/index.scss +9 -0
  115. package/packages/gantt/src/styles/variables.scss +46 -0
  116. package/packages/gantt/src/table/gantt-column.component.ts +25 -0
  117. package/packages/gantt/src/table/gantt-table.component.ts +14 -0
  118. package/packages/gantt/src/table/test/table.spec.ts +56 -0
  119. package/packages/gantt/src/test/gantt.component.spec.ts +404 -0
  120. package/packages/gantt/src/test/mocks/data.ts +303 -0
  121. package/packages/gantt/src/test.ts +21 -0
  122. package/packages/gantt/src/utils/date.ts +276 -0
  123. package/packages/gantt/src/utils/helpers.ts +66 -0
  124. package/packages/gantt/src/utils/test/date.spec.ts +105 -0
  125. package/packages/gantt/src/utils/test/helpers.spec.ts +73 -0
  126. package/packages/gantt/src/utils/testing.ts +64 -0
  127. package/packages/gantt/src/views/day.ts +74 -0
  128. package/packages/gantt/src/views/factory.ts +25 -0
  129. package/packages/gantt/src/views/month.ts +66 -0
  130. package/packages/gantt/src/views/quarter.ts +68 -0
  131. package/packages/gantt/src/views/test/day.spec.ts +45 -0
  132. package/packages/gantt/src/views/test/factory.spec.ts +41 -0
  133. package/packages/gantt/src/views/test/mock.ts +14 -0
  134. package/packages/gantt/src/views/test/month.spec.ts +45 -0
  135. package/packages/gantt/src/views/test/quarter.spec.ts +45 -0
  136. package/packages/gantt/src/views/test/view.spec.ts +144 -0
  137. package/packages/gantt/src/views/test/week.spec.ts +45 -0
  138. package/packages/gantt/src/views/test/year.spec.ts +45 -0
  139. package/packages/gantt/src/views/view.ts +186 -0
  140. package/packages/gantt/src/views/week.ts +66 -0
  141. package/packages/gantt/src/views/year.ts +62 -0
  142. package/packages/gantt/tsconfig.lib.json +20 -0
  143. package/packages/gantt/tsconfig.lib.prod.json +9 -0
  144. package/packages/gantt/tsconfig.schematics.json +25 -0
  145. package/packages/gantt/tsconfig.spec.json +17 -0
  146. package/packages/gantt/tslint.json +18 -0
  147. package/scss-bundle.config.json +7 -0
  148. package/tsconfig.json +26 -0
  149. package/tslint.json +51 -0
  150. package/bundles/worktile-gantt.umd.js +0 -3129
  151. package/bundles/worktile-gantt.umd.js.map +0 -1
  152. package/bundles/worktile-gantt.umd.min.js +0 -16
  153. package/bundles/worktile-gantt.umd.min.js.map +0 -1
  154. package/class/date-point.d.ts +0 -15
  155. package/class/group.d.ts +0 -22
  156. package/class/item.d.ts +0 -70
  157. package/class/view-type.d.ts +0 -7
  158. package/components/bar/bar-drag.d.ts +0 -34
  159. package/components/bar/bar.component.d.ts +0 -23
  160. package/components/calendar/calendar.component.d.ts +0 -25
  161. package/components/drag-backdrop/drag-backdrop.component.d.ts +0 -6
  162. package/components/icon/icon.component.d.ts +0 -10
  163. package/components/icon/icons.d.ts +0 -8
  164. package/components/links/links.component.d.ts +0 -44
  165. package/components/main/gantt-main.component.d.ts +0 -18
  166. package/components/range/range.component.d.ts +0 -10
  167. package/components/table/gantt-table.component.d.ts +0 -31
  168. package/esm2015/class/date-point.js +0 -10
  169. package/esm2015/class/event.js +0 -13
  170. package/esm2015/class/group.js +0 -17
  171. package/esm2015/class/index.js +0 -6
  172. package/esm2015/class/item.js +0 -78
  173. package/esm2015/class/view-type.js +0 -9
  174. package/esm2015/components/bar/bar-drag.js +0 -266
  175. package/esm2015/components/bar/bar.component.js +0 -91
  176. package/esm2015/components/calendar/calendar.component.js +0 -82
  177. package/esm2015/components/drag-backdrop/drag-backdrop.component.js +0 -18
  178. package/esm2015/components/icon/icon.component.js +0 -36
  179. package/esm2015/components/icon/icons.js +0 -87
  180. package/esm2015/components/links/links.component.js +0 -207
  181. package/esm2015/components/main/gantt-main.component.js +0 -35
  182. package/esm2015/components/range/range.component.js +0 -32
  183. package/esm2015/components/table/gantt-table.component.js +0 -128
  184. package/esm2015/gantt-dom.service.js +0 -101
  185. package/esm2015/gantt-drag-container.js +0 -57
  186. package/esm2015/gantt-item-upper.js +0 -55
  187. package/esm2015/gantt-print.service.js +0 -92
  188. package/esm2015/gantt-upper.js +0 -231
  189. package/esm2015/gantt.component.js +0 -105
  190. package/esm2015/gantt.module.js +0 -43
  191. package/esm2015/gantt.pipe.js +0 -33
  192. package/esm2015/gantt.styles.js +0 -15
  193. package/esm2015/public-api.js +0 -16
  194. package/esm2015/root.component.js +0 -111
  195. package/esm2015/table/gantt-column.component.js +0 -28
  196. package/esm2015/table/gantt-table.component.js +0 -18
  197. package/esm2015/utils/date.js +0 -160
  198. package/esm2015/utils/helpers.js +0 -45
  199. package/esm2015/views/day.js +0 -54
  200. package/esm2015/views/factory.js +0 -23
  201. package/esm2015/views/month.js +0 -48
  202. package/esm2015/views/quarter.js +0 -51
  203. package/esm2015/views/view.js +0 -121
  204. package/esm2015/views/week.js +0 -49
  205. package/esm2015/views/year.js +0 -50
  206. package/esm2015/worktile-gantt.js +0 -16
  207. package/fesm2015/worktile-gantt.js +0 -2491
  208. package/fesm2015/worktile-gantt.js.map +0 -1
  209. package/gantt-dom.service.d.ts +0 -29
  210. package/gantt-drag-container.d.ts +0 -20
  211. package/gantt-item-upper.d.ts +0 -17
  212. package/gantt-print.service.d.ts +0 -10
  213. package/gantt-upper.d.ts +0 -62
  214. package/gantt.component.d.ts +0 -28
  215. package/gantt.module.d.ts +0 -2
  216. package/gantt.pipe.d.ts +0 -11
  217. package/gantt.styles.d.ts +0 -15
  218. package/root.component.d.ts +0 -25
  219. package/style.scss +0 -645
  220. package/table/gantt-column.component.d.ts +0 -12
  221. package/table/gantt-table.component.d.ts +0 -7
  222. package/utils/date.d.ts +0 -59
  223. package/utils/helpers.d.ts +0 -11
  224. package/views/day.d.ts +0 -14
  225. package/views/factory.d.ts +0 -8
  226. package/views/month.d.ts +0 -12
  227. package/views/quarter.d.ts +0 -12
  228. package/views/view.d.ts +0 -56
  229. package/views/week.d.ts +0 -12
  230. package/views/year.d.ts +0 -12
  231. package/worktile-gantt.d.ts +0 -15
  232. package/worktile-gantt.metadata.json +0 -1
@@ -0,0 +1,28 @@
1
+ import { Component, OnInit, Input, AfterViewInit, ElementRef, HostBinding } from '@angular/core';
2
+ import { icons } from './icons';
3
+ @Component({
4
+ selector: 'gantt-icon',
5
+ template: ''
6
+ })
7
+ export class GanttIconComponent implements OnInit, AfterViewInit {
8
+ @HostBinding('class.gantt-icon') isIcon = true;
9
+
10
+ @Input() set iconName(name: string) {
11
+ this.setSvg(name);
12
+ }
13
+
14
+ constructor(private elementRef: ElementRef<HTMLElement>) {}
15
+
16
+ ngOnInit(): void {}
17
+
18
+ ngAfterViewInit() {}
19
+
20
+ setSvg(name: string) {
21
+ const iconSvg = icons[name];
22
+ if (iconSvg) {
23
+ this.elementRef.nativeElement.innerHTML = iconSvg;
24
+ } else {
25
+ this.elementRef.nativeElement.innerHTML = '';
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,86 @@
1
+ const angleRight = `<svg xmlns="http://www.w3.org/2000/svg" fit="" preserveAspectRatio="xMidYMid meet" focusable="false"><g id="amnavigation/angle-right" stroke-width="1" fill-rule="evenodd"><path d="M7.978 11.498l-.005.005L2.3 5.831 3.13 5l4.848 4.848L12.826 5l.83.831-5.673 5.672-.005-.005z" transform="rotate(-90 7.978 8.252)"></path></g></svg>`;
2
+ const angleDown = `<svg xmlns="http://www.w3.org/2000/svg" fit="" preserveAspectRatio="xMidYMid meet" focusable="false"><g id="aknavigation/angle-down" stroke-width="1" fill-rule="evenodd"><path d="M7.978 11.997l-.005.006L2.3 6.33l.83-.831 4.848 4.848L12.826 5.5l.83.83-5.673 5.673-.005-.006z" ></path></g></svg>`;
3
+ const plusSquare = `<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fit="" preserveAspectRatio="xMidYMid meet" focusable="false"><g id="kxaction/plus-square" stroke-width="1" fill-rule="evenodd"><path d="M2 0h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 1.2a.8.8 0 0 0-.8.8v12a.8.8 0 0 0 .8.8h12a.8.8 0 0 0 .8-.8V2a.8.8 0 0 0-.8-.8H2zm5.45 6.2V4.75h1.2V7.4h2.65v1.2H8.65v2.65h-1.2V8.6H4.8V7.4h2.65z"></path></g></svg>`;
4
+ const minusSquare = `<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fit="" preserveAspectRatio="xMidYMid meet" focusable="false"><g id="jnaction/minus-square" stroke-width="1" fill-rule="evenodd"><path d="M2 0h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 1.2a.8.8 0 0 0-.8.8v12a.8.8 0 0 0 .8.8h12a.8.8 0 0 0 .8-.8V2a.8.8 0 0 0-.8-.8H2zm2.8 6.2h6.5v1.2H4.8V7.4z"></path></g></svg>`;
5
+ const loadingIcon = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50" xml:space="preserve">
6
+ <path fill="#aaa" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" transform="rotate(275.098 25 25)">
7
+ <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animateTransform>
8
+ </path>
9
+ </svg>`;
10
+ const emptyIcon = `<svg
11
+ width="148px"
12
+ height="134px"
13
+ viewBox="0 0 148 134"
14
+ version="1.1"
15
+ xmlns="http://www.w3.org/2000/svg"
16
+ xmlns:xlink="http://www.w3.org/1999/xlink"
17
+ >
18
+ <defs>
19
+ <filter x="0.0%" y="0.0%" width="100.0%" height="100.0%" filterUnits="objectBoundingBox" id="filter-1">
20
+ <feGaussianBlur stdDeviation="0" in="SourceGraphic"></feGaussianBlur>
21
+ </filter>
22
+ </defs>
23
+ <g id="148x134" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
24
+ <g id="编组-6" transform="translate(1.000000, 1.000000)">
25
+ <ellipse
26
+ id="椭圆形"
27
+ fill="#EDEEF2"
28
+ opacity="0.3"
29
+ filter="url(#filter-1)"
30
+ cx="73.0800017"
31
+ cy="115.920003"
32
+ rx="73.0800017"
33
+ ry="16.8000004"
34
+ ></ellipse>
35
+ <g id="编组-5" transform="translate(15.120000, 0.000000)">
36
+ <polygon
37
+ id="矩形"
38
+ fill="#E2E4E9"
39
+ points="19.2789848 49.5600011 99.1200023 48.7200011 117.600003 75.9297673 117.600003 92.313049 0 92.313049 0 75.0356267"
40
+ ></polygon>
41
+ <path
42
+ d="M23.5200005,0 L94.0800002,0 C97.7913538,2.06413823e-16 100.8,3.00864655 100.8,6.72000015 L100.8,99.1200023 L100.8,99.1200023 L16.8000004,99.1200023 L16.8000004,6.72000015 C16.8000004,3.00864655 19.8086469,1.56994302e-15 23.5200005,0 Z"
43
+ id="矩形"
44
+ fill="#F9FAFB"
45
+ ></path>
46
+ <path
47
+ d="M30.9200007,12.4400003 L86.6800019,12.4400003 C88.5356787,12.4400003 90.040002,13.9443236 90.040002,15.8000004 L90.040002,42.000001 C90.040002,43.8556778 88.5356787,45.360001 86.6800019,45.360001 L30.9200007,45.360001 C29.0643239,45.360001 27.5600006,43.8556778 27.5600006,42.000001 L27.5600006,15.8000004 C27.5600006,13.9443236 29.0643239,12.4400003 30.9200007,12.4400003 Z"
48
+ id="矩形"
49
+ fill="#E8EAEE"
50
+ ></path>
51
+ <text
52
+ id="&lt;/null&gt;"
53
+ font-family="PingFangSC-Medium, PingFang SC"
54
+ font-size="15.1200003"
55
+ font-weight="400"
56
+ fill="#BCBECD"
57
+ >
58
+ <tspan x="33.6000008" y="32.8000004">&lt;/null&gt;</tspan>
59
+ </text>
60
+ <rect id="矩形" fill="#E8EAEE" x="27.5600006" y="52.0800012" width="61.4800014" height="5.04000011" rx="2.52000006"></rect>
61
+ <rect
62
+ id="矩形备份"
63
+ fill="#E8EAEE"
64
+ x="27.5600006"
65
+ y="63.8400014"
66
+ width="61.4800014"
67
+ height="5.04000011"
68
+ rx="2.52000006"
69
+ ></rect>
70
+ <path
71
+ d="M0,75.6000017 L29.280235,75.6000017 C32.0637502,75.6000017 34.3202352,77.8564866 34.3202352,80.6400018 L34.3202352,86.2591426 C34.3202352,89.0426578 36.5767201,91.2991427 39.3602353,91.2991427 L78.4136737,91.2991427 C81.1971889,91.2991427 83.4536738,89.0426578 83.4536738,86.2591426 L83.4536738,80.6400018 C83.4536738,77.8564866 85.7101587,75.6000017 88.4936739,75.6000017 L117.600003,75.6000017 L117.600003,75.6000017 L117.600003,110.880003 C117.600003,115.519195 113.839194,119.280003 109.200002,119.280003 L8.40000019,119.280003 C3.76080819,119.280003 -6.53729019e-15,115.519195 0,110.880003 L0,75.6000017 L0,75.6000017 Z"
72
+ id="矩形"
73
+ fill="#EDEFF2"
74
+ ></path>
75
+ </g>
76
+ </g>
77
+ </g>
78
+ </svg>`;
79
+ export const icons = {
80
+ 'angle-right': angleRight,
81
+ 'angle-down': angleDown,
82
+ 'plus-square': plusSquare,
83
+ 'minus-square': minusSquare,
84
+ loading: loadingIcon,
85
+ empty: emptyIcon
86
+ };
@@ -0,0 +1,19 @@
1
+ <svg [attr.width]="ganttUpper.view.width" class="gantt-links-overlay-main">
2
+ <ng-container *ngFor="let link of links; let i = index; trackBy: trackBy">
3
+ <path [attr.d]="link.path" fill="transparent" stroke-width="2" [attr.stroke]="link.color" pointer-events="none"></path>
4
+ <g>
5
+ <path
6
+ class="link-line"
7
+ (click)="onLineClick($event, link)"
8
+ (mouseenter)="mouseEnterPath(link)"
9
+ (mouseleave)="mouseLeavePath(link)"
10
+ [attr.d]="link.path"
11
+ stroke="transparent"
12
+ stroke-width="9"
13
+ fill="none"
14
+ cursor="pointer"
15
+ ></path>
16
+ </g>
17
+ </ng-container>
18
+ <line class="link-dragging-line"></line>
19
+ </svg>
@@ -0,0 +1,27 @@
1
+ .gantt-links-overlay {
2
+ position: absolute;
3
+ top: 0px;
4
+ left: 0px;
5
+ width: 100%;
6
+ height: 100%;
7
+ svg {
8
+ overflow: visible;
9
+ z-index: 2;
10
+ position: absolute;
11
+ }
12
+ }
13
+
14
+ .link-dragging-container {
15
+ width: 100%;
16
+ height: 1px;
17
+ overflow: visible !important;
18
+ position: absolute;
19
+ top: $gantt-header-height;
20
+ left: 0;
21
+ z-index: 2000;
22
+
23
+ .link-dragging-line {
24
+ stroke: $gantt-link-line-color;
25
+ stroke-width: 2px;
26
+ }
27
+ }
@@ -0,0 +1,263 @@
1
+ import {
2
+ Component,
3
+ OnInit,
4
+ Input,
5
+ Output,
6
+ EventEmitter,
7
+ HostBinding,
8
+ Inject,
9
+ ChangeDetectorRef,
10
+ ElementRef,
11
+ OnDestroy,
12
+ OnChanges
13
+ } from '@angular/core';
14
+ import { merge, Subject } from 'rxjs';
15
+ import { takeUntil, skip } from 'rxjs/operators';
16
+ import { GanttGroupInternal } from '../../class/group';
17
+ import { GanttItemInternal, GanttItem } from './../../class/item';
18
+ import { GanttLineClickEvent } from '../../class/event';
19
+ import { GanttDragContainer } from '../../gantt-drag-container';
20
+ import { recursiveItems } from '../../utils/helpers';
21
+ import { GanttDate } from '../../utils/date';
22
+ import { GANTT_UPPER_TOKEN, GanttUpper } from '../../gantt-upper';
23
+
24
+ enum LinkColors {
25
+ default = '#cacaca',
26
+ blocked = '#FF7575',
27
+ active = '#348FE4'
28
+ }
29
+
30
+ interface GanttLinkItem {
31
+ id: string;
32
+ before: { x: number; y: number };
33
+ after: { x: number; y: number };
34
+ start: GanttDate;
35
+ end: GanttDate;
36
+ origin: GanttItem;
37
+ links: string[];
38
+ }
39
+
40
+ interface LinkInternal {
41
+ path: string;
42
+ source: GanttItem;
43
+ target: GanttItem;
44
+ color: LinkColors;
45
+ }
46
+
47
+ @Component({
48
+ selector: 'gantt-links-overlay',
49
+ templateUrl: './links.component.html'
50
+ })
51
+ export class GanttLinksComponent implements OnInit, OnChanges, OnDestroy {
52
+ @Input() groups: GanttGroupInternal[] = [];
53
+
54
+ @Input() items: GanttItemInternal[] = [];
55
+
56
+ @Output() lineClick = new EventEmitter<GanttLineClickEvent>();
57
+
58
+ public links: LinkInternal[] = [];
59
+
60
+ private linkItems: GanttLinkItem[] = [];
61
+
62
+ private bezierWeight = -0.5;
63
+
64
+ private firstChange = true;
65
+
66
+ private unsubscribe$ = new Subject();
67
+
68
+ @HostBinding('class.gantt-links-overlay') ganttLinksOverlay = true;
69
+
70
+ constructor(
71
+ @Inject(GANTT_UPPER_TOKEN) public ganttUpper: GanttUpper,
72
+ private cdr: ChangeDetectorRef,
73
+ private elementRef: ElementRef,
74
+ private ganttDragContainer: GanttDragContainer
75
+ ) {}
76
+
77
+ ngOnInit() {
78
+ this.buildLinks();
79
+ this.firstChange = false;
80
+
81
+ this.ganttDragContainer.dragStarted.pipe(takeUntil(this.unsubscribe$)).subscribe(() => {
82
+ this.elementRef.nativeElement.style.visibility = 'hidden';
83
+ });
84
+
85
+ merge(
86
+ this.ganttUpper.viewChange,
87
+ this.ganttUpper.expandChange,
88
+ this.ganttUpper.view.start$,
89
+ this.ganttUpper.dragEnded,
90
+ this.ganttUpper.linkDragEnded
91
+ )
92
+ .pipe(takeUntil(this.unsubscribe$), skip(1))
93
+ .subscribe(() => {
94
+ this.elementRef.nativeElement.style.visibility = 'visible';
95
+ this.buildLinks();
96
+ this.cdr.detectChanges();
97
+ });
98
+ }
99
+
100
+ ngOnChanges() {
101
+ if (!this.firstChange) {
102
+ this.buildLinks();
103
+ }
104
+ }
105
+
106
+ private computeItemPosition() {
107
+ const lineHeight = this.ganttUpper.styles.lineHeight;
108
+ const barHeight = this.ganttUpper.styles.barHeight;
109
+ this.linkItems = [];
110
+ if (this.groups.length > 0) {
111
+ let itemNum = 0;
112
+ let groupNum = 0;
113
+ this.groups.forEach((group) => {
114
+ groupNum++;
115
+ if (group.expanded) {
116
+ const items = recursiveItems(group.items);
117
+ items.forEach((item, itemIndex) => {
118
+ const y = (groupNum + itemNum + itemIndex) * lineHeight + item.refs.y + barHeight / 2;
119
+ this.linkItems.push({
120
+ ...item,
121
+ before: {
122
+ x: item.refs.x,
123
+ y
124
+ },
125
+ after: {
126
+ x: item.refs.x + item.refs.width,
127
+ y
128
+ }
129
+ });
130
+ });
131
+ itemNum += items.length;
132
+ }
133
+ });
134
+ } else {
135
+ const items = recursiveItems(this.items);
136
+ items.forEach((item, itemIndex) => {
137
+ const y = itemIndex * lineHeight + item.refs.y + barHeight / 2;
138
+ this.linkItems.push({
139
+ ...item,
140
+ before: {
141
+ x: item.refs.x,
142
+ y
143
+ },
144
+ after: {
145
+ x: item.refs.x + item.refs.width,
146
+ y
147
+ }
148
+ });
149
+ });
150
+ }
151
+ }
152
+
153
+ private generatePath(source: GanttLinkItem, target: GanttLinkItem) {
154
+ if (source.before && source.after && target.before && target.after) {
155
+ const x1 = source.after.x;
156
+ const y1 = source.after.y;
157
+
158
+ const x4 = target.before.x;
159
+ const y4 = target.before.y;
160
+
161
+ const dx = Math.abs(x4 - x1) * this.bezierWeight;
162
+ const x2 = x1 - dx;
163
+ const x3 = x4 + dx;
164
+
165
+ const centerX = (x1 + x4) / 2;
166
+ const centerY = (y1 + y4) / 2;
167
+
168
+ let controlX = this.ganttUpper.styles.lineHeight / 2;
169
+ const controlY = this.ganttUpper.styles.lineHeight / 2;
170
+
171
+ if (x1 >= x4) {
172
+ if (y4 > y1) {
173
+ if (Math.abs(y4 - y1) <= this.ganttUpper.styles.lineHeight) {
174
+ return `M ${x1} ${y1}
175
+ C ${x1 + controlX} ${y1} ${x1 + controlX} ${y1 + controlX} ${x1} ${y1 + controlY}
176
+ L ${x1} ${y1 + controlY} ${centerX} ${centerY}
177
+
178
+ M ${x4} ${y4}
179
+ C ${x4 - controlX} ${y4} ${x4 - controlX} ${y4 - controlX} ${x4} ${y4 - controlY}
180
+ L ${x4} ${y4 - controlY} ${centerX} ${centerY}`;
181
+ } else {
182
+ controlX = this.ganttUpper.styles.lineHeight;
183
+ return `M ${x1} ${y1}
184
+ C ${x1 + controlX} ${y1} ${x1 + controlX} ${y1 + controlX} ${centerX} ${centerY}
185
+
186
+
187
+ M ${x4} ${y4}
188
+ C ${x4 - controlX} ${y4} ${x4 - controlX} ${y4 - controlX} ${centerX} ${centerY}`;
189
+ }
190
+ } else {
191
+ if (Math.abs(y4 - y1) <= this.ganttUpper.styles.lineHeight) {
192
+ return `M ${x1} ${y1}
193
+ C ${x1 + controlX} ${y1} ${x1 + controlX} ${y1 - controlX} ${x1} ${y1 - controlY}
194
+ L ${x1} ${y1 - controlY} ${centerX} ${centerY}
195
+
196
+ M ${x4} ${y4}
197
+ C ${x4 - controlX} ${y4} ${x4 - controlX} ${y4 + controlX} ${x4} ${y4 + controlY}
198
+ L ${x4} ${y4 + controlY} ${centerX} ${centerY}
199
+ `;
200
+ } else {
201
+ controlX = this.ganttUpper.styles.lineHeight;
202
+ return `M ${x1} ${y1}
203
+ C ${x1 + controlX} ${y1} ${x1 + controlX} ${y1 - controlX} ${centerX} ${centerY}
204
+
205
+ M ${x4} ${y4}
206
+ C ${x4 - controlX} ${y4} ${x4 - controlX} ${y4 + controlX} ${centerX} ${centerY}`;
207
+ }
208
+ }
209
+ }
210
+
211
+ return `M ${x1} ${y1} C ${x2} ${y1} ${x3} ${y4} ${x4} ${y4}`;
212
+ }
213
+ }
214
+
215
+ buildLinks() {
216
+ this.computeItemPosition();
217
+ this.links = [];
218
+ this.linkItems.forEach((source) => {
219
+ if (source.origin.start || source.origin.end) {
220
+ source.links.forEach((linkId) => {
221
+ const target = this.linkItems.find((item) => item.id === linkId);
222
+ if (target && (target.origin.start || target.origin.end)) {
223
+ this.links.push({
224
+ path: this.generatePath(source, target),
225
+ source: source.origin,
226
+ target: target.origin,
227
+ color: source.end.getTime() > target.start.getTime() ? LinkColors.blocked : LinkColors.default
228
+ });
229
+ }
230
+ });
231
+ }
232
+ });
233
+ }
234
+
235
+ trackBy(index: number) {
236
+ return index;
237
+ }
238
+
239
+ onLineClick(event: MouseEvent, link: LinkInternal) {
240
+ this.lineClick.emit({
241
+ event,
242
+ source: link.source,
243
+ target: link.target
244
+ });
245
+ }
246
+
247
+ mouseEnterPath(link: LinkInternal) {
248
+ if (link.color === LinkColors.default) {
249
+ link.color = LinkColors.active;
250
+ }
251
+ }
252
+
253
+ mouseLeavePath(link: LinkInternal) {
254
+ if (link.color === LinkColors.active) {
255
+ link.color = LinkColors.default;
256
+ }
257
+ }
258
+
259
+ ngOnDestroy() {
260
+ this.unsubscribe$.next();
261
+ this.unsubscribe$.complete();
262
+ }
263
+ }
@@ -0,0 +1,35 @@
1
+ <gantt-links-overlay [groups]="groups" [items]="items" (lineClick)="lineClick.emit($event)"></gantt-links-overlay>
2
+ <!-- groups -->
3
+ <div class="gantt-main-groups" *ngIf="groups && groups.length > 0; else itemsTemplate" [style.width.px]="ganttUpper.view.width">
4
+ <ng-container *ngFor="let group of groups; trackBy: trackBy">
5
+ <div class="gantt-group" [ngClass]="group.class">
6
+ <ng-template [ngTemplateOutlet]="groupHeaderTemplate" [ngTemplateOutletContext]="{ group: group }"></ng-template>
7
+ </div>
8
+ <div *ngIf="group.expanded" class="gantt-items">
9
+ <ng-template [ngTemplateOutlet]="ganttItems" [ngTemplateOutletContext]="{ items: group.items }"></ng-template>
10
+ </div>
11
+ </ng-container>
12
+ </div>
13
+ <!-- items -->
14
+ <ng-template #itemsTemplate>
15
+ <div class="gantt-main-items" [style.width.px]="ganttUpper.view.width">
16
+ <ng-template [ngTemplateOutlet]="ganttItems" [ngTemplateOutletContext]="{ items: items }"></ng-template>
17
+ </div>
18
+ </ng-template>
19
+
20
+ <ng-template #ganttItems let-items="items">
21
+ <ng-container *ngFor="let item of items; trackBy: trackBy">
22
+ <div class="gantt-item" [style.height.px]="ganttUpper.styles.lineHeight">
23
+ <ng-container *ngIf="item.type | isGanttCustomItem">
24
+ <ng-template [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletContext]="{ item: item.origin, refs: item.refs }"></ng-template>
25
+ </ng-container>
26
+ <gantt-range *ngIf="item.type | isGanttRangeItem" [template]="rangeTemplate" [item]="item"></gantt-range>
27
+ <gantt-bar *ngIf="item.type | isGanttBarItem" [item]="item" [template]="barTemplate" (barClick)="barClick.emit($event)"></gantt-bar>
28
+ </div>
29
+ <ng-template
30
+ *ngIf="item.children && item.expanded"
31
+ [ngTemplateOutlet]="ganttItems"
32
+ [ngTemplateOutletContext]="{ items: item.children }"
33
+ ></ng-template>
34
+ </ng-container>
35
+ </ng-template>
@@ -0,0 +1,35 @@
1
+ import { Component, OnInit, HostBinding, Inject, Input, TemplateRef, Output, EventEmitter } from '@angular/core';
2
+ import { GanttGroupInternal, GanttItemInternal, GanttBarClickEvent, GanttLineClickEvent } from '../../class';
3
+ import { GANTT_UPPER_TOKEN, GanttUpper } from '../../gantt-upper';
4
+
5
+ @Component({
6
+ selector: 'gantt-main',
7
+ templateUrl: './gantt-main.component.html'
8
+ })
9
+ export class GanttMainComponent implements OnInit {
10
+ @Input() groups: GanttGroupInternal[];
11
+
12
+ @Input() items: GanttItemInternal[];
13
+
14
+ @Input() groupHeaderTemplate: TemplateRef<any>;
15
+
16
+ @Input() itemTemplate: TemplateRef<any>;
17
+
18
+ @Input() barTemplate: TemplateRef<any>;
19
+
20
+ @Input() rangeTemplate: TemplateRef<any>;
21
+
22
+ @Output() barClick = new EventEmitter<GanttBarClickEvent>();
23
+
24
+ @Output() lineClick = new EventEmitter<GanttLineClickEvent>();
25
+
26
+ @HostBinding('class.gantt-main-container') ganttMainClass = true;
27
+
28
+ constructor(@Inject(GANTT_UPPER_TOKEN) public ganttUpper: GanttUpper) {}
29
+
30
+ ngOnInit() {}
31
+
32
+ trackBy(item: GanttGroupInternal | GanttItemInternal, index: number) {
33
+ return item.id || index;
34
+ }
35
+ }
@@ -0,0 +1,8 @@
1
+ <ng-container *ngIf="item.start && item.end">
2
+ <div class="gantt-range-main">
3
+ <div class="gantt-range-main-progress" *ngIf="item.progress >= 0" [style.width.%]="item.progress * 100"></div>
4
+ </div>
5
+ <div class="gantt-range-triangle left"></div>
6
+ <div class="gantt-range-triangle right"></div>
7
+ <ng-template [ngTemplateOutlet]="template" [ngTemplateOutletContext]="{ item: item.origin, refs: item.refs }"></ng-template>
8
+ </ng-container>
@@ -0,0 +1,35 @@
1
+ .gantt-range {
2
+ position: absolute;
3
+ z-index: 2;
4
+ .gantt-range-main {
5
+ height: 10px;
6
+ background: #dfdfdf;
7
+ border: 1px solid #888;
8
+ border-radius: 4px 4px 0 0;
9
+ box-sizing: border-box;
10
+ position: relative;
11
+ .gantt-range-main-progress {
12
+ position: absolute;
13
+ left: 0;
14
+ top: 0;
15
+ height: 100%;
16
+ background: #888;
17
+ }
18
+ }
19
+ .gantt-range-triangle {
20
+ width: 0;
21
+ height: 0;
22
+ border-top: 7px solid #888;
23
+ position: absolute;
24
+ top: 10px;
25
+
26
+ &.left {
27
+ border-right: 6px solid transparent;
28
+ left: 0;
29
+ }
30
+ &.right {
31
+ border-left: 6px solid transparent;
32
+ right: 0;
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,27 @@
1
+ import { Component, OnInit, HostBinding, ElementRef, OnChanges, OnDestroy, Inject } from '@angular/core';
2
+ import { GANTT_UPPER_TOKEN, GanttUpper } from '../../gantt-upper';
3
+ import { GanttItemUpper } from '../../gantt-item-upper';
4
+
5
+ @Component({
6
+ selector: 'ngx-gantt-range,gantt-range',
7
+ templateUrl: './range.component.html'
8
+ })
9
+ export class NgxGanttRangeComponent extends GanttItemUpper implements OnInit, OnChanges, OnDestroy {
10
+ @HostBinding('class.gantt-range') ganttRangeClass = true;
11
+
12
+ constructor(elementRef: ElementRef<HTMLDivElement>, @Inject(GANTT_UPPER_TOKEN) ganttUpper: GanttUpper) {
13
+ super(elementRef, ganttUpper);
14
+ }
15
+
16
+ ngOnInit() {
17
+ super.onInit();
18
+ }
19
+
20
+ ngOnChanges(): void {
21
+ super.onChanges();
22
+ }
23
+
24
+ ngOnDestroy() {
25
+ super.onDestroy();
26
+ }
27
+ }
@@ -0,0 +1,80 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, DebugElement } from '@angular/core';
3
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
4
+ import { By } from '@angular/platform-browser';
5
+ import { NgxGanttComponent } from '../../../gantt.component';
6
+ import { NgxGanttModule } from '../../../gantt.module';
7
+ import { GanttDate } from '../../../utils/date';
8
+ import { NgxGanttRangeComponent } from '../range.component';
9
+
10
+ const mockRangeItems = [
11
+ {
12
+ id: 'item-0101',
13
+ title: 'VERSION 0101',
14
+ start: new GanttDate('2020-05-21 12:34:35').getUnixTime(),
15
+ type: 'range',
16
+ progress: 0.5,
17
+ color: '#FF0000',
18
+ children: [
19
+ {
20
+ id: 'item-child-0101',
21
+ title: 'VERSION Children 0101',
22
+ start: new GanttDate('2020-05-21 12:34:35').getUnixTime(),
23
+ color: '#FF0000',
24
+ linkable: false,
25
+ type: 'range'
26
+ }
27
+ ]
28
+ },
29
+ {
30
+ id: 'item-0102',
31
+ title: 'VERSION 0102',
32
+ start: new GanttDate('2020-05-31 22:34:35').getUnixTime(),
33
+ end: new GanttDate('2020-06-05 08:53:20').getUnixTime(),
34
+ color: '#9ACD32',
35
+ expandable: true,
36
+ type: 'range'
37
+ }
38
+ ];
39
+
40
+ @Component({
41
+ selector: 'test-gantt-range',
42
+ template: ` <ngx-gantt #gantt [items]="items" [viewType]="viewType">
43
+ <ngx-gantt-table>
44
+ <ngx-gantt-column name="标题" width="200px">
45
+ <ng-template #cell let-item="item">
46
+ {{ item.title }}
47
+ </ng-template>
48
+ </ngx-gantt-column>
49
+ </ngx-gantt-table>
50
+ </ngx-gantt>`
51
+ })
52
+ export class TestGanttRangeComponent {
53
+ constructor() {}
54
+
55
+ viewType = 'month';
56
+
57
+ items = mockRangeItems;
58
+ }
59
+
60
+ describe('ngx-gantt-range', () => {
61
+ let fixture: ComponentFixture<TestGanttRangeComponent>;
62
+ beforeEach(async () => {
63
+ TestBed.configureTestingModule({
64
+ imports: [CommonModule, NgxGanttModule],
65
+ declarations: [TestGanttRangeComponent]
66
+ }).compileComponents();
67
+ fixture = TestBed.createComponent(TestGanttRangeComponent);
68
+ fixture.detectChanges();
69
+ });
70
+
71
+ it('should render range item', () => {
72
+ const rangeItems = fixture.debugElement.queryAll(By.directive(NgxGanttRangeComponent));
73
+ expect(rangeItems.length).toEqual(mockRangeItems.length);
74
+ });
75
+
76
+ it('should has range progress', () => {
77
+ const rangeProgress = fixture.debugElement.queryAll(By.css('.gantt-range-main-progress'));
78
+ expect(rangeProgress.length).toEqual(1);
79
+ });
80
+ });