@genesislcap/foundation-ui 14.258.3 → 14.259.0
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/dist/custom-elements.json +458 -18
- package/dist/dts/expression-builder/expressions-shared-helpers.d.ts +86 -0
- package/dist/dts/expression-builder/expressions-shared-helpers.d.ts.map +1 -0
- package/dist/dts/expression-builder/index.d.ts +1 -0
- package/dist/dts/expression-builder/index.d.ts.map +1 -1
- package/dist/dts/expression-builder/rule-expression-builder.d.ts +0 -72
- package/dist/dts/expression-builder/rule-expression-builder.d.ts.map +1 -1
- package/dist/dts/expression-builder/types.d.ts +6 -0
- package/dist/dts/expression-builder/types.d.ts.map +1 -1
- package/dist/dts/expression-builder/value-expression-builder.d.ts +16 -0
- package/dist/dts/expression-builder/value-expression-builder.d.ts.map +1 -0
- package/dist/esm/expression-builder/expressions-shared-helpers.js +177 -0
- package/dist/esm/expression-builder/index.js +1 -0
- package/dist/esm/expression-builder/rule-expression-builder.js +3 -181
- package/dist/esm/expression-builder/types.js +3 -0
- package/dist/esm/expression-builder/value-expression-builder.js +297 -0
- package/package.json +18 -18
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { ExpressionBuilder, template, styles, Config } from '@genesislcap/expression-builder';
|
|
3
|
+
import { customElement, observable } from '@microsoft/fast-element';
|
|
4
|
+
import { mapFieldTypeToRuleExpressionType, numberTypes, toBinaryExpression, toMethodExpression, transformRuleValue, rebuildRuleValue, } from './expressions-shared-helpers';
|
|
5
|
+
import { RuleExpression } from './types';
|
|
6
|
+
/**
|
|
7
|
+
* CONFIG
|
|
8
|
+
* TODO: this file doesn't have unit tests, as the unit tests are basically identical to the rule-expression-builder file. Once we properly
|
|
9
|
+
* split responsibilities then everything can receive tests
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Operator names for the server expression
|
|
13
|
+
* Mapped to the RuleExpression names where possible
|
|
14
|
+
* @internal
|
|
15
|
+
**/
|
|
16
|
+
const valueOperatorNames = {
|
|
17
|
+
TRIM: 'TRIM',
|
|
18
|
+
ADD: 'ADD',
|
|
19
|
+
SUBTRACT: 'SUBTRACT',
|
|
20
|
+
MULTIPLY: 'MULTIPLY',
|
|
21
|
+
DIVIDE: 'DIVIDE',
|
|
22
|
+
CONVERT_TO_DATE: 'CONVERT_TO_DATE',
|
|
23
|
+
CONVERT_TO_DATE_TIME: 'CONVERT_TO_DATE_TIME',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Operators for the server expression
|
|
27
|
+
* @internal
|
|
28
|
+
**/
|
|
29
|
+
const valueOperators = [
|
|
30
|
+
{
|
|
31
|
+
type: valueOperatorNames.TRIM,
|
|
32
|
+
applyTo: ['string'],
|
|
33
|
+
nbInputs: 0,
|
|
34
|
+
tooltip: "Returns a string whose value is this string, with all leading and trailing space removed, where space is defined as any character whose codepoint is less than or equal to 'U+0020' (the space character)",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: valueOperatorNames.ADD,
|
|
38
|
+
applyTo: [...numberTypes],
|
|
39
|
+
nbInputs: 1,
|
|
40
|
+
tooltip: 'Returns the result of the field value mathematically added to the specified rule value. FIELD + VALUE',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: valueOperatorNames.SUBTRACT,
|
|
44
|
+
applyTo: [...numberTypes],
|
|
45
|
+
nbInputs: 1,
|
|
46
|
+
tooltip: 'Returns the result of the field value mathematically subtracted by the specified rule value. FIELD - VALUE',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: valueOperatorNames.MULTIPLY,
|
|
50
|
+
applyTo: [...numberTypes],
|
|
51
|
+
nbInputs: 1,
|
|
52
|
+
tooltip: 'Returns the result of the field value mathematically multiplied by the specified rule value. FIELD * VALUE',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: valueOperatorNames.DIVIDE,
|
|
56
|
+
applyTo: [...numberTypes],
|
|
57
|
+
nbInputs: 1,
|
|
58
|
+
tooltip: 'Returns the result of the field value mathematically divided by the specified rule value. FIELD / VALUE',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: valueOperatorNames.CONVERT_TO_DATE,
|
|
62
|
+
applyTo: ['date'],
|
|
63
|
+
nbInputs: 0,
|
|
64
|
+
tooltip: 'Returns the date, which is stored as the epoch time, as a formatted date YYYY/dd/mm',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: valueOperatorNames.CONVERT_TO_DATE_TIME,
|
|
68
|
+
applyTo: ['date-time'],
|
|
69
|
+
nbInputs: 0,
|
|
70
|
+
tooltip: 'Returns the date-time, which is stored as the epoch time, as a formatted date YYYY/dd/mm HH:mm:ss',
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
/**
|
|
74
|
+
* Converts a client operator name to a server operator name
|
|
75
|
+
*
|
|
76
|
+
* The opposite to `transformServerNameToOperatorName`
|
|
77
|
+
*
|
|
78
|
+
* @privateRemarks
|
|
79
|
+
* Most names are the same, but this handles cases where date comparison operator names are different
|
|
80
|
+
* on the display to their server name
|
|
81
|
+
*
|
|
82
|
+
* TODO: We could clean this up if we support labels/aliases on the client component
|
|
83
|
+
*
|
|
84
|
+
* @internal
|
|
85
|
+
**/
|
|
86
|
+
function transformOperatorNameToServerName(op) {
|
|
87
|
+
switch (op) {
|
|
88
|
+
default:
|
|
89
|
+
return op;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Converts a client `Rule` into the correct server `MethodExpression`
|
|
94
|
+
*
|
|
95
|
+
* @internal
|
|
96
|
+
**/
|
|
97
|
+
function ruleToRuleMethodExpression(rule, operatorName) {
|
|
98
|
+
switch (operatorName) {
|
|
99
|
+
case valueOperatorNames.TRIM:
|
|
100
|
+
return toMethodExpression(rule, RuleExpression.methodCall.TRIM, []);
|
|
101
|
+
case valueOperatorNames.CONVERT_TO_DATE:
|
|
102
|
+
return toMethodExpression(rule, RuleExpression.methodCall.LONG_TO_DATE, []);
|
|
103
|
+
case valueOperatorNames.CONVERT_TO_DATE_TIME:
|
|
104
|
+
return toMethodExpression(rule, RuleExpression.methodCall.LONG_TO_DATE_TIME, []);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Converts a client `Rule` into the correct server `Expression`
|
|
109
|
+
*
|
|
110
|
+
* @privateRemarks
|
|
111
|
+
* The server doesn't have a concept for a partial expression so if the user doesn't fill out all values
|
|
112
|
+
* (e.g. chooses a field but not an operator) that would be lost via this process
|
|
113
|
+
*
|
|
114
|
+
* @internal
|
|
115
|
+
**/
|
|
116
|
+
function ruleToRuleExpression(ruleInput) {
|
|
117
|
+
var _a, _b;
|
|
118
|
+
// If the user hasn't fully filled out the rule then we just ignore it for the condition
|
|
119
|
+
if (!(((_a = ruleInput.operator) === null || _a === void 0 ? void 0 : _a.type) && ((_b = ruleInput.field) === null || _b === void 0 ? void 0 : _b.fieldId)))
|
|
120
|
+
return null;
|
|
121
|
+
const rule = transformRuleValue(ruleInput);
|
|
122
|
+
const rhsType = mapFieldTypeToRuleExpressionType(rule);
|
|
123
|
+
const operatorName = transformOperatorNameToServerName(rule.operator.type);
|
|
124
|
+
switch (operatorName) {
|
|
125
|
+
case valueOperatorNames.TRIM:
|
|
126
|
+
case valueOperatorNames.CONVERT_TO_DATE:
|
|
127
|
+
case valueOperatorNames.CONVERT_TO_DATE_TIME:
|
|
128
|
+
return ruleToRuleMethodExpression(rule, operatorName);
|
|
129
|
+
case valueOperatorNames.ADD:
|
|
130
|
+
case valueOperatorNames.SUBTRACT:
|
|
131
|
+
case valueOperatorNames.DIVIDE:
|
|
132
|
+
case valueOperatorNames.MULTIPLY:
|
|
133
|
+
return toBinaryExpression(rule, operatorName, rhsType);
|
|
134
|
+
default:
|
|
135
|
+
throw new Error(`Unmatched case for operator name: ${operatorName}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Convert from Genesis to Expression builder
|
|
140
|
+
*/
|
|
141
|
+
/**
|
|
142
|
+
* Converts a server operator name to a client operator name
|
|
143
|
+
*
|
|
144
|
+
* The opposite to `transformOperatorNameToServerName`
|
|
145
|
+
*
|
|
146
|
+
* @privateRemarks
|
|
147
|
+
* Most names are the same, but this handles cases where date comparison operator names are different
|
|
148
|
+
* on the display to their server name
|
|
149
|
+
*
|
|
150
|
+
* TODO: We could clean this up if we support labels/aliases on the client component
|
|
151
|
+
*
|
|
152
|
+
* @internal
|
|
153
|
+
**/
|
|
154
|
+
function transformServerNameToOperatorName(op, rulePartialField) {
|
|
155
|
+
// TODO: this function usage doens't need to do anything because all binary expression operator names match on client and server
|
|
156
|
+
// for now
|
|
157
|
+
const useDateOperatorNames = rulePartialField.field.type === 'date' || rulePartialField.field.type === 'date-time';
|
|
158
|
+
if (!useDateOperatorNames)
|
|
159
|
+
return op;
|
|
160
|
+
switch (op) {
|
|
161
|
+
default:
|
|
162
|
+
return op;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Handles operator names which have a special client name, but serialised to a normal operator on the server
|
|
167
|
+
*
|
|
168
|
+
* @internal
|
|
169
|
+
**/
|
|
170
|
+
function rebuildOperator(rulePartialField, binExpr) {
|
|
171
|
+
const operator = (() => {
|
|
172
|
+
const clientOperatorName = transformServerNameToOperatorName(binExpr.OPERATION, rulePartialField);
|
|
173
|
+
return valueOperators.find((o) => o.type === clientOperatorName);
|
|
174
|
+
})();
|
|
175
|
+
return Object.assign(Object.assign({}, rulePartialField), { operator });
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Converts a server BinaryExpression to a client BinaryOperator
|
|
179
|
+
*
|
|
180
|
+
* The opposite of `toBinaryExpression`
|
|
181
|
+
* @internal
|
|
182
|
+
**/
|
|
183
|
+
function fromBinaryExpression(fields, binExpr) {
|
|
184
|
+
if (binExpr.LEFT.TYPE !== 'FIELD')
|
|
185
|
+
throw new Error('BinaryExpression LHS must be TYPE === FIELD');
|
|
186
|
+
if (!['STRING', 'NUMBER', 'BOOLEAN', 'NULL'].includes(binExpr.RIGHT.TYPE))
|
|
187
|
+
throw new Error('BinaryExpression RHS must be TYPE === NUMBER | STRING | BOOLEAN | NULL');
|
|
188
|
+
return rebuildRuleValue(rebuildOperator({
|
|
189
|
+
field: fields.find((f) => f.fieldId === binExpr.LEFT.NAME),
|
|
190
|
+
}, binExpr), binExpr.RIGHT);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Converts a server MethodExpression to a client BinaryOperator
|
|
194
|
+
*
|
|
195
|
+
* The opposite of `toMethodExpression`
|
|
196
|
+
*
|
|
197
|
+
* @internal
|
|
198
|
+
**/
|
|
199
|
+
function fromMethodExpression(fields, methodExpr) {
|
|
200
|
+
const [clientOperatorName, value] = (() => {
|
|
201
|
+
switch (true) {
|
|
202
|
+
case methodExpr.METHOD === 'TRIM':
|
|
203
|
+
return [valueOperatorNames[valueOperatorNames.TRIM], undefined];
|
|
204
|
+
case methodExpr.METHOD === 'LONG_TO_DATE':
|
|
205
|
+
return [valueOperatorNames[valueOperatorNames.CONVERT_TO_DATE], undefined];
|
|
206
|
+
case methodExpr.METHOD === 'LONG_TO_DATE_TIME':
|
|
207
|
+
return [valueOperatorNames[valueOperatorNames.CONVERT_TO_DATE_TIME], undefined];
|
|
208
|
+
default:
|
|
209
|
+
throw new Error('Unhandled fromMethodExpression case');
|
|
210
|
+
}
|
|
211
|
+
})();
|
|
212
|
+
return {
|
|
213
|
+
field: fields.find((f) => f.fieldId === methodExpr.PARAMETERS[0].NAME),
|
|
214
|
+
operator: valueOperators.find((o) => o.type === clientOperatorName),
|
|
215
|
+
value,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Converts recursively from a PREDICATE_EXPRESSION to client Groups and Rules
|
|
220
|
+
*
|
|
221
|
+
* @internal
|
|
222
|
+
**/
|
|
223
|
+
function ruleExpressionToGroup(fields, expr) {
|
|
224
|
+
return {
|
|
225
|
+
combinator: Config.NULL_COMBINATOR,
|
|
226
|
+
children: expr.EXPRESSIONS.map((condition) => {
|
|
227
|
+
if (!('TYPE' in condition))
|
|
228
|
+
throw new Error('RuleExpression format not yet supported - no TYPE');
|
|
229
|
+
if (condition.TYPE === 'PREDICATE_EXPRESSION')
|
|
230
|
+
return ruleExpressionToGroup(fields, condition);
|
|
231
|
+
if (condition.TYPE === 'BINARY_EXPRESSION')
|
|
232
|
+
return fromBinaryExpression(fields, condition);
|
|
233
|
+
if (condition.TYPE === 'METHOD_EXPRESSION')
|
|
234
|
+
return fromMethodExpression(fields, condition);
|
|
235
|
+
throw new Error('RuleExpression format not yet supported - unsupported TYPE');
|
|
236
|
+
}),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* We don't create the foundation version of the component in the same way as the other components,
|
|
241
|
+
* they're composed from a base FAST component.
|
|
242
|
+
* The reason for this is that we want to have ExpressionBuilder as an independent and open source
|
|
243
|
+
* component, and due to this we don't want to release it as base components that someone needs to use
|
|
244
|
+
* FAST to compose.
|
|
245
|
+
*/
|
|
246
|
+
let FoundationValueExpressionBuilder = class FoundationValueExpressionBuilder extends ExpressionBuilder {
|
|
247
|
+
valueConfigChanged(_, newConfig) {
|
|
248
|
+
const topLevelPredicateExpr = {
|
|
249
|
+
TYPE: 'PREDICATE_EXPRESSION',
|
|
250
|
+
OPERATION: 'NULL',
|
|
251
|
+
EXPRESSIONS: newConfig.model ? [newConfig.model] : [],
|
|
252
|
+
};
|
|
253
|
+
const model = ruleExpressionToGroup(newConfig.fields, topLevelPredicateExpr);
|
|
254
|
+
this.config = {
|
|
255
|
+
combinators: [Config.NULL_COMBINATOR],
|
|
256
|
+
operators: valueOperators,
|
|
257
|
+
fields: newConfig.fields,
|
|
258
|
+
model,
|
|
259
|
+
maxNesting: newConfig.maxNesting,
|
|
260
|
+
partialRuleValidationWarning: newConfig.partialRuleValidationWarning,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
configChanged(oldConfig, newConfig) {
|
|
264
|
+
if (!newConfig.operators || !newConfig.combinators) {
|
|
265
|
+
throw new Error('Unable to detect operators or combinators. Did you set the config on the rule builder via the config property? Use the valueConfig property instead');
|
|
266
|
+
}
|
|
267
|
+
super.configChanged(oldConfig, newConfig);
|
|
268
|
+
}
|
|
269
|
+
dispatchChangeEvent(group) {
|
|
270
|
+
if (!('children' in group))
|
|
271
|
+
throw new Error('Invalid top level group hierarchy');
|
|
272
|
+
if (group.children.length === 0)
|
|
273
|
+
return;
|
|
274
|
+
if (group.children.length > 1)
|
|
275
|
+
throw new Error('Value expressions should not have multiple rules');
|
|
276
|
+
if ('children' in group.children[0])
|
|
277
|
+
throw new Error('Trying to convert group to rule');
|
|
278
|
+
const valueExpr = ruleToRuleExpression(group.children[0]);
|
|
279
|
+
this.dispatchEvent(new CustomEvent('change', {
|
|
280
|
+
detail: valueExpr,
|
|
281
|
+
bubbles: true,
|
|
282
|
+
cancelable: true,
|
|
283
|
+
composed: true,
|
|
284
|
+
}));
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
__decorate([
|
|
288
|
+
observable
|
|
289
|
+
], FoundationValueExpressionBuilder.prototype, "valueConfig", void 0);
|
|
290
|
+
FoundationValueExpressionBuilder = __decorate([
|
|
291
|
+
customElement({
|
|
292
|
+
name: 'foundation-value-expression-builder',
|
|
293
|
+
styles: styles,
|
|
294
|
+
template,
|
|
295
|
+
})
|
|
296
|
+
], FoundationValueExpressionBuilder);
|
|
297
|
+
export { FoundationValueExpressionBuilder };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genesislcap/foundation-ui",
|
|
3
3
|
"description": "Genesis Foundation UI",
|
|
4
|
-
"version": "14.
|
|
4
|
+
"version": "14.259.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "SEE LICENSE IN license.txt",
|
|
7
7
|
"main": "dist/esm/index.js",
|
|
@@ -83,13 +83,13 @@
|
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@genesislcap/foundation-testing": "14.
|
|
87
|
-
"@genesislcap/genx": "14.
|
|
88
|
-
"@genesislcap/rollup-builder": "14.
|
|
89
|
-
"@genesislcap/ts-builder": "14.
|
|
90
|
-
"@genesislcap/uvu-playwright-builder": "14.
|
|
91
|
-
"@genesislcap/vite-builder": "14.
|
|
92
|
-
"@genesislcap/webpack-builder": "14.
|
|
86
|
+
"@genesislcap/foundation-testing": "14.259.0",
|
|
87
|
+
"@genesislcap/genx": "14.259.0",
|
|
88
|
+
"@genesislcap/rollup-builder": "14.259.0",
|
|
89
|
+
"@genesislcap/ts-builder": "14.259.0",
|
|
90
|
+
"@genesislcap/uvu-playwright-builder": "14.259.0",
|
|
91
|
+
"@genesislcap/vite-builder": "14.259.0",
|
|
92
|
+
"@genesislcap/webpack-builder": "14.259.0",
|
|
93
93
|
"copyfiles": "^2.4.1",
|
|
94
94
|
"rimraf": "^5.0.0",
|
|
95
95
|
"rxjs": "^7.5.4"
|
|
@@ -100,15 +100,15 @@
|
|
|
100
100
|
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
|
101
101
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
|
102
102
|
"@genesiscommunitysuccess/analyzer-import-alias-plugin": "^5.0.3",
|
|
103
|
-
"@genesislcap/expression-builder": "14.
|
|
104
|
-
"@genesislcap/foundation-comms": "14.
|
|
105
|
-
"@genesislcap/foundation-criteria": "14.
|
|
106
|
-
"@genesislcap/foundation-errors": "14.
|
|
107
|
-
"@genesislcap/foundation-events": "14.
|
|
108
|
-
"@genesislcap/foundation-logger": "14.
|
|
109
|
-
"@genesislcap/foundation-notifications": "14.
|
|
110
|
-
"@genesislcap/foundation-user": "14.
|
|
111
|
-
"@genesislcap/foundation-utils": "14.
|
|
103
|
+
"@genesislcap/expression-builder": "14.259.0",
|
|
104
|
+
"@genesislcap/foundation-comms": "14.259.0",
|
|
105
|
+
"@genesislcap/foundation-criteria": "14.259.0",
|
|
106
|
+
"@genesislcap/foundation-errors": "14.259.0",
|
|
107
|
+
"@genesislcap/foundation-events": "14.259.0",
|
|
108
|
+
"@genesislcap/foundation-logger": "14.259.0",
|
|
109
|
+
"@genesislcap/foundation-notifications": "14.259.0",
|
|
110
|
+
"@genesislcap/foundation-user": "14.259.0",
|
|
111
|
+
"@genesislcap/foundation-utils": "14.259.0",
|
|
112
112
|
"@microsoft/fast-colors": "5.3.1",
|
|
113
113
|
"@microsoft/fast-components": "2.30.6",
|
|
114
114
|
"@microsoft/fast-element": "1.14.0",
|
|
@@ -130,5 +130,5 @@
|
|
|
130
130
|
"access": "public"
|
|
131
131
|
},
|
|
132
132
|
"customElements": "dist/custom-elements.json",
|
|
133
|
-
"gitHead": "
|
|
133
|
+
"gitHead": "6656bbcddf94db7587bab3339ca021718ce54709"
|
|
134
134
|
}
|