Hi team,
The tool tip that is coming on dragging of task from grid is not showing the clock icon how we can show it? so that view will be consistence between tool tip showing when hovering inside scheduler and on dragging task from grid.
I attached two screenshot in which one is showing the clock icon on hover inside the calendar and another its not showing clock icon on dragging task form grid.
My Drag.js file code is:-
import { DragHelper, DomHelper, Rectangle, WidgetHelper, StringHelper, DateHelper, Tooltip } from '@bryntum/schedulerpro/schedulerpro.umd';
import { moment } from '../../../utilities/moment';
import {DRAG_PAST_DATE_ERROR_MSG, WORKFLOW_UPDATE_ERROR, TECHNICIAN_OVERLAP_TASK_ERROR, CUSTOM_ERROR_KEY} from "../utills";
import { getLodash } from '../../../utilities/lodash';
import { ActionDispatcher } from '../../../uibuilder/Actions/ActionDispatcher';
import { SetPageContext }
from '../../../uibuilder/ActionType/pageConfig/SetPageContext';
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
});
}
/**
*
* @param {object} schedulerObj : contains the scheduler object
* @param {string} key : contains the key
* @returns {string}: based on the key
*/
getErrorMsg = (schedulerObj, key)=> {
const customError= getLodash(schedulerObj.jsonDef, 'customErrorMessage');
let errorMsg='';
if(key){
switch (key) {
case CUSTOM_ERROR_KEY.TASK_OVERLAPPING_ERROR:
errorMsg= customError?.taskOverlappingErrorMsg || TECHNICIAN_OVERLAP_TASK_ERROR;
break;
case CUSTOM_ERROR_KEY.WORKFLOW_UPDATE_ERROR:
errorMsg= customError?.workflowUpdateErrorMsg || WORKFLOW_UPDATE_ERROR;
break;
case CUSTOM_ERROR_KEY.PAST_DATE_ERROR:
errorMsg= customError?.pastDateErrorMsg || DRAG_PAST_DATE_ERROR_MSG;
break;
default:
break;
}
}
return errorMsg;
}
/**
*
* @param {object} schedulerObj : contains scheduler object
* @param {string} errorMsgKey : contains key based on that error message will come
*/
showErrorMsg = (schedulerObj, errorMsgKey)=> {
const errorMsg= this.getErrorMsg(schedulerObj,errorMsgKey);
schedulerObj.setShowAlert(true);
schedulerObj.setErrorMessage(errorMsg);
}
/**
*
* @param {object} obj : contains the object value use to set the invalid of scheduler
* @returns {boolean} : if valid true else false
*/
isContextValid = (obj)=> {
let isValidContext = false;
if(obj && obj.valid && Boolean(obj.date && obj.resource)){
isValidContext= true;
//Now check for overlap task if allowOverlap false defined in the config
if(obj && obj.schedule && !obj.schedule.allowOverlap && !obj.allowTechnicianOverlap && !obj.allowEventOverlap){
isValidContext= obj.schedule.isDateRangeAvailable(obj.startDate, obj.endDate, null, obj.resource);
!isValidContext && this.showErrorMsg(obj.me, CUSTOM_ERROR_KEY.TASK_OVERLAPPING_ERROR);
}
}
return isValidContext;
}
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');
if (!me.tip) {
me.tip = new Tooltip({
align : 'b-t',
clippedBy : [schedule.timeAxisSubGridElement, schedule.bodyContainer],
forElement : context.element,
cls : 'b-popup b-sch-event-tooltip'
});
}
}
onTaskDrag ({ event, context }) {
const
me = this,
{ schedule } = me,
{ task } = context,
coordinate = DomHelper[`getTranslate${me.schedule.isHorizontal ? 'X' : 'Y'}`](context.element),
date = me.schedule.getDateFromCoordinate(coordinate, 'round', false),
startDate = schedule.getDateFromCoordinate(coordinate, 'round', false),
endDate = startDate && DateHelper.add(startDate, task.duration, task.durationUnit),
// Coordinates required when used in vertical mode, since it does not use actual columns
resource = context.target && 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
paramObj= { valid: context.valid, date,resource},
isValid= this.isContextValid(paramObj);
context.valid = isValid;
// Save reference to resource so we can use it in onTaskDrop
context.resource = resource;
if (me.tip && context.valid) {
const
dateFormat = schedule.displayDateFormat,
formattedStartDate = DateHelper.format(startDate, dateFormat),
formattedEndDate = DateHelper.format(endDate, dateFormat);
me.tip.html = `
<div class="b-sch-event-title">${task.name}</div>
<div class="b-sch-tooltip-startdate">${formattedStartDate}</div>
<div class="b-sch-tooltip-enddate">${formattedEndDate}</div>
`;
me.tip.showBy(context.element);
} else {
me.tip?.hide();
}
}
// 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, resource } = context,
listCount = me.grid.data.length,
{ schedule } = me,
coordinate = DomHelper[`getTranslate${schedule.isHorizontal ? 'X' : 'Y'}`](context.element),
date = me.schedule.getDateFromCoordinate(coordinate, 'round', false),
startDate = schedule.getDateFromCoordinate(coordinate, 'round', false),
endDate = startDate && DateHelper.add(startDate, task.duration, task.durationUnit),
paramObj= { valid: context.valid,
date,resource,schedule,
startDate, endDate ,
me,
allowTechnicianOverlap: resource?.originalData?.allowTechnicianOverlap,
alloweEventOverlap: task?.originalData?.alloweEventOverlap
}
schedule.disableScrollingCloseToEdges(me.schedule.timeAxisSubGrid);
const isValid = this.isContextValid(paramObj);
me.tip && me.tip?.hide();
// If drop was done in a valid location, set the startDate and transfer the task to the Scheduler event store
if (isValid && context.valid && target) {
const
// 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')) {
this.showErrorMsg(me,CUSTOM_ERROR_KEY.PAST_DATE_ERROR)
return false;
}
if (date) {
me.setShowAlert(false);
me.setErrorMessage('');
me.showLoader();
task.startDate = startDate;
task.endDate = endDate;
const pageContext = new SetPageContext({task: task.data, resource: resource?.originalData });
this.dispatch(pageContext.plainAction());
const ah = new ActionDispatcher(this);
ah.doAction(this.jsonDef.dropGridTaskAction);
//const response = await me.submitTaskDetails({ ...task.data, resourceId: context.resource.data.id });
me.hideLoader();
// if(response === null || (response && response.errorCode)) {
// this.showErrorMsg(me,CUSTOM_ERROR_KEY.WORKFLOW_UPDATE_ERROR)
// 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');
}
}