/**
* @module managers/iqueue-manager
* @description This module manages iQueue calls
* @requires common/view
*/
define([
],
function ()
{
// ---------------------------------------------------------------
//
// PStyles Manager
//
// ---------------------------------------------------------------
var Queue = function ()
{
console.log(" * <iqueue>");
window.tEvent.eventStr.EVENT_IQUEUE_GOT_LOCATIONS = "EVENT_IQUEUE_GOT_LOCATIONS";
window.tEvent.eventStr.EVENT_IQUEUE_GOT_WAIT_LIST = "EVENT_IQUEUE_GOT_WAIT_LIST";
window.tEvent.eventStr.EVENT_IQUEUE_GOT_APPOINTMENTS = "EVENT_IQUEUE_GOT_APPOINTMENTS";
window.tEvent.eventStr.EVENT_IQUEUE_GOT_NOTIFICATIONS = "EVENT_IQUEUE_GOT_NOTIFICATIONS";
window.tEvent.eventStr.EVENT_IQUEUE_GOT_NEW_NOTIFICATION = "EVENT_IQUEUE_GOT_NEW_NOTIFICATION";
this.ui = {
};
this.def = {
};
// core json
this.jConfig = -1;
// customer data
this.customer = -1;
this.queue = [];
this.locationsArray = [];
this.selectedLocation = 0;
this.sessionGUID = -1;
this.notifications = [];
this.init();
};
Queue.prototype = {
// ______________________________________________________________
// init
/**
* init
* @description Initializes class
* @fires assignListeners()
* @memberOf module:managers/iqueue-manager
* @instance
*/
init: function() {
this.assignListeners();
},
// ______________________________________________________________
// assignListeners
/**
* assignListeners
* @description Assigns listeners to events used in this class.
* @listens EVENT_MODEL_READY
* @memberOf module:managers/iqueue-manager
* @instance
*/
assignListeners: function() {
var self = this;
if (typeof window.oModel === "undefined" || window.oModel.jConfig === -1){
window.tEvent.addListener("EVENT_MODEL_READY", function(evt, data)
{
// clean up for new page
self.onJsonLoaded(window.oModel.jConfig);
});
} else {
self.onJsonLoaded(window.oModel.jConfig);
}
},
// --------------------------------------------------------------
// HELPERS
// --------------------------------------------------------------
// ______________________________________________________________
// initIqueue
/**
* initIqueue
* @description Loads customer and locations the begins polling based on configCode
* @param {Number} locationIndex - [Optional] Location index
* @fires getSessionGuid()
* @fires cloudConnector.fetchCustomerConfigByConfigCode()
* @fires cloudConnector.fetchCustomerLocationsTable()
* @fires EVENT_IQUEUE_GOT_LOCATIONS
* @memberOf module:managers/iqueue-manager
* @instance
*/
initIqueue: function(locationIndex) {
var self = this;
var configCode = this.jConfig.iqueue.configCode;
// get unique session guid
this.sessionGUID = this.getSessionGuid();
if (typeof configCode === "undefined" || configCode === ""){
console.warn(" * <iqueue.initIqueue> jConfig.iqueue.configCode is missing");
}
// get the details about this customer based on the configCode
cloudConnector.fetchCustomerConfigByConfigCode(configCode, function(success, data){
if (!success) {
console.error(" ! <iqueue.initIqueue|fetchCustomerConfigByConfigCode> failed.", data);
return;
}
//make sure we got a customer back for the config code
if (!data) {
//no customer found for that config code
console.warn(" * <iqueue.initIqueue|fetchCustomerConfigByConfigCode> configCode: '" + configCode + "' is invalid");
return
}
//store the customer so we can use it later
self.customer = data;
console.log(" * <iqueue.initIqueue|fetchCustomerConfigByConfigCode> customer", data);
// fetch the locations for this customer
cloudConnector.fetchCustomerLocationsTable(self.customer.customerID, function(locSuccess, locData){
if (!locSuccess) {
console.error(" ! <iqueue.initIqueue|fetchCustomerConfigByConfigCode|fetchCustomerLocationsTable> failed.", locData);
return;
}
//save the returned locations locally
self.locationsArray = locData;
console.log(" * <iqueue.initIqueue|fetchCustomerConfigByConfigCode|fetchCustomerLocationsTable> locations", self.locationsArray);
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_LOCATIONS, self.locationsArray);
//select the first location
if (typeof locationIndex !== "undefined"){
self.selectLocation(locationIndex);
} else {
self.selectLocation(0);
}
});
});
},
// ______________________________________________________________
// getSessionGuid
/**
* getSessionGuid
* @description Gets unique session guid
* @returns sessionGuid
* @memberOf module:managers/iqueue-manager
* @instance
*/
getSessionGuid: function() {
function _p8(s) {
var p = (Math.random().toString(16) + "000000000").substr(2, 8);
return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
}
return _p8() + _p8(true) + _p8(true) + _p8();
},
// ______________________________________________________________
// selectLocation
/**
* selectLocation
* @description Gets location object and initiates polling
* @param {Number} locationIndex - Location index
* @fires updateWaitlist()
* @fires updateAppointmentlist()
* @fires pollNotificationsQueue()
* @memberOf module:managers/iqueue-manager
* @instance
*/
selectLocation: function(locationIndex) {
this.selectedLocation = this.locationsArray[locationIndex];
console.log(" * <iqueue.selectLocation>", this.selectedLocation.locationDetails.locationName);
//start the polling processes
this.updateWaitlist();
this.updateAppointmentlist();
this.pollNotificationsQueue();
},
// ______________________________________________________________
// updateWaitlist
/**
* updateWaitlist
* @description Gets updated waiting list
* @fires EVENT_IQUEUE_GOT_WAIT_LIST
* @memberOf module:managers/iqueue-manager
* @instance
*/
updateWaitlist: function() {
var self = this;
//NOTE: please don't poll too often, we don't want to pay for excessive server requests
let refreshTimeout = this.jConfig.iqueue.waitListDelay * 1000;
cloudConnector.fetchWaitTime(self.selectedLocation.locationID, function (success, data) {
if (!success) {
console.error(" ! <iqueue.updateWaitlist|fetchWaitTime> Error", data);
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_WAIT_LIST, []);
window.setTimeout(function () {
updateWaitlist();
}, refreshTimeout);
return;
}
self.queue = data;
if (self.queue.length === 0) {
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_WAIT_LIST, self.queue);
console.log(" ! <iqueue.updateWaitlist|fetchWaitTime>", self.queue);
window.setTimeout(function () {
self.updateWaitlist();
}, refreshTimeout);
return;
}
const now = new Date().getTime();
for (let i = 0; i < self.queue.length; i++) {
self.queue[i].createDateTime = new Date(self.queue[i].createTime);
self.queue[i].waitTime = (now - self.queue[i].createDateTime) / 1000; // seconds
}
//sort ascending by the create time
self.queue.sort(function (a, b) {
var createTimeA = a.createTime,
createTimeB = b.createTime;
if (createTimeA < createTimeB) //sort ascending
return -1;
if (createTimeA > createTimeB)
return 1;
return 0 //default return value (no sorting)
});
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_WAIT_LIST, self.queue);
console.log(" ! <iqueue.updateWaitlist|fetchWaitTime>", self.queue);
window.setTimeout(function () {
self.updateWaitlist();
}, refreshTimeout);
});
},
// ______________________________________________________________
// updateAppointmentlist
/**
* updateAppointmentlist
* @description Update appointment list
* @fires EVENT_IQUEUE_GOT_APPOINTMENTS
* @memberOf module:managers/iqueue-manager
* @instance
*/
updateAppointmentlist: function() {
var self = this;
//NOTE: please don't poll too often, we don't want to pay for excessive server requests
let refreshTimeout = this.jConfig.iqueue.appoinmentListDelay * 1000;
cloudConnector.fetchOpenAppointments(self.selectedLocation.locationID, function (success, data) {
if (!success) {
console.error(" ! <iqueue.updateAppointmentlist|fetchOpenAppointments> error", data);
window.setTimeout(function () {
self.updateAppointmentlist()
}, refreshTimeout);
return;
}
self.theAppointments = data;
const now = new Date();
//filter to just today's appointments
self.theAppointments = self.theAppointments.filter(function (appointment) {
const apptDate = new Date(appointment.appointmentDetails.start);
return apptDate.getDate() === now.getDate() && apptDate.getTime() > (now.getTime() - 1000 * 60 * 15)
})
if (self.theAppointments.length === 0) {
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_APPOINTMENTS, self.theAppointments);
window.setTimeout(function () {
self.updateAppointmentlist()
}, refreshTimeout);
return;
}
self.theAppointments.sort(function (a, b) {
return a.appointmentDetails.start - b.appointmentDetails.start
});
//and show the list of appointments
let theHTML = '';
self.theAppointments.forEach(function (appointment, index) {
let startTime = new Date(appointment.appointmentDetails.start)
let hours = startTime.getHours();
let minutes = startTime.getMinutes();
let ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0' + minutes : minutes;
let strTime = hours + ':' + minutes + ' ' + ampm;
self.theAppointments[index]._startTime = strTime;
});
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_APPOINTMENTS, self.theAppointments);
window.setTimeout(function () {
self.updateAppointmentlist()
}, refreshTimeout);
});
},
// ______________________________________________________________
// pollNotificationsQueue
/**
* pollNotificationsQueue
* @description Polls for notifications
* @fires EVENT_IQUEUE_GOT_NOTIFICATIONS
* @fires EVENT_IQUEUE_GOT_NEW_NOTIFICATION
* @memberOf module:managers/iqueue-manager
* @instance
*/
pollNotificationsQueue: function() {
var self = this;
var locationId = self.selectedLocation.locationID;
// NOTE: please don't poll too often, we don't want to pay for excessive server requests
let refreshTimeout = 20 * 1000;
var doNotificationPolling = function() {
cloudConnector.fetchNotifications(locationId, function (success, data) {
if (!success) {
console.error(" ! <iqueue.pollNotificationsQueue|fetchNotifications> error", data);
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_NOTIFICATIONS, []);
window.setTimeout(() => {
doNotificationPolling();
}, refreshTimeout);
return;
}
self.notifications = data
if (self.notifications.length === 0) {
// new Date().toLocaleString()
console.log(" ! <iqueue.pollNotificationsQueue|fetchNotifications>", data);
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_NOTIFICATIONS, self.notifications);
window.setTimeout(() => {
doNotificationPolling();
}, refreshTimeout);
return;
}
// sort the notifications by create time
self.notifications.sort(function (a, b) {
var createTimeA = a.notificationObject.createTime,
createTimeB = b.notificationObject.createTime
if (createTimeA < createTimeB) //sort ascending
return -1
if (createTimeA > createTimeB)
return 1
return 0
});
// NOTE: this code is responsible for keeping the notifications queue clean
// DO NOT skip this step, or the notifications queue will grow forever
// delete the first notification if it's older than 5 minutes
if (self.notifications.length > 0) {
const now = new Date().getTime();
var maxAge = now - 1000 * 60 * 5;
if (self.notifications[0].notificationObject.createTime < maxAge) {
// it's old, so delete it from AWS
cloudConnector.deleteNotification(self.notifications[0].locationID, self.notifications[0].notificationID);
//poll again in 1 second
window.setTimeout(function(){
doNotificationPolling();
}, 1000);
return;
}
}
// filter to just the notifications for the display
self.notifications = self.notifications.filter(function (notification) {
return notification.notificationObject.destination === 'display';
});
// filter to just the notifications for type nowserving
self.notifications = self.notifications.filter(function (notification) {
return notification.notificationObject.type === 'nowserving';
});
if (self.notifications.length === 0) {
//none of the notifications were for the display with type nowserving
console.log(" ! <iqueue.pollNotificationsQueue|fetchNotifications>", data);
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_NOTIFICATIONS, self.notifications);
window.setTimeout(function(){
doNotificationPolling();
}, refreshTimeout);
return;
}
// see if there is a notification that has not yet been presented on this display
var theNotification = null;
for (let i = 0; i < self.notifications.length; i++) {
if (self.notifications[i].notificationObject.presentedArray.indexOf(self.sessionGUID) === -1) {
//this notification has never been presented on this display
theNotification = self.notifications[i];
break;
}
}
if (!theNotification) {
// we got through the loop above without identifying an undisplayed notification
window.setTimeout(function(){
doNotificationPolling();
}, refreshTimeout);
return;
}
// we have a notification that has not yet been presented on this display
console.log(" ! <iqueue.pollNotificationsQueue|fetchNotifications> New notification", theNotification);
window.tEvent.fire(window.tEvent.eventStr.EVENT_IQUEUE_GOT_NEW_NOTIFICATION, theNotification);
// check again after timeout
window.setTimeout(function(){
doNotificationPolling();
}, refreshTimeout);
// record that this message has been displayed on this screen
if (theNotification.notificationObject.presentedArray.indexOf(self.sessionGUID) === -1) {
theNotification.notificationObject.presentedArray.push(self.sessionGUID);
cloudConnector.updateNotification(theNotification);
}
});
};
doNotificationPolling();
},
// --------------------------------------------------------------
// EVENTS
// --------------------------------------------------------------
// ______________________________________________________________
// onJsonLoaded
/**
* onJsonLoaded
* @description When project JSON is loaded process styles
* @param {Object} jData - JSON data
* @memberOf module:managers/iqueue-manager
* @instance
*/
onJsonLoaded: function(jData) {
this.jConfig = jData;
}
};
window.oQueue = new Queue();
return (oQueue);
});