ru.coon 2.7.2 → 2.7.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/package.json +1 -1
  3. package/src/command/ASyncBaseCommand.js +4 -0
  4. package/src/common/component/ChooseColorField.js +142 -0
  5. package/src/common/component/ColorPalette.js +151 -0
  6. package/src/common/component/ColorPalette.scss +102 -0
  7. package/src/common/component/ColorPaletteController.js +189 -0
  8. package/src/common/field/combo/CommandComboBox.js +20 -0
  9. package/src/common/field/withDefault.js +3 -2
  10. package/src/report/component/settings/ReportPropertiesGrid.js +22 -0
  11. package/src/report/component/settings/ReportPropertiesGridController.js +60 -1
  12. package/src/report/component/settings/context/ReportFormContextParametersGrid.js +73 -88
  13. package/src/report/plugin/configPanel/ExecuteCommandButtonPluginConfigPanel.js +92 -59
  14. package/src/report/plugin/configPanel/GridEditorPluginConfig.js +3 -1
  15. package/src/report/plugin/configPanel/GridRowStylePluginConfig.js +130 -94
  16. package/src/report/plugin/configPanel/GridRowStylePluginConfigPropertyGrid.js +10 -15
  17. package/src/report/plugin/grid/ExecuteCommandButtonPlugin.js +23 -8
  18. package/src/report/plugin/grid/GridEditorsPlugin.js +27 -21
  19. package/src/report/plugin/grid/GridRowStylePlugin.js +90 -0
  20. package/src/report/plugin/grid/ReportColumnStatePlugin.js +10 -7
  21. package/src/uielement/component/UiCustomController.js +6 -15
  22. package/src/uielement/component/formchips/Chip.js +2 -2
  23. package/src/uielement/component/formchips/FilterConditionToolbar.js +2 -1
  24. package/src/uielement/component/formchips/FilterConditionToolbarController.js +37 -60
  25. package/src/uielement/component/settings/UiAceEditor.js +1 -1
  26. package/src/uielement/component/settings/UiAceEditorPanel.js +6 -1
  27. package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanel.scss +19 -0
  28. package/src/uielement/plugin/ExecuteCommandPlugin.js +5 -3
  29. package/src/uielement/plugin/configPanel/executeCommand/DataMappingPanel.js +215 -0
  30. package/src/uielement/plugin/configPanel/executeCommand/ExecuteCommandPluginConfigPanelFormEditor.js +625 -0
  31. package/src/uielement/plugin/configPanel/executeCommand/ExecuteCommandPluginConfigPanelFormEditor.scss +22 -0
  32. package/src/util.js +4 -3
  33. package/src/version.js +1 -1
  34. package/src/uielement/plugin/configPanel/ExecuteCommandPluginConfigPanelFormEditor.js +0 -332
