@progress/kendo-angular-scheduler 2.1.6-dev.202111010913 → 2.2.0-dev.202112171600
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-scheduler.js +2 -2
- package/dist/cdn/main.js +1 -1
- package/dist/es/events/slot-drag-end-event.js +17 -0
- package/dist/es/events/slot-drag-event.js +18 -0
- package/dist/es/events/slot-drag-start-event.js +24 -0
- package/dist/es/events.js +3 -0
- package/dist/es/index.js +1 -0
- package/dist/es/package-metadata.js +1 -1
- package/dist/es/scheduler.component.js +73 -1
- package/dist/es/scheduler.module.js +2 -0
- package/dist/es/toolbar/view-selector.component.js +1 -1
- package/dist/es/types/slot-selection.js +23 -0
- package/dist/es/types.js +1 -0
- package/dist/es/views/common/base-view.js +102 -8
- package/dist/es/views/common/slot-selectable.directive.js +117 -0
- package/dist/es/views/day-time/day-time-view.component.js +1 -1
- package/dist/es/views/day-time/day-time.module.js +2 -1
- package/dist/es/views/month/month-view-renderer.component.js +12 -5
- package/dist/es/views/multi-day/multi-day-view-renderer.component.js +3 -3
- package/dist/es/views/timeline/timeline-multi-day-view.component.js +1 -1
- package/dist/es/views/utils.js +49 -0
- package/dist/es/views/view-state.service.js +18 -0
- package/dist/es2015/events/slot-drag-end-event.d.ts +10 -0
- package/dist/es2015/events/slot-drag-end-event.js +10 -0
- package/dist/es2015/events/slot-drag-event.d.ts +39 -0
- package/dist/es2015/events/slot-drag-event.js +16 -0
- package/dist/es2015/events/slot-drag-start-event.d.ts +41 -0
- package/dist/es2015/events/slot-drag-start-event.js +19 -0
- package/dist/es2015/events.d.ts +3 -0
- package/dist/es2015/events.js +3 -0
- package/dist/es2015/index.d.ts +2 -0
- package/dist/es2015/index.js +1 -0
- package/dist/es2015/index.metadata.json +1 -1
- package/dist/es2015/package-metadata.js +1 -1
- package/dist/es2015/scheduler.component.d.ts +27 -0
- package/dist/es2015/scheduler.component.js +73 -1
- package/dist/es2015/scheduler.module.js +2 -0
- package/dist/es2015/toolbar/view-selector.component.js +1 -0
- package/dist/es2015/types/datepicker-options.interface.d.ts +5 -5
- package/dist/es2015/types/slot-selection.d.ts +71 -0
- package/dist/es2015/types/slot-selection.js +19 -0
- package/dist/es2015/types.d.ts +2 -0
- package/dist/es2015/types.js +1 -0
- package/dist/es2015/views/common/base-view.d.ts +26 -5
- package/dist/es2015/views/common/base-view.js +102 -8
- package/dist/es2015/views/common/slot-selectable.directive.d.ts +45 -0
- package/dist/es2015/views/common/slot-selectable.directive.js +112 -0
- package/dist/es2015/views/day-time/day-time-view.component.js +1 -1
- package/dist/es2015/views/day-time/day-time.module.js +2 -1
- package/dist/es2015/views/month/month-view-renderer.component.d.ts +4 -2
- package/dist/es2015/views/month/month-view-renderer.component.js +20 -6
- package/dist/es2015/views/multi-day/multi-day-view-renderer.component.d.ts +1 -1
- package/dist/es2015/views/multi-day/multi-day-view-renderer.component.js +22 -4
- package/dist/es2015/views/timeline/timeline-multi-day-view.component.js +8 -1
- package/dist/es2015/views/utils.d.ts +29 -0
- package/dist/es2015/views/utils.js +49 -0
- package/dist/es2015/views/view-state.service.d.ts +24 -1
- package/dist/es2015/views/view-state.service.js +18 -0
- package/dist/fesm2015/index.js +1638 -1218
- package/dist/fesm5/index.js +1791 -1387
- package/dist/npm/events/slot-drag-end-event.js +19 -0
- package/dist/npm/events/slot-drag-event.js +20 -0
- package/dist/npm/events/slot-drag-start-event.js +26 -0
- package/dist/npm/events.js +6 -0
- package/dist/npm/index.js +2 -0
- package/dist/npm/package-metadata.js +1 -1
- package/dist/npm/scheduler.component.js +73 -1
- package/dist/npm/scheduler.module.js +2 -0
- package/dist/npm/toolbar/view-selector.component.js +1 -1
- package/dist/npm/types/slot-selection.js +25 -0
- package/dist/npm/types.js +2 -0
- package/dist/npm/views/common/base-view.js +101 -7
- package/dist/npm/views/common/slot-selectable.directive.js +119 -0
- package/dist/npm/views/day-time/day-time-view.component.js +1 -1
- package/dist/npm/views/day-time/day-time.module.js +2 -1
- package/dist/npm/views/month/month-view-renderer.component.js +11 -4
- package/dist/npm/views/multi-day/multi-day-view-renderer.component.js +3 -3
- package/dist/npm/views/timeline/timeline-multi-day-view.component.js +1 -1
- package/dist/npm/views/utils.js +53 -0
- package/dist/npm/views/view-state.service.js +18 -0
- package/dist/systemjs/kendo-angular-scheduler.js +1 -1
- package/package.json +9 -7
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2021 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import * as tslib_1 from "tslib";
|
|
6
|
+
import { SlotDragEvent } from './slot-drag-event';
|
|
7
|
+
/**
|
|
8
|
+
* Arguments for the `slotDragEnd` event.
|
|
9
|
+
*/
|
|
10
|
+
var SlotDragEndEvent = /** @class */ (function (_super) {
|
|
11
|
+
tslib_1.__extends(SlotDragEndEvent, _super);
|
|
12
|
+
function SlotDragEndEvent() {
|
|
13
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
14
|
+
}
|
|
15
|
+
return SlotDragEndEvent;
|
|
16
|
+
}(SlotDragEvent));
|
|
17
|
+
export { SlotDragEndEvent };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2021 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* Arguments for the `slotDrag` event.
|
|
7
|
+
*/
|
|
8
|
+
var SlotDragEvent = /** @class */ (function () {
|
|
9
|
+
/**
|
|
10
|
+
* @hidden
|
|
11
|
+
*/
|
|
12
|
+
function SlotDragEvent(sender, args) {
|
|
13
|
+
this.sender = sender;
|
|
14
|
+
Object.assign(this, args);
|
|
15
|
+
}
|
|
16
|
+
return SlotDragEvent;
|
|
17
|
+
}());
|
|
18
|
+
export { SlotDragEvent };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2021 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import * as tslib_1 from "tslib";
|
|
6
|
+
import { PreventableEvent } from './preventable-event';
|
|
7
|
+
/**
|
|
8
|
+
* Arguments for the `slotDragStart` event.
|
|
9
|
+
* The event is preventable and if prevented, subsequent `slotDrag`, `slotDragEnd`, and `slotSelectionChange` will not be fired.
|
|
10
|
+
*/
|
|
11
|
+
var SlotDragStartEvent = /** @class */ (function (_super) {
|
|
12
|
+
tslib_1.__extends(SlotDragStartEvent, _super);
|
|
13
|
+
/**
|
|
14
|
+
* @hidden
|
|
15
|
+
*/
|
|
16
|
+
function SlotDragStartEvent(sender, args) {
|
|
17
|
+
var _this = _super.call(this) || this;
|
|
18
|
+
_this.sender = sender;
|
|
19
|
+
Object.assign(_this, args);
|
|
20
|
+
return _this;
|
|
21
|
+
}
|
|
22
|
+
return SlotDragStartEvent;
|
|
23
|
+
}(PreventableEvent));
|
|
24
|
+
export { SlotDragStartEvent };
|
package/dist/es/events.js
CHANGED
|
@@ -20,3 +20,6 @@ export { DragEvent } from './events/drag-event';
|
|
|
20
20
|
export { DragEndEvent } from './events/drag-end-event';
|
|
21
21
|
export { EditEvent } from './events/edit-event';
|
|
22
22
|
export { AddEvent } from './events/add-event';
|
|
23
|
+
export { SlotDragStartEvent } from './events/slot-drag-start-event';
|
|
24
|
+
export { SlotDragEvent } from './events/slot-drag-event';
|
|
25
|
+
export { SlotDragEndEvent } from './events/slot-drag-end-event';
|
package/dist/es/index.js
CHANGED
|
@@ -59,6 +59,7 @@ export { HintContainerComponent } from './views/common/hint-container.component'
|
|
|
59
59
|
export { RepeatPipe } from './views/common/repeat.pipe';
|
|
60
60
|
export { ResizeHintComponent } from './views/common/resize-hint.component';
|
|
61
61
|
export { ResourceIteratorPipe } from './views/common/resource-iterator.pipe';
|
|
62
|
+
export { SlotSelectableDirective } from './views/common/slot-selectable.directive';
|
|
62
63
|
export { ViewFooterComponent } from './views/common/view-footer.component';
|
|
63
64
|
export { ViewsSharedModule } from './views/common/views-shared.module';
|
|
64
65
|
export { WorkHoursFooterDirective } from './views/common/work-hours-footer.directive';
|
|
@@ -9,7 +9,7 @@ export var packageMetadata = {
|
|
|
9
9
|
name: '@progress/kendo-angular-scheduler',
|
|
10
10
|
productName: 'Kendo UI for Angular',
|
|
11
11
|
productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
|
|
12
|
-
publishDate:
|
|
12
|
+
publishDate: 1639756470,
|
|
13
13
|
version: '',
|
|
14
14
|
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'
|
|
15
15
|
};
|
|
@@ -42,6 +42,9 @@ import { LoadingComponent } from './loading.component';
|
|
|
42
42
|
import { FocusService } from './navigation';
|
|
43
43
|
import { DomEventsService } from './views/common/dom-events.service';
|
|
44
44
|
import { closest } from './common/dom-queries';
|
|
45
|
+
import { alwaysFalse } from './views/utils';
|
|
46
|
+
import { SlotDragEvent } from './events/slot-drag-event';
|
|
47
|
+
import { SlotDragEndEvent } from './events/slot-drag-end-event';
|
|
45
48
|
var todayDate = function () { return getDate(new Date()); };
|
|
46
49
|
var ɵ0 = todayDate;
|
|
47
50
|
var DAYS_IN_WEEK = 7;
|
|
@@ -85,6 +88,12 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
85
88
|
* Specifies if the Scheduler is editable.
|
|
86
89
|
*/
|
|
87
90
|
this.editable = false;
|
|
91
|
+
/**
|
|
92
|
+
* Specifies if the Scheduler's day or time slots are selectable ([see example]({% slug slotselection_scheduler %}#toc-custom-callback)).
|
|
93
|
+
*
|
|
94
|
+
* When this input is set to `true`, the Scheduler component will emit [`slotDragStart`]({% slug api_scheduler_schedulercomponent %}#toc-slotdragstart), [`slotDrag`]({% slug api_scheduler_schedulercomponent %}#toc-slotdrag), and [`slotDragEnd`]({% slug api_scheduler_schedulercomponent %}#toc-slotdragend) events upon user interaction.
|
|
95
|
+
*/
|
|
96
|
+
this.selectable = false;
|
|
88
97
|
/**
|
|
89
98
|
* The height of the events in the **Month** and **Timeline** views, and the height of the **All day** events in the **Day** and **Week** views.
|
|
90
99
|
*/
|
|
@@ -136,6 +145,11 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
136
145
|
* Specifies the Scheduler current time marker settings.
|
|
137
146
|
*/
|
|
138
147
|
this.currentTimeMarker = true;
|
|
148
|
+
/**
|
|
149
|
+
* A callback that executes for each slot of the Scheduler view.
|
|
150
|
+
* If it returns `true`, the `k-state-selected` CSS class will be added to the cell, making it visibly selected.
|
|
151
|
+
*/
|
|
152
|
+
this.isSlotSelected = alwaysFalse;
|
|
139
153
|
/**
|
|
140
154
|
* @hidden
|
|
141
155
|
*/
|
|
@@ -210,6 +224,18 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
210
224
|
* Fires when the user stops dragging a Scheduler event.
|
|
211
225
|
*/
|
|
212
226
|
this.dragEnd = new EventEmitter();
|
|
227
|
+
/**
|
|
228
|
+
* Fires when the user starts drag-selecting a Scheduler slot range.
|
|
229
|
+
*/
|
|
230
|
+
this.slotDragStart = new EventEmitter();
|
|
231
|
+
/**
|
|
232
|
+
* Fires when the user is drag-selecting a Scheduler slot range.
|
|
233
|
+
*/
|
|
234
|
+
this.slotDrag = new EventEmitter();
|
|
235
|
+
/**
|
|
236
|
+
* Fires when the user stops drag-selecting a Scheduler slot range.
|
|
237
|
+
*/
|
|
238
|
+
this.slotDragEnd = new EventEmitter();
|
|
213
239
|
/**
|
|
214
240
|
* Fires when the user clicks the **PDF export** command button.
|
|
215
241
|
*/
|
|
@@ -400,6 +426,30 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
400
426
|
_this.resizeSensor.acceptSize();
|
|
401
427
|
}
|
|
402
428
|
}));
|
|
429
|
+
this.subs.add(this.viewState.slotSelectionStart
|
|
430
|
+
.subscribe(function (e) {
|
|
431
|
+
if (hasObservers(_this.slotDragStart)) {
|
|
432
|
+
_this.zone.run(function () {
|
|
433
|
+
_this.slotDragStart.emit(Object.assign(e, { sender: _this }));
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}));
|
|
437
|
+
this.subs.add(this.viewState.slotSelectionDrag
|
|
438
|
+
.subscribe(function (value) {
|
|
439
|
+
if (hasObservers(_this.slotDrag)) {
|
|
440
|
+
_this.zone.run(function () {
|
|
441
|
+
_this.slotDrag.emit(new SlotDragEvent(_this, value));
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}));
|
|
445
|
+
this.subs.add(this.viewState.slotSelectionEnd
|
|
446
|
+
.subscribe(function (value) {
|
|
447
|
+
if (hasObservers(_this.slotDragEnd)) {
|
|
448
|
+
_this.zone.run(function () {
|
|
449
|
+
_this.slotDragEnd.emit(new SlotDragEndEvent(_this, value));
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
}));
|
|
403
453
|
this.onViewIndexChange();
|
|
404
454
|
this.notifyOptionsChange = this.notifyOptionsChange.bind(this);
|
|
405
455
|
this.subs.add(this.allDayEventTemplate.changes.subscribe(this.notifyOptionsChange));
|
|
@@ -451,7 +501,7 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
451
501
|
if (anyChanged([
|
|
452
502
|
'group', 'resources', 'min', 'max', 'showWorkHours', 'startTime', 'scrollTime', 'endTime', 'eventHeight',
|
|
453
503
|
'workDayStart', 'workDayEnd', 'workWeekStart', 'workWeekEnd', 'weekStart', 'slotDuration', 'slotDivisions',
|
|
454
|
-
'editable', 'timezone', 'slotClass', 'slotFill', 'columnWidth', 'eventClass', 'eventStyles'
|
|
504
|
+
'editable', 'timezone', 'slotClass', 'slotFill', 'columnWidth', 'eventClass', 'eventStyles', 'isSlotSelected', 'selectable'
|
|
455
505
|
], changes)) {
|
|
456
506
|
this.notifyOptionsChange(changes);
|
|
457
507
|
}
|
|
@@ -704,6 +754,7 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
704
754
|
slotDivisions: this.slotDivisions,
|
|
705
755
|
eventHeight: this.eventHeight,
|
|
706
756
|
editable: this.editable,
|
|
757
|
+
selectable: this.selectable,
|
|
707
758
|
timezone: this.timezone,
|
|
708
759
|
currentTimeMarker: this.currentTimeMarker,
|
|
709
760
|
slotClass: this.slotClass,
|
|
@@ -711,6 +762,7 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
711
762
|
columnWidth: this.columnWidth,
|
|
712
763
|
eventClass: this.eventClass,
|
|
713
764
|
eventStyles: this.eventStyles,
|
|
765
|
+
isSlotSelected: this.isSlotSelected,
|
|
714
766
|
changes: changes
|
|
715
767
|
});
|
|
716
768
|
};
|
|
@@ -864,6 +916,10 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
864
916
|
Input(),
|
|
865
917
|
tslib_1.__metadata("design:type", Object)
|
|
866
918
|
], SchedulerComponent.prototype, "editable", void 0);
|
|
919
|
+
tslib_1.__decorate([
|
|
920
|
+
Input(),
|
|
921
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
922
|
+
], SchedulerComponent.prototype, "selectable", void 0);
|
|
867
923
|
tslib_1.__decorate([
|
|
868
924
|
Input(),
|
|
869
925
|
tslib_1.__metadata("design:type", Date)
|
|
@@ -977,6 +1033,10 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
977
1033
|
Input(),
|
|
978
1034
|
tslib_1.__metadata("design:type", Function)
|
|
979
1035
|
], SchedulerComponent.prototype, "eventStyles", void 0);
|
|
1036
|
+
tslib_1.__decorate([
|
|
1037
|
+
Input(),
|
|
1038
|
+
tslib_1.__metadata("design:type", Function)
|
|
1039
|
+
], SchedulerComponent.prototype, "isSlotSelected", void 0);
|
|
980
1040
|
tslib_1.__decorate([
|
|
981
1041
|
Output(),
|
|
982
1042
|
tslib_1.__metadata("design:type", EventEmitter)
|
|
@@ -1049,6 +1109,18 @@ var SchedulerComponent = /** @class */ (function () {
|
|
|
1049
1109
|
Output(),
|
|
1050
1110
|
tslib_1.__metadata("design:type", EventEmitter)
|
|
1051
1111
|
], SchedulerComponent.prototype, "dragEnd", void 0);
|
|
1112
|
+
tslib_1.__decorate([
|
|
1113
|
+
Output(),
|
|
1114
|
+
tslib_1.__metadata("design:type", EventEmitter)
|
|
1115
|
+
], SchedulerComponent.prototype, "slotDragStart", void 0);
|
|
1116
|
+
tslib_1.__decorate([
|
|
1117
|
+
Output(),
|
|
1118
|
+
tslib_1.__metadata("design:type", EventEmitter)
|
|
1119
|
+
], SchedulerComponent.prototype, "slotDrag", void 0);
|
|
1120
|
+
tslib_1.__decorate([
|
|
1121
|
+
Output(),
|
|
1122
|
+
tslib_1.__metadata("design:type", EventEmitter)
|
|
1123
|
+
], SchedulerComponent.prototype, "slotDragEnd", void 0);
|
|
1052
1124
|
tslib_1.__decorate([
|
|
1053
1125
|
Output(),
|
|
1054
1126
|
tslib_1.__metadata("design:type", EventEmitter)
|
|
@@ -55,6 +55,7 @@ import { EditDialogTemplateDirective } from './editing/edit-dialog-template.dire
|
|
|
55
55
|
import { LoadingComponent } from './loading.component';
|
|
56
56
|
import { SharedModule } from './shared.module';
|
|
57
57
|
import { ShortcutsDirective } from './navigation/shortcuts.directive';
|
|
58
|
+
import { SlotSelectableDirective } from './views/common/slot-selectable.directive';
|
|
58
59
|
var TEMPLATES = [
|
|
59
60
|
AgendaDateTemplateDirective,
|
|
60
61
|
AgendaTimeTemplateDirective,
|
|
@@ -75,6 +76,7 @@ var declarations = [
|
|
|
75
76
|
DataBindingDirective,
|
|
76
77
|
ShortcutsDirective,
|
|
77
78
|
ReactiveEditingDirective,
|
|
79
|
+
SlotSelectableDirective,
|
|
78
80
|
SchedulerDateTimePickerComponent,
|
|
79
81
|
RecurrenceEditorComponent,
|
|
80
82
|
RecurrenceEndRuleEditorComponent,
|
|
@@ -77,7 +77,7 @@ var ToolbarViewSelectorComponent = /** @class */ (function () {
|
|
|
77
77
|
Component({
|
|
78
78
|
// tslint:disable-next-line:component-selector
|
|
79
79
|
selector: '[kendoSchedulerToolbarViewSelector]',
|
|
80
|
-
template: "\n <select *ngIf=\"ctx.views?.length > 1\"\n (change)=\"onChange($event)\"\n class=\"k-views-dropdown k-dropdown\">\n <option *ngFor=\"let view of ctx.views\"\n [selected]=\"isSelected(view) == true\"\n [value]=\"view.name\"\n >\n {{ view.title }}\n </option>\n </select>\n <span class=\"k-scheduler-views k-button-group\">\n <button kendoButton\n *ngFor=\"let view of ctx.views\"\n [selected]=\"isSelected(view)\"\n [attr.aria-pressed]=\"isSelected(view)\"\n (click)=\"select(view)\"\n >\n <span class=\"k-button-text\">\n {{ view.title }}\n </span>\n </button>\n </span>\n "
|
|
80
|
+
template: "\n <select *ngIf=\"ctx.views?.length > 1\"\n (change)=\"onChange($event)\"\n class=\"k-views-dropdown k-dropdown\">\n <option *ngFor=\"let view of ctx.views\"\n [selected]=\"isSelected(view) == true\"\n [value]=\"view.name\"\n >\n {{ view.title }}\n </option>\n </select>\n <span class=\"k-scheduler-views k-button-group\">\n <button kendoButton\n type=\"button\"\n *ngFor=\"let view of ctx.views\"\n [selected]=\"isSelected(view)\"\n [attr.aria-pressed]=\"isSelected(view)\"\n (click)=\"select(view)\"\n >\n <span class=\"k-button-text\">\n {{ view.title }}\n </span>\n </button>\n </span>\n "
|
|
81
81
|
}),
|
|
82
82
|
tslib_1.__metadata("design:paramtypes", [ToolbarService])
|
|
83
83
|
], ToolbarViewSelectorComponent);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2021 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
/**
|
|
6
|
+
* The arguments for the [`isSlotSelected`]({% slug api_scheduler_schedulercomponent %}#toc-isslotselected) callback.
|
|
7
|
+
*/
|
|
8
|
+
var IsSlotSelectedArgs = /** @class */ (function () {
|
|
9
|
+
function IsSlotSelectedArgs() {
|
|
10
|
+
}
|
|
11
|
+
return IsSlotSelectedArgs;
|
|
12
|
+
}());
|
|
13
|
+
export { IsSlotSelectedArgs };
|
|
14
|
+
/**
|
|
15
|
+
* @hidden
|
|
16
|
+
*/
|
|
17
|
+
export var slotDragEventName;
|
|
18
|
+
(function (slotDragEventName) {
|
|
19
|
+
slotDragEventName["initDragSelect"] = "initDragSelect";
|
|
20
|
+
slotDragEventName["dragSelect"] = "dragSelect";
|
|
21
|
+
slotDragEventName["refreshSlotSelection"] = "refreshSlotSelection";
|
|
22
|
+
slotDragEventName["dragSelectRelease"] = "dragSelectRelease";
|
|
23
|
+
})(slotDragEventName || (slotDragEventName = {}));
|
package/dist/es/types.js
CHANGED
|
@@ -3,3 +3,4 @@
|
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
5
|
export * from './types/scheduler-view';
|
|
6
|
+
export { IsSlotSelectedArgs } from './types/slot-selection';
|
|
@@ -10,17 +10,19 @@ import { Subscription, BehaviorSubject, combineLatest, fromEvent, merge } from '
|
|
|
10
10
|
import { switchMap, take, map, filter, tap } from 'rxjs/operators';
|
|
11
11
|
import { closestInScope, hasClasses, preventLockedScroll, scrollbarWidth, wheelDeltaY, hasScrollbar } from '../../common/dom-queries';
|
|
12
12
|
import { groupResources, getField, setField, fromClick, fromDoubleClick } from '../../common/util';
|
|
13
|
-
import { assignTasksResources, toPx, elementOffset, pointDistance, ignoreContentChild, resourceItemByValue, convertNgClassBindings } from '../utils';
|
|
13
|
+
import { assignTasksResources, toPx, elementOffset, pointDistance, ignoreContentChild, resourceItemByValue, convertNgClassBindings, toUTCDateTime, dateWithTime, normaliseRangeStartAndEnd } from '../utils';
|
|
14
14
|
import { BORDER_WIDTH } from '../constants';
|
|
15
15
|
import Draggable from '@telerik/kendo-draggable';
|
|
16
16
|
import { HintContainerComponent } from '../common/hint-container.component';
|
|
17
|
+
import { slotDragEventName } from '../../types/slot-selection';
|
|
18
|
+
import { SlotDragStartEvent } from '../../events/slot-drag-start-event';
|
|
17
19
|
var SCROLL_CHANGE = 15;
|
|
18
20
|
var MIN_DISTANCE = 60;
|
|
19
21
|
var SCROLL_INTERVAL = 50;
|
|
20
22
|
var MIN_MOVE_DISTANCE = 10;
|
|
21
23
|
/** @hidden */
|
|
22
24
|
var BaseView = /** @class */ (function () {
|
|
23
|
-
function BaseView(viewContext, viewState, intl, slotService, zone, renderer, element, pdfService, localization) {
|
|
25
|
+
function BaseView(viewContext, viewState, intl, slotService, zone, renderer, element, pdfService, localization, cdr) {
|
|
24
26
|
this.viewContext = viewContext;
|
|
25
27
|
this.viewState = viewState;
|
|
26
28
|
this.intl = intl;
|
|
@@ -30,6 +32,7 @@ var BaseView = /** @class */ (function () {
|
|
|
30
32
|
this.element = element;
|
|
31
33
|
this.pdfService = pdfService;
|
|
32
34
|
this.localization = localization;
|
|
35
|
+
this.cdr = cdr;
|
|
33
36
|
this.items = new BehaviorSubject(null);
|
|
34
37
|
this.horizontalResources = [];
|
|
35
38
|
this.verticalResources = [];
|
|
@@ -43,8 +46,17 @@ var BaseView = /** @class */ (function () {
|
|
|
43
46
|
this.spans = [];
|
|
44
47
|
this.domEvents = [];
|
|
45
48
|
this.resourcesCache = {};
|
|
49
|
+
/**
|
|
50
|
+
* The slot which is currently being dragged over while selecting a range of slots.
|
|
51
|
+
*/
|
|
52
|
+
this.dragSelecting = null;
|
|
53
|
+
/**
|
|
54
|
+
* The slot where the drag-selecting originated. Used for flipping the start and end of the emitted range.
|
|
55
|
+
*/
|
|
56
|
+
this.dragSelectOrigin = null;
|
|
46
57
|
this.autoHeight = false;
|
|
47
58
|
this.rtl = false;
|
|
59
|
+
this.isSlotSelected = function () { return false; };
|
|
48
60
|
this.setSlotClass = this.setSlotClass.bind(this);
|
|
49
61
|
this.setHintClass = this.setHintClass.bind(this);
|
|
50
62
|
this.weekStart = intl.firstDay();
|
|
@@ -175,6 +187,20 @@ var BaseView = /** @class */ (function () {
|
|
|
175
187
|
}
|
|
176
188
|
return result;
|
|
177
189
|
};
|
|
190
|
+
// Similar to https://tc39.es/proposal-temporal/docs/plaindate.html
|
|
191
|
+
// Stores a "plain date" in the UTC parts of a regular `Date`.
|
|
192
|
+
BaseView.prototype.toPlainDate = function (date) {
|
|
193
|
+
var result = toUTCDateTime(this.convertDate(date));
|
|
194
|
+
return result;
|
|
195
|
+
};
|
|
196
|
+
// Similar to https://tc39.es/proposal-temporal/docs/plaindatetime.html
|
|
197
|
+
// Stores a "plain date-time" in the UTC parts of a regular `Date`.
|
|
198
|
+
BaseView.prototype.toPlainDateTime = function (date, time) {
|
|
199
|
+
if (!date || !time) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return this.toPlainDate(dateWithTime(date, time));
|
|
203
|
+
};
|
|
178
204
|
BaseView.prototype.optionsChange = function (options) {
|
|
179
205
|
this.schedulerEventTemplate = options.eventTemplate;
|
|
180
206
|
this.schedulerGroupHeaderTemplate = options.groupHeaderTemplate;
|
|
@@ -182,6 +208,8 @@ var BaseView = /** @class */ (function () {
|
|
|
182
208
|
this.max = options.max;
|
|
183
209
|
this.editable = options.editable;
|
|
184
210
|
this.timezone = options.timezone;
|
|
211
|
+
this.selectable = options.selectable;
|
|
212
|
+
this.isSlotSelected = options.isSlotSelected;
|
|
185
213
|
if (!options.changes || anyChanged(['group', 'resources'], options.changes, false) ||
|
|
186
214
|
options.group !== this.group || options.resources !== this.resources) {
|
|
187
215
|
this.group = options.group;
|
|
@@ -208,6 +236,7 @@ var BaseView = /** @class */ (function () {
|
|
|
208
236
|
this.toggleElement(true);
|
|
209
237
|
this.reflow();
|
|
210
238
|
this.viewState.notifyLayoutEnd();
|
|
239
|
+
this.viewState.emitEvent(slotDragEventName.refreshSlotSelection);
|
|
211
240
|
};
|
|
212
241
|
BaseView.prototype.assignResources = function () {
|
|
213
242
|
assignTasksResources(this.tasks, {
|
|
@@ -249,16 +278,16 @@ var BaseView = /** @class */ (function () {
|
|
|
249
278
|
});
|
|
250
279
|
};
|
|
251
280
|
BaseView.prototype.onPress = function (args) {
|
|
252
|
-
var
|
|
253
|
-
var
|
|
281
|
+
var editResizable = this.editable && this.editable.resize !== false;
|
|
282
|
+
var editDraggable = this.editable && this.editable.drag !== false;
|
|
254
283
|
var target = args.originalEvent.target;
|
|
255
284
|
if (hasClasses(target, 'k-resize-handle')) {
|
|
256
|
-
if (!
|
|
285
|
+
if (!editResizable) {
|
|
257
286
|
return;
|
|
258
287
|
}
|
|
259
288
|
this.initResize(args);
|
|
260
289
|
}
|
|
261
|
-
else if (
|
|
290
|
+
else if (editDraggable) {
|
|
262
291
|
var task = this.targetTask(target);
|
|
263
292
|
if (task) {
|
|
264
293
|
if (!args.isTouch) {
|
|
@@ -268,6 +297,9 @@ var BaseView = /** @class */ (function () {
|
|
|
268
297
|
this.pressTarget = task;
|
|
269
298
|
}
|
|
270
299
|
}
|
|
300
|
+
if (this.selectable) {
|
|
301
|
+
this.initDragSelect(args);
|
|
302
|
+
}
|
|
271
303
|
this.dragArgs = args;
|
|
272
304
|
};
|
|
273
305
|
BaseView.prototype.onDrag = function (args) {
|
|
@@ -282,12 +314,15 @@ var BaseView = /** @class */ (function () {
|
|
|
282
314
|
args.originalEvent.preventDefault();
|
|
283
315
|
this.scrollContainer(this.drag, args);
|
|
284
316
|
}
|
|
317
|
+
if (this.dragSelecting) {
|
|
318
|
+
this.dragSelect(args);
|
|
319
|
+
}
|
|
285
320
|
}
|
|
286
321
|
this.dragArgs = args;
|
|
287
322
|
};
|
|
288
|
-
BaseView.prototype.onRelease = function () {
|
|
323
|
+
BaseView.prototype.onRelease = function (args) {
|
|
289
324
|
clearInterval(this.scrollInterval);
|
|
290
|
-
var _a = this, resizing = _a.resizing, dragging = _a.dragging;
|
|
325
|
+
var _a = this, resizing = _a.resizing, dragging = _a.dragging, dragSelecting = _a.dragSelecting;
|
|
291
326
|
if (resizing) {
|
|
292
327
|
this.emitEvent('resizeEnd', {
|
|
293
328
|
event: resizing.task.event,
|
|
@@ -314,6 +349,20 @@ var BaseView = /** @class */ (function () {
|
|
|
314
349
|
this.resizing = null;
|
|
315
350
|
this.dragging = null;
|
|
316
351
|
}
|
|
352
|
+
if (dragSelecting) {
|
|
353
|
+
var _b = normaliseRangeStartAndEnd(this.dragSelectOrigin, this.dragSelecting), start = _b.start, end = _b.end;
|
|
354
|
+
var range = {
|
|
355
|
+
start: this.convertDate(start),
|
|
356
|
+
end: this.convertDate(end),
|
|
357
|
+
isAllDay: this.dragSelecting.isDaySlot,
|
|
358
|
+
resources: this.resourcesByIndex(this.dragSelecting.id.resourceIndex),
|
|
359
|
+
originalEvent: args.originalEvent
|
|
360
|
+
};
|
|
361
|
+
this.viewState.notifySlotSelectionEnd(range);
|
|
362
|
+
this.dragSelectOrigin = null;
|
|
363
|
+
this.dragSelecting = null;
|
|
364
|
+
this.cdr.markForCheck();
|
|
365
|
+
}
|
|
317
366
|
this.container = null;
|
|
318
367
|
this.dragArgs = null;
|
|
319
368
|
this.pressLocation = null;
|
|
@@ -465,6 +514,51 @@ var BaseView = /** @class */ (function () {
|
|
|
465
514
|
this.updateHintContainer();
|
|
466
515
|
}
|
|
467
516
|
};
|
|
517
|
+
BaseView.prototype.initDragSelect = function (args) {
|
|
518
|
+
this.updateDragContainer(args);
|
|
519
|
+
if (!this.containerOffset) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
var _a = this.coordinatesOffset(args.pageX, args.pageY), x = _a.x, y = _a.y;
|
|
523
|
+
var slot = this.slotByPosition(x, y, this.container);
|
|
524
|
+
if (!slot) {
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
var range = {
|
|
528
|
+
start: this.convertDate(slot.start),
|
|
529
|
+
end: this.convertDate(slot.end),
|
|
530
|
+
isAllDay: slot.isDaySlot,
|
|
531
|
+
resources: this.resourcesByIndex(slot.id.resourceIndex),
|
|
532
|
+
originalEvent: args.originalEvent
|
|
533
|
+
};
|
|
534
|
+
var slotDragStartEvent = new SlotDragStartEvent(null, range);
|
|
535
|
+
this.viewState.notifySlotSelectionStart(slotDragStartEvent);
|
|
536
|
+
if (!slotDragStartEvent.isDefaultPrevented()) {
|
|
537
|
+
this.dragSelecting = slot;
|
|
538
|
+
this.dragSelectOrigin = slot;
|
|
539
|
+
this.cdr.markForCheck();
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
BaseView.prototype.dragSelect = function (args) {
|
|
543
|
+
var _a = this.coordinatesOffset(args.pageX, args.pageY), x = _a.x, y = _a.y;
|
|
544
|
+
var slot = this.slotByPosition(x, y, this.container);
|
|
545
|
+
if (!slot) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (this.dragSelecting !== slot) {
|
|
549
|
+
this.dragSelecting = slot;
|
|
550
|
+
var _b = normaliseRangeStartAndEnd(this.dragSelectOrigin, this.dragSelecting), start = _b.start, end = _b.end;
|
|
551
|
+
var range = {
|
|
552
|
+
start: this.convertDate(start),
|
|
553
|
+
end: this.convertDate(end),
|
|
554
|
+
isAllDay: slot.isDaySlot,
|
|
555
|
+
resources: this.resourcesByIndex(slot.id.resourceIndex),
|
|
556
|
+
originalEvent: args.originalEvent
|
|
557
|
+
};
|
|
558
|
+
this.viewState.notifySlotSelectionDrag(range);
|
|
559
|
+
this.cdr.markForCheck();
|
|
560
|
+
}
|
|
561
|
+
};
|
|
468
562
|
BaseView.prototype.dragHintClasses = function () {
|
|
469
563
|
var hintClass = this.dragging.hintClass;
|
|
470
564
|
var result = [];
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**-----------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright © 2021 Progress Software Corporation. All rights reserved.
|
|
3
|
+
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
+
*-------------------------------------------------------------------------------------------*/
|
|
5
|
+
import * as tslib_1 from "tslib";
|
|
6
|
+
import { Directive, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
|
|
7
|
+
import { Subscription } from 'rxjs';
|
|
8
|
+
import { intersects, isSameRange, resourcesMatch } from '../utils';
|
|
9
|
+
import { SchedulerComponent } from '../../scheduler.component';
|
|
10
|
+
import { distinctUntilChanged, filter } from 'rxjs/operators';
|
|
11
|
+
import { isChanged } from '@progress/kendo-angular-common';
|
|
12
|
+
/**
|
|
13
|
+
* A directive which manages the in-memory selection state of the Scheduler slots
|
|
14
|
+
* ([see example]({% slug slotselection_scheduler %}#toc-built-in-directive)).
|
|
15
|
+
*/
|
|
16
|
+
var SlotSelectableDirective = /** @class */ (function () {
|
|
17
|
+
function SlotSelectableDirective(scheduler, cdr) {
|
|
18
|
+
var _this = this;
|
|
19
|
+
this.scheduler = scheduler;
|
|
20
|
+
this.cdr = cdr;
|
|
21
|
+
/**
|
|
22
|
+
* Fires when the currently selected slot range has changed through user interaction.
|
|
23
|
+
*/
|
|
24
|
+
this.slotSelectionChange = new EventEmitter();
|
|
25
|
+
this.selectedRange = null;
|
|
26
|
+
this.slotSelectionChangeSource = new EventEmitter();
|
|
27
|
+
this.subscriptions = new Subscription();
|
|
28
|
+
this.scheduler.selectable = true;
|
|
29
|
+
this.subscriptions.add(this.slotSelectionChangeSource
|
|
30
|
+
.pipe(distinctUntilChanged(isSameRange)).subscribe(function (v) {
|
|
31
|
+
_this.slotSelectionChange.emit(v);
|
|
32
|
+
}));
|
|
33
|
+
var start$ = this.scheduler.slotDragStart;
|
|
34
|
+
var drag$ = this.scheduler.slotDrag;
|
|
35
|
+
var end$ = this.scheduler.slotDragEnd;
|
|
36
|
+
var startSource = start$.pipe(filter(function (e) { return !e.isDefaultPrevented(); }));
|
|
37
|
+
this.subscriptions.add(startSource.subscribe(function (e) { return _this.initDragSelect(e); }));
|
|
38
|
+
this.subscriptions.add(drag$.subscribe(function (e) { return _this.onDrag(e); }));
|
|
39
|
+
this.subscriptions.add(end$.subscribe(function () { return _this.onRelease(); }));
|
|
40
|
+
}
|
|
41
|
+
SlotSelectableDirective.prototype.ngOnInit = function () {
|
|
42
|
+
this.scheduler.isSlotSelected = this.isSlotSelected.bind(this);
|
|
43
|
+
};
|
|
44
|
+
SlotSelectableDirective.prototype.ngOnChanges = function (changes) {
|
|
45
|
+
if (isChanged("slotSelection", changes, false)) {
|
|
46
|
+
/**
|
|
47
|
+
* The default values for resources below are necessarry because this is not fixed yet: https://github.com/telerik/kendo-angular-scheduler/pull/338
|
|
48
|
+
*/
|
|
49
|
+
var resources = this.scheduler.resources ? [this.scheduler.resources[0].data[0]] : [undefined];
|
|
50
|
+
this.selectedRange = Object.assign({}, { isAllDay: false, resources: resources }, changes.slotSelection.currentValue);
|
|
51
|
+
this.cdr.markForCheck();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
SlotSelectableDirective.prototype.ngOnDestroy = function () {
|
|
55
|
+
this.subscriptions.unsubscribe();
|
|
56
|
+
};
|
|
57
|
+
SlotSelectableDirective.prototype.isSlotSelected = function (_a) {
|
|
58
|
+
var start = _a.start, end = _a.end, isAllDay = _a.isAllDay, resources = _a.resources;
|
|
59
|
+
if (!start || !end || !this.selectedRange) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
var match = resourcesMatch(this.selectedRange.resources, resources, true);
|
|
63
|
+
if (!match) {
|
|
64
|
+
return false; // Limit selection to the grouped resource where the drag started.
|
|
65
|
+
}
|
|
66
|
+
return this.selectedRange && isAllDay === this.selectedRange.isAllDay && this.isInRange(start, end);
|
|
67
|
+
};
|
|
68
|
+
SlotSelectableDirective.prototype.initDragSelect = function (_a) {
|
|
69
|
+
var start = _a.start, end = _a.end, isAllDay = _a.isAllDay, resources = _a.resources, originalEvent = _a.originalEvent;
|
|
70
|
+
this.selectionOriginResources = resources.slice();
|
|
71
|
+
this.selectedRange = { start: start, end: end, isAllDay: isAllDay, resources: resources.slice(), originalEvent: originalEvent };
|
|
72
|
+
this.cdr.markForCheck();
|
|
73
|
+
};
|
|
74
|
+
SlotSelectableDirective.prototype.onDrag = function (_a) {
|
|
75
|
+
var start = _a.start, end = _a.end, resources = _a.resources;
|
|
76
|
+
var match = resourcesMatch(this.selectionOriginResources, resources, false); // Not strict - allow matching [ undefined ] and [ undefined ]
|
|
77
|
+
if (!match) {
|
|
78
|
+
return; // Don't change selection when dragging over a different grouped resource's cells.
|
|
79
|
+
}
|
|
80
|
+
this.selectedRange.start = start;
|
|
81
|
+
this.selectedRange.end = end;
|
|
82
|
+
this.cdr.markForCheck();
|
|
83
|
+
};
|
|
84
|
+
SlotSelectableDirective.prototype.onRelease = function () {
|
|
85
|
+
this.selectionOriginResources = null;
|
|
86
|
+
if (this.selectedRange) {
|
|
87
|
+
this.slotSelectionChangeSource.emit(this.selectedRange);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* @hidden
|
|
92
|
+
* Checks if the selected range contains a local date range.
|
|
93
|
+
*/
|
|
94
|
+
SlotSelectableDirective.prototype.isInRange = function (start, end) {
|
|
95
|
+
if (!this.selectedRange) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
return intersects(start, end, this.selectedRange.start, this.selectedRange.end);
|
|
99
|
+
};
|
|
100
|
+
tslib_1.__decorate([
|
|
101
|
+
Input(),
|
|
102
|
+
tslib_1.__metadata("design:type", Object)
|
|
103
|
+
], SlotSelectableDirective.prototype, "slotSelection", void 0);
|
|
104
|
+
tslib_1.__decorate([
|
|
105
|
+
Output(),
|
|
106
|
+
tslib_1.__metadata("design:type", EventEmitter)
|
|
107
|
+
], SlotSelectableDirective.prototype, "slotSelectionChange", void 0);
|
|
108
|
+
SlotSelectableDirective = tslib_1.__decorate([
|
|
109
|
+
Directive({
|
|
110
|
+
selector: '[kendoSchedulerSlotSelectable]'
|
|
111
|
+
}),
|
|
112
|
+
tslib_1.__metadata("design:paramtypes", [SchedulerComponent,
|
|
113
|
+
ChangeDetectorRef])
|
|
114
|
+
], SlotSelectableDirective);
|
|
115
|
+
return SlotSelectableDirective;
|
|
116
|
+
}());
|
|
117
|
+
export { SlotSelectableDirective };
|
|
@@ -25,7 +25,7 @@ var ɵ2 = getNextDate;
|
|
|
25
25
|
var DayTimeViewComponent = /** @class */ (function (_super) {
|
|
26
26
|
tslib_1.__extends(DayTimeViewComponent, _super);
|
|
27
27
|
function DayTimeViewComponent(changeDetector, viewContext, viewState, intl, slotService, zone, renderer, element, pdfService, localization) {
|
|
28
|
-
var _this = _super.call(this, viewContext, viewState, intl, slotService, zone, renderer, element, pdfService, localization) || this;
|
|
28
|
+
var _this = _super.call(this, viewContext, viewState, intl, slotService, zone, renderer, element, pdfService, localization, changeDetector) || this;
|
|
29
29
|
_this.changeDetector = changeDetector;
|
|
30
30
|
_this.numberOfDays = 1;
|
|
31
31
|
_this.startTime = '00:00';
|
|
@@ -8,6 +8,7 @@ import { CommonModule } from '@angular/common';
|
|
|
8
8
|
import { SharedModule } from '../../shared.module';
|
|
9
9
|
import { TimeSlotDirective, DaySlotDirective } from './event-slot.directive';
|
|
10
10
|
import { DayTimeViewItemComponent } from './day-time-view-item.component';
|
|
11
|
+
import { ViewsSharedModule } from '../common/views-shared.module';
|
|
11
12
|
var DIRECTIVES = [TimeSlotDirective, DaySlotDirective, DayTimeViewItemComponent];
|
|
12
13
|
/**
|
|
13
14
|
* @hidden
|
|
@@ -17,7 +18,7 @@ var DayTimeModule = /** @class */ (function () {
|
|
|
17
18
|
}
|
|
18
19
|
DayTimeModule = tslib_1.__decorate([
|
|
19
20
|
NgModule({
|
|
20
|
-
imports: [CommonModule, SharedModule],
|
|
21
|
+
imports: [CommonModule, SharedModule, ViewsSharedModule],
|
|
21
22
|
exports: [
|
|
22
23
|
DIRECTIVES
|
|
23
24
|
],
|