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