@sap/ux-ui5-tooling 1.24.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/adp-tooling/templates/cf/package.json +1 -1
- package/dist/cli/index.cjs +80636 -72229
- package/dist/control-property-editor/app.css +1 -1
- package/dist/control-property-editor/app.js +43 -43
- package/dist/middlewares/fiori-tools-appreload.js +9127 -8610
- package/dist/middlewares/fiori-tools-preview.js +66066 -56705
- package/dist/middlewares/fiori-tools-proxy.js +52290 -43887
- package/dist/preview-middleware/dist/client/adp/change-file-validator.js +128 -0
- package/dist/preview-middleware/dist/client/adp/change-file-validator.ts +158 -0
- package/dist/preview-middleware/dist/client/adp/init.js +5 -1
- package/dist/preview-middleware/dist/client/adp/init.ts +5 -0
- package/dist/preview-middleware/dist/client/cpe/changes/service.js +85 -57
- package/dist/preview-middleware/dist/client/cpe/changes/service.ts +91 -52
- package/dist/preview-middleware/dist/client/cpe/control-data.js +183 -158
- package/dist/preview-middleware/dist/client/cpe/control-data.ts +221 -163
- package/dist/preview-middleware/dist/client/flp/init.js +2 -2
- package/dist/preview-middleware/dist/client/flp/init.ts +2 -2
- package/dist/preview-middleware/dist/client/messagebundle.properties +2 -0
- package/dist/tasks/cf-deploy/index.js +85092 -76768
- package/dist/tasks/deploy/index.js +57335 -49007
- package/package.json +24 -24
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-private/control-property-editor-common", "../utils/info-center-message"], function (log, ___sap_ux_private_control_property_editor_common, ___utils_info_center_message) {
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
const MessageBarType = ___sap_ux_private_control_property_editor_common["MessageBarType"];
|
|
7
|
+
const sendInfoCenterMessage = ___utils_info_center_message["sendInfoCenterMessage"];
|
|
8
|
+
const CHANGE_TYPE = {
|
|
9
|
+
addXML: 'addXML',
|
|
10
|
+
codeExt: 'codeExt'
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Type guard for changes that reference a fragment or controller extension file.
|
|
14
|
+
*
|
|
15
|
+
* @param change flex change object
|
|
16
|
+
* @returns true if the change is an addXML with fragmentPath or a codeExt with codeRef
|
|
17
|
+
*/
|
|
18
|
+
function isFragmentOrCodeExtChange(change) {
|
|
19
|
+
return !!change.reference && (change.changeType === CHANGE_TYPE.addXML && !!change.content?.fragmentPath || change.changeType === CHANGE_TYPE.codeExt && !!change.content?.codeRef);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Builds a lookup map from module name patterns to change metadata
|
|
24
|
+
* for addXML and codeExt changes.
|
|
25
|
+
*
|
|
26
|
+
* @param changes record of change objects keyed by flex key
|
|
27
|
+
* @returns map from module name substring to orphaned change entry
|
|
28
|
+
*/
|
|
29
|
+
function buildModuleNameMap(changes) {
|
|
30
|
+
const map = new Map();
|
|
31
|
+
for (const change of Object.values(changes)) {
|
|
32
|
+
if (!isFragmentOrCodeExtChange(change)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const prefix = change.reference.replaceAll('.', '/');
|
|
36
|
+
const path = change.changeType === CHANGE_TYPE.addXML ? change.content?.fragmentPath ?? '' : change.content?.codeRef ?? '';
|
|
37
|
+
const changeFileName = `${change.fileName}.${change.fileType ?? 'change'}`;
|
|
38
|
+
const key = change.moduleName ?? `${prefix}/changes/${path}`;
|
|
39
|
+
map.set(key, {
|
|
40
|
+
changeFileName,
|
|
41
|
+
filePath: path,
|
|
42
|
+
changeType: change.changeType
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return map;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates an error handler that matches error messages against known module names
|
|
50
|
+
* and sends InfoCenter errors for orphaned change files.
|
|
51
|
+
*
|
|
52
|
+
* @param moduleNameMap map from module name substring to orphaned change entry
|
|
53
|
+
* @returns error handler function
|
|
54
|
+
*/
|
|
55
|
+
function createErrorHandler(moduleNameMap, restoreConsole) {
|
|
56
|
+
return message => {
|
|
57
|
+
for (const [moduleName, entry] of moduleNameMap) {
|
|
58
|
+
if (message.includes(moduleName)) {
|
|
59
|
+
sendInfoCenterMessage({
|
|
60
|
+
title: {
|
|
61
|
+
key: 'ADP_ORPHANED_CHANGE_ERROR_TITLE'
|
|
62
|
+
},
|
|
63
|
+
description: {
|
|
64
|
+
key: 'ADP_ORPHANED_FILE_DESCRIPTION',
|
|
65
|
+
params: [entry.filePath, entry.changeFileName]
|
|
66
|
+
},
|
|
67
|
+
type: MessageBarType.error
|
|
68
|
+
}).catch(error => {
|
|
69
|
+
log.error('Failed to send orphaned change InfoCenter message', error);
|
|
70
|
+
});
|
|
71
|
+
moduleNameMap.delete(moduleName);
|
|
72
|
+
if (moduleNameMap.size === 0) {
|
|
73
|
+
restoreConsole();
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Initializes orphaned change file detection.
|
|
83
|
+
*
|
|
84
|
+
* Fetches loaded flex changes, builds a lookup map of module names for addXML and codeExt changes,
|
|
85
|
+
* and wraps console.error to intercept UI5 flex change application errors. When UI5 fails to load
|
|
86
|
+
* a fragment or controller extension referenced by a change file, the error is intercepted and an
|
|
87
|
+
* actionable message is shown in the InfoCenter advising the user to delete the orphaned change file.
|
|
88
|
+
*/
|
|
89
|
+
async function initOrphanedChangeDetection() {
|
|
90
|
+
const baseUrl = document.getElementById('sap-ui-bootstrap')?.dataset.openUxPreviewBaseUrl ?? '';
|
|
91
|
+
const response = await fetch(`${baseUrl}/preview/api/changes`, {
|
|
92
|
+
method: 'GET',
|
|
93
|
+
headers: {
|
|
94
|
+
'content-type': 'application/json'
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
log.error(`Failed to fetch changes for orphaned change detection: ${response.status}`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const changes = await response.json();
|
|
102
|
+
const moduleNameMap = buildModuleNameMap(changes);
|
|
103
|
+
if (moduleNameMap.size === 0) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const consoleRef = globalThis.console;
|
|
107
|
+
const originalConsoleError = consoleRef.error;
|
|
108
|
+
const restore = () => {
|
|
109
|
+
consoleRef.error = originalConsoleError;
|
|
110
|
+
};
|
|
111
|
+
const handler = createErrorHandler(moduleNameMap, restore);
|
|
112
|
+
const safetyTimeout = setTimeout(restore, 60_000);
|
|
113
|
+
consoleRef.error = (...args) => {
|
|
114
|
+
originalConsoleError.apply(consoleRef, args);
|
|
115
|
+
const message = args.filter(arg => typeof arg === 'string').join('');
|
|
116
|
+
handler(message);
|
|
117
|
+
if (moduleNameMap.size === 0) {
|
|
118
|
+
clearTimeout(safetyTimeout);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
var __exports = {
|
|
123
|
+
__esModule: true
|
|
124
|
+
};
|
|
125
|
+
__exports.initOrphanedChangeDetection = initOrphanedChangeDetection;
|
|
126
|
+
return __exports;
|
|
127
|
+
});
|
|
128
|
+
//# sourceMappingURL=change-file-validator.js.map
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import log from 'sap/base/Log';
|
|
2
|
+
import { MessageBarType } from '@sap-ux-private/control-property-editor-common';
|
|
3
|
+
|
|
4
|
+
import { sendInfoCenterMessage } from '../utils/info-center-message';
|
|
5
|
+
|
|
6
|
+
const CHANGE_TYPE = {
|
|
7
|
+
addXML: 'addXML',
|
|
8
|
+
codeExt: 'codeExt'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type FlexChangeType = (typeof CHANGE_TYPE)[keyof typeof CHANGE_TYPE];
|
|
12
|
+
|
|
13
|
+
interface ChangeContent {
|
|
14
|
+
fragmentPath?: string;
|
|
15
|
+
codeRef?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface Change {
|
|
19
|
+
changeType: string;
|
|
20
|
+
fileName: string;
|
|
21
|
+
fileType?: string;
|
|
22
|
+
reference: string;
|
|
23
|
+
moduleName?: string;
|
|
24
|
+
content?: ChangeContent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface OrphanedChangeEntry {
|
|
28
|
+
changeFileName: string;
|
|
29
|
+
filePath: string;
|
|
30
|
+
changeType: FlexChangeType;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface RelevantChange extends Change {
|
|
34
|
+
changeType: FlexChangeType;
|
|
35
|
+
reference: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Type guard for changes that reference a fragment or controller extension file.
|
|
40
|
+
*
|
|
41
|
+
* @param change flex change object
|
|
42
|
+
* @returns true if the change is an addXML with fragmentPath or a codeExt with codeRef
|
|
43
|
+
*/
|
|
44
|
+
function isFragmentOrCodeExtChange(change: Change): change is RelevantChange {
|
|
45
|
+
return (
|
|
46
|
+
!!change.reference &&
|
|
47
|
+
((change.changeType === CHANGE_TYPE.addXML && !!change.content?.fragmentPath) ||
|
|
48
|
+
(change.changeType === CHANGE_TYPE.codeExt && !!change.content?.codeRef))
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Builds a lookup map from module name patterns to change metadata
|
|
54
|
+
* for addXML and codeExt changes.
|
|
55
|
+
*
|
|
56
|
+
* @param changes record of change objects keyed by flex key
|
|
57
|
+
* @returns map from module name substring to orphaned change entry
|
|
58
|
+
*/
|
|
59
|
+
function buildModuleNameMap(changes: Record<string, Change>): Map<string, OrphanedChangeEntry> {
|
|
60
|
+
const map = new Map<string, OrphanedChangeEntry>();
|
|
61
|
+
|
|
62
|
+
for (const change of Object.values(changes)) {
|
|
63
|
+
if (!isFragmentOrCodeExtChange(change)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const prefix = change.reference.replaceAll('.', '/');
|
|
68
|
+
const path = change.changeType === CHANGE_TYPE.addXML ? change.content?.fragmentPath ?? '' : change.content?.codeRef ?? '';
|
|
69
|
+
const changeFileName = `${change.fileName}.${change.fileType ?? 'change'}`;
|
|
70
|
+
const key = change.moduleName ?? `${prefix}/changes/${path}`;
|
|
71
|
+
|
|
72
|
+
map.set(key, { changeFileName, filePath: path, changeType: change.changeType });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return map;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Creates an error handler that matches error messages against known module names
|
|
80
|
+
* and sends InfoCenter errors for orphaned change files.
|
|
81
|
+
*
|
|
82
|
+
* @param moduleNameMap map from module name substring to orphaned change entry
|
|
83
|
+
* @returns error handler function
|
|
84
|
+
*/
|
|
85
|
+
function createErrorHandler(
|
|
86
|
+
moduleNameMap: Map<string, OrphanedChangeEntry>,
|
|
87
|
+
restoreConsole: () => void
|
|
88
|
+
): (message: string) => void {
|
|
89
|
+
return (message: string) => {
|
|
90
|
+
for (const [moduleName, entry] of moduleNameMap) {
|
|
91
|
+
if (message.includes(moduleName)) {
|
|
92
|
+
sendInfoCenterMessage({
|
|
93
|
+
title: { key: 'ADP_ORPHANED_CHANGE_ERROR_TITLE' },
|
|
94
|
+
description: {
|
|
95
|
+
key: 'ADP_ORPHANED_FILE_DESCRIPTION',
|
|
96
|
+
params: [entry.filePath, entry.changeFileName]
|
|
97
|
+
},
|
|
98
|
+
type: MessageBarType.error
|
|
99
|
+
}).catch((error) => {
|
|
100
|
+
log.error('Failed to send orphaned change InfoCenter message', error);
|
|
101
|
+
});
|
|
102
|
+
moduleNameMap.delete(moduleName);
|
|
103
|
+
if (moduleNameMap.size === 0) {
|
|
104
|
+
restoreConsole();
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Initializes orphaned change file detection.
|
|
114
|
+
*
|
|
115
|
+
* Fetches loaded flex changes, builds a lookup map of module names for addXML and codeExt changes,
|
|
116
|
+
* and wraps console.error to intercept UI5 flex change application errors. When UI5 fails to load
|
|
117
|
+
* a fragment or controller extension referenced by a change file, the error is intercepted and an
|
|
118
|
+
* actionable message is shown in the InfoCenter advising the user to delete the orphaned change file.
|
|
119
|
+
*/
|
|
120
|
+
export async function initOrphanedChangeDetection(): Promise<void> {
|
|
121
|
+
const baseUrl = document.getElementById('sap-ui-bootstrap')?.dataset.openUxPreviewBaseUrl ?? '';
|
|
122
|
+
const response = await fetch(`${baseUrl}/preview/api/changes`, {
|
|
123
|
+
method: 'GET',
|
|
124
|
+
headers: { 'content-type': 'application/json' }
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (!response.ok) {
|
|
128
|
+
log.error(`Failed to fetch changes for orphaned change detection: ${response.status}`);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const changes = (await response.json()) as Record<string, Change>;
|
|
133
|
+
const moduleNameMap = buildModuleNameMap(changes);
|
|
134
|
+
|
|
135
|
+
if (moduleNameMap.size === 0) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const consoleRef = globalThis.console;
|
|
140
|
+
const originalConsoleError = consoleRef.error;
|
|
141
|
+
|
|
142
|
+
const restore = (): void => {
|
|
143
|
+
consoleRef.error = originalConsoleError;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const handler = createErrorHandler(moduleNameMap, restore);
|
|
147
|
+
|
|
148
|
+
const safetyTimeout = setTimeout(restore, 60_000);
|
|
149
|
+
|
|
150
|
+
consoleRef.error = (...args: unknown[]) => {
|
|
151
|
+
originalConsoleError.apply(consoleRef, args);
|
|
152
|
+
const message = args.filter((arg): arg is string => typeof arg === 'string').join('');
|
|
153
|
+
handler(message);
|
|
154
|
+
if (moduleNameMap.size === 0) {
|
|
155
|
+
clearTimeout(safetyTimeout);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-private/control-property-editor-common", "../utils/version", "../cpe/init", "./sync-views-utils", "../utils/application", "./quick-actions/load", "./init-dialogs", "../utils/info-center-message", "../cpe/communication-service"], function (log, ___sap_ux_private_control_property_editor_common, ___utils_version, __init, ___sync_views_utils, ___utils_application, ___quick_actions_load, ___init_dialogs, ___utils_info_center_message, ___cpe_communication_service) {
|
|
3
|
+
sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-private/control-property-editor-common", "../utils/version", "../cpe/init", "./sync-views-utils", "../utils/application", "./quick-actions/load", "./init-dialogs", "../utils/info-center-message", "../cpe/communication-service", "./change-file-validator"], function (log, ___sap_ux_private_control_property_editor_common, ___utils_version, __init, ___sync_views_utils, ___utils_application, ___quick_actions_load, ___init_dialogs, ___utils_info_center_message, ___cpe_communication_service, ___change_file_validator) {
|
|
4
4
|
"use strict";
|
|
5
5
|
|
|
6
6
|
function _interopRequireDefault(obj) {
|
|
@@ -38,6 +38,7 @@ sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-privat
|
|
|
38
38
|
const initDialogs = ___init_dialogs["initDialogs"];
|
|
39
39
|
const sendInfoCenterMessage = ___utils_info_center_message["sendInfoCenterMessage"];
|
|
40
40
|
const CommunicationService = ___cpe_communication_service["CommunicationService"];
|
|
41
|
+
const initOrphanedChangeDetection = ___change_file_validator["initOrphanedChangeDetection"];
|
|
41
42
|
var __exports = async function (rta) {
|
|
42
43
|
const flexSettings = rta.getFlexSettings();
|
|
43
44
|
if (flexSettings.telemetry === true) {
|
|
@@ -104,6 +105,9 @@ sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-privat
|
|
|
104
105
|
CommunicationService.sendAction(toggleAppPreviewVisibility(false));
|
|
105
106
|
return;
|
|
106
107
|
}
|
|
108
|
+
initOrphanedChangeDetection().catch(error => {
|
|
109
|
+
log.error('Failed to run orphaned change detection', error);
|
|
110
|
+
});
|
|
107
111
|
log.debug('ADP init executed.');
|
|
108
112
|
};
|
|
109
113
|
return __exports;
|
|
@@ -23,6 +23,7 @@ import { loadDefinitions } from './quick-actions/load';
|
|
|
23
23
|
import { initDialogs } from './init-dialogs';
|
|
24
24
|
import { sendInfoCenterMessage } from '../utils/info-center-message';
|
|
25
25
|
import { CommunicationService } from '../cpe/communication-service';
|
|
26
|
+
import { initOrphanedChangeDetection } from './change-file-validator';
|
|
26
27
|
|
|
27
28
|
export default async function (rta: RuntimeAuthoring) {
|
|
28
29
|
const flexSettings = rta.getFlexSettings();
|
|
@@ -88,5 +89,9 @@ export default async function (rta: RuntimeAuthoring) {
|
|
|
88
89
|
return;
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
initOrphanedChangeDetection().catch((error) => {
|
|
93
|
+
log.error('Failed to run orphaned change detection', error);
|
|
94
|
+
});
|
|
95
|
+
|
|
91
96
|
log.debug('ADP init executed.');
|
|
92
97
|
}
|
|
@@ -370,6 +370,88 @@ sap.ui.define(["open/ux/preview/client/thirdparty/@sap-ux-private/control-proper
|
|
|
370
370
|
}
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Build a PendingGenericChange and track config change path if applicable.
|
|
375
|
+
*
|
|
376
|
+
* @param changeDefinition - change definition object
|
|
377
|
+
* @param changeType - the change type string
|
|
378
|
+
* @param handler - the generic change handler
|
|
379
|
+
* @param isActive - whether the change is currently active
|
|
380
|
+
* @param fileName - file name of the change
|
|
381
|
+
* @param textBundle - i18n text bundle
|
|
382
|
+
* @returns Promise resolving to PendingGenericChange
|
|
383
|
+
*/
|
|
384
|
+
async buildGenericChange(changeDefinition, changeType, handler, isActive, fileName, textBundle) {
|
|
385
|
+
const {
|
|
386
|
+
properties,
|
|
387
|
+
changeTitle,
|
|
388
|
+
controlId,
|
|
389
|
+
changeType: type,
|
|
390
|
+
subtitle
|
|
391
|
+
} = await handler(changeDefinition, {
|
|
392
|
+
textBundle,
|
|
393
|
+
appComponent: this.options.rta.getRootControlInstance(),
|
|
394
|
+
configPropertyControlIdMap: this.configPropertyControlIdMap
|
|
395
|
+
});
|
|
396
|
+
const genericChange = {
|
|
397
|
+
kind: GENERIC_CHANGE_KIND,
|
|
398
|
+
type: 'pending',
|
|
399
|
+
changeType: type ?? changeType,
|
|
400
|
+
...(subtitle && {
|
|
401
|
+
subtitle
|
|
402
|
+
}),
|
|
403
|
+
isActive,
|
|
404
|
+
title: textBundle.getText(changeTitle),
|
|
405
|
+
fileName,
|
|
406
|
+
...(controlId && {
|
|
407
|
+
controlId
|
|
408
|
+
}),
|
|
409
|
+
properties
|
|
410
|
+
};
|
|
411
|
+
if (changeType === 'appdescr_fe_changePageConfiguration') {
|
|
412
|
+
const configChangePath = changeDefinition.content.entityPropertyChange.propertyPath;
|
|
413
|
+
if (genericChange.isActive) {
|
|
414
|
+
this.configPropertyPath.add(configChangePath);
|
|
415
|
+
} else {
|
|
416
|
+
// remove value from set if change is undone
|
|
417
|
+
this.configPropertyPath.delete(configChangePath);
|
|
418
|
+
}
|
|
419
|
+
this.trackPendingConfigChanges(genericChange);
|
|
420
|
+
}
|
|
421
|
+
return genericChange;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Build a fallback PendingChange for changes without a registered handler.
|
|
426
|
+
*
|
|
427
|
+
* @param changeType - the change type string
|
|
428
|
+
* @param selectorId - optional selector/control ID
|
|
429
|
+
* @param isActive - whether the change is currently active
|
|
430
|
+
* @param fileName - file name of the change
|
|
431
|
+
* @returns PendingChange
|
|
432
|
+
*/
|
|
433
|
+
buildFallbackChange(changeType, selectorId, isActive, fileName) {
|
|
434
|
+
const title = TITLE_MAP[changeType] ?? '';
|
|
435
|
+
let result = {
|
|
436
|
+
type: PENDING_CHANGE_TYPE,
|
|
437
|
+
kind: UNKNOWN_CHANGE_KIND,
|
|
438
|
+
...(title && {
|
|
439
|
+
title
|
|
440
|
+
}),
|
|
441
|
+
changeType,
|
|
442
|
+
isActive,
|
|
443
|
+
fileName
|
|
444
|
+
};
|
|
445
|
+
if (selectorId) {
|
|
446
|
+
result = {
|
|
447
|
+
...result,
|
|
448
|
+
kind: 'control',
|
|
449
|
+
controlId: selectorId
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
return result;
|
|
453
|
+
}
|
|
454
|
+
|
|
373
455
|
/**
|
|
374
456
|
* Prepares the type of change based on the command and other parameters.
|
|
375
457
|
*
|
|
@@ -391,65 +473,11 @@ sap.ui.define(["open/ux/preview/client/thirdparty/@sap-ux-private/control-proper
|
|
|
391
473
|
fileName
|
|
392
474
|
} = changeDefinition;
|
|
393
475
|
const handler = GENERIC_CHANGE_HANDLER[changeType];
|
|
476
|
+
const isActive = index >= inactiveCommandCount;
|
|
394
477
|
if (handler) {
|
|
395
|
-
|
|
396
|
-
properties,
|
|
397
|
-
changeTitle,
|
|
398
|
-
controlId,
|
|
399
|
-
changeType: type,
|
|
400
|
-
subtitle
|
|
401
|
-
} = await handler(changeDefinition, {
|
|
402
|
-
textBundle,
|
|
403
|
-
appComponent: this.options.rta.getRootControlInstance(),
|
|
404
|
-
configPropertyControlIdMap: this.configPropertyControlIdMap
|
|
405
|
-
});
|
|
406
|
-
const genericChange = {
|
|
407
|
-
kind: GENERIC_CHANGE_KIND,
|
|
408
|
-
type: 'pending',
|
|
409
|
-
changeType: type ?? changeType,
|
|
410
|
-
...(subtitle && {
|
|
411
|
-
subtitle
|
|
412
|
-
}),
|
|
413
|
-
isActive: index >= inactiveCommandCount,
|
|
414
|
-
title: textBundle.getText(changeTitle),
|
|
415
|
-
fileName,
|
|
416
|
-
...(controlId && {
|
|
417
|
-
controlId
|
|
418
|
-
}),
|
|
419
|
-
properties
|
|
420
|
-
};
|
|
421
|
-
if (changeType === 'appdescr_fe_changePageConfiguration') {
|
|
422
|
-
const configChangePath = changeDefinition.content.entityPropertyChange.propertyPath;
|
|
423
|
-
if (genericChange.isActive) {
|
|
424
|
-
this.configPropertyPath.add(configChangePath);
|
|
425
|
-
} else {
|
|
426
|
-
// remove value from set if change is undone
|
|
427
|
-
this.configPropertyPath.delete(configChangePath);
|
|
428
|
-
}
|
|
429
|
-
this.trackPendingConfigChanges(genericChange);
|
|
430
|
-
}
|
|
431
|
-
return genericChange;
|
|
432
|
-
} else {
|
|
433
|
-
const title = TITLE_MAP[changeType] ?? '';
|
|
434
|
-
let result = {
|
|
435
|
-
type: PENDING_CHANGE_TYPE,
|
|
436
|
-
kind: UNKNOWN_CHANGE_KIND,
|
|
437
|
-
...(title && {
|
|
438
|
-
title
|
|
439
|
-
}),
|
|
440
|
-
changeType,
|
|
441
|
-
isActive: index >= inactiveCommandCount,
|
|
442
|
-
fileName
|
|
443
|
-
};
|
|
444
|
-
if (selectorId) {
|
|
445
|
-
result = {
|
|
446
|
-
...result,
|
|
447
|
-
kind: 'control',
|
|
448
|
-
controlId: selectorId
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
return result;
|
|
478
|
+
return this.buildGenericChange(changeDefinition, changeType, handler, isActive, fileName, textBundle);
|
|
452
479
|
}
|
|
480
|
+
return this.buildFallbackChange(changeType, selectorId, isActive, fileName);
|
|
453
481
|
}
|
|
454
482
|
|
|
455
483
|
/**
|
|
@@ -433,6 +433,94 @@ export class ChangeService extends EventTarget {
|
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Build a PendingGenericChange and track config change path if applicable.
|
|
438
|
+
*
|
|
439
|
+
* @param changeDefinition - change definition object
|
|
440
|
+
* @param changeType - the change type string
|
|
441
|
+
* @param handler - the generic change handler
|
|
442
|
+
* @param isActive - whether the change is currently active
|
|
443
|
+
* @param fileName - file name of the change
|
|
444
|
+
* @param textBundle - i18n text bundle
|
|
445
|
+
* @returns Promise resolving to PendingGenericChange
|
|
446
|
+
*/
|
|
447
|
+
private async buildGenericChange(
|
|
448
|
+
changeDefinition: ChangeDefinition,
|
|
449
|
+
changeType: string,
|
|
450
|
+
handler: ChangeHandler<GenericChange>,
|
|
451
|
+
isActive: boolean,
|
|
452
|
+
fileName: string,
|
|
453
|
+
textBundle: Awaited<ReturnType<typeof getTextBundle>>
|
|
454
|
+
): Promise<PendingGenericChange> {
|
|
455
|
+
const {
|
|
456
|
+
properties,
|
|
457
|
+
changeTitle,
|
|
458
|
+
controlId,
|
|
459
|
+
changeType: type,
|
|
460
|
+
subtitle
|
|
461
|
+
} = await handler(changeDefinition as unknown as GenericChange, {
|
|
462
|
+
textBundle,
|
|
463
|
+
appComponent: this.options.rta.getRootControlInstance(),
|
|
464
|
+
configPropertyControlIdMap: this.configPropertyControlIdMap
|
|
465
|
+
});
|
|
466
|
+
const genericChange: PendingGenericChange = {
|
|
467
|
+
kind: GENERIC_CHANGE_KIND,
|
|
468
|
+
type: 'pending',
|
|
469
|
+
changeType: type ?? changeType,
|
|
470
|
+
...(subtitle && { subtitle }),
|
|
471
|
+
isActive,
|
|
472
|
+
title: textBundle.getText(changeTitle),
|
|
473
|
+
fileName,
|
|
474
|
+
...(controlId && { controlId }),
|
|
475
|
+
properties
|
|
476
|
+
};
|
|
477
|
+
if (changeType === 'appdescr_fe_changePageConfiguration') {
|
|
478
|
+
const configChangePath = (changeDefinition as ConfigChange).content.entityPropertyChange.propertyPath;
|
|
479
|
+
if (genericChange.isActive) {
|
|
480
|
+
this.configPropertyPath.add(configChangePath);
|
|
481
|
+
} else {
|
|
482
|
+
// remove value from set if change is undone
|
|
483
|
+
this.configPropertyPath.delete(configChangePath);
|
|
484
|
+
}
|
|
485
|
+
this.trackPendingConfigChanges(genericChange);
|
|
486
|
+
}
|
|
487
|
+
return genericChange;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Build a fallback PendingChange for changes without a registered handler.
|
|
492
|
+
*
|
|
493
|
+
* @param changeType - the change type string
|
|
494
|
+
* @param selectorId - optional selector/control ID
|
|
495
|
+
* @param isActive - whether the change is currently active
|
|
496
|
+
* @param fileName - file name of the change
|
|
497
|
+
* @returns PendingChange
|
|
498
|
+
*/
|
|
499
|
+
private buildFallbackChange(
|
|
500
|
+
changeType: string,
|
|
501
|
+
selectorId: string | undefined,
|
|
502
|
+
isActive: boolean,
|
|
503
|
+
fileName: string
|
|
504
|
+
): PendingChange {
|
|
505
|
+
const title = TITLE_MAP[changeType] ?? '';
|
|
506
|
+
let result: PendingChange = {
|
|
507
|
+
type: PENDING_CHANGE_TYPE,
|
|
508
|
+
kind: UNKNOWN_CHANGE_KIND,
|
|
509
|
+
...(title && { title }),
|
|
510
|
+
changeType,
|
|
511
|
+
isActive,
|
|
512
|
+
fileName
|
|
513
|
+
};
|
|
514
|
+
if (selectorId) {
|
|
515
|
+
result = {
|
|
516
|
+
...result,
|
|
517
|
+
kind: 'control',
|
|
518
|
+
controlId: selectorId
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
return result;
|
|
522
|
+
}
|
|
523
|
+
|
|
436
524
|
/**
|
|
437
525
|
* Prepares the type of change based on the command and other parameters.
|
|
438
526
|
*
|
|
@@ -462,60 +550,11 @@ export class ChangeService extends EventTarget {
|
|
|
462
550
|
const changeDefinition = change.getDefinition ? change.getDefinition() : (change.getJson() as ChangeDefinition);
|
|
463
551
|
const { fileName } = changeDefinition;
|
|
464
552
|
const handler = GENERIC_CHANGE_HANDLER[changeType as ChangeType] as unknown as ChangeHandler<GenericChange>;
|
|
553
|
+
const isActive = index >= inactiveCommandCount;
|
|
465
554
|
if (handler) {
|
|
466
|
-
|
|
467
|
-
properties,
|
|
468
|
-
changeTitle,
|
|
469
|
-
controlId,
|
|
470
|
-
changeType: type,
|
|
471
|
-
subtitle
|
|
472
|
-
} = await handler(changeDefinition as unknown as GenericChange, {
|
|
473
|
-
textBundle,
|
|
474
|
-
appComponent: this.options.rta.getRootControlInstance(),
|
|
475
|
-
configPropertyControlIdMap: this.configPropertyControlIdMap
|
|
476
|
-
});
|
|
477
|
-
const genericChange: PendingGenericChange = {
|
|
478
|
-
kind: GENERIC_CHANGE_KIND,
|
|
479
|
-
type: 'pending',
|
|
480
|
-
changeType: type ?? changeType,
|
|
481
|
-
...(subtitle && { subtitle }),
|
|
482
|
-
isActive: index >= inactiveCommandCount,
|
|
483
|
-
title: textBundle.getText(changeTitle),
|
|
484
|
-
fileName,
|
|
485
|
-
...(controlId && { controlId }),
|
|
486
|
-
properties
|
|
487
|
-
};
|
|
488
|
-
if (changeType === 'appdescr_fe_changePageConfiguration') {
|
|
489
|
-
const configChangePath = (changeDefinition as ConfigChange).content.entityPropertyChange.propertyPath;
|
|
490
|
-
if (genericChange.isActive) {
|
|
491
|
-
this.configPropertyPath.add(configChangePath);
|
|
492
|
-
} else {
|
|
493
|
-
// remove value from set if change is undone
|
|
494
|
-
this.configPropertyPath.delete(configChangePath);
|
|
495
|
-
}
|
|
496
|
-
this.trackPendingConfigChanges(genericChange);
|
|
497
|
-
}
|
|
498
|
-
return genericChange;
|
|
499
|
-
} else {
|
|
500
|
-
const title = TITLE_MAP[changeType] ?? '';
|
|
501
|
-
let result: PendingChange = {
|
|
502
|
-
type: PENDING_CHANGE_TYPE,
|
|
503
|
-
kind: UNKNOWN_CHANGE_KIND,
|
|
504
|
-
...(title && { title }),
|
|
505
|
-
changeType,
|
|
506
|
-
isActive: index >= inactiveCommandCount,
|
|
507
|
-
fileName
|
|
508
|
-
};
|
|
509
|
-
|
|
510
|
-
if (selectorId) {
|
|
511
|
-
result = {
|
|
512
|
-
...result,
|
|
513
|
-
kind: 'control',
|
|
514
|
-
controlId: selectorId
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
return result;
|
|
555
|
+
return this.buildGenericChange(changeDefinition, changeType, handler, isActive, fileName, textBundle);
|
|
518
556
|
}
|
|
557
|
+
return this.buildFallbackChange(changeType, selectorId, isActive, fileName);
|
|
519
558
|
}
|
|
520
559
|
|
|
521
560
|
/**
|