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.
@@ -3411,8 +3411,8 @@ var render = function render() {
3411
3411
  };
3412
3412
  var staticRenderFns = [];
3413
3413
 
3414
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
3415
- var GanttElasticvue_type_template_id_2767341e_render = function render() {
3414
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
3415
+ var GanttElasticvue_type_template_id_100984c8_render = function render() {
3416
3416
  var _vm = this,
3417
3417
  _c = _vm._self._c,
3418
3418
  _setup = _vm._self._setupProxy;
@@ -3435,10 +3435,13 @@ var GanttElasticvue_type_template_id_2767341e_render = function render() {
3435
3435
  },
3436
3436
  slot: "header"
3437
3437
  }), _vm._t("header"), _c('main-view', {
3438
- ref: "mainView"
3438
+ ref: "mainView",
3439
+ on: {
3440
+ "task-updated": _vm.handleTaskUpdated
3441
+ }
3439
3442
  }), _vm._t("footer")], 2);
3440
3443
  };
3441
- var GanttElasticvue_type_template_id_2767341e_staticRenderFns = [];
3444
+ var GanttElasticvue_type_template_id_100984c8_staticRenderFns = [];
3442
3445
 
3443
3446
  // EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
3444
3447
  var es_array_push = __webpack_require__(4114);
@@ -3681,8 +3684,8 @@ var component = normalizeComponent(
3681
3684
  )
3682
3685
 
3683
3686
  /* harmony default export */ var GanttViewFilter = (component.exports);
3684
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
3685
- var MainViewvue_type_template_id_1a4b756c_render = function render() {
3687
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
3688
+ var MainViewvue_type_template_id_33392d22_render = function render() {
3686
3689
  var _vm = this,
3687
3690
  _c = _vm._self._c;
3688
3691
  return _c('div', {
@@ -3751,7 +3754,11 @@ var MainViewvue_type_template_id_1a4b756c_render = function render() {
3751
3754
  return _vm.chartWheel.apply(null, arguments);
3752
3755
  }
3753
3756
  }
3754
- }, [_c('chart')], 1)])]), _c('div', {
3757
+ }, [_c('chart', {
3758
+ on: {
3759
+ "task-updated": _vm.handleTaskUpdated
3760
+ }
3761
+ })], 1)])]), _c('div', {
3755
3762
  ref: "chartScrollContainerVertical",
3756
3763
  staticClass: "gantt-elastic__chart-scroll-container gantt-elastic__chart-scroll-container--vertical",
3757
3764
  style: {
@@ -3787,7 +3794,7 @@ var MainViewvue_type_template_id_1a4b756c_render = function render() {
3787
3794
  }
3788
3795
  })])]);
3789
3796
  };
3790
- var MainViewvue_type_template_id_1a4b756c_staticRenderFns = [];
3797
+ var MainViewvue_type_template_id_33392d22_staticRenderFns = [];
3791
3798
 
3792
3799
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
3793
3800
  var TaskListvue_type_template_id_74ce1216_render = function render() {
@@ -4594,8 +4601,8 @@ var TaskList_component = normalizeComponent(
4594
4601
  )
4595
4602
 
4596
4603
  /* harmony default export */ var TaskList = (TaskList_component.exports);
4597
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
4598
- var Chartvue_type_template_id_1d5eb6d6_render = function render() {
4604
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
4605
+ var Chartvue_type_template_id_2bc7fe5e_render = function render() {
4599
4606
  var _vm = this,
4600
4607
  _c = _vm._self._c;
4601
4608
  return _c('div', {
@@ -4663,14 +4670,17 @@ var Chartvue_type_template_id_1d5eb6d6_render = function render() {
4663
4670
  tag: "component",
4664
4671
  attrs: {
4665
4672
  "task": task
4673
+ },
4674
+ on: {
4675
+ "task-updated": _vm.handleTaskUpdated
4666
4676
  }
4667
4677
  })], 1);
4668
4678
  })], 2)])])])]);
4669
4679
  };
4670
- var Chartvue_type_template_id_1d5eb6d6_staticRenderFns = [];
4680
+ var Chartvue_type_template_id_2bc7fe5e_staticRenderFns = [];
4671
4681
 
4672
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
4673
- var Gridvue_type_template_id_b2e4dec2_render = function render() {
4682
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
4683
+ var Gridvue_type_template_id_244ea0ee_render = function render() {
4674
4684
  var _vm = this,
4675
4685
  _c = _vm._self._c;
4676
4686
  return _c('svg', {
@@ -4732,7 +4742,7 @@ var Gridvue_type_template_id_b2e4dec2_render = function render() {
4732
4742
  }
4733
4743
  })], 2)]);
4734
4744
  };
4735
- var Gridvue_type_template_id_b2e4dec2_staticRenderFns = [];
4745
+ var Gridvue_type_template_id_244ea0ee_staticRenderFns = [];
4736
4746
 
4737
4747
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/Grid.vue?vue&type=script&lang=js
4738
4748
 
@@ -4840,15 +4850,41 @@ var Gridvue_type_template_id_b2e4dec2_staticRenderFns = [];
4840
4850
  let lines = [];
4841
4851
  const state = this.root.state.options;
4842
4852
  let tasks = this.root.visibleTasks;
4843
- for (let index = 0, len = tasks.length; index <= len; index++) {
4844
- const y = index * (state.row.height + state.chart.grid.horizontal.gap * 2) + this.root.style['grid-line-vertical']['stroke-width'] / 2;
4845
- lines.push({
4846
- key: 'hl' + index,
4847
- x1: 0,
4848
- y1: y,
4849
- x2: '100%',
4850
- y2: y
4851
- });
4853
+
4854
+ // If we have tasks, show full grid for all tasks
4855
+ if (tasks.length > 0) {
4856
+ const rowHeight = state.row.height + state.chart.grid.horizontal.gap * 2;
4857
+ const rowCount = tasks.length; // Use actual task count
4858
+
4859
+ for (let index = 0; index <= rowCount; index++) {
4860
+ const y = index * rowHeight + this.root.style['grid-line-vertical']['stroke-width'] / 2;
4861
+ lines.push({
4862
+ key: 'hl' + index,
4863
+ x1: 0,
4864
+ y1: y,
4865
+ x2: '100%',
4866
+ y2: y
4867
+ });
4868
+ }
4869
+ } else {
4870
+ // If no tasks, use reduced viewport height for empty state
4871
+ const viewportHeight = window.innerHeight;
4872
+ const headerHeight = state.calendar.height + state.calendar.gap;
4873
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
4874
+ const reducedHeight = Math.max(availableHeight, 300); // Minimum 300px height
4875
+
4876
+ const rowHeight = state.row.height + state.chart.grid.horizontal.gap * 2;
4877
+ const maxRows = Math.floor(reducedHeight / rowHeight);
4878
+ for (let index = 0; index <= maxRows; index++) {
4879
+ const y = index * rowHeight + this.root.style['grid-line-vertical']['stroke-width'] / 2;
4880
+ lines.push({
4881
+ key: 'hl' + index,
4882
+ x1: 0,
4883
+ y1: y,
4884
+ x2: '100%',
4885
+ y2: y
4886
+ });
4887
+ }
4852
4888
  }
4853
4889
  return lines;
4854
4890
  },
@@ -4897,8 +4933,8 @@ var Gridvue_type_template_id_b2e4dec2_staticRenderFns = [];
4897
4933
  ;
4898
4934
  var Grid_component = normalizeComponent(
4899
4935
  Chart_Gridvue_type_script_lang_js,
4900
- Gridvue_type_template_id_b2e4dec2_render,
4901
- Gridvue_type_template_id_b2e4dec2_staticRenderFns,
4936
+ Gridvue_type_template_id_244ea0ee_render,
4937
+ Gridvue_type_template_id_244ea0ee_staticRenderFns,
4902
4938
  false,
4903
4939
  null,
4904
4940
  null,
@@ -5850,8 +5886,8 @@ var DependencyLines_component = normalizeComponent(
5850
5886
  )
5851
5887
 
5852
5888
  /* harmony default export */ var DependencyLines = (DependencyLines_component.exports);
5853
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
5854
- var Taskvue_type_template_id_208a9baa_render = function render() {
5889
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
5890
+ var Taskvue_type_template_id_2c01a3c8_render = function render() {
5855
5891
  var _vm = this,
5856
5892
  _c = _vm._self._c;
5857
5893
  return _c('g', {
@@ -5888,11 +5924,11 @@ var Taskvue_type_template_id_208a9baa_render = function render() {
5888
5924
  ..._vm.task.style['chart-row-bar']
5889
5925
  },
5890
5926
  attrs: {
5891
- "x": _vm.task.x,
5927
+ "x": _vm.task.x - 8,
5892
5928
  "y": _vm.task.y,
5893
- "width": _vm.task.width,
5929
+ "width": _vm.task.width + 16,
5894
5930
  "height": _vm.task.height,
5895
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
5931
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
5896
5932
  "xmlns": "http://www.w3.org/2000/svg"
5897
5933
  },
5898
5934
  on: {
@@ -5947,20 +5983,74 @@ var Taskvue_type_template_id_208a9baa_render = function render() {
5947
5983
  ..._vm.task.style['chart-row-bar-polygon']
5948
5984
  },
5949
5985
  attrs: {
5950
- "points": _vm.getPoints
5986
+ "points": _vm.getPointsAdjusted
5987
+ },
5988
+ on: {
5989
+ "mousedown": function ($event) {
5990
+ return _vm.startDrag($event, 'move');
5991
+ },
5992
+ "touchstart": function ($event) {
5993
+ return _vm.startDrag($event, 'move');
5994
+ }
5951
5995
  }
5952
5996
  }), _c('progress-bar', {
5953
5997
  attrs: {
5954
5998
  "task": _vm.task,
5955
5999
  "clip-path": 'url(#' + _vm.clipPathId + ')'
5956
6000
  }
6001
+ }), _c('rect', {
6002
+ staticClass: "gantt-elastic__chart-row-extend-handle",
6003
+ staticStyle: {
6004
+ "pointer-events": "all",
6005
+ "z-index": "20"
6006
+ },
6007
+ style: _vm.root.style['chart-row-extend-handle'],
6008
+ attrs: {
6009
+ "x": "8",
6010
+ "y": "0",
6011
+ "width": 8,
6012
+ "height": _vm.task.height
6013
+ },
6014
+ on: {
6015
+ "mousedown": function ($event) {
6016
+ $event.stopPropagation();
6017
+ return _vm.startDrag($event, 'start');
6018
+ },
6019
+ "touchstart": function ($event) {
6020
+ $event.stopPropagation();
6021
+ return _vm.startDrag($event, 'start');
6022
+ }
6023
+ }
6024
+ }), _c('rect', {
6025
+ staticClass: "gantt-elastic__chart-row-extend-handle",
6026
+ staticStyle: {
6027
+ "pointer-events": "all",
6028
+ "z-index": "20"
6029
+ },
6030
+ style: _vm.root.style['chart-row-extend-handle'],
6031
+ attrs: {
6032
+ "x": _vm.task.width - 8,
6033
+ "y": "0",
6034
+ "width": 8,
6035
+ "height": _vm.task.height
6036
+ },
6037
+ on: {
6038
+ "mousedown": function ($event) {
6039
+ $event.stopPropagation();
6040
+ return _vm.startDrag($event, 'end');
6041
+ },
6042
+ "touchstart": function ($event) {
6043
+ $event.stopPropagation();
6044
+ return _vm.startDrag($event, 'end');
6045
+ }
6046
+ }
5957
6047
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
5958
6048
  attrs: {
5959
6049
  "task": _vm.task
5960
6050
  }
5961
6051
  }) : _vm._e()], 1);
5962
6052
  };
5963
- var Taskvue_type_template_id_208a9baa_staticRenderFns = [];
6053
+ var Taskvue_type_template_id_2c01a3c8_staticRenderFns = [];
5964
6054
 
5965
6055
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
5966
6056
  var Textvue_type_template_id_634f40aa_render = function render() {
@@ -6097,15 +6187,16 @@ var Text_component = normalizeComponent(
6097
6187
  )
6098
6188
 
6099
6189
  /* harmony default export */ var Text = (Text_component.exports);
6100
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6101
- var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6190
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6191
+ var ProgressBarvue_type_template_id_2323ee21_render = function render() {
6102
6192
  var _vm = this,
6103
6193
  _c = _vm._self._c;
6104
6194
  return _c('g', {
6105
6195
  staticClass: "gantt-elastic__chart-row-progress-bar-wrapper",
6106
6196
  style: {
6107
6197
  ..._vm.root.style['chart-row-progress-bar-wrapper'],
6108
- ..._vm.task.style['chart-row-progress-bar-wrapper']
6198
+ ..._vm.task.style['chart-row-progress-bar-wrapper'],
6199
+ 'pointer-events': 'none'
6109
6200
  }
6110
6201
  }, [_c('defs', [_c('pattern', {
6111
6202
  attrs: {
@@ -6127,8 +6218,11 @@ var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6127
6218
  "x2": "0",
6128
6219
  "y2": _vm.root.state.options.chart.progress.width
6129
6220
  }
6130
- })])]), _vm.root.state.options.chart.progress.bar ? _c('rect', {
6221
+ })])]), _vm.root.state.options.chart.progress.bar && _vm.task.progress > 0 ? _c('rect', {
6131
6222
  staticClass: "gantt-elastic__chart-row-progress-bar-solid",
6223
+ staticStyle: {
6224
+ "pointer-events": "none"
6225
+ },
6132
6226
  style: {
6133
6227
  ..._vm.root.style['chart-row-progress-bar-solid'],
6134
6228
  ..._vm.task.style['chart-row-progress-bar-solid']
@@ -6138,7 +6232,11 @@ var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6138
6232
  "y": "0",
6139
6233
  "width": _vm.getProgressWidth
6140
6234
  }
6141
- }) : _vm._e(), _vm.root.state.options.chart.progress.pattern ? _c('g', [_c('rect', {
6235
+ }) : _vm._e(), _vm.root.state.options.chart.progress.pattern && _vm.task.progress > 0 ? _c('g', {
6236
+ staticStyle: {
6237
+ "pointer-events": "none"
6238
+ }
6239
+ }, [_c('rect', {
6142
6240
  staticClass: "gantt-elastic__chart-row-progress-bar-pattern",
6143
6241
  style: {
6144
6242
  ..._vm.root.style['chart-row-progress-bar-pattern'],
@@ -6162,7 +6260,7 @@ var ProgressBarvue_type_template_id_bc869ae8_render = function render() {
6162
6260
  }
6163
6261
  })]) : _vm._e()]);
6164
6262
  };
