@zeniai/client-epic-state 5.3.7-betaRD0 → 5.3.8-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 (73) 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/tenant/epic/fetchAllTenantsEpic.js +38 -45
  7. package/lib/entity/timeEntry/timeEntryPayload.d.ts +26 -0
  8. package/lib/entity/timeEntry/timeEntryPayload.js +2 -0
  9. package/lib/entity/timeEntry/timeEntryReducer.d.ts +8 -0
  10. package/lib/entity/timeEntry/timeEntryReducer.js +76 -0
  11. package/lib/entity/timeEntry/timeEntrySelector.d.ts +10 -0
  12. package/lib/entity/timeEntry/timeEntrySelector.js +32 -0
  13. package/lib/entity/timeEntry/timeEntryState.d.ts +43 -0
  14. package/lib/entity/timeEntry/timeEntryState.js +13 -0
  15. package/lib/epic.d.ts +4 -1
  16. package/lib/epic.js +9 -0
  17. package/lib/esm/entity/task/taskPayload.js +1 -0
  18. package/lib/esm/entity/task/taskReducer.js +18 -1
  19. package/lib/esm/entity/tenant/epic/fetchAllTenantsEpic.js +39 -46
  20. package/lib/esm/entity/timeEntry/timeEntryPayload.js +1 -0
  21. package/lib/esm/entity/timeEntry/timeEntryReducer.js +70 -0
  22. package/lib/esm/entity/timeEntry/timeEntrySelector.js +23 -0
  23. package/lib/esm/entity/timeEntry/timeEntryState.js +8 -0
  24. package/lib/esm/epic.js +9 -0
  25. package/lib/esm/index.js +6 -3
  26. package/lib/esm/init.js +3 -14
  27. package/lib/esm/reducer.js +6 -0
  28. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +3 -0
  29. package/lib/esm/view/taskManager/taskListView/taskList.js +5 -0
  30. package/lib/esm/view/taskManager/taskListView/taskListFilterHelpers.js +2 -0
  31. package/lib/esm/view/taskManager/taskListView/taskListViewHelpers.js +37 -0
  32. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +24 -0
  33. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +73 -0
  34. package/lib/esm/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +77 -0
  35. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewPayload.js +1 -0
  36. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewReducer.js +160 -0
  37. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewSelector.js +41 -0
  38. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewState.js +1 -0
  39. package/lib/index.d.ts +7 -4
  40. package/lib/index.js +66 -53
  41. package/lib/init.d.ts +0 -9
  42. package/lib/init.js +4 -17
  43. package/lib/reducer.d.ts +2 -0
  44. package/lib/reducer.js +6 -0
  45. package/lib/rootStateTypes.d.ts +4 -0
  46. package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +4 -0
  47. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +3 -0
  48. package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
  49. package/lib/view/taskManager/taskListView/taskList.js +5 -0
  50. package/lib/view/taskManager/taskListView/taskListFilterHelpers.js +2 -0
  51. package/lib/view/taskManager/taskListView/taskListViewHelpers.d.ts +1 -1
  52. package/lib/view/taskManager/taskListView/taskListViewHelpers.js +37 -0
  53. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.d.ts +18 -0
  54. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +28 -0
  55. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.d.ts +23 -0
  56. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +78 -0
  57. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.d.ts +23 -0
  58. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +83 -0
  59. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.d.ts +27 -0
  60. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.js +2 -0
  61. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.d.ts +48 -0
  62. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.js +164 -0
  63. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.d.ts +24 -0
  64. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.js +46 -0
  65. package/lib/view/taskManager/timeEntryView/timeEntryViewState.d.ts +21 -0
  66. package/lib/view/taskManager/timeEntryView/timeEntryViewState.js +5 -0
  67. package/lib/zeniAPI.d.ts +2 -2
  68. package/package.json +1 -26
  69. package/lib/esm/sessionEndpointsLoader.js +0 -7
  70. package/lib/sessionEndpointsLoader.d.ts +0 -9
  71. package/lib/sessionEndpointsLoader.js +0 -11
  72. package/lib/tsconfig.mocks.tsbuildinfo +0 -1
  73. package/lib/tsconfig.typecheck.tsbuildinfo +0 -1
package/lib/init.d.ts CHANGED
@@ -3,8 +3,6 @@ import { RootState } from './rootStateTypes';
3
3
  import { RESTAPIEndpoints } from './zeniAPI';
