@zeniai/client-epic-state 5.2.77 → 5.2.79

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 (88) hide show
  1. package/lib/esm/view/invoicing/couponView/couponViewReducer.js +14 -25
  2. package/lib/esm/view/invoicing/couponView/couponViewSelector.js +21 -22
  3. package/lib/esm/view/invoicing/couponView/couponViewState.js +2 -0
  4. package/lib/esm/view/invoicing/couponView/fetchInvoicingCouponListEpic.js +26 -8
  5. package/lib/esm/view/invoicing/couponView/fetchInvoicingCouponListPageEpic.js +16 -2
  6. package/lib/esm/view/invoicing/createInvoice/createInvoiceSelector.js +23 -15
  7. package/lib/esm/view/invoicing/createInvoice/epics/fetchCreateInvoiceFormPageEpic.js +5 -2
  8. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +2 -2
  9. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionDetailPageEpic.js +9 -6
  10. package/lib/esm/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListEpic.js +25 -8
  11. package/lib/esm/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListPageEpic.js +15 -2
  12. package/lib/esm/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewReducer.js +12 -23
  13. package/lib/esm/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewSelector.js +6 -9
  14. package/lib/esm/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListEpic.js +26 -8
  15. package/lib/esm/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListPageEpic.js +16 -2
  16. package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.js +14 -25
  17. package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewSelector.js +16 -13
  18. package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.js +2 -0
  19. package/lib/esm/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListEpic.js +25 -8
  20. package/lib/esm/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListPageEpic.js +15 -2
  21. package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.js +12 -23
  22. package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js +6 -9
  23. package/lib/esm/view/invoicing/invoicingListTabCache.js +98 -0
  24. package/lib/esm/view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewEpic.js +4 -7
  25. package/lib/esm/view/invoicing/invoicingOverview/invoicingOverviewSelector.js +8 -5
  26. package/lib/esm/view/invoicing/invoicingSubscriptionListView/epics/fetchInvoicingSubscriptionListEpic.js +28 -9
  27. package/lib/esm/view/invoicing/invoicingSubscriptionListView/epics/fetchInvoicingSubscriptionListPageEpic.js +15 -2
  28. package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.js +13 -25
  29. package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.js +6 -9
  30. package/lib/esm/view/taskManager/taskDetailView/epics/fetchTaskDetailEpic.js +82 -41
  31. package/lib/esm/view/taskManager/taskDetailView/epics/fetchTaskDetailPageEpic.js +9 -1
  32. package/lib/esm/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +2 -23
  33. package/lib/esm/view/taskManager/taskDetailView/taskDetailLocalData.js +36 -0
  34. package/lib/esm/view/taskManager/taskDetailView/taskDetailReducer.js +11 -3
  35. package/lib/view/invoicing/couponView/couponViewReducer.d.ts +8 -1
  36. package/lib/view/invoicing/couponView/couponViewReducer.js +14 -25
  37. package/lib/view/invoicing/couponView/couponViewSelector.js +20 -21
  38. package/lib/view/invoicing/couponView/couponViewState.d.ts +7 -4
  39. package/lib/view/invoicing/couponView/couponViewState.js +3 -1
  40. package/lib/view/invoicing/couponView/fetchInvoicingCouponListEpic.d.ts +1 -1
  41. package/lib/view/invoicing/couponView/fetchInvoicingCouponListEpic.js +25 -7
  42. package/lib/view/invoicing/couponView/fetchInvoicingCouponListPageEpic.js +16 -2
  43. package/lib/view/invoicing/createInvoice/createInvoiceSelector.js +22 -14
  44. package/lib/view/invoicing/createInvoice/epics/fetchCreateInvoiceFormPageEpic.js +5 -2
  45. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +1 -1
  46. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/fetchInvoicingSubscriptionDetailPageEpic.js +9 -6
  47. package/lib/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListEpic.d.ts +1 -1
  48. package/lib/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListEpic.js +24 -7
  49. package/lib/view/invoicing/invoicingCreditNoteListView/epics/fetchInvoicingCreditNoteListPageEpic.js +15 -2
  50. package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewReducer.d.ts +8 -1
  51. package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewReducer.js +12 -23
  52. package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewSelector.js +6 -9
  53. package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewState.d.ts +5 -4
  54. package/lib/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListEpic.d.ts +1 -1
  55. package/lib/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListEpic.js +25 -7
  56. package/lib/view/invoicing/invoicingCustomerListView/epics/fetchInvoicingCustomerListPageEpic.js +16 -2
  57. package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.d.ts +8 -1
  58. package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.js +14 -25
  59. package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewSelector.d.ts +5 -0
  60. package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewSelector.js +17 -13
  61. package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.d.ts +7 -4
  62. package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.js +3 -1
  63. package/lib/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListEpic.d.ts +1 -1
  64. package/lib/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListEpic.js +24 -7
  65. package/lib/view/invoicing/invoicingDunningCaseListView/epics/fetchInvoicingDunningCaseListPageEpic.js +15 -2
  66. package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.d.ts +8 -1
  67. package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewReducer.js +12 -23
  68. package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewSelector.js +6 -9
  69. package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.d.ts +5 -4
  70. package/lib/view/invoicing/invoicingListTabCache.d.ts +71 -0
  71. package/lib/view/invoicing/invoicingListTabCache.js +111 -0
  72. package/lib/view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewEpic.js +4 -7
  73. package/lib/view/invoicing/invoicingOverview/invoicingOverviewSelector.js +8 -5
  74. package/lib/view/invoicing/invoicingSubscriptionListView/epics/fetchInvoicingSubscriptionListEpic.d.ts +1 -1
  75. package/lib/view/invoicing/invoicingSubscriptionListView/epics/fetchInvoicingSubscriptionListEpic.js +27 -8
  76. package/lib/view/invoicing/invoicingSubscriptionListView/epics/fetchInvoicingSubscriptionListPageEpic.js +15 -2
  77. package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.d.ts +8 -1
  78. package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewReducer.js +13 -25
  79. package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.js +6 -9
  80. package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewState.d.ts +5 -5
  81. package/lib/view/taskManager/taskDetailView/epics/fetchTaskDetailEpic.d.ts +2 -2
  82. package/lib/view/taskManager/taskDetailView/epics/fetchTaskDetailEpic.js +80 -39
  83. package/lib/view/taskManager/taskDetailView/epics/fetchTaskDetailPageEpic.js +9 -1
  84. package/lib/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +2 -23
  85. package/lib/view/taskManager/taskDetailView/taskDetailLocalData.d.ts +5 -0
  86. package/lib/view/taskManager/taskDetailView/taskDetailLocalData.js +45 -0
  87. package/lib/view/taskManager/taskDetailView/taskDetailReducer.js +11 -3
  88. package/package.json +1 -1
