complexqa_frontend_core 1.25.1 → 1.27.1

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 (31) hide show
  1. package/package.json +1 -1
  2. package/publish/api/custom_property/custom_property_template_api.js +16 -0
  3. package/publish/api/custom_property_api.js +54 -0
  4. package/publish/api/custom_property_option_api.js +17 -0
  5. package/publish/api/custom_property_value_api.js +82 -0
  6. package/publish/api/index.js +12 -0
  7. package/publish/api/team_domain_api.js +62 -0
  8. package/publish/api/team_management_api.js +1 -1
  9. package/publish/api/util/url_inspect_api.js +54 -0
  10. package/publish/app_configuration/table/helpers/table_element_models.js +8 -0
  11. package/publish/app_configuration/table/sections/custom_property.js +96 -0
  12. package/publish/app_configuration/table/sections/team_domain.js +55 -0
  13. package/publish/app_configuration/table/sections/util_execution_url_inspect.js +60 -0
  14. package/publish/app_configuration/table/table_configuration.js +6 -0
  15. package/publish/index.js +5 -0
  16. package/publish/services/UserService.js +9 -0
  17. package/publish/types/core/1_familyTestDocumentation.js +8 -0
  18. package/publish/types/element_translate/typeCustomProperty.i18n.js +85 -0
  19. package/publish/types/element_translate/typeCustomPropertyValue.i18n.js +65 -0
  20. package/publish/types/element_translate/typeTeamDomain.i18n.js +71 -0
  21. package/publish/types/element_translate/typeTeamTotalStatistic.i18n.js +221 -67
  22. package/publish/types/element_translate/typeUtilExecutionUrlInspect.i18n.js +55 -0
  23. package/publish/types/element_translate/typeUtilExecutionUrlInspectCheck.i18n.js +111 -0
  24. package/publish/types/family_contracts/typeTeamTotalStatistic.js +6 -10
  25. package/publish/types/family_elements/typeCustomProperty.js +138 -0
  26. package/publish/types/family_elements/typeTeam.js +5 -2
  27. package/publish/types/family_elements/typeTeamDomain.js +172 -0
  28. package/publish/types/family_events/familyEvent.js +2 -0
  29. package/publish/types/family_relation/typeCustomPropertyValue.js +117 -0
  30. package/publish/types/family_utils/typeUtilExecutionUrlInspect.js +199 -0
  31. package/publish/types/family_utils/typeUtilExecutionUrlInspectCheck.js +100 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Переводы для typeUtilExecutionUrlInspectCheck.
