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

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 (93) hide show
  1. package/lib/commonStateTypes/animations.d.ts +1 -1
  2. package/lib/commonStateTypes/animations.js +1 -0
  3. package/lib/entity/task/taskPayload.d.ts +0 -1
  4. package/lib/entity/task/taskPayload.js +0 -1
  5. package/lib/entity/task/taskReducer.d.ts +1 -4
  6. package/lib/entity/task/taskReducer.js +2 -19
  7. package/lib/entity/task/taskState.d.ts +0 -3
  8. package/lib/epic.d.ts +2 -4
  9. package/lib/epic.js +2 -9
  10. package/lib/esm/commonStateTypes/animations.js +1 -0
  11. package/lib/esm/entity/task/taskPayload.js +0 -1
  12. package/lib/esm/entity/task/taskReducer.js +1 -18
  13. package/lib/esm/epic.js +2 -9
  14. package/lib/esm/index.js +5 -8
  15. package/lib/esm/reducer.js +0 -6
  16. package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +65 -3
  17. package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +25 -0
  18. package/lib/esm/view/aiCfoView/epics/transcribeAudioEpic.js +60 -0
  19. package/lib/esm/view/expenseAutomationView/types/transactionGroup.js +10 -5
  20. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +0 -3
  21. package/lib/esm/view/taskManager/taskListView/taskList.js +0 -6
  22. package/lib/esm/view/taskManager/taskListView/taskListFilterHelpers.js +0 -7
  23. package/lib/esm/view/taskManager/taskListView/taskListSelector.js +11 -27
  24. package/lib/esm/view/taskManager/taskListView/taskListViewHelpers.js +0 -37
  25. package/lib/esm/view/transactionDetail/createTransaction/createTransactionPayload.js +19 -3
  26. package/lib/esm/view/transactionDetail/createTransaction/createTransactionState.js +2 -0
  27. package/lib/index.d.ts +6 -10
  28. package/lib/index.js +28 -37
  29. package/lib/reducer.d.ts +0 -2
  30. package/lib/reducer.js +0 -6
  31. package/lib/rootStateTypes.d.ts +0 -4
  32. package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +20 -0
  33. package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +2 -2
  34. package/lib/view/aiCfoView/aiCfoViewReducer.js +66 -4
  35. package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +8 -1
  36. package/lib/view/aiCfoView/aiCfoViewSelector.js +27 -0
  37. package/lib/view/aiCfoView/aiCfoViewState.d.ts +9 -0
  38. package/lib/view/aiCfoView/epics/transcribeAudioEpic.d.ts +19 -0
  39. package/lib/view/aiCfoView/epics/transcribeAudioEpic.js +64 -0
  40. package/lib/view/expenseAutomationView/payload/transactionCategorizationPayload.d.ts +2 -2
  41. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +2 -2
  42. package/lib/view/expenseAutomationView/types/transactionGroup.d.ts +6 -6
  43. package/lib/view/expenseAutomationView/types/transactionGroup.js +10 -5
  44. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +2 -2
  45. package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +0 -4
  46. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +0 -3
  47. package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
  48. package/lib/view/taskManager/taskListView/taskList.js +0 -6
  49. package/lib/view/taskManager/taskListView/taskListFilterHelpers.d.ts +0 -4
  50. package/lib/view/taskManager/taskListView/taskListFilterHelpers.js +1 -9
  51. package/lib/view/taskManager/taskListView/taskListSelector.d.ts +3 -6
  52. package/lib/view/taskManager/taskListView/taskListSelector.js +10 -26
  53. package/lib/view/taskManager/taskListView/taskListViewHelpers.d.ts +1 -1
  54. package/lib/view/taskManager/taskListView/taskListViewHelpers.js +0 -37
  55. package/lib/view/transactionDetail/createTransaction/createTransactionPayload.d.ts +6 -3
  56. package/lib/view/transactionDetail/createTransaction/createTransactionPayload.js +19 -3
  57. package/lib/view/transactionDetail/createTransaction/createTransactionState.d.ts +7 -2
  58. package/lib/view/transactionDetail/createTransaction/createTransactionState.js +2 -0
  59. package/lib/view/transactionDetail/transactionDetailReducer.d.ts +20 -20
  60. package/package.json +1 -1
  61. package/lib/entity/timeEntry/timeEntryPayload.d.ts +0 -26
  62. package/lib/entity/timeEntry/timeEntryPayload.js +0 -2
  63. package/lib/entity/timeEntry/timeEntryReducer.d.ts +0 -8
  64. package/lib/entity/timeEntry/timeEntryReducer.js +0 -76
  65. package/lib/entity/timeEntry/timeEntrySelector.d.ts +0 -10
  66. package/lib/entity/timeEntry/timeEntrySelector.js +0 -32
  67. package/lib/entity/timeEntry/timeEntryState.d.ts +0 -43
  68. package/lib/entity/timeEntry/timeEntryState.js +0 -13
  69. package/lib/esm/entity/timeEntry/timeEntryPayload.js +0 -1
  70. package/lib/esm/entity/timeEntry/timeEntryReducer.js +0 -70
  71. package/lib/esm/entity/timeEntry/timeEntrySelector.js +0 -23
  72. package/lib/esm/entity/timeEntry/timeEntryState.js +0 -8
  73. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +0 -24
  74. package/lib/esm/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +0 -73
  75. package/lib/esm/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +0 -77
  76. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewPayload.js +0 -1
  77. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewReducer.js +0 -160
  78. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewSelector.js +0 -41
  79. package/lib/esm/view/taskManager/timeEntryView/timeEntryViewState.js +0 -1
  80. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.d.ts +0 -18
  81. package/lib/view/taskManager/timeEntryView/epic/fetchTaskCategoriesEpic.js +0 -28
  82. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.d.ts +0 -23
  83. package/lib/view/taskManager/timeEntryView/epic/fetchTimeEntriesEpic.js +0 -78
  84. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.d.ts +0 -23
  85. package/lib/view/taskManager/timeEntryView/epic/writeTimeEntryEpic.js +0 -83
  86. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.d.ts +0 -27
  87. package/lib/view/taskManager/timeEntryView/timeEntryViewPayload.js +0 -2
  88. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.d.ts +0 -48
  89. package/lib/view/taskManager/timeEntryView/timeEntryViewReducer.js +0 -164
  90. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.d.ts +0 -24
  91. package/lib/view/taskManager/timeEntryView/timeEntryViewSelector.js +0 -46
  92. package/lib/view/taskManager/timeEntryView/timeEntryViewState.d.ts +0 -21
  93. package/lib/view/taskManager/timeEntryView/timeEntryViewState.js +0 -5
