ru.coon 3.0.58 → 3.0.60
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/.husky/pre-commit +0 -0
- package/CHANGELOG.md +20 -0
- package/package.json +1 -1
- package/src/common/AbstractPlugin.js +17 -0
- package/src/common/field/FieldsHelper.js +0 -0
- package/src/common/panel/WindowWrap.js +0 -0
- package/src/report/component/ReportPanel.js +5 -0
- package/src/report/component/reportpanel/ReportGrid.js +1 -0
- package/src/report/util.js +28 -28
- package/src/uielement/component/UiCustomPanel.js +6 -0
- package/src/util.js +37 -122
- package/src/util.scss +4 -0
- package/src/validator.js +184 -0
- package/src/version.js +1 -1
package/.husky/pre-commit
CHANGED
|
File without changes
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Version 3.0.60, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/b3ba3aeb89954b8e1650cb40e052a4509b4809fb)
|
|
2
|
+
* ## Fixes
|
|
3
|
+
* <span style='color:red'>fix validator, util.getByPath</span> ([608e70], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/608e7096603a0ed31656b0f45686bab7a4ee302b))
|
|
4
|
+
|
|
5
|
+
* update: CHANGELOG.md ([e42a2a], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/e42a2a6fb8b511ba174ab5060fc84c683a046945))
|
|
6
|
+
|
|
7
|
+
# Version 3.0.59, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/065a134b1f6c6211d56ef758b127778d5e104faa)
|
|
8
|
+
* Копирование в буфер обмена без использования дополнительного окна prompt. Related to NEVA-990 ([41cd4e], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/41cd4ed4fdb7088d10df1eac44964c5aadae4646))
|
|
9
|
+
* add Coon.validator singleton class ([a402d0], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/a402d0829e81d7f4297fba2af9b628a4528533c1))
|
|
10
|
+
* upd ([61e613], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/61e6137120af2b8a95c0d7918a85afe2aa3d0456))
|
|
11
|
+
* upd ([0258f1], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/0258f199b5928da341e6549f5589390f1fa87bcd))
|
|
12
|
+
* add validator ([0ca7d7], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/0ca7d719f4715af1845f0b4385333271db2438bb))
|
|
13
|
+
* update: CHANGELOG.md ([5969de], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/5969de159690ff30bc5194f8fe83a4d1d7507dd0))
|
|
14
|
+
|
|
1
15
|
# Version 3.0.58, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/9f4087fb2aba17d56ea49774ac21340c1b414307)
|
|
2
16
|
* update: CHANGELOG.md ([fcea34], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/fcea34f891b7acc6a0b73200d9b6d7b60c383f46))
|
|
3
17
|
|
|
@@ -8,7 +22,13 @@
|
|
|
8
22
|
* ## Features
|
|
9
23
|
* <span style='color:green'>feat: add forceShowHeader</span> ([7ce368], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/7ce368898a1809f08aaa8331af2bdef4f40366da))
|
|
10
24
|
|
|
25
|
+
* update: CHANGELOG.md ([8108ae], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/8108ae12826ada676cd8598e0c1ba8ce067fa32e))
|
|
26
|
+
|
|
27
|
+
# Version 3.0.57, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/28be9d312317e10260c5d784cf2eb09e83a30140)
|
|
11
28
|
* HT-14299: изменение вида несохраненных изменений в вертикальных табах ([590315], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/59031554ed302eabdc194e916e44c3a8a3c77371))
|
|
29
|
+
* update: CHANGELOG.md ([62c8b4], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/62c8b40173f540191ba7eeb9aad48dae93dd5f57))
|
|
30
|
+
|
|
31
|
+
# Version 3.0.56, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/74308acb16cf13c9793236b74d8fd025bd632cab)
|
|
12
32
|
* HT-14580: повторный вход при завершении сессии ([66c811], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/66c81121345e02ec436a9ec3308db087030a25ac))
|
|
13
33
|
* update: CHANGELOG.md ([0cd2cb], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/0cd2cb99bbdcdf6d8cf83c29c744dd0f02daa497))
|
|
14
34
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Ext.define('Coon.common.AbstractPlugin', {
|
|
2
|
+
extend: 'Ext.AbstractPlugin',
|
|
3
|
+
|
|
4
|
+
constructor(config) {
|
|
5
|
+
Ext.apply(this, config || {});
|
|
6
|
+
|
|
7
|
+
if (Array.isArray(this.validConfig)) {
|
|
8
|
+
const state = Coon.validator.isObjectValid(this.pluginConfig.properties, this.validConfig);
|
|
9
|
+
if (!state.valid) {
|
|
10
|
+
console.error(`Invalid configuration for plugin ${this.pluginConfig.name}:\n${state.errors}`);
|
|
11
|
+
}
|
|
12
|
+
this.pluginConfig.validity = state;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
this.callParent([config]);
|
|
16
|
+
},
|
|
17
|
+
});
|
|
File without changes
|
|
File without changes
|
|
@@ -868,6 +868,11 @@ Ext.define('Coon.report.component.ReportPanel', {
|
|
|
868
868
|
}
|
|
869
869
|
config[prefix + 'type'] = plugin[ns.$uiElement].xtype || plugin[ns.$xtype];
|
|
870
870
|
config[ns.$sortSequence] = plugin[ns.$sortSequence] || null;
|
|
871
|
+
config.pluginConfig = {
|
|
872
|
+
properties: Object.assign({}, config),
|
|
873
|
+
type,
|
|
874
|
+
name: prefix + 'type',
|
|
875
|
+
};
|
|
871
876
|
return config;
|
|
872
877
|
});
|
|
873
878
|
},
|
package/src/report/util.js
CHANGED
|
@@ -2,7 +2,7 @@ Ext.define('Coon.report.util', {
|
|
|
2
2
|
singleton: true,
|
|
3
3
|
|
|
4
4
|
validateReportConfig(config) {
|
|
5
|
-
return Coon.
|
|
5
|
+
return Coon.validator.isObjectValid(config, [
|
|
6
6
|
{path: 'reportDescription', valid: 'string, required'},
|
|
7
7
|
{path: 'reportId', valid: 'string, required'},
|
|
8
8
|
{path: 'SQLText', valid: 'string, required'},
|
|
@@ -10,17 +10,17 @@ Ext.define('Coon.report.util', {
|
|
|
10
10
|
path: 'fields',
|
|
11
11
|
valid: 'array',
|
|
12
12
|
rules: [
|
|
13
|
-
{path: '
|
|
14
|
-
{path: '
|
|
15
|
-
{path: '
|
|
16
|
-
{path: '
|
|
13
|
+
{path: 'description', valid: 'string, required'},
|
|
14
|
+
{path: 'reportFieldCd', valid: 'string, required'},
|
|
15
|
+
{path: 'visibleSwitch', valid: 'boolean'},
|
|
16
|
+
{path: 'reportFieldTypeLookup', valid: 'uppercase, required'},
|
|
17
17
|
{
|
|
18
|
-
path: '
|
|
18
|
+
path: 'properties',
|
|
19
19
|
valid: 'array',
|
|
20
20
|
rules: [
|
|
21
|
-
{path: '
|
|
22
|
-
{path: '
|
|
23
|
-
{path: '
|
|
21
|
+
{path: 'sequenceNumber', valid: 'number'},
|
|
22
|
+
{path: 'key', valid: 'type.string'},
|
|
23
|
+
{path: 'value', valid: '!type.undefined'}
|
|
24
24
|
],
|
|
25
25
|
}
|
|
26
26
|
],
|
|
@@ -29,40 +29,40 @@ Ext.define('Coon.report.util', {
|
|
|
29
29
|
path: 'plugins',
|
|
30
30
|
valid: 'array',
|
|
31
31
|
rules: [
|
|
32
|
-
{path: '
|
|
33
|
-
{path: '
|
|
34
|
-
{path: '
|
|
35
|
-
{path: '
|
|
36
|
-
{path: '
|
|
37
|
-
{path: '
|
|
32
|
+
{path: 'xtype', valid: 'string, required'},
|
|
33
|
+
{path: 'type', valid: 'string, required'},
|
|
34
|
+
{path: 'uiElement', valid: 'string, required'},
|
|
35
|
+
{path: 'jsonProperties', valid: 'string, required'},
|
|
36
|
+
{path: 'sequenceNumber', valid: 'number, required'},
|
|
37
|
+
{path: 'sortSequence', valid: 'number, required'}
|
|
38
38
|
],
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
path: 'properties',
|
|
42
42
|
valid: 'array',
|
|
43
43
|
rules: [
|
|
44
|
-
{path: '
|
|
45
|
-
{path: '
|
|
46
|
-
{path: '
|
|
44
|
+
{path: 'key', valid: 'string, required'},
|
|
45
|
+
{path: 'value', valid: 'string, required'},
|
|
46
|
+
{path: 'sequenceNumber', valid: 'string, required'}
|
|
47
47
|
],
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
path: 'parameters',
|
|
51
51
|
valid: 'array',
|
|
52
52
|
rules: [
|
|
53
|
-
{path: '
|
|
54
|
-
{path: '
|
|
55
|
-
{path: '
|
|
56
|
-
{path: '
|
|
57
|
-
{path: '
|
|
58
|
-
{path: '
|
|
53
|
+
{path: 'requiredSwitch', valid: 'boolean'},
|
|
54
|
+
{path: 'visibleSwitch', valid: 'boolean'},
|
|
55
|
+
{path: 'notUsedInSQLSwitch', valid: 'boolean'},
|
|
56
|
+
{path: 'description', valid: 'string, required'},
|
|
57
|
+
{path: 'reportParameterCd', valid: 'string, required'},
|
|
58
|
+
{path: 'reportParameterTypeLookup', valid: 'string, required, uppercase'},
|
|
59
59
|
{
|
|
60
|
-
path: '
|
|
60
|
+
path: 'properties',
|
|
61
61
|
valid: 'array',
|
|
62
62
|
rules: [
|
|
63
|
-
{path: '
|
|
64
|
-
{path: '
|
|
65
|
-
{path: '
|
|
63
|
+
{path: 'key', valid: 'string, required'},
|
|
64
|
+
{path: 'value', valid: 'string, required'},
|
|
65
|
+
{path: 'sequenceNumber', valid: 'number'}
|
|
66
66
|
],
|
|
67
67
|
}
|
|
68
68
|
],
|
|
@@ -9,6 +9,9 @@ Ext.define('Coon.uielement.component.UiCustomPanel', {
|
|
|
9
9
|
'Coon.uielement.component.UiCustomPanelTraceWindow'
|
|
10
10
|
],
|
|
11
11
|
controller: 'UiCustomController',
|
|
12
|
+
mixins: [
|
|
13
|
+
'Coon.validator.mixin'
|
|
14
|
+
],
|
|
12
15
|
|
|
13
16
|
keyMap: {
|
|
14
17
|
'Ctrl+Shift+Alt+F8': {
|
|
@@ -75,6 +78,9 @@ Ext.define('Coon.uielement.component.UiCustomPanel', {
|
|
|
75
78
|
},
|
|
76
79
|
|
|
77
80
|
forceShowHeader(_, title) {
|
|
81
|
+
if (this.assert.is_string_required(title).invalid) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
78
84
|
if (typeof title !== 'string' || !title) {
|
|
79
85
|
return;
|
|
80
86
|
}
|
package/src/util.js
CHANGED
|
@@ -73,19 +73,17 @@ Ext.define('Coon.util', {
|
|
|
73
73
|
}
|
|
74
74
|
return path.reduce((acc, pathProp) => {
|
|
75
75
|
if (acc) {
|
|
76
|
+
if (pathProp.startsWith('[') && pathProp.endsWith(']')) {
|
|
77
|
+
pathProp = pathProp.slice(1, -1) || 0;
|
|
78
|
+
if (Number.isInteger(parseInt(pathProp))) {
|
|
79
|
+
acc = acc[parseInt(pathProp)];
|
|
80
|
+
return acc;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
76
83
|
if (Ext.isObject(acc)) {
|
|
77
84
|
acc = acc[pathProp];
|
|
78
85
|
return acc;
|
|
79
86
|
}
|
|
80
|
-
if (Array.isArray(acc)) {
|
|
81
|
-
if (pathProp.startsWith('[') && pathProp.endsWith(']')) {
|
|
82
|
-
pathProp = pathProp.slice(1, -1) || 0;
|
|
83
|
-
if (Number.isInteger(parseInt(pathProp))) {
|
|
84
|
-
acc = acc[parseInt(pathProp)];
|
|
85
|
-
return acc;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
87
|
} else {
|
|
90
88
|
path = [];
|
|
91
89
|
acc = defaultValue;
|
|
@@ -210,7 +208,7 @@ Ext.define('Coon.util', {
|
|
|
210
208
|
const bAcc = acc;
|
|
211
209
|
acc = this.safeCall(fn, acc);
|
|
212
210
|
if (debug) {
|
|
213
|
-
|
|
211
|
+
// eslint-disable-next-line no-console
|
|
214
212
|
console.debug(`\n \x1b[36m\x1b[4m BEFORE: \x1b[0m ${fn.toString()}`);
|
|
215
213
|
// eslint-disable-next-line no-console
|
|
216
214
|
console.dir(bAcc, {depth: debug.depth || 5});
|
|
@@ -228,7 +226,22 @@ Ext.define('Coon.util', {
|
|
|
228
226
|
return acc;
|
|
229
227
|
},
|
|
230
228
|
|
|
231
|
-
|
|
229
|
+
getHtaEl() {
|
|
230
|
+
const textArea = document.createElement('textarea');
|
|
231
|
+
textArea.style.position = 'fixed';
|
|
232
|
+
textArea.style.top = 0;
|
|
233
|
+
textArea.style.left = 0;
|
|
234
|
+
textArea.style.width = '2em';
|
|
235
|
+
textArea.style.height = '2em';
|
|
236
|
+
textArea.style.padding = 0;
|
|
237
|
+
textArea.style.border = 'none';
|
|
238
|
+
textArea.style.outline = 'none';
|
|
239
|
+
textArea.style.boxShadow = 'none';
|
|
240
|
+
textArea.style.background = 'transparent';
|
|
241
|
+
return textArea;
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
copyToClipboard(copiedData, successText = 'Скопировано успешно') {
|
|
232
245
|
try {
|
|
233
246
|
if (!Ext.browser.is.Firefox && navigator && navigator.clipboard) {
|
|
234
247
|
navigator.permissions.query({name: 'clipboard-write'}).then((result) => {
|
|
@@ -243,13 +256,14 @@ Ext.define('Coon.util', {
|
|
|
243
256
|
if (window.clipboardData && window.clipboardData.setData) {
|
|
244
257
|
window.clipboardData.setData('text', copiedData);
|
|
245
258
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
259
|
+
const hiddenTextArea = this.getHtaEl();
|
|
260
|
+
hiddenTextArea.value = copiedData;
|
|
261
|
+
document.body.appendChild(hiddenTextArea);
|
|
262
|
+
hiddenTextArea.focus();
|
|
263
|
+
hiddenTextArea.select();
|
|
264
|
+
document.execCommand('copy');
|
|
265
|
+
document.body.removeChild(hiddenTextArea);
|
|
266
|
+
Ext.toast({html: successText, cls: ['toast-success']});
|
|
253
267
|
} catch (ex) {
|
|
254
268
|
return prompt('Copy to clipboard: Ctrl+C, Enter', copiedData);
|
|
255
269
|
}
|
|
@@ -369,106 +383,6 @@ Ext.define('Coon.util', {
|
|
|
369
383
|
return acc;
|
|
370
384
|
},
|
|
371
385
|
|
|
372
|
-
/**
|
|
373
|
-
*
|
|
374
|
-
* @param {Object} obj
|
|
375
|
-
* @param {Array} rules
|
|
376
|
-
* @example
|
|
377
|
-
* rules: [
|
|
378
|
-
* {path: 'a.b.c', valid: 'string,nonempty,length.-.30,', msg: 'invalid string'}
|
|
379
|
-
* ]
|
|
380
|
-
*/
|
|
381
|
-
isObjectValid(obj, rules) {
|
|
382
|
-
const getValid = (valid) => {
|
|
383
|
-
if (typeof valid === 'string') {
|
|
384
|
-
return valid.split(',').map((el) => el.trim());
|
|
385
|
-
}
|
|
386
|
-
if (Array.isArray(valid)) {
|
|
387
|
-
return valid;
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
const checkValidity = (validProps, value) => validProps.find((prop) => {
|
|
391
|
-
const [name, ...args] = prop.split('.');
|
|
392
|
-
if (typeof validators[name] === 'function') {
|
|
393
|
-
return !(
|
|
394
|
-
validators[name](value, ...args)
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
// validators
|
|
399
|
-
const validators = {
|
|
400
|
-
empty: (v) => Ext.isEmpty(v),
|
|
401
|
-
required: (v) => !Ext.isEmpty(v),
|
|
402
|
-
uppercase: (v) => typeof v === 'string' && v.toUpperCase() === v,
|
|
403
|
-
lowercase: (v) => typeof v === 'string' && v.toLowerCase() === v,
|
|
404
|
-
true: (v) => v === true,
|
|
405
|
-
false: (v) => v === false,
|
|
406
|
-
allowblank: (v) => true,
|
|
407
|
-
type: (v, expectedType) => {
|
|
408
|
-
if (expectedType === 'null') {
|
|
409
|
-
return v === null;
|
|
410
|
-
}
|
|
411
|
-
if (expectedType === 'array') {
|
|
412
|
-
return Array.isArray(v);
|
|
413
|
-
}
|
|
414
|
-
if (expectedType === 'object') {
|
|
415
|
-
return Ext.isObject(v);
|
|
416
|
-
}
|
|
417
|
-
return typeof v === expectedType;
|
|
418
|
-
},
|
|
419
|
-
not: (name, ...args) => {
|
|
420
|
-
if (typeof validators[name] !== 'function') {
|
|
421
|
-
throw new Error(`validator [${name}] is not exist!`);
|
|
422
|
-
}
|
|
423
|
-
return (v, ...args) => validators[name](v, ...args);
|
|
424
|
-
},
|
|
425
|
-
};
|
|
426
|
-
validators['!type'] = (v, typename) => !validators.type(v, typename);
|
|
427
|
-
validators.string = (v) => validators.type(v, 'string');
|
|
428
|
-
validators.array = (v) => validators.type(v, 'array');
|
|
429
|
-
validators.boolean = (v) => validators.type(v, 'boolean');
|
|
430
|
-
validators.number = (v) => validators.type(v, 'number');
|
|
431
|
-
validators.object = (v) => validators.type(v, 'object');
|
|
432
|
-
// EOF validators
|
|
433
|
-
const getErrors = (obj, rules) => {
|
|
434
|
-
const errors = Coon.util.filterMap(rules, (rule) => {
|
|
435
|
-
if (!rule.path) {
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
const value = Coon.util.getByPath(obj, rule.path);
|
|
439
|
-
const validTags = getValid(rule.valid) || [];
|
|
440
|
-
let subErrors;
|
|
441
|
-
let isInvalid = typeof valid === 'function' ?
|
|
442
|
-
validTags(value) :
|
|
443
|
-
checkValidity(validTags, value);
|
|
444
|
-
if (
|
|
445
|
-
!Ext.isEmpty(value) &&
|
|
446
|
-
!isInvalid &&
|
|
447
|
-
Array.isArray(rule.rules) &&
|
|
448
|
-
rule.rules.length
|
|
449
|
-
) {
|
|
450
|
-
const subResult = getErrors(value, rule.rules);
|
|
451
|
-
if (!subResult.valid) {
|
|
452
|
-
isInvalid = false;
|
|
453
|
-
subErrors = subResult.errors.join('\n');
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
if (isInvalid) {
|
|
457
|
-
rule.msg = rule.msg || `[by path: ${rule.path}], value [${value}] is invalid`;
|
|
458
|
-
if (subErrors) {
|
|
459
|
-
rule.msg = rule.msg + '\n' + subErrors;
|
|
460
|
-
}
|
|
461
|
-
return rule.msg;
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
return {
|
|
465
|
-
valid: !errors.length,
|
|
466
|
-
errors,
|
|
467
|
-
};
|
|
468
|
-
};
|
|
469
|
-
return getErrors(obj, rules);
|
|
470
|
-
},
|
|
471
|
-
|
|
472
386
|
getAllCommandsList() {
|
|
473
387
|
if (Coon.util.locals.getAllCommandsList) {
|
|
474
388
|
return Coon.util.locals.getAllCommandsList;
|
|
@@ -665,10 +579,10 @@ Ext.define('Coon.util', {
|
|
|
665
579
|
|
|
666
580
|
getInstanceIdProperties(instance) {
|
|
667
581
|
if (instance.id ||
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
582
|
+
instance.xtype ||
|
|
583
|
+
instance.ptype ||
|
|
584
|
+
instance.$className ||
|
|
585
|
+
Ext.isObject(instance.initialConfig)
|
|
672
586
|
) {
|
|
673
587
|
return Object.assign(
|
|
674
588
|
{},
|
|
@@ -756,6 +670,7 @@ Ext.define('Coon.util', {
|
|
|
756
670
|
}
|
|
757
671
|
}
|
|
758
672
|
}
|
|
673
|
+
|
|
759
674
|
return detectCycle(data);
|
|
760
675
|
},
|
|
761
676
|
|
package/src/util.scss
ADDED
package/src/validator.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Ext.define('Coon.validator', {
|
|
2
|
+
singleton: true,
|
|
3
|
+
|
|
4
|
+
alternateClassName: 'Coon.v',
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
const validators = {
|
|
8
|
+
empty: (v) => Ext.isEmpty(v),
|
|
9
|
+
notempty: (v) => !Ext.isEmpty(v),
|
|
10
|
+
required: (v) => !Ext.isEmpty(v),
|
|
11
|
+
uppercase: (v) => typeof v === 'string' && v.toUpperCase() === v,
|
|
12
|
+
lowercase: (v) => typeof v === 'string' && v.toLowerCase() === v,
|
|
13
|
+
true: (v) => v === true,
|
|
14
|
+
false: (v) => v === false,
|
|
15
|
+
allowblank: (v) => true,
|
|
16
|
+
type: (v, expectedType) => {
|
|
17
|
+
if (expectedType === 'null') {
|
|
18
|
+
return v === null;
|
|
19
|
+
}
|
|
20
|
+
if (expectedType === 'array') {
|
|
21
|
+
return Array.isArray(v);
|
|
22
|
+
}
|
|
23
|
+
if (expectedType === 'object') {
|
|
24
|
+
return Ext.isObject(v);
|
|
25
|
+
}
|
|
26
|
+
return typeof v === expectedType;
|
|
27
|
+
},
|
|
28
|
+
not: (name, ...args) => {
|
|
29
|
+
if (typeof validators[name] !== 'function') {
|
|
30
|
+
throw new Error(`validator [${name}] is not exist!`);
|
|
31
|
+
}
|
|
32
|
+
return (v, ...args) => validators[name](v, ...args);
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
validators['!type'] = (v, typename) => !validators.type(v, typename);
|
|
36
|
+
validators.string = (v) => validators.type(v, 'string');
|
|
37
|
+
validators.array = (v) => validators.type(v, 'array');
|
|
38
|
+
validators.boolean = (v) => validators.type(v, 'boolean');
|
|
39
|
+
validators.number = (v) => validators.type(v, 'number');
|
|
40
|
+
validators.object = (v) => validators.type(v, 'object');
|
|
41
|
+
this.addValidator = (name, validator, override) => {
|
|
42
|
+
if (!validators[name] || override) {
|
|
43
|
+
validators[name] = validator;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
this.getValidator = (name) => validators[name];
|
|
47
|
+
this.getValidators = () => validators;
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @param {Object} obj
|
|
54
|
+
* @param {Array} rules
|
|
55
|
+
* @example
|
|
56
|
+
* rules: [
|
|
57
|
+
* {path: 'a.b.c', valid: 'string,nonempty,length.-.30,', msg: 'invalid string'}
|
|
58
|
+
* ]
|
|
59
|
+
*/
|
|
60
|
+
isObjectValid(obj, rules) {
|
|
61
|
+
if (!Ext.isObject(obj)) {
|
|
62
|
+
return {
|
|
63
|
+
valid: false,
|
|
64
|
+
errors: ['object is not valid'],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const getValid = (valid) => {
|
|
68
|
+
if (typeof valid === 'string') {
|
|
69
|
+
return valid.split(',').map((el) => el.trim());
|
|
70
|
+
}
|
|
71
|
+
if (Array.isArray(valid)) {
|
|
72
|
+
return valid;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const checkValidity = (validProps, value) => validProps.find((prop) => {
|
|
76
|
+
const [name, ...args] = prop.split('.');
|
|
77
|
+
if (typeof validators[name] === 'function') {
|
|
78
|
+
return validators[name](value, ...args);
|
|
79
|
+
} else {
|
|
80
|
+
console.error(`validator [${name}] is not exist!`);
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const validators = this.getValidators();
|
|
85
|
+
const getErrors = (src, rules) => {
|
|
86
|
+
if (Array.isArray(src)) {
|
|
87
|
+
for (const el of src) {
|
|
88
|
+
const state = getErrors(el, rules);
|
|
89
|
+
if (!state.valid) {
|
|
90
|
+
return state;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return {valid: true, errors: []};
|
|
94
|
+
}
|
|
95
|
+
const errors = Coon.util.filterMap(rules, (rule) => {
|
|
96
|
+
let errorMessage = '';
|
|
97
|
+
if (!rule.path) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const value = Coon.util.getByPath(src, rule.path);
|
|
101
|
+
const validTags = getValid(rule.valid) || [];
|
|
102
|
+
let subResult;
|
|
103
|
+
const isValid = checkValidity(validTags, value);
|
|
104
|
+
if (
|
|
105
|
+
isValid &&
|
|
106
|
+
Array.isArray(rule.rules) &&
|
|
107
|
+
rule.rules.length
|
|
108
|
+
) {
|
|
109
|
+
subResult = getErrors(value, rule.rules);
|
|
110
|
+
}
|
|
111
|
+
if (!isValid) {
|
|
112
|
+
errorMessage += rule.msg ||
|
|
113
|
+
`The property on the path "${rule.path}" with the value ${value} is invalid, validity check: ${rule.valid}`;
|
|
114
|
+
}
|
|
115
|
+
if (subResult && !subResult.valid) {
|
|
116
|
+
errorMessage += '\n---\n ' + subResult.errors.join('\n ');
|
|
117
|
+
}
|
|
118
|
+
return errorMessage || false;
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
valid: !errors.length,
|
|
122
|
+
errors,
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
return getErrors(obj, rules);
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
}, function() {
|
|
129
|
+
this.assert = new Proxy(this, {
|
|
130
|
+
get: function(target, name) {
|
|
131
|
+
if (!name.startsWith('is_')) {
|
|
132
|
+
return target[name];
|
|
133
|
+
}
|
|
134
|
+
const tokens = name.slice(3)
|
|
135
|
+
.split('_')
|
|
136
|
+
.map((name) => {
|
|
137
|
+
if (!Coon.validator.getValidator(name)) {
|
|
138
|
+
return {name};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
fn: (tested) => {
|
|
142
|
+
if (tested.invalid) {
|
|
143
|
+
return tested;
|
|
144
|
+
}
|
|
145
|
+
const isValid = Coon.validator.getValidator(name).call(this, tested.value);
|
|
146
|
+
tested.invalid = !isValid;
|
|
147
|
+
tested.steps.push({[name]: isValid});
|
|
148
|
+
return tested;
|
|
149
|
+
},
|
|
150
|
+
name,
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
if (tokens.find(({fn}) => !fn)) {
|
|
154
|
+
return () => {
|
|
155
|
+
const tested = {steps: []};
|
|
156
|
+
tokens.filter(({fn}) => !fn)
|
|
157
|
+
.map(({name}) => name)
|
|
158
|
+
.forEach((name) => {
|
|
159
|
+
tested.steps.push({[name]: `validator not found`});
|
|
160
|
+
});
|
|
161
|
+
tested.invalid = true;
|
|
162
|
+
return tested;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (tokens.length === 0) {
|
|
166
|
+
return (tested) => {
|
|
167
|
+
tested.valid = true;
|
|
168
|
+
return tested;
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return (value) => Coon.util.chained(
|
|
172
|
+
tokens.map((el) => el.fn),
|
|
173
|
+
{value, steps: []}
|
|
174
|
+
);
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
Ext.define('Coon.validator.mixin', {
|
|
180
|
+
constructor(validator) {
|
|
181
|
+
this.assert = Coon.validator.assert;
|
|
182
|
+
this.callParent(arguments);
|
|
183
|
+
},
|
|
184
|
+
});
|
package/src/version.js
CHANGED