3
+ *
4
+ * @see typeUtilExecutionUrlInspectCheck
5
+ */
6
+ export const typeUtilExecutionUrlInspectCheck_i18n = {
7
+ attribute_name_translate_matrix: {
8
+ en: {
9
+ url_inspect_check_id: 'Check',
10
+ util_execution_id : 'Run',
11
+ sort_order : 'Order',
12
+ check_kind : 'Kind',
13
+ check_status : 'Status',
14
+ finding_code : 'Finding',
15
+ summary_message : 'Summary',
16
+ detail_message : 'Detail',
17
+ },
18
+ ru: {
19
+ url_inspect_check_id: 'Проверка',
20
+ util_execution_id : 'Запуск',
21
+ sort_order : 'Порядок',
22
+ check_kind : 'Вид',
23
+ check_status : 'Статус',
24
+ finding_code : 'Находка',
25
+ summary_message : 'Кратко',
26
+ detail_message : 'Подробности',
27
+ },
28
+ },
29
+ enum_value_translate_matrix: {
30
+ check_kind: {
31
+ en: {
32
+ DNS : 'DNS',
33
+ TCP_80 : 'TCP 80',
34
+ TCP_443 : 'TCP 443',
35
+ TLS : 'TLS',
36
+ HTTP : 'HTTP',
37
+ HTTPS : 'HTTPS',
38
+ SECURITY_HEADERS: 'Security headers',
39
+ BROWSER : 'Browser',
40
+ },
41
+ ru: {
42
+ DNS : 'DNS',
43
+ TCP_80 : 'TCP 80',
44
+ TCP_443 : 'TCP 443',
45
+ TLS : 'TLS',
46
+ HTTP : 'HTTP',
47
+ HTTPS : 'HTTPS',
48
+ SECURITY_HEADERS: 'Заголовки безопасности',
49
+ BROWSER : 'Браузер',
50
+ },
51
+ },
52
+ check_status: {
53
+ en: {
54
+ PENDING : 'Pending',
55
+ QUEUED : 'Queued',
56
+ RUNNING : 'Running',
57
+ COMPLETED: 'Completed',
58
+ SKIPPED : 'Skipped',
59
+ ERROR : 'Error',
60
+ },
61
+ ru: {
62
+ PENDING : 'Ожидает',
63
+ QUEUED : 'В очереди',
64
+ RUNNING : 'Выполняется',
65
+ COMPLETED: 'Завершена',
66
+ SKIPPED : 'Пропущена',
67
+ ERROR : 'Ошибка',
68
+ },
69
+ },
70
+ finding_code: {
71
+ en: {
72
+ SUCCESS : 'Success',
73
+ ERR_NAME_NOT_RESOLVED : 'Name not resolved',
74
+ ERR_CONNECTION_REFUSED : 'Connection refused',
75
+ ERR_CONNECTION_TIMED_OUT : 'Connection timed out',
76
+ ERR_CERT_DATE_INVALID : 'Certificate date invalid',
77
+ ERR_CERT_AUTHORITY_INVALID : 'Certificate authority invalid',
78
+ ERR_CERT_COMMON_NAME_INVALID: 'Certificate name invalid',
79
+ ERR_SSL_PROTOCOL_ERROR : 'TLS protocol error',
80
+ ERR_TOO_MANY_REDIRECTS : 'Too many redirects',
81
+ HTTP_STATUS : 'HTTP status',
82
+ NO_TLS : 'No TLS',
83
+ EMPTY_BODY : 'Empty body',
84
+ PROTOTYPE_BROWSER_SKIPPED : 'Browser skipped (prototype)',
85
+ NO_PUBLIC_ADDRESS : 'No public address',
86
+ UNKNOWN_CHECK_KIND : 'Unknown check kind',
87
+ BROWSER_FAILED : 'Browser failed',
88
+ BROWSER_SUBMIT_FAILED : 'Browser submit failed',
89
+ },
90
+ ru: {
91
+ SUCCESS : 'Успех',
92
+ ERR_NAME_NOT_RESOLVED : 'Имя не резолвится',
93
+ ERR_CONNECTION_REFUSED : 'Соединение отклонено',
94
+ ERR_CONNECTION_TIMED_OUT : 'Таймаут соединения',
95
+ ERR_CERT_DATE_INVALID : 'Срок сертификата недействителен',
96
+ ERR_CERT_AUTHORITY_INVALID : 'Центр сертификации не принят',
97
+ ERR_CERT_COMMON_NAME_INVALID: 'Имя в сертификате не совпадает',
98
+ ERR_SSL_PROTOCOL_ERROR : 'Ошибка протокола TLS',
99
+ ERR_TOO_MANY_REDIRECTS : 'Слишком много редиректов',
100
+ HTTP_STATUS : 'HTTP-статус',
101
+ NO_TLS : 'Нет TLS',
102
+ EMPTY_BODY : 'Пустое тело',
103
+ PROTOTYPE_BROWSER_SKIPPED : 'Браузер пропущен (прототип)',
104
+ NO_PUBLIC_ADDRESS : 'Нет публичного адреса',
105
+ UNKNOWN_CHECK_KIND : 'Неизвестный вид проверки',
106
+ BROWSER_FAILED : 'Ошибка браузера',
107
+ BROWSER_SUBMIT_FAILED : 'Не удалось поставить браузер в очередь',
108
+ },
109
+ },
110
+ },
111
+ };
@@ -2,19 +2,15 @@ import { familyContracts } from "./familyContracts.js";
2
2
  import { typeTeamTotalStatistic_i18n } from "../element_translate/typeTeamTotalStatistic.i18n.js";
