We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Grouping anomalies when switching datasources and resources based on view

I am implementing a calendar into our app that will give the user the options to view a monthly schedule, agenda, and timelines for both day and week. The timeline views feature grouping based on a 'work order' that has individual employees associated to it. If there is not an employee scheduled for a certain time period, an 'Open' employee appears and those shifts are displayed. Due to the amount of data that is needed, I am using our api (built around react-redux and redux-saga) to get information and inject it based on the view. The monthly calendar has a much wider scope, so a lot of information that is needed in the drilldown doesn't exist until it is called for once the view is switched.

With a small dataset, if I get all of the information up front, the calendar renders appropriately in all of the views, however, any time I make a call to get new data it will break the grouping on the timeline views by displaying all events at the parent level. My schedule component is as follow:
<ScheduleComponent
actionBegin={(args) => this.onActionBegin(args)}
actionComplete={(args) => this.onActionComplete(args, data, AppointmentData)}
currentView={this.state.currentView}
eventSettings={{dataSource: data}}
height='750px'
id='job-schedule'
navigating={(args) => this.onNavigation(args)}
quickInfoTemplates={{content: (props) => this.renderQuickInfoBody(props)}}
readonly
ref={t => (this.scheduleObj = t)}
renderCell={(args) => this.renderResourceHeader(args)}
resourceHeaderTemplate={(props) => this.renderResourceData(props)}
selectedDate={this.state.selectedDate}>
<ViewsDirective>
<ViewDirective option='Agenda' />
<ViewDirective option='Month' />
<ViewDirective option='TimelineWeek' interval={1} />
<ViewDirective option='TimelineDay' interval={1} />
</ViewsDirective>
<ResourcesDirective id='job-schedule-resources'>
<ResourceDirective
allowMultiple
dataSource={jobData}
field='JobId'
idField='Id'
name='Jobs'
textField='Subject'
title='Job' />
<ResourceDirective
allowMultiple
dataSource={workerData}
field='WorkerId'
groupIDField='JobId'
idField='WorkerId'
name='Workers'
title='Worker' />
<ResourceDirective
allowMultiple
colorField='Color'
field='AppointmentId'
idField='Id'
name='Appointments'
title='Appointment' />
<ResourceDirective
allowMultiple={false}
colorField='Color'
dataSource={data}
field='Id'
idField='Id'
name='Events'
textField='OwnerText'
title='Event' />
</ResourcesDirective>
<Inject services={[Agenda, Month, TimelineViews]} />
</ScheduleComponent>
On screen entry, they see the monhly view based on the data returned from the db. When switching views, the following occurs in the onActionComplete function (whether or not that should be moved is still something I am exploring):

