@zeniai/client-epic-state 5.2.58-beta0ND → 5.2.58-beta1ND

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1,3 @@
1
- export {};
1
+ // Only an override opens the feedback popup. Silent accepts and retractions post
2
+ // in the background, so they must not drive the popup's loader or its toast.
3
+ export const isPromptedRecommendationFeedback = (outcome) => outcome === 'override_outside' || outcome === 'override_ranked';
@@ -1,8 +1,9 @@
1
1
  import { createSlice } from '@reduxjs/toolkit';
2
2
  import { clearAll } from '../../rootActions';
3
- import { getEntityRecommendationKey, getRecommendationFeedbackKey, initialEntityRecommendationState, } from './recommendationState';
3
+ import { isPromptedRecommendationFeedback, } from './recommendationPayload';
4
+ import { getEntityRecommendationKey, initialEntityRecommendationState, } from './recommendationState';
4
5
  export const initialState = {
5
- feedbackSubmitStateByKey: {},
6
+ feedbackSubmitState: { fetchState: 'Not-Started', error: undefined },
6
7
  recommendationByEntity: {},
7
8
  };
8
9
  const recommendation = createSlice({
@@ -138,9 +139,10 @@ const recommendation = createSlice({
138
139
  // never waits on this: only the feedback popup reads the submit state.
139
140
  submitRecommendationFeedback: {
140
141
  reducer(draft, action) {
141
- const { transactionId, lineId, dimension } = action.payload;
142
- const key = getRecommendationFeedbackKey(transactionId, lineId, dimension);
143
- draft.feedbackSubmitStateByKey[key] = {
142
+ if (!isPromptedRecommendationFeedback(action.payload.outcome)) {
143
+ return;
144
+ }
145
+ draft.feedbackSubmitState = {
144
146
  fetchState: 'In-Progress',
145
147
  error: undefined,
146
148
  };
@@ -151,8 +153,8 @@ const recommendation = createSlice({
151
153
  },
152
154
  submitRecommendationFeedbackCompleted: {
153
155
  reducer(draft, action) {
154
- const { key, succeeded, error } = action.payload;
155
- draft.feedbackSubmitStateByKey[key] = {
156
+ const { succeeded, error } = action.payload;
157
+ draft.feedbackSubmitState = {
156
158
  fetchState: succeeded ? 'Completed' : 'Error',
157
159
  error,
158
160
  };
@@ -1,4 +1,4 @@
1
- import { getEntityRecommendationKey, getRecommendationFeedbackKey, } from './recommendationState';
1
+ import { getEntityRecommendationKey } from './recommendationState';
2
2
  export const getRecommendationsForEntity = (state, entityId, entityType) => {
3
3
  const { entityRecommendationState } = state;
4
4
  const key = getEntityRecommendationKey(entityType, entityId);
@@ -11,4 +11,4 @@ export const getRecommendationsForEntity = (state, entityId, entityType) => {
11
11
  recommendations,
12
12
  };
13
13
  };
14
- export const getRecommendationFeedbackSubmitState = (state, transactionId, lineId, dimension) => state.entityRecommendationState.feedbackSubmitStateByKey[getRecommendationFeedbackKey(transactionId, lineId, dimension)] ?? { fetchState: 'Not-Started', error: undefined };
14
+ export const getRecommendationFeedbackSubmitState = (state) => state.entityRecommendationState.feedbackSubmitState;
@@ -1,5 +1,4 @@
1
1
  export const getEntityRecommendationKey = (entityType, entityIdOrName) => `${entityType}_${entityIdOrName}`;
2
- export const getRecommendationFeedbackKey = (transactionId, lineId, dimension) => `${transactionId}|${lineId ?? ''}|${dimension}`;
3
2
  export const initialEntityRecommendationState = {
4
3
  fetchState: 'Not-Started',
5
4
  error: undefined,
@@ -1,8 +1,8 @@
1
- import { of } from 'rxjs';
1
+ import { EMPTY, of } from 'rxjs';
2
2
  import { catchError, filter, mergeMap } from 'rxjs/operators';
3
3
  import { isSuccessStatus } from '../../responsePayload';
4
+ import { isPromptedRecommendationFeedback, } from './recommendationPayload';
4
5
  import { submitRecommendationFeedback, submitRecommendationFeedbackCompleted, } from './recommendationReducer';
5
- import { getRecommendationFeedbackKey } from './recommendationState';
6
6
  const toRequestBody = (payload) => ({
7
7
  line_id: payload.lineId ?? null,
8
8
  dimension: payload.dimension,
@@ -38,8 +38,10 @@ const toRequestBody = (payload) => ({
38
38
  // user what happened. The categorization itself still never waits on this: a
39
39
  // failure is surfaced in a toast rather than blocking or reverting the change.
40
40
  export const submitRecommendationFeedbackEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(submitRecommendationFeedback.match), mergeMap((action) => {
41
- const { transactionId, lineId, dimension } = action.payload;
42
- const key = getRecommendationFeedbackKey(transactionId, lineId, dimension);
41
+ const { transactionId } = action.payload;
42
+ // Only the override that opened the popup reports completion; accepts and
43
+ // retractions stay fire-and-forget so they cannot settle the popup.
44
+ const isPrompted = isPromptedRecommendationFeedback(action.payload.outcome);
43
45
  return zeniAPI
44
46
  .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/${transactionId}/recommendation-feedback`, toRequestBody(action.payload))
45
47
  .pipe(mergeMap((response) => {
@@ -47,13 +49,16 @@ export const submitRecommendationFeedbackEpic = (actions$, _state$, zeniAPI) =>
47
49
  if (!succeeded) {
48
50
  console.error('submitRecommendationFeedbackEpic: recommendation feedback was not recorded', response.status);
49
51
  }
50
- return of(submitRecommendationFeedbackCompleted({
51
- key,
52
- succeeded,
53
- error: succeeded ? undefined : response.status,
54
- }));
52
+ return isPrompted
53
+ ? of(submitRecommendationFeedbackCompleted({
54
+ succeeded,
55
+ error: succeeded ? undefined : response.status,
56
+ }))
57
+ : EMPTY;
55
58
  }), catchError((error) => {
56
59
  console.error('submitRecommendationFeedbackEpic: failed to submit recommendation feedback', error);
57
- return of(submitRecommendationFeedbackCompleted({ key, succeeded: false }));
60
+ return isPrompted
61
+ ? of(submitRecommendationFeedbackCompleted({ succeeded: false }))
62
+ : EMPTY;
58
63
  }));
59
64
  }));
@@ -15,6 +15,7 @@ export type FetchRecommendationResponseWithCOT = ZeniAPIResponse<FetchRecommenda
15
15
  export type RecommendationFeedbackDimension = 'vendor' | 'category' | 'class';
16
16
  export type RecommendationFeedbackSource = 'primary' | 'alternate' | 'shadow' | 'qbo';
17
17
  export type RecommendationFeedbackOutcome = 'accepted' | 'override_ranked' | 'override_outside' | 'retracted';
18
+ export declare const isPromptedRecommendationFeedback: (outcome: RecommendationFeedbackOutcome) => boolean;
18
19
  export interface RecommendationFeedbackValue {
19
20
  name: string;
20
21
  id?: string | null;
@@ -1,2 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isPromptedRecommendationFeedback = void 0;
4
+ // Only an override opens the feedback popup. Silent accepts and retractions post
5
+ // in the background, so they must not drive the popup's loader or its toast.
6
+ const isPromptedRecommendationFeedback = (outcome) => outcome === 'override_outside' || outcome === 'override_ranked';
7
+ exports.isPromptedRecommendationFeedback = isPromptedRecommendationFeedback;
@@ -6,7 +6,7 @@ import { SupportedTransaction } from '../../entity/transaction/transactionState'
6
6
  import { ZeniAPIStatus } from '../../responsePayload';
7
7
  import { TransactionsTab } from '../expenseAutomationView/types/transactionsViewState';
8
8
  import { SubmitRecommendationFeedbackPayload } from './recommendationPayload';
9
- import { EntityRecommendationState, RecommendationFeedbackKey } from './recommendationState';
9
+ import { EntityRecommendationState } from './recommendationState';
10
10
  export type RecommendationLineUpdateFlowType = 'categorization' | 'detail';
11
11
  type FetchEntityRecommendationsForLineUpdateCommonPayload = {
12
12
  amount: number;
@@ -59,11 +59,9 @@ export declare const fetchEntityRecommendationsByTransactionId: import("@reduxjs
59
59
  entityIdOrName: string;
60
60
  entityType: EntityType;
61
61
  }, "recommendation/indicateReadyToInitializeRecommendation", never, never>, submitRecommendationFeedback: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[args: SubmitRecommendationFeedbackPayload], SubmitRecommendationFeedbackPayload, "recommendation/submitRecommendationFeedback", never, never>, submitRecommendationFeedbackCompleted: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[args: {
62
- key: RecommendationFeedbackKey;
63
62
  succeeded: boolean;
64
63
  error?: ZeniAPIStatus;
65
64
  }], {
66
- key: RecommendationFeedbackKey;
67
65
  succeeded: boolean;
68
66
  error?: ZeniAPIStatus;
69
67
  }, "recommendation/submitRecommendationFeedbackCompleted", never, never>;
@@ -4,9 +4,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.submitRecommendationFeedbackCompleted = exports.submitRecommendationFeedback = exports.indicateReadyToInitializeRecommendation = exports.updateRecommendationForEntityFailure = exports.updateRecommendationForEntity = exports.fetchRecommendationByEntityId = exports.fetchRecommendationByEntityName = exports.fetchEntityRecommendationsForLineUpdate = exports.fetchEntityRecommendationsByTransactionId = exports.initialState = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const rootActions_1 = require("../../rootActions");
7
+ const recommendationPayload_1 = require("./recommendationPayload");
7
8
  const recommendationState_1 = require("./recommendationState");
8
9
  exports.initialState = {
9
- feedbackSubmitStateByKey: {},
10
+ feedbackSubmitState: { fetchState: 'Not-Started', error: undefined },
10
11
  recommendationByEntity: {},
11
12
  };
12
13
  const recommendation = (0, toolkit_1.createSlice)({
@@ -142,9 +143,10 @@ const recommendation = (0, toolkit_1.createSlice)({
142
143
  // never waits on this: only the feedback popup reads the submit state.
143
144
  submitRecommendationFeedback: {
144
145
  reducer(draft, action) {
145
- const { transactionId, lineId, dimension } = action.payload;
146
- const key = (0, recommendationState_1.getRecommendationFeedbackKey)(transactionId, lineId, dimension);
147
- draft.feedbackSubmitStateByKey[key] = {
146
+ if (!(0, recommendationPayload_1.isPromptedRecommendationFeedback)(action.payload.outcome)) {
147
+ return;
148
+ }
149
+ draft.feedbackSubmitState = {
148
150
  fetchState: 'In-Progress',
149
151
  error: undefined,
150
152
  };
@@ -155,8 +157,8 @@ const recommendation = (0, toolkit_1.createSlice)({
155
157
  },
156
158
  submitRecommendationFeedbackCompleted: {
157
159
  reducer(draft, action) {
158
- const { key, succeeded, error } = action.payload;
159
- draft.feedbackSubmitStateByKey[key] = {
160
+ const { succeeded, error } = action.payload;
161
+ draft.feedbackSubmitState = {
160
162
  fetchState: succeeded ? 'Completed' : 'Error',
161
163
  error,
162
164
  };
@@ -9,4 +9,4 @@ export interface RecommendationByEntitySelectorView extends SelectorView {
9
9
  recommendations?: Recommendation[];
10
10
  }
11
11
  export declare const getRecommendationsForEntity: (state: RootState, entityId: string, entityType: EntityType) => RecommendationByEntitySelectorView;
12
- export declare const getRecommendationFeedbackSubmitState: (state: RootState, transactionId: string, lineId: string | null | undefined, dimension: string) => FetchStateAndError;
12
+ export declare const getRecommendationFeedbackSubmitState: (state: RootState) => FetchStateAndError;
@@ -15,5 +15,5 @@ const getRecommendationsForEntity = (state, entityId, entityType) => {
15
15
  };
16
16
  };
17
17
  exports.getRecommendationsForEntity = getRecommendationsForEntity;
18
- const getRecommendationFeedbackSubmitState = (state, transactionId, lineId, dimension) => state.entityRecommendationState.feedbackSubmitStateByKey[(0, recommendationState_1.getRecommendationFeedbackKey)(transactionId, lineId, dimension)] ?? { fetchState: 'Not-Started', error: undefined };
18
+ const getRecommendationFeedbackSubmitState = (state) => state.entityRecommendationState.feedbackSubmitState;
19
19
  exports.getRecommendationFeedbackSubmitState = getRecommendationFeedbackSubmitState;
@@ -3,13 +3,11 @@ import { Recommendation } from '../../commonStateTypes/recommendationBase';
3
3
  import { EntityType } from '../../entity/genericEntity/entity';
4
4
  export declare const getEntityRecommendationKey: (entityType: EntityType, entityIdOrName: string) => `vendor_${string}` | `customer_${string}` | `merchant_${string}`;
5
5
  export type EntityRecommendationKey = ReturnType<typeof getEntityRecommendationKey>;
6
- export declare const getRecommendationFeedbackKey: (transactionId: string, lineId: string | null | undefined, dimension: string) => `${string}|${string}|${string}`;
7
- export type RecommendationFeedbackKey = ReturnType<typeof getRecommendationFeedbackKey>;
8
6
  export interface EntityRecommendationsStatus extends FetchedState {
9
7
  recommendations?: Recommendation[];
10
8
  }
11
9
  export declare const initialEntityRecommendationState: EntityRecommendationsStatus;
12
10
  export interface EntityRecommendationState {
13
- feedbackSubmitStateByKey: Record<RecommendationFeedbackKey, FetchStateAndError>;
11
+ feedbackSubmitState: FetchStateAndError;
14
12
  recommendationByEntity: Record<EntityRecommendationKey, EntityRecommendationsStatus>;
15
13
  }
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initialEntityRecommendationState = exports.getRecommendationFeedbackKey = exports.getEntityRecommendationKey = void 0;
3
+ exports.initialEntityRecommendationState = exports.getEntityRecommendationKey = void 0;
4
4
  const getEntityRecommendationKey = (entityType, entityIdOrName) => `${entityType}_${entityIdOrName}`;
5
5
  exports.getEntityRecommendationKey = getEntityRecommendationKey;
6
- const getRecommendationFeedbackKey = (transactionId, lineId, dimension) => `${transactionId}|${lineId ?? ''}|${dimension}`;
7
- exports.getRecommendationFeedbackKey = getRecommendationFeedbackKey;
8
6
  exports.initialEntityRecommendationState = {
9
7
  fetchState: 'Not-Started',
10
8
  error: undefined,
@@ -4,8 +4,8 @@ exports.submitRecommendationFeedbackEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const responsePayload_1 = require("../../responsePayload");
7
+ const recommendationPayload_1 = require("./recommendationPayload");
7
8
  const recommendationReducer_1 = require("./recommendationReducer");
8
- const recommendationState_1 = require("./recommendationState");
9
9
  const toRequestBody = (payload) => ({
10
10
  line_id: payload.lineId ?? null,
11
11
  dimension: payload.dimension,
@@ -41,8 +41,10 @@ const toRequestBody = (payload) => ({
41
41
  // user what happened. The categorization itself still never waits on this: a
42
42
  // failure is surfaced in a toast rather than blocking or reverting the change.
43
43
  const submitRecommendationFeedbackEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(recommendationReducer_1.submitRecommendationFeedback.match), (0, operators_1.mergeMap)((action) => {
44
- const { transactionId, lineId, dimension } = action.payload;
45
- const key = (0, recommendationState_1.getRecommendationFeedbackKey)(transactionId, lineId, dimension);
44
+ const { transactionId } = action.payload;
45
+ // Only the override that opened the popup reports completion; accepts and
46
+ // retractions stay fire-and-forget so they cannot settle the popup.
47
+ const isPrompted = (0, recommendationPayload_1.isPromptedRecommendationFeedback)(action.payload.outcome);
46
48
  return zeniAPI
47
49
  .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/${transactionId}/recommendation-feedback`, toRequestBody(action.payload))
48
50
  .pipe((0, operators_1.mergeMap)((response) => {
@@ -50,14 +52,17 @@ const submitRecommendationFeedbackEpic = (actions$, _state$, zeniAPI) => actions
50
52
  if (!succeeded) {
51
53
  console.error('submitRecommendationFeedbackEpic: recommendation feedback was not recorded', response.status);
52
54
  }
53
- return (0, rxjs_1.of)((0, recommendationReducer_1.submitRecommendationFeedbackCompleted)({
54
- key,
55
- succeeded,
56
- error: succeeded ? undefined : response.status,
57
- }));
55
+ return isPrompted
56
+ ? (0, rxjs_1.of)((0, recommendationReducer_1.submitRecommendationFeedbackCompleted)({
57
+ succeeded,
58
+ error: succeeded ? undefined : response.status,
59
+ }))
60
+ : rxjs_1.EMPTY;
58
61
  }), (0, operators_1.catchError)((error) => {
59
62
  console.error('submitRecommendationFeedbackEpic: failed to submit recommendation feedback', error);
60
- return (0, rxjs_1.of)((0, recommendationReducer_1.submitRecommendationFeedbackCompleted)({ key, succeeded: false }));
63
+ return isPrompted
64
+ ? (0, rxjs_1.of)((0, recommendationReducer_1.submitRecommendationFeedbackCompleted)({ succeeded: false }))
65
+ : rxjs_1.EMPTY;
61
66
  }));
62
67
  }));
63
68
  exports.submitRecommendationFeedbackEpic = submitRecommendationFeedbackEpic;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.2.58-beta0ND",
3
+ "version": "5.2.58-beta1ND",
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",