@wise/dynamic-flow-client 5.9.2 → 5.11.0
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.
- package/build/controller/FlowController.js +6 -1
- package/build/controller/executeRefresh.js +8 -2
- package/build/controller/executeRequest.js +3 -0
- package/build/controller/executeSubmission.js +1 -0
- package/build/controller/getResponseType.js +3 -3
- package/build/domain/components/step/ExternalConfirmationComponent.js +5 -9
- package/build/domain/mappers/mapStepToComponent.js +1 -1
- package/build/domain/mappers/schema/blobSchemaToComponent.js +2 -2
- package/build/domain/mappers/schema/tests/test-utils.js +1 -1
- package/build/i18n/fr.json +1 -1
- package/build/main.css +4 -0
- package/build/main.js +35 -21
- package/build/main.mjs +35 -21
- package/build/renderers/mappers/externalComponentToProps.js +1 -1
- package/build/stories/spec/behavior/Copy.story.js +14 -2
- package/build/stories/spec/behavior/Link.story.js +40 -0
- package/build/stories/spec/behavior/Modal.story.js +4 -1
- package/build/stories/spec/layouts/Upsell.story.js +1 -1
- package/build/stories/spec/step/ScrollToBottom.story.js +103 -0
- package/build/test-utils/DynamicFlowWise.js +1 -1
- package/build/test-utils/DynamicFlowWiseModal.js +1 -1
- package/build/test-utils/openLinkInNewTab.js +15 -0
- package/build/tests/NoOp.test.js +194 -0
- package/build/tests/ScrollToBottom.test.js +122 -0
- package/build/tests/SingleFileUpload.test.js +81 -1
- package/build/tests/Submission.test.js +163 -18
- package/build/tests/Upsell.test.js +34 -6
- package/build/types/controller/FlowController.d.ts +0 -1
- package/build/types/controller/FlowController.d.ts.map +1 -1
- package/build/types/controller/executeRefresh.d.ts +1 -1
- package/build/types/controller/executeRefresh.d.ts.map +1 -1
- package/build/types/controller/executeRequest.d.ts +2 -0
- package/build/types/controller/executeRequest.d.ts.map +1 -1
- package/build/types/controller/executeSubmission.d.ts.map +1 -1
- package/build/types/controller/getResponseType.d.ts +2 -2
- package/build/types/controller/getResponseType.d.ts.map +1 -1
- package/build/types/domain/components/step/ExternalConfirmationComponent.d.ts +2 -3
- package/build/types/domain/components/step/ExternalConfirmationComponent.d.ts.map +1 -1
- package/build/types/domain/mappers/mapStepToComponent.d.ts.map +1 -1
- package/build/types/domain/mappers/schema/types.d.ts +1 -0
- package/build/types/domain/mappers/schema/types.d.ts.map +1 -1
- package/build/types/renderers/mappers/externalComponentToProps.d.ts.map +1 -1
- package/build/types/test-utils/openLinkInNewTab.d.ts.map +1 -0
- package/package.json +5 -5
- package/build/types/utils/openLinkInNewTab.d.ts.map +0 -1
- package/build/utils/openLinkInNewTab.js +0 -10
- /package/build/types/{utils → test-utils}/openLinkInNewTab.d.ts +0 -0
|
@@ -58,6 +58,7 @@ export const createFlowController = (props) => {
|
|
|
58
58
|
features,
|
|
59
59
|
httpClient,
|
|
60
60
|
onBehavior,
|
|
61
|
+
onLink,
|
|
61
62
|
onPoll,
|
|
62
63
|
onValueChange,
|
|
63
64
|
});
|
|
@@ -273,6 +274,10 @@ export const createFlowController = (props) => {
|
|
|
273
274
|
rootComponent.setLoadingState('idle');
|
|
274
275
|
break;
|
|
275
276
|
}
|
|
277
|
+
case 'no-op': {
|
|
278
|
+
rootComponent.setLoadingState('idle');
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
276
281
|
}
|
|
277
282
|
}
|
|
278
283
|
catch (error) {
|
|
@@ -301,7 +306,7 @@ export const createFlowController = (props) => {
|
|
|
301
306
|
updateStep(Object.assign(Object.assign({}, command.step), { errors }), command.etag);
|
|
302
307
|
}
|
|
303
308
|
break;
|
|
304
|
-
case '
|
|
309
|
+
case 'no-op':
|
|
305
310
|
rootComponent.setLoadingState('idle');
|
|
306
311
|
break;
|
|
307
312
|
case 'error': {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getErrorMessage } from './getErrorMessage';
|
|
2
2
|
import { assertStepResponseBody, isErrorResponseBody, parseResponseBodyAsJsonElement, } from './response-utils';
|
|
3
|
+
import { getResponseType } from './getResponseType';
|
|
3
4
|
export const executeRefresh = async (props) => {
|
|
4
5
|
const { abortSignal, url, model, etag, analytics, httpClient, trackEvent, logEvent } = props;
|
|
5
6
|
trackEvent('Refresh Triggered', analytics);
|
|
@@ -12,7 +13,7 @@ export const executeRefresh = async (props) => {
|
|
|
12
13
|
});
|
|
13
14
|
if (response.status === 304) {
|
|
14
15
|
trackEvent('Refresh Succeeded', analytics);
|
|
15
|
-
return { type: '
|
|
16
|
+
return { type: 'no-op' };
|
|
16
17
|
}
|
|
17
18
|
if (!response.ok) {
|
|
18
19
|
const responseBody = await parseResponseBodyAsJsonElement(response).catch(() => ({}));
|
|
@@ -23,6 +24,11 @@ export const executeRefresh = async (props) => {
|
|
|
23
24
|
}
|
|
24
25
|
const newEtag = response.headers.get('etag') || null;
|
|
25
26
|
const body = await parseResponseBodyAsJsonElement(response);
|
|
27
|
+
const responseType = getResponseType(response.headers, body);
|
|
28
|
+
if (responseType === 'no-op') {
|
|
29
|
+
trackEvent('Refresh Succeeded', analytics);
|
|
30
|
+
return { type: 'no-op' };
|
|
31
|
+
}
|
|
26
32
|
assertStepResponseBody(body);
|
|
27
33
|
trackEvent('Refresh Succeeded', analytics);
|
|
28
34
|
return { type: 'refresh-step', step: body, etag: newEtag };
|
|
@@ -30,7 +36,7 @@ export const executeRefresh = async (props) => {
|
|
|
30
36
|
catch (error) {
|
|
31
37
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
32
38
|
trackEvent('Refresh Aborted', analytics);
|
|
33
|
-
return { type: '
|
|
39
|
+
return { type: 'no-op' };
|
|
34
40
|
}
|
|
35
41
|
trackEvent('Refresh Failed', analytics);
|
|
36
42
|
logEvent('error', 'Dynamic Flow - Refresh Failed', Object.assign(Object.assign({}, analytics), { errorMessage: getErrorMessage(error) }));
|
|
@@ -60,6 +60,9 @@ export const executeRequest = async (props) => {
|
|
|
60
60
|
assertModalResponseBody(responseBody);
|
|
61
61
|
return { type: 'behavior', behavior: Object.assign(Object.assign({}, responseBody), { type: 'modal' }) };
|
|
62
62
|
}
|
|
63
|
+
case 'no-op': {
|
|
64
|
+
return { type: 'no-op' };
|
|
65
|
+
}
|
|
63
66
|
default: {
|
|
64
67
|
throw new Error(`Unsupported response type: ${String(responseType)}`);
|
|
65
68
|
}
|
|
@@ -48,6 +48,7 @@ export const executeSubmission = async (props) => {
|
|
|
48
48
|
trackSubmissionEvent('Action Succeeded', { actionId });
|
|
49
49
|
return Object.assign(Object.assign({}, command), { result: recursiveMerge(command.result, result) });
|
|
50
50
|
}
|
|
51
|
+
case 'no-op':
|
|
51
52
|
default: {
|
|
52
53
|
trackSubmissionEvent('Action Succeeded', { actionId });
|
|
53
54
|
return command;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isObject } from '../utils/type-validators';
|
|
2
|
-
const responseTypes = ['step', 'action', 'exit', 'modal', 'subflow'];
|
|
2
|
+
const responseTypes = ['step', 'action', 'exit', 'modal', 'subflow', 'no-op'];
|
|
3
3
|
/**
|
|
4
|
-
* Returns either 'step', 'action', or '
|
|
4
|
+
* Returns either 'step', 'action', 'exit', 'modal', 'subflow', or 'no-op' based on the response headers and body.
|
|
5
5
|
* This function takes a response body parameter because, for legacy reasons, we still need to consider the body
|
|
6
6
|
* to determine the response type, in cases where the response headers are not set.
|
|
7
7
|
* Ideally it should just be a matter of checking the "X-Df-Response-Type" response header.
|
|
@@ -30,6 +30,6 @@ export const getResponseTypeFromHeader = (headers) => {
|
|
|
30
30
|
};
|
|
31
31
|
function assertDFResponseType(type) {
|
|
32
32
|
if (!responseTypes.includes(type)) {
|
|
33
|
-
throw new Error("Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', '
|
|
33
|
+
throw new Error("Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'modal', 'subflow', 'no-op'.");
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getInputUpdateFunction } from '../utils/component-utils';
|
|
2
|
-
export const createExternalConfirmation = (uid, url, onComponentUpdate) => {
|
|
2
|
+
export const createExternalConfirmation = (uid, url, onLink, onComponentUpdate) => {
|
|
3
3
|
const update = getInputUpdateFunction(onComponentUpdate);
|
|
4
4
|
return {
|
|
5
5
|
type: 'external-confirmation',
|
|
@@ -7,15 +7,11 @@ export const createExternalConfirmation = (uid, url, onComponentUpdate) => {
|
|
|
7
7
|
uid,
|
|
8
8
|
url,
|
|
9
9
|
status: 'initial',
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
});
|
|
14
|
-
},
|
|
15
|
-
onFailure() {
|
|
16
|
-
if (this.status === 'initial') {
|
|
10
|
+
open() {
|
|
11
|
+
if (this.status === 'initial' || this.status === 'failure') {
|
|
12
|
+
const success = onLink(this.url);
|
|
17
13
|
update(this, (draft) => {
|
|
18
|
-
draft.status = 'failure';
|
|
14
|
+
draft.status = success ? 'success' : 'failure';
|
|
19
15
|
});
|
|
20
16
|
}
|
|
21
17
|
},
|
|
@@ -57,7 +57,7 @@ export const mapStepToComponent = (_a) => {
|
|
|
57
57
|
: undefined;
|
|
58
58
|
const stepPrefetch = getStepPrefetch(restProps.httpClient, flowRequestCache, submissionBehaviors);
|
|
59
59
|
const externalConfirmation = (external === null || external === void 0 ? void 0 : external.url)
|
|
60
|
-
? createExternalConfirmation(`${uid}-external-confirmation`, external === null || external === void 0 ? void 0 : external.url, onComponentUpdate)
|
|
60
|
+
? createExternalConfirmation(`${uid}-external-confirmation`, external === null || external === void 0 ? void 0 : external.url, restProps.onLink, onComponentUpdate)
|
|
61
61
|
: undefined;
|
|
62
62
|
const mapperProps = Object.assign(Object.assign({}, restProps), { features,
|
|
63
63
|
trackEvent,
|
|
@@ -3,12 +3,12 @@ import { createUploadInputComponent } from '../../components/UploadInputComponen
|
|
|
3
3
|
import { getRequiredCheck } from '../../features/validation/value-checks';
|
|
4
4
|
import { mapCommonSchemaProps } from './utils/mapCommonSchemaProps';
|
|
5
5
|
export const blobSchemaToComponent = (schemaMapperProps, mapperProps) => {
|
|
6
|
-
const { schema, localValue, required = false, onPersistAsync } = schemaMapperProps;
|
|
6
|
+
const { schema, localValue, model, required = false, onPersistAsync } = schemaMapperProps;
|
|
7
7
|
const { accepts, cameraConfig, maxSize, source, validationMessages } = schema;
|
|
8
8
|
const { getErrorMessageFunctions, onComponentUpdate, onValueChange } = mapperProps;
|
|
9
9
|
const errorMessageFunctions = getErrorMessageFunctions(validationMessages);
|
|
10
10
|
const validLocalValue = isFile(localValue) ? localValue : null;
|
|
11
|
-
const value = onPersistAsync ? validLocalValue : null;
|
|
11
|
+
const value = onPersistAsync && model !== null ? validLocalValue : null;
|
|
12
12
|
return createUploadInputComponent(Object.assign(Object.assign({}, mapCommonSchemaProps(schemaMapperProps)), { accepts, autoComplete: 'off', cameraConfig, format: 'blob', maxSize,
|
|
13
13
|
source,
|
|
14
14
|
value, checks: schema.hidden ? [] : [getRequiredCheck(required, errorMessageFunctions)], schemaOnChange: undefined, onValueChange }), onComponentUpdate);
|
|
@@ -4,7 +4,7 @@ import { mockErrorMessageFunctions } from '../../../features/validation/spec-uti
|
|
|
4
4
|
import { FeatureFlags } from '../../utils/FeatureFlags';
|
|
5
5
|
import { makeRequestCache } from '../../../features/prefetch/request-cache';
|
|
6
6
|
export const getStepMapperProps = () => (Object.assign(Object.assign({}, getMockMapperProps()), { uid: 'root', flowRequestCache: makeRequestCache(), etag: null, loadingState: 'idle', trackEvent: vi.fn(), onPoll: vi.fn() }));
|
|
7
|
-
export const getMockMapperProps = (mapperProps = {}) => (Object.assign({ step: {}, stepLocalValue: null, features: new FeatureFlags({}), onComponentUpdate: vi.fn(), onBehavior: vi.fn(), onValueChange: vi.fn(), getErrorMessageFunctions: vi.fn().mockReturnValue(mockErrorMessageFunctions), trackEvent: vi.fn(), logEvent: vi.fn(), httpClient: vi.fn(), registerSubmissionBehavior: vi.fn() }, mapperProps));
|
|
7
|
+
export const getMockMapperProps = (mapperProps = {}) => (Object.assign({ step: {}, stepLocalValue: null, features: new FeatureFlags({}), onComponentUpdate: vi.fn(), onBehavior: vi.fn(), onLink: vi.fn(), onValueChange: vi.fn(), getErrorMessageFunctions: vi.fn().mockReturnValue(mockErrorMessageFunctions), trackEvent: vi.fn(), logEvent: vi.fn(), httpClient: vi.fn(), registerSubmissionBehavior: vi.fn() }, mapperProps));
|
|
8
8
|
export const getMockSchemaMapperProps = (schemaMapperProps) => (Object.assign({ uid: getRandomId(), localValue: null, model: null, required: false, validationErrors: null }, schemaMapperProps));
|
|
9
9
|
export const getMockRendererMapperProps = () => ({
|
|
10
10
|
render: vi.fn(),
|
package/build/i18n/fr.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dynamicFlows.ExternalConfirmation.open": "Ouvrir dans un nouvel onglet",
|
|
25
25
|
"dynamicFlows.ExternalConfirmation.title": "Veuillez confirmer",
|
|
26
26
|
"dynamicFlows.FileUploadSchema.maxFileSizeError": "Nous sommes désolés, ce fichier est trop volumineux. Veuillez télécharger un fichier plus petit.",
|
|
27
|
-
"dynamicFlows.FileUploadSchema.wrongFileTypeError": "
|
|
27
|
+
"dynamicFlows.FileUploadSchema.wrongFileTypeError": "Désolé, ce format de fichier n'est pas pris en charge. Veuillez en importer un autre.",
|
|
28
28
|
"dynamicFlows.Help.ariaLabel": "Cliquez ici pour plus d'informations.",
|
|
29
29
|
"dynamicFlows.MultiSelect.summary": "{first} et {count} de plus",
|
|
30
30
|
"dynamicFlows.MultipleFileUploadSchema.maxFileSizeError": "Nous sommes désolés, ce fichier est trop volumineux. Veuillez télécharger un fichier plus petit.",
|
package/build/main.css
CHANGED
package/build/main.js
CHANGED
|
@@ -266,7 +266,7 @@ var fr_default = {
|
|
|
266
266
|
"dynamicFlows.ExternalConfirmation.open": "Ouvrir dans un nouvel onglet",
|
|
267
267
|
"dynamicFlows.ExternalConfirmation.title": "Veuillez confirmer",
|
|
268
268
|
"dynamicFlows.FileUploadSchema.maxFileSizeError": "Nous sommes d\xE9sol\xE9s, ce fichier est trop volumineux. Veuillez t\xE9l\xE9charger un fichier plus petit.",
|
|
269
|
-
"dynamicFlows.FileUploadSchema.wrongFileTypeError": "
|
|
269
|
+
"dynamicFlows.FileUploadSchema.wrongFileTypeError": "D\xE9sol\xE9, ce format de fichier n'est pas pris en charge. Veuillez en importer un autre.",
|
|
270
270
|
"dynamicFlows.Help.ariaLabel": "Cliquez ici pour plus d'informations.",
|
|
271
271
|
"dynamicFlows.MultiSelect.summary": "{first} et {count} de plus",
|
|
272
272
|
"dynamicFlows.MultipleFileUploadSchema.maxFileSizeError": "Nous sommes d\xE9sol\xE9s, ce fichier est trop volumineux. Veuillez t\xE9l\xE9charger un fichier plus petit.",
|
|
@@ -2496,7 +2496,7 @@ var modalToComponent = (uid, { content, title }, mapperProps, schemaComponents)
|
|
|
2496
2496
|
);
|
|
2497
2497
|
|
|
2498
2498
|
// src/domain/components/step/ExternalConfirmationComponent.ts
|
|
2499
|
-
var createExternalConfirmation = (uid, url, onComponentUpdate) => {
|
|
2499
|
+
var createExternalConfirmation = (uid, url, onLink, onComponentUpdate) => {
|
|
2500
2500
|
const update = getInputUpdateFunction(onComponentUpdate);
|
|
2501
2501
|
return {
|
|
2502
2502
|
type: "external-confirmation",
|
|
@@ -2504,15 +2504,11 @@ var createExternalConfirmation = (uid, url, onComponentUpdate) => {
|
|
|
2504
2504
|
uid,
|
|
2505
2505
|
url,
|
|
2506
2506
|
status: "initial",
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
});
|
|
2511
|
-
},
|
|
2512
|
-
onFailure() {
|
|
2513
|
-
if (this.status === "initial") {
|
|
2507
|
+
open() {
|
|
2508
|
+
if (this.status === "initial" || this.status === "failure") {
|
|
2509
|
+
const success = onLink(this.url);
|
|
2514
2510
|
update(this, (draft) => {
|
|
2515
|
-
draft.status = "failure";
|
|
2511
|
+
draft.status = success ? "success" : "failure";
|
|
2516
2512
|
});
|
|
2517
2513
|
}
|
|
2518
2514
|
},
|
|
@@ -4445,12 +4441,12 @@ var initialiseBase64Value = async (uploadComponent) => {
|
|
|
4445
4441
|
|
|
4446
4442
|
// src/domain/mappers/schema/blobSchemaToComponent.ts
|
|
4447
4443
|
var blobSchemaToComponent = (schemaMapperProps, mapperProps) => {
|
|
4448
|
-
const { schema, localValue, required = false, onPersistAsync } = schemaMapperProps;
|
|
4444
|
+
const { schema, localValue, model, required = false, onPersistAsync } = schemaMapperProps;
|
|
4449
4445
|
const { accepts, cameraConfig, maxSize, source, validationMessages } = schema;
|
|
4450
4446
|
const { getErrorMessageFunctions, onComponentUpdate, onValueChange } = mapperProps;
|
|
4451
4447
|
const errorMessageFunctions = getErrorMessageFunctions(validationMessages);
|
|
4452
4448
|
const validLocalValue = isFile(localValue) ? localValue : null;
|
|
4453
|
-
const value = onPersistAsync ? validLocalValue : null;
|
|
4449
|
+
const value = onPersistAsync && model !== null ? validLocalValue : null;
|
|
4454
4450
|
return createUploadInputComponent(
|
|
4455
4451
|
__spreadProps(__spreadValues({}, mapCommonSchemaProps(schemaMapperProps)), {
|
|
4456
4452
|
accepts,
|
|
@@ -6006,7 +6002,7 @@ var handleErrorResponse = async (response, actionId, trackEvent) => {
|
|
|
6006
6002
|
};
|
|
6007
6003
|
|
|
6008
6004
|
// src/controller/getResponseType.ts
|
|
6009
|
-
var responseTypes = ["step", "action", "exit", "modal", "subflow"];
|
|
6005
|
+
var responseTypes = ["step", "action", "exit", "modal", "subflow", "no-op"];
|
|
6010
6006
|
var getResponseType = (headers, body) => {
|
|
6011
6007
|
const headerResponseType = getResponseTypeFromHeader(headers);
|
|
6012
6008
|
if (headerResponseType) {
|
|
@@ -6031,7 +6027,7 @@ var getResponseTypeFromHeader = (headers) => {
|
|
|
6031
6027
|
function assertDFResponseType(type) {
|
|
6032
6028
|
if (!responseTypes.includes(type)) {
|
|
6033
6029
|
throw new Error(
|
|
6034
|
-
"Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', '
|
|
6030
|
+
"Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'modal', 'subflow', 'no-op'."
|
|
6035
6031
|
);
|
|
6036
6032
|
}
|
|
6037
6033
|
}
|
|
@@ -6109,6 +6105,9 @@ var executeRequest = async (props) => {
|
|
|
6109
6105
|
assertModalResponseBody(responseBody);
|
|
6110
6106
|
return { type: "behavior", behavior: __spreadProps(__spreadValues({}, responseBody), { type: "modal" }) };
|
|
6111
6107
|
}
|
|
6108
|
+
case "no-op": {
|
|
6109
|
+
return { type: "no-op" };
|
|
6110
|
+
}
|
|
6112
6111
|
default: {
|
|
6113
6112
|
throw new Error(`Unsupported response type: ${String(responseType)}`);
|
|
6114
6113
|
}
|
|
@@ -6177,6 +6176,7 @@ var executeSubmission = async (props) => {
|
|
|
6177
6176
|
trackSubmissionEvent("Action Succeeded", { actionId });
|
|
6178
6177
|
return __spreadProps(__spreadValues({}, command), { result: recursiveMerge(command.result, result) });
|
|
6179
6178
|
}
|
|
6179
|
+
case "no-op":
|
|
6180
6180
|
default: {
|
|
6181
6181
|
trackSubmissionEvent("Action Succeeded", { actionId });
|
|
6182
6182
|
return command;
|
|
@@ -6291,7 +6291,12 @@ var mapStepToComponent = (_a) => {
|
|
|
6291
6291
|
}) : void 0;
|
|
6292
6292
|
const stepRefreshAfter = refreshAfter ? getStepRefreshAfter({ refreshAfter, logEvent, onBehavior }) : void 0;
|
|
6293
6293
|
const stepPrefetch = getStepPrefetch(restProps.httpClient, flowRequestCache, submissionBehaviors);
|
|
6294
|
-
const externalConfirmation = (external == null ? void 0 : external.url) ? createExternalConfirmation(
|
|
6294
|
+
const externalConfirmation = (external == null ? void 0 : external.url) ? createExternalConfirmation(
|
|
6295
|
+
`${uid}-external-confirmation`,
|
|
6296
|
+
external == null ? void 0 : external.url,
|
|
6297
|
+
restProps.onLink,
|
|
6298
|
+
onComponentUpdate
|
|
6299
|
+
) : void 0;
|
|
6295
6300
|
const mapperProps = __spreadProps(__spreadValues({}, restProps), {
|
|
6296
6301
|
features,
|
|
6297
6302
|
trackEvent,
|
|
@@ -6503,7 +6508,7 @@ var executeRefresh = async (props) => {
|
|
|
6503
6508
|
});
|
|
6504
6509
|
if (response.status === 304) {
|
|
6505
6510
|
trackEvent("Refresh Succeeded", analytics);
|
|
6506
|
-
return { type: "
|
|
6511
|
+
return { type: "no-op" };
|
|
6507
6512
|
}
|
|
6508
6513
|
if (!response.ok) {
|
|
6509
6514
|
const responseBody = await parseResponseBodyAsJsonElement(response).catch(() => ({}));
|
|
@@ -6518,13 +6523,18 @@ var executeRefresh = async (props) => {
|
|
|
6518
6523
|
}
|
|
6519
6524
|
const newEtag = response.headers.get("etag") || null;
|
|
6520
6525
|
const body = await parseResponseBodyAsJsonElement(response);
|
|
6526
|
+
const responseType = getResponseType(response.headers, body);
|
|
6527
|
+
if (responseType === "no-op") {
|
|
6528
|
+
trackEvent("Refresh Succeeded", analytics);
|
|
6529
|
+
return { type: "no-op" };
|
|
6530
|
+
}
|
|
6521
6531
|
assertStepResponseBody(body);
|
|
6522
6532
|
trackEvent("Refresh Succeeded", analytics);
|
|
6523
6533
|
return { type: "refresh-step", step: body, etag: newEtag };
|
|
6524
6534
|
} catch (error) {
|
|
6525
6535
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
6526
6536
|
trackEvent("Refresh Aborted", analytics);
|
|
6527
|
-
return { type: "
|
|
6537
|
+
return { type: "no-op" };
|
|
6528
6538
|
}
|
|
6529
6539
|
trackEvent("Refresh Failed", analytics);
|
|
6530
6540
|
logEvent("error", "Dynamic Flow - Refresh Failed", __spreadProps(__spreadValues({}, analytics), {
|
|
@@ -6640,6 +6650,7 @@ var createFlowController = (props) => {
|
|
|
6640
6650
|
features,
|
|
6641
6651
|
httpClient,
|
|
6642
6652
|
onBehavior,
|
|
6653
|
+
onLink,
|
|
6643
6654
|
onPoll,
|
|
6644
6655
|
onValueChange
|
|
6645
6656
|
});
|
|
@@ -6889,6 +6900,10 @@ var createFlowController = (props) => {
|
|
|
6889
6900
|
rootComponent.setLoadingState("idle");
|
|
6890
6901
|
break;
|
|
6891
6902
|
}
|
|
6903
|
+
case "no-op": {
|
|
6904
|
+
rootComponent.setLoadingState("idle");
|
|
6905
|
+
break;
|
|
6906
|
+
}
|
|
6892
6907
|
}
|
|
6893
6908
|
} catch (error) {
|
|
6894
6909
|
closeWithError(error);
|
|
@@ -6920,7 +6935,7 @@ var createFlowController = (props) => {
|
|
|
6920
6935
|
updateStep(__spreadProps(__spreadValues({}, command.step), { errors }), command.etag);
|
|
6921
6936
|
}
|
|
6922
6937
|
break;
|
|
6923
|
-
case "
|
|
6938
|
+
case "no-op":
|
|
6924
6939
|
rootComponent.setLoadingState("idle");
|
|
6925
6940
|
break;
|
|
6926
6941
|
case "error": {
|
|
@@ -7514,9 +7529,8 @@ var externalComponentToProps = (component, rendererMapperProps) => {
|
|
|
7514
7529
|
type: "external-confirmation",
|
|
7515
7530
|
uid: component.uid,
|
|
7516
7531
|
url: component.url,
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
onFailure: component.onFailure.bind(component),
|
|
7532
|
+
visible: component.status === "failure",
|
|
7533
|
+
open: component.open.bind(component),
|
|
7520
7534
|
onCancel: component.onCancel.bind(component)
|
|
7521
7535
|
}, rendererMapperProps);
|
|
7522
7536
|
};
|
package/build/main.mjs
CHANGED
|
@@ -236,7 +236,7 @@ var fr_default = {
|
|
|
236
236
|
"dynamicFlows.ExternalConfirmation.open": "Ouvrir dans un nouvel onglet",
|
|
237
237
|
"dynamicFlows.ExternalConfirmation.title": "Veuillez confirmer",
|
|
238
238
|
"dynamicFlows.FileUploadSchema.maxFileSizeError": "Nous sommes d\xE9sol\xE9s, ce fichier est trop volumineux. Veuillez t\xE9l\xE9charger un fichier plus petit.",
|
|
239
|
-
"dynamicFlows.FileUploadSchema.wrongFileTypeError": "
|
|
239
|
+
"dynamicFlows.FileUploadSchema.wrongFileTypeError": "D\xE9sol\xE9, ce format de fichier n'est pas pris en charge. Veuillez en importer un autre.",
|
|
240
240
|
"dynamicFlows.Help.ariaLabel": "Cliquez ici pour plus d'informations.",
|
|
241
241
|
"dynamicFlows.MultiSelect.summary": "{first} et {count} de plus",
|
|
242
242
|
"dynamicFlows.MultipleFileUploadSchema.maxFileSizeError": "Nous sommes d\xE9sol\xE9s, ce fichier est trop volumineux. Veuillez t\xE9l\xE9charger un fichier plus petit.",
|
|
@@ -2466,7 +2466,7 @@ var modalToComponent = (uid, { content, title }, mapperProps, schemaComponents)
|
|
|
2466
2466
|
);
|
|
2467
2467
|
|
|
2468
2468
|
// src/domain/components/step/ExternalConfirmationComponent.ts
|
|
2469
|
-
var createExternalConfirmation = (uid, url, onComponentUpdate) => {
|
|
2469
|
+
var createExternalConfirmation = (uid, url, onLink, onComponentUpdate) => {
|
|
2470
2470
|
const update = getInputUpdateFunction(onComponentUpdate);
|
|
2471
2471
|
return {
|
|
2472
2472
|
type: "external-confirmation",
|
|
@@ -2474,15 +2474,11 @@ var createExternalConfirmation = (uid, url, onComponentUpdate) => {
|
|
|
2474
2474
|
uid,
|
|
2475
2475
|
url,
|
|
2476
2476
|
status: "initial",
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
});
|
|
2481
|
-
},
|
|
2482
|
-
onFailure() {
|
|
2483
|
-
if (this.status === "initial") {
|
|
2477
|
+
open() {
|
|
2478
|
+
if (this.status === "initial" || this.status === "failure") {
|
|
2479
|
+
const success = onLink(this.url);
|
|
2484
2480
|
update(this, (draft) => {
|
|
2485
|
-
draft.status = "failure";
|
|
2481
|
+
draft.status = success ? "success" : "failure";
|
|
2486
2482
|
});
|
|
2487
2483
|
}
|
|
2488
2484
|
},
|
|
@@ -4415,12 +4411,12 @@ var initialiseBase64Value = async (uploadComponent) => {
|
|
|
4415
4411
|
|
|
4416
4412
|
// src/domain/mappers/schema/blobSchemaToComponent.ts
|
|
4417
4413
|
var blobSchemaToComponent = (schemaMapperProps, mapperProps) => {
|
|
4418
|
-
const { schema, localValue, required = false, onPersistAsync } = schemaMapperProps;
|
|
4414
|
+
const { schema, localValue, model, required = false, onPersistAsync } = schemaMapperProps;
|
|
4419
4415
|
const { accepts, cameraConfig, maxSize, source, validationMessages } = schema;
|
|
4420
4416
|
const { getErrorMessageFunctions, onComponentUpdate, onValueChange } = mapperProps;
|
|
4421
4417
|
const errorMessageFunctions = getErrorMessageFunctions(validationMessages);
|
|
4422
4418
|
const validLocalValue = isFile(localValue) ? localValue : null;
|
|
4423
|
-
const value = onPersistAsync ? validLocalValue : null;
|
|
4419
|
+
const value = onPersistAsync && model !== null ? validLocalValue : null;
|
|
4424
4420
|
return createUploadInputComponent(
|
|
4425
4421
|
__spreadProps(__spreadValues({}, mapCommonSchemaProps(schemaMapperProps)), {
|
|
4426
4422
|
accepts,
|
|
@@ -5976,7 +5972,7 @@ var handleErrorResponse = async (response, actionId, trackEvent) => {
|
|
|
5976
5972
|
};
|
|
5977
5973
|
|
|
5978
5974
|
// src/controller/getResponseType.ts
|
|
5979
|
-
var responseTypes = ["step", "action", "exit", "modal", "subflow"];
|
|
5975
|
+
var responseTypes = ["step", "action", "exit", "modal", "subflow", "no-op"];
|
|
5980
5976
|
var getResponseType = (headers, body) => {
|
|
5981
5977
|
const headerResponseType = getResponseTypeFromHeader(headers);
|
|
5982
5978
|
if (headerResponseType) {
|
|
@@ -6001,7 +5997,7 @@ var getResponseTypeFromHeader = (headers) => {
|
|
|
6001
5997
|
function assertDFResponseType(type) {
|
|
6002
5998
|
if (!responseTypes.includes(type)) {
|
|
6003
5999
|
throw new Error(
|
|
6004
|
-
"Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', '
|
|
6000
|
+
"Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'modal', 'subflow', 'no-op'."
|
|
6005
6001
|
);
|
|
6006
6002
|
}
|
|
6007
6003
|
}
|
|
@@ -6079,6 +6075,9 @@ var executeRequest = async (props) => {
|
|
|
6079
6075
|
assertModalResponseBody(responseBody);
|
|
6080
6076
|
return { type: "behavior", behavior: __spreadProps(__spreadValues({}, responseBody), { type: "modal" }) };
|
|
6081
6077
|
}
|
|
6078
|
+
case "no-op": {
|
|
6079
|
+
return { type: "no-op" };
|
|
6080
|
+
}
|
|
6082
6081
|
default: {
|
|
6083
6082
|
throw new Error(`Unsupported response type: ${String(responseType)}`);
|
|
6084
6083
|
}
|
|
@@ -6147,6 +6146,7 @@ var executeSubmission = async (props) => {
|
|
|
6147
6146
|
trackSubmissionEvent("Action Succeeded", { actionId });
|
|
6148
6147
|
return __spreadProps(__spreadValues({}, command), { result: recursiveMerge(command.result, result) });
|
|
6149
6148
|
}
|
|
6149
|
+
case "no-op":
|
|
6150
6150
|
default: {
|
|
6151
6151
|
trackSubmissionEvent("Action Succeeded", { actionId });
|
|
6152
6152
|
return command;
|
|
@@ -6261,7 +6261,12 @@ var mapStepToComponent = (_a) => {
|
|
|
6261
6261
|
}) : void 0;
|
|
6262
6262
|
const stepRefreshAfter = refreshAfter ? getStepRefreshAfter({ refreshAfter, logEvent, onBehavior }) : void 0;
|
|
6263
6263
|
const stepPrefetch = getStepPrefetch(restProps.httpClient, flowRequestCache, submissionBehaviors);
|
|
6264
|
-
const externalConfirmation = (external == null ? void 0 : external.url) ? createExternalConfirmation(
|
|
6264
|
+
const externalConfirmation = (external == null ? void 0 : external.url) ? createExternalConfirmation(
|
|
6265
|
+
`${uid}-external-confirmation`,
|
|
6266
|
+
external == null ? void 0 : external.url,
|
|
6267
|
+
restProps.onLink,
|
|
6268
|
+
onComponentUpdate
|
|
6269
|
+
) : void 0;
|
|
6265
6270
|
const mapperProps = __spreadProps(__spreadValues({}, restProps), {
|
|
6266
6271
|
features,
|
|
6267
6272
|
trackEvent,
|
|
@@ -6473,7 +6478,7 @@ var executeRefresh = async (props) => {
|
|
|
6473
6478
|
});
|
|
6474
6479
|
if (response.status === 304) {
|
|
6475
6480
|
trackEvent("Refresh Succeeded", analytics);
|
|
6476
|
-
return { type: "
|
|
6481
|
+
return { type: "no-op" };
|
|
6477
6482
|
}
|
|
6478
6483
|
if (!response.ok) {
|
|
6479
6484
|
const responseBody = await parseResponseBodyAsJsonElement(response).catch(() => ({}));
|
|
@@ -6488,13 +6493,18 @@ var executeRefresh = async (props) => {
|
|
|
6488
6493
|
}
|
|
6489
6494
|
const newEtag = response.headers.get("etag") || null;
|
|
6490
6495
|
const body = await parseResponseBodyAsJsonElement(response);
|
|
6496
|
+
const responseType = getResponseType(response.headers, body);
|
|
6497
|
+
if (responseType === "no-op") {
|
|
6498
|
+
trackEvent("Refresh Succeeded", analytics);
|
|
6499
|
+
return { type: "no-op" };
|
|
6500
|
+
}
|
|
6491
6501
|
assertStepResponseBody(body);
|
|
6492
6502
|
trackEvent("Refresh Succeeded", analytics);
|
|
6493
6503
|
return { type: "refresh-step", step: body, etag: newEtag };
|
|
6494
6504
|
} catch (error) {
|
|
6495
6505
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
6496
6506
|
trackEvent("Refresh Aborted", analytics);
|
|
6497
|
-
return { type: "
|
|
6507
|
+
return { type: "no-op" };
|
|
6498
6508
|
}
|
|
6499
6509
|
trackEvent("Refresh Failed", analytics);
|
|
6500
6510
|
logEvent("error", "Dynamic Flow - Refresh Failed", __spreadProps(__spreadValues({}, analytics), {
|
|
@@ -6610,6 +6620,7 @@ var createFlowController = (props) => {
|
|
|
6610
6620
|
features,
|
|
6611
6621
|
httpClient,
|
|
6612
6622
|
onBehavior,
|
|
6623
|
+
onLink,
|
|
6613
6624
|
onPoll,
|
|
6614
6625
|
onValueChange
|
|
6615
6626
|
});
|
|
@@ -6859,6 +6870,10 @@ var createFlowController = (props) => {
|
|
|
6859
6870
|
rootComponent.setLoadingState("idle");
|
|
6860
6871
|
break;
|
|
6861
6872
|
}
|
|
6873
|
+
case "no-op": {
|
|
6874
|
+
rootComponent.setLoadingState("idle");
|
|
6875
|
+
break;
|
|
6876
|
+
}
|
|
6862
6877
|
}
|
|
6863
6878
|
} catch (error) {
|
|
6864
6879
|
closeWithError(error);
|
|
@@ -6890,7 +6905,7 @@ var createFlowController = (props) => {
|
|
|
6890
6905
|
updateStep(__spreadProps(__spreadValues({}, command.step), { errors }), command.etag);
|
|
6891
6906
|
}
|
|
6892
6907
|
break;
|
|
6893
|
-
case "
|
|
6908
|
+
case "no-op":
|
|
6894
6909
|
rootComponent.setLoadingState("idle");
|
|
6895
6910
|
break;
|
|
6896
6911
|
case "error": {
|
|
@@ -7484,9 +7499,8 @@ var externalComponentToProps = (component, rendererMapperProps) => {
|
|
|
7484
7499
|
type: "external-confirmation",
|
|
7485
7500
|
uid: component.uid,
|
|
7486
7501
|
url: component.url,
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
onFailure: component.onFailure.bind(component),
|
|
7502
|
+
visible: component.status === "failure",
|
|
7503
|
+
open: component.open.bind(component),
|
|
7490
7504
|
onCancel: component.onCancel.bind(component)
|
|
7491
7505
|
}, rendererMapperProps);
|
|
7492
7506
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export const externalComponentToProps = (component, rendererMapperProps) => {
|
|
2
|
-
return Object.assign({ type: 'external-confirmation', uid: component.uid, url: component.url,
|
|
2
|
+
return Object.assign({ type: 'external-confirmation', uid: component.uid, url: component.url, visible: component.status === 'failure', open: component.open.bind(component), onCancel: component.onCancel.bind(component) }, rendererMapperProps);
|
|
3
3
|
};
|
|
@@ -7,8 +7,11 @@ export default {
|
|
|
7
7
|
chromatic: { disableSnapshot: true },
|
|
8
8
|
},
|
|
9
9
|
};
|
|
10
|
+
const httpClient = async () => new Promise((resolve) => {
|
|
11
|
+
setTimeout(resolve, 1000);
|
|
12
|
+
});
|
|
10
13
|
export function Copy() {
|
|
11
|
-
return renderWithStep(copyStep);
|
|
14
|
+
return renderWithStep(copyStep, httpClient);
|
|
12
15
|
}
|
|
13
16
|
const copyStep = {
|
|
14
17
|
id: 'copy',
|
|
@@ -49,11 +52,20 @@ const copyStep = {
|
|
|
49
52
|
{
|
|
50
53
|
type: 'button',
|
|
51
54
|
title: 'Click to copy',
|
|
52
|
-
control: '
|
|
55
|
+
control: 'secondary',
|
|
53
56
|
behavior: {
|
|
54
57
|
type: 'copy',
|
|
55
58
|
content: 'This is a button',
|
|
56
59
|
},
|
|
57
60
|
},
|
|
61
|
+
{
|
|
62
|
+
type: 'button',
|
|
63
|
+
title: 'Submit',
|
|
64
|
+
control: 'primary',
|
|
65
|
+
behavior: {
|
|
66
|
+
type: 'action',
|
|
67
|
+
action: { url: '/submit' },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
58
70
|
],
|
|
59
71
|
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import DynamicFlowWise from '../../../test-utils/DynamicFlowWise';
|
|
2
|
+
import { renderWithStep } from '../../utils/render-utils';
|
|
3
|
+
export default {
|
|
4
|
+
component: DynamicFlowWise,
|
|
5
|
+
title: 'Spec/Behavior',
|
|
6
|
+
parameters: {
|
|
7
|
+
chromatic: { disableSnapshot: true },
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
const httpClient = async () => new Promise((resolve) => {
|
|
11
|
+
setTimeout(resolve, 1000);
|
|
12
|
+
});
|
|
13
|
+
export function Link() {
|
|
14
|
+
return renderWithStep(step, httpClient);
|
|
15
|
+
}
|
|
16
|
+
const step = {
|
|
17
|
+
id: 'copy',
|
|
18
|
+
title: 'Link Behavior',
|
|
19
|
+
schemas: [],
|
|
20
|
+
layout: [
|
|
21
|
+
{
|
|
22
|
+
type: 'button',
|
|
23
|
+
title: 'Open Google',
|
|
24
|
+
control: 'secondary',
|
|
25
|
+
behavior: {
|
|
26
|
+
type: 'link',
|
|
27
|
+
url: 'https://www.google.com',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'button',
|
|
32
|
+
title: 'Submit',
|
|
33
|
+
control: 'primary',
|
|
34
|
+
behavior: {
|
|
35
|
+
type: 'action',
|
|
36
|
+
action: { url: '/submit' },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
@@ -7,8 +7,11 @@ export default {
|
|
|
7
7
|
chromatic: { disableSnapshot: true },
|
|
8
8
|
},
|
|
9
9
|
};
|
|
10
|
+
const httpClient = async () => new Promise((resolve) => {
|
|
11
|
+
setTimeout(resolve, 1000);
|
|
12
|
+
});
|
|
10
13
|
export function Modal() {
|
|
11
|
-
return renderWithStep(initialStep);
|
|
14
|
+
return renderWithStep(initialStep, httpClient);
|
|
12
15
|
}
|
|
13
16
|
const initialStep = {
|
|
14
17
|
id: 'modal',
|
|
@@ -33,7 +33,7 @@ const getStep = (urns, dismissable) => ({
|
|
|
33
33
|
},
|
|
34
34
|
callToAction: {
|
|
35
35
|
title: 'Do the thing!',
|
|
36
|
-
behavior: { type: '
|
|
36
|
+
behavior: { type: 'link', url: 'https://google.com' },
|
|
37
37
|
},
|
|
38
38
|
onDismiss: dismissable ? { url: '/upsell-dismissed', method: 'POST' } : undefined,
|
|
39
39
|
margin: 'lg',
|