@@ -2,7 +2,7 @@
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.fetchSkillVersionBodySuccess = exports.fetchSkillVersionBodyFailure = exports.fetchSkillVersionBody = exports.fetchSkillsSuccess = exports.fetchSkillsFailure = exports.fetchSkills = exports.fetchSkillDetailSuccess = exports.fetchSkillDetailFailure = exports.fetchSkillDetail = exports.fetchRoutinesSuccess = exports.fetchRoutinesFailure = exports.fetchRoutines = exports.fetchRoutineRunsSuccess = exports.fetchRoutineRunsFailure = exports.fetchRoutineRuns = exports.fetchChatSessionsForUserSuccess = exports.fetchChatSessionsForUserFailure = exports.fetchChatSessionsForUser = exports.fetchChatHistorySuccess = exports.fetchChatHistoryFailure = exports.fetchChatHistory = exports.deleteSkillSuccess = exports.deleteSkillFailure = exports.deleteSkill = exports.deleteRoutineSuccess = exports.deleteRoutineFailure = exports.deleteRoutine = exports.deleteChatSessionSuccess = exports.deleteChatSessionFailure = exports.deleteChatSession = exports.createSessionSuccess = exports.createSessionFailure = exports.createSessionAndSubmitSuccess = exports.createSessionAndSubmitFailure = exports.createSessionAndSubmit = exports.createSession = exports.closeSkillsBrowser = exports.closeRoutinesBrowser = exports.closeRoutineRuns = exports.clearSkillMutation = exports.clearSkillDetail = exports.clearLastContextMessage = exports.clearDeleteChatSessionStatus = exports.clearCurrentSessionId = exports.clearAiCfoSidePanelHostPageContext = exports.applyAiCfoSidePanelHostPageTransition = exports.acceptMasterTOSSuccess = exports.acceptMasterTOSFailure = exports.acceptMasterTOS = exports.initialAiCfoViewState = void 0;
5
- exports.updateResponseState = exports.updateCurrentInput = exports.updateCotCollapsedState = exports.updateAiCfoViewScrollPosition = exports.submitQuestionSuccess = exports.submitQuestionFailure = exports.submitQuestion = exports.submitFeedbackSuccess = exports.submitFeedbackFailure = exports.submitFeedback = exports.stopSubmitSuccess = exports.stopSubmitQuestionSuccess = exports.stopSubmitQuestionFailure = exports.stopSubmitQuestion = exports.stopSubmitFailure = exports.stopSubmit = exports.setSkillVisibilitySuccess = exports.setSkillVisibilityFailure = exports.setSkillVisibility = exports.setSession = exports.setRoutineEnabled = exports.saveSkillSuccess = exports.saveSkillFailure = exports.saveSkill = exports.saveRoutineSuccess = exports.saveRoutineFailure = exports.saveRoutine = exports.runRoutineSuccess = exports.runRoutineFailure = exports.runRoutine = exports.openSkillsBrowser = exports.openRoutinesBrowser = exports.initializeNewSessionState = exports.fetchSuggestedQuestionsSuccess = exports.fetchSuggestedQuestionsFailure = exports.fetchSuggestedQuestions = exports.fetchSkillVersionsSuccess = exports.fetchSkillVersionsFailure = exports.fetchSkillVersions = void 0;
5
+ exports.updateResponseState = exports.updateCurrentInput = exports.updateCotCollapsedState = exports.updateAiCfoViewScrollPosition = exports.transcribeAudioSuccess = exports.transcribeAudioFailure = exports.transcribeAudio = exports.submitQuestionSuccess = exports.submitQuestionFailure = exports.submitQuestion = exports.submitFeedbackSuccess = exports.submitFeedbackFailure = exports.submitFeedback = exports.stopSubmitSuccess = exports.stopSubmitQuestionSuccess = exports.stopSubmitQuestionFailure = exports.stopSubmitQuestion = exports.stopSubmitFailure = exports.stopSubmit = exports.setSkillVisibilitySuccess = exports.setSkillVisibilityFailure = exports.setSkillVisibility = exports.setSession = exports.setRoutineEnabled = exports.saveSkillSuccess = exports.saveSkillFailure = exports.saveSkill = exports.saveRoutineSuccess = exports.saveRoutineFailure = exports.saveRoutine = exports.runRoutineSuccess = exports.runRoutineFailure = exports.runRoutine = exports.openSkillsBrowser = exports.openRoutinesBrowser = exports.initializeNewSessionState = exports.fetchSuggestedQuestionsSuccess = exports.fetchSuggestedQuestionsFailure = exports.fetchSuggestedQuestions = exports.fetchSkillVersionsSuccess = exports.fetchSkillVersionsFailure = exports.fetchSkillVersions = void 0;
6
6
  const toolkit_1 = require("@reduxjs/toolkit");
7
7
  const rootActions_1 = require("../../rootActions");
