@zeniai/client-epic-state 5.1.16-betaRD1 → 5.1.17

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.
@@ -1,5 +1,5 @@
1
1
  import { from, of } from 'rxjs';
2
- import { catchError, filter, groupBy, mergeMap, switchMap } from 'rxjs/operators';
2
+ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
3
  import { toString } from '../../../../commonStateTypes/timePeriod';
4
4
  import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
5
5
  import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
@@ -8,10 +8,7 @@ import { getLineItemsByTransactionsIdsFromResponse } from '../../helpers/transac
8
8
  import { fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationSuccess, initializeTransactionCategorizationViewLocalData, resetOtherTabsFetchState, updateParentTotalCountForTab, updateTotalCountForTransactionCategorization, updateTransactionCategorizationUIState, } from '../../reducers/transactionsViewReducer';
9
9
  import { DEFAULT_COMPLETED_SUB_TAB } from '../../types/completedSubTab';
10
10
  import { TRANSACTIONS_TABS, toTransactionsSortKey, } from '../../types/transactionsViewState';
11
- export const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchTransactionCategorization.match),
12
- // Per-tab switchMap: cancels in-flight requests for the same tab on a new
13
- // request, but allows both tabs to fetch concurrently (e.g. dual search).
14
- groupBy((action) => action.payload.selectedTab), mergeMap((group$) => group$.pipe(switchMap((action) => {
11
+ export const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchTransactionCategorization.match), switchMap((action) => {
15
12
  const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationTransactionsViewState, } = state$.value;
16
13
  const { period, keepExistingListItems, selectedTab, refreshViewInBackground, } = action.payload;
17
14
  const uiState = expenseAutomationTransactionsViewState.transactionCategorizationView[selectedTab].uiState;
@@ -27,10 +24,6 @@ groupBy((action) => action.payload.selectedTab), mergeMap((group$) => group$.pip
27
24
  page_token: pageToken,
28
25
  page_size: 25,
29
26
  search_text: uiState.searchString,
30
- // Always scope to the active tab's auto_categorized status;
31
- // cross-status search (omit or true) is reserved for Receipts
32
- // manual-match.
33
- search_all_statuses: false,
34
27
  sub_tab: selectedTab === 'autoCategorized'
35
28
  ? expenseAutomationTransactionsViewState.selectedTransactionCategorizationCompletedSubTab
36
29
  : DEFAULT_COMPLETED_SUB_TAB,
@@ -86,4 +79,4 @@ groupBy((action) => action.payload.selectedTab), mergeMap((group$) => group$.pip
86
79
  status: createZeniAPIStatus('Unexpected Error', 'fetch Transaction Categorization REST API call errored out' +
87
80
  JSON.stringify(error)),
88
81
  }))));
89
- }))));
82
+ }));
@@ -7,7 +7,6 @@ import { fetchClassList } from '../../../classList/classListReducer';
7
7
  import { fetchOwnerList } from '../../../ownerList/ownerListReducer';
8
8
  import { fetchProjectList } from '../../../projectList/projectListReducer';
9
9
  import { fetchTransactionCategorization, fetchTransactionCategorizationView, } from '../../reducers/transactionsViewReducer';
10
- import { TRANSACTIONS_TABS } from '../../types/transactionsViewState';
11
10
  export const fetchTransactionCategorizationViewEpic = (actions$, state$) => actions$.pipe(filter(fetchTransactionCategorizationView.match), mergeMap((action) => {
12
11
  const { selectedTab, cacheOverride, keepExistingListItems, pageToken, period, refreshViewInBackground, searchString, resetListItems, isUncategorizedExpenseCategoryEnabled, } = action.payload;
13
12
  const updateActions = [];
@@ -45,20 +44,5 @@ export const fetchTransactionCategorizationViewEpic = (actions$, state$) => acti
45
44
  transactionIds.length === 0) {
46
45
  updateActions.push(fetchTransactionCategorization(selectedTab, period, cacheOverride, keepExistingListItems, searchString, pageToken, refreshViewInBackground, resetListItems, isUncategorizedExpenseCategoryEnabled));
47
46
  }
48
- // When search changes (searchString defined, including empty string to
49
- // clear), also fetch every other tab so all tabs always reflect the same
50
- // search query. Skip if the other tab already has this search string to
51
- // avoid redundant requests on noop updates. cacheOverride=true bypasses
52
- // the cache check; pageToken reset to undefined so the other tab starts
53
- // from page 1; refreshViewInBackground=true because the user isn't
54
- // looking at the other tab, so a silent background fetch is correct.
55
- if (searchString !== undefined) {
56
- TRANSACTIONS_TABS.filter((tab) => tab !== selectedTab).forEach((otherTab) => {
57
- const otherTabSearchString = expenseAutomationTransactionsViewState.transactionCategorizationView[otherTab].uiState.searchString;
58
- if (searchString !== otherTabSearchString) {
59
- updateActions.push(fetchTransactionCategorization(otherTab, period, true, keepExistingListItems, searchString, undefined, true, true, isUncategorizedExpenseCategoryEnabled));
60
- }
61
- });
62
- }
63
47
  return from(updateActions);
64
48
  }));