@@ -2,21 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInvoicingCouponListView = exports.getInvoicingCouponCounts = exports.getInvoicingCouponListFilters = exports.getInvoicingCouponListHasMore = exports.getInvoicingCouponListNextCursor = exports.getInvoicingCouponListFetchState = exports.getInvoicingCouponListItems = void 0;
4
4
  const toolkit_1 = require("@reduxjs/toolkit");
5
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
5
6
  const invoicingTabHelper_1 = require("../invoicingTabHelper");
6
7
  const runningInvoicingActionId_1 = require("../runningInvoicingActionId");
7
8
  const couponViewState_1 = require("./couponViewState");
8
- const getInvoicingCouponListItems = (state) => state.invoicingCouponViewState.ids
9
- .map((id) => state.invoicingCouponState.couponByID[id])
9
+ // These read the unfiltered `all` cache, so a picker never narrows to
10
+ // whichever tab the discounts list was left on.
11
+ const allCouponsTab = (state) => (0, invoicingListTabCache_1.getInvoicingListTab)(state.invoicingCouponViewState.byTab, invoicingListTabCache_1.INVOICING_LIST_ALL_TAB);
12
+ const getInvoicingCouponListItems = (state) => allCouponsTab(state)
13
+ .ids.map((id) => state.invoicingCouponState.couponByID[id])
10
14
  .filter((item) => item != null);
11
15
  exports.getInvoicingCouponListItems = getInvoicingCouponListItems;
12
16
  const getInvoicingCouponListFetchState = (state) => ({
13
- fetchState: state.invoicingCouponViewState.fetchState,
14
- error: state.invoicingCouponViewState.error,
17
+ fetchState: allCouponsTab(state).fetchState,
18
+ error: allCouponsTab(state).error,
15
19
  });
16
20
  exports.getInvoicingCouponListFetchState = getInvoicingCouponListFetchState;
17
- const getInvoicingCouponListNextCursor = (state) => state.invoicingCouponViewState.nextCursor;
21
+ const getInvoicingCouponListNextCursor = (state) => allCouponsTab(state).nextCursor;
18
22
  exports.getInvoicingCouponListNextCursor = getInvoicingCouponListNextCursor;
19
- const getInvoicingCouponListHasMore = (state) => state.invoicingCouponViewState.nextCursor != null;
23
+ const getInvoicingCouponListHasMore = (state) => allCouponsTab(state).nextCursor != null;
20
24
  exports.getInvoicingCouponListHasMore = getInvoicingCouponListHasMore;
21
25
  const getInvoicingCouponListFilters = (state) => state.invoicingCouponViewState.filters;
22
26
  exports.getInvoicingCouponListFilters = getInvoicingCouponListFilters;
@@ -30,20 +34,15 @@ exports.getInvoicingCouponCounts = getInvoicingCouponCounts;
30
34
  */
