@zeniai/client-epic-state 5.0.21-betaVR1 → 5.0.22-betaJK1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/lib/entity/file/fileState.d.ts +4 -4
  2. package/lib/entity/file/fileState.js +4 -0
  3. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  4. package/lib/entity/snackbar/snackbarTypes.js +2 -0
  5. package/lib/entity/task/taskPayload.d.ts +3 -0
  6. package/lib/entity/task/taskPayload.js +5 -0
  7. package/lib/entity/task/taskState.d.ts +3 -0
  8. package/lib/entity/transaction/stateTypes/attachment.d.ts +2 -2
  9. package/lib/epic.d.ts +6 -1
  10. package/lib/epic.js +6 -1
  11. package/lib/esm/entity/file/fileState.js +4 -0
  12. package/lib/esm/entity/snackbar/snackbarTypes.js +2 -0
  13. package/lib/esm/entity/task/taskPayload.js +5 -0
  14. package/lib/esm/epic.js +6 -1
  15. package/lib/esm/index.js +5 -4
  16. package/lib/esm/reducer.js +3 -0
  17. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +2 -6
  18. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +2 -7
  19. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +5 -5
  20. package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +3 -7
  21. package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +0 -2
  22. package/lib/esm/view/taskManager/cannedResponsesView/cannedResponses.js +1 -0
  23. package/lib/esm/view/taskManager/cannedResponsesView/cannedResponsesPayload.js +1 -0
  24. package/lib/esm/view/taskManager/cannedResponsesView/cannedResponsesReducer.js +61 -0
  25. package/lib/esm/view/taskManager/cannedResponsesView/epics/deleteCannedResponseEpic.js +17 -0
  26. package/lib/esm/view/taskManager/cannedResponsesView/epics/fetchCannedResponsesEpic.js +20 -0
  27. package/lib/esm/view/taskManager/cannedResponsesView/epics/saveCannedResponseEpic.js +29 -0
  28. package/lib/esm/view/taskManager/taskDetailView/epics/archiveTaskEpic.js +3 -0
  29. package/lib/esm/view/taskManager/taskDetailView/epics/deleteTaskEpic.js +5 -0
  30. package/lib/esm/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +1 -0
  31. package/lib/esm/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +1 -0
  32. package/lib/esm/view/taskManager/taskDetailView/epics/snoozeTaskEpic.js +65 -0
  33. package/lib/esm/view/taskManager/taskDetailView/epics/unsnoozeTaskEpic.js +56 -0
  34. package/lib/esm/view/taskManager/taskDetailView/taskDetail.js +4 -0
  35. package/lib/esm/view/taskManager/taskDetailView/taskDetailReducer.js +51 -1
  36. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +13 -1
  37. package/lib/esm/view/taskManager/taskListView/epics/bulkUpdateTaskListEpic.js +56 -21
  38. package/lib/esm/view/taskManager/taskListView/epics/dragNDropTasksEpic.js +1 -0
  39. package/lib/esm/view/taskManager/taskListView/epics/fetchTaskListEpic.js +13 -3
  40. package/lib/esm/view/taskManager/taskListView/epics/updateTaskFromListViewEpic.js +3 -2
  41. package/lib/esm/view/taskManager/taskListView/taskList.js +7 -0
  42. package/lib/esm/view/taskManager/taskListView/taskListReducer.js +91 -12
  43. package/lib/esm/view/taskManager/taskListView/taskListSelector.js +48 -39
  44. package/lib/index.d.ts +6 -4
  45. package/lib/index.js +14 -5
  46. package/lib/reducer.d.ts +3 -0
  47. package/lib/reducer.js +3 -0
  48. package/lib/tsconfig.typecheck.tsbuildinfo +1 -0
  49. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +2 -6
  50. package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +2 -7
  51. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +4 -6
  52. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +4 -4
  53. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  54. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +7 -7
  55. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +3 -7
  56. package/lib/view/expenseAutomationView/selectorTypes/missingReceiptsSelectorTypes.d.ts +2 -4
  57. package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +0 -2
  58. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +2 -2
  59. package/lib/view/taskManager/cannedResponsesView/cannedResponses.d.ts +18 -0
  60. package/lib/view/taskManager/cannedResponsesView/cannedResponses.js +2 -0
  61. package/lib/view/taskManager/cannedResponsesView/cannedResponsesPayload.d.ts +11 -0
  62. package/lib/view/taskManager/cannedResponsesView/cannedResponsesPayload.js +2 -0
  63. package/lib/view/taskManager/cannedResponsesView/cannedResponsesReducer.d.ts +30 -0
  64. package/lib/view/taskManager/cannedResponsesView/cannedResponsesReducer.js +65 -0
  65. package/lib/view/taskManager/cannedResponsesView/epics/deleteCannedResponseEpic.d.ts +7 -0
  66. package/lib/view/taskManager/cannedResponsesView/epics/deleteCannedResponseEpic.js +21 -0
  67. package/lib/view/taskManager/cannedResponsesView/epics/fetchCannedResponsesEpic.d.ts +7 -0
  68. package/lib/view/taskManager/cannedResponsesView/epics/fetchCannedResponsesEpic.js +24 -0
  69. package/lib/view/taskManager/cannedResponsesView/epics/saveCannedResponseEpic.d.ts +7 -0
  70. package/lib/view/taskManager/cannedResponsesView/epics/saveCannedResponseEpic.js +33 -0
  71. package/lib/view/taskManager/taskDetailView/epics/archiveTaskEpic.d.ts +2 -1
  72. package/lib/view/taskManager/taskDetailView/epics/archiveTaskEpic.js +3 -0
  73. package/lib/view/taskManager/taskDetailView/epics/deleteTaskEpic.d.ts +2 -1
  74. package/lib/view/taskManager/taskDetailView/epics/deleteTaskEpic.js +5 -0
  75. package/lib/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +1 -0
  76. package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +1 -0
  77. package/lib/view/taskManager/taskDetailView/epics/snoozeTaskEpic.d.ts +9 -0
  78. package/lib/view/taskManager/taskDetailView/epics/snoozeTaskEpic.js +69 -0
  79. package/lib/view/taskManager/taskDetailView/epics/unsnoozeTaskEpic.d.ts +9 -0
  80. package/lib/view/taskManager/taskDetailView/epics/unsnoozeTaskEpic.js +60 -0
  81. package/lib/view/taskManager/taskDetailView/taskDetail.d.ts +2 -0
  82. package/lib/view/taskManager/taskDetailView/taskDetail.js +4 -0
  83. package/lib/view/taskManager/taskDetailView/taskDetailReducer.d.ts +10 -1
  84. package/lib/view/taskManager/taskDetailView/taskDetailReducer.js +52 -2
  85. package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +5 -0
  86. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +12 -0
  87. package/lib/view/taskManager/taskListView/epics/bulkUpdateTaskListEpic.d.ts +6 -7
  88. package/lib/view/taskManager/taskListView/epics/bulkUpdateTaskListEpic.js +56 -22
  89. package/lib/view/taskManager/taskListView/epics/dragNDropTasksEpic.js +1 -0
  90. package/lib/view/taskManager/taskListView/epics/fetchTaskListEpic.js +13 -3
  91. package/lib/view/taskManager/taskListView/epics/updateTaskFromListViewEpic.js +3 -2
  92. package/lib/view/taskManager/taskListView/taskList.d.ts +14 -1
  93. package/lib/view/taskManager/taskListView/taskList.js +8 -1
  94. package/lib/view/taskManager/taskListView/taskListPayload.d.ts +3 -0
  95. package/lib/view/taskManager/taskListView/taskListReducer.d.ts +6 -2
  96. package/lib/view/taskManager/taskListView/taskListReducer.js +92 -13
  97. package/lib/view/taskManager/taskListView/taskListSelector.d.ts +9 -3
  98. package/lib/view/taskManager/taskListView/taskListSelector.js +48 -39
  99. package/package.json +2 -2
