@sap-ux/preview-middleware 0.20.47 → 0.20.49

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 (25) hide show
  1. package/dist/base/config.d.ts +7 -0
  2. package/dist/base/config.js +10 -0
  3. package/dist/base/flp.js +4 -3
  4. package/dist/client/adp/command-executor.ts +1 -1
  5. package/dist/client/adp/controllers/AddCustomFragment.controller.js +92 -0
  6. package/dist/client/adp/controllers/AddCustomFragment.controller.ts +152 -0
  7. package/dist/client/adp/controllers/AddFragment.controller.js +5 -5
  8. package/dist/client/adp/controllers/AddFragment.controller.ts +5 -5
  9. package/dist/client/adp/controllers/AddSubpage.controller.js +1 -1
  10. package/dist/client/adp/controllers/AddSubpage.controller.ts +1 -1
  11. package/dist/client/adp/controllers/AddTableColumnFragments.controller.js +4 -4
  12. package/dist/client/adp/controllers/AddTableColumnFragments.controller.ts +5 -5
  13. package/dist/client/adp/controllers/BaseDialog.controller.js +22 -10
  14. package/dist/client/adp/controllers/BaseDialog.controller.ts +35 -13
  15. package/dist/client/adp/dialog-factory.js +9 -1
  16. package/dist/client/adp/dialog-factory.ts +23 -5
  17. package/dist/client/adp/quick-actions/fe-v4/op-add-custom-section.js +72 -0
  18. package/dist/client/adp/quick-actions/fe-v4/op-add-custom-section.ts +90 -0
  19. package/dist/client/adp/quick-actions/fe-v4/registry.js +2 -2
  20. package/dist/client/adp/quick-actions/fe-v4/registry.ts +1 -1
  21. package/dist/client/adp/ui/AddCustomFragment.fragment.xml +42 -0
  22. package/dist/client/flp/initConnectors.js +1 -1
  23. package/dist/client/flp/initConnectors.ts +1 -1
  24. package/dist/client/tsconfig.tsbuildinfo +1 -0
  25. package/package.json +5 -5
@@ -88,6 +88,13 @@ export declare const DEFAULT_PATH: DefaultFlpPath;
88
88
  * Default intent
89
89
  */
90
90
  export declare const DEFAULT_INTENT: Readonly<DefaultIntent>;
91
+ /**
92
+ * Type guard for FlexConnector.
93
+ *
94
+ * @param connector - the connector to check
95
+ * @returns true if the connector is a FlexConnector, false otherwise
96
+ */
97
+ export declare function isFlexConnector(connector: FlexConnector | CustomConnector): connector is FlexConnector;
91
98
  /**
92
99
  * Default configuration for the FLP.
93
100
  *
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_INTENT = exports.DEFAULT_PATH = exports.DEFAULT_THEME = exports.CARD_GENERATOR_DEFAULT = exports.PREVIEW_URL = void 0;
4
+ exports.isFlexConnector = isFlexConnector;
4
5
  exports.getFlpConfigWithDefaults = getFlpConfigWithDefaults;
5
6
  exports.sanitizeConfig = sanitizeConfig;
6
7
  exports.sanitizeRtaConfig = sanitizeRtaConfig;
@@ -77,6 +78,15 @@ const UI5_LIBS = [
77
78
  'sap.webanalytics',
78
79
  'sap.zen'
79
80
  ];
81
+ /**
82
+ * Type guard for FlexConnector.
83
+ *
84
+ * @param connector - the connector to check
85
+ * @returns true if the connector is a FlexConnector, false otherwise
86
+ */
87
+ function isFlexConnector(connector) {
88
+ return 'connector' in connector;
89
+ }
80
90
  /**
81
91
  * Gets the UI5 libs dependencies from manifest.json.
82
92
  *
package/dist/base/flp.js CHANGED
@@ -186,15 +186,16 @@ class FlpSandbox {
186
186
  * @private
187
187
  */
