complexqa_frontend_core 1.21.8 → 1.22.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 (26) hide show
  1. package/package.json +1 -1
  2. package/publish/api/api_abstract_class.js +1 -1
  3. package/publish/api/file_app_api.js +30 -3
  4. package/publish/api/index.js +6 -0
  5. package/publish/api/project_api.js +31 -8
  6. package/publish/api/public_text_document_api.js +59 -0
  7. package/publish/api/text_document_api.js +205 -0
  8. package/publish/api/text_document_folder_api.js +16 -0
  9. package/publish/app_configuration/table/helpers/table_element_models.js +2 -0
  10. package/publish/app_configuration/table/sections/text_document.js +31 -0
  11. package/publish/app_configuration/table/table_configuration.js +2 -0
  12. package/publish/app_configuration/text_document_editor_config.js +31 -0
  13. package/publish/constants/text_document_limits.js +18 -0
  14. package/publish/index.js +11 -0
  15. package/publish/services/FileAppService.js +103 -10
  16. package/publish/types/core/0_familyGeneralElement.js +0 -2
  17. package/publish/types/element_translate/_familyUtil.i18n.js +302 -68
  18. package/publish/types/element_translate/typeTextDocument.i18n.js +201 -0
  19. package/publish/types/element_translate/typeTextDocumentFolder.i18n.js +108 -0
  20. package/publish/types/element_translate/typeUtilExecution.i18n.js +171 -0
  21. package/publish/types/element_translate/typeUtilExecutionScreenshotMulti.i18n.js +281 -65
  22. package/publish/types/family_elements/typeProject.js +35 -10
  23. package/publish/types/family_files/typeTextDocument.js +88 -0
  24. package/publish/types/family_files/typeTextDocumentFolder.js +68 -0
  25. package/publish/types/family_utils/typeUtilExecution.js +14 -3
  26. package/publish/utils/text_document_image.js +84 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "complexqa_frontend_core",
3
- "version": "1.21.8",
3
+ "version": "1.22.1",
4
4
  "description": "core of web ",
5
5
  "type": "module",
6
6
  "exports": {
@@ -199,7 +199,7 @@ export class ApiAbstractClass
199
199
  url : url
200
200
  };
201
201
 