31
35
  exports.getInvoicingCouponListView = (0, toolkit_1.createSelector)((state) => state.invoicingCouponState, (state) => state.invoicingCouponViewState, (state) => state.invoicingConfigViewState.discountStatusOptions, (state) => state.invoicingConfigViewState.discountLifecycleActionOptions, (state) => state.editInvoicingCouponDetailViewState.actionStateById, (couponState, listViewState, statusOptions, discountLifecycleActionOptions, actionStateById) => {
32
36
  const { activeTab } = listViewState;
33
- const allCoupons = listViewState.ids
37
+ const tab = (0, invoicingListTabCache_1.getInvoicingListTab)(listViewState.byTab, (0, invoicingListTabCache_1.invoicingListSourceTab)(activeTab, couponViewState_1.INVOICING_COUPON_CLIENT_FILTERED_TAB_IDS));
38
+ const tabRows = tab.ids
34
39
  .map((id) => couponState.couponByID[id])
35
40
  .filter((item) => item != null);
36
- // The list API ignores `status`, so it returns every status; filter to the
37
- // active tab client-side. 'all' shows everything and 'inactive' is the
38
- // FE-derived composite of every non-active status (undefined included);
39
- // every other tab is a real backend status and matches exactly — without
40
- // that, config-supplied tabs like `expired` and `archived` would each show
41
- // the whole non-active set.
42
- const coupons = activeTab === 'all'
43
- ? allCoupons
44
- : activeTab === 'inactive'
45
- ? allCoupons.filter((coupon) => coupon.status !== 'active')
46
- : allCoupons.filter((coupon) => coupon.status === activeTab);
41
+ // `inactive` groups every non-active status, which the list API cannot
42
+ // filter on, so it is the `all` rows filtered here.
43
+ const coupons = activeTab === 'inactive'
44
+ ? tabRows.filter((coupon) => coupon.status !== 'active')
45
+ : tabRows;
47
46
  return {
48
47
  activeTab,
49
48
  columns: couponViewState_1.INVOICING_COUPON_COLUMNS,
@@ -51,7 +50,7 @@ exports.getInvoicingCouponListView = (0, toolkit_1.createSelector)((state) => st
51
50
  count: listViewState.counts,
52
51
  countsFetchState: listViewState.countsFetchState,
53
52
  filters: listViewState.filters,
54
- nextCursor: listViewState.nextCursor,
53
+ nextCursor: tab.nextCursor,
55
54
  discountLifecycleActionOptions,
56
55
  statusOptions,
57
56
  tabIds: (0, invoicingTabHelper_1.invoicingTabIdsFromConfig)({
@@ -60,8 +59,8 @@ exports.getInvoicingCouponListView = (0, toolkit_1.createSelector)((state) => st
60
59
  statusOptions,
61
60
  }),
62
61
  runningActionId: (0, runningInvoicingActionId_1.runningInvoicingActionId)(actionStateById),
63
- fetchState: listViewState.fetchState,
64
- error: listViewState.error,
62
+ fetchState: tab.fetchState,
63
+ error: tab.error,
65
64
  sort: listViewState.sort,
66
65
  version: 1.0,
67
66
  };
@@ -1,6 +1,7 @@
1
- import { FetchStateAndError, FetchedState, ID } from '../../../commonStateTypes/common';
1
+ import { FetchStateAndError } from '../../../commonStateTypes/common';
2
2
  import { InvoicingListCounts } from '../../../entity/invoicing/invoicingCommonPayload';
3
3
  import { InvoicingListSort } from '../invoicingApiHelper';
4
+ import { InvoicingListByTab } from '../invoicingListTabCache';
4
5
  export interface InvoicingCouponFilters {
5
6
  search?: string;
6
7
  }
@@ -22,13 +23,15 @@ export declare const INVOICING_COUPON_COLUMNS: InvoicingCouponColumnConfig[];
22
23
  export declare const ALL_INVOICING_COUPON_TAB_IDS: readonly ["all", "active", "inactive"];
23
24
  export declare const toInvoicingCouponTabId: (v: string) => "active" | "inactive" | "all";
24
25
  export type InvoicingCouponTabId = ReturnType<typeof toInvoicingCouponTabId>;
25
- export interface InvoicingCouponViewState extends FetchedState {
26
+ export interface InvoicingCouponViewState {
26
27
  /** Selected status tab (CES-owned so it persists across page revisits). */
27
28
  activeTab: InvoicingCouponTabId;
29
+ /** Per-tab rows, cursor and fetch state; each tab is its own `?status=` query. */
30
+ byTab: InvoicingListByTab;
28
31
  counts: InvoicingListCounts;
29
32
  countsFetchState: FetchStateAndError;
30
33
  filters: InvoicingCouponFilters;
31
- ids: ID[];
32
- nextCursor: string | null;
33
34
  sort?: InvoicingListSort;
34
35
  }
36
+ /** Tabs the list API cannot filter on: they read the `all` rows, filtered here. */
37
+ export declare const INVOICING_COUPON_CLIENT_FILTERED_TAB_IDS: readonly InvoicingCouponTabId[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toInvoicingCouponTabId = exports.ALL_INVOICING_COUPON_TAB_IDS = exports.INVOICING_COUPON_COLUMNS = exports.toInvoicingCouponSortKey = exports.ALL_INVOICING_COUPON_SORT_KEYS = void 0;
3
+ exports.INVOICING_COUPON_CLIENT_FILTERED_TAB_IDS = exports.toInvoicingCouponTabId = exports.ALL_INVOICING_COUPON_TAB_IDS = exports.INVOICING_COUPON_COLUMNS = exports.toInvoicingCouponSortKey = exports.ALL_INVOICING_COUPON_SORT_KEYS = void 0;
4
4
  const stringToUnion_1 = require("../../../commonStateTypes/stringToUnion");
5
5
  exports.ALL_INVOICING_COUPON_SORT_KEYS = [
6
6
  'code',
@@ -33,3 +33,5 @@ exports.ALL_INVOICING_COUPON_TAB_IDS = [
33
33
  ];
34
34
  const toInvoicingCouponTabId = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.ALL_INVOICING_COUPON_TAB_IDS);
35
35
  exports.toInvoicingCouponTabId = toInvoicingCouponTabId;
36
+ /** Tabs the list API cannot filter on: they read the `all` rows, filtered here. */
37
+ exports.INVOICING_COUPON_CLIENT_FILTERED_TAB_IDS = ['inactive'];
@@ -5,4 +5,4 @@ import { RootState } from '../../../rootStateTypes';
5
5
  import { ZeniAPI } from '../../../zeniAPI';
6
6
  import { fetchInvoicingCouponCounts, fetchInvoicingCouponList, fetchInvoicingCouponListPage, updateInvoicingCouponCounts, updateInvoicingCouponCountsFailure, updateInvoicingCouponList, updateInvoicingCouponListFailure } from './couponViewReducer';
7
7
  export type ActionType = ReturnType<typeof fetchInvoicingCouponList> | ReturnType<typeof fetchInvoicingCouponListPage> | ReturnType<typeof fetchInvoicingCouponCounts> | ReturnType<typeof updateInvoicingCouponList> | ReturnType<typeof updateInvoicingCouponListFailure> | ReturnType<typeof updateInvoicingCouponCounts> | ReturnType<typeof updateInvoicingCouponCountsFailure> | ReturnType<typeof updateInvoicingCoupons>;
8
- export declare const fetchInvoicingCouponListEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
8
+ export declare const fetchInvoicingCouponListEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -6,13 +6,18 @@ const operators_1 = require("rxjs/operators");
6
6
  const couponReducer_1 = require("../../../entity/invoicing/coupon/couponReducer");
7
7
  const responsePayload_1 = require("../../../responsePayload");
8
8
  const invoicingApiHelper_1 = require("../invoicingApiHelper");
9
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
9
10
  const couponViewReducer_1 = require("./couponViewReducer");
11
+ const couponViewState_1 = require("./couponViewState");
10
12
  /**
11
13
  * Fetch unless the endpoint is already loaded or in flight — or always when the
12
14
  * caller forces a refresh via `cacheOverride` (e.g. on a filter/sort change).
13
15
  */
14
- const buildQuery = (filters, cursor, sort) => {
16
+ const buildQuery = (filters, cursor, sort, status) => {
15
17
  const params = new URLSearchParams();
18
+ if (status != null) {
19
+ params.set('status', status);
20
+ }
16
21
  if (filters.search != null && filters.search.length > 0) {
17
22
  params.set('search', filters.search);
18
23
  }
@@ -23,9 +28,15 @@ const buildQuery = (filters, cursor, sort) => {
23
28
  (0, invoicingApiHelper_1.applyListSortParams)(params, sort);
24
29
  return params;
25
30
  };
26
- const fetchInvoicingCouponListEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(couponViewReducer_1.fetchInvoicingCouponList.match), (0, operators_1.switchMap)((action) => {
31
+ const fetchInvoicingCouponListEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(couponViewReducer_1.fetchInvoicingCouponList.match), (0, operators_1.map)((action) => ({
32
+ action,
33
+ tabId: (0, invoicingListTabCache_1.invoicingListFetchTab)(state$.value.invoicingCouponViewState.activeTab, action.payload.tabId, couponViewState_1.INVOICING_COUPON_CLIENT_FILTERED_TAB_IDS),
34
+ })),
35
+ // Per tab: a newer fetch of the same tab replaces its in-flight one, while
36
+ // another tab's request keeps running and lands in its own cache.
37
+ (0, operators_1.groupBy)(({ tabId }) => tabId), (0, operators_1.mergeMap)((tabFetches$) => tabFetches$.pipe((0, operators_1.switchMap)(({ action, tabId }) => {
27
38
  const { filters, cursor, keepExistingListItems, sort } = action.payload;
28
- const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/discounts`, buildQuery(filters, cursor, sort));
39
+ const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/discounts`, buildQuery(filters, cursor, sort, (0, invoicingListTabCache_1.invoicingListStatusParam)(tabId)));
29
40
  return zeniAPI.getJSON(apiUrl).pipe((0, operators_1.switchMap)((response) => {
30
41
  if ((0, responsePayload_1.isSuccessResponse)(response)) {
31
42
  const items = response.data?.items ?? [];
@@ -35,11 +46,18 @@ const fetchInvoicingCouponListEpic = (actions$, _state$, zeniAPI) => actions$.pi
35
46
  ids: items.map((item) => item.id),
36
47
  nextCursor: response.data?.next_cursor ?? null,
37
48
  keepExistingListItems,
49
+ tabId,
38
50
  }),
39
51
  ];
40
52
  }
41
- return (0, rxjs_1.of)((0, couponViewReducer_1.updateInvoicingCouponListFailure)(response.status));
42
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, couponViewReducer_1.updateInvoicingCouponListFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch discount list REST API call errored out ' +
43
- JSON.stringify(error))))));
44
- }));
53
+ return (0, rxjs_1.of)((0, couponViewReducer_1.updateInvoicingCouponListFailure)({
54
+ status: response.status,
55
+ tabId,
56
+ }));
57
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, couponViewReducer_1.updateInvoicingCouponListFailure)({
58
+ status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch discount list REST API call errored out ' +
59
+ JSON.stringify(error)),
60
+ tabId,
61
+ }))));
62
+ }))));
45
63
  exports.fetchInvoicingCouponListEpic = fetchInvoicingCouponListEpic;
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fetchInvoicingCouponListPageEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
6
7
  const couponViewReducer_1 = require("./couponViewReducer");
