project-booster-vue 10.16.4 → 10.17.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/package.json +1 -1
- package/src/components/question/configurations-import/ConfigurationsImport.ts +1 -0
- package/src/components/rework/navigation/MPbNavigation.vue +1 -0
- package/src/components/rework/question/configurations-import/MPbConfigurationsImport.vue +147 -194
- package/src/components/rework/question/configurations-import/default-payload.json +3 -15
- package/src/components/rework/question/dimensions-input/DimensionsInput.ts +28 -0
- package/src/components/rework/question/dimensions-input/MPbDimensionsInput.stories.mdx +230 -0
- package/src/components/rework/question/dimensions-input/MPbDimensionsInput.vue +330 -0
- package/src/components/rework/question/dimensions-input/default-payload.json +19 -0
- package/src/components/rework/question/list-select/MPbListSelect-Answers-Multiple.stories.mdx +123 -0
- package/src/components/rework/question/list-select/MPbListSelect-Answers-NextStep.stories.mdx +89 -0
- package/src/components/rework/question/list-select/MPbListSelect-Answers-ShowMore.stories.mdx +204 -0
- package/src/components/rework/question/list-select/MPbListSelect-Answers-Single.stories.mdx +112 -0
- package/src/components/rework/question/list-select/MPbListSelect-Answers-Skippable.stories.mdx +140 -0
- package/src/components/rework/question/list-select/MPbListSelect.stories.mdx +132 -0
- package/src/components/rework/question/list-select/MPbListSelect.vue +381 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-101-sandbox-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-features-answers-multiple-showcase-feature-multiple-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-features-answers-next-step-showcase-feature-next-step-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-features-answers-show-more-showcase-feature-show-more-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-features-answers-show-more-showcase-show-more-color-and-position-properties-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-features-answers-single-showcase-feature-single-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-features-answers-skippable-showcase-feature-skippable-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-showcase-mono-select-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-showcase-multiselect-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-showcase-multiselect-dynamic-label-1-snap.png +0 -0
- package/src/components/rework/question/list-select/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-list-select-/360/237/246/240-showcase-pagination-1-snap.png +0 -0
- package/src/components/rework/question/list-select/default-payload.json +43 -0
- package/src/components/rework/question/list-select/monoselect-payload.json +49 -0
- package/src/components/rework/question/list-select/multiselect-dynamic-label-payload.json +53 -0
- package/src/components/rework/question/list-select/multiselect-payload.json +51 -0
- package/src/components/rework/question/list-select/pagination-payload.json +71 -0
- package/src/components/rework/restitution/MPbRestitutionList.vue +1 -0
- package/src/components/rework/restitution/MPbRestitutionListLine.vue +1 -0
- package/src/components/rework/styles/global.scss +4 -0
- package/src/components/scenario/PbScenario.vue +7 -3
- package/src/components/scenario/scenarii/appointment-qualification-bathroom.json +39 -23
- package/src/components/scenario/scenarii/appointment-qualification-kitchen.json +100 -24
- package/src/components/scenario/scenarii/estimator-attic-insulation.json +6 -6
- package/src/components/scenario/scenarii/estimator-bathroom.json +7 -13
- package/src/components/scenario/scenarii/estimator-floor.json +59 -43
package/package.json
CHANGED
|
@@ -67,24 +67,14 @@
|
|
|
67
67
|
></m-link>
|
|
68
68
|
</div>
|
|
69
69
|
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
JSON.stringify([
|
|
79
|
-
[
|
|
80
|
-
'cdl_event',
|
|
81
|
-
formatEvent({ button_name: button.label, button_location: stepLocation }, EventTypeEnum.BUTTON),
|
|
82
|
-
],
|
|
83
|
-
])
|
|
84
|
-
"
|
|
85
|
-
/>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
70
|
+
<m-pb-navigation
|
|
71
|
+
:answers="answers"
|
|
72
|
+
:payload="payload"
|
|
73
|
+
:trackingStatus="trackingStatus"
|
|
74
|
+
@go-back="$emit('go-back')"
|
|
75
|
+
@next-step="callAction(payload?.viewModel?.nextStep)"
|
|
76
|
+
:step-number="stepNumber"
|
|
77
|
+
/>
|
|
88
78
|
</m-container>
|
|
89
79
|
</div>
|
|
90
80
|
<pb-configurations-search
|
|
@@ -112,16 +102,12 @@
|
|
|
112
102
|
</div>
|
|
113
103
|
</template>
|
|
114
104
|
|
|
115
|
-
<script lang="ts">
|
|
116
|
-
import {
|
|
105
|
+
<script lang="ts" setup>
|
|
106
|
+
import { computed, ref, PropType } from 'vue';
|
|
117
107
|
import { useStore } from 'vuex';
|
|
118
108
|
import PbConfigurationsSearch from '../../../../components/configurations/search/PbConfigurationsSearch.vue';
|
|
119
|
-
import PbStickyFooter from '../../../../components/sticky-footer/PbStickyFooter.vue';
|
|
120
|
-
import MButton from '../../../../components/mozaic/buttons/MButton.vue';
|
|
121
109
|
import MContainer from '../../../../components/mozaic/grid/MContainer.vue';
|
|
122
110
|
import MFlexy from '../../../../components/mozaic/grid/MFlexy.vue';
|
|
123
|
-
import MFlexyCol from '../../../../components/mozaic/grid/MFlexyCol.vue';
|
|
124
|
-
import MFlex from '../../../../components/mozaic/flex/MFlex.vue';
|
|
125
111
|
import MLink from '../../../../components/mozaic/link/MLink.vue';
|
|
126
112
|
import MNotification from '../../../../components/mozaic/notifications/MNotification.vue';
|
|
127
113
|
import PbCard from '../../../../components/cards/PbCard.vue';
|
|
@@ -137,182 +123,149 @@ import { Configuration } from '@/types/pb/Configuration';
|
|
|
137
123
|
import { decorate } from '@/services/decorate';
|
|
138
124
|
import { PayloadAction } from '../../types/genericPayload';
|
|
139
125
|
import { EventTypeEnum, formatEvent } from '../../services/event';
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
MFlexy,
|
|
155
|
-
MFlex,
|
|
156
|
-
MLink,
|
|
157
|
-
MNotification,
|
|
158
|
-
PbConfigurationsSearch,
|
|
159
|
-
PbStickyFooter,
|
|
126
|
+
import MPbNavigation from '../../navigation/MPbNavigation.vue';
|
|
127
|
+
|
|
128
|
+
const emit: any = defineEmits();
|
|
129
|
+
|
|
130
|
+
const props = defineProps({
|
|
131
|
+
/**
|
|
132
|
+
* The component view model and business data as an object. The provided props
|
|
133
|
+
* is merged with the default payload value so only overridden values will change
|
|
134
|
+
* from the default ones.
|
|
135
|
+
*/
|
|
136
|
+
payload: {
|
|
137
|
+
type: Object as PropType<ConfigurationsImportPayload>,
|
|
138
|
+
default: () => null,
|
|
139
|
+
required: true,
|
|
160
140
|
},
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
payload: {
|
|
168
|
-
type: Object as PropType<ConfigurationsImportPayload>,
|
|
169
|
-
default: () => null,
|
|
170
|
-
required: true,
|
|
171
|
-
},
|
|
172
|
-
/**
|
|
173
|
-
* The options provided at runtime to customize component behaviour
|
|
174
|
-
*/
|
|
175
|
-
runtimeOptions: {
|
|
176
|
-
type: Object,
|
|
177
|
-
default: () => ({}),
|
|
178
|
-
},
|
|
179
|
-
/**
|
|
180
|
-
* Flag indicating whether the back button should be displayed
|
|
181
|
-
*/
|
|
182
|
-
showBackButton: {
|
|
183
|
-
type: Boolean,
|
|
184
|
-
default: true,
|
|
185
|
-
},
|
|
186
|
-
/**
|
|
187
|
-
* Name for the event to send when the question is answered
|
|
188
|
-
*/
|
|
189
|
-
completedEventName: {
|
|
190
|
-
type: String,
|
|
191
|
-
default: 'step-completed',
|
|
192
|
-
},
|
|
193
|
-
/**
|
|
194
|
-
* The previous answers to inject
|
|
195
|
-
*/
|
|
196
|
-
answers: {
|
|
197
|
-
type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
|
|
198
|
-
default: () => new Map<string, ScenarioStepAnswer[]>(),
|
|
199
|
-
},
|
|
200
|
-
/**
|
|
201
|
-
* Define the offset for question sticky bottom elements.
|
|
202
|
-
*
|
|
203
|
-
* _Use any value for the [`top` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/top)_
|
|
204
|
-
*/
|
|
205
|
-
stickyBottomOffset: {
|
|
206
|
-
type: String,
|
|
207
|
-
default: '0px',
|
|
208
|
-
},
|
|
209
|
-
/**
|
|
210
|
-
* Step location
|
|
211
|
-
*/
|
|
212
|
-
stepLocation: {
|
|
213
|
-
type: String,
|
|
214
|
-
default: '',
|
|
215
|
-
},
|
|
216
|
-
/**
|
|
217
|
-
* Define the location of the step in the scenario.
|
|
218
|
-
*/
|
|
219
|
-
trackingStatus: {
|
|
220
|
-
type: Boolean,
|
|
221
|
-
default: false,
|
|
222
|
-
},
|
|
141
|
+
/**
|
|
142
|
+
* The options provided at runtime to customize component behaviour
|
|
143
|
+
*/
|
|
144
|
+
runtimeOptions: {
|
|
145
|
+
type: Object,
|
|
146
|
+
default: () => ({}),
|
|
223
147
|
},
|
|
148
|
+
/**
|
|
149
|
+
* Flag indicating whether the back button should be displayed
|
|
150
|
+
*/
|
|
151
|
+
showBackButton: {
|
|
152
|
+
type: Boolean,
|
|
153
|
+
default: true,
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* Name for the event to send when the question is answered
|
|
157
|
+
*/
|
|
158
|
+
completedEventName: {
|
|
159
|
+
type: String,
|
|
160
|
+
default: 'step-completed',
|
|
161
|
+
},
|
|
162
|
+
/**
|
|
163
|
+
* The previous answers to inject
|
|
164
|
+
*/
|
|
165
|
+
answers: {
|
|
166
|
+
type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
|
|
167
|
+
default: () => new Map<string, ScenarioStepAnswer[]>(),
|
|
168
|
+
},
|
|
169
|
+
/**
|
|
170
|
+
* Define the offset for question sticky bottom elements.
|
|
171
|
+
*
|
|
172
|
+
* _Use any value for the [`top` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/top)_
|
|
173
|
+
*/
|
|
174
|
+
stickyBottomOffset: {
|
|
175
|
+
type: String,
|
|
176
|
+
default: '0px',
|
|
177
|
+
},
|
|
178
|
+
/**
|
|
179
|
+
* Step location
|
|
180
|
+
*/
|
|
181
|
+
stepLocation: {
|
|
182
|
+
type: String,
|
|
183
|
+
default: '',
|
|
184
|
+
},
|
|
185
|
+
/**
|
|
186
|
+
* Define the location of the step in the scenario.
|
|
187
|
+
*/
|
|
188
|
+
trackingStatus: {
|
|
189
|
+
type: Boolean,
|
|
190
|
+
default: false,
|
|
191
|
+
},
|
|
192
|
+
/**
|
|
193
|
+
* Current step number
|
|
194
|
+
*/
|
|
195
|
+
stepNumber: {
|
|
196
|
+
type: Number,
|
|
197
|
+
default: 0,
|
|
198
|
+
},
|
|
199
|
+
});
|
|
224
200
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
};
|
|
201
|
+
const store = useStore();
|
|
202
|
+
const projectId = computed(() => store.getters['configurations/getCurrentProjectId']);
|
|
203
|
+
const selectedConfigurations = computed(() => store.getters['configurations/getConfigurations']);
|
|
204
|
+
const showImportConfigurationDialog = ref(false);
|
|
205
|
+
const configurationImportSuccess = ref(false);
|
|
206
|
+
const configurationImportError = ref(false);
|
|
207
|
+
|
|
208
|
+
const navigateTo = (viewModel: ConfigurationsImportViewModel) => {
|
|
209
|
+
if (viewModel.backLink) {
|
|
210
|
+
(<any>window).location = decorate(props.answers, props.runtimeOptions, viewModel.backLink);
|
|
211
|
+
} else {
|
|
212
|
+
/**
|
|
213
|
+
* Emitted when go back link is clicked
|
|
214
|
+
* @event go-back
|
|
215
|
+
*/
|
|
216
|
+
emit('go-back');
|
|
217
|
+
}
|
|
218
|
+
};
|
|
244
219
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
220
|
+
const displayConfigurationDialog = () => {
|
|
221
|
+
showImportConfigurationDialog.value = true;
|
|
222
|
+
};
|
|
248
223
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
224
|
+
const importConfiguration = async (configuration: Configuration) => {
|
|
225
|
+
showImportConfigurationDialog.value = false;
|
|
226
|
+
await store.dispatch('configurations/importConfiguration', configuration);
|
|
227
|
+
await store.dispatch('configurations/searchConfigurations', projectId.value);
|
|
253
228
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
return {
|
|
296
|
-
ADD_ICON,
|
|
297
|
-
BACK_ICON,
|
|
298
|
-
INFO_ICON,
|
|
299
|
-
navigateTo,
|
|
300
|
-
displayConfigurationDialog,
|
|
301
|
-
importConfiguration,
|
|
302
|
-
formatDate,
|
|
303
|
-
emitRefreshConfigurationEvent,
|
|
304
|
-
skipQuestion,
|
|
305
|
-
validMultiSelect,
|
|
306
|
-
showImportConfigurationDialog,
|
|
307
|
-
selectedConfigurations,
|
|
308
|
-
configurationImportSuccess,
|
|
309
|
-
configurationImportError,
|
|
310
|
-
callAction,
|
|
311
|
-
EventTypeEnum,
|
|
312
|
-
formatEvent,
|
|
313
|
-
};
|
|
314
|
-
},
|
|
315
|
-
});
|
|
229
|
+
if (store.getters['configurations/getConfigurationImportSuccess']) {
|
|
230
|
+
configurationImportSuccess.value = true;
|
|
231
|
+
} else if (store.getters['configurations/getConfigurationImportError']) {
|
|
232
|
+
configurationImportError.value = true;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const formatDate = (date: string) => {
|
|
237
|
+
return format(new Date(date), 'dd/MM/yyyy');
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const emitRefreshConfigurationEvent = () => {
|
|
241
|
+
store.dispatch('configurations/loadConfigurations', { projectId: projectId.value });
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const skipQuestion = (button: ConfigurationsImportSkippable) => {
|
|
245
|
+
store.dispatch('sendEventToBus', { code: 'SKIP-IMPORT-SIMULATIONS', payload: { projectId: projectId.value } });
|
|
246
|
+
emit(props.completedEventName, {
|
|
247
|
+
answers: {},
|
|
248
|
+
nextStep: button.nextStep,
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const validMultiSelect = (multiSelectOptions: ConfigurationsImportMultiSelectAction) => {
|
|
253
|
+
emit(props.completedEventName, {
|
|
254
|
+
answers: selectedConfigurations.value,
|
|
255
|
+
nextStep: multiSelectOptions.nextStep,
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const callAction = (action: PayloadAction) => {
|
|
260
|
+
if (action.code != '__BACK__') {
|
|
261
|
+
emit('step-completed', {
|
|
262
|
+
answers: [],
|
|
263
|
+
nextStep: action,
|
|
264
|
+
});
|
|
265
|
+
} else {
|
|
266
|
+
emit('go-back');
|
|
267
|
+
}
|
|
268
|
+
};
|
|
316
269
|
</script>
|
|
317
270
|
|
|
318
271
|
<style lang="scss" scoped>
|
|
@@ -13,23 +13,11 @@
|
|
|
13
13
|
"errorTitle": "Le plan 3D n’a pas pu être importé",
|
|
14
14
|
"errorText": "Une erreur est survenue"
|
|
15
15
|
}
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"callToActions": [
|
|
19
|
-
{
|
|
20
|
-
"label": "Précédent",
|
|
21
|
-
"theme": "bordered-primary-02",
|
|
22
|
-
"nextStep": {
|
|
23
|
-
"code": "__BACK__"
|
|
24
|
-
}
|
|
25
16
|
},
|
|
26
|
-
{
|
|
27
|
-
"
|
|
28
|
-
"nextStep": {
|
|
29
|
-
"code": "LMFR_BATHROOM_DOWNLOAD"
|
|
30
|
-
}
|
|
17
|
+
"nextStep": {
|
|
18
|
+
"code": "LMFR_BATHROOM_DOWNLOAD"
|
|
31
19
|
}
|
|
32
|
-
|
|
20
|
+
},
|
|
33
21
|
"skippable": [
|
|
34
22
|
{
|
|
35
23
|
"isAnswer": true,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface DimensionsInputValidation {
|
|
2
|
+
lengthMinValue?: number;
|
|
3
|
+
lengthMaxValue?: number;
|
|
4
|
+
widthMinValue?: number;
|
|
5
|
+
widthMaxValue?: number;
|
|
6
|
+
lengthMaxErrorMessage?: string;
|
|
7
|
+
lengthMinErrorMessage?: string;
|
|
8
|
+
widthMaxErrorMessage?: string;
|
|
9
|
+
widthMinErrorMessage?: string;
|
|
10
|
+
requiredErrorMessage?: string;
|
|
11
|
+
thresholdsIncluded?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DimensionsInputViewModel {
|
|
15
|
+
label?: string;
|
|
16
|
+
image?: string;
|
|
17
|
+
backLabel?: string;
|
|
18
|
+
lengthPlaceholder?: string;
|
|
19
|
+
widthPlaceholder?: string;
|
|
20
|
+
actionLabel?: string;
|
|
21
|
+
validation: DimensionsInputValidation;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DimensionsInputPayload {
|
|
25
|
+
viewModel: DimensionsInputViewModel;
|
|
26
|
+
value?: { length: string; width: string };
|
|
27
|
+
defaultDecoratorValue?: string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { nestedAppDecorator } from '../../../../../.storybook/nested-app-decorator';
|
|
2
|
+
import { ArgsTable, Canvas, Meta, Source, Story } from '@storybook/addon-docs';
|
|
3
|
+
import MPbDimensionsInput from './MPbDimensionsInput';
|
|
4
|
+
import DEFAULT_PAYLOAD from './default-payload.json';
|
|
5
|
+
|
|
6
|
+
<Meta
|
|
7
|
+
title="Project Booster/Rework/Questions/MPbDimensionsInput 🦠"
|
|
8
|
+
component={MPbDimensionsInput}
|
|
9
|
+
argTypes={{
|
|
10
|
+
'payload': {
|
|
11
|
+
table: {
|
|
12
|
+
defaultValue: {
|
|
13
|
+
summary: 'object',
|
|
14
|
+
detail: JSON.stringify(DEFAULT_PAYLOAD, null, ' '),
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
control: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
'dynamic event name according to completedEventName prop': {
|
|
22
|
+
table: {
|
|
23
|
+
defaultValue: {
|
|
24
|
+
summary: 'Event payload',
|
|
25
|
+
detail: JSON.stringify({ answers: [{ projectName: 'My project name', optin: false }] }, null, ' '),
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
'onStepCompleted': {
|
|
30
|
+
action: 'Step completed',
|
|
31
|
+
table: { disable: true },
|
|
32
|
+
},
|
|
33
|
+
}}
|
|
34
|
+
decorators={[nestedAppDecorator({}, [])]}
|
|
35
|
+
parameters={{ layout: 'fullscreen' }}
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
# 🦠 `MPbDimensionsInput` - Components
|
|
39
|
+
|
|
40
|
+
[](https://github.com/adeo/project-booster-vue/tree/master/src/components/question)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
The `MPbDimensionsInput` Vue component allows to fill multiple dimension. It
|
|
45
|
+
is customizable through the payload property. It has the same
|
|
46
|
+
behaviour as the `PbQuestion` component and is designed to work in scenarii.
|
|
47
|
+
|
|
48
|
+
It has a default provided payload, used in the Sandbox below.
|
|
49
|
+
|
|
50
|
+
The input field is automatically focused.
|
|
51
|
+
|
|
52
|
+
The back button will make `vue-router` trigger the history back feature from the browser. It can be hidden with the
|
|
53
|
+
`showBackButton` flag.
|
|
54
|
+
|
|
55
|
+
# `MPbDimensionsInput` - Component props
|
|
56
|
+
|
|
57
|
+
export const TemplateSandbox = (args, { argTypes }) => ({
|
|
58
|
+
props: Object.keys(argTypes),
|
|
59
|
+
components: { MPbDimensionsInput },
|
|
60
|
+
setup() {
|
|
61
|
+
return { args };
|
|
62
|
+
},
|
|
63
|
+
template: `<m-pb-dimensions-input
|
|
64
|
+
style="width:720px; margin:0 auto;"
|
|
65
|
+
:payload="args.payload"
|
|
66
|
+
:show-back-button="args.showBackButton"
|
|
67
|
+
:answers="args.answers"
|
|
68
|
+
:runtime-options="args.runtimeOptions"
|
|
69
|
+
:completed-event-name="args.completedEventName"
|
|
70
|
+
@step-completed="args.onStepCompleted"
|
|
71
|
+
/>`,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
<Canvas>
|
|
75
|
+
<Story name="101 Sandbox" args={{ payload: DEFAULT_PAYLOAD }}>
|
|
76
|
+
{TemplateSandbox.bind({})}
|
|
77
|
+
</Story>
|
|
78
|
+
</Canvas>
|
|
79
|
+
|
|
80
|
+
<ArgsTable story="101 Sandbox" />
|
|
81
|
+
|
|
82
|
+
# `MPbDimensionsInput` - Features
|
|
83
|
+
|
|
84
|
+
## Customization
|
|
85
|
+
|
|
86
|
+
It is possible to customize the component default behaviour by **overriding** a property in the provided `payload` property.
|
|
87
|
+
|
|
88
|
+
Here is the default payload:
|
|
89
|
+
|
|
90
|
+
<Source language="json" code={JSON.stringify(DEFAULT_PAYLOAD, null, ' ')} />
|
|
91
|
+
|
|
92
|
+
Here is the payload with overridden values:
|
|
93
|
+
|
|
94
|
+
export const overridenLabelsPayload = {
|
|
95
|
+
viewModel: {
|
|
96
|
+
backLabel: 'Retour',
|
|
97
|
+
label: 'Quelles sont les dimensions de cette pièce ?',
|
|
98
|
+
lengthPlaceholder: 'Longueur',
|
|
99
|
+
widthPlaceholder: 'Largeur',
|
|
100
|
+
actionLabel: 'Valider',
|
|
101
|
+
image: 'https://upload.wikimedia.org/wikipedia/commons/f/f8/Lille_vue_gd_place.JPG',
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
<Source language="json" code={JSON.stringify(overridenLabelsPayload, null, ' ')} />
|
|
106
|
+
|
|
107
|
+
<Canvas>
|
|
108
|
+
<Story
|
|
109
|
+
name="Showcase - feature customize"
|
|
110
|
+
parameters={{ controls: { disable: true } }}
|
|
111
|
+
args={{ payload: overridenLabelsPayload }}
|
|
112
|
+
>
|
|
113
|
+
{TemplateSandbox.bind({})}
|
|
114
|
+
</Story>
|
|
115
|
+
</Canvas>
|
|
116
|
+
|
|
117
|
+
## Value injection from a previous answer with default value fallback
|
|
118
|
+
|
|
119
|
+
It is possible to inject a value for the component from a previous answer. To do so, add a `value` to the component
|
|
120
|
+
`payload`. The value should have the same structure as the component anwser when completed (See event payload in the
|
|
121
|
+
[Sandbox story](#pbamountinput---component-props)) :
|
|
122
|
+
|
|
123
|
+
export const valuePayload = {
|
|
124
|
+
value: {
|
|
125
|
+
length: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForLength')}",
|
|
126
|
+
width: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForWidth')}",
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
The `getAnswerValue` function allows to retrieve a value from one provided answer. To retrieve a value, the first
|
|
131
|
+
parameter is the answer Id, the second is an optionnal path to extract a spcific value.
|
|
132
|
+
|
|
133
|
+
<Source language="json" code={JSON.stringify(valuePayload, null, ' ')} />
|
|
134
|
+
|
|
135
|
+
A `defaultDecoratorValue` value can be added as a fallback when no previous answer is found. When no default value is provided and no answer
|
|
136
|
+
is found, the component value will be empty :
|
|
137
|
+
|
|
138
|
+
export const valueWithFallbackPayload = {
|
|
139
|
+
defaultDecoratorValue: {
|
|
140
|
+
length: '2',
|
|
141
|
+
width: '2.5',
|
|
142
|
+
},
|
|
143
|
+
value: {
|
|
144
|
+
length: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForLength') || defaultValue.length}",
|
|
145
|
+
width: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForWidth') || defaultValue.width}",
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
<Source language="json" code={JSON.stringify(valueWithFallbackPayload, null, ' ')} />
|
|
150
|
+
|
|
151
|
+
The `getAnswerValue` function allows to retrieve a value from one provided answer. To retrieve a value, the first
|
|
152
|
+
parameter is the answer's id, the second is an optional path to extract a specific value.
|
|
153
|
+
|
|
154
|
+
It will try to find a value in a previous answer for a question with id `LMFR_PREVIOUS_QUESTION`,
|
|
155
|
+
provided thanks to the `answers` prop. If no value is found, it will use the `defaultDecoratorValue` as a fallback.
|
|
156
|
+
|
|
157
|
+
export const previousAnswers = {
|
|
158
|
+
LMFR_PREVIOUS_QUESTION: [
|
|
159
|
+
{
|
|
160
|
+
pathForLength: '4.56',
|
|
161
|
+
pathForWidth: '7.89',
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
<Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
|
|
167
|
+
|
|
168
|
+
<Canvas>
|
|
169
|
+
<Story
|
|
170
|
+
name="Showcase - Feature previous value from answer"
|
|
171
|
+
parameters={{ controls: { disable: true } }}
|
|
172
|
+
args={{
|
|
173
|
+
payload: valuePayload,
|
|
174
|
+
answers: new Map(Object.entries(previousAnswers)),
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
{TemplateSandbox.bind({})}
|
|
178
|
+
</Story>
|
|
179
|
+
</Canvas>
|
|
180
|
+
|
|
181
|
+
When no answer is found, the default value fallback is used:
|
|
182
|
+
|
|
183
|
+
<Canvas>
|
|
184
|
+
<Story
|
|
185
|
+
name="Showcase - Feature previous value from default"
|
|
186
|
+
parameters={{ controls: { disable: true } }}
|
|
187
|
+
args={{ payload: valueWithFallbackPayload }}
|
|
188
|
+
>
|
|
189
|
+
{TemplateSandbox.bind({})}
|
|
190
|
+
</Story>
|
|
191
|
+
</Canvas>
|
|
192
|
+
|
|
193
|
+
## Custom validation
|
|
194
|
+
|
|
195
|
+
It is possible to customize the input field validation. To do so, provide a `validation` property to the `viewModel`.
|
|
196
|
+
|
|
197
|
+
The default `validation` object is:
|
|
198
|
+
|
|
199
|
+
<Source language="json" code={JSON.stringify(DEFAULT_PAYLOAD.viewModel.validation, null, ' ')} />
|
|
200
|
+
|
|
201
|
+
It is possible to customize those values:
|
|
202
|
+
|
|
203
|
+
export const customValidation = {
|
|
204
|
+
viewModel: {
|
|
205
|
+
validation: {
|
|
206
|
+
lengthMinValue: 1,
|
|
207
|
+
lengthMaxValue: 10,
|
|
208
|
+
thresholdsIncluded: true,
|
|
209
|
+
widthMinValue: 1,
|
|
210
|
+
widthMaxValue: 10,
|
|
211
|
+
lengthMaxErrorMessage: 'La longueur doit être inférieure à 10m',
|
|
212
|
+
lengthMinErrorMessage: 'La longueur doit être supérieure à 1m',
|
|
213
|
+
widthMaxErrorMessage: 'La largeur doit être inférieure à 10m',
|
|
214
|
+
widthMinErrorMessage: 'La largeur doit être supérieure à 1m',
|
|
215
|
+
notValidNumberMessage: 'Veuillez ne saisir que des chiffres',
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
<Source language="json" code={JSON.stringify(customValidation, null, ' ')} />
|
|
221
|
+
|
|
222
|
+
<Canvas>
|
|
223
|
+
<Story
|
|
224
|
+
name="Showcase - Feature custom validation"
|
|
225
|
+
parameters={{ controls: { disable: true }, storyshots: { disable: true } }}
|
|
226
|
+
args={{ payload: customValidation }}
|
|
227
|
+
>
|
|
228
|
+
{TemplateSandbox.bind({})}
|
|
229
|
+
</Story>
|
|
230
|
+
</Canvas>
|