complexqa_frontend_core 1.17.11 → 1.17.13

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "complexqa_frontend_core",
3
- "version": "1.17.11",
3
+ "version": "1.17.13",
4
4
  "description": "core of web ",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,5 +1,9 @@
1
1
  import { typeTableColumn } from '../../../types/family_service/typeTableColumn.js';
2
2
 
3
+ /**
4
+ * Значения по умолчанию для data-колонок.
5
+ * @type {Partial<import('../../../types/family_service/typeTableColumn.js').typeTableColumn>}
6
+ */
3
7
  const COLUMN_DEFAULTS = {
4
8
  width : '120',
5
9
  sort_order : '1',
@@ -15,13 +19,42 @@ const COLUMN_DEFAULTS = {
15
19
  header_element_type: false,
16
20
  };
17
21
 
22
+ /**
23
+ * @typedef {Object} ColumnOverrides
24
+ * @property {string} [header_field] Атрибут для перевода заголовка (по умолчанию = `field`).
25
+ * @property {import('../../../types/core/0_familyGeneralElement.js').familyGeneralElement} [header_model]
26
+ * Модель перевода при bootstrap (по умолчанию = `model`). Итоговый заголовок — в `get_config(lang)`.
27
+ * @property {string} [header_name] Явный заголовок; обычно не нужен — достаточно `header_field`.
28
+ * @property {string|false} [header_element_type] Ключ модели перевода, если ≠ element_type секции.
29
+ * @property {string|number} [width]
30
+ * @property {string|number} [sort_order]
31
+ * @property {boolean} [is_sortable]
32
+ * @property {boolean} [is_filter]
33
+ * @property {boolean} [is_hide]
34
+ * @property {boolean} [is_editable]
35
+ * @property {boolean} [is_required]
36
+ * @property {boolean} [is_title]
37
+ * @property {''|'asc'|'desc'} [default_sort]
38
+ * @property {string} [cell_classes]
39
+ */
40
+
18
41
 
19
42
  /**
20
- * @param {familyGeneralElement} model
21
- * @param {string} locale
22
- * @param {string} field
23
- * @param {object} overrides
43
+ * Data-колонка с переводимым заголовком и сохранённым `header_field`.
44
+ *
45
+ * @param {import('../../../types/core/0_familyGeneralElement.js').familyGeneralElement} model
46
+ * Модель сущности секции.
47
+ * @param {string} locale Локаль bootstrap (для первичного `header_name`; актуальная — в `get_config`).
48
+ * @param {string} field Поле строки (`test_case_status`, `user_id.first_name`, …).
49
+ * @param {ColumnOverrides} [overrides={}]
24
50
  * @returns {typeTableColumn}
51
+ *
52
+ * @example
53
+ * createColumn(model, locale, 'test_case_id.test_case_title', {
54
+ * header_field: 'test_case_title',
55
+ * header_element_type: 'test_case',
56
+ * width: '480',
57
+ * });
25
58
  */
26
59
  export function createColumn(model, locale, field, overrides = {})
27
60
  {
@@ -30,6 +63,7 @@ export function createColumn(model, locale, field, overrides = {})
30
63
 
31
64
  return new typeTableColumn({
32
65
  ...COLUMN_DEFAULTS,
66
+ header_field,
33
67
  header_name: overrides.header_name ?? header_model.get_attribute_name_translate(header_field, locale),
34
68
  field,
35
69
  ...overrides,
@@ -38,9 +72,10 @@ export function createColumn(model, locale, field, overrides = {})
38
72
 
39
73
 
40
74
  /**
41
- * @param {familyGeneralElement} model
42
- * @param {string} locale
43
- * @param {object} overrides
75
+ * Колонка множественного выбора строк (`column_kind: row_select`).
76
+ * Без `header_field` — не локализуется. В web_app: pinned left, чекбоксы.
77
+ *
78
+ * @param {Partial<typeTableColumn>} [overrides={}]
44
79
  * @returns {typeTableColumn}
45
80
  */
46
81
  export function createRowSelectColumn(overrides = {})
@@ -60,9 +95,12 @@ export function createRowSelectColumn(overrides = {})
60
95
 
61
96
 
62
97
  /**
63
- * @param {familyGeneralElement} model
64
- * @param {string} locale
65
- * @param {object} overrides
98
+ * Колонка перехода к деталям (`column_kind: goto`).
99
+ * Заголовок в UI — через `translateGoToHeader` в web_app, не через ядро.
100
+ *
101
+ * @param {import('../../../types/core/0_familyGeneralElement.js').familyGeneralElement} model
102
+ * @param {string} locale Не используется; сохранён для единообразия API фабрик.
103
+ * @param {ColumnOverrides} [overrides={}]
66
104
  * @returns {typeTableColumn}
67
105
  */
68
106
  export function createGoToColumn(model, locale, overrides = {})
@@ -84,9 +122,11 @@ export function createGoToColumn(model, locale, overrides = {})
84
122
 
85
123
 
86
124
  /**
87
- * @param {familyGeneralElement} model
125
+ * Колонка primary key (часто скрытая в listing, видимая в todo).
126
+ *
127
+ * @param {import('../../../types/core/0_familyGeneralElement.js').familyGeneralElement} model
88
128
  * @param {string} locale
89
- * @param {object} overrides
129
+ * @param {ColumnOverrides} [overrides={}]
90
130
  * @returns {typeTableColumn}
91
131
  */
92
132
  export function createPrimaryKeyColumn(model, locale, overrides = {})
@@ -103,10 +143,12 @@ export function createPrimaryKeyColumn(model, locale, overrides = {})
103
143
 
104
144
 
105
145
  /**
106
- * @param {familyGeneralElement} model
146
+ * Колонка для таблиц details: без сортировки и фильтра ag-grid.
147
+ *
148
+ * @param {import('../../../types/core/0_familyGeneralElement.js').familyGeneralElement} model
107
149
  * @param {string} locale
108
150
  * @param {string} field
109
- * @param {object} overrides
151
+ * @param {ColumnOverrides} [overrides={}]
110
152
  * @returns {typeTableColumn}
111
153
  */
112
154
  export function createDetailsColumn(model, locale, field, overrides = {})
@@ -0,0 +1,76 @@
1
+ import { typeTableColumn } from '../../../types/family_service/typeTableColumn.js';
2
+ import { typeTableConfiguration } from '../../../types/family_service/typeTableConfiguration.js';
3
+ import { TABLE_ELEMENT_MODELS } from './table_element_models.js';
4
+
5
+ /**
6
+ * Применяет локаль к заголовку одной data-колонки.
7
+ *
8
+ * Колонки без `header_field` (ручные, goto, row_select, copy) возвращаются без изменений.
9
+ * Модель перевода: `TABLE_ELEMENT_MODELS[header_element_type || element_type]`.
10
+ *
11
+ * @param {typeTableColumn} column
12
+ * @param {string} element_type Ключ сущности секции (`test_case`, `bug`, …).
13
+ * @param {string} lang Код локали (`en`, `ru`, …).
14
+ * @returns {typeTableColumn} Новый экземпляр с обновлённым `header_name` или исходная колонка.
15
+ */
16
+ export function localizeTableColumn(column, element_type, lang)
17
+ {
18
+ if (column.column_kind !== 'data' || !column.header_field)
19
+ {
20
+ return column;
21
+ }
22
+
23
+ const model_key = column.header_element_type || element_type;
24
+ const ModelClass = TABLE_ELEMENT_MODELS[ model_key ];
25
+
26
+ if (!ModelClass)
27
+ {
28
+ return column;
29
+ }
30
+
31
+ const model = new ModelClass();
32
+ const header_name = model.get_attribute_name_translate(column.header_field, lang);
33
+
34
+ return new typeTableColumn({
35
+ header_name : header_name,
36
+ field : column.field,
37
+ width : column.width,
38
+ sort_order : column.sort_order,
39
+ cell_classes : column.cell_classes,
40
+ default_sort : column.default_sort,
41
+ is_sortable : column.is_sortable,
42
+ is_filter : column.is_filter,
43
+ is_hide : column.is_hide,
44
+ is_editable : column.is_editable,
45
+ column_kind : column.column_kind,
46
+ is_required : column.is_required,
47
+ is_title : column.is_title,
48
+ header_element_type : column.header_element_type,
49
+ header_field : column.header_field,
50
+ });
51
+ }
52
+
53
+
54
+ /**
55
+ * Возвращает копию секции с локализованными заголовками всех data-колонок.
56
+ *
57
+ * Вызывается из `TableConfiguration.get_config` — не мутирует кеш bootstrap.
58
+ *
59
+ * @param {{ config: typeTableConfiguration }} section Зарегистрированная секция из `static.config`.
60
+ * @param {string} element_type
61
+ * @param {string} lang
62
+ * @returns {{ config: typeTableConfiguration }}
63
+ */
64
+ export function localizeTableSection(section, element_type, lang)
65
+ {
66
+ const config = section.config;
67
+
68
+ return {
69
+ config: new typeTableConfiguration({
70
+ columns : config.columns.map((column) => localizeTableColumn(column, element_type, lang)),
71
+ for : config.for,
72
+ contained_element_type : config.contained_element_type,
73
+ documentation : config.documentation,
74
+ }),
75
+ };
76
+ }
@@ -2,13 +2,27 @@ import { typeTableConfiguration } from '../../../types/family_service/typeTableC
2
2
  import { typeFOR } from '../../../types/family_service/typeFOR.js';
3
3
  import { typeFilter } from '../../../types/family_service/typeFilter.js';
4
4
 
5
+ /**
6
+ * @typedef {Object} RegisterSectionOptions
7
+ * @property {typeFOR|false} [for=false] Шаблон поиска для листинга.
8
+ * @property {string|false} [contained_element_type=false] Контекст вложенной сущности.
9
+ * @property {{ description: (string|false), link: (string|false) }} [documentation]
10
+ */
5
11
 
6
12
  /**
7
- * @param {object} config
8
- * @param {string} element_type
9
- * @param {string} section
10
- * @param {typeTableColumn[]} columns
11
- * @param {object} options
13
+ * Регистрирует секцию таблицы в реестре `TableConfiguration.config`.
14
+ *
15
+ * @param {Object<string, Object<string, { config: typeTableConfiguration }>>} config Ссылка на `TableConfiguration.config`.
16
+ * @param {string} element_type Ключ сущности.
17
+ * @param {string} section Имя секции (`listing`, `todo`, `details`, …).
18
+ * @param {import('../../../types/family_service/typeTableColumn.js').typeTableColumn[]} columns
19
+ * @param {RegisterSectionOptions} [options={}]
20
+ * @returns {void}
21
+ *
22
+ * @example
23
+ * registerSection(config, 'bug', 'listing', build_bug_listing_columns(locale), {
24
+ * for: createListingFor(['project_id']),
25
+ * });
12
26
  */
13
27
  export function registerSection(config, element_type, section, columns, options = {})
14
28
  {
@@ -31,8 +45,10 @@ export function registerSection(config, element_type, section, columns, options
31
45
 
32
46
 
33
47
  /**
34
- * @param {string} attribute
35
- * @returns {typeFilter}
48
+ * Фильтр-заготовка для runtime-подстановки значения в web_app.
49
+ *
50
+ * @param {string} attribute Имя атрибута (`project_id`, `test_case_id`, …).
51
+ * @returns {typeFilter} `operator: EQUAL`, `value: false` до гидратации.
36
52
  */
37
53
  export function createRuntimeFilter(attribute)
38
54
  {
@@ -45,9 +61,14 @@ export function createRuntimeFilter(attribute)
45
61
 
46
62
 
47
63
  /**
48
- * @param {string[]} filter_attributes
49
- * @param {object|false} for_options
64
+ * Строит шаблон `typeFOR` для листинговых таблиц.
65
+ *
66
+ * @param {string[]} [filter_attributes=['project_id']] Атрибуты, которые web_app заполнит из `filterValues`.
67
+ * @param {Object<string, *>|false} [for_options=false] Доп. опции API (`add: ['users']` и т.д.).
50
68
  * @returns {typeFOR}
69
+ *
70
+ * @example
71
+ * createListingFor(['project_id', 'test_case_id'], { add: ['users'] });
51
72
  */
52
73
  export function createListingFor(filter_attributes = [ 'project_id' ], for_options = false)
53
74
  {
@@ -0,0 +1,34 @@
1
+ import { typeTestCase } from '../../../types/family_elements/typeTestCase.js';
2
+ import { typeProject } from '../../../types/family_elements/typeProject.js';
3
+ import { typeTestRun } from '../../../types/family_elements/typeTestRun.js';
4
+ import { typeBug } from '../../../types/family_elements/typeBug.js';
5
+ import { typeTestRunResult } from '../../../types/family_elements/typeTestRunResult.js';
6
+ import { typeTestAccount } from '../../../types/family_elements/typeTestAccount.js';
7
+ import { typeTeamMember } from '../../../types/family_elements/typeTeamMember.js';
8
+ import { typeTestCaseStep } from '../../../types/family_elements/typeTestCaseStep.js';
9
+ import { typeUser } from '../../../types/family_elements/typeUser.js';
10
+ import { typeTeam } from '../../../types/family_elements/typeTeam.js';
11
+
12
+ /**
13
+ * Реестр классов моделей по ключу `element_type`.
14
+ *
15
+ * Используется для:
16
+ * - `TableBaseConfig.getRowNodeId` — primary key строки;
17
+ * - `localizeTableColumn` — `get_attribute_name_translate(header_field, lang)`.
18
+ *
19
+ * При добавлении новой таблицы сущности — зарегистрировать класс здесь.
20
+ *
21
+ * @type {Object<string, typeof import('../../../types/core/0_familyGeneralElement.js').familyGeneralElement>}
22
+ */
23
+ export const TABLE_ELEMENT_MODELS = {
24
+ test_case : typeTestCase,
25
+ project : typeProject,
26
+ test_run : typeTestRun,
27
+ bug : typeBug,
28
+ test_run_result: typeTestRunResult,
29
+ test_account : typeTestAccount,
30
+ team_member : typeTeamMember,
31
+ test_case_step : typeTestCaseStep,
32
+ user : typeUser,
33
+ team : typeTeam,
34
+ };
@@ -85,6 +85,12 @@ function build_bug_details_columns(locale)
85
85
  }
86
86
 
87
87
 
88
+ /**
89
+ * Секции `bug`: `listing`, `todo`, `details`.
90
+ *
91
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
92
+ * @returns {void}
93
+ */
88
94
  export function bootstrap_bug(config)
89
95
  {
90
96
  const locale = UserService.get_current_language();
@@ -50,6 +50,12 @@ function build_project_todo_column(locale)
50
50
  }
51
51
 
52
52
 
53
+ /**
54
+ * Секции `project`: `domains` (ручные колонки без перевода), `todo_column`.
55
+ *
56
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
57
+ * @returns {void}
58
+ */
53
59
  export function bootstrap_project(config)
54
60
  {
55
61
  const locale = UserService.get_current_language();
@@ -33,6 +33,12 @@ function build_team_total_statistic_columns(locale)
33
33
  }
34
34
 
35
35
 
36
+ /**
37
+ * Секции `team`: `profile`; `team_total_statistic`: `details`.
38
+ *
39
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
40
+ * @returns {void}
41
+ */
36
42
  export function bootstrap_team(config)
37
43
  {
38
44
  const locale = UserService.get_current_language();
@@ -1,5 +1,4 @@
1
1
  import { typeTeamMember } from '../../../types/family_elements/typeTeamMember.js';
2
- import { typeUser } from '../../../types/family_elements/typeUser.js';
3
2
  import { UserService } from '../../../services/UserService.js';
4
3
  import { createColumn } from '../helpers/column_factory.js';
5
4
  import { createListingFor, registerSection } from '../helpers/section_registry.js';
@@ -7,29 +6,26 @@ import { createListingFor, registerSection } from '../helpers/section_registry.j
7
6
  function build_team_member_listing_columns(locale)
8
7
  {
9
8
  const model = new typeTeamMember();
10
- const user_model = new typeUser();
11
9
 
12
10
  return [
13
11
  createColumn(model, locale, 'user_id.first_name', {
14
- header_name : user_model.get_attribute_name_translate('first_name', locale),
12
+ header_field: 'first_name',
15
13
  width : '200',
16
14
  is_filter : false,
17
15
  is_editable : false,
18
- header_element_type: 'user',
19
16
  }),
20
17
  createColumn(model, locale, 'user_id.last_name', {
21
- header_name : user_model.get_attribute_name_translate('last_name', locale),
18
+ header_field: 'last_name',
22
19
  width : '200',
23
20
  is_filter : false,
24
21
  is_editable : false,
25
- header_element_type: 'user',
26
22
  }),
27
23
  createColumn(model, locale, 'user_id.email', {
28
- header_name : user_model.get_attribute_name_translate('email', locale),
29
- width : '200',
30
- is_filter : false,
31
- is_editable : false,
32
- header_element_type: 'user',
24
+ header_field : 'email',
25
+ header_element_type : 'user',
26
+ width : '200',
27
+ is_filter : false,
28
+ is_editable : false,
33
29
  }),
34
30
  createColumn(model, locale, 'team_member_status', { width: '160', is_filter: false, is_editable: true }),
35
31
  createColumn(model, locale, 'member_role', { width: '200', is_filter: false, is_editable: true }),
@@ -37,6 +33,12 @@ function build_team_member_listing_columns(locale)
37
33
  }
38
34
 
39
35
 
36
+ /**
37
+ * Секция `team_member`: `listing`.
38
+ *
39
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
40
+ * @returns {void}
41
+ */
40
42
  export function bootstrap_team_member(config)
41
43
  {
42
44
  const locale = UserService.get_current_language();
@@ -56,6 +56,12 @@ function build_test_account_details_columns(locale)
56
56
  }
57
57
 
58
58
 
59
+ /**
60
+ * Секции `test_account`: `listing`, `details` (в details — колонка `copy`).
61
+ *
62
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
63
+ * @returns {void}
64
+ */
59
65
  export function bootstrap_test_account(config)
60
66
  {
61
67
  const locale = UserService.get_current_language();
@@ -48,6 +48,12 @@ function build_test_case_todo_columns(locale)
48
48
  }
49
49
 
50
50
 
51
+ /**
52
+ * Секции `test_case`: `listing`, `todo`, `picker`.
53
+ *
54
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
55
+ * @returns {void}
56
+ */
51
57
  export function bootstrap_test_case(config)
52
58
  {
53
59
  const locale = UserService.get_current_language();
@@ -45,6 +45,12 @@ function build_test_case_presteps_columns(locale)
45
45
  return build_test_case_step_shared_columns(locale);
46
46
  }
47
47
 
48
+ /**
49
+ * Секции `test_case_step`: `steps`, `presteps` (шаги и престепы тест-кейса).
50
+ *
51
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
52
+ * @returns {void}
53
+ */
48
54
  export function bootstrap_test_case_step(config)
49
55
  {
50
56
  const locale = UserService.get_current_language();
@@ -59,6 +59,12 @@ function build_test_run_todo_columns(locale)
59
59
  }
60
60
 
61
61
 
62
+ /**
63
+ * Секции `test_run`: `listing`, `todo`.
64
+ *
65
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
66
+ * @returns {void}
67
+ */
62
68
  export function bootstrap_test_run(config)
63
69
  {
64
70
  const locale = UserService.get_current_language();
@@ -1,5 +1,4 @@
1
1
  import { typeTestRunResult } from '../../../types/family_elements/typeTestRunResult.js';
2
- import { typeTestCase } from '../../../types/family_elements/typeTestCase.js';
3
2
  import { UserService } from '../../../services/UserService.js';
4
3
  import { createColumn, createGoToColumn, createPrimaryKeyColumn, createRowSelectColumn } from '../helpers/column_factory.js';
5
4
  import { createListingFor, registerSection } from '../helpers/section_registry.js';
@@ -7,7 +6,6 @@ import { createListingFor, registerSection } from '../helpers/section_registry.j
7
6
  function build_test_run_result_listing_columns(locale, { include_select = true } = {})
8
7
  {
9
8
  const model = new typeTestRunResult();
10
- const test_case_model = new typeTestCase();
11
9
  const columns = [];
12
10
 
13
11
  if (include_select)
@@ -16,10 +14,11 @@ function build_test_run_result_listing_columns(locale, { include_select = true }
16
14
  }
17
15
 
18
16
  columns.push(createColumn(model, locale, 'test_case_id.test_case_title', {
19
- header_name : test_case_model.get_attribute_name_translate('test_case_title', locale),
20
- width : '480',
21
- is_editable : false,
22
- is_required : true,
17
+ header_field : 'test_case_title',
18
+ header_element_type : 'test_case',
19
+ width : '480',
20
+ is_editable : false,
21
+ is_required : true,
23
22
  }));
24
23
  columns.push(createColumn(model, locale, 'assigned_to', { width: '220', is_editable: true, is_required: true }));
25
24
  columns.push(createColumn(model, locale, 'created_at', { width: '170', is_required: true }));
@@ -35,16 +34,15 @@ function build_test_run_result_listing_columns(locale, { include_select = true }
35
34
  function build_test_run_result_todo_columns(locale)
36
35
  {
37
36
  const model = new typeTestRunResult();
38
- const test_case_model = new typeTestCase();
39
-
40
37
  return [
41
38
  createPrimaryKeyColumn(model, locale),
42
39
  createColumn(model, locale, 'test_case_id.test_case_title', {
43
- header_name : test_case_model.get_attribute_name_translate('test_case_title', locale),
44
- width : '480',
45
- is_editable : false,
46
- is_required : true,
47
- is_title : true,
40
+ header_field : 'test_case_title',
41
+ header_element_type : 'test_case',
42
+ width : '480',
43
+ is_editable : false,
44
+ is_required : true,
45
+ is_title : true,
48
46
  }),
49
47
  createColumn(model, locale, 'assigned_to', { width: '220', is_editable: true, is_required: true }),
50
48
  createColumn(model, locale, 'test_result_status', { width: '150', is_editable: true, is_required: true }),
@@ -76,6 +74,12 @@ function build_test_run_result_details_columns(locale)
76
74
  }
77
75
 
78
76
 
77
+ /**
78
+ * Секции `test_run_result`: `listing`, `todo`, `details`.
79
+ *
80
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
81
+ * @returns {void}
82
+ */
79
83
  export function bootstrap_test_run_result(config)
80
84
  {
81
85
  const locale = UserService.get_current_language();
@@ -17,6 +17,12 @@ function build_user_profile_columns(locale)
17
17
  }
18
18
 
19
19
 
20
+ /**
21
+ * Секция `user`: `profile`.
22
+ *
23
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
24
+ * @returns {void}
25
+ */
20
26
  export function bootstrap_user(config)
21
27
  {
22
28
  const locale = UserService.get_current_language();
@@ -1,40 +1,29 @@
1
1
  import { LOCALE_AG_GRID_RU } from '../locale_table_ru.js';
2
2
  import { LOCALE_AG_GRID_EG } from '../table_locale_ar.js';
3
- import { typeTestCase } from '../../types/family_elements/typeTestCase.js';
4
- import { typeProject } from '../../types/family_elements/typeProject.js';
5
- import { typeTestRun } from '../../types/family_elements/typeTestRun.js';
6
- import { typeBug } from '../../types/family_elements/typeBug.js';
7
- import { typeTestRunResult } from '../../types/family_elements/typeTestRunResult.js';
8
- import { typeTestAccount } from '../../types/family_elements/typeTestAccount.js';
9
- import { typeTeamMember } from '../../types/family_elements/typeTeamMember.js';
10
- import { typeTestCaseStep } from '../../types/family_elements/typeTestCaseStep.js';
11
- import { typeUser } from '../../types/family_elements/typeUser.js';
12
- import { typeTeam } from '../../types/family_elements/typeTeam.js';
13
-
14
- const ROW_NODE_MODELS = {
15
- test_case : typeTestCase,
16
- project : typeProject,
17
- test_run : typeTestRun,
18
- bug : typeBug,
19
- test_run_result: typeTestRunResult,
20
- test_account : typeTestAccount,
21
- team_member : typeTeamMember,
22
- test_case_step : typeTestCaseStep,
23
- user : typeUser,
24
- team : typeTeam,
25
- };
3
+ import { TABLE_ELEMENT_MODELS } from './helpers/table_element_models.js';
26
4
 
27
5
  /**
28
- * Базовые опции ag-grid, общие для всех таблиц.
6
+ * Базовые опции ag-grid Community, общие для всех таблиц приложения.
7
+ *
8
+ * Не содержит columnDefs — они строятся в web_app из `TableConfiguration`.
9
+ * Дополняет грид: `defaultColDef`, `rowSelection`, `localeText`, `getRowNodeId`.
29
10
  *
30
- * @version v.0.2 (12/06/2026)
11
+ * @see docs/App Configuration/table.MD
12
+ * @version v.0.3 (12/06/2026)
31
13
  */
32
14
  export class TableBaseConfig
33
15
  {
34
16
  /**
35
- * @param {string} element_type
36
- * @param {string} section
37
- * @param {string} lang
17
+ * Возвращает копию общих gridOptions для ag-grid.
18
+ *
19
+ * @param {string} element_type Ключ сущности — для `getRowNodeId` (primary key модели).
20
+ * @param {string} section Имя секции (зарезервировано; сейчас не влияет на ответ).
21
+ * @param {string} [lang='en'] Локаль UI ag-grid. Для `ru` и `ar` добавляется `localeText`.
22
+ * @returns {Object} GridOptions-совместимый объект (без привязки к Vue).
23
+ *
24
+ * @example
25
+ * const { getRowNodeId, localeText, defaultColDef, ...gridOptions } =
26
+ * TableBaseConfig.get_config('bug', 'listing', 'ru');
38
27
  */
39
28
  static get_config(element_type, section, lang)
40
29
  {
@@ -55,8 +44,11 @@ export class TableBaseConfig
55
44
 
56
45
 
57
46
  /**
58
- * @param lang
59
- * @returns {{}}
47
+ * Словарь ag-grid localeText для меню колонок и системных строк.
48
+ *
49
+ * @private
50
+ * @param {string} lang
51
+ * @returns {Object<string, string>}
60
52
  */
61
53
  static #localeText(lang)
62
54
  {
@@ -76,15 +68,18 @@ export class TableBaseConfig
76
68
 
77
69
 
78
70
  /**
79
- * @param element_type
80
- * @returns {function(*): number}
71
+ * Фабрика `getRowNodeId`: возвращает id строки по primary key сущности.
72
+ *
73
+ * @private
74
+ * @param {string} element_type
75
+ * @returns {function(Object): number}
81
76
  */
82
77
  static #getRowNodeId(element_type)
83
78
  {
84
79
  return function (data)
85
80
  {
86
81
  let id = 0;
87
- const ModelClass = ROW_NODE_MODELS[ element_type ];
82
+ const ModelClass = TABLE_ELEMENT_MODELS[ element_type ];
88
83
 
89
84
  if (ModelClass)
90
85
  {
@@ -102,6 +97,10 @@ export class TableBaseConfig
102
97
  }
103
98
 
104
99
 
100
+ /**
101
+ * Статические опции ag-grid по умолчанию.
102
+ * @type {Object}
103
+ */
105
104
  static config = {
106
105
  defaultColDef : {
107
106
  filter : true,
@@ -9,23 +9,40 @@ import { bootstrap_team_member } from './sections/team_member.js';
9
9
  import { bootstrap_user } from './sections/user.js';
10
10
  import { bootstrap_team } from './sections/team.js';
11
11
  import { bootstrap_project } from './sections/project.js';
12
+ import { localizeTableSection } from './helpers/column_locale.js';
12
13
 
13
14
  /**
14
- * Реестр конфигураций таблиц (ag-grid).
15
+ * Реестр конфигураций таблиц ag-grid.
15
16
  *
16
- * @version v.0.2 (12/06/2026)
17
+ * Хранит колонки (`typeTableColumn`), шаблон поиска (`for`) и метаданные по парам
18
+ * `element_type` × `section` (например `test_case` × `listing`).
19
+ *
20
+ * Заголовки data-колонок локализуются при каждом вызове `get_config`, а не при bootstrap.
21
+ * Представление ячеек (renderer/editor) — в web_app (`ColumnFactory`).
22
+ *
23
+ * @see docs/App Configuration/table.MD
24
+ * @version v.0.3 (12/06/2026)
17
25
  */
18
26
  export class TableConfiguration extends abstractAppConfiguration
19
27
  {
28
+ /**
29
+ * Внутренний реестр: `config[element_type][section] → { config: typeTableConfiguration }`.
30
+ * @type {Object<string, Object<string, { config: import('../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>}
31
+ */
20
32
  static config = {};
21
33
 
34
+ /**
35
+ * @type {{ loaded: boolean }}
36
+ */
22
37
  static state = {
23
38
  loaded: false
24
39
  }
25
40
 
26
41
 
27
42
  /**
28
- * @param init_options
43
+ * Синглтон: при первом создании вызывает `bootstrap()`.
44
+ *
45
+ * @param {boolean|object} [init_options=false]
29
46
  */
30
47
  constructor(init_options = false)
31
48
  {
@@ -43,28 +60,43 @@ export class TableConfiguration extends abstractAppConfiguration
43
60
 
44
61
 
45
62
  /**
46
- * @param {string} element_type
47
- * @param {string} section
48
- * @param {string} lang
63
+ * Возвращает конфигурацию секции таблицы с заголовками колонок для запрошенной локали.
64
+ *
65
+ * @param {string} element_type Ключ сущности (`bug`, `test_case`, `test_run`, …).
66
+ * @param {string} section Имя секции (`listing`, `todo`, `details`, `steps`, `presteps`, …).
67
+ * @param {string} [lang='en'] Код локали (`en`, `ru`, `ar`). Передаётся из web_app (`getLocale()`).
68
+ * @returns {{ config: import('../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }|false}
69
+ * Объект с полем `config` или `false`, если секция не зарегистрирована.
49
70
  *
50
- * @todo - header_name модифицируем под локаль
71
+ * @example
72
+ * const section = TableConfiguration.get_config('test_case', 'listing', 'ru');
73
+ * const columns = section.config.columns;
74
+ * const forTemplate = section.config.for;
51
75
  */
52
- static get_config(element_type, section, lang)
76
+ static get_config(element_type, section, lang = 'en')
53
77
  {
54
78
  if (!this.state.loaded)
55
79
  {
56
80
  this.bootstrap();
57
81
  }
58
82
 
59
- if (this.config?.[ element_type ]?.[ section ])
83
+ const section_config = this.config?.[ element_type ]?.[ section ];
84
+
85
+ if (!section_config)
60
86
  {
61
- return this.config?.[ element_type ]?.[ section ];
87
+ return false;
62
88
  }
63
89
 
64
- return false;
90
+ return localizeTableSection(section_config, element_type, lang || 'en');
65
91
  }
66
92
 
67
93
 
94
+ /**
95
+ * Однократная загрузка всех секций из `sections/*` в `static.config`.
96
+ * Повторный вызов — no-op.
97
+ *
98
+ * @returns {void}
99
+ */
68
100
  static bootstrap()
69
101
  {
70
102
  if (this.state.loaded)
@@ -1,58 +1,116 @@
1
- import { familyService } from "./familyService";
2
-
3
- /**
4
- *
5
- * @version v.0.1 (26/04/2025)
6
- */
7
- export class typeTableColumn extends familyService
8
- {
9
- header_name;
10
- field;
11
- width;
12
- sort_order;
13
- cell_classes;
14
- default_sort;
15
- is_sortable;
16
- is_filter;
17
- is_hide;
18
- is_editable;
19
-
20
- /**
21
- * Семантический тип колонки для фабрики ColDef (этап 3).
22
- * @type {'data'|'row_select'|'goto'|'sort_action'|'copy'}
23
- */
24
- column_kind = 'data';
25
-
26
- /**
27
- * Обязательное поле при создании/редактировании строки.
28
- */
29
- is_required = false;
30
-
31
- /**
32
- * Поле-заголовок сущности (например test_case_title).
33
- */
34
- is_title = false;
35
-
36
- /**
37
- * Тип сущности для перевода header_name, если отличается от основной.
38
- */
39
- header_element_type = false;
40
-
41
-
42
- constructor(data = false)
43
- {
44
- super();
45
- if (data && typeof data === 'object')
46
- {
47
- _.mapObject(data, (value, key) =>
48
- {
49
- if (this.hasOwnProperty(key))
50
- {
51
- this [ key ] = value;
52
- }
53
- });
54
- }
55
-
56
- return this;
57
- }
58
- }
1
+ import { familyService } from "./familyService";
2
+
3
+ /**
4
+ * Описание одной колонки таблицы ag-grid.
5
+ *
6
+ * Ядро хранит структуру и флаги; web_app (`ColumnFactory`) маппит в `ColDef`
7
+ * и подбирает cellRenderer / cellEditor по `field` и `column_kind`.
8
+ *
9
+ * @see docs/App Configuration/table.MD
10
+ * @version v.0.2 (12/06/2026)
11
+ */
12
+ export class typeTableColumn extends familyService
13
+ {
14
+ /**
15
+ * Отображаемый заголовок колонки.
16
+ * Для `column_kind: 'data'` пересчитывается в `TableConfiguration.get_config` по `header_field` и `lang`.
17
+ * @type {string|undefined}
18
+ */
19
+ header_name;
20
+
21
+ /**
22
+ * Имя поля в данных строки (ColDef.field).
23
+ * @type {string|undefined}
24
+ */
25
+ field;
26
+
27
+ /**
28
+ * Ширина колонки в пикселях (строка для совместимости с конфигами).
29
+ * @type {string|number|undefined}
30
+ */
31
+ width;
32
+
33
+ /**
34
+ * Порядок колонки (меньше — левее). Сортируется в ColumnFactory перед сборкой ColDef.
35
+ * @type {string|number|undefined}
36
+ */
37
+ sort_order;
38
+
39
+ /**
40
+ * CSS-классы ячейки.
41
+ * @type {string|undefined}
42
+ */
43
+ cell_classes;
44
+
45
+ /**
46
+ * Начальная сортировка: `''`, `'asc'` или `'desc'`.
47
+ * @type {''|'asc'|'desc'|string|undefined}
48
+ */
49
+ default_sort;
50
+
51
+ /** @type {boolean|undefined} */
52
+ is_sortable;
53
+
54
+ /** @type {boolean|undefined} */
55
+ is_filter;
56
+
57
+ /** @type {boolean|undefined} */
58
+ is_hide;
59
+
60
+ /** @type {boolean|undefined} */
61
+ is_editable;
62
+
63
+ /**
64
+ * Семантический тип колонки для фабрики ColDef в web_app.
65
+ * @type {'data'|'row_select'|'goto'|'sort_action'|'copy'}
66
+ */
67
+ column_kind = 'data';
68
+
69
+ /**
70
+ * Обязательное поле при создании/редактировании строки (метаданные для UI).
71
+ * @type {boolean}
72
+ */
73
+ is_required = false;
74
+
75
+ /**
76
+ * Поле-заголовок сущности в строке (например `test_case_title` в todo).
77
+ * Влияет на multiline / flex в ColumnFactory.
78
+ * @type {boolean}
79
+ */
80
+ is_title = false;
81
+
82
+ /**
83
+ * Ключ модели для перевода заголовка, если отличается от `element_type` секции.
84
+ * Пример: `test_case` для колонки `test_case_id.test_case_title` в `test_run_result`.
85
+ * @type {string|false}
86
+ */
87
+ header_element_type = false;
88
+
89
+ /**
90
+ * Имя атрибута в `attribute_name_translate_matrix` для заголовка.
91
+ * Задаётся в `createColumn`; если `false` — заголовок не локализуется при `get_config`.
92
+ * @type {string|false}
93
+ */
94
+ header_field = false;
95
+
96
+
97
+ /**
98
+ * @param {Partial<typeTableColumn>|false} [data=false]
99
+ */
100
+ constructor(data = false)
101
+ {
102
+ super();
103
+ if (data && typeof data === 'object')
104
+ {
105
+ _.mapObject(data, (value, key) =>
106
+ {
107
+ if (this.hasOwnProperty(key))
108
+ {
109
+ this [ key ] = value;
110
+ }
111
+ });
112
+ }
113
+
114
+ return this;
115
+ }
116
+ }
@@ -1,33 +1,40 @@
1
1
  import { typeAppConfiguration } from "./typeAppConfiguration";
2
2
 
3
3
  /**
4
- * Настройки таблиц (aggrid)
4
+ * Конфигурация одной секции таблицы (набор колонок + поиск).
5
5
  *
6
- * @version v.0.1 (26/04/2025)
6
+ * Регистрируется через `registerSection` в `sections/*`.
7
+ * Потребляется web_app: `useTableConfig` → `ColumnFactory` + `buildSearchPayload`.
8
+ *
9
+ * @see docs/App Configuration/table.MD
10
+ * @version v.0.2 (12/06/2026)
7
11
  */
8
12
  export class typeTableConfiguration extends typeAppConfiguration
9
13
  {
10
14
  /**
11
- * @type {array<typeTableColumn>}
15
+ * Список колонок секции.
16
+ * @type {import('./typeTableColumn.js').typeTableColumn[]|undefined}
12
17
  */
13
18
  columns;
14
19
 
15
20
  /**
16
- * @type {array<typeFOR>}
21
+ * Шаблон объекта поиска (`typeFOR`) для листингов.
22
+ * Фильтры с `value: false` гидратируются в web_app через `buildSearchPayload`.
23
+ * @type {import('./typeFOR.js').typeFOR|false|undefined}
17
24
  */
18
25
  for;
19
26
 
20
27
 
21
28
  /**
22
- * Элемент, в составе
23
- * надо ли
29
+ * Тип вложенной сущности для контекстных таблиц (например todo внутри project).
30
+ * @type {string|false|undefined}
24
31
  */
25
32
  contained_element_type;
26
33
 
27
34
 
28
35
 
29
36
  /**
30
- * под развитие
37
+ * Ссылки на внешнюю документацию секции (зарезервировано).
31
38
  * @type {{link: false|string, description: false|string}}
32
39
  */
33
40
  documentation = {
@@ -37,6 +44,9 @@ export class typeTableConfiguration extends typeAppConfiguration
37
44
 
38
45
 
39
46
 
47
+ /**
48
+ * @param {Partial<typeTableConfiguration>|false} [data=false]
49
+ */
40
50
  constructor(data = false)
41
51
  {
42
52
  super();
@@ -53,4 +63,4 @@ export class typeTableConfiguration extends typeAppConfiguration
53
63
 
54
64
  return this;
55
65
  }
56
- }
66
+ }