@@ -156,12 +156,8 @@ const expenseAutomationTransactionsView = createSlice({
156
156
  }
157
157
  draft.transactionCategorizationView[selectedTab].uiState.pageToken =
158
158
  pageToken ?? null;
159
- // Only overwrite when explicitly set; undefined means a non-search fetch
160
- // (tab switch, period change) should preserve the existing search string.
161
- if (searchString !== undefined) {
162
- draft.transactionCategorizationView[selectedTab].uiState.searchString =
163
- searchString;
164
- }
159
+ draft.transactionCategorizationView[selectedTab].uiState.searchString =
160
+ searchString ?? '';
165
161
  draft.transactionCategorizationView[selectedTab].error = undefined;
166
162
  // Reset list when we change the sort order and fetch list again
167
163
  if (resetListItems === true) {
@@ -309,12 +305,10 @@ const expenseAutomationTransactionsView = createSlice({
309
305
  }
310
306
  },
311
307
  updateTransactionFilters(draft, action) {
312
- const { filters } = action.payload;
313
- // Filters are tab-agnostic (payee/category/class/amount), so apply to
314
- // all tabs so switching tabs after filtering shows consistent results.
315
- TRANSACTIONS_TABS.forEach((tab) => {
316
- draft.transactionCategorizationView[tab].filters = filters;
317
- });
308
+ const { selectedTab, filters } = action.payload;
309
+ // `filters` is non-nullable per the payload type, so no runtime
310
+ // null-check is needed dropping it removes a dead defensive branch.
311
+ draft.transactionCategorizationView[selectedTab].filters = filters;
318
312
  },
319
313
  saveTransactionCategorization: {
320
314
  prepare(selectedTab, transactionIds, cotTrackingByTransactionId, isUncategorizedExpenseCategoryEnabled) {
@@ -11,10 +11,7 @@ const transactionCategorizationLocalDataHelper_1 = require("../../helpers/transa
11
11
  const transactionsViewReducer_1 = require("../../reducers/transactionsViewReducer");
12
12
  const completedSubTab_1 = require("../../types/completedSubTab");
13
13
  const transactionsViewState_1 = require("../../types/transactionsViewState");
14
- const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(transactionsViewReducer_1.fetchTransactionCategorization.match),
15
- // Per-tab switchMap: cancels in-flight requests for the same tab on a new
16
- // request, but allows both tabs to fetch concurrently (e.g. dual search).
17
- (0, operators_1.groupBy)((action) => action.payload.selectedTab), (0, operators_1.mergeMap)((group$) => group$.pipe((0, operators_1.switchMap)((action) => {
14
+ const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(transactionsViewReducer_1.fetchTransactionCategorization.match), (0, operators_1.switchMap)((action) => {
18
15
  const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationTransactionsViewState, } = state$.value;
19
16
  const { period, keepExistingListItems, selectedTab, refreshViewInBackground, } = action.payload;
20
17
  const uiState = expenseAutomationTransactionsViewState.transactionCategorizationView[selectedTab].uiState;
@@ -30,10 +27,6 @@ const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) => action
30
27
  page_token: pageToken,
31
28
  page_size: 25,
32
29
  search_text: uiState.searchString,
33
- // Always scope to the active tab's auto_categorized status;
34
- // cross-status search (omit or true) is reserved for Receipts
35
- // manual-match.
36
- search_all_statuses: false,
37
30
  sub_tab: selectedTab === 'autoCategorized'
38
31
  ? expenseAutomationTransactionsViewState.selectedTransactionCategorizationCompletedSubTab
39
32
  : completedSubTab_1.DEFAULT_COMPLETED_SUB_TAB,
@@ -89,5 +82,5 @@ const fetchTransactionCategorizationEpic = (actions$, state$, zeniAPI) => action
89
82
  status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'fetch Transaction Categorization REST API call errored out' +
90
83
  JSON.stringify(error)),
91
84
  }))));
92
- }))));
85
+ }));
93
86
  exports.fetchTransactionCategorizationEpic = fetchTransactionCategorizationEpic;
@@ -10,7 +10,6 @@ const classListReducer_1 = require("../../../classList/classListReducer");
10
10
  const ownerListReducer_1 = require("../../../ownerList/ownerListReducer");
11
11
  const projectListReducer_1 = require("../../../projectList/projectListReducer");
12
12
  const transactionsViewReducer_1 = require("../../reducers/transactionsViewReducer");