onActionComplete = (args, data, AppointmentData) => {
let {activeFilters, filters, onFilterChange} = this.props
let filterState = {}
const schedule = document.getElementById('job-schedule')
if (args.requestType === 'viewNavigate') {
if (this.scheduleObj.currentView === 'Agenda') {
this.scheduleObj.height = '750px'
this.scheduleObj.eventSettings = {dataSource: data, resourceColorField: 'Shifts'}
this.scheduleObj.enableTooltip = false
this.scheduleObj.group = {enableCompactView: true, resources: []}
this.scheduleObj.firstDayOfWeek = 0
}

if (this.scheduleObj.currentView === 'Month') {
this.scheduleObj.height = '750px'
this.scheduleObj.eventSettings = {dataSource: data, resourceColorField: 'Shifts'}
this.scheduleObj.enableTooltip = true
this.scheduleObj.group = {enableCompactView: true, resources: []}
this.scheduleObj.firstDayOfWeek = 0
}

if (this.scheduleObj.currentView === 'TimelineWeek') {
const startDate = this.scheduleObj.activeView.renderDates.find(x => x.getDay() === today.getDay())
let endDate = new Date()
endDate.setDate(startDate.getDate() + 7)

activeFilters.dateRangeFrom = {
name: `Date From: ${moment(startDate).format('L')}`,
type: 'dateRangeFrom',
value: moment(startDate).format('L')
}
activeFilters.dateRangeTo = {
name: `Date To: ${moment(endDate).format('L')}`,
type: 'dateRangeTo',
value: moment(endDate).endOf('day')
}

filters.shiftStartDateTime = {ge: startDate, le: endDate}
filterState.filters = filters
filterState.activeFilters = activeFilters
onFilterChange(filterState)
this.scheduleObj.height = 'auto'
this.scheduleObj.eventSettings = {dataSource: AppointmentData, resourceColorField: 'Appointments'}
this.scheduleObj.group = {enableCompactView: true, resources: ['Jobs', 'FloatPoolMembers']}
this.scheduleObj.enableTooltip = true
this.scheduleObj.timeScale = {enable: true, interval: 480, slotCount: 3}
this.scheduleObj.firstDayOfWeek = today.getDay()
}

if (this.scheduleObj.currentView === 'TimelineDay') {
this.scheduleObj.height = 'auto'
this.scheduleObj.eventSettings = {dataSource: AppointmentData, resourceColorField: 'Appointments'}
this.scheduleObj.group = {enableCompactView: true, resources: ['Jobs', 'Workers']}
this.scheduleObj.enableTooltip = true
this.scheduleObj.timeScale = {enable: true, interval: 60, slotCount: 2}
}
} else if (args.requestType === 'toolBarItemRendered') {
let createJobElement = schedule.querySelector('.e-toolbar-btn')
createJobElement.onclick = () => { this.onCreateJobClick() }
}
}
 
The changes to the filters automatically trigger a call to the backend to get new data, which comes back appropriately. There are multiple issues with the render at that point, however:
  1. The events render at the job level as opposed to the dependent worker group
  2. The color from the Appointments resource is not applied to the event (the color should be based on how soon the event is occuring - ie. within 48, 72, or 96 hours)
  3. If the data returns empty, navigating to a new date throws the following error:

What can I do to remedy some of these issues? Am I approaching some of this wrong? Let me know if you need any more information.

5 Replies

KK Karthigeyan Krishnamurthi Syncfusion Team June 4, 2019 08:44 AM UTC

Hi Brett, 
 
Greetings from Syncfusion. 
Please find the below responses. 
Q1: The events render at the job level as opposed to the dependent worker group 
As we are not clear about the reported problem, kindly share more information/image/ video demo which clearly depicts the issue to serve your better. 
Q2: The color from the Appointments resource is not applied to the event 
In the provided code example colorField field is not mapped within the resources. Therefore, we suggest you to use the below highlighted code to overcome the issue and the same can be available in following link. 
 
 
<ResourcesDirective id='job-schedule-resources'> 
              <ResourceDirective 
                allowMultiple 
                dataSource={this.jobData} 
                field='JobId' 
                idField='Id' 
                name='Jobs' 
                textField='Subject' 
                title='Job' 
                colorField='color' /> 
              <ResourceDirective 
                allowMultiple 
                dataSource={this.workerData} 
                field='WorkerId' 
                textField='Subject' 
                groupIDField='JobId' 
                idField='WorkerId' 
                name='Workers' 
                title='Worker' 
                colorField='color' /> 
 
              <ResourceDirective 
                dataSource={this.Appoint} 
                allowMultiple 
                colorField='Color' 
                field='AppointmentId' 
                textField='Subject' 
                idField='Id' 
                name='Appointments' 
                title='Appointment' /> 
              <ResourceDirective 
                allowMultiple={false} 
                colorField='Color' 
                dataSource={this.events} 
                field='Id' 
                idField='Id' 
                name='Events' 
                textField='OwnerText' 
                title='Event' /> 
            </ResourcesDirective> 
 
 
Note: The value of the resourceColorField field should be the resources name defined in the group property. In your shared actionComplete event you wrongly mapped the resourceColorField as shifts. But in group property the resources doesn’t contain the name ‘shifts’. 
 