@@ -229,6 +229,56 @@ const taskDetailView = createSlice({
229
229
  draft.newTaskState.deleteTaskStatus.error = action.payload.error;
230
230
  }
231
231
  },
232
+ snoozeTask: {
233
+ reducer(draft, action) {
234
+ const { taskId } = action.payload;
235
+ draft.editTaskStateById[taskId] = {
236
+ ...(draft.editTaskStateById[taskId] != null
237
+ ? draft.editTaskStateById[taskId]
238
+ : initialTaskDetail),
239
+ snoozeStatus: {
240
+ fetchState: 'In-Progress',
241
+ error: undefined,
242
+ },
243
+ };
244
+ },
245
+ prepare(taskId, snoozedUntil) {
246
+ return {
247
+ payload: {
248
+ taskId,
249
+ snoozedUntil,
250
+ },
251
+ };
252
+ },
253
+ },
254
+ snoozeTaskSuccessOrFailure(draft, action) {
255
+ const { taskId, fetchState, error } = action.payload;
256
+ if (draft.editTaskStateById[taskId] != null) {
257
+ draft.editTaskStateById[taskId].snoozeStatus.fetchState = fetchState;
258
+ draft.editTaskStateById[taskId].snoozeStatus.error = error;
259
+ }
260
+ },
261
+ unsnoozeTask: {
262
+ reducer(draft, action) {
263
+ const { taskId } = action.payload;
264
+ draft.editTaskStateById[taskId] = {
265
+ ...(draft.editTaskStateById[taskId] != null
266
+ ? draft.editTaskStateById[taskId]
267
+ : initialTaskDetail),
268
+ snoozeStatus: {
269
+ fetchState: 'In-Progress',
270
+ error: undefined,
271
+ },
272
+ };
273
+ },
274
+ prepare(taskId) {
275
+ return {
276
+ payload: {
277
+ taskId,
278
+ },
279
+ };
280
+ },
281
+ },
232
282
  fetchTaskHistory: {
233
283
  reducer(draft, action) {
234
284
  const { taskId, cacheOverride } = action.payload;
@@ -270,5 +320,5 @@ const taskDetailView = createSlice({
270
320
  },
271
321
  },
272
322
  });