8
+ const couponViewState_1 = require("./couponViewState");
7
9
  /**
8
10
  * Fetch unless the endpoint is already loaded or in flight — or always when the
9
11
  * caller forces a refresh via `cacheOverride` (e.g. on a filter/sort change).
@@ -15,8 +17,20 @@ const fetchInvoicingCouponListPageEpic = (actions$, state$) => actions$.pipe((0,
15
17
  const { cacheOverride, filters, sort } = action.payload;
16
18
  const state = state$.value.invoicingCouponViewState;
17
19
  const pageActions = [];
18
- if (shouldFetch({ fetchState: state.fetchState, error: state.error }, cacheOverride)) {
19
- pageActions.push((0, couponViewReducer_1.fetchInvoicingCouponList)({ filters, sort }));
20
+ const tabId = (0, invoicingListTabCache_1.invoicingListSourceTab)(state.activeTab, couponViewState_1.INVOICING_COUPON_CLIENT_FILTERED_TAB_IDS);
21
+ const tabFetch = (0, invoicingListTabCache_1.planInvoicingListTabFetch)((0, invoicingListTabCache_1.getInvoicingListTab)(state.byTab, tabId), cacheOverride);
22
+ if (tabFetch.kind === 'firstPage') {
23
+ pageActions.push((0, couponViewReducer_1.fetchInvoicingCouponList)({ filters, sort, tabId }));
24
+ }
25
+ else if (tabFetch.kind === 'nextPage') {
26
+ // Less than a page cached and the server has more: top it up.
27
+ pageActions.push((0, couponViewReducer_1.fetchInvoicingCouponList)({
28
+ cursor: tabFetch.cursor,
29
+ filters,
30
+ keepExistingListItems: true,
31
+ sort,
32
+ tabId,
33
+ }));
20
34
  }
21
35
  if (shouldFetch(state.countsFetchState, cacheOverride)) {
22
36
  pageActions.push((0, couponViewReducer_1.fetchInvoicingCouponCounts)());
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCreateInvoiceFormView = void 0;
4
+ const toolkit_1 = require("@reduxjs/toolkit");
4
5
  const addressSelector_1 = require("../../../entity/address/addressSelector");
5
6
  const invoicingCatalogSelector_1 = require("../../../entity/invoicing/invoicingCatalog/invoicingCatalogSelector");
6
7
  const invoicingCatalogListViewSelector_1 = require("../invoicingCatalogListView/invoicingCatalogListViewSelector");
@@ -33,6 +34,25 @@ const hasPerUnitRate = (pricingModel) => pricingModel == null ||
33
34
  const planNamePrefillPrice = (pricePoint) => hasPerUnitRate(pricePoint.pricingModel)
34
35
  ? (0, invoicingCatalogSelector_1.invoicingPricePointDisplayAmount)(pricePoint)?.amount
35
36
  : undefined;
37
+ /**
38
+ * Plans, add-ons and one-time charges, one option per price point. Memoized on
39
+ * the catalog list view so the options keep their identity while the form draft
40
+ * changes on every keystroke.
41
+ */
42
+ const getCreateInvoicePlanNames = (0, toolkit_1.createSelector)(invoicingCatalogListViewSelector_1.getInvoicingCatalogListView, (catalogListView) => [...catalogListView.plans, ...catalogListView.products].flatMap((item) => (item.subFamilies ?? [])
43
+ .filter((subFamily) => (subFamily.name ?? '') !== '')
44
+ .map((subFamily) => ({
45
+ // A price point with no flag is taxable, as subscription billing reads it.
46
+ catalogLine: {
47
+ entityId: subFamily.id,
48
+ // The item's kind is `type`; `itemType` is set on its price points.
49
+ entityType: item.type ?? subFamily.itemType ?? 'plan',
50
+ isTaxed: subFamily.isTaxable ?? true,
51
+ },
52
+ planName: item.name ?? '',
53
+ price: planNamePrefillPrice(subFamily),
54
+ subFamilyName: subFamily.name ?? '',
55
+ }))));
36
56
  /**
37
57
  * Display name for a customer option: company, else the full name, else the
38
58
  * email, else the raw id.
@@ -64,7 +84,7 @@ const getCreateInvoiceFormView = (state) => {
64
84
  const catalogListView = (0, invoicingCatalogListViewSelector_1.getInvoicingCatalogListView)(state);
65
85
  return {
66
86
  fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'invoice'),
67
- customers: (0, invoicingCustomerListViewSelector_1.getInvoicingCustomerListView)(state).customers.map((customer) => ({
87
+ customers: (0, invoicingCustomerListViewSelector_1.getInvoicingAllCustomers)(state).map((customer) => ({
68
88
  billingAddress: customer.billingAddressId != null
69
89
  ? (0, addressSelector_1.getAddressByAddressId)(state.addressState, customer.billingAddressId)
70
90
  : undefined,
@@ -73,19 +93,7 @@ const getCreateInvoiceFormView = (state) => {
73
93
  name: customerDisplayName(customer),
74
94
  })),
75
95
  localData: createInvoiceState.formDraft,
76
- planNames: catalogListView.plans.flatMap((plan) => (plan.subFamilies ?? [])
77
- .filter((subFamily) => (subFamily.name ?? '') !== '')
78
- .map((subFamily) => ({
79
- // A price point with no flag is taxable, as subscription billing reads it.
80
- catalogLine: {
81
- entityId: subFamily.id,
82
- entityType: plan.itemType ?? 'plan',
83
- isTaxed: subFamily.isTaxable ?? true,
84
- },
85
- planName: plan.name ?? '',
86
- price: planNamePrefillPrice(subFamily),
87
- subFamilyName: subFamily.name ?? '',
88
- }))),
96
+ planNames: getCreateInvoicePlanNames(state),
89
97
  products: (0, invoicingCatalogListViewSelector_1.getInvoicingCatalogPrices)(catalogListView.products),
90
98
  savedInvoiceId: createInvoiceState.createdInvoiceId,
91
99
  settings: (0, settingsViewSelector_1.getInvoicingSettings)(state),
@@ -5,6 +5,7 @@ const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const invoicingCatalogListViewReducer_1 = require("../../invoicingCatalogListView/invoicingCatalogListViewReducer");
7
7
  const invoicingCustomerListViewReducer_1 = require("../../invoicingCustomerListView/invoicingCustomerListViewReducer");
8
+ const invoicingListTabCache_1 = require("../../invoicingListTabCache");
8
9
  const settingsViewReducer_1 = require("../../settingsView/settingsViewReducer");
9
10
  const createInvoiceReducer_1 = require("../createInvoiceReducer");
10
11
  /**
@@ -24,14 +25,16 @@ const shouldFetch = (fetchStateAndError, cacheOverride) => cacheOverride ||
24
25
  const fetchCreateInvoiceFormPageEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(createInvoiceReducer_1.fetchCreateInvoiceFormPage.match), (0, operators_1.mergeMap)((action) => {
25
26
  const { cacheOverride } = action.payload;
26
27
  const state = state$.value;
27
- const customerState = state.invoicingCustomerListViewState;
28
+ // The customer picker reads the unfiltered `all` cache.
29
+ const customerTab = (0, invoicingListTabCache_1.getInvoicingListTab)(state.invoicingCustomerListViewState.byTab, invoicingListTabCache_1.INVOICING_LIST_ALL_TAB);
28
30
  const catalogState = state.invoicingCatalogListViewState;
29
31
  const settingsState = state.invoicingSettingsViewState;
30
32
  const pageActions = [];
31
- if (shouldFetch({ fetchState: customerState.fetchState, error: customerState.error }, cacheOverride)) {
33
+ if (shouldFetch({ fetchState: customerTab.fetchState, error: customerTab.error }, cacheOverride)) {
32
34
  pageActions.push((0, invoicingCustomerListViewReducer_1.fetchInvoicingCustomerList)({
33
35
  filters: {},
34
36
  keepExistingListItems: false,
37
+ tabId: invoicingListTabCache_1.INVOICING_LIST_ALL_TAB,
35
38
  }));
36
39
  }
37
40
  if (shouldFetch({ fetchState: catalogState.fetchState, error: catalogState.error }, cacheOverride)) {
@@ -287,7 +287,7 @@ const getInvoicingSubscriptionFormView = (state, invoicingSubscriptionID) => {
287
287
  addons: catalogItemOptionsOfType('addon'),
288
288
  charges: catalogItemOptionsOfType('charge'),
289
289
  coupons: (0, couponViewSelector_1.getInvoicingCouponListItems)(state).map(toInvoicingCouponOption),
290
- customers: (0, invoicingCustomerListViewSelector_1.getInvoicingCustomerListView)(state).customers.map(toInvoicingCustomerOption),
290
+ customers: (0, invoicingCustomerListViewSelector_1.getInvoicingAllCustomers)(state).map(toInvoicingCustomerOption),
291
291
  localData,
292
292
  mode,
293
293
  plans: planPrices.map(toInvoicingPlanOption),
@@ -4,8 +4,10 @@ exports.fetchInvoicingSubscriptionDetailPageEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const couponViewReducer_1 = require("../couponView/couponViewReducer");
7
+ const couponViewSelector_1 = require("../couponView/couponViewSelector");
7
8
  const invoicingCatalogListViewReducer_1 = require("../invoicingCatalogListView/invoicingCatalogListViewReducer");
8
9
  const invoicingConfigViewReducer_1 = require("../invoicingConfigView/invoicingConfigViewReducer");
10
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
9
11
  const editInvoicingSubscriptionDetailViewReducer_1 = require("./editInvoicingSubscriptionDetailViewReducer");
10
12
  /**
11
13
  * Fetch unless the endpoint is already loaded or in flight — or always when the
@@ -50,12 +52,13 @@ const fetchInvoicingSubscriptionDetailPageEpic = (actions$, state$) => actions$.
50
52
  keepExistingListItems: false,
51
53
  }));
52
54
  }
53
- const couponListState = state.invoicingCouponViewState;
54
- if (shouldFetch({
55
- error: couponListState.error,
56
- fetchState: couponListState.fetchState,
57
- }, cacheOverride)) {
58
- pageActions.push((0, couponViewReducer_1.fetchInvoicingCouponList)({ filters: {}, keepExistingListItems: false }));
55
+ // The coupon picker reads the unfiltered `all` cache.
56
+ if (shouldFetch((0, couponViewSelector_1.getInvoicingCouponListFetchState)(state), cacheOverride)) {
57
+ pageActions.push((0, couponViewReducer_1.fetchInvoicingCouponList)({
58
+ filters: {},
59
+ keepExistingListItems: false,
60
+ tabId: invoicingListTabCache_1.INVOICING_LIST_ALL_TAB,
61
+ }));
59
62
  }
60
63
  return pageActions.length > 0 ? (0, rxjs_1.from)(pageActions) : rxjs_1.EMPTY;
61
64
  }));
@@ -5,4 +5,4 @@ import { RootState } from '../../../../rootStateTypes';
5
5
  import { ZeniAPI } from '../../../../zeniAPI';
6
6
  import { fetchInvoicingCreditNoteList, updateInvoicingCreditNoteList, updateInvoicingCreditNoteListFailure } from '../invoicingCreditNoteListViewReducer';
7
7
  export type ActionType = ReturnType<typeof fetchInvoicingCreditNoteList> | ReturnType<typeof updateInvoicingCreditNoteList> | ReturnType<typeof updateInvoicingCreditNoteListFailure> | ReturnType<typeof updateInvoicingCreditNotes>;
8
- export declare const fetchInvoicingCreditNoteListEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
8
+ export declare const fetchInvoicingCreditNoteListEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -6,9 +6,13 @@ const operators_1 = require("rxjs/operators");
6
6
  const creditNoteReducer_1 = require("../../../../entity/invoicing/creditNote/creditNoteReducer");
7
7
  const responsePayload_1 = require("../../../../responsePayload");
8
8
  const invoicingApiHelper_1 = require("../../invoicingApiHelper");
9
+ const invoicingListTabCache_1 = require("../../invoicingListTabCache");
9
10
  const invoicingCreditNoteListViewReducer_1 = require("../invoicingCreditNoteListViewReducer");
10
- const buildQuery = (filters, cursor, sort) => {
11
+ const buildQuery = (filters, cursor, sort, status) => {
11
12
  const params = new URLSearchParams();
13
+ if (status != null) {
14
+ params.set('status', status);
15
+ }
12
16
  if (filters.customerId != null) {
13
17
  params.set('customer_id', filters.customerId);
14
18
  }
@@ -22,9 +26,15 @@ const buildQuery = (filters, cursor, sort) => {
22
26
  (0, invoicingApiHelper_1.applyListSortParams)(params, sort);
23
27
  return params;
24
28
  };
25
- const fetchInvoicingCreditNoteListEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingCreditNoteListViewReducer_1.fetchInvoicingCreditNoteList.match), (0, operators_1.switchMap)((action) => {
29
+ const fetchInvoicingCreditNoteListEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingCreditNoteListViewReducer_1.fetchInvoicingCreditNoteList.match), (0, operators_1.map)((action) => ({
30
+ action,
31
+ tabId: (0, invoicingListTabCache_1.invoicingListFetchTab)(state$.value.invoicingCreditNoteListViewState.activeTab, action.payload.tabId),
32
+ })),
33
+ // Per tab: a newer fetch of the same tab replaces its in-flight one, while
34
+ // another tab's request keeps running and lands in its own cache.
35
+ (0, operators_1.groupBy)(({ tabId }) => tabId), (0, operators_1.mergeMap)((tabFetches$) => tabFetches$.pipe((0, operators_1.switchMap)(({ action, tabId }) => {
26
36
  const { filters, cursor, keepExistingListItems, sort } = action.payload;
27
- const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/credits`, buildQuery(filters, cursor, sort));
37
+ const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/credits`, buildQuery(filters, cursor, sort, (0, invoicingListTabCache_1.invoicingListStatusParam)(tabId)));
28
38
  return zeniAPI.getJSON(apiUrl).pipe((0, operators_1.switchMap)((response) => {
29
39
  if ((0, responsePayload_1.isSuccessResponse)(response)) {
30
40
  const items = response.data?.items ?? [];
@@ -34,11 +44,18 @@ const fetchInvoicingCreditNoteListEpic = (actions$, _state$, zeniAPI) => actions
34
44
  ids: items.map((item) => item.id),
35
45
  nextCursor: response.data?.next_cursor ?? null,
36
46
  keepExistingListItems,
47
+ tabId,
37
48
  }),
38
49
  ];
39
50
  }
40
- return (0, rxjs_1.of)((0, invoicingCreditNoteListViewReducer_1.updateInvoicingCreditNoteListFailure)(response.status));
41
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingCreditNoteListViewReducer_1.updateInvoicingCreditNoteListFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch credit note list REST API call errored out ' +
42
- JSON.stringify(error))))));
43
- }));
51
+ return (0, rxjs_1.of)((0, invoicingCreditNoteListViewReducer_1.updateInvoicingCreditNoteListFailure)({
52
+ status: response.status,
53
+ tabId,
54
+ }));
55
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingCreditNoteListViewReducer_1.updateInvoicingCreditNoteListFailure)({
56
+ status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch credit note list REST API call errored out ' +
57
+ JSON.stringify(error)),
58
+ tabId,
59
+ }))));
60
+ }))));
44
61
  exports.fetchInvoicingCreditNoteListEpic = fetchInvoicingCreditNoteListEpic;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fetchInvoicingCreditNoteListPageEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const invoicingListTabCache_1 = require("../../invoicingListTabCache");
6
7
  const invoicingCreditNoteListViewReducer_1 = require("../invoicingCreditNoteListViewReducer");
7
8
  /**
8
9
  * Fetch unless the endpoint is already loaded or in flight — or always when the
@@ -20,8 +21,20 @@ const fetchInvoicingCreditNoteListPageEpic = (actions$, state$) => actions$.pipe
20
21
  const { cacheOverride, filters, sort } = action.payload;
21
22
  const state = state$.value.invoicingCreditNoteListViewState;
22
23
  const pageActions = [];
23
- if (shouldFetch({ fetchState: state.fetchState, error: state.error }, cacheOverride)) {
24
- pageActions.push((0, invoicingCreditNoteListViewReducer_1.fetchInvoicingCreditNoteList)({ filters, sort }));
24
+ const tabId = (0, invoicingListTabCache_1.invoicingListSourceTab)(state.activeTab);
25
+ const tabFetch = (0, invoicingListTabCache_1.planInvoicingListTabFetch)((0, invoicingListTabCache_1.getInvoicingListTab)(state.byTab, tabId), cacheOverride);
26
+ if (tabFetch.kind === 'firstPage') {
27
+ pageActions.push((0, invoicingCreditNoteListViewReducer_1.fetchInvoicingCreditNoteList)({ filters, sort, tabId }));
28
+ }
29
+ else if (tabFetch.kind === 'nextPage') {
30
+ // Less than a page cached and the server has more: top it up.
31
+ pageActions.push((0, invoicingCreditNoteListViewReducer_1.fetchInvoicingCreditNoteList)({
32
+ cursor: tabFetch.cursor,
33
+ filters,
34
+ keepExistingListItems: true,
35
+ sort,
36
+ tabId,
37
+ }));
25
38
  }
26
39
  if (shouldFetch(state.countsFetchState, cacheOverride)) {
27
40
  pageActions.push((0, invoicingCreditNoteListViewReducer_1.fetchInvoicingCreditNoteCounts)());
@@ -9,11 +9,14 @@ export declare const fetchInvoicingCreditNoteList: import("@reduxjs/toolkit").Ac
9
9
  filters?: InvoicingCreditNoteFilters;
10
10
  keepExistingListItems?: boolean;
11
11
  sort?: InvoicingListSort;
12
+ /** The tab cache to fill; defaults to the active tab's. */
13
+ tabId?: string;
12
14
  }], {
13
15
  filters: InvoicingCreditNoteFilters;
14
16
  cursor: string | undefined;
15
17
  keepExistingListItems: boolean;
16
18
  sort: InvoicingListSort | undefined;
19
+ tabId: string | undefined;
17
20
  }, "invoicingCreditNoteListView/fetchInvoicingCreditNoteList", never, never>, fetchInvoicingCreditNoteListPage: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
