@plusscommunities/pluss-maintenance-web 1.1.37-beta.4 → 1.1.37-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/index.cjs.js +615 -573
  2. package/dist/index.esm.js +617 -575
  3. package/dist/index.js +6724 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.umd.js +616 -574
  6. package/package.json +8 -4
  7. package/.babelrc +0 -3
  8. package/rollup.config.js +0 -59
  9. package/src/actions/JobsActions.js +0 -150
  10. package/src/actions/index.js +0 -1
  11. package/src/actions/types.js +0 -8
  12. package/src/apis/index.js +0 -10
  13. package/src/apis/maintenanceActions.js +0 -203
  14. package/src/apis/reactionActions.js +0 -46
  15. package/src/components/ActivityText.js +0 -57
  16. package/src/components/AnalyticsHub.js +0 -364
  17. package/src/components/Configuration.js +0 -392
  18. package/src/components/JobList.js +0 -1108
  19. package/src/components/JobTypes.js +0 -198
  20. package/src/components/PreviewFull.js +0 -33
  21. package/src/components/PreviewGrid.js +0 -29
  22. package/src/components/PreviewWidget.js +0 -35
  23. package/src/components/ViewFull.js +0 -25
  24. package/src/components/ViewWidget.js +0 -23
  25. package/src/feature.config.js +0 -127
  26. package/src/helper/index.js +0 -26
  27. package/src/images/forms/full.png +0 -0
  28. package/src/images/forms/fullNoTitle.png +0 -0
  29. package/src/images/forms/previewWidget.png +0 -0
  30. package/src/images/forms/widget.png +0 -0
  31. package/src/images/full.png +0 -0
  32. package/src/images/fullNoTitle.png +0 -0
  33. package/src/images/previewWidget.png +0 -0
  34. package/src/images/widget.png +0 -0
  35. package/src/index.js +0 -29
  36. package/src/maintenancePriority.json +0 -5
  37. package/src/maintenanceStatus.json +0 -20
  38. package/src/reducers/MaintenanceReducer.js +0 -49
  39. package/src/screens/AddJob.js +0 -1138
  40. package/src/screens/AddJobType.js +0 -865
  41. package/src/screens/Job.js +0 -1531
  42. package/src/screens/RequestsHub.js +0 -237
  43. package/src/values.config.a.js +0 -63
  44. package/src/values.config.default.js +0 -75
  45. package/src/values.config.enquiry.js +0 -76
  46. package/src/values.config.feedback.js +0 -74
  47. package/src/values.config.food.js +0 -74
  48. package/src/values.config.forms.js +0 -74
  49. package/src/values.config.js +0 -75
package/dist/index.cjs.js CHANGED
@@ -6,12 +6,12 @@ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
6
6
  var React = require('react');
7
7
  var reactRedux = require('react-redux');
8
8
  var reactRouter = require('react-router');
9
- var _ = require('lodash');
10
- var moment = require('moment');
11
- var FontAwesome = require('react-fontawesome');
12
9
  var PlussCore = require('@plusscommunities/pluss-core-web');
13
10
  var reactBootstrap = require('react-bootstrap');
14
11
  var reactRouterDom = require('react-router-dom');
12
+ var FontAwesome = require('react-fontawesome');
13
+ var moment = require('moment');
14
+ var _ = require('lodash');
15
15
  var Textarea = require('react-textarea-autosize');
16
16
  var freeSolidSvgIcons = require('@fortawesome/free-solid-svg-icons');
17
17
 
