@zeniai/client-epic-state 4.19.37-betaVR8 → 4.19.37

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 (50) hide show
  1. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  2. package/lib/entity/snackbar/snackbarTypes.js +0 -1
  3. package/lib/epic.d.ts +1 -9
  4. package/lib/epic.js +1 -9
  5. package/lib/esm/entity/snackbar/snackbarTypes.js +0 -1
  6. package/lib/esm/epic.js +1 -9
  7. package/lib/esm/index.js +2 -4
  8. package/lib/esm/view/expenseAutomationView/payload/missingReceiptsPayload.js +1 -100
  9. package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +1 -264
  10. package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +1 -128
  11. package/lib/esm/zeniAPI.js +3 -41
  12. package/lib/index.d.ts +5 -7
  13. package/lib/index.js +30 -58
  14. package/lib/tsconfig.typecheck.tsbuildinfo +1 -0
  15. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  16. package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.d.ts +0 -108
  17. package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.js +0 -107
  18. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +3 -51
  19. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +2 -265
  20. package/lib/view/expenseAutomationView/selectorTypes/missingReceiptsSelectorTypes.d.ts +1 -61
  21. package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.d.ts +1 -1
  22. package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +0 -127
  23. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +0 -104
  24. package/lib/zeniAPI.d.ts +0 -9
  25. package/lib/zeniAPI.js +2 -40
  26. package/package.json +2 -2
  27. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +0 -24
  28. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/confirmBulkUploadMatchEpic.js +0 -49
  29. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +0 -31
  30. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +0 -41
  31. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +0 -57
  32. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +0 -35
  33. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +0 -27
  34. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +0 -41
  35. package/lib/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.d.ts +0 -15
  36. package/lib/view/expenseAutomationView/epics/missingReceipts/bulkUploadReceiptsEpic.js +0 -28
  37. package/lib/view/expenseAutomationView/epics/missingReceipts/confirmBulkUploadMatchEpic.d.ts +0 -7
  38. package/lib/view/expenseAutomationView/epics/missingReceipts/confirmBulkUploadMatchEpic.js +0 -53
  39. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.d.ts +0 -8
  40. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +0 -35
  41. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.d.ts +0 -7
  42. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +0 -45
  43. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.d.ts +0 -8
  44. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +0 -61
  45. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.d.ts +0 -8
  46. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +0 -39
  47. package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.d.ts +0 -6
  48. package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +0 -31
  49. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +0 -15
  50. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +0 -46
@@ -1,68 +1,8 @@
1
1
  import { CompletionStatusType, FetchStateAndError, ID } from '../../../commonStateTypes/common';
2
2
  import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
3
3
  import { SupportedTransaction } from '../../../entity/transaction/transactionState';
