Premium support for our pure JavaScript UI components


Post by sudhanshu.jain »

Hi,

we trying to achieve drag and drop functionality from grid for scheduler pro, https://www.bryntum.com/examples/scheduler/frameworks/react/javascript/drag-from-grid/build/index.html

Added the Grid component as mentioned in the example and code to handle the dragging of unscheduled tasks.

import { DateHelper, WidgetHelper, Grid, Splitter, DragHelper, StringHelper, Rectangle, DomHelper } from 'bryntum-schedulerpro';

class UnplannedGrid extends Grid {

  static get $name () {
    return 'UnplannedGrid';
  }

  // Factoryable type name
  static get type () {
    return 'unplannedgrid';
  }

  static get defaultConfig () {
    return {
      features: {
        stripe: true,
        sort: 'name'
      },

  columns: [{
    text: 'Unassigned tasks',
    flex: 1,
    field: 'name',
    htmlEncode: false,
    renderer: (data) => `${data.record.name}`
  }, {
    text: 'Duration',
    width: 100,
    align: 'right',
    editor: false,
    field: 'duration',
    renderer: (data) => `${data.record.duration} ${data.record.durationUnit}`
  }],

  rowHeight: 50
};
  }

  construct (config) {
    super.construct(config);

this.project.assignmentStore.on({
  remove ({ records }) {
    records.forEach(assignment => {
      this.project.eventStore.remove(assignment.event);
      this.store.add(assignment.event);
    });
  },
  thisObj: this
});
  }
}

 const unplannedGrid = new UnplannedGrid({
      ref: 'unplanned',
      appendTo: targetElement,
      // Schedulers stores are contained by a project, pass it to the grid to allow it to access them
      project: scheduler.current.schedulerInstance.project,
      store: {
        modelClass: Task
      },
      data: [
        {
          'id': 1,
          'name': 'Fun task',
          'duration': 4,
          'durationUnit': 'h',
          'iconCls': 'b-fa b-fa-fw b-fa-beer'
        },
        {
          'id': 2,
          'name': 'Medium fun task',
          'duration': 8,
          'durationUnit': 'h',
          'iconCls': 'b-fa b-fa-fw b-fa-cog'
        },
        {
          'id': 3,
          'name': 'Outright boring task',
          'duration': 2,
          'durationUnit': 'h',
          'iconCls': 'b-fa b-fa-fw b-fa-book'
        }
      ],
      tbar: [
        'Grid view'
      ]
    });
    // Handles dragging
    const drag = new Drag({
      grid: unplannedGrid,
      schedule: scheduler,
      constrain: false,
      outerElement: unplannedGrid.element
    });

on drag and drop from grid, onTaskDrop facing the error 'project.getGraph is not a function' while adding the task to the event store of the scheduler.
The task is not getting dropped in the scheduler component, it is not getting added to the event store of the scheduler.

