@zeniai/client-epic-state 5.3.10 → 5.3.12-beta0DI

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 (66) hide show
  1. package/lib/entity/task/taskPayload.d.ts +1 -0
  2. package/lib/entity/task/taskPayload.js +1 -0
  3. package/lib/entity/task/taskReducer.d.ts +4 -1
  4. package/lib/entity/task/taskReducer.js +19 -2
  5. package/lib/entity/task/taskState.d.ts +3 -0
  6. package/lib/entity/timeEntry/timeEntryPayload.d.ts +26 -0
  7. package/lib/entity/timeEntry/timeEntryPayload.js +2 -0
  8. package/lib/entity/timeEntry/timeEntryReducer.d.ts +8 -0
  9. package/lib/entity/timeEntry/timeEntryReducer.js +76 -0
  10. package/lib/entity/timeEntry/timeEntrySelector.d.ts +10 -0
  11. package/lib/entity/timeEntry/timeEntrySelector.js +32 -0
  12. package/lib/entity/timeEntry/timeEntryState.d.ts +43 -0
  13. package/lib/entity/timeEntry/timeEntryState.js +13 -0
  14. package/lib/epic.d.ts +4 -1
  15. package/lib/epic.js +9 -0
  16. package/lib/esm/entity/task/taskPayload.js +1 -0
  17. package/lib/esm/entity/task/taskReducer.js +18 -1
  18. package/lib/esm/entity/timeEntry/timeEntryPayload.js +1 -0
  19. package/lib/esm/entity/timeEntry/timeEntryReducer.js +70 -0
  20. package/lib/esm/entity/timeEntry/timeEntrySelector.js +23 -0
  21. package/lib/esm/entity/timeEntry/timeEntryState.js +8 -0
  22. package/lib/esm/epic.js +9 -0
  23. package/lib/esm/index.js +4 -1
  24. package/lib/esm/reducer.js +6 -0
  25. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +3 -0
  26. package/lib/esm/view/taskManager/taskListView/taskList.js +6 -0
  27. package/lib/esm/view/taskManager/taskListView/taskListFilterHelpers.js +7 -0
  28. package/lib/esm/view/taskManager/taskListView/taskListSelector.js +27 -11
  29. package/lib/esm/view/taskManager/taskListView/taskListViewHelpers.js +37 -0
  30. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +24 -0
  31. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +73 -0
  32. package/lib/esm/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +77 -0
  33. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewPayload.js +1 -0
  34. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewReducer.js +160 -0
  35. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewSelector.js +41 -0
  36. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewState.js +1 -0
  37. package/lib/index.d.ts +5 -1
  38. package/lib/index.js +31 -16
  39. package/lib/reducer.d.ts +2 -0
  40. package/lib/reducer.js +6 -0
  41. package/lib/rootStateTypes.d.ts +4 -0
  42. package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +4 -0
  43. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +3 -0
  44. package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
  45. package/lib/view/taskManager/taskListView/taskList.js +6 -0
  46. package/lib/view/taskManager/taskListView/taskListFilterHelpers.d.ts +4 -0
  47. package/lib/view/taskManager/taskListView/taskListFilterHelpers.js +9 -1
  48. package/lib/view/taskManager/taskListView/taskListSelector.d.ts +6 -3
  49. package/lib/view/taskManager/taskListView/taskListSelector.js +26 -10
  50. package/lib/view/taskManager/taskListView/taskListViewHelpers.d.ts +1 -1
  51. package/lib/view/taskManager/taskListView/taskListViewHelpers.js +37 -0
  52. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.d.ts +18 -0
  53. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +28 -0
  54. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.d.ts +23 -0
  55. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +78 -0
  56. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.d.ts +23 -0
  57. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +83 -0
  58. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.d.ts +27 -0
  59. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.js +2 -0
  60. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.d.ts +48 -0
  61. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.js +164 -0
  62. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.d.ts +24 -0
  63. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.js +46 -0
  64. package/lib/view/taskManager/timeEntryView/timeEntryViewState.d.ts +21 -0
  65. package/lib/view/taskManager/timeEntryView/timeEntryViewState.js +5 -0
  66. package/package.json +1 -1
