@plusscommunities/pluss-maintenance-web-forms 1.1.37-beta.3 → 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 -571
  2. package/dist/index.esm.js +617 -573
  3. package/dist/index.js +6724 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.umd.js +616 -572
  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 -359
  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 -74
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: 'https://www.plusscommunities.com/forms-feature',
114
114
  stringConfigJobStatus: 'maintenanceJobStatusForms',
115
- stringConfigHideSeen: 'maintenanceDisableSeenForms'
115
+ stringConfigHideSeen: 'maintenanceDisableSeenForms',
116
+ // Comment subscription notification preference
117
+ notificationPreference: {
118
+ key: 'maintenancerequestFormsComments',
119
+ label: 'Forms comments',
120
+ permission: 'maintenanceTrackingForms'
121
+ }
116
122
  };
117
123
 
118
124
  // import * as PlussCore from '../../pluss-core/src';
@@ -235,7 +241,8 @@ const FeatureConfig = {
235
241
  init: environment => {
236
242
  FeatureConfig.env = environment;
237
243
  PlussCore__namespace.Config.init(environment);
238
- }
244
+ },
245
+ notificationPreference: values.notificationPreference
239
246
  };
240
247
 
241
248
  const JOBS_LOADED = values.actionJobsLoaded;
@@ -245,15 +252,15 @@ const JOBS_TYPES_LOADED = values.actionJobsTypesLoaded;
245
252
  const JOBS_STATUSES_LOADED = values.actionJobsStatusesLoaded;
246
253
  const JOBS_HIDE_SEEN = values.actionJobsHideSeen;
247
254
 
248
- 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; }
249
- 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; }
255
+ 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; }
256
+ 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; }
250
257
  const {
251
- Helper: Helper$6,
258
+ Helper: Helper$4,
252
259
  Session: Session$9
253
260
  } = PlussCore__namespace;