273
- export const { fetchTaskDetailPage, fetchTaskDetail, initializeTaskToLocalStore, updateEditTaskFetchStatus, saveTaskUpdatesToLocalStore, discardTaskUpdatesInLocalStore, saveTaskDetail, archiveTask, archiveTaskSuccessOrFailure, saveTaskSuccessOrFailure, deleteTask, removeTaskDetail, deleteTaskSuccessOrFailure, fetchTaskHistory, updateTaskHistory, updateTaskHistoryFetchStatus, clearTaskDetail, updateCreatedTagToLocalStore, updateDeletedTagToLocalStore, } = taskDetailView.actions;
323
+ export const { fetchTaskDetailPage, fetchTaskDetail, initializeTaskToLocalStore, updateEditTaskFetchStatus, saveTaskUpdatesToLocalStore, discardTaskUpdatesInLocalStore, saveTaskDetail, archiveTask, archiveTaskSuccessOrFailure, saveTaskSuccessOrFailure, deleteTask, removeTaskDetail, deleteTaskSuccessOrFailure, snoozeTask, snoozeTaskSuccessOrFailure, unsnoozeTask, fetchTaskHistory, updateTaskHistory, updateTaskHistoryFetchStatus, clearTaskDetail, updateCreatedTagToLocalStore, updateDeletedTagToLocalStore, } = taskDetailView.actions;
274
324
  export default taskDetailView.reducer;
@@ -6,7 +6,7 @@ import { getTaskById } from '../../../entity/task/taskSelector';
6
6
  import { getUserAndUserRole, } from '../../companyView/types/userAndRole';
7
7
  import { getFileDeleteStatusById, getFileUpdateNameStatusById, } from '../../fileView/fileViewSelector';
8
8
  import { getUserList, } from '../../userListView/userListViewSelector';