4
4
  export type ZeniStore = Store<RootState>;
5
5
  export { zeniAPI } from './zeniAPIClientState';
6
- export { setSessionEndpointsLoader } from './sessionEndpointsLoader';
7
- export type { SessionEndpointsLoader } from './sessionEndpointsLoader';
8
6
  export { disconnectPusher, initializePusher, pusher } from './pusherClient';
9
7
  export type { PusherAuthPayload } from './pusherClient';
10
8
  export declare let store: ZeniStore;
@@ -25,13 +23,6 @@ export { injectFeatureModules, injectFeatureEpics } from './configureStore';
25
23
  * @param tenantId
26
24
  */
27
25
  export declare function updateZeniAPIClientConfig(userId?: string, sessionId?: string, tenantId?: string): void;
28
- /**
29
- * Replace the REST endpoints the API client calls. Epics read the endpoints
30
- * at request time, so every request made after this uses the new ones.
31
- * Note: This version SHOULD BE used only in the client side.
32
- * @param restEndPoints
33
- */
34
- export declare function updateZeniAPIEndpoints(restEndPoints: RESTAPIEndpoints): void;
35
26
  /**
36
27
  * Returns current Zeni REST API client config.
37
28
  * @returns
package/lib/init.js CHANGED
@@ -36,10 +36,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.injectFeatureEpics = exports.injectFeatureModules = exports.store = exports.pusher = exports.initializePusher = exports.disconnectPusher = exports.setSessionEndpointsLoader = exports.zeniAPI = void 0;
39
+ exports.injectFeatureEpics = exports.injectFeatureModules = exports.store = exports.pusher = exports.initializePusher = exports.disconnectPusher = exports.zeniAPI = void 0;
40
40
  exports.default = initialize;
41
41
  exports.updateZeniAPIClientConfig = updateZeniAPIClientConfig;
42
- exports.updateZeniAPIEndpoints = updateZeniAPIEndpoints;
43
42
  exports.zeniAPIClientConfig = zeniAPIClientConfig;
44
43
  exports.initializeWithNewStore = initializeWithNewStore;
45
44
  exports.initialize3rdPartyExtensions = initialize3rdPartyExtensions;
@@ -48,8 +47,6 @@ const zeniAPI_1 = require("./zeniAPI");
48
47
  const zeniAPIClientState_1 = require("./zeniAPIClientState");
49
48
  var zeniAPIClientState_2 = require("./zeniAPIClientState");
50
49
  Object.defineProperty(exports, "zeniAPI", { enumerable: true, get: function () { return zeniAPIClientState_2.zeniAPI; } });
51
- var sessionEndpointsLoader_1 = require("./sessionEndpointsLoader");
52
- Object.defineProperty(exports, "setSessionEndpointsLoader", { enumerable: true, get: function () { return sessionEndpointsLoader_1.setSessionEndpointsLoader; } });
53
50
  var pusherClient_1 = require("./pusherClient");
54
51
  Object.defineProperty(exports, "disconnectPusher", { enumerable: true, get: function () { return pusherClient_1.disconnectPusher; } });
55
52
  Object.defineProperty(exports, "initializePusher", { enumerable: true, get: function () { return pusherClient_1.initializePusher; } });
@@ -63,10 +60,11 @@ let initialized = false;
63
60
  */