6165
- var ProgressBarvue_type_template_id_bc869ae8_staticRenderFns = [];
6263
+ var ProgressBarvue_type_template_id_2323ee21_staticRenderFns = [];
6166
6264
 
6167
6265
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Chart/ProgressBar.vue?vue&type=script&lang=js
6168
6266
  /* harmony default export */ var ProgressBarvue_type_script_lang_js = ({
@@ -6223,8 +6321,8 @@ var ProgressBarvue_type_template_id_bc869ae8_staticRenderFns = [];
6223
6321
  ;
6224
6322
  var ProgressBar_component = normalizeComponent(
6225
6323
  Chart_ProgressBarvue_type_script_lang_js,
6226
- ProgressBarvue_type_template_id_bc869ae8_render,
6227
- ProgressBarvue_type_template_id_bc869ae8_staticRenderFns,
6324
+ ProgressBarvue_type_template_id_2323ee21_render,
6325
+ ProgressBarvue_type_template_id_2323ee21_staticRenderFns,
6228
6326
  false,
6229
6327
  null,
6230
6328
  null,
@@ -6281,11 +6379,631 @@ var ProgressBar_component = normalizeComponent(
6281
6379
  }
6282
6380
  }
6283
6381
  });
6382
+ ;// ./src/components/Chart/Row/Draggable.mixin.js
6383
+
6384
+
6385
+ /* harmony default export */ var Draggable_mixin = ({
6386
+ data() {
6387
+ return {
6388
+ isDragging: false,
6389
+ dragStartX: 0,
6390
+ dragStartTime: 0,
6391
+ dragType: null,
6392
+ // 'start', 'end', or 'move'
6393
+ originalStartTime: 0,
6394
+ originalEndTime: 0,
6395
+ originalDuration: 0
6396
+ };
6397
+ },
6398
+ methods: {
6399
+ startDrag(event, type) {
6400
+ event.preventDefault();
6401
+ event.stopPropagation();
6402
+
6403
+ // Debug logging
6404
+ console.log('Starting drag:', {
6405
+ type: type,
6406
+ taskId: this.task.id,
6407
+ taskType: this.task.type,
6408
+ originalStart: this.task.startTime,
6409
+ originalEnd: this.task.endTime
6410
+ });
6411
+
6412
+ // Safety checks
6413
+ if (!this.root || !this.root.state || !this.root.state.options || !this.root.state.options.times) {
6414
+ console.error('Root or times options not available for dragging');
6415
+ return;
6416
+ }
6417
+ this.isDragging = true;
6418
+ this.dragType = type;
6419
+ this.dragStartX = event.clientX || event.touches[0].clientX;
6420
+ this.dragStartTime = this.task.startTime;
6421
+ this.originalStartTime = this.task.startTime;
6422
+ this.originalEndTime = this.task.endTime;
6423
+ this.originalDuration = this.task.duration;
6424
+
6425
+ // Add event listeners
6426
+ document.addEventListener('mousemove', this.handleDrag);
6427
+ document.addEventListener('mouseup', this.endDrag);
6428
+ document.addEventListener('touchmove', this.handleDrag);
6429
+ document.addEventListener('touchend', this.endDrag);
6430
+
6431
+ // Hide hover tooltip when dragging starts
6432
+ this.hideHoverTooltip();
6433
+
6434
+ // Add context menu for extending tasks
6435
+ // this.$el.addEventListener('contextmenu', this.showContextMenu);
6436
+
6437
+ // Add keyboard shortcuts
6438
+ this.$el.addEventListener('keydown', this.handleKeyboardShortcuts);
6439
+
6440
+ // Add dragging class for visual feedback
6441
+ this.$el.classList.add('gantt-elastic__task-dragging');
6442
+ this.$el.classList.add(`gantt-elastic__task-dragging--${type}`);
6443
+
6444
+ // Create date tooltip for all dragging types
6445
+ this.createDateTooltip();
6446
+ },
6447
+ handleDrag(event) {
6448
+ if (!this.isDragging) return;
6449
+ event.preventDefault();
6450
+ const currentX = event.clientX || event.touches[0].clientX;
6451
+ const deltaX = currentX - this.dragStartX;
6452
+
6453
+ // Convert pixel delta to time delta
6454
+ const timeDelta = deltaX * this.root.state.options.times.timePerPixel;
6455
+ if (this.dragType === 'move') {
6456
+ // Move entire task
6457
+ const newStartTime = this.originalStartTime + timeDelta;
6458
+ const newEndTime = this.originalEndTime + timeDelta;
6459
+
6460
+ // Ensure task doesn't go before chart start
6461
+ const chartStartTime = this.root.state.options.times.firstTime;
6462
+ const chartEndTime = this.root.state.options.times.lastTime;
6463
+ if (newStartTime >= chartStartTime && newEndTime <= chartEndTime) {
6464
+ this.updateTaskTime(newStartTime, newEndTime);
6465
+
6466
+ // Update date tooltip for move dragging
6467
+ if (this.dateTooltip) {
6468
+ this.updateDateTooltip(newStartTime);
6469
+ }
6470
+ }
6471
+ } else if (this.dragType === 'start') {
6472
+ // Resize from start - change start date
6473
+ const newStartTime = this.originalStartTime + timeDelta;
6474
+ const newEndTime = this.originalEndTime;
6475
+
6476
+ // Ensure start doesn't go after end and respects minimum duration
6477
+ const minDuration = 24 * 60 * 60 * 1000; // 1 day minimum
6478
+ const chartStartTime = this.root.state.options.times.firstTime;
6479
+ if (newStartTime < newEndTime && newEndTime - newStartTime >= minDuration && newStartTime >= chartStartTime) {
6480
+ this.updateTaskTime(newStartTime, newEndTime);
6481
+
6482
+ // Update date tooltip for start dragging
6483
+ if (this.dateTooltip) {
6484
+ this.updateDateTooltip(newStartTime);
6485
+ }
6486
+ }
6487
+ } else if (this.dragType === 'end') {
6488
+ // Resize from end - change end date while keeping start fixed
6489
+ const newStartTime = this.originalStartTime;
6490
+ const newEndTime = this.originalEndTime + timeDelta;
6491
+
6492
+ // Ensure end doesn't go before start and respects minimum duration
6493
+ const minDuration = 24 * 60 * 60 * 1000; // 1 day minimum
6494
+
6495
+ if (newEndTime > newStartTime && newEndTime - newStartTime >= minDuration) {
6496
+ // Allow extending beyond chart end time if needed
6497
+ this.updateTaskTime(newStartTime, newEndTime);
6498
+
6499
+ // Update date tooltip for end dragging
6500
+ if (this.dateTooltip) {
6501
+ this.updateDateTooltip(newEndTime);
6502
+ }
6503
+ }
6504
+ }
6505
+ },
6506
+ endDrag(event) {
6507
+ if (!this.isDragging) return;
6508
+ this.isDragging = false;
6509
+
6510
+ // Remove event listeners
6511
+ document.removeEventListener('mousemove', this.handleDrag);
6512
+ document.removeEventListener('mouseup', this.endDrag);
6513
+ document.removeEventListener('touchmove', this.handleDrag);
6514
+ document.removeEventListener('touchend', this.endDrag);
6515
+
6516
+ // Remove dragging classes
6517
+ this.$el.classList.remove('gantt-elastic__task-dragging');
6518
+ this.$el.classList.remove(`gantt-elastic__task-dragging--${this.dragType}`);
6519
+
6520
+ // Remove date tooltip
6521
+ this.removeDateTooltip();
6522
+
6523
+ // Emit save event with updated data
6524
+ this.emitSaveEvent();
6525
+ },
6526
+ updateTaskTime(newStartTime, newEndTime) {
6527
+ // Ensure valid times
6528
+ if (newStartTime >= newEndTime) {
6529
+ return; // Don't update if invalid
6530
+ }
6531
+
6532
+ // Debug logging for epic tasks
6533
+ if (this.task.type === 'epic') {
6534
+ console.log('Epic task drag:', {
6535
+ dragType: this.dragType,
6536
+ originalStart: this.originalStartTime,
6537
+ originalEnd: this.originalEndTime,
6538
+ newStart: newStartTime,
6539
+ newEnd: newEndTime,
6540
+ startChanged: newStartTime !== this.originalStartTime,
6541
+ endChanged: newEndTime !== this.originalEndTime
6542
+ });
6543
+ }
6544
+
6545
+ // Update task data
6546
+ this.task.startTime = newStartTime;
6547
+ this.task.endTime = newEndTime;
6548
+ this.task.duration = newEndTime - newStartTime;
6549
+
6550
+ // Debug logging
6551
+ console.log('Updating task time:', {
6552
+ taskId: this.task.id,
6553
+ newStartTime,
6554
+ newEndTime,
6555
+ duration: this.task.duration,
6556
+ root: !!this.root,
6557
+ timeToPixelOffsetX: !!(this.root && this.root.timeToPixelOffsetX),
6558
+ timePerPixel: this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel
6559
+ });
6560
+
6561
+ // Update task position and width using the correct method
6562
+ if (this.root && this.root.timeToPixelOffsetX) {
6563
+ this.task.x = this.root.timeToPixelOffsetX(newStartTime);
6564
+ this.task.width = this.root.timeToPixelOffsetX(newEndTime) - this.task.x;
6565
+ } else {
6566
+ // Fallback calculation if method is not available
6567
+ const timePerPixel = this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel;
6568
+ if (timePerPixel > 0) {
6569
+ this.task.x = (newStartTime - this.root.state.options.times.firstTime) / timePerPixel;
6570
+ this.task.width = (newEndTime - newStartTime) / timePerPixel;
6571
+ } else {
6572
+ console.error('timePerPixel is not available or invalid:', timePerPixel);
6573
+ }
6574
+ }
6575
+
6576
+ // Force update
6577
+ this.$forceUpdate();
6578
+ },
6579
+ emitSaveEvent() {
6580
+ // Calculate date information
6581
+ const startDate = new Date(this.task.startTime);
6582
+ const endDate = new Date(this.task.endTime);
6583
+ const durationDays = Math.ceil(this.task.duration / (24 * 60 * 60 * 1000));
6584
+
6585
+ // Emit event to parent component with updated task data
6586
+ this.$emit('task-updated', {
6587
+ id: this.task.id,
6588
+ startTime: this.task.startTime,
6589
+ endTime: this.task.endTime,
6590
+ duration: this.task.duration,
6591
+ durationDays: durationDays,
6592
+ startDate: startDate.toISOString(),
6593
+ endDate: endDate.toISOString(),
6594
+ startDateFormatted: startDate.toLocaleDateString(),
6595
+ endDateFormatted: endDate.toLocaleDateString(),
6596
+ dragType: this.dragType,
6597
+ originalStartTime: this.originalStartTime,
6598
+ originalEndTime: this.originalEndTime,
6599
+ originalDuration: this.originalDuration
6600
+ });
6601
+
6602
+ // Log the update for debugging
6603
+ console.log('Task drag completed:', {
6604
+ id: this.task.id,
6605
+ dragType: this.dragType,
6606
+ startDate: startDate.toLocaleDateString(),
6607
+ endDate: endDate.toLocaleDateString(),
6608
+ duration: `${durationDays} days`,
6609
+ startTime: this.task.startTime,
6610
+ endTime: this.task.endTime
6611
+ });
6612
+ },
6613
+ /**
6614
+ * Show context menu for task actions
6615
+ *
6616
+ * @param {Event} event - Right-click event
6617
+ */
6618
+ // showContextMenu(event) {
6619
+ // event.preventDefault();
6620
+ //
6621
+ // // Remove existing context menu
6622
+ // this.hideContextMenu();
6623
+ //
6624
+ // // Create context menu
6625
+ // const contextMenu = document.createElement('div');
6626
+ // contextMenu.className = 'gantt-elastic__context-menu';
6627
+ // contextMenu.style.cssText = `
6628
+ // position: fixed;
6629
+ // top: ${event.clientY}px;
6630
+ // left: ${event.clientX}px;
6631
+ // background: white;
6632
+ // border: 1px solid #e5e7eb;
6633
+ // border-radius: 6px;
6634
+ // box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
6635
+ // z-index: 1000;
6636
+ // min-width: 150px;
6637
+ // padding: 4px 0;
6638
+ // `;
6639
+ //
6640
+ // // Add menu items
6641
+ // const menuItems = [
6642
+ // { text: 'Extend to Next Date', action: () => this.extendTaskToNextDate() },
6643
+ // { text: 'Extend by 1 Day', action: () => this.extendTaskByDays(1) },
6644
+ // { text: 'Extend by 3 Days', action: () => this.extendTaskByDays(3) },
6645
+ // { text: 'Extend by 1 Week', action: () => this.extendTaskByDays(7) }
6646
+ // ];
6647
+ //
6648
+ // menuItems.forEach(item => {
6649
+ // const menuItem = document.createElement('div');
6650
+ // menuItem.className = 'gantt-elastic__context-menu-item';
6651
+ // menuItem.textContent = item.text;
6652
+ // menuItem.style.cssText = `
6653
+ // padding: 8px 16px;
6654
+ // cursor: pointer;
6655
+ // font-size: 14px;
6656
+ // color: #374151;
6657
+ // transition: background-color 0.2s;
6658
+ // `;
6659
+ //
6660
+ // menuItem.addEventListener('mouseenter', () => {
6661
+ // menuItem.style.backgroundColor = '#f3f4f6';
6662
+ // });
6663
+ //
6664
+ // menuItem.addEventListener('mouseleave', () => {
6665
+ // menuItem.style.backgroundColor = 'transparent';
6666
+ // });
6667
+ //
6668
+ // menuItem.addEventListener('click', () => {
6669
+ // item.action();
6670
+ // this.hideContextMenu();
6671
+ // });
6672
+ //
6673
+ // contextMenu.appendChild(menuItem);
6674
+ // });
6675
+ //
6676
+ // // Add to document
6677
+ // document.body.appendChild(contextMenu);
6678
+ // this.contextMenu = contextMenu;
6679
+ //
6680
+ // // Close menu when clicking outside
6681
+ // setTimeout(() => {
6682
+ // document.addEventListener('click', this.hideContextMenu);
6683
+ // }, 0);
6684
+ // },
6685
+
6686
+ /**
6687
+ * Hide context menu
6688
+ */
6689
+ // hideContextMenu() {
6690
+ // if (this.contextMenu) {
6691
+ // document.body.removeChild(this.contextMenu);
6692
+ // this.contextMenu = null;
6693
+ // document.removeEventListener('click', this.hideContextMenu);
6694
+ // }
6695
+ // },
6696
+
6697
+ /**
6698
+ * Extend task to next date (1 day)
6699
+ */
6700
+ // extendTaskToNextDate() {
6701
+ // const additionalDuration = 24 * 60 * 60 * 1000; // 1 day
6702
+ // this.task.duration += additionalDuration;
6703
+ // this.task.endTime += additionalDuration;
6704
+ //
6705
+ // // Update task position and width
6706
+ // if (this.root && this.root.timeToPixelOffsetX) {
6707
+ // this.task.width = this.root.timeToPixelOffsetX(this.task.endTime) - this.task.x;
6708
+ // } else {
6709
+ // const timePerPixel = this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel;
6710
+ // if (timePerPixel > 0) {
6711
+ // this.task.width = (this.task.endTime - this.task.startTime) / timePerPixel;
6712
+ // }
6713
+ // }
6714
+ //
6715
+ // // Emit update event
6716
+ // this.emitSaveEvent();
6717
+ //
6718
+ // console.log(`✅ Task extended to next date:`, {
6719
+ // taskId: this.task.id,
6720
+ // newDuration: this.task.duration,
6721
+ // newEndDate: new Date(this.task.endTime).toLocaleDateString()
6722
+ // });
6723
+ // },
6724
+
6725
+ /**
6726
+ * Extend task by specific number of days
6727
+ *
6728
+ * @param {number} days - Number of days to add
6729
+ */
6730
+ // extendTaskByDays(days) {
6731
+ // const additionalDuration = days * 24 * 60 * 60 * 1000;
6732
+ // this.task.duration += additionalDuration;
6733
+ // this.task.endTime += additionalDuration;
6734
+ //
6735
+ // // Update task position and width
6736
+ // if (this.root && this.root.timeToPixelOffsetX) {
6737
+ // this.task.width = this.root.timeToPixelOffsetX(this.task.endTime) - this.task.x;
6738
+ // } else {
6739
+ // const timePerPixel = this.root && this.root.state && this.root.state.options && this.root.state.options.times && this.root.state.options.times.timePerPixel;
6740
+ // if (timePerPixel > 0) {
6741
+ // this.task.width = (this.task.endTime - this.task.startTime) / timePerPixel;
6742
+ // }
6743
+ // }
6744
+ //
6745
+ // // Emit update event
6746
+ // this.emitSaveEvent();
6747
+ //
6748
+ // console.log(`✅ Task extended by ${days} day(s):`, {
6749
+ // taskId: this.task.id,
6750
+ // daysAdded: days,
6751
+ // newDuration: this.task.duration,
6752
+ // newEndDate: new Date(this.task.endTime).toLocaleDateString()
6753
+ // });
6754
+ // },
6755
+
6756
+ /**
6757
+ * Handle keyboard shortcuts for task extension
6758
+ *
6759
+ * @param {KeyboardEvent} event - Keyboard event
6760
+ */
6761
+ handleKeyboardShortcuts(event) {
6762
+ // Only handle if task is focused and not dragging
6763
+ if (this.isDragging) return;
6764
+
6765
+ // Check for Ctrl/Cmd + E for extend to next date
6766
+ if ((event.ctrlKey || event.metaKey) && event.key === 'e') {
6767
+ event.preventDefault();
6768
+ this.extendTaskToNextDate();
6769
+ }
6770
+ // Check for Ctrl/Cmd + Shift + E for extend by 1 day
6771
+ else if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === 'E') {
6772
+ event.preventDefault();
6773
+ this.extendTaskByDays(1);
6774
+ }
6775
+ // Check for Ctrl/Cmd + 3 for extend by 3 days
6776
+ else if ((event.ctrlKey || event.metaKey) && event.key === '3') {
6777
+ event.preventDefault();
6778
+ this.extendTaskByDays(3);
6779
+ }
6780
+ // Check for Ctrl/Cmd + 7 for extend by 1 week
6781
+ else if ((event.ctrlKey || event.metaKey) && event.key === '7') {
6782
+ event.preventDefault();
6783
+ this.extendTaskByDays(7);
6784
+ }
6785
+ },
6786
+ /**
6787
+ * Create date tooltip for end dragging
6788
+ */
6789
+ createDateTooltip() {
6790
+ this.dateTooltip = document.createElement('div');
6791
+ this.dateTooltip.className = 'gantt-elastic__date-tooltip';
6792
+ this.dateTooltip.style.cssText = `
6793
+ position: fixed;
6794
+ background: #000000;
6795
+ color: white;
6796
+ padding: 6px 12px;
6797
+ border-radius: 6px;
6798
+ font-size: 13px;
6799
+ font-family: system-ui, -apple-system, sans-serif;
6800
+ font-weight: 500;
6801
+ pointer-events: none;
6802
+ z-index: 10000;
6803
+ white-space: nowrap;
6804
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
6805
+ border: 1px solid rgba(255, 255, 255, 0.1);
6806
+ `;
6807
+ document.body.appendChild(this.dateTooltip);
6808
+
6809
+ // Initialize tooltip with current values
6810
+ if (this.dragType === 'start') {
6811
+ this.updateDateTooltip(this.originalStartTime);
6812
+ } else if (this.dragType === 'end') {
6813
+ this.updateDateTooltip(this.originalEndTime);
6814
+ } else if (this.dragType === 'move') {
6815
+ this.updateDateTooltip(this.originalStartTime);
6816
+ }
6817
+ },
6818
+ /**
6819
+ * Update date tooltip with new time and day changes
6820
+ *
6821
+ * @param {number} newTime - New time in milliseconds
6822
+ */
6823
+ updateDateTooltip(newTime) {
6824
+ if (!this.dateTooltip) return;
6825
+ const newDate = new Date(newTime);
6826
+ const formattedDate = newDate.toLocaleDateString('en-US', {
6827
+ year: 'numeric',
6828
+ month: 'short',
6829
+ day: 'numeric'
6830
+ });
6831
+
6832
+ // Calculate day changes based on drag type
6833
+ let dayChanges = '';
6834
+ if (this.dragType === 'start') {
6835
+ // For start drag, show how many days we're moving the start date
6836
+ const daysDiff = Math.round((newTime - this.originalStartTime) / (24 * 60 * 60 * 1000));
6837
+ if (daysDiff !== 0) {
6838
+ dayChanges = daysDiff > 0 ? ` (+${daysDiff} days)` : ` (${daysDiff} days)`;
6839
+ }
6840
+ } else if (this.dragType === 'end') {
6841
+ // For end drag, show how many days we're moving the end date
6842
+ const daysDiff = Math.round((newTime - this.originalEndTime) / (24 * 60 * 60 * 1000));
6843
+ if (daysDiff !== 0) {
6844
+ dayChanges = daysDiff > 0 ? ` (+${daysDiff} days)` : ` (${daysDiff} days)`;
6845
+ }
6846
+ } else if (this.dragType === 'move') {
6847
+ // For move drag, show how many days we're moving the entire task
6848
+ const daysDiff = Math.round((newTime - this.originalStartTime) / (24 * 60 * 60 * 1000));
6849
+ if (daysDiff !== 0) {
6850
+ dayChanges = daysDiff > 0 ? ` (+${daysDiff} days)` : ` (${daysDiff} days)`;
6851
+ }
6852
+ }
6853
+ this.dateTooltip.textContent = `${formattedDate}${dayChanges}`;
6854
+
6855
+ // Position tooltip based on drag type
6856
+ const rect = this.$el.getBoundingClientRect();
6857
+ if (this.dragType === 'start') {
6858
+ // Position tooltip on the left side for start drag
6859
+ this.dateTooltip.style.left = `${rect.left - this.dateTooltip.offsetWidth - 10}px`;
6860
+ this.dateTooltip.style.top = `${rect.top + rect.height / 2 - 10}px`;
6861
+ } else if (this.dragType === 'end') {
6862
+ // Position tooltip on the right side for end drag
6863
+ this.dateTooltip.style.left = `${rect.right + 10}px`;
6864
+ this.dateTooltip.style.top = `${rect.top + rect.height / 2 - 10}px`;
6865
+ } else if (this.dragType === 'move') {
6866
+ // Position tooltip on the right side for move drag
6867
+ this.dateTooltip.style.left = `${rect.right + 10}px`;
6868
+ this.dateTooltip.style.top = `${rect.top + rect.height / 2 - 10}px`;
6869
+ }
6870
+ },
6871
+ /**
6872
+ * Remove date tooltip
6873
+ */
6874
+ removeDateTooltip() {
6875
+ if (this.dateTooltip) {
6876
+ document.body.removeChild(this.dateTooltip);
6877
+ this.dateTooltip = null;
6878
+ }
6879
+ },
6880
+ /**
6881
+ * Add hover tooltips for drag handles
6882
+ */
6883
+ addHoverTooltips() {
6884
+ // Find drag handles in the current element
6885
+ const dragHandles = this.$el.querySelectorAll('.gantt-elastic__chart-row-extend-handle');
6886
+ dragHandles.forEach((handle, index) => {
6887
+ const isStartHandle = index === 0; // First handle is start, second is end
6888
+
6889
+ // Remove existing listeners to avoid duplicates
6890
+ handle.removeEventListener('mouseenter', this.handleMouseEnter);
6891
+ handle.removeEventListener('mouseleave', this.handleMouseLeave);
6892
+
6893
+ // Add new listeners
6894
+ handle.addEventListener('mouseenter', this.handleMouseEnter.bind(this));
6895
+ handle.addEventListener('mouseleave', this.handleMouseLeave.bind(this));
6896
+ });
6897
+ },
6898
+ /**
6899
+ * Handle mouse enter on drag handle
6900
+ */
6901
+ handleMouseEnter(event) {
6902
+ if (!this.isDragging) {
6903
+ this.showHoverTooltip(event, false);
6904
+ }
6905
+ },
6906
+ /**
6907
+ * Handle mouse leave on drag handle
6908
+ */
6909
+ handleMouseLeave() {
6910
+ if (!this.isDragging) {
6911
+ this.hideHoverTooltip();
6912
+ }
6913
+ },
6914
+ /**
6915
+ * Show hover tooltip with date range and duration
6916
+ */
6917
+ showHoverTooltip(event, isStartHandle) {
6918
+ this.hideHoverTooltip(); // Remove any existing tooltip
6919
+
6920
+ const startDate = new Date(this.task.startTime);
6921
+ const endDate = new Date(this.task.endTime);
6922
+ const startFormatted = startDate.toLocaleDateString('en-US', {
6923
+ year: 'numeric',
6924
+ month: 'short',
6925
+ day: 'numeric'
6926
+ });
6927
+ const endFormatted = endDate.toLocaleDateString('en-US', {
6928
+ year: 'numeric',
6929
+ month: 'short',
6930
+ day: 'numeric'
6931
+ });
6932
+
6933
+ // Calculate duration in days
6934
+ const durationMs = this.task.endTime - this.task.startTime;
6935
+ const durationDays = Math.ceil(durationMs / (24 * 60 * 60 * 1000));
6936
+ this.hoverTooltip = document.createElement('div');
6937
+ this.hoverTooltip.className = 'gantt-elastic__hover-tooltip';
6938
+ this.hoverTooltip.textContent = `${startFormatted} - ${endFormatted} (${durationDays} days)`;
6939
+ this.hoverTooltip.style.cssText = `
6940
+ position: fixed;
6941
+ background: #333333;
6942
+ color: white;
6943
+ padding: 8px 12px;
6944
+ border-radius: 6px;
6945
+ font-size: 13px;
6946
+ font-family: system-ui, -apple-system, sans-serif;
6947
+ font-weight: 500;
6948
+ pointer-events: none;
6949
+ z-index: 10001;
6950
+ white-space: nowrap;
6951
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
6952
+ border: 1px solid rgba(255, 255, 255, 0.1);
6953
+ `;
6954
+ document.body.appendChild(this.hoverTooltip);
6955
+
6956
+ // Position tooltip above the handle
6957
+ const rect = event.target.getBoundingClientRect();
6958
+ this.hoverTooltip.style.left = `${rect.left + rect.width / 2 - this.hoverTooltip.offsetWidth / 2}px`;
6959
+ this.hoverTooltip.style.top = `${rect.top - this.hoverTooltip.offsetHeight - 8}px`;
6960
+ },
6961
+ /**
6962
+ * Hide hover tooltip
6963
+ */
6964
+ hideHoverTooltip() {
6965
+ if (this.hoverTooltip) {
6966
+ document.body.removeChild(this.hoverTooltip);
6967
+ this.hoverTooltip = null;
6968
+ }
6969
+ }
6970
+ },
6971
+ mounted() {
6972
+ // Add hover tooltips when component is mounted
6973
+ this.$nextTick(() => {
6974
+ this.addHoverTooltips();
6975
+ });
6976
+ },
6977
+ beforeDestroy() {
6978
+ // Clean up event listeners
6979
+ document.removeEventListener('mousemove', this.handleDrag);
6980
+ document.removeEventListener('mouseup', this.endDrag);
6981
+ document.removeEventListener('touchmove', this.handleDrag);
6982
+ document.removeEventListener('touchend', this.endDrag);
6983
+ document.removeEventListener('click', this.hideContextMenu);
6984
+
6985
+ // Clean up context menu
6986
+ this.hideContextMenu();
6987
+
6988
+ // Clean up date tooltip
6989
+ this.removeDateTooltip();
6990
+
6991
+ // Clean up hover tooltip
6992
+ this.hideHoverTooltip();
6993
+
6994
+ // Clean up keyboard listeners
6995
+ if (this.$el) {
6996
+ // this.$el.removeEventListener('contextmenu', this.showContextMenu);
6997
+ this.$el.removeEventListener('keydown', this.handleKeyboardShortcuts);
6998
+ }
6999
+ }
7000
+ });
6284
7001
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6285
7002
 