8
8
  function removeSessionIdFromPageKeyMap(draft, sessionId) {
@@ -52,6 +52,8 @@ exports.initialAiCfoViewState = {
52
52
  fetchChatSessionHistoryByChatSessionId: {},
53
53
  responseStateByChatSessionId: {},
54
54
  stopSubmitStateByChatSessionId: {},
55
+ transcriptionState: { fetchState: 'Not-Started', error: undefined },
56
+ transcribingChatSessionId: undefined,
55
57
  suggestedQuestionsByPageContext: {},
56
58
  skillDetail: {
57
59
  fetchState: 'Not-Started',
@@ -152,6 +154,19 @@ function closeSkillsBrowserState(draft) {
152
154
  draft.uiState.isSkillsBrowserOpen = false;
153
155
  clearOpenSkillState(draft);
154
156
  }
157
+ /**
158
+ * Clear a finished dictation attempt when the conversation moves on, so a failed one
159
+ * stops showing "Could not transcribe that recording" in every later chat. A running
160
+ * take keeps its state — the composer is showing a live "Transcribing…" for it.
161
+ */
162
+ function resetFinishedTranscription(draft) {
163
+ if (draft.transcriptionState.fetchState === 'In-Progress') {
164
+ return;
165
+ }
166
+ draft.transcriptionState.fetchState = 'Not-Started';
167
+ draft.transcriptionState.error = undefined;
168
+ draft.transcribingChatSessionId = undefined;
169
+ }
155
170
  const aiCfoView = (0, toolkit_1.createSlice)({
156
171
  name: 'aiCfoView',
157
172
  initialState: exports.initialAiCfoViewState,
@@ -159,6 +174,7 @@ const aiCfoView = (0, toolkit_1.createSlice)({
159
174
  submitQuestion: {
160
175
  reducer(draft, action) {
161
176
  const { sessionId } = action.payload;
177
+ resetFinishedTranscription(draft);
162
178
  // A turn is being sent, so the chat body has to be what the user sees. Doing this
163
179
  // here rather than at each call site is deliberate: the composer, the sample
164
180
  // chips, Run, and the `/` menu all submit, and every one of them was a separate
@@ -304,6 +320,7 @@ const aiCfoView = (0, toolkit_1.createSlice)({
304
320
  setSession(draft, action) {
305
321
  draft.uiState.currentChatSessionId = action.payload.sessionId;
306
322
  draft.uiState.agentId = action.payload.agentId;
323
+ resetFinishedTranscription(draft);
307
324
  // Picking a session means wanting to see that chat, so the browser cannot stay over
308
325
  // it. In the reducer because there are six dispatch sites across three separate
309
326
  // rails, and covering them one at a time missed half of them.
@@ -356,6 +373,7 @@ const aiCfoView = (0, toolkit_1.createSlice)({
356
373
  createSessionAndSubmit: {
357
374
  reducer(draft, action) {
358
375
  draft.uiState.agentId = action.payload.agentId;
376
+ resetFinishedTranscription(draft);
359
377
  draft.createSessionAndSubmitState.fetchState = 'In-Progress';
360
378
  draft.createSessionAndSubmitState.error = undefined;
361
379
  },
@@ -556,7 +574,49 @@ const aiCfoView = (0, toolkit_1.createSlice)({
556
574
  return { payload: { chatMessageId, error } };
557
575
  },
558
576
  },
577
+ transcribeAudio: {
578
+ reducer(draft, action) {
579
+ draft.transcriptionState.fetchState = 'In-Progress';
580
+ draft.transcriptionState.error = undefined;
581
+ draft.transcribingChatSessionId = action.payload.chatSessionId;
582
+ },
583
+ prepare(audio, language, chatSessionId) {
584
+ return { payload: { audio, chatSessionId, language } };
585
+ },
586
+ },
587
+ transcribeAudioSuccess: {
588
+ reducer(draft, action) {
589
+ draft.transcriptionState.fetchState = 'Completed';
590
+ draft.transcriptionState.error = undefined;
591
+ // The user moved to another session while this was in flight — dropping it
592
+ // is the only safe option, since appending would put their words in a
593
+ // conversation they did not dictate into.
594
+ if (action.payload.chatSessionId !== draft.uiState.currentChatSessionId) {
595
+ return;
596
+ }
597
+ const transcript = action.payload.transcript.trim();
598
+ if (transcript === '') {
599
+ // Silence, not a failure: leave the composer untouched so the user can
600
+ // simply speak again rather than hunting for what went wrong.
601
+ return;
602
+ }
603
+ // Append to whatever is in the box now rather than to a snapshot taken when
604
+ // recording began — a take produces exactly one result, so there is nothing
605
+ // to reconcile, and anything typed while transcribing survives.
606
+ const existing = draft.uiState.currentInput.trim();
607
+ draft.uiState.currentInput =
608
+ existing === '' ? transcript : `${existing} ${transcript}`;
609
+ },
610
+ prepare(transcript, chatSessionId) {
611
+ return { payload: { chatSessionId, transcript } };
612
+ },
613
+ },
614
+ transcribeAudioFailure(draft, action) {
615
+ draft.transcriptionState.fetchState = 'Error';
616
+ draft.transcriptionState.error = action.payload;
617
+ },
559
618
  clearCurrentSessionId(draft) {
619
+ resetFinishedTranscription(draft);
560
620
  // New Chat: the empty composer is the point, so the browser cannot stay over it.
561
621
  if (draft.uiState.isSkillsBrowserOpen === true) {
562
622
  closeSkillsBrowserState(draft);
@@ -840,7 +900,8 @@ const aiCfoView = (0, toolkit_1.createSlice)({
840
900
  // The server has it. Nothing it sends from here on will contain this row,
841
901
  // so the tombstone has done its job and holding it any longer is what
842
902
  // makes a routine recreated under the same id invisible forever.
843
- draft.routines.deletedScheduleIds = draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
903
+ draft.routines.deletedScheduleIds =
904
+ draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
844
905
  draft.routineMutation = {
845
906
  fetchState: 'Completed',
846
907
  error: undefined,
@@ -852,7 +913,8 @@ const aiCfoView = (0, toolkit_1.createSlice)({
852
913
  // is what lets the refetch put the row back — leaving it hidden would
853
914
  // tell the user they had stopped something they had not, which is the
854
915
  // worst outcome this list can produce.
855
- draft.routines.deletedScheduleIds = draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
916
+ draft.routines.deletedScheduleIds =
917
+ draft.routines.deletedScheduleIds.filter((id) => id !== action.payload.scheduleId);
856
918
  // Its own slice: the refetch that puts the row back would otherwise wipe
857
919
  // this error, leaving the row silently reappearing with no explanation.
858
920
  draft.routineMutation = {
@@ -1188,5 +1250,5 @@ const aiCfoView = (0, toolkit_1.createSlice)({
1188
1250
  });
1189
1251
  },
1190
1252
  });
1191
- _a = aiCfoView.actions, exports.acceptMasterTOS = _a.acceptMasterTOS, exports.acceptMasterTOSFailure = _a.acceptMasterTOSFailure, exports.acceptMasterTOSSuccess = _a.acceptMasterTOSSuccess, exports.applyAiCfoSidePanelHostPageTransition = _a.applyAiCfoSidePanelHostPageTransition, exports.clearAiCfoSidePanelHostPageContext = _a.clearAiCfoSidePanelHostPageContext, exports.clearCurrentSessionId = _a.clearCurrentSessionId, exports.clearDeleteChatSessionStatus = _a.clearDeleteChatSessionStatus, exports.clearLastContextMessage = _a.clearLastContextMessage, exports.clearSkillDetail = _a.clearSkillDetail, exports.clearSkillMutation = _a.clearSkillMutation, exports.closeRoutineRuns = _a.closeRoutineRuns, exports.closeRoutinesBrowser = _a.closeRoutinesBrowser, exports.closeSkillsBrowser = _a.closeSkillsBrowser, exports.createSession = _a.createSession, exports.createSessionAndSubmit = _a.createSessionAndSubmit, exports.createSessionAndSubmitFailure = _a.createSessionAndSubmitFailure, exports.createSessionAndSubmitSuccess = _a.createSessionAndSubmitSuccess, exports.createSessionFailure = _a.createSessionFailure, exports.createSessionSuccess = _a.createSessionSuccess, exports.deleteChatSession = _a.deleteChatSession, exports.deleteChatSessionFailure = _a.deleteChatSessionFailure, exports.deleteChatSessionSuccess = _a.deleteChatSessionSuccess, exports.deleteRoutine = _a.deleteRoutine, exports.deleteRoutineFailure = _a.deleteRoutineFailure, exports.deleteRoutineSuccess = _a.deleteRoutineSuccess, exports.deleteSkill = _a.deleteSkill, exports.deleteSkillFailure = _a.deleteSkillFailure, exports.deleteSkillSuccess = _a.deleteSkillSuccess, exports.fetchChatHistory = _a.fetchChatHistory, exports.fetchChatHistoryFailure = _a.fetchChatHistoryFailure, exports.fetchChatHistorySuccess = _a.fetchChatHistorySuccess, exports.fetchChatSessionsForUser = _a.fetchChatSessionsForUser, exports.fetchChatSessionsForUserFailure = _a.fetchChatSessionsForUserFailure, exports.fetchChatSessionsForUserSuccess = _a.fetchChatSessionsForUserSuccess, exports.fetchRoutineRuns = _a.fetchRoutineRuns, exports.fetchRoutineRunsFailure = _a.fetchRoutineRunsFailure, exports.fetchRoutineRunsSuccess = _a.fetchRoutineRunsSuccess, exports.fetchRoutines = _a.fetchRoutines, exports.fetchRoutinesFailure = _a.fetchRoutinesFailure, exports.fetchRoutinesSuccess = _a.fetchRoutinesSuccess, exports.fetchSkillDetail = _a.fetchSkillDetail, exports.fetchSkillDetailFailure = _a.fetchSkillDetailFailure, exports.fetchSkillDetailSuccess = _a.fetchSkillDetailSuccess, exports.fetchSkills = _a.fetchSkills, exports.fetchSkillsFailure = _a.fetchSkillsFailure, exports.fetchSkillsSuccess = _a.fetchSkillsSuccess, exports.fetchSkillVersionBody = _a.fetchSkillVersionBody, exports.fetchSkillVersionBodyFailure = _a.fetchSkillVersionBodyFailure, exports.fetchSkillVersionBodySuccess = _a.fetchSkillVersionBodySuccess, exports.fetchSkillVersions = _a.fetchSkillVersions, exports.fetchSkillVersionsFailure = _a.fetchSkillVersionsFailure, exports.fetchSkillVersionsSuccess = _a.fetchSkillVersionsSuccess, exports.fetchSuggestedQuestions = _a.fetchSuggestedQuestions, exports.fetchSuggestedQuestionsFailure = _a.fetchSuggestedQuestionsFailure, exports.fetchSuggestedQuestionsSuccess = _a.fetchSuggestedQuestionsSuccess, exports.initializeNewSessionState = _a.initializeNewSessionState, exports.openRoutinesBrowser = _a.openRoutinesBrowser, exports.openSkillsBrowser = _a.openSkillsBrowser, exports.runRoutine = _a.runRoutine, exports.runRoutineFailure = _a.runRoutineFailure, exports.runRoutineSuccess = _a.runRoutineSuccess, exports.saveRoutine = _a.saveRoutine, exports.saveRoutineFailure = _a.saveRoutineFailure, exports.saveRoutineSuccess = _a.saveRoutineSuccess, exports.saveSkill = _a.saveSkill, exports.saveSkillFailure = _a.saveSkillFailure, exports.saveSkillSuccess = _a.saveSkillSuccess, exports.setRoutineEnabled = _a.setRoutineEnabled, exports.setSession = _a.setSession, exports.setSkillVisibility = _a.setSkillVisibility, exports.setSkillVisibilityFailure = _a.setSkillVisibilityFailure, exports.setSkillVisibilitySuccess = _a.setSkillVisibilitySuccess, exports.stopSubmit = _a.stopSubmit, exports.stopSubmitFailure = _a.stopSubmitFailure, exports.stopSubmitQuestion = _a.stopSubmitQuestion, exports.stopSubmitQuestionFailure = _a.stopSubmitQuestionFailure, exports.stopSubmitQuestionSuccess = _a.stopSubmitQuestionSuccess, exports.stopSubmitSuccess = _a.stopSubmitSuccess, exports.submitFeedback = _a.submitFeedback, exports.submitFeedbackFailure = _a.submitFeedbackFailure, exports.submitFeedbackSuccess = _a.submitFeedbackSuccess, exports.submitQuestion = _a.submitQuestion, exports.submitQuestionFailure = _a.submitQuestionFailure, exports.submitQuestionSuccess = _a.submitQuestionSuccess, exports.updateAiCfoViewScrollPosition = _a.updateAiCfoViewScrollPosition, exports.updateCotCollapsedState = _a.updateCotCollapsedState, exports.updateCurrentInput = _a.updateCurrentInput, exports.updateResponseState = _a.updateResponseState;
1253
+ _a = aiCfoView.actions, exports.acceptMasterTOS = _a.acceptMasterTOS, exports.acceptMasterTOSFailure = _a.acceptMasterTOSFailure, exports.acceptMasterTOSSuccess = _a.acceptMasterTOSSuccess, exports.applyAiCfoSidePanelHostPageTransition = _a.applyAiCfoSidePanelHostPageTransition, exports.clearAiCfoSidePanelHostPageContext = _a.clearAiCfoSidePanelHostPageContext, exports.clearCurrentSessionId = _a.clearCurrentSessionId, exports.clearDeleteChatSessionStatus = _a.clearDeleteChatSessionStatus, exports.clearLastContextMessage = _a.clearLastContextMessage, exports.clearSkillDetail = _a.clearSkillDetail, exports.clearSkillMutation = _a.clearSkillMutation, exports.closeRoutineRuns = _a.closeRoutineRuns, exports.closeRoutinesBrowser = _a.closeRoutinesBrowser, exports.closeSkillsBrowser = _a.closeSkillsBrowser, exports.createSession = _a.createSession, exports.createSessionAndSubmit = _a.createSessionAndSubmit, exports.createSessionAndSubmitFailure = _a.createSessionAndSubmitFailure, exports.createSessionAndSubmitSuccess = _a.createSessionAndSubmitSuccess, exports.createSessionFailure = _a.createSessionFailure, exports.createSessionSuccess = _a.createSessionSuccess, exports.deleteChatSession = _a.deleteChatSession, exports.deleteChatSessionFailure = _a.deleteChatSessionFailure, exports.deleteChatSessionSuccess = _a.deleteChatSessionSuccess, exports.deleteRoutine = _a.deleteRoutine, exports.deleteRoutineFailure = _a.deleteRoutineFailure, exports.deleteRoutineSuccess = _a.deleteRoutineSuccess, exports.deleteSkill = _a.deleteSkill, exports.deleteSkillFailure = _a.deleteSkillFailure, exports.deleteSkillSuccess = _a.deleteSkillSuccess, exports.fetchChatHistory = _a.fetchChatHistory, exports.fetchChatHistoryFailure = _a.fetchChatHistoryFailure, exports.fetchChatHistorySuccess = _a.fetchChatHistorySuccess, exports.fetchChatSessionsForUser = _a.fetchChatSessionsForUser, exports.fetchChatSessionsForUserFailure = _a.fetchChatSessionsForUserFailure, exports.fetchChatSessionsForUserSuccess = _a.fetchChatSessionsForUserSuccess, exports.fetchRoutineRuns = _a.fetchRoutineRuns, exports.fetchRoutineRunsFailure = _a.fetchRoutineRunsFailure, exports.fetchRoutineRunsSuccess = _a.fetchRoutineRunsSuccess, exports.fetchRoutines = _a.fetchRoutines, exports.fetchRoutinesFailure = _a.fetchRoutinesFailure, exports.fetchRoutinesSuccess = _a.fetchRoutinesSuccess, exports.fetchSkillDetail = _a.fetchSkillDetail, exports.fetchSkillDetailFailure = _a.fetchSkillDetailFailure, exports.fetchSkillDetailSuccess = _a.fetchSkillDetailSuccess, exports.fetchSkills = _a.fetchSkills, exports.fetchSkillsFailure = _a.fetchSkillsFailure, exports.fetchSkillsSuccess = _a.fetchSkillsSuccess, exports.fetchSkillVersionBody = _a.fetchSkillVersionBody, exports.fetchSkillVersionBodyFailure = _a.fetchSkillVersionBodyFailure, exports.fetchSkillVersionBodySuccess = _a.fetchSkillVersionBodySuccess, exports.fetchSkillVersions = _a.fetchSkillVersions, exports.fetchSkillVersionsFailure = _a.fetchSkillVersionsFailure, exports.fetchSkillVersionsSuccess = _a.fetchSkillVersionsSuccess, exports.fetchSuggestedQuestions = _a.fetchSuggestedQuestions, exports.fetchSuggestedQuestionsFailure = _a.fetchSuggestedQuestionsFailure, exports.fetchSuggestedQuestionsSuccess = _a.fetchSuggestedQuestionsSuccess, exports.initializeNewSessionState = _a.initializeNewSessionState, exports.openRoutinesBrowser = _a.openRoutinesBrowser, exports.openSkillsBrowser = _a.openSkillsBrowser, exports.runRoutine = _a.runRoutine, exports.runRoutineFailure = _a.runRoutineFailure, exports.runRoutineSuccess = _a.runRoutineSuccess, exports.saveRoutine = _a.saveRoutine, exports.saveRoutineFailure = _a.saveRoutineFailure, exports.saveRoutineSuccess = _a.saveRoutineSuccess, exports.saveSkill = _a.saveSkill, exports.saveSkillFailure = _a.saveSkillFailure, exports.saveSkillSuccess = _a.saveSkillSuccess, exports.setRoutineEnabled = _a.setRoutineEnabled, exports.setSession = _a.setSession, exports.setSkillVisibility = _a.setSkillVisibility, exports.setSkillVisibilityFailure = _a.setSkillVisibilityFailure, exports.setSkillVisibilitySuccess = _a.setSkillVisibilitySuccess, exports.stopSubmit = _a.stopSubmit, exports.stopSubmitFailure = _a.stopSubmitFailure, exports.stopSubmitQuestion = _a.stopSubmitQuestion, exports.stopSubmitQuestionFailure = _a.stopSubmitQuestionFailure, exports.stopSubmitQuestionSuccess = _a.stopSubmitQuestionSuccess, exports.stopSubmitSuccess = _a.stopSubmitSuccess, exports.submitFeedback = _a.submitFeedback, exports.submitFeedbackFailure = _a.submitFeedbackFailure, exports.submitFeedbackSuccess = _a.submitFeedbackSuccess, exports.submitQuestion = _a.submitQuestion, exports.submitQuestionFailure = _a.submitQuestionFailure, exports.submitQuestionSuccess = _a.submitQuestionSuccess, exports.transcribeAudio = _a.transcribeAudio, exports.transcribeAudioFailure = _a.transcribeAudioFailure, exports.transcribeAudioSuccess = _a.transcribeAudioSuccess, exports.updateAiCfoViewScrollPosition = _a.updateAiCfoViewScrollPosition, exports.updateCotCollapsedState = _a.updateCotCollapsedState, exports.updateCurrentInput = _a.updateCurrentInput, exports.updateResponseState = _a.updateResponseState;
1192
1254
  exports.default = aiCfoView.reducer;
@@ -4,7 +4,7 @@ import { FetchStateAndError } from '../../commonStateTypes/common';
4
4
  import { SelectorView } from '../../commonStateTypes/viewAndReport/viewAndReport';
5
5
  import { AiCfoSelectorView } from '../../entity/aiCfo/aiCfoSelector';
6
6
  import { RootState } from '../../rootStateTypes';
7
- import { AiCfoViewUIState, SkillDetailState, SkillMutationState, SkillVersionBodyState, SkillVersionsState, RoutineMutationState, RoutineRunsState, RoutinesState, SkillsState, SuggestedQuestionsForPageContext } from './aiCfoViewState';
7
+ import { AiCfoViewUIState, RoutineMutationState, RoutineRunsState, RoutinesState, SkillDetailState, SkillMutationState, SkillVersionBodyState, SkillVersionsState, SkillsState, SuggestedQuestionsForPageContext } from './aiCfoViewState';
8
8
  export interface AiCfoViewSelector extends SelectorView, AiCfoSelectorView {
9
9
  createSessionAndSubmitState: FetchStateAndError;
10
10
  createSessionState: FetchStateAndError;
@@ -42,3 +42,10 @@ export declare function getSkillVersionBody(state: RootState): SkillVersionBodyS
42
42
  export declare function getSkillMutation(state: RootState): SkillMutationState;
43
43
  /** True only when the server says the feature is on for this tenant. */
44
44
  export declare function getSkillsEnabled(state: RootState): boolean;
45
+ export declare function getIsTranscribing(state: RootState): boolean;
46
+ /**
47
+ * Set when a transcription request failed. Without surfacing this the composer
48
+ * would just drop the "Transcribing…" label and sit there silently, leaving the
49
+ * user with no sign their recording went nowhere.
50
+ */
51
+ export declare function getTranscriptionFailed(state: RootState): boolean;
@@ -13,6 +13,8 @@ exports.getSkillVersions = getSkillVersions;
13
13
  exports.getSkillVersionBody = getSkillVersionBody;
14
14
  exports.getSkillMutation = getSkillMutation;
15
15
  exports.getSkillsEnabled = getSkillsEnabled;
16
+ exports.getIsTranscribing = getIsTranscribing;
17
+ exports.getTranscriptionFailed = getTranscriptionFailed;
16
18
  const aiCfoReducer_1 = require("../../entity/aiCfo/aiCfoReducer");
17
19
  const aiCfoSelector_1 = require("../../entity/aiCfo/aiCfoSelector");
18
20
  const aiCfoViewReducer_1 = require("./aiCfoViewReducer");
@@ -149,3 +151,28 @@ function getSkillMutation(state) {
149
151
  function getSkillsEnabled(state) {
150
152
  return getSkills(state).skillsEnabled;
151
153
  }
154
+ /** True while a finished voice recording is being transcribed server-side. */
155
+ /**
156
+ * A take belongs to the chat it was dictated into. A new chat has no session id yet on
157
+ * either side, which is a match rather than a mismatch.
158
+ */
159
+ function isTranscribingCurrentSession(state) {
160
+ if (state.aiCfoViewState == null) {
161
+ return false;
162
+ }
163
+ return (state.aiCfoViewState.transcribingChatSessionId ===
164
+ state.aiCfoViewState.uiState.currentChatSessionId);
165
+ }
166
+ function getIsTranscribing(state) {
167
+ return (state.aiCfoViewState?.transcriptionState?.fetchState === 'In-Progress' &&
168
+ isTranscribingCurrentSession(state));
169
+ }
170
+ /**
171
+ * Set when a transcription request failed. Without surfacing this the composer
172
+ * would just drop the "Transcribing…" label and sit there silently, leaving the
173
+ * user with no sign their recording went nowhere.
174
+ */
175
+ function getTranscriptionFailed(state) {
176
+ return (state.aiCfoViewState?.transcriptionState?.fetchState === 'Error' &&
177
+ isTranscribingCurrentSession(state));
178
+ }
@@ -378,5 +378,14 @@ export interface AiCfoViewState extends FetchStateAndError {
378
378
  stopSubmitStateByChatSessionId: Record<ID, FetchStateAndError>;
379
379
  /** Keyed by `page_context` query value (e.g. balance_sheet). */
380
380
  suggestedQuestionsByPageContext: Partial<Record<AiCfoSuggestedQuestionsPageContext, SuggestedQuestionsForPageContext>>;
381
+ /** Voice dictation: in-flight while a recording is being transcribed. */
382
+ transcriptionState: FetchStateAndError;
381
383
  uiState: AiCfoViewUIState;
384
+ /**
385
+ * Conversation the take in `transcriptionState` was dictated into. The spinner and
386
+ * the failure message belong to that chat alone — an epic outlives the component, so
387
+ * without this a take started in one session locks the composer, or shows its error,
388
+ * in whichever session the user has moved to.
389
+ */
390
+ transcribingChatSessionId?: ID;
382
391
  }
@@ -0,0 +1,19 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { Observable } from 'rxjs';
3
+ import { clearAll } from '../../../rootActions';
4
+ import { RootState } from '../../../rootStateTypes';
5
+ import { ZeniAPI } from '../../../zeniAPI';
6
+ import { transcribeAudio, transcribeAudioFailure, transcribeAudioSuccess } from '../aiCfoViewReducer';
7
+ export type ActionType = ReturnType<typeof clearAll> | ReturnType<typeof transcribeAudio> | ReturnType<typeof transcribeAudioSuccess> | ReturnType<typeof transcribeAudioFailure>;
8
+ /**
9
+ * Voice dictation for the AI CFO composer. Dispatch `transcribeAudio(blob, language)` with a
10
+ * finished recording to POST it to the AI CFO micro-service `/1.0/transcriptions` endpoint;
11
+ * on success the transcript is appended to the composer input for the user to edit and send.
12
+ *
13
+ * `switchMap` (not `mergeMap`): a newer recording supersedes an older in-flight one, so a
14
+ * slow response can never append a stale transcript after a fresh one has already landed.
15
+ * The AbortController makes that cancellation real — `fetch` wrapped in a promise ignores
16
+ * an RxJS unsubscribe, so without the signal the superseded request would run to completion
17
+ * and still bill a transcription call whose result nothing wants.
18
+ */
19
+ export declare const transcribeAudioEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transcribeAudioEpic = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ const responsePayload_1 = require("../../../responsePayload");
7
+ const rootActions_1 = require("../../../rootActions");
8
+ const aiCfoViewReducer_1 = require("../aiCfoViewReducer");
9
+ const AUDIO_FIELD = 'audio';
10
+ const LANGUAGE_FIELD = 'language';
11
+ /** Extension only has to match the recorded format; the server reads the part's MIME type. */
12
+ const AUDIO_FILE_NAME = 'dictation.wav';
13
+ /**
14
+ * A hung request would otherwise pin `isTranscribing` true forever, and the composer
15
+ * gates both submit and the mic on it — leaving the user unable to send even typed
16
+ * text until something else resolved it.
17
+ */
18
+ const TRANSCRIPTION_TIMEOUT_MS = 30000;
19
+ /**
20
+ * Voice dictation for the AI CFO composer. Dispatch `transcribeAudio(blob, language)` with a
21
+ * finished recording to POST it to the AI CFO micro-service `/1.0/transcriptions` endpoint;
22
+ * on success the transcript is appended to the composer input for the user to edit and send.
23
+ *
24
+ * `switchMap` (not `mergeMap`): a newer recording supersedes an older in-flight one, so a
25
+ * slow response can never append a stale transcript after a fresh one has already landed.
26
+ * The AbortController makes that cancellation real — `fetch` wrapped in a promise ignores
27
+ * an RxJS unsubscribe, so without the signal the superseded request would run to completion
28
+ * and still bill a transcription call whose result nothing wants.
29
+ */
30
+ const transcribeAudioEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(aiCfoViewReducer_1.transcribeAudio.match), (0, operators_1.switchMap)((action) => {
31
+ const { audio, chatSessionId, language } = action.payload;
32
+ const abortController = new AbortController();
33
+ const formData = new FormData();
34
+ formData.append(AUDIO_FIELD, audio, AUDIO_FILE_NAME);
35
+ if (language != null && language !== '') {
36
+ formData.append(LANGUAGE_FIELD, language);
37
+ }
38
+ return zeniAPI
39
+ .postFormData(`${zeniAPI.apiEndPoints.aiCfoMicroServiceBaseUrl}/1.0/transcriptions`, formData, abortController.signal)
40
+ .pipe((0, operators_1.timeout)(TRANSCRIPTION_TIMEOUT_MS),
41
+ // A tenant switch clears the store; a transcript still in flight must not
42
+ // land in the next tenant's composer (both sessions can be `undefined`, so
43
+ // the reducer's session guard would let it through).
44
+ (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))), (0, operators_1.map)((response) => {
45
+ if (!(0, responsePayload_1.isSuccessResponse)(response)) {
46
+ return (0, aiCfoViewReducer_1.transcribeAudioFailure)(response.status);
47
+ }
48
+ // An EMPTY transcript is a success (the mic caught silence) and the
49
+ // reducer leaves the composer alone. A MISSING one breaks the response
50
+ // contract, so it surfaces as an error rather than being coerced to
51
+ // silence the user cannot distinguish from a quiet room.
52
+ if (response.data?.transcript == null) {
53
+ return (0, aiCfoViewReducer_1.transcribeAudioFailure)((0, responsePayload_1.createZeniAPIStatus)('Transcription succeeded but the response carried no transcript', 'Unexpected Error'));
54
+ }
55
+ // The session id rides along so a transcript that lands after the user
56
+ // switched sessions is dropped rather than misfiled.
57
+ return (0, aiCfoViewReducer_1.transcribeAudioSuccess)(response.data.transcript, chatSessionId);
58
+ }), (0, operators_1.finalize)(() => abortController.abort()), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, aiCfoViewReducer_1.transcribeAudioFailure)((0, responsePayload_1.createZeniAPIStatus)(
59
+ // message (detailed) first, then the short title — per createZeniAPIStatus(message, title).
60
+ // JSON.stringify(Error) drops the (non-enumerable) message — extract it explicitly.
61
+ 'Transcription REST API call errored out: ' +
62
+ (error instanceof Error ? error.message : String(error)), 'Unexpected Error')))));
63
+ }));
64
+ exports.transcribeAudioEpic = transcribeAudioEpic;
@@ -28,8 +28,8 @@ export interface TransactionCategorizationQueryPayload {
28
28
  */
29
29
  search_all_statuses?: boolean;
30
30
  /**
31
- * Statement-level scope (`'expense' | 'income' | 'all'`). Always sent by the
32
- * list epics. The backend `is_revenue_automation_enabled` gate is
31
+ * Statement-level scope (`'expense' | 'income' | 'other' | 'all'`). Always
32
+ * sent by the list epics. The backend `is_revenue_automation_enabled` gate is
33
33
  * authoritative: when it is off the backend ignores this and returns the
34
34
  * legacy expense scope regardless of the value, so there is no need to gate
35
35
  * the send on the client (the gate isn't available to the redux epics anyway
@@ -70,8 +70,8 @@ export declare const fetchTransactionCategorization: import("@reduxjs/toolkit").
70
70
  newSelectedTab: "review" | "autoCategorized";
71
71
  }, "expenseAutomationTransactionsView/updateCurrentSelectedTransactionCategorizationTab", never, never>, updateTransactionCategorizationCompletedSubTab: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[newSubTab: "manual" | "all" | "ai_accountant"], {
72
72
  newSubTab: "manual" | "all" | "ai_accountant";
73
- }, "expenseAutomationTransactionsView/updateTransactionCategorizationCompletedSubTab", never, never>, updateTransactionGroup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[newGroup: "income" | "expense" | "all"], {
74
- newGroup: "income" | "expense" | "all";
73
+ }, "expenseAutomationTransactionsView/updateTransactionCategorizationCompletedSubTab", never, never>, updateTransactionGroup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[newGroup: "income" | "expense" | "other" | "all"], {
74
+ newGroup: "income" | "expense" | "other" | "all";
75
75
  }, "expenseAutomationTransactionsView/updateTransactionGroup", never, never>, updateTransactionCategorizationSaveStatus: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[selectedTab: "review" | "autoCategorized", fetchState: FetchState, error?: ZeniAPIStatus<Record<string, unknown>> | undefined], {
76
76
  selectedTab: "review" | "autoCategorized";
77
77
  fetchState: FetchState;
@@ -3,16 +3,16 @@
3
3
  * verbatim to the listing API as `transaction_group`. When revenue automation is
4
4
  * enabled for the tenant the backend scopes the whole view by the line
5
5
  * account_type: `'expense'` -> expense accounts, `'income'` -> income accounts,
6
- * `'all'` -> both. When off, every value falls back to the legacy expense scope
7
- * on the backend, so the group is only sent when the gate is on.
6
+ * `'other'` -> balance-sheet accounts other than bank/credit card (plus lines
7
+ * with no account type), `'all'` -> all three. The list epics always send it;
8
+ * when the gate is off the backend ignores it and returns the legacy expense
9
+ * scope.
8
10
  *
9
11
  * The wire value for expenses is the singular `'expense'` (matches the backend
10
12
  * `TransactionGroup` enum) even though the picker labels it "Expenses".
11
- * Balance-sheet groups (assets, liability) are reserved for later and are not
12
- * part of this union yet.
13
13
  */
14
- export declare const TRANSACTION_GROUPS: readonly ["all", "income", "expense"];
15
- export declare const toTransactionGroup: (v: string | null | undefined) => "income" | "expense" | "all";
14
+ export declare const TRANSACTION_GROUPS: readonly ["all", "income", "expense", "other"];
15
+ export declare const toTransactionGroup: (v: string | null | undefined) => "income" | "expense" | "other" | "all";
16
16
  export type TransactionGroup = ReturnType<typeof toTransactionGroup>;
17
17
  /**
18
18
  * Default group for the listing — matches the picker's default selection ("All").
@@ -7,15 +7,20 @@ const stringToUnion_1 = require("../../../commonStateTypes/stringToUnion");
7
7
  * verbatim to the listing API as `transaction_group`. When revenue automation is
8
8
  * enabled for the tenant the backend scopes the whole view by the line
9
9
  * account_type: `'expense'` -> expense accounts, `'income'` -> income accounts,
10
- * `'all'` -> both. When off, every value falls back to the legacy expense scope
11
- * on the backend, so the group is only sent when the gate is on.
10
+ * `'other'` -> balance-sheet accounts other than bank/credit card (plus lines
11
+ * with no account type), `'all'` -> all three. The list epics always send it;
12
+ * when the gate is off the backend ignores it and returns the legacy expense
13
+ * scope.
12
14
  *
13
15
  * The wire value for expenses is the singular `'expense'` (matches the backend
14
16
  * `TransactionGroup` enum) even though the picker labels it "Expenses".
15
- * Balance-sheet groups (assets, liability) are reserved for later and are not
16
- * part of this union yet.
17
17
  */
18
- exports.TRANSACTION_GROUPS = ['all', 'income', 'expense'];
18
+ exports.TRANSACTION_GROUPS = [
19
+ 'all',
20
+ 'income',
21
+ 'expense',
22
+ 'other',
23
+ ];
19
24
  const toTransactionGroup = (v) => (0, stringToUnion_1.stringToUnion)(v != null ? v.trim().toLowerCase() : '', exports.TRANSACTION_GROUPS);
20
25
  exports.toTransactionGroup = toTransactionGroup;
21
26
  /**
@@ -152,8 +152,8 @@ export type TransactionsViewState = {
152
152
  selectedTransactionCategorizationCompletedSubTab: CompletedSubTab;
153
153
  selectedTransactionCategorizationTab: TransactionsTab;
154
154
  /**
155
- * Statement-level scope (`'expense' | 'income' | 'all'`) forwarded to the
156
- * listing API as `transaction_group`. Unlike the in-memory {@link
155
+ * Statement-level scope (`'expense' | 'income' | 'other' | 'all'`) forwarded
156
+ * to the listing API as `transaction_group`. Unlike the in-memory {@link
157
157
  * TransactionsTabViewState.filters}, a change here invalidates every tab /
158
158
  * sub-tab / count and drives a server refetch (the backend re-scopes the
159
159
  * whole dataset by account_type). Only surfaced in the UI when the
@@ -25,10 +25,6 @@ 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;
32
28
  taskGroupId?: ID;
33
29
  }
34
30
  export declare const getTaskDetail: (state: RootState, taskId?: ID) => TaskDetailSelectorView;
@@ -32,7 +32,6 @@ const getTaskDetail = (state, taskId) => {
32
32
  let isDeleted = undefined;
33
33
  let depth = undefined;
34
34
  let recurringSourceTaskId = undefined;
35
- let taskCategoryId = undefined;
36
35
  let snoozedUntil = undefined;
37
36
  let taskGroupId = undefined;
38
37
  let subtasks = [];
@@ -46,7 +45,6 @@ const getTaskDetail = (state, taskId) => {
46
45
  if (taskEntity != null) {
47
46
  createdByUser = (0, userAndRole_1.getUserAndUserRole)(userState, userRoleState, addressState, taskEntity.createdBy);
48
47
  depth = taskEntity.depth;
49
- taskCategoryId = taskEntity.taskCategoryId;
50
48
  isArchived = taskEntity.isArchived;
51
49
  isDeleted = taskEntity.isDeleted;
52
50
  recurringSourceTaskId = taskEntity.recurringSourceTaskId;
@@ -111,7 +109,6 @@ const getTaskDetail = (state, taskId) => {
111
109
  version: 0,
112
110
  createdByUser,
113
111
  depth,
114
- taskCategoryId,
115
112
  isArchived,
116
113
  isDeleted,
117
114
  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' | 'createdBy' | 'creationDate' | 'priority' | 'tag' | 'billing';
51
+ export type TaskListFilterCategoryField = 'status' | 'dueDate' | 'assignee' | '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,13 +53,7 @@ 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
- },
61
56
  { value: 'creationDate', type: 'dateRange', multiple: true },
62
- { value: 'billing', type: 'dropdown', multiple: true },
63
57
  ];
64
58
  exports.TASK_LIST_GROUP_BY_CATEGORIES = [
65
59
  { value: 'status' },
@@ -1,7 +1,3 @@
1
- import { ID } from '../../../commonStateTypes/common';
2
1
  import { Task } from '../../../entity/task/taskState';
3
- import { TaskCategory } from '../../../entity/timeEntry/timeEntryState';
4
2
  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;
7
3
  export declare const getCategoryValueForTaskList: (key: string, task: Task) => FilterCategoryValueType | (string | undefined)[] | undefined;
@@ -1,12 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
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;
3
+ exports.getCategoryValueForTaskList = void 0;
10
4
  const getCategoryValueForTaskList = (key, task) => {
11
5
  switch (key) {
12
6
  case 'dueDate':
@@ -21,8 +15,6 @@ const getCategoryValueForTaskList = (key, task) => {
21
15
  return task.createTime;
22
16
  case 'assignee':
23
17
  return task.assignees;
24
- case 'createdBy':
25
- return task.createdBy;
26
18
  default:
27
19
  return undefined;
28
20
  }
@@ -1,10 +1,9 @@
1
- import { FetchStateAndError, ID } from '../../../commonStateTypes/common';
1
+ import { FetchStateAndError } 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';
8
7
  import { UserState } from '../../../entity/user/userState';
9
8
  import { UserGroupsState } from '../../../entity/userGroups/userGroupsState';
10
9
  import { UserRoleState } from '../../../entity/userRole/userRoleState';
@@ -49,10 +48,9 @@ export interface TaskListSelectorView extends SelectorView {
49
48
  * slice. `TaskListState` still satisfies this, so callers are unaffected.
50
49
  */
51
50
  type TaskListGroupingInputs = Pick<TaskListState, 'filters' | 'taskIdsByAssignees' | 'taskIdsByDueDate' | 'taskIdsByGroupsIds' | 'taskIdsByPriority' | 'taskIdsByStatus' | 'taskIdsByTags' | 'uiState'>;
52
- export declare const getTaskListGroupedByAssignees: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }: {
51
+ export declare const getTaskListGroupedByAssignees: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }: {
53
52
  addressState: AddressState;
54
53
  tagState: TagState;
55
- taskCategoriesById: Record<ID, TaskCategory>;
56
54
  taskListState: TaskListGroupingInputs;
57
55
  taskState: TaskState;
58
56
  userGroupsState: UserGroupsState;
@@ -64,10 +62,9 @@ export declare const getTaskListGroupedByAssignees: ({ taskListState, taskState,
64
62
  isDefault: boolean;
65
63
  tasks: TaskWithUserDetails[];
66
64
  }[];
67
- export declare const getTaskListGroupedByPriority: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, taskCategoriesById, }: {
65
+ export declare const getTaskListGroupedByPriority: ({ taskListState, taskState, userState, userRoleState, addressState, tagState, userGroupsState, }: {
68
66
  addressState: AddressState;
69
67
  tagState: TagState;
70
- taskCategoriesById: Record<ID, TaskCategory>;
71
68
  taskListState: TaskListGroupingInputs;
72
69
  taskState: TaskState;
73
70
  userGroupsState: UserGroupsState;