project-booster-vue 9.19.0 → 9.19.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/package.json +1 -2
  2. package/src/components/question/PbQuestion-Features-Answers-Conditional.stories.mdx +2 -2
  3. package/src/components/question/PbQuestion-Features-Answers-Decorated.stories.mdx +1 -1
  4. package/src/components/question/PbQuestion-Features-Answers-Disabled.stories.mdx +2 -2
  5. package/src/components/question/PbQuestion-Features-Question-Footer.stories.mdx +1 -1
  6. package/src/components/question/PbQuestion.vue +13 -4
  7. package/src/components/question/amount-input/PbAmountInput.vue +0 -1
  8. package/src/components/question/dimensions-input/PbDimensionsInput.stories.mdx +9 -11
  9. package/src/components/question/dimensions-input/PbDimensionsInput.vue +4 -5
  10. package/src/components/question/login-redirect/PbLoginRedirect.stories.mdx +1 -1
  11. package/src/components/question/name-input/PbNameInput.stories.mdx +9 -11
  12. package/src/components/question/name-input/PbNameInput.vue +2 -3
  13. package/src/components/question/space-input/PbSpaceInput.stories.mdx +9 -11
  14. package/src/components/question/space-input/PbSpaceInput.vue +1 -2
  15. package/src/services/api/appointmentQualificationsApi.ts +5 -5
  16. package/src/services/api/configApi.ts +2 -2
  17. package/src/services/api/configurationsApi.ts +4 -4
  18. package/src/services/api/consentApi.ts +2 -2
  19. package/src/services/api/documentsApi.ts +3 -3
  20. package/src/services/api/estimatesApi.ts +6 -6
  21. package/src/services/api/eventsApi.ts +9 -9
  22. package/src/services/api/inhabitantsApi.ts +2 -2
  23. package/src/services/api/mediaApi.ts +3 -3
  24. package/src/services/api/productsApi.ts +6 -6
  25. package/src/services/api/projectsApi.ts +8 -8
  26. package/src/services/api/toolsApi.ts +2 -2
  27. package/src/services/htmlEscape.ts +27 -0
  28. package/src/services/scenarioConditionals.ts +2 -2
  29. package/src/types/pb/Scenario.ts +10 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-booster-vue",
3
- "version": "9.19.0",
3
+ "version": "9.19.3",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -45,7 +45,6 @@
45
45
  "core-js": "3.21.1",
46
46
  "date-fns": "2.22.1",
47
47
  "firebase": "8.6.7",
48
- "he": "1.2.0",
49
48
  "hooper": "nicoinch/hooper#1.0.5",
50
49
  "lodash.clonedeep": "4.5.0",
51
50
  "lodash.debounce": "4.0.8",
@@ -75,7 +75,7 @@ export const conditionalAnswersPayload = {
75
75
  <Source language="json" code={JSON.stringify(conditionalAnswersPayload, null, ' ')} />
76
76
 
77
77
  Here, the answer `ANSWER-1` will be hidden because no previous answers are provided (same as answers not matching the
78
- condition):
78
+ condition), `ANSWER-2` will be hidden because of the condition on runtime options :
79
79
 
80
80
  <Canvas>
81
81
  <Story
@@ -116,7 +116,7 @@ Runtime options:
116
116
  parameters={{ controls: { disable: true } }}
117
117
  args={{
118
118
  payload: conditionalAnswersPayload,
119
- answers: conditionalAnswersAnswers,
119
+ answers: new Map(Object.entries(conditionalAnswersAnswers)),
120
120
  runtimeOptions: conditionalAnswersRuntimeOptions,
121
121
  minHeight: 'auto',
122
122
  }}
@@ -100,7 +100,7 @@ Runtime options:
100
100
  parameters={{ controls: { disable: true } }}