64
61
  function initialize(restEndPoints, userId, sessionId, tenantId, isSandboxEnv, onSessionInvalidated) {
65
62
  if (initialized) {
66
- console.warn('client-epic-state is already initialized');
63
+ console.warn(`Already initialized with url ${JSON.stringify(zeniAPIClientState_1.zeniAPI.apiEndPoints)}`);
67
64
  return exports.store;
68
65
  }
69
66
  initialized = true;
67
+ console.info(`initializing with ${JSON.stringify(restEndPoints)}`);
70
68
  initialize3rdPartyExtensions();
71
69
  (0, zeniAPIClientState_1.setZeniAPIClient)(new zeniAPI_1.ZeniAPIClient(restEndPoints, userId, sessionId, tenantId, onSessionInvalidated));
72
70
  exports.store = (0, configureStore_1.default)(zeniAPIClientState_1.zeniAPI, isSandboxEnv);
@@ -86,18 +84,6 @@ Object.defineProperty(exports, "injectFeatureEpics", { enumerable: true, get: fu
86
84
  function updateZeniAPIClientConfig(userId, sessionId, tenantId) {
87
85
  zeniAPIClientState_1.zeniAPI.update(userId, sessionId, tenantId);
88
86
  }
89
- /**
90
- * Replace the REST endpoints the API client calls. Epics read the endpoints
91
- * at request time, so every request made after this uses the new ones.
92
- * Note: This version SHOULD BE used only in the client side.
93
- * @param restEndPoints
94
- */
95
- function updateZeniAPIEndpoints(restEndPoints) {
96
- if (zeniAPIClientState_1.zeniAPI == null) {
97
- throw new Error('Call initialize() before updateZeniAPIEndpoints()');
98
- }
99
- zeniAPIClientState_1.zeniAPI.apiEndPoints = restEndPoints;
100
- }
101
87
  /**
102
88
  * Returns current Zeni REST API client config.
103
89
  * @returns
@@ -124,6 +110,7 @@ function zeniAPIClientConfig() {
124
110
  * @param tenantId tenant id
125
111
  */
126
112
  async function initializeWithNewStore(restEndPoints, userId, sessionId, tenantId) {
113
+ console.info(`initializeWithNewStore with ${JSON.stringify(restEndPoints)}`);
127
114
  initialize3rdPartyExtensions();
128
115
  const zeniHttpClient = new zeniAPI_1.ZeniAPIClient(restEndPoints, userId, sessionId, tenantId);
129
116
  const store = (0, configureStore_1.default)(zeniHttpClient, false);
package/lib/reducer.d.ts CHANGED
@@ -165,6 +165,7 @@ declare const reducers: import("redux").Reducer<import("redux").CombinedState<{
165
165
  taskGroupTemplateViewState: import("./view/taskManager/taskGroupTemplateView/taskGroupTemplateViewState").TaskGroupTemplateViewState;
166
166
  taskGroupViewState: import("./view/taskManager/taskGroupView/taskGroupViewState").TaskGroupViewState;
167
167
  taskListState: import("./view/taskManager/taskListView/taskList").TaskListState;
168
+ timeEntryViewState: import("./view/taskManager/timeEntryView/timeEntryViewState").TimeEntryViewState;
168
169
  tagViewState: import(".").TagViewState;
169
170
  tasksCardState: import("./view/tasksCard/tasksCardState").TasksCardState;
170
171
  topExState: import("./view/topEx/topExState").TopExState;
@@ -265,6 +266,7 @@ declare const reducers: import("redux").Reducer<import("redux").CombinedState<{
265
266
  subscriptionState: import("./entity/subscription/subscription/subscriptionState").SubscriptionState;
266
267
  subscriptionSummaryState: import("./entity/subscription/subscriptionSummary/subscriptionSummaryState").SubscriptionSummaryState;
267
268
  tagState: import(".").TagState;
269
+ timeEntryState: import("./entity/timeEntry/timeEntryState").TimeEntryState;
268
270
  taskGroupState: import(".").TaskGroupState;
269
271
  taskGroupTemplateState: import("./entity/taskGroupTemplate/taskGroupTemplateState").TaskGroupTemplateState;
270
272
  taskState: import("./entity/task/taskState").TaskState;
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"));
@@ -294,6 +295,7 @@ const taskDetailReducer_1 = __importStar(require("./view/taskManager/taskDetailV
294
295
  const taskGroupTemplateViewReducer_1 = __importStar(require("./view/taskManager/taskGroupTemplateView/taskGroupTemplateViewReducer"));
295
296
  const taskGroupViewReducer_1 = __importStar(require("./view/taskManager/taskGroupView/taskGroupViewReducer"));
296
297
  const taskListReducer_1 = __importStar(require("./view/taskManager/taskListView/taskListReducer"));
298
+ const timeEntryViewReducer_1 = __importStar(require("./view/taskManager/timeEntryView/timeEntryViewReducer"));
297
299
  const tasksCardReducer_1 = __importStar(require("./view/tasksCard/tasksCardReducer"));
298
300
  const topExReducer_1 = __importStar(require("./view/topEx/topExReducer"));
299
301
  const transactionActivityLogViewReducer_1 = __importStar(require("./view/transactionActivityLogView/transactionActivityLogViewReducer"));
@@ -382,6 +384,7 @@ const initialEntitiesState = {
382
384
  subscriptionState: subscriptionReducer_1.initialState,
383
385
  subscriptionSummaryState: subscriptionSummaryReducer_1.initialState,
384
386
  tagState: tagReducer_1.initialState,
387
+ timeEntryState: timeEntryReducer_1.initialState,
385
388
  taskGroupState: taskGroupReducer_1.initialState,
386
389
  taskGroupTemplateState: taskGroupTemplateReducer_1.initialState,
387
390
  taskState: taskReducer_1.initialState,
@@ -563,6 +566,7 @@ const initialViewsState = {
563
566
  taskGroupTemplateViewState: taskGroupTemplateViewReducer_1.initialState,
564
567
  taskGroupViewState: taskGroupViewReducer_1.initialState,
565
568
  taskListState: taskListReducer_1.initialState,
569
+ timeEntryViewState: timeEntryViewReducer_1.initialState,
566
570
  tasksCardState: tasksCardReducer_1.initialState,
567
571
  topExState: topExReducer_1.initialState,
568
572
  transactionActivityLogViewState: transactionActivityLogViewReducer_1.initialState,
@@ -671,6 +675,7 @@ const entityReducers = {
671
675
  subscriptionState: subscriptionReducer_1.default,
672
676
  subscriptionSummaryState: subscriptionSummaryReducer_1.default,
673
677
  tagState: tagReducer_1.default,
678
+ timeEntryState: timeEntryReducer_1.default,
674
679
  taskGroupState: taskGroupReducer_1.default,
675
680
  taskGroupTemplateState: taskGroupTemplateReducer_1.default,
676
681
  taskState: taskReducer_1.default,
@@ -851,6 +856,7 @@ const viewReducers = {
851
856
  taskGroupTemplateViewState: taskGroupTemplateViewReducer_1.default,
852
857
  taskGroupViewState: taskGroupViewReducer_1.default,
853
858
  taskListState: taskListReducer_1.default,
859
+ timeEntryViewState: timeEntryViewReducer_1.default,
854
860
  tagViewState: tagViewReducer_1.default,
855
861
  tasksCardState: tasksCardReducer_1.default,
856
862
  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';
@@ -252,6 +253,7 @@ import { TaskDetailViewState } from './view/taskManager/taskDetailView/taskDetai
252
253
  import { TaskGroupTemplateViewState } from './view/taskManager/taskGroupTemplateView/taskGroupTemplateViewState';
253
254
  import { TaskGroupViewState } from './view/taskManager/taskGroupView/taskGroupViewState';
254
255
  import { TaskListState } from './view/taskManager/taskListView/taskList';
256
+ import { TimeEntryViewState } from './view/taskManager/timeEntryView/timeEntryViewState';
255
257
  import { TasksCardState } from './view/tasksCard/tasksCardState';
256
258
  import { TopExState } from './view/topEx/topExState';
257
259
  import { TransactionActivityLogViewState } from './view/transactionActivityLogView/transactionActivityLogViewState';
@@ -344,6 +346,7 @@ export type EntitiesState = {
344
346
  taskState: TaskState;
345
347
  taskSummaryState: TaskSummaryState;
346
348
  tenantState: TenantState;
349
+ timeEntryState: TimeEntryState;
347
350
  toastNotificationState: ToastNotificationState;
348
351
  transactionActivityLogState: TransactionActivityLogState;
349
352
  transactionState: TransactionState;
@@ -521,6 +524,7 @@ export type ViewsState = {
521
524
  taskGroupViewState: TaskGroupViewState;
522
525
  taskListState: TaskListState;
523
526
  tasksCardState: TasksCardState;
527
+ timeEntryViewState: TimeEntryViewState;
524
528
  topExState: TopExState;
525
529
  transactionActivityLogViewState: TransactionActivityLogViewState;
526
530
  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';
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,6 +53,11 @@ 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 },
57
62
  ];
58
63
  exports.TASK_LIST_GROUP_BY_CATEGORIES = [
@@ -15,6 +15,8 @@ const getCategoryValueForTaskList = (key, task) => {
15
15
  return task.createTime;
16
16
  case 'assignee':
17
17
  return task.assignees;
18
+ case 'createdBy':
19
+ return task.createdBy;
18
20
  default:
19
21
  return undefined;
20
22
  }
@@ -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;
@@ -0,0 +1,23 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { Observable } from 'rxjs';
3
+ import { updateTaskTimeSpentMinutes } from '../../../../entity/task/taskReducer';
4
+ import { removeTimeEntry, updateTimeEntries } from '../../../../entity/timeEntry/timeEntryReducer';
5
+ import { RootState } from '../../../../rootStateTypes';
6
+ import { ZeniAPI } from '../../../../zeniAPI';
7
+ import { deleteTimeEntry, logTime, logTimeFailure, logTimeSuccess, timeEntryWriteFailure, timeEntryWriteSuccess, updateTimeEntryMinutes } from '../timeEntryViewReducer';
8
+ export type ActionType = ReturnType<typeof logTime> | ReturnType<typeof logTimeSuccess> | ReturnType<typeof logTimeFailure> | ReturnType<typeof updateTimeEntryMinutes> | ReturnType<typeof deleteTimeEntry> | ReturnType<typeof timeEntryWriteSuccess> | ReturnType<typeof timeEntryWriteFailure> | ReturnType<typeof updateTimeEntries> | ReturnType<typeof removeTimeEntry> | ReturnType<typeof updateTaskTimeSpentMinutes>;
9
+ /**
10
+ * Log time against a task.
11
+ *
12
+ * `mergeMap`, not `switchMap`: two rows on the board can be edited in quick
13
+ * succession and cancelling the first would silently drop that entry.
14
+ */
15
+ export declare const logTimeEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
16
+ /** Correct an entry's minutes. Owner, or a Zeni user as the admin path. */
17
+ export declare const updateTimeEntryEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
18
+ /**
19
+ * Soft delete. The row stays in Datastore for the audit trail but leaves the
20
+ * totals, so the client drops it from the store rather than keeping something
21
+ * every reader would then have to remember to filter.
22
+ */
23
+ export declare const deleteTimeEntryEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteTimeEntryEpic = exports.updateTimeEntryEpic = exports.logTimeEpic = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ const taskReducer_1 = require("../../../../entity/task/taskReducer");
7
+ const timeEntryReducer_1 = require("../../../../entity/timeEntry/timeEntryReducer");
8
+ const timeEntrySelector_1 = require("../../../../entity/timeEntry/timeEntrySelector");
9
+ const responsePayload_1 = require("../../../../responsePayload");
10
+ const timeEntryViewReducer_1 = require("../timeEntryViewReducer");
11
+ const unexpected = (what, error) => (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', `${what} errored out${JSON.stringify(error)}`);
12
+ /**
13
+ * Log time against a task.
14
+ *
15
+ * `mergeMap`, not `switchMap`: two rows on the board can be edited in quick
16
+ * succession and cancelling the first would silently drop that entry.
17
+ */
18
+ const logTimeEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(timeEntryViewReducer_1.logTime.match), (0, operators_1.mergeMap)((action) => {
19
+ const { taskId, minutes, entryDate, source, identifier } = action.payload;
20
+ return zeniAPI
21
+ .postAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks/${taskId}/time-entries`, {
22
+ minutes,
23
+ entry_date: entryDate,
24
+ source,
25
+ // Sent only when the caller has one. The server treats it as the
26
+ // entity key, which is what makes a retried timer stop idempotent.
27
+ ...(identifier != null ? { identifier } : {}),
28
+ })
29
+ .pipe((0, operators_1.mergeMap)((response) => {
30
+ if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
31
+ const { time_entry, task_time_spent_minutes } = response.data;
32
+ return (0, rxjs_1.of)((0, timeEntryReducer_1.updateTimeEntries)([time_entry]),
33
+ // The board reads `Task.time_spent` per row, so it has to be
34
+ // told the new total; otherwise the row keeps the old number
35
+ // until something refetches the whole list.
36
+ (0, taskReducer_1.updateTaskTimeSpentMinutes)({
37
+ taskId,
38
+ minutes: task_time_spent_minutes ?? 0,
39
+ }), (0, timeEntryViewReducer_1.logTimeSuccess)({ taskId, timeEntryId: time_entry.time_entry_id }));
40
+ }
41
+ return (0, rxjs_1.of)((0, timeEntryViewReducer_1.logTimeFailure)({ taskId, status: response.status }));
42
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, timeEntryViewReducer_1.logTimeFailure)({ taskId, status: unexpected('Log time', error) }))));
43
+ }));
44
+ exports.logTimeEpic = logTimeEpic;
45
+ /** Correct an entry's minutes. Owner, or a Zeni user as the admin path. */
46
+ const updateTimeEntryEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(timeEntryViewReducer_1.updateTimeEntryMinutes.match), (0, operators_1.mergeMap)((action) => {
47
+ const { timeEntryId, minutes } = action.payload;
48
+ return zeniAPI
49
+ .putAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/time-entries/${timeEntryId}`, { minutes })
50
+ .pipe((0, operators_1.mergeMap)((response) => {
51
+ if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
52
+ return (0, rxjs_1.of)((0, timeEntryReducer_1.updateTimeEntries)([response.data.time_entry]), (0, timeEntryViewReducer_1.timeEntryWriteSuccess)({ timeEntryId }));
53
+ }
54
+ return (0, rxjs_1.of)((0, timeEntryViewReducer_1.timeEntryWriteFailure)({ timeEntryId, status: response.status }));
55
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, timeEntryViewReducer_1.timeEntryWriteFailure)({
56
+ timeEntryId,
57
+ status: unexpected('Update time entry', error),
58
+ }))));
59
+ }));
60
+ exports.updateTimeEntryEpic = updateTimeEntryEpic;
61
+ /**
62
+ * Soft delete. The row stays in Datastore for the audit trail but leaves the
63
+ * totals, so the client drops it from the store rather than keeping something
64
+ * every reader would then have to remember to filter.
65
+ */
66
+ const deleteTimeEntryEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(timeEntryViewReducer_1.deleteTimeEntry.match), (0, operators_1.mergeMap)((action) => {
67
+ const timeEntryId = action.payload;
68
+ // Read the task id BEFORE the delete: the entry is about to leave the
69
+ // store, and the view slice needs to know which task's id list to prune.
70
+ const taskId = (0, timeEntrySelector_1.getTimeEntryById)(state$.value.timeEntryState, timeEntryId)?.taskId;
71
+ return zeniAPI
72
+ .deleteAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/time-entries/${timeEntryId}`)
73
+ .pipe((0, operators_1.mergeMap)((response) => {
74
+ if ((0, responsePayload_1.isSuccessResponse)(response)) {
75
+ return (0, rxjs_1.of)((0, timeEntryReducer_1.removeTimeEntry)(timeEntryId), (0, timeEntryViewReducer_1.timeEntryWriteSuccess)({ timeEntryId, removedFromTaskId: taskId }));
76
+ }
77
+ return (0, rxjs_1.of)((0, timeEntryViewReducer_1.timeEntryWriteFailure)({ timeEntryId, status: response.status }));
78
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, timeEntryViewReducer_1.timeEntryWriteFailure)({
79
+ timeEntryId,
80
+ status: unexpected('Delete time entry', error),
81
+ }))));
82
+ }));
83
+ exports.deleteTimeEntryEpic = deleteTimeEntryEpic;
@@ -0,0 +1,27 @@
1
+ import { ID } from '../../../commonStateTypes/common';
2
+ import { TaskCategoryPayload, TimeEntryPayload } from '../../../entity/timeEntry/timeEntryPayload';
3
+ import { ZeniAPIResponse } from '../../../responsePayload';
4
+ export interface TimeEntriesPayload {
5
+ time_entries: TimeEntryPayload[];
6
+ total_minutes: number;
7
+ }
8
+ export interface TimeEntryRangePayload extends TimeEntriesPayload {
9
+ end_date: string;
10
+ start_date: string;
11
+ user_id: ID;
12
+ }
13
+ export interface TimeEntryWritePayload {
14
+ /** The ids whose `time_spent` the server recomputed. The client refreshes
15
+ * exactly these board rows instead of the whole list. */
16
+ recomputed_task_ids: ID[];
17
+ time_entry: TimeEntryPayload;
18
+ task_time_spent_minutes?: number;
19
+ }
20
+ export interface TaskCategoriesPayload {
21
+ count: number;
22
+ task_categories: TaskCategoryPayload[];
23
+ }
24
+ export type TimeEntriesResponse = ZeniAPIResponse<TimeEntriesPayload>;
25
+ export type TimeEntryRangeResponse = ZeniAPIResponse<TimeEntryRangePayload>;
26
+ export type TimeEntryWriteResponse = ZeniAPIResponse<TimeEntryWritePayload>;
27
+ export type TaskCategoriesResponse = ZeniAPIResponse<TaskCategoriesPayload>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });