ru.coon 2.8.0 → 2.8.2

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
@@ -1,3 +1,13 @@
1
+ # Version 2.8.2, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/b2e3da084c82fa409dca30ef2388bab2f3ef267b)
2
+ * ## Fixes
3
+ * <span style='color:red'> TR-69409 исправление проверки значения свойства successMessage в ExecuteCommandPlugin</span> ([b77390], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/b77390cabfdbdf3ad837c896b805a4bc7e5e92f3))
4
+
5
+ * update: CHANGELOG.md ([ad61a8], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/ad61a8c449000e7b9ff6e921d39eecd97ddabea2))
6
+
7
+ # Version 2.8.1, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/88c146ad577ce2a14d194c245e3d5151081af6af)
8
+ * add unconditional versioning ([187668], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/187668ff86c8e91b440ce9b8a1052a191a7989d6))
9
+ * update: CHANGELOG.md ([8386a7], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/8386a79fae89b882f1a3baf81849bb08ffd7a298))
10
+
1
11
  # Version 2.8.0, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/74558cb55135099e1cc4ba5ec585ac75e12cbd83)
2
12
  * update: CHANGELOG.md ([46e9bc], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/46e9bc47a9ddb94057c101cc12e5061ba7cf22ce))
3
13
 
@@ -12,6 +22,7 @@
12
22
 
13
23
  # Version 2.7.75, [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/07c180f0c622d325ab34f62f832e1ee801609fdc)
14
24
  * ## Features
25
+ * <span style='color:green'>feat: TR-67905 loginForm and TextFieldFormatter plugin</span> ([aafbfc], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/aafbfc81b05aa91a172905b47bf7c620f720be11))
15
26
  * <span style='color:green'>feat: HT-10115: chain plugin return result, log unified buttons call handlers result</span> ([408dab], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/408dab15c6afc49e47bd80729bf55e1a541522cc))