101
101
  args={{
102
102
  payload: decoratedAnswersPayload,
103
- answers: decoratedAnswersAnswers,
103
+ answers: new Map(Object.entries(decoratedAnswersAnswers)),
104
104
  runtimeOptions: decoratedAnswersRuntimeOptions,
105
105
  minHeight: 'auto',
106
106
  }}
@@ -103,7 +103,7 @@ export const disabledAnswersAnswers = {
103
103
  parameters={{ controls: { disable: true } }}
104
104
  args={{
105
105
  payload: disabledAnswersPayload,
106
- answers: disabledAnswersAnswers,
106
+ answers: new Map(Object.entries(disabledAnswersAnswers)),
107
107
  minHeight: 'auto',
108
108
  }}
109
109
  >
@@ -120,7 +120,7 @@ condition):
120
120
  inline={false}
121
121
  height="862px"
122
122
  parameters={{ controls: { disable: true } }}
123
- args={{ payload: disabledAnswersPayload, minHeight: 'auto' }}
123
+ args={{ payload: disabledAnswersPayload, answers: new Map(), minHeight: 'auto' }}
124
124
  >
125
125
  {TemplateSandbox.bind({})}
126
126
  </Story>
@@ -93,7 +93,7 @@ export const questionFooterAnswers = {
93
93
  parameters={{ controls: { disable: true } }}
94
94
  args={{
95
95
  payload: questionFooterPayload,
96
- answers: questionFooterAnswers,
96
+ answers: new Map(Object.entries(questionFooterAnswers)),
97
97
  minHeight: 'auto',
98
98
  }}
99
99
  >
@@ -318,6 +318,7 @@ import {
318
318
  ScenarioStepPayload,
319
319
  ScenarioStepSkippableOptions,
320
320
  ScenarioStepViewModel,
321
+ ScenarioCondition,
321
322
  } from '@/types/pb/Scenario';
322
323
 
323
324
  const BACK_ICON =
@@ -553,10 +554,18 @@ export default defineComponent({
553
554
  return viewModel.footer && areConditionsValid(viewModel.footer.conditions!, this.answers, this.runtimeOptions);
554
555
  },
555
556
  isAnswerDisabled(answer: ScenarioStepAnswer) {
556
- return (
557
- answer?.viewModel?.disabled &&
558
- areConditionsValid(answer.viewModel.conditions!, this.answers, this.runtimeOptions)
559
- );
557
+ if (answer.viewModel?.disabled instanceof Boolean) {
558
+ return answer.viewModel.disabled;
559
+ } else {
560
+ return (
561
+ answer?.viewModel?.disabled &&
562
+ areConditionsValid(
563
+ (<ScenarioCondition>answer.viewModel.disabled).conditions,
564
+ this.answers,
565
+ this.runtimeOptions,
566
+ )
567
+ );
568
+ }
560
569
  },
561
570
  selectAnswer(stepCode: string, answer: ScenarioStepAnswer) {
562
571
  if (this.isAnswerDisabled(answer)) {
@@ -55,7 +55,6 @@ import { useForm } from 'vee-validate';
55
55
  import * as yup from 'yup';
56
56
  import cloneDeep from 'lodash.clonedeep';
57
57
  import merge from 'lodash.merge';
58
- import objectPath from 'object-path';
59
58
  import MFlex from './../../mozaic/flex/MFlex.vue';
60
59
  import MButton from './../../mozaic/buttons/MButton.vue';
61
60
  import MIcon from './../../mozaic/icon/MIcon.vue';
@@ -153,16 +153,14 @@ 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 = new Map(
157
- Object.entries({
158
- LMFR_PREVIOUS_QUESTION: [
159
- {
160
- pathForLength: '4.56',
161
- pathForWidth: '7.89',
162
- },
163
- ],
164
- }),
165
- );
156
+ export const previousAnswers = {
157
+ LMFR_PREVIOUS_QUESTION: [
158
+ {
159
+ pathForLength: '4.56',
160
+ pathForWidth: '7.89',
161
+ },
162
+ ],
163
+ };
166
164
 
167
165
  <Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
168
166
 
@@ -172,7 +170,7 @@ export const previousAnswers = new Map(
172
170
  parameters={{ controls: { disable: true } }}
173
171
  args={{
174
172
  payload: valuePayload,
175
- answers: previousAnswers,
173
+ answers: new Map(Object.entries(previousAnswers)),
176
174
  }}
177
175
  >
178
176
  {TemplateSandbox.bind({})}
@@ -98,7 +98,6 @@ import MTextInput from './../../mozaic/text-input/MTextInput.vue';
98
98
  import DEFAULT_PAYLOAD from './default-payload.json';
99
99
  import MLink from '../../mozaic/link/MLink.vue';
100
100
  import MIcon from '../../mozaic/icon/MIcon.vue';
101
- import objectPath from 'object-path';
102
101
  import { ref } from 'vue';
103
102
  import { ScenarioStepAnswer } from '@/types/pb/Scenario';
104
103
  import { DimensionsInputPayload } from '@/components/question/dimensions-input/DimensionsInput';
@@ -156,13 +155,13 @@ const computeDefaultValue = (
156
155
  answers,
157
156
  runtimeOptions,
158
157
  computedPayload?.value?.value?.length,
159
- computedPayload?.value?.defaultDecoratorValue,
158
+ computedPayload?.value?.defaultDecoratorValue ?? '',
160
159
  );
161
160
  width.value = decorate(
162
161
  answers,
163
162
  runtimeOptions,
164
163
  computedPayload?.value?.value?.width,
165
- computedPayload?.value?.defaultDecoratorValue,
164
+ computedPayload?.value?.defaultDecoratorValue ?? '',
166
165
  );
167
166
  }
168
167
 
@@ -243,8 +242,8 @@ export default defineComponent({
243
242
  emit(props.completedEventName, {
244
243
  answers: [
245
244
  {
246
- width: values[elementLengthId],
247
- length: values[elementWidthId],
245
+ length: values[elementLengthId],
246
+ width: values[elementWidthId],
248
247
  },
249
248
  ],
250
249
  });
@@ -160,7 +160,7 @@ export const overridenLabelsPayload = {
160
160
  buttonLabelConnect: 'Se connecter',
161
161
  buttonLabelCreateAccount: 'Créer un compte',
162
162
  forceRedirect: false,
163
- link: '/espace-perso/espace-projets.html?hash=/projects/new',
163
+ link: '/espace-perso/espace-projets.html',
164
164
  },
165
165
  };
166
166
 
@@ -220,16 +220,14 @@ With optin value :
220
220
 
221
221
  `answers` prop to add a previous answer :
222
222
 
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
- );
223
+ export const previousAnswersWithOptin = {
224
+ LMFR_PREVIOUS_QUESTION: [
225
+ {
226
+ pathForProjectName: 'Rénover la cuisine',
227
+ pathForOptin: true,
228
+ },
229
+ ],
230
+ };
233
231
 
234
232
  <Source language="json" code={JSON.stringify(previousAnswersWithOptin, null, ' ')} />
235
233
 
@@ -239,7 +237,7 @@ export const previousAnswersWithOptin = new Map(
239
237
  parameters={{ controls: { disable: true } }}
240
238
  args={{
241
239
  payload: valuePayload,
242
- answers: previousAnswersWithOptin,
240
+ answers: new Map(Object.entries(previousAnswersWithOptin)),
243
241
  runtimeOptions: runtimeOptions,
244
242
  }}
245
243
  >
@@ -52,7 +52,6 @@ import { useForm } from 'vee-validate';
52
52
  import * as yup from 'yup';
53
53
  import cloneDeep from 'lodash.clonedeep';
54
54
  import merge from 'lodash.merge';
55
- import objectPath from 'object-path';
56
55
  import MFlex from '../../mozaic/flex/MFlex.vue';
57
56
  import MButton from '../../mozaic/buttons/MButton.vue';
58
57
  import MLink from '../../mozaic/link/MLink.vue';
@@ -99,13 +98,13 @@ const computeDefaultValue = (
99
98
  answers,
100
99
  runtimeOptions,
101
100
  computedPayload?.value?.value?.projectName,
102
- computedPayload?.value?.defaultDecoratorValue,
101
+ computedPayload?.value?.defaultDecoratorValue ?? '',
103
102
  );
104
103
  optin.value = decorate(
105
104
  answers,
106
105
  runtimeOptions,
107
106
  computedPayload?.value?.value?.optin,
108
- computedPayload?.value?.defaultDecoratorValue,
107
+ computedPayload?.value?.defaultDecoratorValue ?? '',
109
108
  );
110
109
  }
111
110
 
@@ -129,7 +129,7 @@ export const valuePayload = {
129
129
  <Source language="json" code={JSON.stringify(valuePayload, null, ' ')} />
130
130
 
131
131
  The `getAnswerValue` function allows to retrieve a value from one provided answer. To retrieve a value, the first
132
- parameter is the answer Id, the second is an optionnal path to extract a spcific value.
132
+ parameter is the answer Id, the second is an optional path to extract a specific value.
133
133
 
134
134
  A `defaultDecoratorValue` value can be added as a fallback when no previous answer is found. When no default value is provided and no answer
135
135
  is found, the component value will be empty :
@@ -148,15 +148,13 @@ 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 = new Map(
152
- Object.entries({
153
- LMFR_PREVIOUS_QUESTION: [
154
- {
155
- pathForSpace: '456',
156
- },
157
- ],
158
- }),
159
- );
151
+ export const previousAnswers = {
152
+ LMFR_PREVIOUS_QUESTION: [
153
+ {
154
+ pathForSpace: '456',
155
+ },
156
+ ],
157
+ };
160
158
 
161
159
  <Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
162
160
 
@@ -166,7 +164,7 @@ export const previousAnswers = new Map(
166
164
  parameters={{ controls: { disable: true } }}
167
165
  args={{
168
166
  payload: valuePayload,
169
- answers: previousAnswers,
167
+ answers: new Map(Object.entries(previousAnswers)),
170
168
  }}
171
169
  >
172
170
  {TemplateSandbox.bind({})}
@@ -87,7 +87,6 @@ import { useForm } from 'vee-validate';
87
87
  import * as yup from 'yup';
88
88
  import cloneDeep from 'lodash.clonedeep';
89
89
  import merge from 'lodash.merge';
90
- import objectPath from 'object-path';
91
90
  import MFlex from '../../mozaic/flex/MFlex.vue';
92
91
  import MButton from '../../mozaic/buttons/MButton.vue';
93
92
  import MLink from '../../mozaic/link/MLink.vue';
@@ -130,7 +129,7 @@ const computeDefaultValue = (
130
129
  answers,
131
130
  runtimeOptions,
132
131
  computedPayload?.value?.value?.space,
133
- computedPayload?.value?.defaultDecoratorValue,
132
+ computedPayload?.value?.defaultDecoratorValue ?? '',
134
133
  );
135
134
  }
136
135
  return space;
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -41,7 +41,7 @@ const saveAnswersByAppointmentQualificationId = async (appointmentQualificationI
41
41
 
42
42
  return JSON.parse(
43
43
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
44
- return `: "${he.escape($1)}"`;
44
+ return `: "${escape($1)}"`;
45
45
  }),
46
46
  );
47
47
  };
@@ -53,7 +53,7 @@ const declarationsWithAppointment = async (data: any) => {
53
53
 
54
54
  return JSON.parse(
55
55
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
56
- return `: "${he.escape($1)}"`;
56
+ return `: "${escape($1)}"`;
57
57
  }),
58
58
  );
59
59
  };
@@ -65,7 +65,7 @@ const declarationsWithoutAppointment = async (data: any) => {
65
65
 
66
66
  return JSON.parse(
67
67
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
68
- return `: "${he.escape($1)}"`;
68
+ return `: "${escape($1)}"`;
69
69
  }),
70
70
  );
