tg-ganttchart 0.0.11 → 0.0.12

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.
@@ -3401,8 +3401,8 @@ var render = function render() {
3401
3401
  };
3402
3402
  var staticRenderFns = [];
3403
3403
 
3404
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=template&id=2767341e
3405
- var GanttElasticvue_type_template_id_2767341e_render = function render() {
3404
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=template&id=100984c8
3405
+ var GanttElasticvue_type_template_id_100984c8_render = function render() {
3406
3406
  var _vm = this,
3407
3407
  _c = _vm._self._c,
3408
3408
  _setup = _vm._self._setupProxy;
@@ -3425,10 +3425,13 @@ var GanttElasticvue_type_template_id_2767341e_render = function render() {
3425
3425
  },
3426
3426
  slot: "header"
3427
3427
  }), _vm._t("header"), _c('main-view', {
3428
- ref: "mainView"
3428
+ ref: "mainView",
3429
+ on: {
3430
+ "task-updated": _vm.handleTaskUpdated
3431
+ }
3429
3432
  }), _vm._t("footer")], 2);
3430
3433
  };
3431
- var GanttElasticvue_type_template_id_2767341e_staticRenderFns = [];
3434
+ var GanttElasticvue_type_template_id_100984c8_staticRenderFns = [];
3432
3435
 
3433
3436
  // EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
3434
3437
  var es_array_push = __webpack_require__(4114);
@@ -3671,8 +3674,8 @@ var component = normalizeComponent(
3671
3674
  )
3672
3675
 
3673
3676
  /* harmony default export */ var GanttViewFilter = (component.exports);
3674
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/MainView.vue?vue&type=template&id=1a4b756c
3675
- var MainViewvue_type_template_id_1a4b756c_render = function render() {
3677
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/MainView.vue?vue&type=template&id=33392d22
3678
+ var MainViewvue_type_template_id_33392d22_render = function render() {
3676
3679
  var _vm = this,
3677
3680
  _c = _vm._self._c;
3678
3681
  return _c('div', {
@@ -3741,7 +3744,11 @@ var MainViewvue_type_template_id_1a4b756c_render = function render() {
3741
3744
  return _vm.chartWheel.apply(null, arguments);
3742
3745
  }
3743
3746
  }
3744
- }, [_c('chart')], 1)])]), _c('div', {
3747
+ }, [_c('chart', {
3748
+ on: {
3749
+ "task-updated": _vm.handleTaskUpdated
3750
+ }
3751
+ })], 1)])]), _c('div', {
3745
3752
  ref: "chartScrollContainerVertical",
3746
3753
  staticClass: "gantt-elastic__chart-scroll-container gantt-elastic__chart-scroll-container--vertical",
3747
3754
  style: {
@@ -3777,7 +3784,7 @@ var MainViewvue_type_template_id_1a4b756c_render = function render() {
3777
3784
  }
3778
3785
  })])]);
3779
3786
  };
3780
- var MainViewvue_type_template_id_1a4b756c_staticRenderFns = [];
3787
+ var MainViewvue_type_template_id_33392d22_staticRenderFns = [];
3781
3788
 
3782
3789
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/TaskList/TaskList.vue?vue&type=template&id=74ce1216
3783
3790
  var TaskListvue_type_template_id_74ce1216_render = function render() {
@@ -4584,8 +4591,8 @@ var TaskList_component = normalizeComponent(
4584
4591
  )
4585
4592
 
4586
4593
  /* harmony default export */ var TaskList = (TaskList_component.exports);
4587
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Chart.vue?vue&type=template&id=1d5eb6d6
4588
- var Chartvue_type_template_id_1d5eb6d6_render = function render() {
4594
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Chart.vue?vue&type=template&id=2bc7fe5e
4595
+ var Chartvue_type_template_id_2bc7fe5e_render = function render() {
4589
4596
  var _vm = this,
4590
4597
  _c = _vm._self._c;
4591
4598
  return _c('div', {
@@ -4653,14 +4660,17 @@ var Chartvue_type_template_id_1d5eb6d6_render = function render() {
4653
4660
  tag: "component",
4654
4661
  attrs: {
4655
4662
  "task": task
4663
+ },
4664
+ on: {
4665
+ "task-updated": _vm.handleTaskUpdated
4656
4666
  }
4657
4667
  })], 1);
4658
4668
  })], 2)])])])]);
4659
4669
  };
4660
- var Chartvue_type_template_id_1d5eb6d6_staticRenderFns = [];
4670
+ var Chartvue_type_template_id_2bc7fe5e_staticRenderFns = [];
4661
4671
 
4662
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Grid.vue?vue&type=template&id=b2e4dec2
4663
- var Gridvue_type_template_id_b2e4dec2_render = function render() {
4672
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Grid.vue?vue&type=template&id=244ea0ee
4673
+ var Gridvue_type_template_id_244ea0ee_render = function render() {
4664
4674
  var _vm = this,
4665
4675
  _c = _vm._self._c;
4666
4676
  return _c('svg', {
@@ -4722,7 +4732,7 @@ var Gridvue_type_template_id_b2e4dec2_render = function render() {
4722
4732
  }
4723
4733
  })], 2)]);
4724
4734
  };
4725
- var Gridvue_type_template_id_b2e4dec2_staticRenderFns = [];
4735
+ var Gridvue_type_template_id_244ea0ee_staticRenderFns = [];
4726
4736
 
4727
4737
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Grid.vue?vue&type=script&lang=js
4728
4738
 
@@ -4830,15 +4840,41 @@ var Gridvue_type_template_id_b2e4dec2_staticRenderFns = [];
4830
4840
  let lines = [];
4831
4841
  const state = this.root.state.options;
4832
4842
  let tasks = this.root.visibleTasks;
4833
- for (let index = 0, len = tasks.length; index <= len; index++) {
4834
- const y = index * (state.row.height + state.chart.grid.horizontal.gap * 2) + this.root.style['grid-line-vertical']['stroke-width'] / 2;
4835
- lines.push({
4836
- key: 'hl' + index,
4837
- x1: 0,
4838
- y1: y,
4839
- x2: '100%',
4840
- y2: y
4841
- });
4843
+
4844
+ // If we have tasks, show full grid for all tasks
4845
+ if (tasks.length > 0) {
4846
+ const rowHeight = state.row.height + state.chart.grid.horizontal.gap * 2;
4847
+ const rowCount = tasks.length; // Use actual task count
4848
+
4849
+ for (let index = 0; index <= rowCount; index++) {
4850
+ const y = index * rowHeight + this.root.style['grid-line-vertical']['stroke-width'] / 2;
4851
+ lines.push({
4852
+ key: 'hl' + index,
4853
+ x1: 0,
4854
+ y1: y,
4855
+ x2: '100%',
4856
+ y2: y
4857
+ });
4858
+ }
4859
+ } else {
4860
+ // If no tasks, use reduced viewport height for empty state
4861
+ const viewportHeight = window.innerHeight;
4862
+ const headerHeight = state.calendar.height + state.calendar.gap;
4863
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
4864
+ const reducedHeight = Math.max(availableHeight, 300); // Minimum 300px height
4865
+
4866
+ const rowHeight = state.row.height + state.chart.grid.horizontal.gap * 2;
4867
+ const maxRows = Math.floor(reducedHeight / rowHeight);
4868
+ for (let index = 0; index <= maxRows; index++) {
4869
+ const y = index * rowHeight + this.root.style['grid-line-vertical']['stroke-width'] / 2;
4870
+ lines.push({
4871
+ key: 'hl' + index,
4872
+ x1: 0,
4873
+ y1: y,
4874
+ x2: '100%',
4875
+ y2: y
4876
+ });
4877
+ }
4842
4878
  }
4843
4879
  return lines;
4844
4880
  },
@@ -4887,8 +4923,8 @@ var Gridvue_type_template_id_b2e4dec2_staticRenderFns = [];
4887
4923
  ;
4888
4924
  var Grid_component = normalizeComponent(
4889
4925
  Chart_Gridvue_type_script_lang_js,
4890
- Gridvue_type_template_id_b2e4dec2_render,
4891
- Gridvue_type_template_id_b2e4dec2_staticRenderFns,
4926
+ Gridvue_type_template_id_244ea0ee_render,
4927
+ Gridvue_type_template_id_244ea0ee_staticRenderFns,
4892
4928
  false,
4893
4929
  null,
4894
4930
  null,
@@ -5840,8 +5876,8 @@ var DependencyLines_component = normalizeComponent(
5840
5876
  )
5841
5877
 
5842
5878
  /* harmony default export */ var DependencyLines = (DependencyLines_component.exports);
5843
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Task.vue?vue&type=template&id=208a9baa
5844
- var Taskvue_type_template_id_208a9baa_render = function render() {
5879
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Task.vue?vue&type=template&id=2c01a3c8
5880
+ var Taskvue_type_template_id_2c01a3c8_render = function render() {
5845
5881
  var _vm = this,
5846
5882
  _c = _vm._self._c;
5847
5883
  return _c('g', {
@@ -5878,11 +5914,11 @@ var Taskvue_type_template_id_208a9baa_render = function render() {
5878
5914
  ..._vm.task.style['chart-row-bar']
5879
5915
  },
5880
5916
  attrs: {
5881
- "x": _vm.task.x,
5917
+ "x": _vm.task.x - 8,
5882
5918
  "y": _vm.task.y,
5883
- "width": _vm.task.width,
5919
+ "width": _vm.task.width + 16,
5884
5920
  "height": _vm.task.height,
5885
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
5921
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
5886
5922
  "xmlns": "http://www.w3.org/2000/svg"
5887
5923
  },
5888
5924
  on: {
@@ -5937,20 +5973,74 @@ var Taskvue_type_template_id_208a9baa_render = function render() {
5937
5973
  ..._vm.task.style['chart-row-bar-polygon']
5938
5974
  },
5939
5975
  attrs: {
5940
- "points": _vm.getPoints
5976
+ "points": _vm.getPointsAdjusted
5977
+ },
5978
+ on: {
5979
+ "mousedown": function ($event) {
5980
+ return _vm.startDrag($event, 'move');
5981
+ },
5982
+ "touchstart": function ($event) {
5983
+ return _vm.startDrag($event, 'move');
5984
+ }
5941
5985
  }
5942
5986
  }), _c('progress-bar', {
5943
5987
  attrs: {
5944
5988
  "task": _vm.task,
5945
5989
  "clip-path": 'url(#' + _vm.clipPathId + ')'
5946
5990
  }
5991
+ }), _c('rect', {
5992
+ staticClass: "gantt-elastic__chart-row-extend-handle",
5993
+ staticStyle: {
5994
+ "pointer-events": "all",
5995
+ "z-index": "20"
5996
+ },
5997
+ style: _vm.root.style['chart-row-extend-handle'],
5998
+ attrs: {
5999
+ "x": "8",
6000
+ "y": "0",
6001
+ "width": 8,
6002
+ "height": _vm.task.height
6003
+ },
6004
+ on: {
6005
+ "mousedown": function ($event) {
6006
+ $event.stopPropagation();
6007
+ return _vm.startDrag($event, 'start');
6008
+ },
6009
+ "touchstart": function ($event) {
6010
+ $event.stopPropagation();
6011
+ return _vm.startDrag($event, 'start');
6012
+ }
6013
+ }
6014
+ }), _c('rect', {
6015
+ staticClass: "gantt-elastic__chart-row-extend-handle",
6016
+ staticStyle: {
6017
+ "pointer-events": "all",
6018
+ "z-index": "20"
6019
+ },
6020
+ style: _vm.root.style['chart-row-extend-handle'],
6021
+ attrs: {
6022
+ "x": _vm.task.width - 8,
6023
+ "y": "0",
6024
+ "width": 8,
6025
+ "height": _vm.task.height
6026
+ },
6027
+ on: {
6028
+ "mousedown": function ($event) {
6029
+ $event.stopPropagation();
6030
+ return _vm.startDrag($event, 'end');
6031
+ },
6032
+ "touchstart": function ($event) {
6033
+ $event.stopPropagation();
6034
+ return _vm.startDrag($event, 'end');
6035
+ }
6036
+ }
5947
6037
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
5948
6038
  attrs: {
5949
6039
  "task": _vm.task
5950
6040
  }
5951
6041
  }) : _vm._e()], 1);
5952
6042
  };
5953
- var Taskvue_type_template_id_208a9baa_staticRenderFns = [];
6043
+ var Taskvue_type_template_id_2c01a3c8_staticRenderFns = [];
5954
6044
 
5955
6045
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Text.vue?vue&type=template&id=634f40aa
5956
6046
  var Textvue_type_template_id_634f40aa_render = function render() {
@@ -6087,15 +6177,16 @@ var Text_component = normalizeComponent(
6087
6177
  )
6088
6178
 
6089
6179
  /* harmony default export */ var Text = (Text_component.exports);
6090
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/ProgressBar.vue?vue&type=template&id=bc869ae8
6091
- var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6180
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/ProgressBar.vue?vue&type=template&id=2323ee21
6181
+ var ProgressBarvue_type_template_id_2323ee21_render = function render() {
6092
6182
  var _vm = this,
6093
6183
  _c = _vm._self._c;
6094
6184
  return _c('g', {
6095
6185
  staticClass: "gantt-elastic__chart-row-progress-bar-wrapper",
6096
6186
  style: {
6097
6187
  ..._vm.root.style['chart-row-progress-bar-wrapper'],
6098
- ..._vm.task.style['chart-row-progress-bar-wrapper']
6188
+ ..._vm.task.style['chart-row-progress-bar-wrapper'],
6189
+ 'pointer-events': 'none'
6099
6190
  }
6100
6191
  }, [_c('defs', [_c('pattern', {
6101
6192
  attrs: {
@@ -6117,8 +6208,11 @@ var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6117
6208
  "x2": "0",
6118
6209
  "y2": _vm.root.state.options.chart.progress.width
6119
6210
  }
6120
- })])]), _vm.root.state.options.chart.progress.bar ? _c('rect', {
6211
+ })])]), _vm.root.state.options.chart.progress.bar && _vm.task.progress > 0 ? _c('rect', {
6121
6212
  staticClass: "gantt-elastic__chart-row-progress-bar-solid",
6213
+ staticStyle: {
6214
+ "pointer-events": "none"
6215
+ },
6122
6216
  style: {
6123
6217
  ..._vm.root.style['chart-row-progress-bar-solid'],
6124
6218
  ..._vm.task.style['chart-row-progress-bar-solid']
@@ -6128,7 +6222,11 @@ var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6128
6222
  "y": "0",
6129
6223
  "width": _vm.getProgressWidth
6130
6224
  }
6131
- }) : _vm._e(), _vm.root.state.options.chart.progress.pattern ? _c('g', [_c('rect', {
6225
+ }) : _vm._e(), _vm.root.state.options.chart.progress.pattern && _vm.task.progress > 0 ? _c('g', {
6226
+ staticStyle: {
6227
+ "pointer-events": "none"
6228
+ }
6229
+ }, [_c('rect', {
6132
6230
  staticClass: "gantt-elastic__chart-row-progress-bar-pattern",
6133
6231
  style: {
6134
6232
  ..._vm.root.style['chart-row-progress-bar-pattern'],
@@ -6152,7 +6250,7 @@ var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6152
6250
  }
6153
6251
  })]) : _vm._e()]);
