Premium support for our pure JavaScript UI components


Post by gorakh.nath »

My use case is :- If we drag and drop task from grid to a technician who already has a task assigned to him at the same time then it should not allow and should throw the error.
Now to achieve this I set allowOverlap to false in event but still it is not throwing error and allowing to drop the task on the same time in which a task assigned to technician.
I have attached the screenshot and sample application.
Please let me know what need to modify in code.

Attachments
Overlapping_Task.zip
(2.98 MiB) Downloaded 72 times
Screenshot 2021-07-21 at 2.19.17 PM.png
Screenshot 2021-07-21 at 2.19.17 PM.png (341.44 KiB) Viewed 800 times

Post by saki »

I haven't found any place in your code where you set allowOverlap:false. Setting it from the console leads to the behavior shown in the video. As you can see there's no error thrown but the drag is cancelled if it would lead to an overlap. If you need an error (popup) you would need to do it in the application.

Untitled.gif
Untitled.gif (505.21 KiB) Viewed 796 times

Post by gorakh.nath »

@saki thanks for quick reply, It is working when adding here:-

<BryntumScheduler
  allowOverlap={false}/>

This will set overlap false to all the technician , but I am looking at each technician level, for example we have two technician(Arcady and Dave):-

{
  "id": 1,
   "name": "Arcady",
   "role": "Core developer",
    "calendar": "day"
},
{
 "id": 2,
  "name": "Dave",
  "role": "Tech Sales",
   "calendar": "day"
}

Now I want to allow overlap true for Dave and false for Arcady.
How can we achieve this?


Post by saki »

That is not configurable because allowOverlap is a Scheduler config option, not a resource config option. You will need to handle it in your code. The general approach to take would be:

  1. Add a field to the resource model (for example allowOverlapEvents)
  2. In the code check the value of this field and execute the different actions depending on the true/false value.

Post by gorakh.nath »

@saki Where I should add the logic I am sharing the drag.js file , you can find the same in sample application I attached above.

/**
 * Taken from the vanilla dragfromgrid example
 */
// we import schedulerpro.umd for IE11 compatibility only. If you don't use IE import:
// import { DragHelper, DomHelper, Rectangle, WidgetHelper } from '@bryntum/schedulerpro';
import { DateHelper, DragHelper, DomHelper, Rectangle, WidgetHelper } from '@bryntum/schedulerpro/schedulerpro.umd';

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);

    // Configure DragHelper with schedule's scrollManager to allow scrolling while dragging
    me.scrollManager = me.schedule.scrollManager;

    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),
        newWidth = 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-sch-event');
    proxy.classList.add('b-unassigned-class');
    proxy.classList.add(`b-${schedule.mode}`);
    proxy.innerHTML = `<i class="${task.iconCls}"></i> ${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
    me.schedule.element.classList.add('b-dragging-event');
}

onTaskDrag({ context }) {
    const
        me           = this,
        { schedule } = me,
        { task }     = context,
        coordinate   = DomHelper[`getTranslate${schedule.isHorizontal ? 'X' : 'Y'}`](context.element),
        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);

    // Don't allow drops anywhere, only allow drops if the drop is on the timeaxis and on top of a Resource
    context.valid &= Boolean(startDate && resource) &&
        (schedule.allowOverlap || schedule.isDateRangeAvailable(startDate, endDate, null, 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)
onTaskDrop({ context }) {
    const
        me = this,
        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 = me.schedule.getDateFromCoordinate(DomHelper.getTranslateX(context.element), 'round', false),
            // Try resolving event record from target element, to determine if drop was on another event
            targetEventRecord = me.schedule.resolveEventRecord(context.target);

        if (date) {
            // Remove from grid first so that the data change
            // below does not fire events into the grid.
            me.grid.store.remove(task);

            task.setStartDate(date, true);
            task.resource = context.resource;
            debugger;
            me.schedule.eventStore.add(task);
        }

        // Dropped on a scheduled event, display toast
        if (targetEventRecord) {
            WidgetHelper.toast(`Dropped on ${targetEventRecord.name}`);
        }

        me.context.finalize();
    }
    else {
        me.abort();
    }

    me.schedule.element.classList.remove('b-dragging-event');
}
};

if I am not wrong you are suggesting to add the setting like this:-

{
 "id": 1,
  "name": "Arcady",
 "role": "Core developer",
"calendar": "day",
"allowOverlapEvents": true
},

Can you please add a example in above code.


Post by saki »

We do not have a ready example for that. Generally, you can add it to onTaskDrag after you have resource available. Pseudo-code:

if(!resource.allowEventOverlap && isOverlapping) { // isOverlapping is to be written
     context.valid = false;
}
else {
     context.valid = true;
}

You would use a similar logic in onTaskDrop:

if(!resource.allowEventOverlap && isOverlapping) { // isOverlapping is to be written 
    me.abort();
}
else {
    me.context.finalize();
}

Post by gorakh.nath »

@saki allowOverlap:false is not working if I am using BryntumSchedulerPro

import { BryntumSchedulerPro }
  from '@bryntum/schedulerpro-react';
<BryntumSchedulerPro
          ref = {scheduler}
          allowOverlap={false}
/>

Can I use this feature in BryntumSchedulerPro?


Post by alex.l »

Yes, you can. I just tested it in our examples here https://www.bryntum.com/examples/scheduler-pro/drag-from-grid/
Run in console: scheduler.allowOverlap = false and it works just fine.
Please share your solution if you still have problems with that.

Thanks,
Alex

All the best,
Alex


Post Reply