APIs

Show:
  1. /**
  2. Settings Backbone View
  3. @class FQManagerView
  4. @constructor
  5. @return {Object} instantiated FQManagerView
  6. **/
  7. define(['jquery', 'backbone', 'ScrollToPlugin', 'TweenMax', 'FQQueuePropView', 'QueuesCollection', 'AnalyticsCollection', 'stopwatch', 'XDate', 'moment'], function ($, Backbone, ScrollToPlugin, TweenMax, FQQueuePropView, QueuesCollection, AnalyticsCollection, stopwatch, XDate, moment) {
  8.  
  9. var FQManagerView = Backbone.View.extend({
  10.  
  11. /**
  12. Constructor
  13. @method initialize
  14. **/
  15. initialize: function () {
  16. var self = this;
  17. self.m_offsetPosition = 0;
  18. self.m_selectedServiceID = -1;
  19. self.m_fqCreatorView = BB.comBroker.getService(BB.SERVICES.FQCREATORVIEW);
  20. self.m_stopWatchHandle = new Stopwatch();
  21. self.m_liveUpdatehandler = undefined;
  22. self.m_inView = false;
  23. self.m_masterPanelInView = true;
  24. self.m_fqQueuePropView = new FQQueuePropView({
  25. el: Elements.FASTERQ_QUEUE_PROPERTIES
  26. });
  27.  
  28. self._listenNextPrev();
  29. self._listenCalled();
  30. self._listenServiced();
  31. self._listenGoBack();
  32. self._listenOpenRemoteStatus();
  33.  
  34. self.listenTo(self.options.stackViewMaster, BB.EVENTS.SELECTED_STACK_VIEW, function (e) {
  35. if (e.$el.selector == Elements.FASTERQ_PANEL) {
  36. self.m_masterPanelInView = true;
  37. } else {
  38. self.m_masterPanelInView = false;
  39. }
  40. });
  41.  
  42. self.listenTo(self.options.stackView, BB.EVENTS.SELECTED_STACK_VIEW, function (e) {
  43. if (e == self) {
  44. self.m_inView = true;
  45. self.m_liveUpdatehandler = setInterval(function () {
  46. if (!self.m_masterPanelInView)
  47. return;
  48. self._getQueues(false);
  49. self._pollNowServicing();
  50. }, 10000);
  51.  
  52. self._getQueues(true);
  53. // self._scrollTo($(Elements.FQ_LINE_QUEUE_COMPONENT + ':first-child'));
  54.  
  55. } else {
  56. self.m_inView = false;
  57. window.clearInterval(self.m_liveUpdatehandler);
  58. window.clearInterval(self.m_statusHandler);
  59. }
  60. });
  61. },
  62.  
  63. /**
  64. Listen to go back to Line selection
  65. @method _listenGoBack
  66. **/
  67. _listenGoBack: function () {
  68. var self = this;
  69. $(Elements.FASTERQ_MANAGER_BACK).on('click', function () {
  70. self.options.stackView.selectView(Elements.FASTERQ_CREATOR_CONTAINER);
  71. self.m_property = BB.comBroker.getService(BB.SERVICES['PROPERTIES_VIEW']).resetPropertiesView();
  72. });
  73. },
  74.  
  75. /**
  76. Get Queues collection from server and render UI
  77. @method _getLines server:getQueues
  78. @params {boolean} i_scrollTo scroll to
  79. **/
  80. _getQueues: function (i_scrollTo) {
  81. var self = this;
  82. self.m_queuesCollection = new QueuesCollection();
  83. self.m_queuesCollection.fetch({
  84. data: {line_id: self.m_fqCreatorView.getSelectedLine()},
  85. success: function (models) {
  86. self._updateTotalToBeServiced();
  87. self._render();
  88. if (i_scrollTo)
  89. self._scrollToFirstNotServiced();
  90. },
  91. error: function () {
  92. log('error fetch /Queues collection');
  93. }
  94. });
  95. },
  96.  
  97. /**
  98. Get the last called service_id for line
  99. @method _pollNowServicing server:LastCalledQueue
  100. **/
  101. _pollNowServicing: function () {
  102. var self = this;
  103. $.ajax({
  104. url: BB.CONSTS.ROOT_URL + '/LastCalledQueue',
  105. data: {
  106. business_id: BB.Pepper.getUserData()['businessID'],
  107. line_id: self.m_fqCreatorView.getSelectedLine()
  108. },
  109. success: function (i_model) {
  110. $(Elements.FQ_NOW_SERVICING).text(i_model.service_id);
  111. },
  112. error: function (e) {
  113. log('error ajax ' + e);
  114. },
  115. dataType: 'json'
  116. });
  117. },
  118.  
  119. /**
  120. Update the total number of queues left to be serviced
  121. @method _updateTotalToBeServiced
  122. **/
  123. _updateTotalToBeServiced: function () {
  124. var self = this;
  125. if (_.isUndefined(self.m_queuesCollection))
  126. return;
  127. var total = 0;
  128. self.m_queuesCollection.each(function (model) {
  129. if (_.isNull(model.get('serviced')))
  130. total++;
  131. $(Elements.FQ_TOTAL_TO_BE_SERVICED).text(total);
  132. });
  133.  
  134. },
  135.  
  136. /**
  137. Start the stop watch UI
  138. @method _watchStart
  139. **/
  140. _watchStart: function () {
  141. var self = this;
  142. self.m_stopWatchHandle.setListener(function (e) {
  143. $(Elements.FQ_TIME_WITH_CUSTOMER).text(self.m_stopWatchHandle.toString());
  144. });
  145. self.m_stopWatchHandle.start();
  146. },
  147.  
  148. /**
  149. Stop the stop watch UI
  150. @method _watchStop
  151. **/
  152. _watchStop: function () {
  153. var self = this;
  154. self.m_stopWatchHandle.stop();
  155. self.m_stopWatchHandle.reset();
  156. $(Elements.FQ_TIME_WITH_CUSTOMER).text('00:00:00');
  157. },
  158.  
  159. /**
  160. Render the UI queues list from returned server data
  161. @method _render
  162. **/
  163. _render: function () {
  164. var self = this;
  165. if (!self.m_inView)
  166. return;
  167. self.m_fqQueuePropView.showProp();
  168. var snippet;
  169.  
  170.  
  171. $(Elements.FQ_LINE_QUEUE_COMPONENT).empty();
  172.  
  173. var selectedLine = self.m_fqCreatorView.getSelectedLine();
  174. $(Elements.FQ_LINE_NAME).text(self.m_fqCreatorView.getSelectedLineName(selectedLine));
  175.  
  176. for (var i = -8; i < 0; i++) {
  177. snippet = '<div class="' + BB.lib.unclass(Elements.CLASS_PERSON_IN_LINE) + '">';
  178. $(Elements.FQ_LINE_QUEUE_COMPONENT).append(snippet);
  179. }
  180.  
  181. self.m_queuesCollection.each(function (model) {
  182. var serviceID = model.get('service_id');
  183. var called = model.get('called');
  184. var serviced = model.get('serviced');
  185. var color = 'gray';
  186.  
  187. if (serviced) {
  188. color = '#ACFD89';
  189. } else if (called) {
  190. color = '#BE6734';
  191. } else {
  192. color = '#D0D0D0';
  193. }
  194.  
  195. var val = BB.lib.padZeros(serviceID, 3, 0);
  196. snippet = '<div data-service_id="' + serviceID + '" class="' + BB.lib.unclass(Elements.CLASS_PERSON_IN_LINE) + '">';
  197. snippet += '<i style="font-size: 90px; color: ' + color + '" class="fa fa-male">';
  198. snippet += '</i><h3 style="position: relative; left: 6px">' + val + '</h3></div>';
  199. $(Elements.FQ_LINE_QUEUE_COMPONENT).append(snippet);
  200. });
  201. self._listenToPersonSelected();
  202. self._getAnalytics();
  203. },
  204.  
  205. /**
  206. Get line analytics / stats
  207. @method _getAnalytics server:lineAnalytics
  208. **/
  209. _getAnalytics: function () {
  210. var self = this;
  211. self.m_analyticsCollection = new AnalyticsCollection();
  212.  
  213. self.m_analyticsCollection.fetch({
  214. data: {line_id: self.m_fqCreatorView.getSelectedLine()},
  215. success: function (models) {
  216. self._calcAverages();
  217. },
  218. error: function () {
  219. log('error fetch /Queues collection');
  220. }
  221. });
  222. },
  223.  
  224. /**
  225. Calculate average respond and service line times
  226. @method _calcAverages
  227. **/
  228. _calcAverages: function () {
  229. var self = this;
  230.  
  231. var avgServiceTime = [];
  232. var avgCalledTime = [];
  233.  
  234. self.m_analyticsCollection.forEach(function (i_model) {
  235. var entered = i_model.get('entered');
  236. var serviced = i_model.get('serviced');
  237. var called = i_model.get('called');
  238.  
  239. if (_.isNull(called)) {
  240. // customer not called, do nothing
  241. } else if (!_.isNull(serviced)) {
  242.  
  243. // customer called & serviced
  244. var xEntered = new XDate(entered);
  245. var minFromEnteredToCalled = xEntered.diffMinutes(called);
  246. if (minFromEnteredToCalled < 0)
  247. minFromEnteredToCalled = 1;
  248. avgCalledTime.push(minFromEnteredToCalled);
  249.  
  250. var xCalled = new XDate(called);
  251. var minFromCalledToServiced = xCalled.diffMinutes(serviced);
  252. avgServiceTime.push(minFromCalledToServiced);
  253.  
  254. } else {
  255.  
  256. // customer called not serviced
  257. var xEntered = new XDate(entered);
  258. var minFromEnteredToCalled = xEntered.diffMinutes(called);
  259. if (minFromEnteredToCalled < 0)
  260. minFromEnteredToCalled = 1;
  261. avgCalledTime.push(minFromEnteredToCalled);
  262. }
  263. });
  264.  
  265. var avgServiceTimeCalc = _.reduce(avgServiceTime, function (memo, num) {
  266. return memo + num;
  267. }, 0) / (avgServiceTime.length === 0 ? 1 : avgServiceTime.length);
  268.  
  269. var avgCalledTimeCalc = _.reduce(avgCalledTime, function (memo, num) {
  270. return memo + num;
  271. }, 0) / (avgCalledTime.length === 0 ? 1 : avgCalledTime.length);
  272.  
  273. $(Elements.FQ_AVG_CUSTOMER_SERVICE).text(BB.lib.parseToFloatDouble(avgServiceTimeCalc))
  274. $(Elements.FQ_AVG_CUSTOMER_WAIT).text(BB.lib.parseToFloatDouble(avgCalledTimeCalc));
  275. },
  276.  
  277. /**
  278. Scroll to first queue that has not been serviced yet, if non exist, scroll to first queue
  279. @method _scrollToFirstNotServiced
  280. **/
  281. _scrollToFirstNotServiced: function () {
  282. var self = this;
  283. var found = false;
  284. if (self.m_queuesCollection.length == 0)
  285. return;
  286. self.m_queuesCollection.each(function (model) {
  287. if (found)
  288. return;
  289. var service_id = model.get('service_id');
  290. var serviced = model.get('serviced');
  291. if (_.isNull(serviced)) {
  292. var elem = self.$('[data-service_id="' + service_id + '"]');
  293. self._scrollTo(elem);
  294. found = true;
  295. }
  296. });
  297. },
  298.  
  299. /**
  300. Listen to UI person / queue click to load selected properties and scroll to selection
  301. @method _listenToPersonSelected
  302. **/
  303. _listenToPersonSelected: function () {
  304. var self = this;
  305. $(Elements.CLASS_PERSON_IN_LINE).off().on('click', function (e) {
  306. var person = $(this).closest('[data-service_id]');
  307. $(person).data('service_id');
  308. self._scrollTo(person);
  309. })
  310. },
  311.  
  312. /**
  313. Scroll to position of selected queue / UI person
  314. @method _scrollTo
  315. @param {Element} i_element
  316. **/
  317. _scrollTo: function (i_element) {
  318. var self = this;
  319. self._watchStop();
  320. if (i_element.length == 0)
  321. return;
  322. self.m_selectedServiceID = $(i_element).data('service_id');
  323. var model = self.m_queuesCollection.where({'service_id': self.m_selectedServiceID})[0];
  324. self._populatePropsQueue(model);
  325.  
  326. var scrollXPos = $(i_element).position().left;
  327. // console.log('current offset ' + scrollXPos + ' ' + 'going to index ' + $(i_element).index() + ' service_id ' + $(i_element).data('service_id'));
  328. self.m_offsetPosition = $(Elements.FQ_LINE_QUEUE_COMPONENT_CONTAINER).scrollLeft();
  329. scrollXPos += self.m_offsetPosition;
  330. var final = scrollXPos - 480;
  331. TweenLite.to(Elements.FQ_LINE_QUEUE_COMPONENT_CONTAINER, 2, {
  332. scrollTo: {x: final, y: 0},
  333. ease: Power4.easeOut
  334. });
  335. },
  336.  
  337. /**
  338. Populate the selected queue's properties UI
  339. @method _populatePropsQueue
  340. @params {Number} i_value
  341. **/
  342. _populatePropsQueue: function (i_model) {
  343. var self = this;
  344. if (_.isUndefined(i_model))
  345. return;
  346. if (!self.m_inView)
  347. return;
  348. $(Elements.FQ_SELECTED_QUEUE).text(i_model.get('service_id'));
  349. $(Elements.FQ_VERIFICATION).text(i_model.get('verification') == -1 ? 'print out' : i_model.get('verification'));
  350. $(Elements.FQ_CALLED_BY).text(_.isNull(i_model.get('called_by')) ? 'none' : i_model.get('called_by'));
  351. },
  352.  
  353. /**
  354. Listen to queue being called, mark on UI and post to server
  355. @method _listenCalled
  356. **/
  357. _listenCalled: function () {
  358. var self = this;
  359. $(Elements.FQ_LINE_COMP_CALL).on('click', function () {
  360. var model = self.m_queuesCollection.where({'service_id': self.m_selectedServiceID})[0];
  361. if (_.isUndefined(model))
  362. return;
  363. if (!_.isNull(model.get('serviced'))) {
  364. bootbox.alert('customer has already been serviced');
  365. return;
  366. }
  367. self._watchStart();
  368. var elem = self.$('[data-service_id="' + (self.m_selectedServiceID) + '"]');
  369. $(elem).find('i').fadeOut(function () {
  370. $(this).css({color: '#BE6734'}).fadeIn();
  371. });
  372. $(Elements.FQ_LAST_CALLED).text(self.m_selectedServiceID);
  373. var d = new XDate();
  374. model.set('called', d.toString('M/d/yyyy hh:mm:ss TT'));
  375. model.set('called_by', pepper.getUserData().userName);
  376. model.set('called_by_override', false);
  377.  
  378. self._populatePropsQueue(model);
  379.  
  380. model.save(null,{
  381. success: (function (model, data) {
  382. if (data.updated == 'alreadyCalled'){
  383. bootbox.confirm('Customer already called by user' + data.called_by + ' <br/><br/>Would you like to call the customer again?', function(result) {
  384. if (result){
  385. model.set('called_by_override', true);
  386. model.save();
  387. }
  388. });
  389. }
  390. }),
  391. error: (function (e) {
  392. bootbox.alert('Service request failure: ' + e);
  393. }),
  394. complete: (function (e) {
  395. })
  396. });
  397. });
  398. },
  399.  
  400. /**
  401. Listen to queue being serviced, mark on UI and post to server
  402. @method _listenServiced
  403. **/
  404. _listenServiced: function () {
  405. var self = this;
  406. $(Elements.FQ_LINE_COMP_SERVICED).on('click', function () {
  407. self._watchStop();
  408. var model = self.m_queuesCollection.where({'service_id': self.m_selectedServiceID})[0];
  409. if (_.isUndefined(model))
  410. return;
  411. if (_.isNull(model.get('called'))) {
  412. bootbox.alert('customer has not been called yet');
  413. return;
  414. }
  415. if (!_.isNull(model.get('serviced'))) {
  416. bootbox.alert('customer has already been serviced');
  417. return;
  418. }
  419. var elem = self.$('[data-service_id="' + (self.m_selectedServiceID) + '"]');
  420. $(elem).find('i').fadeOut(function () {
  421. $(this).css({color: '#ACFD89'}).fadeIn();
  422. });
  423. $(Elements.FQ_LAST_SERVICED).text(self.m_selectedServiceID);
  424. var d = new XDate();
  425. model.set('serviced', d.toString('M/d/yyyy hh:mm:ss TT'));
  426. log('service ' + model.get('serviced'));
  427. model.save({
  428. success: (function (model, data) {
  429. log(model);
  430. }),
  431. error: (function (e) {
  432. log('Service request failure: ' + e);
  433. }),
  434. complete: (function (e) {
  435. })
  436. });
  437. });
  438. },
  439.  
  440. /**
  441. Listen to person navigation button selection to scroll to selected queue index
  442. @method _listenNextPrev
  443. **/
  444. _listenNextPrev: function () {
  445. var self = this;
  446.  
  447. $(Elements.FQ_LINE_COMP_PREV).on('click', function () {
  448. if (_.isUndefined(self.m_queuesCollection))
  449. return;
  450. if (self.m_selectedServiceID == 1)
  451. return;
  452. var elem = self.$('[data-service_id="' + (self.m_selectedServiceID - 1) + '"]');
  453. self._scrollTo(elem);
  454. });
  455.  
  456. $(Elements.FQ_LINE_GOTO).on('click', function () {
  457. var value = $(Elements.FQ_GOTO_LINE_INPUT).val();
  458. if (_.isUndefined(self.m_queuesCollection))
  459. return;
  460. var elem = self.$('[data-service_id="' + value + '"]');
  461. self._scrollTo(elem);
  462. });
  463.  
  464. $(Elements.FQ_LINE_COMP_NEXT).on('click', function () {
  465. if (_.isUndefined(self.m_queuesCollection))
  466. return;
  467. if (self.$('[data-service_id]').children().length == self.m_queuesCollection.length)
  468. return;
  469. var elem = self.$('[data-service_id="' + (self.m_selectedServiceID + 1) + '"]');
  470. self._scrollTo(elem);
  471. });
  472.  
  473. },
  474.  
  475. /**
  476. Open remote status terminal for selected queue
  477. @method _listenOpenRemoteStatus
  478. **/
  479. _listenOpenRemoteStatus: function () {
  480. var self = this;
  481. $(Elements.FQ_OPEN_CUSTOMER_REMOTE_STATUS).on('click', function (e) {
  482. var line_id = self.m_fqCreatorView.getSelectedLine()
  483. var data = {
  484. call_type: 'REMOTE_STATUS',
  485. business_id: BB.Pepper.getUserData()['businessID'],
  486. line_id: line_id,
  487. line_name: self.m_fqCreatorView.getSelectedLineName(line_id)
  488. };
  489. data = $.base64.encode(JSON.stringify(data));
  490. var url = BB.CONSTS.BASE_URL + '?mode=remoteStatus&param=' + data;
  491. window.open(url, "_blank", "toolbar=yes, scrollbars=yes, resizable=yes, top=10, left=10, width=400, height=400");
  492. })
  493. }
  494. });
  495.  
  496. return FQManagerView;
  497. });
  498.  
  499.