project-booster-vue 9.16.2 → 9.17.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-booster-vue",
3
- "version": "9.16.2",
3
+ "version": "9.17.1",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -53,6 +53,14 @@
53
53
  Vous retrouverez ici vos simulation de budgets pour ce projet
54
54
  </div>
55
55
  </m-flex>
56
+ <m-flex class="pb-configurations-section__link-container" v-if="readOnly && project">
57
+ <m-link
58
+ class="pb-configurations-section__link-portal-oaa"
59
+ label="Lien vers le portail OAA"
60
+ size="s"
61
+ @click="window.open(linkPortalOaa, '_blank')"
62
+ />
63
+ </m-flex>
56
64
  </m-flex>
57
65
  </template>
58
66
 
@@ -64,6 +72,7 @@ import MFlex from '../../mozaic/flex/MFlex.vue';
64
72
  import PbAnimableLoader from '../../loader/PbAnimableLoader.vue';
65
73
  import PbConfigurationsList, { CONFIGURATION_ANIMATION_DURATION } from '../list/PbConfigurationsList.vue';
66
74
  import { mapGetters } from 'vuex';
75
+ import MLink from '../../mozaic/link/MLink.vue';
67
76
 
68
77
  export default defineComponent({
69
78
  name: 'PbConfigurationsSection',
@@ -73,6 +82,7 @@ export default defineComponent({
73
82
  MFlex,
74
83
  PbAnimableLoader,
75
84
  PbConfigurationsList,
85
+ MLink,
76
86
  },
77
87
 
78
88
  props: {
@@ -97,6 +107,14 @@ export default defineComponent({
97
107
  configurationsPerPageCount: 'getConfigurationsPerPageCount',
98
108
  hasStillConfigurations: 'hasStillConfigurations',
99
109
  }),
110
+ ...mapGetters('projects', {
111
+ project: 'getProject',
112
+ }),
113
+ linkPortalOaa() {
114
+ return this.project
115
+ ? `http://rcloset.fr.corp.leroymerlin.com:81/page_tunnel_oaa/?mag=${this.project.store}`
116
+ : null;
117
+ },
100
118
  },
101
119
 
102
120
  methods: {
@@ -7,7 +7,8 @@
7
7
  :left-icon="BACK_ICON"
8
8
  :class="{
9
9
  'pb-question__back-button': true,
10
- 'pb-question__back-button--hidden': !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
10
+ 'pb-question__back-button--hidden':
11
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
11
12
  }"
12
13
  @click="navigateTo(payload.viewModel)"
13
14
  />
@@ -19,10 +20,10 @@
19
20
  <div
20
21
  v-if="payload.viewModel.label"
21
22
  class="pb-question__title"
22
- v-html="decorate(payload.viewModel.label, payload.defaultDecoratorValue)"
23
+ v-html="decorate(answers, runtimeOptions, payload.viewModel.label, payload.defaultDecoratorValue)"
23
24
  />
24
25
  <div v-if="payload.viewModel.subtitle" class="pb-question__subtitle">
25
- {{ decorate(payload.viewModel.subtitle, payload.defaultDecoratorValue) }}
26
+ {{ decorate(answers, runtimeOptions, payload.viewModel.subtitle, payload.defaultDecoratorValue) }}
26
27
  <m-link
27
28
  v-if="payload.viewModel.video"
28
29
  :label="payload.viewModel.video.label"
@@ -35,14 +36,14 @@
35
36
  <div class="pb-question__video-block-image-container">
36
37
  <m-image
37
38
  class="pb-question__video-block-image"
38
- :src="decorate(payload.viewModel.videoBlock.image)"
39
+ :src="decorate(answers, runtimeOptions, payload.viewModel.videoBlock.image)"
39
40
  cover
40
41
  />
41
42
  </div>
42
43
  <div class="pb-question__video-block-buttons-container">
43
44
  <m-button
44
- :label="decorate(payload.viewModel.videoBlock.buttonLabel)"
45
- :left-icon="decorate(payload.viewModel.videoBlock.icon)"
45
+ :label="decorate(answers, runtimeOptions, payload.viewModel.videoBlock.buttonLabel)"
46
+ :left-icon="decorate(answers, runtimeOptions, payload.viewModel.videoBlock.icon)"
46
47
  theme="bordered-neutral"
47
48
  @click="displayVideoGuide('')"
48
49
  />
@@ -71,25 +72,47 @@
71
72
  :is="payload.viewModel.answersComponent"
72
73
  v-if="payload.viewModel.answersComponent !== 'MButton'"
73
74
  class="pb-question__answer__component"
74
- :image="decorate(answer.viewModel.image, payload.defaultDecoratorValue)"
75
- :image-title="decorate(answer.viewModel.imageTitle, payload.defaultDecoratorValue)"
76
- :image-ratio="decorate(answer.viewModel.imageRatio, payload.defaultDecoratorValue)"
77
- :flag-label="decorate(answer.viewModel.flagLabel, payload.defaultDecoratorValue)"
78
- :hero="decorate(answer.viewModel.hero, payload.defaultDecoratorValue)"
79
- :title="decorate(answer.viewModel.title, payload.defaultDecoratorValue)"
80
- :text="decorate(answer.viewModel.text, payload.defaultDecoratorValue)"
81
- :button-label="decorate(answer.viewModel.buttonLabel, payload.defaultDecoratorValue)"
82
- :button-href="decorate(answer.viewModel.href, payload.defaultDecoratorValue)"
83
- :link-label="decorate(answer.viewModel.linkLabel, payload.defaultDecoratorValue)"
84
- :type-icon="decorate(answer.viewModel.typeIcon, payload.defaultDecoratorValue)"
85
- :card-min-ratio="decorate(answer.viewModel.cardMinRatio, payload.defaultDecoratorValue)"
86
- :align-vertical="decorate(answer.viewModel.alignVertical, payload.defaultDecoratorValue)"
87
- :align-horizontal="decorate(answer.viewModel.alignHorizontal, payload.defaultDecoratorValue)"
88
- :align-text="decorate(answer.viewModel.alignText, payload.defaultDecoratorValue)"
75
+ :image="decorate(answers, runtimeOptions, answer.viewModel.image, payload.defaultDecoratorValue)"
76
+ :image-title="
77
+ decorate(answers, runtimeOptions, answer.viewModel.imageTitle, payload.defaultDecoratorValue)
78
+ "
79
+ :image-ratio="
80
+ decorate(answers, runtimeOptions, answer.viewModel.imageRatio, payload.defaultDecoratorValue)
81
+ "
82
+ :flag-label="
83
+ decorate(answers, runtimeOptions, answer.viewModel.flagLabel, payload.defaultDecoratorValue)
84
+ "
85
+ :hero="decorate(answers, runtimeOptions, answer.viewModel.hero, payload.defaultDecoratorValue)"
86
+ :title="decorate(answers, runtimeOptions, answer.viewModel.title, payload.defaultDecoratorValue)"
87
+ :text="decorate(answers, runtimeOptions, answer.viewModel.text, payload.defaultDecoratorValue)"
88
+ :button-label="
89
+ decorate(answers, runtimeOptions, answer.viewModel.buttonLabel, payload.defaultDecoratorValue)
90
+ "
91
+ :button-href="decorate(answers, runtimeOptions, answer.viewModel.href, payload.defaultDecoratorValue)"
92
+ :link-label="
93
+ decorate(answers, runtimeOptions, answer.viewModel.linkLabel, payload.defaultDecoratorValue)
94
+ "
95
+ :type-icon="
96
+ decorate(answers, runtimeOptions, answer.viewModel.typeIcon, payload.defaultDecoratorValue)
97
+ "
98
+ :card-min-ratio="
99
+ decorate(answers, runtimeOptions, answer.viewModel.cardMinRatio, payload.defaultDecoratorValue)
100
+ "
101
+ :align-vertical="
102
+ decorate(answers, runtimeOptions, answer.viewModel.alignVertical, payload.defaultDecoratorValue)
103
+ "
104
+ :align-horizontal="
105
+ decorate(answers, runtimeOptions, answer.viewModel.alignHorizontal, payload.defaultDecoratorValue)
106
+ "
107
+ :align-text="
108
+ decorate(answers, runtimeOptions, answer.viewModel.alignText, payload.defaultDecoratorValue)
109
+ "
89
110
  :selectable="!!payload.multiSelect"
90
111
  :selected="selectedAnswers.get(answer.code)"
91
112
  :disabled="isAnswerDisabled(answer)"
92
- :flattened="decorate(answer.viewModel.flattened, payload.defaultDecoratorValue)"
113
+ :flattened="
114
+ decorate(answers, runtimeOptions, answer.viewModel.flattened, payload.defaultDecoratorValue)
115
+ "
93
116
  @card-click="answer.viewModel.href ? '' : selectAnswer(payload.code, answer)"
94
117
  @button-click="handleAnswerButtonClick"
95
118
  @link-click="handleLinkClick(answer)"
@@ -97,14 +120,20 @@
97
120
  <m-button
98
121
  v-else
99
122
  :disabled="isAnswerDisabled(answer)"
100
- :label="decorate(answer.viewModel.label, payload.defaultDecoratorValue)"
101
- :type="decorate(answer.viewModel.type, payload.defaultDecoratorValue)"
102
- :theme="decorate(answer.viewModel.theme, payload.defaultDecoratorValue)"
103
- :left-icon="decorate(answer.viewModel.leftIcon, payload.defaultDecoratorValue)"
104
- :right-icon="decorate(answer.viewModel.rightIcon, payload.defaultDecoratorValue)"
105
- :href="decorate(answer.viewModel.href, payload.defaultDecoratorValue)"
106
- :width="decorate(answer.viewModel.width, payload.defaultDecoratorValue)"
107
- :widthFromM="decorate(answer.viewModel.widthFromM, payload.defaultDecoratorValue)"
123
+ :label="decorate(answers, runtimeOptions, answer.viewModel.label, payload.defaultDecoratorValue)"
124
+ :type="decorate(answers, runtimeOptions, answer.viewModel.type, payload.defaultDecoratorValue)"
125
+ :theme="decorate(answers, runtimeOptions, answer.viewModel.theme, payload.defaultDecoratorValue)"
126
+ :left-icon="
127
+ decorate(answers, runtimeOptions, answer.viewModel.leftIcon, payload.defaultDecoratorValue)
128
+ "
129
+ :right-icon="
130
+ decorate(answers, runtimeOptions, answer.viewModel.rightIcon, payload.defaultDecoratorValue)
131
+ "
132
+ :href="decorate(answers, runtimeOptions, answer.viewModel.href, payload.defaultDecoratorValue)"
133
+ :width="decorate(answers, runtimeOptions, answer.viewModel.width, payload.defaultDecoratorValue)"
134
+ :widthFromM="
135
+ decorate(answers, runtimeOptions, answer.viewModel.widthFromM, payload.defaultDecoratorValue)
136
+ "
108
137
  @click="selectAnswer(payload.code, answer)"
109
138
  />
110
139
  </div>
@@ -296,6 +325,50 @@ const BACK_ICON =
296
325
  const INFO_ICON =
297
326
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Notification_Information_24px.svg';
298
327
 
328
+ // Function used by the scenario conditions
329
+ const getAnswerValue = (answers: Map<string, ScenarioStepAnswer[]>) => {
330
+ return (answerCode: string, path: string) => {
331
+ let answerValue: ScenarioStepAnswer | undefined = undefined;
332
+ if (answers?.get(answerCode)) {
333
+ const answerValues = answers.get(answerCode) ?? [];
334
+ answerValue = objectPath.get(answerValues[0], path);
335
+ }
336
+ return answerValue;
337
+ };
338
+ };
339
+
340
+ export const doEval = (
341
+ answers: Map<string, ScenarioStepAnswer[]>,
342
+ valueToEval: string,
343
+ defaultValue: string,
344
+ runtimeOptions: any,
345
+ ) => {
346
+ return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
347
+ this,
348
+ getAnswerValue(answers),
349
+ answers,
350
+ defaultValue,
351
+ runtimeOptions,
352
+ );
353
+ };
354
+
355
+ export const decorate = (
356
+ answers: Map<string, ScenarioStepAnswer[]>,
357
+ runtimeOptions = {},
358
+ valueToDecorate: string,
359
+ defaultValue = '',
360
+ ) => {
361
+ if (valueToDecorate) {
362
+ valueToDecorate = `\`${valueToDecorate}\``;
363
+ try {
364
+ return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
365
+ } catch (error) {
366
+ return valueToDecorate || defaultValue;
367
+ }
368
+ }
369
+ return valueToDecorate;
370
+ };
371
+
299
372
  export default defineComponent({
300
373
  name: 'PbQuestion',
301
374
 
@@ -385,6 +458,7 @@ export default defineComponent({
385
458
  dialog: undefined as undefined | ScenarioStepAnswerDialog,
386
459
  displayVideo: false,
387
460
  pbQuestionActionsButtonsMaxHeight: 0,
461
+ decorate,
388
462
  }),
389
463
 
390
464
  computed: {
@@ -474,33 +548,6 @@ export default defineComponent({
474
548
 
475
549
  this.updatePbQuestionActionsButtonsSizeHeight();
476
550
  },
477
- decorate(valueToDecorate: string, defaultValue = '') {
478
- if (valueToDecorate) {
479
- valueToDecorate = `\`${valueToDecorate}\``;
480
- try {
481
- return this.doEval(valueToDecorate, defaultValue);
482
- } catch (e) {
483
- console.error(e);
484
- return valueToDecorate;
485
- }
486
- }
487
- return valueToDecorate;
488
- },
489
- decorateBoolean(valueToDecorate: string, defaultValue = false) {
490
- if (valueToDecorate) {
491
- return this.doEval(valueToDecorate, defaultValue);
492
- }
493
- return valueToDecorate;
494
- },
495
- doEval(valueToEval: string, defaultValue: string | boolean) {
496
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
497
- this,
498
- this.getAnswerValue,
499
- Object.fromEntries(this.answers),
500
- defaultValue,
501
- this.runtimeOptions,
502
- );
503
- },
504
551
  isShowingFooter(viewModel: ScenarioStepAnswerViewModel) {
505
552
  return viewModel.footer && areConditionsValid(viewModel.footer.conditions!, this.answers, this.runtimeOptions);
506
553
  },
@@ -548,14 +595,6 @@ export default defineComponent({
548
595
  });
549
596
  },
550
597
  // Function used by the scenario conditions
551
- getAnswerValue(answerCode: string, path: string) {
552
- if (!this.answers.get(answerCode) || this.answers.get(answerCode)?.length === 0) {
553
- return null;
554
- }
555
-
556
- return objectPath.get(this.answers.get(answerCode)?.at(0) as any, path);
557
- },
558
- // Function used by the scenario conditions
559
598
  selectedAnswersNumber() {
560
599
  let selectedAnswersNumber = 0;
561
600
 
@@ -642,7 +681,7 @@ export default defineComponent({
642
681
  },
643
682
  navigateTo(viewModel: ScenarioStepViewModel) {
644
683
  if (viewModel.backLink) {
645
- window.location = this.decorate(viewModel.backLink);
684
+ window.location = decorate(this.answers, this.runtimeOptions, viewModel.backLink, '');
646
685
  } else {
647
686
  /**
648
687
  * Emitted when go back link is clicked
@@ -120,7 +120,7 @@ It is possible to inject a value for the component from a previous answer. To do
120
120
 
121
121
  export const valuePayload = {
122
122
  value: {
123
- amount: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForAmount')",
123
+ amount: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForAmount')}",
124
124
  },
125
125
  };
126
126
 
@@ -137,7 +137,7 @@ export const valueWithFallbackPayload = {
137
137
  amount: '123',
138
138
  },
139
139
  value: {
140
- amount: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForAmount') || defaultValue.amount",
140
+ amount: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForAmount') || defaultValue.amount}",
141
141
  },
142
142
  };
143
143
 
@@ -149,13 +149,15 @@ parameter is the answer Id, the second is an optionnal path to extract a spcific
149
149
  It will try to find a value in a previous answer for a question with id `LMFR_PREVIOUS_QUESTION`,
150
150
  provided thanks to the `answers` prop. If no value is found, it will use the `defaultDecoratorValue` as a fallback.
151
151
 
152
- export const previousAnswers = {
153
- LMFR_PREVIOUS_QUESTION: [
154
- {
155
- pathForAmount: '456',
156
- },
157
- ],
158
- };
152
+ export const previousAnswers = new Map(
153
+ Object.entries({
154
+ LMFR_PREVIOUS_QUESTION: [
155
+ {
156
+ pathForAmount: '456',
157
+ },
158
+ ],
159
+ }),
160
+ );
159
161
 
160
162
  <Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
161
163
 
@@ -7,7 +7,7 @@
7
7
  :class="{
8
8
  'pb-amount-input__back-button': true,
9
9
  'pb-amount-input__back-button--hidden':
10
- !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
10
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
11
11
  }"
12
12
  @click.once="$emit('go-back')"
13
13
  />
@@ -64,6 +64,7 @@ import MTextInput from './../../mozaic/text-input/MTextInput.vue';
64
64
  import DEFAULT_PAYLOAD from './default-payload.json';
65
65
  import { AmountInputPayload } from '@/components/question/amount-input/AmountInput';
66
66
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
67
+ import { decorate } from '@/components/question/PbQuestion.vue';
67
68
 
68
69
  const BACK_ICON =
69
70
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -85,45 +86,6 @@ const initValidation = (componentId: string, computedPayload: ComputedRef<Amount
85
86
  return validationSchema;
86
87
  };
87
88
 
88
- // Function used by the scenario conditions
89
- const getAnswerValue = (answers: Map<string, ScenarioStepAnswer[]>) => {
90
- return (answerCode: string, path: string) => {
91
- let answerValue: ScenarioStepAnswer | undefined = undefined;
92
- if (answers?.get(answerCode)) {
93
- const answerValues = answers.get(answerCode) ?? [];
94
- answerValue = objectPath.get(answerValues[0], path);
95
- }
96
- return answerValue;
97
- };
98
- };
99
-
100
- const doEval = (
101
- answers: Map<string, ScenarioStepAnswer[]>,
102
- valueToEval: string,
103
- defaultValue: string,
104
- runtimeOptions: any,
105
- ) => {
106
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
107
- this,
108
- getAnswerValue(answers),
109
- answers,
110
- defaultValue,
111
- runtimeOptions,
112
- );
113
- };
114
-
115
- const decorate = (
116
- answers: Map<string, ScenarioStepAnswer[]>,
117
- valueToDecorate: string,
118
- defaultValue = '',
119
- runtimeOptions: any,
120
- ) => {
121
- if (valueToDecorate) {
122
- return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
123
- }
124
- return valueToDecorate;
125
- };
126
-
127
89
  const computeDefaultValue = (
128
90
  runtimeOptions: any,
129
91
  answers: Map<string, ScenarioStepAnswer[]>,
@@ -133,9 +95,9 @@ const computeDefaultValue = (
133
95
  if (computedPayload?.value?.value) {
134
96
  amount = decorate(
135
97
  answers,
98
+ runtimeOptions,
136
99
  computedPayload?.value?.value?.amount,
137
100
  computedPayload?.value?.defaultDecoratorValue,
138
- runtimeOptions,
139
101
  );
140
102
  }
141
103
  return amount;
@@ -188,7 +150,7 @@ export default defineComponent({
188
150
  */
189
151
  answers: {
190
152
  type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
191
- default: () => ({}),
153
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
192
154
  },
193
155
  },
194
156
 
@@ -132,9 +132,9 @@ export const valuePayload = {
132
132
  },
133
133
  value: {
134
134
  city: {
135
- name: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForName') || defaultValue.city.name",
136
- region: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForRegion') || defaultValue.city.region",
137
- inseeCode: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForInseeCode') || defaultValue.city.inseeCode",
135
+ name: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForName') || defaultValue.city.name}",
136
+ region: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForRegion') || defaultValue.city.region}",
137
+ inseeCode: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForInseeCode') || defaultValue.city.inseeCode}",
138
138
  },
139
139
  },
140
140
  };
@@ -159,15 +159,17 @@ parameter is the answer Id, the second is an optionnal path to extract a spcific
159
159
 
160
160
  ## Value injection from previous answer
161
161
 
162
- export const previousAnswers = {
163
- LMFR_PREVIOUS_QUESTION: [
164
- {
165
- pathForName: 'Ronchin',
166
- pathForRegion: 'Hauts-de-France',
167
- pathForInseeCode: '59507',
168
- },
169
- ],
170
- };
162
+ export const previousAnswers = new Map(
163
+ Object.entries({
164
+ LMFR_PREVIOUS_QUESTION: [
165
+ {
166
+ pathForName: 'Ronchin',
167
+ pathForRegion: 'Hauts-de-France',
168
+ pathForInseeCode: '59507',
169
+ },
170
+ ],
171
+ }),
172
+ );
171
173
 
172
174
  Reuse the same payload as for default value and add an answer object to the component props :
173
175
 
@@ -6,7 +6,8 @@
6
6
  :left-icon="BACK_ICON"
7
7
  :class="{
8
8
  'pb-city-search__back-button': true,
9
- 'pb-city-search__back-button--hidden': !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
9
+ 'pb-city-search__back-button--hidden':
10
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
10
11
  }"
11
12
  @click.once="$router.go(-1)"
12
13
  />
@@ -96,7 +97,7 @@
96
97
  </template>
97
98
 
98
99
  <script lang="ts">
99
- import { defineComponent } from 'vue';
100
+ import { defineComponent, PropType } from 'vue';
100
101
  import cloneDeep from 'lodash.clonedeep';
101
102
  import debounce from 'lodash.debounce';
102
103
  import merge from 'lodash.merge';
@@ -109,6 +110,8 @@ import MLink from '../../mozaic/link/MLink.vue';
109
110
  import MTextInput from '../../mozaic/text-input/MTextInput.vue';
110
111
  import DEFAULT_PAYLOAD from './default-payload.json';
111
112
  import { DebouncedFunc } from 'lodash-es';
113
+ import { decorate } from '@/components/question/PbQuestion.vue';
114
+ import { ScenarioStepAnswer } from '@/types/pb/Scenario';
112
115
 
113
116
  const BACK_ICON =
114
117
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -158,8 +161,8 @@ export default defineComponent({
158
161
  * The previous answers to inject
159
162
  */
160
163
  answers: {
161
- type: Object,
162
- default: () => ({}),
164
+ type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
165
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
163
166
  },
164
167
  },
165
168
 
@@ -197,9 +200,21 @@ export default defineComponent({
197
200
 
198
201
  if (this.computedPayload?.value) {
199
202
  this.selectedCity = {
200
- name: this.decorate(this?.computedPayload?.value?.city?.name, this?.computedPayload?.defaultDecoratorValue),
201
- region: this.decorate(this?.computedPayload?.value?.city?.region, this?.computedPayload?.defaultDecoratorValue),
202
- inseeCode: this.decorate(
203
+ name: decorate(
204
+ this.answers,
205
+ this.runtimeOptions,
206
+ this?.computedPayload?.value?.city?.name,
207
+ this?.computedPayload?.defaultDecoratorValue,
208
+ ),
209
+ region: decorate(
210
+ this.answers,
211
+ this.runtimeOptions,
212
+ this?.computedPayload?.value?.city?.region,
213
+ this?.computedPayload?.defaultDecoratorValue,
214
+ ),
215
+ inseeCode: decorate(
216
+ this.answers,
217
+ this.runtimeOptions,
203
218
  this?.computedPayload?.value?.city?.inseeCode,
204
219
  this?.computedPayload?.defaultDecoratorValue,
205
220
  ),
@@ -228,27 +243,6 @@ export default defineComponent({
228
243
  updateHeaderHeight() {
229
244
  this.headerHeight = this.$refs?.pbCitySearchHeader?.$el?.offsetHeight;
230
245
  },
231
- decorate(valueToDecorate: string, defaultValue = '') {
232
- if (valueToDecorate) {
233
- return this.doEval(valueToDecorate, defaultValue);
234
- }
235
- return valueToDecorate;
236
- },
237
- decorateBoolean(valueToDecorate: string, defaultValue = '') {
238
- if (valueToDecorate) {
239
- return this.doEval(valueToDecorate, defaultValue);
240
- }
241
- return valueToDecorate;
242
- },
243
- doEval(valueToEval: string, defaultValue: string) {
244
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
245
- this,
246
- this.getAnswerValue,
247
- this.answers,
248
- defaultValue,
249
- this.runtimeOptions,
250
- );
251
- },
252
246
  formatSuggestion(suggestion: google.maps.places.AutocompletePrediction) {
253
247
  let text = '';
254
248
  for (let i = 0; i < suggestion.terms.length - 1; i++) {
@@ -349,14 +343,6 @@ export default defineComponent({
349
343
  console.error(`Could not get place details for ${placeId}`, error);
350
344
  }
351
345
  },
352
- // Function used by the scenario conditions
353
- getAnswerValue(answerCode: string, path: string) {
354
- if (!this.answers[answerCode] || this.answers[answerCode].length === 0) {
355
- return null;
356
- }
357
-
358
- return objectPath.get(this.answers[answerCode][0], path);
359
- },
360
346
  async handleFormValidation() {
361
347
  /**
362
348
  * Emitted when step is completed
@@ -8,7 +8,7 @@
8
8
  :class="{
9
9
  'pb-configurations-import__back-button': true,
10
10
  'pb-configurations-import__back-button--hidden':
11
- !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
11
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
12
12
  }"
13
13
  @click="navigateTo(payload.viewModel)"
14
14
  />
@@ -174,6 +174,7 @@ import {
174
174
  } from '@/components/question/configurations-import/ConfigurationsImport';
175
175
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
176
176
  import { Configuration } from '@/types/pb/Configuration';
177
+ import { decorate } from '@/components/question/PbQuestion.vue';
177
178
 
178
179
  const BACK_ICON =
179
180
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -232,7 +233,7 @@ export default defineComponent({
232
233
  */
233
234
  answers: {
234
235
  type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
235
- default: () => ({}),
236
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
236
237
  },
237
238
  /**
238
239
  * Define the offset for question sticky bottom elements.
@@ -255,7 +256,7 @@ export default defineComponent({
255
256
 
256
257
  const navigateTo = (viewModel: ConfigurationsImportViewModel) => {
257
258
  if (viewModel.backLink) {
258
- window.location = decorate(viewModel.backLink);
259
+ window.location = decorate(props.answers, props.runtimeOptions, viewModel.backLink);
259
260
  } else {
260
261
  /**
261
262
  * Emitted when go back link is clicked
@@ -265,39 +266,6 @@ export default defineComponent({
265
266
  }
266
267
  };
267
268
 
268
- const decorate = (valueToDecorate: string, defaultValue = '') => {
269
- if (valueToDecorate) {
270
- return doEval(valueToDecorate, defaultValue);
271
- }
272
- return valueToDecorate;
273
- };
274
-
275
- const decorateBoolean = (valueToDecorate: string, defaultValue = '') => {
276
- if (valueToDecorate) {
277
- return doEval(valueToDecorate, defaultValue);
278
- }
279
- return valueToDecorate;
280
- };
281
-
282
- const doEval = (valueToEval: string, defaultValue: string) => {
283
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
284
- this,
285
- getAnswerValue,
286
- props.answers,
287
- defaultValue,
288
- props.runtimeOptions,
289
- );
290
- };
291
-
292
- const getAnswerValue = (answerCode: string, path: string) => {
293
- let answerValue: ScenarioStepAnswer | undefined = undefined;
294
- if (props.answers?.get(answerCode)) {
295
- const answerValues = props.answers.get(answerCode) ?? [];
296
- answerValue = objectPath.get(answerValues[0], path);
297
- }
298
- return answerValue;
299
- };
300
-
301
269
  const displayConfigurationDialog = () => {
302
270
  showImportConfigurationDialog.value = true;
303
271
  };
@@ -342,7 +310,6 @@ export default defineComponent({
342
310
  BACK_ICON,
343
311
  INFO_ICON,
344
312
  navigateTo,
345
- decorateBoolean,
346
313
  displayConfigurationDialog,
347
314
  importConfiguration,
348
315
  formatDate,
@@ -121,8 +121,8 @@ It is possible to inject a value for the component from a previous answer. To do
121
121
 
122
122
  export const valuePayload = {
123
123
  value: {
124
- length: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForLength')",
125
- width: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForWidth')",
124
+ length: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForLength')}",
125
+ width: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForWidth')}",
126
126
  },
127
127
  };
128
128
 
@@ -140,8 +140,8 @@ export const valueWithFallbackPayload = {
140
140
  width: '2.5',
141
141
  },
142
142
  value: {
143
- length: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForLength') || defaultValue.length",
144
- width: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForWidth') || defaultValue.width",
143
+ length: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForLength') || defaultValue.length}",
144
+ width: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForWidth') || defaultValue.width}",
145
145
  },
146
146
  };
147
147
 
@@ -153,14 +153,16 @@ parameter is the answer's id, the second is an optional path to extract a specif
153
153
  It will try to find a value in a previous answer for a question with id `LMFR_PREVIOUS_QUESTION`,
154
154
  provided thanks to the `answers` prop. If no value is found, it will use the `defaultDecoratorValue` as a fallback.
155
155
 
156
- export const previousAnswers = {
157
- LMFR_PREVIOUS_QUESTION: [
158
- {
159
- pathForLength: '4.56',
160
- pathForWidth: '7.89',
161
- },
162
- ],
163
- };
156
+ export const previousAnswers = new Map(
157
+ Object.entries({
158
+ LMFR_PREVIOUS_QUESTION: [
159
+ {
160
+ pathForLength: '4.56',
161
+ pathForWidth: '7.89',
162
+ },
163
+ ],
164
+ }),
165
+ );
164
166
 
165
167
  <Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
166
168
 
@@ -7,7 +7,7 @@
7
7
  :class="{
8
8
  'pb-dimensions-input__back-button': true,
9
9
  'pb-dimensions-input__back-button--hidden':
10
- !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
10
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
11
11
  }"
12
12
  @click.once="$emit('go-back')"
13
13
  />
@@ -102,6 +102,7 @@ import objectPath from 'object-path';
102
102
  import { ref } from 'vue';
103
103
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
104
104
  import { DimensionsInputPayload } from '@/components/question/dimensions-input/DimensionsInput';
105
+ import { decorate } from '@/components/question/PbQuestion.vue';
105
106
 
106
107
  const BACK_ICON =
107
108
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -142,77 +143,26 @@ const initValidation = (componentId: string, computedPayload: ComputedRef<Dimens
142
143
  return validationSchema;
143
144
  };
144
145
 
145
- // Function used by the scenario conditions
146
- const getAnswerValue = (answers: Map<string, ScenarioStepAnswer[]>) => {
147
- return (answerCode: string, path: string) => {
148
- let answerValue: ScenarioStepAnswer | undefined = undefined;
149
- if (answers?.get(answerCode)) {
150
- const answerValues = answers.get(answerCode) ?? [];
151
- answerValue = objectPath.get(answerValues[0], path);
152
- }
153
- return answerValue;
154
- };
155
- };
156
-
157
- const doEval = (
158
- answers: Map<string, ScenarioStepAnswer[]>,
159
- valueToEval: string,
160
- defaultValue: string,
161
- runtimeOptions: any,
162
- ) => {
163
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
164
- this,
165
- getAnswerValue(answers),
166
- answers,
167
- defaultValue,
168
- runtimeOptions,
169
- );
170
- };
171
-
172
- const decorate = (
173
- answers: Map<string, ScenarioStepAnswer[]>,
174
- valueToDecorate: string,
175
- defaultValue = '',
176
- runtimeOptions: any,
177
- ) => {
178
- if (valueToDecorate) {
179
- return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
180
- }
181
- return valueToDecorate;
182
- };
183
-
184
- const decorateBoolean = (
185
- answers: Map<string, ScenarioStepAnswer[]>,
186
- valueToDecorate: string,
187
- defaultValue = '',
188
- runtimeOptions: any,
189
- ) => {
190
- if (valueToDecorate) {
191
- return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
192
- }
193
- return valueToDecorate;
194
- };
195
-
196
146
  const computeDefaultValue = (
197
147
  runtimeOptions: any,
198
148
  answers: Map<string, ScenarioStepAnswer[]>,
199
149
  computedPayload: ComputedRef<DimensionsInputPayload>,
200
150
  ) => {
201
- let length = null;
202
- let width = null;
151
+ let length = ref(null);
152
+ let width = ref(null);
203
153
 
204
154
  if (computedPayload?.value?.value) {
205
- length = decorate(
155
+ length.value = decorate(
206
156
  answers,
157
+ runtimeOptions,
207
158
  computedPayload?.value?.value?.length,
208
159
  computedPayload?.value?.defaultDecoratorValue,
209
- runtimeOptions,
210
160
  );
211
- width = decorate(
161
+ width.value = decorate(
212
162
  answers,
163
+ runtimeOptions,
213
164
  computedPayload?.value?.value?.width,
214
165
  computedPayload?.value?.defaultDecoratorValue,
215
- runtimeOptions,
216
166
  );
217
167
  }
218
168
 
@@ -266,7 +216,7 @@ export default defineComponent({
266
216
  */
267
217
  answers: {
268
218
  type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
269
- default: () => ({}),
219
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
270
220
  },
271
221
  },
272
222
 
@@ -6,7 +6,8 @@
6
6
  :left-icon="BACK_ICON"
7
7
  :class="{
8
8
  'pb-list-select__back-button': true,
9
- 'pb-list-select__back-button--hidden': !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
9
+ 'pb-list-select__back-button--hidden':
10
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
10
11
  }"
11
12
  @click.once="$emit('go-back')"
12
13
  />
@@ -82,6 +83,7 @@ import PbItemsList from '../../items/PbItemsList.vue';
82
83
  import { sortAnswers } from '../sortAnswers';
83
84
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
84
85
  import { Item } from '@/types/pb/Item';
86
+ import { decorate } from '@/components/question/PbQuestion.vue';
85
87
 
86
88
  const BACK_ICON =
87
89
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -136,7 +138,7 @@ export default defineComponent({
136
138
  */
137
139
  answers: {
138
140
  type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
139
- default: () => ({}),
141
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
140
142
  },
141
143
  /**
142
144
  * Define the offset for question sticky bottom elements.
@@ -199,7 +201,6 @@ export default defineComponent({
199
201
  }
200
202
  return props.payload?.viewModel?.showMore?.minItemsDisplayed ?? null;
201
203
  });
202
-
203
204
  const showMoreLabel = computed(() => {
204
205
  return props.payload?.viewModel?.showMore?.label ?? 'Show more';
205
206
  });
@@ -232,7 +233,6 @@ export default defineComponent({
232
233
 
233
234
  return { label, leftIcon, rightIcon };
234
235
  });
235
-
236
236
  const submitAnswers = () => {
237
237
  const answersToSubmit = [];
238
238
  for (const answer of selectedAnswers.value) {
@@ -262,7 +262,6 @@ export default defineComponent({
262
262
  nextStep: nextStep,
263
263
  });
264
264
  };
265
-
266
265
  const skipQuestion = () => {
267
266
  /**
268
267
  * Emitted when step is completed
@@ -279,34 +278,10 @@ export default defineComponent({
279
278
  });
280
279
  };
281
280
 
282
- // Function used by the scenario conditions
283
- const doEval = (valueToEval: string, defaultValue: string) => {
284
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
285
- this,
286
- getAnswerValue,
287
- Object.fromEntries(props.answers),
288
- defaultValue,
289
- props.runtimeOptions,
290
- );
291
- };
292
-
293
- const getAnswerValue = (answerCode: string, path: string) => {
294
- const answers = props.answers.get(answerCode);
295
- if (!answers || answers.length === 0) {
296
- return null;
297
- }
298
- return objectPath.get(answers[0], path);
299
- };
300
-
301
- const decorateBoolean = (valueToDecorate: string, defaultValue = '') => {
302
- if (valueToDecorate) {
303
- return doEval(valueToDecorate, defaultValue);
304
- }
305
- return valueToDecorate;
306
- };
307
281
  onMounted(() => {
308
282
  updateSelectedAnswers();
309
283
  });
284
+
310
285
  return {
311
286
  BACK_ICON,
312
287
  INFO_ICON,
@@ -322,7 +297,6 @@ export default defineComponent({
322
297
  itemsListProps,
323
298
  skipQuestion,
324
299
  submitAnswers,
325
- decorateBoolean,
326
300
  updateSelectedAnswers,
327
301
  };
328
302
  },
@@ -146,8 +146,8 @@ It is possible to inject a value for the component from a previous answer. To do
146
146
 
147
147
  export const valuePayload = {
148
148
  value: {
149
- projectName: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName')",
150
- optin: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin')",
149
+ projectName: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName')}",
150
+ optin: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin')}",
151
151
  },
152
152
  };
153
153
 
@@ -165,8 +165,8 @@ export const valueWithFallbackPayload = {
165
165
  optin: true,
166
166
  },
167
167
  value: {
168
- projectName: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName') || defaultValue.projectName",
169
- optin: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin') || defaultValue.optin",
168
+ projectName: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName') || defaultValue.projectName}",
169
+ optin: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin') || defaultValue.optin}",
170
170
  },
171
171
  };
172
172
 
@@ -175,13 +175,15 @@ export const valueWithFallbackPayload = {
175
175
  It will try to find a value in a previous answer for a question with id `LMFR_PREVIOUS_QUESTION`,
176
176
  provided thanks to the `answers` prop. If no value is found, it will use the `defaultDecoratorValue` as a fallback.
177
177
 
178
- export const previousAnswers = {
179
- LMFR_PREVIOUS_QUESTION: [
180
- {
181
- pathForProjectName: 'Rénover la cuisine',
182
- },
183
- ],
184
- };
178
+ export const previousAnswers = new Map(
179
+ Object.entries({
180
+ LMFR_PREVIOUS_QUESTION: [
181
+ {
182
+ pathForProjectName: 'Rénover la cuisine',
183
+ },
184
+ ],
185
+ }),
186
+ );
185
187
 
186
188
  <Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
187
189
 
@@ -218,14 +220,16 @@ With optin value :
218
220
 
219
221
  `answers` prop to add a previous answer :
220
222
 
221
- export const previousAnswersWithOptin = {
222
- LMFR_PREVIOUS_QUESTION: [
223
- {
224
- pathForProjectName: 'Rénover la cuisine',
225
- pathForOptin: true,
226
- },
227
- ],
228
- };
223
+ export const previousAnswersWithOptin = new Map(
224
+ Object.entries({
225
+ LMFR_PREVIOUS_QUESTION: [
226
+ {
227
+ pathForProjectName: 'Rénover la cuisine',
228
+ pathForOptin: true,
229
+ },
230
+ ],
231
+ }),
232
+ );
229
233
 
230
234
  <Source language="json" code={JSON.stringify(previousAnswersWithOptin, null, ' ')} />
231
235
 
@@ -251,8 +255,8 @@ export const valueWithFallbackPayloadAndOptin = {
251
255
  optin: true,
252
256
  },
253
257
  value: {
254
- projectName: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName') || defaultValue.projectName",
255
- optin: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin') || defaultValue.optin",
258
+ projectName: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName') || defaultValue.projectName}",
259
+ optin: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin') || defaultValue.optin}",
256
260
  },
257
261
  };
258
262
 
@@ -6,7 +6,8 @@
6
6
  :left-icon="BACK_ICON"
7
7
  :class="{
8
8
  'pb-name-input__back-button': true,
9
- 'pb-name-input__back-button--hidden': !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
9
+ 'pb-name-input__back-button--hidden':
10
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
10
11
  }"
11
12
  @click.once="$emit('go-back')"
12
13
  />
@@ -60,6 +61,7 @@ import MToggle from '../../mozaic/toggle/MToggle.vue';
60
61
  import DEFAULT_PAYLOAD from './default-payload.json';
61
62
  import { NameInputPayload } from '@/components/question/name-input/NameInput';
62
63
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
64
+ import { decorate } from '@/components/question/PbQuestion.vue';
63
65
 
64
66
  const BACK_ICON =
65
67
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -84,58 +86,6 @@ const initValidation = (componentId: string, computedPayload: ComputedRef<NameIn
84
86
  });
85
87
  return validationSchema;
86
88
  };
87
-
88
- // Function used by the scenario conditions
89
- const getAnswerValue = (answers: Map<string, ScenarioStepAnswer[]>) => {
90
- return (answerCode: string, path: string) => {
91
- let answerValue: ScenarioStepAnswer | undefined = undefined;
92
- if (answers?.get(answerCode)) {
93
- const answerValues = answers.get(answerCode) ?? [];
94
- answerValue = objectPath.get(answerValues[0], path);
95
- }
96
- return answerValue;
97
- };
98
- };
99
-
100
- const doEval = (
101
- answers: Map<string, ScenarioStepAnswer[]>,
102
- valueToEval: string,
103
- defaultValue: string,
104
- runtimeOptions: any,
105
- ) => {
106
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
107
- this,
108
- getAnswerValue(answers),
109
- answers,
110
- defaultValue,
111
- runtimeOptions,
112
- );
113
- };
114
-
115
- const decorate = (
116
- answers: Map<string, ScenarioStepAnswer[]>,
117
- valueToDecorate: string,
118
- defaultValue = '',
119
- runtimeOptions: any,
120
- ) => {
121
- if (valueToDecorate) {
122
- return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
123
- }
124
- return valueToDecorate;
125
- };
126
-
127
- const decorateBoolean = (
128
- answers: Map<string, ScenarioStepAnswer[]>,
129
- valueToDecorate: string,
130
- defaultValue = '',
131
- runtimeOptions: any,
132
- ) => {
133
- if (valueToDecorate) {
134
- return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
135
- }
136
- return valueToDecorate;
137
- };
138
-
139
89
  const computeDefaultValue = (
140
90
  runtimeOptions: any,
141
91
  answers: Map<string, ScenarioStepAnswer[]>,
@@ -147,15 +97,15 @@ const computeDefaultValue = (
147
97
  if (computedPayload?.value?.value) {
148
98
  name.value = decorate(
149
99
  answers,
100
+ runtimeOptions,
150
101
  computedPayload?.value?.value?.projectName,
151
102
  computedPayload?.value?.defaultDecoratorValue,
152
- runtimeOptions,
153
103
  );
154
104
  optin.value = decorate(
155
105
  answers,
106
+ runtimeOptions,
156
107
  computedPayload?.value?.value?.optin,
157
108
  computedPayload?.value?.defaultDecoratorValue,
158
- runtimeOptions,
159
109
  );
160
110
  }
161
111
 
@@ -209,7 +159,7 @@ export default defineComponent({
209
159
  */
210
160
  answers: {
211
161
  type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
212
- default: () => ({}),
162
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
213
163
  },
214
164
  },
215
165
 
@@ -122,7 +122,7 @@ It is possible to inject a value for the component from a previous answer. To do
122
122
 
123
123
  export const valuePayload = {
124
124
  value: {
125
- space: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForSpace')",
125
+ space: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForSpace')}",
126
126
  },
127
127
  };
128
128
 
@@ -139,7 +139,7 @@ export const valueWithFallbackPayload = {
139
139
  space: '123',
140
140
  },
141
141
  value: {
142
- space: "getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForSpace') || defaultValue.space",
142
+ space: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForSpace') || defaultValue.space}",
143
143
  },
144
144
  };
145
145
 
@@ -148,13 +148,15 @@ export const valueWithFallbackPayload = {
148
148
  It will try to find a value in a previous answer for a question with id `LMFR_PREVIOUS_QUESTION`,
149
149
  provided thanks to the `answers` prop. If no value is found, it will use the `defaultDecoratorValue` as a fallback.
150
150
 
151
- export const previousAnswers = {
152
- LMFR_PREVIOUS_QUESTION: [
153
- {
154
- pathForSpace: '456',
155
- },
156
- ],
157
- };
151
+ export const previousAnswers = new Map(
152
+ Object.entries({
153
+ LMFR_PREVIOUS_QUESTION: [
154
+ {
155
+ pathForSpace: '456',
156
+ },
157
+ ],
158
+ }),
159
+ );
158
160
 
159
161
  <Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
160
162
 
@@ -6,7 +6,8 @@
6
6
  :left-icon="BACK_ICON"
7
7
  :class="{
8
8
  'pb-space-input__back-button': true,
9
- 'pb-space-input__back-button--hidden': !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
9
+ 'pb-space-input__back-button--hidden':
10
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
10
11
  }"
11
12
  @click.once="$emit('go-back')"
12
13
  />
@@ -96,6 +97,7 @@ import MIcon from '../../mozaic/icon/MIcon.vue';
96
97
  import DEFAULT_PAYLOAD from './default-payload.json';
97
98
  import { SpaceInputPayload } from '@/components/question/space-input/SpaceInput';
98
99
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
100
+ import { decorate } from '@/components/question/PbQuestion.vue';
99
101
 
100
102
  const BACK_ICON =
101
103
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -117,57 +119,6 @@ const initValidation = (componentId: string, computedPayload: ComputedRef<SpaceI
117
119
  return validationSchema;
118
120
  };
119
121
 
120
- // Function used by the scenario conditions
121
- const getAnswerValue = (answers: Map<string, ScenarioStepAnswer[]>) => {
122
- return (answerCode: string, path: string) => {
123
- let answerValue: ScenarioStepAnswer | undefined = undefined;
124
- if (answers?.get(answerCode)) {
125
- const answerValues = answers.get(answerCode) ?? [];
126
- answerValue = objectPath.get(answerValues[0], path);
127
- }
128
- return answerValue;
129
- };
130
- };
131
-
132
- const doEval = (
133
- answers: Map<string, ScenarioStepAnswer[]>,
134
- valueToEval: string,
135
- defaultValue: string,
136
- runtimeOptions: any,
137
- ) => {
138
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
139
- this,
140
- getAnswerValue(answers),
141
- answers,
142
- defaultValue,
143
- runtimeOptions,
144
- );
145
- };
146
-
147
- const decorate = (
148
- answers: Map<string, ScenarioStepAnswer[]>,
149
- valueToDecorate: string,
150
- defaultValue = '',
151
- runtimeOptions: any,
152
- ) => {
153
- if (valueToDecorate) {
154
- return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
155
- }
156
- return valueToDecorate;
157
- };
158
-
159
- const decorateBoolean = (
160
- answers: Map<string, ScenarioStepAnswer[]>,
161
- valueToDecorate: string,
162
- defaultValue = '',
163
- runtimeOptions: any,
164
- ) => {
165
- if (valueToDecorate) {
166
- return doEval(answers, valueToDecorate, defaultValue, runtimeOptions);
167
- }
168
- return valueToDecorate;
169
- };
170
-
171
122
  const computeDefaultValue = (
172
123
  runtimeOptions: any,
173
124
  answers: Map<string, ScenarioStepAnswer[]>,
@@ -177,9 +128,9 @@ const computeDefaultValue = (
177
128
  if (computedPayload?.value?.value) {
178
129
  space = decorate(
179
130
  answers,
131
+ runtimeOptions,
180
132
  computedPayload?.value?.value?.space,
181
133
  computedPayload?.value?.defaultDecoratorValue,
182
- runtimeOptions,
183
134
  );
184
135
  }
185
136
  return space;
@@ -233,7 +184,7 @@ export default defineComponent({
233
184
  */
234
185
  answers: {
235
186
  type: Object as PropType<Map<string, ScenarioStepAnswer[]>>,
236
- default: () => ({}),
187
+ default: () => new Map<string, ScenarioStepAnswer[]>(),
237
188
  },
238
189
  },
239
190
 
@@ -299,7 +250,6 @@ export default defineComponent({
299
250
  computedPayload,
300
251
  handleFormSubmit,
301
252
  isShowingFooter,
302
- decorateBoolean,
303
253
  skipQuestion,
304
254
  };
305
255
  },
@@ -8,7 +8,7 @@
8
8
  :class="{
9
9
  'pb-upload-document__back-button': true,
10
10
  'pb-upload-document__back-button--hidden':
11
- !showBackButton && !decorateBoolean(payload.viewModel.forceBackButton),
11
+ !showBackButton && !decorate(answers, runtimeOptions, payload.viewModel.forceBackButton),
12
12
  }"
13
13
  @click="navigateTo(payload.viewModel)"
14
14
  />
@@ -156,6 +156,7 @@ import {
156
156
  UploadDocumentViewModel,
157
157
  } from '@/components/question/upload-document/UploadDocument';
158
158
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
159
+ import { decorate, doEval } from '@/components/question/PbQuestion.vue';
159
160
 
160
161
  const BACK_ICON =
161
162
  'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
@@ -261,7 +262,7 @@ export default defineComponent({
261
262
 
262
263
  const navigateTo = (viewModel: UploadDocumentViewModel) => {
263
264
  if (viewModel.backLink) {
264
- window.location = doEval(viewModel.backLink);
265
+ window.location = doEval(props.answers, viewModel.backLink, '', props.runtimeOptions);
265
266
  } else {
266
267
  /**
267
268
  * Emitted when go back link is clicked
@@ -271,38 +272,6 @@ export default defineComponent({
271
272
  }
272
273
  };
273
274
 
274
- const decorate = (answers: Map<string, ScenarioStepAnswer[]>, valueToDecorate: string, defaultValue = '') => {
275
- if (valueToDecorate) {
276
- return doEval(valueToDecorate, defaultValue);
277
- }
278
- return valueToDecorate;
279
- };
280
-
281
- const decorateBoolean = (valueToDecorate: string, defaultValue = '') => {
282
- if (valueToDecorate) {
283
- return doEval(valueToDecorate, defaultValue);
284
- }
285
- return valueToDecorate;
286
- };
287
-
288
- const doEval = (valueToEval: string, defaultValue = '') => {
289
- return new Function('getAnswerValue', 'answers', 'defaultValue', 'runtimeOptions', `return ${valueToEval}`).call(
290
- this,
291
- getAnswerValue,
292
- previousAnswers,
293
- defaultValue,
294
- props.runtimeOptions,
295
- );
296
- };
297
-
298
- const getAnswerValue = (answerCode: string, path: string) => {
299
- const answers = props.answers.get(answerCode);
300
- if (!answers || answers.length === 0) {
301
- return null;
302
- }
303
- return objectPath.get(answers[0], path);
304
- };
305
-
306
275
  const handleDisplayDialogEvent = (event: Event) => {
307
276
  if (!event) {
308
277
  pbMediaUpload.value?.$refs.pbMediaUploadFormInput.click();
@@ -350,7 +319,6 @@ export default defineComponent({
350
319
  showMoreButtonDisplayed,
351
320
  thumbnailUrl,
352
321
  decorate,
353
- decorateBoolean,
354
322
  handleDisplayDialogEvent,
355
323
  validMultiSelect,
356
324
  skipQuestion,