@@ -0,0 +1,625 @@
1
+ Ext.define('Coon.uielement.plugin.configPanel.executeCommand.ExecuteCommandPluginConfigPanelFormEditor', {
2
+ extend: 'Ext.panel.Panel',
3
+ alias: 'widget.ExecuteCommandPluginConfigPanelFormEditor',
4
+ description: 'Выполняет команду, позволяет отслеживать её выполнение и менять сообщения об различных событиях в ходе выполнения',
5
+ requires: [
6
+ 'Coon.uielement.plugin.configPanel.executeCommand.DataMappingPanel'
7
+ ],
8
+ cls: 'ExecuteCommandPluginConfigPanelFormEditor',
9
+ viewModel: {
10
+ data: {
11
+ parameters: '{}',
12
+ handlerName: '',
13
+ ctype: '',
14
+ propertyPath: '',
15
+ disabledReference: undefined,
16
+ completeHandler: undefined,
17
+ errorHandler: undefined,
18
+
19
+ successMessage: false,
20
+ successTitle: 'Операция завершена',
21
+ successText: 'Операция завершена успешно',
22
+
23
+
24
+ confirmExecution: false,
25
+ confirmTitle: 'Сообщение системы',
26
+ confirmText: 'Вы уверены, что хотите выполнить действие?',
27
+
28
+ requiredValidView: false,
29
+ requiredValidReference: '',
30
+ requiredValidTitle: 'Сообщение системы',
31
+ requiredValidMessage: 'Не все обязательные поля заполнены.',
32
+
33
+ saveAnimation: false,
34
+
35
+ mappingMode: 'object',
36
+ dataMapping: '{}',
37
+
38
+ detailsHidden: true,
39
+ },
40
+ formulas: {
41
+ objectMode: {
42
+ bind: {bindTo: '{mappingMode}'},
43
+ get: function(mappingMode) {
44
+ return mappingMode === 'object';
45
+ },
46
+ },
47
+ dataMode: {
48
+ bind: {bindTo: '{mappingMode}'},
49
+ get: function(mappingMode) {
50
+ return mappingMode === 'data';
51
+ },
52
+ },
53
+ mapMode: {
54
+ bind: {bindTo: '{mappingMode}'},
55
+ get: function(mappingMode) {
56
+ return mappingMode === 'map';
57
+ },
58
+ },
59
+
60
+ mappingModeDescr: {
61
+ bind: {bindTo: '{mappingMode}'},
62
+ get: function(mappingMode) {
63
+ switch (mappingMode) {
64
+ case 'object':
65
+ return 'Ответ команды помещаем в свойство как объект (режим «объект»). ' +
66
+ 'Требуется настроить параметр плагина propertyPath.';
67
+ case 'map':
68
+ return 'Мы можем использовать ответ команды, используя настройки переназначение. ' +
69
+ 'Требуется настройка отображения свойств (маппинг) из объекта результата выполнения команды в путь во viewModel.';
70
+ case 'data':
71
+ return 'Ответ команды помещается непосредственно во viewModel (в этом режиме перезаписываются свойства ' +
72
+ 'текущей viewModel. Использовать с осторожностью!)';
73
+ }
74
+ },
75
+ },
76
+ },
77
+ },
78
+ referenceHolder: true,
79
+ commandParameters: [],
80
+
81
+ layout: {
82
+ type: 'vbox', align: 'stretch',
83
+ },
84
+ getData: function() {
85
+ return this.getConfiguration();
86
+ },
87
+ setData: function(data) {
88
+ data && this.doInit(data);
89
+ },
90
+ doInit: function(config) {
91
+ const commandProperties = config.parameters && config.parameters._commandProperties;
92
+ commandProperties && this.lookup('reportPropertiesGrid').setData(
93
+ this.convertProperties(commandProperties)
94
+ );
95
+ this.getViewModel().set('description', this.description);
96
+ for (const parameterName in config) {
97
+ if (!config.hasOwnProperty(parameterName) || parameterName === 'ptype') {
98
+ continue;
99
+ }
100
+ if (parameterName === 'parameters' || parameterName === 'dataMapping') {
101
+ if (config[parameterName].hasOwnProperty('_commandProperties')) {
102
+ delete config[parameterName]['_commandProperties'];
103
+ }
104
+ const stringParam = JSON5.stringify(config[parameterName], {
105
+ space: 4,
106
+ quote: '\'',
107
+ });
108
+
109
+ this.getViewModel().set(parameterName, stringParam);
110
+ continue;
111
+ }
112
+ this.getViewModel().set(parameterName, config[parameterName]);
113
+ }
114
+
115
+ this.lookup('dataMappingPanel').doInit(this.getViewModel().get('dataMapping'));
116
+ },
117
+
118
+ prepareDataMapping: function() {
119
+ const vm = this.getViewModel();
120
+ vm.set('dataMapping', this.lookup('dataMappingPanel').getMapping());
121
+ },
122
+
123
+ getConfiguration: function() {
124
+ const result = {};
125
+ const vm = this.getViewModel();
126
+ this.prepareDataMapping();
127
+ const comProp = this.lookup('reportPropertiesGrid').getData();
128
+ if (this.lookup('parametersRef').links.editor.isJSON5Valid()) {
129
+ vm.set('parameters', this.lookup('parametersRef').getValue());
130
+ } else {
131
+ Ext.Msg.alert('Ошибка', 'В параметрах присутствуют ошибки. Параметры прошлого плагина не сохранены');
132
+ }
133
+ result['parameters'] = JSON5.parse(vm.get('parameters'));
134
+ result['parameters']['_commandProperties'] = comProp;
135
+ if (vm.get('mappingMode') === 'map') {
136
+ result['dataMapping'] = JSON5.parse(this.getViewModel().get('dataMapping'));
137
+ } else if (vm.get('mappingMode') === 'object') {
138
+ result['propertyPath'] = vm.get('propertyPath');
139
+ }
140
+ result['mappingMode'] = vm.get('mappingMode');
141
+ result['handlerName'] = vm.get('handlerName');
142
+ result['ctype'] = vm.get('ctype');
143
+ if (vm.get('confirmExecution')) {
144
+ result['confirmExecution'] = vm.get('confirmExecution');
145
+ result['confirmTitle'] = vm.get('confirmTitle');
146
+ result['confirmText'] = vm.get('confirmText');
147
+ }
148
+ if (vm.get('completeHandler')) {
149
+ result['completeHandler'] = vm.get('completeHandler');
150
+ }
151
+ if (vm.get('errorHandler')) {
152
+ result['errorHandler'] = vm.get('errorHandler');
153
+ }
154
+ if (vm.get('disabledReference')) {
155
+ result['disabledReference'] = vm.get('disabledReference');
156
+ }
157
+ if (vm.get('successMessage')) {
158
+ result['successMessage'] = vm.get('successMessage');
159
+ result['successTitle'] = vm.get('successTitle');
160
+ result['successText'] = vm.get('successText');
161
+ }
162
+ if (vm.get('requiredValidView')) {
163
+ result['requiredValidView'] = vm.get('requiredValidView');
164
+ result['requiredValidTitle'] = vm.get('requiredValidTitle');
165
+ result['requiredValidMessage'] = vm.get('requiredValidMessage');
166
+ result['requiredValidReference'] = vm.get('requiredValidReference') ? vm.get('requiredValidReference'):undefined;
167
+ }
168
+ if (vm.get('saveAnimation')) {
169
+ result['saveAnimation'] = vm.get('saveAnimation');
170
+ }
171
+ return result;
172
+ },
173
+
174
+ initComponent: function() {
175
+ this.items = [
176
+ {
177
+ xtype: 'pluginDescriptionLabel',
178
+ bind: {
179
+ value: '{description}',
180
+ },
181
+ },
182
+ {
183
+ xtype: 'comboBtnWrapper',
184
+ combobox: {
185
+ reference: 'handlerCombo',
186
+ xtype: 'BaseComboBox',
187
+ fieldLabel: 'handlerName',
188
+ labelWidth: 60,
189
+ flex: 1,
190
+ loadOnRender: false,
191
+ hideMode: 'offsets',
192
+ allowBlank: false,
193
+ store: 'codeHandlers',
194
+ bind: {
195
+ value: '{handlerName}',
196
+ },
197
+ valueField: 'id',
198
+ displayField: 'id',
199
+ },
200
+ },
201
+ {
202
+ xtype: 'CommandComboBox',
203
+ reference: 'commandComboBox',
204
+ fieldLabel: 'Команда',
205
+ bind: '{ctype}',
206
+ listeners: {
207
+ change: this.onChangeCommand.bind(this),
208
+ },
209
+ },
210
+ {
211
+ xtype: 'pluginDescriptionLabel',
212
+ fieldLabel: 'Описание команды',
213
+ bind: {
214
+ value: '{commandComboBox.selection.ruDescription}',
215
+ hidden: '{!commandComboBox.selection.ruDescription}',
216
+ },
217
+ },
218
+ {
219
+ xtype: 'tabpanel',
220
+ flex: 1,
221
+ items: [
222
+ {
223
+ xtype: 'panel',
224
+ title: 'Настройки',
225
+ layout: {
226
+ type: 'vbox',
227
+ align: 'stretch',
228
+ },
229
+ scrollable: true,
230
+ items: [
231
+ {
232
+ xtype: 'checkbox',
233
+ boxLabel: 'successMessage',
234
+ boxLabelAlign: 'after',
235
+ padding: '0 0 0 10',
236
+ bind: '{successMessage}',
237
+ },
238
+ {
239
+ xtype: 'textfield',
240
+ fieldLabel: 'successText',
241
+ bind: {
242
+ value: '{successText}',
243
+ visible: '{successMessage}',
244
+ },
245
+ },
246
+ {
247
+ xtype: 'textfield',
248
+ fieldLabel: 'successTitle',
249
+ bind: {
250
+ value: '{successTitle}',
251
+ visible: '{successMessage}',
252
+ },
253
+ },
254
+ {
255
+ xtype: 'checkbox',
256
+ boxLabel: 'confirmExecution',
257
+ boxLabelAlign: 'after',
258
+ padding: '0 0 0 10',
259
+ bind: '{confirmExecution}',
260
+ },
261
+ {
262
+ xtype: 'textfield',
263
+ fieldLabel: 'confirmText',
264
+ bind: {
265
+ value: '{confirmText}',
266
+ visible: '{confirmExecution}',
267
+ },
268
+ },
269
+ {
270
+ xtype: 'checkbox',
271
+ padding: '0 0 0 10',
272
+ boxLabel: 'saveAnimation',
273
+ bind: {
274
+ value: '{saveAnimation}',
275
+ },
276
+ },
277
+ {
278
+ xtype: 'textfield',
279
+ fieldLabel: 'confirmTitle',
280
+ bind: {
281
+ value: '{confirmTitle}',
282
+ visible: '{confirmExecution}',
283
+ },
284
+ },
285
+ {
286
+ xtype: 'checkbox',
287
+ boxLabel: 'нужна ли валидация view[requiredValidView]',
288
+ boxLabelAlign: 'after',
289
+ padding: '0 0 0 10',
290
+ bind: '{requiredValidView}',
291
+ },
292
+ {
293
+ xtype: 'textfield',
294
+ fieldLabel: 'референс компонента для валидации[requiredValidReference]',
295
+ bind: {
296
+ value: '{requiredValidReference}',
297
+ visible: '{requiredValidView}',
298
+ },
299
+ },
300
+ {
301
+ xtype: 'textfield',
302
+ fieldLabel: 'requiredValidMessage',
303
+ bind: {
304
+ value: '{requiredValidMessage}',
305
+ visible: '{requiredValidView}',
306
+ },
307
+ },
308
+ {
309
+ xtype: 'textfield',
310
+ fieldLabel: 'requiredValidTitle',
311
+ bind: {
312
+ value: '{requiredValidTitle}',
313
+ visible: '{requiredValidView}',
314
+ },
315
+ },
316
+ {
317
+ xtype: 'textfield',
318
+ fieldLabel: 'disabledReference',
319
+ bind: '{disabledReference}',
320
+ description: `Здесь при необходимости указывается reference, который при выполнении команды блокируется.
321
+ Частый вариант использования - блокировка повторного нажатия кнопки, которая вызывает выполнение команды. `,
322
+ triggers: {
323
+ help: {
324
+ cls: 'x-fa fa-question helpicon',
325
+ handler: this.showDescription,
326
+ },
327
+ },
328
+ },
329
+ {
330
+ xtype: 'ReportPropertiesGrid',
331
+ title: 'Свойства',
332
+ reference: 'reportPropertiesGrid',
333
+ loadPropertiesSource: {
334
+ field: undefined,
335
+ },
336
+ }
337
+ ],
338
+ },
339
+ {
340
+ title: 'Параметры',
341
+ tooltip: 'Настройка свойств и параметров команды',
342
+ xtype: 'panel',
343
+ layout: 'fit',
344
+ // layout: {
345
+ // type: 'vbox', align: 'stretch',
346
+ // },
347
+ title: 'Параметры',
348
+ tbar: [
349
+ {
350
+ text: 'Загрузить параметры',
351
+ tooltip: 'Параметры, определенные в классе команды, будут созданы в редакторе с пустыми значениями.' +
352
+ 'Если параметры уже определены в редакторе, то они не будут изменены.',
353
+ ui: 'blue-text-button-border',
354
+ hidden: true,
355
+ bind: {
356
+ hidden: '{!commandComboBox.selection}',
357
+ },
358
+ handler: this.loadParametersHandler.bind(this),
359
+ }
360
+ ],
361
+ items: [
362
+ {
363
+ xtype: 'UiAceEditorPanel',
364
+ reference: 'parametersRef',
365
+ hideSearchPanel: true,
366
+ layout: 'fit',
367
+ bind: {
368
+ value: '{parameters}',
369
+ },
370
+ }
371
+ ],
372
+ },
373
+ {
374
+ title: 'Отражение результатов',
375
+ scrollable: true,
376
+ tooltip: 'Отражение результатов команды во viewModel',
377
+ layout: {
378
+ type: 'vbox', align: 'stretch',
379
+ },
380
+ items: [
381
+ {
382
+ xtype: 'textfield',
383
+ fieldLabel: 'completeHandler',
384
+ bind: '{completeHandler}',
385
+ },
386
+ {
387
+ xtype: 'textfield',
388
+ fieldLabel: 'errorHandler',
389
+ bind: '{errorHandler}',
390
+ },
391
+ {
392
+ xtype: 'container',
393
+ items: {
394
+ xtype: 'segmentedbutton',
395
+ bind: {
396
+ value: '{mappingMode}',
397
+ },
398
+ defaults: {
399
+ width: 100,
400
+ },
401
+ width: 300,
402
+ items: [
403
+ {
404
+ text: 'object',
405
+ value: 'object',
406
+ },
407
+ {
408
+ text: 'map',
409
+ value: 'map',
410
+ },
411
+ {
412
+ text: 'data ',
413
+ value: 'data',
414
+ }
415
+ ],
416
+ },
417
+ },
418
+ {
419
+ xtype: 'pluginDescriptionLabel',
420
+ bind: {
421
+ value: '{mappingModeDescr}',
422
+ },
423
+ },
424
+ {
425
+ xtype: 'textfield',
426
+ fieldLabel: 'propertyPath',
427
+ afterLabelTextTpl: '<span class="required-flag">*</span>',
428
+ bind: {
429
+ value: '{propertyPath}',
430
+ visible: '{objectMode}',
431
+ },
432
+ },
433
+ {
434
+ xtype: 'DataMappingPanel',
435
+ reference: 'dataMappingPanel',
436
+ bind: {
437
+ hidden: '{!mapMode}',
438
+ },
439
+ minHeight: 200,
440
+ },
441
+ {
442
+ xtype: 'panel',
443
+ title: 'Помощь',
444
+ collapsible: true,
445
+ defaults: {
446
+ xtype: 'panel',
447
+ },
448
+ bodyPadding: 5,
449
+ items: [
450
+ {
451
+ bind: {
452
+ hidden: '{!objectMode}',
453
+ },
454
+ html: 'В этом весь ответ команды (из объекта) будет помещаем в свойство propertyPath ' +
455
+ 'текущей viewModel.' +
456
+ 'Поэтому обязательно требуется настроить параметр плагина propertyPath.' +
457
+ '<br>Примеры:' +
458
+ '<br><span class="code">ab</span> - Во viewModel будет создано свойство ab, ' +
459
+ 'содержащее результаты команды.' +
460
+ '<br><span class="code">ab.cd</span> - <span class="code">{ ab: { cd: результат }}</span>',
461
+ },
462
+
463
+ {
464
+ bind: {
465
+ hidden: '{!mapMode}',
466
+ },
467
+ layout: {type: 'vbox', align: 'stretch'},
468
+ defaults: {paddig: 5},
469
+ items: [
470
+ {
471
+ xtype: 'component',
472
+ html: '<br>Маппинг предназначен отражения результатов выполнения команды во вьюмодель. ' +
473
+ 'Каждое строка состоит из двух частей. ' +
474
+ '<br>Первая часть - путь в объекте результатов выполнения команды. По этому пути извлекается ' +
475
+ 'значение и помещается во viewModel. ' +
476
+ '<br>Вторая часть - путь в объекте viewModel. По этому пути будет записано значение, ' +
477
+ 'извлеченное из результатов выполнения команды. ',
478
+ },
479
+ {
480
+ margin: 5,
481
+ items: {
482
+ xtype: 'button',
483
+ text: 'Подробнее',
484
+ handler: function(btn) {
485
+ const vm = btn.up('ExecuteCommandPluginConfigPanelFormEditor').getViewModel();
486
+ const detailsHidden = vm.get('detailsHidden');
487
+ vm.set('detailsHidden', !detailsHidden);
488
+ btn.setText(detailsHidden? 'Скрыть':'Подробнее');
489
+ },
490
+ },
491
+ },
492
+ {
493
+ bind: {
494
+ hidden: '{detailsHidden}',
495
+ },
496
+ html: '<br> Пусть результат выполнения команды - объект вида:' +
497
+ '<br> <span class="code">{ A: { B: 123 } }</span>' +
498
+ '<p> <span style="font-weight: bold">Пример 1:</span> <span class="code">"A": "RESULT"</span>' +
499
+ '<br> где "A" - путь в объекте результата выполнения команды.' +
500
+ '<br> "RESULT" - путь во viewModel.' +
501
+ '<br> В итоге при получении результатов выполнения команды из ответа будет извлечено' +
502
+ 'значение по ключу "A", и во viewModel будет создано свойство RESULT со значением { B: 123 }.' +
503
+ '<br> <span class="code">{ RESULT: { B: 123 } }</span> </p>' +
504
+ '<p> <span style="font-weight: bold">Пример 2:</span> ' +
505
+ '<span class="code">"A.B": "RESULT.C"</span>' +
506
+ '<br> В данном примере "A.B" - это путь. Точка - разделитель ключей. При получении ' +
507
+ 'результатов выполнения команды из объекта результата будет извлечено значение по ' +
508
+ 'ключу "A", это объект. Из этого объекта извлечется значение по ключу "B", это число 123. ' +
509
+ 'Затем во viewModel будет создан объект по ключу "RESULT" и в объекте по ключу "C" ' +
510
+ 'будет записано извеченное число 123.' +
511
+ '<br> <span class="code">{ RESULT: { C: 123 } }</span>' +
512
+ '</p>',
513
+ }
514
+ ],
515
+ },
516
+ {
517
+ bind: {
518
+ hidden: '{!dataMode}',
519
+ },
520
+ html: 'Результат выполнения команды должен быть объектом - {}. ' +
521
+ '<br>Результат выполнения команды будет помещен во viewModel полностью прямо в корень. ' +
522
+ 'В этом режиме нужно четко понимать, что возвращает команда, и что есть во viewModel. ' +
523
+ '<br>Если есть одинаковые свойства в результате выполнения команды и во viewModel, ' +
524
+ 'то данные во viewModel будут затерты данными из команды. ' +
525
+ '<br>Родительская viewModel не будет затронута.',
526
+ }
527
+ ],
528
+ }
529
+ ],
530
+ }
531
+ ],
532
+ }
533
+ ];
534
+ this.callParent();
535
+ this.lookup('reportPropertiesGrid').loadPropertiesSource.field = this.lookup('commandComboBox');
536
+ },
537
+
538
+ convertProperties: function(properties) {
539
+ if (!Ext.isEmpty(properties) && !Ext.isArray(properties)) {
540
+ const data = [];
541
+ for (const key in properties) {
542
+ if (properties.hasOwnProperty(key)) {
543
+ data.push({key: key, value: properties[key]});
544
+ }
545
+ }
546
+ return data;
547
+ }
548
+ return properties;
549
+ },
550
+
551
+ showDescription: function(cmp) {
552
+ Ext.Msg.alert('Описание свойства', cmp.description);
553
+ },
554
+
555
+ loadParametersHandler: function() {
556
+ const vm = this.getViewModel();
557
+ const xtype = this.lookup('commandComboBox').getSelectedRecord().get('xtype');
558
+ if (xtype) {
559
+ const currentParameters = JSON5.parse(this.lookup('parametersRef').getValue());
560
+ this.commandParameters.forEach((parametr) => {
561
+ if (!Ext.isObject(parametr)) {
562
+ return;
563
+ }
564
+ const name = parametr.name;
565
+ if (!currentParameters.hasOwnProperty(name)) {
566
+ currentParameters[name] = '';
567
+ }
568
+ });
569
+
570
+ const stringParam = JSON5.stringify(currentParameters, {
571
+ space: 4,
572
+ quote: '\'',
573
+ });
574
+
575
+ vm.set('parameters', stringParam);
576
+ this.checkParameters(currentParameters);
577
+ }
578
+ },
579
+
580
+ /**
581
+ * Проверка текущих параметров. Не должно быть параметров, которые не определены у команды
582
+ * @param {Object} currentParameters
583
+ */
584
+ checkParameters: function(currentParameters) {
585
+ const commandName = this.lookup('commandComboBox').getSelectedRecord().get('xtype');
586
+ const wrongParameters = Object.keys(currentParameters)
587
+ .filter((name) => !this.commandParameters.find((parameter) => parameter['name']===name));
588
+ let goodParametersStr = this.commandParameters
589
+ .reduce((acc, cur) => {
590
+ const required = cur.required ? 'обязательный' : 'не обязательный';
591
+ acc.push(`<li> ${cur.name} - ${required} </li>`);
592
+ return acc;
593
+ }, [])
594
+ .join('<br>');
595
+
596
+ if (wrongParameters.length) {
597
+ const paramsString = `<span class="wrong-parameters"> ${wrongParameters.join(', ')} </span>`;
598
+ goodParametersStr = `<ul class="wrong-parameters"> ${goodParametersStr} </ul>`;
599
+ Ext.Msg.show({
600
+ title: 'Внимание!',
601
+ message: `Следующие параметры: <br> ${paramsString} <br> не являются параметрами команды ${commandName}.
602
+ <p>Список параметров команды: ${goodParametersStr}</p>
603
+ `,
604
+ buttons: Ext.Msg.YES,
605
+ cls: 'ExecuteCommandPluginConfigPanelFormEditor',
606
+ });
607
+ }
608
+ },
609
+
610
+ /**
611
+ * При смене команды фиксируем ее параметры
612
+ * @param combo
613
+ */
614
+ onChangeCommand: function(combo) {
615
+ if (!combo.getSelectedRecord()) {
616
+ return;
617
+ }
618
+ const xtype = combo.getSelectedRecord().get('xtype');
619
+ if (xtype) {
620
+ const fullSource = Ext.ClassManager.aliasToName['command.' + xtype];
621
+ this.commandParameters = Ext.ClassManager.classes[fullSource].prototype.inputParameters &&
622
+ Ext.ClassManager.classes[fullSource].prototype.inputParameters();
623
+ }
624
+ },
625
+ });
@@ -0,0 +1,22 @@
1
+ .ExecuteCommandPluginConfigPanelFormEditor {
2
+ $required-flag-color: dynamic(#bf1313);
3
+ font-size: 12px;
4
+ margin: 5px;
5
+ .required-flag {
6
+ font-size: 18px;
7
+ color: $required-flag-color;
8
+ }
9
+ span.code {
10
+ color: green;
11
+ font-family: "Lucida Console", "Courier New", monospace;
12
+ }
13
+ .x-form-trigger-default.helpicon {
14
+ background-color: white;
15
+ }
16
+
17
+ .wrong-parameters {
18
+ color: green;
19
+ font-style: italic;
20
+ font-family: "Lucida Console", "Courier New", monospace;
21
+ }
22
+ }
package/src/util.js CHANGED
@@ -497,16 +497,17 @@ Ext.define('Coon.util', {
497
497
  const alias = cls.prototype && cls.prototype.alias;
498
498
  if (isCommand(alias)) {
499
499
  const url = cls.prototype.url;
500
+ const ruDescription = cls.prototype.description;
500
501
  if (Array.isArray(alias)) {
501
502
  alias.filter(check).forEach((el) => {
502
- acc.push({description: className, xtype: el.split('.').pop(), url});
503
+ acc.push({description: className, xtype: el.split('.').pop(), url, ruDescription});
503
504
  });
504
505
  } else {
505
- acc.push({description: className, xtype: alias.split('.').pop(), url});
506
+ acc.push({description: className, xtype: alias.split('.').pop(), url, ruDescription});
506
507
  }
507
508
  }
508
509
  return acc;
509
- }, []);
510
+ }, []).sort((a, b) => a.xtype.localeCompare(b.xtype));
510
511
  return Coon.util.locals.getAllCommandsList;
511
512
  },
512
513
  /**