mod-build 4.0.100-beta.4 → 4.0.100

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/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 4.0.100
4
4
 
5
- - Refactored `get-default-trade-questions.js` to reduce duplicated logic in `lead-form` and enable reuse across instances.
5
+ - Added field-level `move` support in `get-default-trade-questions` (e.g. `move: [{ from: 3, to: 0 }]`) to reorder default options while merging
6
6
 
7
7
  ## 4.0.99
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mod-build",
3
- "version": "4.0.100-beta.4",
3
+ "version": "4.0.100",
4
4
  "description": "Share components for S3 sites.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -2,7 +2,7 @@
2
2
  import merge from 'lodash.merge';
3
3
  import { defaultSettings } from '../src/data/config.js';
4
4
 
5
- export function resolveRefs(value, root = value, refChain = new Set()) {
5
+ function resolveRefs(value, root, refChain = new Set()) {
6
6
  if (value === null || typeof value !== 'object') {
7
7
  return value;
8
8
  }
@@ -33,137 +33,184 @@ export function resolveRefs(value, root = value, refChain = new Set()) {
33
33
  return resolved;
34
34
  }
35
35
 
36
- function mergeQuestionFields(fields, defaultFields, {
37
- legendAttributes,
38
- optionFieldTypes,
39
- errorMessages
40
- }) {
41
- let defaultOptions = [];
42
- let defaultLegend = {};
43
- defaultFields.forEach((defaultField) => {
44
- defaultOptions = defaultField.options;
45
- defaultLegend = defaultField.legend;
46
-
47
- if (defaultLegend && legendAttributes) {
48
- defaultLegend.attributes = {
49
- ...defaultLegend.attributes,
50
- ...legendAttributes
51
- };
52
- }
53
- });
54
-
55
- fields.forEach((field) => {
56
- if (field.legend) {
57
- field.legend = merge(defaultLegend, field.legend);
58
- } else {
59
- field.legend = defaultLegend;
60
- }
61
-
62
- if (field.remove) {
63
- if (field.remove.includes('all')) {
64
- defaultOptions = [];
65
- } else {
66
- defaultOptions = defaultOptions.filter((_, index) => !field.remove.includes(index));
67
- }
68
- }
69
-
70
- if (!optionFieldTypes.includes(field.fieldType)) {
71
- return;
72
- }
73
-
74
- if (!field.errorMessage && errorMessages[field.fieldType]) {
75
- field.errorMessage = errorMessages[field.fieldType];
76
- }
77
-
78
- if (Array.isArray(field.options)) {
79
- field.options.forEach((option) => {
80
- if (typeof option.update === 'number') {
81
- if (option.attributes?.checked === false) {
82
- delete option.attributes.checked;
83
- delete defaultOptions[option.update]?.attributes?.checked;
84
- }
85
- merge(defaultOptions[option.update], option);
86
- } else if (typeof option.insertAt === 'number') {
87
- defaultOptions.splice(option.insertAt, 0, option);
88
- } else {
89
- defaultOptions.push(option);
90
- }
91
- });
92
- }
93
- field.options = defaultOptions;
94
- });
95
- }
96
-
97
- export function mergeDefaultTradeQuestionsIntoItems(items, steps, options = {}) {
98
- if (!Array.isArray(items) || !steps || typeof steps !== 'object') {
99
- return;
100
- }
101
-
102
- const mergeOptions = {
103
- legendAttributes: options.legendAttributes,
104
- optionFieldTypes: options.optionFieldTypes || ['radio', 'checkbox-group'],
105
- errorMessages: {
106
- radio: 'Professionals need this info to generate a quote.',
107
- 'checkbox-group': 'Please select at least one option.',
108
- ...options.errorMessages
109
- }
110
- };
111
-
112
- items.forEach((item) => {
113
- const stepName = item.attributes?.data?.['step-name'];
114
- const defaultStep = steps[stepName];
115
- if (!defaultStep) {
116
- return;
117
- }
118
-
119
- if (!item.stepContent) {
120
- item.stepContent = {};
121
- }
122
- if (!item.stepContent.fields) {
123
- item.stepContent.fields = [];
124
- }
125
-
126
- mergeQuestionFields(item.stepContent.fields, defaultStep.fields, mergeOptions);
127
-
128
- const extraQuestionBlock = item.stepContent.extraQuestionBlock;
129
- if (extraQuestionBlock) {
130
- if (!extraQuestionBlock.fields) {
131
- extraQuestionBlock.fields = [];
132
- }
133
- mergeQuestionFields(
134
- extraQuestionBlock.fields,
135
- defaultStep.extraQuestionBlock.fields,
136
- mergeOptions
137
- );
138
- }
139
- });
140
- }
141
-
142
- export function mergeDefaultTradeQuestionsConfigOnSteps(config, steps, options) {
36
+ function mergeDefaultTradeQuestionsConfigOnSteps(config, steps) {
143
37
  if (!config || typeof config !== 'object') return;
144
38
 
145
39
  if (config.steps && typeof config.steps === 'object' && config.steps.items) {
146
40
  // cloning steps to keep multiple steps: {} objects independent
147
41
  const clonedSteps = JSON.parse(JSON.stringify(steps));
148
- mergeDefaultTradeQuestionsConfig(config, clonedSteps, options);
42
+ mergeDefaultTradeQuestionsConfig(config, clonedSteps);
149
43
  }
150
44
 
151
45
  for (const key in config) {
152
46
  if (config.hasOwnProperty(key)) {
153
47
  const value = config[key];
154
48
  if (typeof value === 'object' && value !== null) {
155
- mergeDefaultTradeQuestionsConfigOnSteps(value, steps, options);
49
+ mergeDefaultTradeQuestionsConfigOnSteps(value, steps);
156
50
  }
157
51
  }
158
52
  }
159
53
  }
160
54
 
161
- export function mergeDefaultTradeQuestionsConfig(config, steps, options) {
55
+ function mergeDefaultTradeQuestionsConfig(config, steps) {
162
56
  if (!config || !config.steps || !config.steps.items || !Array.isArray(config.steps.items)) {
163
57
  return;
164
58
  }
165
59
 
166
- mergeDefaultTradeQuestionsIntoItems(config.steps.items, steps, options);
60
+ config.steps.items.forEach((item) => {
61
+ const stepName = item.attributes.data['step-name'];
62
+ if (steps[stepName]) {
63
+ if (!item.stepContent) {
64
+ item.stepContent = {};
65
+ }
66
+
67
+ if (!item.stepContent.fields) {
68
+ item.stepContent.fields = [];
69
+ }
70
+ const defaultStepFields = steps[stepName].fields;
71
+ let defaultStepOptions = [];
72
+ let defaultQuestionLegend = {};
73
+ defaultStepFields.forEach((defaultField) => {
74
+ defaultStepOptions = defaultField.options;
75
+ defaultQuestionLegend = defaultField.legend;
76
+ });
77
+
78
+ item.stepContent.fields.forEach((field) => {
79
+ if (field.legend) {
80
+ field.legend = merge(defaultQuestionLegend, field.legend);
81
+ } else {
82
+ field.legend = defaultQuestionLegend;
83
+ }
84
+
85
+ if (field && field.remove) {
86
+ if (field.remove.includes('all')) {
87
+ defaultStepOptions = [];
88
+ } else {
89
+ defaultStepOptions = defaultStepOptions.filter((_, i) => !field.remove.includes(i));
90
+ }
91
+ }
92
+
93
+ if (field && field.move) {
94
+ // field.move will look like [{from: 0, to: 1}]
95
+ // we need to remove option at from index and insert at to index
96
+ field.move.forEach((move) => {
97
+ const fromIndex = move.from;
98
+ const toIndex = move.to;
99
+ const fromOption = defaultStepOptions.splice(fromIndex, 1);
100
+ defaultStepOptions.splice(toIndex, 0, fromOption[0]);
101
+ });
102
+ }
103
+
104
+ if (field.fieldType === 'radio' || field.fieldType === 'checkbox-group') {
105
+ if (!field.errorMessage) {
106
+ field.errorMessage = field.fieldType === 'checkbox-group' ? 'Please select at least one option.' : 'Professionals need this info to generate a quote.';
107
+ }
108
+
109
+ if (field.options && Array.isArray(field.options) && field.options.length) {
110
+ field.options.forEach((option) => {
111
+ if (typeof option.update === 'number') {
112
+ if (option.attributes && option.attributes.checked === false) {
113
+ delete option.attributes.checked;
114
+ delete defaultStepOptions[option.update].attributes.checked;
115
+ }
116
+ merge(defaultStepOptions[option.update], option);
117
+ } else {
118
+ if (typeof option.insertAt === 'number') {
119
+ defaultStepOptions.splice(option.insertAt, 0, option);
120
+ } else {
121
+ defaultStepOptions.push(option);
122
+ }
123
+ }
124
+ });
125
+ }
126
+ field.options = defaultStepOptions;
127
+ } else {
128
+ if (field && Array.isArray(field) && field.length) {
129
+ if (typeof field.update === 'number') {
130
+ merge(defaultStepFields[field.update], field);
131
+ } else {
132
+ if (typeof field.insertAt === 'number') {
133
+ defaultStepFields.splice(field.insertAt, 0, field);
134
+ } else {
135
+ defaultStepFields.push(field);
136
+ }
137
+ }
138
+ }
139
+
140
+ field = defaultStepFields;
141
+ }
142
+ });
143
+
144
+ // extra question block
145
+ if (item.stepContent.extraQuestionBlock) {
146
+ if (!item.stepContent.extraQuestionBlock.fields) {
147
+ item.stepContent.extraQuestionBlock.fields = [];
148
+ }
149
+
150
+ const defaultExtraQuestionFields = steps[stepName].extraQuestionBlock.fields;
151
+ let defaultExtraQuestionOptions = [];
152
+ let defaultExtraQuestionLegend = {};
153
+ defaultExtraQuestionFields.forEach((defaultExtraQuestionField) => {
154
+ defaultExtraQuestionOptions = defaultExtraQuestionField.options;
155
+ defaultExtraQuestionLegend = defaultExtraQuestionField.legend;
156
+ });
157
+ item.stepContent.extraQuestionBlock.fields.forEach((field) => {
158
+
159
+ if (field.legend) {
160
+ field.legend = merge(defaultExtraQuestionLegend, field.legend);
161
+ } else {
162
+ field.legend = defaultExtraQuestionLegend;
163
+ }
164
+
165
+ if (field && field.remove) {
166
+ if (field.remove.includes('all')) {
167
+ defaultExtraQuestionOptions = [];
168
+ } else {
169
+ defaultExtraQuestionOptions = defaultExtraQuestionOptions.filter((_, i) => !field.remove.includes(i));
170
+ }
171
+ }
172
+
173
+ if (field.fieldType === 'radio') {
174
+ if (!field.errorMessage) {
175
+ field.errorMessage = 'Professionals need this info to generate a quote.';
176
+ }
177
+
178
+ if (field.options && Array.isArray(field.options) && field.options.length) {
179
+ field.options.forEach((option, optionIndex) => {
180
+ if (typeof option.update === 'number') {
181
+ if (option.attributes && option.attributes.checked === false) {
182
+ delete option.attributes.checked;
183
+ delete defaultStepOptions[option.update].attributes.checked;
184
+ }
185
+ merge(defaultExtraQuestionOptions[option.update], option);
186
+ } else {
187
+ if (typeof option.insertAt === 'number') {
188
+ defaultExtraQuestionOptions.splice(option.insertAt, 0, option);
189
+ } else {
190
+ defaultExtraQuestionOptions.push(option);
191
+ }
192
+ }
193
+ });
194
+ }
195
+ field.options = defaultExtraQuestionOptions;
196
+ } else {
197
+ if (field && Array.isArray(field) && field.length) {
198
+ if (typeof field.update === 'number') {
199
+ merge(defaultExtraQuestionFields[field.update], field);
200
+ } else {
201
+ if (typeof field.insertAt === 'number') {
202
+ defaultExtraQuestionFields.splice(field.insertAt, 0, field);
203
+ } else {
204
+ defaultExtraQuestionFields.push(field);
205
+ }
206
+ }
207
+ }
208
+ field = defaultExtraQuestionFields;
209
+ }
210
+ });
211
+ }
212
+ }
213
+ });
167
214
  }
168
215
 
169
216
  export default async function(config) {