71
71
  };
@@ -81,7 +81,7 @@ const linkInhabitantProjectToAppointmentQualification = async (data: any, inhabi
81
81
 
82
82
  return JSON.parse(
83
83
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
84
- return `: "${he.escape($1)}"`;
84
+ return `: "${escape($1)}"`;
85
85
  }),
86
86
  );
87
87
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -23,7 +23,7 @@ const getConfiguration = async () => {
23
23
 
24
24
  return JSON.parse(
25
25
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
26
- return `: "${he.escape($1)}"`;
26
+ return `: "${escape($1)}"`;
27
27
  }),
28
28
  );
29
29
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -39,7 +39,7 @@ const getProjectConfigurationsForProjectType = async (
39
39
 
40
40
  return JSON.parse(
41
41
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
42
- return `: "${he.escape($1)}"`;
42
+ return `: "${escape($1)}"`;
43
43
  }),
44
44
  );
45
45
  };
@@ -56,7 +56,7 @@ const getAllProjectConfigurations = async (inhabitantProjectId: string, forceNoP
56
56
 
57
57
  return JSON.parse(
58
58
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
59
- return `: "${he.escape($1)}"`;
59
+ return `: "${escape($1)}"`;
60
60
  }),
61
61
  );
62
62
  };
@@ -66,7 +66,7 @@ const linkConfiguration = async (id: string, inhabitantProjectId: string) => {
66
66
 
67
67
  return JSON.parse(
68
68
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
69
- return `: "${he.escape($1)}"`;
69
+ return `: "${escape($1)}"`;
70
70
  }),