@@ -37,10 +37,10 @@ function _interopNamespace(e) {
37
37
 
38
38
  var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
39
39
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
40
- var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
41
- var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
42
- var FontAwesome__default = /*#__PURE__*/_interopDefaultLegacy(FontAwesome);
43
40
  var PlussCore__namespace = /*#__PURE__*/_interopNamespace(PlussCore);
41
+ var FontAwesome__default = /*#__PURE__*/_interopDefaultLegacy(FontAwesome);
42
+ var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
43
+ var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
44
44
  var Textarea__default = /*#__PURE__*/_interopDefaultLegacy(Textarea);
45
45
 
46
46
  const values = {
@@ -112,7 +112,13 @@ const values = {
112
112
  hasHelpButton: true,
113
113
  helpGuideURL: '',
114
114
  stringConfigJobStatus: 'maintenanceJobStatus',
115
- stringConfigHideSeen: 'maintenanceDisableSeen'
115
+ stringConfigHideSeen: 'maintenanceDisableSeen',
116
+ // Comment subscription notification preference
117
+ notificationPreference: {
118
+ key: 'maintenancerequestComments',
119
+ label: 'Maintenance comments',
120
+ permission: 'maintenanceTracking'
121
+ }
116
122
  };
117
123
 
118
124
  // import * as PlussCore from '../../pluss-core/src';
@@ -241,7 +247,8 @@ const FeatureConfig = {
241
247
  init: environment => {
242
248
  FeatureConfig.env = environment;
243
249
  PlussCore__namespace.Config.init(environment);
244
- }
250
+ },
251
+ notificationPreference: values.notificationPreference
245
252
  };
246
253
 
247
254
  const JOBS_LOADED = values.actionJobsLoaded;
@@ -251,15 +258,15 @@ const JOBS_TYPES_LOADED = values.actionJobsTypesLoaded;
251
258
  const JOBS_STATUSES_LOADED = values.actionJobsStatusesLoaded;
252
259
  const JOBS_HIDE_SEEN = values.actionJobsHideSeen;
253
260
 
254
- function ownKeys$8(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
255
- function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$8(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$8(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
261
+ function ownKeys$7(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
262
+ function _objectSpread$7(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$7(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$7(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
256
263
  const {
257
- Helper: Helper$6,
264
+ Helper: Helper$4,
258
265
  Session: Session$9
259
266
  } = PlussCore__namespace;
260
- const maintenanceActions = {
267
+ const maintenanceActions$1 = {
261
268
  getJobType: (site, typeId) => {
262
- let url = Helper$6.getUrl(values.serviceKey, 'getjobtype');
269
+ let url = Helper$4.getUrl(values.serviceKey, 'getjobtype');
263
270
  return Session$9.authedFunction({
264
271
  method: 'POST',
265
272
  url,
@@ -270,7 +277,7 @@ const maintenanceActions = {
270
277
  });
271
278
  },
272
279
  getJobTypes: (site, id) => {
273
- let url = Helper$6.getUrl(values.serviceKey, 'getjobtypes');
280
+ let url = Helper$4.getUrl(values.serviceKey, 'getjobtypes');
274
281
  return Session$9.authedFunction({
275
282
  method: 'POST',
276
283
  url,
@@ -280,7 +287,7 @@ const maintenanceActions = {
280
287
  });
281
288
  },
282
289
  getJob: (site, id) => {
283
- let url = Helper$6.getUrl(values.serviceKey, 'getJob');
290
+ let url = Helper$4.getUrl(values.serviceKey, 'getJob');
284
291
  return Session$9.authedFunction({
285
292
  method: 'POST',
286
293
  url,
@@ -291,7 +298,7 @@ const maintenanceActions = {
291
298
  });
292
299
  },
293
300
  getJobByJobId: (site, jobId) => {
294
- let url = Helper$6.getUrl(values.serviceKey, 'getJob');
301
+ let url = Helper$4.getUrl(values.serviceKey, 'getJob');
295
302
  return Session$9.authedFunction({
296
303
  method: 'POST',
297
304
  url,
@@ -306,7 +313,7 @@ const maintenanceActions = {
306
313
  let type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
307
314
  return Session$9.authedFunction({
308
315
  method: 'POST',
309
- url: Helper$6.getUrl(values.serviceKey, 'getJobs'),
316
+ url: Helper$4.getUrl(values.serviceKey, 'getJobs'),
310
317
  data: {
311
318
  site,
312
319
  status,
@@ -314,7 +321,7 @@ const maintenanceActions = {
314
321
  }
315
322
  });
316
323
  },
317
- getJobs2: (site, status, type, lastKey) => {
324
+ getJobs2: (site, status, type, priority, assignee, startTime, endTime, search, lastKey) => {
318
325
  const query = {
319
326
  site
320
327
  };
@@ -324,37 +331,57 @@ const maintenanceActions = {
324
331
  if (type) {
325
332
  query.type = type;
326
333
  }
334
+ if (priority) {
335
+ query.priority = priority;
336
+ }
337
+ if (assignee) {
338
+ query.assignee = assignee;
339
+ }
340
+ if (startTime) {
341
+ query.startTime = startTime;
342
+ }
343
+ if (endTime) {
344
+ query.endTime = endTime;
345
+ }
346
+ if (search) {
347
+ query.search = search;
348
+ }
327
349
  if (lastKey) {
328
350
  query.lastKey = JSON.stringify(lastKey);
329
351
  }
330
352
  return Session$9.authedFunction({
331
353
  method: 'GET',
332
- url: Helper$6.getUrl(values.serviceKey, 'get/requests', query)
354
+ url: Helper$4.getUrl(values.serviceKey, 'get/requests', query)
333
355
  });
334
356
  },
357
+ /**
358
+ * @deprecated Use getJobs2 with pagination instead.
359
+ * This method recursively fetches ALL pages which can be slow for large datasets.
360
+ * Only use for CSV export where all data is needed.
361
+ */
335
362
  getJobsRecursive: function (site, status, type, lastKey) {
336
363
  let jobs = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
337
- return new Promise(resolve => {
338
- maintenanceActions.getJobs2(site, status, type, lastKey).then(jobRes => {
364
+ return new Promise((resolve, reject) => {
365
+ maintenanceActions$1.getJobs2(site, status, type, undefined, undefined, undefined, undefined, undefined, lastKey).then(jobRes => {
339
366
  const newJobs = [...jobs, ...jobRes.data.Items];
340
367
  if (!jobRes.data.LastKey) {
341
368
  return resolve(newJobs);
342
369
  }
343
- return resolve(maintenanceActions.getJobsRecursive(site, status, type, jobRes.data.LastKey, newJobs));
344
- });
370
+ maintenanceActions$1.getJobsRecursive(site, status, type, jobRes.data.LastKey, newJobs).then(resolve).catch(reject);
371
+ }).catch(reject);
345
372
  });
346
373
  },
347
374
  createJob: job => {
348
375
  return Session$9.authedFunction({
349
376
  method: 'POST',
350
- url: Helper$6.getUrl(values.serviceKey, 'sendMaintenance'),
351
- data: _objectSpread$8({}, job)
377
+ url: Helper$4.getUrl(values.serviceKey, 'sendMaintenance'),
378
+ data: _objectSpread$7({}, job)
352
379
  });
353
380
  },
354
381
  editJob: (job, site) => {
355
382
  return Session$9.authedFunction({
356
383
  method: 'POST',
357
- url: Helper$6.getUrl(values.serviceKey, 'editJob'),
384
+ url: Helper$4.getUrl(values.serviceKey, 'editJob'),
358
385
  data: {
359
386
  job,
360
387
  site
@@ -364,7 +391,7 @@ const maintenanceActions = {
364
391
  deleteJob: (site, id) => {
365
392
  return Session$9.authedFunction({
366
393
  method: 'POST',
367
- url: Helper$6.getUrl(values.serviceKey, 'requests/remove'),
394
+ url: Helper$4.getUrl(values.serviceKey, 'requests/remove'),
368
395
  data: {
369
396
  site,
370
397
  id
@@ -374,7 +401,7 @@ const maintenanceActions = {
374
401
  editJobStatus: (id, status) => {
375
402
  return Session$9.authedFunction({
376
403
  method: 'POST',
377
- url: Helper$6.getUrl(values.serviceKey, 'editJobStatus'),
404
+ url: Helper$4.getUrl(values.serviceKey, 'editJobStatus'),
378
405
  data: {
379
406
  id,
380
407
  status
@@ -384,7 +411,7 @@ const maintenanceActions = {
384
411
  editJobPriority: (id, priority) => {
385
412
  return Session$9.authedFunction({
386
413
  method: 'POST',
387
- url: Helper$6.getUrl(values.serviceKey, 'update/priority'),
414
+ url: Helper$4.getUrl(values.serviceKey, 'update/priority'),
388
415
  data: {
389
416
  id,
390
417
  priority
@@ -394,7 +421,7 @@ const maintenanceActions = {
394
421
  assignJob: (jobId, userId) => {
395
422
  return Session$9.authedFunction({
396
423
  method: 'POST',
397
- url: Helper$6.getUrl(values.serviceKey, 'update/assign'),
424
+ url: Helper$4.getUrl(values.serviceKey, 'update/assign'),
398
425
  data: {
399
426
  id: jobId,
400
427
  userId
@@ -404,7 +431,7 @@ const maintenanceActions = {
404
431
  getAssignees: site => {
405
432
  return Session$9.authedFunction({
406
433
  method: 'GET',
407
- url: Helper$6.getUrl(values.serviceKey, 'get/assignees', {
434
+ url: Helper$4.getUrl(values.serviceKey, 'get/assignees', {
408
435
  site
409
436
  })
410
437
  });
@@ -412,7 +439,7 @@ const maintenanceActions = {
412
439
  addNote: (jobId, note, attachments, images) => {
413
440
  return Session$9.authedFunction({
414
441
  method: 'POST',
415
- url: Helper$6.getUrl(values.serviceKey, 'requests/note'),
442
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
416
443
  data: {
417
444
  id: jobId,
418
445
  note,
@@ -425,7 +452,7 @@ const maintenanceActions = {
425
452
  editNote: (jobId, noteId, note, attachments, images) => {
426
453
  return Session$9.authedFunction({
427
454
  method: 'POST',
428
- url: Helper$6.getUrl(values.serviceKey, 'requests/note'),
455
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
429
456
  data: {
430
457
  id: jobId,
431
458
  note,
@@ -439,7 +466,7 @@ const maintenanceActions = {
439
466
  deleteNote: (jobId, noteId) => {
440
467
  return Session$9.authedFunction({
441
468
  method: 'POST',
442
- url: Helper$6.getUrl(values.serviceKey, 'requests/note'),
469
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
443
470
  data: {
444
471
  id: jobId,
445
472
  noteId,
@@ -459,7 +486,7 @@ const maintenanceActions = {
459
486
  };
460
487
  return Session$9.authedFunction({
461
488
  method: 'POST',
462
- url: Helper$6.getUrl(values.serviceKey, 'createJobType'),
489
+ url: Helper$4.getUrl(values.serviceKey, 'createJobType'),
463
490
  data
464
491
  });
465
492
  },
@@ -477,14 +504,14 @@ const maintenanceActions = {
477
504
  if (hasCustomFields && customFields) data.customFields = customFields;
478
505
  return Session$9.authedFunction({
479
506
  method: 'POST',
480
- url: Helper$6.getUrl(values.serviceKey, 'editJobType'),
507
+ url: Helper$4.getUrl(values.serviceKey, 'editJobType'),
481
508
  data
482
509
  });
483
510
  },
484
511
  deleteJobType: (site, id) => {
485
512
  return Session$9.authedFunction({
486
513
  method: 'POST',
487
- url: Helper$6.getUrl(values.serviceKey, 'deleteJobType'),
514
+ url: Helper$4.getUrl(values.serviceKey, 'deleteJobType'),
488
515
  data: {
489
516
  site,
490
517
  id
@@ -494,7 +521,7 @@ const maintenanceActions = {
494
521
  getExternalSync: jobId => {
495
522
  return Session$9.authedFunction({
496
523
  method: 'GET',
497
- url: Helper$6.getUrl(values.serviceKey, 'get/externalsync', {
524
+ url: Helper$4.getUrl(values.serviceKey, 'get/externalsync', {
498
525
  id: jobId
499
526
  })
500
527
  });
@@ -502,7 +529,7 @@ const maintenanceActions = {
502
529
  retrySync: jobId => {
503
530
  return Session$9.authedFunction({
504
531
  method: 'POST',
505
- url: Helper$6.getUrl(values.serviceKey, 'update/retrysync'),
532
+ url: Helper$4.getUrl(values.serviceKey, 'update/retrysync'),
506
533
  data: {
507
534
  id: jobId
508
535
  }
@@ -511,7 +538,7 @@ const maintenanceActions = {
511
538
  };
512
539
 
513
540
  const {
514
- Helper: Helper$5,
541
+ Helper: Helper$3,
515
542
  Session: Session$8
516
543
  } = PlussCore__namespace;
517
544
  const reactionActions = {
@@ -529,7 +556,7 @@ const reactionActions = {
529
556
  }
530
557
  return Session$8.authedFunction({
531
558
  method: 'POST',
532
- url: Helper$5.getUrl('reactions', 'comments/add'),
559
+ url: Helper$3.getUrl('reactions', 'comments/add'),
533
560
  data
534
561
  });
535
562
  },
@@ -552,7 +579,7 @@ const reactionActions = {
552
579
  }
553
580
  return Session$8.authedFunction({
554
581
  method: 'GET',
555
- url: Helper$5.getUrl('reactions', 'comments/get', query)
582
+ url: Helper$3.getUrl('reactions', 'comments/get', query)
556
583
  });
557
584
  }
558
585
  };
@@ -585,30 +612,6 @@ var jobStatusOptions = [
585
612
  }
586
613
  ];
587
614
 
588
- const {
589
- Helper: Helper$4
590
- } = PlussCore__namespace;
591
- const jobsUpdate = (site, isdashboard) => {
592
- return dispatch => {
593
- if (isdashboard) dispatch({
594
- type: JOBS_LOADING
595
- });
596
- maintenanceActions.getJobsRecursive(site).then(res => {
597
- const currentSite = Helper$4.readStorageWithCookie('site');
598
- if (!___default["default"].isEmpty(res) && res[0].site === currentSite) {
599
- dispatch({
600
- type: JOBS_LOADED,
601
- payload: res
602
- });
603
- } else {
604
- dispatch({
605
- type: JOBS_LOADED,
606
- payload: []
607
- });
608
- }
609
- });
610
- };
611
- };
612
615
  const jobsLoaded = events => {
613
616
  return {
614
617
  type: JOBS_LOADED,
@@ -746,8 +749,8 @@ const getJobPriority = priority => {
746
749
  return priorityOption || getDefaultPriority();
747
750
  };
748
751
 
749
- function ownKeys$7(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
750
- function _objectSpread$7(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$7(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$7(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
752
+ function ownKeys$6(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
753
+ function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$6(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$6(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
751
754
  const {
752
755
  Session: Session$7,
753
756
  Components: Components$7,
@@ -755,41 +758,241 @@ const {
755
758
  } = PlussCore__namespace;
756
759
  class JobList extends React.Component {
757
760
  constructor(props) {
761
+ var _this;
758
762
  super(props);
759
- _defineProperty__default["default"](this, "setRequesters", jobs => {
760
- const requesters = ___default["default"].orderBy(___default["default"].uniqBy(jobs.map(j => ({
761
- id: j.userID,
762
- displayName: j.userName,
763
- profilePic: j.userProfilePic
764
- })), 'id'), 'displayName', 'asc');
765
- this.setState({
766
- requesters
767
- });
763
+ _this = this;
764
+ _defineProperty__default["default"](this, "getAssignees", async () => {
765
+ try {
766
+ const res = await maintenanceActions$1.getAssignees(this.props.auth.site);
767
+ this.setState({
768
+ assignees: res.data.Users
769
+ });
770
+ } catch (error) {
771
+ console.error('getAssignees', error);
772
+ }
768
773
  });
769
- _defineProperty__default["default"](this, "getJobs", async () => {
774
+ /**
775
+ * Build server-side filter params from current filter state.
776
+ * Translates UI filter selections into API query parameters.
777
+ */
778
+ _defineProperty__default["default"](this, "buildFilterParams", () => {
770
779
  const {
771
- auth
780
+ selectedStatusFilter,
781
+ selectedTypeFilter,
782
+ selectedPriorityFilter,
783
+ selectedUserFilter,
784
+ selectedTimeFilterStart,
785
+ selectedTimeFilterEnd,
786
+ searchTerm
787
+ } = this.state;
788
+ const {
789
+ statusTypes
772
790
  } = this.props;
773
- try {
774
- const res = await maintenanceActions.getJobsRecursive(auth.site);
775
- if (!___default["default"].isEmpty(res) && res[0].site === auth.site) {
776
- this.setRequesters(res);
777
- this.props.jobsLoaded(res);
791
+ const params = {};
792
+
793
+ // Status filter: translate "All Incomplete" into the actual incomplete statuses
794
+ if (selectedStatusFilter) {
795
+ if (selectedStatusFilter === STATUS_IMCOMPLETE) {
796
+ // Exclude completed statuses - pass all non-completed status texts
797
+ const incompleteStatuses = statusTypes.filter(s => s.category !== STATUS_COMPLETED).map(s => s.text);
798
+ if (incompleteStatuses.length > 0) {
799
+ params.status = incompleteStatuses.join(',');
800
+ }
801
+ } else {
802
+ params.status = selectedStatusFilter;
778
803
  }
779
- } catch (error) {
780
- console.error('getJobs', error);
781
804
  }
805
+ if (selectedTypeFilter) {
806
+ params.type = selectedTypeFilter;
807
+ }
808
+ if (selectedPriorityFilter) {
809
+ params.priority = selectedPriorityFilter;
810
+ }
811
+ if (selectedUserFilter) {
812
+ params.assignee = selectedUserFilter;
813
+ }
814
+ if (selectedTimeFilterStart) {
815
+ params.startTime = selectedTimeFilterStart;
816
+ }
817
+ if (selectedTimeFilterEnd) {
818
+ params.endTime = selectedTimeFilterEnd;
819
+ }
820
+ if (searchTerm) {
821
+ params.search = searchTerm;
822
+ }
823
+ return params;
824
+ });
825
+ /**
826
+ * Minimum number of items to auto-fill before stopping background fetch.
827
+ * Because DynamoDB pages are unfiltered and the backend filters after
828
+ * query, a single page may yield very few matching results. We keep
829
+ * fetching in the background until we have this many items to display.
830
+ */
831
+ _defineProperty__default["default"](this, "MIN_PAGE_SIZE", 20);
832
+ /**
833
+ * Monotonically increasing ID used to ignore stale fetch results.
834
+ * When a filter changes, fetchJobs() increments this counter. Any
835
+ * in-flight fetch or autoFillPages loop checks the counter before
836
+ * applying results — if it doesn't match, the results are discarded.
837
+ *
838
+ * Alternative: AbortController would actually cancel the HTTP request
839
+ * (axios supports it via the `signal` config option). That would save
840
+ * bandwidth and server load but requires threading `signal` through
841
+ * authedFunction → getJobs2 → fetchPage (3 layers). The fetchId
842
+ * approach is simpler and sufficient — stale requests still complete
843
+ * in the background but their results are ignored.
844
+ */
845
+ _defineProperty__default["default"](this, "_fetchId", 0);
846
+ /**
847
+ * Fetch a single page from the server using the given lastKey.
848
+ */
849
+ _defineProperty__default["default"](this, "fetchPage", async function () {
850
+ let lastKey = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
851
+ const {
852
+ auth
853
+ } = _this.props;
854
+ const filters = _this.buildFilterParams();
855
+ return maintenanceActions$1.getJobs2(auth.site, filters.status, filters.type, filters.priority, filters.assignee, filters.startTime, filters.endTime, filters.search, lastKey);
856
+ });
857
+ /**
858
+ * Fetch the first page and render immediately.
859
+ * If fewer than MIN_PAGE_SIZE items returned and there's more data,
860
+ * kicks off a background loop that keeps fetching and appending
861
+ * so results appear progressively.
862
+ */
863
+ _defineProperty__default["default"](this, "fetchJobs", async () => {
864
+ const fetchId = ++this._fetchId;
865
+ this.setState({
866
+ loading: true,
867
+ loadingMore: false
868
+ }, async () => {
869
+ try {
870
+ const res = await this.fetchPage(null);
871
+ if (this._fetchId !== fetchId) return; // stale fetch
872
+
873
+ const items = res.data.Items || [];
874
+ const lastKey = res.data.LastKey || null;
875
+ this.setState({
876
+ jobs: items,
877
+ lastKey,
878
+ hasMore: !!lastKey,
879
+ loading: false
880
+ });
881
+ this.props.jobsLoaded(items);
882
+ this.setRequesters(items);
883
+
884
+ // Auto-fill in background if first page was sparse
885
+ if (lastKey && items.length < this.MIN_PAGE_SIZE) {
886
+ this.autoFillPages(items, lastKey, fetchId);
887
+ }
888
+ } catch (error) {
889
+ if (this._fetchId !== fetchId) return; // stale fetch
890
+ console.error('fetchJobs', error);
891
+ this.setState({
892
+ loading: false
893
+ });
894
+ }
895
+ });
782
896
  });
783
- _defineProperty__default["default"](this, "getAssignees", async () => {
897
+ /**
898
+ * Background loop: keep fetching pages and appending results
899
+ * until we have MIN_PAGE_SIZE items or run out of data.
900
+ * Each page is rendered as it arrives so the user sees
901
+ * results appearing progressively.
902
+ */
903
+ _defineProperty__default["default"](this, "autoFillPages", async (existingJobs, startKey, fetchId) => {
904
+ this.setState({
905
+ loadingMore: true
906
+ });
907
+ let currentJobs = existingJobs;
908
+ let currentLastKey = startKey;
784
909
  try {
785
- const res = await maintenanceActions.getAssignees(this.props.auth.site);
786
- this.setState({
787
- assignees: res.data.Users
788
- });
910
+ while (currentLastKey && currentJobs.length < this.MIN_PAGE_SIZE) {
911
+ const res = await this.fetchPage(currentLastKey);
912
+ if (this._fetchId !== fetchId) return; // stale fetch
913
+
914
+ const items = res.data.Items || [];
915
+ currentLastKey = res.data.LastKey || null;
916
+ currentJobs = [...currentJobs, ...items];
917
+
918
+ // Append to UI immediately after each page arrives
919
+ this.setState({
920
+ jobs: currentJobs,
921
+ lastKey: currentLastKey,
922
+ hasMore: !!currentLastKey
923
+ });
924
+ if (items.length > 0) {
925
+ this.props.jobsLoaded(items);
926
+ this.setRequesters(currentJobs);
927
+ }
928
+ }
789
929
  } catch (error) {
790
- console.error('getAssignees', error);
930
+ if (this._fetchId !== fetchId) return; // stale fetch
931
+ console.error('autoFillPages', error);
932
+ } finally {
933
+ if (this._fetchId === fetchId) {
934
+ this.setState({
935
+ loadingMore: false
936
+ });
937
+ }
791
938
  }
792
939
  });
940
+ /**
941
+ * Load the next batch of jobs when the user clicks "Load More".
942
+ * Fetches one page and also auto-fills in background if sparse.
943
+ */
944
+ _defineProperty__default["default"](this, "loadMore", async () => {
945
+ const fetchId = ++this._fetchId;
946
+ const {
947
+ lastKey,
948
+ jobs
949
+ } = this.state;
950
+ this.setState({
951
+ loadingMore: true
952
+ }, async () => {
953
+ try {
954
+ const res = await this.fetchPage(lastKey);
955
+ if (this._fetchId !== fetchId) return; // stale fetch
956
+
957
+ const items = res.data.Items || [];
958
+ const newLastKey = res.data.LastKey || null;
959
+ const updatedJobs = [...jobs, ...items];
960
+ this.setState({
961
+ jobs: updatedJobs,
962
+ lastKey: newLastKey,
963
+ hasMore: !!newLastKey
964
+ });
965
+ if (items.length > 0) {
966
+ this.props.jobsLoaded(items);
967
+ }
968
+
969
+ // Auto-fill in background if this page was sparse
970
+ if (newLastKey && items.length < this.MIN_PAGE_SIZE) {
971
+ this.autoFillPages(updatedJobs, newLastKey, fetchId);
972
+ } else {
973
+ this.setState({
974
+ loadingMore: false
975
+ });
976
+ }
977
+ } catch (error) {
978
+ if (this._fetchId !== fetchId) return; // stale fetch
979
+ console.error('loadMore', error);
980
+ this.setState({
981
+ loadingMore: false
982
+ });
983
+ }
984
+ });
985
+ });
986
+ _defineProperty__default["default"](this, "setRequesters", jobs => {
987
+ const requesters = ___default["default"].orderBy(___default["default"].uniqBy(jobs.map(j => ({
988
+ id: j.userID,
989
+ displayName: j.userName,
990
+ profilePic: j.userProfilePic
991
+ })), 'id'), 'displayName', 'asc');
992
+ this.setState({
993
+ requesters
994
+ });
995
+ });
793
996
  _defineProperty__default["default"](this, "sortByCol", col => {
794
997
  const {
795
998
  sortColumn,
@@ -809,9 +1012,12 @@ class JobList extends React.Component {
809
1012
  _defineProperty__default["default"](this, "onRemoveRequest", async request => {
810
1013
  if (window.confirm(values.textAreYouSureYouWantToDelete)) {
811
1014
  this.props.removeJob(request.id);
1015
+ // Remove from local state immediately
1016
+ this.setState(prevState => ({
1017
+ jobs: prevState.jobs.filter(j => j.id !== request.id)
1018
+ }));
812
1019
  try {
813
- await maintenanceActions.deleteJob(this.props.auth.site, request.id);
814
- this.getJobs();
1020
+ await maintenanceActions$1.deleteJob(this.props.auth.site, request.id);
815
1021
  } catch (error) {
816
1022
  console.log('onRemoveRequest', error);
817
1023
  alert('Something went wrong with the request. Please try again.');
@@ -830,20 +1036,20 @@ class JobList extends React.Component {
830
1036
  });
831
1037
  _defineProperty__default["default"](this, "selectTypeFilter", filter => {
832
1038
  this.setState({
833
- selectedTypeFilter: filter
834
- });
1039
+ selectedTypeFilter: filter || null
1040
+ }, () => this.fetchJobs());
835
1041
  this.closeFilter();
836
1042
  });
837
1043
  _defineProperty__default["default"](this, "selectPriorityFilter", filter => {
838
1044
  this.setState({
839
- selectedPriorityFilter: filter
840
- });
1045
+ selectedPriorityFilter: filter || null
1046
+ }, () => this.fetchJobs());
841
1047
  this.closeFilter();
842
1048
  });
843
1049
  _defineProperty__default["default"](this, "selectStatusFilter", filter => {
844
1050
  this.setState({
845
- selectedStatusFilter: filter
846
- });
1051
+ selectedStatusFilter: filter || null
1052
+ }, () => this.fetchJobs());
847
1053
  this.closeFilter();
848
1054
  });
849
1055
  _defineProperty__default["default"](this, "timeFilterChanged", selectedTimeFilter => {
@@ -887,7 +1093,7 @@ class JobList extends React.Component {
887
1093
  selectedTimeFilterStart: startTime,
888
1094
  selectedTimeFilterEnd: endTime,
889
1095
  selectedTimeFilterText: text
890
- });
1096
+ }, () => this.fetchJobs());
891
1097
  this.closeFilter();
892
1098
  });
893
1099
  _defineProperty__default["default"](this, "removeTimeFilter", () => {
@@ -895,7 +1101,7 @@ class JobList extends React.Component {
895
1101
  selectedTimeFilterStart: null,
896
1102
  selectedTimeFilterEnd: null,
897
1103
  selectedTimeFilterText: null
898
- });
1104
+ }, () => this.fetchJobs());
899
1105
  });
900
1106
  _defineProperty__default["default"](this, "onHandleChange", event => {
901
1107
  var stateChange = {};
@@ -911,7 +1117,7 @@ class JobList extends React.Component {
911
1117
  this.setState({
912
1118
  selectedUserFilter: null,
913
1119
  selectedUserFilterText: null
914
- });
1120
+ }, () => this.fetchJobs());
915
1121
  });
916
1122
  _defineProperty__default["default"](this, "saveUserFilter", () => {
917
1123
  if (!this.state.selectedAssignee) {
@@ -921,7 +1127,7 @@ class JobList extends React.Component {
921
1127
  selectedUserFilter: this.state.selectedAssignee.id,
922
1128
  selectedUserFilterText: this.state.selectedAssignee.displayName,
923
1129
  selectedAssignee: null
924
- });
1130
+ }, () => this.fetchJobs());
925
1131
  }
926
1132
  this.closeFilter();
927
1133
  });
@@ -934,7 +1140,7 @@ class JobList extends React.Component {
934
1140
  this.setState({
935
1141
  selectedRequesterFilter: null,
936
1142
  selectedRequesterFilterText: null
937
- });
1143
+ }, () => this.fetchJobs());
938
1144
  });
939
1145
  _defineProperty__default["default"](this, "saveRequesterFilter", () => {
940
1146
  if (!this.state.selectedRequester) {
@@ -944,7 +1150,7 @@ class JobList extends React.Component {
944
1150
  selectedRequesterFilter: this.state.selectedRequester.id,
945
1151
  selectedRequesterFilterText: this.state.selectedRequester.displayName,
946
1152
  selectedRequester: null
947
- });
1153
+ }, () => this.fetchJobs());
948
1154
  }
949
1155
  this.closeFilter();
950
1156
  });
@@ -955,85 +1161,47 @@ class JobList extends React.Component {
955
1161
  lastSearch: thisSearchTime
956
1162
  });
957
1163
  setTimeout(() => {
958
- // delayed setter to avoid filtering on every keypress
1164
+ // delayed setter to avoid searching on every keypress
959
1165
  if (this.state.lastSearch === thisSearchTime) {
960
1166
  this.setState({
961
1167
  searchTerm: this.state.search
962
- });
1168
+ }, () => this.fetchJobs());
963
1169
  }
964
1170
  }, 500);
965
1171
  });
1172
+ /**
1173
+ * Get the source array for rendering.
1174
+ * With server-side filtering, this is simply the local jobs array
1175
+ * sorted by the user's selected sort column.
1176
+ * The requester filter still applies client-side since the backend
1177
+ * doesn't have a requester/userID filter param.
1178
+ */
966
1179
  _defineProperty__default["default"](this, "getSource", () => {
967
- let source = this.props.source;
1180
+ let source = this.state.jobs;
968
1181
 
969
- // filter by time
970
- if (this.state.selectedTimeFilterStart && this.state.selectedTimeFilterEnd) {
971
- source = ___default["default"].filter(source, r => {
972
- return r.createdUnix >= this.state.selectedTimeFilterStart && r.createdUnix <= this.state.selectedTimeFilterEnd;
973
- });
974
- }
975
-
976
- // filter by type
977
- if (this.state.selectedTypeFilter) {
978
- source = ___default["default"].filter(source, r => {
979
- return r.type === this.state.selectedTypeFilter;
980
- });
981
- }
982
-
983
- // filter by priority
984
- if (this.state.selectedPriorityFilter) {
985
- const defaultPriority = getDefaultPriority().name;
986
- source = ___default["default"].filter(source, r => {
987
- return r.priority === this.state.selectedPriorityFilter || this.state.selectedPriorityFilter === defaultPriority && ___default["default"].isNil(r.priority);
988
- });
989
- }
1182
+ // Filter out deleted items
1183
+ source = ___default["default"].filter(source, ev => ev != null && !ev.Deleted);
990
1184
 
991
- // filter by status
992
- if (this.state.selectedStatusFilter) {
993
- const {
994
- statusTypes
995
- } = this.props;
996
- const defaultStatus = statusTypes.find(s => s.category === STATUS_NOT_ACTIONED);
997
- source = ___default["default"].filter(source, r => {
998
- const status = statusTypes.find(s => s.text === r.status) || defaultStatus;
999
- if (this.state.selectedStatusFilter === STATUS_IMCOMPLETE) {
1000
- return status.category !== STATUS_COMPLETED;
1001
- }
1002
- return status.text === this.state.selectedStatusFilter;
1003
- });
1004
- }
1005
- if (this.state.selectedUserFilter) {
1006
- source = ___default["default"].filter(source, r => {
1007
- return r.AssigneeId === this.state.selectedUserFilter;
1008
- });
1009
- }
1185
+ // Requester filter still client-side (no backend param for userID filtering)
1010
1186
  if (this.state.selectedRequesterFilter) {
1011
1187
  source = ___default["default"].filter(source, r => {
1012
1188
  return r.userID === this.state.selectedRequesterFilter;
1013
1189
  });
1014
1190
  }
1015
- if (!___default["default"].isEmpty(this.state.searchTerm)) {
1016
- source = ___default["default"].filter(source, r => {
1017
- if (r.jobId && r.jobId === this.state.searchTerm) {
1018
- return true;
1019
- }
1020
- if (r.room && r.room.toLowerCase().indexOf(this.state.searchTerm.toLowerCase()) > -1) {
1021
- return true;
1022
- }
1023
- if (r.title && r.title.toLowerCase().indexOf(this.state.searchTerm.toLowerCase()) > -1) {
1024
- return true;
1191
+
1192
+ // Skip sorting while auto-fill is appending results to avoid jumpiness.
1193
+ // Sort is re-applied when the user clicks a column header or when
1194
+ // auto-fill completes.
1195
+ if (!this.state.loadingMore) {
1196
+ source = ___default["default"].sortBy(source, event => {
1197
+ if (this.state.sortColumn === 'assigned') {
1198
+ return event.Assignee ? event.Assignee.displayName : 'Unassigned';
1025
1199
  }
1026
- return false;
1200
+ if (this.state.sortColumn !== 'createdUnix') return event[this.state.sortColumn];
1201
+ return event.createdUnix;
1027
1202
  });
1203
+ if (this.state.sortDesc) source.reverse();
1028
1204
  }
1029
- source = ___default["default"].sortBy(source, event => {
1030
- if (this.state.sortColumn === 'assigned') {
1031
- return event.Assignee ? event.Assignee.displayName : 'Unassigned';
1032
- }
1033
- if (this.state.sortColumn !== 'createdUnix') return event[this.state.sortColumn];
1034
- return event.createdUnix;
1035
- });
1036
- if (this.state.sortDesc) source.reverse();
1037
1205
  return source;
1038
1206
  });
1039
1207
  _defineProperty__default["default"](this, "getCustomFieldValue", field => {
@@ -1113,7 +1281,7 @@ class JobList extends React.Component {
1113
1281
  });
1114
1282
  const customFieldValues = this.getCustomFields(r, customColumns);
1115
1283
  const priority = r.priority || defaultPriority;
1116
- return _objectSpread$7(_objectSpread$7(_objectSpread$7({}, r), customFieldValues), {}, {
1284
+ return _objectSpread$6(_objectSpread$6(_objectSpread$6({}, r), customFieldValues), {}, {
1117
1285
  notes,
1118
1286
  progressTime,
1119
1287
  completedTime,
@@ -1145,13 +1313,60 @@ class JobList extends React.Component {
1145
1313
  exportCsvOpen: false
1146
1314
  });
1147
1315
  });
1316
+ _defineProperty__default["default"](this, "hasActiveFilters", () => {
1317
+ const {
1318
+ selectedTypeFilter,
1319
+ selectedPriorityFilter,
1320
+ selectedStatusFilter,
1321
+ selectedTimeFilterStart,
1322
+ selectedUserFilter,
1323
+ selectedRequesterFilter,
1324
+ searchTerm
1325
+ } = this.state;
1326
+ return !!(selectedTypeFilter || selectedPriorityFilter || selectedStatusFilter || selectedTimeFilterStart || selectedUserFilter || selectedRequesterFilter || searchTerm);
1327
+ });
1328
+ _defineProperty__default["default"](this, "clearAllFilters", () => {
1329
+ this.setState({
1330
+ selectedTypeFilter: null,
1331
+ selectedPriorityFilter: null,
1332
+ selectedStatusFilter: null,
1333
+ selectedTimeFilterStart: null,
1334
+ selectedTimeFilterEnd: null,
1335
+ selectedTimeFilterText: null,
1336
+ selectedUserFilter: null,
1337
+ selectedUserFilterText: null,
1338
+ selectedRequesterFilter: null,
1339
+ selectedRequesterFilterText: null,
1340
+ search: '',
1341
+ searchTerm: ''
1342
+ }, () => this.fetchJobs());
1343
+ });
1148
1344
  this.state = {
1149
- showCompleted: false,
1150
1345
  sortColumn: 'createdUnix',
1151
1346
  sortDesc: true,
1152
1347
  selectedTimeFilter: Analytics$2.getAnalyticsFilterOptions()[1],
1153
1348
  assignees: [],
1154
- requesters: []
1349
+ requesters: [],
1350
+ // Server-side pagination state
1351
+ jobs: [],
1352
+ lastKey: null,
1353
+ hasMore: false,
1354
+ loading: false,
1355
+ loadingMore: false,
1356
+ // Filters (applied to server-side queries)
1357
+ selectedTypeFilter: null,
1358
+ selectedPriorityFilter: null,
1359
+ selectedStatusFilter: null,
1360
+ selectedTimeFilterStart: null,
1361
+ selectedTimeFilterEnd: null,
1362
+ selectedTimeFilterText: null,
1363
+ selectedUserFilter: null,
1364
+ selectedUserFilterText: null,
1365
+ selectedRequesterFilter: null,
1366
+ selectedRequesterFilterText: null,
1367
+ search: '',
1368
+ searchTerm: '',
1369
+ lastSearch: null
1155
1370
  };
1156
1371
  this.exportColumns = [{
1157
1372
  label: 'Select All',
@@ -1211,7 +1426,7 @@ class JobList extends React.Component {
1211
1426
  }
1212
1427
  componentDidMount() {
1213
1428
  this.props.jobStatusesUpdate(this.props.auth.site);
1214
- this.getJobs();
1429
+ this.fetchJobs();
1215
1430
  this.getAssignees();
1216
1431
  }
1217
1432
  renderFilterPopup() {
@@ -1225,7 +1440,7 @@ class JobList extends React.Component {
1225
1440
  minWidth: 400,
1226
1441
  hasPadding: true,
1227
1442
  onClose: this.closeFilter
1228
- }, ___default["default"].sortBy(___default["default"].uniq(this.props.source.map(r => r.type)), t => t.toLowerCase()).map(type => {
1443
+ }, ___default["default"].sortBy(___default["default"].uniq(this.state.jobs.map(r => r.type)), t => t.toLowerCase()).map(type => {
1229
1444
  return /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1230
1445
  key: type,
1231
1446
  onClick: () => {
@@ -1416,7 +1631,7 @@ class JobList extends React.Component {
1416
1631
  const status = ev.status && statusTypes.find(s => s.text === ev.status) || defaultStatus;
1417
1632
  const priority = getJobPriority(ev.priority);
1418
1633
  return /*#__PURE__*/React__default["default"].createElement("tr", {
1419
- key: index
1634
+ key: ev.id || index
1420
1635
  }, /*#__PURE__*/React__default["default"].createElement("td", null, ev.jobId), /*#__PURE__*/React__default["default"].createElement("td", {
1421
1636
  className: "table-TitleColumn"
1422
1637
  }, /*#__PURE__*/React__default["default"].createElement(reactRouterDom.Link, {
@@ -1497,8 +1712,28 @@ class JobList extends React.Component {
1497
1712
  if (col !== this.state.sortColumn) return '';
1498
1713
  return ' table--columnActive';
1499
1714
  }
1715
+ renderLoading() {
1716
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1717
+ className: "flex flex-center-row",
1718
+ style: {
1719
+ padding: 40
1720
+ }
1721
+ }, /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
1722
+ style: {
1723
+ fontSize: 32,
1724
+ color: PlussCore.Colours.COLOUR_DUSK_LIGHT
1725
+ },
1726
+ name: "spinner fa-pulse fa-fw"
1727
+ }), /*#__PURE__*/React__default["default"].createElement("span", {
1728
+ className: "marginLeft-16 fontRegular fontSize-14",
1729
+ style: {
1730
+ color: PlussCore.Colours.TEXT_MID
1731
+ }
1732
+ }, "Loading ", values.textTitleRequests, "\u2026"));
1733
+ }
1500
1734
  renderEmpty() {
1501
1735
  const title = this.props.strings["".concat(values.featureKey, "_textTitleRequests")] || values.textTitleRequests;
1736
+ const hasFilters = this.hasActiveFilters();
1502
1737
  return /*#__PURE__*/React__default["default"].createElement("div", {
1503
1738
  style: {
1504
1739
  display: 'flex',
@@ -1510,7 +1745,22 @@ class JobList extends React.Component {
1510
1745
  }
1511
1746
  }, /*#__PURE__*/React__default["default"].createElement("div", {
1512
1747
  className: "emptyState"
1513
- }), /*#__PURE__*/React__default["default"].createElement("div", {
1748
+ }), hasFilters ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
1749
+ className: "marginTop-32",
1750
+ style: {
1751
+ maxWidth: 500,
1752
+ textAlign: 'center'
1753
+ }
1754
+ }, /*#__PURE__*/React__default["default"].createElement("span", {
1755
+ className: "fontRegular fontSize-13"
1756
+ }, "No ", title.toLowerCase(), " match your current filters.")), /*#__PURE__*/React__default["default"].createElement("div", {
1757
+ className: "marginTop-16"
1758
+ }, /*#__PURE__*/React__default["default"].createElement(Components$7.Button, {
1759
+ inline: true,
1760
+ buttonType: "tertiary",
1761
+ onClick: this.clearAllFilters,
1762
+ isActive: true
1763
+ }, "Clear All Filters"))) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
1514
1764
  className: "marginTop-32",
1515
1765
  style: {
1516
1766
  maxWidth: 500,
@@ -1526,11 +1776,58 @@ class JobList extends React.Component {
1526
1776
  maxWidth: 500,
1527
1777
  textAlign: 'center'
1528
1778
  }
1529
- }, values.textEmptyExample));
1779
+ }, values.textEmptyExample)));
1780
+ }
1781
+ renderLoadMore() {
1782
+ const {
1783
+ hasMore,
1784
+ loadingMore
1785
+ } = this.state;
1786
+ if (!hasMore && !loadingMore) return null;
1787
+
1788
+ // During background auto-fill, show a subtle spinner without a button
1789
+ if (loadingMore) {
1790
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1791
+ className: "flex flex-center-row",
1792
+ style: {
1793
+ padding: '16px 0'
1794
+ }
1795
+ }, /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
1796
+ name: "spinner fa-pulse fa-fw",
1797
+ style: {
1798
+ fontSize: 16,
1799
+ color: PlussCore.Colours.TEXT_MID,
1800
+ marginRight: 8
1801
+ }
1802
+ }), /*#__PURE__*/React__default["default"].createElement("span", {
1803
+ className: "fontRegular fontSize-13",
1804
+ style: {
1805
+ color: PlussCore.Colours.TEXT_MID
1806
+ }
1807
+ }, "Loading more results\u2026"));
1808
+ }
1809
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1810
+ className: "flex flex-center-row",
1811
+ style: {
1812
+ padding: '16px 0'
1813
+ }
1814
+ }, /*#__PURE__*/React__default["default"].createElement(Components$7.Button, {
1815
+ inline: true,
1816
+ buttonType: "tertiary",
1817
+ onClick: this.loadMore,
1818
+ isActive: true
1819
+ }, "Load More"));
1530
1820
  }
1531
1821
  renderContent() {
1532
- if (___default["default"].isEmpty(this.props.source)) return this.renderEmpty();
1533
- return /*#__PURE__*/React__default["default"].createElement(reactBootstrap.Table, {
1822
+ const {
1823
+ loading,
1824
+ loadingMore,
1825
+ jobs
1826
+ } = this.state;
1827
+ if (loading) return this.renderLoading();
1828
+ if (___default["default"].isEmpty(jobs) && !loadingMore) return this.renderEmpty();
1829
+ if (___default["default"].isEmpty(jobs)) return this.renderLoading();
1830
+ return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement(reactBootstrap.Table, {
1534
1831
  className: "plussTable",
1535
1832
  striped: true,
1536
1833
  bordered: true,
@@ -1613,7 +1910,7 @@ class JobList extends React.Component {
1613
1910
  style: {
1614
1911
  width: 50
1615
1912
  }
1616
- }))), /*#__PURE__*/React__default["default"].createElement("tbody", null, this.renderRequests()));
1913
+ }))), /*#__PURE__*/React__default["default"].createElement("tbody", null, this.renderRequests())), this.renderLoadMore());
1617
1914
  }
1618
1915
  renderFilters() {
1619
1916
  let typeFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
@@ -1662,13 +1959,9 @@ class JobList extends React.Component {
1662
1959
  typeFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1663
1960
  className: "marginRight-10",
1664
1961
  onClick: () => {
1665
- this.openFilter('type');
1666
- },
1667
- rightIcon: "close",
1668
- rightClick: e => {
1669
- e.stopPropagation();
1670
1962
  this.selectTypeFilter();
1671
1963
  },
1964
+ rightIcon: "close",
1672
1965
  text: this.state.selectedTypeFilter
1673
1966
  });
1674
1967
  }
@@ -1676,13 +1969,9 @@ class JobList extends React.Component {
1676
1969
  priorityFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1677
1970
  className: "marginRight-10",
1678
1971
  onClick: () => {
1679
- this.openFilter('priority');
1680
- },
1681
- rightIcon: "close",
1682
- rightClick: e => {
1683
- e.stopPropagation();
1684
1972
  this.selectPriorityFilter();
1685
1973
  },
1974
+ rightIcon: "close",
1686
1975
  text: this.state.selectedPriorityFilter
1687
1976
  });
1688
1977
  }
@@ -1690,13 +1979,9 @@ class JobList extends React.Component {
1690
1979
  statusFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1691
1980
  className: "marginRight-10",
1692
1981
  onClick: () => {
1693
- this.openFilter('status');
1694
- },
1695
- rightIcon: "close",
1696
- rightClick: e => {
1697
- e.stopPropagation();
1698
1982
  this.selectStatusFilter();
1699
1983
  },
1984
+ rightIcon: "close",
1700
1985
  text: this.state.selectedStatusFilter
1701
1986
  });
1702
1987
  }
@@ -1718,13 +2003,9 @@ class JobList extends React.Component {
1718
2003
  userFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1719
2004
  className: "marginRight-10",
1720
2005
  onClick: () => {
1721
- this.openFilter('user');
1722
- },
1723
- rightIcon: "close",
1724
- rightClick: e => {
1725
- e.stopPropagation();
1726
2006
  this.removeUserFilter();
1727
2007
  },
2008
+ rightIcon: "close",
1728
2009
  text: this.state.selectedUserFilterText
1729
2010
  });
1730
2011
  }
@@ -1732,13 +2013,9 @@ class JobList extends React.Component {
1732
2013
  requesterFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1733
2014
  className: "marginRight-10",
1734
2015
  onClick: () => {
1735
- this.openFilter('requester');
1736
- },
1737
- rightIcon: "close",
1738
- rightClick: e => {
1739
- e.stopPropagation();
1740
2016
  this.removeRequesterFilter();
1741
2017
  },
2018
+ rightIcon: "close",
1742
2019
  text: this.state.selectedRequesterFilterText
1743
2020
  });
1744
2021
  }
@@ -1816,7 +2093,7 @@ class JobTypes extends React.Component {
1816
2093
  super(props);
1817
2094
  _defineProperty__default["default"](this, "getJobTypes", async () => {
1818
2095
  try {
1819
- const res = await maintenanceActions.getJobTypes(this.props.auth.site);
2096
+ const res = await maintenanceActions$1.getJobTypes(this.props.auth.site);
1820
2097
  if (res.data != null) this.props.jobTypesLoaded(res.data);
1821
2098
  } catch (error) {
1822
2099
  console.error('getJobTypes', error);
@@ -1841,7 +2118,7 @@ class JobTypes extends React.Component {
1841
2118
  _defineProperty__default["default"](this, "onRemoveJobType", async ev => {
1842
2119
  if (!window.confirm("Are you sure you want to delete ".concat(ev.typeName, "?"))) return;
1843
2120
  try {
1844
- await maintenanceActions.deleteJobType(this.props.auth.site, ev.id);
2121
+ await maintenanceActions$1.deleteJobType(this.props.auth.site, ev.id);
1845
2122
  const index = ___default["default"].findIndex(this.state.jobList, job => {
1846
2123
  return job != null && job.id === ev.id;
1847
2124
  });
@@ -2046,12 +2323,12 @@ var JobTypes$1 = reactRedux.connect(mapStateToProps$6, {
2046
2323
  jobTypesUpdate
2047
2324
  })(reactRouter.withRouter(JobTypes));
2048
2325
 
2049
- function ownKeys$6(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2050
- function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$6(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$6(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2326
+ function ownKeys$5(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2327
+ function _objectSpread$5(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$5(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$5(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2051
2328
  const {
2052
2329
  Session: Session$5,
2053
2330
  Components: Components$5,
2054
- Colours: Colours$3
2331
+ Colours: Colours$2
2055
2332
  } = PlussCore__namespace;
2056
2333
  class Configuration extends React.Component {
2057
2334
  constructor(props) {
@@ -2242,43 +2519,43 @@ class Configuration extends React.Component {
2242
2519
  return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("p", {
2243
2520
  className: "fontMedium fontSize-36 text-dark"
2244
2521
  }, "Statuses"), /*#__PURE__*/React__default["default"].createElement("div", {
2245
- style: styles$6.statusCategoryHeading
2522
+ style: styles$5.statusCategoryHeading
2246
2523
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2247
2524
  className: "fontMedium fontSize-16 text-bold"
2248
2525
  }, "Status Category")), statusTypes.map((status, index) => {
2249
2526
  return /*#__PURE__*/React__default["default"].createElement("div", {
2250
2527
  key: "".concat(status.text, "_").concat(index),
2251
- style: styles$6.statusTypeContainer
2528
+ style: styles$5.statusTypeContainer
2252
2529
  }, /*#__PURE__*/React__default["default"].createElement("div", {
2253
2530
  key: status.text,
2254
2531
  className: "statusLabel",
2255
- style: _objectSpread$6(_objectSpread$6({}, styles$6.statusTextContainer), {}, {
2532
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusTextContainer), {}, {
2256
2533
  backgroundColor: status.color
2257
2534
  })
2258
2535
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2259
2536
  className: "statusLabel_text"
2260
2537
  }, status.text)), /*#__PURE__*/React__default["default"].createElement("div", {
2261
- style: styles$6.statusCategoryContainer
2538
+ style: styles$5.statusCategoryContainer
2262
2539
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2263
2540
  className: "fontMedium fontSize-16 text-dark"
2264
2541
  }, status.category)), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2265
- style: _objectSpread$6(_objectSpread$6({}, styles$6.statusIcon), {}, {
2542
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusIcon), {}, {
2266
2543
  visibility: index === 0 ? 'hidden' : 'visible'
2267
2544
  }),
2268
2545
  name: 'arrow-up',
2269
2546
  onClick: () => this.onMoveStatus(index, true)
2270
2547
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2271
- style: _objectSpread$6(_objectSpread$6({}, styles$6.statusIcon), {}, {
2548
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusIcon), {}, {
2272
2549
  visibility: index === statusTypes.length - 1 ? 'hidden' : 'visible'
2273
2550
  }),
2274
2551
  name: 'arrow-down',
2275
2552
  onClick: () => this.onMoveStatus(index, false)
2276
2553
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2277
- style: _objectSpread$6({}, styles$6.statusIcon),
2554
+ style: _objectSpread$5({}, styles$5.statusIcon),
2278
2555
  name: "pencil",
2279
2556
  onClick: () => this.onEditStatus(index)
2280
2557
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2281
- style: _objectSpread$6({}, styles$6.statusIcon),
2558
+ style: _objectSpread$5({}, styles$5.statusIcon),
2282
2559
  name: "minus-circle",
2283
2560
  onClick: () => this.onDeleteStatus(index)
2284
2561
  }));
@@ -2327,8 +2604,8 @@ class Configuration extends React.Component {
2327
2604
  renderSuccess() {
2328
2605
  if (!this.state.success) return null;
2329
2606
  return /*#__PURE__*/React__default["default"].createElement("span", {
2330
- style: _objectSpread$6(_objectSpread$6({}, styles$6.savedText), {}, {
2331
- color: Colours$3.COLOUR_GREEN
2607
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.savedText), {}, {
2608
+ color: Colours$2.COLOUR_GREEN
2332
2609
  })
2333
2610
  }, "Saved");
2334
2611
  }
@@ -2444,7 +2721,7 @@ class Configuration extends React.Component {
2444
2721
  }, this.renderSubmit(), this.renderSuccess()), this.renderNewStatusPopup());
2445
2722
  }
2446
2723
  }
2447
- const styles$6 = {
2724
+ const styles$5 = {
2448
2725
  statusCategoryHeading: {
2449
2726
  marginLeft: 130,
2450
2727
  width: 160,
@@ -2469,7 +2746,7 @@ const styles$6 = {
2469
2746
  fontSize: 20,
2470
2747
  padding: 5,
2471
2748
  marginLeft: 10,
2472
- color: Colours$3.COLOUR_BRANDING_ACTION,
2749
+ color: Colours$2.COLOUR_BRANDING_ACTION,
2473
2750
  visibility: 'visible'
2474
2751
  },
2475
2752
  savedText: {
@@ -2503,52 +2780,6 @@ const {
2503
2780
  class RequestsHub extends React.Component {
2504
2781
  constructor(props) {
2505
2782
  super(props);
2506
- _defineProperty__default["default"](this, "setData", () => {
2507
- const allList = [];
2508
- this.state.allList.forEach(ev => {
2509
- if (ev != null && !ev.Deleted) allList.push(ev);
2510
- });
2511
- const upcoming = ___default["default"].filter(allList, ev => {
2512
- if (!ev) return false;
2513
- if (ev.status && ev.status === 'Completed') return false;
2514
- return true;
2515
- });
2516
- const completed = ___default["default"].filter(allList, ev => {
2517
- if (!ev) return false;
2518
- if (ev.status && ev.status === 'Completed') return true;
2519
- return false;
2520
- });
2521
-
2522
- // console.log('setData', upcoming, completed);
2523
- this.setState({
2524
- allList,
2525
- upcoming,
2526
- completed
2527
- });
2528
- });
2529
- _defineProperty__default["default"](this, "getData", () => {
2530
- const {
2531
- auth
2532
- } = this.props;
2533
- this.setState({
2534
- loadingAll: true
2535
- }, async () => {
2536
- try {
2537
- const res = await maintenanceActions.getJobsRecursive(auth.site);
2538
- this.setState({
2539
- loadingAll: false
2540
- });
2541
- if (!___default["default"].isEmpty(res) && res[0].site === auth.site) {
2542
- this.props.jobsLoaded(res);
2543
- }
2544
- } catch (error) {
2545
- console.error('getData', error);
2546
- this.setState({
2547
- loadingAll: false
2548
- });
2549
- }
2550
- });
2551
- });
2552
2783
  _defineProperty__default["default"](this, "onAddNew", () => {
2553
2784
  const {
2554
2785
  auth
@@ -2575,38 +2806,10 @@ class RequestsHub extends React.Component {
2575
2806
  _defineProperty__default["default"](this, "getSideBarSectionColour", id => this.state.selectedSection === id ? {
2576
2807
  backgroundColor: '#fff'
2577
2808
  } : {});
2578
- _defineProperty__default["default"](this, "renderStats", (stat, loading) => loading ? /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2579
- style: styles$5.spinner,
2580
- name: "spinner fa-pulse fa-fw"
2581
- }) : stat);
2582
2809
  this.state = {
2583
- selectedSection: 'all',
2584
- location: '',
2585
- loadingAll: false,
2586
- loadingSubmissions: false,
2587
- submissionEntries: [],
2588
- allList: [],
2589
- completed: [],
2590
- upcoming: [],
2591
- now: moment__default["default"].utc(),
2592
- onlyFuture: true,
2593
- search: ''
2810
+ selectedSection: 'all'
2594
2811
  };
2595
2812
  }
2596
- UNSAFE_componentWillMount() {
2597
- this.updateProps(this.props);
2598
- }
2599
- componentDidMount() {
2600
- this.getData();
2601
- }
2602
- UNSAFE_componentWillReceiveProps(nextProps) {
2603
- if (!___default["default"].isEqual(this.props.jobs, nextProps.jobs)) this.updateProps(nextProps);
2604
- }
2605
- updateProps(props) {
2606
- this.setState({
2607
- allList: props.jobs
2608
- }, this.setData);
2609
- }
2610
2813
  renderLeftBar() {
2611
2814
  const sectionItems = [];
2612
2815
  if (this.canAddNew()) {
@@ -2676,9 +2879,7 @@ class RequestsHub extends React.Component {
2676
2879
  } else if (this.state.selectedSection === 'config') {
2677
2880
  return /*#__PURE__*/React__default["default"].createElement(Configuration$1, null);
2678
2881
  }
2679
- return /*#__PURE__*/React__default["default"].createElement(JobList$1, {
2680
- source: this.state.allList
2681
- });
2882
+ return /*#__PURE__*/React__default["default"].createElement(JobList$1, null);
2682
2883
  }
2683
2884
  render() {
2684
2885
  return /*#__PURE__*/React__default["default"].createElement("div", {
@@ -2690,50 +2891,24 @@ class RequestsHub extends React.Component {
2690
2891
  }, this.renderRight())));
2691
2892
  }
2692
2893
  }
2693
- const styles$5 = {
2694
- sideBarTitleSection: {
2695
- lineHeight: '40px',
2696
- marginTop: 30,
2697
- marginBottom: 30,
2698
- paddingLeft: 24,
2699
- paddingRight: 24
2700
- },
2701
- sideBarSection: {
2702
- weight: '100%',
2703
- minWidth: 200,
2704
- padding: 32,
2705
- paddingLeft: 24,
2706
- cursor: 'pointer',
2707
- display: 'flex',
2708
- flexDirection: 'column',
2709
- justifyContent: 'center'
2710
- },
2711
- spinner: {
2712
- fontSize: 32,
2713
- color: FeatureConfig.env.colourBrandingOff
2714
- }
2715
- };
2716
2894
  const mapStateToProps$4 = state => {
2717
2895
  const {
2718
2896
  auth
2719
2897
  } = state;
2720
2898
  return {
2721
- jobs: state[values.reducerKey].jobs,
2722
2899
  auth,
2723
2900
  strings: state.strings && state.strings.config || {}
2724
2901
  };
2725
2902
  };
2726
- var RequestsHub$1 = reactRedux.connect(mapStateToProps$4, {
2727
- jobsLoaded
2728
- })(reactRouter.withRouter(RequestsHub));
2903
+ var RequestsHub$1 = reactRedux.connect(mapStateToProps$4)(reactRouter.withRouter(RequestsHub));
2729
2904
 
2730
- function ownKeys$5(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2731
- function _objectSpread$5(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$5(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$5(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2905
+ function ownKeys$4(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2906
+ function _objectSpread$4(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$4(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$4(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2732
2907
  const {
2733
2908
  Apis: Apis$1,
2734
- Helper: Helper$3,
2909
+ Helper: Helper$2,
2735
2910
  Session: Session$3,
2736
- Colours: Colours$2,
2911
+ Colours: Colours$1,
2737
2912
  Components: Components$3
2738
2913
  } = PlussCore__namespace;
2739
2914
  const IMAGE_SIZE_NOTE = 72;
@@ -2742,7 +2917,7 @@ class Job extends React.Component {
2742
2917
  super(props);
2743
2918
  _defineProperty__default["default"](this, "getJob", async () => {
2744
2919
  try {
2745
- const res = await maintenanceActions.getJob(this.props.auth.site, this.state.jobId);
2920
+ const res = await maintenanceActions$1.getJob(this.props.auth.site, this.state.jobId);
2746
2921
  this.setState({
2747
2922
  updating: false
2748
2923
  });
@@ -2754,7 +2929,7 @@ class Job extends React.Component {
2754
2929
  });
2755
2930
  _defineProperty__default["default"](this, "getAssignees", async () => {
2756
2931
  try {
2757
- const res = await maintenanceActions.getAssignees(this.props.auth.site);
2932
+ const res = await maintenanceActions$1.getAssignees(this.props.auth.site);
2758
2933
  this.setState({
2759
2934
  assignees: res.data.Users
2760
2935
  });
@@ -2767,7 +2942,7 @@ class Job extends React.Component {
2767
2942
  this.setState({
2768
2943
  loadingExternalSync: true
2769
2944
  });
2770
- const res = await maintenanceActions.getExternalSync(this.state.jobId);
2945
+ const res = await maintenanceActions$1.getExternalSync(this.state.jobId);
2771
2946
  this.setState({
2772
2947
  externalSync: res.data,
2773
2948
  loadingExternalSync: false
@@ -2792,7 +2967,7 @@ class Job extends React.Component {
2792
2967
  retrySyncError: null
2793
2968
  });
2794
2969
  try {
2795
- await maintenanceActions.retrySync(job.id);
2970
+ await maintenanceActions$1.retrySync(job.id);
2796
2971
  // Refresh job data to get updated history
2797
2972
  await this.getJob();
2798
2973
  this.setState({
@@ -2815,7 +2990,7 @@ class Job extends React.Component {
2815
2990
  let statusType = statusTypes.find(s => s.text === status);
2816
2991
  if (!statusType) {
2817
2992
  const defaultStatus = statusTypes.find(s => s.category === STATUS_NOT_ACTIONED);
2818
- statusType = _objectSpread$5(_objectSpread$5({}, defaultStatus), {}, {
2993
+ statusType = _objectSpread$4(_objectSpread$4({}, defaultStatus), {}, {
2819
2994
  text: status
2820
2995
  });
2821
2996
  }
@@ -2958,7 +3133,7 @@ class Job extends React.Component {
2958
3133
  // Method to handle user assignment
2959
3134
  _defineProperty__default["default"](this, "onAssignUser", async userId => {
2960
3135
  try {
2961
- const res = await maintenanceActions.assignJob(this.state.jobId, userId);
3136
+ const res = await maintenanceActions$1.assignJob(this.state.jobId, userId);
2962
3137
  this.getJob();
2963
3138
  } catch (err) {
2964
3139
  console.error("onAssignUser", err);
@@ -2970,12 +3145,12 @@ class Job extends React.Component {
2970
3145
  this.setState({
2971
3146
  submittingNote: true
2972
3147
  });
2973
- const res = await (this.state.editingNote ? maintenanceActions.editNote(this.state.jobId, this.state.editingNote, this.state.noteInput, this.state.noteAttachments.map(a => {
3148
+ const res = await (this.state.editingNote ? maintenanceActions$1.editNote(this.state.jobId, this.state.editingNote, this.state.noteInput, this.state.noteAttachments.map(a => {
2974
3149
  return {
2975
3150
  Title: a.Title,
2976
3151
  Source: a.Source
2977
3152
  };
2978
- }), this.state.noteImages) : maintenanceActions.addNote(this.state.jobId, this.state.noteInput, this.state.noteAttachments.map(a => {
3153
+ }), this.state.noteImages) : maintenanceActions$1.addNote(this.state.jobId, this.state.noteInput, this.state.noteAttachments.map(a => {
2979
3154
  return {
2980
3155
  Title: a.Title,
2981
3156
  Source: a.Source
@@ -3003,9 +3178,9 @@ class Job extends React.Component {
3003
3178
  });
3004
3179
  return;
3005
3180
  }
3006
- maintenanceActions.deleteNote(this.state.jobId, n.Id);
3181
+ maintenanceActions$1.deleteNote(this.state.jobId, n.Id);
3007
3182
  const newNotes = ___default["default"].filter(this.state.job.Notes, note => note.Id !== n.Id);
3008
- const newJob = _objectSpread$5({}, this.state.job);
3183
+ const newJob = _objectSpread$4({}, this.state.job);
3009
3184
  newJob.Notes = newNotes;
3010
3185
  this.setState({
3011
3186
  job: newJob,
@@ -3041,7 +3216,7 @@ class Job extends React.Component {
3041
3216
  seen: true,
3042
3217
  status: job.status || "Unassigned"
3043
3218
  };
3044
- await maintenanceActions.editJob(update, auth.site);
3219
+ await maintenanceActions$1.editJob(update, auth.site);
3045
3220
  } catch (error) {
3046
3221
  this.setState({
3047
3222
  updating: false
@@ -3089,13 +3264,13 @@ class Job extends React.Component {
3089
3264
  });
3090
3265
  _defineProperty__default["default"](this, "onSelectPriority", async priority => {
3091
3266
  this.setState({
3092
- job: _objectSpread$5(_objectSpread$5({}, this.state.job), {}, {
3267
+ job: _objectSpread$4(_objectSpread$4({}, this.state.job), {}, {
3093
3268
  priority
3094
3269
  }),
3095
3270
  priorityChangerOpen: false
3096
3271
  });
3097
3272
  try {
3098
- const res = await maintenanceActions.editJobPriority(this.state.job.id, priority);
3273
+ const res = await maintenanceActions$1.editJobPriority(this.state.job.id, priority);
3099
3274
  const {
3100
3275
  job
3101
3276
  } = res.data;
@@ -3114,13 +3289,13 @@ class Job extends React.Component {
3114
3289
  });
3115
3290
  _defineProperty__default["default"](this, "onSelectStatus", async status => {
3116
3291
  this.setState({
3117
- job: _objectSpread$5(_objectSpread$5({}, this.state.job), {}, {
3292
+ job: _objectSpread$4(_objectSpread$4({}, this.state.job), {}, {
3118
3293
  status: status
3119
3294
  }),
3120
3295
  statusChangerOpen: false
3121
3296
  });
3122
3297
  try {
3123
- const res = await maintenanceActions.editJobStatus(this.state.job.id, status);
3298
+ const res = await maintenanceActions$1.editJobStatus(this.state.job.id, status);
3124
3299
  const {
3125
3300
  job
3126
3301
  } = res.data;
@@ -3133,7 +3308,7 @@ class Job extends React.Component {
3133
3308
  }
3134
3309
  });
3135
3310
  this.state = {
3136
- jobId: Helper$3.safeReadParams(props, "jobId") ? props.match.params.jobId : null,
3311
+ jobId: Helper$2.safeReadParams(props, "jobId") ? props.match.params.jobId : null,
3137
3312
  job: null,
3138
3313
  showingSelector: false,
3139
3314
  updating: false,
@@ -3336,7 +3511,7 @@ class Job extends React.Component {
3336
3511
  }, /*#__PURE__*/React__default["default"].createElement("div", {
3337
3512
  className: "imageGrid_image",
3338
3513
  style: {
3339
- backgroundImage: "url('".concat(Helper$3.get1400(image), "')"),
3514
+ backgroundImage: "url('".concat(Helper$2.get1400(image), "')"),
3340
3515
  width: size,
3341
3516
  height: size
3342
3517
  }
@@ -3533,7 +3708,7 @@ class Job extends React.Component {
3533
3708
  }, /*#__PURE__*/React__default["default"].createElement("div", {
3534
3709
  className: "maintenanceNote_top"
3535
3710
  }, this.props.auth && this.props.auth.user && this.props.auth.user.Id === note.User.id && /*#__PURE__*/React__default["default"].createElement(Components$3.SVGIcon, {
3536
- colour: Colours$2.COLOUR_DUSK_LIGHT,
3711
+ colour: Colours$1.COLOUR_DUSK_LIGHT,
3537
3712
  icon: "more15",
3538
3713
  className: "maintenanceNote_moreIcon",
3539
3714
  onClick: () => this.onOpenNoteMenu(index)
@@ -3551,7 +3726,7 @@ class Job extends React.Component {
3551
3726
  }]
3552
3727
  })), /*#__PURE__*/React__default["default"].createElement("p", {
3553
3728
  className: "maintenanceNote_text"
3554
- }, Helper$3.toParagraphed(note.Note)), note.Attachments.map((a, i) => this.renderAttachment(a, i)), note.Images && note.Images.length > 0 ? this.renderImageGrid(note.Images, IMAGE_SIZE_NOTE) : null));
3729
+ }, Helper$2.toParagraphed(note.Note)), note.Attachments.map((a, i) => this.renderAttachment(a, i)), note.Images && note.Images.length > 0 ? this.renderImageGrid(note.Images, IMAGE_SIZE_NOTE) : null));
3555
3730
  }
3556
3731
  renderAssignment() {
3557
3732
  const {
@@ -3584,7 +3759,7 @@ class Job extends React.Component {
3584
3759
  }, moment__default["default"].utc(e.timestamp).local().format("D MMM YYYY h:mma")), /*#__PURE__*/React__default["default"].createElement("div", {
3585
3760
  className: "statusLabel statusLabel-large statusLabel-full",
3586
3761
  style: {
3587
- backgroundColor: Colours$2.COLOUR_DUSK
3762
+ backgroundColor: Colours$1.COLOUR_DUSK
3588
3763
  }
3589
3764
  }, /*#__PURE__*/React__default["default"].createElement("span", {
3590
3765
  className: "statusLabel_text"
@@ -3592,7 +3767,7 @@ class Job extends React.Component {
3592
3767
  }
3593
3768
  renderExternalSyncEntry(e, i) {
3594
3769
  const isSuccess = e.EntryType === "ExternalIDSet";
3595
- const backgroundColor = isSuccess ? Colours$2.COLOUR_GREEN : Colours$2.COLOUR_RED; // Green for success, red for failure
3770
+ const backgroundColor = isSuccess ? Colours$1.COLOUR_GREEN : Colours$1.COLOUR_RED; // Green for success, red for failure
3596
3771
 
3597
3772
  return /*#__PURE__*/React__default["default"].createElement("div", {
3598
3773
  className: "ticketHistoryEntry",
@@ -3652,7 +3827,7 @@ class Job extends React.Component {
3652
3827
  return /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
3653
3828
  style: {
3654
3829
  fontSize: 20,
3655
- color: Colours$2.COLOUR_DUSK_LIGHT,
3830
+ color: Colours$1.COLOUR_DUSK_LIGHT,
3656
3831
  marginLeft: 8
3657
3832
  },
3658
3833
  name: "spinner fa-pulse fa-fw"
@@ -3662,7 +3837,7 @@ class Job extends React.Component {
3662
3837
  className: "statusLabel pointer",
3663
3838
  onClick: this.onRetrySync,
3664
3839
  style: {
3665
- backgroundColor: Colours$2.COLOUR_RED,
3840
+ backgroundColor: Colours$1.COLOUR_RED,
3666
3841
  marginLeft: 8
3667
3842
  }
3668
3843
  }, /*#__PURE__*/React__default["default"].createElement("span", {
@@ -3683,7 +3858,7 @@ class Job extends React.Component {
3683
3858
  className: "userStatusIcon",
3684
3859
  name: "times-circle",
3685
3860
  style: {
3686
- color: Colours$2.COLOUR_RED
3861
+ color: Colours$1.COLOUR_RED
3687
3862
  }
3688
3863
  }), " ", retrySyncError);
3689
3864
  }
@@ -3696,7 +3871,7 @@ class Job extends React.Component {
3696
3871
  className: "userStatusIcon",
3697
3872
  name: "check-circle",
3698
3873
  style: {
3699
- color: Colours$2.COLOUR_GREEN
3874
+ color: Colours$1.COLOUR_GREEN
3700
3875
  }
3701
3876
  }), " ", "Sync retry initiated. Check back shortly for results.");
3702
3877
  }
@@ -3709,7 +3884,7 @@ class Job extends React.Component {
3709
3884
  className: "userStatusIcon",
3710
3885
  name: "times-circle",
3711
3886
  style: {
3712
- color: Colours$2.COLOUR_RED
3887
+ color: Colours$1.COLOUR_RED
3713
3888
  }
3714
3889
  }), " ", "External sync failed. Use the retry button to attempt again.");
3715
3890
  }
@@ -3753,11 +3928,11 @@ class Job extends React.Component {
3753
3928
  } = this.state;
3754
3929
  if (!job || !job.history) return null;
3755
3930
  const source = ___default["default"].sortBy([...job.history.map(e => {
3756
- return _objectSpread$5(_objectSpread$5({}, e), {}, {
3931
+ return _objectSpread$4(_objectSpread$4({}, e), {}, {
3757
3932
  EntryType: e.EntryType || "status"
3758
3933
  });
3759
3934
  }), ...(job.Notes || []).map(e => {
3760
- return _objectSpread$5(_objectSpread$5({}, e), {}, {
3935
+ return _objectSpread$4(_objectSpread$4({}, e), {}, {
3761
3936
  timestamp: e.Timestamp,
3762
3937
  EntryType: "note"
3763
3938
  });
@@ -3906,7 +4081,7 @@ class Job extends React.Component {
3906
4081
  onClick: () => {
3907
4082
  this.onSelectAssignee();
3908
4083
  },
3909
- colour: Colours$2.COLOUR_DUSK
4084
+ colour: Colours$1.COLOUR_DUSK
3910
4085
  })
3911
4086
  }));
3912
4087
  } else {
@@ -3980,14 +4155,14 @@ var Job$1 = reactRedux.connect(mapStateToProps$3, {
3980
4155
  jobStatusesUpdate
3981
4156
  })(reactRouter.withRouter(Job));
3982
4157
 
3983
- function ownKeys$4(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3984
- function _objectSpread$4(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$4(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$4(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4158
+ function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4159
+ function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3985
4160
  const {
3986
4161
  Actions,
3987
4162
  Components: Components$2,
3988
- Helper: Helper$2,
4163
+ Helper: Helper$1,
3989
4164
  Session: Session$2,
3990
- Colours: Colours$1,
4165
+ Colours,
3991
4166
  Apis
3992
4167
  } = PlussCore__namespace;
3993
4168
  class AddJob extends React.Component {
@@ -3997,7 +4172,7 @@ class AddJob extends React.Component {
3997
4172
  _this = this;
3998
4173
  _defineProperty__default["default"](this, "getJob", async () => {
3999
4174
  try {
4000
- const res = await maintenanceActions.getJob(this.props.auth.site, this.state.jobId);
4175
+ const res = await maintenanceActions$1.getJob(this.props.auth.site, this.state.jobId);
4001
4176
  res.data.location = res.data.site;
4002
4177
  const {
4003
4178
  userID,
@@ -4006,7 +4181,7 @@ class AddJob extends React.Component {
4006
4181
  type,
4007
4182
  customFields
4008
4183
  } = res.data;
4009
- this.setState(_objectSpread$4(_objectSpread$4({}, res.data), {}, {
4184
+ this.setState(_objectSpread$3(_objectSpread$3({}, res.data), {}, {
4010
4185
  prevType: type,
4011
4186
  prevCustomFileds: customFields,
4012
4187
  type,
@@ -4031,7 +4206,7 @@ class AddJob extends React.Component {
4031
4206
  });
4032
4207
  _defineProperty__default["default"](this, "getJobTypes", async () => {
4033
4208
  try {
4034
- const res = await maintenanceActions.getJobTypes(this.props.auth.site);
4209
+ const res = await maintenanceActions$1.getJobTypes(this.props.auth.site);
4035
4210
  this.setState({
4036
4211
  types: res.data
4037
4212
  });
@@ -4254,7 +4429,7 @@ class AddJob extends React.Component {
4254
4429
  event.target.value = "";
4255
4430
  });
4256
4431
  _defineProperty__default["default"](this, "onToggleDatePicker", qId => {
4257
- const showDate = _objectSpread$4({}, this.state.showDate);
4432
+ const showDate = _objectSpread$3({}, this.state.showDate);
4258
4433
  showDate[qId] = !showDate[qId];
4259
4434
  this.setState({
4260
4435
  showDate
@@ -4291,7 +4466,7 @@ class AddJob extends React.Component {
4291
4466
  customFields: this.state.customFields
4292
4467
  };
4293
4468
  if (this.state.id != null) {
4294
- maintenanceActions.editJob(job, this.props.auth.site).then(res => {
4469
+ maintenanceActions$1.editJob(job, this.props.auth.site).then(res => {
4295
4470
  this.setState({
4296
4471
  success: true,
4297
4472
  updating: false
@@ -4305,12 +4480,12 @@ class AddJob extends React.Component {
4305
4480
  });
4306
4481
  } else {
4307
4482
  // Create New Job
4308
- maintenanceActions.createJob(job).then(res => {
4483
+ maintenanceActions$1.createJob(job).then(res => {
4309
4484
  this.setState({
4310
4485
  success: true,
4311
4486
  updating: false
4312
4487
  });
4313
- this.props.jobsUpdate(this.props.auth.site);
4488
+ // JobList fetches fresh data on mount — no action needed here
4314
4489
  }).catch(res => {
4315
4490
  this.setState({
4316
4491
  updating: false
@@ -4343,7 +4518,7 @@ class AddJob extends React.Component {
4343
4518
  if (___default["default"].isNil(answer) || ___default["default"].isEmpty(answer)) return true;
4344
4519
  switch (type) {
4345
4520
  case "email":
4346
- return Helper$2.isEmail(answer);
4521
+ return Helper$1.isEmail(answer);
4347
4522
  case "date":
4348
4523
  return moment__default["default"](answer, "YYYY-MM-DD", true).isValid();
4349
4524
  case "time":
@@ -4364,7 +4539,7 @@ class AddJob extends React.Component {
4364
4539
  this.customImageInputs = {};
4365
4540
  this.customDocumentInputs = {};
4366
4541
  this.state = {
4367
- jobId: Helper$2.safeReadParams(this.props, "jobId") ? this.props.match.params.jobId : null,
4542
+ jobId: Helper$1.safeReadParams(this.props, "jobId") ? this.props.match.params.jobId : null,
4368
4543
  job: null,
4369
4544
  showingSelector: false,
4370
4545
  updating: false,
@@ -4716,7 +4891,7 @@ class AddJob extends React.Component {
4716
4891
  return /*#__PURE__*/React__default["default"].createElement("p", {
4717
4892
  className: "visitorSignIn_text-staticText",
4718
4893
  key: fieldId
4719
- }, Helper$2.toParagraphed(field.label, {
4894
+ }, Helper$1.toParagraphed(field.label, {
4720
4895
  marginTop: 10
4721
4896
  }));
4722
4897
  case "date":
@@ -4735,7 +4910,7 @@ class AddJob extends React.Component {
4735
4910
  alwaysShowLabel: true,
4736
4911
  readOnly: true,
4737
4912
  rightContent: !___default["default"].isEmpty(field.answer) && /*#__PURE__*/React__default["default"].createElement(Components$2.SVGIcon, {
4738
- colour: Colours$1.COLOUR_DUSK_LIGHT,
4913
+ colour: Colours.COLOUR_DUSK_LIGHT,
4739
4914
  icon: "close",
4740
4915
  className: "timepicker_clear",
4741
4916
  onClick: () => this.onChangeDateAnswer(fieldId, undefined, false)
@@ -4768,7 +4943,7 @@ class AddJob extends React.Component {
4768
4943
  }
4769
4944
  }),
4770
4945
  rightContent: !___default["default"].isEmpty(field.answer) && /*#__PURE__*/React__default["default"].createElement(Components$2.SVGIcon, {
4771
- colour: Colours$1.COLOUR_DUSK_LIGHT,
4946
+ colour: Colours.COLOUR_DUSK_LIGHT,
4772
4947
  icon: "close",
4773
4948
  className: "timepicker_clear",
4774
4949
  onClick: () => this.onChangeTimeAnswer(fieldId, undefined)
@@ -4971,11 +5146,10 @@ const mapStateToProps$2 = state => {
4971
5146
  return {
4972
5147
  auth,
4973
5148
  strings: state.strings && state.strings.config || {},
4974
- optionOnlyForResidents: Helper$2.getSiteSettingFromState(state, values.optionOnlyForResidents)
5149
+ optionOnlyForResidents: Helper$1.getSiteSettingFromState(state, values.optionOnlyForResidents)
4975
5150
  };
4976
5151
  };
4977
5152
  var AddJob$1 = reactRedux.connect(mapStateToProps$2, {
4978
- jobsUpdate,
4979
5153
  jobsLoaded,
4980
5154
  addRecentlyCreated: Actions.addRecentlyCreated
4981
5155
  })(reactRouter.withRouter(AddJob));
@@ -4983,7 +5157,7 @@ var AddJob$1 = reactRedux.connect(mapStateToProps$2, {
4983
5157
  const {
4984
5158
  Components: Components$1,
4985
5159
  Session: Session$1,
4986
- Helper: Helper$1
5160
+ Helper
4987
5161
  } = PlussCore__namespace;
4988
5162
  const DEFAULT_FIELD = {
4989
5163
  type: 'text',
@@ -4997,7 +5171,7 @@ class AddJobType extends React.Component {
4997
5171
  super(props);
4998
5172
  _defineProperty__default["default"](this, "getJobType", async () => {
4999
5173
  try {
5000
- const res = await maintenanceActions.getJobType(this.props.auth.site, this.state.jobTypeId);
5174
+ const res = await maintenanceActions$1.getJobType(this.props.auth.site, this.state.jobTypeId);
5001
5175
  const {
5002
5176
  typeName,
5003
5177
  email,
@@ -5026,7 +5200,7 @@ class AddJobType extends React.Component {
5026
5200
  const {
5027
5201
  jobTypeEmail
5028
5202
  } = this.state;
5029
- return !___default["default"].isEmpty(jobTypeEmail) && Helper$1.isEmail(jobTypeEmail);
5203
+ return !___default["default"].isEmpty(jobTypeEmail) && Helper.isEmail(jobTypeEmail);
5030
5204
  });
5031
5205
  _defineProperty__default["default"](this, "isJobTypeValid", () => {
5032
5206
  const {
@@ -5169,9 +5343,9 @@ class AddJobType extends React.Component {
5169
5343
  }, async () => {
5170
5344
  try {
5171
5345
  if (jobTypeId) {
5172
- await maintenanceActions.editJobType(site, jobTypeId, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5346
+ await maintenanceActions$1.editJobType(site, jobTypeId, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5173
5347
  } else {
5174
- await maintenanceActions.addJobType(site, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5348
+ await maintenanceActions$1.addJobType(site, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5175
5349
  }
5176
5350
  this.props.jobTypesUpdate(site);
5177
5351
  this.setState({
@@ -5228,7 +5402,7 @@ class AddJobType extends React.Component {
5228
5402
  }];
5229
5403
  this.state = {
5230
5404
  loading: false,
5231
- jobTypeId: Helper$1.safeReadParams(this.props, 'jobTypeId') ? this.props.match.params.jobTypeId : null,
5405
+ jobTypeId: Helper.safeReadParams(this.props, 'jobTypeId') ? this.props.match.params.jobTypeId : null,
5232
5406
  jobTypeName: '',
5233
5407
  jobTypeEmail: '',
5234
5408
  jobTypeDescription: '',
@@ -5793,14 +5967,10 @@ var AddJobType$1 = reactRedux.connect(mapStateToProps$1, {
5793
5967
  jobTypesUpdate
5794
5968
  })(reactRouter.withRouter(AddJobType));
5795
5969
 
5796
- function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5797
- function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5798
5970
  const {
5799
5971
  Analytics: Analytics$1,
5800
5972
  Session,
5801
- Components,
5802
- Helper,
5803
- Colours
5973
+ Components
5804
5974
  } = PlussCore__namespace;
5805
5975
  const getInitialState = () => ({
5806
5976
  requests: 0,
@@ -5820,21 +5990,10 @@ const AnalyticsHub = _ref => {
5820
5990
  auth,
5821
5991
  prevText,
5822
5992
  dayCount,
5823
- strings,
5824
- userType,
5825
- userCategory,
5826
- selectedSites
5993
+ strings
5827
5994
  } = _ref;
5828
5995
  const [analyticsData, setAnalyticsData] = React.useState(getInitialState());
5829
5996
  const [isExportOpen, setIsExportOpen] = React.useState(false);
5830
- const [failedSites, setFailedSites] = React.useState([]);
5831
- const [comparisonData, setComparisonData] = React.useState({
5832
- requests: [],
5833
- completedRequests: [],
5834
- comments: [],
5835
- isLoading: true
5836
- });
5837
- const comparisonMode = selectedSites && selectedSites.length > 1;
5838
5997
  const hasAccess = Session.validateAccess(auth.site, values.permissionMaintenanceTracking, auth);
5839
5998
  if (!hasAccess) {
5840
5999
  return null;
@@ -5846,130 +6005,50 @@ const AnalyticsHub = _ref => {
5846
6005
  return strings.sideNav[key];
5847
6006
  })();
5848
6007
  const exportColumns = [{
5849
- label: "Select All",
5850
- key: ""
5851
- }, ...(comparisonMode ? [{
5852
- label: "Site",
5853
- key: "site"
5854
- }] : []), {
5855
- label: "Start Date",
5856
- key: "startDate"
6008
+ label: 'Select All',
6009
+ key: ''
5857
6010
  }, {
5858
- label: "End Date",
5859
- key: "endDate"
6011
+ label: 'Start Date',
6012
+ key: 'startDate'
6013
+ }, {
6014
+ label: 'End Date',
6015
+ key: 'endDate'
5860
6016
  }, {
5861
6017
  label: "".concat(values.textSingularName, "s"),
5862
- key: "requests"
6018
+ key: 'requests'
5863
6019
  }, {
5864
6020
  label: "Completed ".concat(values.textSingularName, "s"),
5865
- key: "completedRequests"
6021
+ key: 'completedRequests'
5866
6022
  }, {
5867
- label: "Comments",
5868
- key: "comments"
6023
+ label: 'Comments',
6024
+ key: 'comments'
5869
6025
  }];
5870
6026
  React.useEffect(() => {
5871
6027
  getData();
5872
- }, [startTime, endTime, userType, userCategory, selectedSites]);
6028
+ }, [startTime, endTime]);
5873
6029
  const getData = async () => {
5874
- try {
5875
- setFailedSites([]);
5876
- if (comparisonMode) {
5877
- setComparisonData({
5878
- requests: [],
5879
- completedRequests: [],
5880
- comments: [],
5881
- isLoading: true
5882
- });
5883
- const multiSiteResultsObj = await Analytics$1.fetchMultiSiteData(selectedSites, async site => {
5884
- const {
5885
- data
5886
- } = await analyticsActions.getAggregateEntityStats(site, values.analyticsKey, startTime, endTime, true, {
5887
- userType,
5888
- userCategory
5889
- });
5890
- return data;
5891
- });
5892
- const roles = auth.user.Roles;
5893
- const failed = Object.entries(multiSiteResultsObj).filter(_ref2 => {
5894
- let [, data] = _ref2;
5895
- return data === null;
5896
- }).map(_ref3 => {
5897
- let [site] = _ref3;
5898
- return Helper.getSiteNameFromRoles(site, roles);
5899
- });
5900
- setFailedSites(failed);
5901
- const multiSiteResults = Object.entries(multiSiteResultsObj).filter(_ref4 => {
5902
- let [, data] = _ref4;
5903
- return data !== null;
5904
- }).map(_ref5 => {
5905
- let [site, data] = _ref5;
5906
- return {
5907
- site,
5908
- data
5909
- };
5910
- });
5911
- const buildComparison = (activityKey, countType) => multiSiteResults.map(result => ({
5912
- name: Helper.getSiteNameFromRoles(result.site, roles),
5913
- value: Analytics$1.countActivities(result.data, activityKey, countType)
5914
- }));
5915
- setComparisonData({
5916
- requests: buildComparison("Request", "total"),
5917
- completedRequests: buildComparison("RequestCompleted", "unique"),
5918
- comments: buildComparison("Comment", "total"),
5919
- isLoading: false
5920
- });
5921
- } else {
5922
- setAnalyticsData(getInitialState());
5923
- const site = selectedSites && selectedSites.length === 1 ? selectedSites[0] : auth.site;
5924
- const timeDifference = endTime - startTime;
5925
- const [currentStatsResponse, prevStatsResponse] = await Promise.all([analyticsActions.getAggregateEntityStats(site, values.analyticsKey, startTime, endTime, true, {
5926
- userType,
5927
- userCategory
5928
- }), analyticsActions.getAggregateEntityStats(site, values.analyticsKey, startTime - timeDifference, startTime, true, {
5929
- userType,
5930
- userCategory
5931
- })]);
5932
- const data = {
5933
- requests: Analytics$1.countActivities(currentStatsResponse.data, "Request", "total"),
5934
- prevRequests: Analytics$1.countActivities(prevStatsResponse.data, "Request", "total"),
5935
- completedRequests: Analytics$1.countActivities(currentStatsResponse.data, "RequestCompleted", "unique"),
5936
- prevCompletedRequests: Analytics$1.countActivities(prevStatsResponse.data, "RequestCompleted", "unique"),
5937
- comments: Analytics$1.countActivities(currentStatsResponse.data, "Comment", "total"),
5938
- prevComments: Analytics$1.countActivities(prevStatsResponse.data, "Comment", "total"),
5939
- isLoading: false
5940
- };
5941
- setAnalyticsData(data);
5942
- }
5943
- } catch (err) {
5944
- if (comparisonMode) {
5945
- setComparisonData(prev => _objectSpread$3(_objectSpread$3({}, prev), {}, {
5946
- isLoading: false
5947
- }));
5948
- } else {
5949
- setAnalyticsData(prev => _objectSpread$3(_objectSpread$3({}, prev), {}, {
5950
- isLoading: false
5951
- }));
5952
- }
5953
- }
6030
+ setAnalyticsData(getInitialState());
6031
+ // Load analytics data here using startTime and endTime
6032
+ const timeDifference = endTime - startTime;
6033
+ const [currentStatsResponse, prevStatsResponse] = await Promise.all([analyticsActions.getAggregateEntityStats(auth.site, values.analyticsKey, startTime, endTime, true), analyticsActions.getAggregateEntityStats(auth.site, values.analyticsKey, startTime - timeDifference, startTime, true)]);
6034
+ const data = {
6035
+ requests: Analytics$1.countActivities(currentStatsResponse.data, 'Request', 'total'),
6036
+ prevRequests: Analytics$1.countActivities(prevStatsResponse.data, 'Request', 'total'),
6037
+ completedRequests: Analytics$1.countActivities(currentStatsResponse.data, 'RequestCompleted', 'unique'),
6038
+ prevCompletedRequests: Analytics$1.countActivities(prevStatsResponse.data, 'RequestCompleted', 'unique'),
6039
+ comments: Analytics$1.countActivities(currentStatsResponse.data, 'Comment', 'total'),
6040
+ prevComments: Analytics$1.countActivities(prevStatsResponse.data, 'Comment', 'total'),
6041
+ isLoading: false
6042
+ };
6043
+ setAnalyticsData(data);
5954
6044
  };
5955
6045
  const isReadyToOpenCSV = () => {
5956
- return comparisonMode ? !comparisonData.isLoading : !analyticsData.isLoading;
6046
+ return !analyticsData.isLoading;
5957
6047
  };
5958
6048
  const getExportSource = () => {
5959
- if (comparisonMode) {
5960
- const sites = comparisonData.requests || [];
5961
- return sites.map((site, i) => ({
5962
- site: site.name,
5963
- startDate: moment__default["default"](startTime + 1).format("D-MM-YYYY"),
5964
- endDate: moment__default["default"](endTime).format("D-MM-YYYY"),
5965
- requests: site.value,
5966
- completedRequests: comparisonData.completedRequests[i] && comparisonData.completedRequests[i].value || 0,
5967
- comments: comparisonData.comments[i] && comparisonData.comments[i].value || 0
5968
- }));
5969
- }
5970
6049
  return [{
5971
- startDate: moment__default["default"](startTime + 1).format("D-MM-YYYY"),
5972
- endDate: moment__default["default"](endTime).format("D-MM-YYYY"),
6050
+ startDate: moment__default["default"](startTime + 1).format('D-MM-YYYY'),
6051
+ endDate: moment__default["default"](endTime).format('D-MM-YYYY'),
5973
6052
  requests: analyticsData.requests,
5974
6053
  completedRequests: analyticsData.completedRequests,
5975
6054
  comments: analyticsData.comments
@@ -5980,14 +6059,13 @@ const AnalyticsHub = _ref => {
5980
6059
  return null;
5981
6060
  }
5982
6061
  const source = getExportSource();
5983
- const filterSuffix = [userType, userCategory].filter(Boolean).map(f => f.toLowerCase().replace(/\s+/g, "-")).join("_");
5984
6062
  return /*#__PURE__*/React__default["default"].createElement(Components.ExportCsvPopup, {
5985
6063
  onClose: () => {
5986
6064
  setIsExportOpen(false);
5987
6065
  },
5988
6066
  columns: exportColumns,
5989
6067
  source: source,
5990
- filename: "".concat(values.analyticsKey, "analytics").concat(comparisonMode ? "_comparison" : "").concat(filterSuffix ? "_".concat(filterSuffix) : "", "_").concat(source[0].startDate, "_").concat(source[0].endDate, ".csv")
6068
+ filename: "".concat(values.analyticsKey, "analytics_").concat(source[0].startDate, "_").concat(source[0].endDate, ".csv")
5991
6069
  });
5992
6070
  };
5993
6071
  return /*#__PURE__*/React__default["default"].createElement("div", {
@@ -6004,69 +6082,33 @@ const AnalyticsHub = _ref => {
6004
6082
  },
6005
6083
  isActive: isReadyToOpenCSV(),
6006
6084
  leftIcon: "file-code-o"
6007
- }, "Export CSV")), failedSites.length > 0 && /*#__PURE__*/React__default["default"].createElement(Components.Text, {
6008
- type: "help",
6009
- style: {
6010
- color: Colours.COLOUR_RED,
6011
- marginTop: 8
6012
- }
6013
- }, "Data unavailable for: ", failedSites.join(", ")), /*#__PURE__*/React__default["default"].createElement("div", {
6085
+ }, "Export CSV")), /*#__PURE__*/React__default["default"].createElement("div", {
6014
6086
  className: "analyticsSection dashboardSection_content"
6015
- }, (() => {
6016
- const chartSuffix = [selectedSites && selectedSites.length > 0 ? "&sites=".concat(selectedSites.join(",")) : "", userType ? "&userType=".concat(encodeURIComponent(userType)) : "", userCategory ? "&userCategory=".concat(encodeURIComponent(userCategory)) : ""].join("");
6017
- if (comparisonMode) {
6018
- return /*#__PURE__*/React__default["default"].createElement("div", {
6019
- style: {
6020
- display: "flex",
6021
- flexDirection: "column",
6022
- gap: 16
6023
- }
6024
- }, /*#__PURE__*/React__default["default"].createElement(Components.ComparisonStatBox, {
6025
- title: "".concat(featureTitle, " Requests"),
6026
- data: comparisonData.requests,
6027
- prevText: prevText,
6028
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Request&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6029
- isLoading: comparisonData.isLoading
6030
- }), /*#__PURE__*/React__default["default"].createElement(Components.ComparisonStatBox, {
6031
- title: "Completed ".concat(featureTitle, " Requests"),
6032
- data: comparisonData.completedRequests,
6033
- prevText: prevText,
6034
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=RequestCompleted&countType=unique&dayCount=").concat(dayCount).concat(chartSuffix),
6035
- isLoading: comparisonData.isLoading
6036
- }), /*#__PURE__*/React__default["default"].createElement(Components.ComparisonStatBox, {
6037
- title: "".concat(featureTitle, " Comments"),
6038
- data: comparisonData.comments,
6039
- prevText: prevText,
6040
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Comment&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6041
- isLoading: comparisonData.isLoading
6042
- }));
6043
- }
6044
- return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6045
- title: "".concat(featureTitle, " Requests"),
6046
- icon: freeSolidSvgIcons.faWrench,
6047
- value: analyticsData.requests,
6048
- previousValue: analyticsData.prevRequests,
6049
- prevText: prevText,
6050
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Request&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6051
- isLoading: analyticsData.isLoading
6052
- }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6053
- title: "Completed ".concat(featureTitle, " Requests"),
6054
- icon: freeSolidSvgIcons.faCircleCheck,
6055
- value: analyticsData.completedRequests,
6056
- previousValue: analyticsData.prevCompletedRequests,
6057
- prevText: prevText,
6058
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=RequestCompleted&countType=unique&dayCount=").concat(dayCount).concat(chartSuffix),
6059
- isLoading: analyticsData.isLoading
6060
- }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6061
- title: "".concat(featureTitle, " Comments"),
6062
- icon: freeSolidSvgIcons.faComment,
6063
- value: analyticsData.comments,
6064
- previousValue: analyticsData.prevComments,
6065
- prevText: prevText,
6066
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Comment&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6067
- isLoading: analyticsData.isLoading
6068
- }));
6069
- })()));
6087
+ }, /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6088
+ title: "".concat(featureTitle, " Requests"),
6089
+ icon: freeSolidSvgIcons.faWrench,
6090
+ value: analyticsData.requests,
6091
+ previousValue: analyticsData.prevRequests,
6092
+ prevText: prevText,
6093
+ viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Request&countType=total&dayCount=").concat(dayCount),
6094
+ isLoading: analyticsData.isLoading
6095
+ }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6096
+ title: "Completed ".concat(featureTitle, " Requests"),
6097
+ icon: freeSolidSvgIcons.faCircleCheck,
6098
+ value: analyticsData.completedRequests,
6099
+ previousValue: analyticsData.prevCompletedRequests,
6100
+ prevText: prevText,
6101
+ viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=RequestCompleted&countType=unique&dayCount=").concat(dayCount),
6102
+ isLoading: analyticsData.isLoading
6103
+ }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6104
+ title: "".concat(featureTitle, " Comments"),
6105
+ icon: freeSolidSvgIcons.faComment,
6106
+ value: analyticsData.comments,
6107
+ previousValue: analyticsData.prevComments,
6108
+ prevText: prevText,
6109
+ viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Comment&countType=total&dayCount=").concat(dayCount),
6110
+ isLoading: analyticsData.isLoading
6111
+ })));
6070
6112
  };
6071
6113
  const mapStateToProps = state => {
6072
6114
  const {