onTaskDrop ({ context }) {
    const
      scheduler = this.schedule.current.schedulerInstance,
      { task, target } = context;

scheduler.disableScrollingCloseToEdges(scheduler.timeAxisSubGrid);

// 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${scheduler.isHorizontal ? 'X' : 'Y'}`](context.element),
    date = scheduler.getDateFromCoordinate(coordinate, '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.
    this.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}`);
  }

  this.context.finalize();
} else { // Dropped somewhere undesired, abort
  this.abort();
}

scheduler.element.classList.remove('b-dragging-event');

  }
}

Image

Here is the code for the scheduler component

<BryntumScheduler
    ref = {scheduler}
    autoHeight = {true}
    viewPreset = {getViewPreset(timelineView)}
    tbar = {
        [
            {
                type: 'combo',
                value: 'dayAndWeek',
                editable: false,
                ref: 'viewPresetCombo',
                cls: 'select-view',
                listCls: 'list-items',
                listeners: { change: viewPresetHandler },
                items: [{
                    value: 'monthAndYear',
                    text: 'Month'
                },
                    {
                        value: 'weekAndDay',
                        text: 'Week'
                    },
                    {
                        value: 'dayAndWeek',
                        text: 'Day'
                    }]
            },
            {
                type: 'dateField',
                editable: false,
                cls: 'date-field',
                listeners: {
                    change: setSelectedDate,
                    trigger: onDatePickerLoad
                },
                ref: 'selectDate'
            },
            '->',
            {
                type: 'button',
                text: 'Today',
                listeners: { click: setCurrentDate },
                cls: 'btn-today'
            },
            {
                type: 'button',
                icon: 'b-fa-angle-left',
                cls: 'btn-prev',
                listeners: { click: viewPrevious }
            },
            {
                type: 'button',
                icon: 'b-fa-angle-right',
                cls: 'btn-next',
                listeners: { click: viewNext }
            },
            {
                type: 'textfield',
                ref: 'filterByName',
                placeholder: 'Search..',
                cls: 'input-search',
                clearable: true,
                keyStrokeChangeDelay: 100,
                triggers: {
                    filter: {
                        align: 'start',
                        cls: 'b-fa b-fa-search'
                    }
                },
                listeners: { change: searchHandler }
            }
        ]
    }
    resources = {data.resources}
    startDate = {new Date(endYear, ZERO, ONE)}
    endDate = {new Date(endYear, TEN, TWENTY_TWO)}
    visibleDate = {new Date()}
    emptyText = {'No matches'}
    columns = {getColumnsList(getLodash(jsonDef, 'columns', []))}
    filterBarFeature = {true} 
    listeners = {{
        eventClick: ({ eventRecord, eventElement, event }) => {
            eventRecord.data.elementType = TASK;
            openEventPopup(eventRecord, eventElement, event.x, event.y, TASK);
        },
        scheduleDblClick: ({ resourceRecord, tickStartDate,
                               tickEndDate, event }) => onScheduleClick(
            resourceRecord, tickStartDate, tickEndDate, event),
        async beforeEventDropFinalize ({ context }) {
            // update the task with the dropped dates and resource id
            const task = {
                ...context.eventRecords[FIRST_INDEX].data,
                startDate: context.startDate,
                endDate: context.endDate,
                resourceId: context.newResource.id
            };
            // check again if the date is less than today
            if(moment().isBefore(task.startDate, 'second')) {
                // show progress bar
                scheduler?.current?.schedulerInstance?.mask({
                    text: ''
                });
                const response = await submitTaskDetails(task);
                if(response === null) {
                    setShowAlert(true);
                    setErrorMessage(ErrorMessageForUpdateWorkflow);
                }
                if(props.dragCompleted) {
                    props?.dragCompleted(task);
                }
                // hide progress bar
                scheduler?.current?.schedulerInstance?.unmask();
            }
        }
    }}
    events = {data.events}
    eventStyle = {'colored'}
    eventLayout = {'stack'}
    eventBodyTemplate = {(data) => getEventTemplate(data)}
    eventRenderer = {(eventRecord) => eventRenderer(eventRecord)}
    eventMenuFeature = {false} 
    eventEditFeature = {{
        disabled: true 
    }}
    eventDragCreateFeature = {{
        disabled: true 
    }}
    eventDragFeature = {{
        disabled: !jsonDef?.dragAllow,
        validatorFn ({ startDate }) {
            if(moment().isAfter(startDate, 'second')) {
                return {
                    valid: false,
                    message: ErrorMessageForPastDate
                };
            }
            return {
                valid: true
            };
        }
    }}
    eventResizeFeature = {{
        disabled: true
    }}
    timeRangesFeature = {{
        showCurrentTimeLine: true,
        showHeaderElements: true,
        enableResizing: true
    }}
/>

can you please help in fixing the error while drag and drop of tasks from the grid

Attachments
Screenshot 2021-05-05 at 12.56.30 PM.png
Screenshot 2021-05-05 at 12.56.30 PM.png (296.89 KiB) Viewed 484 times

Post by saki »

Make sure please that you extend the correct Model. For Scheduler Pro, Task.js should look like this:

import { EventModel } from '@bryntum/schedulerpro/schedulerpro.umd';

export default class Task extends EventModel {
    static get defaults() {
        return {
            // in this demo, default duration for tasks will be hours (instead of days)
            durationUnit : 'h'
        };
    }
}

Post Reply