188
188
  checkDeleteConnectors(ui5VersionMajor, ui5VersionMinor) {
189
- if (ui5VersionMajor === 1 && ui5VersionMinor < 78) {
190
- this.templateConfig.ui5.flex?.splice(1, 1);
189
+ if (ui5VersionMajor === 1 && ui5VersionMinor < 76) {
190
+ this.templateConfig.ui5.flex = this.templateConfig.ui5.flex.filter((connector) => (0, config_1.isFlexConnector)(connector));
191
191
  this.logger.debug(`The Fiori Tools local connector (WorkspaceConnector) is not being used because the current UI5 version does not support it. The Fiori Tools fake connector (FakeLrepConnector) will be used instead.`);
192
192
  }
193
193
  else {
194
194
  this.logger.debug(`The Fiori Tools local connector (WorkspaceConnector) is being used.`);
195
195
  }
196
196
  if (this.projectType === 'CAPJava' || this.projectType === 'CAPNodejs') {
197
- this.templateConfig.ui5.flex?.splice(0, 1);
197
+ this.templateConfig.ui5.flex = this.templateConfig.ui5.flex.filter((connector) => !(0, config_1.isFlexConnector)(connector) ||
198
+ ((0, config_1.isFlexConnector)(connector) && !connector.url?.startsWith('/sap/bc/lrep')));
198
199
  this.logger.debug(`The ABAP connector is not being used because the current project type is '${this.projectType}'.`);
199
200
  }
200
201
  else {
@@ -8,7 +8,7 @@ import type DesignTimeMetadata from 'sap/ui/dt/DesignTimeMetadata';
8
8
  import type FlexCommand from 'sap/ui/rta/command/FlexCommand';
9
9
  import { getError } from '../utils/error';
10
10
 
11
- type CommandNames = 'addXML' | 'codeExt';
11
+ type CommandNames = 'addXML' | 'codeExt' | 'appDescriptor';
12
12
 
13
13
  /**
14
14
  * Class responsible for handling rta calls
@@ -0,0 +1,92 @@
1
+ 'use strict';
2
+ sap.ui.define([
3
+ 'sap/ui/model/json/JSONModel',
4
+ '../../i18n',
5
+ '../command-executor',
6
+ '../api-handler',
7
+ './BaseDialog.controller',
8
+ '../utils',
9
+ 'open/ux/preview/client/thirdparty/@sap-ux-private/control-property-editor-common',
10
+ '../../cpe/communication-service'
11
+ ], function (JSONModel, ____i18n, __CommandExecutor, ___api_handler, __BaseDialog, ___utils, ___sap_ux_private_control_property_editor_common, ____cpe_communication_service) {
12
+ 'use strict';
13
+ function _interopRequireDefault(obj) {
14
+ return obj && obj.__esModule && typeof obj.default !== 'undefined' ? obj.default : obj;
15
+ }
16
+ const getResourceModel = ____i18n['getResourceModel'];
17
+ const getTextBundle = ____i18n['getTextBundle'];
18
+ const CommandExecutor = _interopRequireDefault(__CommandExecutor);
19
+ const getFragments = ___api_handler['getFragments'];
20
+ const BaseDialog = _interopRequireDefault(__BaseDialog);
21
+ const notifyUser = ___utils['notifyUser'];
22
+ const setApplicationRequiresReload = ___sap_ux_private_control_property_editor_common['setApplicationRequiresReload'];
23
+ const CommunicationService = ____cpe_communication_service['CommunicationService'];
24
+ const AddCustomFragment = BaseDialog.extend('open.ux.preview.client.adp.controllers.AddCustomFragment', {
25
+ constructor: function _constructor(name, overlays, rta, options, telemetryData) {
26
+ BaseDialog.prototype.constructor.call(this, name, telemetryData);
27
+ this.options = options;
28
+ this.rta = rta;
29
+ this.overlays = overlays;
30
+ this.model = new JSONModel({ title: options.title });
31
+ this.commandExecutor = new CommandExecutor(this.rta);
32
+ },
33
+ setup: async function _setup(dialog) {
34
+ this.dialog = dialog;
35
+ this.setEscapeHandler();
36
+ await this.buildDialogData();
37
+ const resourceModel = await getResourceModel('open.ux.preview.client');
38
+ this.dialog.setModel(resourceModel, 'i18n');
39
+ this.dialog.setModel(this.model);
40
+ this.dialog.open();
41
+ },
42
+ onCreateBtnPress: async function _onCreateBtnPress(event) {
43
+ const source = event.getSource();
44
+ source.setEnabled(false);
45
+ await BaseDialog.prototype.onCreateBtnPressHandler.call(this);
46
+ const fragmentName = this.model.getProperty('/newFragmentName');
47
+ const template = `fragments.${ fragmentName }`;
48
+ await this.createAppDescriptorChangeForV4(template);
49
+ CommunicationService.sendAction(setApplicationRequiresReload(true));
50
+ const bundle = await getTextBundle();
51
+ notifyUser(bundle.getText('ADP_ADD_FRAGMENT_NOTIFICATION', [fragmentName]), 8000);
52
+ this.handleDialogClose();
53
+ },
54
+ buildDialogData: async function _buildDialogData() {
55
+ try {
56
+ const {fragments} = await getFragments();
57
+ this.model.setProperty('/fragmentList', fragments);
58
+ } catch (e) {
59
+ this.handleError(e);
60
+ }
61
+ },
62
+ createAppDescriptorChangeForV4: async function _createAppDescriptorChangeForV(templatePath) {
63
+ const fragmentName = this.model.getProperty('/newFragmentName');
64
+ const template = `${ this.options.appDescriptor?.projectId }.changes.${ templatePath }`;
65
+ let sectionId = this.options.appDescriptor?.anchor;
66
+ const flexSettings = this.rta.getFlexSettings();
67
+ const modifiedValue = {
68
+ reference: this.options.appDescriptor?.projectId,
69
+ appComponent: this.options.appDescriptor?.appComponent,
70
+ changeType: 'appdescr_fe_changePageConfiguration',
71
+ parameters: {
72
+ page: this.options.appDescriptor?.pageId,
73
+ entityPropertyChange: {
74
+ propertyPath: `${ this.options.propertyPath }${ fragmentName }`,
75
+ operation: 'UPSERT',
76
+ propertyValue: {
77
+ template,
78
+ title: 'New Custom Section',
79
+ position: {
80
+ placement: 'After',
81
+ anchor: `${ sectionId }`
82
+ }
83
+ }
84
+ }
85
+ }
86
+ };
87
+ const command = await this.commandExecutor.getCommand(this.getRuntimeControl(), 'appDescriptor', modifiedValue, flexSettings);
88
+ await this.commandExecutor.pushAndExecuteCommand(command);
89
+ }
90
+ });
91
+ return AddCustomFragment;
92
+ });
@@ -0,0 +1,152 @@
1
+ /** sap.m */
2
+ import Button from 'sap/m/Button';
3
+ import type Dialog from 'sap/m/Dialog';
4
+
5
+ /** sap.ui.core */
6
+ import type UI5Element from 'sap/ui/core/Element';
7
+
8
+ /** sap.ui.base */
9
+ import type Event from 'sap/ui/base/Event';
10
+
11
+ /** sap.ui.model */
12
+ import JSONModel from 'sap/ui/model/json/JSONModel';
13
+
14
+ /** sap.ui.rta */
15
+ import type RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
16
+
17
+ import { getResourceModel, getTextBundle } from '../../i18n';
18
+ import CommandExecutor from '../command-executor';
19
+ import { getFragments } from '../api-handler';
20
+ import BaseDialog from './BaseDialog.controller';
21
+ import { notifyUser } from '../utils';
22
+ import { QuickActionTelemetryData } from '../../cpe/quick-actions/quick-action-definition';
23
+ import { setApplicationRequiresReload } from '@sap-ux-private/control-property-editor-common';
24
+ import { CommunicationService } from '../../cpe/communication-service';
25
+ import FlexCommand from 'sap/ui/rta/command/FlexCommand';
26
+ import type AppComponentV4 from 'sap/fe/core/AppComponent';
27
+
28
+ export type AddFragmentModel = JSONModel & {
29
+ getProperty(sPath: '/title'): string;
30
+ getProperty(sPath: '/newFragmentName'): string;
31
+ };
32
+ export interface PageDescriptorV4 {
33
+ appType: 'fe-v4';
34
+ appComponent: AppComponentV4;
35
+ pageId: string;
36
+ projectId: string;
37
+ anchor: string;
38
+ }
39
+
40
+ export interface AddCustomFragmentOptions {
41
+ title: string;
42
+ propertyPath: string;
43
+ appDescriptor?: PageDescriptorV4;
44
+ }
45
+
46
+ /**
47
+ * @namespace open.ux.preview.client.adp.controllers
48
+ */
49
+ export default class AddCustomFragment extends BaseDialog<AddFragmentModel> {
50
+ constructor(
51
+ name: string,
52
+ overlays: UI5Element,
53
+ rta: RuntimeAuthoring,
54
+ readonly options: AddCustomFragmentOptions,
55
+ telemetryData?: QuickActionTelemetryData
56
+ ) {
57
+ super(name, telemetryData);
58
+ this.rta = rta;
59
+ this.overlays = overlays;
60
+ this.model = new JSONModel({
61
+ title: options.title
62
+ });
63
+ this.commandExecutor = new CommandExecutor(this.rta);
64
+ }
65
+
66
+ /**
67
+ * Setups the Dialog and the JSON Model
68
+ *
69
+ * @param {Dialog} dialog - Dialog instance
70
+ */
71
+ async setup(dialog: Dialog): Promise<void> {
72
+ this.dialog = dialog;
73
+
74
+ this.setEscapeHandler();
75
+ await this.buildDialogData();
76
+ const resourceModel = await getResourceModel('open.ux.preview.client');
77
+
78
+ this.dialog.setModel(resourceModel, 'i18n');
79
+ this.dialog.setModel(this.model);
80
+
81
+ this.dialog.open();
82
+ }
83
+
84
+ /**
85
+ * Handles create button press
86
+ *
87
+ * @param event Event
88
+ */
89
+ async onCreateBtnPress(event: Event) {
90
+ const source = event.getSource<Button>();
91
+ source.setEnabled(false);
92
+
93
+ await super.onCreateBtnPressHandler();
94
+
95
+ const fragmentName = this.model.getProperty('/newFragmentName');
96
+ const template = `fragments.${fragmentName}`;
97
+ await this.createAppDescriptorChangeForV4(template);
98
+ CommunicationService.sendAction(setApplicationRequiresReload(true));
99
+
100
+ const bundle = await getTextBundle();
101
+ notifyUser(bundle.getText('ADP_ADD_FRAGMENT_NOTIFICATION', [fragmentName]), 8000);
102
+
103
+ this.handleDialogClose();
104
+ }
105
+
106
+ /**
107
+ * Builds data that is used in the dialog
108
+ */
109
+ async buildDialogData(): Promise<void> {
110
+ try {
111
+ const { fragments } = await getFragments();
112
+ this.model.setProperty('/fragmentList', fragments);
113
+ } catch (e) {
114
+ this.handleError(e);
115
+ }
116
+ }
117
+
118
+ private async createAppDescriptorChangeForV4(templatePath: string) {
119
+ const fragmentName = this.model.getProperty('/newFragmentName');
120
+ const template = `${this.options.appDescriptor?.projectId}.changes.${templatePath}`;
121
+ let sectionId = this.options.appDescriptor?.anchor;
122
+ const flexSettings = this.rta.getFlexSettings();
123
+ const modifiedValue = {
124
+ reference: this.options.appDescriptor?.projectId,
125
+ appComponent: this.options.appDescriptor?.appComponent,
126
+ changeType: 'appdescr_fe_changePageConfiguration',
127
+ parameters: {
128
+ page: this.options.appDescriptor?.pageId,
129
+ entityPropertyChange: {
130
+ propertyPath: `${this.options.propertyPath}${fragmentName}`, // e.g. 'content/body/sections/test'
131
+ operation: 'UPSERT',
132
+ propertyValue: {
133
+ template,
134
+ title: 'New Custom Section',
135
+ position: {
136
+ placement: 'After',
137
+ anchor: `${sectionId}`
138
+ }
139
+ }
140
+ }
141
+ }
142
+ };
143
+ const command = await this.commandExecutor.getCommand<FlexCommand>(
144
+ this.getRuntimeControl(),
145
+ 'appDescriptor',
146
+ modifiedValue,
147
+ flexSettings
148
+ );
149
+
150
+ await this.commandExecutor.pushAndExecuteCommand(command);
151
+ }
152
+ }
@@ -59,7 +59,7 @@ sap.ui.define([
59
59
  }
60
60
  this.model.setProperty('/selectedAggregation/key', selectedKey);
61
61
  this.model.setProperty('/selectedAggregation/value', selectedItemText);
62
- let newSelectedControlChildren = Object.keys(ControlUtils.getControlAggregationByName(this.runtimeControl, selectedItemText));
62
+ let newSelectedControlChildren = Object.keys(ControlUtils.getControlAggregationByName(this.getRuntimeControl(), selectedItemText));
63
63
  newSelectedControlChildren = newSelectedControlChildren.map(key => {
64
64
  return parseInt(key, radix);
65
65
  });
@@ -86,7 +86,7 @@ sap.ui.define([
86
86
  } else {
87
87
  await this.createFragmentChange(modifiedValue);
88
88
  }
89
- const templateName = getFragmentTemplateName(this.runtimeControl.getId(), targetAggregation);
89
+ const templateName = getFragmentTemplateName(this.getRuntimeControl().getId(), targetAggregation);
90
90
  if (templateName) {
91
91
  CommunicationService.sendAction(setApplicationRequiresReload(true));
92
92
  }
@@ -98,7 +98,7 @@ sap.ui.define([
98
98
  const {controlMetadata, targetAggregation} = this.getControlMetadata();
99
99
  const defaultAggregation = this.options.aggregation ?? controlMetadata.getDefaultAggregationName();
100
100
  const selectedControlName = controlMetadata.getName();
101
- let selectedControlChildren = Object.keys(ControlUtils.getControlAggregationByName(this.runtimeControl, defaultAggregation));
101
+ let selectedControlChildren = Object.keys(ControlUtils.getControlAggregationByName(this.getRuntimeControl(), defaultAggregation));
102
102
  selectedControlChildren = selectedControlChildren.map(key => {
103
103
  return parseInt(key, radix);
104
104
  });
@@ -141,9 +141,9 @@ sap.ui.define([
141
141
  },
142
142
  createFragmentChange: async function _createFragmentChange(modifiedValue) {
143
143
  const flexSettings = this.rta.getFlexSettings();
144
- const overlay = OverlayRegistry.getOverlay(this.runtimeControl);
144
+ const overlay = OverlayRegistry.getOverlay(this.getRuntimeControl());
145
145
  const designMetadata = overlay.getDesignTimeMetadata();
146
- const command = await this.commandExecutor.getCommand(this.runtimeControl, 'addXML', modifiedValue, flexSettings, designMetadata);
146
+ const command = await this.commandExecutor.getCommand(this.getRuntimeControl(), 'addXML', modifiedValue, flexSettings, designMetadata);
147
147
  await this.commandExecutor.pushAndExecuteCommand(command);
148
148
  }
149
149
  });
@@ -114,7 +114,7 @@ export default class AddFragment extends BaseDialog<AddFragmentModel> {
114
114
  this.model.setProperty('/selectedAggregation/value', selectedItemText);
115
115
 
116
116
  let newSelectedControlChildren: string[] | number[] = Object.keys(
117
- ControlUtils.getControlAggregationByName(this.runtimeControl, selectedItemText)
117
+ ControlUtils.getControlAggregationByName(this.getRuntimeControl(), selectedItemText)
118
118
  );
119
119
 
120
120
  newSelectedControlChildren = newSelectedControlChildren.map((key) => {
@@ -157,7 +157,7 @@ export default class AddFragment extends BaseDialog<AddFragmentModel> {
157
157
  await this.createFragmentChange(modifiedValue);
158
158
  }
159
159
 
160
- const templateName = getFragmentTemplateName(this.runtimeControl.getId(), targetAggregation);
160
+ const templateName = getFragmentTemplateName(this.getRuntimeControl().getId(), targetAggregation);
161
161
  if (templateName) {
162
162
  CommunicationService.sendAction(setApplicationRequiresReload(true));
163
163
  }
@@ -177,7 +177,7 @@ export default class AddFragment extends BaseDialog<AddFragmentModel> {
177
177
  const selectedControlName = controlMetadata.getName();
178
178
 
179
179
  let selectedControlChildren: string[] | number[] = Object.keys(
180
- ControlUtils.getControlAggregationByName(this.runtimeControl, defaultAggregation)
180
+ ControlUtils.getControlAggregationByName(this.getRuntimeControl(), defaultAggregation)
181
181
  );
182
182
 
183
183
  selectedControlChildren = selectedControlChildren.map((key) => {
@@ -236,11 +236,11 @@ export default class AddFragment extends BaseDialog<AddFragmentModel> {
236
236
  private async createFragmentChange(modifiedValue: DeferredXmlFragmentData): Promise<void> {
237
237
  const flexSettings = this.rta.getFlexSettings();
238
238
 
239
- const overlay = OverlayRegistry.getOverlay(this.runtimeControl as UI5Element);
239
+ const overlay = OverlayRegistry.getOverlay(this.getRuntimeControl() as UI5Element);
240
240
  const designMetadata = overlay.getDesignTimeMetadata();
241
241
 
242
242
  const command = await this.commandExecutor.getCommand<AddFragmentChangeContentType>(
243
- this.runtimeControl,
243
+ this.getRuntimeControl(),
244
244
  'addXML',
245
245
  modifiedValue,
246
246
  flexSettings,
@@ -103,7 +103,7 @@ sap.ui.define([
103
103
  }
104
104
  };
105
105
  }
106
- const command = await CommandFactory.getCommandFor(this.runtimeControl, 'appDescriptor', modifiedValue, null, flexSettings);
106
+ const command = await CommandFactory.getCommandFor(this.getRuntimeControl(), 'appDescriptor', modifiedValue, null, flexSettings);
107
107
  await this.commandExecutor.pushAndExecuteCommand(command);
108
108
  CommunicationService.sendAction(setApplicationRequiresReload(true));
109
109
  this.handleDialogClose();
@@ -179,7 +179,7 @@ export default class AddSubpage extends BaseDialog<AddSubpageModel> {
179
179
  }
180
180
 
181
181
  const command = await CommandFactory.getCommandFor(
182
- this.runtimeControl,
182
+ this.getRuntimeControl(),
183
183
  'appDescriptor',
184
184
  modifiedValue,
185
185
  null,
@@ -80,7 +80,7 @@ sap.ui.define([
80
80
  const {controlMetadata, targetAggregation} = this.getControlMetadata();
81
81
  const defaultAggregation = this.options.aggregation ?? controlMetadata.getDefaultAggregationName();
82
82
  const selectedControlName = controlMetadata.getName();
83
- let selectedControlChildren = Object.keys(ControlUtils.getControlAggregationByName(this.runtimeControl, defaultAggregation));
83
+ let selectedControlChildren = Object.keys(ControlUtils.getControlAggregationByName(this.getRuntimeControl(), defaultAggregation));
84
84
  selectedControlChildren = selectedControlChildren.map(key => {
85
85
  return parseInt(key, radix);
86
86
  });
@@ -149,9 +149,9 @@ sap.ui.define([
149
149
  createFragmentChange: async function _createFragmentChange(fragmentData) {
150
150
  const {fragments, index} = fragmentData;
151
151
  const flexSettings = this.rta.getFlexSettings();
152
- const overlay = OverlayRegistry.getOverlay(this.runtimeControl);
152
+ const overlay = OverlayRegistry.getOverlay(this.getRuntimeControl());
153
153
  const designMetadata = overlay.getDesignTimeMetadata();
154
- const compositeCommand = await this.commandExecutor.createCompositeCommand(this.runtimeControl);
154
+ const compositeCommand = await this.commandExecutor.createCompositeCommand(this.getRuntimeControl());
155
155
  for (const fragment of fragments) {
156
156
  const modifiedValue = {
157
157
  fragment: `<core:FragmentDefinition xmlns:core='sap.ui.core'></core:FragmentDefinition>`,
@@ -159,7 +159,7 @@ sap.ui.define([
159
159
  index: index ?? 0,
160
160
  targetAggregation: fragment.targetAggregation === ITEMS_AGGREGATION ? CELLS_AGGREGATION : fragment.targetAggregation
161
161
  };
162
- const targetObject = fragment.targetAggregation === COLUMNS_AGGREGATION ? this.runtimeControl : this.runtimeControl.getAggregation(ITEMS_AGGREGATION)[0];
162
+ const targetObject = fragment.targetAggregation === COLUMNS_AGGREGATION ? this.getRuntimeControl() : this.getRuntimeControl().getAggregation(ITEMS_AGGREGATION)[0];
163
163
  const command = await this.commandExecutor.getCommand(targetObject, 'addXML', modifiedValue, flexSettings, designMetadata);
164
164
  const templateName = fragment.targetAggregation === COLUMNS_AGGREGATION ? `V2_SMART_TABLE_COLUMN` : 'V2_SMART_TABLE_CELL';
165
165
  const preparedChange = command.getPreparedChange();
@@ -147,7 +147,7 @@ export default class AddTableColumnFragments extends BaseDialog<AddTableColumnsF
147
147
  const selectedControlName = controlMetadata.getName();
148
148
 
149
149
  let selectedControlChildren: string[] | number[] = Object.keys(
150
- ControlUtils.getControlAggregationByName(this.runtimeControl, defaultAggregation)
150
+ ControlUtils.getControlAggregationByName(this.getRuntimeControl(), defaultAggregation)
151
151
  );
152
152
 
153
153
  selectedControlChildren = selectedControlChildren.map((key) => {
@@ -260,10 +260,10 @@ export default class AddTableColumnFragments extends BaseDialog<AddTableColumnsF
260
260
 
261
261
  const flexSettings = this.rta.getFlexSettings();
262
262
 
263
- const overlay = OverlayRegistry.getOverlay(this.runtimeControl as UI5Element);
263
+ const overlay = OverlayRegistry.getOverlay(this.getRuntimeControl() as UI5Element);
264
264
  const designMetadata = overlay.getDesignTimeMetadata();
265
265
 
266
- const compositeCommand = await this.commandExecutor.createCompositeCommand(this.runtimeControl);
266
+ const compositeCommand = await this.commandExecutor.createCompositeCommand(this.getRuntimeControl());
267
267
 
268
268
  for (const fragment of fragments) {
269
269
  const modifiedValue = {
@@ -276,8 +276,8 @@ export default class AddTableColumnFragments extends BaseDialog<AddTableColumnsF
276
276
 
277
277
  const targetObject =
278
278
  fragment.targetAggregation === COLUMNS_AGGREGATION
279
- ? this.runtimeControl
280
- : (this.runtimeControl.getAggregation(ITEMS_AGGREGATION) as ManagedObject[])[0];
279
+ ? this.getRuntimeControl()
280
+ : (this.getRuntimeControl().getAggregation(ITEMS_AGGREGATION) as ManagedObject[])[0];
281
281
 
282
282
  const command = await this.commandExecutor.getCommand<AddTableCellFragmentChangeContentType>(
283
283
  targetObject,
@@ -37,15 +37,21 @@ sap.ui.define([
37
37
  Log.error('Error in reporting Telemetry:', error);
38
38
  }
39
39
  },
40
+ getRuntimeControl: function _getRuntimeControl() {
41
+ if (!this._runtimeControl && this.overlays) {
42
+ const selectorId = this.overlays.getId();
43
+ const overlayControl = getControlById(selectorId);
44
+ if (!overlayControl) {
45
+ throw new Error('Cannot get overlay control');
46
+ }
47
+ this._runtimeControl = ControlUtils.getRuntimeControl(overlayControl);
48
+ }
49
+ return this._runtimeControl;
50
+ },
40
51
  getControlMetadata: function _getControlMetadata() {
41
- const selectorId = this.overlays.getId();
42
- let controlMetadata;
43
- const overlayControl = getControlById(selectorId);
44
- if (overlayControl) {
45
- this.runtimeControl = ControlUtils.getRuntimeControl(overlayControl);
46
- controlMetadata = this.runtimeControl.getMetadata();
47
- } else {
48
- throw new Error('Cannot get overlay control');
52
+ const controlMetadata = this.getRuntimeControl().getMetadata();
53
+ if (!controlMetadata) {
54
+ throw new Error('Cannot get control metadata');
49
55
  }
50
56
  const allAggregations = Object.keys(controlMetadata.getAllAggregations());
51
57
  const hiddenAggregations = [
@@ -123,6 +129,12 @@ sap.ui.define([
123
129
  updateDialogState(ValueState.Error, 'Enter a different name. The fragment name entered matches the name of an unsaved fragment.');
124
130
  return;
125
131
  }
132
+ const template = `${ this.rta.getFlexSettings()?.projectId }.changes.fragments.${ fragmentName }`;
133
+ const v4CustomXMLChange = checkForExistingChange(this.rta, 'appdescr_fe_changePageConfiguration', 'content.entityPropertyChange.propertyValue.template', template);
134
+ if (v4CustomXMLChange) {
135
+ updateDialogState(ValueState.Error, 'Enter a different name. The fragment name entered matches the name of an unsaved fragment.');
136
+ return;
137
+ }
126
138
  updateDialogState(ValueState.Success);
127
139
  this.model.setProperty('/newFragmentName', fragmentName);
128
140
  },
@@ -143,10 +155,10 @@ sap.ui.define([
143
155
  throw error;
144
156
  },
145
157
  specialIndexHandling: function _specialIndexHandling(specialIndexAggregation) {
146
- const overlay = OverlayRegistry.getOverlay(this.runtimeControl);
158
+ const overlay = OverlayRegistry.getOverlay(this.getRuntimeControl());
147
159
  const aggregations = overlay.getDesignTimeMetadata().getData().aggregations;
148
160
  if (specialIndexAggregation in aggregations && 'specialIndexHandling' in aggregations[specialIndexAggregation]) {
149
- const controlType = this.runtimeControl.getMetadata().getName();
161
+ const controlType = this.getRuntimeControl().getMetadata().getName();
150
162
  this.model.setProperty('/indexHandlingFlag', false);
151
163
  this.model.setProperty('/specialIndexHandlingIcon', true);
152
164
  this.model.setProperty('/iconTooltip', `Index is defined by special logic of ${ controlType } and can't be set here`);
@@ -44,7 +44,7 @@ export default abstract class BaseDialog<T extends BaseDialogModel = BaseDialogM
44
44
  /**
45
45
  * Runtime control managed object
46
46
  */
47
- protected runtimeControl: ManagedObject;
47
+ private _runtimeControl: ManagedObject;
48
48
  /**
49
49
  * Dialog instance
50
50
  */
@@ -71,21 +71,26 @@ export default abstract class BaseDialog<T extends BaseDialogModel = BaseDialogM
71
71
  }
72
72
  }
73
73
 
74
+ protected getRuntimeControl(): ManagedObject {
75
+ if (!this._runtimeControl && this.overlays) {
76
+ const selectorId = this.overlays.getId();
77
+ const overlayControl = getControlById(selectorId) as unknown as ElementOverlay;
78
+ if (!overlayControl) {
79
+ throw new Error('Cannot get overlay control');
80
+ }
81
+ this._runtimeControl = ControlUtils.getRuntimeControl(overlayControl);
82
+ }
83
+ return this._runtimeControl;
84
+ }
85
+
74
86
  /**
75
87
  * Method is used in add fragment dialog controllers to get current control metadata which are needed on the dialog
76
88
  * @returns control metadata and target aggregations
77
89
  */
78
90
  protected getControlMetadata(): { controlMetadata: ManagedObjectMetadata; targetAggregation: string[] } {
79
- const selectorId = this.overlays.getId();
80
-
81
- let controlMetadata: ManagedObjectMetadata;
82
-
83
- const overlayControl = getControlById(selectorId) as unknown as ElementOverlay;
84
- if (overlayControl) {
85
- this.runtimeControl = ControlUtils.getRuntimeControl(overlayControl);
86
- controlMetadata = this.runtimeControl.getMetadata();
87
- } else {
88
- throw new Error('Cannot get overlay control');
91
+ const controlMetadata: ManagedObjectMetadata = this.getRuntimeControl().getMetadata();
92
+ if (!controlMetadata) {
93
+ throw new Error('Cannot get control metadata');
89
94
  }
90
95
 
91
96
  const allAggregations = Object.keys(controlMetadata.getAllAggregations());
@@ -181,6 +186,23 @@ export default abstract class BaseDialog<T extends BaseDialogModel = BaseDialogM
181
186
  );
182
187
  return;
183
188
  }
189
+ // 'changes.fragments' is the current folder structure where fragment changes are written.
190
+ // following value is subjected to change if the folder structure changes
191
+ const template = `${this.rta.getFlexSettings()?.projectId}.changes.fragments.${fragmentName}`;
192
+ const v4CustomXMLChange = checkForExistingChange(
193
+ this.rta,
194
+ 'appdescr_fe_changePageConfiguration',
195
+ 'content.entityPropertyChange.propertyValue.template',
196
+ template
197
+ );
198
+
199
+ if (v4CustomXMLChange) {
200
+ updateDialogState(
201
+ ValueState.Error,
202
+ 'Enter a different name. The fragment name entered matches the name of an unsaved fragment.'
203
+ );
204
+ return;
205
+ }
184
206
 
185
207
  updateDialogState(ValueState.Success);
186
208
  this.model.setProperty('/newFragmentName', fragmentName);
@@ -222,14 +244,14 @@ export default abstract class BaseDialog<T extends BaseDialogModel = BaseDialogM
222
244
  * @param specialIndexAggregation string | number
223
245
  */
224
246
  protected specialIndexHandling(specialIndexAggregation: string | number): void {
225
- const overlay = OverlayRegistry.getOverlay(this.runtimeControl as UI5Element);
247
+ const overlay = OverlayRegistry.getOverlay(this.getRuntimeControl() as UI5Element);
226
248
  const aggregations = overlay.getDesignTimeMetadata().getData().aggregations;
227
249
 
228
250
  if (
229
251
  specialIndexAggregation in aggregations &&
230
252
  'specialIndexHandling' in aggregations[specialIndexAggregation]
231
253
  ) {
232
- const controlType = this.runtimeControl.getMetadata().getName();
254
+ const controlType = this.getRuntimeControl().getMetadata().getName();
233
255
  this.model.setProperty('/indexHandlingFlag', false);
234
256
  this.model.setProperty('/specialIndexHandlingIcon', true);
235
257
  this.model.setProperty(