9
- import { initialTaskDetail, } from './taskDetail';
9
+ import { initialTaskDetail } from './taskDetail';
10
10
  export const getTaskDetail = (state, taskId) => {
11
11
  const { taskDetailState, classListState, classState, fileState, fileViewState, userState, userRoleState, userListViewState, addressState, taskState, } = state;
12
12
  const deleteFileStatusById = {};
@@ -22,11 +22,19 @@ export const getTaskDetail = (state, taskId) => {
22
22
  };
23
23
  let taskHistory = [];
24
24
  let createdByUser = undefined;
25
+ let isArchived = undefined;
26
+ let isDeleted = undefined;
27
+ let recurringSourceTaskId = undefined;
28
+ let snoozedUntil = undefined;
25
29
  if (taskId != null && sourceTaskDetail != null) {
26
30
  const taskEntity = getTaskById(taskState, taskId);
27
31
  const fileIdsInEntity = taskEntity?.fileIds ?? [];
28
32
  if (taskEntity != null) {
29
33
  createdByUser = getUserAndUserRole(userState, userRoleState, addressState, taskEntity.createdBy);
34
+ isArchived = taskEntity.isArchived;
35
+ isDeleted = taskEntity.isDeleted;
36
+ recurringSourceTaskId = taskEntity.recurringSourceTaskId;
37
+ snoozedUntil = taskEntity.snoozedUntil;
30
38
  }
31
39
  if (fileIdsInEntity.length > 0) {
32
40
  fetchStatus = reduceFetchState([
@@ -74,7 +82,11 @@ export const getTaskDetail = (state, taskId) => {
74
82
  error: fetchStatus.error,
75
83
  version: 0,
76
84
  createdByUser,
85
+ isArchived,
86
+ isDeleted,
87
+ recurringSourceTaskId,
77
88
  showTaskDetailFormFooter,
89
+ snoozedUntil,
78
90
  };
79
91
  };
80
92
  export const allTaskStatus = [
@@ -5,21 +5,26 @@ import { convertHHMMStrToMinutes } from '../../../../commonStateTypes/fiscalYear
5
5
  import { DEFAULT_DATE_FORMAT } from '../../../../commonStateTypes/fiscalYearHelpers/formatZeniDateFY';
6
6
  import { updateTasks } from '../../../../entity/task/taskReducer';
7
7
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
8
- import { bulkUpdateTaskList, updateTasksListOnBulkUpdateTasksFailure, updateTasksListOnBulkUpdateTasksSuccess, } from '../taskListReducer';
9
- export const bulkUpdateTaskListEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(bulkUpdateTaskList.match), switchMap((action) => {
10
- const state = state$.value;
8
+ import { bulkUpdateTaskList, fetchTaskList, updateTasksListOnBulkUpdateTasksFailure, updateTasksListOnBulkUpdateTasksSuccess, } from '../taskListReducer';
9
+ export const bulkUpdateTaskListEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUpdateTaskList.match), switchMap((action) => {
11
10
  const { taskIds, updates, groupId } = action.payload;
12
- const payload = {
13
- tasks: getTasksListPayload(state, taskIds, updates),
14
- };
11
+ const bulkUpdates = toBulkUpdatesPayload(updates);
12
+ if (groupId != null) {
13
+ bulkUpdates.task_group_ids = [groupId];
14
+ }
15
+ const payload = { task_ids: taskIds, updates: bulkUpdates };
15
16
  return zeniAPI
16
- .putAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks`, payload)
17
+ .putAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks/bulk-update`, payload)
17
18
  .pipe(mergeMap((response) => {
18
19
  if (isSuccessResponse(response) && response.data != null) {
20
+ const removeFromList = updates.isArchived === true ||
21
+ updates.isDeleted === true ||
22
+ ('snoozedUntil' in updates && updates.snoozedUntil != null);
19
23
  return of(updateTasks(response.data.tasks), updateTasksListOnBulkUpdateTasksSuccess({
20
24
  taskIds,
21
25
  groupId,
22
- }));
26
+ removeFromList,
27
+ }), fetchTaskList());
23
28
  }
24
29
  else {
25
30
  return of(updateTasksListOnBulkUpdateTasksFailure({
@@ -33,19 +38,46 @@ export const bulkUpdateTaskListEpic = (actions$, state$, zeniAPI) => actions$.pi
33
38
  }));
34
39
  }));
35
40
  }));
36
- export const getTasksListPayload = (state, taskIds, updates) => {
37
- const { taskState } = state;
38
- const tasksList = taskIds
39
- .map((taskId) => {
40
- const task = get(taskState.taskByID, taskId);
41
- return {
42
- ...task,
43
- ...updates,
44
- };
45
- })
46
- .filter((task) => task != null);
47
- const tasksPayload = tasksList.map((task) => toTaskPayload(state, task));
48
- return tasksPayload;
41
+ /**
42
+ * Helpers
43
+ */
44
+ const toBulkUpdatesPayload = (updates) => {
45
+ const payload = {};
46
+ if (updates.status != null) {
47
+ payload.status = updates.status.code;
48
+ }
49
+ if (updates.priority != null) {
50
+ payload.priority = updates.priority.code;
51
+ }
52
+ if (updates.assignees != null) {
53
+ payload.assignees = updates.assignees;
54
+ }
55
+ if (updates.groupAssignees != null) {
56
+ payload.group_assignees = updates.groupAssignees;
57
+ }
58
+ if (updates.dueDate != null) {
59
+ payload.due_date = updates.dueDate.format(DEFAULT_DATE_FORMAT);
60
+ }
61
+ if (updates.tagIds != null) {
62
+ payload.tags = updates.tagIds;
63
+ }
64
+ if (updates.timeSpent != null) {
65
+ payload.time_spent = convertHHMMStrToMinutes(updates.timeSpent.replace(/\D/g, ''));
66
+ }
67
+ if (updates.isArchived != null) {
68
+ payload.is_archived = updates.isArchived;
69
+ }
70
+ if (updates.isDeleted != null) {
71
+ payload.is_deleted = updates.isDeleted;
72
+ }
73
+ // Bulk snooze is not supported — only bulk unsnooze (clear all snooze fields)
74
+ if ('snoozedUntil' in updates) {
75
+ payload.snoozed_until = null;
76
+ payload.snoozed_by = null;
77
+ payload.snoozed_at = null;
78
+ payload.is_snooze_notification_sent = false;
79
+ }
80
+ return payload;
49
81
  };
50
82
  export const getTaskPayload = (state, taskId, updates) => {
51
83
  const { taskState } = state;
@@ -71,6 +103,9 @@ const toTaskPayload = (state, task) => {
71
103
  assignees: task.assignees,
72
104
  description: task.description,
73
105
  group_assignees: task.groupAssignees,
106
+ is_archived: task.isArchived,
107
+ is_deleted: task.isDeleted,
108
+ snoozed_until: task.snoozedUntil != null ? task.snoozedUntil.toISOString() : null,
74
109
  due_date: task.dueDate != null ? task.dueDate.format(DEFAULT_DATE_FORMAT) : null,
75
110
  priority: task.priority.code,
76
111
  status: task.status.code,
@@ -11,6 +11,7 @@ export const dragNDropTasksEpic = (actions$, state$) => actions$.pipe(filter(dra
11
11
  updateTasksListOnBulkUpdateTasksSuccess({
12
12
  taskIds,
13
13
  groupId,
14
+ removeFromList: false,
14
15
  }),
15
16
  bulkUpdateTaskList(taskIds, groupId, updates),
16
17
  ];
@@ -9,10 +9,20 @@ export const fetchTaskListEpic = (actions$, _state$, zeniAPI) => actions$.pipe(f
9
9
  .getJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks?query=${encodeURIComponent(`{"task_type": "all"}`)}`)
10
10
  .pipe(mergeMap((response) => {
11
11
  if (isSuccessResponse(response) && response.data != null) {
12
- return of(updateTasks(response.data.tasks), updateTaskList({
13
- data: response.data.tasks,
12
+ const { tasks, deleted, archived, snoozed } = response.data;
13
+ const allTasks = [
14
+ ...tasks,
15
+ ...(deleted ?? []),
16
+ ...(archived ?? []),
17
+ ...(snoozed ?? []),
18
+ ];
19
+ return of(updateTasks(allTasks), updateTaskList({
20
+ data: tasks,
21
+ deleted: deleted ?? [],
22
+ archived: archived ?? [],
23
+ snoozed: snoozed ?? [],
14
24
  updateType: 'replace',
15
- }), updateTags(response.data.tasks.map((task) => task.tags).flat()));
25
+ }), updateTags(allTasks.map((task) => task.tags).flat()));
16
26
  }
17
27
  else {
18
28
  return of(updateTaskListFetchStatus({
@@ -8,9 +8,10 @@ export const updateTaskFromListViewEpic = (actions$, state$, zeniAPI) => actions
8
8
  const state = state$.value;
9
9
  const { task, updates } = action.payload;
10
10
  const taskId = task.id;
11
- const taskData = getTaskPayload(state, taskId, updates);
11
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
12
+ const { snoozed_until: _snoozedUntil, ...taskData } = getTaskPayload(state, taskId, updates);
12
13
  return zeniAPI
13
- .putAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks/${taskId}`, { ...taskData })
14
+ .putAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks/${taskId}`, taskData)
14
15
  .pipe(mergeMap((response) => {
15
16
  if (isSuccessResponse(response) && response.data != null) {
16
17
  return from([
@@ -1,4 +1,10 @@
1
1
  import { stringToUnion, stringToUnionStrict, } from '../../../commonStateTypes/stringToUnion';
2
+ export const ALL_TASK_LIST_TABS = [
3
+ 'live',
4
+ 'archived',
5
+ 'deleted',
6
+ 'snoozed',
7
+ ];
2
8
  export const DUE_DATE_GROUP_KEYS = [
3
9
  'overdue',
4
10
  'today',
@@ -26,6 +32,7 @@ const ALL_TASK_LIST_SORT_KEYS = [
26
32
  'status',
27
33
  'priority',
28
34
  'timeSpent',
35
+ 'visibility',
29
36
  ];
30
37
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
31
38
  const toTaskListSortKeyType = (v) => stringToUnion(v, ALL_TASK_LIST_SORT_KEYS);
@@ -29,7 +29,23 @@ const initialTaskIdsByDueDate = {
29
29
  today: [],
30
30
  upcoming: [],
31
31
  };
32
+ const initialTabData = {
33
+ taskIds: [],
34
+ taskIdsByAssignees: {},
35
+ taskIdsByDueDate: { ...initialTaskIdsByDueDate },
36
+ taskIdsByGroupsIds: {},
37
+ taskIdsByPriority: { ...initialTaskIdsByPriority },
38
+ taskIdsByStatus: { ...initialTaskIdsByStatus },
39
+ taskIdsByTags: {},
40
+ };
32
41
  export const initialState = {
42
+ currentTab: 'live',
43
+ byTab: {
44
+ live: { ...initialTabData },
45
+ archived: { ...initialTabData },
46
+ deleted: { ...initialTabData },
47
+ snoozed: { ...initialTabData },
48
+ },
33
49
  taskIds: [],
34
50
  taskIdsByGroupsIds: {},
35
51
  taskIdsByPriority: initialTaskIdsByPriority,
@@ -86,17 +102,30 @@ const taskList = createSlice({
86
102
  draft.error = undefined;
87
103
  },
88
104
  updateTaskList(draft, action) {
89
- const { data } = action.payload;
105
+ const { data, archived, deleted, snoozed } = action.payload;
90
106
  draft.fetchState = 'Completed';
91
107
  draft.error = undefined;
92
- const { taskIds, taskIdsGroupedByPriority, taskIdsByGroupIds, taskIdsGroupedByStatus, taskIdsByAssignees, taskIdsByDueDate, taskIdsByTags, } = getGroupedTaskIds(data);
93
- draft.taskIds = taskIds;
94
- draft.taskIdsByGroupsIds = taskIdsByGroupIds;
95
- draft.taskIdsByPriority = taskIdsGroupedByPriority;
96
- draft.taskIdsByStatus = taskIdsGroupedByStatus;
97
- draft.taskIdsByAssignees = taskIdsByAssignees;
98
- draft.taskIdsByDueDate = taskIdsByDueDate;
99
- draft.taskIdsByTags = taskIdsByTags;
108
+ // Group live tasks
109
+ const liveGrouped = getGroupedTaskIds(data);
110
+ draft.byTab.live = toTabData(liveGrouped);
111
+ // Group other tabs if provided
112
+ if (archived != null) {
113
+ draft.byTab.archived = toTabData(getGroupedTaskIds(archived));
114
+ }
115
+ if (deleted != null) {
116
+ draft.byTab.deleted = toTabData(getGroupedTaskIds(deleted));
117
+ }
118
+ if (snoozed != null) {
119
+ draft.byTab.snoozed = toTabData(getGroupedTaskIds(snoozed));
120
+ }
121
+ // Copy active tab data to top-level fields
122
+ const activeTabData = draft.byTab[draft.currentTab];
123
+ copyTabDataToTopLevel(draft, activeTabData);
124
+ },
125
+ updateTaskListTab(draft, action) {
126
+ draft.currentTab = action.payload;
127
+ const activeTabData = draft.byTab[action.payload];
128
+ copyTabDataToTopLevel(draft, activeTabData);
100
129
  },
101
130
  initiateTaskListLocalData(draft, action) {
102
131
  const { taskGroupById } = action.payload;
@@ -184,10 +213,13 @@ const taskList = createSlice({
184
213
  },
185
214
  },
186
215
  updateTasksListOnBulkUpdateTasksSuccess(draft, action) {
187
- const { taskIds, groupId } = action.payload;
216
+ const { taskIds, groupId, removeFromList } = action.payload;
188
217
  draft.updateTasksFetchState.fetchState = 'Completed';
189
218
  draft.updateTasksFetchState.error = undefined;
190
- if (groupId != null) {
219
+ if (removeFromList) {
220
+ removeTaskIds(draft, taskIds);
221
+ }
222
+ else if (groupId != null) {
191
223
  const { groupByKey } = draft.uiState;
192
224
  if (groupByKey === 'groupName') {
193
225
  Object.keys(draft.taskIdsByGroupsIds).forEach((gId) => {
@@ -404,12 +436,15 @@ const taskList = createSlice({
404
436
  draft.updateTasksFetchState.fetchState = 'Error';
405
437
  draft.updateTasksFetchState.error = action.payload.error;
406
438
  },
439
+ removeTaskFromList(draft, action) {
440
+ removeTaskIds(draft, [action.payload]);
441
+ },
407
442
  clearTaskList(draft) {
408
443
  Object.assign(draft, initialState);
409
444
  },
410
445
  },
411
446
  });
412
- export const { fetchTaskListPage, fetchTaskList, updateTaskList, updateTaskListFetchStatus, updateTaskListSearchText, updateTaskListUIState, updateTaskFilters, updateTaskListOnNewGroupCreationSuccess, bulkUpdateTaskList, updateTasksListOnBulkUpdateTasksSuccess, updateTasksListOnBulkUpdateTasksFailure, initiateTaskListLocalData, updateTaskListLocalData, updateTaskListOnTaskGroupDeletion, dragNDropTasks, updateTaskListOnNewTaskCreationSuccess, updateTaskListOnTaskGroupNameUpdate, updateTaskFromListView, updateTasksListOnUpdateTaskSuccess, updateTasksListOnUpdateTaskFailure, updateTaskListOnCreateTaskFromTemplateSuccess, clearTaskList, } = taskList.actions;
447
+ export const { fetchTaskListPage, fetchTaskList, updateTaskList, updateTaskListTab, updateTaskListFetchStatus, updateTaskListSearchText, updateTaskListUIState, updateTaskFilters, updateTaskListOnNewGroupCreationSuccess, bulkUpdateTaskList, updateTasksListOnBulkUpdateTasksSuccess, updateTasksListOnBulkUpdateTasksFailure, initiateTaskListLocalData, updateTaskListLocalData, updateTaskListOnTaskGroupDeletion, dragNDropTasks, updateTaskListOnNewTaskCreationSuccess, updateTaskListOnTaskGroupNameUpdate, updateTaskFromListView, updateTasksListOnUpdateTaskSuccess, updateTasksListOnUpdateTaskFailure, updateTaskListOnCreateTaskFromTemplateSuccess, removeTaskFromList, clearTaskList, } = taskList.actions;
413
448
  export default taskList.reducer;
414
449
  /**
415
450
  * helpers
@@ -488,6 +523,50 @@ const getTagsGroupKey = (tags) => {
488
523
  tagIds.sort();
489
524
  return tagIds.join(',');
490
525
  };
526
+ const toTabData = (grouped) => ({
527
+ taskIds: grouped.taskIds,
528
+ taskIdsByAssignees: grouped.taskIdsByAssignees,
529
+ taskIdsByDueDate: grouped.taskIdsByDueDate,
530
+ taskIdsByGroupsIds: grouped.taskIdsByGroupIds,
531
+ taskIdsByPriority: grouped.taskIdsGroupedByPriority,
532
+ taskIdsByStatus: grouped.taskIdsGroupedByStatus,
533
+ taskIdsByTags: grouped.taskIdsByTags,
534
+ });
535
+ const copyTabDataToTopLevel = (draft, tabData) => {
536
+ draft.taskIds = tabData.taskIds;
537
+ draft.taskIdsByGroupsIds = tabData.taskIdsByGroupsIds;
538
+ draft.taskIdsByPriority = tabData.taskIdsByPriority;
539
+ draft.taskIdsByStatus = tabData.taskIdsByStatus;
540
+ draft.taskIdsByAssignees = tabData.taskIdsByAssignees;
541
+ draft.taskIdsByDueDate = tabData.taskIdsByDueDate;
542
+ draft.taskIdsByTags = tabData.taskIdsByTags;
543
+ };
544
+ const removeIdsFromTabData = (tabData, taskIds) => {
545
+ const isRemoved = (id) => taskIds.includes(id);
546
+ tabData.taskIds = tabData.taskIds.filter((id) => !isRemoved(id));
547
+ Object.keys(tabData.taskIdsByGroupsIds).forEach((gId) => {
548
+ tabData.taskIdsByGroupsIds[gId] = tabData.taskIdsByGroupsIds[gId].filter((id) => !isRemoved(id));
549
+ });
550
+ Object.keys(tabData.taskIdsByPriority).forEach((key) => {
551
+ tabData.taskIdsByPriority[key] = tabData.taskIdsByPriority[key].filter((id) => !isRemoved(id));
552
+ });
553
+ Object.keys(tabData.taskIdsByStatus).forEach((key) => {
554
+ tabData.taskIdsByStatus[key] = tabData.taskIdsByStatus[key].filter((id) => !isRemoved(id));
555
+ });
556
+ Object.keys(tabData.taskIdsByDueDate).forEach((key) => {
557
+ tabData.taskIdsByDueDate[key] = tabData.taskIdsByDueDate[key].filter((id) => !isRemoved(id));
558
+ });
559
+ Object.keys(tabData.taskIdsByAssignees).forEach((key) => {
560
+ tabData.taskIdsByAssignees[key] = tabData.taskIdsByAssignees[key].filter((id) => !isRemoved(id));
561
+ });
562
+ Object.keys(tabData.taskIdsByTags).forEach((key) => {
563
+ tabData.taskIdsByTags[key] = tabData.taskIdsByTags[key].filter((id) => !isRemoved(id));
564
+ });
565
+ };
566
+ const removeTaskIds = (draft, taskIds) => {
567
+ removeIdsFromTabData(draft, taskIds);
568
+ removeIdsFromTabData(draft.byTab[draft.currentTab], taskIds);
569
+ };
491
570
  const getGroupedTaskIds = (tasks) => {
492
571
  const taskIds = [];
493
572
  const taskIdsByGroupIds = {};