71
71
  );
72
72
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -23,7 +23,7 @@ export const getConsents = async () => {
23
23
 
24
24
  return JSON.parse(
25
25
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
26
- return `: "${he.escape($1)}"`;
26
+ return `: "${escape($1)}"`;
27
27
  }),
28
28
  );
29
29
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -53,7 +53,7 @@ const getDocumentsByInhabitantProjectId = async (
53
53
 
54
54
  return JSON.parse(
55
55
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
56
- return `: "${he.escape($1)}"`;
56
+ return `: "${escape($1)}"`;
57
57
  }),
58
58
  );
59
59
  };
@@ -63,7 +63,7 @@ const getDocumentById = async (inhabitantProjectId: string, documentId: string)
63
63
 
64
64
  return JSON.parse(
65
65
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
66
- return `: "${he.escape($1)}"`;
66
+ return `: "${escape($1)}"`;
67
67
  }),
68
68
  );
69
69
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
  import { Estimate } from '@/types/pb/Estimate';
4
4
  import { ScenarioAnswer } from '@/types/pb/Scenario';
5
5
 
@@ -31,7 +31,7 @@ export const getAllEstimates = async (
31
31
 
32
32
  return JSON.parse(
33
33
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
34
- return `: "${he.escape($1)}"`;
34
+ return `: "${escape($1)}"`;
35
35
  }),