254
- const maintenanceActions = {
261
+ const maintenanceActions$1 = {
255
262
  getJobType: (site, typeId) => {
256
- let url = Helper$6.getUrl(values.serviceKey, 'getjobtype');
263
+ let url = Helper$4.getUrl(values.serviceKey, 'getjobtype');
257
264
  return Session$9.authedFunction({
258
265
  method: 'POST',
259
266
  url,
@@ -264,7 +271,7 @@ const maintenanceActions = {
264
271
  });
265
272
  },
266
273
  getJobTypes: (site, id) => {
267
- let url = Helper$6.getUrl(values.serviceKey, 'getjobtypes');
274
+ let url = Helper$4.getUrl(values.serviceKey, 'getjobtypes');
268
275
  return Session$9.authedFunction({
269
276
  method: 'POST',
270
277
  url,
@@ -274,7 +281,7 @@ const maintenanceActions = {
274
281
  });
275
282
  },
276
283
  getJob: (site, id) => {
277
- let url = Helper$6.getUrl(values.serviceKey, 'getJob');
284
+ let url = Helper$4.getUrl(values.serviceKey, 'getJob');
278
285
  return Session$9.authedFunction({
279
286
  method: 'POST',
280
287
  url,
@@ -285,7 +292,7 @@ const maintenanceActions = {
285
292
  });
286
293
  },
287
294
  getJobByJobId: (site, jobId) => {
288
- let url = Helper$6.getUrl(values.serviceKey, 'getJob');
295
+ let url = Helper$4.getUrl(values.serviceKey, 'getJob');
289
296
  return Session$9.authedFunction({
290
297
  method: 'POST',
291
298
  url,
@@ -300,7 +307,7 @@ const maintenanceActions = {
300
307
  let type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
301
308
  return Session$9.authedFunction({
302
309
  method: 'POST',
303
- url: Helper$6.getUrl(values.serviceKey, 'getJobs'),
310
+ url: Helper$4.getUrl(values.serviceKey, 'getJobs'),
304
311
  data: {
305
312
  site,
306
313
  status,
@@ -308,7 +315,7 @@ const maintenanceActions = {
308
315
  }
309
316
  });
310
317
  },
311
- getJobs2: (site, status, type, lastKey) => {
318
+ getJobs2: (site, status, type, priority, assignee, startTime, endTime, search, lastKey) => {
312
319
  const query = {
313
320
  site
314
321
  };
@@ -318,37 +325,57 @@ const maintenanceActions = {
318
325
  if (type) {
319
326
  query.type = type;
320
327
  }
328
+ if (priority) {
329
+ query.priority = priority;
330
+ }
331
+ if (assignee) {
332
+ query.assignee = assignee;
333
+ }
334
+ if (startTime) {
335
+ query.startTime = startTime;
336
+ }
337
+ if (endTime) {
338
+ query.endTime = endTime;
339
+ }
340
+ if (search) {
341
+ query.search = search;
342
+ }
321
343
  if (lastKey) {
322
344
  query.lastKey = JSON.stringify(lastKey);
323
345
  }
324
346
  return Session$9.authedFunction({
325
347
  method: 'GET',
326
- url: Helper$6.getUrl(values.serviceKey, 'get/requests', query)
348
+ url: Helper$4.getUrl(values.serviceKey, 'get/requests', query)
327
349
  });
328
350
  },
351
+ /**
352
+ * @deprecated Use getJobs2 with pagination instead.
353
+ * This method recursively fetches ALL pages which can be slow for large datasets.
354
+ * Only use for CSV export where all data is needed.
355
+ */
329
356
  getJobsRecursive: function (site, status, type, lastKey) {
330
357
  let jobs = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
331
- return new Promise(resolve => {
332
- maintenanceActions.getJobs2(site, status, type, lastKey).then(jobRes => {
358
+ return new Promise((resolve, reject) => {
359
+ maintenanceActions$1.getJobs2(site, status, type, undefined, undefined, undefined, undefined, undefined, lastKey).then(jobRes => {
333
360
  const newJobs = [...jobs, ...jobRes.data.Items];
334
361
  if (!jobRes.data.LastKey) {
335
362
  return resolve(newJobs);
336
363
  }
337
- return resolve(maintenanceActions.getJobsRecursive(site, status, type, jobRes.data.LastKey, newJobs));
338
- });
364
+ maintenanceActions$1.getJobsRecursive(site, status, type, jobRes.data.LastKey, newJobs).then(resolve).catch(reject);
365
+ }).catch(reject);
339
366
  });
340
367
  },
341
368
  createJob: job => {
342
369
  return Session$9.authedFunction({
343
370
  method: 'POST',
344
- url: Helper$6.getUrl(values.serviceKey, 'sendMaintenance'),
345
- data: _objectSpread$8({}, job)
371
+ url: Helper$4.getUrl(values.serviceKey, 'sendMaintenance'),
372
+ data: _objectSpread$7({}, job)
346
373
  });
347
374
  },
348
375
  editJob: (job, site) => {
349
376
  return Session$9.authedFunction({
350
377
  method: 'POST',
351
- url: Helper$6.getUrl(values.serviceKey, 'editJob'),
378
+ url: Helper$4.getUrl(values.serviceKey, 'editJob'),
352
379
  data: {
353
380
  job,
354
381
  site
@@ -358,7 +385,7 @@ const maintenanceActions = {
358
385
  deleteJob: (site, id) => {
359
386
  return Session$9.authedFunction({
360
387
  method: 'POST',
361
- url: Helper$6.getUrl(values.serviceKey, 'requests/remove'),
388
+ url: Helper$4.getUrl(values.serviceKey, 'requests/remove'),
362
389
  data: {
363
390
  site,
364
391
  id
@@ -368,7 +395,7 @@ const maintenanceActions = {
368
395
  editJobStatus: (id, status) => {
369
396
  return Session$9.authedFunction({
370
397
  method: 'POST',
371
- url: Helper$6.getUrl(values.serviceKey, 'editJobStatus'),
398
+ url: Helper$4.getUrl(values.serviceKey, 'editJobStatus'),
372
399
  data: {
373
400
  id,
374
401
  status
@@ -378,7 +405,7 @@ const maintenanceActions = {
378
405
  editJobPriority: (id, priority) => {
379
406
  return Session$9.authedFunction({
380
407
  method: 'POST',
381
- url: Helper$6.getUrl(values.serviceKey, 'update/priority'),
408
+ url: Helper$4.getUrl(values.serviceKey, 'update/priority'),
382
409
  data: {
383
410
  id,
384
411
  priority
@@ -388,7 +415,7 @@ const maintenanceActions = {
388
415
  assignJob: (jobId, userId) => {
389
416
  return Session$9.authedFunction({
390
417
  method: 'POST',
391
- url: Helper$6.getUrl(values.serviceKey, 'update/assign'),
418
+ url: Helper$4.getUrl(values.serviceKey, 'update/assign'),
392
419
  data: {
393
420
  id: jobId,
394
421
  userId
@@ -398,7 +425,7 @@ const maintenanceActions = {
398
425
  getAssignees: site => {
399
426
  return Session$9.authedFunction({
400
427
  method: 'GET',
401
- url: Helper$6.getUrl(values.serviceKey, 'get/assignees', {
428
+ url: Helper$4.getUrl(values.serviceKey, 'get/assignees', {
402
429
  site
403
430
  })
404
431
  });
@@ -406,7 +433,7 @@ const maintenanceActions = {
406
433
  addNote: (jobId, note, attachments, images) => {
407
434
  return Session$9.authedFunction({
408
435
  method: 'POST',
409
- url: Helper$6.getUrl(values.serviceKey, 'requests/note'),
436
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
410
437
  data: {
411
438
  id: jobId,
412
439
  note,
@@ -419,7 +446,7 @@ const maintenanceActions = {
419
446
  editNote: (jobId, noteId, note, attachments, images) => {
420
447
  return Session$9.authedFunction({
421
448
  method: 'POST',
422
- url: Helper$6.getUrl(values.serviceKey, 'requests/note'),
449
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
423
450
  data: {
424
451
  id: jobId,
425
452
  note,
@@ -433,7 +460,7 @@ const maintenanceActions = {
433
460
  deleteNote: (jobId, noteId) => {
434
461
  return Session$9.authedFunction({
435
462
  method: 'POST',
436
- url: Helper$6.getUrl(values.serviceKey, 'requests/note'),
463
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
437
464
  data: {
438
465
  id: jobId,
439
466
  noteId,
@@ -453,7 +480,7 @@ const maintenanceActions = {
453
480
  };
454
481
  return Session$9.authedFunction({
455
482
  method: 'POST',
456
- url: Helper$6.getUrl(values.serviceKey, 'createJobType'),
483
+ url: Helper$4.getUrl(values.serviceKey, 'createJobType'),
457
484
  data
458
485
  });
459
486
  },
@@ -471,14 +498,14 @@ const maintenanceActions = {
471
498
  if (hasCustomFields && customFields) data.customFields = customFields;
472
499
  return Session$9.authedFunction({
473
500
  method: 'POST',
474
- url: Helper$6.getUrl(values.serviceKey, 'editJobType'),
501
+ url: Helper$4.getUrl(values.serviceKey, 'editJobType'),
475
502
  data
476
503
  });
477
504
  },
478
505
  deleteJobType: (site, id) => {
479
506
  return Session$9.authedFunction({
480
507
  method: 'POST',
481
- url: Helper$6.getUrl(values.serviceKey, 'deleteJobType'),
508
+ url: Helper$4.getUrl(values.serviceKey, 'deleteJobType'),
482
509
  data: {
483
510
  site,
484
511
  id
@@ -488,7 +515,7 @@ const maintenanceActions = {
488
515
  getExternalSync: jobId => {
489
516
  return Session$9.authedFunction({
490
517
  method: 'GET',
491
- url: Helper$6.getUrl(values.serviceKey, 'get/externalsync', {
518
+ url: Helper$4.getUrl(values.serviceKey, 'get/externalsync', {
492
519
  id: jobId
493
520
  })
494
521
  });
@@ -496,7 +523,7 @@ const maintenanceActions = {
496
523
  retrySync: jobId => {
497
524
  return Session$9.authedFunction({
498
525
  method: 'POST',
499
- url: Helper$6.getUrl(values.serviceKey, 'update/retrysync'),
526
+ url: Helper$4.getUrl(values.serviceKey, 'update/retrysync'),
500
527
  data: {
501
528
  id: jobId
502
529
  }
@@ -505,7 +532,7 @@ const maintenanceActions = {
505
532
  };
506
533
 
507
534
  const {
508
- Helper: Helper$5,
535
+ Helper: Helper$3,
509
536
  Session: Session$8
510
537
  } = PlussCore__namespace;
511
538
  const reactionActions = {
@@ -523,7 +550,7 @@ const reactionActions = {
523
550
  }
524
551
  return Session$8.authedFunction({
525
552
  method: 'POST',
526
- url: Helper$5.getUrl('reactions', 'comments/add'),
553
+ url: Helper$3.getUrl('reactions', 'comments/add'),
527
554
  data
528
555
  });
529
556
  },
@@ -546,7 +573,7 @@ const reactionActions = {
546
573
  }
547
574
  return Session$8.authedFunction({
548
575
  method: 'GET',
549
- url: Helper$5.getUrl('reactions', 'comments/get', query)
576
+ url: Helper$3.getUrl('reactions', 'comments/get', query)
550
577
  });
551
578
  }
552
579
  };
@@ -579,30 +606,6 @@ var jobStatusOptions = [
579
606
  }
580
607
  ];
581
608
 
582
- const {
583
- Helper: Helper$4
584
- } = PlussCore__namespace;
585
- const jobsUpdate = (site, isdashboard) => {
586
- return dispatch => {
587
- if (isdashboard) dispatch({
588
- type: JOBS_LOADING
589
- });
590
- maintenanceActions.getJobsRecursive(site).then(res => {
591
- const currentSite = Helper$4.readStorageWithCookie('site');
592
- if (!___default["default"].isEmpty(res) && res[0].site === currentSite) {
593
- dispatch({
594
- type: JOBS_LOADED,
595
- payload: res
596
- });
597
- } else {
598
- dispatch({
599
- type: JOBS_LOADED,
600
- payload: []
601
- });
602
- }
603
- });
604
- };
605
- };
606
609
  const jobsLoaded = events => {
607
610
  return {
608
611
  type: JOBS_LOADED,
@@ -740,8 +743,8 @@ const getJobPriority = priority => {
740
743
  return priorityOption || getDefaultPriority();
741
744
  };
742
745
 
743
- 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; }
744
- 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; }
746
+ 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; }
747
+ 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; }
745
748
  const {
746
749
  Session: Session$7,
747
750
  Components: Components$7,
@@ -749,41 +752,241 @@ const {
749
752
  } = PlussCore__namespace;
750
753
  class JobList extends React.Component {
751
754
  constructor(props) {
755
+ var _this;
752
756
  super(props);
753
- _defineProperty__default["default"](this, "setRequesters", jobs => {
754
- const requesters = ___default["default"].orderBy(___default["default"].uniqBy(jobs.map(j => ({
755
- id: j.userID,
756
- displayName: j.userName,
757
- profilePic: j.userProfilePic
758
- })), 'id'), 'displayName', 'asc');
759
- this.setState({
760
- requesters
761
- });
757
+ _this = this;
758
+ _defineProperty__default["default"](this, "getAssignees", async () => {
759
+ try {
760
+ const res = await maintenanceActions$1.getAssignees(this.props.auth.site);
761
+ this.setState({
762
+ assignees: res.data.Users
763
+ });
764
+ } catch (error) {
765
+ console.error('getAssignees', error);
766
+ }
762
767
  });
763
- _defineProperty__default["default"](this, "getJobs", async () => {
768
+ /**
769
+ * Build server-side filter params from current filter state.
770
+ * Translates UI filter selections into API query parameters.
771
+ */
772
+ _defineProperty__default["default"](this, "buildFilterParams", () => {
764
773
  const {
765
- auth
774
+ selectedStatusFilter,
775
+ selectedTypeFilter,
776
+ selectedPriorityFilter,
777
+ selectedUserFilter,
778
+ selectedTimeFilterStart,
779
+ selectedTimeFilterEnd,
780
+ searchTerm
781
+ } = this.state;
782
+ const {
783
+ statusTypes
766
784
  } = this.props;
767
- try {
768
- const res = await maintenanceActions.getJobsRecursive(auth.site);
769
- if (!___default["default"].isEmpty(res) && res[0].site === auth.site) {
770
- this.setRequesters(res);
771
- this.props.jobsLoaded(res);
785
+ const params = {};
786
+
787
+ // Status filter: translate "All Incomplete" into the actual incomplete statuses
788
+ if (selectedStatusFilter) {
789
+ if (selectedStatusFilter === STATUS_IMCOMPLETE) {
790
+ // Exclude completed statuses - pass all non-completed status texts
791
+ const incompleteStatuses = statusTypes.filter(s => s.category !== STATUS_COMPLETED).map(s => s.text);
792
+ if (incompleteStatuses.length > 0) {
793
+ params.status = incompleteStatuses.join(',');
794
+ }
795
+ } else {
796
+ params.status = selectedStatusFilter;
772
797
  }
773
- } catch (error) {
774
- console.error('getJobs', error);
775
798
  }
799
+ if (selectedTypeFilter) {
800
+ params.type = selectedTypeFilter;
801
+ }
802
+ if (selectedPriorityFilter) {
803
+ params.priority = selectedPriorityFilter;
804
+ }
805
+ if (selectedUserFilter) {
806
+ params.assignee = selectedUserFilter;
807
+ }
808
+ if (selectedTimeFilterStart) {
809
+ params.startTime = selectedTimeFilterStart;
810
+ }
811
+ if (selectedTimeFilterEnd) {
812
+ params.endTime = selectedTimeFilterEnd;
813
+ }
814
+ if (searchTerm) {
815
+ params.search = searchTerm;
816
+ }
817
+ return params;
818
+ });
819
+ /**
820
+ * Minimum number of items to auto-fill before stopping background fetch.
821
+ * Because DynamoDB pages are unfiltered and the backend filters after
822
+ * query, a single page may yield very few matching results. We keep
823
+ * fetching in the background until we have this many items to display.
824
+ */
825
+ _defineProperty__default["default"](this, "MIN_PAGE_SIZE", 20);
826
+ /**
827
+ * Monotonically increasing ID used to ignore stale fetch results.
828
+ * When a filter changes, fetchJobs() increments this counter. Any
829
+ * in-flight fetch or autoFillPages loop checks the counter before
830
+ * applying results — if it doesn't match, the results are discarded.
831
+ *
832
+ * Alternative: AbortController would actually cancel the HTTP request
833
+ * (axios supports it via the `signal` config option). That would save
834
+ * bandwidth and server load but requires threading `signal` through
835
+ * authedFunction → getJobs2 → fetchPage (3 layers). The fetchId
836
+ * approach is simpler and sufficient — stale requests still complete
837
+ * in the background but their results are ignored.
838
+ */
839
+ _defineProperty__default["default"](this, "_fetchId", 0);
840
+ /**
841
+ * Fetch a single page from the server using the given lastKey.
842
+ */
843
+ _defineProperty__default["default"](this, "fetchPage", async function () {
844
+ let lastKey = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
845
+ const {
846
+ auth
847
+ } = _this.props;
848
+ const filters = _this.buildFilterParams();
849
+ return maintenanceActions$1.getJobs2(auth.site, filters.status, filters.type, filters.priority, filters.assignee, filters.startTime, filters.endTime, filters.search, lastKey);
850
+ });
851
+ /**
852
+ * Fetch the first page and render immediately.
853
+ * If fewer than MIN_PAGE_SIZE items returned and there's more data,
854
+ * kicks off a background loop that keeps fetching and appending
855
+ * so results appear progressively.
856
+ */
857
+ _defineProperty__default["default"](this, "fetchJobs", async () => {
858
+ const fetchId = ++this._fetchId;
859
+ this.setState({
860
+ loading: true,
861
+ loadingMore: false
862
+ }, async () => {
863
+ try {
864
+ const res = await this.fetchPage(null);
865
+ if (this._fetchId !== fetchId) return; // stale fetch
866
+
867
+ const items = res.data.Items || [];
868
+ const lastKey = res.data.LastKey || null;
869
+ this.setState({
870
+ jobs: items,
871
+ lastKey,
872
+ hasMore: !!lastKey,
873
+ loading: false
874
+ });
875
+ this.props.jobsLoaded(items);
876
+ this.setRequesters(items);
877
+
878
+ // Auto-fill in background if first page was sparse
879
+ if (lastKey && items.length < this.MIN_PAGE_SIZE) {
880
+ this.autoFillPages(items, lastKey, fetchId);
881
+ }
882
+ } catch (error) {
883
+ if (this._fetchId !== fetchId) return; // stale fetch
884
+ console.error('fetchJobs', error);
885
+ this.setState({
886
+ loading: false
887
+ });
888
+ }
889
+ });
776
890
  });
777
- _defineProperty__default["default"](this, "getAssignees", async () => {
891
+ /**
892
+ * Background loop: keep fetching pages and appending results
893
+ * until we have MIN_PAGE_SIZE items or run out of data.
894
+ * Each page is rendered as it arrives so the user sees
895
+ * results appearing progressively.
896
+ */
897
+ _defineProperty__default["default"](this, "autoFillPages", async (existingJobs, startKey, fetchId) => {
898
+ this.setState({
899
+ loadingMore: true
900
+ });
901
+ let currentJobs = existingJobs;
902
+ let currentLastKey = startKey;
778
903
  try {
779
- const res = await maintenanceActions.getAssignees(this.props.auth.site);
780
- this.setState({
781
- assignees: res.data.Users
782
- });
904
+ while (currentLastKey && currentJobs.length < this.MIN_PAGE_SIZE) {
905
+ const res = await this.fetchPage(currentLastKey);
906
+ if (this._fetchId !== fetchId) return; // stale fetch
907
+
908
+ const items = res.data.Items || [];
909
+ currentLastKey = res.data.LastKey || null;
910
+ currentJobs = [...currentJobs, ...items];
911
+
912
+ // Append to UI immediately after each page arrives
913
+ this.setState({
914
+ jobs: currentJobs,
915
+ lastKey: currentLastKey,
916
+ hasMore: !!currentLastKey
917
+ });
918
+ if (items.length > 0) {
919
+ this.props.jobsLoaded(items);
920
+ this.setRequesters(currentJobs);
921
+ }
922
+ }
783
923
  } catch (error) {
784
- console.error('getAssignees', error);
924
+ if (this._fetchId !== fetchId) return; // stale fetch
925
+ console.error('autoFillPages', error);
926
+ } finally {
927
+ if (this._fetchId === fetchId) {
928
+ this.setState({
929
+ loadingMore: false
930
+ });
931
+ }
785
932
  }
786
933
  });
934
+ /**
935
+ * Load the next batch of jobs when the user clicks "Load More".
936
+ * Fetches one page and also auto-fills in background if sparse.
937
+ */
938
+ _defineProperty__default["default"](this, "loadMore", async () => {
939
+ const fetchId = ++this._fetchId;
940
+ const {
941
+ lastKey,
942
+ jobs
943
+ } = this.state;
944
+ this.setState({
945
+ loadingMore: true
946
+ }, async () => {
947
+ try {
948
+ const res = await this.fetchPage(lastKey);
949
+ if (this._fetchId !== fetchId) return; // stale fetch
950
+
951
+ const items = res.data.Items || [];
952
+ const newLastKey = res.data.LastKey || null;
953
+ const updatedJobs = [...jobs, ...items];
954
+ this.setState({
955
+ jobs: updatedJobs,
956
+ lastKey: newLastKey,
957
+ hasMore: !!newLastKey
958
+ });
959
+ if (items.length > 0) {
960
+ this.props.jobsLoaded(items);
961
+ }
962
+
963
+ // Auto-fill in background if this page was sparse
964
+ if (newLastKey && items.length < this.MIN_PAGE_SIZE) {
965
+ this.autoFillPages(updatedJobs, newLastKey, fetchId);
966
+ } else {
967
+ this.setState({
968
+ loadingMore: false
969
+ });
970
+ }
971
+ } catch (error) {
972
+ if (this._fetchId !== fetchId) return; // stale fetch
973
+ console.error('loadMore', error);
974
+ this.setState({
975
+ loadingMore: false
976
+ });
977
+ }
978
+ });
979
+ });
980
+ _defineProperty__default["default"](this, "setRequesters", jobs => {
981
+ const requesters = ___default["default"].orderBy(___default["default"].uniqBy(jobs.map(j => ({
982
+ id: j.userID,
983
+ displayName: j.userName,
984
+ profilePic: j.userProfilePic
985
+ })), 'id'), 'displayName', 'asc');
986
+ this.setState({
987
+ requesters
988
+ });
989
+ });
787
990
  _defineProperty__default["default"](this, "sortByCol", col => {
788
991
  const {
789
992
  sortColumn,
@@ -803,9 +1006,12 @@ class JobList extends React.Component {
803
1006
  _defineProperty__default["default"](this, "onRemoveRequest", async request => {
804
1007
  if (window.confirm(values.textAreYouSureYouWantToDelete)) {
805
1008
  this.props.removeJob(request.id);
1009
+ // Remove from local state immediately
1010
+ this.setState(prevState => ({
1011
+ jobs: prevState.jobs.filter(j => j.id !== request.id)
1012
+ }));
806
1013
  try {
807
- await maintenanceActions.deleteJob(this.props.auth.site, request.id);
808
- this.getJobs();
1014
+ await maintenanceActions$1.deleteJob(this.props.auth.site, request.id);
809
1015
  } catch (error) {
810
1016
  console.log('onRemoveRequest', error);
811
1017
  alert('Something went wrong with the request. Please try again.');
@@ -824,20 +1030,20 @@ class JobList extends React.Component {
824
1030
  });
825
1031
  _defineProperty__default["default"](this, "selectTypeFilter", filter => {
826
1032
  this.setState({
827
- selectedTypeFilter: filter
828
- });
1033
+ selectedTypeFilter: filter || null
1034
+ }, () => this.fetchJobs());
829
1035
  this.closeFilter();
830
1036
  });
831
1037
  _defineProperty__default["default"](this, "selectPriorityFilter", filter => {
832
1038
  this.setState({
833
- selectedPriorityFilter: filter
834
- });
1039
+ selectedPriorityFilter: filter || null
1040
+ }, () => this.fetchJobs());
835
1041
  this.closeFilter();
836
1042
  });
837
1043
  _defineProperty__default["default"](this, "selectStatusFilter", filter => {
838
1044
  this.setState({
839
- selectedStatusFilter: filter
840
- });
1045
+ selectedStatusFilter: filter || null
1046
+ }, () => this.fetchJobs());
841
1047
  this.closeFilter();
842
1048
  });
843
1049
  _defineProperty__default["default"](this, "timeFilterChanged", selectedTimeFilter => {
@@ -881,7 +1087,7 @@ class JobList extends React.Component {
881
1087
  selectedTimeFilterStart: startTime,
882
1088
  selectedTimeFilterEnd: endTime,
883
1089
  selectedTimeFilterText: text
884
- });
1090
+ }, () => this.fetchJobs());
885
1091
  this.closeFilter();
886
1092
  });
887
1093
  _defineProperty__default["default"](this, "removeTimeFilter", () => {
@@ -889,7 +1095,7 @@ class JobList extends React.Component {
889
1095
  selectedTimeFilterStart: null,
890
1096
  selectedTimeFilterEnd: null,
891
1097
  selectedTimeFilterText: null
892
- });
1098
+ }, () => this.fetchJobs());
893
1099
  });
894
1100
  _defineProperty__default["default"](this, "onHandleChange", event => {
895
1101
  var stateChange = {};
@@ -905,7 +1111,7 @@ class JobList extends React.Component {
905
1111
  this.setState({
906
1112
  selectedUserFilter: null,
907
1113
  selectedUserFilterText: null
908
- });
1114
+ }, () => this.fetchJobs());
909
1115
  });
910
1116
  _defineProperty__default["default"](this, "saveUserFilter", () => {
911
1117
  if (!this.state.selectedAssignee) {
@@ -915,7 +1121,7 @@ class JobList extends React.Component {
915
1121
  selectedUserFilter: this.state.selectedAssignee.id,
916
1122
  selectedUserFilterText: this.state.selectedAssignee.displayName,
917
1123
  selectedAssignee: null
918
- });
1124
+ }, () => this.fetchJobs());
919
1125
  }
920
1126
  this.closeFilter();
921
1127
  });
@@ -928,7 +1134,7 @@ class JobList extends React.Component {
928
1134
  this.setState({
929
1135
  selectedRequesterFilter: null,
930
1136
  selectedRequesterFilterText: null
931
- });
1137
+ }, () => this.fetchJobs());
932
1138
  });
933
1139
  _defineProperty__default["default"](this, "saveRequesterFilter", () => {
934
1140
  if (!this.state.selectedRequester) {
@@ -938,7 +1144,7 @@ class JobList extends React.Component {
938
1144
  selectedRequesterFilter: this.state.selectedRequester.id,
939
1145
  selectedRequesterFilterText: this.state.selectedRequester.displayName,
940
1146
  selectedRequester: null
941
- });
1147
+ }, () => this.fetchJobs());
942
1148
  }
943
1149
  this.closeFilter();
944
1150
  });
@@ -949,85 +1155,47 @@ class JobList extends React.Component {
949
1155
  lastSearch: thisSearchTime
950
1156
  });
951
1157
  setTimeout(() => {
952
- // delayed setter to avoid filtering on every keypress
1158
+ // delayed setter to avoid searching on every keypress
953
1159
  if (this.state.lastSearch === thisSearchTime) {
954
1160
  this.setState({
955
1161
  searchTerm: this.state.search
956
- });
1162
+ }, () => this.fetchJobs());
957
1163
  }
958
1164
  }, 500);
959
1165
  });
1166
+ /**
1167
+ * Get the source array for rendering.
1168
+ * With server-side filtering, this is simply the local jobs array
1169
+ * sorted by the user's selected sort column.
1170
+ * The requester filter still applies client-side since the backend
1171
+ * doesn't have a requester/userID filter param.
1172
+ */
960
1173
  _defineProperty__default["default"](this, "getSource", () => {
961
- let source = this.props.source;
1174
+ let source = this.state.jobs;
962
1175
 
963
- // filter by time
964
- if (this.state.selectedTimeFilterStart && this.state.selectedTimeFilterEnd) {
965
- source = ___default["default"].filter(source, r => {
966
- return r.createdUnix >= this.state.selectedTimeFilterStart && r.createdUnix <= this.state.selectedTimeFilterEnd;
967
- });
968
- }
969
-
970
- // filter by type
971
- if (this.state.selectedTypeFilter) {
972
- source = ___default["default"].filter(source, r => {
973
- return r.type === this.state.selectedTypeFilter;
974
- });
975
- }
976
-
977
- // filter by priority
978
- if (this.state.selectedPriorityFilter) {
979
- const defaultPriority = getDefaultPriority().name;
980
- source = ___default["default"].filter(source, r => {
981
- return r.priority === this.state.selectedPriorityFilter || this.state.selectedPriorityFilter === defaultPriority && ___default["default"].isNil(r.priority);
982
- });
983
- }
1176
+ // Filter out deleted items
1177
+ source = ___default["default"].filter(source, ev => ev != null && !ev.Deleted);
984
1178
 
985
- // filter by status
986
- if (this.state.selectedStatusFilter) {
987
- const {
988
- statusTypes
989
- } = this.props;
990
- const defaultStatus = statusTypes.find(s => s.category === STATUS_NOT_ACTIONED);
991
- source = ___default["default"].filter(source, r => {
992
- const status = statusTypes.find(s => s.text === r.status) || defaultStatus;
993
- if (this.state.selectedStatusFilter === STATUS_IMCOMPLETE) {
994
- return status.category !== STATUS_COMPLETED;
995
- }
996
- return status.text === this.state.selectedStatusFilter;
997
- });
998
- }
999
- if (this.state.selectedUserFilter) {
1000
- source = ___default["default"].filter(source, r => {
1001
- return r.AssigneeId === this.state.selectedUserFilter;
1002
- });
1003
- }
1179
+ // Requester filter still client-side (no backend param for userID filtering)
1004
1180
  if (this.state.selectedRequesterFilter) {
1005
1181
  source = ___default["default"].filter(source, r => {
1006
1182
  return r.userID === this.state.selectedRequesterFilter;
1007
1183
  });
1008
1184
  }
1009
- if (!___default["default"].isEmpty(this.state.searchTerm)) {
1010
- source = ___default["default"].filter(source, r => {
1011
- if (r.jobId && r.jobId === this.state.searchTerm) {
1012
- return true;
1013
- }
1014
- if (r.room && r.room.toLowerCase().indexOf(this.state.searchTerm.toLowerCase()) > -1) {
1015
- return true;
1016
- }
1017
- if (r.title && r.title.toLowerCase().indexOf(this.state.searchTerm.toLowerCase()) > -1) {
1018
- return true;
1185
+
1186
+ // Skip sorting while auto-fill is appending results to avoid jumpiness.
1187
+ // Sort is re-applied when the user clicks a column header or when
1188
+ // auto-fill completes.
1189
+ if (!this.state.loadingMore) {
1190
+ source = ___default["default"].sortBy(source, event => {
1191
+ if (this.state.sortColumn === 'assigned') {
1192
+ return event.Assignee ? event.Assignee.displayName : 'Unassigned';
1019
1193
  }
1020
- return false;
1194
+ if (this.state.sortColumn !== 'createdUnix') return event[this.state.sortColumn];
1195
+ return event.createdUnix;
1021
1196
  });
1197
+ if (this.state.sortDesc) source.reverse();
1022
1198
  }
1023
- source = ___default["default"].sortBy(source, event => {
1024
- if (this.state.sortColumn === 'assigned') {
1025
- return event.Assignee ? event.Assignee.displayName : 'Unassigned';
1026
- }
1027
- if (this.state.sortColumn !== 'createdUnix') return event[this.state.sortColumn];
1028
- return event.createdUnix;
1029
- });
1030
- if (this.state.sortDesc) source.reverse();
1031
1199
  return source;
1032
1200
  });
1033
1201
  _defineProperty__default["default"](this, "getCustomFieldValue", field => {
@@ -1107,7 +1275,7 @@ class JobList extends React.Component {
1107
1275
  });
1108
1276
  const customFieldValues = this.getCustomFields(r, customColumns);
1109
1277
  const priority = r.priority || defaultPriority;
1110
- return _objectSpread$7(_objectSpread$7(_objectSpread$7({}, r), customFieldValues), {}, {
1278
+ return _objectSpread$6(_objectSpread$6(_objectSpread$6({}, r), customFieldValues), {}, {
1111
1279
  notes,
1112
1280
  progressTime,
1113
1281
  completedTime,
@@ -1139,13 +1307,60 @@ class JobList extends React.Component {
1139
1307
  exportCsvOpen: false
1140
1308
  });
1141
1309
  });
1310
+ _defineProperty__default["default"](this, "hasActiveFilters", () => {
1311
+ const {
1312
+ selectedTypeFilter,
1313
+ selectedPriorityFilter,
1314
+ selectedStatusFilter,
1315
+ selectedTimeFilterStart,
1316
+ selectedUserFilter,
1317
+ selectedRequesterFilter,
1318
+ searchTerm
1319
+ } = this.state;
1320
+ return !!(selectedTypeFilter || selectedPriorityFilter || selectedStatusFilter || selectedTimeFilterStart || selectedUserFilter || selectedRequesterFilter || searchTerm);
1321
+ });
1322
+ _defineProperty__default["default"](this, "clearAllFilters", () => {
1323
+ this.setState({
1324
+ selectedTypeFilter: null,
1325
+ selectedPriorityFilter: null,
1326
+ selectedStatusFilter: null,
1327
+ selectedTimeFilterStart: null,
1328
+ selectedTimeFilterEnd: null,
1329
+ selectedTimeFilterText: null,
1330
+ selectedUserFilter: null,
1331
+ selectedUserFilterText: null,
1332
+ selectedRequesterFilter: null,
1333
+ selectedRequesterFilterText: null,
1334
+ search: '',
1335
+ searchTerm: ''
1336
+ }, () => this.fetchJobs());
1337
+ });
1142
1338
  this.state = {
1143
- showCompleted: false,
1144
1339
  sortColumn: 'createdUnix',
1145
1340
  sortDesc: true,
1146
1341
  selectedTimeFilter: Analytics$2.getAnalyticsFilterOptions()[1],
1147
1342
  assignees: [],
1148
- requesters: []
1343
+ requesters: [],
1344
+ // Server-side pagination state
1345
+ jobs: [],
1346
+ lastKey: null,
1347
+ hasMore: false,
1348
+ loading: false,
1349
+ loadingMore: false,
1350
+ // Filters (applied to server-side queries)
1351
+ selectedTypeFilter: null,
1352
+ selectedPriorityFilter: null,
1353
+ selectedStatusFilter: null,
1354
+ selectedTimeFilterStart: null,
1355
+ selectedTimeFilterEnd: null,
1356
+ selectedTimeFilterText: null,
1357
+ selectedUserFilter: null,
1358
+ selectedUserFilterText: null,
1359
+ selectedRequesterFilter: null,
1360
+ selectedRequesterFilterText: null,
1361
+ search: '',
1362
+ searchTerm: '',
1363
+ lastSearch: null
1149
1364
  };
1150
1365
  this.exportColumns = [{
1151
1366
  label: 'Select All',
@@ -1205,7 +1420,7 @@ class JobList extends React.Component {
1205
1420
  }
1206
1421
  componentDidMount() {
1207
1422
  this.props.jobStatusesUpdate(this.props.auth.site);
1208
- this.getJobs();
1423
+ this.fetchJobs();
1209
1424
  this.getAssignees();
1210
1425
  }
1211
1426
  renderFilterPopup() {
@@ -1219,7 +1434,7 @@ class JobList extends React.Component {
1219
1434
  minWidth: 400,
1220
1435
  hasPadding: true,
1221
1436
  onClose: this.closeFilter
1222
- }, ___default["default"].sortBy(___default["default"].uniq(this.props.source.map(r => r.type)), t => t.toLowerCase()).map(type => {
1437
+ }, ___default["default"].sortBy(___default["default"].uniq(this.state.jobs.map(r => r.type)), t => t.toLowerCase()).map(type => {
1223
1438
  return /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1224
1439
  key: type,
1225
1440
  onClick: () => {
@@ -1410,7 +1625,7 @@ class JobList extends React.Component {
1410
1625
  const status = ev.status && statusTypes.find(s => s.text === ev.status) || defaultStatus;
1411
1626
  const priority = getJobPriority(ev.priority);
1412
1627
  return /*#__PURE__*/React__default["default"].createElement("tr", {
1413
- key: index
1628
+ key: ev.id || index
1414
1629
  }, /*#__PURE__*/React__default["default"].createElement("td", null, ev.jobId), /*#__PURE__*/React__default["default"].createElement("td", {
1415
1630
  className: "table-TitleColumn"
1416
1631
  }, /*#__PURE__*/React__default["default"].createElement(reactRouterDom.Link, {
@@ -1491,8 +1706,28 @@ class JobList extends React.Component {
1491
1706
  if (col !== this.state.sortColumn) return '';
1492
1707
  return ' table--columnActive';
1493
1708
  }
1709
+ renderLoading() {
1710
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1711
+ className: "flex flex-center-row",
1712
+ style: {
1713
+ padding: 40
1714
+ }
1715
+ }, /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
1716
+ style: {
1717
+ fontSize: 32,
1718
+ color: PlussCore.Colours.COLOUR_DUSK_LIGHT
1719
+ },
1720
+ name: "spinner fa-pulse fa-fw"
1721
+ }), /*#__PURE__*/React__default["default"].createElement("span", {
1722
+ className: "marginLeft-16 fontRegular fontSize-14",
1723
+ style: {
1724
+ color: PlussCore.Colours.TEXT_MID
1725
+ }
1726
+ }, "Loading ", values.textTitleRequests, "\u2026"));
1727
+ }
1494
1728
  renderEmpty() {
1495
1729
  const title = this.props.strings["".concat(values.featureKey, "_textTitleRequests")] || values.textTitleRequests;
1730
+ const hasFilters = this.hasActiveFilters();
1496
1731
  return /*#__PURE__*/React__default["default"].createElement("div", {
1497
1732
  style: {
1498
1733
  display: 'flex',
@@ -1504,7 +1739,22 @@ class JobList extends React.Component {
1504
1739
  }
1505
1740
  }, /*#__PURE__*/React__default["default"].createElement("div", {
1506
1741
  className: "emptyState"
1507
- }), /*#__PURE__*/React__default["default"].createElement("div", {
1742
+ }), hasFilters ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
1743
+ className: "marginTop-32",
1744
+ style: {
1745
+ maxWidth: 500,
1746
+ textAlign: 'center'
1747
+ }
1748
+ }, /*#__PURE__*/React__default["default"].createElement("span", {
1749
+ className: "fontRegular fontSize-13"
1750
+ }, "No ", title.toLowerCase(), " match your current filters.")), /*#__PURE__*/React__default["default"].createElement("div", {
1751
+ className: "marginTop-16"
1752
+ }, /*#__PURE__*/React__default["default"].createElement(Components$7.Button, {
1753
+ inline: true,
1754
+ buttonType: "tertiary",
1755
+ onClick: this.clearAllFilters,
1756
+ isActive: true
1757
+ }, "Clear All Filters"))) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
1508
1758
  className: "marginTop-32",
1509
1759
  style: {
1510
1760
  maxWidth: 500,
@@ -1520,11 +1770,58 @@ class JobList extends React.Component {
1520
1770
  maxWidth: 500,
1521
1771
  textAlign: 'center'
1522
1772
  }
1523
- }, values.textEmptyExample));
1773
+ }, values.textEmptyExample)));
1774
+ }
1775
+ renderLoadMore() {
1776
+ const {
1777
+ hasMore,
1778
+ loadingMore
1779
+ } = this.state;
1780
+ if (!hasMore && !loadingMore) return null;
1781
+
1782
+ // During background auto-fill, show a subtle spinner without a button
1783
+ if (loadingMore) {
1784
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1785
+ className: "flex flex-center-row",
1786
+ style: {
1787
+ padding: '16px 0'
1788
+ }
1789
+ }, /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
1790
+ name: "spinner fa-pulse fa-fw",
1791
+ style: {
1792
+ fontSize: 16,
1793
+ color: PlussCore.Colours.TEXT_MID,
1794
+ marginRight: 8
1795
+ }
1796
+ }), /*#__PURE__*/React__default["default"].createElement("span", {
1797
+ className: "fontRegular fontSize-13",
1798
+ style: {
1799
+ color: PlussCore.Colours.TEXT_MID
1800
+ }
1801
+ }, "Loading more results\u2026"));
1802
+ }
1803
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1804
+ className: "flex flex-center-row",
1805
+ style: {
1806
+ padding: '16px 0'
1807
+ }
1808
+ }, /*#__PURE__*/React__default["default"].createElement(Components$7.Button, {
1809
+ inline: true,
1810
+ buttonType: "tertiary",
1811
+ onClick: this.loadMore,
1812
+ isActive: true
1813
+ }, "Load More"));
1524
1814
  }
1525
1815
  renderContent() {
1526
- if (___default["default"].isEmpty(this.props.source)) return this.renderEmpty();
1527
- return /*#__PURE__*/React__default["default"].createElement(reactBootstrap.Table, {
1816
+ const {
1817
+ loading,
1818
+ loadingMore,
1819
+ jobs
1820
+ } = this.state;
1821
+ if (loading) return this.renderLoading();
1822
+ if (___default["default"].isEmpty(jobs) && !loadingMore) return this.renderEmpty();
1823
+ if (___default["default"].isEmpty(jobs)) return this.renderLoading();
1824
+ return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement(reactBootstrap.Table, {
1528
1825
  className: "plussTable",
1529
1826
  striped: true,
1530
1827
  bordered: true,
@@ -1607,7 +1904,7 @@ class JobList extends React.Component {
1607
1904
  style: {
1608
1905
  width: 50
1609
1906
  }
1610
- }))), /*#__PURE__*/React__default["default"].createElement("tbody", null, this.renderRequests()));
1907
+ }))), /*#__PURE__*/React__default["default"].createElement("tbody", null, this.renderRequests())), this.renderLoadMore());
1611
1908
  }
1612
1909
  renderFilters() {
1613
1910
  let typeFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
@@ -1656,13 +1953,9 @@ class JobList extends React.Component {
1656
1953
  typeFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1657
1954
  className: "marginRight-10",
1658
1955
  onClick: () => {
1659
- this.openFilter('type');
1660
- },
1661
- rightIcon: "close",
1662
- rightClick: e => {
1663
- e.stopPropagation();
1664
1956
  this.selectTypeFilter();
1665
1957
  },
1958
+ rightIcon: "close",
1666
1959
  text: this.state.selectedTypeFilter
1667
1960
  });
1668
1961
  }
@@ -1670,13 +1963,9 @@ class JobList extends React.Component {
1670
1963
  priorityFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1671
1964
  className: "marginRight-10",
1672
1965
  onClick: () => {
1673
- this.openFilter('priority');
1674
- },
1675
- rightIcon: "close",
1676
- rightClick: e => {
1677
- e.stopPropagation();
1678
1966
  this.selectPriorityFilter();
1679
1967
  },
1968
+ rightIcon: "close",
1680
1969
  text: this.state.selectedPriorityFilter
1681
1970
  });
1682
1971
  }
@@ -1684,13 +1973,9 @@ class JobList extends React.Component {
1684
1973
  statusFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1685
1974
  className: "marginRight-10",
1686
1975
  onClick: () => {
1687
- this.openFilter('status');
1688
- },
1689
- rightIcon: "close",
1690
- rightClick: e => {
1691
- e.stopPropagation();
1692
1976
  this.selectStatusFilter();
1693
1977
  },
1978
+ rightIcon: "close",
1694
1979
  text: this.state.selectedStatusFilter
1695
1980
  });
1696
1981
  }
@@ -1712,13 +1997,9 @@ class JobList extends React.Component {
1712
1997
  userFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1713
1998
  className: "marginRight-10",
1714
1999
  onClick: () => {
1715
- this.openFilter('user');
1716
- },
1717
- rightIcon: "close",
1718
- rightClick: e => {
1719
- e.stopPropagation();
1720
2000
  this.removeUserFilter();
1721
2001
  },
2002
+ rightIcon: "close",
1722
2003
  text: this.state.selectedUserFilterText
1723
2004
  });
1724
2005
  }
@@ -1726,13 +2007,9 @@ class JobList extends React.Component {
1726
2007
  requesterFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1727
2008
  className: "marginRight-10",
1728
2009
  onClick: () => {
1729
- this.openFilter('requester');
1730
- },
1731
- rightIcon: "close",
1732
- rightClick: e => {
1733
- e.stopPropagation();
1734
2010
  this.removeRequesterFilter();
1735
2011
  },
2012
+ rightIcon: "close",
1736
2013
  text: this.state.selectedRequesterFilterText
1737
2014
  });
1738
2015
  }
@@ -1810,7 +2087,7 @@ class JobTypes extends React.Component {
1810
2087
  super(props);
1811
2088
  _defineProperty__default["default"](this, "getJobTypes", async () => {
1812
2089
  try {
1813
- const res = await maintenanceActions.getJobTypes(this.props.auth.site);
2090
+ const res = await maintenanceActions$1.getJobTypes(this.props.auth.site);
1814
2091
  if (res.data != null) this.props.jobTypesLoaded(res.data);
1815
2092
  } catch (error) {
1816
2093
  console.error('getJobTypes', error);
@@ -1835,7 +2112,7 @@ class JobTypes extends React.Component {
1835
2112
  _defineProperty__default["default"](this, "onRemoveJobType", async ev => {
1836
2113
  if (!window.confirm("Are you sure you want to delete ".concat(ev.typeName, "?"))) return;
1837
2114
  try {
1838
- await maintenanceActions.deleteJobType(this.props.auth.site, ev.id);
2115
+ await maintenanceActions$1.deleteJobType(this.props.auth.site, ev.id);
1839
2116
  const index = ___default["default"].findIndex(this.state.jobList, job => {
1840
2117
  return job != null && job.id === ev.id;
1841
2118
  });
@@ -2040,12 +2317,12 @@ var JobTypes$1 = reactRedux.connect(mapStateToProps$6, {
2040
2317
  jobTypesUpdate
2041
2318
  })(reactRouter.withRouter(JobTypes));
2042
2319
 
2043
- 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; }
2044
- 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; }
2320
+ 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; }
2321
+ 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; }
2045
2322
  const {
2046
2323
  Session: Session$5,
2047
2324
  Components: Components$5,
2048
- Colours: Colours$3
2325
+ Colours: Colours$2
2049
2326
  } = PlussCore__namespace;
2050
2327
  class Configuration extends React.Component {
2051
2328
  constructor(props) {
@@ -2236,43 +2513,43 @@ class Configuration extends React.Component {
2236
2513
  return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("p", {
2237
2514
  className: "fontMedium fontSize-36 text-dark"
2238
2515
  }, "Statuses"), /*#__PURE__*/React__default["default"].createElement("div", {
2239
- style: styles$6.statusCategoryHeading
2516
+ style: styles$5.statusCategoryHeading
2240
2517
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2241
2518
  className: "fontMedium fontSize-16 text-bold"
2242
2519
  }, "Status Category")), statusTypes.map((status, index) => {
2243
2520
  return /*#__PURE__*/React__default["default"].createElement("div", {
2244
2521
  key: "".concat(status.text, "_").concat(index),
2245
- style: styles$6.statusTypeContainer
2522
+ style: styles$5.statusTypeContainer
2246
2523
  }, /*#__PURE__*/React__default["default"].createElement("div", {
2247
2524
  key: status.text,
2248
2525
  className: "statusLabel",
2249
- style: _objectSpread$6(_objectSpread$6({}, styles$6.statusTextContainer), {}, {
2526
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusTextContainer), {}, {
2250
2527
  backgroundColor: status.color
2251
2528
  })
2252
2529
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2253
2530
  className: "statusLabel_text"
2254
2531
  }, status.text)), /*#__PURE__*/React__default["default"].createElement("div", {
2255
- style: styles$6.statusCategoryContainer
2532
+ style: styles$5.statusCategoryContainer
2256
2533
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2257
2534
  className: "fontMedium fontSize-16 text-dark"
2258
2535
  }, status.category)), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2259
- style: _objectSpread$6(_objectSpread$6({}, styles$6.statusIcon), {}, {
2536
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusIcon), {}, {
2260
2537
  visibility: index === 0 ? 'hidden' : 'visible'
2261
2538
  }),
2262
2539
  name: 'arrow-up',
2263
2540
  onClick: () => this.onMoveStatus(index, true)
2264
2541
  }), /*#__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 === statusTypes.length - 1 ? 'hidden' : 'visible'
2267
2544
  }),
2268
2545
  name: 'arrow-down',
2269
2546
  onClick: () => this.onMoveStatus(index, false)
2270
2547
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2271
- style: _objectSpread$6({}, styles$6.statusIcon),
2548
+ style: _objectSpread$5({}, styles$5.statusIcon),
2272
2549
  name: "pencil",
2273
2550
  onClick: () => this.onEditStatus(index)
2274
2551
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2275
- style: _objectSpread$6({}, styles$6.statusIcon),
2552
+ style: _objectSpread$5({}, styles$5.statusIcon),
2276
2553
  name: "minus-circle",
2277
2554
  onClick: () => this.onDeleteStatus(index)
2278
2555
  }));
@@ -2321,8 +2598,8 @@ class Configuration extends React.Component {
2321
2598
  renderSuccess() {
2322
2599
  if (!this.state.success) return null;
2323
2600
  return /*#__PURE__*/React__default["default"].createElement("span", {
2324
- style: _objectSpread$6(_objectSpread$6({}, styles$6.savedText), {}, {
2325
- color: Colours$3.COLOUR_GREEN
2601
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.savedText), {}, {
2602
+ color: Colours$2.COLOUR_GREEN
2326
2603
  })
2327
2604
  }, "Saved");
2328
2605
  }
@@ -2438,7 +2715,7 @@ class Configuration extends React.Component {
2438
2715
  }, this.renderSubmit(), this.renderSuccess()), this.renderNewStatusPopup());
2439
2716
  }
2440
2717
  }
2441
- const styles$6 = {
2718
+ const styles$5 = {
2442
2719
  statusCategoryHeading: {
2443
2720
  marginLeft: 130,
2444
2721
  width: 160,
@@ -2463,7 +2740,7 @@ const styles$6 = {
2463
2740
  fontSize: 20,
2464
2741
  padding: 5,
2465
2742
  marginLeft: 10,
2466
- color: Colours$3.COLOUR_BRANDING_ACTION,
2743
+ color: Colours$2.COLOUR_BRANDING_ACTION,
2467
2744
  visibility: 'visible'
2468
2745
  },
2469
2746
  savedText: {
@@ -2497,52 +2774,6 @@ const {
2497
2774
  class RequestsHub extends React.Component {
2498
2775
  constructor(props) {
2499
2776
  super(props);
2500
- _defineProperty__default["default"](this, "setData", () => {
2501
- const allList = [];
2502
- this.state.allList.forEach(ev => {
2503
- if (ev != null && !ev.Deleted) allList.push(ev);
2504
- });
2505
- const upcoming = ___default["default"].filter(allList, ev => {
2506
- if (!ev) return false;
2507
- if (ev.status && ev.status === 'Completed') return false;
2508
- return true;
2509
- });
2510
- const completed = ___default["default"].filter(allList, ev => {
2511
- if (!ev) return false;
2512
- if (ev.status && ev.status === 'Completed') return true;
2513
- return false;
2514
- });
2515
-
2516
- // console.log('setData', upcoming, completed);
2517
- this.setState({
2518
- allList,
2519
- upcoming,
2520
- completed
2521
- });
2522
- });
2523
- _defineProperty__default["default"](this, "getData", () => {
2524
- const {
2525
- auth
2526
- } = this.props;
2527
- this.setState({
2528
- loadingAll: true
2529
- }, async () => {
2530
- try {
2531
- const res = await maintenanceActions.getJobsRecursive(auth.site);
2532
- this.setState({
2533
- loadingAll: false
2534
- });
2535
- if (!___default["default"].isEmpty(res) && res[0].site === auth.site) {
2536
- this.props.jobsLoaded(res);
2537
- }
2538
- } catch (error) {
2539
- console.error('getData', error);
2540
- this.setState({
2541
- loadingAll: false
2542
- });
2543
- }
2544
- });
2545
- });
2546
2777
  _defineProperty__default["default"](this, "onAddNew", () => {
2547
2778
  const {
2548
2779
  auth
@@ -2569,38 +2800,10 @@ class RequestsHub extends React.Component {
2569
2800
  _defineProperty__default["default"](this, "getSideBarSectionColour", id => this.state.selectedSection === id ? {
2570
2801
  backgroundColor: '#fff'
2571
2802
  } : {});
2572
- _defineProperty__default["default"](this, "renderStats", (stat, loading) => loading ? /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2573
- style: styles$5.spinner,
2574
- name: "spinner fa-pulse fa-fw"
2575
- }) : stat);
2576
2803
  this.state = {
2577
- selectedSection: 'all',
2578
- location: '',
2579
- loadingAll: false,
2580
- loadingSubmissions: false,
2581
- submissionEntries: [],
2582
- allList: [],
2583
- completed: [],
2584
- upcoming: [],
2585
- now: moment__default["default"].utc(),
2586
- onlyFuture: true,
2587
- search: ''
2804
+ selectedSection: 'all'
2588
2805
  };
2589
2806
  }
2590
- UNSAFE_componentWillMount() {
2591
- this.updateProps(this.props);
2592
- }
2593
- componentDidMount() {
2594
- this.getData();
2595
- }
2596
- UNSAFE_componentWillReceiveProps(nextProps) {
2597
- if (!___default["default"].isEqual(this.props.jobs, nextProps.jobs)) this.updateProps(nextProps);
2598
- }
2599
- updateProps(props) {
2600
- this.setState({
2601
- allList: props.jobs
2602
- }, this.setData);
2603
- }
2604
2807
  renderLeftBar() {
2605
2808
  const sectionItems = [];
2606
2809
  if (this.canAddNew()) {
@@ -2670,9 +2873,7 @@ class RequestsHub extends React.Component {
2670
2873
  } else if (this.state.selectedSection === 'config') {
2671
2874
  return /*#__PURE__*/React__default["default"].createElement(Configuration$1, null);
2672
2875
  }
2673
- return /*#__PURE__*/React__default["default"].createElement(JobList$1, {
2674
- source: this.state.allList
2675
- });
2876
+ return /*#__PURE__*/React__default["default"].createElement(JobList$1, null);
2676
2877
  }
2677
2878
  render() {
2678
2879
  return /*#__PURE__*/React__default["default"].createElement("div", {
@@ -2684,50 +2885,24 @@ class RequestsHub extends React.Component {
2684
2885
  }, this.renderRight())));
2685
2886
  }
2686
2887
  }
2687
- const styles$5 = {
2688
- sideBarTitleSection: {
2689
- lineHeight: '40px',
2690
- marginTop: 30,
2691
- marginBottom: 30,
2692
- paddingLeft: 24,
2693
- paddingRight: 24
2694
- },
2695
- sideBarSection: {
2696
- weight: '100%',
2697
- minWidth: 200,
2698
- padding: 32,
2699
- paddingLeft: 24,
2700
- cursor: 'pointer',
2701
- display: 'flex',
2702
- flexDirection: 'column',
2703
- justifyContent: 'center'
2704
- },
2705
- spinner: {
2706
- fontSize: 32,
2707
- color: FeatureConfig.env.colourBrandingOff
2708
- }
2709
- };
2710
2888
  const mapStateToProps$4 = state => {
2711
2889
  const {
2712
2890
  auth
2713
2891
  } = state;
2714
2892
  return {
2715
- jobs: state[values.reducerKey].jobs,
2716
2893
  auth,
2717
2894
  strings: state.strings && state.strings.config || {}
2718
2895
  };
2719
2896
  };
2720
- var RequestsHub$1 = reactRedux.connect(mapStateToProps$4, {
2721
- jobsLoaded
2722
- })(reactRouter.withRouter(RequestsHub));
2897
+ var RequestsHub$1 = reactRedux.connect(mapStateToProps$4)(reactRouter.withRouter(RequestsHub));
2723
2898
 
2724
- 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; }
2725
- 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; }
2899
+ 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; }
2900
+ 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; }
2726
2901
  const {
2727
2902
  Apis: Apis$1,
2728
- Helper: Helper$3,
2903
+ Helper: Helper$2,
2729
2904
  Session: Session$3,
2730
- Colours: Colours$2,
2905
+ Colours: Colours$1,
2731
2906
  Components: Components$3
2732
2907
  } = PlussCore__namespace;
2733
2908
  const IMAGE_SIZE_NOTE = 72;
@@ -2736,7 +2911,7 @@ class Job extends React.Component {
2736
2911
  super(props);
2737
2912
  _defineProperty__default["default"](this, "getJob", async () => {
2738
2913
  try {
2739
- const res = await maintenanceActions.getJob(this.props.auth.site, this.state.jobId);
2914
+ const res = await maintenanceActions$1.getJob(this.props.auth.site, this.state.jobId);
2740
2915
  this.setState({
2741
2916
  updating: false
2742
2917
  });
@@ -2748,7 +2923,7 @@ class Job extends React.Component {
2748
2923
  });
2749
2924
  _defineProperty__default["default"](this, "getAssignees", async () => {
2750
2925
  try {
2751
- const res = await maintenanceActions.getAssignees(this.props.auth.site);
2926
+ const res = await maintenanceActions$1.getAssignees(this.props.auth.site);
2752
2927
  this.setState({
2753
2928
  assignees: res.data.Users
2754
2929
  });
@@ -2761,7 +2936,7 @@ class Job extends React.Component {
2761
2936
  this.setState({
2762
2937
  loadingExternalSync: true
2763
2938
  });
2764
- const res = await maintenanceActions.getExternalSync(this.state.jobId);
2939
+ const res = await maintenanceActions$1.getExternalSync(this.state.jobId);
2765
2940
  this.setState({
2766
2941
  externalSync: res.data,
2767
2942
  loadingExternalSync: false
@@ -2786,7 +2961,7 @@ class Job extends React.Component {
2786
2961
  retrySyncError: null
2787
2962
  });
2788
2963
  try {
2789
- await maintenanceActions.retrySync(job.id);
2964
+ await maintenanceActions$1.retrySync(job.id);
2790
2965
  // Refresh job data to get updated history
2791
2966
  await this.getJob();
2792
2967
  this.setState({
@@ -2809,7 +2984,7 @@ class Job extends React.Component {
2809
2984
  let statusType = statusTypes.find(s => s.text === status);
2810
2985
  if (!statusType) {
2811
2986
  const defaultStatus = statusTypes.find(s => s.category === STATUS_NOT_ACTIONED);
2812
- statusType = _objectSpread$5(_objectSpread$5({}, defaultStatus), {}, {
2987
+ statusType = _objectSpread$4(_objectSpread$4({}, defaultStatus), {}, {
2813
2988
  text: status
2814
2989
  });
2815
2990
  }
@@ -2952,7 +3127,7 @@ class Job extends React.Component {
2952
3127
  // Method to handle user assignment
2953
3128
  _defineProperty__default["default"](this, "onAssignUser", async userId => {
2954
3129
  try {
2955
- const res = await maintenanceActions.assignJob(this.state.jobId, userId);
3130
+ const res = await maintenanceActions$1.assignJob(this.state.jobId, userId);
2956
3131
  this.getJob();
2957
3132
  } catch (err) {
2958
3133
  console.error("onAssignUser", err);
@@ -2964,12 +3139,12 @@ class Job extends React.Component {
2964
3139
  this.setState({
2965
3140
  submittingNote: true
2966
3141
  });
2967
- const res = await (this.state.editingNote ? maintenanceActions.editNote(this.state.jobId, this.state.editingNote, this.state.noteInput, this.state.noteAttachments.map(a => {
3142
+ const res = await (this.state.editingNote ? maintenanceActions$1.editNote(this.state.jobId, this.state.editingNote, this.state.noteInput, this.state.noteAttachments.map(a => {
2968
3143
  return {
2969
3144
  Title: a.Title,
2970
3145
  Source: a.Source
2971
3146
  };
2972
- }), this.state.noteImages) : maintenanceActions.addNote(this.state.jobId, this.state.noteInput, this.state.noteAttachments.map(a => {
3147
+ }), this.state.noteImages) : maintenanceActions$1.addNote(this.state.jobId, this.state.noteInput, this.state.noteAttachments.map(a => {
2973
3148
  return {
2974
3149
  Title: a.Title,
2975
3150
  Source: a.Source
@@ -2997,9 +3172,9 @@ class Job extends React.Component {
2997
3172
  });
2998
3173
  return;
2999
3174
  }
3000
- maintenanceActions.deleteNote(this.state.jobId, n.Id);
3175
+ maintenanceActions$1.deleteNote(this.state.jobId, n.Id);
3001
3176
  const newNotes = ___default["default"].filter(this.state.job.Notes, note => note.Id !== n.Id);
3002
- const newJob = _objectSpread$5({}, this.state.job);
3177
+ const newJob = _objectSpread$4({}, this.state.job);
3003
3178
  newJob.Notes = newNotes;
3004
3179
  this.setState({
3005
3180
  job: newJob,
@@ -3035,7 +3210,7 @@ class Job extends React.Component {
3035
3210
  seen: true,
3036
3211
  status: job.status || "Unassigned"
3037
3212
  };
3038
- await maintenanceActions.editJob(update, auth.site);
3213
+ await maintenanceActions$1.editJob(update, auth.site);
3039
3214
  } catch (error) {
3040
3215
  this.setState({
3041
3216
  updating: false
@@ -3083,13 +3258,13 @@ class Job extends React.Component {
3083
3258
  });
3084
3259
  _defineProperty__default["default"](this, "onSelectPriority", async priority => {
3085
3260
  this.setState({
3086
- job: _objectSpread$5(_objectSpread$5({}, this.state.job), {}, {
3261
+ job: _objectSpread$4(_objectSpread$4({}, this.state.job), {}, {
3087
3262
  priority
3088
3263
  }),
3089
3264
  priorityChangerOpen: false
3090
3265
  });
3091
3266
  try {
3092
- const res = await maintenanceActions.editJobPriority(this.state.job.id, priority);
3267
+ const res = await maintenanceActions$1.editJobPriority(this.state.job.id, priority);
3093
3268
  const {
3094
3269
  job
3095
3270
  } = res.data;
@@ -3108,13 +3283,13 @@ class Job extends React.Component {
3108
3283
  });
3109
3284
  _defineProperty__default["default"](this, "onSelectStatus", async status => {
3110
3285
  this.setState({
3111
- job: _objectSpread$5(_objectSpread$5({}, this.state.job), {}, {
3286
+ job: _objectSpread$4(_objectSpread$4({}, this.state.job), {}, {
3112
3287
  status: status
3113
3288
  }),
3114
3289
  statusChangerOpen: false
3115
3290
  });
3116
3291
  try {
3117
- const res = await maintenanceActions.editJobStatus(this.state.job.id, status);
3292
+ const res = await maintenanceActions$1.editJobStatus(this.state.job.id, status);
3118
3293
  const {
3119
3294
  job
3120
3295
  } = res.data;
@@ -3127,7 +3302,7 @@ class Job extends React.Component {
3127
3302
  }
3128
3303
  });
3129
3304
  this.state = {
3130
- jobId: Helper$3.safeReadParams(props, "jobId") ? props.match.params.jobId : null,
3305
+ jobId: Helper$2.safeReadParams(props, "jobId") ? props.match.params.jobId : null,
3131
3306
  job: null,
3132
3307
  showingSelector: false,
3133
3308
  updating: false,
@@ -3330,7 +3505,7 @@ class Job extends React.Component {
3330
3505
  }, /*#__PURE__*/React__default["default"].createElement("div", {
3331
3506
  className: "imageGrid_image",
3332
3507
  style: {
3333
- backgroundImage: "url('".concat(Helper$3.get1400(image), "')"),
3508
+ backgroundImage: "url('".concat(Helper$2.get1400(image), "')"),
3334
3509
  width: size,
3335
3510
  height: size
3336
3511
  }
@@ -3527,7 +3702,7 @@ class Job extends React.Component {
3527
3702
  }, /*#__PURE__*/React__default["default"].createElement("div", {
3528
3703
  className: "maintenanceNote_top"
3529
3704
  }, this.props.auth && this.props.auth.user && this.props.auth.user.Id === note.User.id && /*#__PURE__*/React__default["default"].createElement(Components$3.SVGIcon, {
3530
- colour: Colours$2.COLOUR_DUSK_LIGHT,
3705
+ colour: Colours$1.COLOUR_DUSK_LIGHT,
3531
3706
  icon: "more15",
3532
3707
  className: "maintenanceNote_moreIcon",
3533
3708
  onClick: () => this.onOpenNoteMenu(index)
@@ -3545,7 +3720,7 @@ class Job extends React.Component {
3545
3720
  }]
3546
3721
  })), /*#__PURE__*/React__default["default"].createElement("p", {
3547
3722
  className: "maintenanceNote_text"
3548
- }, 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));
3723
+ }, 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));
3549
3724
  }
3550
3725
  renderAssignment() {
3551
3726
  const {
@@ -3578,7 +3753,7 @@ class Job extends React.Component {
3578
3753
  }, moment__default["default"].utc(e.timestamp).local().format("D MMM YYYY h:mma")), /*#__PURE__*/React__default["default"].createElement("div", {
3579
3754
  className: "statusLabel statusLabel-large statusLabel-full",
3580
3755
  style: {
3581
- backgroundColor: Colours$2.COLOUR_DUSK
3756
+ backgroundColor: Colours$1.COLOUR_DUSK
3582
3757
  }
3583
3758
  }, /*#__PURE__*/React__default["default"].createElement("span", {
3584
3759
  className: "statusLabel_text"
@@ -3586,7 +3761,7 @@ class Job extends React.Component {
3586
3761
  }
3587
3762
  renderExternalSyncEntry(e, i) {
3588
3763
  const isSuccess = e.EntryType === "ExternalIDSet";
3589
- const backgroundColor = isSuccess ? Colours$2.COLOUR_GREEN : Colours$2.COLOUR_RED; // Green for success, red for failure
3764
+ const backgroundColor = isSuccess ? Colours$1.COLOUR_GREEN : Colours$1.COLOUR_RED; // Green for success, red for failure
3590
3765
 
3591
3766
  return /*#__PURE__*/React__default["default"].createElement("div", {
3592
3767
  className: "ticketHistoryEntry",
@@ -3646,7 +3821,7 @@ class Job extends React.Component {
3646
3821
  return /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
3647
3822
  style: {
3648
3823
  fontSize: 20,
3649
- color: Colours$2.COLOUR_DUSK_LIGHT,
3824
+ color: Colours$1.COLOUR_DUSK_LIGHT,
3650
3825
  marginLeft: 8
3651
3826
  },
3652
3827
  name: "spinner fa-pulse fa-fw"
@@ -3656,7 +3831,7 @@ class Job extends React.Component {
3656
3831
  className: "statusLabel pointer",
3657
3832
  onClick: this.onRetrySync,
3658
3833
  style: {
3659
- backgroundColor: Colours$2.COLOUR_RED,
3834
+ backgroundColor: Colours$1.COLOUR_RED,
3660
3835
  marginLeft: 8
3661
3836
  }
3662
3837
  }, /*#__PURE__*/React__default["default"].createElement("span", {
@@ -3677,7 +3852,7 @@ class Job extends React.Component {
3677
3852
  className: "userStatusIcon",
3678
3853
  name: "times-circle",
3679
3854
  style: {
3680
- color: Colours$2.COLOUR_RED
3855
+ color: Colours$1.COLOUR_RED
3681
3856
  }
3682
3857
  }), " ", retrySyncError);
3683
3858
  }
@@ -3690,7 +3865,7 @@ class Job extends React.Component {
3690
3865
  className: "userStatusIcon",
3691
3866
  name: "check-circle",
3692
3867
  style: {
3693
- color: Colours$2.COLOUR_GREEN
3868
+ color: Colours$1.COLOUR_GREEN
3694
3869
  }
3695
3870
  }), " ", "Sync retry initiated. Check back shortly for results.");
3696
3871
  }
@@ -3703,7 +3878,7 @@ class Job extends React.Component {
3703
3878
  className: "userStatusIcon",
3704
3879
  name: "times-circle",
3705
3880
  style: {
3706
- color: Colours$2.COLOUR_RED
3881
+ color: Colours$1.COLOUR_RED
3707
3882
  }
3708
3883
  }), " ", "External sync failed. Use the retry button to attempt again.");
3709
3884
  }
@@ -3747,11 +3922,11 @@ class Job extends React.Component {
3747
3922
  } = this.state;
3748
3923
  if (!job || !job.history) return null;
3749
3924
  const source = ___default["default"].sortBy([...job.history.map(e => {
3750
- return _objectSpread$5(_objectSpread$5({}, e), {}, {
3925
+ return _objectSpread$4(_objectSpread$4({}, e), {}, {
3751
3926
  EntryType: e.EntryType || "status"
3752
3927
  });
3753
3928
  }), ...(job.Notes || []).map(e => {
3754
- return _objectSpread$5(_objectSpread$5({}, e), {}, {
3929
+ return _objectSpread$4(_objectSpread$4({}, e), {}, {
3755
3930
  timestamp: e.Timestamp,
3756
3931
  EntryType: "note"
3757
3932
  });
@@ -3900,7 +4075,7 @@ class Job extends React.Component {
3900
4075
  onClick: () => {
3901
4076
  this.onSelectAssignee();
3902
4077
  },
3903
- colour: Colours$2.COLOUR_DUSK
4078
+ colour: Colours$1.COLOUR_DUSK
3904
4079
  })
3905
4080
  }));
3906
4081
  } else {
@@ -3974,14 +4149,14 @@ var Job$1 = reactRedux.connect(mapStateToProps$3, {
3974
4149
  jobStatusesUpdate
3975
4150
  })(reactRouter.withRouter(Job));
3976
4151
 
3977
- 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; }
3978
- 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; }
4152
+ 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; }
4153
+ 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; }
3979
4154
  const {
3980
4155
  Actions,
3981
4156
  Components: Components$2,
3982
- Helper: Helper$2,
4157
+ Helper: Helper$1,
3983
4158
  Session: Session$2,
3984
- Colours: Colours$1,
4159
+ Colours,
3985
4160
  Apis
3986
4161
  } = PlussCore__namespace;
3987
4162
  class AddJob extends React.Component {
@@ -3991,7 +4166,7 @@ class AddJob extends React.Component {
3991
4166
  _this = this;
3992
4167
  _defineProperty__default["default"](this, "getJob", async () => {
3993
4168
  try {
3994
- const res = await maintenanceActions.getJob(this.props.auth.site, this.state.jobId);
4169
+ const res = await maintenanceActions$1.getJob(this.props.auth.site, this.state.jobId);
3995
4170
  res.data.location = res.data.site;
3996
4171
  const {
3997
4172
  userID,
@@ -4000,7 +4175,7 @@ class AddJob extends React.Component {
4000
4175
  type,
4001
4176
  customFields
4002
4177
  } = res.data;
4003
- this.setState(_objectSpread$4(_objectSpread$4({}, res.data), {}, {
4178
+ this.setState(_objectSpread$3(_objectSpread$3({}, res.data), {}, {
4004
4179
  prevType: type,
4005
4180
  prevCustomFileds: customFields,
4006
4181
  type,
@@ -4025,7 +4200,7 @@ class AddJob extends React.Component {
4025
4200
  });
4026
4201
  _defineProperty__default["default"](this, "getJobTypes", async () => {
4027
4202
  try {
4028
- const res = await maintenanceActions.getJobTypes(this.props.auth.site);
4203
+ const res = await maintenanceActions$1.getJobTypes(this.props.auth.site);
4029
4204
  this.setState({
4030
4205
  types: res.data
4031
4206
  });
@@ -4248,7 +4423,7 @@ class AddJob extends React.Component {
4248
4423
  event.target.value = "";
4249
4424
  });
4250
4425
  _defineProperty__default["default"](this, "onToggleDatePicker", qId => {
4251
- const showDate = _objectSpread$4({}, this.state.showDate);
4426
+ const showDate = _objectSpread$3({}, this.state.showDate);
4252
4427
  showDate[qId] = !showDate[qId];
4253
4428
  this.setState({
4254
4429
  showDate
@@ -4285,7 +4460,7 @@ class AddJob extends React.Component {
4285
4460
  customFields: this.state.customFields
4286
4461
  };
4287
4462
  if (this.state.id != null) {
4288
- maintenanceActions.editJob(job, this.props.auth.site).then(res => {
4463
+ maintenanceActions$1.editJob(job, this.props.auth.site).then(res => {
4289
4464
  this.setState({
4290
4465
  success: true,
4291
4466
  updating: false
@@ -4299,12 +4474,12 @@ class AddJob extends React.Component {
4299
4474
  });
4300
4475
  } else {
4301
4476
  // Create New Job
4302
- maintenanceActions.createJob(job).then(res => {
4477
+ maintenanceActions$1.createJob(job).then(res => {
4303
4478
  this.setState({
4304
4479
  success: true,
4305
4480
  updating: false
4306
4481
  });
4307
- this.props.jobsUpdate(this.props.auth.site);
4482
+ // JobList fetches fresh data on mount — no action needed here
4308
4483
  }).catch(res => {
4309
4484
  this.setState({
4310
4485
  updating: false
@@ -4337,7 +4512,7 @@ class AddJob extends React.Component {
4337
4512
  if (___default["default"].isNil(answer) || ___default["default"].isEmpty(answer)) return true;
4338
4513
  switch (type) {
4339
4514
  case "email":
4340
- return Helper$2.isEmail(answer);
4515
+ return Helper$1.isEmail(answer);
4341
4516
  case "date":
4342
4517
  return moment__default["default"](answer, "YYYY-MM-DD", true).isValid();
4343
4518
  case "time":
@@ -4358,7 +4533,7 @@ class AddJob extends React.Component {
4358
4533
  this.customImageInputs = {};
4359
4534
  this.customDocumentInputs = {};
4360
4535
  this.state = {
4361
- jobId: Helper$2.safeReadParams(this.props, "jobId") ? this.props.match.params.jobId : null,
4536
+ jobId: Helper$1.safeReadParams(this.props, "jobId") ? this.props.match.params.jobId : null,
4362
4537
  job: null,
4363
4538
  showingSelector: false,
4364
4539
  updating: false,
@@ -4710,7 +4885,7 @@ class AddJob extends React.Component {
4710
4885
  return /*#__PURE__*/React__default["default"].createElement("p", {
4711
4886
  className: "visitorSignIn_text-staticText",
4712
4887
  key: fieldId
4713
- }, Helper$2.toParagraphed(field.label, {
4888
+ }, Helper$1.toParagraphed(field.label, {
4714
4889
  marginTop: 10
4715
4890
  }));
4716
4891
  case "date":
@@ -4729,7 +4904,7 @@ class AddJob extends React.Component {
4729
4904
  alwaysShowLabel: true,
4730
4905
  readOnly: true,
4731
4906
  rightContent: !___default["default"].isEmpty(field.answer) && /*#__PURE__*/React__default["default"].createElement(Components$2.SVGIcon, {
4732
- colour: Colours$1.COLOUR_DUSK_LIGHT,
4907
+ colour: Colours.COLOUR_DUSK_LIGHT,
4733
4908
  icon: "close",
4734
4909
  className: "timepicker_clear",
4735
4910
  onClick: () => this.onChangeDateAnswer(fieldId, undefined, false)
@@ -4762,7 +4937,7 @@ class AddJob extends React.Component {
4762
4937
  }
4763
4938
  }),
4764
4939
  rightContent: !___default["default"].isEmpty(field.answer) && /*#__PURE__*/React__default["default"].createElement(Components$2.SVGIcon, {
4765
- colour: Colours$1.COLOUR_DUSK_LIGHT,
4940
+ colour: Colours.COLOUR_DUSK_LIGHT,
4766
4941
  icon: "close",
4767
4942
  className: "timepicker_clear",
4768
4943
  onClick: () => this.onChangeTimeAnswer(fieldId, undefined)
@@ -4965,11 +5140,10 @@ const mapStateToProps$2 = state => {
4965
5140
  return {
4966
5141
  auth,
4967
5142
  strings: state.strings && state.strings.config || {},
4968
- optionOnlyForResidents: Helper$2.getSiteSettingFromState(state, values.optionOnlyForResidents)
5143
+ optionOnlyForResidents: Helper$1.getSiteSettingFromState(state, values.optionOnlyForResidents)
4969
5144
  };
4970
5145
  };
4971
5146
  var AddJob$1 = reactRedux.connect(mapStateToProps$2, {
4972
- jobsUpdate,
4973
5147
  jobsLoaded,
4974
5148
  addRecentlyCreated: Actions.addRecentlyCreated
4975
5149
  })(reactRouter.withRouter(AddJob));
@@ -4977,7 +5151,7 @@ var AddJob$1 = reactRedux.connect(mapStateToProps$2, {
4977
5151
  const {
4978
5152
  Components: Components$1,
4979
5153
  Session: Session$1,
4980
- Helper: Helper$1
5154
+ Helper
4981
5155
  } = PlussCore__namespace;
4982
5156
  const DEFAULT_FIELD = {
4983
5157
  type: 'text',
@@ -4991,7 +5165,7 @@ class AddJobType extends React.Component {
4991
5165
  super(props);
4992
5166
  _defineProperty__default["default"](this, "getJobType", async () => {
4993
5167
  try {
4994
- const res = await maintenanceActions.getJobType(this.props.auth.site, this.state.jobTypeId);
5168
+ const res = await maintenanceActions$1.getJobType(this.props.auth.site, this.state.jobTypeId);
4995
5169
  const {
4996
5170
  typeName,
4997
5171
  email,
@@ -5020,7 +5194,7 @@ class AddJobType extends React.Component {
5020
5194
  const {
5021
5195
  jobTypeEmail
5022
5196
  } = this.state;
5023
- return !___default["default"].isEmpty(jobTypeEmail) && Helper$1.isEmail(jobTypeEmail);
5197
+ return !___default["default"].isEmpty(jobTypeEmail) && Helper.isEmail(jobTypeEmail);
5024
5198
  });
5025
5199
  _defineProperty__default["default"](this, "isJobTypeValid", () => {
5026
5200
  const {
@@ -5163,9 +5337,9 @@ class AddJobType extends React.Component {
5163
5337
  }, async () => {
5164
5338
  try {
5165
5339
  if (jobTypeId) {
5166
- await maintenanceActions.editJobType(site, jobTypeId, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5340
+ await maintenanceActions$1.editJobType(site, jobTypeId, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5167
5341
  } else {
5168
- await maintenanceActions.addJobType(site, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5342
+ await maintenanceActions$1.addJobType(site, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5169
5343
  }
5170
5344
  this.props.jobTypesUpdate(site);
5171
5345
  this.setState({
@@ -5222,7 +5396,7 @@ class AddJobType extends React.Component {
5222
5396
  }];
5223
5397
  this.state = {
5224
5398
  loading: false,
5225
- jobTypeId: Helper$1.safeReadParams(this.props, 'jobTypeId') ? this.props.match.params.jobTypeId : null,
5399
+ jobTypeId: Helper.safeReadParams(this.props, 'jobTypeId') ? this.props.match.params.jobTypeId : null,
5226
5400
  jobTypeName: '',
5227
5401
  jobTypeEmail: '',
5228
5402
  jobTypeDescription: '',
@@ -5771,14 +5945,10 @@ var AddJobType$1 = reactRedux.connect(mapStateToProps$1, {
5771
5945
  jobTypesUpdate
5772
5946
  })(reactRouter.withRouter(AddJobType));
5773
5947
 
5774
- 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; }
5775
- 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; }
5776
5948
  const {
5777
5949
  Analytics: Analytics$1,
5778
5950
  Session,
5779
- Components,
5780
- Helper,
5781
- Colours
5951
+ Components
5782
5952
  } = PlussCore__namespace;
5783
5953
  const getInitialState = () => ({
5784
5954
  requests: 0,
@@ -5798,21 +5968,10 @@ const AnalyticsHub = _ref => {
5798
5968
  auth,
5799
5969
  prevText,
5800
5970
  dayCount,
5801
- strings,
5802
- userType,
5803
- userCategory,
5804
- selectedSites
5971
+ strings
5805
5972
  } = _ref;
5806
5973
  const [analyticsData, setAnalyticsData] = React.useState(getInitialState());
5807
5974
  const [isExportOpen, setIsExportOpen] = React.useState(false);
5808
- const [failedSites, setFailedSites] = React.useState([]);
5809
- const [comparisonData, setComparisonData] = React.useState({
5810
- requests: [],
5811
- completedRequests: [],
5812
- comments: [],
5813
- isLoading: true
5814
- });
5815
- const comparisonMode = selectedSites && selectedSites.length > 1;
5816
5975
  const hasAccess = Session.validateAccess(auth.site, values.permissionMaintenanceTracking, auth);
5817
5976
  if (!hasAccess) {
5818
5977
  return null;
@@ -5824,129 +5983,50 @@ const AnalyticsHub = _ref => {
5824
5983
  return strings.sideNav[key];
5825
5984
  })();
5826
5985
  const exportColumns = [{
5827
- label: "Select All",
5828
- key: ""
5829
- }, ...(comparisonMode ? [{
5830
- label: "Site",
5831
- key: "site"
5832
- }] : []), {
5833
- label: "Start Date",
5834
- key: "startDate"
5986
+ label: 'Select All',
5987
+ key: ''
5835
5988
  }, {
5836
- label: "End Date",
5837
- key: "endDate"
5989
+ label: 'Start Date',
5990
+ key: 'startDate'
5991
+ }, {
5992
+ label: 'End Date',
5993
+ key: 'endDate'
5838
5994
  }, {
5839
5995
  label: "".concat(values.textSingularName, "s"),
5840
- key: "requests"
5996
+ key: 'requests'
5841
5997
  }, {
5842
5998
  label: "Completed ".concat(values.textSingularName, "s"),
5843
- key: "completedRequests"
5999
+ key: 'completedRequests'
5844
6000
  }, {
5845
- label: "Comments",
5846
- key: "comments"
6001
+ label: 'Comments',
6002
+ key: 'comments'
5847
6003
  }];
5848
6004
  React.useEffect(() => {
5849
6005
  getData();
5850
- }, [startTime, endTime, userType, userCategory, selectedSites]);
6006
+ }, [startTime, endTime]);
5851
6007
  const getData = async () => {
5852
- try {
5853
- if (comparisonMode) {
5854
- setComparisonData({
5855
- requests: [],
5856
- completedRequests: [],
5857
- comments: [],
5858
- isLoading: true
5859
- });
5860
- const multiSiteResultsObj = await Analytics$1.fetchMultiSiteData(selectedSites, async site => {
5861
- const {
5862
- data
5863
- } = await analyticsActions.getAggregateEntityStats(site, values.analyticsKey, startTime, endTime, true, {
5864
- userType,
5865
- userCategory
5866
- });
5867
- return data;
5868
- });
5869
- const roles = auth.user.Roles;
5870
- const failed = Object.entries(multiSiteResultsObj).filter(_ref2 => {
5871
- let [, data] = _ref2;
5872
- return data === null;
5873
- }).map(_ref3 => {
5874
- let [site] = _ref3;
5875
- return Helper.getSiteNameFromRoles(site, roles);
5876
- });
5877
- setFailedSites(failed);
5878
- const multiSiteResults = Object.entries(multiSiteResultsObj).filter(_ref4 => {
5879
- let [, data] = _ref4;
5880
- return data !== null;
5881
- }).map(_ref5 => {
5882
- let [site, data] = _ref5;
5883
- return {
5884
- site,
5885
- data
5886
- };
5887
- });
5888
- const buildComparison = (activityKey, countType) => multiSiteResults.map(result => ({
5889
- name: Helper.getSiteNameFromRoles(result.site, roles),
5890
- value: Analytics$1.countActivities(result.data, activityKey, countType)
5891
- }));
5892
- setComparisonData({
5893
- requests: buildComparison("Request", "total"),
5894
- completedRequests: buildComparison("RequestCompleted", "unique"),
5895
- comments: buildComparison("Comment", "total"),
5896
- isLoading: false
5897
- });
5898
- } else {
5899
- setAnalyticsData(getInitialState());
5900
- const site = selectedSites && selectedSites.length === 1 ? selectedSites[0] : auth.site;
5901
- const timeDifference = endTime - startTime;
5902
- const [currentStatsResponse, prevStatsResponse] = await Promise.all([analyticsActions.getAggregateEntityStats(site, values.analyticsKey, startTime, endTime, true, {
5903
- userType,
5904
- userCategory
5905
- }), analyticsActions.getAggregateEntityStats(site, values.analyticsKey, startTime - timeDifference, startTime, true, {
5906
- userType,
5907
- userCategory
5908
- })]);
5909
- const data = {
5910
- requests: Analytics$1.countActivities(currentStatsResponse.data, "Request", "total"),
5911
- prevRequests: Analytics$1.countActivities(prevStatsResponse.data, "Request", "total"),
5912
- completedRequests: Analytics$1.countActivities(currentStatsResponse.data, "RequestCompleted", "unique"),
5913
- prevCompletedRequests: Analytics$1.countActivities(prevStatsResponse.data, "RequestCompleted", "unique"),
5914
- comments: Analytics$1.countActivities(currentStatsResponse.data, "Comment", "total"),
5915
- prevComments: Analytics$1.countActivities(prevStatsResponse.data, "Comment", "total"),
5916
- isLoading: false
5917
- };
5918
- setAnalyticsData(data);
5919
- }
5920
- } catch (err) {
5921
- if (comparisonMode) {
5922
- setComparisonData(prev => _objectSpread$3(_objectSpread$3({}, prev), {}, {
5923
- isLoading: false
5924
- }));
5925
- } else {
5926
- setAnalyticsData(prev => _objectSpread$3(_objectSpread$3({}, prev), {}, {
5927
- isLoading: false
5928
- }));
5929
- }
5930
- }
6008
+ setAnalyticsData(getInitialState());
6009
+ // Load analytics data here using startTime and endTime
6010
+ const timeDifference = endTime - startTime;
6011
+ 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)]);
6012
+ const data = {
6013
+ requests: Analytics$1.countActivities(currentStatsResponse.data, 'Request', 'total'),
6014
+ prevRequests: Analytics$1.countActivities(prevStatsResponse.data, 'Request', 'total'),
6015
+ completedRequests: Analytics$1.countActivities(currentStatsResponse.data, 'RequestCompleted', 'unique'),
6016
+ prevCompletedRequests: Analytics$1.countActivities(prevStatsResponse.data, 'RequestCompleted', 'unique'),
6017
+ comments: Analytics$1.countActivities(currentStatsResponse.data, 'Comment', 'total'),
6018
+ prevComments: Analytics$1.countActivities(prevStatsResponse.data, 'Comment', 'total'),
6019
+ isLoading: false
6020
+ };
6021
+ setAnalyticsData(data);
5931
6022
  };
5932
6023
  const isReadyToOpenCSV = () => {
5933
- return comparisonMode ? !comparisonData.isLoading : !analyticsData.isLoading;
6024
+ return !analyticsData.isLoading;
5934
6025
  };
5935
6026
  const getExportSource = () => {
5936
- if (comparisonMode) {
5937
- const sites = comparisonData.requests || [];
5938
- return sites.map((site, i) => ({
5939
- site: site.name,
5940
- startDate: moment__default["default"](startTime + 1).format("D-MM-YYYY"),
5941
- endDate: moment__default["default"](endTime).format("D-MM-YYYY"),
5942
- requests: site.value,
5943
- completedRequests: comparisonData.completedRequests[i] && comparisonData.completedRequests[i].value || 0,
5944
- comments: comparisonData.comments[i] && comparisonData.comments[i].value || 0
5945
- }));
5946
- }
5947
6027
  return [{
5948
- startDate: moment__default["default"](startTime + 1).format("D-MM-YYYY"),
5949
- endDate: moment__default["default"](endTime).format("D-MM-YYYY"),
6028
+ startDate: moment__default["default"](startTime + 1).format('D-MM-YYYY'),
6029
+ endDate: moment__default["default"](endTime).format('D-MM-YYYY'),
5950
6030
  requests: analyticsData.requests,
5951
6031
  completedRequests: analyticsData.completedRequests,
5952
6032
  comments: analyticsData.comments
@@ -5957,14 +6037,13 @@ const AnalyticsHub = _ref => {
5957
6037
  return null;
5958
6038
  }
5959
6039
  const source = getExportSource();
5960
- const filterSuffix = [userType, userCategory].filter(Boolean).map(f => f.toLowerCase().replace(/\s+/g, "-")).join("_");
5961
6040
  return /*#__PURE__*/React__default["default"].createElement(Components.ExportCsvPopup, {
5962
6041
  onClose: () => {
5963
6042
  setIsExportOpen(false);
5964
6043
  },
5965
6044
  columns: exportColumns,
5966
6045
  source: source,
5967
- filename: "".concat(values.analyticsKey, "analytics").concat(comparisonMode ? "_comparison" : "").concat(filterSuffix ? "_".concat(filterSuffix) : "", "_").concat(source[0].startDate, "_").concat(source[0].endDate, ".csv")
6046
+ filename: "".concat(values.analyticsKey, "analytics_").concat(source[0].startDate, "_").concat(source[0].endDate, ".csv")
5968
6047
  });
5969
6048
  };
5970
6049
  return /*#__PURE__*/React__default["default"].createElement("div", {
@@ -5981,68 +6060,33 @@ const AnalyticsHub = _ref => {
5981
6060
  },
5982
6061
  isActive: isReadyToOpenCSV(),
5983
6062
  leftIcon: "file-code-o"
5984
- }, "Export CSV")), failedSites.length > 0 && /*#__PURE__*/React__default["default"].createElement(Components.Text, {
5985
- type: "help",
5986
- style: {
5987
- color: Colours.COLOUR_RED
5988
- }
5989
- }, "Data unavailable for: ", failedSites.join(", ")), /*#__PURE__*/React__default["default"].createElement("div", {
6063
+ }, "Export CSV")), /*#__PURE__*/React__default["default"].createElement("div", {
5990
6064
  className: "analyticsSection dashboardSection_content"
5991
- }, (() => {
5992
- const chartSuffix = [selectedSites && selectedSites.length > 0 ? "&sites=".concat(selectedSites.join(",")) : "", userType ? "&userType=".concat(encodeURIComponent(userType)) : "", userCategory ? "&userCategory=".concat(encodeURIComponent(userCategory)) : ""].join("");
5993
- if (comparisonMode) {
5994
- return /*#__PURE__*/React__default["default"].createElement("div", {
5995
- style: {
5996
- display: "flex",
5997
- flexDirection: "column",
5998
- gap: 16
5999
- }
6000
- }, /*#__PURE__*/React__default["default"].createElement(Components.ComparisonStatBox, {
6001
- title: "".concat(featureTitle, " Requests"),
6002
- data: comparisonData.requests,
6003
- prevText: prevText,
6004
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Request&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6005
- isLoading: comparisonData.isLoading
6006
- }), /*#__PURE__*/React__default["default"].createElement(Components.ComparisonStatBox, {
6007
- title: "Completed ".concat(featureTitle, " Requests"),
6008
- data: comparisonData.completedRequests,
6009
- prevText: prevText,
6010
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=RequestCompleted&countType=unique&dayCount=").concat(dayCount).concat(chartSuffix),
6011
- isLoading: comparisonData.isLoading
6012
- }), /*#__PURE__*/React__default["default"].createElement(Components.ComparisonStatBox, {
6013
- title: "".concat(featureTitle, " Comments"),
6014
- data: comparisonData.comments,
6015
- prevText: prevText,
6016
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Comment&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6017
- isLoading: comparisonData.isLoading
6018
- }));
6019
- }
6020
- return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6021
- title: "".concat(featureTitle, " Requests"),
6022
- icon: freeSolidSvgIcons.faWrench,
6023
- value: analyticsData.requests,
6024
- previousValue: analyticsData.prevRequests,
6025
- prevText: prevText,
6026
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Request&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6027
- isLoading: analyticsData.isLoading
6028
- }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6029
- title: "Completed ".concat(featureTitle, " Requests"),
6030
- icon: freeSolidSvgIcons.faCircleCheck,
6031
- value: analyticsData.completedRequests,
6032
- previousValue: analyticsData.prevCompletedRequests,
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: analyticsData.isLoading
6036
- }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6037
- title: "".concat(featureTitle, " Comments"),
6038
- icon: freeSolidSvgIcons.faComment,
6039
- value: analyticsData.comments,
6040
- previousValue: analyticsData.prevComments,
6041
- prevText: prevText,
6042
- viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Comment&countType=total&dayCount=").concat(dayCount).concat(chartSuffix),
6043
- isLoading: analyticsData.isLoading
6044
- }));
6045
- })()));
6065
+ }, /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6066
+ title: "".concat(featureTitle, " Requests"),
6067
+ icon: freeSolidSvgIcons.faWrench,
6068
+ value: analyticsData.requests,
6069
+ previousValue: analyticsData.prevRequests,
6070
+ prevText: prevText,
6071
+ viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Request&countType=total&dayCount=").concat(dayCount),
6072
+ isLoading: analyticsData.isLoading
6073
+ }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6074
+ title: "Completed ".concat(featureTitle, " Requests"),
6075
+ icon: freeSolidSvgIcons.faCircleCheck,
6076
+ value: analyticsData.completedRequests,
6077
+ previousValue: analyticsData.prevCompletedRequests,
6078
+ prevText: prevText,
6079
+ viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=RequestCompleted&countType=unique&dayCount=").concat(dayCount),
6080
+ isLoading: analyticsData.isLoading
6081
+ }), /*#__PURE__*/React__default["default"].createElement(Components.StatBox, {
6082
+ title: "".concat(featureTitle, " Comments"),
6083
+ icon: freeSolidSvgIcons.faComment,
6084
+ value: analyticsData.comments,
6085
+ previousValue: analyticsData.prevComments,
6086
+ prevText: prevText,
6087
+ viewGraphLink: "/chart?entity=".concat(values.analyticsKey, "&startTime=").concat(startTime, "&endTime=").concat(endTime, "&key=Comment&countType=total&dayCount=").concat(dayCount),
6088
+ isLoading: analyticsData.isLoading
6089
+ })));
6046
6090
  };
6047
6091
  const mapStateToProps = state => {
6048
6092
  const {