@zeniai/client-epic-state 5.1.45-betaDI3 → 5.1.45
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 +0 -3
- package/lib/entity/task/taskPayload.d.ts +1 -3
- package/lib/entity/task/taskPayload.js +2 -24
- package/lib/entity/task/taskReducer.d.ts +1 -8
- package/lib/entity/task/taskReducer.js +4 -29
- package/lib/entity/task/taskState.d.ts +0 -2
- package/lib/entity/tenant/epic/saveExternalConnectionEpic.d.ts +1 -2
- package/lib/entity/tenant/epic/saveExternalConnectionEpic.js +0 -17
- package/lib/epic.d.ts +3 -6
- package/lib/epic.js +3 -6
- package/lib/esm/entity/snackbar/snackbarTypes.js +0 -3
- package/lib/esm/entity/task/taskPayload.js +2 -24
- package/lib/esm/entity/task/taskReducer.js +3 -28
- package/lib/esm/entity/tenant/epic/saveExternalConnectionEpic.js +0 -17
- package/lib/esm/epic.js +3 -6
- package/lib/esm/index.js +8 -8
- package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +1 -31
- package/lib/esm/view/aiCfoView/epics/fetchSkillsEpic.js +8 -33
- package/lib/esm/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +0 -3
- package/lib/esm/view/companyTaskManagerView/epics/fetchTaskManagerMetricsEpic.js +1 -7
- package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +0 -7
- package/lib/esm/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +0 -1
- package/lib/esm/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +9 -70
- package/lib/esm/view/taskManager/taskDetailView/taskDetailReducer.js +2 -56
- package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +9 -35
- package/lib/esm/view/taskManager/taskListView/epics/fetchTaskListEpic.js +1 -3
- package/lib/esm/view/taskManager/taskListView/taskList.js +0 -1
- package/lib/esm/view/taskManager/taskListView/taskListReducer.js +18 -310
- package/lib/esm/view/taskManager/taskListView/taskListSelector.js +0 -1
- package/lib/esm/view/taskManager/taskListView/taskListViewHelpers.js +0 -58
- package/lib/esm/view/transactionDetail/epics/saveTransactionHelper.js +0 -22
- package/lib/esm/view/transactionDetail/epics/updateTransactionDetailEpic.js +3 -75
- package/lib/esm/view/transactionDetail/journalEntryLinesViewModel.js +0 -58
- package/lib/esm/view/transactionDetail/transactionDetailLocalDataHelper.js +8 -10
- package/lib/esm/view/transactionDetail/transactionDetailReducer.js +1 -66
- package/lib/index.d.ts +11 -12
- package/lib/index.js +28 -37
- package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +0 -10
- package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +2 -7
- package/lib/view/aiCfoView/aiCfoViewReducer.js +2 -32
- package/lib/view/aiCfoView/aiCfoViewState.d.ts +1 -5
- package/lib/view/aiCfoView/epics/fetchSkillsEpic.js +8 -33
- package/lib/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +0 -3
- package/lib/view/companyTaskManagerView/epics/fetchTaskManagerMetricsEpic.js +1 -7
- package/lib/view/companyView/types/cockpitTypes.d.ts +0 -3
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +0 -7
- package/lib/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +0 -1
- package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.d.ts +2 -2
- package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +8 -69
- package/lib/view/taskManager/taskDetailView/taskDetail.d.ts +0 -15
- package/lib/view/taskManager/taskDetailView/taskDetailReducer.d.ts +2 -14
- package/lib/view/taskManager/taskDetailView/taskDetailReducer.js +3 -57
- package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +1 -3
- package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +7 -33
- package/lib/view/taskManager/taskListView/epics/fetchTaskListEpic.js +1 -3
- package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
- package/lib/view/taskManager/taskListView/taskList.js +0 -1
- package/lib/view/taskManager/taskListView/taskListPayload.d.ts +0 -4
- package/lib/view/taskManager/taskListView/taskListReducer.d.ts +2 -6
- package/lib/view/taskManager/taskListView/taskListReducer.js +19 -311
- package/lib/view/taskManager/taskListView/taskListSelector.js +0 -1
- package/lib/view/taskManager/taskListView/taskListViewHelpers.d.ts +0 -11
- package/lib/view/taskManager/taskListView/taskListViewHelpers.js +1 -60
- package/lib/view/transactionDetail/epics/saveTransactionHelper.js +0 -22
- package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.d.ts +1 -5
- package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.js +4 -77
- package/lib/view/transactionDetail/journalEntryLinesViewModel.d.ts +0 -27
- package/lib/view/transactionDetail/journalEntryLinesViewModel.js +1 -61
- package/lib/view/transactionDetail/transactionDetailLocalDataHelper.js +8 -10
- package/lib/view/transactionDetail/transactionDetailReducer.d.ts +2 -11
- package/lib/view/transactionDetail/transactionDetailReducer.js +2 -67
- package/lib/view/transactionDetail/transactionDetailState.d.ts +1 -8
- package/lib/view/transactionDetail/transactionDetailTypes.d.ts +0 -2
- package/package.json +1 -1
- package/lib/esm/view/aiCfoView/epics/submitFeedbackEpic.js +0 -39
- package/lib/esm/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +0 -96
- package/lib/esm/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +0 -53
- package/lib/view/aiCfoView/epics/submitFeedbackEpic.d.ts +0 -13
- package/lib/view/aiCfoView/epics/submitFeedbackEpic.js +0 -43
- package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.d.ts +0 -9
- package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +0 -100
- package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.d.ts +0 -8
- package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +0 -57
|
@@ -383,36 +383,6 @@ const aiCfoView = createSlice({
|
|
|
383
383
|
const { chatSessionId } = action.payload;
|
|
384
384
|
delete draft.deleteChatSessionStateByChatSessionId[chatSessionId];
|
|
385
385
|
},
|
|
386
|
-
// AI CFO answer feedback (👍/👎). Fire-and-forget: submitFeedbackEpic POSTs to /1.0/feedback
|
|
387
|
-
// and the server emits the analytics event + routes negatives, so there's no view state to
|
|
388
|
-
// mutate — the reducers are intentional no-ops; prepare carries the params.
|
|
389
|
-
submitFeedback: {
|
|
390
|
-
reducer() { },
|
|
391
|
-
prepare(chatSessionId, chatMessageId, feedbackType, questionText, answerText, model) {
|
|
392
|
-
return {
|
|
393
|
-
payload: {
|
|
394
|
-
chatMessageId,
|
|
395
|
-
chatSessionId,
|
|
396
|
-
feedbackType,
|
|
397
|
-
answerText,
|
|
398
|
-
model,
|
|
399
|
-
questionText,
|
|
400
|
-
},
|
|
401
|
-
};
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
submitFeedbackSuccess: {
|
|
405
|
-
reducer() { },
|
|
406
|
-
prepare(chatMessageId) {
|
|
407
|
-
return { payload: { chatMessageId } };
|
|
408
|
-
},
|
|
409
|
-
},
|
|
410
|
-
submitFeedbackFailure: {
|
|
411
|
-
reducer() { },
|
|
412
|
-
prepare(chatMessageId, error) {
|
|
413
|
-
return { payload: { chatMessageId, error } };
|
|
414
|
-
},
|
|
415
|
-
},
|
|
416
386
|
clearInput(draft) {
|
|
417
387
|
draft.uiState.currentInput = '';
|
|
418
388
|
},
|
|
@@ -511,5 +481,5 @@ const aiCfoView = createSlice({
|
|
|
511
481
|
},
|
|
512
482
|
},
|
|
513
483
|
});
|
|
514
|
-
export const { submitQuestion, submitQuestionSuccess, submitQuestionFailure, updateResponseState, updateAiCfoViewScrollPosition, updateCurrentInput,
|
|
484
|
+
export const { submitQuestion, submitQuestionSuccess, submitQuestionFailure, updateResponseState, updateAiCfoViewScrollPosition, updateCurrentInput, clearInput, setSession, createSession, createSessionSuccess, createSessionFailure, createSessionAndSubmit, initializeNewSessionState, createSessionAndSubmitSuccess, createSessionAndSubmitFailure, fetchChatSessionsForUser, fetchChatSessionsForUserSuccess, fetchChatSessionsForUserFailure, fetchChatHistory, fetchChatHistorySuccess, fetchChatHistoryFailure, clearCurrentSessionId, clearLastContextMessage, stopSubmit, stopSubmitSuccess, stopSubmitFailure, stopSubmitQuestion, stopSubmitQuestionSuccess, stopSubmitQuestionFailure, acceptMasterTOS, acceptMasterTOSSuccess, acceptMasterTOSFailure, deleteChatSession, deleteChatSessionSuccess, deleteChatSessionFailure, clearDeleteChatSessionStatus, clearAiCfoView, updateCotCollapsedState, fetchSuggestedQuestions, fetchSuggestedQuestionsSuccess, fetchSuggestedQuestionsFailure, fetchSkills, fetchSkillsSuccess, fetchSkillsFailure, applyAiCfoSidePanelHostPageTransition, clearAiCfoSidePanelHostPageContext, } = aiCfoView.actions;
|
|
515
485
|
export default aiCfoView.reducer;
|
|
@@ -2,39 +2,14 @@ import { of } from 'rxjs';
|
|
|
2
2
|
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
3
|
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
4
4
|
import { fetchSkills, fetchSkillsFailure, fetchSkillsSuccess, } from '../aiCfoViewReducer';
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
typeof parameterHints !== 'object' ||
|
|
14
|
-
Array.isArray(parameterHints)) {
|
|
15
|
-
return [];
|
|
16
|
-
}
|
|
17
|
-
const hints = Object.values(parameterHints).flatMap((value) => {
|
|
18
|
-
if (isNonBlankString(value)) {
|
|
19
|
-
return [value.trim()];
|
|
20
|
-
}
|
|
21
|
-
if (Array.isArray(value)) {
|
|
22
|
-
return value.filter(isNonBlankString).map((item) => item.trim());
|
|
23
|
-
}
|
|
24
|
-
return [];
|
|
25
|
-
});
|
|
26
|
-
// The menu joins these into one flat "try: a · b" line, so a repeated phrase reads as
|
|
27
|
-
// a broken duplicate to the user — dedupe across parameter keys and array entries.
|
|
28
|
-
return Array.from(new Set(hints));
|
|
29
|
-
};
|
|
30
|
-
const toSkill = (skillSummaryPayload) => ({
|
|
31
|
-
macroId: skillSummaryPayload.macro_id,
|
|
32
|
-
name: skillSummaryPayload.name,
|
|
33
|
-
displayName: skillSummaryPayload.display_name,
|
|
34
|
-
description: skillSummaryPayload.description,
|
|
35
|
-
semver: skillSummaryPayload.semver,
|
|
36
|
-
exampleHints: toExampleHints(skillSummaryPayload.parameter_hints),
|
|
37
|
-
hasScripts: skillSummaryPayload.has_scripts,
|
|
5
|
+
const toSkill = (s) => ({
|
|
6
|
+
macroId: s.macro_id,
|
|
7
|
+
name: s.name,
|
|
8
|
+
displayName: s.display_name,
|
|
9
|
+
description: s.description,
|
|
10
|
+
semver: s.semver,
|
|
11
|
+
parameterHints: s.parameter_hints,
|
|
12
|
+
hasScripts: s.has_scripts,
|
|
38
13
|
});
|
|
39
14
|
/** GET {aiCfoMicroServiceBaseUrl}/1.0/skills — chat-visible skills for the `/` menu. */
|
|
40
15
|
export const fetchSkillsEpic = (actions$,
|
|
@@ -18,9 +18,6 @@ export const fetchCompanyTaskManagerViewEpic = (actions$, _state$, zeniAPI) => a
|
|
|
18
18
|
...(filters?.categories != null && filters.categories.length > 0
|
|
19
19
|
? { filter_by: toFilterByPayload(filters) }
|
|
20
20
|
: {}),
|
|
21
|
-
task_group_scopes: filters?.taskGroupScopes != null && filters.taskGroupScopes.length > 0
|
|
22
|
-
? filters.taskGroupScopes
|
|
23
|
-
: ['internal'],
|
|
24
21
|
};
|
|
25
22
|
return zeniAPI
|
|
26
23
|
.getJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels/tasks-es?query=${encodeURIComponent(JSON.stringify(queryValue))}`)
|
|
@@ -3,13 +3,7 @@ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
|
3
3
|
import { isSuccessResponse } from '../../../responsePayload';
|
|
4
4
|
import { fetchTaskManagerMetrics, updateTaskManagerMetrics, updateTaskManagerMetricsOnFailure, } from '../companyTaskManagerViewReducer';
|
|
5
5
|
export const fetchTaskManagerMetricsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchTaskManagerMetrics.match), switchMap(() => {
|
|
6
|
-
|
|
7
|
-
// pending count. The dashboard counts every task (subtasks included);
|
|
8
|
-
// cockpit's default of include_subtasks=false otherwise undercounts.
|
|
9
|
-
const query = JSON.stringify({
|
|
10
|
-
is_filter_by_logged_in_user: true,
|
|
11
|
-
include_subtasks: true,
|
|
12
|
-
});
|
|
6
|
+
const query = JSON.stringify({ is_filter_by_logged_in_user: true });
|
|
13
7
|
return zeniAPI
|
|
14
8
|
.getJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels/tasks-es-metrics?query=${encodeURIComponent(query)}`)
|
|
15
9
|
.pipe(mergeMap((response) => {
|
|
@@ -168,13 +168,6 @@ const expenseAutomationTransactionsView = createSlice({
|
|
|
168
168
|
if (searchString !== undefined) {
|
|
169
169
|
draft.transactionCategorizationView[selectedTab].uiState.searchString =
|
|
170
170
|
searchString;
|
|
171
|
-
// When search is cleared, drop all sub-tab snapshots. A snapshot
|
|
172
|
-
// captured while search was active holds filtered row IDs — restoring
|
|
173
|
-
// it after the clear would show stale search results instead of the
|
|
174
|
-
// full unfiltered list.
|
|
175
|
-
if (searchString === '' && selectedTab === 'autoCategorized') {
|
|
176
|
-
draft.autoCategorizedSubTabCache = {};
|
|
177
|
-
}
|
|
178
171
|
}
|
|
179
172
|
draft.transactionCategorizationView[selectedTab].error = undefined;
|
|
180
173
|
const monthYearPeriod = {
|
|
@@ -28,7 +28,6 @@ export const initializeTaskToLocalStoreEpic = (actions$, state$) => actions$.pip
|
|
|
28
28
|
recurringStartDate: task.recurringStartDate,
|
|
29
29
|
timeSpent: task.timeSpent,
|
|
30
30
|
isPrivate: task.isPrivate,
|
|
31
|
-
taskGroupId: task.taskGroupIds[0],
|
|
32
31
|
};
|
|
33
32
|
const actions = [
|
|
34
33
|
saveTaskUpdatesToLocalStore({ taskDetailLocalData, taskId }),
|
|
@@ -6,52 +6,23 @@ import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
|
|
|
6
6
|
import { updateTasks } from '../../../../entity/task/taskReducer';
|
|
7
7
|
import { getTaskById } from '../../../../entity/task/taskSelector';
|
|
8
8
|
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
|
|
9
|
-
import {
|
|
9
|
+
import { updateTaskListOnNewTaskCreationSuccess } from '../../taskListView/taskListReducer';
|
|
10
10
|
import { saveTaskDetail, saveTaskSuccessOrFailure } from '../taskDetailReducer';
|
|
11
11
|
export const saveTaskDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(saveTaskDetail.match), mergeMap((action) => {
|
|
12
12
|
const { taskId, taskGroupId } = action.payload;
|
|
13
13
|
const state = state$.value;
|
|
14
14
|
const isTaskListFetched = state.taskListState.fetchState === 'Completed';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
?.taskGroupId
|
|
20
|
-
: undefined;
|
|
21
|
-
// groupWasCleared distinguishes "user explicitly cleared the group"
|
|
22
|
-
// (localTaskGroupId === null → send []) from "user did not touch it"
|
|
23
|
-
// (undefined → fall back to entity). Without this, the `??` fallback
|
|
24
|
-
// would resurrect the stale entity value after a clear.
|
|
25
|
-
const groupWasCleared = taskId != null && localTaskGroupId === null;
|
|
26
|
-
const entityTaskGroupIds = taskId != null
|
|
27
|
-
? (getTaskById(state.taskState, taskId)?.taskGroupIds ?? [])
|
|
28
|
-
: [];
|
|
29
|
-
// Distinguish three save shapes:
|
|
30
|
-
// - cleared → []
|
|
31
|
-
// - user picked a different group locally → [localTaskGroupId]
|
|
32
|
-
// - no local edit → entire entityTaskGroupIds (preserves multi-
|
|
33
|
-
// group membership; without this, unrelated field edits silently
|
|
34
|
-
// drop extra groups).
|
|
35
|
-
const localGroupChanged = localTaskGroupId != null;
|
|
36
|
-
const taskGroupIdsForPayload = groupWasCleared
|
|
37
|
-
? []
|
|
38
|
-
: localGroupChanged
|
|
39
|
-
? [localTaskGroupId]
|
|
40
|
-
: taskId != null
|
|
41
|
-
? entityTaskGroupIds
|
|
42
|
-
: taskGroupId != null
|
|
43
|
-
? [taskGroupId]
|
|
44
|
-
: [];
|
|
45
|
-
// Keep `updatedTaskGroupId` (single id) for downstream list-update
|
|
46
|
-
// dispatches that still bucket against one group at a time.
|
|
47
|
-
const updatedTaskGroupId = taskGroupIdsForPayload[0];
|
|
48
|
-
const payload = prepareTaskPayload(state, taskId, taskGroupIdsForPayload);
|
|
15
|
+
const updatedTaskGroupId = taskId == null
|
|
16
|
+
? taskGroupId
|
|
17
|
+
: getTaskById(state.taskState, taskId)?.taskGroupIds[0];
|
|
18
|
+
const payload = prepareTaskPayload(state, taskId, updatedTaskGroupId);
|
|
49
19
|
const saveTaskApi = taskId != null
|
|
50
20
|
? zeniAPI.putAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks/${taskId}`, payload)
|
|
51
21
|
: zeniAPI.postAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks`, payload);
|
|
52
22
|
return saveTaskApi.pipe(mergeMap((response) => {
|
|
53
23
|
if (isSuccessResponse(response) &&
|
|
54
24
|
response.data != null &&
|
|
25
|
+
updatedTaskGroupId != null &&
|
|
55
26
|
response.data.tasks.length > 0) {
|
|
56
27
|
const newTaskId = response.data.tasks[0].task_id;
|
|
57
28
|
const actions = [
|
|
@@ -62,24 +33,7 @@ export const saveTaskDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe(f
|
|
|
62
33
|
taskId,
|
|
63
34
|
}),
|
|
64
35
|
];
|
|
65
|
-
|
|
66
|
-
// when the saved task's status no longer matches the tab —
|
|
67
|
-
// otherwise doUpdateTaskList writes the row back into the
|
|
68
|
-
// current tab's grouping arrays even after updateTasks moved
|
|
69
|
-
// it to Completed. Archived/snoozed/deleted are owned by
|
|
70
|
-
// their dedicated actions and must keep the pre-PR optimistic
|
|
71
|
-
// update path so their grouping arrays don't go stale.
|
|
72
|
-
const savedTask = response.data.tasks[0];
|
|
73
|
-
const savedIsCompleted = savedTask.status?.code === 'resolved';
|
|
74
|
-
const activeTab = state.taskListState.currentTab;
|
|
75
|
-
const isLiveOrCompletedTab = activeTab === 'live' || activeTab === 'completed';
|
|
76
|
-
const statusMatchesActiveTab = !isLiveOrCompletedTab ||
|
|
77
|
-
(savedIsCompleted && activeTab === 'completed') ||
|
|
78
|
-
(!savedIsCompleted && activeTab === 'live');
|
|
79
|
-
if (isTaskListFetched === true &&
|
|
80
|
-
groupWasCleared === false &&
|
|
81
|
-
updatedTaskGroupId != null &&
|
|
82
|
-
statusMatchesActiveTab === true) {
|
|
36
|
+
if (isTaskListFetched === true) {
|
|
83
37
|
actions.push(updateTaskListOnNewTaskCreationSuccess({
|
|
84
38
|
taskGroupId: updatedTaskGroupId,
|
|
85
39
|
task: response.data.tasks[0],
|
|
@@ -88,21 +42,6 @@ export const saveTaskDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe(f
|
|
|
88
42
|
: undefined,
|
|
89
43
|
}));
|
|
90
44
|
}
|
|
91
|
-
else if (isTaskListFetched === true &&
|
|
92
|
-
groupWasCleared === true &&
|
|
93
|
-
taskId != null) {
|
|
94
|
-
// Group was cleared — skip the list-insert action (no
|
|
95
|
-
// destination bucket) and explicitly drop the row from every
|
|
96
|
-
// previously-held group so the list re-renders without the
|
|
97
|
-
// stale entry under the old group until next refetch.
|
|
98
|
-
const previousTask = getTaskById(state.taskState, taskId);
|
|
99
|
-
previousTask?.taskGroupIds.forEach((previousGroupId) => {
|
|
100
|
-
actions.push(removeTaskFromGroupBucket({
|
|
101
|
-
taskId,
|
|
102
|
-
taskGroupId: previousGroupId,
|
|
103
|
-
}));
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
45
|
return from(actions);
|
|
107
46
|
}
|
|
108
47
|
else {
|
|
@@ -128,7 +67,7 @@ export const saveTaskDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe(f
|
|
|
128
67
|
error: createZeniAPIStatus('Unexpected Error', 'Save Task REST API call errored out' + JSON.stringify(error)),
|
|
129
68
|
}))));
|
|
130
69
|
}));
|
|
131
|
-
const prepareTaskPayload = (state, taskId,
|
|
70
|
+
const prepareTaskPayload = (state, taskId, taskGroupId) => {
|
|
132
71
|
const { taskDetailState, taskState } = state;
|
|
133
72
|
const syncToken = taskId != null ? (getTaskById(taskState, taskId)?.syncToken ?? '') : '';
|
|
134
73
|
const sourceState = taskId != null
|
|
@@ -157,7 +96,7 @@ const prepareTaskPayload = (state, taskId, taskGroupIds) => {
|
|
|
157
96
|
? (localData.recurringDaysOfWeek ?? [])
|
|
158
97
|
: [],
|
|
159
98
|
sync_token: syncToken,
|
|
160
|
-
task_group_ids:
|
|
99
|
+
task_group_ids: taskGroupId != null ? [taskGroupId] : [],
|
|
161
100
|
time_spent: convertHHMMStrToMinutes(localData.timeSpent),
|
|
162
101
|
group_assignees: localData.groupAssignees,
|
|
163
102
|
...(taskId == null ? { is_private: localData.isPrivate ?? false } : {}),
|
|
@@ -6,11 +6,6 @@ import { initialTaskDetail, } from './taskDetail';
|
|
|
6
6
|
export const initialState = {
|
|
7
7
|
newTaskState: initialTaskDetail,
|
|
8
8
|
editTaskStateById: {},
|
|
9
|
-
subTaskCreateStatus: {
|
|
10
|
-
fetchState: 'Not-Started',
|
|
11
|
-
error: undefined,
|
|
12
|
-
},
|
|
13
|
-
subTaskListFetchStatusByParentId: {},
|
|
14
9
|
taskHistoryById: {},
|
|
15
10
|
};
|
|
16
11
|
const taskDetailView = createSlice({
|
|
@@ -55,7 +50,7 @@ const taskDetailView = createSlice({
|
|
|
55
50
|
updateEditTaskFetchStatus(draft, action) {
|
|
56
51
|
const { taskId, fetchState, error } = action.payload;
|
|
57
52
|
draft.editTaskStateById[taskId] = {
|
|
58
|
-
...
|
|
53
|
+
...draft.editTaskStateById[taskId],
|
|
59
54
|
fetchTaskStatus: {
|
|
60
55
|
fetchState,
|
|
61
56
|
error: fetchState === 'Error' ? error : undefined,
|
|
@@ -323,59 +318,10 @@ const taskDetailView = createSlice({
|
|
|
323
318
|
error,
|
|
324
319
|
};
|
|
325
320
|
},
|
|
326
|
-
createSubTask: {
|
|
327
|
-
reducer(draft) {
|
|
328
|
-
draft.subTaskCreateStatus = {
|
|
329
|
-
fetchState: 'In-Progress',
|
|
330
|
-
error: undefined,
|
|
331
|
-
};
|
|
332
|
-
},
|
|
333
|
-
prepare(payload) {
|
|
334
|
-
return { payload };
|
|
335
|
-
},
|
|
336
|
-
},
|
|
337
|
-
createSubTaskSuccessOrFailure(draft, action) {
|
|
338
|
-
const { fetchState, error } = action.payload;
|
|
339
|
-
draft.subTaskCreateStatus = {
|
|
340
|
-
fetchState,
|
|
341
|
-
error,
|
|
342
|
-
};
|
|
343
|
-
},
|
|
344
|
-
resetSubTaskCreateStatus(draft) {
|
|
345
|
-
draft.subTaskCreateStatus = {
|
|
346
|
-
...initialState.subTaskCreateStatus,
|
|
347
|
-
};
|
|
348
|
-
},
|
|
349
|
-
fetchSubTasks: {
|
|
350
|
-
reducer(draft, action) {
|
|
351
|
-
const { parentTaskId } = action.payload;
|
|
352
|
-
draft.subTaskListFetchStatusByParentId[parentTaskId] = {
|
|
353
|
-
fetchState: 'In-Progress',
|
|
354
|
-
error: undefined,
|
|
355
|
-
};
|
|
356
|
-
},
|
|
357
|
-
prepare(parentTaskId) {
|
|
358
|
-
return { payload: { parentTaskId } };
|
|
359
|
-
},
|
|
360
|
-
},
|
|
361
|
-
updateSubTasks(draft, action) {
|
|
362
|
-
const { parentTaskId } = action.payload;
|
|
363
|
-
draft.subTaskListFetchStatusByParentId[parentTaskId] = {
|
|
364
|
-
fetchState: 'Completed',
|
|
365
|
-
error: undefined,
|
|
366
|
-
};
|
|
367
|
-
},
|
|
368
|
-
updateSubTasksFetchStatus(draft, action) {
|
|
369
|
-
const { parentTaskId, fetchState, error } = action.payload;
|
|
370
|
-
draft.subTaskListFetchStatusByParentId[parentTaskId] = {
|
|
371
|
-
fetchState,
|
|
372
|
-
error,
|
|
373
|
-
};
|
|
374
|
-
},
|
|
375
321
|
clearTaskDetail(draft) {
|
|
376
322
|
Object.assign(draft, initialState);
|
|
377
323
|
},
|
|
378
324
|
},
|
|
379
325
|
});
|
|
380
|
-
export const { fetchTaskDetailPage, fetchTaskDetail, initializeTaskToLocalStore, updateEditTaskFetchStatus, saveTaskUpdatesToLocalStore, discardTaskUpdatesInLocalStore, saveTaskDetail, archiveTask, archiveTaskSuccessOrFailure, saveTaskSuccessOrFailure,
|
|
326
|
+
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;
|
|
381
327
|
export default taskDetailView.reducer;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import isEqual from 'lodash/isEqual';
|
|
2
|
-
import {
|
|
2
|
+
import { reduceFetchState } from '../../../commonStateTypes/reduceFetchState';
|
|
3
3
|
import { getClassesByIds } from '../../../entity/class/classSelector';
|
|
4
4
|
import { getFilesByFileIds } from '../../../entity/file/fileSelector';
|
|
5
|
-
import { getTaskById
|
|
5
|
+
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';
|
|
@@ -24,58 +24,40 @@ export const getTaskDetail = (state, taskId) => {
|
|
|
24
24
|
let createdByUser = undefined;
|
|
25
25
|
let isArchived = undefined;
|
|
26
26
|
let isDeleted = undefined;
|
|
27
|
-
let depth = undefined;
|
|
28
27
|
let recurringSourceTaskId = undefined;
|
|
29
28
|
let snoozedUntil = undefined;
|
|
30
29
|
let taskGroupId = undefined;
|
|
31
|
-
let subtasks = [];
|
|
32
30
|
if (taskId != null && sourceTaskDetail != null) {
|
|
33
31
|
const taskEntity = getTaskById(taskState, taskId);
|
|
34
|
-
subtasks =
|
|
35
|
-
taskEntity != null
|
|
36
|
-
? getTasksByIds(taskState, taskEntity.subTasksIds)
|
|
37
|
-
: [];
|
|
38
32
|
const fileIdsInEntity = taskEntity?.fileIds ?? [];
|
|
39
33
|
if (taskEntity != null) {
|
|
40
34
|
createdByUser = getUserAndUserRole(userState, userRoleState, addressState, taskEntity.createdBy);
|
|
41
|
-
depth = taskEntity.depth;
|
|
42
35
|
isArchived = taskEntity.isArchived;
|
|
43
36
|
isDeleted = taskEntity.isDeleted;
|
|
44
37
|
recurringSourceTaskId = taskEntity.recurringSourceTaskId;
|
|
45
38
|
snoozedUntil = taskEntity.snoozedUntil;
|
|
46
39
|
taskGroupId = taskEntity.taskGroupIds[0];
|
|
47
40
|
}
|
|
48
|
-
// Treat "no entry" as Completed so it doesn't block the combined
|
|
49
|
-
// fetch state. The Not-Started default would pin the detail page
|
|
50
|
-
// below Completed forever before the first fetchSubTasks dispatches.
|
|
51
|
-
const completedSubTaskStatus = {
|
|
52
|
-
fetchState: 'Completed',
|
|
53
|
-
error: undefined,
|
|
54
|
-
};
|
|
55
|
-
const subTaskStatus = taskDetailState.subTaskListFetchStatusByParentId[taskId] ??
|
|
56
|
-
completedSubTaskStatus;
|
|
57
41
|
if (fileIdsInEntity.length > 0) {
|
|
58
|
-
fetchStatus =
|
|
42
|
+
fetchStatus = reduceFetchState([
|
|
59
43
|
fileViewState.fetchFilesStatus,
|
|
60
44
|
sourceTaskDetail.fetchTaskStatus,
|
|
61
45
|
userList,
|
|
62
46
|
classListState,
|
|
63
|
-
subTaskStatus,
|
|
64
47
|
]);
|
|
65
48
|
}
|
|
66
49
|
else {
|
|
67
|
-
fetchStatus =
|
|
50
|
+
fetchStatus = reduceFetchState([
|
|
68
51
|
sourceTaskDetail.fetchTaskStatus,
|
|
69
52
|
userList,
|
|
70
53
|
classListState,
|
|
71
|
-
subTaskStatus,
|
|
72
54
|
]);
|
|
73
55
|
}
|
|
74
56
|
showTaskDetailFormFooter = showFormFooter(sourceTaskDetail.taskDetailLocalData, taskEntity);
|
|
75
57
|
taskHistory = taskDetailState.taskHistoryById[taskId]?.historicEvents ?? [];
|
|
76
58
|
}
|
|
77
59
|
else if (taskId == null) {
|
|
78
|
-
fetchStatus =
|
|
60
|
+
fetchStatus = reduceFetchState([userList, classListState]);
|
|
79
61
|
}
|
|
80
62
|
const { classIds } = classListState;
|
|
81
63
|
const allAccountingClasses = getClassesByIds(classState, {
|
|
@@ -102,14 +84,12 @@ export const getTaskDetail = (state, taskId) => {
|
|
|
102
84
|
error: fetchStatus.error,
|
|
103
85
|
version: 0,
|
|
104
86
|
createdByUser,
|
|
105
|
-
depth,
|
|
106
87
|
isArchived,
|
|
107
88
|
isDeleted,
|
|
108
89
|
recurringSourceTaskId,
|
|
109
90
|
showTaskDetailFormFooter,
|
|
110
91
|
snoozedUntil,
|
|
111
92
|
taskGroupId,
|
|
112
|
-
subtasks,
|
|
113
93
|
};
|
|
114
94
|
};
|
|
115
95
|
export const allTaskStatus = [
|
|
@@ -157,16 +137,13 @@ export const allTaskPriority = [
|
|
|
157
137
|
},
|
|
158
138
|
];
|
|
159
139
|
const showFormFooter = (taskDetailLocalData, taskDetailInStore) => {
|
|
160
|
-
if (
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
if (taskDetailLocalData.name !== taskDetailInStore.name ||
|
|
140
|
+
if (taskDetailLocalData.name !== taskDetailInStore?.name ||
|
|
164
141
|
taskDetailLocalData.description !== taskDetailInStore.description ||
|
|
165
142
|
taskDetailLocalData.priority !== taskDetailInStore.priority.code ||
|
|
166
143
|
taskDetailLocalData.status !== taskDetailInStore.status.code ||
|
|
167
144
|
!isEqual(taskDetailInStore.tagIds, taskDetailLocalData.tagIds) ||
|
|
168
|
-
!isEqual(taskDetailLocalData.assignee, taskDetailInStore
|
|
169
|
-
!isEqual(taskDetailLocalData.groupAssignees, taskDetailInStore
|
|
145
|
+
!isEqual(taskDetailLocalData.assignee, taskDetailInStore?.assignees ?? []) ||
|
|
146
|
+
!isEqual(taskDetailLocalData.groupAssignees, taskDetailInStore?.groupAssignees ?? []) ||
|
|
170
147
|
!isEqual(taskDetailLocalData.fileIds, taskDetailInStore.fileIds ?? []) ||
|
|
171
148
|
!isEqual(taskDetailLocalData.dueDate, taskDetailInStore.dueDate) ||
|
|
172
149
|
!isEqual(taskDetailLocalData.type, taskDetailInStore.type) ||
|
|
@@ -174,10 +151,7 @@ const showFormFooter = (taskDetailLocalData, taskDetailInStore) => {
|
|
|
174
151
|
!isEqual(taskDetailLocalData.recurringFrequency, taskDetailInStore.recurringFrequency) ||
|
|
175
152
|
!isEqual(taskDetailLocalData.recurringDaysOfWeek, taskDetailInStore.recurringDaysOfWeek) ||
|
|
176
153
|
!isEqual(taskDetailLocalData.recurringStartDate, taskDetailInStore.recurringStartDate) ||
|
|
177
|
-
!isEqual(taskDetailLocalData.timeSpent, taskDetailInStore.timeSpent)
|
|
178
|
-
!isEqual(taskDetailLocalData.taskGroupId, taskDetailInStore.taskGroupIds.length > 0
|
|
179
|
-
? taskDetailInStore.taskGroupIds[0]
|
|
180
|
-
: undefined)) {
|
|
154
|
+
!isEqual(taskDetailLocalData.timeSpent, taskDetailInStore.timeSpent)) {
|
|
181
155
|
return true;
|
|
182
156
|
}
|
|
183
157
|
return false;
|
|
@@ -9,17 +9,15 @@ 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
|
|
12
|
+
const { tasks, deleted, archived, snoozed } = response.data;
|
|
13
13
|
const allTasks = [
|
|
14
14
|
...tasks,
|
|
15
|
-
...(completed ?? []),
|
|
16
15
|
...(deleted ?? []),
|
|
17
16
|
...(archived ?? []),
|
|
18
17
|
...(snoozed ?? []),
|
|
19
18
|
];
|
|
20
19
|
return of(updateTasks(allTasks), updateTaskList({
|
|
21
20
|
data: tasks,
|
|
22
|
-
completed: completed ?? [],
|
|
23
21
|
deleted: deleted ?? [],
|
|
24
22
|
archived: archived ?? [],
|
|
25
23
|
snoozed: snoozed ?? [],
|