-
Notifications
You must be signed in to change notification settings - Fork 0
/
objectBuilderConfigurator.js
136 lines (117 loc) · 4.9 KB
/
objectBuilderConfigurator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* Valence UI plugin that allows for a custom experience when configuring the ObjectBuilder Filter.
*/
import ValenceUIConfigurator from 'c/valenceUIConfigurator';
export default class ObjectBuilderConfigurator extends ValenceUIConfigurator {
originalResultFieldName = null; // we use this to allow the user to change the result field name then change it back without fussing at them
resultFieldHasError = false;
fieldList = [];
/**
* Recursive function that calculates the full field path to all the fields in a schema tree and builds them into a flat list.
*
* @param children Immediate children of a given node in the tree
* @param ancestorPath The chain we traveled to get here
*/
extractFieldPaths(children, ancestorPath) {
const returnValue = [];
if(children) {
Object.values(children).forEach((node) => {
const pathToHere = ancestorPath.concat(node.field.fieldName);
returnValue.push({'value' : pathToHere.join('::'), 'label' : pathToHere.join('.')});
returnValue.push(...this.extractFieldPaths(node.children, pathToHere));
});
}
return returnValue;
}
/**
* Don't allow the User to name their object the same as an existing source field.
*/
checkNameConflict() {
const resultFieldInput = this.template.querySelector('lightning-input[data-name="resultField"]');
if(resultFieldInput) { // field isn't there before first render
if(resultFieldInput.value !== this.originalResultFieldName && this.fieldList.find(field => field.value === resultFieldInput.value)) {
resultFieldInput.setCustomValidity('There is already a source field with this name. Use a name that doesn\'t already exist.');
this.resultFieldHasError = true;
} else {
resultFieldInput.setCustomValidity('');
this.resultFieldHasError = false;
}
resultFieldInput.reportValidity();
}
}
connectedCallback() {
if(!this.originalResultFieldName) {
this.originalResultFieldName = this.configuration.resultName;
}
}
// ------------------------------------------
// ----- Configurator Lifecycle Methods -----
// ------------------------------------------
/**
* Set up our fieldList whenever we are given schema
*/
onSetSchema() {
console.log('setSchema: ', this.schema);
this.fieldList = this.extractFieldPaths(this.schema.Source.children, []);
this.fieldList.sort((a, b) => a.value.localeCompare(b.value));
console.log('fieldList:', this.fieldList);
}
/**
* Because combobox has to work with a string value and sourcePaths are arrays, we enrich each configuration record with a flattened path
*/
onSetConfiguration() {
console.log('setConfiguration: ', this.configuration);
this.configuration.fields = this.configuration.fields.map(field => Object.assign({'flattened' : field.sourcePath.join('::')}, field));
this.checkNameConflict(); // re-run our name check since the resultField value might have just changed
console.log('configurationAfter:', this.configuration);
}
/**
* This is called just before sending the configuration up the chain. We return a simplified version of configuration since we added stuff to it.
*/
tweakConfiguration() {
return {
'resultName' : this.configuration.resultName,
'fields' : this.configuration.fields.map(field => {
return {'fieldName' : field.fieldName, 'sourcePath' : field.sourcePath};
})
};
}
// -------------------------------------------
// ----- User Manipulating Configuration -----
// -------------------------------------------
updateResultField(event) {
this.configuration.resultName = event.target.value;
this.configUpdated(); // propagate our configuration changes
}
addField() {
this.configuration.fields.push({'fieldName' : '', 'sourcePath' : []});
this.configUpdated(); // propagate our configuration changes
}
removeField(event) {
this.configuration.fields.splice(event.target.value, 1);
this.configUpdated(); // propagate our configuration changes
}
updateFieldName(event) {
this.configuration.fields[event.target.dataset.index].fieldName = event.target.value;
this.configUpdated(); // propagate our configuration changes
}
updateSourcePath(event) {
this.configuration.fields[event.target.dataset.index].sourcePath = event.target.value.split('::');
this.configUpdated(); // propagate our configuration changes
}
// -----------------------------------------
// ----- Required Configurator Methods -----
// -----------------------------------------
getDefaultShape() {
console.log('defaultShape called');
return {resultName : null, fields : []};
}
computeValid() {
let fieldsCheckOut = true;
this.configuration.fields.forEach(field => {
fieldsCheckOut = fieldsCheckOut && field.fieldName && field.sourcePath;
});
// valid if we've selected a unique result name, have at least one field we're pulling in, and all fields have name and path populated
return !this.resultFieldHasError && this.configuration.resultName && this.configuration.fields.length > 0 && fieldsCheckOut;
}
}