Hi,
I have enabled resourceNonWorkingTimeFeature = {true} and nonWorkingTimeFeature={ true }
It is working as expected.Now if I drag and drop from the grid to the non-workingTime then it will find the next available working time and setting that automatically.
My use case is different:-
The task could be scheduled at a time when the technician is not available
We should enable solutions to configure this such that a popup could appear if needed (this could be turned off if not needed)
Eg if the task is dragged onto the unavailable time slot, show a popup saying “Are you sure you want to schedule this Task to Technician A outside their shift?”
Please suggest me how to achieve this requirement?
My drag.js file code is:-
import { DragHelper, DomHelper, Rectangle, WidgetHelper, StringHelper } from '@bryntum/schedulerpro/schedulerpro.umd';
import { moment } from '../../../utilities/moment';
import {DRAG_PAST_DATE_ERROR_MSG, WORKFLOW_UPDATE_ERROR} from "../utills";
import { getLodash } from '../../../utilities/lodash';
export default class Drag extends DragHelper {
static get defaultConfig () {
return {
// Don't drag the actual row element, clone it
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:not(.b-group-row)'
};
}
construct (config) {
const me = this;
super.construct(config);
me.on({
dragstart: me.onTaskDragStart,
drag: me.onTaskDrag,
drop: me.onTaskDrop,
thisObj: me
});
}
onTaskDragStart ({ context }) {
const
me = this,
{ schedule } = me,
mouseX = context.clientX,
proxy = context.element,
task = me.grid.getRecordFromElement(context.grabbed),
newSize = me.schedule.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.classList.add(`b-${schedule.mode}`);
// proxy.innerHTML = `<i class="${task.iconCls}"></i> ${task.name}`;
proxy.innerHTML = StringHelper.xss`
<div class="b-sch-event b-has-content">
<div class="b-sch-event-content">
<div>${task.name}</div>
<span>Duration: ${task.duration} ${task.durationUnit}</span>
</div>
</div>
`;
me.schedule.enableScrollingCloseToEdges(me.schedule.timeAxisSubGrid);
if (schedule.isHorizontal) {
// If the new width is narrower than the grabbed element...
if (context.grabbed.offsetWidth > newSize) {
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 + newSize - 20) {
context.newX = context.elementStartX = context.elementX = mouseX - newSize / 2;
DomHelper.setTranslateX(proxy, context.newX);
}
}
proxy.style.width = `${newSize}px`;
} else {
const width = schedule.resourceColumns.columnWidth;
// Always center horizontal under mouse for vertical mode
context.newX = context.elementStartX = context.elementX = mouseX - width / 2;
DomHelper.setTranslateX(proxy, context.newX);
proxy.style.width = `${width}px`;
proxy.style.height = `${newSize}px`;
}
// Prevent tooltips from showing while dragging
schedule.element.classList.add('b-dragging-event');
}
onTaskDrag ({ event, context }) {
const
me = this,
coordinate = DomHelper[`getTranslate${me.schedule.isHorizontal ? 'X' : 'Y'}`](context.element),
date = me.schedule.getDateFromCoordinate(coordinate, 'round', false),
// Coordinates required when used in vertical mode, since it does not use actual columns
resource = context.target && me.schedule.resolveResourceRecord(context.target, [event.offsetX, event.offsetY]);
// Don't allow drops anywhere, only allow drops if the drop is on the timeaxis 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;
}
// Drop callback after a mouse up, take action and transfer the unplanned task to the real SchedulerEventStore (if it's valid)
async onTaskDrop ({ context, event }) {
const
me = this,
{ task, target } = context;
const listCount = me.grid.data.length;
me.schedule.disableScrollingCloseToEdges(me.schedule.timeAxisSubGrid);
const customErrorMessage= getLodash(me.jsonDef, 'customErrorMessage');
// 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
coordinate = DomHelper[`getTranslate${me.schedule.isHorizontal ? 'X' : 'Y'}`](context.element),
date = me.schedule.getDateFromCoordinate(coordinate, 'round', false),
// Try resolving event record from target element, to determine if drop was on another event
targetEventRecord = me.schedule.resolveEventRecord(context.target);
const finalize = me.context.finalize;
if(moment().isAfter(date, 'second')) {
me.setShowAlert(true);
const errorMsg= (customErrorMessage && customErrorMessage.pastDateErrorMsg) || DRAG_PAST_DATE_ERROR_MSG;
me.setErrorMessage(errorMsg);
return false;
}
if (date) {
me.setShowAlert(false);
me.setErrorMessage('');
me.showLoader();
const response = await me.submitTaskDetails({ ...task.data, resourceId: context.resource.data.id });
me.hideLoader();
// if(response === null || (response && response.errorCode)) {
// const errorMsg= (customErrorMessage && customErrorMessage.workflowUpdateErrorMsg) || WORKFLOW_UPDATE_ERROR;
// me.setShowAlert(true);
// me.setErrorMessage(errorMsg);
// return false;
// }
// Remove from grid first so that the data change
// below does not fire events into the grid.
me.setTaskListCount(listCount-1);
me.grid.store.remove(task);
// task.setStartDate(date, true);
task.startDate = date;
task.resource = context.resource;
me.schedule.eventStore.add(task);
}
// Dropped on a scheduled event, display toast
if (targetEventRecord) {
WidgetHelper.toast(`Dropped on ${targetEventRecord.name}`);
}
finalize();
// me.context.finalize();
} else {
me.abort();
}
me.schedule.element.classList.remove('b-dragging-event');
}
}