202
- if (this.method === 'get')
202
+ if (method === 'get' || method === 'GET')
203
203
  {
204
204
  request_options.paramsSerializer = this.object_to_string;
205
205
  request_options.params = request_params;
@@ -26,7 +26,7 @@ export class FileAppApi extends ApiAbstractClass
26
26
  const url = `/${ this.api_prefix }/${ this.module_prefix }/issue_access_token`;
27
27
  payload = this.handle_request_payload(payload);
28
28
  let response = this.api_request(url, payload);
29
- response = this.handle_response(response, false);
29
+ response = await this.handle_response(response, false);
30
30
 
31
31
  return {
32
32
  response: response,
@@ -51,7 +51,34 @@ export class FileAppApi extends ApiAbstractClass
51
51
 
52
52
  payload = this.handle_request_payload(payload);
53
53
  let response = this.api_request(url, payload);
54
- response = this.handle_response(response, false);
54
+ response = await this.handle_response(response, false);
55
+
56
+ this.method = prev_method;
57
+
58
+ return {
59
+ response: response,
60
+ payload : payload,
61
+ };
62
+ }
63
+
64
+
65
+ /**
66
+ * GET|POST /web_api/file_app/file_access_urls?file_uuids[]=&disposition=
67
+ *
68
+ * @param {object} payload
69
+ *
70
+ * @returns {Promise<{payload: object, response: object}>}
71
+ */
72
+ async file_access_urls(payload)
73
+ {
74
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/file_access_urls`;
75
+ const prev_method = this.method;
76
+
77
+ this.method = 'get';
78
+
79
+ payload = this.handle_request_payload(payload);
80
+ let response = this.api_request(url, payload);
81
+ response = await this.handle_response(response, false);
55
82
 
56
83
  this.method = prev_method;
57
84
 
@@ -78,7 +105,7 @@ export class FileAppApi extends ApiAbstractClass
78
105
 
79
106
  payload = this.handle_request_payload(payload);
80
107
  let response = this.api_request(url, payload);
81
- response = this.handle_response(response, false);
108
+ response = await this.handle_response(response, false);
82
109
 
83
110
  this.method = prev_method;
84
111
 
@@ -22,6 +22,9 @@ import { ContextOsApi } from "./context/context_os_api.js";
22
22
  import { ContextScreenResolutionApi } from "./context/context_screen_resolution_api.js";
23
23
  import { BrowserToolsUtilExecutionApi } from "./util/browser_tools_util_execution_api.js";
24
24
  import { BrowserToolsScreenshotMultiApi } from "./util/browser_tools_screenshot_multi_api.js";
25
+ import { TextDocumentApi } from "./text_document_api.js";
26
+ import { PublicTextDocumentApi } from "./public_text_document_api.js";
27
+ import { TextDocumentFolderApi } from "./text_document_folder_api.js";
25
28
  import { FileAppApi } from "./file_app_api.js";
26
29
 
27
30
  /**
@@ -163,6 +166,9 @@ export class Api
163
166
  this.browser_tools_util_execution = new BrowserToolsUtilExecutionApi(payload);
164
167
  this.browser_tools_screenshot_multi = new BrowserToolsScreenshotMultiApi(payload);
165
168
  this.file_app = new FileAppApi(payload);
169
+ this.text_document = new TextDocumentApi(payload);
170
+ this.text_document_folder = new TextDocumentFolderApi(payload);
171
+ this.public_text_document = new PublicTextDocumentApi(payload);
166
172
 
167
173
  this.reference = this.bootstrap_reference(payload)
168
174
  }
@@ -20,16 +20,12 @@ export class ProjectApi extends ApiAbstractElementClass
20
20
 
21
21
  /**
22
22
  *
23
- * All test cases + suites
24
- *
25
- * @version v.1.1 (04/02/2026)
26
- * @param payload
27
- * @todo - валидация входящих параметров
23
+ * @param {string} url
24
+ * @param {object} payload
25
+ * @returns {Promise<{response: *, payload: *}>}
28
26
  */
29
- async get_test_structure(payload)
27
+ async _get_project_structure(url, payload)
30
28
  {
31
- let url = `/web_api/project/get/test_structure`;
32
-
33
29
  payload = this.handle_request_payload(payload);
34
30
  let response = this.api_request(url, payload);
35
31
  response = this.handle_response(response, false);
@@ -39,4 +35,31 @@ export class ProjectApi extends ApiAbstractElementClass
39
35
  payload : payload
40
36
  };
41
37
  }
38
+
39
+
40
+ /**
41
+ *
42
+ * All test cases + suites
43
+ *
44
+ * @version v.1.1 (04/02/2026)
45
+ * @param payload
46
+ * @todo - валидация входящих параметров
47
+ */
48
+ async get_test_structure(payload)
49
+ {
50
+ return this._get_project_structure('/web_api/project/get/test_structure', payload);
51
+ }
52
+
53
+
54
+ /**
55
+ *
56
+ * All text documents + folders
57
+ *
58
+ * @version v.1.0 (04/07/2026)
59
+ * @param payload
60
+ */
61
+ async get_text_document_structure(payload)
62
+ {
63
+ return this._get_project_structure('/web_api/project/get/text_document_structure', payload);
64
+ }
42
65
  }
@@ -0,0 +1,59 @@
1
+ import { ApiAbstractClass } from "./api_abstract_class.js";
2
+
3
+ /**
4
+ * Guest public text document view API.
5
+ *
6
+ * @version v.1.0 (04/07/2026)
7
+ */
8
+ export class PublicTextDocumentApi extends ApiAbstractClass
9
+ {
10
+ module_prefix = 'public/text_document';
11
+ api_prefix = 'web_api';
12
+
13
+
14
+ /**
15
+ * GET|POST /web_api/public/text_document/view
16
+ *
17
+ * @param {object} payload token, password?
18
+ * @returns {Promise<{payload: object, response: object}>}
19
+ */
20
+ async view(payload)
21
+ {
22
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/view`;
23
+ const prev_method = this.method;
24
+
25
+ this.method = 'get';
26
+
27
+ payload = this.handle_request_payload(payload);
28
+ let response = this.api_request(url, payload);
29
+ response = await this.handle_response(response, false);
30
+
31
+ this.method = prev_method;
32
+
33
+ return {
34
+ response: response,
35
+ payload : payload,
36
+ };
37
+ }
38
+
39
+
40
+ /**
41
+ * POST /web_api/public/text_document/report
42
+ *
43
+ * @param {object} payload token, reason, reporter_email, password?
44
+ * @returns {Promise<{payload: object, response: object}>}
45
+ */
46
+ async report(payload)
47
+ {
48
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/report`;
49
+
50
+ payload = this.handle_request_payload(payload);
51
+ let response = this.api_request(url, payload);
52
+ response = await this.handle_response(response, false);
53
+
54
+ return {
55
+ response: response,
56
+ payload : payload,
57
+ };
58
+ }
59
+ }
@@ -0,0 +1,205 @@
1
+ import { ApiAbstractElementClass } from "./api_abstract_element_class.js";
2
+ import { typeTextDocument } from "../types/family_files/typeTextDocument.js";
3
+
4
+ /**
5
+ * @version v.1.1 (05/07/2026)
6
+ */
7
+ export class TextDocumentApi extends ApiAbstractElementClass
8
+ {
9
+ module_prefix = 'text_document';
10
+
11
+ constructor(options)
12
+ {
13
+ super(options);
14
+ this.set_element_class_instance(typeTextDocument);
15
+ }
16
+
17
+
18
+ /**
19
+ * GET /web_api/text_document/list_project_images?project_id=
20
+ *
21
+ * @param {object} payload
22
+ * @returns {Promise<{payload: object, response: object}>}
23
+ */
24
+ async list_project_images(payload)
25
+ {
26
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/list_project_images`;
27
+
28
+ payload = this.handle_request_payload(payload);
29
+ let response = this.api_request(url, payload, 'GET');
30
+ response = await this.handle_response(response, false);
31
+
32
+ return {
33
+ response: response,
34
+ payload : payload,
35
+ };
36
+ }
37
+
38
+
39
+ /**
40
+ * GET /web_api/text_document/load_body?text_document_id=
41
+ *
42
+ * @param {object} payload
43
+ * @returns {Promise<{payload: object, response: object}>}
44
+ */
45
+ async load_body(payload)
46
+ {
47
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/load_body`;
48
+
49
+ payload = this.handle_request_payload(payload);
50
+ let response = this.api_request(url, payload, 'GET');
51
+ response = await this.handle_response(response, false);
52
+
53
+ return {
54
+ response: response,
55
+ payload : payload,
56
+ };
57
+ }
58
+
59
+
60
+ /**
61
+ * GET /web_api/text_document/list_versions?text_document_id=
62
+ *
63
+ * @param {object} payload
64
+ * @returns {Promise<{payload: object, response: object}>}
65
+ */
66
+ async list_versions(payload)
67
+ {
68
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/list_versions`;
69
+
70
+ payload = this.handle_request_payload(payload);
71
+ let response = this.api_request(url, payload, 'GET');
72
+ response = await this.handle_response(response, false);
73
+
74
+ return {
75
+ response: response,
76
+ payload : payload,
77
+ };
78
+ }
79
+
80
+
81
+ /**
82
+ * POST /web_api/text_document/restore_version
83
+ *
84
+ * @param {object} payload
85
+ * @returns {Promise<{payload: object, response: object}>}
86
+ */
87
+ async restore_version(payload)
88
+ {
89
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/restore_version`;
90
+
91
+ payload = this.handle_request_payload(payload);
92
+ let response = this.api_request(url, payload);
93
+ response = await this.handle_response(response, false);
94
+
95
+ return {
96
+ response: response,
97
+ payload : payload,
98
+ };
99
+ }
100
+
101
+
102
+ /**
103
+ * POST /web_api/text_document/enforce_version_retention
104
+ *
105
+ * @param {object} payload
106
+ * @returns {Promise<{payload: object, response: object}>}
107
+ */
108
+ async enforce_version_retention(payload)
109
+ {
110
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/enforce_version_retention`;
111
+
112
+ payload = this.handle_request_payload(payload);
113
+ let response = this.api_request(url, payload);
114
+ response = await this.handle_response(response, false);
115
+
116
+ return {
117
+ response: response,
118
+ payload : payload,
119
+ };
120
+ }
121
+
122
+
123
+ /**
124
+ * GET /web_api/text_document/public_share_status?text_document_id=
125
+ *
126
+ * @param {object} payload
127
+ * @returns {Promise<{payload: object, response: object}>}
128
+ */
129
+ async public_share_status(payload)
130
+ {
131
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/public_share_status`;
132
+
133
+ payload = this.handle_request_payload(payload);
134
+ let response = this.api_request(url, payload, 'GET');
135
+ response = await this.handle_response(response, false);
136
+
137
+ return {
138
+ response: response,
139
+ payload : payload,
140
+ };
141
+ }
142
+
143
+
144
+ /**
145
+ * POST /web_api/text_document/create_public_share
146
+ *
147
+ * @param {object} payload
148
+ * @returns {Promise<{payload: object, response: object}>}
149
+ */
150
+ async create_public_share(payload)
151
+ {
152
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/create_public_share`;
153
+
154
+ payload = this.handle_request_payload(payload);
155
+ let response = this.api_request(url, payload);
156
+ response = await this.handle_response(response, false);
157
+
158
+ return {
159
+ response: response,
160
+ payload : payload,
161
+ };
162
+ }
163
+
164
+
165
+ /**
166
+ * POST /web_api/text_document/revoke_public_share
167
+ *
168
+ * @param {object} payload
169
+ * @returns {Promise<{payload: object, response: object}>}
170
+ */
171
+ async revoke_public_share(payload)
172
+ {
173
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/revoke_public_share`;
174
+
175
+ payload = this.handle_request_payload(payload);
176
+ let response = this.api_request(url, payload);
177
+ response = await this.handle_response(response, false);
178
+
179
+ return {
180
+ response: response,
181
+ payload : payload,
182
+ };
183
+ }
184
+
185
+
186
+ /**
187
+ * GET /web_api/text_document/public_share_analytics?text_document_id=
188
+ *
189
+ * @param {object} payload
190
+ * @returns {Promise<{payload: object, response: object}>}
191
+ */
192
+ async public_share_analytics(payload)
193
+ {
194
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/public_share_analytics`;
195
+
196
+ payload = this.handle_request_payload(payload);
197
+ let response = this.api_request(url, payload, 'GET');
198
+ response = await this.handle_response(response, false);
199
+
200
+ return {
201
+ response: response,
202
+ payload : payload,
203
+ };
204
+ }
205
+ }
@@ -0,0 +1,16 @@
1
+ import { ApiAbstractElementClass } from "./api_abstract_element_class.js";
2
+ import { typeTextDocumentFolder } from "../types/family_files/typeTextDocumentFolder.js";
3
+
4
+ /**
5
+ * @version v.1.0 (04/07/2026)
6
+ */
7
+ export class TextDocumentFolderApi extends ApiAbstractElementClass
8
+ {
9
+ module_prefix = 'text_document_folder';
10
+
11
+ constructor(options)
12
+ {
13
+ super(options);
14
+ this.set_element_class_instance(typeTextDocumentFolder);
15
+ }
16
+ }
@@ -11,6 +11,7 @@ import { typeTestCaseStep } from '../../../types/family_elements/typeTestCaseSte
11
11
  import { typeUser } from '../../../types/family_elements/typeUser.js';