16
27
  * <span style='color:green'>feat: [ReportTree][CharacteristicGridCopyPlugin] Added testId generation. Related to HT-8881.</span> ([2bc5e8], [link](http://gitlab-dbr.sigma-it.local/dbr/ru.coon/-/commit/2bc5e899f6a5d390844fcc25fc4511b5d195fbb8))
17
28
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "ru.coon"
5
5
  },
6
6
  "description": "",
7
- "version": "2.8.0",
7
+ "version": "2.8.2",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "git+http://gitlab-dbr.sigma-it.local/dbr/ru.coon"
@@ -0,0 +1,143 @@
1
+ Ext.define('Coon.app.login.LoginForm', {
2
+ extend: 'Ext.form.Panel',
3
+ xtype: 'LoginForm',
4
+ cls: 'login-form',
5
+ requires: [
6
+ 'Ext.form.field.Text',
7
+ 'Ext.layout.container.HBox',
8
+ 'Ext.layout.container.VBox',
9
+ 'Coon.report.plugin.form.EnterConfirmFormPlugin'
10
+ ],
11
+ controller: 'LoginFormController',
12
+ viewModel: 'LoginFormModel',
13
+ layout: {
14
+ type: 'vbox',
15
+ align: 'stretch',
16
+ },
17
+ plugins: [
18
+ {
19
+ ptype: 'EnterConfirmFormPlugin',
20
+ confirmHandler(panel) {
21
+ panel.fireEvent('submit');
22
+ },
23
+ }
24
+ ],
25
+ defaults: {
26
+ margin: '8px 0',
27
+ },
28
+ items: [
29
+ {
30
+ xtype: 'container',
31
+ layout: {
32
+ type: 'hbox',
33
+ align: 'stretch',
34
+ },
35
+ items: [
36
+ {
37
+ xtype: 'label',
38
+ reference: 'error',
39
+ maxWidth: 300,
40
+ hidden: true,
41
+ flex: 1,
42
+ bind: {
43
+ text: '{error}',
44
+ hidden: '{!error}',
45
+ },
46
+ },
47
+ {
48
+ xtype: 'button',
49
+ hidden: true,
50
+ cls: 'loginquestion',
51
+ reference: 'details',
52
+ iconCls: 'x-fas fa-question-circle',
53
+ tooltip: 'Подробнее',
54
+ handler: 'showDetails',
55
+ bind: {
56
+ hidden: '{!detailMessage}',
57
+ },
58
+ }
59
+ ],
60
+ },
61
+ {
62
+ xtype: 'textfield',
63
+ align: 'stretch',
64
+ allowBlank: false,
65
+ ui: 'login-field',
66
+ emptyText: 'Логин',
67
+ bind: {
68
+ hidden: '{requireTwoFactor}',
69
+ value: '{loginPassData.username}',
70
+ },
71
+ plugins: {
72
+ TextFieldFormatter: {
73
+ rules: ['noSpaces'],
74
+ },
75
+ },
76
+ },
77
+ {
78
+ xtype: 'textfield',
79
+ align: 'stretch',
80
+ ui: 'login-field',
81
+ inputType: 'password',
82
+ allowBlank: false,
83
+ emptyText: 'Пароль',
84
+ bind: {
85
+ hidden: '{requireTwoFactor}',
86
+ value: '{loginPassData.password}',
87
+ },
88
+ plugins: {
89
+ TextFieldFormatter: {
90
+ rules: ['noSpaces'],
91
+ },
92
+ },
93
+ },
94
+ {
95
+ xtype: 'component',
96
+ bind: {
97
+ html: '{statusMessage}',
98
+ hidden: '{!statusMessage}',
99
+ },
100
+ },
101
+ {
102
+ xtype: 'textfield',
103
+ align: 'stretch',
104
+ ui: 'login-field',
105
+ hidden: true,
106
+ allowBlank: false,
107
+ emptyText: 'введите код,6 цифр',
108
+ bind: {
109
+ visible: '{requireTwoFactor}',
110
+ disabled: '{!requireTwoFactor}',
111
+ value: '{otp}',
112
+ },
113
+ plugins: {
114
+ TextFieldFormatter: {
115
+ rules: ['noSpaces', 'number', 'length:6'],
116
+ },
117
+ },
118
+ },
119
+ {
120
+ xtype: 'button',
121
+ reference: 'submit',
122
+ ui: 'login-button',
123
+ scale: 'large',
124
+ text: 'Войти',
125
+ formBind: true,
126
+ handler: 'onSubmit',
127
+ bind: {
128
+ disabled: '{processLogin}',
129
+ },
130
+ },
131
+ {
132
+ xtype: 'button',
133
+ itemId: 'cancelBtn',
134
+ cls: 'twofactor-cancel-btn',
135
+ hidden: true,
136
+ text: 'Отменить',
137
+ handler: 'resetForm',
138
+ bind: {
139
+ visible: '{requireTwoFactor}',
140
+ },
141
+ }
142
+ ],
143
+ });
@@ -0,0 +1,103 @@
1
+ .login-form {
2
+
3
+ @include extjs-button-large-ui(
4
+ $ui: 'login-button',
5
+ $font-family: "Tahoma",
6
+ $border-radius: 4px,
7
+ $border-color: darken($base-color, 20%),
8
+ $border-color-over: $base-color,
9
+ $border-color-focus: #cccccc,
10
+ $border-color-pressed: #cccccc,
11
+ $border-color-focus-over: #cccccc,
12
+ $border-color-focus-pressed: $base-color,
13
+ $border-color-disabled: #cccccc,
14
+ $background-color: $base-color,
15
+ $background-color-over: transparentize($base-color, 20%),
16
+ $background-color-focus: transparentize($base-color, 20%),
17
+ $background-color-pressed: $base-color,
18
+ $background-color-focus-over: transparentize($base-color, 20%),
19
+ $background-color-focus-pressed: $base-color,
20
+ $background-color-disabled: null,
21
+ $font-weight: normal,
22
+ $color: white
23
+ );
24
+
25
+ @include extjs-text-field-ui(
26
+ $ui: 'login-field',
27
+ $ui-background-color: transparent,
28
+ $ui-empty-color: #e3e3e3,
29
+ $ui-height: 30px,
30
+ $ui-border-radius: 4px,
31
+ $ui-font-size: 16px,
32
+ $ui-font-weight: normal,
33
+ $ui-font-family: "Tahoma"
34
+ );
35
+
36
+
37
+ $placeholderColor: #a0a0a0;
38
+
39
+ label {
40
+ color: red;
41
+ }
42
+
43
+ input {
44
+ text-align: center;
45
+ font-family: Tahoma;
46
+ }
47
+
48
+ input::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
49
+ color: $placeholderColor;
50
+ opacity: 1; /* Firefox */
51
+ }
52
+
53
+ input:-ms-input-placeholder { /* Internet Explorer 10-11 */
54
+ color: $placeholderColor;
55
+ }
56
+
57
+ input::-ms-input-placeholder { /* Microsoft Edge */
58
+ color: $placeholderColor;
59
+ }
60
+
61
+ .x-form-empty-field::placeholder {
62
+ color: $placeholderColor;
63
+ }
64
+
65
+ .twofactor-cancel-btn {
66
+ background-color: white;
67
+ }
68
+
69
+
70
+ .x-form-text-field-body-login-field {
71
+ max-width: 100%;
72
+ }
73
+
74
+ .x-form-trigger-wrap-login-field{
75
+ height: 40px;
76
+ border: 1px solid #b5bfcc;
77
+ border-radius: 4px;
78
+ background-color: white;
79
+ }
80
+
81
+ .x-form-type-password .x-form-text {
82
+ height: 100%;
83
+ }
84
+
85
+ .x-panel-body-default{
86
+ background: transparent;
87
+ }
88
+
89
+ .loginquestion {
90
+ padding: 0 5px;
91
+ .x-btn-icon-el-default-small {
92
+ color: red;
93
+ }
94
+ &.x-btn-pressed, &.x-btn-focus{
95
+ background-color: transparent !important;
96
+ }
97
+ &.x-btn-over:not(&.x-btn-focus) {
98
+ background-color: transparent !important;
99
+ }
100
+ }
101
+
102
+ }
103
+
@@ -0,0 +1,140 @@
1
+ Ext.define('Coon.app.login.LoginFormController', {
2
+ alternateClassName: 'SigmaUtilities.view.login.LoginFormController',
3
+ extend: 'Ext.app.ViewController',
4
+ alias: 'controller.LoginFormController',
5
+
6
+ init() {
7
+ this.vm = this.getViewModel();
8
+ this.getView().on('submit', this.onSubmit, this);
9
+ const userData = localStorage.getJson('userData');
10
+ if (userData && userData.requireTwoFactorAuthentication) {
11
+ this.process2FA(userData);
12
+ }
13
+ },
14
+
15
+ onSubmit() {
16
+ this.vm.set({
17
+ 'error': undefined,
18
+ 'detailMessage': undefined,
19
+ 'processLogin': true,
20
+ });
21
+ if (this.vm.get('requireTwoFactor')) {
22
+ this.process2FA();
23
+ } else {
24
+ this.onSubmitLogin();
25
+ }
26
+ },
27
+
28
+ resetForm() {
29
+ this.vm.set({
30
+ 'statusMessage': false,
31
+ 'requireTwoFactor': false,
32
+ 'processLogin': false,
33
+ 'loginPassData': {},
34
+ 'otp': undefined,
35
+ });
36
+ this.getView().reset();
37
+ },
38
+
39
+ get2FAEmailMessage() {
40
+ const userData = localStorage.getJson('userData');
41
+ return `<span style="color:#555;">
42
+ на почту <span style="color:black;">${userData.email}</span> отправлено письмо с проверочным одноразовым кодом
43
+ </span>`;
44
+ },
45
+
46
+ process2FA() {
47
+ this.vm.set({
48
+ 'processLogin': false,
49
+ 'requireTwoFactor': true,
50
+ 'statusMessage': this.get2FAEmailMessage(),
51
+ });
52
+ const otpValue = this.vm.get('otp');
53
+ if (otpValue) {
54
+ this.vm.set({
55
+ 'processLogin': true,
56
+ 'statusMessage': 'проверка кода...',
57
+ });
58
+ return this.check2FACode(otpValue)
59
+ .then((res) => {
60
+ if (res.responseText === 'true') {
61
+ this.processView();
62
+ } else {
63
+ this.vm.set('statusMessage', this.get2FAEmailMessage());
64
+ }
65
+ })
66
+ .catch((res) => {
67
+ this.vm.set({
68
+ 'processLogin': false,
69
+ 'statusMessage': 'произошла ошибка отправки письма, попробуйте еще раз',
70
+ });
71
+ console.error(res.trace || res.error || res.responseText || res.message || res.localizedMessage);
72
+ });
73
+ }
74
+ },
75
+
76
+ check2FACode(oneTimePassword) {
77
+ return Ext.Ajax.request({
78
+ url: `/twoFactor/validateOneTimePasswordEmail`,
79
+ headers: {'X-CSRF-Token': localStorage.getItem('CSRFToken')},
80
+ method: 'POST',
81
+ params: {
82
+ oneTimePassword,
83
+ },
84
+ });
85
+ },
86
+
87
+ onSubmitLogin: function() {
88
+ const me = this;
89
+ const loginPassData = this.vm.get('loginPassData');
90
+ this.getLoginData(loginPassData)
91
+ .then(function(response) {
92
+ if (response.authenticated !== true) {
93
+ me.vm.set({
94
+ 'processLogin': false,
95
+ 'error': 'Неправильно указан логин или пароль',
96
+ 'detailMessage': response.stackTrace});
97
+ return;
98
+ }
99
+ localStorage.setJson('userData', response);
100
+ if (response.requireTwoFactorAuthentication) {
101
+ return me.process2FA();
102
+ }
103
+ me.processView();
104
+ })
105
+ .catch((error) => {
106
+ me.vm.set('processLogin', false);
107
+ console.error(error);
108
+ });
109
+ },
110
+
111
+ processView() {
112
+ const tokenCommand = Ext.create('command.GetCSRFTokenCommand');
113
+ tokenCommand.on('complete', function(token) {
114
+ if (!Ext.isEmpty(token)) {
115
+ localStorage.setItem('CSRFToken', token);
116
+ }
117
+
118
+ Ext.fireEvent('auth:loginSuccessful');
119
+ }, this);
120
+ tokenCommand.execute();
121
+ },
122
+
123
+ showDetails: function() {
124
+ Ext.Msg.alert('Ошибка', this.vm.get('detailMessage'));
125
+ },
126
+
127
+ getLoginData: function(loginPassData) {
128
+ return Ext.Ajax.request({
129
+ url: 'login',
130
+ params: {
131
+ username: loginPassData.username,
132
+ password: loginPassData.password,
133
+ },
134
+ })
135
+ .then((response) => Ext.decode(response.responseText))
136
+ .catch((response) => {
137
+ throw new Error('server-side failure with status code ' + response.status);
138
+ });
139
+ },
140
+ });
@@ -0,0 +1,17 @@
1
+ Ext.define('Coon.app.login.LoginFormModel', {
2
+ alternateClassName: 'SigmaUtilities.view.login.LoginFormModel',
3
+ extend: 'Ext.app.ViewModel',
4
+ alias: 'viewmodel.LoginFormModel',
5
+ data: {
6
+ requireTwoFactor: false,
7
+ statusMessage: undefined,
8
+ processLogin: undefined,
9
+ detailMessage: undefined,
10
+ loginPassData: {
11
+ username: undefined,
12
+ password: undefined,
13
+ },
14
+ otp: undefined,
15
+ error: undefined,
16
+ },
17
+ });
@@ -0,0 +1,82 @@
1
+ /**
2
+ * TextFieldFormatter Плагин позволяет задать правила форматирование value для поля ввода
3
+ * @param {[string]} rules список правил, которые применяются к тексту в поле в моменте change
4
+ * Для каждого правила должа быть соотвествующая функция, имя функции задается как имя правила + Fn,
5
+ * например rules: ['noSpaces'] вызовет функцию noSpacesFn
6
+ *
7
+ * Пример:
8
+ * {
9
+ * xtype: 'textfield',
10
+ * allowBlank: false,
11
+ * emptyText: 'Тест',
12
+ * plugins: {
13
+ * TextFieldFormatter: {
14
+ * rules: ['noSpaces', 'number', 'length:6'],
15
+ * },
16
+ * },
17
+ */
18
+
19
+ Ext.define('Coon.plugin.TextFieldFormatter', {
20
+ extend: 'Ext.plugin.Abstract',
21
+ alias: 'plugin.TextFieldFormatter',
22
+ id: 'TextFieldFormatter',
23
+ config: {
24
+ rules: [],
25
+ },
26
+ transformers: {
27
+ noSpaces() { // текст без пробелов
28
+ this.fieldValue = this.fieldValue.replaceAll(' ', '');
29
+ },
30
+ length(length) { // ограничение мин/макс длины текста в поле
31
+ this.field.minLength = length;
32
+ this.fieldValue = this.fieldValue.substring(0, length);
33
+ },
34
+ number() { // ввод только числовое значение
35
+ this.fieldValue = this.fieldValue.replace(/\D/g, '');
36
+ },
37
+ },
38
+
39
+ init() {
40
+ this.field = this.getCmp();
41
+ this.fieldName = this.field.fieldLabel ? this.field.fieldLabel : (this.field.reference || this.field.name);
42
+ this.field.on('change', function() {
43
+ const newValue = this.field.getValue();
44
+ if (newValue !== this.fieldValue) {
45
+ this.fieldValue = newValue;
46
+ this.formatValue();
47
+ this.field.setValue(this.fieldValue);
48
+ }
49
+ }, this);
50
+ },
51
+
52
+ formatValue() {
53
+ const rules = this.getValidatedRules();
54
+ rules && rules.forEach((rule) => {
55
+ const [functionName, setting] = rule.split(':');
56
+ this.executeFunction(functionName, setting);
57
+ });
58
+ },
59
+
60
+ getValidatedRules: function() {
61
+ let rules = this.getRules();
62
+ if (!Array.isArray(rules)) {
63
+ Coon.log.error(`[TextFieldFormatter]: список rules для ${this.fieldName} должен быть массивом`);
64
+ return false;
65
+ }
66
+ rules = rules.filter((item) => typeof item === 'string' && isNaN(item));
67
+ if (Ext.isEmpty(rules)) {
68
+ Coon.log.error(`[TextFieldFormatter]: не найдено данных rules для форматирования поля ${this.fieldName}`);
69
+ return false;
70
+ }
71
+ return rules;
72
+ },
73
+
74
+ executeFunction: function(functionName, setting) {
75
+ const transformerFunction = this.transformers[functionName];
76
+ if (Ext.isFunction(transformerFunction)) {
77
+ transformerFunction.call(this, setting);
78
+ } else {
79
+ Coon.log.error(`[TextFieldFormatter]: не найдено функции форматирования [${functionName}] для поля ${this.fieldName}`);
80
+ }
81
+ },
82
+ });
@@ -8,12 +8,7 @@ Ext.define('Coon.report.component.settings.AddVersioningTab', {
8
8
  },
9
9
 
10
10
  initAction: function() {
11
- if (this.isEnabled()) {
12
- this.getView().add({xtype: 'ReportFormHistoryPanel'});
13
- }
11
+ this.getView().add({xtype: 'ReportFormHistoryPanel'});
14
12
  },
15
13
 
16
- isEnabled: function() {
17
- return Coon.setup.getOption('reportVersioning');
18
- },
19
14
  });