6154
6252
  };
6155
- var ProgressBarvue_type_template_id_bc869ae8_staticRenderFns = [];
6253
+ var ProgressBarvue_type_template_id_2323ee21_staticRenderFns = [];
6156
6254
 
6157
6255
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/ProgressBar.vue?vue&type=script&lang=js
6158
6256
  /* harmony default export */ var ProgressBarvue_type_script_lang_js = ({
@@ -6213,8 +6311,8 @@ var ProgressBarvue_type_template_id_bc869ae8_staticRenderFns = [];
6213
6311
  ;
6214
6312
  var ProgressBar_component = normalizeComponent(
6215
6313
  Chart_ProgressBarvue_type_script_lang_js,
6216
- ProgressBarvue_type_template_id_bc869ae8_render,
6217
- ProgressBarvue_type_template_id_bc869ae8_staticRenderFns,
6314
+ ProgressBarvue_type_template_id_2323ee21_render,
6315
+ ProgressBarvue_type_template_id_2323ee21_staticRenderFns,
6218
6316
  false,
6219
6317
  null,
6220
6318
  null,
@@ -6271,11 +6369,631 @@ var ProgressBar_component = normalizeComponent(
6271
6369
  }
6272
6370
  }
6273
6371
  });
6372
+ ;// ./src/components/Chart/Row/Draggable.mixin.js
6373
+
6374
+
6375
+ /* harmony default export */ var Draggable_mixin = ({
6376
+ data() {
6377
+ return {
6378
+ isDragging: false,
6379
+ dragStartX: 0,
6380
+ dragStartTime: 0,
6381
+ dragType: null,
6382
+ // 'start', 'end', or 'move'
6383
+ originalStartTime: 0,
6384
+ originalEndTime: 0,
6385
+ originalDuration: 0
6386
+ };
6387
+ },
6388
+ methods: {
6389
+ startDrag(event, type) {
6390
+ event.preventDefault();
6391
+ event.stopPropagation();
6392
+
6393
+ // Debug logging
6394
+ console.log('Starting drag:', {
6395
+ type: type,
6396
+ taskId: this.task.id,
6397
+ taskType: this.task.type,
6398
+ originalStart: this.task.startTime,
6399
+ originalEnd: this.task.endTime
6400
+ });
6401
+
6402
+ // Safety checks
6403
+ if (!this.root || !this.root.state || !this.root.state.options || !this.root.state.options.times) {
6404
+ console.error('Root or times options not available for dragging');
6405
+ return;
6406
+ }
6407
+ this.isDragging = true;
6408
+ this.dragType = type;
6409
+ this.dragStartX = event.clientX || event.touches[0].clientX;
6410
+ this.dragStartTime = this.task.startTime;
6411
+ this.originalStartTime = this.task.startTime;
6412
+ this.originalEndTime = this.task.endTime;
6413
+ this.originalDuration = this.task.duration;
6414
+
6415
+ // Add event listeners
6416
+ document.addEventListener('mousemove', this.handleDrag);
6417
+ document.addEventListener('mouseup', this.endDrag);
6418
+ document.addEventListener('touchmove', this.handleDrag);
6419
+ document.addEventListener('touchend', this.endDrag);
6420
+
6421
+ // Hide hover tooltip when dragging starts
6422
+ this.hideHoverTooltip();
6423
+
6424
+ // Add context menu for extending tasks
6425
+ // this.$el.addEventListener('contextmenu', this.showContextMenu);
6426
+
6427
+ // Add keyboard shortcuts
6428
+ this.$el.addEventListener('keydown', this.handleKeyboardShortcuts);
6429
+
6430
+ // Add dragging class for visual feedback
6431
+ this.$el.classList.add('gantt-elastic__task-dragging');
6432
+ this.$el.classList.add(`gantt-elastic__task-dragging--${type}`);
6433
+
6434
+ // Create date tooltip for all dragging types
6435
+ this.createDateTooltip();
6436
+ },
6437
+ handleDrag(event) {
6438
+ if (!this.isDragging) return;
6439
+ event.preventDefault();
6440
+ const currentX = event.clientX || event.touches[0].clientX;
6441
+ const deltaX = currentX - this.dragStartX;
6442
+
6443
+ // Convert pixel delta to time delta
6444
+ const timeDelta = deltaX * this.root.state.options.times.timePerPixel;
6445
+ if (this.dragType === 'move') {
6446
+ // Move entire task
6447
+ const newStartTime = this.originalStartTime + timeDelta;
6448
+ const newEndTime = this.originalEndTime + timeDelta;
6449
+
6450
+ // Ensure task doesn't go before chart start
6451
+ const chartStartTime = this.root.state.options.times.firstTime;
6452
+ const chartEndTime = this.root.state.options.times.lastTime;
6453
+ if (newStartTime >= chartStartTime && newEndTime <= chartEndTime) {
6454
+ this.updateTaskTime(newStartTime, newEndTime);
6455
+
6456
+ // Update date tooltip for move dragging
6457
+ if (this.dateTooltip) {
6458
+ this.updateDateTooltip(newStartTime);
6459
+ }
6460
+ }
6461
+ } else if (this.dragType === 'start') {
6462
+ // Resize from start - change start date
6463
+ const newStartTime = this.originalStartTime + timeDelta;
6464
+ const newEndTime = this.originalEndTime;
6465
+
6466
+ // Ensure start doesn't go after end and respects minimum duration
6467
+ const minDuration = 24 * 60 * 60 * 1000; // 1 day minimum
6468
+ const chartStartTime = this.root.state.options.times.firstTime;
6469
+ if (newStartTime < newEndTime && newEndTime - newStartTime >= minDuration && newStartTime >= chartStartTime) {
6470
+ this.updateTaskTime(newStartTime, newEndTime);
6471
+
6472
+ // Update date tooltip for start dragging
6473
+ if (this.dateTooltip) {
6474
+ this.updateDateTooltip(newStartTime);
6475
+ }
6476
+ }
6477
+ } else if (this.dragType === 'end') {
6478
+ // Resize from end - change end date while keeping start fixed
6479
+ const newStartTime = this.originalStartTime;
6480
+ const newEndTime = this.originalEndTime + timeDelta;
6481
+
6482
+ // Ensure end doesn't go before start and respects minimum duration
6483
+ const minDuration = 24 * 60 * 60 * 1000; // 1 day minimum
6484
+
6485
+ if (newEndTime > newStartTime && newEndTime - newStartTime >= minDuration) {
6486
+ // Allow extending beyond chart end time if needed
6487
+ this.updateTaskTime(newStartTime, newEndTime);
6488
+
6489
+ // Update date tooltip for end dragging
6490
+ if (this.dateTooltip) {
6491
+ this.updateDateTooltip(newEndTime);
6492
+ }
6493
+ }
6494
+ }
6495
+ },
6496
+ endDrag(event) {
6497
+ if (!this.isDragging) return;
6498
+ this.isDragging = false;
6499
+
6500
+ // Remove event listeners
6501
+ document.removeEventListener('mousemove', this.handleDrag);
6502
+ document.removeEventListener('mouseup', this.endDrag);
6503
+ document.removeEventListener('touchmove', this.handleDrag);
6504
+ document.removeEventListener('touchend', this.endDrag);
6505
+
6506
+ // Remove dragging classes
6507
+ this.$el.classList.remove('gantt-elastic__task-dragging');
6508
+ this.$el.classList.remove(`gantt-elastic__task-dragging--${this.dragType}`);
6509
+
6510
+ // Remove date tooltip
6511
+ this.removeDateTooltip();
6512
+
6513
+ // Emit save event with updated data
6514
+ this.emitSaveEvent();
6515
+ },
6516
+ updateTaskTime(newStartTime, newEndTime) {
6517
+ // Ensure valid times
6518
+ if (newStartTime >= newEndTime) {
6519
+ return; // Don't update if invalid
6520
+ }
6521
+
6522
+ // Debug logging for epic tasks
6523
+ if (this.task.type === 'epic') {
6524
+ console.log('Epic task drag:', {
6525
+ dragType: this.dragType,
6526
+ originalStart: this.originalStartTime,
6527
+ originalEnd: this.originalEndTime,
6528
+ newStart: newStartTime,
6529
+ newEnd: newEndTime,
6530
+ startChanged: newStartTime !== this.originalStartTime,
6531
+ endChanged: newEndTime !== this.originalEndTime
6532
+ });
6533
+ }
6534
+
6535
+ // Update task data
6536
+ this.task.startTime = newStartTime;
6537
+ this.task.endTime = newEndTime;
6538
+ this.task.duration = newEndTime - newStartTime;
6539
+
6540
+ // Debug logging
6541
+ console.log('Updating task time:', {
6542
+ taskId: this.task.id,
6543
+ newStartTime,
6544
+ newEndTime,
6545
+ duration: this.task.duration,
6546
+ root: !!this.root,
6547
+ timeToPixelOffsetX: !!(this.root && this.root.timeToPixelOffsetX),
6548
+ timePerPixel: this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel
6549
+ });
6550
+
6551
+ // Update task position and width using the correct method
6552
+ if (this.root && this.root.timeToPixelOffsetX) {
6553
+ this.task.x = this.root.timeToPixelOffsetX(newStartTime);
6554
+ this.task.width = this.root.timeToPixelOffsetX(newEndTime) - this.task.x;
6555
+ } else {
6556
+ // Fallback calculation if method is not available
6557
+ const timePerPixel = this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel;
6558
+ if (timePerPixel > 0) {
6559
+ this.task.x = (newStartTime - this.root.state.options.times.firstTime) / timePerPixel;
6560
+ this.task.width = (newEndTime - newStartTime) / timePerPixel;
6561
+ } else {
6562
+ console.error('timePerPixel is not available or invalid:', timePerPixel);
6563
+ }
6564
+ }
6565
+
6566
+ // Force update
6567
+ this.$forceUpdate();
6568
+ },
6569
+ emitSaveEvent() {
6570
+ // Calculate date information
6571
+ const startDate = new Date(this.task.startTime);
6572
+ const endDate = new Date(this.task.endTime);
6573
+ const durationDays = Math.ceil(this.task.duration / (24 * 60 * 60 * 1000));
6574
+
6575
+ // Emit event to parent component with updated task data
6576
+ this.$emit('task-updated', {
6577
+ id: this.task.id,
6578
+ startTime: this.task.startTime,
6579
+ endTime: this.task.endTime,
6580
+ duration: this.task.duration,
6581
+ durationDays: durationDays,
6582
+ startDate: startDate.toISOString(),
6583
+ endDate: endDate.toISOString(),
6584
+ startDateFormatted: startDate.toLocaleDateString(),
6585
+ endDateFormatted: endDate.toLocaleDateString(),
6586
+ dragType: this.dragType,
6587
+ originalStartTime: this.originalStartTime,
6588
+ originalEndTime: this.originalEndTime,
6589
+ originalDuration: this.originalDuration
6590
+ });
6591
+
6592
+ // Log the update for debugging
6593
+ console.log('Task drag completed:', {
6594
+ id: this.task.id,
6595
+ dragType: this.dragType,
6596
+ startDate: startDate.toLocaleDateString(),
6597
+ endDate: endDate.toLocaleDateString(),
6598
+ duration: `${durationDays} days`,
6599
+ startTime: this.task.startTime,
6600
+ endTime: this.task.endTime
6601
+ });
6602
+ },
6603
+ /**
6604
+ * Show context menu for task actions
6605
+ *
6606
+ * @param {Event} event - Right-click event
6607
+ */
6608
+ // showContextMenu(event) {
6609
+ // event.preventDefault();
6610
+ //
6611
+ // // Remove existing context menu
6612
+ // this.hideContextMenu();
6613
+ //
6614
+ // // Create context menu
6615
+ // const contextMenu = document.createElement('div');
6616
+ // contextMenu.className = 'gantt-elastic__context-menu';
6617
+ // contextMenu.style.cssText = `
6618
+ // position: fixed;
6619
+ // top: ${event.clientY}px;
6620
+ // left: ${event.clientX}px;
6621
+ // background: white;
6622
+ // border: 1px solid #e5e7eb;
6623
+ // border-radius: 6px;
6624
+ // box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
6625
+ // z-index: 1000;
6626
+ // min-width: 150px;
6627
+ // padding: 4px 0;
6628
+ // `;
6629
+ //
6630
+ // // Add menu items
6631
+ // const menuItems = [
6632
+ // { text: 'Extend to Next Date', action: () => this.extendTaskToNextDate() },
6633
+ // { text: 'Extend by 1 Day', action: () => this.extendTaskByDays(1) },
6634
+ // { text: 'Extend by 3 Days', action: () => this.extendTaskByDays(3) },
6635
+ // { text: 'Extend by 1 Week', action: () => this.extendTaskByDays(7) }
6636
+ // ];
6637
+ //
6638
+ // menuItems.forEach(item => {
6639
+ // const menuItem = document.createElement('div');
6640
+ // menuItem.className = 'gantt-elastic__context-menu-item';
6641
+ // menuItem.textContent = item.text;
6642
+ // menuItem.style.cssText = `
6643
+ // padding: 8px 16px;
6644
+ // cursor: pointer;
6645
+ // font-size: 14px;
6646
+ // color: #374151;
6647
+ // transition: background-color 0.2s;
6648
+ // `;
6649
+ //
6650
+ // menuItem.addEventListener('mouseenter', () => {
6651
+ // menuItem.style.backgroundColor = '#f3f4f6';
6652
+ // });
6653
+ //
6654
+ // menuItem.addEventListener('mouseleave', () => {
6655
+ // menuItem.style.backgroundColor = 'transparent';
6656
+ // });
6657
+ //
6658
+ // menuItem.addEventListener('click', () => {
6659
+ // item.action();
6660
+ // this.hideContextMenu();
6661
+ // });
6662
+ //
6663
+ // contextMenu.appendChild(menuItem);
6664
+ // });
6665
+ //
6666
+ // // Add to document
6667
+ // document.body.appendChild(contextMenu);
6668
+ // this.contextMenu = contextMenu;
6669
+ //
6670
+ // // Close menu when clicking outside
6671
+ // setTimeout(() => {
6672
+ // document.addEventListener('click', this.hideContextMenu);
6673
+ // }, 0);
6674
+ // },
6675
+
6676
+ /**
6677
+ * Hide context menu
6678
+ */
6679
+ // hideContextMenu() {
6680
+ // if (this.contextMenu) {
6681
+ // document.body.removeChild(this.contextMenu);
6682
+ // this.contextMenu = null;
6683
+ // document.removeEventListener('click', this.hideContextMenu);
6684
+ // }
6685
+ // },
6686
+
6687
+ /**
6688
+ * Extend task to next date (1 day)
6689
+ */
6690
+ // extendTaskToNextDate() {
6691
+ // const additionalDuration = 24 * 60 * 60 * 1000; // 1 day
6692
+ // this.task.duration += additionalDuration;
6693
+ // this.task.endTime += additionalDuration;
6694
+ //
6695
+ // // Update task position and width
6696
+ // if (this.root && this.root.timeToPixelOffsetX) {
6697
+ // this.task.width = this.root.timeToPixelOffsetX(this.task.endTime) - this.task.x;
6698
+ // } else {
6699
+ // const timePerPixel = this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel;
6700
+ // if (timePerPixel > 0) {
6701
+ // this.task.width = (this.task.endTime - this.task.startTime) / timePerPixel;
6702
+ // }
6703
+ // }
6704
+ //
6705
+ // // Emit update event
6706
+ // this.emitSaveEvent();
6707
+ //
6708
+ // console.log(`✅ Task extended to next date:`, {
6709
+ // taskId: this.task.id,
6710
+ // newDuration: this.task.duration,
6711
+ // newEndDate: new Date(this.task.endTime).toLocaleDateString()
6712
+ // });
6713
+ // },
6714
+
6715
+ /**
6716
+ * Extend task by specific number of days
6717
+ *
6718
+ * @param {number} days - Number of days to add
6719
+ */
6720
+ // extendTaskByDays(days) {
6721
+ // const additionalDuration = days * 24 * 60 * 60 * 1000;
6722
+ // this.task.duration += additionalDuration;
6723
+ // this.task.endTime += additionalDuration;
6724
+ //
6725
+ // // Update task position and width
6726
+ // if (this.root && this.root.timeToPixelOffsetX) {
6727
+ // this.task.width = this.root.timeToPixelOffsetX(this.task.endTime) - this.task.x;
6728
+ // } else {
6729
+ // const timePerPixel = this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel;
6730
+ // if (timePerPixel > 0) {
6731
+ // this.task.width = (this.task.endTime - this.task.startTime) / timePerPixel;
6732
+ // }
6733
+ // }
6734
+ //
6735
+ // // Emit update event
6736
+ // this.emitSaveEvent();
6737
+ //
6738
+ // console.log(`✅ Task extended by ${days} day(s):`, {
6739
+ // taskId: this.task.id,
6740
+ // daysAdded: days,
6741
+ // newDuration: this.task.duration,
6742
+ // newEndDate: new Date(this.task.endTime).toLocaleDateString()
6743
+ // });
6744
+ // },
6745
+
6746
+ /**
6747
+ * Handle keyboard shortcuts for task extension
6748
+ *
6749
+ * @param {KeyboardEvent} event - Keyboard event
6750
+ */
6751
+ handleKeyboardShortcuts(event) {
6752
+ // Only handle if task is focused and not dragging
6753
+ if (this.isDragging) return;
6754
+
6755
+ // Check for Ctrl/Cmd + E for extend to next date
6756
+ if ((event.ctrlKey || event.metaKey) && event.key === 'e') {
6757
+ event.preventDefault();
6758
+ this.extendTaskToNextDate();
6759
+ }
6760
+ // Check for Ctrl/Cmd + Shift + E for extend by 1 day
6761
+ else if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'E') {
6762
+ event.preventDefault();
6763
+ this.extendTaskByDays(1);
6764
+ }
6765
+ // Check for Ctrl/Cmd + 3 for extend by 3 days
6766
+ else if ((event.ctrlKey || event.metaKey) && event.key === '3') {
6767
+ event.preventDefault();
6768
+ this.extendTaskByDays(3);
6769
+ }
6770
+ // Check for Ctrl/Cmd + 7 for extend by 1 week
6771
+ else if ((event.ctrlKey || event.metaKey) && event.key === '7') {
6772
+ event.preventDefault();
6773
+ this.extendTaskByDays(7);
6774
+ }
6775
+ },
6776
+ /**
6777
+ * Create date tooltip for end dragging
6778
+ */
6779
+ createDateTooltip() {
6780
+ this.dateTooltip = document.createElement('div');
6781
+ this.dateTooltip.className = 'gantt-elastic__date-tooltip';
6782
+ this.dateTooltip.style.cssText = `
6783
+ position: fixed;
6784
+ background: #000000;
6785
+ color: white;
6786
+ padding: 6px 12px;
6787
+ border-radius: 6px;
6788
+ font-size: 13px;
6789
+ font-family: system-ui, -apple-system, sans-serif;
6790
+ font-weight: 500;
6791
+ pointer-events: none;
6792
+ z-index: 10000;
6793
+ white-space: nowrap;
6794
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
6795
+ border: 1px solid rgba(255, 255, 255, 0.1);
6796
+ `;
6797
+ document.body.appendChild(this.dateTooltip);
6798
+
6799
+ // Initialize tooltip with current values
6800
+ if (this.dragType === 'start') {
6801
+ this.updateDateTooltip(this.originalStartTime);
6802
+ } else if (this.dragType === 'end') {
6803
+ this.updateDateTooltip(this.originalEndTime);
6804
+ } else if (this.dragType === 'move') {
6805
+ this.updateDateTooltip(this.originalStartTime);
6806
+ }
6807
+ },
6808
+ /**
6809
+ * Update date tooltip with new time and day changes
6810
+ *
6811
+ * @param {number} newTime - New time in milliseconds
6812
+ */
6813
+ updateDateTooltip(newTime) {
6814
+ if (!this.dateTooltip) return;
6815
+ const newDate = new Date(newTime);
6816
+ const formattedDate = newDate.toLocaleDateString('en-US', {
6817
+ year: 'numeric',
6818
+ month: 'short',
6819
+ day: 'numeric'
6820
+ });
6821
+
6822
+ // Calculate day changes based on drag type
6823
+ let dayChanges = '';
6824
+ if (this.dragType === 'start') {
6825
+ // For start drag, show how many days we're moving the start date
6826
+ const daysDiff = Math.round((newTime - this.originalStartTime) / (24 * 60 * 60 * 1000));
6827
+ if (daysDiff !== 0) {
6828
+ dayChanges = daysDiff > 0 ? ` (+${daysDiff} days)` : ` (${daysDiff} days)`;
6829
+ }
6830
+ } else if (this.dragType === 'end') {
6831
+ // For end drag, show how many days we're moving the end date
6832
+ const daysDiff = Math.round((newTime - this.originalEndTime) / (24 * 60 * 60 * 1000));
6833
+ if (daysDiff !== 0) {
6834
+ dayChanges = daysDiff > 0 ? ` (+${daysDiff} days)` : ` (${daysDiff} days)`;
6835
+ }
6836
+ } else if (this.dragType === 'move') {
6837
+ // For move drag, show how many days we're moving the entire task
6838
+ const daysDiff = Math.round((newTime - this.originalStartTime) / (24 * 60 * 60 * 1000));
6839
+ if (daysDiff !== 0) {
6840
+ dayChanges = daysDiff > 0 ? ` (+${daysDiff} days)` : ` (${daysDiff} days)`;
6841
+ }
6842
+ }
6843
+ this.dateTooltip.textContent = `${formattedDate}${dayChanges}`;
6844
+
6845
+ // Position tooltip based on drag type
6846
+ const rect = this.$el.getBoundingClientRect();
6847
+ if (this.dragType === 'start') {
6848
+ // Position tooltip on the left side for start drag
6849
+ this.dateTooltip.style.left = `${rect.left - this.dateTooltip.offsetWidth - 10}px`;
6850
+ this.dateTooltip.style.top = `${rect.top + rect.height / 2 - 10}px`;
6851
+ } else if (this.dragType === 'end') {
6852
+ // Position tooltip on the right side for end drag
6853
+ this.dateTooltip.style.left = `${rect.right + 10}px`;
6854
+ this.dateTooltip.style.top = `${rect.top + rect.height / 2 - 10}px`;
6855
+ } else if (this.dragType === 'move') {
6856
+ // Position tooltip on the right side for move drag
6857
+ this.dateTooltip.style.left = `${rect.right + 10}px`;
6858
+ this.dateTooltip.style.top = `${rect.top + rect.height / 2 - 10}px`;
6859
+ }
6860
+ },
6861
+ /**
6862
+ * Remove date tooltip
6863
+ */
6864
+ removeDateTooltip() {
6865
+ if (this.dateTooltip) {
6866
+ document.body.removeChild(this.dateTooltip);
6867
+ this.dateTooltip = null;
6868
+ }
6869
+ },
6870
+ /**
6871
+ * Add hover tooltips for drag handles
6872
+ */
6873
+ addHoverTooltips() {
6874
+ // Find drag handles in the current element
6875
+ const dragHandles = this.$el.querySelectorAll('.gantt-elastic__chart-row-extend-handle');
6876
+ dragHandles.forEach((handle, index) => {
6877
+ const isStartHandle = index === 0; // First handle is start, second is end
6878
+
6879
+ // Remove existing listeners to avoid duplicates
6880
+ handle.removeEventListener('mouseenter', this.handleMouseEnter);
6881
+ handle.removeEventListener('mouseleave', this.handleMouseLeave);
6882
+
6883
+ // Add new listeners
6884
+ handle.addEventListener('mouseenter', this.handleMouseEnter.bind(this));
6885
+ handle.addEventListener('mouseleave', this.handleMouseLeave.bind(this));
6886
+ });
6887
+ },
6888
+ /**
6889
+ * Handle mouse enter on drag handle
6890
+ */
6891
+ handleMouseEnter(event) {
6892
+ if (!this.isDragging) {
6893
+ this.showHoverTooltip(event, false);
6894
+ }
6895
+ },
6896
+ /**
6897
+ * Handle mouse leave on drag handle
6898
+ */
6899
+ handleMouseLeave() {
6900
+ if (!this.isDragging) {
6901
+ this.hideHoverTooltip();
6902
+ }
6903
+ },
6904
+ /**
6905
+ * Show hover tooltip with date range and duration
6906
+ */
6907
+ showHoverTooltip(event, isStartHandle) {
6908
+ this.hideHoverTooltip(); // Remove any existing tooltip
6909
+
6910
+ const startDate = new Date(this.task.startTime);
6911
+ const endDate = new Date(this.task.endTime);
6912
+ const startFormatted = startDate.toLocaleDateString('en-US', {
6913
+ year: 'numeric',
6914
+ month: 'short',
6915
+ day: 'numeric'
6916
+ });
6917
+ const endFormatted = endDate.toLocaleDateString('en-US', {
6918
+ year: 'numeric',
6919
+ month: 'short',
6920
+ day: 'numeric'
6921
+ });
6922
+
6923
+ // Calculate duration in days
6924
+ const durationMs = this.task.endTime - this.task.startTime;
6925
+ const durationDays = Math.ceil(durationMs / (24 * 60 * 60 * 1000));
6926
+ this.hoverTooltip = document.createElement('div');
6927
+ this.hoverTooltip.className = 'gantt-elastic__hover-tooltip';
6928
+ this.hoverTooltip.textContent = `${startFormatted} - ${endFormatted} (${durationDays} days)`;
6929
+ this.hoverTooltip.style.cssText = `
6930
+ position: fixed;
6931
+ background: #333333;
6932
+ color: white;
6933
+ padding: 8px 12px;
6934
+ border-radius: 6px;
6935
+ font-size: 13px;
6936
+ font-family: system-ui, -apple-system, sans-serif;
6937
+ font-weight: 500;
6938
+ pointer-events: none;
6939
+ z-index: 10001;
6940
+ white-space: nowrap;
6941
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
6942
+ border: 1px solid rgba(255, 255, 255, 0.1);
6943
+ `;
6944
+ document.body.appendChild(this.hoverTooltip);
6945
+
6946
+ // Position tooltip above the handle
6947
+ const rect = event.target.getBoundingClientRect();
6948
+ this.hoverTooltip.style.left = `${rect.left + rect.width / 2 - this.hoverTooltip.offsetWidth / 2}px`;
6949
+ this.hoverTooltip.style.top = `${rect.top - this.hoverTooltip.offsetHeight - 8}px`;
6950
+ },
6951
+ /**
6952
+ * Hide hover tooltip
6953
+ */
6954
+ hideHoverTooltip() {
6955
+ if (this.hoverTooltip) {
6956
+ document.body.removeChild(this.hoverTooltip);
6957
+ this.hoverTooltip = null;
6958
+ }
6959
+ }
6960
+ },
6961
+ mounted() {
6962
+ // Add hover tooltips when component is mounted
6963
+ this.$nextTick(() => {
6964
+ this.addHoverTooltips();
6965
+ });
6966
+ },
6967
+ beforeDestroy() {
6968
+ // Clean up event listeners
6969
+ document.removeEventListener('mousemove', this.handleDrag);
6970
+ document.removeEventListener('mouseup', this.endDrag);
6971
+ document.removeEventListener('touchmove', this.handleDrag);
6972
+ document.removeEventListener('touchend', this.endDrag);
6973
+ document.removeEventListener('click', this.hideContextMenu);
6974
+
6975
+ // Clean up context menu
6976
+ this.hideContextMenu();
6977
+
6978
+ // Clean up date tooltip
6979
+ this.removeDateTooltip();
6980
+
6981
+ // Clean up hover tooltip
6982
+ this.hideHoverTooltip();
6983
+
6984
+ // Clean up keyboard listeners
6985
+ if (this.$el) {
6986
+ // this.$el.removeEventListener('contextmenu', this.showContextMenu);
6987
+ this.$el.removeEventListener('keydown', this.handleKeyboardShortcuts);
6988
+ }
6989
+ }
6990
+ });
6274
6991
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Task.vue?vue&type=script&lang=js
6275
6992
 