3
3
 
4
4
  /**
5
+ * Translation contract for team total_usage rows
6
+ * (`element_model` / `util_action_key` labels).
5
7
  *
6
- * @version v.1.0 (31/03/2026)
8
+ * API row: { kind, element_model, count, price_limit }
9
+ *
10
+ * @version v.1.1 (14/08/2026)
7
11
  */
8
12
  export class typeTeamTotalStatistic extends familyContracts
9
13
  {
10
- project;
11
- test_suite;
12
- test_case;
13
- test_case_step;
14
- test_run;
15
- team_member;
16
-
17
-
18
14
  attribute_name_translate_matrix = typeTeamTotalStatistic_i18n.attribute_name_translate_matrix;
19
15
 
20
- }
16
+ }
@@ -0,0 +1,138 @@
1
+ import { familyTestDocumentation } from "../core/1_familyTestDocumentation.js";
2
+ import { is_object } from "../../utils/utils.js";
3
+ import _ from 'underscore';
4
+ import { typeCustomProperty_i18n } from "../element_translate/typeCustomProperty.i18n.js";
5
+
6
+ /**
7
+ * Team-scoped custom property catalog slot for one element_type (test_case | bug).
8
+ * Server CUD requires member_role = ADMINISTRATOR. Do not set clone_element = false (listing CM).
9
+ *
10
+ * @see docs/CustomProperties/custom-property-docs.MD
11
+ *
12
+ * @version v.0.1 (15/08/2026)
13
+ */
14
+ export class typeCustomProperty extends familyTestDocumentation
15
+ {
16
+ custom_property_id;
17
+ team_id;
18
+ element_type;
19
+ property_key;
20
+ value_type;
21
+ cardinality;
22
+ name;
23
+ description;
24
+ is_required;
25
+ is_enabled;
26
+ is_searchable;
27
+ sort_order;
28
+ created_at;
29
+ updated_at;
30
+
31
+ /** Hydrated via search options.add: ['options'] */
32
+ options;
33
+
34
+ primary_key = 'custom_property_id';
35
+ api_key = 'custom_property';
36
+
37
+ structure_scheme = {
38
+ custom_property_id: 'integer | require',
39
+ team_id : 'integer | require',
40
+ element_type : 'string | enum | require',
41
+ property_key : 'string | require',
42
+ value_type : 'string | enum | require',
43
+ cardinality : 'string | enum | require',
44
+ name : 'string | require',
45
+ description : 'string | optional',
46
+ is_required : 'integer | optional',
47
+ is_enabled : 'integer | optional',
48
+ is_searchable : 'integer | optional',
49
+ sort_order : 'integer | optional',
50
+ created_at : 'timestamp | optional',
51
+ updated_at : 'timestamp | optional',
52
+ };
53
+
54
+ create_scheme = [
55
+ 'element_type',
56
+ 'property_key',
57
+ 'value_type',
58
+ 'name',
59
+ 'cardinality',
60
+ 'description',
61
+ 'is_required',
62
+ 'is_enabled',
63
+ 'is_searchable',
64
+ 'sort_order',
65
+ ];
66
+
67
+ available_enum_values = {
68
+ element_type: typeCustomProperty.get_element_type_values(),
69
+ value_type : typeCustomProperty.get_value_type_values(),
70
+ cardinality : typeCustomProperty.get_cardinality_values(),
71
+ };
72
+
73
+ enum_value_translate_matrix = typeCustomProperty_i18n.enum_value_translate_matrix;
74
+
75
+ attribute_name_translate_matrix = typeCustomProperty_i18n.attribute_name_translate_matrix;
76
+
77
+
78
+ static get_element_type_values()
79
+ {
80
+ return [ 'test_case', 'bug' ];
81
+ }
82
+
83
+
84
+ static get_value_type_values()
85
+ {
86
+ return [
87
+ 'STRING',
88
+ 'TEXT',
89
+ 'INTEGER',
90
+ 'DATE',
91
+ 'URL',
92
+ 'USER',
93
+ 'DROPDOWN',
94
+ 'CHECKBOX',
95
+ 'MULTISELECT',
96
+ ];
97
+ }
98
+
99
+
100
+ static get_cardinality_values()
101
+ {
102
+ return [ 'SINGLE', 'MULTIPLE' ];
103
+ }
104
+
105
+
106
+ /**
107
+ * @param {object|false|undefined} data
108
+ * @returns {typeCustomProperty}
109
+ */
110
+ constructor(data = false)
111
+ {
112
+ super();
113
+
114
+ if (data && is_object(data))
115
+ {
116
+ _.mapObject(data, (value, key) =>
117
+ {
118
+ if (this.hasOwnProperty(key))
119
+ {
120
+ this[ key ] = value;
121
+ }
122
+ });
123
+ }
124
+
125
+ return this;
126
+ }
127
+
128
+
129
+ get_element_name()
130
+ {
131
+ if (this.name)
132
+ {
133
+ return String(this.name);
134
+ }
135
+
136
+ return String(this.property_key ?? this.custom_property_id ?? '');
137
+ }
138
+ }
@@ -107,9 +107,12 @@ export class typeTeam extends familyGeneralElement
107
107
 
