project-booster-vue 8.119.0 → 8.119.4
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 +4 -4
- package/scenario-validator/index.js +115 -0
- package/scenario-validator/jsonExplorer.js +165 -0
- package/src/components/projects/project-item-save/PbProjectItemSave.stories.mdx +101 -0
- package/src/components/restitution/PbRestitutionBlock.vue +25 -28
- package/src/components/restitution/PbRestitutionLine.vue +23 -33
- package/src/services/api/appointmentQualificationsApi.js +10 -9
- package/src/services/api/configApi.js +3 -3
- package/src/services/api/configurationsApi.js +13 -11
- package/src/services/api/documentsApi.js +16 -15
- package/src/services/api/estimatesApi.js +17 -14
- package/src/services/api/eventsApi.js +21 -23
- package/src/services/api/inhabitantsApi.js +3 -3
- package/src/services/api/mediaApi.js +17 -17
- package/src/services/api/productsApi.js +13 -14
- package/src/services/api/projectsApi.js +20 -22
- package/src/services/api/toolsApi.js +3 -3
- package/src/stores/modules/projectsStore.js +5 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-booster-vue",
|
|
3
|
-
"version": "8.119.
|
|
3
|
+
"version": "8.119.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test:unit": "vue-cli-service test:unit --forceExit --detectOpenHandles",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"dist/*",
|
|
25
25
|
"src/*",
|
|
26
26
|
"public/*",
|
|
27
|
+
"scenario-validator/*",
|
|
27
28
|
"*.json"
|
|
28
29
|
],
|
|
29
30
|
"dependencies": {
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
"@vue/babel-preset-app": "4.5.13",
|
|
37
38
|
"@vue/compat": "3.2.6",
|
|
38
39
|
"ajv": "8.6.0",
|
|
39
|
-
"axios": "0.
|
|
40
|
+
"axios": "0.25.0",
|
|
40
41
|
"contentful": "8.4.2",
|
|
41
42
|
"core-js": "3.19.1",
|
|
42
43
|
"date-fns": "2.22.1",
|
|
@@ -54,7 +55,6 @@
|
|
|
54
55
|
"object-path": "0.11.5",
|
|
55
56
|
"ramda": "0.26.1",
|
|
56
57
|
"request": "2.88.0",
|
|
57
|
-
"superagent": "6.1.0",
|
|
58
58
|
"svg-injector": "1.1.3",
|
|
59
59
|
"uuid": "8.3.2",
|
|
60
60
|
"vee-validate": "4.4.5",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"eslint-plugin-prettier": "4.0.0",
|
|
118
118
|
"eslint-plugin-storybook": "0.5.6",
|
|
119
119
|
"eslint-plugin-vue": "7.11.1",
|
|
120
|
-
"fluent-schema": "
|
|
120
|
+
"fluent-json-schema": "3.0.1",
|
|
121
121
|
"husky": "6.0.0",
|
|
122
122
|
"msw": "0.35.0",
|
|
123
123
|
"msw-storybook-addon": "1.6.0",
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const R = require('ramda');
|
|
2
|
+
const request = require('request');
|
|
3
|
+
const axios = require('axios');
|
|
4
|
+
const Ajv = require('ajv');
|
|
5
|
+
const {
|
|
6
|
+
getAllStepName,
|
|
7
|
+
hasTemplates,
|
|
8
|
+
hasNoTemplates,
|
|
9
|
+
createDirectGraphForJson,
|
|
10
|
+
getAllConfigurationForTemplateLiteral,
|
|
11
|
+
getPictures,
|
|
12
|
+
getStepComponent,
|
|
13
|
+
} = require('./jsonExplorer');
|
|
14
|
+
|
|
15
|
+
const getUrlStatusCode = (url) => {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const r = request(url);
|
|
18
|
+
r.on('response', (response) => {
|
|
19
|
+
r.abort();
|
|
20
|
+
resolve(response.statusCode);
|
|
21
|
+
});
|
|
22
|
+
r.on('error', function (err) {
|
|
23
|
+
reject(err);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const isOffline = process.env.OFFLINE;
|
|
29
|
+
|
|
30
|
+
const itOnline = isOffline ? it.skip : it;
|
|
31
|
+
|
|
32
|
+
const testImage = (url) => {
|
|
33
|
+
describe(url, () => {
|
|
34
|
+
itOnline('should exist', async () => {
|
|
35
|
+
const status = await getUrlStatusCode(url);
|
|
36
|
+
expect(status).toBe(200);
|
|
37
|
+
});
|
|
38
|
+
it('should not be on a subproject bucket', () => {
|
|
39
|
+
const bucketRegex = /^https:\/\/storage.googleapis.com\/budget-estimate-[^\/]+subproject-forms\/.*/;
|
|
40
|
+
expect(bucketRegex.test(url)).toBeFalsy();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const validateSchema = (rawJson) => {
|
|
46
|
+
itOnline('should be valid according to json schema', async () => {
|
|
47
|
+
const jsonSchema = (await axios.get('https://adeo.github.io/project-booster-vue/jsonSchema/scenario.json')).data;
|
|
48
|
+
const ajv = new Ajv({ allErrors: true });
|
|
49
|
+
const validate = ajv.compile(jsonSchema);
|
|
50
|
+
const valid = validate(rawJson);
|
|
51
|
+
if (!valid) {
|
|
52
|
+
console.error(validate.errors);
|
|
53
|
+
}
|
|
54
|
+
expect(valid).toBeTruthy();
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
const sharedScenarioTests = (json) => {
|
|
58
|
+
validateSchema(json);
|
|
59
|
+
it('should have a __START__ step', () => {
|
|
60
|
+
expect(json['__START__']).toBeDefined();
|
|
61
|
+
});
|
|
62
|
+
it('should have keys same as code', () => {
|
|
63
|
+
R.toPairs(json).forEach(([key, { code }]) => {
|
|
64
|
+
expect(key).toEqual(code);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('images', () => {
|
|
68
|
+
describe('static images', () => {
|
|
69
|
+
const images = getPictures(json).filter(hasNoTemplates);
|
|
70
|
+
for (let url of images) {
|
|
71
|
+
testImage(url);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
describe('dynamic images', () => {
|
|
75
|
+
const images = getPictures(json)
|
|
76
|
+
.filter(hasTemplates)
|
|
77
|
+
.filter((v, i, a) => a.indexOf(v) === i);
|
|
78
|
+
for (let template of images) {
|
|
79
|
+
describe(template, () => {
|
|
80
|
+
for (let url of getAllConfigurationForTemplateLiteral(json, template)) {
|
|
81
|
+
testImage(url);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('steps', () => {
|
|
88
|
+
const graph = createDirectGraphForJson(json);
|
|
89
|
+
const allSteps = getAllStepName(json);
|
|
90
|
+
Object.entries(graph).map(([key, val]) => {
|
|
91
|
+
describe(key, () => {
|
|
92
|
+
it('should have valid destination', () => {
|
|
93
|
+
val.forEach((destination) => {
|
|
94
|
+
expect(allSteps.indexOf(destination)).toBeGreaterThanOrEqual(0);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const stepComponentName = getStepComponent(json[key]);
|
|
99
|
+
|
|
100
|
+
if (stepComponentName === 'PbSpaceInput' || stepComponentName === 'PbAmountInput') {
|
|
101
|
+
it('should have a value for going back for a numeric input', () => {
|
|
102
|
+
expect(json[key].payload.value).toBeDefined();
|
|
103
|
+
expect(typeof json[key].payload.value).toBe('object');
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
module.exports.sharedScenarioTests = sharedScenarioTests;
|
|
112
|
+
module.exports.validateSchema = validateSchema;
|
|
113
|
+
module.exports.testImage = testImage;
|
|
114
|
+
module.exports.getUrlStatusCode = getUrlStatusCode;
|
|
115
|
+
module.exports.getPictures = getPictures;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
const R = require('ramda');
|
|
2
|
+
|
|
3
|
+
const getStepComponent = (step) => (step && step.component) || undefined;
|
|
4
|
+
|
|
5
|
+
const getTemplates = R.match(/(\${.*?})/g);
|
|
6
|
+
|
|
7
|
+
const hasTemplates = (string) => getTemplates(string).length > 0;
|
|
8
|
+
const hasNoTemplates = (string) => getTemplates(string).length === 0;
|
|
9
|
+
|
|
10
|
+
const getPictures = (json) => {
|
|
11
|
+
const polishArray = R.pipe(R.reject(R.isNil), R.flatten, R.reject(R.isNil), R.filter(R.reject(R.isNil)), R.uniq);
|
|
12
|
+
const getAnswersImages = R.pipe(
|
|
13
|
+
R.map(R.pipe(R.path(['payload', 'answers']), R.values, R.map(R.path(['viewModel', 'image'])))),
|
|
14
|
+
R.values,
|
|
15
|
+
);
|
|
16
|
+
const getStrips = R.pipe(R.values, R.map(R.path(['payload', 'viewModel', 'decoratorStripe'])));
|
|
17
|
+
const images = [...getStrips(json), ...getAnswersImages(json)];
|
|
18
|
+
return images.length > 0 ? polishArray(images) : images;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const getAllConfigurationForTemplateLiteral = (json, string) => {
|
|
22
|
+
const stepForString = R.pipe(
|
|
23
|
+
R.values,
|
|
24
|
+
R.filter(
|
|
25
|
+
R.compose(
|
|
26
|
+
R.includes(string),
|
|
27
|
+
R.pipe(R.path(['payload', 'answers']), R.values, R.map(R.path(['viewModel', 'image']))),
|
|
28
|
+
),
|
|
29
|
+
),
|
|
30
|
+
)(json)[0];
|
|
31
|
+
|
|
32
|
+
const defaultValuesData = R.path(['payload', 'defaultDecoratorValue'], stepForString);
|
|
33
|
+
|
|
34
|
+
const defaultValues = R.pipe(
|
|
35
|
+
R.match(/defaultValue\..+?[ }]/g),
|
|
36
|
+
R.map(
|
|
37
|
+
R.pipe(
|
|
38
|
+
R.split('.'),
|
|
39
|
+
R.nth(1),
|
|
40
|
+
(str) => str.substring(0, str.length - 1),
|
|
41
|
+
(val) => R.path([val], defaultValuesData),
|
|
42
|
+
),
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const answersValues = R.pipe(
|
|
47
|
+
R.match(/(.+?)\[0]\.value/g),
|
|
48
|
+
R.map(
|
|
49
|
+
R.pipe(
|
|
50
|
+
R.split('.'),
|
|
51
|
+
R.nth(1),
|
|
52
|
+
R.split('['),
|
|
53
|
+
R.nth(0),
|
|
54
|
+
(val) => json[val],
|
|
55
|
+
R.path(['payload', 'answers']),
|
|
56
|
+
R.values,
|
|
57
|
+
R.map(R.path(['value'])),
|
|
58
|
+
R.flatten,
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
R.flatten,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const combinator = R.pipe(
|
|
65
|
+
getTemplates,
|
|
66
|
+
R.map((val) => R.concat(defaultValues(val), answersValues(val))),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
let combined = combinator(string);
|
|
70
|
+
|
|
71
|
+
if (combined.length > 1) {
|
|
72
|
+
combined = R.reduce(R.xprod, [], combined);
|
|
73
|
+
} else {
|
|
74
|
+
combined = R.splitEvery(1, combined[0]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const urls = R.map((pair) => {
|
|
78
|
+
const templates = getTemplates(string);
|
|
79
|
+
let newString = string;
|
|
80
|
+
pair.forEach((value, i) => {
|
|
81
|
+
newString = R.replace(templates[i], value, newString);
|
|
82
|
+
});
|
|
83
|
+
return newString;
|
|
84
|
+
}, combined);
|
|
85
|
+
|
|
86
|
+
return R.uniq(urls);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const isTypeScenario = R.propEq('type', 'SCENARIO');
|
|
90
|
+
|
|
91
|
+
const getDestinationFromScenario = (step) => {
|
|
92
|
+
const direction = R.prop('stepCode');
|
|
93
|
+
|
|
94
|
+
return R.filter(R.is(String))([direction(step)]);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getDestinationFromStep = (step) => {
|
|
98
|
+
const forPayload = R.pipe(
|
|
99
|
+
R.path(['payload', 'multiSelect', 'actions', 'VALIDATE', 'nextStep', 'code']),
|
|
100
|
+
R.ifElse(
|
|
101
|
+
R.is(String),
|
|
102
|
+
(val) => [val],
|
|
103
|
+
() => [],
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const baseForStep = R.ifElse(
|
|
108
|
+
R.has('nextStep'),
|
|
109
|
+
R.pipe(
|
|
110
|
+
R.prop('nextStep'),
|
|
111
|
+
R.ifElse(
|
|
112
|
+
R.has('code'),
|
|
113
|
+
R.pipe(R.prop('code'), (val) => [val]),
|
|
114
|
+
R.ifElse(
|
|
115
|
+
R.has('conditionals'),
|
|
116
|
+
R.pipe(R.prop('conditionals'), R.map(R.path(['nextStep', 'code']))),
|
|
117
|
+
R.pipe(() => []),
|
|
118
|
+
),
|
|
119
|
+
),
|
|
120
|
+
(val) => val || [],
|
|
121
|
+
),
|
|
122
|
+
() => [],
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const stepsInside = R.pipe(
|
|
126
|
+
R.ifElse(
|
|
127
|
+
R.propEq('component', 'PbQuestion'),
|
|
128
|
+
R.pipe(R.path(['payload', 'answers']), R.values, R.map(R.path(['nextStep', 'code']))),
|
|
129
|
+
R.ifElse(
|
|
130
|
+
R.propEq('component', 'PbRestitution'),
|
|
131
|
+
R.pipe(
|
|
132
|
+
R.path(['payload', 'callToActions']),
|
|
133
|
+
R.values,
|
|
134
|
+
R.map(R.prop('action')),
|
|
135
|
+
R.filter(R.is(Object)),
|
|
136
|
+
R.map(R.prop('code')),
|
|
137
|
+
),
|
|
138
|
+
() => R.init([]),
|
|
139
|
+
),
|
|
140
|
+
),
|
|
141
|
+
(val) => val || [],
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const ret = R.filter(R.is(String))(R.concat(stepsInside(step), R.concat(baseForStep(step), forPayload(step))));
|
|
145
|
+
|
|
146
|
+
return ret || [];
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const getAllStepName = R.keys;
|
|
150
|
+
|
|
151
|
+
const createDirectGraphForJson = (json) => {
|
|
152
|
+
const directGraph = R.pipe(
|
|
153
|
+
R.map(R.pipe(R.ifElse(isTypeScenario, getDestinationFromScenario, getDestinationFromStep), R.uniq())),
|
|
154
|
+
)(json);
|
|
155
|
+
|
|
156
|
+
return R.map(R.filter((val) => val !== 'null'))(directGraph);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
module.exports.getPictures = getPictures;
|
|
160
|
+
module.exports.getAllStepName = getAllStepName;
|
|
161
|
+
module.exports.getStepComponent = getStepComponent;
|
|
162
|
+
module.exports.createDirectGraphForJson = createDirectGraphForJson;
|
|
163
|
+
module.exports.hasTemplates = hasTemplates;
|
|
164
|
+
module.exports.hasNoTemplates = hasNoTemplates;
|
|
165
|
+
module.exports.getAllConfigurationForTemplateLiteral = getAllConfigurationForTemplateLiteral;
|
|
@@ -33,6 +33,107 @@ The `PbProjectItemSave` component to save project item in existing project or ne
|
|
|
33
33
|
components: { PbProjectItemSave },
|
|
34
34
|
created() {
|
|
35
35
|
this.$store.dispatch('projects/loadProjects');
|
|
36
|
+
this.$store.dispatch('estimates/setSummary', {
|
|
37
|
+
subprojectId: 'ae62d167-e02e-4744-81b1-102cc5816be2',
|
|
38
|
+
subprojectTemplateId: '22248ac3-9391-47f4-8a54-6fe280c2fa5b',
|
|
39
|
+
businessUnit: 'LMFR',
|
|
40
|
+
summaryDate: '2020-05-13T09:49:45.886602047Z',
|
|
41
|
+
cost: {
|
|
42
|
+
min: 691526.2,
|
|
43
|
+
max: 1443197.48,
|
|
44
|
+
currency: 'EURO',
|
|
45
|
+
},
|
|
46
|
+
components: [
|
|
47
|
+
{
|
|
48
|
+
componentId: 'LAND',
|
|
49
|
+
title: 'Terrain en lotissement',
|
|
50
|
+
cost: {
|
|
51
|
+
min: 20664,
|
|
52
|
+
max: 38523.6,
|
|
53
|
+
currency: 'EURO',
|
|
54
|
+
},
|
|
55
|
+
lines: [
|
|
56
|
+
{
|
|
57
|
+
text: '- Terrain seul',
|
|
58
|
+
details: 'Terrain constructible, délimité et viabilisé. La nature du sous-sol est garantie.',
|
|
59
|
+
cost: {
|
|
60
|
+
min: 19680,
|
|
61
|
+
max: 35670,
|
|
62
|
+
currency: 'EURO',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
text: '- Frais de notaire',
|
|
67
|
+
cost: {
|
|
68
|
+
min: 984,
|
|
69
|
+
max: 2853.6,
|
|
70
|
+
currency: 'EURO',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
componentId: 'HOUSE',
|
|
77
|
+
title: 'Maison contemporaine livrée prête à finir',
|
|
78
|
+
cost: {
|
|
79
|
+
min: 664562.5,
|
|
80
|
+
max: 1381050,
|
|
81
|
+
currency: 'EURO',
|
|
82
|
+
},
|
|
83
|
+
lines: [
|
|
84
|
+
{
|
|
85
|
+
text: '- Budget construction maison',
|
|
86
|
+
details:
|
|
87
|
+
"Ce budget n'inclut pas : le terrain, la viabilisation, l'aménagement extérieur et la taxe d'aménagement.",
|
|
88
|
+
cost: {
|
|
89
|
+
min: 651000,
|
|
90
|
+
max: 1255500,
|
|
91
|
+
currency: 'EURO',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
componentId: 'TAXES',
|
|
98
|
+
title: "Taxe d'aménagement",
|
|
99
|
+
details:
|
|
100
|
+
"Taxe qui s'applique pour les projets de construction, de reconstruction et d'agrandissement qui nécessitent des autorisations de travaux. Un abattement de 50% est prévu sur les 100 premiers m².",
|
|
101
|
+
cost: {
|
|
102
|
+
min: 6299.7,
|
|
103
|
+
max: 23623.88,
|
|
104
|
+
currency: 'EURO',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
subprojectAttributes: {
|
|
109
|
+
finish: 'PARTIALLY_BY_MYSELF',
|
|
110
|
+
houseType: 'CONTEMPORARY',
|
|
111
|
+
inseeCode: '59350',
|
|
112
|
+
land: 'NOT_YET',
|
|
113
|
+
landSurfaceInSquareMeters: 123,
|
|
114
|
+
landType: 'IN_A_LOT',
|
|
115
|
+
livingAreaInSquareMeters: 465,
|
|
116
|
+
},
|
|
117
|
+
suggestedTypologies: [
|
|
118
|
+
{
|
|
119
|
+
domesticSpaceLabel: 'Cuisine',
|
|
120
|
+
domesticSpaceHref: '/domestic-spaces/59405',
|
|
121
|
+
projectKindHref: '/project-kinds/34048',
|
|
122
|
+
projectTypeHref: '/project-types/29239',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
domesticSpaceLabel: 'Tout le logement',
|
|
126
|
+
domesticSpaceHref: '/domestic-spaces/59461',
|
|
127
|
+
projectKindHref: '/project-kinds/34048',
|
|
128
|
+
projectTypeHref: '/project-types/61855',
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
legalMentions: [
|
|
132
|
+
"Les prix ci-dessus ne sont proposés qu'à titre indicatif et sont basés sur les prix du marché.",
|
|
133
|
+
"L'outil d'estimation ne vaut pas offre de vente.",
|
|
134
|
+
"La disponibilité des produits au moment de l'achat n'est pas garantie.",
|
|
135
|
+
],
|
|
136
|
+
});
|
|
36
137
|
this.$store.dispatch('projects/loadTypologies');
|
|
37
138
|
},
|
|
38
139
|
template: ` <div style="flex-direction: column;display: flex;place-content: flex-start;align-items: stretch;min-height: 100vh;">
|
|
@@ -2,23 +2,16 @@
|
|
|
2
2
|
<div :class="`pb-restitution-block`">
|
|
3
3
|
<m-accordion :label="accordionLabel">
|
|
4
4
|
<template #content>
|
|
5
|
-
<
|
|
5
|
+
<div
|
|
6
6
|
direction="column"
|
|
7
7
|
justify-content="space-between"
|
|
8
8
|
align-items="baseline"
|
|
9
9
|
class="pb-restitution-block__head"
|
|
10
|
-
full-width
|
|
11
10
|
>
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
align-items="stretch"
|
|
17
|
-
full-width
|
|
18
|
-
>
|
|
19
|
-
<m-flex class="pb-restitution-block__details-label" align-items="center">{{ component.details }}</m-flex>
|
|
20
|
-
</m-flex>
|
|
21
|
-
</m-flex>
|
|
11
|
+
<div v-if="component.details" class="pb-restitution-block__details">
|
|
12
|
+
{{ component.details }}
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
22
15
|
<pb-restitution-line
|
|
23
16
|
v-for="(line, index) in component.lines"
|
|
24
17
|
:key="`${index}-${line.text}`"
|
|
@@ -31,7 +24,6 @@
|
|
|
31
24
|
</template>
|
|
32
25
|
|
|
33
26
|
<script>
|
|
34
|
-
import MFlex from '../mozaic/flex/MFlex';
|
|
35
27
|
import MAccordion from '../mozaic/accordions/MAccordion';
|
|
36
28
|
import PbRestitutionLine from './PbRestitutionLine';
|
|
37
29
|
|
|
@@ -39,7 +31,6 @@ export default {
|
|
|
39
31
|
name: 'PbRestitutionBlock',
|
|
40
32
|
|
|
41
33
|
components: {
|
|
42
|
-
MFlex,
|
|
43
34
|
MAccordion,
|
|
44
35
|
PbRestitutionLine,
|
|
45
36
|
},
|
|
@@ -75,15 +66,12 @@ export default {
|
|
|
75
66
|
$responsive-breakpoint: 'm';
|
|
76
67
|
|
|
77
68
|
.pb-restitution-block {
|
|
78
|
-
margin-bottom: $mu150;
|
|
79
69
|
width: 100%;
|
|
80
70
|
|
|
81
71
|
&__head {
|
|
82
72
|
@include set-font-face('semi-bold');
|
|
83
73
|
@include set-font-scale('06', 'm');
|
|
84
74
|
|
|
85
|
-
padding-bottom: $mu050;
|
|
86
|
-
|
|
87
75
|
@include set-from-screen($responsive-breakpoint) {
|
|
88
76
|
@include set-font-scale('07', 'm');
|
|
89
77
|
}
|
|
@@ -94,26 +82,35 @@ $responsive-breakpoint: 'm';
|
|
|
94
82
|
@include set-border-radius('m');
|
|
95
83
|
@include set-font-scale('04', 'm');
|
|
96
84
|
|
|
85
|
+
background-color: $color-primary-01-100;
|
|
97
86
|
box-sizing: border-box;
|
|
87
|
+
color: $color-font-dark;
|
|
98
88
|
color: $color-font-darker;
|
|
99
|
-
margin-bottom: $mu050;
|
|
100
89
|
padding: $mu100;
|
|
90
|
+
position: relative;
|
|
91
|
+
width: 100%;
|
|
101
92
|
|
|
102
|
-
|
|
103
|
-
|
|
93
|
+
.a11y-high-contrast & {
|
|
94
|
+
background-color: $color-primary-01-300;
|
|
104
95
|
}
|
|
105
96
|
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
&::before {
|
|
98
|
+
border-bottom: $mu050 solid $color-primary-01-100;
|
|
99
|
+
border-left: $mu050 solid transparent;
|
|
100
|
+
border-right: $mu050 solid transparent;
|
|
101
|
+
content: '';
|
|
102
|
+
height: 0;
|
|
103
|
+
position: absolute;
|
|
104
|
+
top: -$mu050;
|
|
105
|
+
width: 0;
|
|
108
106
|
}
|
|
109
|
-
}
|
|
110
107
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
.a11y-high-contrast &::before {
|
|
109
|
+
border-bottom: $mu050 solid $color-primary-01-200;
|
|
110
|
+
}
|
|
114
111
|
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
@include set-from-screen($responsive-breakpoint) {
|
|
113
|
+
@include set-font-scale('05', 'l');
|
|
117
114
|
}
|
|
118
115
|
}
|
|
119
116
|
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<m-flex :class="`pb-restitution-line`" direction="column">
|
|
3
3
|
<m-flex full-width>
|
|
4
|
-
<
|
|
5
|
-
<div>{{ line.text }}</div>
|
|
6
|
-
<div v-if="line.details" @click="displayDetails = !displayDetails" class="pb-restitution-line__label-icon">
|
|
7
|
-
<m-icon :icon="INFO_ICON" size="s" color="primary-01-600" />
|
|
8
|
-
</div>
|
|
9
|
-
</m-flex>
|
|
4
|
+
<div class="pb-restitution-line__label">{{ line.text }}</div>
|
|
10
5
|
<m-flex class="pb-restitution-line__price" v-if="line.cost" justify-content="flex-end" wrap>
|
|
11
6
|
<div v-if="line.cost.min !== line.cost.max" class="pb-restitution-line__price-min">
|
|
12
7
|
{{ formatPriceRange(line.cost.min, line.cost.max).min }} -
|
|
@@ -16,12 +11,7 @@
|
|
|
16
11
|
</div>
|
|
17
12
|
</m-flex>
|
|
18
13
|
</m-flex>
|
|
19
|
-
<
|
|
20
|
-
<m-flex class="pb-restitution-line__details-label" align-items="center">{{ line.details }}</m-flex>
|
|
21
|
-
<m-flex class="pb-restitution-line__details-cross" @click="displayDetails = false" justify-content="flex-start">
|
|
22
|
-
<m-icon :icon="CROSS_ICON" size="s" color="grey-600" />
|
|
23
|
-
</m-flex>
|
|
24
|
-
</m-flex>
|
|
14
|
+
<div v-if="line.details" class="pb-restitution-line__details">{{ line.details }}</div>
|
|
25
15
|
</m-flex>
|
|
26
16
|
</template>
|
|
27
17
|
|
|
@@ -39,7 +29,6 @@ export default {
|
|
|
39
29
|
|
|
40
30
|
components: {
|
|
41
31
|
MFlex,
|
|
42
|
-
MIcon,
|
|
43
32
|
},
|
|
44
33
|
|
|
45
34
|
props: {
|
|
@@ -54,7 +43,6 @@ export default {
|
|
|
54
43
|
},
|
|
55
44
|
|
|
56
45
|
data: () => ({
|
|
57
|
-
displayDetails: false,
|
|
58
46
|
CROSS_ICON,
|
|
59
47
|
INFO_ICON,
|
|
60
48
|
}),
|
|
@@ -114,33 +102,35 @@ $responsive-breakpoint: 'm';
|
|
|
114
102
|
@include set-border-radius('m');
|
|
115
103
|
@include set-font-scale('04', 'm');
|
|
116
104
|
|
|
117
|
-
|
|
105
|
+
background-color: $color-primary-01-100;
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
color: $color-font-dark;
|
|
108
|
+
margin-top: $mu050;
|
|
118
109
|
padding: $mu100;
|
|
110
|
+
position: relative;
|
|
111
|
+
width: 100%;
|
|
119
112
|
|
|
120
|
-
|
|
121
|
-
|
|
113
|
+
.a11y-high-contrast & {
|
|
114
|
+
background-color: $color-primary-01-200;
|
|
122
115
|
}
|
|
123
116
|
|
|
124
|
-
|
|
125
|
-
|
|
117
|
+
&::before {
|
|
118
|
+
border-bottom: $mu050 solid $color-primary-01-100;
|
|
119
|
+
border-left: $mu050 solid transparent;
|
|
120
|
+
border-right: $mu050 solid transparent;
|
|
121
|
+
content: '';
|
|
122
|
+
height: 0;
|
|
123
|
+
position: absolute;
|
|
124
|
+
top: -$mu050;
|
|
125
|
+
width: 0;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
padding-left: $mu150;
|
|
131
|
-
|
|
132
|
-
&:hover {
|
|
133
|
-
cursor: pointer;
|
|
134
|
-
}
|
|
128
|
+
.a11y-high-contrast &::before {
|
|
129
|
+
border-bottom: $mu050 solid $color-primary-01-200;
|
|
135
130
|
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
&__details {
|
|
139
|
-
background-color: $color-primary-01-100;
|
|
140
|
-
color: $color-font-dark;
|
|
141
131
|
|
|
142
|
-
|
|
143
|
-
|
|
132
|
+
@include set-from-screen($responsive-breakpoint) {
|
|
133
|
+
@include set-font-scale('05', 'l');
|
|
144
134
|
}
|
|
145
135
|
}
|
|
146
136
|
}
|
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
const getAppointmentQualification = async (start, end, inhabitantProjectId, groupId, appointmentId) => {
|
|
5
5
|
var url = inhabitantProjectId
|
|
6
6
|
? `/api/appointment-qualifications?range=${start}-${end}&inhabitantProjectId=${inhabitantProjectId}`
|
|
7
7
|
: `/api/appointment-qualifications?range=${start}-${end}&groupId=${groupId}&appointmentId=${appointmentId}`;
|
|
8
|
-
const response = await
|
|
8
|
+
const response = await axios.get(url);
|
|
9
9
|
|
|
10
10
|
return JSON.parse(
|
|
11
|
-
JSON.stringify(response.
|
|
11
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
12
12
|
return `: "${he.escape($1)}"`;
|
|
13
13
|
}),
|
|
14
14
|
);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const saveAnswersByAppointmentQualificationId = async (appointmentQualificationId, data) => {
|
|
18
|
-
const response = await
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.send(data);
|
|
18
|
+
const response = await axios.put(`/api/appointment-qualifications/${appointmentQualificationId}/answers`, data, {
|
|
19
|
+
headers: { 'Content-Type': 'application/json' },
|
|
20
|
+
});
|
|
22
21
|
|
|
23
22
|
return JSON.parse(
|
|
24
|
-
JSON.stringify(response.
|
|
23
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
25
24
|
return `: "${he.escape($1)}"`;
|
|
26
25
|
}),
|
|
27
26
|
);
|
|
28
27
|
};
|
|
29
28
|
|
|
30
29
|
const declarationsWithAppointment = async (data) => {
|
|
31
|
-
return await
|
|
30
|
+
return await axios.post('/api/declarations-with-appointment', data, {
|
|
31
|
+
headers: { 'Content-Type': 'application/json' },
|
|
32
|
+
});
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
export { declarationsWithAppointment, saveAnswersByAppointmentQualificationId, getAppointmentQualification };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
const getConfiguration = async () => {
|
|
5
|
-
const response = await
|
|
5
|
+
const response = await axios.get('/configuration');
|
|
6
6
|
|
|
7
7
|
return JSON.parse(
|
|
8
|
-
JSON.stringify(response.
|
|
8
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
9
9
|
return `: "${he.escape($1)}"`;
|
|
10
10
|
}),
|
|
11
11
|
);
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
const getProjectConfigurationsForProjectType = async (inhabitantProjectId, all) => {
|
|
5
5
|
let response;
|
|
6
6
|
if (all) {
|
|
7
|
-
response = await
|
|
7
|
+
response = await axios.get('/api/simulations', { params: { inhabitantProjectId, all } });
|
|
8
8
|
} else {
|
|
9
|
-
response = await
|
|
9
|
+
response = await axios.get('/api/simulations', { params: { inhabitantProjectId } });
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
console.log(response);
|
|
13
|
+
|
|
12
14
|
return JSON.parse(
|
|
13
|
-
JSON.stringify(response.
|
|
15
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
14
16
|
return `: "${he.escape($1)}"`;
|
|
15
17
|
}),
|
|
16
18
|
);
|
|
@@ -19,25 +21,25 @@ const getProjectConfigurationsForProjectType = async (inhabitantProjectId, all)
|
|
|
19
21
|
const getAllProjectConfigurations = async (inhabitantProjectId, forceNoPriceUpdate) => {
|
|
20
22
|
let response;
|
|
21
23
|
if (forceNoPriceUpdate) {
|
|
22
|
-
response = await
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
response = await axios.get(`/api/inhabitant-projects/${inhabitantProjectId}/simulations`, {
|
|
25
|
+
params: { forceNoPriceUpdate },
|
|
26
|
+
});
|
|
25
27
|
} else {
|
|
26
|
-
response = await
|
|
28
|
+
response = await axios.get(`/api/inhabitant-projects/${inhabitantProjectId}/simulations`);
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
return JSON.parse(
|
|
30
|
-
JSON.stringify(response.
|
|
32
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
31
33
|
return `: "${he.escape($1)}"`;
|
|
32
34
|
}),
|
|
33
35
|
);
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
const linkConfiguration = async (id, inhabitantProjectId) => {
|
|
37
|
-
const response = await
|
|
39
|
+
const response = await axios.post(`/api/inhabitant-projects/${inhabitantProjectId}/simulations/${id}`);
|
|
38
40
|
|
|
39
41
|
return JSON.parse(
|
|
40
|
-
JSON.stringify(response.
|
|
42
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
41
43
|
return `: "${he.escape($1)}"`;
|
|
42
44
|
}),
|
|
43
45
|
);
|
|
@@ -1,47 +1,48 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
const uploadDocument = async (formData, inhabitantProjectId, correlationId, subType, trackProgress, fileName) => {
|
|
5
5
|
const [name, file] = formData.entries().next().value;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
const data = new FormData();
|
|
7
|
+
data.append('document', file);
|
|
8
|
+
data.append('metadata', JSON.stringify({ type: 'PLAN', correlationId, subType, title: fileName }, null, '\t'));
|
|
9
|
+
return await axios.post(`/api/inhabitant-projects/${inhabitantProjectId}/documents`, data, {
|
|
10
|
+
onUploadProgress: trackProgress,
|
|
11
|
+
});
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
const getDocumentsByInhabitantProjectId = async (start, end, inhabitantProjectId) => {
|
|
14
|
-
const response = await
|
|
15
|
+
const response = await axios.get(`/api/inhabitant-projects/${inhabitantProjectId}/documents?range=${start}-${end}`);
|
|
15
16
|
|
|
16
17
|
return JSON.parse(
|
|
17
|
-
JSON.stringify(response.
|
|
18
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
18
19
|
return `: "${he.escape($1)}"`;
|
|
19
20
|
}),
|
|
20
21
|
);
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const getDocumentById = async (inhabitantProjectId, documentId) => {
|
|
24
|
-
const response = await
|
|
25
|
+
const response = await axios.get(`/api/inhabitant-projects/${inhabitantProjectId}/documents/${documentId}`);
|
|
25
26
|
|
|
26
27
|
return JSON.parse(
|
|
27
|
-
JSON.stringify(response.
|
|
28
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
28
29
|
return `: "${he.escape($1)}"`;
|
|
29
30
|
}),
|
|
30
31
|
);
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
const getDocumentThumbnail = async (inhabitantProjectId, documentId) => {
|
|
34
|
-
return await
|
|
35
|
+
return await axios.get(`/api/inhabitant-projects/${inhabitantProjectId}/documents/${documentId}/thumbnail`);
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
const updateDocumentName = async (inhabitantProjectId, documentId, documentName) => {
|
|
38
|
-
return await
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
return await axios.patch(`/api/inhabitant-projects/${inhabitantProjectId}/documents/${documentId}`, {
|
|
40
|
+
title: documentName,
|
|
41
|
+
});
|
|
41
42
|
};
|
|
42
43
|
|
|
43
44
|
const deleteDocument = async (inhabitantProjectId, documentId) => {
|
|
44
|
-
return await
|
|
45
|
+
return await axios.delete(`/api/inhabitant-projects/${inhabitantProjectId}/documents/${documentId}`);
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
export {
|
|
@@ -1,56 +1,59 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
export const getAllEstimates = async (currentEstimatesPage, estimatesPerPageCount, inhabitantProjectId) => {
|
|
5
5
|
const start = currentEstimatesPage * estimatesPerPageCount;
|
|
6
6
|
const end = start + estimatesPerPageCount - 1;
|
|
7
|
-
const response = await
|
|
7
|
+
const response = await axios.get(`/api/estimates?range=${start}-${end}&inhabitantProjectId=${inhabitantProjectId}`);
|
|
8
8
|
|
|
9
9
|
return JSON.parse(
|
|
10
|
-
JSON.stringify(response.
|
|
10
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
11
11
|
return `: "${he.escape($1)}"`;
|
|
12
12
|
}),
|
|
13
13
|
);
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export const getEstimateById = async (id) => {
|
|
17
|
-
const response = await
|
|
17
|
+
const response = await axios.get(`/api/estimates/${id}`);
|
|
18
18
|
|
|
19
19
|
return JSON.parse(
|
|
20
|
-
JSON.stringify(response.
|
|
20
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
21
21
|
return `: "${he.escape($1)}"`;
|
|
22
22
|
}),
|
|
23
23
|
);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export const deleteEstimateById = async (id) => {
|
|
27
|
-
const response = await
|
|
27
|
+
const response = await axios.delete(`/api/estimates/${id}`);
|
|
28
28
|
|
|
29
29
|
return JSON.parse(
|
|
30
|
-
JSON.stringify(response.
|
|
30
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
31
31
|
return `: "${he.escape($1)}"`;
|
|
32
32
|
}),
|
|
33
33
|
);
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
export const saveEstimate = async (estimate) => {
|
|
37
|
-
const response = await
|
|
37
|
+
const response = await axios.post('/api/estimates', estimate, {
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
38
42
|
|
|
39
43
|
return JSON.parse(
|
|
40
|
-
JSON.stringify(response.
|
|
44
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
41
45
|
return `: "${he.escape($1)}"`;
|
|
42
46
|
}),
|
|
43
47
|
);
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
export const estimate = async (estimatorId, statelessEstimate) => {
|
|
47
|
-
const response = await
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.send(statelessEstimate);
|
|
51
|
+
const response = await axios.post(`/api/estimators/${estimatorId}:estimate`, statelessEstimate, {
|
|
52
|
+
headers: { 'Content-Type': 'application/json' },
|
|
53
|
+
});
|
|
51
54
|
|
|
52
55
|
return JSON.parse(
|
|
53
|
-
JSON.stringify(response.
|
|
56
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
54
57
|
return `: "${he.escape($1)}"`;
|
|
55
58
|
}),
|
|
56
59
|
);
|
|
@@ -1,63 +1,61 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
export const sendAppointmentQualificationEvent = async (event) => {
|
|
5
|
-
const response = await
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
.send(event);
|
|
5
|
+
const response = await axios.post('/api/events/appointment-qualification-events', event, {
|
|
6
|
+
headers: { 'Content-Type': 'application/json' },
|
|
7
|
+
});
|
|
9
8
|
|
|
10
9
|
return JSON.parse(
|
|
11
|
-
JSON.stringify(response.
|
|
10
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
12
11
|
return `: "${he.escape($1)}"`;
|
|
13
12
|
}),
|
|
14
13
|
);
|
|
15
14
|
};
|
|
16
15
|
|
|
17
16
|
export const sendAppointmentQualificationAnswers = async (event) => {
|
|
18
|
-
const response = await
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.send(event);
|
|
17
|
+
const response = await axios.post('/api/events/appointment-qualification-answers', event, {
|
|
18
|
+
headers: { 'Content-Type': 'application/json' },
|
|
19
|
+
});
|
|
22
20
|
|
|
23
21
|
return JSON.parse(
|
|
24
|
-
JSON.stringify(response.
|
|
22
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
25
23
|
return `: "${he.escape($1)}"`;
|
|
26
24
|
}),
|
|
27
25
|
);
|
|
28
26
|
};
|
|
29
27
|
|
|
30
28
|
export const sendDocumentsEvent = async (event) => {
|
|
31
|
-
const response = await
|
|
29
|
+
const response = await axios.post('/api/events/documents', event, {
|
|
30
|
+
headers: { 'Content-Type': 'application/json' },
|
|
31
|
+
});
|
|
32
32
|
|
|
33
33
|
return JSON.parse(
|
|
34
|
-
JSON.stringify(response.
|
|
34
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
35
35
|
return `: "${he.escape($1)}"`;
|
|
36
36
|
}),
|
|
37
37
|
);
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
export const sendCardClickEvent = async (event) => {
|
|
41
|
-
const response = await
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.send(event);
|
|
41
|
+
const response = await axios.post('/api/events/pushed-card-clicks', event, {
|
|
42
|
+
headers: { 'Content-Type': 'application/json' },
|
|
43
|
+
});
|
|
45
44
|
|
|
46
45
|
return JSON.parse(
|
|
47
|
-
JSON.stringify(response.
|
|
46
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
48
47
|
return `: "${he.escape($1)}"`;
|
|
49
48
|
}),
|
|
50
49
|
);
|
|
51
50
|
};
|
|
52
51
|
|
|
53
52
|
export const sendDeclarationEvent = async (event) => {
|
|
54
|
-
const response = await
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.send(event);
|
|
53
|
+
const response = await axios.post('/api/events/project-declarations', event, {
|
|
54
|
+
headers: { 'Content-Type': 'application/json' },
|
|
55
|
+
});
|
|
58
56
|
|
|
59
57
|
return JSON.parse(
|
|
60
|
-
JSON.stringify(response.
|
|
58
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
61
59
|
return `: "${he.escape($1)}"`;
|
|
62
60
|
}),
|
|
63
61
|
);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
export const getInhabitantById = async (inhabitantId, buId = '001') => {
|
|
5
|
-
const response = await
|
|
5
|
+
const response = await axios.get(`/api/inhabitant-api/users/${buId}/${inhabitantId}`);
|
|
6
6
|
|
|
7
7
|
return JSON.parse(
|
|
8
|
-
JSON.stringify(response.
|
|
8
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
9
9
|
return `: "${he.escape($1)}"`;
|
|
10
10
|
}),
|
|
11
11
|
);
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
const getAllMedia = async (start, end, inhabitantProjectId) => {
|
|
5
|
-
const response = await
|
|
5
|
+
const response = await axios.get(`/api/media?range=${start}-${end}&inhabitantProjectId=${inhabitantProjectId}`);
|
|
6
6
|
|
|
7
7
|
return JSON.parse(
|
|
8
|
-
JSON.stringify(response.
|
|
8
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
9
9
|
return `: "${he.escape($1)}"`;
|
|
10
10
|
}),
|
|
11
11
|
);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const getMediumById = async (mediumId) => {
|
|
15
|
-
const response = await
|
|
15
|
+
const response = await axios.get(`/api/media/${mediumId}`);
|
|
16
16
|
|
|
17
17
|
return JSON.parse(
|
|
18
|
-
JSON.stringify(response.
|
|
18
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
19
19
|
return `: "${he.escape($1)}"`;
|
|
20
20
|
}),
|
|
21
21
|
);
|
|
@@ -23,27 +23,27 @@ const getMediumById = async (mediumId) => {
|
|
|
23
23
|
|
|
24
24
|
const uploadMedia = async (formData, inhabitantProjectId, correlationId, fileName, isRoomPicture, trackProgress) => {
|
|
25
25
|
const [name, file] = formData.entries().next().value;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
const data = new FormData();
|
|
27
|
+
data.append(name, file);
|
|
28
|
+
data.append(
|
|
29
|
+
'metadata',
|
|
30
|
+
JSON.stringify({ inhabitantProjectId, correlationId, title: fileName, roomPicture: isRoomPicture }, null, '\t'),
|
|
31
|
+
);
|
|
32
|
+
return await axios.post('/api/media', data, {
|
|
33
|
+
onUploadProgress: trackProgress,
|
|
34
|
+
});
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
const updateMediaName = async (mediaId, mediaName) => {
|
|
38
|
-
return await
|
|
38
|
+
return await axios.patch(`/api/media/${mediaId}`, { title: mediaName });
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
const makeMediaPublic = async (mediaId) => {
|
|
42
|
-
return await
|
|
42
|
+
return await axios.patch(`/api/media/${mediaId}`, { public: true });
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const deleteMedia = async (mediaId) => {
|
|
46
|
-
return await
|
|
46
|
+
return await axios.delete(`/api/media/${mediaId}`);
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
export { getAllMedia, getMediumById, uploadMedia, updateMediaName, makeMediaPublic, deleteMedia };
|
|
@@ -1,54 +1,53 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
export const getWorkKindsByProjectTypeId = async (projectTypeId) => {
|
|
5
|
-
const response = await
|
|
5
|
+
const response = await axios.get(`/api/project-types/${projectTypeId}/work-kinds`);
|
|
6
6
|
|
|
7
7
|
return JSON.parse(
|
|
8
|
-
JSON.stringify(response.
|
|
8
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
9
9
|
return `: "${he.escape($1)}"`;
|
|
10
10
|
}),
|
|
11
11
|
);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const getProductsByWorkKind = async (workKindId, storeId) => {
|
|
15
|
-
const response = await
|
|
15
|
+
const response = await axios.get(`/api/work-kinds/${workKindId}/products${storeId ? '?storeId=' + storeId : ''}`);
|
|
16
16
|
|
|
17
17
|
return JSON.parse(
|
|
18
|
-
JSON.stringify(response.
|
|
18
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
19
19
|
return `: "${he.escape($1)}"`;
|
|
20
20
|
}),
|
|
21
21
|
);
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export const getProductsFeatureFlag = async (projectTypeId) => {
|
|
25
|
-
const response = await
|
|
25
|
+
const response = await axios.get(`/api/project-types/${projectTypeId}/products-feature-flag`);
|
|
26
26
|
|
|
27
27
|
return JSON.parse(
|
|
28
|
-
JSON.stringify(response.
|
|
28
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
29
29
|
return `: "${he.escape($1)}"`;
|
|
30
30
|
}),
|
|
31
31
|
);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
export const saveWorkKinds = async (inhabitantProjectId, workKinds) => {
|
|
35
|
-
const response = await
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.send(workKinds);
|
|
35
|
+
const response = await axios.put(`/api/inhabitant-projects/${inhabitantProjectId}/work-kinds`, workKinds, {
|
|
36
|
+
headers: { 'Content-Type': 'application/json' },
|
|
37
|
+
});
|
|
39
38
|
|
|
40
39
|
return JSON.parse(
|
|
41
|
-
JSON.stringify(response.
|
|
40
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
42
41
|
return `: "${he.escape($1)}"`;
|
|
43
42
|
}),
|
|
44
43
|
);
|
|
45
44
|
};
|
|
46
45
|
|
|
47
46
|
export const getWorkKindsByProjectId = async (inhabitantProjectId) => {
|
|
48
|
-
const response = await
|
|
47
|
+
const response = await axios.get(`/api/inhabitant-projects/${inhabitantProjectId}/work-kinds`);
|
|
49
48
|
|
|
50
49
|
return JSON.parse(
|
|
51
|
-
JSON.stringify(response.
|
|
50
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
52
51
|
return `: "${he.escape($1)}"`;
|
|
53
52
|
}),
|
|
54
53
|
);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
export const getAllProjects = async (currentProjectsPage, projectsPerPageCount) => {
|
|
5
5
|
const start = currentProjectsPage * projectsPerPageCount;
|
|
6
6
|
const end = start + projectsPerPageCount - 1;
|
|
7
|
-
const response = await
|
|
7
|
+
const response = await axios.get(`/api/inhabitant-projects?range=${start}-${end}`);
|
|
8
8
|
|
|
9
9
|
return JSON.parse(
|
|
10
|
-
JSON.stringify(response.
|
|
10
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
11
11
|
return `: "${he.escape($1)}"`;
|
|
12
12
|
}),
|
|
13
13
|
);
|
|
@@ -16,71 +16,69 @@ export const getAllProjects = async (currentProjectsPage, projectsPerPageCount)
|
|
|
16
16
|
export const getAllProjectsForUserId = async (currentProjectsPage, projectsPerPageCount, userId) => {
|
|
17
17
|
const start = currentProjectsPage * projectsPerPageCount;
|
|
18
18
|
const end = start + projectsPerPageCount - 1;
|
|
19
|
-
const response = await
|
|
19
|
+
const response = await axios.get(`/api/inhabitant-projects?range=${start}-${end}&userId=${userId}`);
|
|
20
20
|
|
|
21
21
|
return JSON.parse(
|
|
22
|
-
JSON.stringify(response.
|
|
22
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
23
23
|
return `: "${he.escape($1)}"`;
|
|
24
24
|
}),
|
|
25
25
|
);
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export const getProjectById = async (id) => {
|
|
29
|
-
const response = await
|
|
29
|
+
const response = await axios.get(`/api/inhabitant-projects/${id}`);
|
|
30
30
|
|
|
31
31
|
return JSON.parse(
|
|
32
|
-
JSON.stringify(response.
|
|
32
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
33
33
|
return `: "${he.escape($1)}"`;
|
|
34
34
|
}),
|
|
35
35
|
);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
export const deleteProjectById = async (id) => {
|
|
39
|
-
const response = await
|
|
39
|
+
const response = await axios.delete(`/api/inhabitant-projects/${id}`);
|
|
40
40
|
|
|
41
41
|
return JSON.parse(
|
|
42
|
-
JSON.stringify(response.
|
|
42
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
43
43
|
return `: "${he.escape($1)}"`;
|
|
44
44
|
}),
|
|
45
45
|
);
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
export const saveInhabitantProject = async (inhabitantProject) => {
|
|
49
|
-
const response = await
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.send(inhabitantProject);
|
|
49
|
+
const response = await axios.post('/api/inhabitant-projects', inhabitantProject, {
|
|
50
|
+
headers: { 'Content-Type': 'application/json' },
|
|
51
|
+
});
|
|
53
52
|
return response.headers.location;
|
|
54
53
|
};
|
|
55
54
|
|
|
56
55
|
export const saveProjectDeclaration = async (projectDeclaration) => {
|
|
57
|
-
const response = await
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
.send(projectDeclaration);
|
|
56
|
+
const response = await axios.post('/api/declarations', projectDeclaration, {
|
|
57
|
+
headers: { 'Content-Type': 'application/json' },
|
|
58
|
+
});
|
|
61
59
|
|
|
62
60
|
return JSON.parse(
|
|
63
|
-
JSON.stringify(response.
|
|
61
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
64
62
|
return `: "${he.escape($1)}"`;
|
|
65
63
|
}),
|
|
66
64
|
);
|
|
67
65
|
};
|
|
68
66
|
|
|
69
67
|
export const getProjectAttributesById = async (id) => {
|
|
70
|
-
const response = await
|
|
68
|
+
const response = await axios.get(`/api/inhabitant-projects/${id}/attributes`);
|
|
71
69
|
|
|
72
70
|
return JSON.parse(
|
|
73
|
-
JSON.stringify(response.
|
|
71
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
74
72
|
return `: "${he.escape($1)}"`;
|
|
75
73
|
}),
|
|
76
74
|
);
|
|
77
75
|
};
|
|
78
76
|
|
|
79
77
|
export const getAppointmentById = async (id) => {
|
|
80
|
-
const response = await
|
|
78
|
+
const response = await axios.get(`/api/inhabitant-projects/${id}/main-appointment`);
|
|
81
79
|
|
|
82
80
|
return JSON.parse(
|
|
83
|
-
JSON.stringify(response.
|
|
81
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
84
82
|
return `: "${he.escape($1)}"`;
|
|
85
83
|
}),
|
|
86
84
|
);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import axios from 'axios';
|
|
2
2
|
import he from 'he';
|
|
3
3
|
|
|
4
4
|
export const getAllTools = async (projectType) => {
|
|
5
|
-
const response = await
|
|
5
|
+
const response = await axios.get(`${config.VUE_APP_TOOLS_CONFIGURATION_STORAGE}/${projectType}.json`);
|
|
6
6
|
|
|
7
7
|
return JSON.parse(
|
|
8
|
-
JSON.stringify(response.
|
|
8
|
+
JSON.stringify(response.data).replace(/:"([^"]+)"/g, (match, $1) => {
|
|
9
9
|
return `: "${he.escape($1)}"`;
|
|
10
10
|
}),
|
|
11
11
|
);
|
|
@@ -586,6 +586,9 @@ export const projectTypologiesStoreOptions = {
|
|
|
586
586
|
setTypologies(state, typologies) {
|
|
587
587
|
state.typologies = typologies;
|
|
588
588
|
},
|
|
589
|
+
addTypologies(state, typologies) {
|
|
590
|
+
state.typologies.push(...typologies);
|
|
591
|
+
},
|
|
589
592
|
setTypologiesLoadError(state, typologiesLoadError) {
|
|
590
593
|
state.typologiesLoadError = typologiesLoadError;
|
|
591
594
|
},
|
|
@@ -603,10 +606,10 @@ export const projectTypologiesStoreOptions = {
|
|
|
603
606
|
},
|
|
604
607
|
},
|
|
605
608
|
actions: {
|
|
606
|
-
async loadTypologies({ commit, state }) {
|
|
609
|
+
async loadTypologies({ commit, state, rootGetters }) {
|
|
607
610
|
commit('setTypologiesLoadError', null);
|
|
608
611
|
try {
|
|
609
|
-
const typologies =
|
|
612
|
+
const typologies = rootGetters['estimates/getSummary']?.suggestedTypologies?.map((typology) => ({
|
|
610
613
|
code: typology.domesticSpaceHref,
|
|
611
614
|
title: typology.domesticSpaceLabel,
|
|
612
615
|
}));
|