12
12
  import { typeTeam } from '../../../types/family_elements/typeTeam.js';
13
13
  import { typeUtilExecutionScreenshotMulti } from '../../../types/family_utils/typeUtilExecutionScreenshotMulti.js';
14
+ import { typeTextDocument } from '../../../types/family_files/typeTextDocument.js';
14
15
 
15
16
  /**
16
17
  * Реестр классов моделей по ключу `element_type`.
@@ -36,5 +37,6 @@ export const TABLE_ELEMENT_MODELS = {
36
37
  test_case_step : typeTestCaseStep,
37
38
  user : typeUser,
38
39
  team : typeTeam,
40
+ text_document : typeTextDocument,
39
41
  util_execution : typeUtilExecutionScreenshotMulti,
40
42
  };
@@ -0,0 +1,31 @@
1
+ import { typeTextDocument } from '../../../types/family_files/typeTextDocument.js';
2
+ import { UserService } from '../../../services/UserService.js';
3
+ import { createColumn, createGoToColumn, createPrimaryKeyColumn } from '../helpers/column_factory.js';
4
+ import { createListingFor, registerSection } from '../helpers/section_registry.js';
5
+
6
+ function build_text_document_listing_columns(locale)
7
+ {
8
+ const model = new typeTextDocument();
9
+
10
+ return [
11
+ createPrimaryKeyColumn(model, locale),
12
+ createColumn(model, locale, 'text_document_title', { width: '320', is_editable: true, is_title: true }),
13
+ createColumn(model, locale, 'text_document_status', { width: '140', is_editable: true }),
14
+ createColumn(model, locale, 'text_document_folder_id', { width: '120' }),
15
+ createColumn(model, locale, 'created_at', { width: '170' }),
16
+ createColumn(model, locale, 'updated_at', { width: '170' }),
17
+ createGoToColumn(model, locale),
18
+ ];
19
+ }
20
+
21
+ /**
22
+ * @param {Object<string, Object<string, { config: import('../../../types/family_service/typeTableConfiguration.js').typeTableConfiguration }>>} config
23
+ */
24
+ export function bootstrap_text_document(config)
25
+ {
26
+ const locale = UserService.get_current_language();
27
+
28
+ registerSection(config, 'text_document', 'listing', build_text_document_listing_columns(locale), {
29
+ for: createListingFor([ 'project_id', 'text_document_folder_id' ]),
30
+ });
31
+ }
@@ -12,6 +12,7 @@ import { bootstrap_team_member } from './sections/team_member.js';
12
12
  import { bootstrap_user } from './sections/user.js';
