@progress/kendo-angular-gantt 0.3.0-dev.202201111723 → 0.3.0-dev.202201131518
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.
- package/dist/cdn/js/kendo-angular-gantt.js +2 -2
- package/dist/cdn/main.js +4 -10
- package/dist/es/common/touch-enabled.js +9 -0
- package/dist/es/dependencies/utils.js +34 -0
- package/dist/es/dragging/dependency-drag-create.directive.js +347 -0
- package/dist/es/dragging/drag-validation-tooltip.component.js +27 -0
- package/dist/es/editing/{util.js → utils.js} +0 -0
- package/dist/es/gantt.component.js +125 -7
- package/dist/es/gantt.module.js +23 -6
- package/dist/es/index.js +4 -0
- package/dist/es/main.js +1 -0
- package/dist/es/models/events/dependency-add-event.interface.js +4 -0
- package/dist/es/models/view-item.interface.js +4 -0
- package/dist/es/package-metadata.js +1 -1
- package/dist/es/rendering/gantt-milestone-task.component.js +7 -4
- package/dist/es/rendering/gantt-summary-task.component.js +7 -4
- package/dist/es/rendering/gantt-task-base.js +30 -19
- package/dist/es/rendering/gantt-task.component.js +8 -6
- package/dist/es/rendering/gantt-tasks-table-body.component.js +5 -1
- package/dist/es/scrolling/drag-scroll-settings.js +20 -0
- package/dist/es/scrolling/timeline-scroll.directive.js +89 -0
- package/dist/es/scrolling/timeline-scroll.service.js +39 -0
- package/dist/es/scrolling/utils.js +80 -0
- package/dist/es/timeline/gantt-timeline.component.js +45 -3
- package/dist/es/utils.js +143 -12
- package/dist/es2015/common/touch-enabled.d.ts +9 -0
- package/dist/es2015/common/touch-enabled.js +9 -0
- package/dist/es2015/dependencies/utils.d.ts +15 -0
- package/dist/es2015/dependencies/utils.js +34 -0
- package/dist/es2015/dragging/dependency-drag-create.directive.d.ts +72 -0
- package/dist/es2015/dragging/dependency-drag-create.directive.js +324 -0
- package/dist/es2015/dragging/drag-validation-tooltip.component.d.ts +29 -0
- package/dist/es2015/dragging/drag-validation-tooltip.component.js +76 -0
- package/dist/es2015/editing/{util.d.ts → utils.d.ts} +0 -0
- package/dist/es2015/editing/{util.js → utils.js} +0 -0
- package/dist/es2015/gantt.component.d.ts +39 -3
- package/dist/es2015/gantt.component.js +117 -6
- package/dist/es2015/gantt.module.js +23 -6
- package/dist/es2015/index.d.ts +4 -0
- package/dist/es2015/index.js +4 -0
- package/dist/es2015/index.metadata.json +1 -1
- package/dist/es2015/main.d.ts +1 -0
- package/dist/es2015/main.js +1 -0
- package/dist/es2015/models/events/dependency-add-event.interface.d.ts +26 -0
- package/dist/es2015/models/events/dependency-add-event.interface.js +4 -0
- package/dist/es2015/models/models.d.ts +2 -0
- package/dist/es2015/models/view-item.interface.d.ts +35 -0
- package/dist/es2015/models/view-item.interface.js +4 -0
- package/dist/es2015/package-metadata.js +1 -1
- package/dist/es2015/rendering/gantt-milestone-task.component.d.ts +2 -1
- package/dist/es2015/rendering/gantt-milestone-task.component.js +18 -5
- package/dist/es2015/rendering/gantt-summary-task.component.d.ts +2 -1
- package/dist/es2015/rendering/gantt-summary-task.component.js +18 -5
- package/dist/es2015/rendering/gantt-task-base.d.ts +11 -5
- package/dist/es2015/rendering/gantt-task-base.js +30 -19
- package/dist/es2015/rendering/gantt-task.component.d.ts +2 -1
- package/dist/es2015/rendering/gantt-task.component.js +19 -7
- package/dist/es2015/rendering/gantt-tasks-table-body.component.d.ts +1 -0
- package/dist/es2015/rendering/gantt-tasks-table-body.component.js +10 -3
- package/dist/es2015/scrolling/drag-scroll-settings.d.ts +47 -0
- package/dist/es2015/scrolling/drag-scroll-settings.js +20 -0
- package/dist/es2015/scrolling/timeline-scroll.directive.d.ts +24 -0
- package/dist/es2015/scrolling/timeline-scroll.directive.js +78 -0
- package/dist/es2015/scrolling/timeline-scroll.service.d.ts +20 -0
- package/dist/es2015/scrolling/timeline-scroll.service.js +44 -0
- package/dist/es2015/scrolling/utils.d.ts +29 -0
- package/dist/es2015/scrolling/utils.js +80 -0
- package/dist/es2015/timeline/gantt-timeline.component.d.ts +25 -2
- package/dist/es2015/timeline/gantt-timeline.component.js +56 -3
- package/dist/es2015/utils.d.ts +70 -8
- package/dist/es2015/utils.js +143 -12
- package/dist/fesm2015/index.js +1337 -372
- package/dist/fesm5/index.js +1206 -298
- package/dist/npm/common/touch-enabled.js +11 -0
- package/dist/npm/dependencies/utils.js +34 -0
- package/dist/npm/dragging/dependency-drag-create.directive.js +349 -0
- package/dist/npm/dragging/drag-validation-tooltip.component.js +29 -0
- package/dist/npm/editing/{util.js → utils.js} +0 -0
- package/dist/npm/gantt.component.js +127 -9
- package/dist/npm/gantt.module.js +22 -5
- package/dist/npm/index.js +8 -0
- package/dist/npm/main.js +2 -0
- package/dist/npm/models/events/dependency-add-event.interface.js +6 -0
- package/dist/npm/models/view-item.interface.js +6 -0
- package/dist/npm/package-metadata.js +1 -1
- package/dist/npm/rendering/gantt-milestone-task.component.js +6 -3
- package/dist/npm/rendering/gantt-summary-task.component.js +6 -3
- package/dist/npm/rendering/gantt-task-base.js +30 -19
- package/dist/npm/rendering/gantt-task.component.js +7 -5
- package/dist/npm/rendering/gantt-tasks-table-body.component.js +5 -1
- package/dist/npm/scrolling/drag-scroll-settings.js +22 -0
- package/dist/npm/scrolling/timeline-scroll.directive.js +91 -0
- package/dist/npm/scrolling/timeline-scroll.service.js +41 -0
- package/dist/npm/scrolling/utils.js +83 -0
- package/dist/npm/timeline/gantt-timeline.component.js +44 -2
- package/dist/npm/utils.js +143 -12
- package/dist/systemjs/kendo-angular-gantt.js +1 -1
- package/package.json +5 -4
package/dist/fesm2015/index.js
CHANGED
|
@@ -3,25 +3,26 @@
|
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
5
|
import { __decorate, __metadata, __param } from 'tslib';
|
|
6
|
-
import { Input, EventEmitter, Injectable, Directive, Optional, TemplateRef, QueryList, ContentChildren, ContentChild, Component, forwardRef, SkipSelf, Host, Injector, NgZone,
|
|
6
|
+
import { Input, EventEmitter, Injectable, Directive, Optional, TemplateRef, QueryList, ContentChildren, ContentChild, Component, forwardRef, SkipSelf, Host, Injector, NgZone, ViewChild, ElementRef, ViewContainerRef, HostBinding, Output, Renderer2, isDevMode, InjectionToken, Inject, ChangeDetectorRef, NgModule } from '@angular/core';
|
|
7
7
|
import { ColumnBase, ColumnComponent, ColumnGroupComponent, SpanColumnComponent, TreeListComponent, DataBoundTreeComponent, ExpandableTreeComponent, FlatBindingDirective, HierarchyBindingDirective, ExpandableDirective, TreeListModule } from '@progress/kendo-angular-treelist';
|
|
8
8
|
import { cloneDate, addWeeks, firstDayInWeek, addDays, getDate, lastDayOfMonth, firstDayOfMonth, addMonths, isEqual, MS_PER_HOUR, MS_PER_DAY } from '@progress/kendo-date-math';
|
|
9
9
|
import { of, Subject, Subscription, fromEvent, forkJoin, EMPTY, isObservable } from 'rxjs';
|
|
10
10
|
import { validatePackage } from '@progress/kendo-licensing';
|
|
11
|
-
import {
|
|
11
|
+
import { closestInScope, matchesClasses, isDocumentAvailable, anyChanged, hasObservers, EventsModule, DraggableModule } from '@progress/kendo-angular-common';
|
|
12
|
+
import { LocalizationService, ComponentMessages, L10N_PREFIX } from '@progress/kendo-angular-l10n';
|
|
12
13
|
import { IntlService } from '@progress/kendo-angular-intl';
|
|
13
14
|
import { orderBy } from '@progress/kendo-data-query';
|
|
14
|
-
import { getter } from '@progress/kendo-common';
|
|
15
|
+
import { getter, touchEnabled } from '@progress/kendo-common';
|
|
15
16
|
import { map, distinctUntilChanged, take, expand, reduce, filter, switchMap } from 'rxjs/operators';
|
|
16
|
-
import { LocalizationService, ComponentMessages, L10N_PREFIX } from '@progress/kendo-angular-l10n';
|
|
17
17
|
import { CommonModule } from '@angular/common';
|
|
18
|
+
import { FormArray, FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
18
19
|
import { SplitterModule, TabStripModule } from '@progress/kendo-angular-layout';
|
|
19
20
|
import { ButtonsModule } from '@progress/kendo-angular-buttons';
|
|
20
21
|
import { DialogModule } from '@progress/kendo-angular-dialog';
|
|
21
|
-
import { FormArray, FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
22
22
|
import { LabelModule } from '@progress/kendo-angular-label';
|
|
23
23
|
import { InputsModule } from '@progress/kendo-angular-inputs';
|
|
24
24
|
import { DateInputsModule } from '@progress/kendo-angular-dateinputs';
|
|
25
|
+
import { PopupService, PopupModule } from '@progress/kendo-angular-popup';
|
|
25
26
|
import { GridModule } from '@progress/kendo-angular-grid';
|
|
26
27
|
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
|
|
27
28
|
|
|
@@ -32,7 +33,7 @@ const packageMetadata = {
|
|
|
32
33
|
name: '@progress/kendo-angular-gantt',
|
|
33
34
|
productName: 'Kendo UI for Angular',
|
|
34
35
|
productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
|
|
35
|
-
publishDate:
|
|
36
|
+
publishDate: 1642086647,
|
|
36
37
|
version: '',
|
|
37
38
|
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
|
|
38
39
|
};
|
|
@@ -634,6 +635,60 @@ const taskClassCallback = () => null;
|
|
|
634
635
|
*/
|
|
635
636
|
const isSelected = () => false;
|
|
636
637
|
|
|
638
|
+
/**
|
|
639
|
+
* The dependency type when two tasks are connected.
|
|
640
|
+
*
|
|
641
|
+
* The supported values are:
|
|
642
|
+
* * `FF`—from 'finish' to 'finish'
|
|
643
|
+
* * `FS`—from 'finish' to 'start'
|
|
644
|
+
* * `SS`—from 'start' to 'start'
|
|
645
|
+
* * `SF`—from 'start' to 'finish'
|
|
646
|
+
*/
|
|
647
|
+
var DependencyType;
|
|
648
|
+
(function (DependencyType) {
|
|
649
|
+
DependencyType[DependencyType["FF"] = 0] = "FF";
|
|
650
|
+
DependencyType[DependencyType["FS"] = 1] = "FS";
|
|
651
|
+
DependencyType[DependencyType["SF"] = 2] = "SF";
|
|
652
|
+
DependencyType[DependencyType["SS"] = 3] = "SS"; // task B can't start before task A starts
|
|
653
|
+
})(DependencyType || (DependencyType = {}));
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* @hidden
|
|
657
|
+
*/
|
|
658
|
+
class PreventableEvent {
|
|
659
|
+
constructor() {
|
|
660
|
+
this.prevented = false;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Prevents the default action for a specified event.
|
|
664
|
+
* In this way, the source component suppresses
|
|
665
|
+
* the built-in behavior that follows the event.
|
|
666
|
+
*/
|
|
667
|
+
preventDefault() {
|
|
668
|
+
this.prevented = true;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Returns `true` if the event was prevented
|
|
672
|
+
* by any of its subscribers.
|
|
673
|
+
*
|
|
674
|
+
* @returns `true` if the default action was prevented.
|
|
675
|
+
* Otherwise, returns `false`.
|
|
676
|
+
*/
|
|
677
|
+
isDefaultPrevented() {
|
|
678
|
+
return this.prevented;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Called every time a user leaves an edited cell.
|
|
684
|
+
*/
|
|
685
|
+
class CellCloseEvent extends PreventableEvent {
|
|
686
|
+
constructor(options) {
|
|
687
|
+
super();
|
|
688
|
+
Object.assign(this, options);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
637
692
|
/**
|
|
638
693
|
* @hidden
|
|
639
694
|
*/
|
|
@@ -733,15 +788,34 @@ const isNumber = (contender) => typeof contender === 'number' && !isNaN(contende
|
|
|
733
788
|
* @hidden
|
|
734
789
|
*/
|
|
735
790
|
const isString = (contender) => typeof contender === 'string';
|
|
791
|
+
/**
|
|
792
|
+
* @hidden
|
|
793
|
+
*
|
|
794
|
+
* Gets the closest timeline task wrapper element from an event target.
|
|
795
|
+
* Restricts the search up to the provided parent element from the second param.
|
|
796
|
+
*/
|
|
797
|
+
const getClosestTaskWrapper = (element, parentScope) => {
|
|
798
|
+
return closestInScope(element, matchesClasses('k-task-wrap'), parentScope);
|
|
799
|
+
};
|
|
800
|
+
/**
|
|
801
|
+
* @hidden
|
|
802
|
+
*
|
|
803
|
+
* Checks whether the queried item or its parent items has a `k-task-wrap` selector.
|
|
804
|
+
* Restricts the search up to the provided parent element from the second param.
|
|
805
|
+
*/
|
|
806
|
+
const isTaskWrapper = (contender, parentScope) => {
|
|
807
|
+
const taskWrapper = closestInScope(contender, matchesClasses('k-task-wrap'), parentScope);
|
|
808
|
+
return isPresent(taskWrapper);
|
|
809
|
+
};
|
|
736
810
|
/**
|
|
737
811
|
* @hidden
|
|
738
812
|
*
|
|
739
813
|
* Gets the closest timeline task element index from an event target.
|
|
740
814
|
* Uses the `data-task-index` attribute assigned to each task.
|
|
741
|
-
* Restricts the search up to the provided
|
|
815
|
+
* Restricts the search up to the provided parent element from the second param.
|
|
742
816
|
*/
|
|
743
|
-
const getClosestTaskIndex = (element,
|
|
744
|
-
const task = closestInScope(element, matchesClasses('k-task'),
|
|
817
|
+
const getClosestTaskIndex = (element, parentScope) => {
|
|
818
|
+
const task = closestInScope(element, matchesClasses('k-task-wrap'), parentScope);
|
|
745
819
|
if (!isPresent(task)) {
|
|
746
820
|
return null;
|
|
747
821
|
}
|
|
@@ -751,22 +825,133 @@ const getClosestTaskIndex = (element, gantt) => {
|
|
|
751
825
|
* @hidden
|
|
752
826
|
*
|
|
753
827
|
* Checks whether the queried item or its parent items has a `k-task` selector.
|
|
754
|
-
* Restricts the search up to the provided
|
|
828
|
+
* Restricts the search up to the provided parent element from the second param.
|
|
755
829
|
*/
|
|
756
|
-
const isTask = (contender,
|
|
757
|
-
const task = closestInScope(contender, matchesClasses('k-task'),
|
|
830
|
+
const isTask = (contender, parentScope) => {
|
|
831
|
+
const task = closestInScope(contender, matchesClasses('k-task'), parentScope);
|
|
758
832
|
return isPresent(task);
|
|
759
833
|
};
|
|
760
834
|
/**
|
|
761
835
|
* @hidden
|
|
762
836
|
*
|
|
763
837
|
* Checks whether the queried item or its parent items has a `k-task-actions` selector - used for the clear button.
|
|
764
|
-
* Restricts the search up to the provided
|
|
838
|
+
* Restricts the search up to the provided parent element from the second param.
|
|
765
839
|
*/
|
|
766
|
-
const isClearButton = (contender,
|
|
767
|
-
const clearButtonContainer = closestInScope(contender, matchesClasses('k-task-actions'),
|
|
840
|
+
const isClearButton = (contender, parentScope) => {
|
|
841
|
+
const clearButtonContainer = closestInScope(contender, matchesClasses('k-task-actions'), parentScope);
|
|
768
842
|
return isPresent(clearButtonContainer);
|
|
769
843
|
};
|
|
844
|
+
/**
|
|
845
|
+
* @hidden
|
|
846
|
+
*
|
|
847
|
+
* Checks whether the queried item has a `k-task-dot` selector - used for the dependency drag clues.
|
|
848
|
+
*/
|
|
849
|
+
const isDependencyDragClue = (element) => {
|
|
850
|
+
if (!isPresent(element)) {
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
return element.classList.contains('k-task-dot');
|
|
854
|
+
};
|
|
855
|
+
/**
|
|
856
|
+
* @hidden
|
|
857
|
+
*
|
|
858
|
+
* Checks whether the queried item has a `k-task-dot` & `k-task-start` selector - used for the dependency drag start clues.
|
|
859
|
+
*/
|
|
860
|
+
const isDependencyDragStartClue = (element) => {
|
|
861
|
+
if (!isPresent(element)) {
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
return element.classList.contains('k-task-dot') && element.classList.contains('k-task-start');
|
|
865
|
+
};
|
|
866
|
+
/**
|
|
867
|
+
* @hidden
|
|
868
|
+
*
|
|
869
|
+
* Gets the `DependencyType` for an attempted dependency create from the provided two elements.
|
|
870
|
+
* The two linked drag clue HTML elements are used to extract this data (via their CSS classes).
|
|
871
|
+
*/
|
|
872
|
+
const getDependencyTypeFromTargetTasks = (fromTaskClue, toTaskClue) => {
|
|
873
|
+
if (!isDependencyDragClue(fromTaskClue) || !isDependencyDragClue(toTaskClue)) {
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
const fromTaskType = isDependencyDragStartClue(fromTaskClue) ? 'S' : 'F';
|
|
877
|
+
const toTaskType = isDependencyDragStartClue(toTaskClue) ? 'S' : 'F';
|
|
878
|
+
const dependencyTypeName = `${fromTaskType}${toTaskType}`;
|
|
879
|
+
switch (dependencyTypeName) {
|
|
880
|
+
case 'FF': return DependencyType.FF;
|
|
881
|
+
case 'FS': return DependencyType.FS;
|
|
882
|
+
case 'SF': return DependencyType.SF;
|
|
883
|
+
case 'SS': return DependencyType.SS;
|
|
884
|
+
default: return null;
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
/**
|
|
888
|
+
* @hidden
|
|
889
|
+
*
|
|
890
|
+
* Checks whether the two provided drag clues belong to the same task element.
|
|
891
|
+
*/
|
|
892
|
+
const sameTaskClues = (fromTaskClue, toTaskClue, parentScope) => {
|
|
893
|
+
if (!isPresent(fromTaskClue) || !isPresent(toTaskClue)) {
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
896
|
+
const fromTaskWrapper = getClosestTaskWrapper(fromTaskClue, parentScope);
|
|
897
|
+
const toTaskWrapper = getClosestTaskWrapper(toTaskClue, parentScope);
|
|
898
|
+
return fromTaskWrapper === toTaskWrapper;
|
|
899
|
+
};
|
|
900
|
+
/**
|
|
901
|
+
* @hidden
|
|
902
|
+
*
|
|
903
|
+
* Fits a contender number between a min and max range.
|
|
904
|
+
* If the contender is below the min value, the min value is returned.
|
|
905
|
+
* If the contender is above the max value, the max value is returned.
|
|
906
|
+
*/
|
|
907
|
+
const fitToRange = (contender, min, max) => {
|
|
908
|
+
if (contender > max) {
|
|
909
|
+
return max;
|
|
910
|
+
}
|
|
911
|
+
else if (contender < min) {
|
|
912
|
+
return min;
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
return contender;
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
/**
|
|
919
|
+
* @hidden
|
|
920
|
+
*
|
|
921
|
+
* Checks whether either of the two provided tasks is a parent of the other.
|
|
922
|
+
*/
|
|
923
|
+
const areParentChild = (taskA, taskB) => {
|
|
924
|
+
let parentChildRelationship = false;
|
|
925
|
+
let taskAParent = taskA;
|
|
926
|
+
while (isPresent(taskAParent) && isPresent(taskAParent.data)) {
|
|
927
|
+
if (taskAParent.data === taskB.data) {
|
|
928
|
+
parentChildRelationship = true;
|
|
929
|
+
break;
|
|
930
|
+
}
|
|
931
|
+
taskAParent = taskAParent.parent;
|
|
932
|
+
}
|
|
933
|
+
let taskBParent = taskB;
|
|
934
|
+
while (!parentChildRelationship && isPresent(taskBParent) && isPresent(taskBParent.data)) {
|
|
935
|
+
if (taskBParent.data === taskA.data) {
|
|
936
|
+
parentChildRelationship = true;
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
taskBParent = taskBParent.parent;
|
|
940
|
+
}
|
|
941
|
+
return parentChildRelationship;
|
|
942
|
+
};
|
|
943
|
+
/**
|
|
944
|
+
* @hidden
|
|
945
|
+
*
|
|
946
|
+
* Extracts an element from the provided client coords.
|
|
947
|
+
* Using the `event.target` is not reliable under mobile devices with the current implementation of the draggable, so use this instead.
|
|
948
|
+
*/
|
|
949
|
+
const elementFromPoint = (clientX, clientY) => {
|
|
950
|
+
if (!isDocumentAvailable()) {
|
|
951
|
+
return null;
|
|
952
|
+
}
|
|
953
|
+
return document.elementFromPoint(clientX, clientY);
|
|
954
|
+
};
|
|
770
955
|
|
|
771
956
|
/**
|
|
772
957
|
* @hidden
|
|
@@ -1419,6 +1604,61 @@ EditService = __decorate([
|
|
|
1419
1604
|
__metadata("design:paramtypes", [MappingService])
|
|
1420
1605
|
], EditService);
|
|
1421
1606
|
|
|
1607
|
+
/**
|
|
1608
|
+
* @hidden
|
|
1609
|
+
*
|
|
1610
|
+
* Notifies the timeline-scroll.directive to scroll into view to requested coordinates.
|
|
1611
|
+
* The scrolling is performed based on client (viewport) coordinates.
|
|
1612
|
+
*/
|
|
1613
|
+
let TimelineScrollService = class TimelineScrollService {
|
|
1614
|
+
/**
|
|
1615
|
+
* @hidden
|
|
1616
|
+
*
|
|
1617
|
+
* Notifies the timeline-scroll.directive to scroll into view to requested coordinates.
|
|
1618
|
+
* The scrolling is performed based on client (viewport) coordinates.
|
|
1619
|
+
*/
|
|
1620
|
+
constructor() {
|
|
1621
|
+
this.horizontalScroll = new Subject();
|
|
1622
|
+
this.verticalScroll = new Subject();
|
|
1623
|
+
this.scrollCancel = new Subject();
|
|
1624
|
+
}
|
|
1625
|
+
ngOnDestroy() {
|
|
1626
|
+
this.horizontalScroll.complete();
|
|
1627
|
+
this.verticalScroll.complete();
|
|
1628
|
+
this.scrollCancel.complete();
|
|
1629
|
+
}
|
|
1630
|
+
requestHorizontalScroll(clientTop) {
|
|
1631
|
+
this.horizontalScroll.next(clientTop);
|
|
1632
|
+
}
|
|
1633
|
+
requestVerticalScroll(clientLeft) {
|
|
1634
|
+
this.verticalScroll.next(clientLeft);
|
|
1635
|
+
}
|
|
1636
|
+
requestScrollCancel() {
|
|
1637
|
+
this.scrollCancel.next();
|
|
1638
|
+
}
|
|
1639
|
+
};
|
|
1640
|
+
TimelineScrollService = __decorate([
|
|
1641
|
+
Injectable()
|
|
1642
|
+
], TimelineScrollService);
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* @hidden
|
|
1646
|
+
*
|
|
1647
|
+
* Needed to keep the Gantt's LocalizationService reference and be able to use it component's inside the TabStrip
|
|
1648
|
+
*/
|
|
1649
|
+
let GanttLocalizationService = class GanttLocalizationService {
|
|
1650
|
+
constructor(localizationService) {
|
|
1651
|
+
this.localizationService = localizationService;
|
|
1652
|
+
}
|
|
1653
|
+
get(token) {
|
|
1654
|
+
return this.localizationService.get(token);
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1657
|
+
GanttLocalizationService = __decorate([
|
|
1658
|
+
Injectable(),
|
|
1659
|
+
__metadata("design:paramtypes", [LocalizationService])
|
|
1660
|
+
], GanttLocalizationService);
|
|
1661
|
+
|
|
1422
1662
|
/**
|
|
1423
1663
|
* @hidden
|
|
1424
1664
|
*/
|
|
@@ -1677,84 +1917,322 @@ ToolbarTemplateDirective = __decorate([
|
|
|
1677
1917
|
], ToolbarTemplateDirective);
|
|
1678
1918
|
|
|
1679
1919
|
/**
|
|
1680
|
-
*
|
|
1920
|
+
* @hidden
|
|
1681
1921
|
*/
|
|
1682
|
-
class
|
|
1922
|
+
let GanttTimelineComponent = class GanttTimelineComponent {
|
|
1923
|
+
constructor(scrollSyncService, dependencyDomService, renderer, zone) {
|
|
1924
|
+
this.scrollSyncService = scrollSyncService;
|
|
1925
|
+
this.dependencyDomService = dependencyDomService;
|
|
1926
|
+
this.renderer = renderer;
|
|
1927
|
+
this.zone = zone;
|
|
1928
|
+
this.hostClass = true;
|
|
1929
|
+
this.dependencies = [];
|
|
1930
|
+
// as all drag-and-drop operations are on the timeline container, use a single draggable instance
|
|
1931
|
+
this.timelineContainerPress = new EventEmitter();
|
|
1932
|
+
this.timelineContainerDrag = new EventEmitter();
|
|
1933
|
+
this.timelineContainerRelease = new EventEmitter();
|
|
1934
|
+
this.subscriptions = new Subscription();
|
|
1935
|
+
this.subscriptions.add(
|
|
1936
|
+
// task changes indicates change in row content, number, height, etc.
|
|
1937
|
+
this.dependencyDomService.taskChanges
|
|
1938
|
+
.pipe(filter(args => isPresent(args.timelineRow)), switchMap(args => this.zone.onStable.pipe(take(1), map(() => args))) // ensure the content is rendered
|
|
1939
|
+
)
|
|
1940
|
+
.subscribe(({ timelineRow }) => {
|
|
1941
|
+
const timelineRowHeight = isDocumentAvailable() ? timelineRow.getBoundingClientRect().height : 0;
|
|
1942
|
+
this.renderer.setStyle(this.timelineColumns.nativeElement, 'height', `${(this.rows || []).length * timelineRowHeight}px`);
|
|
1943
|
+
}));
|
|
1944
|
+
}
|
|
1683
1945
|
/**
|
|
1684
|
-
*
|
|
1685
|
-
* @hidden
|
|
1946
|
+
* Specifies whether the draggable will attach or detach its pointer event listeners.
|
|
1686
1947
|
*/
|
|
1687
|
-
|
|
1688
|
-
this.
|
|
1689
|
-
this.dependencyDomService = dependencyDomService;
|
|
1690
|
-
/**
|
|
1691
|
-
* The width of the time slot headers. Values are treated as pixels.
|
|
1692
|
-
*
|
|
1693
|
-
* @default 100
|
|
1694
|
-
*/
|
|
1695
|
-
this.slotWidth = 100;
|
|
1948
|
+
get draggableEnabled() {
|
|
1949
|
+
return this.renderDependencyDragClues;
|
|
1696
1950
|
}
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1951
|
+
ngAfterViewInit() {
|
|
1952
|
+
const timelineHeader = this.timelineHeaderWrap.nativeElement;
|
|
1953
|
+
const rightContainer = this.timelineContent.nativeElement;
|
|
1954
|
+
this.scrollSyncService.registerElement(rightContainer, 'timeline');
|
|
1955
|
+
this.scrollSyncService.registerElement(timelineHeader, 'header');
|
|
1956
|
+
this.dependencyDomService.registerContentContainer(this.tasksContainer.nativeElement);
|
|
1702
1957
|
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
Input(),
|
|
1706
|
-
__metadata("design:type", Number)
|
|
1707
|
-
], ViewBase.prototype, "slotWidth", void 0);
|
|
1708
|
-
|
|
1709
|
-
/**
|
|
1710
|
-
* @hidden
|
|
1711
|
-
*/
|
|
1712
|
-
const getEditItem = (dataItem, data, mapper) => {
|
|
1713
|
-
const treeListDataItem = data.find(item => mapper.extractFromTask(item.data, 'id') === mapper.extractFromTask(dataItem, 'id'));
|
|
1714
|
-
return mapPath(treeListDataItem);
|
|
1715
|
-
};
|
|
1716
|
-
const mapPath = (item) => ({
|
|
1717
|
-
dataItem: item.data,
|
|
1718
|
-
parent: item.parent.data ? mapPath(item.parent) : null
|
|
1719
|
-
});
|
|
1720
|
-
|
|
1721
|
-
/**
|
|
1722
|
-
* @hidden
|
|
1723
|
-
*
|
|
1724
|
-
* Needed to keep the Gantt's LocalizationService reference and be able to use it component's inside the TabStrip
|
|
1725
|
-
*/
|
|
1726
|
-
let GanttLocalizationService = class GanttLocalizationService {
|
|
1727
|
-
constructor(localizationService) {
|
|
1728
|
-
this.localizationService = localizationService;
|
|
1958
|
+
ngOnDestroy() {
|
|
1959
|
+
this.subscriptions.unsubscribe();
|
|
1729
1960
|
}
|
|
1730
|
-
|
|
1731
|
-
return
|
|
1961
|
+
isNonWorking(item) {
|
|
1962
|
+
return item.hasOwnProperty('isWorking') && !item.isWorking;
|
|
1732
1963
|
}
|
|
1733
1964
|
};
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
__metadata("design:
|
|
1737
|
-
],
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1965
|
+
__decorate([
|
|
1966
|
+
ViewChild('timelineContent', { static: true }),
|
|
1967
|
+
__metadata("design:type", ElementRef)
|
|
1968
|
+
], GanttTimelineComponent.prototype, "timelineContent", void 0);
|
|
1969
|
+
__decorate([
|
|
1970
|
+
ViewChild('timelineColumns', { static: true }),
|
|
1971
|
+
__metadata("design:type", ElementRef)
|
|
1972
|
+
], GanttTimelineComponent.prototype, "timelineColumns", void 0);
|
|
1973
|
+
__decorate([
|
|
1974
|
+
ViewChild('timelineHeaderWrap', { static: true }),
|
|
1975
|
+
__metadata("design:type", ElementRef)
|
|
1976
|
+
], GanttTimelineComponent.prototype, "timelineHeaderWrap", void 0);
|
|
1977
|
+
__decorate([
|
|
1978
|
+
ViewChild('tasksContainer', { static: true }),
|
|
1979
|
+
__metadata("design:type", ElementRef)
|
|
1980
|
+
], GanttTimelineComponent.prototype, "tasksContainer", void 0);
|
|
1981
|
+
__decorate([
|
|
1982
|
+
ViewChild('dragPopupContainer', { static: false, read: ViewContainerRef }),
|
|
1983
|
+
__metadata("design:type", ViewContainerRef)
|
|
1984
|
+
], GanttTimelineComponent.prototype, "dragPopupContainer", void 0);
|
|
1985
|
+
__decorate([
|
|
1986
|
+
ViewChild('dependencyDragCreatePolyline', { static: false }),
|
|
1987
|
+
__metadata("design:type", ElementRef)
|
|
1988
|
+
], GanttTimelineComponent.prototype, "dependencyDragCreatePolyline", void 0);
|
|
1989
|
+
__decorate([
|
|
1990
|
+
HostBinding('class.k-gantt-timeline'),
|
|
1991
|
+
__metadata("design:type", Boolean)
|
|
1992
|
+
], GanttTimelineComponent.prototype, "hostClass", void 0);
|
|
1993
|
+
__decorate([
|
|
1994
|
+
Input(),
|
|
1995
|
+
__metadata("design:type", Array)
|
|
1996
|
+
], GanttTimelineComponent.prototype, "rows", void 0);
|
|
1997
|
+
__decorate([
|
|
1998
|
+
Input(),
|
|
1999
|
+
__metadata("design:type", Array)
|
|
2000
|
+
], GanttTimelineComponent.prototype, "slots", void 0);
|
|
2001
|
+
__decorate([
|
|
2002
|
+
Input(),
|
|
2003
|
+
__metadata("design:type", Array)
|
|
2004
|
+
], GanttTimelineComponent.prototype, "groupSlots", void 0);
|
|
2005
|
+
__decorate([
|
|
2006
|
+
Input(),
|
|
2007
|
+
__metadata("design:type", Number)
|
|
2008
|
+
], GanttTimelineComponent.prototype, "tableWidth", void 0);
|
|
2009
|
+
__decorate([
|
|
2010
|
+
Input(),
|
|
2011
|
+
__metadata("design:type", String)
|
|
2012
|
+
], GanttTimelineComponent.prototype, "activeView", void 0);
|
|
2013
|
+
__decorate([
|
|
2014
|
+
Input(),
|
|
2015
|
+
__metadata("design:type", TemplateRef)
|
|
2016
|
+
], GanttTimelineComponent.prototype, "taskContentTemplate", void 0);
|
|
2017
|
+
__decorate([
|
|
2018
|
+
Input(),
|
|
2019
|
+
__metadata("design:type", TemplateRef)
|
|
2020
|
+
], GanttTimelineComponent.prototype, "taskTemplate", void 0);
|
|
2021
|
+
__decorate([
|
|
2022
|
+
Input(),
|
|
2023
|
+
__metadata("design:type", TemplateRef)
|
|
2024
|
+
], GanttTimelineComponent.prototype, "summaryTaskTemplate", void 0);
|
|
2025
|
+
__decorate([
|
|
2026
|
+
Input(),
|
|
2027
|
+
__metadata("design:type", Function)
|
|
2028
|
+
], GanttTimelineComponent.prototype, "taskClass", void 0);
|
|
2029
|
+
__decorate([
|
|
2030
|
+
Input(),
|
|
2031
|
+
__metadata("design:type", Function)
|
|
2032
|
+
], GanttTimelineComponent.prototype, "isTaskSelected", void 0);
|
|
2033
|
+
__decorate([
|
|
2034
|
+
Input(),
|
|
2035
|
+
__metadata("design:type", Boolean)
|
|
2036
|
+
], GanttTimelineComponent.prototype, "renderDependencyDragClues", void 0);
|
|
2037
|
+
__decorate([
|
|
2038
|
+
Input(),
|
|
2039
|
+
__metadata("design:type", Object)
|
|
2040
|
+
], GanttTimelineComponent.prototype, "dragScrollSettings", void 0);
|
|
2041
|
+
__decorate([
|
|
2042
|
+
Input(),
|
|
2043
|
+
__metadata("design:type", Function)
|
|
2044
|
+
], GanttTimelineComponent.prototype, "hasChildren", void 0);
|
|
2045
|
+
__decorate([
|
|
2046
|
+
Input(),
|
|
2047
|
+
__metadata("design:type", Array)
|
|
2048
|
+
], GanttTimelineComponent.prototype, "dependencies", void 0);
|
|
2049
|
+
__decorate([
|
|
2050
|
+
Output(),
|
|
2051
|
+
__metadata("design:type", EventEmitter)
|
|
2052
|
+
], GanttTimelineComponent.prototype, "timelineContainerPress", void 0);
|
|
2053
|
+
__decorate([
|
|
2054
|
+
Output(),
|
|
2055
|
+
__metadata("design:type", EventEmitter)
|
|
2056
|
+
], GanttTimelineComponent.prototype, "timelineContainerDrag", void 0);
|
|
2057
|
+
__decorate([
|
|
2058
|
+
Output(),
|
|
2059
|
+
__metadata("design:type", EventEmitter)
|
|
2060
|
+
], GanttTimelineComponent.prototype, "timelineContainerRelease", void 0);
|
|
2061
|
+
GanttTimelineComponent = __decorate([
|
|
2062
|
+
Component({
|
|
2063
|
+
selector: 'kendo-gantt-timeline',
|
|
2064
|
+
template: `
|
|
2065
|
+
<div class="k-timeline k-grid k-widget">
|
|
2066
|
+
<div class="k-grid-header">
|
|
2067
|
+
<div #timelineHeaderWrap class="k-grid-header-wrap">
|
|
2068
|
+
<table
|
|
2069
|
+
role="presentation"
|
|
2070
|
+
[style.width.px]="tableWidth"
|
|
2071
|
+
>
|
|
2072
|
+
<tbody
|
|
2073
|
+
kendoGanttHeaderTableBody
|
|
2074
|
+
[groupSlots]="groupSlots"
|
|
2075
|
+
[slots]="slots">
|
|
2076
|
+
</tbody>
|
|
2077
|
+
</table>
|
|
2078
|
+
</div>
|
|
2079
|
+
</div>
|
|
2080
|
+
<div
|
|
2081
|
+
#timelineContent
|
|
2082
|
+
class="k-grid-content"
|
|
2083
|
+
kendoGanttTimelineScrollable
|
|
2084
|
+
[scrollSettings]="dragScrollSettings"
|
|
2085
|
+
kendoDraggable
|
|
2086
|
+
[enableDrag]="draggableEnabled"
|
|
2087
|
+
(kendoPress)="timelineContainerPress.emit($event)"
|
|
2088
|
+
(kendoDrag)="timelineContainerDrag.emit($event)"
|
|
2089
|
+
(kendoRelease)="timelineContainerRelease.emit($event)"
|
|
2090
|
+
>
|
|
2091
|
+
<div class="k-gantt-tables">
|
|
2092
|
+
<table
|
|
2093
|
+
class="k-gantt-rows"
|
|
2094
|
+
[style.width.px]="tableWidth"
|
|
2095
|
+
role="presentation"
|
|
2096
|
+
>
|
|
2097
|
+
<tbody>
|
|
2098
|
+
<tr *ngFor="let item of rows; let i = index;"
|
|
2099
|
+
[class.k-alt]="i % 2"
|
|
2100
|
+
>
|
|
2101
|
+
<td></td>
|
|
2102
|
+
</tr>
|
|
2103
|
+
</tbody>
|
|
2104
|
+
</table>
|
|
2105
|
+
|
|
2106
|
+
<table
|
|
2107
|
+
#timelineColumns
|
|
2108
|
+
class="k-gantt-columns"
|
|
2109
|
+
role="presentation"
|
|
2110
|
+
[style.width.px]="tableWidth"
|
|
2111
|
+
>
|
|
2112
|
+
<colgroup>
|
|
2113
|
+
<col *ngFor="let item of slots">
|
|
2114
|
+
</colgroup>
|
|
2115
|
+
|
|
2116
|
+
<tbody>
|
|
2117
|
+
<tr>
|
|
2118
|
+
<td *ngFor="let item of slots"
|
|
2119
|
+
[class.k-nonwork-hour]="isNonWorking(item)"
|
|
2120
|
+
>
|
|
2121
|
+
</td>
|
|
2122
|
+
</tr>
|
|
2123
|
+
</tbody>
|
|
2124
|
+
</table>
|
|
2125
|
+
|
|
2126
|
+
<table
|
|
2127
|
+
#tasksContainer
|
|
2128
|
+
class="k-gantt-tasks"
|
|
2129
|
+
role="presentation"
|
|
2130
|
+
style="border-collapse: collapse;"
|
|
2131
|
+
[style.width.px]="tableWidth"
|
|
2132
|
+
>
|
|
2133
|
+
<tbody
|
|
2134
|
+
kendoGanttTasksTableBody
|
|
2135
|
+
[rows]="rows"
|
|
2136
|
+
[activeView]="activeView"
|
|
2137
|
+
[taskContentTemplate]="taskContentTemplate"
|
|
2138
|
+
[taskTemplate]="taskTemplate"
|
|
2139
|
+
[summaryTaskTemplate]="summaryTaskTemplate"
|
|
2140
|
+
[taskClass]="taskClass"
|
|
2141
|
+
[hasChildren]="hasChildren"
|
|
2142
|
+
[isTaskSelected]="isTaskSelected"
|
|
2143
|
+
[renderDependencyDragClues]="renderDependencyDragClues"
|
|
2144
|
+
>
|
|
2145
|
+
</tbody>
|
|
2146
|
+
</table>
|
|
2147
|
+
</div>
|
|
2148
|
+
<svg class="k-gantt-dependencies-svg">
|
|
2149
|
+
<polyline
|
|
2150
|
+
*ngFor="let dependency of dependencies"
|
|
2151
|
+
kendoGanttDependency
|
|
2152
|
+
[dependency]="dependency"
|
|
2153
|
+
/>
|
|
2154
|
+
<polyline #dependencyDragCreatePolyline />
|
|
2155
|
+
</svg>
|
|
2156
|
+
|
|
2157
|
+
<!-- placeholder for the dependency drag popup; its position is not arbitrary - the popup is intended to be absolutely positioned inside the .k-grid-content element -->
|
|
2158
|
+
<ng-container #dragPopupContainer></ng-container>
|
|
2159
|
+
</div>
|
|
2160
|
+
</div>
|
|
2161
|
+
`
|
|
2162
|
+
}),
|
|
2163
|
+
__metadata("design:paramtypes", [ScrollSyncService,
|
|
2164
|
+
DependencyDomService,
|
|
2165
|
+
Renderer2,
|
|
2166
|
+
NgZone])
|
|
2167
|
+
], GanttTimelineComponent);
|
|
2168
|
+
|
|
2169
|
+
/**
|
|
2170
|
+
* The base class for the column components of the Gantt.
|
|
2171
|
+
*/
|
|
2172
|
+
class ViewBase {
|
|
2173
|
+
/**
|
|
2174
|
+
*
|
|
2175
|
+
* @hidden
|
|
2176
|
+
*/
|
|
2177
|
+
constructor(optionChangesService, dependencyDomService) {
|
|
2178
|
+
this.optionChangesService = optionChangesService;
|
|
2179
|
+
this.dependencyDomService = dependencyDomService;
|
|
2180
|
+
/**
|
|
2181
|
+
* The width of the time slot headers. Values are treated as pixels.
|
|
2182
|
+
*
|
|
2183
|
+
* @default 100
|
|
2184
|
+
*/
|
|
2185
|
+
this.slotWidth = 100;
|
|
2186
|
+
}
|
|
2187
|
+
ngOnChanges(changes) {
|
|
2188
|
+
if (anyChanged(['slotWidth'], changes)) {
|
|
2189
|
+
this.optionChangesService.notifyColumnChanges();
|
|
2190
|
+
this.dependencyDomService.notifyChanges();
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
__decorate([
|
|
2195
|
+
Input(),
|
|
2196
|
+
__metadata("design:type", Number)
|
|
2197
|
+
], ViewBase.prototype, "slotWidth", void 0);
|
|
2198
|
+
|
|
2199
|
+
/**
|
|
2200
|
+
* @hidden
|
|
2201
|
+
*/
|
|
2202
|
+
const getEditItem = (dataItem, data, mapper) => {
|
|
2203
|
+
const treeListDataItem = data.find(item => mapper.extractFromTask(item.data, 'id') === mapper.extractFromTask(dataItem, 'id'));
|
|
2204
|
+
return mapPath(treeListDataItem);
|
|
2205
|
+
};
|
|
2206
|
+
const mapPath = (item) => ({
|
|
2207
|
+
dataItem: item.data,
|
|
2208
|
+
parent: item.parent.data ? mapPath(item.parent) : null
|
|
2209
|
+
});
|
|
2210
|
+
|
|
2211
|
+
var GanttComponent_1;
|
|
2212
|
+
const TREELIST_GROUP_COLUMNS_CLASS = 'k-gantt-treelist-nested-columns';
|
|
2213
|
+
const DEFAULT_VIEW = 'week';
|
|
2214
|
+
const DEFAULT_DRAG_SCROLL_SETTINGS = {
|
|
2215
|
+
enabled: true,
|
|
2216
|
+
step: 3,
|
|
2217
|
+
interval: 1,
|
|
2218
|
+
threshold: 10
|
|
2219
|
+
};
|
|
2220
|
+
/**
|
|
2221
|
+
* Represents the Kendo UI Gantt component for Angular.
|
|
2222
|
+
*
|
|
2223
|
+
* @example
|
|
2224
|
+
* ```ts-preview
|
|
2225
|
+
* _@Component({
|
|
2226
|
+
* selector: 'my-app',
|
|
2227
|
+
* template: `
|
|
2228
|
+
* <kendo-gantt
|
|
2229
|
+
* [style.height.px]="500"
|
|
2230
|
+
* [kendoGanttHierarchyBinding]="data"
|
|
2231
|
+
* childrenField="subtasks"
|
|
2232
|
+
* [dependencies]="dependencies">
|
|
2233
|
+
* <kendo-gantt-column
|
|
2234
|
+
* field="title"
|
|
2235
|
+
* title="Task"
|
|
1758
2236
|
* [width]="200"
|
|
1759
2237
|
* [expandable]="true"></kendo-gantt-column>
|
|
1760
2238
|
* <kendo-gantt-column
|
|
@@ -1824,11 +2302,22 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
|
|
|
1824
2302
|
this.zone = zone;
|
|
1825
2303
|
this.hostClasses = true;
|
|
1826
2304
|
/**
|
|
1827
|
-
*
|
|
2305
|
+
* Specifies a callback that determines if the given task is selected ([see example]({% slug selection_gantt %}#toc-custom-selection)).
|
|
1828
2306
|
*
|
|
1829
2307
|
* > The [`selectable`]({% slug api_gantt_ganttcomponent %}#toc-selectable) prop has to be set to `true` in order for this callback to be executed.
|
|
1830
2308
|
*/
|
|
1831
2309
|
this.isSelected = isSelected;
|
|
2310
|
+
/**
|
|
2311
|
+
* Specifies a callback that determines if a new dependency is valid.
|
|
2312
|
+
* Used when evaluating if an attempt to create a new dependency will result in a valid link between the two tasks
|
|
2313
|
+
* [see example]({% slug editing_drag_create_dependencies_gantt %}#toc-validation).
|
|
2314
|
+
*
|
|
2315
|
+
* By defalut, dependencies are deemed invalid when:
|
|
2316
|
+
* - The two tasks are in a parent-child relationship.
|
|
2317
|
+
* - The two tasks are already dependent on one another. Only one dependency is allowed per pair.
|
|
2318
|
+
* - The start or end times of the two tasks are incompatible with the attempted dependency type.
|
|
2319
|
+
*/
|
|
2320
|
+
this.validateNewDependency = this.defaultValidateNewDependencyCallback.bind(this);
|
|
1832
2321
|
/**
|
|
1833
2322
|
* Fires when the Gantt selection is changed through user interaction.
|
|
1834
2323
|
*
|
|
@@ -1949,6 +2438,11 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
|
|
|
1949
2438
|
* Fires when the user adds a task.
|
|
1950
2439
|
*/
|
|
1951
2440
|
this.taskAdd = new EventEmitter();
|
|
2441
|
+
/**
|
|
2442
|
+
* Fires when the user adds a dependency via dragging
|
|
2443
|
+
* [see example]({% slug editing_drag_create_dependencies_gantt %}#toc-basic-concepts).
|
|
2444
|
+
*/
|
|
2445
|
+
this.dependencyAdd = new EventEmitter();
|
|
1952
2446
|
/**
|
|
1953
2447
|
* Fires when the sorting of the Gantt is changed.
|
|
1954
2448
|
* You have to handle the event yourself and sort the data.
|
|
@@ -2005,6 +2499,15 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
|
|
|
2005
2499
|
* Fires when a task is clicked.
|
|
2006
2500
|
*/
|
|
2007
2501
|
this.taskClick = new EventEmitter();
|
|
2502
|
+
/**
|
|
2503
|
+
* @hidden
|
|
2504
|
+
*
|
|
2505
|
+
* Specifies whether the dependency drag clues will be rendered.
|
|
2506
|
+
* Set internally by the dependency-drag-create directive.
|
|
2507
|
+
*
|
|
2508
|
+
* @default false
|
|
2509
|
+
*/
|
|
2510
|
+
this.renderDependencyDragClues = false;
|
|
2008
2511
|
/**
|
|
2009
2512
|
* @hidden
|
|
2010
2513
|
*
|
|
@@ -2021,6 +2524,7 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
|
|
|
2021
2524
|
this.showConfirmationDialog = false;
|
|
2022
2525
|
this._columns = new QueryList();
|
|
2023
2526
|
this._data = [];
|
|
2527
|
+
this._dragScrollSettings = Object.assign({}, DEFAULT_DRAG_SCROLL_SETTINGS);
|
|
2024
2528
|
this._timelinePaneOptions = Object.assign({}, DEFAULT_TIMELINE_PANE_SETTINGS);
|
|
2025
2529
|
this._treeListPaneOptions = Object.assign({}, DEFAULT_TREELIST_PANE_SETTINGS);
|
|
2026
2530
|
this._rowClass = rowClassCallback;
|
|
@@ -2236,6 +2740,17 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
|
|
|
2236
2740
|
get taskIdField() {
|
|
2237
2741
|
return this.mapper.taskFields.id;
|
|
2238
2742
|
}
|
|
2743
|
+
/**
|
|
2744
|
+
* Specifies the settings for auto-scrolling during dragging
|
|
2745
|
+
* when the pointer moves outside of the container bounderies
|
|
2746
|
+
* [see example]({% slug editing_drag_create_dependencies_gantt %}#toc-auto-scrolling).
|
|
2747
|
+
*/
|
|
2748
|
+
set dragScrollSettings(settings) {
|
|
2749
|
+
this._dragScrollSettings = Object.assign({}, DEFAULT_DRAG_SCROLL_SETTINGS, settings);
|
|
2750
|
+
}
|
|
2751
|
+
get dragScrollSettings() {
|
|
2752
|
+
return this._dragScrollSettings;
|
|
2753
|
+
}
|
|
2239
2754
|
/**
|
|
2240
2755
|
* @hidden
|
|
2241
2756
|
*/
|
|
@@ -2656,11 +3171,60 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
|
|
|
2656
3171
|
const loadedItems = this.renderedTreeListItems || [];
|
|
2657
3172
|
return loadedItems.find(isSelectedCallback);
|
|
2658
3173
|
}
|
|
3174
|
+
defaultValidateNewDependencyCallback(dependency) {
|
|
3175
|
+
const fromTaskId = this.mapper.extractFromDependency(dependency, 'fromId');
|
|
3176
|
+
const toTaskId = this.mapper.extractFromDependency(dependency, 'toId');
|
|
3177
|
+
const fromTask = this.treeList.view.data.find(task => this.mapper.extractFromTask(task.data, 'id') === fromTaskId);
|
|
3178
|
+
const toTask = this.treeList.view.data.find(task => this.mapper.extractFromTask(task.data, 'id') === toTaskId);
|
|
3179
|
+
// mark as invalid if the attempted dependency is lacking valid from- and to-tasks
|
|
3180
|
+
// or when the from- and to-tasks are actually the same task
|
|
3181
|
+
if (!isPresent(fromTask) || !isPresent(fromTask.data) ||
|
|
3182
|
+
!isPresent(toTask) || !isPresent(toTask.data) ||
|
|
3183
|
+
fromTask.data === toTask.data) {
|
|
3184
|
+
return false;
|
|
3185
|
+
}
|
|
3186
|
+
const tasksDependentOnOneAnother = this.dependencies.some(current => {
|
|
3187
|
+
const currentFromId = this.mapper.extractFromDependency(current, 'fromId');
|
|
3188
|
+
const currentToId = this.mapper.extractFromDependency(current, 'toId');
|
|
3189
|
+
return (fromTaskId === currentFromId && toTaskId === currentToId) ||
|
|
3190
|
+
(toTaskId === currentFromId && fromTaskId === currentToId);
|
|
3191
|
+
});
|
|
3192
|
+
// mark as invalid if the attempted dependency is trying to connect already dependent tasks
|
|
3193
|
+
// mark as invalid if the two tasks are in parent-child relationship
|
|
3194
|
+
if (tasksDependentOnOneAnother || areParentChild(fromTask, toTask)) {
|
|
3195
|
+
return false;
|
|
3196
|
+
}
|
|
3197
|
+
const fromTaskStart = this.mapper.extractFromTask(fromTask.data, 'start');
|
|
3198
|
+
const fromTaskEnd = this.mapper.extractFromTask(fromTask.data, 'end');
|
|
3199
|
+
const toTaskStart = this.mapper.extractFromTask(toTask.data, 'start');
|
|
3200
|
+
const toTaskEnd = this.mapper.extractFromTask(toTask.data, 'end');
|
|
3201
|
+
// if the two tasks are available to be connected via a dependency,
|
|
3202
|
+
// check if their start and end time allow for the attempted dependency type
|
|
3203
|
+
switch (this.mapper.extractFromDependency(dependency, 'type')) {
|
|
3204
|
+
// finish to finish (FF) — the from-task ends before the to-task can end
|
|
3205
|
+
case DependencyType.FF:
|
|
3206
|
+
return fromTaskEnd <= toTaskEnd;
|
|
3207
|
+
// finish to start (FS) — the from-task ends before the to-task can begin
|
|
3208
|
+
case DependencyType.FS:
|
|
3209
|
+
return fromTaskEnd <= toTaskStart;
|
|
3210
|
+
// start to finish (SF) — the from-task begins before the to-task can end
|
|
3211
|
+
case DependencyType.SF:
|
|
3212
|
+
return fromTaskStart <= toTaskEnd;
|
|
3213
|
+
// start to start (SS) — the from-task begins before the to-task can begin
|
|
3214
|
+
case DependencyType.SS:
|
|
3215
|
+
return fromTaskStart <= toTaskStart;
|
|
3216
|
+
default: return false;
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
2659
3219
|
};
|
|
2660
3220
|
__decorate([
|
|
2661
3221
|
ViewChild(TreeListComponent, { static: true }),
|
|
2662
3222
|
__metadata("design:type", TreeListComponent)
|
|
2663
3223
|
], GanttComponent.prototype, "treeList", void 0);
|
|
3224
|
+
__decorate([
|
|
3225
|
+
ViewChild(GanttTimelineComponent, { static: false }),
|
|
3226
|
+
__metadata("design:type", GanttTimelineComponent)
|
|
3227
|
+
], GanttComponent.prototype, "timeline", void 0);
|
|
2664
3228
|
__decorate([
|
|
2665
3229
|
ContentChild(GanttTaskContentTemplateDirective, { static: true }),
|
|
2666
3230
|
__metadata("design:type", GanttTaskContentTemplateDirective)
|
|
@@ -2719,6 +3283,10 @@ __decorate([
|
|
|
2719
3283
|
Input(),
|
|
2720
3284
|
__metadata("design:type", Function)
|
|
2721
3285
|
], GanttComponent.prototype, "isSelected", void 0);
|
|
3286
|
+
__decorate([
|
|
3287
|
+
Input(),
|
|
3288
|
+
__metadata("design:type", Function)
|
|
3289
|
+
], GanttComponent.prototype, "validateNewDependency", void 0);
|
|
2722
3290
|
__decorate([
|
|
2723
3291
|
Output(),
|
|
2724
3292
|
__metadata("design:type", EventEmitter)
|
|
@@ -2818,6 +3386,11 @@ __decorate([
|
|
|
2818
3386
|
Input(),
|
|
2819
3387
|
__metadata("design:type", Boolean)
|
|
2820
3388
|
], GanttComponent.prototype, "columnsResizable", void 0);
|
|
3389
|
+
__decorate([
|
|
3390
|
+
Input(),
|
|
3391
|
+
__metadata("design:type", Object),
|
|
3392
|
+
__metadata("design:paramtypes", [Object])
|
|
3393
|
+
], GanttComponent.prototype, "dragScrollSettings", null);
|
|
2821
3394
|
__decorate([
|
|
2822
3395
|
Output(),
|
|
2823
3396
|
__metadata("design:type", EventEmitter)
|
|
@@ -2857,7 +3430,11 @@ __decorate([
|
|
|
2857
3430
|
__decorate([
|
|
2858
3431
|
Output(),
|
|
2859
3432
|
__metadata("design:type", EventEmitter)
|
|
2860
|
-
], GanttComponent.prototype, "taskAdd", void 0);
|
|
3433
|
+
], GanttComponent.prototype, "taskAdd", void 0);
|
|
3434
|
+
__decorate([
|
|
3435
|
+
Output(),
|
|
3436
|
+
__metadata("design:type", EventEmitter)
|
|
3437
|
+
], GanttComponent.prototype, "dependencyAdd", void 0);
|
|
2861
3438
|
__decorate([
|
|
2862
3439
|
Output(),
|
|
2863
3440
|
__metadata("design:type", EventEmitter)
|
|
@@ -2933,7 +3510,8 @@ GanttComponent = GanttComponent_1 = __decorate([
|
|
|
2933
3510
|
DependencyDomService,
|
|
2934
3511
|
MappingService,
|
|
2935
3512
|
OptionChangesService,
|
|
2936
|
-
EditService
|
|
3513
|
+
EditService,
|
|
3514
|
+
TimelineScrollService
|
|
2937
3515
|
],
|
|
2938
3516
|
template: `
|
|
2939
3517
|
<ng-container kendoGanttLocalizedMessages
|
|
@@ -3248,6 +3826,8 @@ GanttComponent = GanttComponent_1 = __decorate([
|
|
|
3248
3826
|
[scrollable]="false">
|
|
3249
3827
|
<kendo-gantt-timeline
|
|
3250
3828
|
*ngIf="views && views.length"
|
|
3829
|
+
[renderDependencyDragClues]="renderDependencyDragClues"
|
|
3830
|
+
[dragScrollSettings]="dragScrollSettings"
|
|
3251
3831
|
[rows]="renderedTreeListItems"
|
|
3252
3832
|
[slots]="timelineSlots"
|
|
3253
3833
|
[groupSlots]="timelineGroupSlots"
|
|
@@ -3311,199 +3891,7 @@ GanttComponent = GanttComponent_1 = __decorate([
|
|
|
3311
3891
|
/**
|
|
3312
3892
|
* @hidden
|
|
3313
3893
|
*/
|
|
3314
|
-
|
|
3315
|
-
constructor(scrollSyncService, dependencyDomService, renderer, zone) {
|
|
3316
|
-
this.scrollSyncService = scrollSyncService;
|
|
3317
|
-
this.dependencyDomService = dependencyDomService;
|
|
3318
|
-
this.renderer = renderer;
|
|
3319
|
-
this.zone = zone;
|
|
3320
|
-
this.hostClass = true;
|
|
3321
|
-
this.dependencies = [];
|
|
3322
|
-
this.subscriptions = new Subscription();
|
|
3323
|
-
this.subscriptions.add(
|
|
3324
|
-
// task changes indicates change in row content, number, height, etc.
|
|
3325
|
-
this.dependencyDomService.taskChanges
|
|
3326
|
-
.pipe(filter(args => isPresent(args.timelineRow)), switchMap(args => this.zone.onStable.pipe(take(1), map(() => args))) // ensure the content is rendered
|
|
3327
|
-
)
|
|
3328
|
-
.subscribe(({ timelineRow }) => {
|
|
3329
|
-
const timelineRowHeight = isDocumentAvailable() ? timelineRow.getBoundingClientRect().height : 0;
|
|
3330
|
-
this.renderer.setStyle(this.timelineColumns.nativeElement, 'height', `${(this.rows || []).length * timelineRowHeight}px`);
|
|
3331
|
-
}));
|
|
3332
|
-
}
|
|
3333
|
-
ngAfterViewInit() {
|
|
3334
|
-
const timelineHeader = this.timelineHeaderWrap.nativeElement;
|
|
3335
|
-
const rightContainer = this.timelineContent.nativeElement;
|
|
3336
|
-
this.scrollSyncService.registerElement(rightContainer, 'timeline');
|
|
3337
|
-
this.scrollSyncService.registerElement(timelineHeader, 'header');
|
|
3338
|
-
this.dependencyDomService.registerContentContainer(this.tasksContainer.nativeElement);
|
|
3339
|
-
}
|
|
3340
|
-
ngOnDestroy() {
|
|
3341
|
-
this.subscriptions.unsubscribe();
|
|
3342
|
-
}
|
|
3343
|
-
isNonWorking(item) {
|
|
3344
|
-
return item.hasOwnProperty('isWorking') && !item.isWorking;
|
|
3345
|
-
}
|
|
3346
|
-
};
|
|
3347
|
-
__decorate([
|
|
3348
|
-
ViewChild('timelineContent', { static: true }),
|
|
3349
|
-
__metadata("design:type", ElementRef)
|
|
3350
|
-
], GanttTimelineComponent.prototype, "timelineContent", void 0);
|
|
3351
|
-
__decorate([
|
|
3352
|
-
ViewChild('timelineColumns', { static: true }),
|
|
3353
|
-
__metadata("design:type", ElementRef)
|
|
3354
|
-
], GanttTimelineComponent.prototype, "timelineColumns", void 0);
|
|
3355
|
-
__decorate([
|
|
3356
|
-
ViewChild('timelineHeaderWrap', { static: true }),
|
|
3357
|
-
__metadata("design:type", ElementRef)
|
|
3358
|
-
], GanttTimelineComponent.prototype, "timelineHeaderWrap", void 0);
|
|
3359
|
-
__decorate([
|
|
3360
|
-
ViewChild('tasksContainer', { static: true }),
|
|
3361
|
-
__metadata("design:type", ElementRef)
|
|
3362
|
-
], GanttTimelineComponent.prototype, "tasksContainer", void 0);
|
|
3363
|
-
__decorate([
|
|
3364
|
-
HostBinding('class.k-gantt-timeline'),
|
|
3365
|
-
__metadata("design:type", Boolean)
|
|
3366
|
-
], GanttTimelineComponent.prototype, "hostClass", void 0);
|
|
3367
|
-
__decorate([
|
|
3368
|
-
Input(),
|
|
3369
|
-
__metadata("design:type", Array)
|
|
3370
|
-
], GanttTimelineComponent.prototype, "rows", void 0);
|
|
3371
|
-
__decorate([
|
|
3372
|
-
Input(),
|
|
3373
|
-
__metadata("design:type", Array)
|
|
3374
|
-
], GanttTimelineComponent.prototype, "slots", void 0);
|
|
3375
|
-
__decorate([
|
|
3376
|
-
Input(),
|
|
3377
|
-
__metadata("design:type", Array)
|
|
3378
|
-
], GanttTimelineComponent.prototype, "groupSlots", void 0);
|
|
3379
|
-
__decorate([
|
|
3380
|
-
Input(),
|
|
3381
|
-
__metadata("design:type", Number)
|
|
3382
|
-
], GanttTimelineComponent.prototype, "tableWidth", void 0);
|
|
3383
|
-
__decorate([
|
|
3384
|
-
Input(),
|
|
3385
|
-
__metadata("design:type", String)
|
|
3386
|
-
], GanttTimelineComponent.prototype, "activeView", void 0);
|
|
3387
|
-
__decorate([
|
|
3388
|
-
Input(),
|
|
3389
|
-
__metadata("design:type", TemplateRef)
|
|
3390
|
-
], GanttTimelineComponent.prototype, "taskContentTemplate", void 0);
|
|
3391
|
-
__decorate([
|
|
3392
|
-
Input(),
|
|
3393
|
-
__metadata("design:type", TemplateRef)
|
|
3394
|
-
], GanttTimelineComponent.prototype, "taskTemplate", void 0);
|
|
3395
|
-
__decorate([
|
|
3396
|
-
Input(),
|
|
3397
|
-
__metadata("design:type", TemplateRef)
|
|
3398
|
-
], GanttTimelineComponent.prototype, "summaryTaskTemplate", void 0);
|
|
3399
|
-
__decorate([
|
|
3400
|
-
Input(),
|
|
3401
|
-
__metadata("design:type", Function)
|
|
3402
|
-
], GanttTimelineComponent.prototype, "taskClass", void 0);
|
|
3403
|
-
__decorate([
|
|
3404
|
-
Input(),
|
|
3405
|
-
__metadata("design:type", Function)
|
|
3406
|
-
], GanttTimelineComponent.prototype, "isTaskSelected", void 0);
|
|
3407
|
-
__decorate([
|
|
3408
|
-
Input(),
|
|
3409
|
-
__metadata("design:type", Function)
|
|
3410
|
-
], GanttTimelineComponent.prototype, "hasChildren", void 0);
|
|
3411
|
-
__decorate([
|
|
3412
|
-
Input(),
|
|
3413
|
-
__metadata("design:type", Array)
|
|
3414
|
-
], GanttTimelineComponent.prototype, "dependencies", void 0);
|
|
3415
|
-
GanttTimelineComponent = __decorate([
|
|
3416
|
-
Component({
|
|
3417
|
-
selector: 'kendo-gantt-timeline',
|
|
3418
|
-
template: `
|
|
3419
|
-
<div class="k-timeline k-grid k-widget">
|
|
3420
|
-
<div class="k-grid-header">
|
|
3421
|
-
<div #timelineHeaderWrap class="k-grid-header-wrap">
|
|
3422
|
-
<table
|
|
3423
|
-
role="presentation"
|
|
3424
|
-
[style.width.px]="tableWidth"
|
|
3425
|
-
>
|
|
3426
|
-
<tbody
|
|
3427
|
-
kendoGanttHeaderTableBody
|
|
3428
|
-
[groupSlots]="groupSlots"
|
|
3429
|
-
[slots]="slots">
|
|
3430
|
-
</tbody>
|
|
3431
|
-
</table>
|
|
3432
|
-
</div>
|
|
3433
|
-
</div>
|
|
3434
|
-
<div #timelineContent class="k-grid-content">
|
|
3435
|
-
<div class="k-gantt-tables">
|
|
3436
|
-
<table
|
|
3437
|
-
class="k-gantt-rows"
|
|
3438
|
-
[style.width.px]="tableWidth"
|
|
3439
|
-
role="presentation"
|
|
3440
|
-
>
|
|
3441
|
-
<tbody>
|
|
3442
|
-
<tr *ngFor="let item of rows; let i = index;"
|
|
3443
|
-
[class.k-alt]="i % 2"
|
|
3444
|
-
>
|
|
3445
|
-
<td></td>
|
|
3446
|
-
</tr>
|
|
3447
|
-
</tbody>
|
|
3448
|
-
</table>
|
|
3449
|
-
|
|
3450
|
-
<table
|
|
3451
|
-
#timelineColumns
|
|
3452
|
-
class="k-gantt-columns"
|
|
3453
|
-
role="presentation"
|
|
3454
|
-
[style.width.px]="tableWidth"
|
|
3455
|
-
>
|
|
3456
|
-
<colgroup>
|
|
3457
|
-
<col *ngFor="let item of slots">
|
|
3458
|
-
</colgroup>
|
|
3459
|
-
|
|
3460
|
-
<tbody>
|
|
3461
|
-
<tr>
|
|
3462
|
-
<td *ngFor="let item of slots"
|
|
3463
|
-
[class.k-nonwork-hour]="isNonWorking(item)"
|
|
3464
|
-
>
|
|
3465
|
-
</td>
|
|
3466
|
-
</tr>
|
|
3467
|
-
</tbody>
|
|
3468
|
-
</table>
|
|
3469
|
-
|
|
3470
|
-
<table
|
|
3471
|
-
#tasksContainer
|
|
3472
|
-
class="k-gantt-tasks"
|
|
3473
|
-
role="presentation"
|
|
3474
|
-
style="border-collapse: collapse;"
|
|
3475
|
-
[style.width.px]="tableWidth"
|
|
3476
|
-
>
|
|
3477
|
-
<tbody
|
|
3478
|
-
kendoGanttTasksTableBody
|
|
3479
|
-
[rows]="rows"
|
|
3480
|
-
[activeView]="activeView"
|
|
3481
|
-
[taskContentTemplate]="taskContentTemplate"
|
|
3482
|
-
[taskTemplate]="taskTemplate"
|
|
3483
|
-
[summaryTaskTemplate]="summaryTaskTemplate"
|
|
3484
|
-
[taskClass]="taskClass"
|
|
3485
|
-
[hasChildren]="hasChildren"
|
|
3486
|
-
[isTaskSelected]="isTaskSelected"
|
|
3487
|
-
>
|
|
3488
|
-
</tbody>
|
|
3489
|
-
</table>
|
|
3490
|
-
</div>
|
|
3491
|
-
<svg class="k-gantt-dependencies-svg">
|
|
3492
|
-
<polyline
|
|
3493
|
-
*ngFor="let dependency of dependencies"
|
|
3494
|
-
kendoGanttDependency
|
|
3495
|
-
[dependency]="dependency"
|
|
3496
|
-
/>
|
|
3497
|
-
</svg>
|
|
3498
|
-
</div>
|
|
3499
|
-
</div>
|
|
3500
|
-
`
|
|
3501
|
-
}),
|
|
3502
|
-
__metadata("design:paramtypes", [ScrollSyncService,
|
|
3503
|
-
DependencyDomService,
|
|
3504
|
-
Renderer2,
|
|
3505
|
-
NgZone])
|
|
3506
|
-
], GanttTimelineComponent);
|
|
3894
|
+
const TOUCH_ENABLED = new InjectionToken('gantt-touch-enabled');
|
|
3507
3895
|
|
|
3508
3896
|
/**
|
|
3509
3897
|
* @hidden
|
|
@@ -3561,6 +3949,10 @@ __decorate([
|
|
|
3561
3949
|
Input(),
|
|
3562
3950
|
__metadata("design:type", Function)
|
|
3563
3951
|
], GanttTasksTableBodyComponent.prototype, "isTaskSelected", void 0);
|
|
3952
|
+
__decorate([
|
|
3953
|
+
Input(),
|
|
3954
|
+
__metadata("design:type", Boolean)
|
|
3955
|
+
], GanttTasksTableBodyComponent.prototype, "renderDependencyDragClues", void 0);
|
|
3564
3956
|
GanttTasksTableBodyComponent = __decorate([
|
|
3565
3957
|
Component({
|
|
3566
3958
|
selector: '[kendoGanttTasksTableBody]',
|
|
@@ -3573,7 +3965,8 @@ GanttTasksTableBodyComponent = __decorate([
|
|
|
3573
3965
|
[activeView]="activeView"
|
|
3574
3966
|
[taskClass]="taskClass"
|
|
3575
3967
|
[isSelected]="isTaskSelected"
|
|
3576
|
-
[index]="index"
|
|
3968
|
+
[attr.data-task-index]="index"
|
|
3969
|
+
[renderDependencyDragClues]="renderDependencyDragClues"
|
|
3577
3970
|
>
|
|
3578
3971
|
</kendo-gantt-milestone-task>
|
|
3579
3972
|
<ng-template #task>
|
|
@@ -3584,7 +3977,8 @@ GanttTasksTableBodyComponent = __decorate([
|
|
|
3584
3977
|
[activeView]="activeView"
|
|
3585
3978
|
[taskClass]="taskClass"
|
|
3586
3979
|
[isSelected]="isTaskSelected"
|
|
3587
|
-
[index]="index"
|
|
3980
|
+
[attr.data-task-index]="index"
|
|
3981
|
+
[renderDependencyDragClues]="renderDependencyDragClues"
|
|
3588
3982
|
>
|
|
3589
3983
|
</kendo-gantt-summary-task>
|
|
3590
3984
|
<kendo-gantt-task
|
|
@@ -3595,7 +3989,8 @@ GanttTasksTableBodyComponent = __decorate([
|
|
|
3595
3989
|
[activeView]="activeView"
|
|
3596
3990
|
[taskClass]="taskClass"
|
|
3597
3991
|
[isSelected]="isTaskSelected"
|
|
3598
|
-
[index]="index"
|
|
3992
|
+
[attr.data-task-index]="index"
|
|
3993
|
+
[renderDependencyDragClues]="renderDependencyDragClues"
|
|
3599
3994
|
>
|
|
3600
3995
|
</kendo-gantt-task>
|
|
3601
3996
|
</ng-template>
|
|
@@ -3666,29 +4061,18 @@ class GanttTaskBase {
|
|
|
3666
4061
|
get slotWidth() {
|
|
3667
4062
|
return this.viewService.options.slotWidth;
|
|
3668
4063
|
}
|
|
3669
|
-
ngOnChanges(changes) {
|
|
3670
|
-
if (isPresent(changes.dataItem)) {
|
|
3671
|
-
if (isPresent(changes.dataItem.previousValue)) {
|
|
3672
|
-
this.dependencyDomService.unregisterTask(changes.dataItem.previousValue);
|
|
3673
|
-
}
|
|
3674
|
-
this.dependencyDomService.registerTask(this.dataItem, this.taskElement.nativeElement);
|
|
3675
|
-
}
|
|
3676
|
-
else if (isPresent(changes.activeView)) {
|
|
3677
|
-
this.dependencyDomService.notifyChanges();
|
|
3678
|
-
}
|
|
3679
|
-
}
|
|
3680
|
-
ngOnDestroy() {
|
|
3681
|
-
if (isPresent(this.dataItem)) {
|
|
3682
|
-
this.dependencyDomService.unregisterTask(this.dataItem);
|
|
3683
|
-
}
|
|
3684
|
-
this.viewChangesSubscription.unsubscribe();
|
|
3685
|
-
}
|
|
3686
4064
|
get taskWidth() {
|
|
3687
4065
|
const itemDuration = this.mapper.extractFromTask(this.dataItem, 'end') - this.mapper.extractFromTask(this.dataItem, 'start');
|
|
3688
4066
|
const durationInSlotUnits = itemDuration / this.slotUnitDuration;
|
|
3689
4067
|
const width = durationInSlotUnits * this.slotWidth;
|
|
3690
4068
|
return width;
|
|
3691
4069
|
}
|
|
4070
|
+
/**
|
|
4071
|
+
* The `left` style prop has to be applied to the host element (.k-task-wrap), as the drag clue elements are displayed on .k-task-wrap hover.
|
|
4072
|
+
* Applying the `left` offset to the inner .k-task element leaves the .k-task-wrap element rendered with an offset of 0 somewhere on the left
|
|
4073
|
+
* and hovering just the .k-task element doesn't expose the drag clues.
|
|
4074
|
+
* Additionally, positioning the entire container takes care of positioning the hints as well.
|
|
4075
|
+
*/
|
|
3692
4076
|
get taskOffset() {
|
|
3693
4077
|
const timeAfterViewStart = this.mapper.extractFromTask(this.dataItem, 'start') - this.viewService.viewStart;
|
|
3694
4078
|
const offsetInSlotUnits = timeAfterViewStart / this.slotUnitDuration;
|
|
@@ -3700,6 +4084,23 @@ class GanttTaskBase {
|
|
|
3700
4084
|
// fall-back to 0 in case no completionRatio is provided
|
|
3701
4085
|
return isNumber(overlayWidth) ? overlayWidth : 0;
|
|
3702
4086
|
}
|
|
4087
|
+
ngOnChanges(changes) {
|
|
4088
|
+
if (isPresent(changes.dataItem)) {
|
|
4089
|
+
if (isPresent(changes.dataItem.previousValue)) {
|
|
4090
|
+
this.dependencyDomService.unregisterTask(changes.dataItem.previousValue);
|
|
4091
|
+
}
|
|
4092
|
+
this.dependencyDomService.registerTask(this.dataItem, this.taskElement.nativeElement);
|
|
4093
|
+
}
|
|
4094
|
+
else if (isPresent(changes.activeView)) {
|
|
4095
|
+
this.dependencyDomService.notifyChanges();
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
ngOnDestroy() {
|
|
4099
|
+
if (isPresent(this.dataItem)) {
|
|
4100
|
+
this.dependencyDomService.unregisterTask(this.dataItem);
|
|
4101
|
+
}
|
|
4102
|
+
this.viewChangesSubscription.unsubscribe();
|
|
4103
|
+
}
|
|
3703
4104
|
}
|
|
3704
4105
|
__decorate([
|
|
3705
4106
|
HostBinding('class.k-task-wrap'),
|
|
@@ -3715,8 +4116,8 @@ __decorate([
|
|
|
3715
4116
|
], GanttTaskBase.prototype, "dataItem", void 0);
|
|
3716
4117
|
__decorate([
|
|
3717
4118
|
Input(),
|
|
3718
|
-
__metadata("design:type",
|
|
3719
|
-
], GanttTaskBase.prototype, "
|
|
4119
|
+
__metadata("design:type", Boolean)
|
|
4120
|
+
], GanttTaskBase.prototype, "renderDependencyDragClues", void 0);
|
|
3720
4121
|
__decorate([
|
|
3721
4122
|
Input(),
|
|
3722
4123
|
__metadata("design:type", Function)
|
|
@@ -3729,15 +4130,21 @@ __decorate([
|
|
|
3729
4130
|
Input(),
|
|
3730
4131
|
__metadata("design:type", Function)
|
|
3731
4132
|
], GanttTaskBase.prototype, "taskClass", void 0);
|
|
4133
|
+
__decorate([
|
|
4134
|
+
HostBinding('style.left.px'),
|
|
4135
|
+
__metadata("design:type", Number),
|
|
4136
|
+
__metadata("design:paramtypes", [])
|
|
4137
|
+
], GanttTaskBase.prototype, "taskOffset", null);
|
|
3732
4138
|
|
|
3733
4139
|
var GanttTaskComponent_1;
|
|
3734
4140
|
/**
|
|
3735
4141
|
* @hidden
|
|
3736
4142
|
*/
|
|
3737
4143
|
let GanttTaskComponent = GanttTaskComponent_1 = class GanttTaskComponent extends GanttTaskBase {
|
|
3738
|
-
constructor(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr
|
|
4144
|
+
constructor(editService, touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
|
|
3739
4145
|
super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr);
|
|
3740
4146
|
this.editService = editService;
|
|
4147
|
+
this.touchEnabled = touchEnabled$$1;
|
|
3741
4148
|
}
|
|
3742
4149
|
onTaskDelete() {
|
|
3743
4150
|
this.editService.dataItem = this.dataItem;
|
|
@@ -3767,9 +4174,7 @@ GanttTaskComponent = GanttTaskComponent_1 = __decorate([
|
|
|
3767
4174
|
class="k-task k-task-single"
|
|
3768
4175
|
[ngClass]="taskClass(dataItem)"
|
|
3769
4176
|
[style.width.px]="taskWidth"
|
|
3770
|
-
[style.left.px]="taskOffset"
|
|
3771
4177
|
[attr.title]="mapper.extractFromTask(dataItem, 'title')"
|
|
3772
|
-
[attr.data-task-index]="index"
|
|
3773
4178
|
[class.k-state-selected]="isSelected(dataItem)"
|
|
3774
4179
|
>
|
|
3775
4180
|
<ng-container *ngIf="!taskTemplate">
|
|
@@ -3809,14 +4214,26 @@ GanttTaskComponent = GanttTaskComponent_1 = __decorate([
|
|
|
3809
4214
|
>
|
|
3810
4215
|
</ng-template>
|
|
3811
4216
|
</div>
|
|
4217
|
+
<ng-container *ngIf="renderDependencyDragClues">
|
|
4218
|
+
<div
|
|
4219
|
+
class="k-task-dot k-task-start k-touch-action-none"
|
|
4220
|
+
[class.k-display-block]="touchEnabled"
|
|
4221
|
+
>
|
|
4222
|
+
</div>
|
|
4223
|
+
<div
|
|
4224
|
+
class="k-task-dot k-task-end k-touch-action-none"
|
|
4225
|
+
[class.k-display-block]="touchEnabled"
|
|
4226
|
+
>
|
|
4227
|
+
</div>
|
|
4228
|
+
</ng-container>
|
|
3812
4229
|
`
|
|
3813
4230
|
}),
|
|
3814
|
-
|
|
4231
|
+
__param(1, Inject(TOUCH_ENABLED)),
|
|
4232
|
+
__metadata("design:paramtypes", [EditService, Boolean, MappingService,
|
|
3815
4233
|
TimelineViewService,
|
|
3816
4234
|
DependencyDomService,
|
|
3817
4235
|
OptionChangesService,
|
|
3818
|
-
ChangeDetectorRef
|
|
3819
|
-
EditService])
|
|
4236
|
+
ChangeDetectorRef])
|
|
3820
4237
|
], GanttTaskComponent);
|
|
3821
4238
|
|
|
3822
4239
|
var GanttSummaryTaskComponent_1;
|
|
@@ -3824,8 +4241,9 @@ var GanttSummaryTaskComponent_1;
|
|
|
3824
4241
|
* @hidden
|
|
3825
4242
|
*/
|
|
3826
4243
|
let GanttSummaryTaskComponent = GanttSummaryTaskComponent_1 = class GanttSummaryTaskComponent extends GanttTaskBase {
|
|
3827
|
-
constructor(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
|
|
4244
|
+
constructor(touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
|
|
3828
4245
|
super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr);
|
|
4246
|
+
this.touchEnabled = touchEnabled$$1;
|
|
3829
4247
|
this.summaryWrapperClass = true;
|
|
3830
4248
|
}
|
|
3831
4249
|
};
|
|
@@ -3852,9 +4270,7 @@ GanttSummaryTaskComponent = GanttSummaryTaskComponent_1 = __decorate([
|
|
|
3852
4270
|
class="k-task k-task-summary"
|
|
3853
4271
|
[ngClass]="taskClass(dataItem)"
|
|
3854
4272
|
[style.width.px]="taskWidth"
|
|
3855
|
-
[style.left.px]="taskOffset"
|
|
3856
4273
|
[attr.title]="mapper.extractFromTask(dataItem, 'title')"
|
|
3857
|
-
[attr.data-task-index]="index"
|
|
3858
4274
|
[class.k-state-selected]="isSelected(dataItem)"
|
|
3859
4275
|
>
|
|
3860
4276
|
<div *ngIf="!template; else summaryTemplate"
|
|
@@ -3876,9 +4292,22 @@ GanttSummaryTaskComponent = GanttSummaryTaskComponent_1 = __decorate([
|
|
|
3876
4292
|
>
|
|
3877
4293
|
</ng-template>
|
|
3878
4294
|
</div>
|
|
4295
|
+
<ng-container *ngIf="renderDependencyDragClues">
|
|
4296
|
+
<div
|
|
4297
|
+
class="k-task-dot k-task-start k-touch-action-none"
|
|
4298
|
+
[class.k-display-block]="touchEnabled"
|
|
4299
|
+
>
|
|
4300
|
+
</div>
|
|
4301
|
+
<div
|
|
4302
|
+
class="k-task-dot k-task-end k-touch-action-none"
|
|
4303
|
+
[class.k-display-block]="touchEnabled"
|
|
4304
|
+
>
|
|
4305
|
+
</div>
|
|
4306
|
+
</ng-container>
|
|
3879
4307
|
`
|
|
3880
4308
|
}),
|
|
3881
|
-
|
|
4309
|
+
__param(0, Inject(TOUCH_ENABLED)),
|
|
4310
|
+
__metadata("design:paramtypes", [Boolean, MappingService,
|
|
3882
4311
|
TimelineViewService,
|
|
3883
4312
|
DependencyDomService,
|
|
3884
4313
|
OptionChangesService,
|
|
@@ -3890,8 +4319,9 @@ var GanttMilestoneTaskComponent_1;
|
|
|
3890
4319
|
* @hidden
|
|
3891
4320
|
*/
|
|
3892
4321
|
let GanttMilestoneTaskComponent = GanttMilestoneTaskComponent_1 = class GanttMilestoneTaskComponent extends GanttTaskBase {
|
|
3893
|
-
constructor(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
|
|
4322
|
+
constructor(touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
|
|
3894
4323
|
super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr);
|
|
4324
|
+
this.touchEnabled = touchEnabled$$1;
|
|
3895
4325
|
this.milestoneWrapperClass = true;
|
|
3896
4326
|
}
|
|
3897
4327
|
};
|
|
@@ -3913,15 +4343,26 @@ GanttMilestoneTaskComponent = GanttMilestoneTaskComponent_1 = __decorate([
|
|
|
3913
4343
|
#task
|
|
3914
4344
|
class="k-task k-task-milestone"
|
|
3915
4345
|
[ngClass]="taskClass(dataItem)"
|
|
3916
|
-
[style.left.px]="taskOffset"
|
|
3917
4346
|
[attr.title]="mapper.extractFromTask(dataItem, 'title')"
|
|
3918
4347
|
[class.k-state-selected]="isSelected(dataItem)"
|
|
3919
|
-
[attr.data-task-index]="index"
|
|
3920
4348
|
>
|
|
3921
4349
|
</div>
|
|
4350
|
+
<ng-container *ngIf="renderDependencyDragClues">
|
|
4351
|
+
<div
|
|
4352
|
+
class="k-task-dot k-task-start k-touch-action-none"
|
|
4353
|
+
[class.k-display-block]="touchEnabled"
|
|
4354
|
+
>
|
|
4355
|
+
</div>
|
|
4356
|
+
<div
|
|
4357
|
+
class="k-task-dot k-task-end k-touch-action-none"
|
|
4358
|
+
[class.k-display-block]="touchEnabled"
|
|
4359
|
+
>
|
|
4360
|
+
</div>
|
|
4361
|
+
</ng-container>
|
|
3922
4362
|
`
|
|
3923
4363
|
}),
|
|
3924
|
-
|
|
4364
|
+
__param(0, Inject(TOUCH_ENABLED)),
|
|
4365
|
+
__metadata("design:paramtypes", [Boolean, MappingService,
|
|
3925
4366
|
TimelineViewService,
|
|
3926
4367
|
DependencyDomService,
|
|
3927
4368
|
OptionChangesService,
|
|
@@ -4254,23 +4695,6 @@ ViewSelectorComponent = __decorate([
|
|
|
4254
4695
|
__metadata("design:paramtypes", [LocalizationService])
|
|
4255
4696
|
], ViewSelectorComponent);
|
|
4256
4697
|
|
|
4257
|
-
/**
|
|
4258
|
-
* The dependency type when two tasks are connected.
|
|
4259
|
-
*
|
|
4260
|
-
* The supported values are:
|
|
4261
|
-
* * `FF`—from 'finish' to 'finish'
|
|
4262
|
-
* * `FS`—from 'finish' to 'start'
|
|
4263
|
-
* * `SS`—from 'start' to 'start'
|
|
4264
|
-
* * `SF`—from 'start' to 'finish'
|
|
4265
|
-
*/
|
|
4266
|
-
var DependencyType;
|
|
4267
|
-
(function (DependencyType) {
|
|
4268
|
-
DependencyType[DependencyType["FF"] = 0] = "FF";
|
|
4269
|
-
DependencyType[DependencyType["FS"] = 1] = "FS";
|
|
4270
|
-
DependencyType[DependencyType["SF"] = 2] = "SF";
|
|
4271
|
-
DependencyType[DependencyType["SS"] = 3] = "SS"; // task B can't start before task A starts
|
|
4272
|
-
})(DependencyType || (DependencyType = {}));
|
|
4273
|
-
|
|
4274
4698
|
/**
|
|
4275
4699
|
* @hidden
|
|
4276
4700
|
*
|
|
@@ -4281,6 +4705,9 @@ const getOffsetRelativeToParent = (element, targetParent) => {
|
|
|
4281
4705
|
top: 0,
|
|
4282
4706
|
left: 0
|
|
4283
4707
|
};
|
|
4708
|
+
if (!targetParent.contains(element)) {
|
|
4709
|
+
return offset;
|
|
4710
|
+
}
|
|
4284
4711
|
let offsetParent = element;
|
|
4285
4712
|
while (offsetParent && offsetParent !== targetParent) {
|
|
4286
4713
|
offset.top += offsetParent.offsetTop;
|
|
@@ -4427,6 +4854,37 @@ const getArrowEast = (top, left, arrowSize) => {
|
|
|
4427
4854
|
});
|
|
4428
4855
|
return points;
|
|
4429
4856
|
};
|
|
4857
|
+
/**
|
|
4858
|
+
* @hidden
|
|
4859
|
+
*
|
|
4860
|
+
* Translates the provided client `left` and `top` coords to coords relative to the provided container.
|
|
4861
|
+
* https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems#standard_cssom_coordinate_systems
|
|
4862
|
+
*/
|
|
4863
|
+
const clientToOffsetCoords = (clientLeft, clientTop, offsetContainer) => {
|
|
4864
|
+
// client (viewport) coordinates of the target container
|
|
4865
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#value
|
|
4866
|
+
const offsetContainerClientRect = offsetContainer.getBoundingClientRect();
|
|
4867
|
+
return {
|
|
4868
|
+
left: clientLeft - offsetContainerClientRect.left + offsetContainer.scrollLeft,
|
|
4869
|
+
top: clientTop - offsetContainerClientRect.top + offsetContainer.scrollTop
|
|
4870
|
+
};
|
|
4871
|
+
};
|
|
4872
|
+
/**
|
|
4873
|
+
* @hidden
|
|
4874
|
+
*
|
|
4875
|
+
* Retrieves the `left` and `top` values of the center of the provided element.
|
|
4876
|
+
* The retrieved values are relative to the current viewport (client values).
|
|
4877
|
+
* https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems#standard_cssom_coordinate_systems
|
|
4878
|
+
*/
|
|
4879
|
+
const getElementClientCenterCoords = (element) => {
|
|
4880
|
+
// client (viewport) coordinates of the targeted element
|
|
4881
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#value
|
|
4882
|
+
const { left, top, width, height } = element.getBoundingClientRect();
|
|
4883
|
+
return {
|
|
4884
|
+
left: left + (width / 2),
|
|
4885
|
+
top: top + (height / 2)
|
|
4886
|
+
};
|
|
4887
|
+
};
|
|
4430
4888
|
|
|
4431
4889
|
/**
|
|
4432
4890
|
* Defines the size of the arrow that will be drawn at the end of each Gantt dependency.
|
|
@@ -4502,6 +4960,540 @@ GanttDependencyDirective = __decorate([
|
|
|
4502
4960
|
DependencyDomService])
|
|
4503
4961
|
], GanttDependencyDirective);
|
|
4504
4962
|
|
|
4963
|
+
/**
|
|
4964
|
+
* @hidden
|
|
4965
|
+
*/
|
|
4966
|
+
let DragValidationTooltipComponent = class DragValidationTooltipComponent {
|
|
4967
|
+
/**
|
|
4968
|
+
* @hidden
|
|
4969
|
+
*/
|
|
4970
|
+
constructor() {
|
|
4971
|
+
/**
|
|
4972
|
+
* Sets the status class of the attempted operation.
|
|
4973
|
+
* Note that the status will be ignored and the `neutral` status class will be rendered,
|
|
4974
|
+
* if the any of the fromTaskName or toTaskName are not populated.
|
|
4975
|
+
*/
|
|
4976
|
+
this.isValid = false;
|
|
4977
|
+
}
|
|
4978
|
+
};
|
|
4979
|
+
DragValidationTooltipComponent = __decorate([
|
|
4980
|
+
Component({
|
|
4981
|
+
template: `
|
|
4982
|
+
<div
|
|
4983
|
+
class="k-tooltip k-gantt-tooltip-validation"
|
|
4984
|
+
[class.k-gantt-tooltip-valid]="showValidityStatus && isValid"
|
|
4985
|
+
[class.k-gantt-tooltip-invalid]="showValidityStatus && !isValid"
|
|
4986
|
+
>
|
|
4987
|
+
<div class="k-gantt-tooltip-validation-row">
|
|
4988
|
+
<span class="k-gantt-tooltip-validation-label">From:</span>
|
|
4989
|
+
<span class="k-gantt-tooltip-validation-value">{{ fromTaskName }}</span>
|
|
4990
|
+
</div>
|
|
4991
|
+
<div class="k-gantt-tooltip-validation-row">
|
|
4992
|
+
<span class="k-gantt-tooltip-validation-label">To:</span>
|
|
4993
|
+
<span class="k-gantt-tooltip-validation-value">{{ toTaskName }}</span>
|
|
4994
|
+
</div>
|
|
4995
|
+
</div>
|
|
4996
|
+
`,
|
|
4997
|
+
styles: [`
|
|
4998
|
+
.k-gantt-tooltip-validation {
|
|
4999
|
+
max-width: 200px;
|
|
5000
|
+
display: block;
|
|
5001
|
+
}
|
|
5002
|
+
.k-gantt-tooltip-validation::before {
|
|
5003
|
+
content: '';
|
|
5004
|
+
position: absolute;
|
|
5005
|
+
left: 0;
|
|
5006
|
+
top: 0;
|
|
5007
|
+
width: 4px;
|
|
5008
|
+
height: 100%;
|
|
5009
|
+
background: #656565;
|
|
5010
|
+
}
|
|
5011
|
+
.k-gantt-tooltip-validation.k-gantt-tooltip-valid::before {
|
|
5012
|
+
background: #37B400;
|
|
5013
|
+
}
|
|
5014
|
+
.k-gantt-tooltip-validation.k-gantt-tooltip-invalid::before {
|
|
5015
|
+
background: #F31700;
|
|
5016
|
+
}
|
|
5017
|
+
.k-gantt-tooltip-validation-row {
|
|
5018
|
+
white-space: nowrap;
|
|
5019
|
+
overflow: hidden;
|
|
5020
|
+
text-overflow: ellipsis;
|
|
5021
|
+
}
|
|
5022
|
+
.k-gantt-tooltip-validation-label {
|
|
5023
|
+
display: inline-flex;
|
|
5024
|
+
width: 50px;
|
|
5025
|
+
}
|
|
5026
|
+
.k-gantt-tooltip-validation-value {
|
|
5027
|
+
font-weight: bold;
|
|
5028
|
+
}
|
|
5029
|
+
`]
|
|
5030
|
+
})
|
|
5031
|
+
], DragValidationTooltipComponent);
|
|
5032
|
+
|
|
5033
|
+
/**
|
|
5034
|
+
* When added to the .k-task-dot, the element will be kept with hover styles.
|
|
5035
|
+
* Used for the drag clue from which the dragging has started.
|
|
5036
|
+
*/
|
|
5037
|
+
const DRAG_CLUE_HOVER_CLASS = 'k-state-hover';
|
|
5038
|
+
/**
|
|
5039
|
+
* Add the selection disabling class to the enitre container.
|
|
5040
|
+
* Otherwise existing selection on a given task text prevents dragging the clue even if the clue has `user-select: none` styles.
|
|
5041
|
+
*/
|
|
5042
|
+
const USER_SELECT_NONE_CLASS = 'k-user-select-none';
|
|
5043
|
+
/**
|
|
5044
|
+
* When added to the .k-task-wrap, the containing .k-task-dot elements will be kept visible even when not hovered.
|
|
5045
|
+
* Used for the drag clue from which the dragging has started.
|
|
5046
|
+
*/
|
|
5047
|
+
const TASK_WRAPPER_DRAG_CLASS = 'k-origin';
|
|
5048
|
+
/**
|
|
5049
|
+
* Use 20px margin between the pointer and the popup.
|
|
5050
|
+
* Could be made user-configurable if there's demand.
|
|
5051
|
+
*/
|
|
5052
|
+
const DEFAULT_POPUP_VERTICAL_MARGIN = 20;
|
|
5053
|
+
/**
|
|
5054
|
+
* A directive which enables the creation of new dependencies via dragging.
|
|
5055
|
+
*/
|
|
5056
|
+
let DependencyDragCreateDirective = class DependencyDragCreateDirective {
|
|
5057
|
+
constructor(gantt, zone, renderer, mapper, popupService, timelineScrollService) {
|
|
5058
|
+
this.gantt = gantt;
|
|
5059
|
+
this.zone = zone;
|
|
5060
|
+
this.renderer = renderer;
|
|
5061
|
+
this.mapper = mapper;
|
|
5062
|
+
this.popupService = popupService;
|
|
5063
|
+
this.timelineScrollService = timelineScrollService;
|
|
5064
|
+
/**
|
|
5065
|
+
* Specifies whether the validation tooltip will be displayed during drag operations.
|
|
5066
|
+
*
|
|
5067
|
+
* @default true
|
|
5068
|
+
*/
|
|
5069
|
+
this.displayValidationTooltip = true;
|
|
5070
|
+
this.gantt.renderDependencyDragClues = true;
|
|
5071
|
+
}
|
|
5072
|
+
get container() {
|
|
5073
|
+
if (!isPresent(this.gantt.timeline) || !isPresent(this.gantt.timeline.timelineContent)) {
|
|
5074
|
+
return null;
|
|
5075
|
+
}
|
|
5076
|
+
return this.gantt.timeline.timelineContent.nativeElement;
|
|
5077
|
+
}
|
|
5078
|
+
get polyline() {
|
|
5079
|
+
if (!isPresent(this.gantt.timeline) || !isPresent(this.gantt.timeline.dependencyDragCreatePolyline)) {
|
|
5080
|
+
return null;
|
|
5081
|
+
}
|
|
5082
|
+
return this.gantt.timeline.dependencyDragCreatePolyline.nativeElement;
|
|
5083
|
+
}
|
|
5084
|
+
get popupContainer() {
|
|
5085
|
+
if (!isPresent(this.gantt.timeline) || !isPresent(this.gantt.timeline.dragPopupContainer)) {
|
|
5086
|
+
return null;
|
|
5087
|
+
}
|
|
5088
|
+
return this.gantt.timeline.dragPopupContainer;
|
|
5089
|
+
}
|
|
5090
|
+
ngAfterViewInit() {
|
|
5091
|
+
this.subscribeDraggable();
|
|
5092
|
+
this.addScrollListener();
|
|
5093
|
+
}
|
|
5094
|
+
ngOnDestroy() {
|
|
5095
|
+
this.unsubscribeDraggable();
|
|
5096
|
+
this.removeScrollListener();
|
|
5097
|
+
this.fromTaskClue = null;
|
|
5098
|
+
this.cancelScroll();
|
|
5099
|
+
this.closeDragPopup();
|
|
5100
|
+
}
|
|
5101
|
+
subscribeDraggable() {
|
|
5102
|
+
this.dragSubscriptions = this.gantt.timeline.timelineContainerPress
|
|
5103
|
+
.subscribe(this.handlePress.bind(this));
|
|
5104
|
+
this.dragSubscriptions.add(this.gantt.timeline.timelineContainerDrag
|
|
5105
|
+
.subscribe(this.handleDrag.bind(this)));
|
|
5106
|
+
this.dragSubscriptions.add(this.gantt.timeline.timelineContainerRelease
|
|
5107
|
+
.subscribe(this.handleRelease.bind(this)));
|
|
5108
|
+
}
|
|
5109
|
+
unsubscribeDraggable() {
|
|
5110
|
+
if (isPresent(this.dragSubscriptions)) {
|
|
5111
|
+
this.dragSubscriptions.unsubscribe();
|
|
5112
|
+
this.dragSubscriptions = null;
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5115
|
+
handlePress({ clientX, clientY }) {
|
|
5116
|
+
// using `originalEvent.target` is not reliable under mobile devices with the current implementation of the draggable, so use this instead
|
|
5117
|
+
const target = elementFromPoint(clientX, clientY);
|
|
5118
|
+
if (isDependencyDragClue(target)) {
|
|
5119
|
+
this.fromTaskClue = target;
|
|
5120
|
+
this.assignDragStartClasses(this.fromTaskClue);
|
|
5121
|
+
// use the center of the target clue as polyline starting point
|
|
5122
|
+
const dragClueCenterCoords = getElementClientCenterCoords(this.fromTaskClue);
|
|
5123
|
+
// the polyline uses `position: aboslute`, so translate the client coordinates to offset coordinates (`left` and `top` relative to the timeline container)
|
|
5124
|
+
this.polylineStartCoords = clientToOffsetCoords(dragClueCenterCoords.left, dragClueCenterCoords.top, this.container);
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
handleDrag({ clientX, clientY }) {
|
|
5128
|
+
if (isPresent(this.fromTaskClue)) {
|
|
5129
|
+
// the polyline uses `position: aboslute`, so translate the client coordinates to offset coordinates (`left` and `top` relative to the timeline container)
|
|
5130
|
+
const pointerOffsetCoords = clientToOffsetCoords(clientX, clientY, this.container);
|
|
5131
|
+
// the start coords are calculated just once per drag session in handlePress
|
|
5132
|
+
// use the current drag coords as polyline end coords
|
|
5133
|
+
this.updatePolyline(this.polylineStartCoords, pointerOffsetCoords);
|
|
5134
|
+
this.currentPointerClientCoords = { left: clientX, top: clientY };
|
|
5135
|
+
if (this.gantt.dragScrollSettings.enabled) {
|
|
5136
|
+
// use client coordinates for scroll trigger
|
|
5137
|
+
this.scrollPointIntoView(this.currentPointerClientCoords);
|
|
5138
|
+
}
|
|
5139
|
+
if (this.displayValidationTooltip) {
|
|
5140
|
+
this.updateDragPopup(pointerOffsetCoords);
|
|
5141
|
+
}
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
handleRelease({ clientX, clientY }) {
|
|
5145
|
+
if (!isPresent(this.fromTaskClue)) {
|
|
5146
|
+
return;
|
|
5147
|
+
}
|
|
5148
|
+
// using `originalEvent.target` is not reliable under mobile devices with the current implementation of the draggable, so use this instead
|
|
5149
|
+
const target = elementFromPoint(clientX, clientY);
|
|
5150
|
+
if (isDependencyDragClue(target) && !sameTaskClues(this.fromTaskClue, target, this.container)) {
|
|
5151
|
+
this.zone.run(() => {
|
|
5152
|
+
const fromTaskClue = this.fromTaskClue;
|
|
5153
|
+
const toTaskClue = target;
|
|
5154
|
+
const fromTask = this.gantt.renderedTreeListItems[getClosestTaskIndex(fromTaskClue, this.container)];
|
|
5155
|
+
const toTask = this.gantt.renderedTreeListItems[getClosestTaskIndex(toTaskClue, this.container)];
|
|
5156
|
+
const dependencyType = getDependencyTypeFromTargetTasks(fromTaskClue, toTaskClue);
|
|
5157
|
+
const { fromId, toId, type } = this.mapper.dependencyFields;
|
|
5158
|
+
this.gantt.dependencyAdd.emit({
|
|
5159
|
+
fromTask: fromTask,
|
|
5160
|
+
toTask: toTask,
|
|
5161
|
+
type: dependencyType,
|
|
5162
|
+
isValid: this.gantt.validateNewDependency({
|
|
5163
|
+
[fromId]: this.mapper.extractFromTask(fromTask, 'id'),
|
|
5164
|
+
[toId]: this.mapper.extractFromTask(toTask, 'id'),
|
|
5165
|
+
[type]: dependencyType
|
|
5166
|
+
})
|
|
5167
|
+
});
|
|
5168
|
+
});
|
|
5169
|
+
}
|
|
5170
|
+
this.clearPolyline();
|
|
5171
|
+
this.removeDragStartClasses(this.fromTaskClue);
|
|
5172
|
+
this.fromTaskClue = null;
|
|
5173
|
+
this.cancelScroll();
|
|
5174
|
+
this.closeDragPopup();
|
|
5175
|
+
}
|
|
5176
|
+
updatePolyline(start, end) {
|
|
5177
|
+
const points = `${start.left},${start.top} ${end.left},${end.top}`;
|
|
5178
|
+
this.renderer.setAttribute(this.polyline, 'points', points);
|
|
5179
|
+
}
|
|
5180
|
+
clearPolyline() {
|
|
5181
|
+
this.renderer.removeAttribute(this.polyline, 'points');
|
|
5182
|
+
}
|
|
5183
|
+
assignDragStartClasses(dragClue) {
|
|
5184
|
+
if (!isPresent(dragClue)) {
|
|
5185
|
+
return;
|
|
5186
|
+
}
|
|
5187
|
+
this.renderer.addClass(this.container, USER_SELECT_NONE_CLASS);
|
|
5188
|
+
this.renderer.addClass(dragClue, DRAG_CLUE_HOVER_CLASS);
|
|
5189
|
+
const taskWrapper = getClosestTaskWrapper(dragClue, this.container);
|
|
5190
|
+
if (isPresent(taskWrapper)) {
|
|
5191
|
+
this.renderer.addClass(taskWrapper, TASK_WRAPPER_DRAG_CLASS);
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
removeDragStartClasses(dragClue) {
|
|
5195
|
+
if (!isPresent(dragClue)) {
|
|
5196
|
+
return;
|
|
5197
|
+
}
|
|
5198
|
+
this.renderer.removeClass(this.container, USER_SELECT_NONE_CLASS);
|
|
5199
|
+
this.renderer.removeClass(dragClue, DRAG_CLUE_HOVER_CLASS);
|
|
5200
|
+
const taskWrapper = getClosestTaskWrapper(dragClue, this.container);
|
|
5201
|
+
if (isPresent(taskWrapper)) {
|
|
5202
|
+
this.renderer.removeClass(taskWrapper, TASK_WRAPPER_DRAG_CLASS);
|
|
5203
|
+
}
|
|
5204
|
+
}
|
|
5205
|
+
scrollPointIntoView({ left, top }) {
|
|
5206
|
+
this.timelineScrollService.requestScrollCancel();
|
|
5207
|
+
this.timelineScrollService.requestHorizontalScroll(left);
|
|
5208
|
+
this.timelineScrollService.requestVerticalScroll(top);
|
|
5209
|
+
}
|
|
5210
|
+
cancelScroll() {
|
|
5211
|
+
this.timelineScrollService.requestScrollCancel();
|
|
5212
|
+
}
|
|
5213
|
+
addScrollListener() {
|
|
5214
|
+
if (!isDocumentAvailable()) {
|
|
5215
|
+
return;
|
|
5216
|
+
}
|
|
5217
|
+
this.zone.runOutsideAngular(() => this.scrollListenerDisposer = this.renderer.listen(this.container, 'scroll', () => {
|
|
5218
|
+
// update the polyline only if we're currently dragging
|
|
5219
|
+
if (isPresent(this.fromTaskClue) && isPresent(this.currentPointerClientCoords)) {
|
|
5220
|
+
const { left, top } = this.currentPointerClientCoords;
|
|
5221
|
+
const pointerOffsetCoords = clientToOffsetCoords(left, top, this.container);
|
|
5222
|
+
this.updatePolyline(this.polylineStartCoords, pointerOffsetCoords);
|
|
5223
|
+
if (this.displayValidationTooltip) {
|
|
5224
|
+
this.updateDragPopup(pointerOffsetCoords);
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
}));
|
|
5228
|
+
}
|
|
5229
|
+
removeScrollListener() {
|
|
5230
|
+
if (isPresent(this.scrollListenerDisposer)) {
|
|
5231
|
+
this.scrollListenerDisposer();
|
|
5232
|
+
this.scrollListenerDisposer = null;
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
openDragPopup() {
|
|
5236
|
+
if (isPresent(this.dragPopup)) {
|
|
5237
|
+
this.closeDragPopup();
|
|
5238
|
+
}
|
|
5239
|
+
this.dragPopup = this.popupService.open({
|
|
5240
|
+
animate: false,
|
|
5241
|
+
content: DragValidationTooltipComponent,
|
|
5242
|
+
appendTo: this.popupContainer,
|
|
5243
|
+
positionMode: 'absolute',
|
|
5244
|
+
popupClass: 'k-popup-transparent'
|
|
5245
|
+
});
|
|
5246
|
+
}
|
|
5247
|
+
updateDragPopup(pointerOffsetPosition) {
|
|
5248
|
+
if (!isPresent(this.dragPopup)) {
|
|
5249
|
+
this.openDragPopup();
|
|
5250
|
+
}
|
|
5251
|
+
const tooltip = this.dragPopup.content.instance;
|
|
5252
|
+
const { fromTaskName, toTaskName, isValid, showValidityStatus } = this.getTooltipContext();
|
|
5253
|
+
if (tooltip.fromTaskName !== fromTaskName ||
|
|
5254
|
+
tooltip.toTaskName !== toTaskName ||
|
|
5255
|
+
tooltip.isValid !== isValid ||
|
|
5256
|
+
tooltip.showValidityStatus !== showValidityStatus) {
|
|
5257
|
+
tooltip.fromTaskName = fromTaskName;
|
|
5258
|
+
tooltip.toTaskName = toTaskName;
|
|
5259
|
+
tooltip.isValid = isValid;
|
|
5260
|
+
tooltip.showValidityStatus = showValidityStatus;
|
|
5261
|
+
this.dragPopup.content.changeDetectorRef.detectChanges();
|
|
5262
|
+
}
|
|
5263
|
+
this.dragPopup.popup.instance.offset = this.normalizePopupPosition(pointerOffsetPosition);
|
|
5264
|
+
this.dragPopup.popup.changeDetectorRef.detectChanges();
|
|
5265
|
+
}
|
|
5266
|
+
closeDragPopup() {
|
|
5267
|
+
if (isPresent(this.dragPopup)) {
|
|
5268
|
+
this.dragPopup.close();
|
|
5269
|
+
this.dragPopup = null;
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
extractTaskName(target) {
|
|
5273
|
+
if (!isTaskWrapper(target, this.container)) {
|
|
5274
|
+
return null;
|
|
5275
|
+
}
|
|
5276
|
+
const taskIndex = getClosestTaskIndex(target, this.container);
|
|
5277
|
+
const task = this.gantt.renderedTreeListItems[taskIndex];
|
|
5278
|
+
const taskName = this.mapper.extractFromTask(task, 'title');
|
|
5279
|
+
return taskName;
|
|
5280
|
+
}
|
|
5281
|
+
getTooltipContext() {
|
|
5282
|
+
const fromTaskName = this.extractTaskName(this.fromTaskClue);
|
|
5283
|
+
const currentPointerTarget = elementFromPoint(this.currentPointerClientCoords.left, this.currentPointerClientCoords.top);
|
|
5284
|
+
const toTaskName = isTaskWrapper(currentPointerTarget, this.container) && !sameTaskClues(this.fromTaskClue, currentPointerTarget, this.container) ?
|
|
5285
|
+
this.extractTaskName(currentPointerTarget) :
|
|
5286
|
+
'';
|
|
5287
|
+
const showValidityStatus = isDependencyDragClue(currentPointerTarget) && !sameTaskClues(this.fromTaskClue, currentPointerTarget, this.container);
|
|
5288
|
+
const { fromId, toId, type } = this.mapper.dependencyFields;
|
|
5289
|
+
return {
|
|
5290
|
+
fromTaskName,
|
|
5291
|
+
toTaskName,
|
|
5292
|
+
showValidityStatus,
|
|
5293
|
+
isValid: showValidityStatus && this.gantt.validateNewDependency({
|
|
5294
|
+
[fromId]: this.mapper.extractFromTask(this.gantt.renderedTreeListItems[getClosestTaskIndex(this.fromTaskClue, this.container)], 'id'),
|
|
5295
|
+
[toId]: this.mapper.extractFromTask(this.gantt.renderedTreeListItems[getClosestTaskIndex(currentPointerTarget, this.container)], 'id'),
|
|
5296
|
+
[type]: getDependencyTypeFromTargetTasks(this.fromTaskClue, currentPointerTarget)
|
|
5297
|
+
})
|
|
5298
|
+
};
|
|
5299
|
+
}
|
|
5300
|
+
/**
|
|
5301
|
+
* Restricts the popup position to not go below the scroll height or width of the container.
|
|
5302
|
+
* Flips the position of the popup when there's not enough vertical space in the visible part of the container to render the popup.
|
|
5303
|
+
*/
|
|
5304
|
+
normalizePopupPosition(pointerOffsetPosition) {
|
|
5305
|
+
let top = pointerOffsetPosition.top + DEFAULT_POPUP_VERTICAL_MARGIN;
|
|
5306
|
+
const containerClientBottom = this.container.clientHeight + this.container.scrollTop;
|
|
5307
|
+
const popupHeight = this.dragPopup.popupElement.querySelector('.k-tooltip').clientHeight;
|
|
5308
|
+
const enoughSpaceToRender = top < containerClientBottom - popupHeight;
|
|
5309
|
+
// flip the popup above the pointer if there's not enough space in the bottom of the container
|
|
5310
|
+
if (!enoughSpaceToRender) {
|
|
5311
|
+
// margin * 2 to account for the already applied margin
|
|
5312
|
+
top -= popupHeight + (DEFAULT_POPUP_VERTICAL_MARGIN * 2);
|
|
5313
|
+
}
|
|
5314
|
+
// center the popup horizontally according to the pointer position
|
|
5315
|
+
const popupWidth = this.dragPopup.popupElement.querySelector('.k-tooltip').clientWidth;
|
|
5316
|
+
const left = pointerOffsetPosition.left - popupWidth / 2;
|
|
5317
|
+
// don't allow the popup to be cut out of the viewport
|
|
5318
|
+
const minLeftTop = 0;
|
|
5319
|
+
// restrict the popup from being positioned beyond or before the available scrollable space
|
|
5320
|
+
return {
|
|
5321
|
+
left: fitToRange(left, minLeftTop, this.container.scrollWidth - popupWidth),
|
|
5322
|
+
top: fitToRange(top, minLeftTop, this.container.scrollHeight - popupHeight)
|
|
5323
|
+
};
|
|
5324
|
+
}
|
|
5325
|
+
};
|
|
5326
|
+
__decorate([
|
|
5327
|
+
Input(),
|
|
5328
|
+
__metadata("design:type", Boolean)
|
|
5329
|
+
], DependencyDragCreateDirective.prototype, "displayValidationTooltip", void 0);
|
|
5330
|
+
DependencyDragCreateDirective = __decorate([
|
|
5331
|
+
Directive({
|
|
5332
|
+
selector: '[kendoGanttDependencyDragCreate]'
|
|
5333
|
+
}),
|
|
5334
|
+
__metadata("design:paramtypes", [GanttComponent,
|
|
5335
|
+
NgZone,
|
|
5336
|
+
Renderer2,
|
|
5337
|
+
MappingService,
|
|
5338
|
+
PopupService,
|
|
5339
|
+
TimelineScrollService])
|
|
5340
|
+
], DependencyDragCreateDirective);
|
|
5341
|
+
|
|
5342
|
+
/**
|
|
5343
|
+
* @hidden
|
|
5344
|
+
*/
|
|
5345
|
+
var ScrollDirection;
|
|
5346
|
+
(function (ScrollDirection) {
|
|
5347
|
+
ScrollDirection[ScrollDirection["Backwards"] = -1] = "Backwards";
|
|
5348
|
+
ScrollDirection[ScrollDirection["Forward"] = 1] = "Forward";
|
|
5349
|
+
})(ScrollDirection || (ScrollDirection = {}));
|
|
5350
|
+
/**
|
|
5351
|
+
* @hidden
|
|
5352
|
+
*/
|
|
5353
|
+
var ScrollAxis;
|
|
5354
|
+
(function (ScrollAxis) {
|
|
5355
|
+
ScrollAxis["Vertical"] = "scrollTop";
|
|
5356
|
+
ScrollAxis["Horizontal"] = "scrollLeft";
|
|
5357
|
+
})(ScrollAxis || (ScrollAxis = {}));
|
|
5358
|
+
|
|
5359
|
+
/**
|
|
5360
|
+
* @hidden
|
|
5361
|
+
*
|
|
5362
|
+
* Checks if the beginning of the scrollable element is reached (top/left).
|
|
5363
|
+
* Floors the top value.
|
|
5364
|
+
*/
|
|
5365
|
+
const isUpperLimitReached = (element, axis) => Math.floor(element[axis]) <= 0;
|
|
5366
|
+
/**
|
|
5367
|
+
* @hidden
|
|
5368
|
+
*
|
|
5369
|
+
* Checks if the end of the scrollable element is reached (bottom/right).
|
|
5370
|
+
* Ceils the top value.
|
|
5371
|
+
*/
|
|
5372
|
+
const isBottomLimitReached = (element, axis) => {
|
|
5373
|
+
const elementSize = axis === ScrollAxis.Horizontal ?
|
|
5374
|
+
element.scrollWidth - element.clientWidth :
|
|
5375
|
+
element.scrollHeight - element.clientHeight;
|
|
5376
|
+
return Math.ceil(element[axis]) >= elementSize;
|
|
5377
|
+
};
|
|
5378
|
+
/**
|
|
5379
|
+
* @hidden
|
|
5380
|
+
*
|
|
5381
|
+
* Scrolls the element in the given direction by the provided step in the provided scroll axis.
|
|
5382
|
+
*
|
|
5383
|
+
* If the targeted scroll incrementation doesn't yield any result due to device pixel ratio issues (https://github.com/dimitar-pechev/RenderingIndependentScrollOffsets#readme),
|
|
5384
|
+
* increments the step with 1px and again attempts to change the scrollTop of the element, until the content is actually scrolled.
|
|
5385
|
+
*
|
|
5386
|
+
* Cuts the operation short after 20 unsuccessful attempts to prevent infinite loops in possible corner-case scenarios.
|
|
5387
|
+
*/
|
|
5388
|
+
const scrollElement = (element, step, direction, scrollAxis) => {
|
|
5389
|
+
if (!(isPresent(element) && isDocumentAvailable())) {
|
|
5390
|
+
return;
|
|
5391
|
+
}
|
|
5392
|
+
const initialScrollPosition = element[scrollAxis];
|
|
5393
|
+
let currentStep = step;
|
|
5394
|
+
let iterations = 0;
|
|
5395
|
+
while (initialScrollPosition === element[scrollAxis] &&
|
|
5396
|
+
!(direction === ScrollDirection.Backwards && isUpperLimitReached(element, scrollAxis)) &&
|
|
5397
|
+
!(direction === ScrollDirection.Forward && isBottomLimitReached(element, scrollAxis)) &&
|
|
5398
|
+
iterations < 20 // cut the operation short in 20 attempts - in case of a wild corner case
|
|
5399
|
+
) {
|
|
5400
|
+
element[scrollAxis] += (currentStep * direction);
|
|
5401
|
+
// try with a larger step if the current one doesn't update the scroll position successfully
|
|
5402
|
+
currentStep += 1;
|
|
5403
|
+
iterations += 1;
|
|
5404
|
+
}
|
|
5405
|
+
};
|
|
5406
|
+
/**
|
|
5407
|
+
* @hidden
|
|
5408
|
+
*
|
|
5409
|
+
* As client coordinates are not restricted to the range 0px - {viewportSize}px, but can have negative starting values or ending values greater than the viewport size,
|
|
5410
|
+
* this function extracts the visible boundaries of the provided element - fall-backing to 0 when the top/left are below 0,
|
|
5411
|
+
* and fall-backing to the actual visible size of the container for bottom/right.
|
|
5412
|
+
*/
|
|
5413
|
+
const getViewportBoundaries = (element) => {
|
|
5414
|
+
const elementRect = element.getBoundingClientRect();
|
|
5415
|
+
// if the beginning of the scrollable container is above/before the current viewport, fall-back to 0
|
|
5416
|
+
const topLimit = Math.max(elementRect.top, 0);
|
|
5417
|
+
const leftLimit = Math.max(elementRect.left, 0);
|
|
5418
|
+
// if the end of the scrollable container is beneath/after the current viewport, fall-back to its client height
|
|
5419
|
+
// add the distance from the start of the viewport to the beginning of the container to ensure scrolling bottom begins when the actual end of the container is reached
|
|
5420
|
+
const bottomLimit = topLimit + Math.min(elementRect.bottom, element.clientHeight);
|
|
5421
|
+
const rightLimit = leftLimit + Math.min(elementRect.right, element.clientWidth);
|
|
5422
|
+
return {
|
|
5423
|
+
top: topLimit,
|
|
5424
|
+
bottom: bottomLimit,
|
|
5425
|
+
left: leftLimit,
|
|
5426
|
+
right: rightLimit
|
|
5427
|
+
};
|
|
5428
|
+
};
|
|
5429
|
+
|
|
5430
|
+
/**
|
|
5431
|
+
* @hidden
|
|
5432
|
+
*/
|
|
5433
|
+
let TimelineScrollableDirective = class TimelineScrollableDirective {
|
|
5434
|
+
constructor(timelineScrollableContainer, scrollService, zone) {
|
|
5435
|
+
this.timelineScrollableContainer = timelineScrollableContainer;
|
|
5436
|
+
this.scrollService = scrollService;
|
|
5437
|
+
this.zone = zone;
|
|
5438
|
+
this.subscriptions = new Subscription();
|
|
5439
|
+
this.subscriptions.add(this.scrollService.horizontalScroll
|
|
5440
|
+
.subscribe(this.scrollHorizontallyTo.bind(this)));
|
|
5441
|
+
this.subscriptions.add(this.scrollService.verticalScroll
|
|
5442
|
+
.subscribe(this.scrollVerticallyTo.bind(this)));
|
|
5443
|
+
this.subscriptions.add(this.scrollService.scrollCancel
|
|
5444
|
+
.subscribe(this.cancelScroll.bind(this)));
|
|
5445
|
+
}
|
|
5446
|
+
ngOnDestroy() {
|
|
5447
|
+
this.subscriptions.unsubscribe();
|
|
5448
|
+
}
|
|
5449
|
+
scrollHorizontallyTo(left) {
|
|
5450
|
+
this.zone.runOutsideAngular(() => {
|
|
5451
|
+
const container = this.timelineScrollableContainer.nativeElement;
|
|
5452
|
+
const visibleBoundaries = getViewportBoundaries(container);
|
|
5453
|
+
if (left < visibleBoundaries.left + this.scrollSettings.threshold) {
|
|
5454
|
+
this.horizontalScrollInterval = setInterval(() => scrollElement(container, this.scrollSettings.step, ScrollDirection.Backwards, ScrollAxis.Horizontal), this.scrollSettings.interval);
|
|
5455
|
+
}
|
|
5456
|
+
else if (left > visibleBoundaries.right - this.scrollSettings.threshold) {
|
|
5457
|
+
this.horizontalScrollInterval = setInterval(() => scrollElement(container, this.scrollSettings.step, ScrollDirection.Forward, ScrollAxis.Horizontal), this.scrollSettings.interval);
|
|
5458
|
+
}
|
|
5459
|
+
});
|
|
5460
|
+
}
|
|
5461
|
+
scrollVerticallyTo(top) {
|
|
5462
|
+
this.zone.runOutsideAngular(() => {
|
|
5463
|
+
const container = this.timelineScrollableContainer.nativeElement;
|
|
5464
|
+
const visibleBoundaries = getViewportBoundaries(container);
|
|
5465
|
+
if (top < visibleBoundaries.top + this.scrollSettings.threshold) {
|
|
5466
|
+
this.verticalScrollInterval = setInterval(() => scrollElement(container, this.scrollSettings.step, ScrollDirection.Backwards, ScrollAxis.Vertical), this.scrollSettings.interval);
|
|
5467
|
+
}
|
|
5468
|
+
else if (top > visibleBoundaries.bottom - this.scrollSettings.threshold) {
|
|
5469
|
+
this.verticalScrollInterval = setInterval(() => scrollElement(container, this.scrollSettings.step, ScrollDirection.Forward, ScrollAxis.Vertical), this.scrollSettings.interval);
|
|
5470
|
+
}
|
|
5471
|
+
});
|
|
5472
|
+
}
|
|
5473
|
+
cancelScroll() {
|
|
5474
|
+
if (isPresent(this.verticalScrollInterval)) {
|
|
5475
|
+
clearInterval(this.verticalScrollInterval);
|
|
5476
|
+
this.verticalScrollInterval = null;
|
|
5477
|
+
}
|
|
5478
|
+
if (isPresent(this.horizontalScrollInterval)) {
|
|
5479
|
+
clearInterval(this.horizontalScrollInterval);
|
|
5480
|
+
this.horizontalScrollInterval = null;
|
|
5481
|
+
}
|
|
5482
|
+
}
|
|
5483
|
+
};
|
|
5484
|
+
__decorate([
|
|
5485
|
+
Input(),
|
|
5486
|
+
__metadata("design:type", Object)
|
|
5487
|
+
], TimelineScrollableDirective.prototype, "scrollSettings", void 0);
|
|
5488
|
+
TimelineScrollableDirective = __decorate([
|
|
5489
|
+
Directive({
|
|
5490
|
+
selector: '[kendoGanttTimelineScrollable]'
|
|
5491
|
+
}),
|
|
5492
|
+
__metadata("design:paramtypes", [ElementRef,
|
|
5493
|
+
TimelineScrollService,
|
|
5494
|
+
NgZone])
|
|
5495
|
+
], TimelineScrollableDirective);
|
|
5496
|
+
|
|
4505
5497
|
var TimelineDayViewComponent_1;
|
|
4506
5498
|
let TimelineDayViewComponent = TimelineDayViewComponent_1 = class TimelineDayViewComponent extends ViewBase {
|
|
4507
5499
|
constructor(optionChangesService, dependencyDomService) {
|
|
@@ -5314,6 +6306,8 @@ const IMPORTED_MODULES = [
|
|
|
5314
6306
|
ButtonsModule,
|
|
5315
6307
|
DialogModule,
|
|
5316
6308
|
EventsModule,
|
|
6309
|
+
PopupModule,
|
|
6310
|
+
DraggableModule,
|
|
5317
6311
|
TabStripModule,
|
|
5318
6312
|
GridModule,
|
|
5319
6313
|
DropDownsModule
|
|
@@ -5346,6 +6340,7 @@ const DECLARATIONS = [
|
|
|
5346
6340
|
FooterTemplateDirective,
|
|
5347
6341
|
GanttExpandableDirective,
|
|
5348
6342
|
GanttDependencyDirective,
|
|
6343
|
+
DependencyDragCreateDirective,
|
|
5349
6344
|
TimelineDayViewComponent,
|
|
5350
6345
|
TimelineWeekViewComponent,
|
|
5351
6346
|
TimelineMonthViewComponent,
|
|
@@ -5354,9 +6349,12 @@ const DECLARATIONS = [
|
|
|
5354
6349
|
CustomMessagesComponent,
|
|
5355
6350
|
LocalizedMessagesDirective,
|
|
5356
6351
|
GanttAddTaskComponent,
|
|
6352
|
+
DragValidationTooltipComponent,
|
|
6353
|
+
TimelineScrollableDirective,
|
|
5357
6354
|
DependenciesTableComponent,
|
|
5358
6355
|
TaskFieldsComponent
|
|
5359
6356
|
];
|
|
6357
|
+
const ɵ0$3 = touchEnabled;
|
|
5360
6358
|
/**
|
|
5361
6359
|
* Represents the [NgModule]({{ site.data.urls.angular['ngmoduleapi'] }})
|
|
5362
6360
|
* definition for the Gantt component.
|
|
@@ -5395,52 +6393,19 @@ GanttModule = __decorate([
|
|
|
5395
6393
|
imports: [...IMPORTED_MODULES],
|
|
5396
6394
|
declarations: [...DECLARATIONS],
|
|
5397
6395
|
exports: [...DECLARATIONS],
|
|
6396
|
+
entryComponents: [DragValidationTooltipComponent],
|
|
5398
6397
|
providers: [{
|
|
5399
6398
|
provide: L10N_PREFIX,
|
|
5400
6399
|
useValue: 'kendo.gantt'
|
|
6400
|
+
}, {
|
|
6401
|
+
provide: TOUCH_ENABLED,
|
|
6402
|
+
useValue: ɵ0$3
|
|
5401
6403
|
}]
|
|
5402
6404
|
})
|
|
5403
6405
|
], GanttModule);
|
|
5404
6406
|
|
|
5405
|
-
/**
|
|
5406
|
-
* @hidden
|
|
5407
|
-
*/
|
|
5408
|
-
class PreventableEvent {
|
|
5409
|
-
constructor() {
|
|
5410
|
-
this.prevented = false;
|
|
5411
|
-
}
|
|
5412
|
-
/**
|
|
5413
|
-
* Prevents the default action for a specified event.
|
|
5414
|
-
* In this way, the source component suppresses
|
|
5415
|
-
* the built-in behavior that follows the event.
|
|
5416
|
-
*/
|
|
5417
|
-
preventDefault() {
|
|
5418
|
-
this.prevented = true;
|
|
5419
|
-
}
|
|
5420
|
-
/**
|
|
5421
|
-
* Returns `true` if the event was prevented
|
|
5422
|
-
* by any of its subscribers.
|
|
5423
|
-
*
|
|
5424
|
-
* @returns `true` if the default action was prevented.
|
|
5425
|
-
* Otherwise, returns `false`.
|
|
5426
|
-
*/
|
|
5427
|
-
isDefaultPrevented() {
|
|
5428
|
-
return this.prevented;
|
|
5429
|
-
}
|
|
5430
|
-
}
|
|
5431
|
-
|
|
5432
|
-
/**
|
|
5433
|
-
* Called every time a user leaves an edited cell.
|
|
5434
|
-
*/
|
|
5435
|
-
class CellCloseEvent extends PreventableEvent {
|
|
5436
|
-
constructor(options) {
|
|
5437
|
-
super();
|
|
5438
|
-
Object.assign(this, options);
|
|
5439
|
-
}
|
|
5440
|
-
}
|
|
5441
|
-
|
|
5442
6407
|
/**
|
|
5443
6408
|
* Generated bundle index. Do not edit.
|
|
5444
6409
|
*/
|
|
5445
6410
|
|
|
5446
|
-
export { MappingService, OptionChangesService, DependencyDomService, GanttDependencyDirective, GanttAddTaskComponent, DependenciesTableComponent, EditDialogComponent, EditService, TaskFieldsComponent, CustomMessagesComponent, GanttLocalizationService, LocalizedMessagesDirective, Messages, PreventableEvent, GanttHeaderTableBodyComponent, GanttMilestoneTaskComponent, GanttSummaryTaskComponent, GanttTaskBase, GanttTaskComponent, GanttTasksTableBodyComponent, ScrollSyncService, GanttTimelineComponent, TimelineBaseViewService, TimelineDayViewComponent, TimelineDayViewService, TimelineMonthViewComponent, TimelineMonthViewService, TimelineViewService, TimelineWeekViewComponent, TimelineWeekViewService, ViewBase, ToolbarComponent, ViewSelectorComponent, GanttComponent, GanttModule, GanttHierarchyBindingDirective, GanttFlatBindingDirective, GanttExpandableDirective, GanttTaskTemplateDirective, GanttTaskContentTemplateDirective, GanttSummaryTaskTemplateDirective, ToolbarTemplateDirective, SelectableDirective, DependencyType, CellCloseEvent, GanttColumnBase, GanttColumnComponent, GanttColumnGroupComponent, GanttSpanColumnComponent, CellTemplateDirective, HeaderTemplateDirective, FooterTemplateDirective, ColumnMenuTemplateDirective, FilterCellTemplateDirective, FilterMenuTemplateDirective, EditTemplateDirective };
|
|
6411
|
+
export { MappingService, OptionChangesService, TOUCH_ENABLED, DependencyDomService, GanttDependencyDirective, DragValidationTooltipComponent, GanttAddTaskComponent, DependenciesTableComponent, EditDialogComponent, EditService, TaskFieldsComponent, CustomMessagesComponent, GanttLocalizationService, LocalizedMessagesDirective, Messages, PreventableEvent, GanttHeaderTableBodyComponent, GanttMilestoneTaskComponent, GanttSummaryTaskComponent, GanttTaskBase, GanttTaskComponent, GanttTasksTableBodyComponent, ScrollSyncService, TimelineScrollableDirective, TimelineScrollService, GanttTimelineComponent, TimelineBaseViewService, TimelineDayViewComponent, TimelineDayViewService, TimelineMonthViewComponent, TimelineMonthViewService, TimelineViewService, TimelineWeekViewComponent, TimelineWeekViewService, ViewBase, ToolbarComponent, ViewSelectorComponent, GanttComponent, GanttModule, GanttHierarchyBindingDirective, GanttFlatBindingDirective, GanttExpandableDirective, DependencyDragCreateDirective, GanttTaskTemplateDirective, GanttTaskContentTemplateDirective, GanttSummaryTaskTemplateDirective, ToolbarTemplateDirective, SelectableDirective, DependencyType, CellCloseEvent, GanttColumnBase, GanttColumnComponent, GanttColumnGroupComponent, GanttSpanColumnComponent, CellTemplateDirective, HeaderTemplateDirective, FooterTemplateDirective, ColumnMenuTemplateDirective, FilterCellTemplateDirective, FilterMenuTemplateDirective, EditTemplateDirective };
|