@zeniai/client-epic-state 5.1.42 → 5.1.43
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/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.js +1 -0
- package/lib/entity/task/taskPayload.d.ts +2 -1
- package/lib/entity/task/taskPayload.js +8 -1
- package/lib/entity/task/taskReducer.d.ts +8 -1
- package/lib/entity/task/taskReducer.js +29 -4
- package/lib/entity/task/taskState.d.ts +1 -0
- package/lib/epic.d.ts +5 -3
- package/lib/epic.js +5 -3
- package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
- package/lib/esm/entity/task/taskPayload.js +8 -1
- package/lib/esm/entity/task/taskReducer.js +28 -3
- package/lib/esm/epic.js +5 -3
- package/lib/esm/index.js +3 -3
- package/lib/esm/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +3 -0
- package/lib/esm/view/companyTaskManagerView/epics/fetchTaskManagerMetricsEpic.js +7 -1
- package/lib/esm/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +96 -0
- package/lib/esm/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +53 -0
- package/lib/esm/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +1 -0
- package/lib/esm/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +70 -9
- package/lib/esm/view/taskManager/taskDetailView/taskDetailReducer.js +56 -2
- package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +32 -9
- package/lib/esm/view/taskManager/taskListView/epics/fetchTaskListEpic.js +3 -1
- package/lib/esm/view/taskManager/taskListView/taskList.js +1 -0
- package/lib/esm/view/taskManager/taskListView/taskListReducer.js +240 -12
- package/lib/esm/view/taskManager/taskListView/taskListSelector.js +1 -0
- package/lib/esm/view/taskManager/taskListView/taskListViewHelpers.js +58 -0
- package/lib/index.d.ts +6 -6
- package/lib/index.js +13 -9
- package/lib/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +3 -0
- package/lib/view/companyTaskManagerView/epics/fetchTaskManagerMetricsEpic.js +7 -1
- package/lib/view/companyView/types/cockpitTypes.d.ts +3 -0
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.d.ts +9 -0
- package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +100 -0
- package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.d.ts +8 -0
- package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +57 -0
- package/lib/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +1 -0
- package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.d.ts +2 -2
- package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +69 -8
- package/lib/view/taskManager/taskDetailView/taskDetail.d.ts +15 -0
- package/lib/view/taskManager/taskDetailView/taskDetailReducer.d.ts +14 -2
- package/lib/view/taskManager/taskDetailView/taskDetailReducer.js +57 -3
- package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +2 -1
- package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +30 -7
- package/lib/view/taskManager/taskListView/epics/fetchTaskListEpic.js +3 -1
- package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
- package/lib/view/taskManager/taskListView/taskList.js +1 -0
- package/lib/view/taskManager/taskListView/taskListPayload.d.ts +4 -0
- package/lib/view/taskManager/taskListView/taskListReducer.d.ts +6 -2
- package/lib/view/taskManager/taskListView/taskListReducer.js +241 -13
- package/lib/view/taskManager/taskListView/taskListSelector.js +1 -0
- package/lib/view/taskManager/taskListView/taskListViewHelpers.d.ts +11 -0
- package/lib/view/taskManager/taskListView/taskListViewHelpers.js +60 -1
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import isEqual from 'lodash/isEqual';
|
|
2
|
-
import {
|
|
2
|
+
import { reduceAnyFetchState } from '../../../commonStateTypes/reduceFetchState';
|
|
3
3
|
import { getClassesByIds } from '../../../entity/class/classSelector';
|
|
4
4
|
import { getFilesByFileIds } from '../../../entity/file/fileSelector';
|
|
5
|
-
import { getTaskById } from '../../../entity/task/taskSelector';
|
|
5
|
+
import { getTaskById, getTasksByIds } 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';
|
|
@@ -27,8 +27,13 @@ export const getTaskDetail = (state, taskId) => {
|
|
|
27
27
|
let recurringSourceTaskId = undefined;
|
|
28
28
|
let snoozedUntil = undefined;
|
|
29
29
|
let taskGroupId = undefined;
|
|
30
|
+
let subtasks = [];
|
|
30
31
|
if (taskId != null && sourceTaskDetail != null) {
|
|
31
32
|
const taskEntity = getTaskById(taskState, taskId);
|
|
33
|
+
subtasks =
|
|
34
|
+
taskEntity != null
|
|
35
|
+
? getTasksByIds(taskState, taskEntity.subTasksIds)
|
|
36
|
+
: [];
|
|
32
37
|
const fileIdsInEntity = taskEntity?.fileIds ?? [];
|
|
33
38
|
if (taskEntity != null) {
|
|
34
39
|
createdByUser = getUserAndUserRole(userState, userRoleState, addressState, taskEntity.createdBy);
|
|
@@ -38,26 +43,37 @@ export const getTaskDetail = (state, taskId) => {
|
|
|
38
43
|
snoozedUntil = taskEntity.snoozedUntil;
|
|
39
44
|
taskGroupId = taskEntity.taskGroupIds[0];
|
|
40
45
|
}
|
|
46
|
+
// Treat "no entry" as Completed so it doesn't block the combined
|
|
47
|
+
// fetch state. The Not-Started default would pin the detail page
|
|
48
|
+
// below Completed forever before the first fetchSubTasks dispatches.
|
|
49
|
+
const completedSubTaskStatus = {
|
|
50
|
+
fetchState: 'Completed',
|
|
51
|
+
error: undefined,
|
|
52
|
+
};
|
|
53
|
+
const subTaskStatus = taskDetailState.subTaskListFetchStatusByParentId[taskId] ??
|
|
54
|
+
completedSubTaskStatus;
|
|
41
55
|
if (fileIdsInEntity.length > 0) {
|
|
42
|
-
fetchStatus =
|
|
56
|
+
fetchStatus = reduceAnyFetchState([
|
|
43
57
|
fileViewState.fetchFilesStatus,
|
|
44
58
|
sourceTaskDetail.fetchTaskStatus,
|
|
45
59
|
userList,
|
|
46
60
|
classListState,
|
|
61
|
+
subTaskStatus,
|
|
47
62
|
]);
|
|
48
63
|
}
|
|
49
64
|
else {
|
|
50
|
-
fetchStatus =
|
|
65
|
+
fetchStatus = reduceAnyFetchState([
|
|
51
66
|
sourceTaskDetail.fetchTaskStatus,
|
|
52
67
|
userList,
|
|
53
68
|
classListState,
|
|
69
|
+
subTaskStatus,
|
|
54
70
|
]);
|
|
55
71
|
}
|
|
56
72
|
showTaskDetailFormFooter = showFormFooter(sourceTaskDetail.taskDetailLocalData, taskEntity);
|
|
57
73
|
taskHistory = taskDetailState.taskHistoryById[taskId]?.historicEvents ?? [];
|
|
58
74
|
}
|
|
59
75
|
else if (taskId == null) {
|
|
60
|
-
fetchStatus =
|
|
76
|
+
fetchStatus = reduceAnyFetchState([userList, classListState]);
|
|
61
77
|
}
|
|
62
78
|
const { classIds } = classListState;
|
|
63
79
|
const allAccountingClasses = getClassesByIds(classState, {
|
|
@@ -90,6 +106,7 @@ export const getTaskDetail = (state, taskId) => {
|
|
|
90
106
|
showTaskDetailFormFooter,
|
|
91
107
|
snoozedUntil,
|
|
92
108
|
taskGroupId,
|
|
109
|
+
subtasks,
|
|
93
110
|
};
|
|
94
111
|
};
|
|
95
112
|
export const allTaskStatus = [
|
|
@@ -137,13 +154,16 @@ export const allTaskPriority = [
|
|
|
137
154
|
},
|
|
138
155
|
];
|
|
139
156
|
const showFormFooter = (taskDetailLocalData, taskDetailInStore) => {
|
|
140
|
-
if (
|
|
157
|
+
if (taskDetailInStore == null) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
if (taskDetailLocalData.name !== taskDetailInStore.name ||
|
|
141
161
|
taskDetailLocalData.description !== taskDetailInStore.description ||
|
|
142
162
|
taskDetailLocalData.priority !== taskDetailInStore.priority.code ||
|
|
143
163
|
taskDetailLocalData.status !== taskDetailInStore.status.code ||
|
|
144
164
|
!isEqual(taskDetailInStore.tagIds, taskDetailLocalData.tagIds) ||
|
|
145
|
-
!isEqual(taskDetailLocalData.assignee, taskDetailInStore
|
|
146
|
-
!isEqual(taskDetailLocalData.groupAssignees, taskDetailInStore
|
|
165
|
+
!isEqual(taskDetailLocalData.assignee, taskDetailInStore.assignees ?? []) ||
|
|
166
|
+
!isEqual(taskDetailLocalData.groupAssignees, taskDetailInStore.groupAssignees ?? []) ||
|
|
147
167
|
!isEqual(taskDetailLocalData.fileIds, taskDetailInStore.fileIds ?? []) ||
|
|
148
168
|
!isEqual(taskDetailLocalData.dueDate, taskDetailInStore.dueDate) ||
|
|
149
169
|
!isEqual(taskDetailLocalData.type, taskDetailInStore.type) ||
|
|
@@ -151,7 +171,10 @@ const showFormFooter = (taskDetailLocalData, taskDetailInStore) => {
|
|
|
151
171
|
!isEqual(taskDetailLocalData.recurringFrequency, taskDetailInStore.recurringFrequency) ||
|
|
152
172
|
!isEqual(taskDetailLocalData.recurringDaysOfWeek, taskDetailInStore.recurringDaysOfWeek) ||
|
|
153
173
|
!isEqual(taskDetailLocalData.recurringStartDate, taskDetailInStore.recurringStartDate) ||
|
|
154
|
-
!isEqual(taskDetailLocalData.timeSpent, taskDetailInStore.timeSpent)
|
|
174
|
+
!isEqual(taskDetailLocalData.timeSpent, taskDetailInStore.timeSpent) ||
|
|
175
|
+
!isEqual(taskDetailLocalData.taskGroupId, taskDetailInStore.taskGroupIds.length > 0
|
|
176
|
+
? taskDetailInStore.taskGroupIds[0]
|
|
177
|
+
: undefined)) {
|
|
155
178
|
return true;
|
|
156
179
|
}
|
|
157
180
|
return false;
|
|
@@ -9,15 +9,17 @@ 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
|
-
const { tasks, deleted, archived, snoozed } = response.data;
|
|
12
|
+
const { tasks, deleted, archived, snoozed, completed } = response.data;
|
|
13
13
|
const allTasks = [
|
|
14
14
|
...tasks,
|
|
15
|
+
...(completed ?? []),
|
|
15
16
|
...(deleted ?? []),
|
|
16
17
|
...(archived ?? []),
|
|
17
18
|
...(snoozed ?? []),
|
|
18
19
|
];
|
|
19
20
|
return of(updateTasks(allTasks), updateTaskList({
|
|
20
21
|
data: tasks,
|
|
22
|
+
completed: completed ?? [],
|
|
21
23
|
deleted: deleted ?? [],
|
|
22
24
|
archived: archived ?? [],
|
|
23
25
|
snoozed: snoozed ?? [],
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
+
import { updateTasks } from '../../../entity/task/taskReducer';
|
|
2
3
|
import { toPriorityCodeType, toTaskStatusCodeType, } from '../../../entity/task/taskState';
|
|
3
4
|
import { date, dateNow } from '../../../zeniDayJS';
|
|
4
5
|
import { toDueDateGroupKeyType, } from './taskList';
|
|
@@ -42,6 +43,7 @@ export const initialState = {
|
|
|
42
43
|
currentTab: 'live',
|
|
43
44
|
byTab: {
|
|
44
45
|
live: { ...initialTabData },
|
|
46
|
+
completed: { ...initialTabData },
|
|
45
47
|
archived: { ...initialTabData },
|
|
46
48
|
deleted: { ...initialTabData },
|
|
47
49
|
snoozed: { ...initialTabData },
|
|
@@ -63,14 +65,12 @@ export const initialState = {
|
|
|
63
65
|
},
|
|
64
66
|
filters: {
|
|
65
67
|
categoryCombinationOperator: 'AND',
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
},
|
|
73
|
-
],
|
|
68
|
+
// Default to no filters. The Completed tab now owns the "hide resolved
|
|
69
|
+
// tasks from the live list" responsibility via the byTab split in
|
|
70
|
+
// updateTaskList / updateTaskFromListView / the updateTasks
|
|
71
|
+
// extraReducer. Keeping the historical `status != resolved` filter
|
|
72
|
+
// here would empty out the Completed tab.
|
|
73
|
+
categories: [],
|
|
74
74
|
},
|
|
75
75
|
hasValidState() {
|
|
76
76
|
return this.fetchState == 'Completed';
|
|
@@ -102,13 +102,16 @@ const taskList = createSlice({
|
|
|
102
102
|
draft.error = undefined;
|
|
103
103
|
},
|
|
104
104
|
updateTaskList(draft, action) {
|
|
105
|
-
const { data, archived, deleted, snoozed } = action.payload;
|
|
105
|
+
const { data, archived, completed, deleted, snoozed } = action.payload;
|
|
106
106
|
draft.fetchState = 'Completed';
|
|
107
107
|
draft.error = undefined;
|
|
108
108
|
// Group live tasks
|
|
109
109
|
const liveGrouped = getGroupedTaskIds(data);
|
|
110
110
|
draft.byTab.live = toTabData(liveGrouped);
|
|
111
111
|
// Group other tabs if provided
|
|
112
|
+
if (completed != null) {
|
|
113
|
+
draft.byTab.completed = toTabData(getGroupedTaskIds(completed));
|
|
114
|
+
}
|
|
112
115
|
if (archived != null) {
|
|
113
116
|
draft.byTab.archived = toTabData(getGroupedTaskIds(archived));
|
|
114
117
|
}
|
|
@@ -354,9 +357,26 @@ const taskList = createSlice({
|
|
|
354
357
|
draft.taskIdsByAssignees[assigneeKey] = draft.taskIdsByAssignees[assigneeKey].filter((taskId) => taskId !== currentTaskState.id);
|
|
355
358
|
draft.taskIdsByTags[tagsKey] = draft.taskIdsByTags[tagsKey].filter((taskId) => taskId !== currentTaskState.id);
|
|
356
359
|
draft.taskIdsByDueDate[dueDateKey] = draft.taskIdsByDueDate[dueDateKey].filter((taskId) => taskId !== currentTaskState.id);
|
|
357
|
-
|
|
360
|
+
// Remove from EVERY previous group bucket the task lived in, not
|
|
361
|
+
// just the destination bucket. Otherwise a detail-page save that
|
|
362
|
+
// moves a task from group A to group B leaves the row listed
|
|
363
|
+
// under both A and B until refetch.
|
|
364
|
+
const previousGroupIds = currentTaskState.taskGroupIds ?? [];
|
|
365
|
+
const allGroupIdsToClean = new Set([
|
|
366
|
+
...previousGroupIds,
|
|
367
|
+
taskGroupId,
|
|
368
|
+
]);
|
|
369
|
+
allGroupIdsToClean.forEach((gid) => {
|
|
370
|
+
if (draft.taskIdsByGroupsIds[gid] != null) {
|
|
371
|
+
draft.taskIdsByGroupsIds[gid] = draft.taskIdsByGroupsIds[gid].filter((id) => id !== currentTaskState.id);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
358
374
|
}
|
|
359
375
|
doUpdateTaskList(draft, task, taskGroupId);
|
|
376
|
+
// Mirror top-level grouping into the active tab's byTab snapshot,
|
|
377
|
+
// otherwise the next updateTaskListTab call copies stale byTab data
|
|
378
|
+
// back over this optimistic update.
|
|
379
|
+
syncTopLevelToActiveTab(draft);
|
|
360
380
|
},
|
|
361
381
|
updateTaskListOnCreateTaskFromTemplateSuccess(draft, action) {
|
|
362
382
|
const { tasks } = action.payload;
|
|
@@ -380,6 +400,7 @@ const taskList = createSlice({
|
|
|
380
400
|
const taskId = task.id;
|
|
381
401
|
draft.updateTasksFetchState.fetchState = 'In-Progress';
|
|
382
402
|
draft.updateTasksFetchState.error = undefined;
|
|
403
|
+
let didMigrateTab = false;
|
|
383
404
|
if (updates.priority != null) {
|
|
384
405
|
const prevPriorityCode = toPriorityCodeType(task.priority.code);
|
|
385
406
|
draft.taskIdsByPriority[prevPriorityCode] = draft.taskIdsByPriority[prevPriorityCode].filter((id) => id != taskId);
|
|
@@ -391,6 +412,25 @@ const taskList = createSlice({
|
|
|
391
412
|
draft.taskIdsByStatus[prevStatusCode] = draft.taskIdsByStatus[prevStatusCode].filter((id) => id != taskId);
|
|
392
413
|
const newStatusCode = toTaskStatusCodeType(updates.status.code);
|
|
393
414
|
draft.taskIdsByStatus[newStatusCode].push(taskId);
|
|
415
|
+
// Optimistically re-bucket between the live and completed tabs
|
|
416
|
+
// when status transitions in/out of "resolved", so the task
|
|
417
|
+
// moves to the Completed tab without waiting for the next
|
|
418
|
+
// fetch. Mirrors backend split in task_handler.py: only
|
|
419
|
+
// `resolved` counts as completed; `done` stays Active.
|
|
420
|
+
//
|
|
421
|
+
// Subtasks travel with their parent — they appear nested under
|
|
422
|
+
// the parent row, not as standalone entries in byTab.taskIds.
|
|
423
|
+
// So we only rebucket parent tasks (tasks with no parentTaskId).
|
|
424
|
+
const isTopLevelTask = task.parentTaskId == null;
|
|
425
|
+
const wasCompleted = prevStatusCode === 'resolved';
|
|
426
|
+
const isCompleted = newStatusCode === 'resolved';
|
|
427
|
+
if (isTopLevelTask && wasCompleted !== isCompleted) {
|
|
428
|
+
const from = isCompleted ? 'live' : 'completed';
|
|
429
|
+
const to = isCompleted ? 'completed' : 'live';
|
|
430
|
+
const updatedTask = { ...task, ...updates };
|
|
431
|
+
migrateTaskBetweenTabs(draft, taskId, updatedTask, from, to);
|
|
432
|
+
didMigrateTab = true;
|
|
433
|
+
}
|
|
394
434
|
}
|
|
395
435
|
if (updates.assignees != null) {
|
|
396
436
|
const prevGroupId = getAssigneesGroupKey(task.assignees);
|
|
@@ -430,7 +470,18 @@ const taskList = createSlice({
|
|
|
430
470
|
};
|
|
431
471
|
}
|
|
432
472
|
}
|
|
433
|
-
|
|
473
|
+
if (didMigrateTab) {
|
|
474
|
+
// The migration moved the task out of the source byTab and into
|
|
475
|
+
// the destination byTab. The active tab's grouping arrays are
|
|
476
|
+
// now authoritative — mirror them back to the top-level so the
|
|
477
|
+
// UI sees the task gone from Live (or freshly arrived in
|
|
478
|
+
// Completed). Inverse of syncTopLevelToActiveTab, used only on
|
|
479
|
+
// this path.
|
|
480
|
+
copyTabDataToTopLevel(draft, draft.byTab[draft.currentTab]);
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
syncTopLevelToActiveTab(draft);
|
|
484
|
+
}
|
|
434
485
|
},
|
|
435
486
|
updateTasksListOnUpdateTaskSuccess(draft) {
|
|
436
487
|
draft.updateTasksFetchState.fetchState = 'Completed';
|
|
@@ -443,12 +494,80 @@ const taskList = createSlice({
|
|
|
443
494
|
removeTaskFromList(draft, action) {
|
|
444
495
|
removeTaskIds(draft, [action.payload]);
|
|
445
496
|
},
|
|
497
|
+
/**
|
|
498
|
+
* Remove a task id from a single group bucket without touching tab
|
|
499
|
+
* membership or other groupings. Used when the user clears a task's
|
|
500
|
+
* group on the Detail page so the row stops appearing under the old
|
|
501
|
+
* group while saveTaskDetailEpic skips the standard list re-insert.
|
|
502
|
+
*/
|
|
503
|
+
removeTaskFromGroupBucket(draft, action) {
|
|
504
|
+
const { taskId, taskGroupId } = action.payload;
|
|
505
|
+
if (draft.taskIdsByGroupsIds[taskGroupId] != null) {
|
|
506
|
+
draft.taskIdsByGroupsIds[taskGroupId] = draft.taskIdsByGroupsIds[taskGroupId].filter((id) => id !== taskId);
|
|
507
|
+
}
|
|
508
|
+
// Mirror to the active tab's grouping so the UI re-renders.
|
|
509
|
+
const activeTab = draft.byTab[draft.currentTab];
|
|
510
|
+
if (activeTab.taskIdsByGroupsIds[taskGroupId] != null) {
|
|
511
|
+
activeTab.taskIdsByGroupsIds[taskGroupId] =
|
|
512
|
+
activeTab.taskIdsByGroupsIds[taskGroupId].filter((id) => id !== taskId);
|
|
513
|
+
}
|
|
514
|
+
},
|
|
446
515
|
clearTaskList(draft) {
|
|
447
516
|
Object.assign(draft, initialState);
|
|
448
517
|
},
|
|
449
518
|
},
|
|
519
|
+
extraReducers: (builder) => {
|
|
520
|
+
// When the entity store receives updated tasks (e.g. from task detail
|
|
521
|
+
// save, snooze/archive/unarchive, etc.), re-bucket parent tasks between
|
|
522
|
+
// the live and completed tabs based on the new status. Mirrors the
|
|
523
|
+
// backend split in task_handler.py: only `resolved` parents count as
|
|
524
|
+
// completed. Subtasks are nested under their parent row, so they
|
|
525
|
+
// never move between tabs on their own.
|
|
526
|
+
builder.addCase(updateTasks, (draft, action) => {
|
|
527
|
+
action.payload.forEach((taskPayload) => {
|
|
528
|
+
// Only re-bucket parents; subtasks (parent_task_id is a non-empty
|
|
529
|
+
// string) are nested under their parent row and don't move tabs.
|
|
530
|
+
if (taskPayload.parent_task_id != null &&
|
|
531
|
+
taskPayload.parent_task_id !== '') {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const taskId = taskPayload.task_id;
|
|
535
|
+
// `TaskPayload.status` is required per the type — every producer
|
|
536
|
+
// in this repo sends it, and `mapTaskPayloadToTask` dereferences
|
|
537
|
+
// it unguarded. The optional chain + null guard are defensive
|
|
538
|
+
// only, in case a downstream consumer (web-app-ui / cockpit-ui)
|
|
539
|
+
// ever dispatches `updateTasks` with a partial payload; in that
|
|
540
|
+
// case we treat missing status as "no status change" and skip
|
|
541
|
+
// re-bucketing so we don't migrate a Completed task back into
|
|
542
|
+
// the Live tab.
|
|
543
|
+
const statusCode = taskPayload.status?.code;
|
|
544
|
+
if (statusCode == null) {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
const isCompleted = statusCode === 'resolved';
|
|
548
|
+
const targetTab = isCompleted ? 'completed' : 'live';
|
|
549
|
+
const otherTab = isCompleted ? 'live' : 'completed';
|
|
550
|
+
// Skip if the task isn't currently in either of these buckets
|
|
551
|
+
// (archived/snoozed/deleted are managed by their own actions).
|
|
552
|
+
const inLive = draft.byTab.live.taskIds.includes(taskId);
|
|
553
|
+
const inCompleted = draft.byTab.completed.taskIds.includes(taskId);
|
|
554
|
+
if (!inLive && !inCompleted) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
if (draft.byTab[otherTab].taskIds.includes(taskId)) {
|
|
558
|
+
migrateTaskPayloadBetweenTabs(draft, taskId, taskPayload, otherTab, targetTab);
|
|
559
|
+
}
|
|
560
|
+
else if (!draft.byTab[targetTab].taskIds.includes(taskId)) {
|
|
561
|
+
draft.byTab[targetTab].taskIds.push(taskId);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
// Re-sync the top-level taskIds / grouping arrays for whichever
|
|
565
|
+
// tab the user is currently looking at.
|
|
566
|
+
copyTabDataToTopLevel(draft, draft.byTab[draft.currentTab]);
|
|
567
|
+
});
|
|
568
|
+
},
|
|
450
569
|
});
|
|
451
|
-
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;
|
|
570
|
+
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, removeTaskFromGroupBucket, clearTaskList, } = taskList.actions;
|
|
452
571
|
export default taskList.reducer;
|
|
453
572
|
/**
|
|
454
573
|
* helpers
|
|
@@ -555,6 +674,115 @@ const copyTabDataToTopLevel = (draft, tabData) => {
|
|
|
555
674
|
draft.taskIdsByDueDate = tabData.taskIdsByDueDate;
|
|
556
675
|
draft.taskIdsByTags = tabData.taskIdsByTags;
|
|
557
676
|
};
|
|
677
|
+
/**
|
|
678
|
+
* Migrate a parent task between two `byTab` buckets (live ↔ completed)
|
|
679
|
+
* when its status flips into / out of `resolved`. The destination tab
|
|
680
|
+
* picks up the task in EVERY grouping dimension (status, priority,
|
|
681
|
+
* group id, assignees, dueDate, tags) using the UPDATED task as the
|
|
682
|
+
* source-of-truth for the new bucket keys. Otherwise the Completed tab
|
|
683
|
+
* shows the task in the right tab-level list but the grouped views
|
|
684
|
+
* (Group by Status, Group by Priority, etc.) miss it until the next
|
|
685
|
+
* full fetch.
|
|
686
|
+
*/
|
|
687
|
+
const migrateTaskBetweenTabs = (draft, taskId, updatedTask, from, to) => {
|
|
688
|
+
const fromTab = draft.byTab[from];
|
|
689
|
+
const toTab = draft.byTab[to];
|
|
690
|
+
// Source tab: drop the task from every grouping dimension.
|
|
691
|
+
removeIdsFromTabData(fromTab, [taskId]);
|
|
692
|
+
// Destination tab: add the task to taskIds (deduped) plus the
|
|
693
|
+
// appropriate bucket inside each grouping dimension based on the
|
|
694
|
+
// updated task.
|
|
695
|
+
if (!toTab.taskIds.includes(taskId)) {
|
|
696
|
+
toTab.taskIds.push(taskId);
|
|
697
|
+
}
|
|
698
|
+
const priorityKey = toPriorityCodeType(updatedTask.priority.code);
|
|
699
|
+
if (!toTab.taskIdsByPriority[priorityKey].includes(taskId)) {
|
|
700
|
+
toTab.taskIdsByPriority[priorityKey].push(taskId);
|
|
701
|
+
}
|
|
702
|
+
const statusKey = toTaskStatusCodeType(updatedTask.status.code);
|
|
703
|
+
if (!toTab.taskIdsByStatus[statusKey].includes(taskId)) {
|
|
704
|
+
toTab.taskIdsByStatus[statusKey].push(taskId);
|
|
705
|
+
}
|
|
706
|
+
const dueDateKey = updatedTask.dueDate != null
|
|
707
|
+
? getDueDateGroupKey(updatedTask.dueDate.toString())
|
|
708
|
+
: 'upcoming';
|
|
709
|
+
if (!toTab.taskIdsByDueDate[dueDateKey].includes(taskId)) {
|
|
710
|
+
toTab.taskIdsByDueDate[dueDateKey].push(taskId);
|
|
711
|
+
}
|
|
712
|
+
const assigneeKey = getAssigneesGroupKey(updatedTask.assignees);
|
|
713
|
+
if (toTab.taskIdsByAssignees[assigneeKey] == null) {
|
|
714
|
+
toTab.taskIdsByAssignees[assigneeKey] = [taskId];
|
|
715
|
+
}
|
|
716
|
+
else if (!toTab.taskIdsByAssignees[assigneeKey].includes(taskId)) {
|
|
717
|
+
toTab.taskIdsByAssignees[assigneeKey].push(taskId);
|
|
718
|
+
}
|
|
719
|
+
const tagIds = [...updatedTask.tagIds].sort();
|
|
720
|
+
const tagsKey = tagIds.join(',');
|
|
721
|
+
if (toTab.taskIdsByTags[tagsKey] == null) {
|
|
722
|
+
toTab.taskIdsByTags[tagsKey] = [taskId];
|
|
723
|
+
}
|
|
724
|
+
else if (!toTab.taskIdsByTags[tagsKey].includes(taskId)) {
|
|
725
|
+
toTab.taskIdsByTags[tagsKey].push(taskId);
|
|
726
|
+
}
|
|
727
|
+
(updatedTask.taskGroupIds ?? []).forEach((groupId) => {
|
|
728
|
+
if (toTab.taskIdsByGroupsIds[groupId] == null) {
|
|
729
|
+
toTab.taskIdsByGroupsIds[groupId] = [taskId];
|
|
730
|
+
}
|
|
731
|
+
else if (!toTab.taskIdsByGroupsIds[groupId].includes(taskId)) {
|
|
732
|
+
toTab.taskIdsByGroupsIds[groupId].push(taskId);
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
};
|
|
736
|
+
/**
|
|
737
|
+
* `updateTasks` extraReducer variant — same migration semantics but
|
|
738
|
+
* keyed off the raw `TaskPayload` instead of the rich `Task` entity.
|
|
739
|
+
*/
|
|
740
|
+
const migrateTaskPayloadBetweenTabs = (draft, taskId, payload, from, to) => {
|
|
741
|
+
const fromTab = draft.byTab[from];
|
|
742
|
+
const toTab = draft.byTab[to];
|
|
743
|
+
removeIdsFromTabData(fromTab, [taskId]);
|
|
744
|
+
if (!toTab.taskIds.includes(taskId)) {
|
|
745
|
+
toTab.taskIds.push(taskId);
|
|
746
|
+
}
|
|
747
|
+
if (payload.priority?.code != null) {
|
|
748
|
+
const priorityKey = toPriorityCodeType(payload.priority.code);
|
|
749
|
+
if (!toTab.taskIdsByPriority[priorityKey].includes(taskId)) {
|
|
750
|
+
toTab.taskIdsByPriority[priorityKey].push(taskId);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
if (payload.status?.code != null) {
|
|
754
|
+
const statusKey = toTaskStatusCodeType(payload.status.code);
|
|
755
|
+
if (!toTab.taskIdsByStatus[statusKey].includes(taskId)) {
|
|
756
|
+
toTab.taskIdsByStatus[statusKey].push(taskId);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
const dueDateKey = getDueDateGroupKey(payload.due_date);
|
|
760
|
+
if (!toTab.taskIdsByDueDate[dueDateKey].includes(taskId)) {
|
|
761
|
+
toTab.taskIdsByDueDate[dueDateKey].push(taskId);
|
|
762
|
+
}
|
|
763
|
+
const assigneeKey = getAssigneesGroupKey(payload.assignees ?? []);
|
|
764
|
+
if (toTab.taskIdsByAssignees[assigneeKey] == null) {
|
|
765
|
+
toTab.taskIdsByAssignees[assigneeKey] = [taskId];
|
|
766
|
+
}
|
|
767
|
+
else if (!toTab.taskIdsByAssignees[assigneeKey].includes(taskId)) {
|
|
768
|
+
toTab.taskIdsByAssignees[assigneeKey].push(taskId);
|
|
769
|
+
}
|
|
770
|
+
const tagsKey = getTagsGroupKey(payload.tags ?? []);
|
|
771
|
+
if (toTab.taskIdsByTags[tagsKey] == null) {
|
|
772
|
+
toTab.taskIdsByTags[tagsKey] = [taskId];
|
|
773
|
+
}
|
|
774
|
+
else if (!toTab.taskIdsByTags[tagsKey].includes(taskId)) {
|
|
775
|
+
toTab.taskIdsByTags[tagsKey].push(taskId);
|
|
776
|
+
}
|
|
777
|
+
(payload.task_group_ids ?? []).forEach((groupId) => {
|
|
778
|
+
if (toTab.taskIdsByGroupsIds[groupId] == null) {
|
|
779
|
+
toTab.taskIdsByGroupsIds[groupId] = [taskId];
|
|
780
|
+
}
|
|
781
|
+
else if (!toTab.taskIdsByGroupsIds[groupId].includes(taskId)) {
|
|
782
|
+
toTab.taskIdsByGroupsIds[groupId].push(taskId);
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
};
|
|
558
786
|
const removeIdsFromTabData = (tabData, taskIds) => {
|
|
559
787
|
const removedSet = new Set(taskIds);
|
|
560
788
|
const isRemoved = (id) => removedSet.has(id);
|
|
@@ -334,6 +334,7 @@ export const getAllTasks = createSelector((state) => state.taskListState, (state
|
|
|
334
334
|
const taskGroupTemplates = getTaskGroupTemplateByIds(taskGroupTemplateState, taskGroupTemplateViewState.taskGroupTemplateIds);
|
|
335
335
|
const tabCounts = {
|
|
336
336
|
live: taskListState.byTab.live.taskIds.length,
|
|
337
|
+
completed: taskListState.byTab.completed.taskIds.length,
|
|
337
338
|
archived: taskListState.byTab.archived.taskIds.length,
|
|
338
339
|
deleted: taskListState.byTab.deleted.taskIds.length,
|
|
339
340
|
snoozed: taskListState.byTab.snoozed.taskIds.length,
|
|
@@ -48,3 +48,61 @@ export const getTaskUpdates = (groupByKey, groupId) => {
|
|
|
48
48
|
taskGroupIds: [groupId],
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* Sort a subtask list by one of the sortable columns. Pure — no state
|
|
53
|
+
* dependency. `statusOrder` is derived from `allTaskStatus` so any new
|
|
54
|
+
* status added upstream slots in by its enum position instead of
|
|
55
|
+
* falling into a catch-all bucket.
|
|
56
|
+
*/
|
|
57
|
+
export const sortSubtasks = (subtasks, sortKey, sortOrder, userList, tagList) => {
|
|
58
|
+
if (sortKey == null) {
|
|
59
|
+
return subtasks;
|
|
60
|
+
}
|
|
61
|
+
const statusOrder = allTaskStatus.reduce((acc, status, index) => {
|
|
62
|
+
acc[status.code] = index;
|
|
63
|
+
return acc;
|
|
64
|
+
}, {});
|
|
65
|
+
const unknownStatusRank = allTaskStatus.length;
|
|
66
|
+
const cmpStr = (a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' });
|
|
67
|
+
const keyFn = (task) => {
|
|
68
|
+
if (sortKey === 'name') {
|
|
69
|
+
return task.name ?? '';
|
|
70
|
+
}
|
|
71
|
+
if (sortKey === 'status') {
|
|
72
|
+
return statusOrder[task.status.code] ?? unknownStatusRank;
|
|
73
|
+
}
|
|
74
|
+
if (sortKey === 'assignee') {
|
|
75
|
+
const firstId = task.assignees?.[0];
|
|
76
|
+
if (firstId == null) {
|
|
77
|
+
return '';
|
|
78
|
+
}
|
|
79
|
+
const user = userList.find((candidate) => candidate.userId === firstId);
|
|
80
|
+
return user
|
|
81
|
+
? `${user.firstName ?? ''} ${user.lastName ?? ''}`.trim()
|
|
82
|
+
: '';
|
|
83
|
+
}
|
|
84
|
+
if (sortKey === 'tag') {
|
|
85
|
+
const firstTagId = task.tagIds?.[0];
|
|
86
|
+
if (firstTagId == null) {
|
|
87
|
+
return '';
|
|
88
|
+
}
|
|
89
|
+
const tag = tagList.find((candidate) => candidate.tagId === firstTagId);
|
|
90
|
+
return tag?.name ?? '';
|
|
91
|
+
}
|
|
92
|
+
return '';
|
|
93
|
+
};
|
|
94
|
+
const copy = [...subtasks];
|
|
95
|
+
copy.sort((a, b) => {
|
|
96
|
+
const av = keyFn(a);
|
|
97
|
+
const bv = keyFn(b);
|
|
98
|
+
let cmp;
|
|
99
|
+
if (typeof av === 'number' && typeof bv === 'number') {
|
|
100
|
+
cmp = av - bv;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
cmp = cmpStr(String(av), String(bv));
|
|
104
|
+
}
|
|
105
|
+
return sortOrder === 'asc' ? cmp : -cmp;
|
|
106
|
+
});
|
|
107
|
+
return copy;
|
|
108
|
+
};
|
package/lib/index.d.ts
CHANGED
|
@@ -256,7 +256,7 @@ import { CompanyPassportLocalStoreDataView, CompanyPassportView, getCompanyPassp
|
|
|
256
256
|
import { CompanyPortfolioView, getCompanyPortfolioView, isInfiniteRunway } from './view/companyView/selector/companyPortfolioViewSelector';
|
|
257
257
|
import { AllCockpitTabsView, getAllCockpitTabsFilterView } from './view/companyView/selector/getAllCockpitTabsFilterView';
|
|
258
258
|
import { ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, CockpitDownloadTabsID, CockpitTabsFileType, CockpitTabsID, toCockpitTabsFileTypeStrict, toCockpitTabsIDStrict } from './view/companyView/types/cockpitTabsID';
|
|
259
|
-
import { CockpitFilterCategory, CockpitFilters, DownloadCockpitTabOptions, FilterCombinationsByTabs, HealthMonitorViewFilterCategoryField, HealthViewSortKey, ManagementViewFilterCategoryField, ManagementViewSortKey, OnboardingViewSortKey, PortfolioViewFilterCategoryField, PortfolioViewSortKey, SubscriptionViewFilterCategoryField, TaskManagerViewFilterCategoryField, TaskManagerViewSortKey, toHealthSortKeyType, toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toTaskManagerSortKeyType } from './view/companyView/types/cockpitTypes';
|
|
259
|
+
import { CockpitFilterCategory, CockpitFilters, DownloadCockpitTabOptions, FilterCombinationsByTabs, HealthMonitorViewFilterCategoryField, HealthViewSortKey, ManagementViewFilterCategoryField, ManagementViewSortKey, OnboardingViewSortKey, PortfolioViewFilterCategoryField, PortfolioViewSortKey, SubscriptionViewFilterCategoryField, TaskGroupScope, TaskManagerViewFilterCategoryField, TaskManagerViewSortKey, toHealthSortKeyType, toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toTaskManagerSortKeyType } from './view/companyView/types/cockpitTypes';
|
|
260
260
|
import { ManagementUIState } from './view/companyView/types/companyManagementViewState';
|
|
261
261
|
import { CompanyDetailsLocalData, CompanyInfoLocalData, IncInfoLocalData, TaxDetailsLocalData } from './view/companyView/types/companyPassport/companyDetailsLocalData';
|
|
262
262
|
import { CompanyPassportLocalData, toCompanyPassportLocalData } from './view/companyView/types/companyPassport/companyPassportLocalData';
|
|
@@ -563,15 +563,15 @@ import { TagViewState } from './view/tagView/tagViewState';
|
|
|
563
563
|
import { CannedResponse, CannedResponsesViewState } from './view/taskManager/cannedResponsesView/cannedResponses';
|
|
564
564
|
import { deleteCannedResponse, fetchCannedResponses, saveCannedResponse } from './view/taskManager/cannedResponsesView/cannedResponsesReducer';
|
|
565
565
|
import { getCannedResponsesView } from './view/taskManager/cannedResponsesView/cannedResponsesSelector';
|
|
566
|
-
import { EditTaskLocalData, initialTaskDetail, initialTaskDetailLocalData } from './view/taskManager/taskDetailView/taskDetail';
|
|
567
|
-
import { archiveTask, deleteTask, discardTaskUpdatesInLocalStore, fetchTaskDetailPage, saveTaskDetail, saveTaskUpdatesToLocalStore, snoozeTask, unsnoozeTask } from './view/taskManager/taskDetailView/taskDetailReducer';
|
|
566
|
+
import { CreateSubTaskPayload, EditTaskLocalData, initialTaskDetail, initialTaskDetailLocalData } from './view/taskManager/taskDetailView/taskDetail';
|
|
567
|
+
import { archiveTask, createSubTask, deleteTask, discardTaskUpdatesInLocalStore, fetchSubTasks, fetchTaskDetailPage, resetSubTaskCreateStatus, saveTaskDetail, saveTaskUpdatesToLocalStore, snoozeTask, unsnoozeTask } from './view/taskManager/taskDetailView/taskDetailReducer';
|
|
568
568
|
import { TaskDetailSelectorView, allTaskPriority, allTaskStatus, getTaskDetail } from './view/taskManager/taskDetailView/taskDetailSelector';
|
|
569
569
|
import { createTaskFromTaskGroupTemplate } from './view/taskManager/taskGroupTemplateView/taskGroupTemplateViewReducer';
|
|
570
570
|
import { createNewTaskGroup, deleteTaskGroup, fetchAllTaskGroups, updateTaskGroupName } from './view/taskManager/taskGroupView/taskGroupViewReducer';
|
|
571
571
|
import { ALL_TASK_LIST_TABS, DueDateGroupKey, TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, TaskFilterCategory, TaskGroupKey, TaskListFilterCategoryField, TaskListFilters, TaskListLocalData, TaskListTab, TaskListUIState, TaskListViewSortKey, toDueDateGroupKeyType, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict } from './view/taskManager/taskListView/taskList';
|
|
572
572
|
import { bulkUpdateTaskList, dragNDropTasks, fetchTaskListPage, initiateTaskListLocalData, removeTaskFromList, updateTaskFilters, updateTaskFromListView, updateTaskListLocalData, updateTaskListSearchText, updateTaskListTab, updateTaskListUIState } from './view/taskManager/taskListView/taskListReducer';
|
|
573
573
|
import { TaskGroupWithTasksList, TaskListSelectorView, TaskWithUserDetails, getAllTasks } from './view/taskManager/taskListView/taskListSelector';
|
|
574
|
-
import { getDueDateValueFromDueDateGroupId, getTaskUpdates } from './view/taskManager/taskListView/taskListViewHelpers';
|
|
574
|
+
import { SubtaskSortKey, SubtaskSortOrder, getDueDateValueFromDueDateGroupId, getTaskUpdates, sortSubtasks } from './view/taskManager/taskListView/taskListViewHelpers';
|
|
575
575
|
import { fetchTasksCard } from './view/tasksCard/tasksCardReducer';
|
|
576
576
|
import { TasksCardReport } from './view/tasksCard/tasksCardSelector';
|
|
577
577
|
import { fetchTopEx, updateTopExDownloadState, updateTopExTimeFrame } from './view/topEx/topExReducer';
|
|
@@ -784,7 +784,7 @@ export { AllCockpitTabsView, getAllCockpitTabsFilterView };
|
|
|
784
784
|
export { AuditSummaryData, fetchImproveUsingZeniGPT, fetchCompanyMonthEndReportView, sendCompanyMonthEndReport, saveCompanyMonthEndReport, resetCompanyMonthEndReportFetchStatus, resetSendCompanyMonthEndReportFetchStatus, getCompanyMonthEndReportSelectorView, CompanyMonthEndReportSelectorView, fetchCompanyMonthEndReportHistoricDates, fetchCompanyMonthEndReportHistoricData, fetchCompanyMonthEndReportTemplates, getCompanyMonthEndReportHistoricData, CompanyMonthEndReportHistoricDataSelectorView, CompanyMonthEndReportData, TemplatesList, CompanyMonthReportTemplates, };
|
|
785
785
|
export { Runway, AccountingSummary };
|
|
786
786
|
export { newAddressInLocalStore, getAddress, getNewAddress, getAllNewAddresses, getFormattedAddress, fetchAddress, clearAddressView, AddressType, NewAddressData, AddressUpdatableInfo, createAddress, removeNewAddressDataInLocalStore, };
|
|
787
|
-
export { CockpitFilterCategory, CockpitFilters, DownloadCockpitTabOptions, FilterCombinationsByTabs, HealthViewSortKey, ManagementViewFilterCategoryField, ManagementViewSortKey, OnboardingViewSortKey, PortfolioViewFilterCategoryField, HealthMonitorViewFilterCategoryField, TaskManagerViewFilterCategoryField, PortfolioViewSortKey, SubscriptionViewFilterCategoryField, toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toHealthSortKeyType, TaskManagerViewSortKey, toTaskManagerSortKeyType, updateCompanyTaskManagerViewFilters, };
|
|
787
|
+
export { CockpitFilterCategory, CockpitFilters, DownloadCockpitTabOptions, FilterCombinationsByTabs, HealthViewSortKey, ManagementViewFilterCategoryField, ManagementViewSortKey, OnboardingViewSortKey, PortfolioViewFilterCategoryField, HealthMonitorViewFilterCategoryField, TaskManagerViewFilterCategoryField, PortfolioViewSortKey, SubscriptionViewFilterCategoryField, toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toHealthSortKeyType, TaskGroupScope, TaskManagerViewSortKey, toTaskManagerSortKeyType, updateCompanyTaskManagerViewFilters, };
|
|
788
788
|
export { CockpitDownloadTabsID, CockpitTabsFileType, CockpitTabsID, ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, toCockpitTabsIDStrict, toCockpitTabsFileTypeStrict, };
|
|
789
789
|
export { AllowedValueWithCode, AllowedValue, AllowedValueWithID, isAllowedValueWithCode, isAllowedValueWithID, };
|
|
790
790
|
export { ManagementUIState, PortfolioUIState };
|
|
@@ -893,7 +893,7 @@ export { fetchGlobalMerchantRecommendation, createGlobalMerchant, updateCreateGl
|
|
|
893
893
|
export { approveVendorGlobalReview, rejectVendorGlobalReview, fetchVendorGlobalReviewView, updateSelectedGlobalMerchant, updateVendorGlobalReviewViewUIState, getVendorGlobalReviewView, getTenantMerchantByMerchantId, toVendorGlobalReviewColumnSortKeyType, VendorGlobalReview, VendorGlobalReviewViewUIState, VendorGlobalReviewViewColumnSortKey, VendorGlobalReviewViewSelectorView, VendorGlobalReviewViewState, VendorGlobalReviewViewLocalData, updateVendorGlobalReviewViewLocalData, GlobalReviewPageCurrentSelectionByColumn, GlobalRecommendationFetchSource, };
|
|
894
894
|
export { fetchArAging, updateArAgingUIState, fetchArAgingDetail, updateArAgingDetailUIState, ArAgingReport, ArAgingDetail, NestedAgingBalancesByCustomer, getArAgingReport, getArAgingDetailForCustomer, updateArAgingNodeCollapseState, };
|
|
895
895
|
export { toRecurringBillFrequency, toRecurringBillFrequencyStrict, RecurringBillFrequency, RecurringBillDetail, RecurringBillConfig, RecurringBillStatus, RecurringBillPaymentStatus, };
|
|
896
|
-
export { Task, TaskPayload, TaskListSelectorView, TaskWithUserDetails, TaskListViewSortKey, TaskListUIState, TaskDetailSelectorView, EditTaskLocalData, TaskStatusCodeType, PriorityCodeType, getTaskGroupById, TaskStatus, TaskPriority, TaskCodeType, getAllTasks, fetchTaskListPage, getTaskDetail, fetchTaskDetailPage, saveTaskUpdatesToLocalStore, saveTaskDetail, archiveTask, CannedResponse, CannedResponsesViewState, fetchCannedResponses, saveCannedResponse, deleteCannedResponse, getCannedResponsesView, updateTaskListSearchText, updateTaskListUIState, allTaskStatus, allTaskPriority, TaskListFilters, updateTaskFilters, TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, TaskListFilterCategoryField, deleteTask, discardTaskUpdatesInLocalStore, TaskFilterCategory, TaskType, TaskGroupWithTasksList, TaskListLocalData, bulkUpdateTaskList, createNewTaskGroup, initiateTaskListLocalData, deleteTaskGroup, updateTaskListLocalData, dragNDropTasks, updateTaskGroupName, TaskGroupState, TaskGroupKey, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict, getTaskUpdates, fetchAllTaskGroups, initialTaskDetail, getDueDateValueFromDueDateGroupId, toPriorityCodeType, toTaskStatusCodeType, DueDateGroupKey, toDueDateGroupKeyType, updateTaskFromListView, updateTaskListTab, removeTaskFromList, snoozeTask, unsnoozeTask, convertHHMMStrToMinutes, initialTaskDetailLocalData, TaskListTab, ALL_TASK_LIST_TABS, };
|
|
896
|
+
export { Task, TaskPayload, TaskListSelectorView, TaskWithUserDetails, TaskListViewSortKey, TaskListUIState, TaskDetailSelectorView, EditTaskLocalData, TaskStatusCodeType, PriorityCodeType, getTaskGroupById, TaskStatus, TaskPriority, TaskCodeType, getAllTasks, fetchTaskListPage, getTaskDetail, fetchTaskDetailPage, saveTaskUpdatesToLocalStore, saveTaskDetail, createSubTask, resetSubTaskCreateStatus, fetchSubTasks, CreateSubTaskPayload, archiveTask, CannedResponse, CannedResponsesViewState, fetchCannedResponses, saveCannedResponse, deleteCannedResponse, getCannedResponsesView, updateTaskListSearchText, updateTaskListUIState, allTaskStatus, allTaskPriority, TaskListFilters, updateTaskFilters, TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, TaskListFilterCategoryField, deleteTask, discardTaskUpdatesInLocalStore, TaskFilterCategory, TaskType, TaskGroupWithTasksList, TaskListLocalData, bulkUpdateTaskList, createNewTaskGroup, initiateTaskListLocalData, deleteTaskGroup, updateTaskListLocalData, dragNDropTasks, updateTaskGroupName, TaskGroupState, TaskGroupKey, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict, SubtaskSortKey, SubtaskSortOrder, getTaskUpdates, sortSubtasks, fetchAllTaskGroups, initialTaskDetail, getDueDateValueFromDueDateGroupId, toPriorityCodeType, toTaskStatusCodeType, DueDateGroupKey, toDueDateGroupKeyType, updateTaskFromListView, updateTaskListTab, removeTaskFromList, snoozeTask, unsnoozeTask, convertHHMMStrToMinutes, initialTaskDetailLocalData, TaskListTab, ALL_TASK_LIST_TABS, };
|
|
897
897
|
export { Tag, TagState, TagViewState, getAllTags, TagViewSelectorView, fetchTagList, createTag, deleteTag, };
|
|
898
898
|
export { CardPayment, CardPaymentViewState, SetupIntentData, CardPaymentSelectorView, getAllCardsAndBankPaymentMethods, createCardSetupIntent, confirmCardSetupIntent, addCardPaymentSource, fetchPaymentSources, resetCardPaymentErrorStatuses, clearCardPaymentView, AddCardPaymentSourceType, };
|
|
899
899
|
export { getAuditReportGroupViewSelectorView, getAuditRuleGroupViewSelectorView, getUserFromAllUsers, AuditReportGroupSelectorView, AuditReportGroupViewSelectorView, AuditRuleGroupViewSelectorView, fetchAuditRuleGroupView, fetchAuditReportGroupView, saveReasonForAuditRule, AuditRuleGroup, AuditRuleGroupReport, AuditReportRule, AuditRuleEntityType, AuditRuleEntityIdType, AuditRuleBypassReason, clearAuditReportGroupViewByCompanyId, };
|