Q3: If the data returns empty, navigating to a new date throws the following error: 
We have checked the reported scenario by preparing sample with your shared code but when data returns empty, scheduler renders in all the views without any script error. The same can be checked from the following link.  
 
 
Kindly try the shared sample and if the issue persist still revert us back an issue reproducing sample or issue replicating steps to check and proceed further.  
 
Regards, 
Karthi 
 
 
 



BS Brett Simmonds June 4, 2019 08:28 PM UTC

Thanks for the quick response.

1. The events render at the job level as opposed to the dependent worker group:



This is what is happening when calling for new data. If I switch views and the data is already there, the events render properly with the appropriate worker. Using react-redux to make the backend call (whether changing views or changing the date) it will render as shown above. The worker under the top job should each show an event and the same with the worker under job 2.

2. The color from the Appointments resource is not applied to the event 
In the monthly view, the colors are all rendering properly. I fixed that resource naming issue (copied it over wrong when I was copying for the forum post) for that particular view, but the timeline views remain the issue. Looking at the image above, you can see that it is still defaulting to the standard color. This is different from your examples because I need the color to come from the datasource (Appointments) and the actual grouping occurs with the resources provided on the change (Jobs and Workers):
this.scheduleObj.group = {enableCompactView: true, resources: ['Jobs', 'Workers']}
(I apologize that in putting the post together I realize the resource on the TimelineWeek view was improperly named 'FloatPoolMembers' as well, but that has been corrected).

3.  If the data returns empty, navigating to a new date throws the following error:
I am currently exploring this issue further. The issue wasn't the render with an empty dataset, it was navigating away from that date when the dataset was empty, but I will take a look at the example provided and see if I can't resolve this portion.

Again, thank you for your time on this.


KK Karthigeyan Krishnamurthi Syncfusion Team June 6, 2019 10:35 AM UTC

Hi Brett, 
 
Thanks for the update. 
 
Below are the possible cause for the issues and kindly ensure it in your end. 
 
Q1: We suspects that the WorkerId field is not in event collection which could be the cause. In the below sample, Workflow Analysis event has no WorkerId field and the reported issue can be seen. So kindly check whether your datasource having the WorkerId filed for all events. If still issue persists please share the appointment collection to check further. 
 
{ 
      Id: 1, 
      Subject: "Workflow Analysis", 
      StartTime: new Date(2019, 5, 1, 10, 0, 0), 
      EndTime: new Date(2019, 5, 1, 12, 0, 0), 
      IsAllDay: false, 
      JobId: 1, 
      AppointmentId: 1, 
      Id: 1 
    }, { 
      Id: 11, 
      Subject: "Test Analysis", 
      StartTime: new Date(2019, 5, 1, 10, 0, 0), 
      EndTime: new Date(2019, 5, 1, 19, 0, 0), 
      IsAllDay: false, 
      JobId: 1, 
      WorkerId: 1, 
      AppointmentId: 2, 
      Id: 1 
    } 
 
Q2: We suspect parent resource datasource (this.jobData) may not contain the color definition. In the above sample, the PROJECT 1 collection will not have color field and the reported issue can be seen. It is related to Q1. Please check your resource datasource that has a color field and if still issue persists, please share your resource datasouces to serve you better. 
 
this.jobData = [ 
      { Subject: 'PROJECT 1', Id: 1 }, 
      { Subject: 'PROJECT 2', Id: 2, color: '#56ca85' }, 
      { Subject: 'PROJECT 3', Id: 3, color: '#df5286' } 
    ]; 
 
Q3: We will wait for your update. 
 
Regards, 
Karthi 
 



BS Brett Simmonds June 7, 2019 05:34 PM UTC

I was able to solve the issue with the first question. It was actually an oversight on my part that had to do with the render switching the datasource again. Once I sorted that out, the appointments rendered with the appropriate worker.