13
13
  import { bootstrap_team } from './sections/team.js';
14
14
  import { bootstrap_project } from './sections/project.js';
15
+ import { bootstrap_text_document } from './sections/text_document.js';
15
16
  import { localizeTableSection } from './helpers/column_locale.js';
16
17
 
17
18
  /**
@@ -120,6 +121,7 @@ export class TableConfiguration extends abstractAppConfiguration
120
121
  bootstrap_user(this.config);
121
122
  bootstrap_team(this.config);
122
123
  bootstrap_project(this.config);
124
+ bootstrap_text_document(this.config);
123
125
 
124
126
  this.state.loaded = true;
125
127
  }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * LEGACY — TipTap toolbar stub from early text document plan (not shipped).
3
+ *
4
+ * Text documents use CKEditor 4 in web_app (`textDocumentEditorConfig.ts`).
5
+ * TipTap was evaluated and rejected — see complex_processes/text_editor/01-decisions.md.
6
+ *
7
+ * @deprecated Not consumed by web_app. Kept for export compatibility only.
8
+ * @version v.1.1 (04/07/2026)
9
+ */
10
+ export const text_document_editor_config = {
11
+ starterKit: {
12
+ heading: {
13
+ levels: [ 1, 2, 3 ],
14
+ },
15
+ },
16
+ underline : true,
17
+ textAlign : true,
18
+ color : true,
19
+ highlight : true,
20
+ link : true,
21
+ placeholder : 'Start writing…',
22
+ numberedHeadings: true,
23
+ };
24
+
25
+ /**
26
+ * @returns {typeof text_document_editor_config}
27
+ */
28
+ export function get_text_document_editor_config()
29
+ {
30
+ return text_document_editor_config;
31
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Limits for text document feature (sync with test_site and file-app).
3
+ *
4
+ * @version v.1.0 (04/07/2026)
5
+ */
6
+ export const TEXT_DOCUMENT_MAX_IMAGES = 20;
7
+
8
+ export const TEXT_DOCUMENT_MAX_BODY_BYTES = 5242880;
9
+
10
+ export const TEXT_DOCUMENT_MAX_VERSIONS = 15;
11
+
12
+ export const TEXT_DOCUMENT_AUTOSAVE_STORAGE_PREFIX = 'text_document_autosave_';
13
+
14
+ /**
15
+ * img[src] required by file-app HTMLPurifier on html body upload.
16
+ * Real URL is resolved on load via data-file-uuid + file_access_url.
17
+ */
18
+ export const TEXT_DOCUMENT_IMAGE_STORAGE_PLACEHOLDER_SRC = 'https://landing.complexqa.com/icons/favicon_192.png';
package/publish/index.js CHANGED
@@ -45,6 +45,17 @@ export { typeFilePostman } from './types/family_files/typeFilePostman.js';
45
45
  export { typeFileVideo } from './types/family_files/typeFileVideo.js';
46
46
  export { typeFileJson } from './types/family_files/typeFileJson.js';
47
47
  export { create_type_file_from_wire } from './types/family_files/typeFileFactory.js';
48
+ export { typeTextDocument } from './types/family_files/typeTextDocument.js';
49
+ export { typeTextDocumentFolder } from './types/family_files/typeTextDocumentFolder.js';
50
+
51
+ export { TEXT_DOCUMENT_MAX_IMAGES, TEXT_DOCUMENT_MAX_BODY_BYTES, TEXT_DOCUMENT_MAX_VERSIONS, TEXT_DOCUMENT_AUTOSAVE_STORAGE_PREFIX, TEXT_DOCUMENT_IMAGE_STORAGE_PLACEHOLDER_SRC } from './constants/text_document_limits.js';
52
+ export {
53
+ count_text_document_images,
54
+ collect_text_document_image_uuids,
55
+ build_text_document_image_html,
56
+ can_add_text_document_image,
57
+ } from './utils/text_document_image.js';
58
+ export { text_document_editor_config, get_text_document_editor_config } from './app_configuration/text_document_editor_config.js';
48
59
 
49
60
  export { typeUser } from './types/family_elements/typeUser.js';
50
61
  export { typeTeam } from './types/family_elements/typeTeam.js';