Our powerful JS Calendar component


Post by orthobridge »

Hi,

Thanks for the feedback, it was throwing code at the wall - struggle with the documentation tbh.

If you want to reproduce the loadOnDemand + resourceview issue - using your own demo

https://bryntum.com/products/calendar/examples/resourceview/

Go to the URL above.

add these pieces of code


datePicker : {
    showEvents : true
}

//Inside of the features object :

loadOnDemand : true  

Exact same issue

Attachments
Capture.PNG
Capture.PNG (239.37 KiB) Viewed 700 times

Post by Animal »

This one I can reproduce. It is a known bug. I am working on it now.

I am slightly mystified by how your app is initially kicking off the first load though.

A resource view has to have a loaded resource store so that it knows what resources to create views for. But no views exist yet, so there is no load kicked off, so it cannot create views.

How has your app kicked this process off?


Post by Animal »

OK, if your sidebar datepicker has showEvents : true, that will do it. That will ask for a month's worth of events

I will have to make it work without that though. I will make it by default "prime the pump" with a months worth of events centered on the view's current date


Post by orthobridge »

Here's my source. Modelled on the sample code. The JSON is being built in a PostGreSQL query - example below.


<script>
    const { Toast, ArrayHelper, DateHelper, StringHelper, Calendar, Splitter } = bryntum.calendar;
    
