I want to autoshift the tasks when 1 task is dropped on other. I referred the drag from grid demo and tried below code but does not seem to work.
The rescheduleoverlapping tasks seems to have some issue
Any assistance would be helpful
import { Component, ViewChild, ElementRef, AfterViewInit, OnInit, Input } from '@angular/core';
import { SchedulerComponent } from 'bryntum-angular-shared';
import { HttpClient } from '@angular/common/http';
// UMD bundle is used to support IE11 browser. If you don't need it just use import from 'bryntum-scheduler' instead
import { DateField, DomClassList, DateHelper, DragHelper, Scheduler, RowReorder, DependencyModel, StateTrackingManager, Store, ColumnReorder, Grid, GridFeatures, PresetManager, EventResize, Toast, DomHelper, Rectangle, WidgetHelper, EventModel, EventStore, Splitter } from 'bryntum-scheduler/scheduler.umd.js';
import { SCHEDULER } from '@angular/core/src/render3/component_ref';
//import { Scheduler } from 'rxjs';
declare var window: any;
let a, b, schedule;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit, OnInit {
@ViewChild(SchedulerComponent) scheduler: SchedulerComponent;
@ViewChild('datePickerContainer') datePickerContainer: ElementRef;
@ViewChild('Scheduler') schedule: Scheduler;
// rowReorderFeature = true;
@Input() autoRescheduleTasks: boolean = true;
dependenciesFeature = true;
scheduleTooltipFeature = false;
filterBarFeature = true;
multiEventSelect = true;
// eventDragCreateFeature = true;
//stripeFeature = true;
// bind properties from the application to the scheduler component
rowHeight = 50;
crudManager = {
autoLoad: true,
autoCommit: true,
eventStore: {
modelClass: EventModel,
// durationUnit : 'h'
},
transport: {
load: {
url: 'assets/data/data.json',
},
// sync: {
// method: 'PUT',
// url: 'https://localhost:3000/events',
// },
},
// autoSyncTimeout : 100,
// autoSync: true,
}
barMargin = 8;
startDate = new Date(2018, 1, 7, 8);
endDate = new Date(2019, 2, 7, 22);
// viewPreset = 'weekAndDayLetter';
viewPreset = 'weekAndDay';
listeners = {
eventselectionchange() {
const count = this.Scheduler.schedulerEngine.selectedEvents.length;
Toast.show(count + " " + "selected");
//countLabel.html = `${count} test${count === 1 ? '' : 's'} selected`;
}
}
columns = [
{
type: 'resourceInfo', text: 'Resource', field: 'name',
cellMenuItems: [
{
text: 'Lock',
icon: 'b-fa b-fa-fw b-fa-lock',
onItem: ({ record, eventRecord }) => {
record.flagged = true;
Toast.show('you have locked' + " " + record.name);
eventRecord.draggable = false;
eventRecord.resizable = false;
}
},
{
text: 'Unlock',
icon: 'b-fa b-fa-fw b-fa-unlock',
onItem: ({ record, eventRecord }) => {
Toast.show('you have unlocked' + " " + record.name);
record.flagged = false;
eventRecord.draggable = true;
eventRecord.resizable = true;
}
}
],
imagePath: 'assets/users/'
},
{
text: 'lossrate',
field: 'loss'
},
];
nonWorkingTimeFeature = {
highlightWeekends: true
};
rowReorderFeature = {
listeners: {
gridRowBeforeDragStart: function (event) {
const context = event.context,
record = this.grid.getRecordFromElement(context.element);
return !record.flagged;
}
}
}
eventContextMenuFeature = {
// Extra items for all events
items: {
deleteEvent: false,
eventEdit: false,
lockitem:
{
text: 'Lock',
icon: 'b-fa b-fa-fw b-fa-lock',
onItem({ eventRecord }) {
eventRecord.flagged = true;
eventRecord.draggable = false;
eventRecord.resizable = false;
a = eventRecord.data.color;
eventRecord.style = 'color:black;background-color:gray';
Toast.show('you have locked' + " " + eventRecord.name);
}
},
unlockitem:
{
text: 'unLock',
icon: 'b-fa b-fa-fw b-fa-unlock',
onItem({ eventRecord }) {
eventRecord.draggable = true;
eventRecord.resizable = true;
eventRecord.style = a;
Toast.show('you have unlocked' + " " + eventRecord.name);
}
}
}
};
eventRenderer = ({ eventRecord, resourceRecord, tplData }) => {
return `
<div class="info">
<div class="name">${eventRecord.name}</div>
<div class="desc">${eventRecord.desc}</div>
</div>
`;
};
ngOnInit() {
//
}
ngAfterViewInit() {
// exposing scheduling engine to be easily accessible from console
const
scheduler = this.scheduler.schedulerEngine,
eventStore = scheduler.eventStore
;
window.scheduler = this.scheduler.schedulerEngine;
eventStore.on({
update: ({ record, changes }) => {
if ('resourceId' in changes && !record.resourceId) {
eventStore.remove(record);
// grid.store.add(record);
}
if (this.autoRescheduleTasks) {
this.rescheduleOverlappingTasks(record, eventStore);
// eventStore.beginBatch();
}
},
add: ({ records }) => {
if (this.autoRescheduleTasks) {
eventStore.beginBatch();
}
if (this.autoRescheduleTasks) {
records.forEach((eventRecord) => this.rescheduleOverlappingTasks(eventRecord, eventStore));
eventStore.endBatch();
}
}
});
this.initDrag(scheduler);
// access the engine to reach the entire scheduler API, see API docs at /docs.
// some small examples:
//
// 1. Sort resources by name
// this.scheduler.schedulerEngine.resourceStore.sort('name');
//
// 2. Add a new event
// this.scheduler.schedulerEngine.eventStore.add({ startDate : xx, endDate: xx, ... });
//
// 3. Change the color of the first event
// this.scheduler.schedulerEngine.eventStore.first.eventColor = 'orange';
}
//
// this.schedule.features.rowReorder.disabled = false;
// fetch data for the scheduler
onToggle(pressed) {
console.log('hit')
this.autoRescheduleTasks = pressed;
} // eo function onRescheduleClick
initDrag(scheduler) {
const drag = new DragHelper({
cloneTarget: true,
mode: 'translateXY',
// Only allow drops on the schedule area
dropTargetSelector: '.b-timeline-subgrid',
// Only allow drag of row elements inside on the unplanned grid
targetSelector: '.b-grid-row',
constrain: false,
// outerElement : grid.element
});
drag.on({
dragstart: ({ event, context }) => {
const
me = drag,
mouseX = context.clientX,
proxy = context.element
// task = grid.getRecordFromElement(context.grabbed),
// newWidth = scheduler.timeAxisViewModel.getDistanceForDuration(task.durationMS)
;
// save a reference to the task so we can access it later
// context.task = task;
// Mutate dragged element (grid row) into an event bar
proxy.classList.remove('b-grid-row');
proxy.classList.add('b-sch-event-wrap');
proxy.classList.add('b-unassigned-class');
// proxy.innerHTML = task.name;
// If the new width is narrower than the grabbed element...
// if (context.grabbed.offsetWidth > newWidth) {
// const proxyRect = Rectangle.from(context.grabbed);
// // If the mouse is off (nearly or) the end, centre the element on the mouse
// if (mouseX > proxyRect.x + newWidth - 20) {
// context.newX = context.elementStartX = context.elementX = mouseX - newWidth / 2;
// DomHelper.setTranslateX(proxy, context.newX);
// }
// }
// proxy.style.width = `${newWidth}px`;
// // Prevent tooltips from showing while dragging
// scheduler.element.classList.add('b-dragging-event');
}, // eo dragstart listener
drag: ({ event, context }) => {
const
me = drag,
date = scheduler.getDateFromCoordinate(DomHelper.getTranslateX(context.element), 'round', false),
resource = context.target && scheduler.resolveResourceRecord(context.target)
;
// Don't allow drops anywhere, only allow drops if the drop is on the time axis and on top of a Resource
context.valid = context.valid && Boolean(date && resource);
// Save reference to resource so we can use it in onTaskDrop
context.resource = resource;
}, // eo drag listener
drop: ({ context, event }) => {
const
me = drag,
task = context.task,
target = context.target
;
// If drop was done in a valid location, set the startDate and transfer the task to the Scheduler event store
if (context.valid && target) {
const date = scheduler.getDateFromCoordinate(DomHelper.getTranslateX(context.element), 'round', false),
// Try resolving event record from target element, to determine if drop was on another event
targetEventRecord = scheduler.resolveEventRecord(context.target);
if (date) {
// Remove from grid first so that the data change
// below does not fire events into the grid.
// grid.store.remove(task);
task.setStartDate(date, true);
// task.startDate = date;
task.resource = context.resource;
scheduler.eventStore.add(task);
}
// Dropped on a scheduled event, display toast
if (targetEventRecord) {
WidgetHelper.toast(`Dropped on ${targetEventRecord.name}`);
}
context.finalize();
}
else {
me.abort();
}
scheduler.element.classList.remove('b-dragging-event');
} // eo drop listener
})
} // eo function initDrag
rescheduleOverlappingTasks(eventRecord, eventStore) {
if (eventRecord.resource) {
const
futureEvents = [],
earlierEvents = [];
// Split tasks into future and earlier tasks, ignoring tasks in the past
eventRecord.resource.events.forEach(event => {
// Don't modify events in the past
if (event.endDate > Date.now() && event !== eventRecord) {
if (event.startDate >= eventRecord.startDate) {
futureEvents.push(event);
}
else {
earlierEvents.push(event);
}
}
});
if (futureEvents.length || earlierEvents.length) {
futureEvents.sort((a, b) => a.startDate > b.startDate ? 1 : -1);
earlierEvents.sort((a, b) => a.startDate > b.startDate ? -1 : 1);
futureEvents.forEach((ev, i) => {
const prev = futureEvents[i - 1] || eventRecord;
ev.startDate = DateHelper.max(prev.endDate, ev.startDate);
});
// Walk backwards and remove any overlap
[eventRecord, ...earlierEvents].forEach((ev, i, all) => {
const prev = all[i - 1];
if (ev.endDate > Date.now() && ev !== eventRecord && prev) {
ev.setEndDate(DateHelper.min(prev.startDate, ev.endDate), true);
}
});
eventStore.endBatch();
}
}
}
// Uncomment the code in this method to start "logging" events
onSchedulerEvents(event: any) {
// // catch scheduler events here, for example when dropping an event:
if (event.type === 'eventdrop') {
// console.log('Drop: ', event);
// Toast.show('event has been dropped');
}
if (event.type === 'eventschange') {
console.log('eventchanged');
}
//
// // or when editing one:
// if (event.type === 'eventschange') {
// console.log('EventStore: ', event);
// }
//
// // or when editing a resource:
// if (event.type === 'resourceschange') {
// console.log('ResourceStore: ', event);
// }
}
onZoomIn() {
this.scheduler.schedulerEngine.zoomIn();
} // eo function onZoomIn
/**
* Handles zoom-out click event
* @param event
*/
onZoomOut() {
this.scheduler.schedulerEngine.zoomOut();
} // eo function onZoomOut
// add event button click handled here
onAddEventClick() {
this.scheduler.addEvent();
}
// remove event button click handled here
onRemoveEventClick() {
this.scheduler.removeEvent();
}
// change scheduler start/end dates
onDatePickerChange({ value }) {
this.scheduler.schedulerEngine.setTimeSpan(DateHelper.add(value, 8, 'hour'), DateHelper.add(value, 18, 'hour'));
}
filterEvents(value) {
value = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
this.scheduler.schedulerEngine.eventStore.filter({
filters: event => event.name.match(new RegExp(value, 'i')),
replace: true
});
}
}