Repeat schedule entry span on timeline

Fredrik v S
Mega Guru

Hello,

I'm currently working on creating a timeline view over upcoming change requests, however I'd also like to add maintenance and blackout schedules into the same view.

Change Schedule.PNG

I have created a script include that shows the upcoming change requests and groups them based on their workflow stage (u_wf_stage). I seem to be unable to add the blackout and maintenance schedules into this timeline view, it works in the calendar view using schedule.addpage but that's not what I'm looking for. I'm curious as to how I'm supposed to be able to create a span from a cmn_schedule entry.

This is the particular part I can't get to work:

  var g = new GlideRecord('cmn_schedule');

  g.initialize();

  g.addQuery('type', 'blackout');

  g.query();

  while (g.next()) {

  var item1 = new GlideTimelineItem(g.getTableName(), g.sys_id);

  var span1 = item1.createTimelineSpan(g.getTableName(), g.sys_id);

  item1.setParent(groupBlackout.getSysId());

  item1.setLeftLabelText(g.name);

  // span1.setTimeSpan(g.getElement('start_date_time').getGlideObject().getNumericValue(), gr.getElement('end_date_time').getGlideObject().getNumericValue());

  // schedulePage.addSchedule(g.sys_id, '#000', null, true);

  this.add(item1);

  }

  g.initialize();

  g.addQuery('type', 'maintenance');

  g.query();

  while (g.next()) {

  var item2 = new GlideTimelineItem(g.getTableName(), g.sys_id);

  var span2 = item2.createTimelineSpan(g.getTableName(), g.sys_id);

  item2.setParent(groupMaintenance.getSysId());

  item2.setLeftLabelText(g.name);

  // schedulePage.addSchedule(g.sys_id, '#e9ff00', null, true);

  this.add(item2);

Now the queries return and group then where they ought to be, as intended by setParent

However, I am unable to get it to draw the values returned in the timeline, because I can't draw a span based on what's returned to me using (because of how schedules are calculated in Service Now):

span1.setTimeSpan(g.getElement('start_date_time').getGlideObject().getNumericValue(), g.getElement('end_date_time').getGlideObject().getNumericValue());

Has anyone been able to resolve an issue similar to this one while stil using the OOB-function for schedules and in this particular case maintenance windows and blackout windows?

5 REPLIES 5

Fredrik v S
Mega Guru

From what I understand calling upon the underlying engine for calculating the spans for schedules is not an option, which means you have to construct an evaluator of the data in cmn_schedule and from that construct the spans within the script and then add those spans to create start and end dates for maintenance and blackout. Unfortunate, but possible to work around it.


Hi - Did you find a way to this ? I am wanting to do the same as you and although I can get the Start Date of the span using the whenNext() function, I can't get the end date of the same span to be able to add it to a timeline.


mylamariejordan
Tera Contributor

I haven't stuck this into a Time Line yet but hoping this will give you some ideas of how to get start/end dates from a schedule:



var timeZone = "GMT";



// Since Holiday spans are a type of "Excluded" you need to stuff them into your GlideSchedule


// If I had done this with a blackout or maintenance schedule this step would be avoided and


// you would just set up your schedule as follows:


// var schedule = new GlideSchedule(scheduleSysID);


// schedule.setTimeZone(timeZone);


var thisSchedule = new GlideSchedule();


thisSchedule.setTimeZone(timeZone);


var ss = new GlideRecord('cmn_schedule_span');


ss.addQuery('schedule', '55ebbbf15f002000b12e3572f2b47714'); // OOB U.S. Holiday Schedule


ss.orderBy('start_date_time');


ss.query();


while (ss.next()) {


      gs.log("addHoliday to Schedule " + ss.name);


      thisSchedule.addTimeSpan(ss);


}



// Start from Today


var gd = new GlideDate();


var gdt = new GlideDateTime();


gdt.setNumericValue(gd.getNumericValue());



// GDT (GlideDateTime)


// Start Date


var sd = new GlideDateTime();


sd.setValue(gdt.getDate() + " 00:00:00");


// End Date


var ed = new GlideDateTime();


ed.setValue(gdt.getDate() + " 23:59:59");


ed.addDaysUTC(730); // Look 2 years ahead (this could be anything)


                           


// SDT (GlideScheduleDateTime)


// Start Date


var ssd =   new GlideScheduleDateTime(sd); // Start Day


ssd.setTimeZone(timeZone);


// End Date


var sed =   new GlideScheduleDateTime(ed); // End Day


sed.setTimeZone(timeZone);



// Get Where Schedule Entries overlap with your Start/End Dates    


var scheduleMap = thisSchedule.getTimeMap(sd, ed, timeZone);


var span = new GlideScheduleDateTimeSpan(ssd, sed);


var thisMap = new GlideScheduleTimeMap();


thisMap.addInclude(span);


thisMap.buildMap(timeZone);


overlaps = scheduleMap.overlapsWith(thisMap, timeZone);


overlaps.buildMap(timeZone);


while (overlaps.hasNext()) {


      var overlapSpan = overlaps.next();


   


      // overlapSpan.getStart() and getEnd() will give you start/end for your time line...I hope


      gs.log("overlapSpan Dates:   " + overlapSpan.getStart() + " - " + overlapSpan.getEnd());



    // getStart()/getEnd() should be returning a GlideScheduleDateTime


    // getStart().getMS() would give you a numeric value if you need that


    // Hoping your span then would be as follows:


    // span1.setTimeSpan(overlapSpan.getStart(), overlapSpan.getEnd());  


}



If I get mine working I'll post the span entry back here.



NOTE:   If you run the above in Scripts Background you should get the following output (assuming the OOB Holiday schedule exists)


*** Script: addHoliday to Schedule New Year's Day


*** Script: addHoliday to Schedule Martin Luther King, Jr. Day


*** Script: addHoliday to Schedule Presidents' Day


*** Script: addHoliday to Schedule Memorial Day


*** Script: addHoliday to Schedule Independence Day


*** Script: addHoliday to Schedule Labor Day


*** Script: addHoliday to Schedule Columbus Day


*** Script: addHoliday to Schedule Veterans Day


*** Script: addHoliday to Schedule Thanksgiving Day


*** Script: addHoliday to Schedule Christmas Eve


*** Script: addHoliday to Schedule Christmas Day


*** Script: addHoliday to Schedule New Year's Eve


*** Script: overlapSpan Dates: 2016-12-24 00:00:00 to 2016-12-26 00:00:00


*** Script: overlapSpan Dates: 2016-12-31 00:00:00 to 2017-01-02 00:00:00


*** Script: overlapSpan Dates: 2017-01-16 00:00:00 to 2017-01-17 00:00:00


*** Script: overlapSpan Dates: 2017-02-20 00:00:00 to 2017-02-21 00:00:00


*** Script: overlapSpan Dates: 2017-05-29 00:00:00 to 2017-05-30 00:00:00


*** Script: overlapSpan Dates: 2017-07-04 00:00:00 to 2017-07-05 00:00:00


*** Script: overlapSpan Dates: 2017-09-04 00:00:00 to 2017-09-05 00:00:00


*** Script: overlapSpan Dates: 2017-10-09 00:00:00 to 2017-10-10 00:00:00


*** Script: overlapSpan Dates: 2017-11-11 00:00:00 to 2017-11-12 00:00:00


*** Script: overlapSpan Dates: 2017-11-23 00:00:00 to 2017-11-24 00:00:00


*** Script: overlapSpan Dates: 2017-12-24 00:00:00 to 2017-12-26 00:00:00


*** Script: overlapSpan Dates: 2017-12-31 00:00:00 to 2018-01-02 00:00:00


*** Script: overlapSpan Dates: 2018-01-15 00:00:00 to 2018-01-16 00:00:00


*** Script: overlapSpan Dates: 2018-02-19 00:00:00 to 2018-02-20 00:00:00


*** Script: overlapSpan Dates: 2018-05-28 00:00:00 to 2018-05-29 00:00:00


*** Script: overlapSpan Dates: 2018-07-04 00:00:00 to 2018-07-05 00:00:00


*** Script: overlapSpan Dates: 2018-09-03 00:00:00 to 2018-09-04 00:00:00


*** Script: overlapSpan Dates: 2018-10-08 00:00:00 to 2018-10-09 00:00:00


*** Script: overlapSpan Dates: 2018-11-11 00:00:00 to 2018-11-12 00:00:00


*** Script: overlapSpan Dates: 2018-11-22 00:00:00 to 2018-11-23 00:00:00



mylamariejordan
Tera Contributor

This was quick and dirty - a lot of optimization can and should be done but it does work...this gave me a timeline with my changes along with Blackout/Maint and Holidays shown.


     


getItems already existed within TimelineGeneratorSchedulePageWindows (copy of TimelineGeneratorSchedulePage).  


I just added populateWindows() and populateHolidays()


     


getItems : function() {


  var result = this._getPageRecord();


  if (typeof result == "number")


      return this._setStatusError(result);



  // Set page title


  if (result.name != '')


      this.setPageTitle(result.name);



  //Create range calculator if specified


  var calculator;


  if (result.range_calculator && result.range_calculator.name)


      eval("calculator = new " + result.range_calculator.name + "()");



  this.populateWindows();


  this.pouplateHolidays();


  this.populateItems(result, null, -1, -1, null, calculator);


},



populateWindows: function() {


  var timeZone = gs.getSession().getTimeZoneName();



  // Start from Today


  var gd = new GlideDate();


  var gdt = new GlideDateTime();


  gdt.setNumericValue(gd.getNumericValue());



  // GDT (GlideDateTime)


  // Start Date


  var sd = new GlideDateTime();


  sd.setValue(gdt.getDate() + " 00:00:00");


  // End Date


  var ed = new GlideDateTime();


  ed.setValue(gdt.getDate() + " 23:59:59");


  ed.addDaysUTC(730); // Look 2 years ahead (this could be anything)


                             


  // SDT (GlideScheduleDateTime)


  // Start Date


  var ssd =   new GlideScheduleDateTime(sd); // Start Day


  ssd.setTimeZone(timeZone);


  // End Date


  var sed =   new GlideScheduleDateTime(ed); // End Day


  sed.setTimeZone(timeZone);



  var timeZone = gs.getSession().getTimeZoneName();


  var scheduleGR = new GlideRecord('cmn_schedule');


  scheduleGR.addQuery('type', 'blackout').addOrCondition('type', 'maintenance');


  scheduleGR.query();


  while (scheduleGR.next()) {


      var schedule = new GlideSchedule(scheduleGR.sys_id);



      var spanText = scheduleGR.name;


      var spanColor = "#000000";


      if (scheduleGR.type != 'blackout')


          spanColor = "#696969";



      // Get Where Schedule Entries overlap with you Start/End Dates      


      var scheduleMap = schedule.getTimeMap(sd, ed, timeZone);


      var span = new GlideScheduleDateTimeSpan(ssd, sed);


      var thisMap = new GlideScheduleTimeMap();


      thisMap.addInclude(span);


      thisMap.buildMap(timeZone);


      overlaps = scheduleMap.overlapsWith(thisMap, timeZone);



      var item1 = new TimelineItem("cmn_schedule", "");


      item1.setLeftLabelText(spanText);



      overlaps.buildMap(timeZone);


      while (overlaps.hasNext()) {


          var overlapSpan = overlaps.next();


          var span1 = item1.createTimelineSpan("cmn_schedule", "");


          span1.setTimeSpan(overlapSpan.getStart().getMS(), overlapSpan.getEnd().getMS());


          span1.setSpanColor(spanColor);


          span1.setLabelColor(spanColor);


          span1.setSpanText(spanText);


          span1.setTooltip(spanText);


      }


      this.add(item1);


  }


},



pouplateHolidays: function() {


  var timeZone = gs.getSession().getTimeZoneName();



  // Start from Today


  var gd = new GlideDate();


  var gdt = new GlideDateTime();


  gdt.setNumericValue(gd.getNumericValue());



  // GDT (GlideDateTime)


  // Start Date


  var sd = new GlideDateTime();


  sd.setValue(gdt.getDate() + " 00:00:00");


  // End Date


  var ed = new GlideDateTime();


  ed.setValue(gdt.getDate() + " 23:59:59");


  ed.addDaysUTC(730); // Look 2 years ahead (this could be anything)


                             


  // SDT (GlideScheduleDateTime)


  // Start Date


  var ssd =   new GlideScheduleDateTime(sd); // Start Day


  ssd.setTimeZone(timeZone);


  // End Date


  var sed =   new GlideScheduleDateTime(ed); // End Day


  sed.setTimeZone(timeZone);



  var thisSchedule = new GlideSchedule();


  thisSchedule.setTimeZone(timeZone);


  var ss = new GlideRecord('cmn_schedule_span');


  ss.addQuery('schedule', '55ebbbf15f002000b12e3572f2b47714'); // OOB U.S. Holiday Schedule


  ss.orderBy('start_date_time');


  ss.query();


  while (ss.next()) {


      thisSchedule.addTimeSpan(ss);


  }



  // Get Where Schedule Entries overlap with you Start/End Dates      


  var scheduleMap = thisSchedule.getTimeMap(sd, ed, timeZone);


  var span = new GlideScheduleDateTimeSpan(ssd, sed);


  var thisMap = new GlideScheduleTimeMap();


  thisMap.addInclude(span);


  thisMap.buildMap(timeZone);


  overlaps = scheduleMap.overlapsWith(thisMap, timeZone);



  var item1 = new TimelineItem("cmn_schedule", "");


  item1.setLeftLabelText("Holidays");



  overlaps.buildMap(timeZone);


  while (overlaps.hasNext()) {


      var overlapSpan = overlaps.next();


      var span1 = item1.createTimelineSpan("cmn_schedule", "");


      span1.setTimeSpan(overlapSpan.getStart().getMS(), overlapSpan.getEnd().getMS());


      span1.setSpanColor("#3CB371");


      span1.setLabelColor("#3CB371");


      span1.setSpanText("Holiday " + overlapSpan.getStart());


      span1.setTooltip("Holiday " + overlapSpan.getStart());


  }


  this.add(item1);


},