$(document).ready(function () { const calendar = new Calendar({ // Start life looking at this date date : new Date(), includeWeekendsButton: false, // Features named by the properties are included. features : { loadOnDemand: true, drag : false, eventTooltip : { // Override the default which is to show on click. //showOn : 'hover', deleteEvent : null, // We want the tooltip's left edge aligned to the right edge of the event if possible. align : 'l-r', // Mustn't shrink because of large, graphical content minWidth : null, renderer : data => `<dl> <dt>Assigned to:</dt> <dd> ${StringHelper.encodeHtml(data.eventRecord.resource.name)} </dd> <dt>Time:</dt> <dd> ${DateHelper.format(data.eventRecord.startDate, 'LT')} - ${DateHelper.format(data.eventRecord.endDate, 'LT')} </dd> <dt>Note:</dt> ${data.eventRecord.get('notes') ? `<dd>${StringHelper.encodeHtml(data.eventRecord.notes)}</dd>` : '<dd>n/a</dd>'} </dl> `, }, }, // CrudManager arranges loading and syncing of data in JSON form from/to a web service crudManager: { transport: { load: { url: '/api/practice/calendar/resource_events' } }, autoLoad: false, }, // Render to a DIV with this id appendTo : 'container', modes : { // Mode name can be anything if it contains a "type" property. dayResources: { type: 'resource', title: 'Day', resourceWidth: '30em', view: { type: 'dayview', dayStartTime: 8, dayEndTime: 20, tools: { close: { cls: 'b-fa b-fa-times', tooltip: 'Remove chair', handler() { const calendar = this.up('calendar'), resourceFilter = calendar.widgetMap.resourceFilter, resource = this.resource; resourceFilter.selected.remove(resource); } } } }, meta: resource => resource.title }, // Mode name can be anything if it contains a "type" property. weekResources : { // Type has the final say over which view type is created type : 'resource', title : 'Week', resourceWidth : '30em', // This is a config object for the subviews view : { dayStartTime : 8, // Dock an additional widget at the end of the header // Show a close icon to filter out the resource tools : { close : { cls : 'b-fa b-fa-times', tooltip : 'Filter out this resource', handler() { const calendar = this.up('calendar'), resourceFilter = calendar.widgetMap.resourceFilter, resource = this.resource; resourceFilter.selected.remove(resource); } } } }, // Info to display below a resource name meta : resource => resource.title }, // Let's not show the default views day : null, week : null, month : null, year : null, agenda : null, }, listeners: { beforeEventDelete({ eventRecords, context }) { // creating new event or editing console.log(context); console.log(eventRecords); if (eventRecords[0].resource.isVirtualChair) { alert('Event summaries cannot be cancelled - cancel the appointment in the chair'); } else { _setAppointmentID(eventRecords[0].id); dmx.parse('modal_cancel_booking.show()'); } return false; }, beforeEventEdit({ eventRecord }) { // creating new event or editing console.log(eventRecord.resource); if (eventRecord.resource.isUnavailable || eventRecord.resource.isVirtualChair) { _alertNOResource(); } else { // adding event - get timeslot details if (eventRecord.meta.isCreating) { _setAppointmentID(''); _setStartDate(eventRecord.startDate); } else { _setAppointmentID(eventRecord.id); } _setSelectedChair(eventRecord.resource.id); dmx.parse('modal_event_editor.show()'); } return false; } }, // A block of configs which is applied to all modes. modeDefaults: { view: { hourHeight: 120 }, }, }); calendar.crudManager.load(); window.calendar = calendar; }); // init our data function _setAppointmentID(id) { dmx.parse("var_editing_appointment_id.setValue('" + id + "')"); } // init our data function _setSelectedChair(id) { dmx.parse("var_practise_room_chair_id.setValue('" + id + "')"); } // init our data function _setStartDate(_startDate) { dmx.parse("var_start_date.setValue('" + _startDate + "')"); } // clear up any native leftovers function _reloadData() { calendar.crudManager.load(); } function _alertNOResource() { dmx.parse("run({'bootbox.alert':{buttons:{ok:{label:'Cancel',className:'btn-info'}},message:'No resource available on selected date',title:'NO APPOINTMENTS'}})"); calendar.crudManager.load(); } </script>

JSON sample:


{
  "success": true,
  "resources": {
    "rows": [
      {
        "id": "a0e40761-23a2-4f6c-a960-32bb33690548",
        "name": "Chair 1 - Jo",
        "title": "Mrs. Jo King",
        "isActive": true,
        "eventColor": "#ac2020",
        "isUnavailable": false,
        "isVirtualChair": false
      },
      {
        "id": "459fb9f7-b0f3-46b9-b023-dd02bcdc6c28",
        "name": "Chair 2 - Angus",
        "title": null,
        "isActive": true,
        "eventColor": "#9c9da5",
        "isUnavailable": true,
        "isVirtualChair": false
      },
      {
        "id": "331507f9-2e8a-4340-847c-dc17aa81eb0d",
        "name": "Chair 3 - Carol",
        "title": null,
        "isActive": true,
        "eventColor": "#9c9da5",
        "isUnavailable": true,
        "isVirtualChair": false
      },
      {
        "id": "d43b99a6-8753-46ae-b97c-3b9b85be2417",
        "name": "Chair 4 - Francis therapist 1",
        "title": "Dr. Roger Stephens",
        "isActive": true,
        "eventColor": "#c1bb0b",
        "isUnavailable": false,
        "isVirtualChair": false
      },
      {
        "id": "38dd904b-94c3-46dd-bcee-ff90480fd5b7",
        "name": "Chair 5 - Francis therapist 2",
        "title": "Dr. Roger Stephens",
        "isActive": true,
        "eventColor": "#acf50f",
        "isUnavailable": false,
        "isVirtualChair": false
      },
      {
        "id": "b68514d5-f2c6-4e19-acd5-576c153358a6",
        "name": "Chair 6 - Francis therapist 3",
        "title": "Dr. Roger Stephens",
        "isActive": true,
        "eventColor": "#03dd28",
        "isUnavailable": false,
        "isVirtualChair": false
      },
      {
        "id": "5bf9e786-de26-4ec5-8726-8a78380adb40",
        "name": "Chair 7 - Francis therapist 4",
        "title": "Dr. Roger Stephens",
        "isActive": true,
        "eventColor": "#a8481f",
        "isUnavailable": false,
        "isVirtualChair": false
      },
      {
        "id": "374bc0ee-8c23-47a8-8054-e47e6bd9b8fa",
        "name": "Justin - Chair 1 Room 1",
        "title": "Mr. john Curley",
        "isActive": true,
        "eventColor": "#e10909",
        "isUnavailable": false,
        "isVirtualChair": false
      },
      {
        "id": "df74d09a-9c41-4734-8d0d-2a46d00080d8",
        "name": "SUPERVISOR",
        "title": "Dr. Roger Stephens",
        "isActive": true,
        "eventColor": null,
        "isUnavailable": false,
        "isVirtualChair": true
      }
    ]
  },
  "events": {
    "rows": [
      {
        "id": "16dfcc02-2475-4c41-ad88-753321262779",
        "name": " CHAT 10 | Kent Chanel",
        "notes": "Chat, upsell tooth whitener. Get things done.",
        "endDate": "2022-12-02T09:30:00+00:00",
        "iconCls": "b-fa b-fa-arrows-alt-h ",
        "startDate": "2022-12-02T09:00:00+00:00",
        "eventColor": "#336bdb",
        "resourceId": "5bf9e786-de26-4ec5-8726-8a78380adb40"
      },
      {
        "id": "62c893b6-4984-4782-ae24-a89aad5c5b77",
        "name": " BOND 30 | Kendall Paradowski",
        "notes": "Plug battery in",
        "endDate": "2022-12-02T09:30:00+00:00",
        "iconCls": "b-fa b-fa-exclamation-triangle",
        "startDate": "2022-12-02T09:00:00+00:00",
        "eventColor": "red",
        "resourceId": "d43b99a6-8753-46ae-b97c-3b9b85be2417"
      },
      {
        "id": "323fab88-d3d3-4525-a3ab-9d18a940728b",
        "name": " CHAT 10 | Kent Chanel | SUPERVISION",
        "notes": "Chat, upsell tooth whitener. Get things done.",
        "endDate": "2022-12-02T09:10:00+00:00",
        "iconCls": "b-fa b-fa-arrows-alt-h",
        "startDate": "2022-12-02T09:00:00+00:00",
        "eventColor": "#336bdb",
        "resourceId": "df74d09a-9c41-4734-8d0d-2a46d00080d8"
      },
      {
        "id": "625267d6-7784-402e-a9e1-042e348140cb",
        "name": " BOND 30 | Kendall Paradowski | SUPERVISION",
        "notes": "Plug battery in",
        "endDate": "2022-12-02T09:15:00+00:00",
        "iconCls": "b-fa b-fa-exclamation-triangle",
        "startDate": "2022-12-02T09:00:00+00:00",
        "eventColor": "#336bdb",
        "resourceId": "df74d09a-9c41-4734-8d0d-2a46d00080d8"
      },
      {
        "id": "bb257719-5566-40c9-abe6-3eebadfd08b6",
        "name": " CHAT 10 | Letha Jacka",
        "notes": "See more stuff to patients",
        "endDate": "2022-12-02T09:35:00+00:00",
        "iconCls": "b-fa b-fa-exclamation-triangle",
        "startDate": "2022-12-02T09:05:00+00:00",
        "eventColor": "red",
        "resourceId": "38dd904b-94c3-46dd-bcee-ff90480fd5b7"
      },
      {
        "id": "f0ee6353-cda3-4102-899f-ca861f2a9548",
        "name": " CHAT 10 | Letha Jacka | SUPERVISION",
        "notes": "See more stuff to patients",
        "endDate": "2022-12-02T09:15:00+00:00",
        "iconCls": "b-fa b-fa-exclamation-triangle",
        "startDate": "2022-12-02T09:05:00+00:00",
        "eventColor": "#336bdb",
        "resourceId": "df74d09a-9c41-4734-8d0d-2a46d00080d8"
      }
    ]
  }
}



Post by Animal »

OK, you kick off crudManager.load() with no params.

Does that then return all events? If you do that, then why are you using loadOnDemand?


Post by orthobridge »

It loads an initial 7 days from today's date - it's just a buffer.

From that point on, the calendar issues requests.

Loading ALL events isn't feasible. Most orthos will have 40-50 appointments per day, 5 days a week, 5 doctors per practice. On average. It's too much data and all needs to be sync'd (web sockets next)


Post by Animal »

Yes, that's entirely reasonable. I have majorly refactored the LoadOnDemand feature today to be much more robust.

I have added tests which test it when using ResourceView and when using showEvents in the sidebar date picker.

This should all work fine for you in the next release. If I can get this past the review process quickly, then it should be available in a nightly build if you have access to the Customer Zone.


Post Reply