108
108
 
109
109
  /**
110
- * Return {"project":1,"test_suite":1,"test_case":1,"test_case_step":1,"test_runs":1,"team_member":1}
110
+ * Billing catalog usage for the current team.
111
111
  *
112
- * @version v.0.1 (21/03/2026)
112
+ * Rows: [{ kind, element_model, count, price_limit }, ...]
113
+ * kind = entity | util; price_limit null = unlimited.
114
+ *
115
+ * @version v.0.2 (14/08/2026)
113
116
  * @returns {Promise<object>}
114
117
  */
115
118
  async get_team_total_statistic()
@@ -0,0 +1,172 @@
1
+ import { familyGeneralElement } from "../core/0_familyGeneralElement.js";
2
+ import { echo, is_object } from "../../utils/utils.js";
3
+ import { typeTeamDomain_i18n } from "../element_translate/typeTeamDomain.i18n.js";
4
+
5
+
6
+ /**
7
+ * Team-owned domain (cqa_team.team_domains). Shared across projects of the team.
8
+ * Verify/revoke via ApiService.team_domain; url.inspect requires VERIFIED.
9
+ * Backend: test_site/docs/team/team-domains.md
10
+ *
11
+ * @version v.0.1 (14/08/2026)
12
+ */
13
+ export class typeTeamDomain extends familyGeneralElement
14
+ {
15
+ team_domain_id;
16
+ team_id;
17
+ domain_canon;
18
+ display_name;
19
+ verification_method;
20
+ domain_status;
21
+ verification_token;
22
+ last_error_message;
23
+ verified_at;
24
+ created_at;
25
+ updated_at;
26
+ file_url_https;
27
+ file_url_http;
28
+ file_body;
29
+ dns_host;
30
+ dns_txt_value;
31
+ instruction;
32
+
33
+ primary_key = 'team_domain_id';
34
+ api_key = 'team_domain';
35
+
36
+ structure_scheme = {
37
+ team_domain_id : 'integer | optional',
38
+ team_id : 'integer | optional',
39
+ domain_canon : 'string | max:255 | require',
40
+ display_name : 'string | max:255 | optional',
41
+ verification_method: 'string | enum | require',
42
+ domain_status : 'string | enum | optional',
43
+ verification_token : 'string | optional',
44
+ last_error_message : 'string | optional',
45
+ verified_at : 'timestamp | optional',
46
+ created_at : 'timestamp | optional',
47
+ updated_at : 'timestamp | optional',
48
+ file_url_https : 'string | optional',
49
+ file_url_http : 'string | optional',
50
+ file_body : 'string | optional',
51
+ dns_host : 'string | optional',
52
+ dns_txt_value : 'string | optional',
53
+ instruction : 'string | optional',
54
+ };
55
+
56
+ create_scheme = [
57
+ 'domain_canon',
58
+ 'display_name',
59
+ 'verification_method',
60
+ ];
61
+
62
+ available_enum_values = {
63
+ verification_method: [ 'FILE', 'DNS_TXT' ],
64
+ domain_status : [ 'PENDING', 'VERIFIED', 'FAILED', 'REVOKED' ],
65
+ };
66
+
67
+ enum_value_translate_matrix = typeTeamDomain_i18n.enum_value_translate_matrix;
68
+ attribute_name_translate_matrix = typeTeamDomain_i18n.attribute_name_translate_matrix;
69
+
70
+ status_color = {
71
+ PENDING : '#4D92FA',
72
+ VERIFIED: '#009688',
73
+ FAILED : '#E66565',
74
+ REVOKED : '#9E9E9E',
75
+ };
76
+
77
+ clone_element = false;
78
+ delete_mass = false;
79
+ update_properties = false;
80
+ update = false;
81
+ clone_element_mass = false;
82
+
83
+
84
+ /**
85
+ * @param {object|false|undefined} data
86
+ */
87
+ constructor(data = false)
88
+ {
89
+ super();
90
+
91
+ if (data && is_object(data))
92
+ {
93
+ _.mapObject(data, (value, key) =>
94
+ {
95
+ if (this.hasOwnProperty(key))
96
+ {
97
+ this [ key ] = value;
98
+ }
99
+ });
100
+ }
101
+
102
+ return this;
103
+ }
104
+
105
+
106
+ /**
107
+ * @param {object} payload
108
+ * @param {object} callback
109
+ */
110
+ verify(payload, callback)
111
+ {
112
+ if (typeof callback?.before === 'function')
113
+ {
114
+ callback?.before({ payload });
115
+ }
116
+
117
+ return ApiService[ this.api_key ].verify(payload).then((response) =>
118
+ {
119
+ if (typeof callback?.success === 'function')
120
+ {
121
+ callback?.success({ response, payload });
122
+ }
123
+ }).catch((error) =>
124
+ {
125
+ echo({ error });
126
+ if (typeof callback?.error === 'function')
127
+ {
128
+ callback?.error({ error, payload });
129
+ }
130
+ }).finally((response) =>
131
+ {
132
+ if (typeof callback?.final === 'function')
133
+ {
134
+ callback?.final({ response, payload });
135
+ }
136
+ });
137
+ }
138
+
139
+
140
+ /**
141
+ * @param {object} payload
142
+ * @param {object} callback
143
+ */
144
+ revoke(payload, callback)
145
+ {
146
+ if (typeof callback?.before === 'function')
147
+ {
148
+ callback?.before({ payload });
149
+ }
150
+
151
+ return ApiService[ this.api_key ].revoke(payload).then((response) =>
152
+ {
153
+ if (typeof callback?.success === 'function')
154
+ {
155
+ callback?.success({ response, payload });
156
+ }
157
+ }).catch((error) =>
158
+ {
159
+ echo({ error });
160
+ if (typeof callback?.error === 'function')
161
+ {
162
+ callback?.error({ error, payload });
163
+ }
164
+ }).finally((response) =>
165
+ {
166
+ if (typeof callback?.final === 'function')
167
+ {
168
+ callback?.final({ response, payload });
169
+ }
170
+ });
171
+ }
172
+ }
@@ -40,6 +40,7 @@ export class familyEvent extends familyGeneralElement
40
40
 