@@ -8,19 +8,13 @@ Ext.define('Coon.uielement.component.settings.AddVersioningTab', {
8
8
  },
9
9
 
10
10
  initAction: function() {
11
- if (this.isEnabled()) {
12
- this.getView().down('tabpanel').add({
13
- xtype: 'UiCPVersionPanel',
14
- title: 'версии',
15
- bind: {
16
- uiElement: '{uiElement}',
17
- },
18
- });
19
- }
20
- },
21
-
22
- isEnabled: function() {
23
- return Coon.setup.getOption('customPanelVersioning');
11
+ this.getView().down('tabpanel').add({
12
+ xtype: 'UiCPVersionPanel',
13
+ title: 'версии',
14
+ bind: {
15
+ uiElement: '{uiElement}',
16
+ },
17
+ });
24
18
  },
25
19
 
26
20
  });
@@ -52,6 +52,9 @@ Ext.define('Coon.uielement.plugin.ExecuteCommandPlugin', {
52
52
  preventRefocus: true,
53
53
  });
54
54
  }
55
+ if (typeof this.successMessage !== 'string' && this.successMessage) {
56
+ this.successMessage = 'alert';
57
+ }
55
58
  },
56
59
 
57
60
  parseProperty: function(obj, property) {
@@ -182,7 +185,7 @@ Ext.define('Coon.uielement.plugin.ExecuteCommandPlugin', {
182
185
  }
183
186
  if (this.successMessage) {
184
187
  Coon.uielement.plugin.configPanel.executeCommand.ExecuteCommandPluginConfigPanelFormEditor.showMessage(
185
- this.asAlert, this.successTitle, this.successText
188
+ this.successMessage, this.successTitle, this.successText
186
189
  );
187
190
  }
188
191
 
package/src/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  Ext.define('Coon.version', {
2
2
  singleton: true,
3
- number: '2.8.0',
3
+ number: '2.8.2',
4
4
  });