@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
@@ -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 InvoicingDunningCaseFilters {
5
6
  search?: string;
6
7
  }
@@ -22,14 +23,14 @@ export declare const INVOICING_DUNNING_CASE_COLUMNS: InvoicingDunningCaseColumnC
22
23
  export declare const ALL_INVOICING_DUNNING_CASE_TAB_IDS: readonly ["all", "retrying", "scheduled", "manual_review", "paused", "resolved", "cancelled"];
23
24
  export declare const toInvoicingDunningCaseTabId: (v: string) => "paused" | "cancelled" | "scheduled" | "retrying" | "manual_review" | "resolved" | "all";
24
25
  export type InvoicingDunningCaseTabId = ReturnType<typeof toInvoicingDunningCaseTabId>;
25
- export interface InvoicingDunningCaseListViewState extends FetchedState {
26
+ export interface InvoicingDunningCaseListViewState {
26
27
  /** Selected status tab (CES-owned so it persists across page revisits). */
27
28
  activeTab: InvoicingDunningCaseTabId;
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: InvoicingDunningCaseFilters;
31
- ids: ID[];
32
- nextCursor: string | null;
33
34
  /** Active server-side sort (undefined = backend default order). */
34
35
  sort?: InvoicingListSort;
35
36
  }
@@ -0,0 +1,71 @@
1
+ import { FetchStateAndError, ID } from '../../commonStateTypes/common';
2
+ import { ZeniAPIStatus } from '../../responsePayload';
3
+ import { InvoicingListSort } from './invoicingApiHelper';
4
+ /**
5
+ * One status tab of a list. Each tab is its own server query (`?status=`), so
6
+ * its rows, cursor and fetch state are cached apart: switching back to a loaded
7
+ * tab costs no request.
8
+ */
9
+ export interface InvoicingListTab extends FetchStateAndError {
10
+ ids: ID[];
11
+ nextCursor: string | null;
12
+ }
13
+ /**
14
+ * Keyed by the raw tab id: tabs come from `/1.0/config`, so a status this
15
+ * build's tab-id union does not know still gets a cache entry.
16
+ */
17
+ export type InvoicingListByTab = Record<string, InvoicingListTab>;
18
+ export declare const INVOICING_LIST_ALL_TAB = "all";
19
+ /** A tab's cache, or a not-started one when it was never fetched. */
20
+ export declare const getInvoicingListTab: (byTab: InvoicingListByTab, tabId: string) => InvoicingListTab;
21
+ /**
22
+ * The cache a tab reads and fetches. A tab the list API cannot filter on (a
23
+ * derived grouping such as the customers' `at_risk`, not a stored status) is
24
+ * the `all` rows, filtered by the selector.
25
+ */
26
+ export declare const invoicingListSourceTab: (tabId: string, clientFilteredTabIds?: readonly string[]) => string;
27
+ /**
28
+ * The cache a list fetch fills: the tab the caller named, else the active tab's
29
+ * source. The reducer and the epic both resolve it, so they agree on the tab.
30
+ */
31
+ export declare const invoicingListFetchTab: (activeTab: string, requestedTab: string | undefined, clientFilteredTabIds?: readonly string[]) => string;
32
+ /** The `status` query param for a source tab; `all` sends none. */
33
+ export declare const invoicingListStatusParam: (sourceTab: string) => string | undefined;
34
+ /**
35
+ * Whether two list queries match, so their per-tab caches stay valid. A filter
36
+ * left unset and one cleared to `''` are the same query.
37
+ */
38
+ export declare const isSameInvoicingListQuery: (a: {
39
+ filters: object;
40
+ sort?: InvoicingListSort;
41
+ }, b: {
42
+ filters: object;
43
+ sort?: InvoicingListSort;
44
+ }) => boolean;
45
+ /** What opening a tab should fetch, if anything. */
46
+ export type InvoicingListTabFetch = {
47
+ kind: 'none';
48
+ } | {
49
+ kind: 'firstPage';
50
+ } | {
51
+ cursor: string;
52
+ kind: 'nextPage';
53
+ };
54
+ /**
55
+ * Fetch a tab that is empty or failed; top up one that holds less than a page
56
+ * while the server says there is more; leave a full or complete one cached.
57
+ * Runs on page/tab visits only, so a server returning short pages cannot loop.
58
+ */
59
+ export declare function planInvoicingListTabFetch(tab: InvoicingListTab, cacheOverride: boolean): InvoicingListTabFetch;
60
+ export declare function startInvoicingListTabFetch(byTab: InvoicingListByTab, tabId: string, keepExistingListItems: boolean): void;
61
+ export declare function completeInvoicingListTabFetch(byTab: InvoicingListByTab, tabId: string, page: {
62
+ ids: ID[];
63
+ keepExistingListItems: boolean;
64
+ nextCursor: string | null;
65
+ }): void;
66
+ export declare function failInvoicingListTabFetch(byTab: InvoicingListByTab, tabId: string, error: ZeniAPIStatus): void;
67
+ /**
68
+ * A created record leads `all` and, when its status is known, that status's
69
+ * tab if already loaded. Returns false when `all` already had it.
70
+ */
71
+ export declare function addToInvoicingListTabs(byTab: InvoicingListByTab, id: ID, status?: string): boolean;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSameInvoicingListQuery = exports.invoicingListStatusParam = exports.invoicingListFetchTab = exports.invoicingListSourceTab = exports.getInvoicingListTab = exports.INVOICING_LIST_ALL_TAB = void 0;
4
+ exports.planInvoicingListTabFetch = planInvoicingListTabFetch;
5
+ exports.startInvoicingListTabFetch = startInvoicingListTabFetch;
6
+ exports.completeInvoicingListTabFetch = completeInvoicingListTabFetch;
7
+ exports.failInvoicingListTabFetch = failInvoicingListTabFetch;
8
+ exports.addToInvoicingListTabs = addToInvoicingListTabs;
9
+ const invoicingApiHelper_1 = require("./invoicingApiHelper");
10
+ exports.INVOICING_LIST_ALL_TAB = 'all';
11
+ const NOT_STARTED_TAB = Object.freeze({
12
+ ids: [],
13
+ nextCursor: null,
14
+ fetchState: 'Not-Started',
15
+ error: undefined,
16
+ });
17
+ /** A tab's cache, or a not-started one when it was never fetched. */
18
+ const getInvoicingListTab = (byTab, tabId) => byTab[tabId] ?? NOT_STARTED_TAB;
19
+ exports.getInvoicingListTab = getInvoicingListTab;
20
+ /**
21
+ * The cache a tab reads and fetches. A tab the list API cannot filter on (a
22
+ * derived grouping such as the customers' `at_risk`, not a stored status) is
23
+ * the `all` rows, filtered by the selector.
24
+ */
25
+ const invoicingListSourceTab = (tabId, clientFilteredTabIds = []) => clientFilteredTabIds.includes(tabId) ? exports.INVOICING_LIST_ALL_TAB : tabId;
26
+ exports.invoicingListSourceTab = invoicingListSourceTab;
27
+ /**
28
+ * The cache a list fetch fills: the tab the caller named, else the active tab's
29
+ * source. The reducer and the epic both resolve it, so they agree on the tab.
30
+ */
31
+ const invoicingListFetchTab = (activeTab, requestedTab, clientFilteredTabIds = []) => requestedTab ?? (0, exports.invoicingListSourceTab)(activeTab, clientFilteredTabIds);
32
+ exports.invoicingListFetchTab = invoicingListFetchTab;
33
+ /** The `status` query param for a source tab; `all` sends none. */
34
+ const invoicingListStatusParam = (sourceTab) => sourceTab === exports.INVOICING_LIST_ALL_TAB ? undefined : sourceTab;
35
+ exports.invoicingListStatusParam = invoicingListStatusParam;
36
+ /**
37
+ * Whether two list queries match, so their per-tab caches stay valid. A filter
38
+ * left unset and one cleared to `''` are the same query.
39
+ */
40
+ const isSameInvoicingListQuery = (a, b) => {
41
+ const aFilters = a.filters;
42
+ const bFilters = b.filters;
43
+ const keys = new Set([...Object.keys(aFilters), ...Object.keys(bFilters)]);
44
+ return ([...keys].every((key) => (aFilters[key] ?? '') === (bFilters[key] ?? '')) &&
45
+ a.sort?.field === b.sort?.field &&
46
+ a.sort?.dir === b.sort?.dir);
47
+ };
48
+ exports.isSameInvoicingListQuery = isSameInvoicingListQuery;
49
+ /**
50
+ * Fetch a tab that is empty or failed; top up one that holds less than a page
51
+ * while the server says there is more; leave a full or complete one cached.
52
+ * Runs on page/tab visits only, so a server returning short pages cannot loop.
53
+ */
54
+ function planInvoicingListTabFetch(tab, cacheOverride) {
55
+ if (cacheOverride) {
56
+ return { kind: 'firstPage' };
57
+ }
58
+ if (tab.fetchState === 'In-Progress') {
59
+ return { kind: 'none' };
60
+ }
61
+ if (tab.fetchState !== 'Completed') {
62
+ return { kind: 'firstPage' };
63
+ }
64
+ if (tab.ids.length < invoicingApiHelper_1.INVOICING_LIST_PAGE_SIZE && tab.nextCursor != null) {
65
+ return { cursor: tab.nextCursor, kind: 'nextPage' };
66
+ }
67
+ return { kind: 'none' };
68
+ }
69
+ const tabFor = (byTab, tabId) => {
70
+ byTab[tabId] ?? (byTab[tabId] = { ...NOT_STARTED_TAB, ids: [] });
71
+ return byTab[tabId];
72
+ };
73
+ function startInvoicingListTabFetch(byTab, tabId, keepExistingListItems) {
74
+ const tab = tabFor(byTab, tabId);
75
+ if (!keepExistingListItems) {
76
+ tab.ids = [];
77
+ tab.nextCursor = null;
78
+ }
79
+ tab.fetchState = 'In-Progress';
80
+ tab.error = undefined;
81
+ }
82
+ function completeInvoicingListTabFetch(byTab, tabId, page) {
83
+ const tab = tabFor(byTab, tabId);
84
+ tab.ids = page.keepExistingListItems
85
+ ? [...new Set([...tab.ids, ...page.ids])]
86
+ : page.ids;
87
+ tab.nextCursor = page.nextCursor;
88
+ tab.fetchState = 'Completed';
89
+ tab.error = undefined;
90
+ }
91
+ function failInvoicingListTabFetch(byTab, tabId, error) {
92
+ const tab = tabFor(byTab, tabId);
93
+ tab.fetchState = 'Error';
94
+ tab.error = error;
95
+ }
96
+ /**
97
+ * A created record leads `all` and, when its status is known, that status's
98
+ * tab if already loaded. Returns false when `all` already had it.
99
+ */
100
+ function addToInvoicingListTabs(byTab, id, status) {
101
+ const all = tabFor(byTab, exports.INVOICING_LIST_ALL_TAB);
102
+ if (all.ids.includes(id)) {
103
+ return false;
104
+ }
105
+ all.ids = [id, ...all.ids];
106
+ const statusTab = status != null ? byTab[status] : undefined;
107
+ if (statusTab != null && !statusTab.ids.includes(id)) {
108
+ statusTab.ids = [id, ...statusTab.ids];
109
+ }
110
+ return true;
111
+ }
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fetchInvoicingOverviewEpic = 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 invoicingSubscriptionListViewReducer_1 = require("../../invoicingSubscriptionListView/invoicingSubscriptionListViewReducer");
7
- const invoicingSubscriptionListViewSelector_1 = require("../../invoicingSubscriptionListView/invoicingSubscriptionListViewSelector");
8
8
  const settingsViewReducer_1 = require("../../settingsView/settingsViewReducer");
9
9
  const settingsViewSelector_1 = require("../../settingsView/settingsViewSelector");
10
10
  const invoicingOverviewReducer_1 = require("../invoicingOverviewReducer");
@@ -47,12 +47,9 @@ const fetchInvoicingOverviewEpic = (actions$, state$) => actions$.pipe((0, opera
47
47
  if (shouldFetch((0, settingsViewSelector_1.getInvoicingSettingsFetchState)(rootState), cacheOverride)) {
48
48
  overviewActions.push((0, settingsViewReducer_1.fetchInvoicingSettings)());
49
49
  }
50
- const subscriptionListView = (0, invoicingSubscriptionListViewSelector_1.getInvoicingSubscriptionListView)(rootState);
51
- if (shouldFetch({
52
- fetchState: subscriptionListView.fetchState,
53
- error: subscriptionListView.error,
54
- }, cacheOverride)) {
55
- overviewActions.push((0, invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionList)({}));
50
+ const subscriptionsTab = (0, invoicingListTabCache_1.getInvoicingListTab)(rootState.invoicingSubscriptionListViewState.byTab, invoicingListTabCache_1.INVOICING_LIST_ALL_TAB);
51
+ if (shouldFetch(subscriptionsTab, cacheOverride)) {
52
+ overviewActions.push((0, invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionList)({ tabId: invoicingListTabCache_1.INVOICING_LIST_ALL_TAB }));
56
53
  }
57
54
  return (0, rxjs_1.concat)((0, rxjs_1.from)(overviewActions));
58
55
  }));
@@ -3,7 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInvoicingOverview = void 0;
4
4
  exports.buildPeriodOptions = buildPeriodOptions;
5
5
  const reduceFetchState_1 = require("../../../commonStateTypes/reduceFetchState");
6
- const invoicingSubscriptionListViewSelector_1 = require("../invoicingSubscriptionListView/invoicingSubscriptionListViewSelector");
6
+ const invoicingSubscriptionSelector_1 = require("../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionSelector");
7
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
7
8
  const settingsViewSelector_1 = require("../settingsView/settingsViewSelector");
8
9
  const PERIOD_OPTION_MONTHS = 12;
9
10
  function daysInMonth(year, month) {
@@ -29,10 +30,12 @@ function buildPeriodOptions() {
29
30
  const getInvoicingOverview = (state) => {
30
31
  const overview = state.invoicingOverviewState;
31
32
  const settingsFetchState = (0, settingsViewSelector_1.getInvoicingSettingsFetchState)(state);
32
- const subscriptionListView = (0, invoicingSubscriptionListViewSelector_1.getInvoicingSubscriptionListView)(state);
33
+ // The overview waits on the unfiltered `all` subscriptions, not the tab the
34
+ // subscriptions list was left on.
35
+ const subscriptionsTab = (0, invoicingListTabCache_1.getInvoicingListTab)(state.invoicingSubscriptionListViewState.byTab, invoicingListTabCache_1.INVOICING_LIST_ALL_TAB);
33
36
  const subscriptionListFetchState = {
34
- fetchState: subscriptionListView.fetchState,
35
- error: subscriptionListView.error,
37
+ fetchState: subscriptionsTab.fetchState,
38
+ error: subscriptionsTab.error,
36
39
  };
37
40
  const reducedFetchState = (0, reduceFetchState_1.reduceAllFetchState)([
38
41
  overview.kpisFetchState,
@@ -60,7 +63,7 @@ const getInvoicingOverview = (state) => {
60
63
  fetchState: settingsFetchState,
61
64
  },
62
65
  subscriptionList: {
63
- data: subscriptionListView.subscriptions,
66
+ data: (0, invoicingSubscriptionSelector_1.getInvoicingSubscriptionsByIds)(state.invoicingSubscriptionState, subscriptionsTab.ids),
64
67
  fetchState: subscriptionListFetchState,
65
68
  },
66
69
  ...reducedFetchState,
@@ -6,4 +6,4 @@ import { RootState } from '../../../../rootStateTypes';
6
6
  import { ZeniAPI } from '../../../../zeniAPI';
7
7
  import { fetchInvoicingSubscriptionList, updateInvoicingSubscriptionList, updateInvoicingSubscriptionListFailure } from '../invoicingSubscriptionListViewReducer';
8
8
  export type ActionType = ReturnType<typeof fetchInvoicingSubscriptionList> | ReturnType<typeof updateInvoicingSubscriptionList> | ReturnType<typeof updateInvoicingSubscriptionListFailure> | ReturnType<typeof updateAddresses> | ReturnType<typeof updateInvoicingSubscriptions>;
9
- export declare const fetchInvoicingSubscriptionListEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
9
+ export declare const fetchInvoicingSubscriptionListEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -8,9 +8,13 @@ const invoicingSubscriptionPayload_1 = require("../../../../entity/invoicing/inv
8
8
  const invoicingSubscriptionReducer_1 = require("../../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionReducer");
9
9
  const responsePayload_1 = require("../../../../responsePayload");
10
10
  const invoicingApiHelper_1 = require("../../invoicingApiHelper");
11
+ const invoicingListTabCache_1 = require("../../invoicingListTabCache");
11
12
  const invoicingSubscriptionListViewReducer_1 = require("../invoicingSubscriptionListViewReducer");
12
- const buildQuery = (filters, cursor, sort) => {
13
+ const buildQuery = (filters, cursor, sort, status) => {
13
14
  const params = new URLSearchParams();
15
+ if (status != null) {
16
+ params.set('status', status);
17
+ }
14
18
  if (filters.customerId != null) {
15
19
  params.set('customer_id', filters.customerId);
16
20
  }
@@ -30,10 +34,18 @@ const buildQuery = (filters, cursor, sort) => {
30
34
  (0, invoicingApiHelper_1.applyListSortParams)(params, sort);
31
35
  return params;
32
36
  };
33
- const fetchInvoicingSubscriptionListEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionList.match), (0, operators_1.switchMap)((action) => {
37
+ const fetchInvoicingSubscriptionListEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionList.match), (0, operators_1.map)((action) => ({
38
+ action,
39
+ tabId: (0, invoicingListTabCache_1.invoicingListFetchTab)(state$.value.invoicingSubscriptionListViewState.activeTab, action.payload.tabId),
40
+ })),
41
+ // Per tab: a newer fetch of the same tab replaces its in-flight one, while
42
+ // another tab's request keeps running and lands in its own cache.
43
+ (0, operators_1.groupBy)(({ tabId }) => tabId), (0, operators_1.mergeMap)((tabFetches$) => tabFetches$.pipe((0, operators_1.switchMap)(({ action, tabId }) => {
34
44
  const { filters, cursor, keepExistingListItems, sort } = action.payload;
35
- const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/subscriptions`, buildQuery(filters, cursor, sort));
36
- return zeniAPI.getJSON(apiUrl).pipe((0, operators_1.switchMap)((response) => {
45
+ const apiUrl = (0, invoicingApiHelper_1.withQuery)(`${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/subscriptions`, buildQuery(filters, cursor, sort, (0, invoicingListTabCache_1.invoicingListStatusParam)(tabId)));
46
+ return zeniAPI
47
+ .getJSON(apiUrl)
48
+ .pipe((0, operators_1.switchMap)((response) => {
37
49
  if ((0, responsePayload_1.isSuccessResponse)(response)) {
38
50
  const items = response.data?.items ?? [];
39
51
  return [
@@ -43,11 +55,18 @@ const fetchInvoicingSubscriptionListEpic = (actions$, _state$, zeniAPI) => actio
43
55
  ids: items.map((item) => item.id),
44
56
  nextCursor: response.data?.next_cursor ?? null,
45
57
  keepExistingListItems,
58
+ tabId,
46
59
  }),
47
60
  ];
48
61
  }
49
- return (0, rxjs_1.of)((0, invoicingSubscriptionListViewReducer_1.updateInvoicingSubscriptionListFailure)(response.status));
50
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingSubscriptionListViewReducer_1.updateInvoicingSubscriptionListFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch subscription list REST API call errored out ' +
51
- JSON.stringify(error))))));
52
- }));
62
+ return (0, rxjs_1.of)((0, invoicingSubscriptionListViewReducer_1.updateInvoicingSubscriptionListFailure)({
63
+ status: response.status,
64
+ tabId,
65
+ }));
66
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingSubscriptionListViewReducer_1.updateInvoicingSubscriptionListFailure)({
67
+ status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch subscription list REST API call errored out ' +
68
+ JSON.stringify(error)),
69
+ tabId,
70
+ }))));
71
+ }))));
53
72
  exports.fetchInvoicingSubscriptionListEpic = fetchInvoicingSubscriptionListEpic;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fetchInvoicingSubscriptionListPageEpic = 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 invoicingSubscriptionListViewReducer_1 = require("../invoicingSubscriptionListViewReducer");
7
8
  /**
8
9
  * Fetch unless the endpoint is already loaded or in flight — or always when the
@@ -20,8 +21,20 @@ const fetchInvoicingSubscriptionListPageEpic = (actions$, state$) => actions$.pi
20
21
  const { cacheOverride, filters, sort } = action.payload;
21
22
  const state = state$.value.invoicingSubscriptionListViewState;
22
23
  const pageActions = [];
23
- if (shouldFetch({ fetchState: state.fetchState, error: state.error }, cacheOverride)) {
24
- pageActions.push((0, invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionList)({ 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, invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionList)({ 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, invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionList)({
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, invoicingSubscriptionListViewReducer_1.fetchInvoicingSubscriptionCounts)());
@@ -10,11 +10,14 @@ export declare const fetchInvoicingSubscriptionList: import("@reduxjs/toolkit").
10
10
  filters?: InvoicingSubscriptionFilters;
11
11
  keepExistingListItems?: boolean;
12
12
  sort?: InvoicingListSort;
13
+ /** The tab cache to fill; defaults to the active tab's. */
14
+ tabId?: string;
13
15
  }], {
14
16
  filters: InvoicingSubscriptionFilters;
15
17
  cursor: string | undefined;
16
18
  keepExistingListItems: boolean;
17
19
  sort: InvoicingListSort | undefined;
20
+ tabId: string | undefined;
18
21
  }, "invoicingSubscriptionListView/fetchInvoicingSubscriptionList", never, never>, fetchInvoicingSubscriptionListPage: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
19
22
  cacheOverride?: boolean;
20
23
  filters?: InvoicingSubscriptionFilters;
@@ -27,7 +30,11 @@ export declare const fetchInvoicingSubscriptionList: import("@reduxjs/toolkit").
27
30
  ids: ID[];
28
31
  keepExistingListItems: boolean;
29
32
  nextCursor: string | null;
30
- }, "invoicingSubscriptionListView/updateInvoicingSubscriptionList">, updateInvoicingSubscriptionListFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingSubscriptionListView/updateInvoicingSubscriptionListFailure">, fetchInvoicingSubscriptionCounts: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingSubscriptionListView/fetchInvoicingSubscriptionCounts">, updateInvoicingSubscriptionCounts: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingListCounts, "invoicingSubscriptionListView/updateInvoicingSubscriptionCounts">, updateInvoicingSubscriptionCountsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingSubscriptionListView/updateInvoicingSubscriptionCountsFailure">, updateInvoicingSubscriptionFilters: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingSubscriptionFilters, "invoicingSubscriptionListView/updateInvoicingSubscriptionFilters">, setInvoicingSubscriptionActiveTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<"paused" | "active" | "cancelled" | "future" | "in_trial" | "non_renewing" | "all", "invoicingSubscriptionListView/setInvoicingSubscriptionActiveTab">, addInvoicingSubscriptionToList: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
33
+ tabId: string;
34
+ }, "invoicingSubscriptionListView/updateInvoicingSubscriptionList">, updateInvoicingSubscriptionListFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
35
+ status: ZeniAPIStatus;
36
+ tabId: string;
37
+ }, "invoicingSubscriptionListView/updateInvoicingSubscriptionListFailure">, fetchInvoicingSubscriptionCounts: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingSubscriptionListView/fetchInvoicingSubscriptionCounts">, updateInvoicingSubscriptionCounts: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingListCounts, "invoicingSubscriptionListView/updateInvoicingSubscriptionCounts">, updateInvoicingSubscriptionCountsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingSubscriptionListView/updateInvoicingSubscriptionCountsFailure">, updateInvoicingSubscriptionFilters: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingSubscriptionFilters, "invoicingSubscriptionListView/updateInvoicingSubscriptionFilters">, setInvoicingSubscriptionActiveTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<"paused" | "active" | "cancelled" | "future" | "in_trial" | "non_renewing" | "all", "invoicingSubscriptionListView/setInvoicingSubscriptionActiveTab">, addInvoicingSubscriptionToList: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
31
38
  id: ID;
32
39
  status?: InvoicingSubscriptionStatus;
33
40
  }, "invoicingSubscriptionListView/addInvoicingSubscriptionToList">;
@@ -4,18 +4,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.addInvoicingSubscriptionToList = exports.setInvoicingSubscriptionActiveTab = exports.updateInvoicingSubscriptionFilters = exports.updateInvoicingSubscriptionCountsFailure = exports.updateInvoicingSubscriptionCounts = exports.fetchInvoicingSubscriptionCounts = exports.updateInvoicingSubscriptionListFailure = exports.updateInvoicingSubscriptionList = exports.fetchInvoicingSubscriptionListPage = exports.fetchInvoicingSubscriptionList = 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 invoicingSubscriptionListView = (0, toolkit_1.createSlice)({
21
16
  name: 'invoicingSubscriptionListView',
@@ -23,14 +18,9 @@ const invoicingSubscriptionListView = (0, toolkit_1.createSlice)({
23
18
  reducers: {
24
19
  fetchInvoicingSubscriptionList: {
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 invoicingSubscriptionListView = (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
  fetchInvoicingSubscriptionListPage: {
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 invoicingSubscriptionListView = (0, toolkit_1.createSlice)({
59
54
  },
60
55
  },
61
56
  updateInvoicingSubscriptionList(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
  updateInvoicingSubscriptionListFailure(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
  fetchInvoicingSubscriptionCounts(draft) {
74
63
  draft.countsFetchState.fetchState = 'In-Progress';
@@ -86,8 +75,8 @@ const invoicingSubscriptionListView = (0, toolkit_1.createSlice)({
86
75
  updateInvoicingSubscriptionFilters(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
  setInvoicingSubscriptionActiveTab(draft, action) {
92
81
  draft.activeTab = action.payload;
93
82
  },
@@ -96,10 +85,9 @@ const invoicingSubscriptionListView = (0, toolkit_1.createSlice)({
96
85
  // doubles as the per-tab count key (tab ids mirror InvoicingSubscriptionStatus).
97
86
  addInvoicingSubscriptionToList(draft, action) {
98
87
  const { id, status } = action.payload;
99
- if (draft.ids.includes(id)) {
88
+ if (!(0, invoicingListTabCache_1.addToInvoicingListTabs)(draft.byTab, id, status)) {
100
89
  return;
101
90
  }
102
- draft.ids = [id, ...draft.ids];
103
91
  draft.counts.all += 1;
104
92
  if (status != null) {
105
93
  draft.counts[status] = (draft.counts[status] ?? 0) + 1;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInvoicingSubscriptionListView = void 0;
4
4
  const toolkit_1 = require("@reduxjs/toolkit");
5
5
  const invoicingSubscriptionSelector_1 = require("../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionSelector");
6
+ const invoicingListTabCache_1 = require("../invoicingListTabCache");
6
7
  const invoicingTabHelper_1 = require("../invoicingTabHelper");
7
8
  const runningInvoicingActionId_1 = require("../runningInvoicingActionId");
8
9
  const invoicingSubscriptionListViewState_1 = require("./invoicingSubscriptionListViewState");
@@ -15,20 +16,16 @@ const invoicingSubscriptionListViewState_1 = require("./invoicingSubscriptionLis
15
16
  */
16
17
  exports.getInvoicingSubscriptionListView = (0, toolkit_1.createSelector)((state) => state.invoicingSubscriptionState, (state) => state.invoicingSubscriptionListViewState, (state) => state.invoicingConfigViewState.subscriptionStatusOptions, (state) => state.invoicingConfigViewState, (state) => state.editInvoicingSubscriptionDetailViewState.actionStateById, (subscriptionState, listViewState, statusOptions, configState, actionStateById) => {
17
18
  const { activeTab } = listViewState;
18
- const allSubscriptions = (0, invoicingSubscriptionSelector_1.getInvoicingSubscriptionsByIds)(subscriptionState, listViewState.ids);
19
- // The list API ignores `status`, so it returns every status; filter to the
20
- // active tab client-side ('all' shows everything).
21
- const subscriptions = activeTab === 'all'
22
- ? allSubscriptions
23
- : allSubscriptions.filter((subscription) => subscription.status === activeTab);
19
+ const tab = (0, invoicingListTabCache_1.getInvoicingListTab)(listViewState.byTab, (0, invoicingListTabCache_1.invoicingListSourceTab)(activeTab));
20
+ const subscriptions = (0, invoicingSubscriptionSelector_1.getInvoicingSubscriptionsByIds)(subscriptionState, tab.ids);
24
21
  return {
25
22
  runningActionId: (0, runningInvoicingActionId_1.runningInvoicingActionId)(actionStateById),
26
23
  activeTab,
27
24
  columns: invoicingSubscriptionListViewState_1.INVOICING_SUBSCRIPTION_COLUMNS,
28
25
  subscriptions,
29
- fetchState: listViewState.fetchState,
30
- error: listViewState.error,
31
- nextCursor: listViewState.nextCursor,
26
+ fetchState: tab.fetchState,
27
+ error: tab.error,
28
+ nextCursor: tab.nextCursor,
32
29
  filters: listViewState.filters,
33
30
  count: listViewState.counts,
34
31
  countsFetchState: listViewState.countsFetchState,
@@ -1,6 +1,7 @@
1
- import { FetchStateAndError, FetchedState, ID } from '../../../commonStateTypes/common';
1
+ import { FetchStateAndError, ID } 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 InvoicingSubscriptionFilters {
5
6
  customerId?: ID;
6
7
  search?: string;
@@ -25,15 +26,14 @@ export declare const INVOICING_SUBSCRIPTION_COLUMNS: InvoicingSubscriptionColumn
25
26
  export declare const ALL_INVOICING_SUBSCRIPTION_TAB_IDS: readonly ["all", "active", "in_trial", "future", "non_renewing", "paused", "cancelled"];
26
27
  export declare const toInvoicingSubscriptionTabId: (v: string) => "paused" | "active" | "cancelled" | "future" | "in_trial" | "non_renewing" | "all";
27
28
  export type InvoicingSubscriptionTabId = ReturnType<typeof toInvoicingSubscriptionTabId>;
28
- export interface InvoicingSubscriptionListViewState extends FetchedState {
29
+ export interface InvoicingSubscriptionListViewState {
29
30
  /** Selected status tab (CES-owned so it persists across page revisits). */
30
31
  activeTab: InvoicingSubscriptionTabId;
32
+ /** Per-tab rows, cursor and fetch state; each tab is its own `?status=` query. */
33
+ byTab: InvoicingListByTab;
31
34
  counts: InvoicingListCounts;
32
35
  countsFetchState: FetchStateAndError;
33
36
  filters: InvoicingSubscriptionFilters;
34
- /** Full list ids (all statuses); the selector filters by `activeTab`. */
35
- ids: ID[];
36
- nextCursor: string | null;
37
37
  /** Active server-side sort (undefined = backend default order). */
38
38
  sort?: InvoicingListSort;
39
39
  }
@@ -6,6 +6,6 @@ import { updateTasks } from '../../../../entity/task/taskReducer';
6
6
  import { RootState } from '../../../../rootStateTypes';
7
7
  import { ZeniAPI } from '../../../../zeniAPI';
8
8
  import { fetchFileList } from '../../../fileView/fileViewReducer';
9
- import { fetchTaskDetail, initializeTaskToLocalStore, removeTaskDetail, updateEditTaskFetchStatus } from '../taskDetailReducer';
10
- export type ActionType = ReturnType<typeof fetchTaskDetail> | ReturnType<typeof updateTags> | ReturnType<typeof updateEditTaskFetchStatus> | ReturnType<typeof removeTaskDetail> | ReturnType<typeof updateTasks> | ReturnType<typeof initializeTaskToLocalStore> | ReturnType<typeof fetchFileList> | ReturnType<typeof openSnackbar>;
9
+ import { fetchTaskDetail, initializeTaskToLocalStore, removeTaskDetail, saveTaskUpdatesToLocalStore, updateEditTaskFetchStatus } from '../taskDetailReducer';
10
+ export type ActionType = ReturnType<typeof fetchTaskDetail> | ReturnType<typeof updateTags> | ReturnType<typeof updateEditTaskFetchStatus> | ReturnType<typeof removeTaskDetail> | ReturnType<typeof updateTasks> | ReturnType<typeof initializeTaskToLocalStore> | ReturnType<typeof saveTaskUpdatesToLocalStore> | ReturnType<typeof fetchFileList> | ReturnType<typeof openSnackbar>;
11
11
  export declare const fetchTaskDetailEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;