6286
7003
 
6287
7004
 
6288
7005
 
7006
+
6289
7007
  /* harmony default export */ var Taskvue_type_script_lang_js = ({
6290
7008
  name: 'Task',
6291
7009
  components: {
@@ -6295,7 +7013,7 @@ var ProgressBar_component = normalizeComponent(
6295
7013
  },
6296
7014
  inject: ['root'],
6297
7015
  props: ['task'],
6298
- mixins: [Task_mixin],
7016
+ mixins: [Task_mixin, Draggable_mixin],
6299
7017
  data() {
6300
7018
  return {};
6301
7019
  },
@@ -6316,6 +7034,15 @@ var ProgressBar_component = normalizeComponent(
6316
7034
  getPoints() {
6317
7035
  const task = this.task;
6318
7036
  return `0,0 ${task.width},0 ${task.width},${task.height} 0,${task.height}`;
7037
+ },
7038
+ /**
7039
+ * Get points adjusted for viewBox
7040
+ *
7041
+ * @returns {string}
7042
+ */
7043
+ getPointsAdjusted() {
7044
+ const task = this.task;
7045
+ return `8,0 ${task.width + 8},0 ${task.width + 8},${task.height} 8,${task.height}`;
6319
7046
  }
6320
7047
  }
6321
7048
  });
@@ -6331,8 +7058,8 @@ var ProgressBar_component = normalizeComponent(
6331
7058
  ;
6332
7059
  var Task_component = normalizeComponent(
6333
7060
  Row_Taskvue_type_script_lang_js,
6334
- Taskvue_type_template_id_208a9baa_render,
6335
- Taskvue_type_template_id_208a9baa_staticRenderFns,
7061
+ Taskvue_type_template_id_2c01a3c8_render,
7062
+ Taskvue_type_template_id_2c01a3c8_staticRenderFns,
6336
7063
  false,
6337
7064
  null,
6338
7065
  null,
@@ -6341,8 +7068,8 @@ var Task_component = normalizeComponent(
6341
7068
  )
6342
7069
 
6343
7070
  /* harmony default export */ var Task = (Task_component.exports);
6344
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6345
- var Milestonevue_type_template_id_edd49e02_render = function render() {
7071
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
7072
+ var Milestonevue_type_template_id_4cea99c4_render = function render() {
6346
7073
  var _vm = this,
6347
7074
  _c = _vm._self._c;
6348
7075
  return _c('g', {
@@ -6379,11 +7106,11 @@ var Milestonevue_type_template_id_edd49e02_render = function render() {
6379
7106
  ..._vm.task.style['chart-row-bar']
6380
7107
  },
6381
7108
  attrs: {
6382
- "x": _vm.task.x,
7109
+ "x": _vm.task.x - 8,
6383
7110
  "y": _vm.task.y,
6384
- "width": _vm.task.width,
7111
+ "width": _vm.task.width + 16,
6385
7112
  "height": _vm.task.height,
6386
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7113
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6387
7114
  "xmlns": "http://www.w3.org/2000/svg"
6388
7115
  },
6389
7116
  on: {
@@ -6438,26 +7165,81 @@ var Milestonevue_type_template_id_edd49e02_render = function render() {
6438
7165
  ..._vm.task.style['chart-row-bar-polygon']
6439
7166
  },
6440
7167
  attrs: {
6441
- "points": _vm.getPoints
7168
+ "points": _vm.getPointsAdjusted
7169
+ },
7170
+ on: {
7171
+ "mousedown": function ($event) {
7172
+ return _vm.startDrag($event, 'move');
7173
+ },
7174
+ "touchstart": function ($event) {
7175
+ return _vm.startDrag($event, 'move');
7176
+ }
6442
7177
  }
6443
7178
  }), _c('progress-bar', {
6444
7179
  attrs: {
6445
7180
  "task": _vm.task,
6446
7181
  "clip-path": 'url(#' + _vm.clipPathId + ')'
6447
7182
  }
7183
+ }), _c('rect', {
7184
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7185
+ staticStyle: {
7186
+ "pointer-events": "all",
7187
+ "z-index": "20"
7188
+ },
7189
+ style: _vm.root.style['chart-row-extend-handle'],
7190
+ attrs: {
7191
+ "x": "8",
7192
+ "y": "0",
7193
+ "width": 8,
7194
+ "height": _vm.task.height
7195
+ },
7196
+ on: {
7197
+ "mousedown": function ($event) {
7198
+ $event.stopPropagation();
7199
+ return _vm.startDrag($event, 'start');
7200
+ },
7201
+ "touchstart": function ($event) {
7202
+ $event.stopPropagation();
7203
+ return _vm.startDrag($event, 'start');
7204
+ }
7205
+ }
7206
+ }), _c('rect', {
7207
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7208
+ staticStyle: {
7209
+ "pointer-events": "all",
7210
+ "z-index": "20"
7211
+ },
7212
+ style: _vm.root.style['chart-row-extend-handle'],
7213
+ attrs: {
7214
+ "x": _vm.task.width - 8,
7215
+ "y": "0",
7216
+ "width": 8,
7217
+ "height": _vm.task.height
7218
+ },
7219
+ on: {
7220
+ "mousedown": function ($event) {
7221
+ $event.stopPropagation();
7222
+ return _vm.startDrag($event, 'end');
7223
+ },
7224
+ "touchstart": function ($event) {
7225
+ $event.stopPropagation();
7226
+ return _vm.startDrag($event, 'end');
7227
+ }
7228
+ }
6448
7229
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
6449
7230
  attrs: {
6450
7231
  "task": _vm.task
6451
7232
  }
6452
7233
  }) : _vm._e()], 1);
6453
7234
  };
6454
- var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
7235
+ var Milestonevue_type_template_id_4cea99c4_staticRenderFns = [];
6455
7236
 
6456
7237
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6457
7238
 
6458
7239
 
6459
7240
 
6460
7241
 
7242
+
6461
7243
  /* harmony default export */ var Milestonevue_type_script_lang_js = ({
6462
7244
  name: 'Milestone',
6463
7245
  components: {
@@ -6467,7 +7249,7 @@ var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
6467
7249
  },
6468
7250
  inject: ['root'],
6469
7251
  props: ['task'],
6470
- mixins: [Task_mixin],
7252
+ mixins: [Task_mixin, Draggable_mixin],
6471
7253
  data() {
6472
7254
  return {};
6473
7255
  },
@@ -6498,6 +7280,25 @@ var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
6498
7280
  ${task.width},${fifty}
6499
7281
  ${task.width - offset},${task.height}
6500
7282
  ${offset},${task.height}`;
7283
+ },
7284
+ /**
7285
+ * Get points adjusted for viewBox
7286
+ *
7287
+ * @returns {string}
7288
+ */
7289
+ getPointsAdjusted() {
7290
+ const task = this.task;
7291
+ const fifty = task.height / 2;
7292
+ let offset = fifty;
7293
+ if (task.width / 2 - offset < 0) {
7294
+ offset = task.width / 2;
7295
+ }
7296
+ return `${8},${fifty}
7297
+ ${8 + offset},0
7298
+ ${8 + task.width - offset},0
7299
+ ${8 + task.width},${fifty}
7300
+ ${8 + task.width - offset},${task.height}
7301
+ ${8 + offset},${task.height}`;
6501
7302
  }
6502
7303
  }
6503
7304
  });
@@ -6513,8 +7314,8 @@ var Milestonevue_type_template_id_edd49e02_staticRenderFns = [];
6513
7314
  ;
6514
7315
  var Milestone_component = normalizeComponent(
6515
7316
  Row_Milestonevue_type_script_lang_js,
6516
- Milestonevue_type_template_id_edd49e02_render,
6517
- Milestonevue_type_template_id_edd49e02_staticRenderFns,
7317
+ Milestonevue_type_template_id_4cea99c4_render,
7318
+ Milestonevue_type_template_id_4cea99c4_staticRenderFns,
6518
7319
  false,
6519
7320
  null,
6520
7321
  null,
@@ -6523,8 +7324,8 @@ var Milestone_component = normalizeComponent(
6523
7324
  )
6524
7325
 
6525
7326
  /* harmony default export */ var Milestone = (Milestone_component.exports);
6526
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6527
- var Projectvue_type_template_id_760bf767_render = function render() {
7327
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
7328
+ var Projectvue_type_template_id_5dcaf9ef_render = function render() {
6528
7329
  var _vm = this,
6529
7330
  _c = _vm._self._c;
6530
7331
  return _c('g', {
@@ -6561,11 +7362,11 @@ var Projectvue_type_template_id_760bf767_render = function render() {
6561
7362
  ..._vm.task.style['chart-row-bar']
6562
7363
  },
6563
7364
  attrs: {
6564
- "x": _vm.task.x,
7365
+ "x": _vm.task.x - 8,
6565
7366
  "y": _vm.task.y,
6566
- "width": _vm.task.width,
7367
+ "width": _vm.task.width + 16,
6567
7368
  "height": _vm.task.height,
6568
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7369
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6569
7370
  "xmlns": "http://www.w3.org/2000/svg"
6570
7371
  },
6571
7372
  on: {
@@ -6620,26 +7421,81 @@ var Projectvue_type_template_id_760bf767_render = function render() {
6620
7421
  ..._vm.task.style['chart-row-bar-polygon']
6621
7422
  },
6622
7423
  attrs: {
6623
- "d": _vm.getPoints
7424
+ "d": _vm.getPointsAdjusted
7425
+ },
7426
+ on: {
7427
+ "mousedown": function ($event) {
7428
+ return _vm.startDrag($event, 'move');
7429
+ },
7430
+ "touchstart": function ($event) {
7431
+ return _vm.startDrag($event, 'move');
7432
+ }
6624
7433
  }
6625
7434
  }), _c('progress-bar', {
6626
7435
  attrs: {
6627
7436
  "task": _vm.task,
6628
7437
  "clip-path": 'url(#' + _vm.clipPathId + ')'
6629
7438
  }
7439
+ }), _c('rect', {
7440
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7441
+ staticStyle: {
7442
+ "pointer-events": "all",
7443
+ "z-index": "20"
7444
+ },
7445
+ style: _vm.root.style['chart-row-extend-handle'],
7446
+ attrs: {
7447
+ "x": "8",
7448
+ "y": "0",
7449
+ "width": 8,
7450
+ "height": _vm.task.height
7451
+ },
7452
+ on: {
7453
+ "mousedown": function ($event) {
7454
+ $event.stopPropagation();
7455
+ return _vm.startDrag($event, 'start');
7456
+ },
7457
+ "touchstart": function ($event) {
7458
+ $event.stopPropagation();
7459
+ return _vm.startDrag($event, 'start');
7460
+ }
7461
+ }
7462
+ }), _c('rect', {
7463
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7464
+ staticStyle: {
7465
+ "pointer-events": "all",
7466
+ "z-index": "20"
7467
+ },
7468
+ style: _vm.root.style['chart-row-extend-handle'],
7469
+ attrs: {
7470
+ "x": _vm.task.width - 8,
7471
+ "y": "0",
7472
+ "width": 8,
7473
+ "height": _vm.task.height
7474
+ },
7475
+ on: {
7476
+ "mousedown": function ($event) {
7477
+ $event.stopPropagation();
7478
+ return _vm.startDrag($event, 'end');
7479
+ },
7480
+ "touchstart": function ($event) {
7481
+ $event.stopPropagation();
7482
+ return _vm.startDrag($event, 'end');
7483
+ }
7484
+ }
6630
7485
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
6631
7486
  attrs: {
6632
7487
  "task": _vm.task
6633
7488
  }
6634
7489
  }) : _vm._e()], 1);
6635
7490
  };
6636
- var Projectvue_type_template_id_760bf767_staticRenderFns = [];
7491
+ var Projectvue_type_template_id_5dcaf9ef_staticRenderFns = [];
6637
7492
 
6638
7493
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6639
7494
 
6640
7495
 
6641
7496
 
6642
7497
 
7498
+
6643
7499
  /* harmony default export */ var Projectvue_type_script_lang_js = ({
6644
7500
  name: 'Project',
6645
7501
  components: {
@@ -6649,7 +7505,7 @@ var Projectvue_type_template_id_760bf767_staticRenderFns = [];
6649
7505
  },
6650
7506
  inject: ['root'],
6651
7507
  props: ['task'],
6652
- mixins: [Task_mixin],
7508
+ mixins: [Task_mixin, Draggable_mixin],
6653
7509
  data() {
6654
7510
  return {};
6655
7511
  },
@@ -6685,6 +7541,29 @@ var Projectvue_type_template_id_760bf767_staticRenderFns = [];
6685
7541
  Z
6686
7542
  `;
6687
7543
  },
7544
+ /**
7545
+ * Get points adjusted for viewBox
7546
+ *
7547
+ * @returns {string}
7548
+ */
7549
+ getPointsAdjusted() {
7550
+ const task = this.task;
7551
+ const bottom = task.height - task.height / 4;
7552
+ const corner = task.height / 6;
7553
+ const smallCorner = task.height / 8;
7554
+ return `M ${8 + smallCorner},0
7555
+ L ${8 + task.width - smallCorner} 0
7556
+ L ${8 + task.width} ${smallCorner}
7557
+ L ${8 + task.width} ${bottom}
7558
+ L ${8 + task.width - corner} ${task.height}
7559
+ L ${8 + task.width - corner * 2} ${bottom}
7560
+ L ${8 + corner * 2} ${bottom}
7561
+ L ${8 + corner} ${task.height}
7562
+ L ${8} ${bottom}
7563
+ L ${8} ${smallCorner}
7564
+ Z
7565
+ `;
7566
+ },
6688
7567
  /**
6689
7568
  * Should we display expander?
6690
7569
  *
@@ -6709,8 +7588,8 @@ var Projectvue_type_template_id_760bf767_staticRenderFns = [];
6709
7588
  ;
6710
7589
  var Project_component = normalizeComponent(
6711
7590
  Row_Projectvue_type_script_lang_js,
6712
- Projectvue_type_template_id_760bf767_render,
6713
- Projectvue_type_template_id_760bf767_staticRenderFns,
7591
+ Projectvue_type_template_id_5dcaf9ef_render,
7592
+ Projectvue_type_template_id_5dcaf9ef_staticRenderFns,
6714
7593
  false,
6715
7594
  null,
6716
7595
  null,
@@ -6719,8 +7598,8 @@ var Project_component = normalizeComponent(
6719
7598
  )
6720
7599
 
6721
7600
  /* harmony default export */ var Project = (Project_component.exports);
6722
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6723
- var Epicvue_type_template_id_a2e89cd8_render = function render() {
7601
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
7602
+ var Epicvue_type_template_id_6e337196_render = function render() {
6724
7603
  var _vm = this,
6725
7604
  _c = _vm._self._c;
6726
7605
  return _c('g', {
@@ -6757,11 +7636,11 @@ var Epicvue_type_template_id_a2e89cd8_render = function render() {
6757
7636
  ..._vm.task.style['chart-row-bar']
6758
7637
  },
6759
7638
  attrs: {
6760
- "x": _vm.task.x,
7639
+ "x": _vm.task.x - 8,
6761
7640
  "y": _vm.task.y,
6762
- "width": _vm.task.width,
7641
+ "width": _vm.task.width + 16,
6763
7642
  "height": _vm.task.height,
6764
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7643
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6765
7644
  "xmlns": "http://www.w3.org/2000/svg"
6766
7645
  },
6767
7646
  on: {
@@ -6813,29 +7692,86 @@ var Epicvue_type_template_id_a2e89cd8_render = function render() {
6813
7692
  ..._vm.root.style['chart-row-bar-polygon'],
6814
7693
  ..._vm.root.style['chart-row-epic-polygon'],
6815
7694
  ..._vm.task.style['base'],
6816
- ..._vm.task.style['chart-row-bar-polygon']
7695
+ ..._vm.task.style['chart-row-bar-polygon'],
7696
+ 'pointer-events': 'all',
7697
+ 'z-index': '10'
6817
7698
  },
6818
7699
  attrs: {
6819
- "d": _vm.getPoints
7700
+ "d": _vm.getPointsAdjusted
7701
+ },
7702
+ on: {
7703
+ "mousedown": function ($event) {
7704
+ return _vm.startDrag($event, 'move');
7705
+ },
7706
+ "touchstart": function ($event) {
7707
+ return _vm.startDrag($event, 'move');
7708
+ }
6820
7709
  }
6821
- }), _c('progress-bar', {
7710
+ }), _vm.task.progress > 0 ? _c('progress-bar', {
6822
7711
  attrs: {
6823
7712
  "task": _vm.task,
6824
7713
  "clip-path": 'url(#' + _vm.clipPathId + ')'
6825
7714
  }
7715
+ }) : _vm._e(), _c('rect', {
7716
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7717
+ staticStyle: {
7718
+ "pointer-events": "all",
7719
+ "z-index": "30"
7720
+ },
7721
+ style: _vm.root.style['chart-row-extend-handle'],
7722
+ attrs: {
7723
+ "x": "8",
7724
+ "y": "0",
7725
+ "width": 8,
7726
+ "height": _vm.task.height
7727
+ },
7728
+ on: {
7729
+ "mousedown": function ($event) {
7730
+ $event.stopPropagation();
7731
+ return _vm.startDrag($event, 'start');
7732
+ },
7733
+ "touchstart": function ($event) {
7734
+ $event.stopPropagation();
7735
+ return _vm.startDrag($event, 'start');
7736
+ }
7737
+ }
7738
+ }), _c('rect', {
7739
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7740
+ staticStyle: {
7741
+ "pointer-events": "all",
7742
+ "z-index": "30"
7743
+ },
7744
+ style: _vm.root.style['chart-row-extend-handle'],
7745
+ attrs: {
7746
+ "x": _vm.task.width - 8,
7747
+ "y": "0",
7748
+ "width": 8,
7749
+ "height": _vm.task.height
7750
+ },
7751
+ on: {
7752
+ "mousedown": function ($event) {
7753
+ $event.stopPropagation();
7754
+ return _vm.startDrag($event, 'end');
7755
+ },
7756
+ "touchstart": function ($event) {
7757
+ $event.stopPropagation();
7758
+ return _vm.startDrag($event, 'end');
7759
+ }
7760
+ }
6826
7761
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
6827
7762
  attrs: {
6828
7763
  "task": _vm.task
6829
7764
  }
6830
7765
  }) : _vm._e()], 1);
6831
7766
  };
6832
- var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
7767
+ var Epicvue_type_template_id_6e337196_staticRenderFns = [];
6833
7768
 
6834
7769
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6835
7770
 
6836
7771
 
6837
7772
 
6838
7773
 
7774
+
6839
7775
  /* harmony default export */ var Epicvue_type_script_lang_js = ({
6840
7776
  name: 'Epic',
6841
7777
  components: {
@@ -6845,7 +7781,7 @@ var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
6845
7781
  },
6846
7782
  inject: ['root'],
6847
7783
  props: ['task'],
6848
- mixins: [Task_mixin],
7784
+ mixins: [Task_mixin, Draggable_mixin],
6849
7785
  data() {
6850
7786
  return {};
6851
7787
  },
@@ -6881,6 +7817,29 @@ var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
6881
7817
  Z
6882
7818
  `;
6883
7819
  },
7820
+ /**
7821
+ * Get points adjusted for viewBox
7822
+ *
7823
+ * @returns {string}
7824
+ */
7825
+ getPointsAdjusted() {
7826
+ const task = this.task;
7827
+ const bottom = task.height - task.height / 4;
7828
+ const corner = task.height / 6;
7829
+ const smallCorner = task.height / 8;
7830
+ return `M ${8 + smallCorner},0
7831
+ L ${8 + task.width - smallCorner} 0
7832
+ L ${8 + task.width} ${smallCorner}
7833
+ L ${8 + task.width} ${bottom}
7834
+ L ${8 + task.width - corner} ${task.height}
7835
+ L ${8 + task.width - corner * 2} ${bottom}
7836
+ L ${8 + corner * 2} ${bottom}
7837
+ L ${8 + corner} ${task.height}
7838
+ L ${8} ${bottom}
7839
+ L ${8} ${smallCorner}
7840
+ Z
7841
+ `;
7842
+ },
6884
7843
  /**
6885
7844
  * Should we display expander?
6886
7845
  *
@@ -6905,8 +7864,8 @@ var Epicvue_type_template_id_a2e89cd8_staticRenderFns = [];
6905
7864
  ;
6906
7865
  var Epic_component = normalizeComponent(
6907
7866
  Row_Epicvue_type_script_lang_js,
6908
- Epicvue_type_template_id_a2e89cd8_render,
6909
- Epicvue_type_template_id_a2e89cd8_staticRenderFns,
7867
+ Epicvue_type_template_id_6e337196_render,
7868
+ Epicvue_type_template_id_6e337196_staticRenderFns,
6910
7869
  false,
6911
7870
  null,
6912
7871
  null,
@@ -6915,8 +7874,8 @@ var Epic_component = normalizeComponent(
6915
7874
  )
6916
7875
 
6917
7876
  /* harmony default export */ var Epic = (Epic_component.exports);
6918
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
6919
- var Subtaskvue_type_template_id_86599310_render = function render() {
7877
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
7878
+ var Subtaskvue_type_template_id_339b7174_render = function render() {
6920
7879
  var _vm = this,
6921
7880
  _c = _vm._self._c;
6922
7881
  return _c('g', {
@@ -6953,11 +7912,11 @@ var Subtaskvue_type_template_id_86599310_render = function render() {
6953
7912
  ..._vm.task.style['chart-row-bar']
6954
7913
  },
6955
7914
  attrs: {
6956
- "x": _vm.task.x,
7915
+ "x": _vm.task.x - 8,
6957
7916
  "y": _vm.task.y,
6958
- "width": _vm.task.width,
7917
+ "width": _vm.task.width + 16,
6959
7918
  "height": _vm.task.height,
6960
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
7919
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
6961
7920
  "xmlns": "http://www.w3.org/2000/svg"
6962
7921
  },
6963
7922
  on: {
@@ -7012,26 +7971,81 @@ var Subtaskvue_type_template_id_86599310_render = function render() {
7012
7971
  ..._vm.task.style['chart-row-bar-polygon']
7013
7972
  },
7014
7973
  attrs: {
7015
- "points": _vm.getPoints
7974
+ "points": _vm.getPointsAdjusted
7975
+ },
7976
+ on: {
7977
+ "mousedown": function ($event) {
7978
+ return _vm.startDrag($event, 'move');
7979
+ },
7980
+ "touchstart": function ($event) {
7981
+ return _vm.startDrag($event, 'move');
7982
+ }
7016
7983
  }
7017
7984
  }), _c('progress-bar', {
7018
7985
  attrs: {
7019
7986
  "task": _vm.task,
7020
7987
  "clip-path": 'url(#' + _vm.clipPathId + ')'
7021
7988
  }
7989
+ }), _c('rect', {
7990
+ staticClass: "gantt-elastic__chart-row-extend-handle",
7991
+ staticStyle: {
7992
+ "pointer-events": "all",
7993
+ "z-index": "20"
7994
+ },
7995
+ style: _vm.root.style['chart-row-extend-handle'],
7996
+ attrs: {
7997
+ "x": "8",
7998
+ "y": "0",
7999
+ "width": 8,
8000
+ "height": _vm.task.height
8001
+ },
8002
+ on: {
8003
+ "mousedown": function ($event) {
8004
+ $event.stopPropagation();
8005
+ return _vm.startDrag($event, 'start');
8006
+ },
8007
+ "touchstart": function ($event) {
8008
+ $event.stopPropagation();
8009
+ return _vm.startDrag($event, 'start');
8010
+ }
8011
+ }
8012
+ }), _c('rect', {
8013
+ staticClass: "gantt-elastic__chart-row-extend-handle",
8014
+ staticStyle: {
8015
+ "pointer-events": "all",
8016
+ "z-index": "20"
8017
+ },
8018
+ style: _vm.root.style['chart-row-extend-handle'],
8019
+ attrs: {
8020
+ "x": _vm.task.width - 8,
8021
+ "y": "0",
8022
+ "width": 8,
8023
+ "height": _vm.task.height
8024
+ },
8025
+ on: {
8026
+ "mousedown": function ($event) {
8027
+ $event.stopPropagation();
8028
+ return _vm.startDrag($event, 'end');
8029
+ },
8030
+ "touchstart": function ($event) {
8031
+ $event.stopPropagation();
8032
+ return _vm.startDrag($event, 'end');
8033
+ }
8034
+ }
7022
8035
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
7023
8036
  attrs: {
7024
8037
  "task": _vm.task
7025
8038
  }
7026
8039
  }) : _vm._e()], 1);
7027
8040
  };
7028
- var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
8041
+ var Subtaskvue_type_template_id_339b7174_staticRenderFns = [];
7029
8042
 
7030
8043
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
7031
8044
 
7032
8045
 
7033
8046
 
7034
8047
 
8048
+
7035
8049
  /* harmony default export */ var Subtaskvue_type_script_lang_js = ({
7036
8050
  name: 'Subtask',
7037
8051
  components: {
@@ -7041,7 +8055,7 @@ var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
7041
8055
  },
7042
8056
  inject: ['root'],
7043
8057
  props: ['task'],
7044
- mixins: [Task_mixin],
8058
+ mixins: [Task_mixin, Draggable_mixin],
7045
8059
  data() {
7046
8060
  return {};
7047
8061
  },
@@ -7063,6 +8077,15 @@ var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
7063
8077
  const task = this.task;
7064
8078
  return `0,0 ${task.width},0 ${task.width},${task.height} 0,${task.height}`;
7065
8079
  },
8080
+ /**
8081
+ * Get points adjusted for viewBox
8082
+ *
8083
+ * @returns {string}
8084
+ */
8085
+ getPointsAdjusted() {
8086
+ const task = this.task;
8087
+ return `8,0 ${task.width + 8},0 ${task.width + 8},${task.height} 8,${task.height}`;
8088
+ },
7066
8089
  /**
7067
8090
  * Should we display expander?
7068
8091
  *
@@ -7087,8 +8110,8 @@ var Subtaskvue_type_template_id_86599310_staticRenderFns = [];
7087
8110
  ;
7088
8111
  var Subtask_component = normalizeComponent(
7089
8112
  Row_Subtaskvue_type_script_lang_js,
7090
- Subtaskvue_type_template_id_86599310_render,
7091
- Subtaskvue_type_template_id_86599310_staticRenderFns,
8113
+ Subtaskvue_type_template_id_339b7174_render,
8114
+ Subtaskvue_type_template_id_339b7174_staticRenderFns,
7092
8115
  false,
7093
8116
  null,
7094
8117
  null,
@@ -7097,8 +8120,8 @@ var Subtask_component = normalizeComponent(
7097
8120
  )
7098
8121
 
7099
8122
  /* harmony default export */ var Subtask = (Subtask_component.exports);
7100
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
7101
- var Storyvue_type_template_id_1f59b61a_render = function render() {
8123
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
8124
+ var Storyvue_type_template_id_3d0395f2_render = function render() {
7102
8125
  var _vm = this,
7103
8126
  _c = _vm._self._c;
7104
8127
  return _c('g', {
@@ -7135,11 +8158,11 @@ var Storyvue_type_template_id_1f59b61a_render = function render() {
7135
8158
  ..._vm.task.style['chart-row-bar']
7136
8159
  },
7137
8160
  attrs: {
7138
- "x": _vm.task.x,
8161
+ "x": _vm.task.x - 8,
7139
8162
  "y": _vm.task.y,
7140
- "width": _vm.task.width,
8163
+ "width": _vm.task.width + 16,
7141
8164
  "height": _vm.task.height,
7142
- "viewBox": `0 0 ${_vm.task.width} ${_vm.task.height}`,
8165
+ "viewBox": `-8 0 ${_vm.task.width + 16} ${_vm.task.height}`,
7143
8166
  "xmlns": "http://www.w3.org/2000/svg"
7144
8167
  },
7145
8168
  on: {
@@ -7194,26 +8217,81 @@ var Storyvue_type_template_id_1f59b61a_render = function render() {
7194
8217
  ..._vm.task.style['chart-row-bar-polygon']
7195
8218
  },
7196
8219
  attrs: {
7197
- "d": _vm.getPoints
8220
+ "d": _vm.getPointsAdjusted
8221
+ },
8222
+ on: {
8223
+ "mousedown": function ($event) {
8224
+ return _vm.startDrag($event, 'move');
8225
+ },
8226
+ "touchstart": function ($event) {
8227
+ return _vm.startDrag($event, 'move');
8228
+ }
7198
8229
  }
7199
8230
  }), _c('progress-bar', {
7200
8231
  attrs: {
7201
8232
  "task": _vm.task,
7202
8233
  "clip-path": 'url(#' + _vm.clipPathId + ')'
7203
8234
  }
8235
+ }), _c('rect', {
8236
+ staticClass: "gantt-elastic__chart-row-extend-handle",
8237
+ staticStyle: {
8238
+ "pointer-events": "all",
8239
+ "z-index": "20"
8240
+ },
8241
+ style: _vm.root.style['chart-row-extend-handle'],
8242
+ attrs: {
8243
+ "x": "8",
8244
+ "y": "0",
8245
+ "width": 8,
8246
+ "height": _vm.task.height
8247
+ },
8248
+ on: {
8249
+ "mousedown": function ($event) {
8250
+ $event.stopPropagation();
8251
+ return _vm.startDrag($event, 'start');
8252
+ },
8253
+ "touchstart": function ($event) {
8254
+ $event.stopPropagation();
8255
+ return _vm.startDrag($event, 'start');
8256
+ }
8257
+ }
8258
+ }), _c('rect', {
8259
+ staticClass: "gantt-elastic__chart-row-extend-handle",
8260
+ staticStyle: {
8261
+ "pointer-events": "all",
8262
+ "z-index": "20"
8263
+ },
8264
+ style: _vm.root.style['chart-row-extend-handle'],
8265
+ attrs: {
8266
+ "x": _vm.task.width - 8,
8267
+ "y": "0",
8268
+ "width": 8,
8269
+ "height": _vm.task.height
8270
+ },
8271
+ on: {
8272
+ "mousedown": function ($event) {
8273
+ $event.stopPropagation();
8274
+ return _vm.startDrag($event, 'end');
8275
+ },
8276
+ "touchstart": function ($event) {
8277
+ $event.stopPropagation();
8278
+ return _vm.startDrag($event, 'end');
8279
+ }
8280
+ }
7204
8281
  })], 1), _vm.root.state.options.chart.text.display ? _c('chart-text', {
7205
8282
  attrs: {
7206
8283
  "task": _vm.task
7207
8284
  }
7208
8285
  }) : _vm._e()], 1);
7209
8286
  };
7210
- var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
8287
+ var Storyvue_type_template_id_3d0395f2_staticRenderFns = [];
7211
8288
 
7212
8289
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-83.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
7213
8290
 
7214
8291
 
7215
8292
 
7216
8293
 
8294
+
7217
8295
  /* harmony default export */ var Storyvue_type_script_lang_js = ({
7218
8296
  name: 'Story',
7219
8297
  components: {
@@ -7223,7 +8301,7 @@ var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
7223
8301
  },
7224
8302
  inject: ['root'],
7225
8303
  props: ['task'],
7226
- mixins: [Task_mixin],
8304
+ mixins: [Task_mixin, Draggable_mixin],
7227
8305
  data() {
7228
8306
  return {};
7229
8307
  },
@@ -7255,6 +8333,25 @@ var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
7255
8333
  Q 0 0 ${corner} 0
7256
8334
  Z`;
7257
8335
  },
8336
+ /**
8337
+ * Get points adjusted for viewBox
8338
+ *
8339
+ * @returns {string}
8340
+ */
8341
+ getPointsAdjusted() {
8342
+ const task = this.task;
8343
+ const corner = Math.min(task.height / 4, 8); // Rounded corners
8344
+ return `M ${8 + corner},0
8345
+ L ${8 + task.width - corner} 0
8346
+ Q ${8 + task.width} 0 ${8 + task.width} ${corner}
8347
+ L ${8 + task.width} ${task.height - corner}
8348
+ Q ${8 + task.width} ${task.height} ${8 + task.width - corner} ${task.height}
8349
+ L ${8 + corner} ${task.height}
8350
+ Q ${8} ${task.height} ${8} ${task.height - corner}
8351
+ L ${8} ${corner}
8352
+ Q ${8} 0 ${8 + corner} 0
8353
+ Z`;
8354
+ },
7258
8355
  /**
7259
8356
  * Should we display expander?
7260
8357
  *
@@ -7279,8 +8376,8 @@ var Storyvue_type_template_id_1f59b61a_staticRenderFns = [];
7279
8376
  ;
7280
8377
  var Story_component = normalizeComponent(
7281
8378
  Row_Storyvue_type_script_lang_js,
7282
- Storyvue_type_template_id_1f59b61a_render,
7283
- Storyvue_type_template_id_1f59b61a_staticRenderFns,
8379
+ Storyvue_type_template_id_3d0395f2_render,
8380
+ Storyvue_type_template_id_3d0395f2_staticRenderFns,
7284
8381
  false,
7285
8382
  null,
7286
8383
  null,
@@ -7330,6 +8427,42 @@ var Story_component = normalizeComponent(
7330
8427
  this.root.state.refs.chartGraph = this.$refs.chartGraph;
7331
8428
  this.root.state.refs.chartGraphSvg = this.$refs.chartGraphSvg;
7332
8429
  },
8430
+ methods: {
8431
+ /**
8432
+ * Handle task updated event
8433
+ *
8434
+ * @param {Object} updatedTask - Updated task data
8435
+ */
8436
+ handleTaskUpdated(updatedTask) {
8437
+ // Emit event to parent component
8438
+ this.$emit('task-updated', updatedTask);
8439
+
8440
+ // Update the task in the root state
8441
+ const taskIndex = this.root.state.tasks.findIndex(task => task.id === updatedTask.id);
8442
+ if (taskIndex !== -1) {
8443
+ // Update task data
8444
+ this.root.state.tasks[taskIndex].startTime = updatedTask.startTime;
8445
+ this.root.state.tasks[taskIndex].endTime = updatedTask.endTime;
8446
+ this.root.state.tasks[taskIndex].duration = updatedTask.duration;
8447
+
8448
+ // Update task position and width
8449
+ if (this.root && this.root.timeToPixelOffsetX) {
8450
+ this.root.state.tasks[taskIndex].x = this.root.timeToPixelOffsetX(updatedTask.startTime);
8451
+ this.root.state.tasks[taskIndex].width = this.root.timeToPixelOffsetX(updatedTask.endTime) - this.root.state.tasks[taskIndex].x;
8452
+ } else {
8453
+ // Fallback calculation if method is not available
8454
+ const timePerPixel = this.root.state.options.times.timePerPixel;
8455
+ if (timePerPixel > 0) {
8456
+ this.root.state.tasks[taskIndex].x = (updatedTask.startTime - this.root.state.options.times.firstTime) / timePerPixel;
8457
+ this.root.state.tasks[taskIndex].width = (updatedTask.endTime - updatedTask.startTime) / timePerPixel;
8458
+ }
8459
+ }
8460
+
8461
+ // Force update
8462
+ this.$forceUpdate();
8463
+ }
8464
+ }
8465
+ },
7333
8466
  computed: {
7334
8467
  /**
7335
8468
  * Get view box
@@ -7353,8 +8486,8 @@ var Story_component = normalizeComponent(
7353
8486
  ;
7354
8487
  var Chart_component = normalizeComponent(
7355
8488
  Chart_Chartvue_type_script_lang_js,
7356
- Chartvue_type_template_id_1d5eb6d6_render,
7357
- Chartvue_type_template_id_1d5eb6d6_staticRenderFns,
8489
+ Chartvue_type_template_id_2bc7fe5e_render,
8490
+ Chartvue_type_template_id_2bc7fe5e_staticRenderFns,
7358
8491
  false,
7359
8492
  null,
7360
8493
  null,
@@ -7443,6 +8576,15 @@ let ignoreScrollEvents = false;
7443
8576
  }
7444
8577
  },
7445
8578
  methods: {
8579
+ /**
8580
+ * Handle task updated event from chart
8581
+ *
8582
+ * @param {Object} updatedTask - Updated task data
8583
+ */
8584
+ handleTaskUpdated(updatedTask) {
8585
+ // Emit event to parent component
8586
+ this.$emit('task-updated', updatedTask);
8587
+ },
7446
8588
  /**
7447
8589
  * Emit event when mouse is moving inside main view
7448
8590
  */
@@ -7559,8 +8701,8 @@ let ignoreScrollEvents = false;
7559
8701
  ;
7560
8702
  var MainView_component = normalizeComponent(
7561
8703
  components_MainViewvue_type_script_lang_js,
7562
- MainViewvue_type_template_id_1a4b756c_render,
7563
- MainViewvue_type_template_id_1a4b756c_staticRenderFns,
8704
+ MainViewvue_type_template_id_33392d22_render,
8705
+ MainViewvue_type_template_id_33392d22_staticRenderFns,
7564
8706
  false,
7565
8707
  null,
7566
8708
  null,
@@ -7883,6 +9025,192 @@ function getStyle(fontSize = '12px', fontFamily = 'Arial, sans-serif') {
7883
9025
  'text-overflow': 'ellipsis',
7884
9026
  'max-width': '120px'
7885
9027
  },
9028
+ 'chart-row-resize-handle': {
9029
+ fill: 'rgba(59, 130, 246, 0.2)',
9030
+ stroke: 'rgba(59, 130, 246, 0.8)',
9031
+ 'stroke-width': '2',
9032
+ cursor: 'ew-resize',
9033
+ opacity: '0.3',
9034
+ transition: 'opacity 0.2s ease',
9035
+ 'pointer-events': 'all'
9036
+ },
9037
+ 'chart-row-resize-handle--start': {
9038
+ cursor: 'w-resize',
9039
+ fill: 'rgba(34, 197, 94, 0.3)',
9040
+ stroke: 'rgba(34, 197, 94, 0.9)',
9041
+ 'stroke-width': '2'
9042
+ },
9043
+ 'chart-row-resize-handle--end': {
9044
+ cursor: 'e-resize',
9045
+ fill: 'rgba(239, 68, 68, 0.4)',
9046
+ stroke: 'rgba(239, 68, 68, 1)',
9047
+ 'stroke-width': '2'
9048
+ },
9049
+ 'chart-row-bar-wrapper:hover .chart-row-resize-handle': {
9050
+ opacity: '0.8'
9051
+ },
9052
+ 'chart-row-resize-handle:hover': {
9053
+ opacity: '1',
9054
+ fill: 'rgba(59, 130, 246, 0.4)',
9055
+ stroke: 'rgba(59, 130, 246, 1)'
9056
+ },
9057
+ 'chart-row-resize-handle--start:hover': {
9058
+ fill: 'rgba(34, 197, 94, 0.4)',
9059
+ stroke: 'rgba(34, 197, 94, 1)'
9060
+ },
9061
+ 'chart-row-resize-handle--end:hover': {
9062
+ fill: 'rgba(239, 68, 68, 0.5)',
9063
+ stroke: 'rgba(239, 68, 68, 1)',
9064
+ 'stroke-width': '3'
9065
+ },
9066
+ 'chart-row-resize-handle--corner': {
9067
+ fill: 'rgba(147, 51, 234, 0.6)',
9068
+ stroke: 'rgba(147, 51, 234, 1)',
9069
+ 'stroke-width': '2',
9070
+ cursor: 'nw-resize',
9071
+ opacity: '0.9',
9072
+ transition: 'opacity 0.2s ease',
9073
+ 'pointer-events': 'all'
9074
+ },
9075
+ 'chart-row-resize-handle--corner:hover': {
9076
+ fill: 'rgba(147, 51, 234, 0.8)',
9077
+ stroke: 'rgba(147, 51, 234, 1)',
9078
+ 'stroke-width': '3',
9079
+ opacity: '1'
9080
+ },
9081
+ 'chart-row-resize-handle--corner--start': {
9082
+ fill: 'rgba(34, 197, 94, 0.7)',
9083
+ stroke: 'rgba(34, 197, 94, 1)',
9084
+ 'stroke-width': '2',
9085
+ cursor: 'w-resize'
9086
+ },
9087
+ 'chart-row-resize-handle--corner--end': {
9088
+ fill: 'rgba(239, 68, 68, 0.7)',
9089
+ stroke: 'rgba(239, 68, 68, 1)',
9090
+ 'stroke-width': '2',
9091
+ cursor: 'e-resize'
9092
+ },
9093
+ 'chart-row-corner-handle--start': {
9094
+ fill: 'rgba(34, 197, 94, 0.8)',
9095
+ stroke: 'rgba(34, 197, 94, 1)',
9096
+ 'stroke-width': '2',
9097
+ cursor: 'w-resize',
9098
+ opacity: '0.9',
9099
+ transition: 'opacity 0.2s ease',
9100
+ 'pointer-events': 'all'
9101
+ },
9102
+ 'chart-row-corner-handle--end': {
9103
+ fill: 'rgba(239, 68, 68, 0.8)',
9104
+ stroke: 'rgba(239, 68, 68, 1)',
9105
+ 'stroke-width': '2',
9106
+ cursor: 'e-resize',
9107
+ opacity: '0.9',
9108
+ transition: 'opacity 0.2s ease',
9109
+ 'pointer-events': 'all'
9110
+ },
9111
+ 'chart-row-corner-handle--start:hover': {
9112
+ fill: 'rgba(34, 197, 94, 0.5)',
9113
+ stroke: 'rgba(34, 197, 94, 1)',
9114
+ 'stroke-width': '2',
9115
+ opacity: '0.9'
9116
+ },
9117
+ 'chart-row-corner-handle--end:hover': {
9118
+ fill: 'rgba(239, 68, 68, 0.5)',
9119
+ stroke: 'rgba(239, 68, 68, 1)',
9120
+ 'stroke-width': '2',
9121
+ opacity: '0.9'
9122
+ },
9123
+ 'chart-row-extend-handle': {
9124
+ fill: 'rgba(255, 255, 255, 0.1)',
9125
+ stroke: 'rgba(255, 255, 255, 0.3)',
9126
+ 'stroke-width': '1',
9127
+ cursor: 'ew-resize',
9128
+ opacity: '0.3',
9129
+ transition: 'opacity 0.2s ease',
9130
+ 'pointer-events': 'all',
9131
+ 'z-index': '10'
9132
+ },
9133
+ 'chart-row-extend-handle:hover': {
9134
+ fill: 'rgba(255, 255, 255, 0.2)',
9135
+ stroke: 'rgba(255, 255, 255, 0.6)',
9136
+ 'stroke-width': '2',
9137
+ opacity: '0.8'
9138
+ },
9139
+ 'chart-row-expand-icon-bg': {
9140
+ fill: 'rgba(255, 255, 255, 0.95)',
9141
+ stroke: 'rgba(0, 0, 0, 0.5)',
9142
+ 'stroke-width': '1.5',
9143
+ cursor: 'ew-resize',
9144
+ opacity: '1',
9145
+ transition: 'opacity 0.2s ease',
9146
+ 'pointer-events': 'all'
9147
+ },
9148
+ 'chart-row-expand-icon-arrow': {
9149
+ fill: 'rgba(0, 0, 0, 0.9)',
9150
+ cursor: 'ew-resize',
9151
+ 'pointer-events': 'all'
9152
+ },
9153
+ 'chart-row-expand-icon:hover .gantt-elastic__chart-row-expand-icon-bg': {
9154
+ fill: 'rgba(255, 255, 255, 1)',
9155
+ stroke: 'rgba(0, 0, 0, 0.5)',
9156
+ 'stroke-width': '1.5',
9157
+ opacity: '1'
9158
+ },
9159
+ 'chart-row-expand-icon:hover .gantt-elastic__chart-row-expand-icon-arrow': {
9160
+ fill: 'rgba(0, 0, 0, 1)'
9161
+ },
9162
+ 'gantt-elastic__task-dragging': {
9163
+ opacity: '0.8',
9164
+ 'pointer-events': 'none',
9165
+ 'filter': 'drop-shadow(0 4px 8px rgba(0, 0, 0, 0.2))'
9166
+ },
9167
+ 'gantt-elastic__task-dragging--start': {
9168
+ 'border-left': '3px solid #22c55e',
9169
+ 'box-shadow': 'inset 3px 0 0 #22c55e'
9170
+ },
9171
+ 'gantt-elastic__task-dragging--end': {
9172
+ 'border-right': '3px solid #ef4444',
9173
+ 'box-shadow': 'inset -3px 0 0 #ef4444'
9174
+ },
9175
+ 'gantt-elastic__task-dragging--move': {
9176
+ 'border': '2px solid #3b82f6',
9177
+ 'box-shadow': '0 0 0 2px rgba(59, 130, 246, 0.3)'
9178
+ },
9179
+ 'gantt-elastic__context-menu': {
9180
+ 'position': 'fixed',
9181
+ 'background': 'white',
9182
+ 'border': '1px solid #e5e7eb',
9183
+ 'border-radius': '6px',
9184
+ 'box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
9185
+ 'z-index': '1000',
9186
+ 'min-width': '150px',
9187
+ 'padding': '4px 0',
9188
+ 'font-family': 'system-ui, -apple-system, sans-serif'
9189
+ },
9190
+ 'gantt-elastic__context-menu-item': {
9191
+ 'padding': '8px 16px',
9192
+ 'cursor': 'pointer',
9193
+ 'font-size': '14px',
9194
+ 'color': '#374151',
9195
+ 'transition': 'background-color 0.2s',
9196
+ 'user-select': 'none'
9197
+ },
9198
+ 'gantt-elastic__context-menu-item:hover': {
9199
+ 'background-color': '#f3f4f6'
9200
+ },
9201
+ 'gantt-elastic__date-tooltip': {
9202
+ 'position': 'fixed',
9203
+ 'background': 'rgba(0, 0, 0, 0.8)',
9204
+ 'color': 'white',
9205
+ 'padding': '4px 8px',
9206
+ 'border-radius': '4px',
9207
+ 'font-size': '12px',
9208
+ 'font-family': 'system-ui, -apple-system, sans-serif',
9209
+ 'pointer-events': 'none',
9210
+ 'z-index': '10000',
9211
+ 'white-space': 'nowrap',
9212
+ 'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.2)'
9213
+ },
7886
9214
  'chart-row-text-content--text': {},
7887
9215
  'chart-row-text-content--html': {},
7888
9216
  'chart-row-wrapper': {},
@@ -10074,6 +11402,23 @@ const GanttElastic = {
10074
11402
  }
10075
11403
  });
10076
11404
  },
11405
+ /**
11406
+ * Handle task updated event from dragging
11407
+ *
11408
+ * @param {Object} updatedTask - Updated task data
11409
+ */
11410
+ handleTaskUpdated(updatedTask) {
11411
+ // Emit event to parent component
11412
+ this.$emit('task-updated', updatedTask);
11413
+
11414
+ // Log the update for debugging
11415
+ console.log('Task updated:', updatedTask);
11416
+
11417
+ // You can add additional logic here like:
11418
+ // - Save to backend
11419
+ // - Update local storage
11420
+ // - Trigger other updates
11421
+ },
10077
11422
  /**
10078
11423
  * Calculate height of scrollbar in current browser
10079
11424
  *
@@ -10426,7 +11771,18 @@ const GanttElastic = {
10426
11771
  * @returns {number}
10427
11772
  */
10428
11773
  getHeight(visibleTasks, outer = false) {
10429
- 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;
11774
+ let height;
11775
+
11776
+ // If we have tasks, use their actual height for full grid
11777
+ if (visibleTasks.length > 0) {
11778
+ 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;
11779
+ } else {
11780
+ // If no tasks, use 70% of viewport height for empty state
11781
+ const viewportHeight = window.innerHeight;
11782
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
11783
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
11784
+ height = Math.max(availableHeight, 300); // Minimum 300px height
11785
+ }
10430
11786
  if (outer) {
10431
11787
  height += this.state.options.scrollBarHeight;
10432
11788
  }
@@ -10449,7 +11805,20 @@ const GanttElastic = {
10449
11805
  * @returns {number}
10450
11806
  */
10451
11807
  getTasksHeight(visibleTasks) {
10452
- return visibleTasks.length * this.getTaskHeight();
11808
+ const taskHeight = visibleTasks.length * this.getTaskHeight();
11809
+
11810
+ // If we have tasks, use their actual height for full grid
11811
+ if (visibleTasks.length > 0) {
11812
+ return taskHeight;
11813
+ }
11814
+
11815
+ // If no tasks, use 70% of viewport height for empty state
11816
+ const viewportHeight = window.innerHeight;
11817
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
11818
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
11819
+ const reducedHeight = Math.max(availableHeight, 300); // Minimum 300px height
11820
+
11821
+ return reducedHeight;
10453
11822
  },
10454
11823
  /**
10455
11824
  * Convert time (in milliseconds) to pixel offset inside chart
@@ -10756,15 +12125,15 @@ const GanttElastic = {
10756
12125
  getMaxWidthMultiplier(stepDuration, stepCount) {
10757
12126
  const clientWidth = this.state.options.clientWidth;
10758
12127
 
10759
- // Base multipliers for different screen sizes
12128
+ // Base multipliers for different screen sizes (reduced for better balance)
10760
12129
  const baseMultipliers = {
10761
- mobile: 2,
10762
- // 2x viewport width on mobile
10763
- tablet: 2.5,
10764
- // 2.5x viewport width on tablet
10765
- desktopSmall: 3,
10766
- // 3x viewport width on small desktop
10767
- desktopBig: 4 // 4x viewport width on big desktop
12130
+ mobile: 1.5,
12131
+ // 1.5x viewport width on mobile
12132
+ tablet: 1.8,
12133
+ // 1.8x viewport width on tablet
12134
+ desktopSmall: 2.2,
12135
+ // 2.2x viewport width on small desktop
12136
+ desktopBig: 2.5 // 2.5x viewport width on big desktop
10768
12137
  };
10769
12138
 
10770
12139
  // Determine screen size
@@ -10791,7 +12160,7 @@ const GanttElastic = {
10791
12160
  // If we have more data than minimum visibility, allow more width
10792
12161
  if (stepCount > minVisibilitySteps[stepDuration]) {
10793
12162
  const dataRatio = stepCount / minVisibilitySteps[stepDuration];
10794
- multiplier = Math.min(multiplier * (1 + dataRatio * 0.5), 6); // Max 6x viewport width
12163
+ multiplier = Math.min(multiplier * (1 + dataRatio * 0.3), 3); // Max 3x viewport width
10795
12164
  }
10796
12165
  return multiplier;
10797
12166
  },
@@ -10892,7 +12261,7 @@ const GanttElastic = {
10892
12261
  const maxWidth = this.state.options.clientWidth * maxWidthMultiplier;
10893
12262
 
10894
12263
  // Ensure minimum width for scrolling when we have minimum visibility requirements
10895
- const minWidthForScrolling = this.state.options.clientWidth * 1.2; // 20% more than viewport
12264
+ const minWidthForScrolling = this.state.options.clientWidth * 1.1; // 10% more than viewport
10896
12265
  const finalWidth = Math.max(calculatedWidth, minWidthForScrolling);
10897
12266
  if (finalWidth > maxWidth) {
10898
12267
  // Only limit width if it's truly excessive
@@ -11182,6 +12551,29 @@ const GanttElastic = {
11182
12551
  width: 0
11183
12552
  }).width;
11184
12553
  },
12554
+ /**
12555
+ * Recalculate height based on current tasks and viewport
12556
+ */
12557
+ recalculateHeight() {
12558
+ const visibleTasks = this.state.tasks.filter(task => this.isTaskVisible(task));
12559
+ if (visibleTasks.length > 0) {
12560
+ // Use full task height for complete grid
12561
+ this.state.options.rowsHeight = this.getTasksHeight(visibleTasks);
12562
+ this.state.options.height = this.getHeight(visibleTasks);
12563
+ this.state.options.allVisibleTasksHeight = this.getTasksHeight(visibleTasks);
12564
+ this.state.options.outerHeight = this.getHeight(visibleTasks, true);
12565
+ } else {
12566
+ // Use reduced viewport height for empty state
12567
+ const viewportHeight = window.innerHeight;
12568
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
12569
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40;
12570
+ const reducedHeight = Math.max(availableHeight, 300);
12571
+ this.state.options.rowsHeight = reducedHeight;
12572
+ this.state.options.height = reducedHeight + this.state.options.calendar.height + this.state.options.calendar.gap;
12573
+ this.state.options.allVisibleTasksHeight = reducedHeight;
12574
+ this.state.options.outerHeight = this.state.options.height + this.state.options.scrollBarHeight;
12575
+ }
12576
+ },
11185
12577
  /**
11186
12578
  * Global resize event (from window.addEventListener)
11187
12579
  */
@@ -11190,6 +12582,15 @@ const GanttElastic = {
11190
12582
  return;
11191
12583
  }
11192
12584
  this.state.options.clientWidth = this.$el.clientWidth;
12585
+
12586
+ // Only set height if no tasks are present (let visibleTasks computed property handle height when tasks exist)
12587
+ if (this.state.tasks.length === 0) {
12588
+ // Set height to 70% of viewport height for better balance when no tasks
12589
+ const viewportHeight = window.innerHeight;
12590
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
12591
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40; // 70% of viewport, 40px for padding/margins
12592
+ this.state.options.height = Math.max(availableHeight, 300); // Minimum 300px height
12593
+ }
11193
12594
  if (this.state.options.taskList.widthFromPercentage > this.state.options.clientWidth / 100 * this.state.options.taskList.widthThreshold) {
11194
12595
  const diff = this.state.options.taskList.widthFromPercentage - this.state.options.clientWidth / 100 * this.state.options.taskList.widthThreshold;
11195
12596
  let diffPercent = 100 - diff / this.state.options.taskList.widthFromPercentage * 100;
@@ -11212,6 +12613,9 @@ const GanttElastic = {
11212
12613
  this.computeCalendarWidths();
11213
12614
  this.$emit('calendar-recalculate');
11214
12615
  this.syncScrollTop();
12616
+
12617
+ // Recalculate height after resize
12618
+ this.recalculateHeight();
11215
12619
  }
11216
12620
  },
11217
12621
  computed: {
@@ -11222,16 +12626,17 @@ const GanttElastic = {
11222
12626
  */
11223
12627
  visibleTasks() {
11224
12628
  const visibleTasks = this.state.tasks.filter(task => this.isTaskVisible(task));
11225
- const maxRows = visibleTasks.slice(0, this.state.options.maxRows);
11226
- this.state.options.rowsHeight = this.getTasksHeight(maxRows);
12629
+
12630
+ // Use full visible tasks for height calculations to show complete grid
12631
+ this.state.options.rowsHeight = this.getTasksHeight(visibleTasks);
11227
12632
  let heightCompensation = 0;
11228
12633
  if (this.state.options.maxHeight && this.state.options.rowsHeight > this.state.options.maxHeight) {
11229
12634
  heightCompensation = this.state.options.rowsHeight - this.state.options.maxHeight;
11230
12635
  this.state.options.rowsHeight = this.state.options.maxHeight;
11231
12636
  }
11232
- this.state.options.height = this.getHeight(maxRows) - heightCompensation;
12637
+ this.state.options.height = this.getHeight(visibleTasks) - heightCompensation;
11233
12638
  this.state.options.allVisibleTasksHeight = this.getTasksHeight(visibleTasks);
11234
- this.state.options.outerHeight = this.getHeight(maxRows, true) - heightCompensation;
12639
+ this.state.options.outerHeight = this.getHeight(visibleTasks, true) - heightCompensation;
11235
12640
  let len = visibleTasks.length;
11236
12641
  for (let index = 0; index < len; index++) {
11237
12642
  let task = visibleTasks[index];
@@ -11282,6 +12687,10 @@ const GanttElastic = {
11282
12687
  if (notEqual) {
11283
12688
  this.setup('tasks');
11284
12689
  }
12690
+ // Recalculate height when tasks change
12691
+ this.$nextTick(() => {
12692
+ this.recalculateHeight();
12693
+ });
11285
12694
  }, {
11286
12695
  deep: true
11287
12696
  });
@@ -11331,11 +12740,23 @@ const GanttElastic = {
11331
12740
  */
11332
12741
  mounted() {
11333
12742
  this.state.options.clientWidth = this.$el.clientWidth;
12743
+
12744
+ // Set initial height based on whether tasks exist
12745
+ if (this.state.tasks.length === 0) {
12746
+ const viewportHeight = window.innerHeight;
12747
+ const headerHeight = this.state.options.calendar.height + this.state.options.calendar.gap;
12748
+ const availableHeight = viewportHeight * 0.7 - headerHeight - 40;
12749
+ this.state.options.height = Math.max(availableHeight, 300);
12750
+ }
11334
12751
  this.state.resizeObserver = new ResizeObserver_es((entries, observer) => {
11335
12752
  this.globalOnResize();
11336
12753
  });
11337
12754
  this.state.resizeObserver.observe(this.$el.parentNode);
12755
+
12756
+ // Add window resize listener for full viewport responsiveness
12757
+ window.addEventListener('resize', this.globalOnResize);
11338
12758
  this.globalOnResize();
12759
+ this.recalculateHeight();
11339
12760
  this.$emit('ready', this);
11340
12761
  this.$root.$emit('gantt-elastic-mounted', this);
11341
12762
  this.$emit('mounted', this);
@@ -11360,6 +12781,7 @@ const GanttElastic = {
11360
12781
  */
11361
12782
  beforeDestroy() {
11362
12783
  this.state.resizeObserver.unobserve(this.$el.parentNode);
12784
+ window.removeEventListener('resize', this.globalOnResize);
11363
12785
  this.state.unwatchTasks();
11364
12786
  this.state.unwatchOptions();
11365
12787
  this.state.unwatchStyle();
@@ -11378,10 +12800,10 @@ const GanttElastic = {
11378
12800
  /* harmony default export */ var GanttElasticvue_type_script_lang_js = (GanttElastic);
11379
12801
  ;// ./src/GanttElastic.vue?vue&type=script&lang=js
11380
12802
  /* harmony default export */ var src_GanttElasticvue_type_script_lang_js = (GanttElasticvue_type_script_lang_js);
11381
- ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-55.use[0]!./node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??clonedRuleSet-55.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-55.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
12803
+ ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-55.use[0]!./node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??clonedRuleSet-55.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-55.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
11382
12804
  // extracted by mini-css-extract-plugin
11383
12805
 
11384
- ;// ./src/GanttElastic.vue?vue&type=style&index=0&id=2767341e&prod&lang=css
12806
+ ;// ./src/GanttElastic.vue?vue&type=style&index=0&id=100984c8&prod&lang=css
11385
12807
 
11386
12808
  ;// ./src/GanttElastic.vue
11387
12809
 
@@ -11394,8 +12816,8 @@ const GanttElastic = {
11394
12816
 
11395
12817
  var GanttElastic_component = normalizeComponent(
11396
12818
  src_GanttElasticvue_type_script_lang_js,
11397
- GanttElasticvue_type_template_id_2767341e_render,
11398
- GanttElasticvue_type_template_id_2767341e_staticRenderFns,
12819
+ GanttElasticvue_type_template_id_100984c8_render,
12820
+ GanttElasticvue_type_template_id_100984c8_staticRenderFns,
11399
12821
  false,
11400
12822
  null,
11401
12823
  null,