41
41
  /**
42
42
  * Каталог subject_type (= api_key), совпадает с seed event-service.
43
+ * `custom_property` — CUD слота каталога; значения на хосте публикуются как test_case/bug UPDATE.
43
44
  *
44
45
  * @returns {string[]}
45
46
  */
@@ -61,6 +62,7 @@ export class familyEvent extends familyGeneralElement
61
62
  'attachment',
62
63
  'tag',
63
64
  'tag_relation',
65
+ 'custom_property',
64
66
  'test_account',
65
67
  'user_profile',
66
68
  'text_document',
@@ -0,0 +1,117 @@
1
+ import { is_object } from '../../utils/utils.js';
2
+ import _ from 'underscore';
3
+ import { familyRelation } from '../core/1_familyRelation.js';
4
+ import { typeCustomPropertyValue_i18n } from '../element_translate/typeCustomPropertyValue.i18n.js';
5
+
6
+ /**
7
+ * One typed value row on a host element (test_case | bug).
8
+ * Mutations go through CustomPropertyValueApi.set / add / delete, not union create().
9
+ * Server rejects member_role = READONLY (api_code = -501). MEMBER may write.
10
+ *
11
+ * @see docs/CustomProperties/custom-property-docs.MD
12
+ *
13
+ * @version v.0.1 (15/08/2026)
14
+ */
15
+ export class typeCustomPropertyValue extends familyRelation
16
+ {
17
+ custom_property_value_id;
18
+ custom_property_id;
19
+ team_id;
20
+ project_id;
21
+ element_type;
22
+ element_id;
23
+ sort_order;
24
+ user_id;
25
+ created_at;
26
+ updated_at;
27
+
28
+ string_value;
29
+ text_value;
30
+ integer_value;
31
+ date_value;
32
+ url;
33
+ url_caption;
34
+ user_id_value;
35
+ checkbox_value;
36
+ option_id;
37
+
38
+ source_key = 'custom_property_id';
39
+ target_key = 'element_id';
40
+ relation_type_key = 'element_type';
41
+
42
+ primary_key = 'custom_property_value_id';
43
+ api_key = 'custom_property_value';
44
+
45
+ static relation_target_map = {
46
+ test_case: { type_token: 'typeTestCase', primary_key: 'test_case_id', api_key: 'test_case' },
47
+ bug : { type_token: 'typeBug', primary_key: 'bug_id', api_key: 'bug' },
48
+ };
49
+
50
+ structure_scheme = {
51
+ custom_property_value_id: 'integer | require',
52
+ custom_property_id : 'integer | typeCustomProperty | require',
53
+ team_id : 'integer | require',
54
+ project_id : 'integer | require',
55
+ element_type : 'string | enum | require',
56
+ element_id : 'integer | require',
57
+ sort_order : 'integer | optional',
58
+ user_id : 'integer | optional',
59
+ created_at : 'timestamp | optional',
60
+ updated_at : 'timestamp | optional',
61
+ };
62
+
63
+ create_scheme = [
64
+ 'custom_property_id',
65
+ 'element_type',
66
+ 'element_id',
67
+ ];
68
+
69
+ available_enum_values = {
70
+ element_type: typeCustomPropertyValue.get_relation_type_values(),
71
+ };
72
+
73
+ enum_value_translate_matrix = typeCustomPropertyValue_i18n.enum_value_translate_matrix;
74
+
75
+ attribute_name_translate_matrix = typeCustomPropertyValue_i18n.attribute_name_translate_matrix;
76
+
77
+
78
+ static get_relation_type_values()
79
+ {
80
+ return Object.keys(typeCustomPropertyValue.relation_target_map);
81
+ }
82
+
83
+
84
+ static get_relation_target_map()
85
+ {
86
+ return typeCustomPropertyValue.relation_target_map;
87
+ }
88
+
89
+
90
+ /**
91
+ * @param {object|false|undefined} data
92
+ * @returns {typeCustomPropertyValue}
93
+ */
94
+ constructor(data = false)
95
+ {
96
+ super();
97
+
98
+ if (data && is_object(data))
99
+ {
100
+ _.mapObject(data, (value, key) =>
101
+ {
102
+ if (this.hasOwnProperty(key))
103
+ {
104
+ this[ key ] = value;
105
+ }
106
+ });
107
+ }
108
+
109
+ return this;
110
+ }
111
+
112
+
113
+ get_relation_target_meta()
114
+ {
115
+ return typeCustomPropertyValue.resolve_relation_target(this.element_type);
116
+ }
117
+ }