18
21
  cacheOverride?: boolean;
19
22
  filters?: InvoicingCreditNoteFilters;
@@ -26,6 +29,10 @@ export declare const fetchInvoicingCreditNoteList: import("@reduxjs/toolkit").Ac
26
29
  ids: ID[];
27
30
  keepExistingListItems: boolean;
28
31
  nextCursor: string | null;
29
- }, "invoicingCreditNoteListView/updateInvoicingCreditNoteList">, updateInvoicingCreditNoteListFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingCreditNoteListView/updateInvoicingCreditNoteListFailure">, fetchInvoicingCreditNoteCounts: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingCreditNoteListView/fetchInvoicingCreditNoteCounts">, updateInvoicingCreditNoteCounts: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingListCounts, "invoicingCreditNoteListView/updateInvoicingCreditNoteCounts">, updateInvoicingCreditNoteCountsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingCreditNoteListView/updateInvoicingCreditNoteCountsFailure">, updateInvoicingCreditNoteFilters: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingCreditNoteFilters, "invoicingCreditNoteListView/updateInvoicingCreditNoteFilters">, setInvoicingCreditNoteActiveTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<"adjusted" | "refunded" | "refund_due" | "voided" | "all", "invoicingCreditNoteListView/setInvoicingCreditNoteActiveTab">;
32
+ tabId: string;
33
+ }, "invoicingCreditNoteListView/updateInvoicingCreditNoteList">, updateInvoicingCreditNoteListFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
34
+ status: ZeniAPIStatus;
35
+ tabId: string;
36
+ }, "invoicingCreditNoteListView/updateInvoicingCreditNoteListFailure">, fetchInvoicingCreditNoteCounts: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingCreditNoteListView/fetchInvoicingCreditNoteCounts">, updateInvoicingCreditNoteCounts: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingListCounts, "invoicingCreditNoteListView/updateInvoicingCreditNoteCounts">, updateInvoicingCreditNoteCountsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingCreditNoteListView/updateInvoicingCreditNoteCountsFailure">, updateInvoicingCreditNoteFilters: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingCreditNoteFilters, "invoicingCreditNoteListView/updateInvoicingCreditNoteFilters">, setInvoicingCreditNoteActiveTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<"adjusted" | "refunded" | "refund_due" | "voided" | "all", "invoicingCreditNoteListView/setInvoicingCreditNoteActiveTab">;
30
37
  declare const _default: import("redux").Reducer<InvoicingCreditNoteListViewState>;