36
36
  );
37
37
  };
@@ -41,7 +41,7 @@ export const getEstimateById = async (id: string) => {
41
41
 
42
42
  return JSON.parse(
43
43
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
44
- return `: "${he.escape($1)}"`;
44
+ return `: "${escape($1)}"`;
45
45
  }),
46
46
  );
47
47
  };
@@ -51,7 +51,7 @@ export const deleteEstimateById = async (id: string) => {
51
51
 
52
52
  return JSON.parse(
53
53
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
54
- return `: "${he.escape($1)}"`;
54
+ return `: "${escape($1)}"`;
55
55
  }),
56
56
  );
57
57
  };
@@ -65,7 +65,7 @@ export const saveEstimate = async (estimate: Estimate) => {
65
65
 
66
66
  return JSON.parse(
67
67
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
68
- return `: "${he.escape($1)}"`;
68
+ return `: "${escape($1)}"`;
69
69
  }),
70
70
  );
71
71
  };
@@ -80,7 +80,7 @@ export const estimate = async (
80
80
 
81
81
  return JSON.parse(
82
82
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
83
- return `: "${he.escape($1)}"`;
83
+ return `: "${escape($1)}"`;
84
84
  }),
85
85
  );
86
86
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -25,7 +25,7 @@ export const buildEventApi = (target: string) => async (event: any) => {
25
25
 
26
26
  return JSON.parse(
27
27
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
28
- return `: "${he.escape($1)}"`;
28
+ return `: "${escape($1)}"`;
29
29
  }),