package/lib/reducer.js CHANGED
@@ -109,6 +109,7 @@ const taskGroupReducer_1 = __importStar(require("./entity/taskGroup/taskGroupRed
109
109
  const taskGroupTemplateReducer_1 = __importStar(require("./entity/taskGroupTemplate/taskGroupTemplateReducer"));
110
110
  const taskSummaryReducer_1 = __importStar(require("./entity/taskSummary/taskSummaryReducer"));
111
111
  const tenantReducer_1 = __importStar(require("./entity/tenant/tenantReducer"));
112
+ const timeEntryReducer_1 = __importStar(require("./entity/timeEntry/timeEntryReducer"));
112
113
  const toastNotificationReducer_1 = __importStar(require("./entity/toastNotification/toastNotificationReducer"));
113
114
  const transactionReducer_1 = __importStar(require("./entity/transaction/transactionReducer"));
114
115
  const transactionActivityLogReducer_1 = __importStar(require("./entity/transactionActivityLog/transactionActivityLogReducer"));
@@ -295,6 +296,7 @@ const taskDetailReducer_1 = __importStar(require("./view/taskManager/taskDetailV
295
296
  const taskGroupTemplateViewReducer_1 = __importStar(require("./view/taskManager/taskGroupTemplateView/taskGroupTemplateViewReducer"));
296
297
  const taskGroupViewReducer_1 = __importStar(require("./view/taskManager/taskGroupView/taskGroupViewReducer"));
297
298
  const taskListReducer_1 = __importStar(require("./view/taskManager/taskListView/taskListReducer"));
299
+ const timeEntryViewReducer_1 = __importStar(require("./view/taskManager/timeEntryView/timeEntryViewReducer"));
298
300
  const tasksCardReducer_1 = __importStar(require("./view/tasksCard/tasksCardReducer"));
299
301
  const topExReducer_1 = __importStar(require("./view/topEx/topExReducer"));
300
302
  const transactionActivityLogViewReducer_1 = __importStar(require("./view/transactionActivityLogView/transactionActivityLogViewReducer"));
@@ -383,6 +385,7 @@ const initialEntitiesState = {
383
385
  subscriptionState: subscriptionReducer_1.initialState,
384
386
  subscriptionSummaryState: subscriptionSummaryReducer_1.initialState,
385
387
  tagState: tagReducer_1.initialState,
388
+ timeEntryState: timeEntryReducer_1.initialState,
386
389
  taskGroupState: taskGroupReducer_1.initialState,
387
390
  taskGroupTemplateState: taskGroupTemplateReducer_1.initialState,
388
391
  taskState: taskReducer_1.initialState,
@@ -565,6 +568,7 @@ const initialViewsState = {
565
568
  taskGroupTemplateViewState: taskGroupTemplateViewReducer_1.initialState,
566
569
  taskGroupViewState: taskGroupViewReducer_1.initialState,
567
570
  taskListState: taskListReducer_1.initialState,
571
+ timeEntryViewState: timeEntryViewReducer_1.initialState,
568
572
  tasksCardState: tasksCardReducer_1.initialState,
569
573
  topExState: topExReducer_1.initialState,
570
574
  transactionActivityLogViewState: transactionActivityLogViewReducer_1.initialState,
@@ -673,6 +677,7 @@ const entityReducers = {
673
677
  subscriptionState: subscriptionReducer_1.default,
674
678
  subscriptionSummaryState: subscriptionSummaryReducer_1.default,
675
679
  tagState: tagReducer_1.default,
680
+ timeEntryState: timeEntryReducer_1.default,
676
681
  taskGroupState: taskGroupReducer_1.default,
677
682
  taskGroupTemplateState: taskGroupTemplateReducer_1.default,
678
683
  taskState: taskReducer_1.default,
@@ -854,6 +859,7 @@ const viewReducers = {
854
859
  taskGroupTemplateViewState: taskGroupTemplateViewReducer_1.default,
855
860
  taskGroupViewState: taskGroupViewReducer_1.default,
856
861
  taskListState: taskListReducer_1.default,
862
+ timeEntryViewState: timeEntryViewReducer_1.default,
857
863
  tagViewState: tagViewReducer_1.default,
858
864
  tasksCardState: tasksCardReducer_1.default,
859
865
  topExState: topExReducer_1.default,
@@ -69,6 +69,7 @@ import { TaskGroupState } from './entity/taskGroup/taskGroupState';
69
69
  import { TaskGroupTemplateState } from './entity/taskGroupTemplate/taskGroupTemplateState';
70
70
  import { TaskSummaryState } from './entity/taskSummary/taskSummaryState';
71
71
  import { TenantState } from './entity/tenant/tenantState';
72
+ import { TimeEntryState } from './entity/timeEntry/timeEntryState';
72
73
  import { ToastNotificationState } from './entity/toastNotification/toastNotificationState';
73
74
  import { TransactionState } from './entity/transaction/transactionState';
74
75
  import { TransactionActivityLogState } from './entity/transactionActivityLog/transactionActivityLogState';
@@ -253,6 +254,7 @@ import { TaskDetailViewState } from './view/taskManager/taskDetailView/taskDetai
253
254
  import { TaskGroupTemplateViewState } from './view/taskManager/taskGroupTemplateView/taskGroupTemplateViewState';
254
255
  import { TaskGroupViewState } from './view/taskManager/taskGroupView/taskGroupViewState';
255
256
  import { TaskListState } from './view/taskManager/taskListView/taskList';
257
+ import { TimeEntryViewState } from './view/taskManager/timeEntryView/timeEntryViewState';
256
258
  import { TasksCardState } from './view/tasksCard/tasksCardState';
257
259
  import { TopExState } from './view/topEx/topExState';
258
260
  import { TransactionActivityLogViewState } from './view/transactionActivityLogView/transactionActivityLogViewState';
@@ -345,6 +347,7 @@ export type EntitiesState = {
345
347
  taskState: TaskState;
346
348
  taskSummaryState: TaskSummaryState;
347
349
  tenantState: TenantState;
350
+ timeEntryState: TimeEntryState;
348
351
  toastNotificationState: ToastNotificationState;
349
352
  transactionActivityLogState: TransactionActivityLogState;
350
353
  transactionState: TransactionState;
@@ -523,6 +526,7 @@ export type ViewsState = {
523
526
  taskGroupViewState: TaskGroupViewState;
524
527
  taskListState: TaskListState;
525
528
  tasksCardState: TasksCardState;
529
+ timeEntryViewState: TimeEntryViewState;
526
530
  topExState: TopExState;
527
531
  transactionActivityLogViewState: TransactionActivityLogViewState;
528
532
  transactionDetailState: TransactionDetailState;
@@ -25,6 +25,10 @@ export interface TaskDetailSelectorView extends SelectorView {
25
25
  isDeleted?: boolean;
26
26
  recurringSourceTaskId?: ID;
27
27
  snoozedUntil?: ZeniDate | null;
28
+ /** Drives the Category control in the For Internal Use block. Read from
29
+ * the task entity rather than mirrored into local form data: it is not
30
+ * editable inline, and a mirror would need its own discard path. */
31
+ taskCategoryId?: ID;
28
32
  taskGroupId?: ID;
29
33
  }
30
34
  export declare const getTaskDetail: (state: RootState, taskId?: ID) => TaskDetailSelectorView;
@@ -32,6 +32,7 @@ const getTaskDetail = (state, taskId) => {
32
32
  let isDeleted = undefined;
33
33
  let depth = undefined;
34
34
  let recurringSourceTaskId = undefined;
35
+ let taskCategoryId = undefined;
35
36
  let snoozedUntil = undefined;
36
37
  let taskGroupId = undefined;
37
38
  let subtasks = [];
@@ -45,6 +46,7 @@ const getTaskDetail = (state, taskId) => {
45
46
  if (taskEntity != null) {
46
47
  createdByUser = (0, userAndRole_1.getUserAndUserRole)(userState, userRoleState, addressState, taskEntity.createdBy);
47
48
  depth = taskEntity.depth;
49
+ taskCategoryId = taskEntity.taskCategoryId;
48
50
  isArchived = taskEntity.isArchived;
49
51
  isDeleted = taskEntity.isDeleted;
50
52
  recurringSourceTaskId = taskEntity.recurringSourceTaskId;
@@ -109,6 +111,7 @@ const getTaskDetail = (state, taskId) => {
109
111
  version: 0,
110
112
  createdByUser,
111
113
  depth,
114
+ taskCategoryId,
112
115
  isArchived,
113
116
  isDeleted,
114
117
  recurringSourceTaskId,
@@ -48,7 +48,7 @@ export interface TaskFilterCategory {
48
48
  values: (string | ZeniDate)[];
49
49
  valuesCombinationOperator: 'ANY';
50
50
  }
51
- export type TaskListFilterCategoryField = 'status' | 'dueDate' | 'assignee' | 'creationDate' | 'priority' | 'tag';
51
+ export type TaskListFilterCategoryField = 'status' | 'dueDate' | 'assignee' | 'createdBy' | 'creationDate' | 'priority' | 'tag' | 'billing';
52
52
  export declare const TASK_LIST_GROUP_BY_KEYS: readonly ["groupName", "status", "dueDate", "assignee", "priority", "tag"];
53
53
  export declare const toTaskListGroupByKeyType: (v: string) => "status" | "dueDate" | "priority" | "assignee" | "tag" | "groupName";
54
54
  export declare const toTaskListGroupByKeyTypeStrict: (v: string) => "status" | "dueDate" | "priority" | "assignee" | "tag" | "groupName" | undefined;
@@ -53,7 +53,13 @@ exports.TASK_LIST_FILTER_CATEGORIES = [
53
53
  type: 'user',
54
54
  multiple: true,
55
55
  },
56
+ {
57
+ value: 'createdBy',
58
+ type: 'user',
59
+ multiple: true,
60
+ },
56
61
  { value: 'creationDate', type: 'dateRange', multiple: true },
62
+ { value: 'billing', type: 'dropdown', multiple: true },
57
63
  ];
58
64
  exports.TASK_LIST_GROUP_BY_CATEGORIES = [
59
65
  { value: 'status' },
@@ -1,3 +1,7 @@
1
+ import { ID } from '../../../commonStateTypes/common';
1
2
  import { Task } from '../../../entity/task/taskState';
3
+ import { TaskCategory } from '../../../entity/timeEntry/timeEntryState';
2
4
  import { FilterCategoryValueType } from '../../spendManagement/spendManagementFilterHelpers';
5
+ /** Billing lives on the task's category, not the task, so it needs the catalog. */
6
+ export declare const buildCategoryValueGetter: (taskCategoriesById: Record<ID, TaskCategory>) => (key: string, task: Task) => FilterCategoryValueType | (string | undefined)[] | undefined;
3
7
  export declare const getCategoryValueForTaskList: (key: string, task: Task) => FilterCategoryValueType | (string | undefined)[] | undefined;
@@ -1,6 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getCategoryValueForTaskList = void 0;
3
+ exports.getCategoryValueForTaskList = exports.buildCategoryValueGetter = void 0;
4
+ /** Billing lives on the task's category, not the task, so it needs the catalog. */
5
+ const buildCategoryValueGetter = (taskCategoriesById) => (key, task) => key === 'billing'
6
+ ? (taskCategoriesById[task.taskCategoryId ?? '']?.billingType ??
7
+ 'non_billable')
8
+ : (0, exports.getCategoryValueForTaskList)(key, task);
9
+ exports.buildCategoryValueGetter = buildCategoryValueGetter;
4
10
  const getCategoryValueForTaskList = (key, task) => {
5
11
  switch (key) {
6
12
  case 'dueDate':
@@ -15,6 +21,8 @@ const getCategoryValueForTaskList = (key, task) => {
15
21
  return task.createTime;
16
22
  case 'assignee':
17
23
  return task.assignees;
24
+ case 'createdBy':
25
+ return task.createdBy;
18
26
  default:
19
27
  return undefined;
20
28
  }
@@ -1,9 +1,10 @@
1
- import { FetchStateAndError } from '../../../commonStateTypes/common';
1
+ import { FetchStateAndError, ID } from '../../../commonStateTypes/common';
2
2
  import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
3
3
  import { AddressState } from '../../../entity/address/addressState';
4
4
  import { TagState } from '../../../entity/tag/tagState';
5
5
  import { Task, TaskState } from '../../../entity/task/taskState';
6
6
  import { TaskGroupTemplate } from '../../../entity/taskGroupTemplate/taskGroupTemplateState';
7
+ import { TaskCategory } from '../../../entity/timeEntry/timeEntryState';
7
8
  import { UserState } from '../../../entity/user/userState';
8
9
  import { UserGroupsState } from '../../../entity/userGroups/userGroupsState';
9
10
  import { UserRoleState } from '../../../entity/userRole/userRoleState';
@@ -48,9 +49,10 @@ export interface TaskListSelectorView extends SelectorView {
48
49
  * slice. `TaskListState` still satisfies this, so callers are unaffected.
49
50
  */
50
51
  type TaskListGroupingInputs = Pick<TaskListState, 'filters' | 'taskIdsByAssignees' | 'taskIdsByDueDate' | 'taskIdsByGroupsIds' | 'taskIdsByPriority' | 'taskIdsByStatus' | 'taskIdsByTags' | 'uiState'>;
51
- export declare const getTaskListGroupedByAssignees: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }: {
52
+ export declare const getTaskListGroupedByAssignees: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }: {
52
53
  addressState: AddressState;
53
54
  tagState: TagState;
55
+ taskCategoriesById: Record<ID, TaskCategory>;
54
56
  taskListState: TaskListGroupingInputs;
55
57
  taskState: TaskState;
56
58
  userGroupsState: UserGroupsState;
@@ -62,9 +64,10 @@ export declare const getTaskListGroupedByAssignees: ({ taskListState, taskState,
62
64
  isDefault: boolean;
63
65
  tasks: TaskWithUserDetails[];
64
66
  }[];
65
- export declare const getTaskListGroupedByPriority: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }: {
67
+ export declare const getTaskListGroupedByPriority: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }: {
66
68
  addressState: AddressState;
67
69
  tagState: TagState;
70
+ taskCategoriesById: Record<ID, TaskCategory>;
68
71
  taskListState: TaskListGroupingInputs;
69
72
  taskState: TaskState;
70
73
  userGroupsState: UserGroupsState;
@@ -53,7 +53,7 @@ const sortTasksList = (tagState, tasksList, sortKey, sortOrder) => {
53
53
  }, sortOrder);
54
54
  return tasksInOrder;
55
55
  };
56
- const getTasksWithUserDetails = ({ taskListState, taskState, userState, userRoleState, addressState, taskIds, tagState, userGroupsState, }) => {
56
+ const getTasksWithUserDetails = ({ taskListState, taskState, userState, userRoleState, addressState, taskIds, tagState, userGroupsState, taskCategoriesById, }) => {
57
57
  const { sortKey, searchText } = taskListState.uiState;
58
58
  const sortOrder = (0, sortOrderPayload_1.getSortOrder)(taskListState.uiState.sortOrder);
59
59
  const tasks = taskIds
@@ -76,11 +76,11 @@ const getTasksWithUserDetails = ({ taskListState, taskState, userState, userRole
76
76
  return undefined;
77
77
  })
78
78
  .filter((value) => value?.name.toLowerCase().includes(searchText.toLowerCase()) === true);
79
- const filteredTaskList = (0, spendManagementFilterHelpers_1.applyAdvancedFiltersOnList)(taskListFilterHelpers_1.getCategoryValueForTaskList, tasks, taskListState.filters);
79
+ const filteredTaskList = (0, spendManagementFilterHelpers_1.applyAdvancedFiltersOnList)((0, taskListFilterHelpers_1.buildCategoryValueGetter)(taskCategoriesById), tasks, taskListState.filters);
80
80
  const sortedTaskList = sortTasksList(tagState, filteredTaskList, sortKey, sortOrder);
81
81
  return sortedTaskList;
82
82
  };
83
- const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupState, taskGroupsIds, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
83
+ const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupState, taskGroupsIds, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
84
84
  const taskGroupsWithTasksList = taskGroupsIds
85
85
  .map((taskGroupId) => {
86
86
  const taskGroup = (0, taskGroupSelector_1.getTaskGroupById)(taskGroupState, taskGroupId);
@@ -94,6 +94,7 @@ const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupStat
94
94
  taskIds,
95
95
  tagState,
96
96
  userGroupsState,
97
+ taskCategoriesById,
97
98
  });
98
99
  if (taskGroup != null) {
99
100
  return {
@@ -125,7 +126,7 @@ const getTaskListGroupedByGroupName = ({ taskListState, taskState, taskGroupStat
125
126
  // Also hides deleted groups, which are empty as a side effect.
126
127
  return sortedTaskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
127
128
  };
128
- const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
129
+ const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
129
130
  const assigneeGroups = Object.keys(taskListState.taskIdsByAssignees);
130
131
  const taskGroupsWithTasksList = assigneeGroups.map((groupKey) => {
131
132
  const taskIds = taskListState.taskIdsByAssignees[groupKey];
@@ -138,6 +139,7 @@ const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, us
138
139
  taskIds,
139
140
  tagState,
140
141
  userGroupsState,
142
+ taskCategoriesById,
141
143
  });
142
144
  const assigneeIds = groupKey.split(',');
143
145
  const groupName = (0, userSelector_1.getUsersByUserIds)(userState, assigneeIds)
@@ -156,7 +158,7 @@ const getTaskListGroupedByAssignees = ({ taskListState, taskState, userState, us
156
158
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
157
159
  };
158
160
  exports.getTaskListGroupedByAssignees = getTaskListGroupedByAssignees;
159
- const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
161
+ const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
160
162
  const taskGroupsWithTasksList = taskState_1.ALL_PRIORITY_CODE.map((groupKey) => {
161
163
  const taskIds = taskListState.taskIdsByPriority[groupKey] ?? [];
162
164
  const tasksWithUserDetails = getTasksWithUserDetails({
@@ -168,6 +170,7 @@ const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, use
168
170
  taskIds,
169
171
  tagState,
170
172
  userGroupsState,
173
+ taskCategoriesById,
171
174
  });
172
175
  return {
173
176
  groupName: taskDetailSelector_1.allTaskPriority.find((priority) => priority.code === groupKey)?.name ??
@@ -180,7 +183,7 @@ const getTaskListGroupedByPriority = ({ taskListState, taskState, userState, use
180
183
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
181
184
  };
182
185
  exports.getTaskListGroupedByPriority = getTaskListGroupedByPriority;
183
- const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
186
+ const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
184
187
  const taskGroupsWithTasksList = taskState_1.ALL_TASK_STATUS_CODE.map((groupKey) => {
185
188
  const taskIds = taskListState.taskIdsByStatus[groupKey] ?? [];
186
189
  const tasksWithUserDetails = getTasksWithUserDetails({
@@ -192,6 +195,7 @@ const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userR
192
195
  taskIds,
193
196
  tagState,
194
197
  userGroupsState,
198
+ taskCategoriesById,
195
199
  });
196
200
  return {
197
201
  groupName: taskDetailSelector_1.allTaskStatus.find((taskStatus) => taskStatus.code === groupKey)
@@ -203,7 +207,7 @@ const getTaskListGroupedByStatus = ({ taskListState, taskState, userState, userR
203
207
  });
204
208
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
205
209
  };
206
- const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
210
+ const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
207
211
  const tagGroups = Object.keys(taskListState.taskIdsByTags);
208
212
  const taskGroupsWithTasksList = tagGroups.map((groupKey) => {
209
213
  const taskIds = taskListState.taskIdsByTags[groupKey];
@@ -216,6 +220,7 @@ const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRol
216
220
  taskIds,
217
221
  tagState,
218
222
  userGroupsState,
223
+ taskCategoriesById,
219
224
  });
220
225
  const tagIds = groupKey.split(',');
221
226
  const groupName = (0, tagSelector_1.getTagsByIds)(tagState, tagIds)
@@ -232,7 +237,7 @@ const getTaskListGroupedByTags = ({ taskListState, taskState, userState, userRol
232
237
  });
233
238
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
234
239
  };
235
- const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }) => {
240
+ const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }) => {
236
241
  const taskGroupsWithTasksList = taskList_1.DUE_DATE_GROUP_KEYS.map((groupKey) => {
237
242
  const taskIds = taskListState.taskIdsByDueDate[groupKey];
238
243
  const tasksWithUserDetails = getTasksWithUserDetails({
@@ -244,6 +249,7 @@ const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, user
244
249
  taskIds,
245
250
  tagState,
246
251
  userGroupsState,
252
+ taskCategoriesById,
247
253
  });
248
254
  return {
249
255
  groupName: groupKey,
@@ -254,7 +260,7 @@ const getTaskListGroupedByDueDate = ({ taskListState, taskState, userState, user
254
260
  });
255
261
  return taskGroupsWithTasksList.filter((group) => group.tasks.length > 0);
256
262
  };
257
- const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState, }) => {
263
+ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState, taskCategoriesById, }) => {
258
264
  const { groupByKey } = taskListState.uiState;
259
265
  if (groupByKey === 'groupName') {
260
266
  return getTaskListGroupedByGroupName({
@@ -267,6 +273,7 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
267
273
  taskGroupsIds,
268
274
  tagState,
269
275
  userGroupsState,
276
+ taskCategoriesById,
270
277
  });
271
278
  }
272
279
  if (groupByKey === 'assignee') {
@@ -278,6 +285,7 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
278
285
  addressState,
279
286
  tagState,
280
287
  userGroupsState,
288
+ taskCategoriesById,
281
289
  });
282
290
  }
283
291
  if (groupByKey === 'priority') {
@@ -289,6 +297,7 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
289
297
  addressState,
290
298
  tagState,
291
299
  userGroupsState,
300
+ taskCategoriesById,
292
301
  });
293
302
  }
294
303
  if (groupByKey === 'status') {
@@ -300,6 +309,7 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
300
309
  addressState,
301
310
  tagState,
302
311
  userGroupsState,
312
+ taskCategoriesById,
303
313
  });
304
314
  }
305
315
  if (groupByKey === 'tag') {
@@ -311,6 +321,7 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
311
321
  addressState,
312
322
  tagState,
313
323
  userGroupsState,
324
+ taskCategoriesById,
314
325
  });
315
326
  }
316
327
  return getTaskListGroupedByDueDate({
@@ -321,6 +332,7 @@ const getTaskGroupsWithTaskList = ({ taskListState, taskState, userState, userRo
321
332
  addressState,
322
333
  tagState,
323
334
  userGroupsState,
335
+ taskCategoriesById,
324
336
  });
325
337
  };
326
338
  /**
@@ -345,7 +357,10 @@ const getTaskGroupsWithTaskListMemoized = (0, toolkit_1.createSelector)((state)
345
357
  // invalidate this memo and rebuild a board the user is already using.
346
358
  (state) => tagsAreStructural(state.taskListState.uiState)
347
359
  ? state.tagState
348
- : EMPTY_TAG_STATE, (state) => state.userGroupsState, (uiState, filters, taskIdsByGroupsIds, taskIdsByAssignees, taskIdsByPriority, taskIdsByStatus, taskIdsByTags, taskIdsByDueDate, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState) => getTaskGroupsWithTaskList({
360
+ : EMPTY_TAG_STATE, (state) => state.userGroupsState,
361
+ // Only the catalog, not the whole timeEntry slice: billing is read off
362
+ // the task's category, and a timer tick must not rebuild the board.
363
+ (state) => state.timeEntryState.taskCategoriesById, (uiState, filters, taskIdsByGroupsIds, taskIdsByAssignees, taskIdsByPriority, taskIdsByStatus, taskIdsByTags, taskIdsByDueDate, taskState, userState, userRoleState, addressState, taskGroupState, taskGroupsIds, tagState, userGroupsState, taskCategoriesById) => getTaskGroupsWithTaskList({
349
364
  taskListState: {
350
365
  uiState,
351
366
  filters,
@@ -364,6 +379,7 @@ const getTaskGroupsWithTaskListMemoized = (0, toolkit_1.createSelector)((state)
364
379
  taskGroupsIds,
365
380
  tagState,
366
381
  userGroupsState,
382
+ taskCategoriesById,
367
383
  }));
368
384
  exports.getAllTasks = (0, toolkit_1.createSelector)(
369
385
  // `taskState`, `taskGroupState`, `addressState` and `tagState` are gone from
@@ -3,7 +3,7 @@ import { Task } from '../../../entity/task/taskState';
3
3
  import { User } from '../../../entity/user/userState';
4
4
  import { ZeniDate } from '../../../zeniDayJS';
5
5
  import { TaskGroupKey } from './taskList';
6
- export type SubtaskSortKey = 'name' | 'status' | 'assignee' | 'tag';
6
+ export type SubtaskSortKey = 'name' | 'status' | 'assignee' | 'tag' | 'priority' | 'dueDate' | 'timeSpent';
7
7
  export type SubtaskSortOrder = 'asc' | 'desc';
8
8
  export declare const getDueDateValueFromDueDateGroupId: (groupId: string) => ZeniDate;
9
9
  export declare const getTaskUpdates: (groupByKey: TaskGroupKey, groupId: string) => Partial<Task>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sortSubtasks = exports.getTaskUpdates = exports.getDueDateValueFromDueDateGroupId = void 0;
4
+ const formatMinutesToFromHHMM_1 = require("../../../commonStateTypes/fiscalYearHelpers/formatMinutesToFromHHMM");
4
5
  const zeniDayJS_1 = require("../../../zeniDayJS");
5
6
  const taskDetailSelector_1 = require("../taskDetailView/taskDetailSelector");
6
7
  const taskList_1 = require("./taskList");
@@ -68,6 +69,11 @@ const sortSubtasks = (subtasks, sortKey, sortOrder, userList, tagList) => {
68
69
  return acc;
69
70
  }, {});
70
71
  const unknownStatusRank = taskDetailSelector_1.allTaskStatus.length;
72
+ const priorityOrder = taskDetailSelector_1.allTaskPriority.reduce((acc, priority, index) => {
73
+ acc[priority.code] = index;
74
+ return acc;
75
+ }, {});
76
+ const unknownPriorityRank = taskDetailSelector_1.allTaskPriority.length;
71
77
  const cmpStr = (a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' });
72
78
  const keyFn = (task) => {
73
79
  if (sortKey === 'name') {
@@ -94,6 +100,37 @@ const sortSubtasks = (subtasks, sortKey, sortOrder, userList, tagList) => {
94
100
  const tag = tagList.find((candidate) => candidate.tagId === firstTagId);
95
101
  return tag?.name ?? '';
96
102
  }
103
+ if (sortKey === 'priority') {
104
+ // Rank by the canonical order, not the code string: alphabetical would
105
+ // sort "high" before "urgent" and read as wrong to anyone scanning it.
106
+ return priorityOrder[task.priority?.code] ?? unknownPriorityRank;
107
+ }
108
+ if (sortKey === 'dueDate') {
109
+ // A task with no date is not "earliest", so undated rows belong at the
110
+ // bottom in BOTH directions. The comparator negates for 'desc', so one
111
+ // fixed sentinel would flip them to the top — the sentinel has to flip
112
+ // with the order to survive that negation.
113
+ // `dueDate` is already a ZeniDate (dayjs), so valueOf() is the epoch.
114
+ // An unparseable date yields NaN, and a NaN comparator leaves the array
115
+ // untouched -- the same silent failure the timeSpent branch guards.
116
+ // Treat it as undated rather than as a date.
117
+ const due = task.dueDate;
118
+ const epoch = due?.valueOf();
119
+ if (epoch == null || Number.isNaN(epoch)) {
120
+ return sortOrder === 'asc'
121
+ ? Number.MAX_SAFE_INTEGER
122
+ : Number.MIN_SAFE_INTEGER;
123
+ }
124
+ return epoch;
125
+ }
126
+ if (sortKey === 'timeSpent') {
127
+ // `timeSpent` is an "HHMM" STRING (no colon). Comparing it as text puts
128
+ // "1000" before "0900" only by luck of padding, and any malformed value
129
+ // makes the converter return NaN -- which a comparator turns into "no
130
+ // sort at all", silently. Coerce that to 0.
131
+ const minutes = (0, formatMinutesToFromHHMM_1.convertHHMMStrToMinutes)(task.timeSpent ?? '');
132
+ return Number.isFinite(minutes) ? minutes : 0;
133
+ }
97
134
  return '';
98
135
  };
99
136
  const copy = [...subtasks];
@@ -0,0 +1,18 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { Observable } from 'rxjs';
3
+ import { updateTaskCategories } from '../../../../entity/timeEntry/timeEntryReducer';
4
+ import { RootState } from '../../../../rootStateTypes';
5
+ import { ZeniAPI } from '../../../../zeniAPI';
6
+ import { fetchTaskCategories, fetchTaskCategoriesFailure, fetchTaskCategoriesSuccess } from '../timeEntryViewReducer';
7
+ export type ActionType = ReturnType<typeof fetchTaskCategories> | ReturnType<typeof fetchTaskCategoriesSuccess> | ReturnType<typeof fetchTaskCategoriesFailure> | ReturnType<typeof updateTaskCategories>;
8
+ /**
9
+ * The 156-category catalog that fills the Category dropdown.
10
+ *
11
+ * `switchMap` here, unlike the entry epics: there is one catalog, so a second
12
+ * request supersedes the first rather than racing it.
13
+ *
14
+ * Zeni-only on the server (the billing marker is commercially sensitive), so
15
+ * a customer user gets a 401 — surfaced as Error rather than an empty list,
16
+ * because an empty catalog looks like "no categories exist".
17
+ */
18
+ export declare const fetchTaskCategoriesEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchTaskCategoriesEpic = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ const operators_2 = require("rxjs/operators");
7
+ const timeEntryReducer_1 = require("../../../../entity/timeEntry/timeEntryReducer");
8
+ const responsePayload_1 = require("../../../../responsePayload");
9
+ const timeEntryViewReducer_1 = require("../timeEntryViewReducer");
10
+ /**
11
+ * The 156-category catalog that fills the Category dropdown.
12
+ *
13
+ * `switchMap` here, unlike the entry epics: there is one catalog, so a second
14
+ * request supersedes the first rather than racing it.
15
+ *
16
+ * Zeni-only on the server (the billing marker is commercially sensitive), so
17
+ * a customer user gets a 401 — surfaced as Error rather than an empty list,
18
+ * because an empty catalog looks like "no categories exist".
19
+ */
20
+ const fetchTaskCategoriesEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(timeEntryViewReducer_1.fetchTaskCategories.match), (0, operators_1.switchMap)(() => zeniAPI
21
+ .getJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/task-categories`)
22
+ .pipe((0, operators_2.mergeMap)((response) => {
23
+ if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
24
+ return (0, rxjs_1.of)((0, timeEntryReducer_1.updateTaskCategories)(response.data.task_categories ?? []), (0, timeEntryViewReducer_1.fetchTaskCategoriesSuccess)());
25
+ }
26
+ return (0, rxjs_1.of)((0, timeEntryViewReducer_1.fetchTaskCategoriesFailure)(response.status));
27
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, timeEntryViewReducer_1.fetchTaskCategoriesFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch task categories errored out' + JSON.stringify(error))))))));
28
+ exports.fetchTaskCategoriesEpic = fetchTaskCategoriesEpic;
@@ -0,0 +1,23 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { Observable } from 'rxjs';
3
+ import { updateTimeEntries } from '../../../../entity/timeEntry/timeEntryReducer';
4
+ import { RootState } from '../../../../rootStateTypes';
5
+ import { ZeniAPI } from '../../../../zeniAPI';
6
+ import { fetchTimeEntriesForRange, fetchTimeEntriesForRangeFailure, fetchTimeEntriesForRangeSuccess, fetchTimeEntriesForTask, fetchTimeEntriesForTaskFailure, fetchTimeEntriesForTaskSuccess } from '../timeEntryViewReducer';
7
+ export type ActionType = ReturnType<typeof fetchTimeEntriesForTask> | ReturnType<typeof fetchTimeEntriesForTaskSuccess> | ReturnType<typeof fetchTimeEntriesForTaskFailure> | ReturnType<typeof fetchTimeEntriesForRange> | ReturnType<typeof fetchTimeEntriesForRangeSuccess> | ReturnType<typeof fetchTimeEntriesForRangeFailure> | ReturnType<typeof updateTimeEntries>;
8
+ /**
9
+ * Every entry on one task, all users — the task detail breakdown.
10
+ *
11
+ * `mergeMap`, not `switchMap`: a detail page and an expanded board row can
12
+ * ask for two different tasks at once, and cancelling the first would leave
13
+ * its breakdown stuck In-Progress forever.
14
+ */
15
+ export declare const fetchTimeEntriesForTaskEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
16
+ /**
17
+ * One user's entries in an inclusive date range — the weekly timesheet.
18
+ *
19
+ * Needs the `is_deleted + user_id + entry_date` composite index (api #593).
20
+ * Without it the server returns 500, not an empty list, so the failure is
21
+ * surfaced rather than rendered as a blank week.
22
+ */
23
+ export declare const fetchTimeEntriesForRangeEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchTimeEntriesForRangeEpic = exports.fetchTimeEntriesForTaskEpic = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ const timeEntryReducer_1 = require("../../../../entity/timeEntry/timeEntryReducer");
7
+ const responsePayload_1 = require("../../../../responsePayload");
8
+ const timeEntryViewReducer_1 = require("../timeEntryViewReducer");
9
+ const timeEntryViewState_1 = require("../timeEntryViewState");
10
+ /**
11
+ * Every entry on one task, all users — the task detail breakdown.
12
+ *
13
+ * `mergeMap`, not `switchMap`: a detail page and an expanded board row can
14
+ * ask for two different tasks at once, and cancelling the first would leave
15
+ * its breakdown stuck In-Progress forever.
16
+ */
17
+ const fetchTimeEntriesForTaskEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(timeEntryViewReducer_1.fetchTimeEntriesForTask.match), (0, operators_1.mergeMap)((action) => {
18
+ const { taskId, cacheOverride } = action.payload;
19
+ const cached = state$.value.timeEntryViewState.timeEntryIdsByTaskId[taskId];
20
+ const status = state$.value.timeEntryViewState.fetchStateByTaskId[taskId];
21
+ // The reducer has already flipped this request to In-Progress, so the
22
+ // guard reads the COMPLETED cache, never the fetch state -- a fetch
23
+ // state is not an in-flight signal.
24
+ if (cacheOverride !== true &&
25
+ cached != null &&
26
+ status?.fetchState === 'In-Progress') {
27
+ return (0, rxjs_1.of)((0, timeEntryViewReducer_1.fetchTimeEntriesForTaskSuccess)({ taskId, timeEntryIds: cached }));
28
+ }
29
+ return zeniAPI
30
+ .getJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks/${taskId}/time-entries`)
31
+ .pipe((0, operators_1.mergeMap)((response) => {
32
+ if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
33
+ const entries = response.data.time_entries ?? [];
34
+ return (0, rxjs_1.of)((0, timeEntryReducer_1.updateTimeEntries)(entries), (0, timeEntryViewReducer_1.fetchTimeEntriesForTaskSuccess)({
35
+ taskId,
36
+ timeEntryIds: entries.map((entry) => entry.time_entry_id),
37
+ }));
38
+ }
39
+ return (0, rxjs_1.of)((0, timeEntryViewReducer_1.fetchTimeEntriesForTaskFailure)({ taskId, status: response.status }));
40
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, timeEntryViewReducer_1.fetchTimeEntriesForTaskFailure)({
41
+ taskId,
42
+ status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch time entries for task errored out' +
43
+ JSON.stringify(error)),
44
+ }))));
45
+ }));
46
+ exports.fetchTimeEntriesForTaskEpic = fetchTimeEntriesForTaskEpic;
47
+ /**
48
+ * One user's entries in an inclusive date range — the weekly timesheet.
49
+ *
50
+ * Needs the `is_deleted + user_id + entry_date` composite index (api #593).
51
+ * Without it the server returns 500, not an empty list, so the failure is
52
+ * surfaced rather than rendered as a blank week.
53
+ */
54
+ const fetchTimeEntriesForRangeEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(timeEntryViewReducer_1.fetchTimeEntriesForRange.match), (0, operators_1.mergeMap)((action) => {
55
+ const { userId, startDate, endDate } = action.payload;
56
+ const rangeKey = (0, timeEntryViewState_1.toTimeEntryRangeKey)(userId, startDate, endDate);
57
+ const query = `user_id=${encodeURIComponent(userId)}&start_date=${encodeURIComponent(startDate)}&end_date=${encodeURIComponent(endDate)}`;
58
+ return zeniAPI
59
+ .getJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/time-entries?${query}`)
60
+ .pipe((0, operators_1.mergeMap)((response) => {
61
+ if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
62
+ const entries = response.data.time_entries ?? [];
63
+ return (0, rxjs_1.of)((0, timeEntryReducer_1.updateTimeEntries)(entries), (0, timeEntryViewReducer_1.fetchTimeEntriesForRangeSuccess)({
64
+ rangeKey,
65
+ timeEntryIds: entries.map((entry) => entry.time_entry_id),
66
+ }));
67
+ }
68
+ return (0, rxjs_1.of)((0, timeEntryViewReducer_1.fetchTimeEntriesForRangeFailure)({
69
+ rangeKey,
70
+ status: response.status,
71
+ }));
72
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, timeEntryViewReducer_1.fetchTimeEntriesForRangeFailure)({
73
+ rangeKey,
74
+ status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch time entries for range errored out' +
75
+ JSON.stringify(error)),
76
+ }))));
77
+ }));
78
+ exports.fetchTimeEntriesForRangeEpic = fetchTimeEntriesForRangeEpic;