@plusscommunities/pluss-maintenance-web-a 1.1.36 → 1.1.37-beta.0

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.
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 = {
@@ -250,12 +250,12 @@ const JOBS_HIDE_SEEN = values.actionJobsHideSeen;
250
250
  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; }
251
251
  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; }
252
252
  const {
253
- Helper: Helper$5,
253
+ Helper: Helper$4,
254
254
  Session: Session$9
255
255
  } = PlussCore__namespace;
256
- const maintenanceActions = {
256
+ const maintenanceActions$1 = {
257
257
  getJobType: (site, typeId) => {
258
- let url = Helper$5.getUrl(values.serviceKey, 'getjobtype');
258
+ let url = Helper$4.getUrl(values.serviceKey, 'getjobtype');
259
259
  return Session$9.authedFunction({
260
260
  method: 'POST',
261
261
  url,
@@ -266,7 +266,7 @@ const maintenanceActions = {
266
266
  });
267
267
  },
268
268
  getJobTypes: (site, id) => {
269
- let url = Helper$5.getUrl(values.serviceKey, 'getjobtypes');
269
+ let url = Helper$4.getUrl(values.serviceKey, 'getjobtypes');
270
270
  return Session$9.authedFunction({
271
271
  method: 'POST',
272
272
  url,
@@ -276,7 +276,7 @@ const maintenanceActions = {
276
276
  });
277
277
  },
278
278
  getJob: (site, id) => {
279
- let url = Helper$5.getUrl(values.serviceKey, 'getJob');
279
+ let url = Helper$4.getUrl(values.serviceKey, 'getJob');
280
280
  return Session$9.authedFunction({
281
281
  method: 'POST',
282
282
  url,
@@ -287,7 +287,7 @@ const maintenanceActions = {
287
287
  });
288
288
  },
289
289
  getJobByJobId: (site, jobId) => {
290
- let url = Helper$5.getUrl(values.serviceKey, 'getJob');
290
+ let url = Helper$4.getUrl(values.serviceKey, 'getJob');
291
291
  return Session$9.authedFunction({
292
292
  method: 'POST',
293
293
  url,
@@ -302,7 +302,7 @@ const maintenanceActions = {
302
302
  let type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
303
303
  return Session$9.authedFunction({
304
304
  method: 'POST',
305
- url: Helper$5.getUrl(values.serviceKey, 'getJobs'),
305
+ url: Helper$4.getUrl(values.serviceKey, 'getJobs'),
306
306
  data: {
307
307
  site,
308
308
  status,
@@ -310,7 +310,7 @@ const maintenanceActions = {
310
310
  }
311
311
  });
312
312
  },
313
- getJobs2: (site, status, type, lastKey) => {
313
+ getJobs2: (site, status, type, priority, assignee, startTime, endTime, search, lastKey) => {
314
314
  const query = {
315
315
  site
316
316
  };
@@ -320,37 +320,57 @@ const maintenanceActions = {
320
320
  if (type) {
321
321
  query.type = type;
322
322
  }
323
+ if (priority) {
324
+ query.priority = priority;
325
+ }
326
+ if (assignee) {
327
+ query.assignee = assignee;
328
+ }
329
+ if (startTime) {
330
+ query.startTime = startTime;
331
+ }
332
+ if (endTime) {
333
+ query.endTime = endTime;
334
+ }
335
+ if (search) {
336
+ query.search = search;
337
+ }
323
338
  if (lastKey) {
324
339
  query.lastKey = JSON.stringify(lastKey);
325
340
  }
326
341
  return Session$9.authedFunction({
327
342
  method: 'GET',
328
- url: Helper$5.getUrl(values.serviceKey, 'get/requests', query)
343
+ url: Helper$4.getUrl(values.serviceKey, 'get/requests', query)
329
344
  });
330
345
  },
346
+ /**
347
+ * @deprecated Use getJobs2 with pagination instead.
348
+ * This method recursively fetches ALL pages which can be slow for large datasets.
349
+ * Only use for CSV export where all data is needed.
350
+ */
331
351
  getJobsRecursive: function (site, status, type, lastKey) {
332
352
  let jobs = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : [];
333
- return new Promise(resolve => {
334
- maintenanceActions.getJobs2(site, status, type, lastKey).then(jobRes => {
353
+ return new Promise((resolve, reject) => {
354
+ maintenanceActions$1.getJobs2(site, status, type, undefined, undefined, undefined, undefined, undefined, lastKey).then(jobRes => {
335
355
  const newJobs = [...jobs, ...jobRes.data.Items];
336
356
  if (!jobRes.data.LastKey) {
337
357
  return resolve(newJobs);
338
358
  }
339
- return resolve(maintenanceActions.getJobsRecursive(site, status, type, jobRes.data.LastKey, newJobs));
340
- });
359
+ maintenanceActions$1.getJobsRecursive(site, status, type, jobRes.data.LastKey, newJobs).then(resolve).catch(reject);
360
+ }).catch(reject);
341
361
  });
342
362
  },
343
363
  createJob: job => {
344
364
  return Session$9.authedFunction({
345
365
  method: 'POST',
346
- url: Helper$5.getUrl(values.serviceKey, 'sendMaintenance'),
366
+ url: Helper$4.getUrl(values.serviceKey, 'sendMaintenance'),
347
367
  data: _objectSpread$7({}, job)
348
368
  });
349
369
  },
350
370
  editJob: (job, site) => {
351
371
  return Session$9.authedFunction({
352
372
  method: 'POST',
353
- url: Helper$5.getUrl(values.serviceKey, 'editJob'),
373
+ url: Helper$4.getUrl(values.serviceKey, 'editJob'),
354
374
  data: {
355
375
  job,
356
376
  site
@@ -360,7 +380,7 @@ const maintenanceActions = {
360
380
  deleteJob: (site, id) => {
361
381
  return Session$9.authedFunction({
362
382
  method: 'POST',
363
- url: Helper$5.getUrl(values.serviceKey, 'requests/remove'),
383
+ url: Helper$4.getUrl(values.serviceKey, 'requests/remove'),
364
384
  data: {
365
385
  site,
366
386
  id
@@ -370,7 +390,7 @@ const maintenanceActions = {
370
390
  editJobStatus: (id, status) => {
371
391
  return Session$9.authedFunction({
372
392
  method: 'POST',
373
- url: Helper$5.getUrl(values.serviceKey, 'editJobStatus'),
393
+ url: Helper$4.getUrl(values.serviceKey, 'editJobStatus'),
374
394
  data: {
375
395
  id,
376
396
  status
@@ -380,7 +400,7 @@ const maintenanceActions = {
380
400
  editJobPriority: (id, priority) => {
381
401
  return Session$9.authedFunction({
382
402
  method: 'POST',
383
- url: Helper$5.getUrl(values.serviceKey, 'update/priority'),
403
+ url: Helper$4.getUrl(values.serviceKey, 'update/priority'),
384
404
  data: {
385
405
  id,
386
406
  priority
@@ -390,7 +410,7 @@ const maintenanceActions = {
390
410
  assignJob: (jobId, userId) => {
391
411
  return Session$9.authedFunction({
392
412
  method: 'POST',
393
- url: Helper$5.getUrl(values.serviceKey, 'update/assign'),
413
+ url: Helper$4.getUrl(values.serviceKey, 'update/assign'),
394
414
  data: {
395
415
  id: jobId,
396
416
  userId
@@ -400,7 +420,7 @@ const maintenanceActions = {
400
420
  getAssignees: site => {
401
421
  return Session$9.authedFunction({
402
422
  method: 'GET',
403
- url: Helper$5.getUrl(values.serviceKey, 'get/assignees', {
423
+ url: Helper$4.getUrl(values.serviceKey, 'get/assignees', {
404
424
  site
405
425
  })
406
426
  });
@@ -408,7 +428,7 @@ const maintenanceActions = {
408
428
  addNote: (jobId, note, attachments, images) => {
409
429
  return Session$9.authedFunction({
410
430
  method: 'POST',
411
- url: Helper$5.getUrl(values.serviceKey, 'requests/note'),
431
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
412
432
  data: {
413
433
  id: jobId,
414
434
  note,
@@ -421,7 +441,7 @@ const maintenanceActions = {
421
441
  editNote: (jobId, noteId, note, attachments, images) => {
422
442
  return Session$9.authedFunction({
423
443
  method: 'POST',
424
- url: Helper$5.getUrl(values.serviceKey, 'requests/note'),
444
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
425
445
  data: {
426
446
  id: jobId,
427
447
  note,
@@ -435,7 +455,7 @@ const maintenanceActions = {
435
455
  deleteNote: (jobId, noteId) => {
436
456
  return Session$9.authedFunction({
437
457
  method: 'POST',
438
- url: Helper$5.getUrl(values.serviceKey, 'requests/note'),
458
+ url: Helper$4.getUrl(values.serviceKey, 'requests/note'),
439
459
  data: {
440
460
  id: jobId,
441
461
  noteId,
@@ -455,7 +475,7 @@ const maintenanceActions = {
455
475
  };
456
476
  return Session$9.authedFunction({
457
477
  method: 'POST',
458
- url: Helper$5.getUrl(values.serviceKey, 'createJobType'),
478
+ url: Helper$4.getUrl(values.serviceKey, 'createJobType'),
459
479
  data
460
480
  });
461
481
  },
@@ -473,14 +493,14 @@ const maintenanceActions = {
473
493
  if (hasCustomFields && customFields) data.customFields = customFields;
474
494
  return Session$9.authedFunction({
475
495
  method: 'POST',
476
- url: Helper$5.getUrl(values.serviceKey, 'editJobType'),
496
+ url: Helper$4.getUrl(values.serviceKey, 'editJobType'),
477
497
  data
478
498
  });
479
499
  },
480
500
  deleteJobType: (site, id) => {
481
501
  return Session$9.authedFunction({
482
502
  method: 'POST',
483
- url: Helper$5.getUrl(values.serviceKey, 'deleteJobType'),
503
+ url: Helper$4.getUrl(values.serviceKey, 'deleteJobType'),
484
504
  data: {
485
505
  site,
486
506
  id
@@ -490,7 +510,7 @@ const maintenanceActions = {
490
510
  getExternalSync: jobId => {
491
511
  return Session$9.authedFunction({
492
512
  method: 'GET',
493
- url: Helper$5.getUrl(values.serviceKey, 'get/externalsync', {
513
+ url: Helper$4.getUrl(values.serviceKey, 'get/externalsync', {
494
514
  id: jobId
495
515
  })
496
516
  });
@@ -498,7 +518,7 @@ const maintenanceActions = {
498
518
  retrySync: jobId => {
499
519
  return Session$9.authedFunction({
500
520
  method: 'POST',
501
- url: Helper$5.getUrl(values.serviceKey, 'update/retrysync'),
521
+ url: Helper$4.getUrl(values.serviceKey, 'update/retrysync'),
502
522
  data: {
503
523
  id: jobId
504
524
  }
@@ -507,7 +527,7 @@ const maintenanceActions = {
507
527
  };
508
528
 
509
529
  const {
510
- Helper: Helper$4,
530
+ Helper: Helper$3,
511
531
  Session: Session$8
512
532
  } = PlussCore__namespace;
513
533
  const reactionActions = {
@@ -525,7 +545,7 @@ const reactionActions = {
525
545
  }
526
546
  return Session$8.authedFunction({
527
547
  method: 'POST',
528
- url: Helper$4.getUrl('reactions', 'comments/add'),
548
+ url: Helper$3.getUrl('reactions', 'comments/add'),
529
549
  data
530
550
  });
531
551
  },
@@ -548,7 +568,7 @@ const reactionActions = {
548
568
  }
549
569
  return Session$8.authedFunction({
550
570
  method: 'GET',
551
- url: Helper$4.getUrl('reactions', 'comments/get', query)
571
+ url: Helper$3.getUrl('reactions', 'comments/get', query)
552
572
  });
553
573
  }
554
574
  };
@@ -581,30 +601,6 @@ var jobStatusOptions = [
581
601
  }
582
602
  ];
583
603
 
584
- const {
585
- Helper: Helper$3
586
- } = PlussCore__namespace;
587
- const jobsUpdate = (site, isdashboard) => {
588
- return dispatch => {
589
- if (isdashboard) dispatch({
590
- type: JOBS_LOADING
591
- });
592
- maintenanceActions.getJobsRecursive(site).then(res => {
593
- const currentSite = Helper$3.readStorageWithCookie('site');
594
- if (!___default["default"].isEmpty(res) && res[0].site === currentSite) {
595
- dispatch({
596
- type: JOBS_LOADED,
597
- payload: res
598
- });
599
- } else {
600
- dispatch({
601
- type: JOBS_LOADED,
602
- payload: []
603
- });
604
- }
605
- });
606
- };
607
- };
608
604
  const jobsLoaded = events => {
609
605
  return {
610
606
  type: JOBS_LOADED,
@@ -751,7 +747,171 @@ const {
751
747
  } = PlussCore__namespace;
752
748
  class JobList extends React.Component {
753
749
  constructor(props) {
750
+ var _this;
754
751
  super(props);
752
+ _this = this;
753
+ _defineProperty__default["default"](this, "getAssignees", async () => {
754
+ try {
755
+ const res = await maintenanceActions$1.getAssignees(this.props.auth.site);
756
+ this.setState({
757
+ assignees: res.data.Users
758
+ });
759
+ } catch (error) {
760
+ console.error('getAssignees', error);
761
+ }
762
+ });
763
+ /**
764
+ * Build server-side filter params from current filter state.
765
+ * Translates UI filter selections into API query parameters.
766
+ */
767
+ _defineProperty__default["default"](this, "buildFilterParams", () => {
768
+ const {
769
+ selectedStatusFilter,
770
+ selectedTypeFilter,
771
+ selectedPriorityFilter,
772
+ selectedUserFilter,
773
+ selectedTimeFilterStart,
774
+ selectedTimeFilterEnd,
775
+ searchTerm
776
+ } = this.state;
777
+ const {
778
+ statusTypes
779
+ } = this.props;
780
+ const params = {};
781
+
782
+ // Status filter: translate "All Incomplete" into the actual incomplete statuses
783
+ if (selectedStatusFilter) {
784
+ if (selectedStatusFilter === STATUS_IMCOMPLETE) {
785
+ // Exclude completed statuses - pass all non-completed status texts
786
+ const incompleteStatuses = statusTypes.filter(s => s.category !== STATUS_COMPLETED).map(s => s.text);
787
+ if (incompleteStatuses.length > 0) {
788
+ params.status = incompleteStatuses.join(',');
789
+ }
790
+ } else {
791
+ params.status = selectedStatusFilter;
792
+ }
793
+ }
794
+ if (selectedTypeFilter) {
795
+ params.type = selectedTypeFilter;
796
+ }
797
+ if (selectedPriorityFilter) {
798
+ params.priority = selectedPriorityFilter;
799
+ }
800
+ if (selectedUserFilter) {
801
+ params.assignee = selectedUserFilter;
802
+ }
803
+ if (selectedTimeFilterStart) {
804
+ params.startTime = selectedTimeFilterStart;
805
+ }
806
+ if (selectedTimeFilterEnd) {
807
+ params.endTime = selectedTimeFilterEnd;
808
+ }
809
+ if (searchTerm) {
810
+ params.search = searchTerm;
811
+ }
812
+ return params;
813
+ });
814
+ /**
815
+ * Minimum number of items to show before stopping auto-pagination.
816
+ * DynamoDB returns unfiltered pages; the backend filters after query.
817
+ * A single DynamoDB page may yield very few matching results,
818
+ * so we auto-fetch additional pages until we have enough to display.
819
+ */
820
+ _defineProperty__default["default"](this, "MIN_PAGE_SIZE", 50);
821
+ /**
822
+ * Fetch a single page from the server using the given lastKey.
823
+ */
824
+ _defineProperty__default["default"](this, "fetchPage", async function () {
825
+ let lastKey = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
826
+ const {
827
+ auth
828
+ } = _this.props;
829
+ const filters = _this.buildFilterParams();
830
+ return maintenanceActions$1.getJobs2(auth.site, filters.status, filters.type, filters.priority, filters.assignee, filters.startTime, filters.endTime, filters.search, lastKey);
831
+ });
832
+ /**
833
+ * Fetch the first page of jobs with current filters.
834
+ * Auto-paginates if the server returns fewer items than MIN_PAGE_SIZE
835
+ * (because DynamoDB pages are unfiltered — a single page may yield
836
+ * very few results after server-side filtering).
837
+ */
838
+ _defineProperty__default["default"](this, "fetchJobs", async () => {
839
+ this.setState({
840
+ loading: true
841
+ }, async () => {
842
+ try {
843
+ let allJobs = [];
844
+ let lastKey = null;
845
+
846
+ // Keep fetching pages until we have enough items or run out of data
847
+ do {
848
+ const res = await this.fetchPage(lastKey);
849
+ const items = res.data.Items || [];
850
+ lastKey = res.data.LastKey || null;
851
+ allJobs = [...allJobs, ...items];
852
+ } while (lastKey && allJobs.length < this.MIN_PAGE_SIZE);
853
+ this.setState({
854
+ jobs: allJobs,
855
+ lastKey,
856
+ hasMore: !!lastKey,
857
+ loading: false
858
+ });
859
+
860
+ // Sync to Redux so other components (e.g. Job detail) can access
861
+ this.props.jobsLoaded(allJobs);
862
+
863
+ // Update requesters list for the requester filter
864
+ this.setRequesters(allJobs);
865
+ } catch (error) {
866
+ console.error('fetchJobs', error);
867
+ this.setState({
868
+ loading: false
869
+ });
870
+ }
871
+ });
872
+ });
873
+ /**
874
+ * Load the next page of jobs and append to the existing list.
875
+ * Also auto-paginates to fill up to MIN_PAGE_SIZE new items.
876
+ */
877
+ _defineProperty__default["default"](this, "loadMore", async () => {
878
+ const {
879
+ lastKey
880
+ } = this.state;
881
+ this.setState({
882
+ loadingMore: true
883
+ }, async () => {
884
+ try {
885
+ let newJobs = [];
886
+ let currentLastKey = lastKey;
887
+ const existingCount = this.state.jobs.length;
888
+
889
+ // Keep fetching pages until we have enough new items or run out of data
890
+ do {
891
+ const res = await this.fetchPage(currentLastKey);
892
+ const items = res.data.Items || [];
893
+ currentLastKey = res.data.LastKey || null;
894
+ newJobs = [...newJobs, ...items];
895
+ } while (currentLastKey && existingCount + newJobs.length < existingCount + this.MIN_PAGE_SIZE);
896
+ this.setState(prevState => ({
897
+ jobs: [...prevState.jobs, ...newJobs],
898
+ lastKey: currentLastKey,
899
+ hasMore: !!currentLastKey,
900
+ loadingMore: false
901
+ }));
902
+
903
+ // Sync newly loaded jobs to Redux (append)
904
+ if (newJobs.length > 0) {
905
+ this.props.jobsLoaded(newJobs);
906
+ }
907
+ } catch (error) {
908
+ console.error('loadMore', error);
909
+ this.setState({
910
+ loadingMore: false
911
+ });
912
+ }
913
+ });
914
+ });
755
915
  _defineProperty__default["default"](this, "setRequesters", jobs => {
756
916
  const requesters = ___default["default"].orderBy(___default["default"].uniqBy(jobs.map(j => ({
757
917
  id: j.userID,
@@ -762,30 +922,6 @@ class JobList extends React.Component {
762
922
  requesters
763
923
  });
764
924
  });
765
- _defineProperty__default["default"](this, "getJobs", async () => {
766
- const {
767
- auth
768
- } = this.props;
769
- try {
770
- const res = await maintenanceActions.getJobsRecursive(auth.site);
771
- if (!___default["default"].isEmpty(res) && res[0].site === auth.site) {
772
- this.setRequesters(res);
773
- this.props.jobsLoaded(res);
774
- }
775
- } catch (error) {
776
- console.error('getJobs', error);
777
- }
778
- });
779
- _defineProperty__default["default"](this, "getAssignees", async () => {
780
- try {
781
- const res = await maintenanceActions.getAssignees(this.props.auth.site);
782
- this.setState({
783
- assignees: res.data.Users
784
- });
785
- } catch (error) {
786
- console.error('getAssignees', error);
787
- }
788
- });
789
925
  _defineProperty__default["default"](this, "sortByCol", col => {
790
926
  const {
791
927
  sortColumn,
@@ -805,9 +941,12 @@ class JobList extends React.Component {
805
941
  _defineProperty__default["default"](this, "onRemoveRequest", async request => {
806
942
  if (window.confirm(values.textAreYouSureYouWantToDelete)) {
807
943
  this.props.removeJob(request.id);
944
+ // Remove from local state immediately
945
+ this.setState(prevState => ({
946
+ jobs: prevState.jobs.filter(j => j.id !== request.id)
947
+ }));
808
948
  try {
809
- await maintenanceActions.deleteJob(this.props.auth.site, request.id);
810
- this.getJobs();
949
+ await maintenanceActions$1.deleteJob(this.props.auth.site, request.id);
811
950
  } catch (error) {
812
951
  console.log('onRemoveRequest', error);
813
952
  alert('Something went wrong with the request. Please try again.');
@@ -826,20 +965,20 @@ class JobList extends React.Component {
826
965
  });
827
966
  _defineProperty__default["default"](this, "selectTypeFilter", filter => {
828
967
  this.setState({
829
- selectedTypeFilter: filter
830
- });
968
+ selectedTypeFilter: filter || null
969
+ }, () => this.fetchJobs());
831
970
  this.closeFilter();
832
971
  });
833
972
  _defineProperty__default["default"](this, "selectPriorityFilter", filter => {
834
973
  this.setState({
835
- selectedPriorityFilter: filter
836
- });
974
+ selectedPriorityFilter: filter || null
975
+ }, () => this.fetchJobs());
837
976
  this.closeFilter();
838
977
  });
839
978
  _defineProperty__default["default"](this, "selectStatusFilter", filter => {
840
979
  this.setState({
841
- selectedStatusFilter: filter
842
- });
980
+ selectedStatusFilter: filter || null
981
+ }, () => this.fetchJobs());
843
982
  this.closeFilter();
844
983
  });
845
984
  _defineProperty__default["default"](this, "timeFilterChanged", selectedTimeFilter => {
@@ -883,7 +1022,7 @@ class JobList extends React.Component {
883
1022
  selectedTimeFilterStart: startTime,
884
1023
  selectedTimeFilterEnd: endTime,
885
1024
  selectedTimeFilterText: text
886
- });
1025
+ }, () => this.fetchJobs());
887
1026
  this.closeFilter();
888
1027
  });
889
1028
  _defineProperty__default["default"](this, "removeTimeFilter", () => {
@@ -891,7 +1030,7 @@ class JobList extends React.Component {
891
1030
  selectedTimeFilterStart: null,
892
1031
  selectedTimeFilterEnd: null,
893
1032
  selectedTimeFilterText: null
894
- });
1033
+ }, () => this.fetchJobs());
895
1034
  });
896
1035
  _defineProperty__default["default"](this, "onHandleChange", event => {
897
1036
  var stateChange = {};
@@ -907,7 +1046,7 @@ class JobList extends React.Component {
907
1046
  this.setState({
908
1047
  selectedUserFilter: null,
909
1048
  selectedUserFilterText: null
910
- });
1049
+ }, () => this.fetchJobs());
911
1050
  });
912
1051
  _defineProperty__default["default"](this, "saveUserFilter", () => {
913
1052
  if (!this.state.selectedAssignee) {
@@ -917,7 +1056,7 @@ class JobList extends React.Component {
917
1056
  selectedUserFilter: this.state.selectedAssignee.id,
918
1057
  selectedUserFilterText: this.state.selectedAssignee.displayName,
919
1058
  selectedAssignee: null
920
- });
1059
+ }, () => this.fetchJobs());
921
1060
  }
922
1061
  this.closeFilter();
923
1062
  });
@@ -930,7 +1069,7 @@ class JobList extends React.Component {
930
1069
  this.setState({
931
1070
  selectedRequesterFilter: null,
932
1071
  selectedRequesterFilterText: null
933
- });
1072
+ }, () => this.fetchJobs());
934
1073
  });
935
1074
  _defineProperty__default["default"](this, "saveRequesterFilter", () => {
936
1075
  if (!this.state.selectedRequester) {
@@ -940,7 +1079,7 @@ class JobList extends React.Component {
940
1079
  selectedRequesterFilter: this.state.selectedRequester.id,
941
1080
  selectedRequesterFilterText: this.state.selectedRequester.displayName,
942
1081
  selectedRequester: null
943
- });
1082
+ }, () => this.fetchJobs());
944
1083
  }
945
1084
  this.closeFilter();
946
1085
  });
@@ -951,77 +1090,33 @@ class JobList extends React.Component {
951
1090
  lastSearch: thisSearchTime
952
1091
  });
953
1092
  setTimeout(() => {
954
- // delayed setter to avoid filtering on every keypress
1093
+ // delayed setter to avoid searching on every keypress
955
1094
  if (this.state.lastSearch === thisSearchTime) {
956
1095
  this.setState({
957
1096
  searchTerm: this.state.search
958
- });
1097
+ }, () => this.fetchJobs());
959
1098
  }
960
1099
  }, 500);
961
1100
  });
1101
+ /**
1102
+ * Get the source array for rendering.
1103
+ * With server-side filtering, this is simply the local jobs array
1104
+ * sorted by the user's selected sort column.
1105
+ * The requester filter still applies client-side since the backend
1106
+ * doesn't have a requester/userID filter param.
1107
+ */
962
1108
  _defineProperty__default["default"](this, "getSource", () => {
963
- let source = this.props.source;
964
-
965
- // filter by time
966
- if (this.state.selectedTimeFilterStart && this.state.selectedTimeFilterEnd) {
967
- source = ___default["default"].filter(source, r => {
968
- return r.createdUnix >= this.state.selectedTimeFilterStart && r.createdUnix <= this.state.selectedTimeFilterEnd;
969
- });
970
- }
971
-
972
- // filter by type
973
- if (this.state.selectedTypeFilter) {
974
- source = ___default["default"].filter(source, r => {
975
- return r.type === this.state.selectedTypeFilter;
976
- });
977
- }
1109
+ let source = this.state.jobs;
978
1110
 
979
- // filter by priority
980
- if (this.state.selectedPriorityFilter) {
981
- const defaultPriority = getDefaultPriority().name;
982
- source = ___default["default"].filter(source, r => {
983
- return r.priority === this.state.selectedPriorityFilter || this.state.selectedPriorityFilter === defaultPriority && ___default["default"].isNil(r.priority);
984
- });
985
- }
1111
+ // Filter out deleted items
1112
+ source = ___default["default"].filter(source, ev => ev != null && !ev.Deleted);
986
1113
 
987
- // filter by status
988
- if (this.state.selectedStatusFilter) {
989
- const {
990
- statusTypes
991
- } = this.props;
992
- const defaultStatus = statusTypes.find(s => s.category === STATUS_NOT_ACTIONED);
993
- source = ___default["default"].filter(source, r => {
994
- const status = statusTypes.find(s => s.text === r.status) || defaultStatus;
995
- if (this.state.selectedStatusFilter === STATUS_IMCOMPLETE) {
996
- return status.category !== STATUS_COMPLETED;
997
- }
998
- return status.text === this.state.selectedStatusFilter;
999
- });
1000
- }
1001
- if (this.state.selectedUserFilter) {
1002
- source = ___default["default"].filter(source, r => {
1003
- return r.AssigneeId === this.state.selectedUserFilter;
1004
- });
1005
- }
1114
+ // Requester filter still client-side (no backend param for userID filtering)
1006
1115
  if (this.state.selectedRequesterFilter) {
1007
1116
  source = ___default["default"].filter(source, r => {
1008
1117
  return r.userID === this.state.selectedRequesterFilter;
1009
1118
  });
1010
1119
  }
1011
- if (!___default["default"].isEmpty(this.state.searchTerm)) {
1012
- source = ___default["default"].filter(source, r => {
1013
- if (r.jobId && r.jobId === this.state.searchTerm) {
1014
- return true;
1015
- }
1016
- if (r.room && r.room.toLowerCase().indexOf(this.state.searchTerm.toLowerCase()) > -1) {
1017
- return true;
1018
- }
1019
- if (r.title && r.title.toLowerCase().indexOf(this.state.searchTerm.toLowerCase()) > -1) {
1020
- return true;
1021
- }
1022
- return false;
1023
- });
1024
- }
1025
1120
  source = ___default["default"].sortBy(source, event => {
1026
1121
  if (this.state.sortColumn === 'assigned') {
1027
1122
  return event.Assignee ? event.Assignee.displayName : 'Unassigned';
@@ -1141,13 +1236,60 @@ class JobList extends React.Component {
1141
1236
  exportCsvOpen: false
1142
1237
  });
1143
1238
  });
1239
+ _defineProperty__default["default"](this, "hasActiveFilters", () => {
1240
+ const {
1241
+ selectedTypeFilter,
1242
+ selectedPriorityFilter,
1243
+ selectedStatusFilter,
1244
+ selectedTimeFilterStart,
1245
+ selectedUserFilter,
1246
+ selectedRequesterFilter,
1247
+ searchTerm
1248
+ } = this.state;
1249
+ return !!(selectedTypeFilter || selectedPriorityFilter || selectedStatusFilter || selectedTimeFilterStart || selectedUserFilter || selectedRequesterFilter || searchTerm);
1250
+ });
1251
+ _defineProperty__default["default"](this, "clearAllFilters", () => {
1252
+ this.setState({
1253
+ selectedTypeFilter: null,
1254
+ selectedPriorityFilter: null,
1255
+ selectedStatusFilter: null,
1256
+ selectedTimeFilterStart: null,
1257
+ selectedTimeFilterEnd: null,
1258
+ selectedTimeFilterText: null,
1259
+ selectedUserFilter: null,
1260
+ selectedUserFilterText: null,
1261
+ selectedRequesterFilter: null,
1262
+ selectedRequesterFilterText: null,
1263
+ search: '',
1264
+ searchTerm: ''
1265
+ }, () => this.fetchJobs());
1266
+ });
1144
1267
  this.state = {
1145
- showCompleted: false,
1146
1268
  sortColumn: 'createdUnix',
1147
1269
  sortDesc: true,
1148
1270
  selectedTimeFilter: Analytics$2.getAnalyticsFilterOptions()[1],
1149
1271
  assignees: [],
1150
- requesters: []
1272
+ requesters: [],
1273
+ // Server-side pagination state
1274
+ jobs: [],
1275
+ lastKey: null,
1276
+ hasMore: false,
1277
+ loading: false,
1278
+ loadingMore: false,
1279
+ // Filters (applied to server-side queries)
1280
+ selectedTypeFilter: null,
1281
+ selectedPriorityFilter: null,
1282
+ selectedStatusFilter: null,
1283
+ selectedTimeFilterStart: null,
1284
+ selectedTimeFilterEnd: null,
1285
+ selectedTimeFilterText: null,
1286
+ selectedUserFilter: null,
1287
+ selectedUserFilterText: null,
1288
+ selectedRequesterFilter: null,
1289
+ selectedRequesterFilterText: null,
1290
+ search: '',
1291
+ searchTerm: '',
1292
+ lastSearch: null
1151
1293
  };
1152
1294
  this.exportColumns = [{
1153
1295
  label: 'Select All',
@@ -1207,7 +1349,7 @@ class JobList extends React.Component {
1207
1349
  }
1208
1350
  componentDidMount() {
1209
1351
  this.props.jobStatusesUpdate(this.props.auth.site);
1210
- this.getJobs();
1352
+ this.fetchJobs();
1211
1353
  this.getAssignees();
1212
1354
  }
1213
1355
  renderFilterPopup() {
@@ -1221,7 +1363,7 @@ class JobList extends React.Component {
1221
1363
  minWidth: 400,
1222
1364
  hasPadding: true,
1223
1365
  onClose: this.closeFilter
1224
- }, ___default["default"].sortBy(___default["default"].uniq(this.props.source.map(r => r.type)), t => t.toLowerCase()).map(type => {
1366
+ }, ___default["default"].sortBy(___default["default"].uniq(this.state.jobs.map(r => r.type)), t => t.toLowerCase()).map(type => {
1225
1367
  return /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1226
1368
  key: type,
1227
1369
  onClick: () => {
@@ -1412,7 +1554,7 @@ class JobList extends React.Component {
1412
1554
  const status = ev.status && statusTypes.find(s => s.text === ev.status) || defaultStatus;
1413
1555
  const priority = getJobPriority(ev.priority);
1414
1556
  return /*#__PURE__*/React__default["default"].createElement("tr", {
1415
- key: index
1557
+ key: ev.id || index
1416
1558
  }, /*#__PURE__*/React__default["default"].createElement("td", null, ev.jobId), /*#__PURE__*/React__default["default"].createElement("td", {
1417
1559
  className: "table-TitleColumn"
1418
1560
  }, /*#__PURE__*/React__default["default"].createElement(reactRouterDom.Link, {
@@ -1493,8 +1635,28 @@ class JobList extends React.Component {
1493
1635
  if (col !== this.state.sortColumn) return '';
1494
1636
  return ' table--columnActive';
1495
1637
  }
1638
+ renderLoading() {
1639
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1640
+ className: "flex flex-center-row",
1641
+ style: {
1642
+ padding: 40
1643
+ }
1644
+ }, /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
1645
+ style: {
1646
+ fontSize: 32,
1647
+ color: PlussCore.Colours.COLOUR_DUSK_LIGHT
1648
+ },
1649
+ name: "spinner fa-pulse fa-fw"
1650
+ }), /*#__PURE__*/React__default["default"].createElement("span", {
1651
+ className: "marginLeft-16 fontRegular fontSize-14",
1652
+ style: {
1653
+ color: PlussCore.Colours.TEXT_MID
1654
+ }
1655
+ }, "Loading ", values.textTitleRequests, "\u2026"));
1656
+ }
1496
1657
  renderEmpty() {
1497
1658
  const title = this.props.strings["".concat(values.featureKey, "_textTitleRequests")] || values.textTitleRequests;
1659
+ const hasFilters = this.hasActiveFilters();
1498
1660
  return /*#__PURE__*/React__default["default"].createElement("div", {
1499
1661
  style: {
1500
1662
  display: 'flex',
@@ -1506,7 +1668,22 @@ class JobList extends React.Component {
1506
1668
  }
1507
1669
  }, /*#__PURE__*/React__default["default"].createElement("div", {
1508
1670
  className: "emptyState"
1509
- }), /*#__PURE__*/React__default["default"].createElement("div", {
1671
+ }), hasFilters ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
1672
+ className: "marginTop-32",
1673
+ style: {
1674
+ maxWidth: 500,
1675
+ textAlign: 'center'
1676
+ }
1677
+ }, /*#__PURE__*/React__default["default"].createElement("span", {
1678
+ className: "fontRegular fontSize-13"
1679
+ }, "No ", title.toLowerCase(), " match your current filters.")), /*#__PURE__*/React__default["default"].createElement("div", {
1680
+ className: "marginTop-16"
1681
+ }, /*#__PURE__*/React__default["default"].createElement(Components$7.Button, {
1682
+ inline: true,
1683
+ buttonType: "tertiary",
1684
+ onClick: this.clearAllFilters,
1685
+ isActive: true
1686
+ }, "Clear All Filters"))) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
1510
1687
  className: "marginTop-32",
1511
1688
  style: {
1512
1689
  maxWidth: 500,
@@ -1522,11 +1699,39 @@ class JobList extends React.Component {
1522
1699
  maxWidth: 500,
1523
1700
  textAlign: 'center'
1524
1701
  }
1525
- }, values.textEmptyExample));
1702
+ }, values.textEmptyExample)));
1703
+ }
1704
+ renderLoadMore() {
1705
+ const {
1706
+ hasMore,
1707
+ loadingMore
1708
+ } = this.state;
1709
+ if (!hasMore) return null;
1710
+ return /*#__PURE__*/React__default["default"].createElement("div", {
1711
+ className: "flex flex-center-row",
1712
+ style: {
1713
+ padding: '16px 0'
1714
+ }
1715
+ }, /*#__PURE__*/React__default["default"].createElement(Components$7.Button, {
1716
+ inline: true,
1717
+ buttonType: "tertiary",
1718
+ onClick: this.loadMore,
1719
+ isActive: !loadingMore
1720
+ }, loadingMore ? /*#__PURE__*/React__default["default"].createElement("span", null, /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
1721
+ name: "spinner fa-pulse fa-fw",
1722
+ style: {
1723
+ marginRight: 8
1724
+ }
1725
+ }), "Loading more\u2026") : 'Load More'));
1526
1726
  }
1527
1727
  renderContent() {
1528
- if (___default["default"].isEmpty(this.props.source)) return this.renderEmpty();
1529
- return /*#__PURE__*/React__default["default"].createElement(reactBootstrap.Table, {
1728
+ const {
1729
+ loading,
1730
+ jobs
1731
+ } = this.state;
1732
+ if (loading) return this.renderLoading();
1733
+ if (___default["default"].isEmpty(jobs)) return this.renderEmpty();
1734
+ return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement(reactBootstrap.Table, {
1530
1735
  className: "plussTable",
1531
1736
  striped: true,
1532
1737
  bordered: true,
@@ -1609,7 +1814,7 @@ class JobList extends React.Component {
1609
1814
  style: {
1610
1815
  width: 50
1611
1816
  }
1612
- }))), /*#__PURE__*/React__default["default"].createElement("tbody", null, this.renderRequests()));
1817
+ }))), /*#__PURE__*/React__default["default"].createElement("tbody", null, this.renderRequests())), this.renderLoadMore());
1613
1818
  }
1614
1819
  renderFilters() {
1615
1820
  let typeFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
@@ -1658,13 +1863,9 @@ class JobList extends React.Component {
1658
1863
  typeFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1659
1864
  className: "marginRight-10",
1660
1865
  onClick: () => {
1661
- this.openFilter('type');
1662
- },
1663
- rightIcon: "close",
1664
- rightClick: e => {
1665
- e.stopPropagation();
1666
1866
  this.selectTypeFilter();
1667
1867
  },
1868
+ rightIcon: "close",
1668
1869
  text: this.state.selectedTypeFilter
1669
1870
  });
1670
1871
  }
@@ -1672,13 +1873,9 @@ class JobList extends React.Component {
1672
1873
  priorityFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1673
1874
  className: "marginRight-10",
1674
1875
  onClick: () => {
1675
- this.openFilter('priority');
1676
- },
1677
- rightIcon: "close",
1678
- rightClick: e => {
1679
- e.stopPropagation();
1680
1876
  this.selectPriorityFilter();
1681
1877
  },
1878
+ rightIcon: "close",
1682
1879
  text: this.state.selectedPriorityFilter
1683
1880
  });
1684
1881
  }
@@ -1686,13 +1883,9 @@ class JobList extends React.Component {
1686
1883
  statusFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1687
1884
  className: "marginRight-10",
1688
1885
  onClick: () => {
1689
- this.openFilter('status');
1690
- },
1691
- rightIcon: "close",
1692
- rightClick: e => {
1693
- e.stopPropagation();
1694
1886
  this.selectStatusFilter();
1695
1887
  },
1888
+ rightIcon: "close",
1696
1889
  text: this.state.selectedStatusFilter
1697
1890
  });
1698
1891
  }
@@ -1714,13 +1907,9 @@ class JobList extends React.Component {
1714
1907
  userFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1715
1908
  className: "marginRight-10",
1716
1909
  onClick: () => {
1717
- this.openFilter('user');
1718
- },
1719
- rightIcon: "close",
1720
- rightClick: e => {
1721
- e.stopPropagation();
1722
1910
  this.removeUserFilter();
1723
1911
  },
1912
+ rightIcon: "close",
1724
1913
  text: this.state.selectedUserFilterText
1725
1914
  });
1726
1915
  }
@@ -1728,13 +1917,9 @@ class JobList extends React.Component {
1728
1917
  requesterFilter = /*#__PURE__*/React__default["default"].createElement(Components$7.Tag, {
1729
1918
  className: "marginRight-10",
1730
1919
  onClick: () => {
1731
- this.openFilter('requester');
1732
- },
1733
- rightIcon: "close",
1734
- rightClick: e => {
1735
- e.stopPropagation();
1736
1920
  this.removeRequesterFilter();
1737
1921
  },
1922
+ rightIcon: "close",
1738
1923
  text: this.state.selectedRequesterFilterText
1739
1924
  });
1740
1925
  }
@@ -1812,7 +1997,7 @@ class JobTypes extends React.Component {
1812
1997
  super(props);
1813
1998
  _defineProperty__default["default"](this, "getJobTypes", async () => {
1814
1999
  try {
1815
- const res = await maintenanceActions.getJobTypes(this.props.auth.site);
2000
+ const res = await maintenanceActions$1.getJobTypes(this.props.auth.site);
1816
2001
  if (res.data != null) this.props.jobTypesLoaded(res.data);
1817
2002
  } catch (error) {
1818
2003
  console.error('getJobTypes', error);
@@ -1837,7 +2022,7 @@ class JobTypes extends React.Component {
1837
2022
  _defineProperty__default["default"](this, "onRemoveJobType", async ev => {
1838
2023
  if (!window.confirm("Are you sure you want to delete ".concat(ev.typeName, "?"))) return;
1839
2024
  try {
1840
- await maintenanceActions.deleteJobType(this.props.auth.site, ev.id);
2025
+ await maintenanceActions$1.deleteJobType(this.props.auth.site, ev.id);
1841
2026
  const index = ___default["default"].findIndex(this.state.jobList, job => {
1842
2027
  return job != null && job.id === ev.id;
1843
2028
  });
@@ -2238,43 +2423,43 @@ class Configuration extends React.Component {
2238
2423
  return /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement("p", {
2239
2424
  className: "fontMedium fontSize-36 text-dark"
2240
2425
  }, "Statuses"), /*#__PURE__*/React__default["default"].createElement("div", {
2241
- style: styles$6.statusCategoryHeading
2426
+ style: styles$5.statusCategoryHeading
2242
2427
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2243
2428
  className: "fontMedium fontSize-16 text-bold"
2244
2429
  }, "Status Category")), statusTypes.map((status, index) => {
2245
2430
  return /*#__PURE__*/React__default["default"].createElement("div", {
2246
2431
  key: "".concat(status.text, "_").concat(index),
2247
- style: styles$6.statusTypeContainer
2432
+ style: styles$5.statusTypeContainer
2248
2433
  }, /*#__PURE__*/React__default["default"].createElement("div", {
2249
2434
  key: status.text,
2250
2435
  className: "statusLabel",
2251
- style: _objectSpread$5(_objectSpread$5({}, styles$6.statusTextContainer), {}, {
2436
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusTextContainer), {}, {
2252
2437
  backgroundColor: status.color
2253
2438
  })
2254
2439
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2255
2440
  className: "statusLabel_text"
2256
2441
  }, status.text)), /*#__PURE__*/React__default["default"].createElement("div", {
2257
- style: styles$6.statusCategoryContainer
2442
+ style: styles$5.statusCategoryContainer
2258
2443
  }, /*#__PURE__*/React__default["default"].createElement("span", {
2259
2444
  className: "fontMedium fontSize-16 text-dark"
2260
2445
  }, status.category)), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2261
- style: _objectSpread$5(_objectSpread$5({}, styles$6.statusIcon), {}, {
2446
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusIcon), {}, {
2262
2447
  visibility: index === 0 ? 'hidden' : 'visible'
2263
2448
  }),
2264
2449
  name: 'arrow-up',
2265
2450
  onClick: () => this.onMoveStatus(index, true)
2266
2451
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2267
- style: _objectSpread$5(_objectSpread$5({}, styles$6.statusIcon), {}, {
2452
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.statusIcon), {}, {
2268
2453
  visibility: index === statusTypes.length - 1 ? 'hidden' : 'visible'
2269
2454
  }),
2270
2455
  name: 'arrow-down',
2271
2456
  onClick: () => this.onMoveStatus(index, false)
2272
2457
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2273
- style: _objectSpread$5({}, styles$6.statusIcon),
2458
+ style: _objectSpread$5({}, styles$5.statusIcon),
2274
2459
  name: "pencil",
2275
2460
  onClick: () => this.onEditStatus(index)
2276
2461
  }), /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2277
- style: _objectSpread$5({}, styles$6.statusIcon),
2462
+ style: _objectSpread$5({}, styles$5.statusIcon),
2278
2463
  name: "minus-circle",
2279
2464
  onClick: () => this.onDeleteStatus(index)
2280
2465
  }));
@@ -2323,7 +2508,7 @@ class Configuration extends React.Component {
2323
2508
  renderSuccess() {
2324
2509
  if (!this.state.success) return null;
2325
2510
  return /*#__PURE__*/React__default["default"].createElement("span", {
2326
- style: _objectSpread$5(_objectSpread$5({}, styles$6.savedText), {}, {
2511
+ style: _objectSpread$5(_objectSpread$5({}, styles$5.savedText), {}, {
2327
2512
  color: Colours$2.COLOUR_GREEN
2328
2513
  })
2329
2514
  }, "Saved");
@@ -2440,7 +2625,7 @@ class Configuration extends React.Component {
2440
2625
  }, this.renderSubmit(), this.renderSuccess()), this.renderNewStatusPopup());
2441
2626
  }
2442
2627
  }
2443
- const styles$6 = {
2628
+ const styles$5 = {
2444
2629
  statusCategoryHeading: {
2445
2630
  marginLeft: 130,
2446
2631
  width: 160,
@@ -2499,52 +2684,6 @@ const {
2499
2684
  class RequestsHub extends React.Component {
2500
2685
  constructor(props) {
2501
2686
  super(props);
2502
- _defineProperty__default["default"](this, "setData", () => {
2503
- const allList = [];
2504
- this.state.allList.forEach(ev => {
2505
- if (ev != null && !ev.Deleted) allList.push(ev);
2506
- });
2507
- const upcoming = ___default["default"].filter(allList, ev => {
2508
- if (!ev) return false;
2509
- if (ev.status && ev.status === 'Completed') return false;
2510
- return true;
2511
- });
2512
- const completed = ___default["default"].filter(allList, ev => {
2513
- if (!ev) return false;
2514
- if (ev.status && ev.status === 'Completed') return true;
2515
- return false;
2516
- });
2517
-
2518
- // console.log('setData', upcoming, completed);
2519
- this.setState({
2520
- allList,
2521
- upcoming,
2522
- completed
2523
- });
2524
- });
2525
- _defineProperty__default["default"](this, "getData", () => {
2526
- const {
2527
- auth
2528
- } = this.props;
2529
- this.setState({
2530
- loadingAll: true
2531
- }, async () => {
2532
- try {
2533
- const res = await maintenanceActions.getJobsRecursive(auth.site);
2534
- this.setState({
2535
- loadingAll: false
2536
- });
2537
- if (!___default["default"].isEmpty(res) && res[0].site === auth.site) {
2538
- this.props.jobsLoaded(res);
2539
- }
2540
- } catch (error) {
2541
- console.error('getData', error);
2542
- this.setState({
2543
- loadingAll: false
2544
- });
2545
- }
2546
- });
2547
- });
2548
2687
  _defineProperty__default["default"](this, "onAddNew", () => {
2549
2688
  const {
2550
2689
  auth
@@ -2571,38 +2710,10 @@ class RequestsHub extends React.Component {
2571
2710
  _defineProperty__default["default"](this, "getSideBarSectionColour", id => this.state.selectedSection === id ? {
2572
2711
  backgroundColor: '#fff'
2573
2712
  } : {});
2574
- _defineProperty__default["default"](this, "renderStats", (stat, loading) => loading ? /*#__PURE__*/React__default["default"].createElement(FontAwesome__default["default"], {
2575
- style: styles$5.spinner,
2576
- name: "spinner fa-pulse fa-fw"
2577
- }) : stat);
2578
2713
  this.state = {
2579
- selectedSection: 'all',
2580
- location: '',
2581
- loadingAll: false,
2582
- loadingSubmissions: false,
2583
- submissionEntries: [],
2584
- allList: [],
2585
- completed: [],
2586
- upcoming: [],
2587
- now: moment__default["default"].utc(),
2588
- onlyFuture: true,
2589
- search: ''
2714
+ selectedSection: 'all'
2590
2715
  };
2591
2716
  }
2592
- UNSAFE_componentWillMount() {
2593
- this.updateProps(this.props);
2594
- }
2595
- componentDidMount() {
2596
- this.getData();
2597
- }
2598
- UNSAFE_componentWillReceiveProps(nextProps) {
2599
- if (!___default["default"].isEqual(this.props.jobs, nextProps.jobs)) this.updateProps(nextProps);
2600
- }
2601
- updateProps(props) {
2602
- this.setState({
2603
- allList: props.jobs
2604
- }, this.setData);
2605
- }
2606
2717
  renderLeftBar() {
2607
2718
  const sectionItems = [];
2608
2719
  if (this.canAddNew()) {
@@ -2672,9 +2783,7 @@ class RequestsHub extends React.Component {
2672
2783
  } else if (this.state.selectedSection === 'config') {
2673
2784
  return /*#__PURE__*/React__default["default"].createElement(Configuration$1, null);
2674
2785
  }
2675
- return /*#__PURE__*/React__default["default"].createElement(JobList$1, {
2676
- source: this.state.allList
2677
- });
2786
+ return /*#__PURE__*/React__default["default"].createElement(JobList$1, null);
2678
2787
  }
2679
2788
  render() {
2680
2789
  return /*#__PURE__*/React__default["default"].createElement("div", {
@@ -2686,42 +2795,16 @@ class RequestsHub extends React.Component {
2686
2795
  }, this.renderRight())));
2687
2796
  }
2688
2797
  }
2689
- const styles$5 = {
2690
- sideBarTitleSection: {
2691
- lineHeight: '40px',
2692
- marginTop: 30,
2693
- marginBottom: 30,
2694
- paddingLeft: 24,
2695
- paddingRight: 24
2696
- },
2697
- sideBarSection: {
2698
- weight: '100%',
2699
- minWidth: 200,
2700
- padding: 32,
2701
- paddingLeft: 24,
2702
- cursor: 'pointer',
2703
- display: 'flex',
2704
- flexDirection: 'column',
2705
- justifyContent: 'center'
2706
- },
2707
- spinner: {
2708
- fontSize: 32,
2709
- color: FeatureConfig.env.colourBrandingOff
2710
- }
2711
- };
2712
2798
  const mapStateToProps$4 = state => {
2713
2799
  const {
2714
2800
  auth
2715
2801
  } = state;
2716
2802
  return {
2717
- jobs: state[values.reducerKey].jobs,
2718
2803
  auth,
2719
2804
  strings: state.strings && state.strings.config || {}
2720
2805
  };
2721
2806
  };
2722
- var RequestsHub$1 = reactRedux.connect(mapStateToProps$4, {
2723
- jobsLoaded
2724
- })(reactRouter.withRouter(RequestsHub));
2807
+ var RequestsHub$1 = reactRedux.connect(mapStateToProps$4)(reactRouter.withRouter(RequestsHub));
2725
2808
 
2726
2809
  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; }
2727
2810
  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; }
@@ -2738,7 +2821,7 @@ class Job extends React.Component {
2738
2821
  super(props);
2739
2822
  _defineProperty__default["default"](this, "getJob", async () => {
2740
2823
  try {
2741
- const res = await maintenanceActions.getJob(this.props.auth.site, this.state.jobId);
2824
+ const res = await maintenanceActions$1.getJob(this.props.auth.site, this.state.jobId);
2742
2825
  this.setState({
2743
2826
  updating: false
2744
2827
  });
@@ -2750,7 +2833,7 @@ class Job extends React.Component {
2750
2833
  });
2751
2834
  _defineProperty__default["default"](this, "getAssignees", async () => {
2752
2835
  try {
2753
- const res = await maintenanceActions.getAssignees(this.props.auth.site);
2836
+ const res = await maintenanceActions$1.getAssignees(this.props.auth.site);
2754
2837
  this.setState({
2755
2838
  assignees: res.data.Users
2756
2839
  });
@@ -2763,7 +2846,7 @@ class Job extends React.Component {
2763
2846
  this.setState({
2764
2847
  loadingExternalSync: true
2765
2848
  });
2766
- const res = await maintenanceActions.getExternalSync(this.state.jobId);
2849
+ const res = await maintenanceActions$1.getExternalSync(this.state.jobId);
2767
2850
  this.setState({
2768
2851
  externalSync: res.data,
2769
2852
  loadingExternalSync: false
@@ -2788,7 +2871,7 @@ class Job extends React.Component {
2788
2871
  retrySyncError: null
2789
2872
  });
2790
2873
  try {
2791
- await maintenanceActions.retrySync(job.id);
2874
+ await maintenanceActions$1.retrySync(job.id);
2792
2875
  // Refresh job data to get updated history
2793
2876
  await this.getJob();
2794
2877
  this.setState({
@@ -2954,7 +3037,7 @@ class Job extends React.Component {
2954
3037
  // Method to handle user assignment
2955
3038
  _defineProperty__default["default"](this, "onAssignUser", async userId => {
2956
3039
  try {
2957
- const res = await maintenanceActions.assignJob(this.state.jobId, userId);
3040
+ const res = await maintenanceActions$1.assignJob(this.state.jobId, userId);
2958
3041
  this.getJob();
2959
3042
  } catch (err) {
2960
3043
  console.error("onAssignUser", err);
@@ -2966,12 +3049,12 @@ class Job extends React.Component {
2966
3049
  this.setState({
2967
3050
  submittingNote: true
2968
3051
  });
2969
- const res = await (this.state.editingNote ? maintenanceActions.editNote(this.state.jobId, this.state.editingNote, this.state.noteInput, this.state.noteAttachments.map(a => {
3052
+ const res = await (this.state.editingNote ? maintenanceActions$1.editNote(this.state.jobId, this.state.editingNote, this.state.noteInput, this.state.noteAttachments.map(a => {
2970
3053
  return {
2971
3054
  Title: a.Title,
2972
3055
  Source: a.Source
2973
3056
  };
2974
- }), this.state.noteImages) : maintenanceActions.addNote(this.state.jobId, this.state.noteInput, this.state.noteAttachments.map(a => {
3057
+ }), this.state.noteImages) : maintenanceActions$1.addNote(this.state.jobId, this.state.noteInput, this.state.noteAttachments.map(a => {
2975
3058
  return {
2976
3059
  Title: a.Title,
2977
3060
  Source: a.Source
@@ -2999,7 +3082,7 @@ class Job extends React.Component {
2999
3082
  });
3000
3083
  return;
3001
3084
  }
3002
- maintenanceActions.deleteNote(this.state.jobId, n.Id);
3085
+ maintenanceActions$1.deleteNote(this.state.jobId, n.Id);
3003
3086
  const newNotes = ___default["default"].filter(this.state.job.Notes, note => note.Id !== n.Id);
3004
3087
  const newJob = _objectSpread$4({}, this.state.job);
3005
3088
  newJob.Notes = newNotes;
@@ -3037,7 +3120,7 @@ class Job extends React.Component {
3037
3120
  seen: true,
3038
3121
  status: job.status || "Unassigned"
3039
3122
  };
3040
- await maintenanceActions.editJob(update, auth.site);
3123
+ await maintenanceActions$1.editJob(update, auth.site);
3041
3124
  } catch (error) {
3042
3125
  this.setState({
3043
3126
  updating: false
@@ -3091,7 +3174,7 @@ class Job extends React.Component {
3091
3174
  priorityChangerOpen: false
3092
3175
  });
3093
3176
  try {
3094
- const res = await maintenanceActions.editJobPriority(this.state.job.id, priority);
3177
+ const res = await maintenanceActions$1.editJobPriority(this.state.job.id, priority);
3095
3178
  const {
3096
3179
  job
3097
3180
  } = res.data;
@@ -3116,7 +3199,7 @@ class Job extends React.Component {
3116
3199
  statusChangerOpen: false
3117
3200
  });
3118
3201
  try {
3119
- const res = await maintenanceActions.editJobStatus(this.state.job.id, status);
3202
+ const res = await maintenanceActions$1.editJobStatus(this.state.job.id, status);
3120
3203
  const {
3121
3204
  job
3122
3205
  } = res.data;
@@ -3993,7 +4076,7 @@ class AddJob extends React.Component {
3993
4076
  _this = this;
3994
4077
  _defineProperty__default["default"](this, "getJob", async () => {
3995
4078
  try {
3996
- const res = await maintenanceActions.getJob(this.props.auth.site, this.state.jobId);
4079
+ const res = await maintenanceActions$1.getJob(this.props.auth.site, this.state.jobId);
3997
4080
  res.data.location = res.data.site;
3998
4081
  const {
3999
4082
  userID,
@@ -4027,7 +4110,7 @@ class AddJob extends React.Component {
4027
4110
  });
4028
4111
  _defineProperty__default["default"](this, "getJobTypes", async () => {
4029
4112
  try {
4030
- const res = await maintenanceActions.getJobTypes(this.props.auth.site);
4113
+ const res = await maintenanceActions$1.getJobTypes(this.props.auth.site);
4031
4114
  this.setState({
4032
4115
  types: res.data
4033
4116
  });
@@ -4287,7 +4370,7 @@ class AddJob extends React.Component {
4287
4370
  customFields: this.state.customFields
4288
4371
  };
4289
4372
  if (this.state.id != null) {
4290
- maintenanceActions.editJob(job, this.props.auth.site).then(res => {
4373
+ maintenanceActions$1.editJob(job, this.props.auth.site).then(res => {
4291
4374
  this.setState({
4292
4375
  success: true,
4293
4376
  updating: false
@@ -4301,12 +4384,12 @@ class AddJob extends React.Component {
4301
4384
  });
4302
4385
  } else {
4303
4386
  // Create New Job
4304
- maintenanceActions.createJob(job).then(res => {
4387
+ maintenanceActions$1.createJob(job).then(res => {
4305
4388
  this.setState({
4306
4389
  success: true,
4307
4390
  updating: false
4308
4391
  });
4309
- this.props.jobsUpdate(this.props.auth.site);
4392
+ // JobList fetches fresh data on mount — no action needed here
4310
4393
  }).catch(res => {
4311
4394
  this.setState({
4312
4395
  updating: false
@@ -4971,7 +5054,6 @@ const mapStateToProps$2 = state => {
4971
5054
  };
4972
5055
  };
4973
5056
  var AddJob$1 = reactRedux.connect(mapStateToProps$2, {
4974
- jobsUpdate,
4975
5057
  jobsLoaded,
4976
5058
  addRecentlyCreated: Actions.addRecentlyCreated
4977
5059
  })(reactRouter.withRouter(AddJob));
@@ -4993,7 +5075,7 @@ class AddJobType extends React.Component {
4993
5075
  super(props);
4994
5076
  _defineProperty__default["default"](this, "getJobType", async () => {
4995
5077
  try {
4996
- const res = await maintenanceActions.getJobType(this.props.auth.site, this.state.jobTypeId);
5078
+ const res = await maintenanceActions$1.getJobType(this.props.auth.site, this.state.jobTypeId);
4997
5079
  const {
4998
5080
  typeName,
4999
5081
  email,
@@ -5165,9 +5247,9 @@ class AddJobType extends React.Component {
5165
5247
  }, async () => {
5166
5248
  try {
5167
5249
  if (jobTypeId) {
5168
- await maintenanceActions.editJobType(site, jobTypeId, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5250
+ await maintenanceActions$1.editJobType(site, jobTypeId, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5169
5251
  } else {
5170
- await maintenanceActions.addJobType(site, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5252
+ await maintenanceActions$1.addJobType(site, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields);
5171
5253
  }
5172
5254
  this.props.jobTypesUpdate(site);
5173
5255
  this.setState({