30
30
  );
31
31
  };
@@ -37,7 +37,7 @@ export const sendAppointmentQualificationEvent = async (event: any) => {
37
37
 
38
38
  return JSON.parse(
39
39
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
40
- return `: "${he.escape($1)}"`;
40
+ return `: "${escape($1)}"`;
41
41
  }),
42
42
  );
43
43
  };
@@ -49,7 +49,7 @@ export const sendAppointmentQualificationAnswers = async (event: any) => {
49
49
 
50
50
  return JSON.parse(
51
51
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
52
- return `: "${he.escape($1)}"`;
52
+ return `: "${escape($1)}"`;
53
53
  }),
54
54
  );
55
55
  };
@@ -76,7 +76,7 @@ export const sendDocumentsEvent = async (event: {
76
76
 
77
77
  return JSON.parse(
78
78
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
79
- return `: "${he.escape($1)}"`;
79
+ return `: "${escape($1)}"`;
80
80
  }),
81
81
  );
82
82
  };
@@ -100,7 +100,7 @@ export const sendMediaEvent = async (event: {
100
100
 
101
101
  return JSON.parse(
102
102
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
103
- return `: "${he.escape($1)}"`;
103
+ return `: "${escape($1)}"`;
104
104
  }),
105
105
  );
106
106
  };
@@ -112,7 +112,7 @@ export const sendCardClickEvent = async (event: any) => {
112
112
 
113
113
  return JSON.parse(
114
114
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
115
- return `: "${he.escape($1)}"`;
115
+ return `: "${escape($1)}"`;
116
116
  }),
117
117
  );
118
118
  };
@@ -124,7 +124,7 @@ export const sendDeclarationEvent = async (event: any) => {
124
124
 
125
125
  return JSON.parse(
126
126
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
127
- return `: "${he.escape($1)}"`;
127
+ return `: "${escape($1)}"`;
128
128
  }),
129
129
  );
130
130
  };
@@ -136,7 +136,7 @@ export const sendSimulationEvent = async (event: any) => {
136
136
 
137
137
  return JSON.parse(
138
138
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
139
- return `: "${he.escape($1)}"`;
139
+ return `: "${escape($1)}"`;
140
140
  }),
141
141
  );
142
142
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -23,7 +23,7 @@ export const getInhabitantById = async (inhabitantId: string, buId = '001') => {
23
23
 
24
24
  return JSON.parse(
25
25
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
26
- return `: "${he.escape($1)}"`;
26
+ return `: "${escape($1)}"`;
27
27
  }),
28
28
  );
29
29
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -23,7 +23,7 @@ const getAllMedia = async (start: number, end: number, inhabitantProjectId: stri
23
23
 
24
24
  return JSON.parse(
25
25
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
26
- return `: "${he.escape($1)}"`;
26
+ return `: "${escape($1)}"`;
27
27
  }),
28
28
  );
29
29
  };
@@ -33,7 +33,7 @@ const getMediumById = async (mediumId: string) => {
33
33
 
34
34
  return JSON.parse(
35
35
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
36
- return `: "${he.escape($1)}"`;
36
+ return `: "${escape($1)}"`;
37
37
  }),