31
38
  export default _default;
@@ -4,18 +4,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.setInvoicingCreditNoteActiveTab = exports.updateInvoicingCreditNoteFilters = exports.updateInvoicingCreditNoteCountsFailure = exports.updateInvoicingCreditNoteCounts = exports.fetchInvoicingCreditNoteCounts = exports.updateInvoicingCreditNoteListFailure = exports.updateInvoicingCreditNoteList = exports.fetchInvoicingCreditNoteListPage = exports.fetchInvoicingCreditNoteList = exports.initialState = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const rootActions_1 = require("../../../rootActions");
7
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
7
8
  exports.initialState = {
8
- fetchState: 'Not-Started',
9
- error: undefined,
10
9
  activeTab: 'all',
11
- ids: [],
12
- nextCursor: null,
10
+ byTab: {},
13
11
  filters: {},
14
12
  counts: { all: 0 },
15
13
  countsFetchState: { fetchState: 'Not-Started', error: undefined },
16
- hasValidState() {
17
- return this.fetchState === 'Completed';
18
- },
19
14
  };
20
15
  const invoicingCreditNoteListView = (0, toolkit_1.createSlice)({
21
16
  name: 'invoicingCreditNoteListView',
@@ -23,14 +18,9 @@ const invoicingCreditNoteListView = (0, toolkit_1.createSlice)({
23
18
  reducers: {
24
19
  fetchInvoicingCreditNoteList: {
25
20
  reducer(draft, action) {
26
- if (!action.payload.keepExistingListItems) {
27
- draft.ids = [];
28
- draft.nextCursor = null;
29
- }
21
+ (0, invoicingListTabCache_1.startInvoicingListTabFetch)(draft.byTab, (0, invoicingListTabCache_1.invoicingListFetchTab)(draft.activeTab, action.payload.tabId), action.payload.keepExistingListItems);
30
22
  draft.filters = action.payload.filters;
31
23
  draft.sort = action.payload.sort;
32
- draft.fetchState = 'In-Progress';
33
- draft.error = undefined;
34
24
  },
35
25
  prepare(payload) {
36
26
  return {
@@ -39,12 +29,17 @@ const invoicingCreditNoteListView = (0, toolkit_1.createSlice)({
39
29
  cursor: payload.cursor,
40
30
  keepExistingListItems: payload.keepExistingListItems ?? false,
41
31
  sort: payload.sort,
32
+ tabId: payload.tabId,
42
33
  },
43
34
  };
44
35
  },
45
36
  },
46
37
  fetchInvoicingCreditNoteListPage: {
47
38
  reducer(draft, action) {
39
+ // Another search or sort makes every cached tab stale.
40
+ if (!(0, invoicingListTabCache_1.isSameInvoicingListQuery)(draft, action.payload)) {
41
+ draft.byTab = {};
42
+ }
48
43
  draft.filters = action.payload.filters;
49
44
  draft.sort = action.payload.sort;
50
45
  },
@@ -59,16 +54,10 @@ const invoicingCreditNoteListView = (0, toolkit_1.createSlice)({
59
54
  },
60
55
  },
61
56
  updateInvoicingCreditNoteList(draft, action) {
62
- draft.ids = action.payload.keepExistingListItems
63
- ? [...new Set([...draft.ids, ...action.payload.ids])]
64
- : action.payload.ids;
65
- draft.nextCursor = action.payload.nextCursor;
66
- draft.fetchState = 'Completed';
67
- draft.error = undefined;
57
+ (0, invoicingListTabCache_1.completeInvoicingListTabFetch)(draft.byTab, action.payload.tabId, action.payload);
68
58
  },
69
59
  updateInvoicingCreditNoteListFailure(draft, action) {
70
- draft.fetchState = 'Error';
71
- draft.error = action.payload;
60
+ (0, invoicingListTabCache_1.failInvoicingListTabFetch)(draft.byTab, action.payload.tabId, action.payload.status);
72
61
  },
73
62
  fetchInvoicingCreditNoteCounts(draft) {
74
63
  draft.countsFetchState.fetchState = 'In-Progress';
@@ -86,8 +75,8 @@ const invoicingCreditNoteListView = (0, toolkit_1.createSlice)({
86
75
  updateInvoicingCreditNoteFilters(draft, action) {
87
76
  draft.filters = action.payload;
88
77
  },
89
- // Select a status tab. The list API ignores `status` (returns all statuses),
90
- // so the selector filters rows to this tab client-side — no refetch needed.
78
+ // Select a status tab. The view dispatches the page fetch after, which loads
79
+ // the tab from the server only when its cache is empty or failed.
91
80
  setInvoicingCreditNoteActiveTab(draft, action) {
92
81
  draft.activeTab = action.payload;
93
82
  },
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInvoicingCreditNoteListView = void 0;
4
4
  const toolkit_1 = require("@reduxjs/toolkit");
5
5
  const creditNoteSelector_1 = require("../../../entity/invoicing/creditNote/creditNoteSelector");
6
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
6
7
  const invoicingTabHelper_1 = require("../invoicingTabHelper");
7
8
  const invoicingCreditNoteListViewState_1 = require("./invoicingCreditNoteListViewState");
8
9
  /**
@@ -12,12 +13,8 @@ const invoicingCreditNoteListViewState_1 = require("./invoicingCreditNoteListVie
12
13
  */
13
14
  exports.getInvoicingCreditNoteListView = (0, toolkit_1.createSelector)((state) => state.invoicingCreditNoteState, (state) => state.invoicingCreditNoteListViewState, (state) => state.invoicingConfigViewState.creditNoteStatusOptions, (state) => state.invoicingConfigViewState.creditNoteTypeOptions, (creditNoteState, listViewState, statusOptions, typeOptions) => {
14
15
  const { activeTab } = listViewState;
15
- const allCreditNotes = (0, creditNoteSelector_1.getInvoicingCreditNotesByIds)(creditNoteState, listViewState.ids);
16
- // The list API ignores `status`, so it returns every status; filter to the
17
- // active tab client-side ('all' shows everything).
18
- const creditNotes = activeTab === 'all'
19
- ? allCreditNotes
20
- : allCreditNotes.filter((creditNote) => creditNote.status === activeTab);
16
+ const tab = (0, invoicingListTabCache_1.getInvoicingListTab)(listViewState.byTab, (0, invoicingListTabCache_1.invoicingListSourceTab)(activeTab));
17
+ const creditNotes = (0, creditNoteSelector_1.getInvoicingCreditNotesByIds)(creditNoteState, tab.ids);
21
18
  return {
22
19
  activeTab,
23
20
  columns: invoicingCreditNoteListViewState_1.INVOICING_CREDIT_NOTE_COLUMNS,
@@ -25,15 +22,15 @@ exports.getInvoicingCreditNoteListView = (0, toolkit_1.createSelector)((state) =
25
22
  count: listViewState.counts,
26
23
  countsFetchState: listViewState.countsFetchState,
27
24
  filters: listViewState.filters,
28
- nextCursor: listViewState.nextCursor,
25
+ nextCursor: tab.nextCursor,
29
26
  statusOptions,
30
27
  typeOptions,
31
28
  tabIds: (0, invoicingTabHelper_1.invoicingTabIdsFromConfig)({
32
29
  allTabIds: invoicingCreditNoteListViewState_1.ALL_INVOICING_CREDIT_NOTE_TAB_IDS,
33
30
  statusOptions,
34
31
  }),
35
- fetchState: listViewState.fetchState,
36
- error: listViewState.error,
32
+ fetchState: tab.fetchState,
33
+ error: tab.error,
37
34
  sort: listViewState.sort,
38
35
  version: 1.0,
39
36
  };