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