@sap-ux/preview-middleware 0.16.91 → 0.16.93

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.
@@ -2,7 +2,8 @@ import type {
2
2
  ExternalAction,
3
3
  PendingChange,
4
4
  SavedPropertyChange,
5
- UnknownSavedChange
5
+ UnknownSavedChange,
6
+ SavedControlChange
6
7
  } from '@sap-ux-private/control-property-editor-common';
7
8
  import {
8
9
  changeProperty,
@@ -16,13 +17,15 @@ import {
16
17
  } from '@sap-ux-private/control-property-editor-common';
17
18
  import { applyChange } from './flex-change';
18
19
  import type { SelectionService } from '../selection';
19
-
20
20
  import type { ActionSenderFunction, SubscribeFunction, UI5AdaptationOptions } from '../types';
21
21
  import type Event from 'sap/ui/base/Event';
22
22
  import type FlexCommand from 'sap/ui/rta/command/FlexCommand';
23
23
  import Log from 'sap/base/Log';
24
24
  import { modeAndStackChangeHandler } from '../rta-service';
25
+ import JsControlTreeModifier from 'sap/ui/core/util/reflection/JsControlTreeModifier';
26
+ import FlexChange from 'sap/ui/fl/Change';
25
27
  import { getError } from '../../utils/error';
28
+ import { isLowerThanMinimalUi5Version, getUi5Version } from '../../utils/version';
26
29
  import MessageToast from 'sap/m/MessageToast';
27
30
  import { getTextBundle } from '../../i18n';
28
31
 
@@ -94,9 +97,12 @@ function modifyRTAErrorMessage(errorMessage: string, id: string, type: string):
94
97
  * A Class of ChangeService
95
98
  */
96
99
  export class ChangeService {
97
- private savedChanges: SavedPropertyChange[] = [];
100
+ private savedChanges: SavedPropertyChange[] | UnknownSavedChange[] | SavedControlChange[] = [];
98
101
  private changesRequiringReload = 0;
99
102
  private sendAction: (action: ExternalAction) => void;
103
+ private pendingChanges: PendingChange[] = [];
104
+ private changedFiles: Record<string, object> = {};
105
+ private readonly eventStack: object[] = [];
100
106
  /**
101
107
  *
102
108
  * @param options ui5 adaptation options.
@@ -159,11 +165,11 @@ export class ChangeService {
159
165
  *
160
166
  * @param pendingChanges Changes that are waiting to be saved
161
167
  */
162
- private updateStack(pendingChanges: PendingChange[] = []) {
168
+ private updateStack() {
163
169
  this.sendAction(
164
170
  changeStackModified({
165
- saved: this.savedChanges,
166
- pending: pendingChanges
171
+ saved: this.savedChanges ?? [],
172
+ pending: this.pendingChanges ?? []
167
173
  })
168
174
  );
169
175
  }
@@ -172,54 +178,80 @@ export class ChangeService {
172
178
  * Fetches saved changes from the workspace and sorts them.
173
179
  */
174
180
  private async fetchSavedChanges(): Promise<void> {
181
+ this.changedFiles = {};
175
182
  const savedChangesResponse = await fetch(FlexChangesEndPoints.changes + `?_=${Date.now()}`);
176
183
  const savedChanges = (await savedChangesResponse.json()) as SavedChangesResponse;
177
184
  const changes = (
178
- Object.keys(savedChanges ?? {})
179
- .map((key): SavedPropertyChange | UnknownSavedChange | undefined => {
180
- const change: Change = savedChanges[key];
181
- try {
182
- assertChange(change);
183
- if (
184
- [change.content.newValue, change.content.newBinding].every(
185
- (item) => item === undefined || item === null
186
- )
187
- ) {
188
- throw new Error('Invalid change, missing new value in the change file');
189
- }
190
- if (change.changeType !== 'propertyChange' && change.changeType !== 'propertyBindingChange') {
191
- throw new Error('Unknown Change Type');
192
- }
193
- return {
194
- type: 'saved',
195
- kind: 'property',
196
- fileName: change.fileName,
197
- controlId: change.selector.id,
198
- propertyName: change.content.property,
199
- value: change.content.newValue ?? change.content.newBinding,
200
- timestamp: new Date(change.creation).getTime(),
201
- controlName: change.selector.type ? (change.selector.type.split('.').pop() as string) : '',
202
- changeType: change.changeType
203
- };
204
- } catch (error) {
205
- // Gracefully handle change files with invalid content
206
- if (change.fileName) {
207
- const unknownChange: UnknownSavedChange = {
208
- type: 'saved',
209
- kind: 'unknown',
210
- changeType: change.changeType,
211
- fileName: change.fileName,
212
- controlId: change.selector?.id // some changes may not have selector
213
- };
214
- if (change.creation) {
215
- unknownChange.timestamp = new Date(change.creation).getTime();
185
+ (
186
+ await Promise.all(
187
+ Object.keys(savedChanges ?? {}).map(
188
+ async (
189
+ key
190
+ ): Promise<SavedPropertyChange | UnknownSavedChange | SavedControlChange | undefined> => {
191
+ const change: Change = savedChanges[key];
192
+ let selectorId;
193
+ try {
194
+ const flexObject = await this.getFlexObject(change);
195
+ selectorId = await this.getControlIdByChange(flexObject);
196
+ assertChange(change);
197
+ if (
198
+ [change.content.newValue, change.content.newBinding].every(
199
+ (item) => item === undefined || item === null
200
+ )
201
+ ) {
202
+ throw new Error('Invalid change, missing new value in the change file');
203
+ }
204
+ if (
205
+ change.changeType !== 'propertyChange' &&
206
+ change.changeType !== 'propertyBindingChange'
207
+ ) {
208
+ throw new Error('Unknown Change Type');
209
+ }
210
+ this.changedFiles[change.fileName] = change;
211
+ return {
212
+ type: 'saved',
213
+ kind: 'property',
214
+ fileName: change.fileName,
215
+ controlId: selectorId,
216
+ propertyName: change.content.property,
217
+ value: change.content.newValue ?? change.content.newBinding,
218
+ timestamp: new Date(change.creation).getTime(),
219
+ controlName: change.selector.type
220
+ ? (change.selector.type.split('.').pop() as string)
221
+ : '',
222
+ changeType: change.changeType
223
+ } as SavedPropertyChange;
224
+ } catch (error) {
225
+ // Gracefully handle change files with invalid content
226
+ if (change.fileName) {
227
+ this.changedFiles[change.fileName] = change;
228
+ const unknownChange: UnknownSavedChange = {
229
+ type: 'saved',
230
+ kind: 'unknown',
231
+ changeType: change.changeType,
232
+ fileName: change.fileName,
233
+ timestamp: new Date(change.creation).getTime()
234
+ };
235
+ if (change.creation) {
236
+ unknownChange.timestamp = new Date(change.creation).getTime();
237
+ }
238
+ if (selectorId) {
239
+ const controlChange: SavedControlChange = {
240
+ ...unknownChange,
241
+ kind: 'control',
242
+ controlId: selectorId
243
+ };
244
+
245
+ return controlChange;
246
+ }
247
+ return unknownChange;
248
+ }
249
+ return undefined;
216
250
  }
217
- return unknownChange;
218
251
  }
219
- return undefined;
220
- }
221
- })
222
- .filter((change) => !!change) as SavedPropertyChange[]
252
+ )
253
+ )
254
+ ).filter((change) => !!change) as SavedPropertyChange[]
223
255
  ).sort((a, b) => b.timestamp - a.timestamp);
224
256
  this.savedChanges = changes;
225
257
  }
@@ -232,11 +264,19 @@ export class ChangeService {
232
264
  */
233
265
  public async deleteChange(controlId: string, propertyName: string, fileName?: string): Promise<void> {
234
266
  const filesToDelete = this.savedChanges
235
- .filter((change) =>
236
- fileName
237
- ? fileName === change.fileName
238
- : change.controlId === controlId && change.propertyName === propertyName
239
- )
267
+ .filter((change) => {
268
+ if (fileName) {
269
+ return fileName === change.fileName;
270
+ }
271
+
272
+ if (change.kind === 'property') {
273
+ return change.controlId === controlId && change.propertyName === propertyName;
274
+ }
275
+
276
+ if (change.kind === 'control') {
277
+ return change.controlId === controlId;
278
+ }
279
+ })
240
280
  .map((change) =>
241
281
  fetch(FlexChangesEndPoints.changes, {
242
282
  method: 'DELETE',
@@ -261,67 +301,101 @@ export class ChangeService {
261
301
  */
262
302
  private createOnStackChangeHandler(): (event: Event) => Promise<void> {
263
303
  const handleStackChange = modeAndStackChangeHandler(this.sendAction, this.options.rta);
264
- return async (): Promise<void> => {
304
+ return async (event): Promise<void> => {
305
+ const pendingChanges: PendingChange[] = [];
306
+ this.eventStack.push(event);
265
307
  const stack = this.options.rta.getCommandStack();
266
308
  const allCommands = stack.getCommands();
267
309
  const executedCommands = stack.getAllExecutedCommands();
268
310
  const inactiveCommandCount = allCommands.length - executedCommands.length;
269
- let activeChanges: PendingChange[] = [];
270
- allCommands.forEach((command: FlexCommand, i): void => {
311
+ let i: number, command: FlexCommand;
312
+ for ([i, command] of allCommands.entries()) {
271
313
  try {
272
314
  if (typeof command.getCommands === 'function') {
273
315
  const subCommands = command.getCommands();
274
- subCommands.forEach((subCommand) => {
275
- const pendingChange = this.prepareChangeType(subCommand, inactiveCommandCount, i);
276
- if (pendingChange) {
277
- activeChanges.push(pendingChange);
278
- }
279
- });
280
- } else {
281
- const pendingChange = this.prepareChangeType(command, inactiveCommandCount, i);
282
- if (pendingChange) {
283
- activeChanges.push(pendingChange);
316
+ for (const subCommand of subCommands) {
317
+ await this.handleCommand(subCommand, inactiveCommandCount, i, pendingChanges);
284
318
  }
319
+ } else {
320
+ await this.handleCommand(command, inactiveCommandCount, i, pendingChanges);
285
321
  }
286
322
  } catch (error) {
287
323
  Log.error('CPE: Change creation Failed', getError(error));
288
324
  }
289
- });
290
-
291
- activeChanges = activeChanges.filter((change): boolean => !!change);
292
- const changesRequiringReload = activeChanges.reduce(
293
- (sum, change) => (change.changeType === 'appdescr_fe_changePageConfiguration' ? sum + 1 : sum),
294
- 0
295
- );
296
- if (changesRequiringReload > this.changesRequiringReload) {
297
- const resourceBundle = await getTextBundle();
298
- MessageToast.show(resourceBundle.getText('CPE_CHANGES_VISIBLE_AFTER_SAVE_AND_RELOAD_MESSAGE'), {
299
- duration: 8000
300
- });
301
- this.sendAction(setApplicationRequiresReload(changesRequiringReload > 0));
302
325
  }
303
- this.changesRequiringReload = changesRequiringReload;
304
-
326
+ const resourceBundle = await getTextBundle();
327
+ const eventIndex = this.eventStack.indexOf(event);
328
+ if (this.eventStack.length - 1 === eventIndex) {
329
+ this.pendingChanges = pendingChanges.filter((change): boolean => !!change);
330
+ const changesRequiringReload = this.pendingChanges.reduce(
331
+ (sum, change) => (change.changeType === 'appdescr_fe_changePageConfiguration' ? sum + 1 : sum),
332
+ 0
333
+ );
334
+ if (changesRequiringReload > this.changesRequiringReload) {
335
+ MessageToast.show(resourceBundle.getText('CPE_CHANGES_VISIBLE_AFTER_SAVE_AND_RELOAD_MESSAGE'), {
336
+ duration: 8000
337
+ });
338
+ this.sendAction(setApplicationRequiresReload(changesRequiringReload > 0));
339
+ }
340
+ this.changesRequiringReload = changesRequiringReload;
341
+ }
342
+ this.eventStack.splice(eventIndex, 1);
305
343
  if (Array.isArray(allCommands) && allCommands.length === 0) {
344
+ this.pendingChanges = [];
306
345
  await this.fetchSavedChanges();
307
346
  }
308
-
309
- this.updateStack(activeChanges);
347
+ this.updateStack();
310
348
  handleStackChange();
311
349
  };
312
350
  }
313
351
 
314
- private prepareChangeType(
352
+ /**
353
+ * Handles a command by preparing a pending change and adding it to the list of pending changes.
354
+ *
355
+ * @param {FlexCommand} command - The command to process.
356
+ * @param {number} inactiveCommandCount - The number of inactive commands.
357
+ * @param {number} index - The index of the current command being processed.
358
+ * @param {PendingChange[]} pendingChanges - The list of pending changes to update.
359
+ * @returns {Promise<void>} A promise that resolves when the command is handled.
360
+ */
361
+ private async handleCommand(
362
+ command: FlexCommand,
363
+ inactiveCommandCount: number,
364
+ index: number,
365
+ pendingChanges: PendingChange[]
366
+ ): Promise<void> {
367
+ const pendingChange = await this.prepareChangeType(command, inactiveCommandCount, index);
368
+ if (pendingChange) {
369
+ pendingChanges.push(pendingChange);
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Prepares the type of change based on the command and other parameters.
375
+ *
376
+ * @param {FlexCommand} command - The command to process.
377
+ * @param {number} inactiveCommandCount - The number of inactive commands.
378
+ * @param {number} index - The index of the current command being processed.
379
+ * @returns {Promise<PendingChange | undefined>} - A promise that resolves to a `PendingChange` or `undefined`.
380
+ */
381
+ private async prepareChangeType(
315
382
  command: FlexCommand,
316
383
  inactiveCommandCount: number,
317
384
  index: number
318
- ): PendingChange | undefined {
385
+ ): Promise<PendingChange | undefined> {
319
386
  let result: PendingChange;
320
387
  let value = '';
321
- const selectorId = this.getCommandSelectorId(command);
388
+
389
+ const change = command.getPreparedChange();
390
+
391
+ const selectorId =
392
+ typeof change.getSelector === 'function'
393
+ ? await this.getControlIdByChange(change)
394
+ : this.getCommandSelectorId(command);
395
+
322
396
  const changeType = this.getCommandChangeType(command);
323
397
 
324
- if (!selectorId || !changeType) {
398
+ if (!changeType) {
325
399
  return undefined;
326
400
  }
327
401
 
@@ -333,8 +407,9 @@ export class ChangeService {
333
407
  value = command.getProperty('newBinding') as string;
334
408
  break;
335
409
  }
336
- const { fileName } = command.getPreparedChange().getDefinition();
337
- if (changeType === 'propertyChange' || changeType === 'propertyBindingChange') {
410
+
411
+ const { fileName } = change.getDefinition();
412
+ if ((changeType === 'propertyChange' || changeType === 'propertyBindingChange') && selectorId) {
338
413
  result = {
339
414
  type: 'pending',
340
415
  kind: 'property',
@@ -350,15 +425,18 @@ export class ChangeService {
350
425
  result = {
351
426
  type: 'pending',
352
427
  kind: 'unknown',
353
- controlId: selectorId,
354
428
  changeType,
355
429
  isActive: index >= inactiveCommandCount,
356
- controlName:
357
- changeType === 'addXMLAtExtensionPoint'
358
- ? command.getSelector().name ?? ''
359
- : command.getElement().getMetadata().getName().split('.').pop() ?? '',
360
430
  fileName
361
431
  };
432
+
433
+ if (selectorId) {
434
+ result = {
435
+ ...result,
436
+ kind: 'control',
437
+ controlId: selectorId
438
+ };
439
+ }
362
440
  }
363
441
 
364
442
  return result;
@@ -414,4 +492,84 @@ export class ChangeService {
414
492
  () => command.getParent()?.getElement().getId()
415
493
  ]) as string | undefined;
416
494
  }
495
+
496
+ /**
497
+ * Get element id by change.
498
+ *
499
+ * @param change to be executed for creating change
500
+ * @returns element id or empty string
501
+ */
502
+ private async getControlIdByChange(change: FlexChange<ChangeContent>): Promise<string | undefined> {
503
+ const appComponent = this.options.rta.getRootControlInstance();
504
+ const selector = typeof change.getSelector === 'function' ? change.getSelector() : undefined;
505
+ const changeType = change.getChangeType();
506
+ const layer = change.getLayer();
507
+
508
+ if (!selector?.id) {
509
+ return;
510
+ }
511
+
512
+ try {
513
+ let control = JsControlTreeModifier.bySelector(selector, appComponent);
514
+ if (!control) {
515
+ return selector.id;
516
+ }
517
+
518
+ const changeHandlerAPI = (await import('sap/ui/fl/write/api/ChangesWriteAPI')).default;
519
+
520
+ const changeHandler = await changeHandlerAPI.getChangeHandler({
521
+ changeType,
522
+ element: control,
523
+ modifier: JsControlTreeModifier,
524
+ layer
525
+ });
526
+
527
+ if (changeHandler && typeof changeHandler.getChangeVisualizationInfo === 'function') {
528
+ const result: { affectedControls?: [string] } = await changeHandler.getChangeVisualizationInfo(
529
+ change,
530
+ appComponent
531
+ );
532
+ return JsControlTreeModifier.getControlIdBySelector(
533
+ result?.affectedControls?.[0] ?? selector,
534
+ appComponent
535
+ );
536
+ }
537
+
538
+ return JsControlTreeModifier.getControlIdBySelector(selector, appComponent);
539
+ } catch (error) {
540
+ Log.error('Getting element ID from change has failed:', getError(error));
541
+ return selector.id;
542
+ }
543
+ }
544
+
545
+ /**
546
+ * Sync outline changes to place modification markers when outline is changed.
547
+ *
548
+ * @returns void
549
+ */
550
+ public async syncOutlineChanges(): Promise<void> {
551
+ for (const change of this.savedChanges) {
552
+ if (change.kind !== 'unknown') {
553
+ const flexObject = await this.getFlexObject(this.changedFiles[change.fileName]);
554
+ change.controlId = (await this.getControlIdByChange(flexObject)) ?? '';
555
+ }
556
+ }
557
+ this.updateStack();
558
+ }
559
+
560
+ /**
561
+ * Get FlexObject from change object based on UI5 version.
562
+ *
563
+ * @param change change object
564
+ * @returns FlexChange
565
+ */
566
+ private async getFlexObject(change: object): Promise<FlexChange<ChangeContent>> {
567
+ if (isLowerThanMinimalUi5Version(await getUi5Version(), { major: 1, minor: 109 })) {
568
+ const Change = (await import('sap/ui/fl/Change')).default;
569
+ return new Change(change);
570
+ }
571
+
572
+ const FlexObjectFactory = (await import('sap/ui/fl/apply/_internal/flexObjects/FlexObjectFactory')).default;
573
+ return FlexObjectFactory.createFromFileContent(change) as FlexChange<ChangeContent>;
574
+ }
417
575
  }
@@ -41,7 +41,7 @@ sap.ui.define([
41
41
  const changesService = new ChangeService({ rta }, selectionService);
42
42
  const connectorService = new WorkspaceConnectorService();
43
43
  const rtaService = new RtaService(rta);
44
- const outlineService = new OutlineService(rta);
44
+ const outlineService = new OutlineService(rta, changesService);
45
45
  const quickActionService = new QuickActionService(rta, outlineService, registries);
46
46
  const services = [
47
47
  connectorService,
@@ -45,7 +45,7 @@ export default function init(
45
45
  const changesService = new ChangeService({ rta }, selectionService);
46
46
  const connectorService = new WorkspaceConnectorService();
47
47
  const rtaService = new RtaService(rta);
48
- const outlineService = new OutlineService(rta);
48
+ const outlineService = new OutlineService(rta, changesService);
49
49
  const quickActionService = new QuickActionService(rta, outlineService, registries);
50
50
  const services: Service[] = [
51
51
  connectorService,
@@ -15,9 +15,10 @@ sap.ui.define([
15
15
  const transformNodes = ___nodes['transformNodes'];
16
16
  const OUTLINE_CHANGE_EVENT = 'OUTLINE_CHANGED';
17
17
  class OutlineService extends EventTarget {
18
- constructor(rta) {
18
+ constructor(rta, changeService) {
19
19
  super();
20
20
  this.rta = rta;
21
+ this.changeService = changeService;
21
22
  }
22
23
  async init(sendAction) {
23
24
  const outline = await this.rta.getService('outline');
@@ -32,6 +33,7 @@ sap.ui.define([
32
33
  const viewNodes = await outline.get();
33
34
  const controlIndex = {};
34
35
  const outlineNodes = await transformNodes(viewNodes, scenario, reuseComponentsIds, controlIndex);
36
+ await this.changeService.syncOutlineChanges();
35
37
  const event = new CustomEvent(OUTLINE_CHANGE_EVENT, { detail: { controlIndex } });
36
38
  this.dispatchEvent(event);
37
39
  sendAction(outlineChanged(outlineNodes));
@@ -1,6 +1,7 @@
1
1
  import Log from 'sap/base/Log';
2
2
  import type RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
3
3
  import type RTAOutlineService from 'sap/ui/rta/command/OutlineService';
4
+ import type { ChangeService } from '../changes/service';
4
5
 
5
6
  import type { ExternalAction } from '@sap-ux-private/control-property-editor-common';
6
7
  import { outlineChanged, SCENARIO, showMessage } from '@sap-ux-private/control-property-editor-common';
@@ -19,7 +20,7 @@ export interface OutlineChangedEventDetail {
19
20
  * A Class of WorkspaceConnectorService
20
21
  */
21
22
  export class OutlineService extends EventTarget {
22
- constructor(private rta: RuntimeAuthoring) {
23
+ constructor(private readonly rta: RuntimeAuthoring, private readonly changeService: ChangeService) {
23
24
  super();
24
25
  }
25
26
 
@@ -41,6 +42,7 @@ export class OutlineService extends EventTarget {
41
42
  const viewNodes = await outline.get();
42
43
  const controlIndex: ControlTreeIndex = {};
43
44
  const outlineNodes = await transformNodes(viewNodes, scenario, reuseComponentsIds, controlIndex);
45
+ await this.changeService.syncOutlineChanges();
44
46
 
45
47
  const event = new CustomEvent(OUTLINE_CHANGE_EVENT, {
46
48
  detail: {
@@ -8,7 +8,7 @@ sap.ui.define((function () { 'use strict';
8
8
 
9
9
  (function (exports) {
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.setApplicationRequiresReload = exports.executeQuickAction = exports.updateQuickAction = exports.quickActionListChanged = exports.save = exports.redo = exports.undo = exports.appLoaded = exports.setSaveEnablement = exports.setUndoRedoEnablement = exports.applicationModeChanged = exports.setAppMode = exports.storageFileChanged = exports.reloadApplication = exports.showMessage = exports.changeStackModified = exports.propertyChangeFailed = exports.propertyChanged = exports.changeProperty = exports.outlineChanged = exports.deletePropertyChanges = exports.addExtensionPoint = exports.selectControl = exports.controlSelected = exports.iconsLoaded = exports.EXTERNAL_ACTION_PREFIX = exports.NESTED_QUICK_ACTION_KIND = exports.SIMPLE_QUICK_ACTION_KIND = exports.UNKNOWN_CHANGE_KIND = exports.PROPERTY_CHANGE_KIND = exports.SAVED_CHANGE_TYPE = exports.PENDING_CHANGE_TYPE = exports.SCENARIO = exports.CHECKBOX_EDITOR_TYPE = exports.DROPDOWN_EDITOR_TYPE = exports.INPUT_EDITOR_TYPE = exports.STRING_VALUE_TYPE = exports.FLOAT_VALUE_TYPE = exports.INTEGER_VALUE_TYPE = exports.BOOLEAN_VALUE_TYPE = void 0;
11
+ exports.setApplicationRequiresReload = exports.executeQuickAction = exports.updateQuickAction = exports.quickActionListChanged = exports.save = exports.redo = exports.undo = exports.appLoaded = exports.setSaveEnablement = exports.setUndoRedoEnablement = exports.applicationModeChanged = exports.setAppMode = exports.storageFileChanged = exports.reloadApplication = exports.showMessage = exports.changeStackModified = exports.propertyChangeFailed = exports.propertyChanged = exports.changeProperty = exports.outlineChanged = exports.deletePropertyChanges = exports.addExtensionPoint = exports.selectControl = exports.controlSelected = exports.iconsLoaded = exports.EXTERNAL_ACTION_PREFIX = exports.NESTED_QUICK_ACTION_KIND = exports.SIMPLE_QUICK_ACTION_KIND = exports.CONTROL_CHANGE_KIND = exports.UNKNOWN_CHANGE_KIND = exports.PROPERTY_CHANGE_KIND = exports.SAVED_CHANGE_TYPE = exports.PENDING_CHANGE_TYPE = exports.SCENARIO = exports.CHECKBOX_EDITOR_TYPE = exports.DROPDOWN_EDITOR_TYPE = exports.INPUT_EDITOR_TYPE = exports.STRING_VALUE_TYPE = exports.FLOAT_VALUE_TYPE = exports.INTEGER_VALUE_TYPE = exports.BOOLEAN_VALUE_TYPE = void 0;
12
12
  exports.BOOLEAN_VALUE_TYPE = 'boolean';
13
13
  exports.INTEGER_VALUE_TYPE = 'integer';
14
14
  exports.FLOAT_VALUE_TYPE = 'float';
@@ -27,6 +27,7 @@ sap.ui.define((function () { 'use strict';
27
27
  exports.SAVED_CHANGE_TYPE = 'saved';
28
28
  exports.PROPERTY_CHANGE_KIND = 'property';
29
29
  exports.UNKNOWN_CHANGE_KIND = 'unknown';
30
+ exports.CONTROL_CHANGE_KIND = 'control';
30
31
  exports.SIMPLE_QUICK_ACTION_KIND = 'simple';
31
32
  exports.NESTED_QUICK_ACTION_KIND = 'nested';
32
33
  /**