complexqa_frontend_core 1.23.1 → 1.25.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.
- package/package.json +1 -1
- package/publish/api/attachment_api.js +55 -0
- package/publish/api/file_app_api.js +22 -0
- package/publish/api/index.js +10 -0
- package/publish/api/tag/tag_color_api.js +16 -0
- package/publish/api/tag/tag_template_api.js +16 -0
- package/publish/api/tag_api.js +52 -0
- package/publish/api/tag_relation_api.js +57 -0
- package/publish/app_configuration/table/helpers/table_element_models.js +6 -0
- package/publish/app_configuration/table/sections/bug.js +7 -1
- package/publish/app_configuration/table/sections/tag.js +84 -0
- package/publish/app_configuration/table/sections/tag_relation.js +309 -0
- package/publish/app_configuration/table/sections/test_account.js +7 -1
- package/publish/app_configuration/table/sections/test_case.js +7 -1
- package/publish/app_configuration/table/sections/test_run.js +7 -1
- package/publish/app_configuration/table/sections/test_run_result.js +7 -1
- package/publish/app_configuration/table/sections/text_document.js +7 -1
- package/publish/app_configuration/table/table_configuration.js +4 -0
- package/publish/index.js +3 -0
- package/publish/services/FileAppService.js +67 -21
- package/publish/types/core/1_familyTestDocumentation.js +9 -1
- package/publish/types/element_translate/typeAttachment.i18n.js +201 -0
- package/publish/types/element_translate/typeBug.i18n.js +11 -0
- package/publish/types/element_translate/typeTag.i18n.js +69 -0
- package/publish/types/element_translate/typeTagRelation.i18n.js +74 -0
- package/publish/types/element_translate/typeTestAccount.i18n.js +11 -0
- package/publish/types/element_translate/typeTestCase.i18n.js +11 -0
- package/publish/types/element_translate/typeTestRun.i18n.js +11 -0
- package/publish/types/element_translate/typeTestRunResult.i18n.js +11 -0
- package/publish/types/element_translate/typeTextDocument.i18n.js +11 -0
- package/publish/types/family_elements/typeAttachment.js +119 -0
- package/publish/types/family_elements/typeBug.js +0 -2
- package/publish/types/family_elements/typeTag.js +84 -0
- package/publish/types/family_elements/typeTestAccount.js +2 -0
- package/publish/types/family_events/familyEvent.js +3 -0
- package/publish/types/family_files/typeFileScreenshot.js +2 -2
- package/publish/types/family_files/typeTextDocument.js +2 -0
- package/publish/types/family_relation/typeTagRelation.js +123 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { typeTagRelation } from '../../../types/family_relation/typeTagRelation.js';
|
|
2
|
+
import { typeTestCase } from '../../../types/family_elements/typeTestCase.js';
|
|
3
|
+
import { typeBug } from '../../../types/family_elements/typeBug.js';
|
|
4
|
+
import { typeTestRun } from '../../../types/family_elements/typeTestRun.js';
|
|
5
|
+
import { typeTestSuite } from '../../../types/family_elements/typeTestSuite.js';
|
|
6
|
+
import { typeTestAccount } from '../../../types/family_elements/typeTestAccount.js';
|
|
7
|
+
import { typeTestRunResult } from '../../../types/family_elements/typeTestRunResult.js';
|
|
8
|
+
import { typeTextDocument } from '../../../types/family_files/typeTextDocument.js';
|
|
9
|
+
import { typeExecutionContext } from '../../../types/family_context/typeExecutionContext.js';
|
|
10
|
+
import { UserService } from '../../../services/UserService.js';
|
|
11
|
+
import { createColumn, createGoToColumn } from '../helpers/column_factory.js';
|
|
12
|
+
import { get_execution_context_listing_field_specs } from '../helpers/execution_context_listing_fields.js';
|
|
13
|
+
import { createListingFor, registerSection } from '../helpers/section_registry.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Nested column helper: `element_id.<field>` with header from target element type.
|
|
17
|
+
*
|
|
18
|
+
* @param {typeTagRelation} relation_model
|
|
19
|
+
* @param {string} locale
|
|
20
|
+
* @param {string} header_element_type
|
|
21
|
+
* @param {string} field
|
|
22
|
+
* @param {object} [overrides]
|
|
23
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn}
|
|
24
|
+
*/
|
|
25
|
+
function elementColumn(relation_model, locale, header_element_type, field, overrides = {})
|
|
26
|
+
{
|
|
27
|
+
return createColumn(relation_model, locale, `element_id.${ field }`, {
|
|
28
|
+
header_field : overrides.header_field || field,
|
|
29
|
+
header_element_type: overrides.header_element_type || header_element_type,
|
|
30
|
+
is_editable : false,
|
|
31
|
+
...overrides,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Linked test cases on tag/details — same fields as test_case × listing (read-only).
|
|
38
|
+
*
|
|
39
|
+
* @param {string} locale
|
|
40
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
41
|
+
*/
|
|
42
|
+
function build_tag_relation_test_cases_columns(locale)
|
|
43
|
+
{
|
|
44
|
+
const relation_model = new typeTagRelation();
|
|
45
|
+
const test_case_model = new typeTestCase();
|
|
46
|
+
const col = (field, overrides = {}) =>
|
|
47
|
+
elementColumn(relation_model, locale, 'test_case', field, overrides);
|
|
48
|
+
|
|
49
|
+
return [
|
|
50
|
+
col('test_case_id', { width: '60', default_sort: 'desc' }),
|
|
51
|
+
col('test_case_title', { width: '480', is_required: true, is_title: true }),
|
|
52
|
+
col('assigned_to', { width: '220' }),
|
|
53
|
+
col('test_case_time_to_execute', { width: '80', is_required: true }),
|
|
54
|
+
col('test_case_complexity', { width: '80', is_required: true }),
|
|
55
|
+
col('test_case_importance', { width: '80', is_required: true }),
|
|
56
|
+
col('test_case_status', { width: '150', is_required: true }),
|
|
57
|
+
createGoToColumn(test_case_model, locale, { field: 'element_id' }),
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Linked bugs on tag/details — same fields as bug × listing (read-only, without tags).
|
|
64
|
+
*
|
|
65
|
+
* @param {string} locale
|
|
66
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
67
|
+
*/
|
|
68
|
+
function build_tag_relation_bugs_columns(locale)
|
|
69
|
+
{
|
|
70
|
+
const relation_model = new typeTagRelation();
|
|
71
|
+
const bug_model = new typeBug();
|
|
72
|
+
const col = (field, overrides = {}) =>
|
|
73
|
+
elementColumn(relation_model, locale, 'bug', field, overrides);
|
|
74
|
+
|
|
75
|
+
return [
|
|
76
|
+
col('bug_id', { width: '60', default_sort: 'desc' }),
|
|
77
|
+
col('bug_title', { width: '420', is_required: true, is_title: true }),
|
|
78
|
+
col('bug_status', { width: '150', is_required: true }),
|
|
79
|
+
col('bug_priority', { width: '130', is_required: true }),
|
|
80
|
+
col('bug_severity', { width: '130', is_required: true }),
|
|
81
|
+
col('bug_type', { width: '150', is_required: true }),
|
|
82
|
+
col('bug_resolution', { width: '150', is_required: true, is_hide: true }),
|
|
83
|
+
col('assigned_to', { width: '220', is_required: true }),
|
|
84
|
+
col('created_at', { width: '170', is_required: true }),
|
|
85
|
+
col('completed_at', { width: '170', is_required: true, is_hide: true }),
|
|
86
|
+
createGoToColumn(bug_model, locale, { field: 'element_id' }),
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Linked test runs on tag/details — same fields as test_run × listing (read-only, without tags).
|
|
93
|
+
*
|
|
94
|
+
* @param {string} locale
|
|
95
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
96
|
+
*/
|
|
97
|
+
function build_tag_relation_test_runs_columns(locale)
|
|
98
|
+
{
|
|
99
|
+
const relation_model = new typeTagRelation();
|
|
100
|
+
const test_run_model = new typeTestRun();
|
|
101
|
+
const col = (field, overrides = {}) =>
|
|
102
|
+
elementColumn(relation_model, locale, 'test_run', field, overrides);
|
|
103
|
+
|
|
104
|
+
return [
|
|
105
|
+
col('test_run_id', { width: '60', default_sort: 'desc' }),
|
|
106
|
+
col('test_run_name', { width: '480', is_required: true, is_title: true }),
|
|
107
|
+
col('test_run_description', { width: '480', is_required: true }),
|
|
108
|
+
col('assigned_to', { width: '220', is_required: true }),
|
|
109
|
+
col('test_run_status', { width: '150', is_required: true }),
|
|
110
|
+
col('created_at', { width: '170', is_required: true }),
|
|
111
|
+
col('completed_at', { width: '170', is_required: true }),
|
|
112
|
+
createGoToColumn(test_run_model, locale, { field: 'element_id' }),
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Linked test suites on tag/details.
|
|
119
|
+
*
|
|
120
|
+
* @param {string} locale
|
|
121
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
122
|
+
*/
|
|
123
|
+
function build_tag_relation_test_suites_columns(locale)
|
|
124
|
+
{
|
|
125
|
+
const relation_model = new typeTagRelation();
|
|
126
|
+
const test_suite_model = new typeTestSuite();
|
|
127
|
+
const col = (field, overrides = {}) =>
|
|
128
|
+
elementColumn(relation_model, locale, 'test_suite', field, overrides);
|
|
129
|
+
|
|
130
|
+
return [
|
|
131
|
+
col('test_suite_id', { width: '60', default_sort: 'desc' }),
|
|
132
|
+
col('test_suite_name', { width: '480', is_required: true, is_title: true }),
|
|
133
|
+
createGoToColumn(test_suite_model, locale, { field: 'element_id' }),
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Linked test accounts on tag/details — same fields as test_account × listing (read-only, without tags).
|
|
140
|
+
*
|
|
141
|
+
* @param {string} locale
|
|
142
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
143
|
+
*/
|
|
144
|
+
function build_tag_relation_test_accounts_columns(locale)
|
|
145
|
+
{
|
|
146
|
+
const relation_model = new typeTagRelation();
|
|
147
|
+
const test_account_model = new typeTestAccount();
|
|
148
|
+
const col = (field, overrides = {}) =>
|
|
149
|
+
elementColumn(relation_model, locale, 'test_account', field, overrides);
|
|
150
|
+
|
|
151
|
+
return [
|
|
152
|
+
col('test_account_id', { width: '60', default_sort: 'desc' }),
|
|
153
|
+
col('resource', { width: '480', is_required: true, is_title: true }),
|
|
154
|
+
col('login', { width: '480', is_required: true }),
|
|
155
|
+
col('password', { width: '480' }),
|
|
156
|
+
col('test_account_description', { width: '480' }),
|
|
157
|
+
col('created_at', { width: '170' }),
|
|
158
|
+
col('updated_at', { width: '170' }),
|
|
159
|
+
createGoToColumn(test_account_model, locale, { field: 'element_id' }),
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Linked test run results on tag/details — same fields as bug_relation × test_run_results.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} locale
|
|
168
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
169
|
+
*/
|
|
170
|
+
function build_tag_relation_test_run_results_columns(locale)
|
|
171
|
+
{
|
|
172
|
+
const relation_model = new typeTagRelation();
|
|
173
|
+
const result_model = new typeTestRunResult();
|
|
174
|
+
const col = (field, overrides = {}) =>
|
|
175
|
+
elementColumn(relation_model, locale, 'test_run_result', field, overrides);
|
|
176
|
+
|
|
177
|
+
return [
|
|
178
|
+
col('test_run_result_id', { width: '60', default_sort: 'desc' }),
|
|
179
|
+
col('assigned_to', { width: '220', is_required: true }),
|
|
180
|
+
col('created_at', { width: '170', is_required: true }),
|
|
181
|
+
col('updated_at', { width: '170', is_required: true }),
|
|
182
|
+
col('completed_at', { width: '170', is_required: true }),
|
|
183
|
+
col('test_result_status', { width: '150', is_required: true }),
|
|
184
|
+
createGoToColumn(result_model, locale, { field: 'element_id' }),
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Linked text documents on tag/details — same fields as text_document × listing (read-only, without tags).
|
|
191
|
+
*
|
|
192
|
+
* @param {string} locale
|
|
193
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
194
|
+
*/
|
|
195
|
+
function build_tag_relation_text_documents_columns(locale)
|
|
196
|
+
{
|
|
197
|
+
const relation_model = new typeTagRelation();
|
|
198
|
+
const text_document_model = new typeTextDocument();
|
|
199
|
+
const col = (field, overrides = {}) =>
|
|
200
|
+
elementColumn(relation_model, locale, 'text_document', field, overrides);
|
|
201
|
+
|
|
202
|
+
return [
|
|
203
|
+
col('text_document_id', { width: '60', default_sort: 'desc' }),
|
|
204
|
+
col('text_document_title', { width: '320', is_title: true }),
|
|
205
|
+
col('text_document_status', { width: '140' }),
|
|
206
|
+
col('text_document_folder_id', { width: '120' }),
|
|
207
|
+
col('created_at', { width: '170' }),
|
|
208
|
+
col('updated_at', { width: '170' }),
|
|
209
|
+
createGoToColumn(text_document_model, locale, { field: 'element_id' }),
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Linked execution contexts on tag/details.
|
|
216
|
+
*
|
|
217
|
+
* @param {string} locale
|
|
218
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
219
|
+
*/
|
|
220
|
+
function build_tag_relation_execution_contexts_columns(locale)
|
|
221
|
+
{
|
|
222
|
+
const relation_model = new typeTagRelation();
|
|
223
|
+
const context_model = new typeExecutionContext();
|
|
224
|
+
const col = (field, overrides = {}) =>
|
|
225
|
+
elementColumn(relation_model, locale, 'execution_context', field, overrides);
|
|
226
|
+
|
|
227
|
+
return [
|
|
228
|
+
...get_execution_context_listing_field_specs().map(({ field, overrides }) => col(field, overrides)),
|
|
229
|
+
createGoToColumn(context_model, locale, { field: 'element_id' }),
|
|
230
|
+
];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Tags attached to an element (hydrate tag_id).
|
|
236
|
+
*
|
|
237
|
+
* @param {string} locale
|
|
238
|
+
* @returns {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]}
|
|
239
|
+
*/
|
|
240
|
+
function build_element_tags_columns(locale)
|
|
241
|
+
{
|
|
242
|
+
const relation_model = new typeTagRelation();
|
|
243
|
+
const columns = [];
|
|
244
|
+
|
|
245
|
+
const tagColumn = (field, overrides = {}) => createColumn(relation_model, locale, `tag_id.${ field }`, {
|
|
246
|
+
header_field : field,
|
|
247
|
+
header_element_type: 'tag',
|
|
248
|
+
is_editable : false,
|
|
249
|
+
...overrides,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
columns.push(tagColumn('tag_id', { width: '60', default_sort: 'desc' }));
|
|
253
|
+
columns.push(tagColumn('name', {
|
|
254
|
+
width : '280',
|
|
255
|
+
is_required: true,
|
|
256
|
+
is_title : true,
|
|
257
|
+
}));
|
|
258
|
+
columns.push(tagColumn('tag_color_id', { width: '120' }));
|
|
259
|
+
|
|
260
|
+
return columns;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Секции `tag_relation` для tag/details tabs и attach на элементах.
|
|
266
|
+
*
|
|
267
|
+
* @param {Object} config
|
|
268
|
+
* @returns {void}
|
|
269
|
+
*/
|
|
270
|
+
export function bootstrap_tag_relation(config)
|
|
271
|
+
{
|
|
272
|
+
const locale = UserService.get_current_language();
|
|
273
|
+
|
|
274
|
+
registerSection(config, 'tag_relation', 'test_cases', build_tag_relation_test_cases_columns(locale), {
|
|
275
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
registerSection(config, 'tag_relation', 'bugs', build_tag_relation_bugs_columns(locale), {
|
|
279
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
registerSection(config, 'tag_relation', 'test_runs', build_tag_relation_test_runs_columns(locale), {
|
|
283
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
registerSection(config, 'tag_relation', 'test_suites', build_tag_relation_test_suites_columns(locale), {
|
|
287
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
registerSection(config, 'tag_relation', 'test_accounts', build_tag_relation_test_accounts_columns(locale), {
|
|
291
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
registerSection(config, 'tag_relation', 'test_run_results', build_tag_relation_test_run_results_columns(locale), {
|
|
295
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
registerSection(config, 'tag_relation', 'text_documents', build_tag_relation_text_documents_columns(locale), {
|
|
299
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
registerSection(config, 'tag_relation', 'execution_contexts', build_tag_relation_execution_contexts_columns(locale), {
|
|
303
|
+
for: createListingFor([ 'tag_id', 'element_type' ], { add: [ 'elements' ] }),
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
registerSection(config, 'tag_relation', 'element_tags', build_element_tags_columns(locale), {
|
|
307
|
+
for: createListingFor([ 'element_type', 'element_id' ], { add: [ 'tags' ] }),
|
|
308
|
+
});
|
|
309
|
+
}
|
|
@@ -12,6 +12,12 @@ function build_test_account_listing_columns(locale)
|
|
|
12
12
|
createPrimaryKeyColumn(model, locale),
|
|
13
13
|
createColumn(model, locale, 'resource', { width: '480', is_editable: true, is_required: true }),
|
|
14
14
|
createColumn(model, locale, 'login', { width: '480', is_editable: true, is_required: true }),
|
|
15
|
+
createColumn(model, locale, 'tags', {
|
|
16
|
+
width : '220',
|
|
17
|
+
is_editable: false,
|
|
18
|
+
is_sortable: false,
|
|
19
|
+
is_required: false,
|
|
20
|
+
}),
|
|
15
21
|
createColumn(model, locale, 'password', { width: '480', is_editable: true }),
|
|
16
22
|
createColumn(model, locale, 'test_account_description', { width: '480', is_editable: true }),
|
|
17
23
|
createColumn(model, locale, 'created_at', { width: '170' }),
|
|
@@ -67,7 +73,7 @@ export function bootstrap_test_account(config)
|
|
|
67
73
|
const locale = UserService.get_current_language();
|
|
68
74
|
|
|
69
75
|
registerSection(config, 'test_account', 'listing', build_test_account_listing_columns(locale), {
|
|
70
|
-
for: createListingFor([ 'project_id' ]),
|
|
76
|
+
for: createListingFor([ 'project_id' ], { add: [ 'tags' ] }),
|
|
71
77
|
});
|
|
72
78
|
|
|
73
79
|
registerSection(config, 'test_account', 'details', build_test_account_details_columns(locale));
|
|
@@ -21,6 +21,12 @@ function build_test_case_listing_columns(locale, { include_select = true, includ
|
|
|
21
21
|
is_title : true,
|
|
22
22
|
}));
|
|
23
23
|
columns.push(createColumn(model, locale, 'assigned_to', { width: '220', is_editable: true }));
|
|
24
|
+
columns.push(createColumn(model, locale, 'tags', {
|
|
25
|
+
width : '220',
|
|
26
|
+
is_editable: false,
|
|
27
|
+
is_sortable: false,
|
|
28
|
+
is_required: false,
|
|
29
|
+
}));
|
|
24
30
|
columns.push(createColumn(model, locale, 'test_case_time_to_execute', { width: '80', is_editable: true, is_required: true }));
|
|
25
31
|
columns.push(createColumn(model, locale, 'test_case_complexity', { width: '80', is_editable: true, is_required: true }));
|
|
26
32
|
columns.push(createColumn(model, locale, 'test_case_importance', { width: '80', is_editable: true, is_required: true }));
|
|
@@ -59,7 +65,7 @@ export function bootstrap_test_case(config)
|
|
|
59
65
|
const locale = UserService.get_current_language();
|
|
60
66
|
|
|
61
67
|
registerSection(config, 'test_case', 'listing', build_test_case_listing_columns(locale), {
|
|
62
|
-
for: createListingFor([ 'project_id', 'test_suite_id' ]),
|
|
68
|
+
for: createListingFor([ 'project_id', 'test_suite_id' ], { add: [ 'tags' ] }),
|
|
63
69
|
});
|
|
64
70
|
|
|
65
71
|
registerSection(config, 'test_case', 'todo', build_test_case_todo_columns(locale), {
|
|
@@ -25,6 +25,12 @@ function build_test_run_listing_columns(locale, { include_select = true } = {})
|
|
|
25
25
|
is_required : true,
|
|
26
26
|
}));
|
|
27
27
|
columns.push(createColumn(model, locale, 'assigned_to', { width: '220', is_editable: true, is_required: true }));
|
|
28
|
+
columns.push(createColumn(model, locale, 'tags', {
|
|
29
|
+
width : '220',
|
|
30
|
+
is_editable: false,
|
|
31
|
+
is_sortable: false,
|
|
32
|
+
is_required: false,
|
|
33
|
+
}));
|
|
28
34
|
columns.push(createColumn(model, locale, 'test_run_status', { width: '150', is_editable: true, is_required: true }));
|
|
29
35
|
columns.push(createColumn(model, locale, 'created_at', { width: '170', is_required: true }));
|
|
30
36
|
columns.push(createColumn(model, locale, 'completed_at', { width: '170', is_required: true }));
|
|
@@ -70,7 +76,7 @@ export function bootstrap_test_run(config)
|
|
|
70
76
|
const locale = UserService.get_current_language();
|
|
71
77
|
|
|
72
78
|
registerSection(config, 'test_run', 'listing', build_test_run_listing_columns(locale), {
|
|
73
|
-
for: createListingFor([ 'project_id' ]),
|
|
79
|
+
for: createListingFor([ 'project_id' ], { add: [ 'tags' ] }),
|
|
74
80
|
});
|
|
75
81
|
|
|
76
82
|
registerSection(config, 'test_run', 'todo', build_test_run_todo_columns(locale), {
|
|
@@ -22,6 +22,12 @@ function build_test_run_result_listing_columns(locale, { include_select = true }
|
|
|
22
22
|
is_required : true,
|
|
23
23
|
}));
|
|
24
24
|
columns.push(createColumn(model, locale, 'assigned_to', { width: '220', is_editable: true, is_required: true }));
|
|
25
|
+
columns.push(createColumn(model, locale, 'tags', {
|
|
26
|
+
width : '220',
|
|
27
|
+
is_editable: false,
|
|
28
|
+
is_sortable: false,
|
|
29
|
+
is_required: false,
|
|
30
|
+
}));
|
|
25
31
|
columns.push(createColumn(model, locale, 'created_at', { width: '170', is_required: true }));
|
|
26
32
|
columns.push(createColumn(model, locale, 'updated_at', { width: '170', is_required: true }));
|
|
27
33
|
columns.push(createColumn(model, locale, 'completed_at', { width: '170', is_required: true }));
|
|
@@ -128,7 +134,7 @@ export function bootstrap_test_run_result(config)
|
|
|
128
134
|
const locale = UserService.get_current_language();
|
|
129
135
|
|
|
130
136
|
registerSection(config, 'test_run_result', 'listing', build_test_run_result_listing_columns(locale), {
|
|
131
|
-
for: createListingFor([ 'project_id', 'test_case_id', 'test_run_id' ]),
|
|
137
|
+
for: createListingFor([ 'project_id', 'test_case_id', 'test_run_id' ], { add: [ 'tags' ] }),
|
|
132
138
|
});
|
|
133
139
|
|
|
134
140
|
registerSection(config, 'test_run_result', 'picker', build_test_run_result_picker_columns(locale), {
|
|
@@ -10,6 +10,12 @@ function build_text_document_listing_columns(locale)
|
|
|
10
10
|
return [
|
|
11
11
|
createPrimaryKeyColumn(model, locale),
|
|
12
12
|
createColumn(model, locale, 'text_document_title', { width: '320', is_editable: true, is_title: true }),
|
|
13
|
+
createColumn(model, locale, 'tags', {
|
|
14
|
+
width : '220',
|
|
15
|
+
is_editable: false,
|
|
16
|
+
is_sortable: false,
|
|
17
|
+
is_required: false,
|
|
18
|
+
}),
|
|
13
19
|
createColumn(model, locale, 'text_document_status', { width: '140', is_editable: true }),
|
|
14
20
|
createColumn(model, locale, 'text_document_folder_id', { width: '120' }),
|
|
15
21
|
createColumn(model, locale, 'created_at', { width: '170' }),
|
|
@@ -26,6 +32,6 @@ export function bootstrap_text_document(config)
|
|
|
26
32
|
const locale = UserService.get_current_language();
|
|
27
33
|
|
|
28
34
|
registerSection(config, 'text_document', 'listing', build_text_document_listing_columns(locale), {
|
|
29
|
-
for: createListingFor([ 'project_id', 'text_document_folder_id' ]),
|
|
35
|
+
for: createListingFor([ 'project_id', 'text_document_folder_id' ], { add: [ 'tags' ] }),
|
|
30
36
|
});
|
|
31
37
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { abstractAppConfiguration } from '../abstract_app_configuration.js';
|
|
2
2
|
import { bootstrap_bug } from './sections/bug.js';
|
|
3
3
|
import { bootstrap_bug_relation } from './sections/bug_relation.js';
|
|
4
|
+
import { bootstrap_tag } from './sections/tag.js';
|
|
5
|
+
import { bootstrap_tag_relation } from './sections/tag_relation.js';
|
|
4
6
|
import { bootstrap_test_case } from './sections/test_case.js';
|
|
5
7
|
import { bootstrap_test_case_step } from './sections/test_case_step.js';
|
|
6
8
|
import { bootstrap_test_run } from './sections/test_run.js';
|
|
@@ -111,6 +113,8 @@ export class TableConfiguration extends abstractAppConfiguration
|
|
|
111
113
|
|
|
112
114
|
bootstrap_bug(this.config);
|
|
113
115
|
bootstrap_bug_relation(this.config);
|
|
116
|
+
bootstrap_tag(this.config);
|
|
117
|
+
bootstrap_tag_relation(this.config);
|
|
114
118
|
bootstrap_test_case(this.config);
|
|
115
119
|
bootstrap_test_case_step(this.config);
|
|
116
120
|
bootstrap_test_run(this.config);
|
package/publish/index.js
CHANGED
|
@@ -16,9 +16,12 @@ export { typeTestRun } from './types/family_elements/typeTestRun.js'
|
|
|
16
16
|
export { typeTestRunResult } from './types/family_elements/typeTestRunResult.js'
|
|
17
17
|
export { typeTestAccount } from './types/family_elements/typeTestAccount.js'
|
|
18
18
|
export {typeBug} from './types/family_elements/typeBug.js';
|
|
19
|
+
export { typeTag } from './types/family_elements/typeTag.js';
|
|
20
|
+
export { typeAttachment } from './types/family_elements/typeAttachment.js';
|
|
19
21
|
|
|
20
22
|
export { familyRelation } from './types/core/1_familyRelation.js';
|
|
21
23
|
export { typeBugRelation } from './types/family_relation/typeBugRelation.js';
|
|
24
|
+
export { typeTagRelation } from './types/family_relation/typeTagRelation.js';
|
|
22
25
|
|
|
23
26
|
export { familyContext } from './types/core/1_familyContext.js';
|
|
24
27
|
export { typeBrowserContext } from './types/family_context/typeBrowserContext.js';
|
|
@@ -75,13 +75,53 @@ export class FileAppService extends abstractService
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Whether entity_type is present for File App binding.
|
|
80
|
+
* Empty / null / 0 → omit from token and upload init.
|
|
81
|
+
*
|
|
82
|
+
* @param {*} value
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
static #has_entity_type(value)
|
|
86
|
+
{
|
|
87
|
+
if (value === null || value === undefined)
|
|
88
|
+
{
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const s = String(value).trim();
|
|
93
|
+
|
|
94
|
+
return s !== '' && s !== '0';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Whether entity_id is present for File App binding.
|
|
100
|
+
* Empty / null / 0 / NaN → omit from token and upload init.
|
|
101
|
+
*
|
|
102
|
+
* @param {*} value
|
|
103
|
+
* @returns {boolean}
|
|
104
|
+
*/
|
|
105
|
+
static #has_entity_id(value)
|
|
106
|
+
{
|
|
107
|
+
if (value === null || value === undefined || value === '')
|
|
108
|
+
{
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const n = Number(value);
|
|
113
|
+
|
|
114
|
+
return !Number.isNaN(n) && n !== 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
78
118
|
/**
|
|
79
119
|
* Upload browser File/Blob to File App (token via Main App bridge).
|
|
80
120
|
*
|
|
81
121
|
* @param {object} payload
|
|
82
122
|
* @param {File|Blob} payload.file
|
|
83
|
-
* @param {string} payload.entity_type
|
|
84
|
-
* @param {number} payload.entity_id
|
|
123
|
+
* @param {string} [payload.entity_type] — omit / null / 0 for unbound upload (attachments)
|
|
124
|
+
* @param {number} [payload.entity_id] — omit / null / 0 for unbound upload (attachments)
|
|
85
125
|
* @param {string} payload.category
|
|
86
126
|
* @param {string} [payload.original_name]
|
|
87
127
|
* @param {string} [payload.file_uuid] — re-upload / new version for existing file
|
|
@@ -97,20 +137,24 @@ export class FileAppService extends abstractService
|
|
|
97
137
|
throw new Error('FileAppService.upload_file: file is required');
|
|
98
138
|
}
|
|
99
139
|
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
140
|
+
const has_entity_type = FileAppService.#has_entity_type(payload.entity_type);
|
|
141
|
+
const has_entity_id = FileAppService.#has_entity_id(payload.entity_id);
|
|
142
|
+
const entity_type = has_entity_type ? String(payload.entity_type) : undefined;
|
|
143
|
+
const entity_id = has_entity_id ? Number(payload.entity_id) : undefined;
|
|
144
|
+
const category = String(payload.category || '');
|
|
145
|
+
const mime_type = file.type || 'application/octet-stream';
|
|
146
|
+
const size_bytes = Number(file.size || 0);
|
|
147
|
+
const original_name = String(payload.original_name || file.name || 'upload');
|
|
148
|
+
const api = FileAppService.#get_api_service();
|
|
149
|
+
|
|
150
|
+
const token_payload = {
|
|
151
|
+
scopes: [ 'file:upload', 'file:read' ],
|
|
112
152
|
size_bytes,
|
|
113
|
-
|
|
153
|
+
...(has_entity_type ? { entity_type } : {}),
|
|
154
|
+
...(has_entity_id ? { entity_id } : {}),
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const token_wrap = await api.file_app.issue_access_token(token_payload);
|
|
114
158
|
|
|
115
159
|
const token_data = await token_wrap?.response;
|
|
116
160
|
|
|
@@ -130,15 +174,17 @@ export class FileAppService extends abstractService
|
|
|
130
174
|
throw new ApiException({ message: 'File App access token was not issued' });
|
|
131
175
|
}
|
|
132
176
|
|
|
133
|
-
const
|
|
177
|
+
const init_payload = {
|
|
134
178
|
category,
|
|
135
179
|
mime_type,
|
|
136
180
|
size_bytes,
|
|
137
181
|
original_name,
|
|
138
|
-
entity_type,
|
|
139
|
-
entity_id,
|
|
182
|
+
...(has_entity_type ? { entity_type } : {}),
|
|
183
|
+
...(has_entity_id ? { entity_id } : {}),
|
|
140
184
|
...(payload.file_uuid ? { file_uuid: String(payload.file_uuid) } : {}),
|
|
141
|
-
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const init_response = await axios.post(`${ file_app_url }/api/v1/uploads`, init_payload, {
|
|
142
188
|
headers: {
|
|
143
189
|
Authorization: `Bearer ${ access_token }`,
|
|
144
190
|
Accept : 'application/json',
|
|
@@ -183,8 +229,8 @@ export class FileAppService extends abstractService
|
|
|
183
229
|
const wire = {
|
|
184
230
|
...confirmed,
|
|
185
231
|
category : confirmed.category || category,
|
|
186
|
-
entity_type: confirmed.entity_type
|
|
187
|
-
entity_id : confirmed.entity_id ?? entity_id,
|
|
232
|
+
entity_type: confirmed.entity_type ?? entity_type ?? null,
|
|
233
|
+
entity_id : confirmed.entity_id ?? entity_id ?? null,
|
|
188
234
|
mime_type : confirmed.mime_type || mime_type,
|
|
189
235
|
};
|
|
190
236
|
|
|
@@ -8,6 +8,14 @@ import { familyGeneralElement } from "./0_familyGeneralElement.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export class familyTestDocumentation extends familyGeneralElement
|
|
10
10
|
{
|
|
11
|
+
/**
|
|
12
|
+
* Hydrated on element search via options.add: ['tags'].
|
|
13
|
+
* Catalog entities (e.g. typeTag) leave this unset.
|
|
14
|
+
*
|
|
15
|
+
* @type {Array<object>|undefined}
|
|
16
|
+
*/
|
|
17
|
+
tags;
|
|
18
|
+
|
|
11
19
|
|
|
12
20
|
/**
|
|
13
21
|
*
|
|
@@ -18,4 +26,4 @@ export class familyTestDocumentation extends familyGeneralElement
|
|
|
18
26
|
super();
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
}
|
|
29
|
+
}
|