38
38
  );
39
39
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({
5
5
  baseURL: '/project-booster/api',
@@ -24,7 +24,7 @@ export const getWorkKindsByProjectTypeId = async (projectTypeId: string) => {
24
24
 
25
25
  return JSON.parse(
26
26
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
27
- return `: "${he.escape($1)}"`;
27
+ return `: "${escape($1)}"`;
28
28
  }),
29
29
  );
30
30
  };
@@ -34,7 +34,7 @@ export const getProductsByWorkKind = async (workKindId: string, storeId: string)
34
34
 
35
35
  return JSON.parse(
36
36
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
37
- return `: "${he.escape($1)}"`;
37
+ return `: "${escape($1)}"`;
38
38
  }),
39
39
  );
40
40
  };
@@ -44,7 +44,7 @@ export const getProductsFeatureFlag = async (projectTypeId: string) => {
44
44
 
45
45
  return JSON.parse(
46
46
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
47
- return `: "${he.escape($1)}"`;
47
+ return `: "${escape($1)}"`;
48
48
  }),
49
49
  );
50
50
  };
@@ -56,7 +56,7 @@ export const saveWorkKinds = async (inhabitantProjectId: string, workKinds: any)
56
56
 
57
57
  return JSON.parse(
58
58
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
59
- return `: "${he.escape($1)}"`;
59
+ return `: "${escape($1)}"`;
60
60
  }),
61
61
  );
62
62
  };
@@ -66,7 +66,7 @@ export const getWorkKindsByProjectId = async (inhabitantProjectId: string) => {
66
66
 
67
67
  return JSON.parse(
68
68
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
69
- return `: "${he.escape($1)}"`;
69
+ return `: "${escape($1)}"`;
70
70
  }),
71
71
  );
72
72
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
  import { Project, ProjectToSave } from '@/types/pb/Project';
4
4
 
5
5
  export const clientApi = axios.create({
@@ -26,7 +26,7 @@ export const getAllProjects = async (currentProjectsPage: number, projectsPerPag
26
26
 
27
27
  return JSON.parse(
28
28
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
29
- return `: "${he.escape($1)}"`;
29
+ return `: "${escape($1)}"`;
30
30
  }),
31
31
  );
32
32
  };
@@ -42,7 +42,7 @@ export const getAllProjectsForUserId = async (
42
42
 
43
43
  return JSON.parse(
44
44
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
45
- return `: "${he.escape($1)}"`;
45
+ return `: "${escape($1)}"`;
46
46
  }),
47
47
  );
48
48
  };
@@ -52,7 +52,7 @@ export const getProjectById = async (id: string) => {
52
52
 
53
53
  return JSON.parse(
54
54
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
55
- return `: "${he.escape($1)}"`;
55
+ return `: "${escape($1)}"`;
56
56
  }),
57
57
  );
58
58
  };
@@ -62,7 +62,7 @@ export const deleteProjectById = async (id: string) => {
62
62
 
63
63
  return JSON.parse(
64
64
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
65
- return `: "${he.escape($1)}"`;
65
+ return `: "${escape($1)}"`;
66
66
  }),
67
67
  );
68
68
  };
@@ -81,7 +81,7 @@ export const saveProjectDeclaration = async (projectDeclaration: ProjectToSave)
81
81
 
82
82
  return JSON.parse(
83
83
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
84
- return `: "${he.escape($1)}"`;
84
+ return `: "${escape($1)}"`;
85
85
  }),
86
86
  );
87
87
  };
@@ -91,7 +91,7 @@ export const getProjectAttributesById = async (id: string) => {
91
91
 
92
92
  return JSON.parse(
93
93
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
94
- return `: "${he.escape($1)}"`;
94
+ return `: "${escape($1)}"`;
95
95
  }),