I am still having an issue with the colors, however. The color needs to be based on the appointment time itself (red if within 48 hours, orange if within 72, yellow if within 96) and then blue or green otherwise (blue if it is populated by a worker, green if open). 

The resources in question are as follows:
      allowMultiple
dataSource={jobData}
field='JobId'
idField='Id'
name='Jobs'
textField='Subject'
title='Job' />
allowMultiple
dataSource={workerData}
field='WorkerId'
groupIDField='JobId'
idField='WorkerId'
name='Workers'
title='Worker' />
allowMultiple
colorField='Color'       dataSource={appointmentData}
field='AppointmentId'
idField='Id'
name='Appointments'       textField='Subject'
title='Appointment' />
On action complete I am modifying the following when it is TimelineWeek or Day:
this.scheduleObj.height = 'auto'
this.scheduleObj.eventSettings = {dataSource: appointmentData, resourceColorField: 'Appointments'}
this.scheduleObj.group = {enableCompactView: true, resources: ['Jobs', 'Workers']}
this.scheduleObj.enableTooltip = true
this.scheduleObj.timeScale = {enable: true, interval: 480, slotCount: 3}
Here is some sample data of what the objects look like:
const appointmentData = [{
Color: '#FF0000',
EndTime: '2019-06-09T18:00:00Z',
Worker: 'Open',
Id: 1020,
JobId: 9,
StartTime: '2019-06-09T10:00:00Z',
Subject: '06/09/2019'
},
{
Color: '#FF8C00',
EndTime: '2019-06-08T18:00:00Z',
Worker: 'Open',
Id: 1019,
JobId: 9,
StartTime: '2019-06-08T10:00:00Z',
Subject: '06/08/2019'},
{
Color: '#92bdd5',
EndTime: '2019-06-07T00:00:00Z',
WorkerId: 378875,
Id: 13,
JobId: 9,
StartTime: '2019-06-06T12:00:00Z',
Subject: '06/06/2019'
}]

const workerData = [{
Agency: '',
Worker: 'Open',
WorkerId: '9-0',
JobId: 9
}, {
Agency: 'Agency 1',
Worker: 'Johnny Gargano',
WorkerId: 378875,
JobId: 3
}]

const jobData = [{
Id: 9,
Subject: 'Job #9'
}]
It still renders the default color at this point. Any suggestions?



HB Hareesh Balasubramanian Syncfusion Team June 10, 2019 12:38 PM UTC

Hi Brett, 

Thanks for the update. 

We suggest you to set the group option to each individual views within view settings instead of achieving it in actionComplete event and for the same we have prepared a sample. And also we have used eventRendered event to change the appointment colors based on the duration of the appointments. Please refer it following link, 

            <ViewsDirective> 
              <ViewDirective option='Agenda' /> 
              <ViewDirective option='Month' /> 
              <ViewDirective option='TimelineWeek' group={{ resources: ['Jobs', 'Workers'] }} interval={1} /> 
              <ViewDirective option='TimelineDay' group={{ resources: ['Jobs', 'Workers'] }} interval={1} /> 
            </ViewsDirective> 

  onEventRendered(args) { 
    if (this.scheduleObj.currentView === "TimelineWeek" || this.scheduleObj.currentView === "TimelineDay") { 
      var diff = (args.data.data.EndTime.getTime() - args.data.data.StartTime.getTime()) / 1000; 
      diff /= (60 * 60); 
      diff = Math.abs(Math.round(diff)); 
      if (diff <= 48) { 
        args.element.style.backgroundColor = "red"; 
      } else if (diff > 48 && diff <= 72) { 
        args.element.style.backgroundColor = "green"; 
      } else if ( diff> 72 && diff <= 96) { 
        args.element.style.backgroundColor = "blue"; 
      } 
    } 
  } 




Regards, 
Hareesh B 



Loader.
Live Chat Icon For mobile
Up arrow icon