13
- const transactionsViewState_1 = require("../../types/transactionsViewState");
14
13
  const fetchTransactionCategorizationViewEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(transactionsViewReducer_1.fetchTransactionCategorizationView.match), (0, operators_1.mergeMap)((action) => {
15
14
  const { selectedTab, cacheOverride, keepExistingListItems, pageToken, period, refreshViewInBackground, searchString, resetListItems, isUncategorizedExpenseCategoryEnabled, } = action.payload;
16
15
  const updateActions = [];
@@ -48,21 +47,6 @@ const fetchTransactionCategorizationViewEpic = (actions$, state$) => actions$.pi
48
47
  transactionIds.length === 0) {
49
48
  updateActions.push((0, transactionsViewReducer_1.fetchTransactionCategorization)(selectedTab, period, cacheOverride, keepExistingListItems, searchString, pageToken, refreshViewInBackground, resetListItems, isUncategorizedExpenseCategoryEnabled));
50
49
  }
51
- // When search changes (searchString defined, including empty string to
52
- // clear), also fetch every other tab so all tabs always reflect the same
53
- // search query. Skip if the other tab already has this search string to
54
- // avoid redundant requests on noop updates. cacheOverride=true bypasses
55
- // the cache check; pageToken reset to undefined so the other tab starts
56
- // from page 1; refreshViewInBackground=true because the user isn't
57
- // looking at the other tab, so a silent background fetch is correct.
58
- if (searchString !== undefined) {
59
- transactionsViewState_1.TRANSACTIONS_TABS.filter((tab) => tab !== selectedTab).forEach((otherTab) => {
60
- const otherTabSearchString = expenseAutomationTransactionsViewState.transactionCategorizationView[otherTab].uiState.searchString;
61
- if (searchString !== otherTabSearchString) {
62
- updateActions.push((0, transactionsViewReducer_1.fetchTransactionCategorization)(otherTab, period, true, keepExistingListItems, searchString, undefined, true, true, isUncategorizedExpenseCategoryEnabled));
63
- }
64
- });
65
- }
66
50
  return (0, rxjs_1.from)(updateActions);
67
51
  }));
68
52
  exports.fetchTransactionCategorizationViewEpic = fetchTransactionCategorizationViewEpic;
@@ -19,13 +19,6 @@ export interface TransactionCategorizationQueryPayload {
19
19
  * on the backend.
20
20
  */
21
21
  sub_tab: CompletedSubTab;
22
- /**
23
- * When `false`, the backend scopes the search to the active tab's
24
- * categorization status (respects `auto_categorized`). When `true` or
25
- * omitted, the backend searches across all statuses — the legacy behaviour
26
- * that the Receipts manual-match flow relies on.
27
- */
28
- search_all_statuses?: boolean;
29
22
  }
30
23
  export interface TransactionCategorizationPayload {
31
24
  next_page_token: string | null;
@@ -163,12 +163,8 @@ const expenseAutomationTransactionsView = (0, toolkit_1.createSlice)({
163
163
  }
164
164
  draft.transactionCategorizationView[selectedTab].uiState.pageToken =
165
165
  pageToken ?? null;
166
- // Only overwrite when explicitly set; undefined means a non-search fetch
167
- // (tab switch, period change) should preserve the existing search string.
168
- if (searchString !== undefined) {
169
- draft.transactionCategorizationView[selectedTab].uiState.searchString =
170
- searchString;
171
- }
166
+ draft.transactionCategorizationView[selectedTab].uiState.searchString =
167
+ searchString ?? '';
172
168
  draft.transactionCategorizationView[selectedTab].error = undefined;
173
169
  // Reset list when we change the sort order and fetch list again
174
170
  if (resetListItems === true) {
@@ -316,12 +312,10 @@ const expenseAutomationTransactionsView = (0, toolkit_1.createSlice)({
316
312
  }
317
313
  },
318
314
  updateTransactionFilters(draft, action) {
319
- const { filters } = action.payload;
320
- // Filters are tab-agnostic (payee/category/class/amount), so apply to
321
- // all tabs so switching tabs after filtering shows consistent results.
322
- transactionsViewState_1.TRANSACTIONS_TABS.forEach((tab) => {
323
- draft.transactionCategorizationView[tab].filters = filters;
324
- });
315
+ const { selectedTab, filters } = action.payload;
316
+ // `filters` is non-nullable per the payload type, so no runtime
317
+ // null-check is needed dropping it removes a dead defensive branch.
318
+ draft.transactionCategorizationView[selectedTab].filters = filters;
325
319
  },
326
320
  saveTransactionCategorization: {
327
321
  prepare(selectedTab, transactionIds, cotTrackingByTransactionId, isUncategorizedExpenseCategoryEnabled) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.1.16-betaRD1",
3
+ "version": "5.1.17",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",