96
96
  );
97
97
  };
@@ -101,7 +101,7 @@ export const getAppointmentById = async (id: string) => {
101
101
 
102
102
  return JSON.parse(
103
103
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
104
- return `: "${he.escape($1)}"`;
104
+ return `: "${escape($1)}"`;
105
105
  }),
106
106
  );
107
107
  };
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import he from 'he';
2
+ import { escape } from '../../services/htmlEscape';
3
3
 
4
4
  export const clientApi = axios.create({});
5
5
 
@@ -17,7 +17,7 @@ export const getAllTools = async (projectType: string) => {
17
17
 
18
18
  return JSON.parse(
19
19
  JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
20
- return `: "${he.escape($1)}"`;
20
+ return `: "${escape($1)}"`;
21
21
  }),
22
22
  );
23
23
  };
@@ -0,0 +1,27 @@
1
+ // Issue with kobi rewriting the lib we extract the part that we need here
2
+
3
+ const regexEscape: RegExp = /["&'<>`]/g;
4
+
5
+ const escapeMap: Record<string, string> = {
6
+ '"': '&quot;',
7
+ '&': '&amp;',
8
+ "'": '&#x27;',
9
+ '<': '&lt;',
10
+ // See https://mathiasbynens.be/notes/ambiguous-ampersands: in HTML, the
11
+ // following is not strictly necessary unless it’s part of a tag or an
12
+ // unquoted attribute value. We’re only escaping it to support those
13
+ // situations, and for XML support.
14
+ '>': '&gt;',
15
+ // In Internet Explorer ≤ 8, the backtick character can be used
16
+ // to break out of (un)quoted attribute values or HTML comments.
17
+ // See http://html5sec.org/#102, http://html5sec.org/#108, and
18
+ // http://html5sec.org/#133.
19
+ '`': '&#x60;',
20
+ };
21
+
22
+ export const escape = (string: string) => {
23
+ return string.replace(regexEscape, function ($0) {
24
+ // Note: there is no need to check `has(escapeMap, $0)` here.
25
+ return escapeMap[$0];
26
+ });
27
+ };
@@ -33,13 +33,13 @@ const Condition = (
33
33
  };
34
34
 
35
35
  export const areConditionsValid = (
36
- conditions: string[],
36
+ conditions: boolean | string[],
37
37
  answers: Map<string, ScenarioStepAnswer[]>,
38
38
  runtimeOptions: Record<string, any>,
39
39
  ) => {
40
40
  let valid = true;
41
41
 
42
- if (conditions) {
42
+ if (conditions && conditions instanceof Array) {
43
43
  valid = false;
44
44
  for (const condition of conditions) {
45
45
  try {
@@ -37,6 +37,10 @@ export interface ScenarioStepAnswerDialog {
37
37
  imageUrl?: string;
38
38
  }
39
39
 
40
+ export interface ScenarioCondition {
41
+ conditions: string[];
42
+ }
43
+
40
44
  export interface ScenarioStepAnswerViewModel {
41
45
  title?: string;
42
46
  flagLabel?: string;
@@ -47,7 +51,7 @@ export interface ScenarioStepAnswerViewModel {
47
51
  alignVertical?: string;
48
52
  alignHorizontal?: string;
49
53
  alignText?: string;
50
- disabled?: boolean;
54
+ disabled?: boolean | ScenarioCondition;
51
55
  footer?: ScenarioStepFooterOptions;
52
56
  conditions?: string[];
53
57
  dialog?: ScenarioStepAnswerDialog;
@@ -62,6 +66,11 @@ export interface ScenarioStepAnswer {
62
66
  meta?: {
63
67
  order: number;
64
68
  stringSort: string;
69
+ ProjectTypeLabel?: string;
70
+ domesticSpace?: string;
71
+ projectType?: string;
72
+ ranking?: number;
73
+ projectKind?: string;
65
74
  };
66
75
  }
67
76