6276
6993
 
6277
6994
 
6278
6995
 
6996
+
6279
6997
  /* harmony default export */ var Taskvue_type_script_lang_js = ({
6280
6998
  name: 'Task',
6281
6999
  components: {
@@ -6285,7 +7003,7 @@ var ProgressBar_component = normalizeComponent(
6285
7003
  },
6286
7004
  inject: ['root'],
6287
7005
  props: ['task'],
6288
- mixins: [Task_mixin],
7006
+ mixins: [Task_mixin, Draggable_mixin],
6289
7007
  data() {
6290
7008
  return {};
6291
7009
  },
@@ -6306,6 +7024,15 @@ var ProgressBar_component = normalizeComponent(
6306
7024
  getPoints() {
6307
7025
  const task = this.task;
6308
7026
  return `0,0 ${task.width},0 ${task.width},${task.height} 0,${task.height}`;
7027
+ },
7028
+ /**
7029
+ * Get points adjusted for viewBox
7030
+ *
7031
+ * @returns {string}
7032
+ */
7033
+ getPointsAdjusted() {
7034
+ const task = this.task;
7035
+ return `8,0 ${task.width + 8},0 ${task.width + 8},${task.height} 8,${task.height}`;
6309
7036
  }
6310
7037
  }
6311
7038
  });
@@ -6321,8 +7048,8 @@ var ProgressBar_component = normalizeComponent(
6321
7048
  ;
6322
7049
  var Task_component = normalizeComponent(
6323
7050
  Row_Taskvue_type_script_lang_js,
6324
- Taskvue_type_template_id_208a9baa_render,
6325
- Taskvue_type_template_id_208a9baa_staticRenderFns,
7051
+ Taskvue_type_template_id_2c01a3c8_render,
7052
+ Taskvue_type_template_id_2c01a3c8_staticRenderFns,
6326
7053
  false,
6327
7054
  null,
6328
7055
  null,
@@ -6331,8 +7058,8 @@ var Task_component = normalizeComponent(
6331
7058
  )
6332
7059
 
6333
7060
  /* harmony default export */ var Task = (Task_component.exports);
6334
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Milestone.vue?vue&type=template&id=edd49e02
6335
- var Milestonevue_type_template_id_edd49e02_render = function render() {
7061
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Milestone.vue?vue&type=template&id=4cea99c4
7062
+ var Milestonevue_type_template_id_4cea99c4_render = function render() {
6336
7063
  var _vm = this,
6337
7064
  _c = _vm._self._c;
6338
7065
  return _c('g', {
@@ -6369,11 +7096,11 @@ var Milestonevue_type_template_id_edd49e02_render = function render() {
6369
7096
  ..._vm.task.style['chart-row-bar']
6370
7097
  },
6371
7098
  attrs: {
6372
- "x": _vm.task.x,
7099
+ "x": _vm.task.x - 8,
6373
7100
  "y": _vm.task.y,
6374
- "width": _vm.task.width,
7101
+ "width": _vm.task.width + 16,
6375
7102
  "height": _vm.task.height,
6376
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7103
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6377
7104
  "xmlns": "http://www.w3.org/2000/svg"
6378
7105
  },
6379
7106
  on: {
@@ -6428,26 +7155,81 @@ var Milestonevue_type_template_id_edd49e02_render = function render() {
6428
7155
  ..._vm.task.style['chart-row-bar-polygon']
6429
7156
  },
6430
7157
  attrs: {
6431
- "points": _vm.getPoints
7158
+ "points": _vm.getPointsAdjusted
7159
+ },
7160
+ on: {
7161
+ "mousedown": function ($event) {
7162
+ return _vm.startDrag($event, 'move');
7163
+ },
7164
+ "touchstart": function ($event) {
7165
+ return _vm.startDrag($event, 'move');
7166
+ }
6432
7167
  }
6433
7168
  }), _c('progress-bar', {
6434
7169
  attrs: {
6435
7170
  "task": _vm.task,
6436
7171
  "clip-path": 'url(#' + _vm.clipPathId + ')'
6437
7172
  }
7173
+ }), _c('rect', {
7174
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7175
+ staticStyle: {
7176
+ "pointer-events": "all",
7177
+ "z-index": "20"
7178
+ },
7179
+ style: _vm.root.style['chart-row-extend-handle'],
7180
+ attrs: {
7181
+ "x": "8",
7182
+ "y": "0",
7183
+ "width": 8,
7184
+ "height": _vm.task.height
7185
+ },
7186
+ on: {
7187
+ "mousedown": function ($event) {
7188
+ $event.stopPropagation();
7189
+ return _vm.startDrag($event, 'start');
7190
+ },
7191
+ "touchstart": function ($event) {
7192
+ $event.stopPropagation();
7193
+ return _vm.startDrag($event, 'start');
7194
+ }
7195
+ }
7196
+ }), _c('rect', {
7197
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7198
+ staticStyle: {
7199
+ "pointer-events": "all",
7200
+ "z-index": "20"
7201
+ },
7202
+ style: _vm.root.style['chart-row-extend-handle'],
7203
+ attrs: {
7204
+ "x": _vm.task.width - 8,
7205
+ "y": "0",
7206
+ "width": 8,
7207
+ "height": _vm.task.height
7208
+ },
7209
+ on: {
7210
+ "mousedown": function ($event) {
7211
+ $event.stopPropagation();
7212
+ return _vm.startDrag($event, 'end');
7213
+ },
7214
+ "touchstart": function ($event) {
7215
+ $event.stopPropagation();
7216
+ return _vm.startDrag($event, 'end');
7217
+ }
7218
+ }
6438
7219
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
6439
7220
  attrs: {
6440
7221
  "task": _vm.task
6441
7222
  }
6442
7223
  }) : _vm._e()], 1);
6443
7224
  };
6444
- var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
7225
+ var Milestonevue_type_template_id_4cea99c4_staticRenderFns = [];
6445
7226
 
6446
7227
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Milestone.vue?vue&type=script&lang=js
6447
7228
 
6448
7229
 
6449
7230
 
6450
7231
 
7232
+
6451
7233
  /* harmony default export */ var Milestonevue_type_script_lang_js = ({
6452
7234
  name: 'Milestone',
6453
7235
  components: {
@@ -6457,7 +7239,7 @@ var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
6457
7239
  },
6458
7240
  inject: ['root'],
6459
7241
  props: ['task'],
6460
- mixins: [Task_mixin],
7242
+ mixins: [Task_mixin, Draggable_mixin],
6461
7243
  data() {
6462
7244
  return {};
6463
7245
  },
@@ -6488,6 +7270,25 @@ var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
6488
7270
  ${task.width},${fifty}
6489
7271
  ${task.width - offset},${task.height}
6490
7272
  ${offset},${task.height}`;
7273
+ },
7274
+ /**
7275
+ * Get points adjusted for viewBox
7276
+ *
7277
+ * @returns {string}
7278
+ */
7279
+ getPointsAdjusted() {
7280
+ const task = this.task;
7281
+ const fifty = task.height / 2;
7282
+ let offset = fifty;
7283
+ if (task.width / 2 - offset < 0) {
7284
+ offset = task.width / 2;
7285
+ }
7286
+ return `${8},${fifty}
7287
+ ${8 + offset},0
7288
+ ${8 + task.width - offset},0
7289
+ ${8 + task.width},${fifty}
7290
+ ${8 + task.width - offset},${task.height}
7291
+ ${8 + offset},${task.height}`;
6491
7292
  }
6492
7293
  }
6493
7294
  });
@@ -6503,8 +7304,8 @@ var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
6503
7304
  ;
6504
7305
  var Milestone_component = normalizeComponent(
6505
7306
  Row_Milestonevue_type_script_lang_js,
6506
- Milestonevue_type_template_id_edd49e02_render,
6507
- Milestonevue_type_template_id_edd49e02_staticRenderFns,
7307
+ Milestonevue_type_template_id_4cea99c4_render,
7308
+ Milestonevue_type_template_id_4cea99c4_staticRenderFns,
6508
7309
  false,
6509
7310
  null,
6510
7311
  null,
@@ -6513,8 +7314,8 @@ var Milestone_component = normalizeComponent(
6513
7314
  )
6514
7315
 
6515
7316
  /* harmony default export */ var Milestone = (Milestone_component.exports);
6516
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Project.vue?vue&type=template&id=760bf767
6517
- var Projectvue_type_template_id_760bf767_render = function render() {
7317
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Project.vue?vue&type=template&id=5dcaf9ef
7318
+ var Projectvue_type_template_id_5dcaf9ef_render = function render() {
6518
7319
  var _vm = this,
6519
7320
  _c = _vm._self._c;
6520
7321
  return _c('g', {
@@ -6551,11 +7352,11 @@ var Projectvue_type_template_id_760bf767_render = function render() {
6551
7352
  ..._vm.task.style['chart-row-bar']
6552
7353
  },
6553
7354
  attrs: {
6554
- "x": _vm.task.x,
7355
+ "x": _vm.task.x - 8,
6555
7356
  "y": _vm.task.y,
6556
- "width": _vm.task.width,
7357
+ "width": _vm.task.width + 16,
6557
7358
  "height": _vm.task.height,
6558
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7359
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6559
7360
  "xmlns": "http://www.w3.org/2000/svg"
6560
7361
  },
6561
7362
  on: {
@@ -6610,26 +7411,81 @@ var Projectvue_type_template_id_760bf767_render = function render() {
6610
7411
  ..._vm.task.style['chart-row-bar-polygon']
6611
7412
  },
6612
7413
  attrs: {
6613
- "d": _vm.getPoints
7414
+ "d": _vm.getPointsAdjusted
7415
+ },
7416
+ on: {
7417
+ "mousedown": function ($event) {
7418
+ return _vm.startDrag($event, 'move');
7419
+ },
7420
+ "touchstart": function ($event) {
7421
+ return _vm.startDrag($event, 'move');
7422
+ }
6614
7423
  }
6615
7424
  }), _c('progress-bar', {
6616
7425
  attrs: {
6617
7426
  "task": _vm.task,
6618
7427
  "clip-path": 'url(#' + _vm.clipPathId + ')'
6619
7428
  }
7429
+ }), _c('rect', {
7430
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7431
+ staticStyle: {
7432
+ "pointer-events": "all",
7433
+ "z-index": "20"
7434
+ },
7435
+ style: _vm.root.style['chart-row-extend-handle'],
7436
+ attrs: {
7437
+ "x": "8",
7438
+ "y": "0",
7439
+ "width": 8,
7440
+ "height": _vm.task.height
7441
+ },
7442
+ on: {
7443
+ "mousedown": function ($event) {
7444
+ $event.stopPropagation();
7445
+ return _vm.startDrag($event, 'start');
7446
+ },
7447
+ "touchstart": function ($event) {
7448
+ $event.stopPropagation();
7449
+ return _vm.startDrag($event, 'start');
7450
+ }
7451
+ }
7452
+ }), _c('rect', {
7453
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7454
+ staticStyle: {
7455
+ "pointer-events": "all",
7456
+ "z-index": "20"
7457
+ },
7458
+ style: _vm.root.style['chart-row-extend-handle'],
7459
+ attrs: {
7460
+ "x": _vm.task.width - 8,
7461
+ "y": "0",
7462
+ "width": 8,
7463
+ "height": _vm.task.height
7464
+ },
7465
+ on: {
7466
+ "mousedown": function ($event) {
7467
+ $event.stopPropagation();
7468
+ return _vm.startDrag($event, 'end');
7469
+ },
7470
+ "touchstart": function ($event) {
7471
+ $event.stopPropagation();
7472
+ return _vm.startDrag($event, 'end');
7473
+ }
7474
+ }
6620
7475
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
6621
7476
  attrs: {
6622
7477
  "task": _vm.task
6623
7478
  }
6624
7479
  }) : _vm._e()], 1);
6625
7480
  };
6626
- var Projectvue_type_template_id_760bf767_staticRenderFns = [];
7481
+ var Projectvue_type_template_id_5dcaf9ef_staticRenderFns = [];
6627
7482
 
6628
7483
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Project.vue?vue&type=script&lang=js
6629
7484
 
6630
7485
 
6631
7486
 
6632
7487
 
7488
+
6633
7489
  /* harmony default export */ var Projectvue_type_script_lang_js = ({
6634
7490
  name: 'Project',
6635
7491
  components: {
@@ -6639,7 +7495,7 @@ var Projectvue_type_template_id_760bf767_staticRenderFns = [];
6639
7495
  },
6640
7496
  inject: ['root'],
6641
7497
  props: ['task'],
6642
- mixins: [Task_mixin],
7498
+ mixins: [Task_mixin, Draggable_mixin],
6643
7499
  data() {
6644
7500
  return {};
6645
7501
  },
@@ -6675,6 +7531,29 @@ var Projectvue_type_template_id_760bf767_staticRenderFns = [];
6675
7531
  Z
6676
7532
  `;
6677
7533
  },
7534
+ /**
7535
+ * Get points adjusted for viewBox
7536
+ *
7537
+ * @returns {string}
7538
+ */
7539
+ getPointsAdjusted() {
7540
+ const task = this.task;
7541
+ const bottom = task.height - task.height / 4;
7542
+ const corner = task.height / 6;
7543
+ const smallCorner = task.height / 8;
7544
+ return `M ${8 + smallCorner},0
7545
+ L ${8 + task.width - smallCorner} 0
7546
+ L ${8 + task.width} ${smallCorner}
7547
+ L ${8 + task.width} ${bottom}
7548
+ L ${8 + task.width - corner} ${task.height}
7549
+ L ${8 + task.width - corner * 2} ${bottom}
7550
+ L ${8 + corner * 2} ${bottom}
7551
+ L ${8 + corner} ${task.height}
7552
+ L ${8} ${bottom}
7553
+ L ${8} ${smallCorner}
7554
+ Z
7555
+ `;
7556
+ },
6678
7557
  /**
6679
7558
  * Should we display expander?
6680
7559
  *
@@ -6699,8 +7578,8 @@ var Projectvue_type_template_id_760bf767_staticRenderFns = [];
6699
7578
  ;
6700
7579
  var Project_component = normalizeComponent(
6701
7580
  Row_Projectvue_type_script_lang_js,
6702
- Projectvue_type_template_id_760bf767_render,
6703
- Projectvue_type_template_id_760bf767_staticRenderFns,
7581
+ Projectvue_type_template_id_5dcaf9ef_render,
7582
+ Projectvue_type_template_id_5dcaf9ef_staticRenderFns,
6704
7583
  false,
6705
7584
  null,
6706
7585
  null,
@@ -6709,8 +7588,8 @@ var Project_component = normalizeComponent(
6709
7588
  )
6710
7589
 
6711
7590
  /* harmony default export */ var Project = (Project_component.exports);
6712
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Epic.vue?vue&type=template&id=a2e89cd8
6713
- var Epicvue_type_template_id_a2e89cd8_render = function render() {
7591
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Epic.vue?vue&type=template&id=6e337196
7592
+ var Epicvue_type_template_id_6e337196_render = function render() {
6714
7593
  var _vm = this,
6715
7594
  _c = _vm._self._c;
6716
7595
  return _c('g', {
@@ -6747,11 +7626,11 @@ var Epicvue_type_template_id_a2e89cd8_render = function render() {
6747
7626
  ..._vm.task.style['chart-row-bar']
6748
7627
  },
6749
7628
  attrs: {
6750
- "x": _vm.task.x,
7629
+ "x": _vm.task.x - 8,
6751
7630
  "y": _vm.task.y,
6752
- "width": _vm.task.width,
7631
+ "width": _vm.task.width + 16,
6753
7632
  "height": _vm.task.height,
6754
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7633
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6755
7634
  "xmlns": "http://www.w3.org/2000/svg"
6756
7635
  },
6757
7636
  on: {
@@ -6803,29 +7682,86 @@ var Epicvue_type_template_id_a2e89cd8_render = function render() {
6803
7682
  ..._vm.root.style['chart-row-bar-polygon'],
6804
7683
  ..._vm.root.style['chart-row-epic-polygon'],
6805
7684
  ..._vm.task.style['base'],
6806
- ..._vm.task.style['chart-row-bar-polygon']
7685
+ ..._vm.task.style['chart-row-bar-polygon'],
7686
+ 'pointer-events': 'all',
7687
+ 'z-index': '10'
6807
7688
  },
6808
7689
  attrs: {
6809
- "d": _vm.getPoints
7690
+ "d": _vm.getPointsAdjusted
7691
+ },
7692
+ on: {
7693
+ "mousedown": function ($event) {
7694
+ return _vm.startDrag($event, 'move');
7695
+ },
7696
+ "touchstart": function ($event) {
7697
+ return _vm.startDrag($event, 'move');
7698
+ }
6810
7699
  }
6811
- }), _c('progress-bar', {
7700
+ }), _vm.task.progress > 0 ? _c('progress-bar', {
6812
7701
  attrs: {
6813
7702
  "task": _vm.task,
6814
7703
  "clip-path": 'url(#' + _vm.clipPathId + ')'
6815
7704
  }
7705
+ }) : _vm._e(), _c('rect', {
7706
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7707
+ staticStyle: {
7708
+ "pointer-events": "all",
7709
+ "z-index": "30"
7710
+ },
7711
+ style: _vm.root.style['chart-row-extend-handle'],
7712
+ attrs: {
7713
+ "x": "8",
7714
+ "y": "0",
7715
+ "width": 8,
7716
+ "height": _vm.task.height
7717
+ },
7718
+ on: {
7719
+ "mousedown": function ($event) {
7720
+ $event.stopPropagation();
7721
+ return _vm.startDrag($event, 'start');
7722
+ },
7723
+ "touchstart": function ($event) {
7724
+ $event.stopPropagation();
7725
+ return _vm.startDrag($event, 'start');
7726
+ }
7727
+ }
7728
+ }), _c('rect', {
7729
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7730
+ staticStyle: {
7731
+ "pointer-events": "all",
7732
+ "z-index": "30"
7733
+ },
7734
+ style: _vm.root.style['chart-row-extend-handle'],
7735
+ attrs: {
7736
+ "x": _vm.task.width - 8,
7737
+ "y": "0",
7738
+ "width": 8,
7739
+ "height": _vm.task.height
7740
+ },
7741
+ on: {
7742
+ "mousedown": function ($event) {
7743
+ $event.stopPropagation();
7744
+ return _vm.startDrag($event, 'end');
7745
+ },
7746
+ "touchstart": function ($event) {
7747
+ $event.stopPropagation();
7748
+ return _vm.startDrag($event, 'end');
7749
+ }
7750
+ }
6816
7751
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
6817
7752
  attrs: {
6818
7753
  "task": _vm.task
6819
7754
  }
6820
7755
  }) : _vm._e()], 1);
6821
7756
  };
6822
- var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
7757
+ var Epicvue_type_template_id_6e337196_staticRenderFns = [];
6823
7758
 
6824
7759
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Epic.vue?vue&type=script&lang=js
6825
7760
 
6826
7761
 
6827
7762
 
6828
7763
 
7764
+
6829
7765
  /* harmony default export */ var Epicvue_type_script_lang_js = ({
6830
7766
  name: 'Epic',
6831
7767
  components: {
@@ -6835,7 +7771,7 @@ var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
6835
7771
  },
6836
7772
  inject: ['root'],
6837
7773
  props: ['task'],
6838
- mixins: [Task_mixin],
7774
+ mixins: [Task_mixin, Draggable_mixin],
6839
7775
  data() {
6840
7776
  return {};
6841
7777
  },
@@ -6871,6 +7807,29 @@ var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
6871
7807
  Z
6872
7808
  `;
6873
7809
  },
7810
+ /**
7811
+ * Get points adjusted for viewBox
7812
+ *
7813
+ * @returns {string}
7814
+ */
7815
+ getPointsAdjusted() {
7816
+ const task = this.task;
7817
+ const bottom = task.height - task.height / 4;
7818
+ const corner = task.height / 6;
7819
+ const smallCorner = task.height / 8;
7820
+ return `M ${8 + smallCorner},0
7821
+ L ${8 + task.width - smallCorner} 0
7822
+ L ${8 + task.width} ${smallCorner}
7823
+ L ${8 + task.width} ${bottom}
7824
+ L ${8 + task.width - corner} ${task.height}
7825
+ L ${8 + task.width - corner * 2} ${bottom}
7826
+ L ${8 + corner * 2} ${bottom}
7827
+ L ${8 + corner} ${task.height}
7828
+ L ${8} ${bottom}
7829
+ L ${8} ${smallCorner}
7830
+ Z
7831
+ `;
7832
+ },
6874
7833
  /**
6875
7834
  * Should we display expander?
6876
7835
  *
@@ -6895,8 +7854,8 @@ var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
6895
7854
  ;
6896
7855
  var Epic_component = normalizeComponent(
6897
7856
  Row_Epicvue_type_script_lang_js,
6898
- Epicvue_type_template_id_a2e89cd8_render,
6899
- Epicvue_type_template_id_a2e89cd8_staticRenderFns,
7857
+ Epicvue_type_template_id_6e337196_render,
7858
+ Epicvue_type_template_id_6e337196_staticRenderFns,
6900
7859
  false,
6901
7860
  null,
6902
7861
  null,
@@ -6905,8 +7864,8 @@ var Epic_component = normalizeComponent(
6905
7864
  )
6906
7865
 
6907
7866
  /* harmony default export */ var Epic = (Epic_component.exports);
6908
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Subtask.vue?vue&type=template&id=86599310
6909
- var Subtaskvue_type_template_id_86599310_render = function render() {
7867
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Subtask.vue?vue&type=template&id=339b7174
7868
+ var Subtaskvue_type_template_id_339b7174_render = function render() {
6910
7869
  var _vm = this,
6911
7870
  _c = _vm._self._c;
6912
7871
  return _c('g', {
@@ -6943,11 +7902,11 @@ var Subtaskvue_type_template_id_86599310_render = function render() {
6943
7902
  ..._vm.task.style['chart-row-bar']
6944
7903
  },
6945
7904
  attrs: {
6946
- "x": _vm.task.x,
7905
+ "x": _vm.task.x - 8,
6947
7906
  "y": _vm.task.y,
6948
- "width": _vm.task.width,
7907
+ "width": _vm.task.width + 16,
6949
7908
  "height": _vm.task.height,
6950
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7909
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6951
7910
  "xmlns": "http://www.w3.org/2000/svg"
6952
7911
  },
6953
7912
  on: {
@@ -7002,26 +7961,81 @@ var Subtaskvue_type_template_id_86599310_render = function render() {
7002
7961
  ..._vm.task.style['chart-row-bar-polygon']
7003
7962
  },
7004
7963
  attrs: {
7005
- "points": _vm.getPoints
7964
+ "points": _vm.getPointsAdjusted
7965
+ },
7966
+ on: {
7967
+ "mousedown": function ($event) {
7968
+ return _vm.startDrag($event, 'move');
7969
+ },
7970
+ "touchstart": function ($event) {
7971
+ return _vm.startDrag($event, 'move');
7972
+ }
7006
7973
  }
7007
7974
  }), _c('progress-bar', {
7008
7975
  attrs: {
7009
7976
  "task": _vm.task,
7010
7977
  "clip-path": 'url(#' + _vm.clipPathId + ')'
7011
7978
  }
7979
+ }), _c('rect', {
7980
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7981
+ staticStyle: {
7982
+ "pointer-events": "all",
7983
+ "z-index": "20"
7984
+ },
7985
+ style: _vm.root.style['chart-row-extend-handle'],
7986
+ attrs: {
7987
+ "x": "8",
7988
+ "y": "0",
7989
+ "width": 8,
7990
+ "height": _vm.task.height
7991
+ },
7992
+ on: {
7993
+ "mousedown": function ($event) {
7994
+ $event.stopPropagation();
7995
+ return _vm.startDrag($event, 'start');
7996
+ },
7997
+ "touchstart": function ($event) {
7998
+ $event.stopPropagation();
7999
+ return _vm.startDrag($event, 'start');
8000
+ }
8001
+ }
8002
+ }), _c('rect', {
8003
+ staticClass: "gantt-elastic__chart-row-extend-handle",
8004
+ staticStyle: {
8005
+ "pointer-events": "all",
8006
+ "z-index": "20"
8007
+ },
8008
+ style: _vm.root.style['chart-row-extend-handle'],
8009
+ attrs: {
8010
+ "x": _vm.task.width - 8,
8011
+ "y": "0",
8012
+ "width": 8,
8013
+ "height": _vm.task.height
8014
+ },
8015
+ on: {
8016
+ "mousedown": function ($event) {
8017
+ $event.stopPropagation();
8018
+ return _vm.startDrag($event, 'end');
8019
+ },
8020
+ "touchstart": function ($event) {
8021
+ $event.stopPropagation();
8022
+ return _vm.startDrag($event, 'end');
8023
+ }
8024
+ }
7012
8025
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
7013
8026
  attrs: {
7014
8027
  "task": _vm.task
7015
8028
  }
7016
8029
  }) : _vm._e()], 1);
7017
8030
  };
7018
- var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
8031
+ var Subtaskvue_type_template_id_339b7174_staticRenderFns = [];
7019
8032
 
7020
8033
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Subtask.vue?vue&type=script&lang=js
7021
8034
 
7022
8035
 
7023
8036
 
7024
8037
 
8038
+
7025
8039
  /* harmony default export */ var Subtaskvue_type_script_lang_js = ({
7026
8040
  name: 'Subtask',
7027
8041
  components: {
@@ -7031,7 +8045,7 @@ var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
7031
8045
  },
7032
8046
  inject: ['root'],
7033
8047
  props: ['task'],
7034
- mixins: [Task_mixin],
8048
+ mixins: [Task_mixin, Draggable_mixin],
7035
8049
  data() {
7036
8050
  return {};
7037
8051
  },
@@ -7053,6 +8067,15 @@ var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
7053
8067
  const task = this.task;
7054
8068
  return `0,0 ${task.width},0 ${task.width},${task.height} 0,${task.height}`;
7055
8069
  },
8070
+ /**
8071
+ * Get points adjusted for viewBox
8072
+ *
8073
+ * @returns {string}
8074
+ */
8075
+ getPointsAdjusted() {
8076
+ const task = this.task;
8077
+ return `8,0 ${task.width + 8},0 ${task.width + 8},${task.height} 8,${task.height}`;
8078
+ },
7056
8079
  /**
7057
8080
  * Should we display expander?
7058
8081
  *
@@ -7077,8 +8100,8 @@ var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
7077
8100
  ;
7078
8101
  var Subtask_component = normalizeComponent(
7079
8102
  Row_Subtaskvue_type_script_lang_js,
7080
- Subtaskvue_type_template_id_86599310_render,
7081
- Subtaskvue_type_template_id_86599310_staticRenderFns,
8103
+ Subtaskvue_type_template_id_339b7174_render,
8104
+ Subtaskvue_type_template_id_339b7174_staticRenderFns,
7082
8105
  false,
7083
8106
  null,
7084
8107
  null,
@@ -7087,8 +8110,8 @@ var Subtask_component = normalizeComponent(
7087
8110
  )
7088
8111
 
7089
8112
  /* harmony default export */ var Subtask = (Subtask_component.exports);
7090
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Story.vue?vue&type=template&id=1f59b61a
7091
- var Storyvue_type_template_id_1f59b61a_render = function render() {
8113
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Story.vue?vue&type=template&id=3d0395f2
8114
+ var Storyvue_type_template_id_3d0395f2_render = function render() {
7092
8115
  var _vm = this,
7093
8116
  _c = _vm._self._c;
7094
8117
  return _c('g', {
@@ -7125,11 +8148,11 @@ var Storyvue_type_template_id_1f59b61a_render = function render() {
7125
8148
  ..._vm.task.style['chart-row-bar']
7126
8149
  },
7127
8150
  attrs: {
7128
- "x": _vm.task.x,
8151
+ "x": _vm.task.x - 8,
7129
8152
  "y": _vm.task.y,
7130
- "width": _vm.task.width,
8153
+ "width": _vm.task.width + 16,
7131
8154
  "height": _vm.task.height,
7132
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
8155
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
7133
8156
  "xmlns": "http://www.w3.org/2000/svg"
7134
8157
  },
7135
8158
  on: {
@@ -7184,26 +8207,81 @@ var Storyvue_type_template_id_1f59b61a_render = function render() {
7184
8207
  ..._vm.task.style['chart-row-bar-polygon']
7185
8208
  },
7186
8209
  attrs: {
7187
- "d": _vm.getPoints
8210
+ "d": _vm.getPointsAdjusted
8211
+ },
8212
+ on: {
8213
+ "mousedown": function ($event) {
8214
+ return _vm.startDrag($event, 'move');
8215
+ },
8216
+ "touchstart": function ($event) {
8217
+ return _vm.startDrag($event, 'move');
8218
+ }
7188
8219
  }
7189
8220
  }), _c('progress-bar', {
7190
8221
  attrs: {
7191
8222
  "task": _vm.task,
7192
8223
  "clip-path": 'url(#' + _vm.clipPathId + ')'
7193
8224
  }
8225
+ }), _c('rect', {
8226
+ staticClass: "gantt-elastic__chart-row-extend-handle",
8227
+ staticStyle: {
8228
+ "pointer-events": "all",
8229
+ "z-index": "20"
8230
+ },
8231
+ style: _vm.root.style['chart-row-extend-handle'],
8232
+ attrs: {
8233
+ "x": "8",
8234
+ "y": "0",
8235
+ "width": 8,
8236
+ "height": _vm.task.height
8237
+ },
8238
+ on: {
8239
+ "mousedown": function ($event) {
8240
+ $event.stopPropagation();
8241
+ return _vm.startDrag($event, 'start');
8242
+ },
8243
+ "touchstart": function ($event) {
8244
+ $event.stopPropagation();
8245
+ return _vm.startDrag($event, 'start');
8246
+ }
8247
+ }
8248
+ }), _c('rect', {
8249
+ staticClass: "gantt-elastic__chart-row-extend-handle",
8250
+ staticStyle: {
8251
+ "pointer-events": "all",
8252
+ "z-index": "20"
8253
+ },
8254
+ style: _vm.root.style['chart-row-extend-handle'],
8255
+ attrs: {
8256
+ "x": _vm.task.width - 8,
8257
+ "y": "0",
8258
+ "width": 8,
8259
+ "height": _vm.task.height
8260
+ },
8261
+ on: {
8262
+ "mousedown": function ($event) {
8263
+ $event.stopPropagation();
8264
+ return _vm.startDrag($event, 'end');
8265
+ },
8266
+ "touchstart": function ($event) {
8267
+ $event.stopPropagation();
8268
+ return _vm.startDrag($event, 'end');
8269
+ }
8270
+ }
7194
8271
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
7195
8272
  attrs: {
7196
8273
  "task": _vm.task
7197
8274
  }
7198
8275
  }) : _vm._e()], 1);
7199
8276
  };
7200
- var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
8277
+ var Storyvue_type_template_id_3d0395f2_staticRenderFns = [];
7201
8278
 
7202
8279
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Row/Story.vue?vue&type=script&lang=js
7203
8280
 
7204
8281
 
7205
8282
 
7206
8283
 
8284
+
7207
8285
  /* harmony default export */ var Storyvue_type_script_lang_js = ({
7208
8286
  name: 'Story',
7209
8287
  components: {
@@ -7213,7 +8291,7 @@ var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
7213
8291
  },
7214
8292
  inject: ['root'],
7215
8293
  props: ['task'],
7216
- mixins: [Task_mixin],
8294
+ mixins: [Task_mixin, Draggable_mixin],
7217
8295
  data() {
7218
8296
  return {};
7219
8297
  },
@@ -7245,6 +8323,25 @@ var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
7245
8323
  Q 0 0 ${corner} 0
7246
8324
  Z`;
7247
8325
  },
8326
+ /**
8327
+ * Get points adjusted for viewBox
8328
+ *
8329
+ * @returns {string}
8330
+ */
8331
+ getPointsAdjusted() {
8332
+ const task = this.task;
8333
+ const corner = Math.min(task.height / 4, 8); // Rounded corners
8334
+ return `M ${8 + corner},0
8335
+ L ${8 + task.width - corner} 0
8336
+ Q ${8 + task.width} 0 ${8 + task.width} ${corner}
8337
+ L ${8 + task.width} ${task.height - corner}
8338
+ Q ${8 + task.width} ${task.height} ${8 + task.width - corner} ${task.height}
8339
+ L ${8 + corner} ${task.height}
8340
+ Q ${8} ${task.height} ${8} ${task.height - corner}
8341
+ L ${8} ${corner}
8342
+ Q ${8} 0 ${8 + corner} 0
8343
+ Z`;
8344
+ },
7248
8345
  /**
7249
8346
  * Should we display expander?
7250
8347
  *
@@ -7269,8 +8366,8 @@ var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
7269
8366
  ;
7270
8367
  var Story_component = normalizeComponent(
7271
8368
  Row_Storyvue_type_script_lang_js,
7272
- Storyvue_type_template_id_1f59b61a_render,
7273
- Storyvue_type_template_id_1f59b61a_staticRenderFns,
8369
+ Storyvue_type_template_id_3d0395f2_render,
8370
+ Storyvue_type_template_id_3d0395f2_staticRenderFns,
7274
8371
  false,
7275
8372
  null,
7276
8373
  null,
@@ -7320,6 +8417,42 @@ var Story_component = normalizeComponent(
7320
8417
  this.root.state.refs.chartGraph = this.$refs.chartGraph;
7321
8418
  this.root.state.refs.chartGraphSvg = this.$refs.chartGraphSvg;
7322
8419
  },
8420
+ methods: {
8421
+ /**
8422
+ * Handle task updated event
8423
+ *
8424
+ * @param {Object} updatedTask - Updated task data
8425
+ */
8426
+ handleTaskUpdated(updatedTask) {
8427
+ // Emit event to parent component
8428
+ this.$emit('task-updated', updatedTask);
8429
+
8430
+ // Update the task in the root state
8431
+ const taskIndex = this.root.state.tasks.findIndex(task => task.id === updatedTask.id);
8432
+ if (taskIndex !== -1) {
8433
+ // Update task data
8434
+ this.root.state.tasks[taskIndex].startTime = updatedTask.startTime;
8435
+ this.root.state.tasks[taskIndex].endTime = updatedTask.endTime;
8436
+ this.root.state.tasks[taskIndex].duration = updatedTask.duration;
8437
+
8438
+ // Update task position and width
8439
+ if (this.root && this.root.timeToPixelOffsetX) {
8440
+ this.root.state.tasks[taskIndex].x = this.root.timeToPixelOffsetX(updatedTask.startTime);
8441
+ this.root.state.tasks[taskIndex].width = this.root.timeToPixelOffsetX(updatedTask.endTime) - this.root.state.tasks[taskIndex].x;
8442
+ } else {
8443
+ // Fallback calculation if method is not available
8444
+ const timePerPixel = this.root.state.options.times.timePerPixel;
8445
+ if (timePerPixel > 0) {
8446
+ this.root.state.tasks[taskIndex].x = (updatedTask.startTime - this.root.state.options.times.firstTime) / timePerPixel;
8447
+ this.root.state.tasks[taskIndex].width = (updatedTask.endTime - updatedTask.startTime) / timePerPixel;
8448
+ }
8449
+ }
8450
+
8451
+ // Force update
8452
+ this.$forceUpdate();
8453
+ }
8454
+ }
8455
+ },
7323
8456
  computed: {
7324
8457
  /**
7325
8458
  * Get view box
@@ -7343,8 +8476,8 @@ var Story_component = normalizeComponent(
7343
8476
  ;
7344
8477
  var Chart_component = normalizeComponent(
7345
8478
  Chart_Chartvue_type_script_lang_js,
7346
- Chartvue_type_template_id_1d5eb6d6_render,
7347
- Chartvue_type_template_id_1d5eb6d6_staticRenderFns,
8479
+ Chartvue_type_template_id_2bc7fe5e_render,
8480
+ Chartvue_type_template_id_2bc7fe5e_staticRenderFns,
7348
8481
  false,
7349
8482
  null,
7350
8483
  null,
@@ -7433,6 +8566,15 @@ let ignoreScrollEvents = false;
7433
8566
  }
7434
8567
  },
7435
8568
  methods: {
8569
+ /**
8570
+ * Handle task updated event from chart
8571
+ *
8572
+ * @param {Object} updatedTask - Updated task data
8573
+ */
8574
+ handleTaskUpdated(updatedTask) {
8575
+ // Emit event to parent component
8576
+ this.$emit('task-updated', updatedTask);
8577
+ },
7436
8578
  /**
7437
8579
  * Emit event when mouse is moving inside main view
7438
8580
  */
@@ -7549,8 +8691,8 @@ let ignoreScrollEvents = false;
7549
8691
  ;
7550
8692
  var MainView_component = normalizeComponent(
7551
8693
  components_MainViewvue_type_script_lang_js,
7552
- MainViewvue_type_template_id_1a4b756c_render,
7553
- MainViewvue_type_template_id_1a4b756c_staticRenderFns,
8694
+ MainViewvue_type_template_id_33392d22_render,
8695
+ MainViewvue_type_template_id_33392d22_staticRenderFns,
7554
8696
  false,
7555
8697
  null,
7556
8698
  null,
@@ -7873,6 +9015,192 @@ function getStyle(fontSize = '12px', fontFamily = 'Arial, sans-serif') {
7873
9015
  'text-overflow': 'ellipsis',
7874
9016
  'max-width': '120px'
7875
9017
  },
9018
+ 'chart-row-resize-handle': {
9019
+ fill: 'rgba(59, 130, 246, 0.2)',
9020
+ stroke: 'rgba(59, 130, 246, 0.8)',
9021
+ 'stroke-width': '2',
9022
+ cursor: 'ew-resize',
9023
+ opacity: '0.3',
9024
+ transition: 'opacity 0.2s ease',
9025
+ 'pointer-events': 'all'
9026
+ },
9027
+ 'chart-row-resize-handle--start': {
9028
+ cursor: 'w-resize',
9029
+ fill: 'rgba(34, 197, 94, 0.3)',
9030
+ stroke: 'rgba(34, 197, 94, 0.9)',
9031
+ 'stroke-width': '2'
9032
+ },
9033
+ 'chart-row-resize-handle--end': {
9034
+ cursor: 'e-resize',
9035
+ fill: 'rgba(239, 68, 68, 0.4)',
9036
+ stroke: 'rgba(239, 68, 68, 1)',
9037
+ 'stroke-width': '2'
9038
+ },
9039
+ 'chart-row-bar-wrapper:hover .chart-row-resize-handle': {
9040
+ opacity: '0.8'
9041
+ },
9042
+ 'chart-row-resize-handle:hover': {
9043
+ opacity: '1',
9044
+ fill: 'rgba(59, 130, 246, 0.4)',
9045
+ stroke: 'rgba(59, 130, 246, 1)'
9046
+ },
9047
+ 'chart-row-resize-handle--start:hover': {
9048
+ fill: 'rgba(34, 197, 94, 0.4)',
9049
+ stroke: 'rgba(34, 197, 94, 1)'
9050
+ },
9051
+ 'chart-row-resize-handle--end:hover': {
9052
+ fill: 'rgba(239, 68, 68, 0.5)',
9053
+ stroke: 'rgba(239, 68, 68, 1)',
9054
+ 'stroke-width': '3'
9055
+ },
9056
+ 'chart-row-resize-handle--corner': {
9057
+ fill: 'rgba(147, 51, 234, 0.6)',
9058
+ stroke: 'rgba(147, 51, 234, 1)',
9059
+ 'stroke-width': '2',
9060
+ cursor: 'nw-resize',
9061
+ opacity: '0.9',
9062
+ transition: 'opacity 0.2s ease',
9063
+ 'pointer-events': 'all'
9064
+ },
9065
+ 'chart-row-resize-handle--corner:hover': {
9066
+ fill: 'rgba(147, 51, 234, 0.8)',
9067
+ stroke: 'rgba(147, 51, 234, 1)',
9068
+ 'stroke-width': '3',
9069
+ opacity: '1'
9070
+ },
9071
+ 'chart-row-resize-handle--corner--start': {
9072
+ fill: 'rgba(34, 197, 94, 0.7)',
9073
+ stroke: 'rgba(34, 197, 94, 1)',
9074
+ 'stroke-width': '2',
9075
+ cursor: 'w-resize'
9076
+ },
9077
+ 'chart-row-resize-handle--corner--end': {
9078
+ fill: 'rgba(239, 68, 68, 0.7)',
9079
+ stroke: 'rgba(239, 68, 68, 1)',
9080
+ 'stroke-width': '2',
9081
+ cursor: 'e-resize'
9082
+ },
9083
+ 'chart-row-corner-handle--start': {
9084
+ fill: 'rgba(34, 197, 94, 0.8)',
9085
+ stroke: 'rgba(34, 197, 94, 1)',
9086
+ 'stroke-width': '2',
9087
+ cursor: 'w-resize',
9088
+ opacity: '0.9',
9089
+ transition: 'opacity 0.2s ease',
9090
+ 'pointer-events': 'all'
9091
+ },
9092
+ 'chart-row-corner-handle--end': {
9093
+ fill: 'rgba(239, 68, 68, 0.8)',
9094
+ stroke: 'rgba(239, 68, 68, 1)',
9095
+ 'stroke-width': '2',
9096
+ cursor: 'e-resize',
9097
+ opacity: '0.9',
9098
+ transition: 'opacity 0.2s ease',
9099
+ 'pointer-events': 'all'
9100
+ },
9101
+ 'chart-row-corner-handle--start:hover': {
9102
+ fill: 'rgba(34, 197, 94, 0.5)',
9103
+ stroke: 'rgba(34, 197, 94, 1)',
9104
+ 'stroke-width': '2',
9105
+ opacity: '0.9'
9106
+ },
9107
+ 'chart-row-corner-handle--end:hover': {
9108
+ fill: 'rgba(239, 68, 68, 0.5)',
9109
+ stroke: 'rgba(239, 68, 68, 1)',
9110
+ 'stroke-width': '2',
9111
+ opacity: '0.9'
9112
+ },
9113
+ 'chart-row-extend-handle': {
9114
+ fill: 'rgba(255, 255, 255, 0.1)',
9115
+ stroke: 'rgba(255, 255, 255, 0.3)',
9116
+ 'stroke-width': '1',
9117
+ cursor: 'ew-resize',
9118
+ opacity: '0.3',
9119
+ transition: 'opacity 0.2s ease',
9120
+ 'pointer-events': 'all',
9121
+ 'z-index': '10'
9122
+ },
9123
+ 'chart-row-extend-handle:hover': {
9124
+ fill: 'rgba(255, 255, 255, 0.2)',
9125
+ stroke: 'rgba(255, 255, 255, 0.6)',
9126
+ 'stroke-width': '2',
9127
+ opacity: '0.8'
9128
+ },
9129
+ 'chart-row-expand-icon-bg': {
9130
+ fill: 'rgba(255, 255, 255, 0.95)',
9131
+ stroke: 'rgba(0, 0, 0, 0.5)',
9132
+ 'stroke-width': '1.5',
9133
+ cursor: 'ew-resize',
9134
+ opacity: '1',
9135
+ transition: 'opacity 0.2s ease',
9136
+ 'pointer-events': 'all'
9137
+ },
9138
+ 'chart-row-expand-icon-arrow': {
9139
+ fill: 'rgba(0, 0, 0, 0.9)',
9140
+ cursor: 'ew-resize',
9141
+ 'pointer-events': 'all'
9142
+ },
9143
+ 'chart-row-expand-icon:hover .gantt-elastic__chart-row-expand-icon-bg': {
9144
+ fill: 'rgba(255, 255, 255, 1)',
9145
+ stroke: 'rgba(0, 0, 0, 0.5)',
9146
+ 'stroke-width': '1.5',
9147
+ opacity: '1'
9148
+ },
9149
+ 'chart-row-expand-icon:hover .gantt-elastic__chart-row-expand-icon-arrow': {
9150
+ fill: 'rgba(0, 0, 0, 1)'
9151
+ },
9152
+ 'gantt-elastic__task-dragging': {
9153
+ opacity: '0.8',
9154
+ 'pointer-events': 'none',
9155
+ 'filter': 'drop-shadow(0 4px 8px rgba(0, 0, 0, 0.2))'
9156
+ },
9157
+ 'gantt-elastic__task-dragging--start': {
9158
+ 'border-left': '3px solid #22c55e',
9159
+ 'box-shadow': 'inset 3px 0 0 #22c55e'
9160
+ },
9161
+ 'gantt-elastic__task-dragging--end': {
9162
+ 'border-right': '3px solid #ef4444',
9163
+ 'box-shadow': 'inset -3px 0 0 #ef4444'
9164
+ },
9165
+ 'gantt-elastic__task-dragging--move': {
9166
+ 'border': '2px solid #3b82f6',
9167
+ 'box-shadow': '0 0 0 2px rgba(59, 130, 246, 0.3)'
9168
+ },
9169
+ 'gantt-elastic__context-menu': {
9170
+ 'position': 'fixed',
9171
+ 'background': 'white',
9172
+ 'border': '1px solid #e5e7eb',
9173
+ 'border-radius': '6px',
9174
+ 'box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
9175
+ 'z-index': '1000',
9176
+ 'min-width': '150px',
9177
+ 'padding': '4px 0',
9178
+ 'font-family': 'system-ui, -apple-system, sans-serif'
9179
+ },
9180
+ 'gantt-elastic__context-menu-item': {
9181
+ 'padding': '8px 16px',
9182
+ 'cursor': 'pointer',
9183
+ 'font-size': '14px',
9184
+ 'color': '#374151',
9185
+ 'transition': 'background-color 0.2s',
9186
+ 'user-select': 'none'
9187
+ },
9188
+ 'gantt-elastic__context-menu-item:hover': {
9189
+ 'background-color': '#f3f4f6'
9190
+ },
9191
+ 'gantt-elastic__date-tooltip': {
9192
+ 'position': 'fixed',
9193
+ 'background': 'rgba(0, 0, 0, 0.8)',
9194
+ 'color': 'white',
9195
+ 'padding': '4px 8px',
9196
+ 'border-radius': '4px',
9197
+ 'font-size': '12px',
9198
+ 'font-family': 'system-ui, -apple-system, sans-serif',
9199
+ 'pointer-events': 'none',
9200
+ 'z-index': '10000',
9201
+ 'white-space': 'nowrap',
9202
+ 'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.2)'
9203
+ },
7876
9204
  'chart-row-text-content--text': {},
7877
9205
  'chart-row-text-content--html': {},
7878
9206
  'chart-row-wrapper': {},
@@ -10064,6 +11392,23 @@ const GanttElastic = {
10064
11392
  }
10065
11393
  });
10066
11394
  },
11395
+ /**
11396
+ * Handle task updated event from dragging
11397
+ *
11398
+ * @param {Object} updatedTask - Updated task data
11399
+ */
11400
+ handleTaskUpdated(updatedTask) {
11401
+ // Emit event to parent component
11402
+ this.$emit('task-updated', updatedTask);
11403
+
11404
+ // Log the update for debugging
11405
+ console.log('Task updated:', updatedTask);
11406
+
11407
+ // You can add additional logic here like:
11408
+ // - Save to backend
11409
+ // - Update local storage
11410
+ // - Trigger other updates
11411
+ },
10067
11412
  /**
10068
11413
  * Calculate height of scrollbar in current browser
10069
11414
  *
@@ -10416,7 +11761,18 @@ const GanttElastic = {
10416
11761
  * @returns {number}
10417
11762
  */
10418
11763
  getHeight(visibleTasks, outer = false) {
10419
- let height = visibleTasks.length * (this.state.options.row.height + this.state.options.chart.grid.horizontal.gap * 2) + this.state.options.calendar.height + this.state.options.calendar.strokeWidth + this.state.options.calendar.gap;
11764
+ let height;
11765
+
11766
+ // If we have tasks, use their actual height for full grid
11767
+ if (visibleTasks.length > 0) {
11768
+ height = visibleTasks.length * (this.state.options.row.height + this.state.options.chart.grid.horizontal.gap * 2) + this.state.options.calendar.height + this.state.options.calendar.strokeWidth + this.state.options.calendar.gap;
11769
+ } else {
11770
+ // If no tasks, use 70% of viewport height for empty state
11771
+ const viewportHeight = window.innerHeight;
11772
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
11773
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
11774
+ height = Math.max(availableHeight, 300); // Minimum 300px height
11775
+ }
10420
11776
  if (outer) {
10421
11777
  height += this.state.options.scrollBarHeight;
10422
11778
  }
@@ -10439,7 +11795,20 @@ const GanttElastic = {
10439
11795
  * @returns {number}
10440
11796
  */
10441
11797
  getTasksHeight(visibleTasks) {
10442
- return visibleTasks.length * this.getTaskHeight();
11798
+ const taskHeight = visibleTasks.length * this.getTaskHeight();
11799
+
11800
+ // If we have tasks, use their actual height for full grid
11801
+ if (visibleTasks.length > 0) {
11802
+ return taskHeight;
11803
+ }
11804
+
11805
+ // If no tasks, use 70% of viewport height for empty state
11806
+ const viewportHeight = window.innerHeight;
11807
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
11808
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
11809
+ const reducedHeight = Math.max(availableHeight, 300); // Minimum 300px height
11810
+
11811
+ return reducedHeight;
10443
11812
  },
10444
11813
  /**
10445
11814
  * Convert time (in milliseconds) to pixel offset inside chart
@@ -10746,15 +12115,15 @@ const GanttElastic = {
10746
12115
  getMaxWidthMultiplier(stepDuration, stepCount) {
10747
12116
  const clientWidth = this.state.options.clientWidth;
10748
12117
 
10749
- // Base multipliers for different screen sizes
12118
+ // Base multipliers for different screen sizes (reduced for better balance)
10750
12119
  const baseMultipliers = {
10751
- mobile: 2,
10752
- // 2x viewport width on mobile
10753
- tablet: 2.5,
10754
- // 2.5x viewport width on tablet
10755
- desktopSmall: 3,
10756
- // 3x viewport width on small desktop
10757
- desktopBig: 4 // 4x viewport width on big desktop
12120
+ mobile: 1.5,
12121
+ // 1.5x viewport width on mobile
12122
+ tablet: 1.8,
12123
+ // 1.8x viewport width on tablet
12124
+ desktopSmall: 2.2,
12125
+ // 2.2x viewport width on small desktop
12126
+ desktopBig: 2.5 // 2.5x viewport width on big desktop
10758
12127
  };
10759
12128
 
10760
12129
  // Determine screen size
@@ -10781,7 +12150,7 @@ const GanttElastic = {
10781
12150
  // If we have more data than minimum visibility, allow more width
10782
12151
  if (stepCount > minVisibilitySteps[stepDuration]) {
10783
12152
  const dataRatio = stepCount / minVisibilitySteps[stepDuration];
10784
- multiplier = Math.min(multiplier * (1 + dataRatio * 0.5), 6); // Max 6x viewport width
12153
+ multiplier = Math.min(multiplier * (1 + dataRatio * 0.3), 3); // Max 3x viewport width
10785
12154
  }
10786
12155
  return multiplier;
10787
12156
  },
@@ -10882,7 +12251,7 @@ const GanttElastic = {
10882
12251
  const maxWidth = this.state.options.clientWidth * maxWidthMultiplier;
10883
12252
 
10884
12253
  // Ensure minimum width for scrolling when we have minimum visibility requirements
10885
- const minWidthForScrolling = this.state.options.clientWidth * 1.2; // 20% more than viewport
12254
+ const minWidthForScrolling = this.state.options.clientWidth * 1.1; // 10% more than viewport
10886
12255
  const finalWidth = Math.max(calculatedWidth, minWidthForScrolling);
10887
12256
  if (finalWidth > maxWidth) {
10888
12257
  // Only limit width if it's truly excessive
@@ -11172,6 +12541,29 @@ const GanttElastic = {
11172
12541
  width: 0
11173
12542
  }).width;
11174
12543
  },
12544
+ /**
12545
+ * Recalculate height based on current tasks and viewport
12546
+ */
12547
+ recalculateHeight() {
12548
+ const visibleTasks = this.state.tasks.filter(task => this.isTaskVisible(task));
12549
+ if (visibleTasks.length > 0) {
12550
+ // Use full task height for complete grid
12551
+ this.state.options.rowsHeight = this.getTasksHeight(visibleTasks);
12552
+ this.state.options.height = this.getHeight(visibleTasks);
12553
+ this.state.options.allVisibleTasksHeight = this.getTasksHeight(visibleTasks);
12554
+ this.state.options.outerHeight = this.getHeight(visibleTasks, true);
12555
+ } else {
12556
+ // Use reduced viewport height for empty state
12557
+ const viewportHeight = window.innerHeight;
12558
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
12559
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40;
12560
+ const reducedHeight = Math.max(availableHeight, 300);
12561
+ this.state.options.rowsHeight = reducedHeight;
12562
+ this.state.options.height = reducedHeight + this.state.options.calendar.height + this.state.options.calendar.gap;
12563
+ this.state.options.allVisibleTasksHeight = reducedHeight;
12564
+ this.state.options.outerHeight = this.state.options.height + this.state.options.scrollBarHeight;
12565
+ }
12566
+ },
11175
12567
  /**
11176
12568
  * Global resize event (from window.addEventListener)
11177
12569
  */
@@ -11180,6 +12572,15 @@ const GanttElastic = {
11180
12572
  return;
11181
12573
  }
11182
12574
  this.state.options.clientWidth = this.$el.clientWidth;
12575
+
12576
+ // Only set height if no tasks are present (let visibleTasks computed property handle height when tasks exist)
12577
+ if (this.state.tasks.length === 0) {
12578
+ // Set height to 70% of viewport height for better balance when no tasks
12579
+ const viewportHeight = window.innerHeight;
12580
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
12581
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
12582
+ this.state.options.height = Math.max(availableHeight, 300); // Minimum 300px height
12583
+ }
11183
12584
  if (this.state.options.taskList.widthFromPercentage > this.state.options.clientWidth / 100 * this.state.options.taskList.widthThreshold) {
11184
12585
  const diff = this.state.options.taskList.widthFromPercentage - this.state.options.clientWidth / 100 * this.state.options.taskList.widthThreshold;
11185
12586
  let diffPercent = 100 - diff / this.state.options.taskList.widthFromPercentage * 100;
@@ -11202,6 +12603,9 @@ const GanttElastic = {
11202
12603
  this.computeCalendarWidths();
11203
12604
  this.$emit('calendar-recalculate');
11204
12605
  this.syncScrollTop();
12606
+
12607
+ // Recalculate height after resize
12608
+ this.recalculateHeight();
11205
12609
  }
11206
12610
  },
11207
12611
  computed: {
@@ -11212,16 +12616,17 @@ const GanttElastic = {
11212
12616
  */
11213
12617
  visibleTasks() {
11214
12618
  const visibleTasks = this.state.tasks.filter(task => this.isTaskVisible(task));
11215
- const maxRows = visibleTasks.slice(0, this.state.options.maxRows);
11216
- this.state.options.rowsHeight = this.getTasksHeight(maxRows);
12619
+
12620
+ // Use full visible tasks for height calculations to show complete grid
12621
+ this.state.options.rowsHeight = this.getTasksHeight(visibleTasks);
11217
12622
  let heightCompensation = 0;
11218
12623
  if (this.state.options.maxHeight && this.state.options.rowsHeight > this.state.options.maxHeight) {
11219
12624
  heightCompensation = this.state.options.rowsHeight - this.state.options.maxHeight;
11220
12625
  this.state.options.rowsHeight = this.state.options.maxHeight;
11221
12626
  }
11222
- this.state.options.height = this.getHeight(maxRows) - heightCompensation;
12627
+ this.state.options.height = this.getHeight(visibleTasks) - heightCompensation;
11223
12628
  this.state.options.allVisibleTasksHeight = this.getTasksHeight(visibleTasks);
11224
- this.state.options.outerHeight = this.getHeight(maxRows, true) - heightCompensation;
12629
+ this.state.options.outerHeight = this.getHeight(visibleTasks, true) - heightCompensation;
11225
12630
  let len = visibleTasks.length;
11226
12631
  for (let index = 0; index < len; index++) {
11227
12632
  let task = visibleTasks[index];
@@ -11272,6 +12677,10 @@ const GanttElastic = {
11272
12677
  if (notEqual) {
11273
12678
  this.setup('tasks');
11274
12679
  }
12680
+ // Recalculate height when tasks change
12681
+ this.$nextTick(() => {
12682
+ this.recalculateHeight();
12683
+ });
11275
12684
  }, {
11276
12685
  deep: true
11277
12686
  });
@@ -11321,11 +12730,23 @@ const GanttElastic = {
11321
12730
  */
11322
12731
  mounted() {
11323
12732
  this.state.options.clientWidth = this.$el.clientWidth;
12733
+
12734
+ // Set initial height based on whether tasks exist
12735
+ if (this.state.tasks.length === 0) {
12736
+ const viewportHeight = window.innerHeight;
12737
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
12738
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40;
12739
+ this.state.options.height = Math.max(availableHeight, 300);
12740
+ }
11324
12741
  this.state.resizeObserver = new ResizeObserver_es((entries, observer) => {
11325
12742
  this.globalOnResize();
11326
12743
  });
11327
12744
  this.state.resizeObserver.observe(this.$el.parentNode);
12745
+
12746
+ // Add window resize listener for full viewport responsiveness
12747
+ window.addEventListener('resize', this.globalOnResize);
11328
12748
  this.globalOnResize();
12749
+ this.recalculateHeight();
11329
12750
  this.$emit('ready', this);
11330
12751
  this.$root.$emit('gantt-elastic-mounted', this);
11331
12752
  this.$emit('mounted', this);
@@ -11350,6 +12771,7 @@ const GanttElastic = {
11350
12771
  */
11351
12772
  beforeDestroy() {
11352
12773
  this.state.resizeObserver.unobserve(this.$el.parentNode);
12774
+ window.removeEventListener('resize', this.globalOnResize);
11353
12775
  this.state.unwatchTasks();
11354
12776
  this.state.unwatchOptions();
11355
12777
  this.state.unwatchStyle();
@@ -11368,10 +12790,10 @@ const GanttElastic = {
11368
12790
  /* harmony default export */ var GanttElasticvue_type_script_lang_js = (GanttElastic);
11369
12791
  ;// ./src/GanttElastic.vue?vue&type=script&lang=js
11370
12792
  /* harmony default export */ var src_GanttElasticvue_type_script_lang_js = (GanttElasticvue_type_script_lang_js);
11371
- ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=style&index=0&id=2767341e&prod&lang=css
12793
+ ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=style&index=0&id=100984c8&prod&lang=css
11372
12794
  // extracted by mini-css-extract-plugin
11373
12795
 
11374
- ;// ./src/GanttElastic.vue?vue&type=style&index=0&id=2767341e&prod&lang=css
12796
+ ;// ./src/GanttElastic.vue?vue&type=style&index=0&id=100984c8&prod&lang=css
11375
12797
 
11376
12798
  ;// ./src/GanttElastic.vue
11377
12799
 
@@ -11384,8 +12806,8 @@ const GanttElastic = {
11384
12806
 
11385
12807
  var GanttElastic_component = normalizeComponent(
11386
12808
  src_GanttElasticvue_type_script_lang_js,
11387
- GanttElasticvue_type_template_id_2767341e_render,
11388
- GanttElasticvue_type_template_id_2767341e_staticRenderFns,
12809
+ GanttElasticvue_type_template_id_100984c8_render,
12810
+ GanttElasticvue_type_template_id_100984c8_staticRenderFns,
11389
12811
  false,
11390
12812
  null,
11391
12813
  null,