4
- import { SortOrder } from '../../../commonStateTypes/selectorTypes/sortOrderTypes';
5
- import type { BatchFileStatus, BatchListItem, BatchStatus, BulkUploadPhase, BulkUploadResultsTab, BulkUploadSortKey, CompletedSubTab, ManualSearchState, MatchSource, MissingReceiptsViewUIState } from '../types/missingReceiptsViewState';
6
- export interface CompletedTransactionsSelectorData {
7
- fetchState: FetchStateAndError;
8
- nextPageToken: string | null;
9
- totalCount: number;
10
- transactions: SupportedTransaction[];
11
- }
12
- export interface ResolvedCandidate {
13
- matchScore: number;
14
- transaction: SupportedTransaction;
15
- }
16
- export interface ResolvedBatchFile {
17
- attachmentId: ID;
18
- fileId: ID;
19
- filename: string;
20
- filePreviewUrl: string | null;
21
- status: BatchFileStatus;
22
- candidates?: ResolvedCandidate[];
23
- matchedTransaction?: SupportedTransaction;
24
- matchSource?: MatchSource;
25
- }
26
- export interface BulkUploadSelectorData {
27
- batchDetails: ResolvedBatchDetails | undefined;
28
- batchList: BatchListItem[];
29
- batchListFetchState: FetchStateAndError;
30
- batchStatus: BatchStatus | undefined;
31
- completedSubTab: CompletedSubTab;
32
- completedTransactions: CompletedTransactionsSelectorData;
33
- confirmMatchStatus: FetchStateAndError;
34
- currentResultsTab: BulkUploadResultsTab;
35
- manualSearch: ManualSearchState;
36
- matchedFiles: ResolvedBatchFile[];
37
- pastBatches: BatchListItem[];
38
- pastUnmatchedFiles: ResolvedBatchFile[];
39
- phase: BulkUploadPhase;
40
- progress: {
41
- percentage: number;
42
- processed: number;
43
- total: number;
44
- };
45
- sortKey: BulkUploadSortKey;
46
- sortOrder: SortOrder;
47
- unmatchedFiles: ResolvedBatchFile[];
48
- uploadProgress: number;
49
- uploadStatus: FetchStateAndError;
50
- }
51
- export interface ResolvedBatchDetails {
52
- batchId: ID;
53
- createdAt: string;
54
- files: ResolvedBatchFile[];
55
- status: string;
56
- summary: {
57
- failed: number;
58
- matched: number;
59
- noMatch: number;
60
- possibleMatches: number;
61
- total: number;
62
- };
63
- }
4
+ import { MissingReceiptsViewUIState } from '../types/missingReceiptsViewState';
64
5
  export interface ExpenseAutomationMissingReceiptsViewSelector extends SelectorView {
65
- bulkUpload: BulkUploadSelectorData;
66
6
  completionStatus: CompletionStatusType;
67
7
  refreshStatus: FetchStateAndError;
68
8
  transactions: SupportedTransaction[];
@@ -1,3 +1,3 @@
1
1
  import { RootState } from '../../../reducer';
2
- import type { ExpenseAutomationMissingReceiptsViewSelector } from '../selectorTypes/missingReceiptsSelectorTypes';
2
+ import { ExpenseAutomationMissingReceiptsViewSelector } from '../selectorTypes/missingReceiptsSelectorTypes';
3
3
  export declare function getExpenseAutomationMissingReceiptsView(state: RootState): ExpenseAutomationMissingReceiptsViewSelector;
@@ -53,79 +53,6 @@ function getExpenseAutomationMissingReceiptsView(state) {
53
53
  const completionStatus = missingReceiptsCompletionStatus != null
54
54
  ? missingReceiptsCompletionStatus
55
55
  : 'incomplete';
56
- const { bulkUpload } = expenseAutomationMissingReceiptsViewState;
57
- const currentBatchStatus = bulkUpload.currentBatchId != null
58
- ? bulkUpload.batchStatusById[bulkUpload.currentBatchId]
59
- : undefined;
60
- const currentBatchDetails = bulkUpload.currentBatchId != null
61
- ? bulkUpload.batchDetailsById[bulkUpload.currentBatchId]
62
- : undefined;
63
- const resolvedFiles = currentBatchDetails?.files.map((file) => resolveBatchFile(file, transactionState));
64
- const getSortValue = (file) => {
65
- const t = file.matchedTransaction;
66
- if (t == null) {
67
- return null;
68
- }
69
- switch (bulkUpload.sortKey) {
70
- case 'vendor':
71
- return (t.vendorName ?? t.description)?.toLowerCase() ?? null;
72
- case 'category': {
73
- const line = t.lines?.[0];
74
- return line?.account?.accountName?.toLowerCase() ?? null;
75
- }
76
- case 'class': {
77
- const line = t.lines?.[0];
78
- return line?.class?.className?.toLowerCase() ?? null;
79
- }
80
- case 'date':
81
- return t.date.valueOf();
82
- case 'amount':
83
- return t.amount.amount;
84
- default:
85
- return null;
86
- }
87
- };
88
- const bulkUploadSortDirection = bulkUpload.sortOrder === 'ascending' ? 'asc' : 'desc';
89
- const matchedFiles = (0, orderBy_1.default)(resolvedFiles?.filter((f) => f.status === 'matched') ?? [], getSortValue, bulkUploadSortDirection);
90
- const unmatchedFiles = (0, orderBy_1.default)(resolvedFiles?.filter((f) => f.status === 'un_matched' || f.status === 'no_match') ?? [], getSortValue, bulkUploadSortDirection);
91
- const progress = currentBatchStatus != null
92
- ? {
93
- ...currentBatchStatus.progress,
94
- percentage: currentBatchStatus.progress.total > 0
95
- ? Math.round((currentBatchStatus.progress.processed /
96
- currentBatchStatus.progress.total) *
97
- 100)
98
- : 0,
99
- }
100
- : { total: 0, processed: 0, percentage: 0 };
101
- const batchList = monthYearPeriodId != null
102
- ? bulkUpload.batchListByPeriod[monthYearPeriodId] ?? []
103
- : [];
104
- const batchListFetchState = bulkUpload.batchListFetchState;
105
- const pastBatches = batchList.filter((b) => b.batchId !== bulkUpload.currentBatchId);
106
- const pastUnmatchedFiles = pastBatches.flatMap((b) => {
107
- const details = bulkUpload.batchDetailsById[b.batchId];
108
- if (details == null) {
109
- return [];
110
- }
111
- return details.files
112
- .filter((f) => f.status === 'un_matched' || f.status === 'no_match')
113
- .map((f) => resolveBatchFile(f, transactionState));
114
- });
115
- const completedTransactionsForPeriod = monthYearPeriodId != null
116
- ? bulkUpload.completedTransactionsByPeriod[monthYearPeriodId]
117
- : undefined;
118
- const completedTransactionIds = completedTransactionsForPeriod?.transactionIds ?? [];
119
- const resolvedCompletedTransactions = (0, transactionSelector_1.getSupportedTransactionsByIds)(transactionState, completedTransactionIds);
120
- const resolvedBatchDetails = currentBatchDetails != null && resolvedFiles != null
121
- ? {
122
- batchId: currentBatchDetails.batchId,
123
- createdAt: currentBatchDetails.createdAt,
124
- files: resolvedFiles,
125
- status: currentBatchDetails.status,
126
- summary: currentBatchDetails.summary,
127
- }
128
- : undefined;
129
56
  return {
130
57
  fetchState,
131
58
  error,
@@ -134,59 +61,5 @@ function getExpenseAutomationMissingReceiptsView(state) {
134
61
  refreshStatus,
135
62
  transactions: sortedTransactions,
136
63
  completionStatus,
137
- bulkUpload: {
138
- phase: bulkUpload.phase,
139
- uploadStatus: bulkUpload.uploadStatus,
140
- batchStatus: currentBatchStatus,
141
- batchDetails: resolvedBatchDetails,
142
- completedSubTab: bulkUpload.completedSubTab,
143
- completedTransactions: {
144
- fetchState: completedTransactionsForPeriod?.fetchState ?? {
145
- fetchState: 'Not-Started',
146
- error: undefined,
147
- },
148
- nextPageToken: completedTransactionsForPeriod?.nextPageToken ?? null,
149
- totalCount: completedTransactionsForPeriod?.totalCount ?? 0,
150
- transactions: resolvedCompletedTransactions,
151
- },
152
- matchedFiles,
153
- unmatchedFiles,
154
- progress,
155
- currentResultsTab: bulkUpload.currentResultsTab,
156
- sortKey: bulkUpload.sortKey,
157
- sortOrder: bulkUpload.sortOrder,
158
- batchList,
159
- batchListFetchState,
160
- pastBatches,
161
- pastUnmatchedFiles,
162
- confirmMatchStatus: bulkUpload.confirmMatchStatus,
163
- manualSearch: bulkUpload.manualSearch,
164
- uploadProgress: bulkUpload.uploadProgress,
165
- },
166
- };
167
- }
168
- function resolveBatchFile(file, transactionState) {
169
- const matchedTransaction = file.matchedTransactionId != null
170
- ? (0, transactionSelector_1.getSupportedTransactionById)(transactionState, file.matchedTransactionId)
171
- : undefined;
172
- const candidates = file.candidates
173
- ?.map((ref) => {
174
- const transaction = (0, transactionSelector_1.getSupportedTransactionById)(transactionState, ref.transactionId);
175
- return transaction != null
176
- ? { transaction, matchScore: ref.matchScore }
177
- : undefined;
178
- })
179
- .filter((c) => c != null);
180
- return {
181
- attachmentId: file.attachmentId,
182
- fileId: file.fileId,
183
- filename: file.filename,
184
- filePreviewUrl: file.filePreviewUrl,
185
- status: file.status,
186
- matchedTransaction,
187
- candidates: candidates != null && candidates.length > 0
188
- ? candidates
189
- : undefined,
190
- matchSource: file.matchSource,
191
64
  };
192
65
  }
@@ -3,7 +3,6 @@ import { SortOrder } from '../../../commonStateTypes/selectorTypes/sortOrderType
3
3
  import { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
4
4
  export declare const toMissingReceiptsSortKey: (v: string) => "date" | "amount" | "vendor" | "category" | "class";
5
5
  export type MissingReceiptsSortKey = ReturnType<typeof toMissingReceiptsSortKey>;
6
- export type BulkUploadSortKey = 'amount' | 'category' | 'class' | 'date' | 'vendor';
7
6
  export interface MissingReceiptsViewUIState {
8
7
  scrollPosition: {
9
8
  scrollTop: number;
@@ -13,110 +12,7 @@ export interface MissingReceiptsViewUIState {
13
12
  sortKey: MissingReceiptsSortKey;
14
13
  sortOrder: SortOrder;
15
14
  }
16
- export type BatchStatusValue = 'pending' | 'processing' | 'completed';
17
- export type BatchFileStatus = 'matched' | 'un_matched' | 'no_match' | 'failed';
18
- export type BulkUploadPhase = 'idle' | 'uploading' | 'matching' | 'completed';
19
- export type BulkUploadResultsTab = 'completed' | 'unmatched';
20
- export type MissingReceiptsTab = 'missing' | BulkUploadResultsTab;
21
- export type CompletedSubTab = 'all' | 'ai_accountant' | 'manual';
22
- export type MatchSource = 'ai' | 'manual';
23
- export interface CandidateRef {
24
- matchScore: number;
25
- transactionId: ID;
26
- }
27
- export interface MatchCandidate {
28
- amount: number;
29
- currencyCode: string;
30
- matchScore: number;
31
- transactionDate: string;
32
- transactionId: ID;
33
- transactionType: string;
34
- vendorName: string;
35
- vendorLogo?: string;
36
- }
37
- export interface BatchFile {
38
- attachmentId: ID;
39
- fileId: ID;
40
- filename: string;
41
- filePreviewUrl: string | null;
42
- status: BatchFileStatus;
43
- candidates?: CandidateRef[];
44
- matchedTransactionId?: ID;
45
- matchSource?: MatchSource;
46
- }
47
- export interface BatchSummary {
48
- failed: number;
49
- matched: number;
50
- noMatch: number;
51
- possibleMatches: number;
52
- total: number;
53
- }
54
- export interface BatchStatus {
55
- batchId: ID;
56
- progress: {
57
- processed: number;
58
- total: number;
59
- };
60
- status: BatchStatusValue;
61
- }
62
- export interface BatchDetails {
63
- batchId: ID;
64
- createdAt: string;
65
- files: BatchFile[];
66
- status: BatchStatusValue;
67
- summary: BatchSummary;
68
- }
69
- export interface BatchListItem {
70
- batchId: ID;
71
- createdAt: string;
72
- failedCount: number;
73
- matchedCount: number;
74
- noMatchCount: number;
75
- possibleMatchesCount: number;
76
- status: string;
77
- totalFiles: number;
78
- }
79
- export interface ManualSearchResult {
80
- amount: number;
81
- currencyCode: string;
82
- entityId: string;
83
- memo: string;
84
- transactionDate: string;
85
- transactionId: ID;
86
- transactionType: string;
87
- vendorName: string;
88
- }
89
- export interface ManualSearchState {
90
- fetchState: FetchStateAndError;
91
- results: ManualSearchResult[];
92
- searchQuery: string;
93
- }
94
- export type CompletedTransactionsMatchType = 'all' | 'ai_accountant' | 'manual';
95
- export interface CompletedTransactionsState {
96
- fetchState: FetchStateAndError;
97
- nextPageToken: string | null;
98
- totalCount: number;
99
- transactionIds: ID[];
100
- }
101
- export interface BulkUploadState {
102
- batchDetailsById: Record<ID, BatchDetails>;
103
- batchListByPeriod: Record<MonthYearPeriodId, BatchListItem[]>;
104
- batchListFetchState: FetchStateAndError;
105
- batchStatusById: Record<ID, BatchStatus>;
106
- completedSubTab: CompletedSubTab;
107
- completedTransactionsByPeriod: Record<MonthYearPeriodId, CompletedTransactionsState>;
108
- confirmMatchStatus: FetchStateAndError;
109
- currentResultsTab: BulkUploadResultsTab;
110
- manualSearch: ManualSearchState;
111
- phase: BulkUploadPhase;
112
- sortKey: BulkUploadSortKey;
113
- sortOrder: SortOrder;
114
- uploadProgress: number;
115
- uploadStatus: FetchStateAndError;
116
- currentBatchId?: ID;
117
- }
118
15
  export interface MissingReceiptsViewState extends FetchedState {
119
- bulkUpload: BulkUploadState;
120
16
  refreshStatus: FetchStateAndError;
121
17
  transactionIdsBySelectedPeriod: Record<MonthYearPeriodId, ID[]>;
122
18
  uiState: MissingReceiptsViewUIState;
package/lib/zeniAPI.d.ts CHANGED
@@ -1,12 +1,5 @@
1
1
  import { fetch } from 'cross-fetch';
2
2
  import { Observable } from 'rxjs';
3
- export type FormDataUploadEvent<T> = {
4
- percentage: number;
5
- type: 'progress';
6
- } | {
7
- data: T;
8
- type: 'response';
9
- };
10
3
  type ThenArgRecursive<T> = T extends PromiseLike<infer U> ? ThenArgRecursive<U> : T;
11
4
  export type FetchResponse = ThenArgRecursive<ReturnType<typeof fetch>>;
12
5
  export interface RESTAPIEndpoints {
@@ -41,7 +34,6 @@ export interface ZeniAPI<ResponseType = FetchResponse> {
41
34
  patchAndGetJSON<T>(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<T>;
42
35
  postAndGetJSON<T>(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<T>;
43
36
  postFormData<T>(restEndPoint: string, formData: FormData, signal?: AbortSignal): Observable<T>;
44
- postFormDataWithProgress<T>(restEndPoint: string, formData: FormData, signal?: AbortSignal): Observable<FormDataUploadEvent<T>>;
45
37
  postJSON(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<ResponseType>;
46
38
  putAndGetJSON<T>(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<T>;
47
39
  update(userId?: string, sessionId?: string, tenantId?: string): void;
@@ -69,7 +61,6 @@ export declare class ZeniAPIClient implements ZeniAPI {
69
61
  postJSON(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<FetchResponse>;
70
62
  postAndGetJSON<T>(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<T>;
71
63
  postFormData<T>(restEndPoint: string, formData: FormData, signal?: AbortSignal): Observable<T>;
72
- postFormDataWithProgress<T>(restEndPoint: string, formData: FormData, signal?: AbortSignal): Observable<FormDataUploadEvent<T>>;
73
64
  deleteAndGetJSON<T>(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<T>;
74
65
  putAndGetJSON<T>(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<T>;
75
66
  patchAndGetJSON<T>(restEndPoint: string, body?: Record<string, unknown>, headers?: Record<string, unknown>, signal?: AbortSignal): Observable<T>;
package/lib/zeniAPI.js CHANGED
@@ -82,6 +82,8 @@ class ZeniAPIClient {
82
82
  return (0, rxjs_1.from)(promise);
83
83
  }
84
84
  postFormData(restEndPoint, formData, signal) {
85
+ // Use apiHeaders for auth headers, then remove Content-Type
86
+ // so the browser sets multipart/form-data with the correct boundary
85
87
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
86
88
  const { 'Content-Type': _contentType, ...headers } = this.apiHeaders();
87
89
  const promise = (0, cross_fetch_1.fetch)(restEndPoint, {
@@ -92,46 +94,6 @@ class ZeniAPIClient {
92
94
  }).then((response) => this.processJsonResponse(response));
93
95
  return (0, rxjs_1.from)(promise);
94
96
  }
95
- postFormDataWithProgress(restEndPoint, formData, signal) {
96
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
97
- const { 'Content-Type': _ct, ...headers } = this.apiHeaders();
98
- return new rxjs_1.Observable((subscriber) => {
99
- const xhr = new XMLHttpRequest();
100
- xhr.upload.onprogress = (event) => {
101
- if (event.lengthComputable) {
102
- const percentage = Math.round((event.loaded / event.total) * 100);
103
- subscriber.next({ type: 'progress', percentage });
104
- }
105
- };
106
- xhr.onload = () => {
107
- try {
108
- const json = JSON.parse(xhr.responseText);
109
- this.checkSessionValidity(json);
110
- subscriber.next({ type: 'response', data: json });
111
- subscriber.complete();
112
- }
113
- catch (e) {
114
- subscriber.error(e);
115
- }
116
- };
117
- xhr.onerror = () => {
118
- subscriber.error(new Error('Upload failed'));
119
- };
120
- xhr.open('POST', restEndPoint);
121
- Object.entries(headers).forEach(([key, value]) => {
122
- xhr.setRequestHeader(key, String(value));
123
- });
124
- xhr.send(formData);
125
- if (signal != null) {
126
- signal.addEventListener('abort', () => xhr.abort());
127
- }
128
- return () => {
129
- if (xhr.readyState !== XMLHttpRequest.DONE) {
130
- xhr.abort();
131
- }
132
- };
133
- });
134
- }
135
97
  deleteAndGetJSON(restEndPoint, body, headers, signal) {
136
98
  let apiHeaders = this.apiHeaders(headers);
137
99
  if (body != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "4.19.37-betaVR8",
3
+ "version": "4.19.37",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",
@@ -111,7 +111,7 @@
111
111
  "find-dead-code": "ts-prune | grep -v '(used in module)'",
112
112
  "find-unused-exports": "ts-unused-exports ./tsconfig.json",
113
113
  "circular-dependency": "npx madge --circular --extensions ts ./src",
114
- "build": "concurrently --kill-others-on-fail --handle-input \"echo 'Running ESLint...' && eslint . --ext .js,.jsx,.ts,.tsx\" \"echo 'TypeScript build in progress...' && time tsc && echo 'ESM build...' && tsc -p tsconfig.esm.json\"",
114
+ "build": "concurrently --kill-others-on-fail --handle-input \"echo 'Running ESLint...' && eslint . --ext .js,.jsx,.ts,.tsx\" \"echo 'TypeScript build in progress...' && time tsc && echo 'ESM build...' && tsc -p tsconfig.esm.json\" \"echo 'Running tests and typecheck...' && pnpm test\" && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
115
115
  "only-build": "eslint . --ext .js,.jsx,.ts,.tsx && time tsc && tsc -p tsconfig.esm.json && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
116
116
  "format": "prettier --write --ignore-unknown \"src/**/*\" && pnpm lint",
117
117
  "format-watch": "(git diff --name-only --diff-filter=ACM && git ls-files --others --exclude-standard) | grep -E '\\.(ts|tsx)$' | xargs prettier --write",
@@ -1,24 +0,0 @@
1
- import { of } from 'rxjs';
2
- import { catchError, filter, mergeMap } from 'rxjs/operators';
3
- import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
- import { bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, } from '../../reducers/missingReceiptsViewReducer';
5
- export const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceipts.match), mergeMap((action) => {
6
- const { files } = action.payload;
7
- const formData = new FormData();
8
- for (const file of files) {
9
- formData.append('files', file, file.name);
10
- }
11
- return zeniAPI
12
- .postFormData(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/receipts/bulk-upload`, formData)
13
- .pipe(mergeMap((response) => {
14
- if (isSuccessResponse(response) && response.data != null) {
15
- return of(bulkUploadReceiptsSuccess({
16
- batchId: response.data.batch_id,
17
- }));
18
- }
19
- return of(bulkUploadReceiptsFailure({ error: response.status }));
20
- }), catchError((error) => of(bulkUploadReceiptsFailure({
21
- error: createZeniAPIStatus('Unexpected Error', 'Bulk upload receipts API call errored out: ' +
22
- JSON.stringify(error)),
23
- }))));
24
- }));
@@ -1,49 +0,0 @@
1
- import { from } from 'rxjs';
2
- import { catchError, filter, mergeMap } from 'rxjs/operators';
3
- import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
4
- import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
5
- import { confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, } from '../../reducers/missingReceiptsViewReducer';
6
- export const confirmBulkUploadMatchEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(confirmBulkUploadMatch.match), mergeMap((action) => {
7
- const { batchId, attachmentId, transactionId, transactionType, fileName } = action.payload;
8
- return zeniAPI
9
- .postAndGetJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/receipts/manual-match`, {
10
- attachment_id: attachmentId,
11
- transaction_id: transactionId,
12
- transaction_type: transactionType,
13
- file_name: fileName,
14
- })
15
- .pipe(mergeMap((response) => {
16
- if (isSuccessResponse(response)) {
17
- return from([
18
- confirmBulkUploadMatchSuccess({
19
- batchId,
20
- attachmentId,
21
- transactionId,
22
- }),
23
- openSnackbar({
24
- messageSection: 'receipt_match',
25
- messageText: 'success',
26
- type: 'success',
27
- }),
28
- ]);
29
- }
30
- return from([
31
- confirmBulkUploadMatchFailure({ error: response.status }),
32
- openSnackbar({
33
- messageSection: 'receipt_match',
34
- messageText: 'failed',
35
- type: 'error',
36
- }),
37
- ]);
38
- }), catchError((error) => from([
39
- confirmBulkUploadMatchFailure({
40
- error: createZeniAPIStatus('Unexpected Error', 'Confirm bulk upload match errored out: ' +
41
- JSON.stringify(error)),
42
- }),
43
- openSnackbar({
44
- messageSection: 'receipt_match',
45
- messageText: 'failed',
46
- type: 'error',
47
- }),
48
- ])));
49
- }));
@@ -1,31 +0,0 @@
1
- import { from, of } from 'rxjs';
2
- import { catchError, filter, mergeMap } from 'rxjs/operators';
3
- import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
4
- import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
5
- import { extractTransactionPayloadsFromBatchFiles, toBatchDetails, } from '../../payload/missingReceiptsPayload';
6
- import { fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, } from '../../reducers/missingReceiptsViewReducer';
7
- export const fetchBulkUploadBatchDetailsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchBulkUploadBatchDetails.match), mergeMap(() => {
8
- const { currentBatchId } = state$.value.expenseAutomationMissingReceiptsViewState.bulkUpload;
9
- if (currentBatchId == null) {
10
- return of(fetchBulkUploadBatchDetailsFailure({
11
- error: createZeniAPIStatus('Unexpected Error', 'No current batch ID available'),
12
- }));
13
- }
14
- return zeniAPI
15
- .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/receipts/batches/${currentBatchId}`)
16
- .pipe(mergeMap((response) => {
17
- if (isSuccessResponse(response) && response.data != null) {
18
- const actions = [];
19
- const transactionPayloads = extractTransactionPayloadsFromBatchFiles(response.data.files);
20
- if (transactionPayloads.length > 0) {
21
- actions.push(updateTransactions(transactionPayloads, (value) => value.transaction_id));
22
- }
23
- actions.push(fetchBulkUploadBatchDetailsSuccess(toBatchDetails(response.data)));
24
- actions.push(fetchBulkUploadBatches(true));
25
- return from(actions);
26
- }
27
- return of(fetchBulkUploadBatchDetailsFailure({ error: response.status }));
28
- }), catchError((error) => of(fetchBulkUploadBatchDetailsFailure({
29
- error: createZeniAPIStatus('Unexpected Error', 'Fetch batch details errored out: ' + JSON.stringify(error)),
30
- }))));
31
- }));
@@ -1,41 +0,0 @@
1
- import { of } from 'rxjs';
2
- import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
- import { convertToPeriod, toMonthYearPeriodId, } from '../../../../commonStateTypes/timePeriod';
4
- import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
5
- import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
6
- import { toBatchListItem, } from '../../payload/missingReceiptsPayload';
7
- import { fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, } from '../../reducers/missingReceiptsViewReducer';
8
- export const fetchBulkUploadBatchesEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchBulkUploadBatches.match), switchMap((action) => {
9
- const { cacheOverride } = action.payload;
10
- const state = state$.value;
11
- const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationMissingReceiptsViewState: { bulkUpload }, } = state;
12
- const currentTenant = getCurrentTenant(state);
13
- const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
14
- const periodId = toMonthYearPeriodId(selectedPeriod);
15
- const existingBatches = bulkUpload.batchListByPeriod[periodId] ?? [];
16
- if (cacheOverride !== true && existingBatches.length > 0) {
17
- return of(fetchBulkUploadBatchesSuccess({
18
- batchList: existingBatches,
19
- selectedPeriod,
20
- }));
21
- }
22
- const period = convertToPeriod(selectedPeriod);
23
- return zeniAPI
24
- .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/receipts/batches?start_date=${period.start}&end_date=${period.end}`)
25
- .pipe(mergeMap((response) => {
26
- if (isSuccessResponse(response) && response.data != null) {
27
- return of(fetchBulkUploadBatchesSuccess({
28
- batchList: response.data.batches.map(toBatchListItem),
29
- selectedPeriod,
30
- }));
31
- }
32
- return of(fetchBulkUploadBatchesFailure({
33
- error: response.status,
34
- selectedPeriod,
35
- }));
36
- }), catchError((error) => of(fetchBulkUploadBatchesFailure({
37
- error: createZeniAPIStatus('Unexpected Error', 'Fetch bulk upload batches errored out: ' +
38
- JSON.stringify(error)),
39
- selectedPeriod,
40
- }))));
41
- }));
@@ -1,57 +0,0 @@
1
- import { from, of } from 'rxjs';
2
- import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
- import { convertToPeriod, toMonthYearPeriodId, } from '../../../../commonStateTypes/timePeriod';
4
- import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
5
- import { updateTransactions } from '../../../../entity/transaction/transactionReducer';
6
- import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
7
- import { fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, } from '../../reducers/missingReceiptsViewReducer';
8
- export const fetchCompletedTransactionsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchCompletedTransactions.match), switchMap((action) => {
9
- const state = state$.value;
10
- const { expenseAutomationViewState: { selectedPeriodByTenantId }, expenseAutomationMissingReceiptsViewState: { bulkUpload }, } = state;
11
- const currentTenant = getCurrentTenant(state);
12
- const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
13
- const periodId = toMonthYearPeriodId(selectedPeriod);
14
- const isInitialLoad = action.payload.pageToken == null;
15
- const existingData = bulkUpload.completedTransactionsByPeriod[periodId];
16
- if (isInitialLoad && existingData != null && existingData.transactionIds.length > 0) {
17
- return from([]);
18
- }
19
- const period = convertToPeriod(selectedPeriod);
20
- const queryPayload = {
21
- start_date: period.start,
22
- end_date: period.end,
23
- sort_by: bulkUpload.sortKey,
24
- sort_order: bulkUpload.sortOrder === 'ascending' ? 'asc' : 'desc',
25
- page_token: action.payload.pageToken ?? null,
26
- page_size: 25,
27
- };
28
- if (bulkUpload.completedSubTab !== 'all') {
29
- queryPayload.match_type = bulkUpload.completedSubTab;
30
- }
31
- const encodedQuery = encodeURIComponent(JSON.stringify(queryPayload));
32
- return zeniAPI
33
- .getJSON(`${zeniAPI.apiEndPoints.communicationAgentMicroServiceBaseUrl}/1.0/receipt-agent/transactions/completed?query=${encodedQuery}`)
34
- .pipe(mergeMap((response) => {
35
- if (isSuccessResponse(response) && response.data != null) {
36
- const transactionIds = response.data.transactions.map((t) => t.transaction_id);
37
- const updateActions = [];
38
- updateActions.push(updateTransactions(response.data.transactions, (value) => value.transaction_id));
39
- updateActions.push(fetchCompletedTransactionsSuccess({
40
- isInitialLoad,
41
- transactionIds,
42
- nextPageToken: response.data.next_page_token,
43
- totalCount: response.data.total_count,
44
- selectedPeriod,
45
- }));
46
- return from(updateActions);
47
- }
48
- return of(fetchCompletedTransactionsFailure({
49
- error: response.status,
50
- selectedPeriod,
51
- }));
52
- }), catchError((error) => of(fetchCompletedTransactionsFailure({
53
- error: createZeniAPIStatus('Unexpected Error', 'Fetch completed transactions errored: ' +
54
- JSON.stringify(error)),
55
- selectedPeriod,
56
- }))));
57
- }));