@sap-ux/preview-middleware 0.13.18 → 0.13.20
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/dist/base/flex.d.ts +5 -15
- package/dist/base/flex.js +4 -32
- package/dist/base/flp.d.ts +12 -2
- package/dist/base/flp.js +27 -5
- package/dist/client/adp/controllers/AddFragment.controller.js +4 -25
- package/dist/client/adp/controllers/AddFragment.controller.ts +5 -24
- package/dist/client/adp/controllers/BaseDialog.controller.js +18 -1
- package/dist/client/adp/controllers/BaseDialog.controller.ts +36 -2
- package/dist/client/adp/controllers/ExtensionPoint.controller.js +8 -18
- package/dist/client/adp/controllers/ExtensionPoint.controller.ts +9 -22
- package/dist/client/adp/utils.js +29 -1
- package/dist/client/adp/utils.ts +34 -0
- package/package.json +8 -4
package/dist/base/flex.d.ts
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
/// <reference path="../../../../types/ui5.d.ts" />
|
|
2
2
|
import type { Logger } from '@sap-ux/logger';
|
|
3
3
|
import type { ReaderCollection } from '@ui5/fs';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
export interface FlexChange {
|
|
8
|
-
[key: string]: string | object | undefined;
|
|
9
|
-
changeType: string;
|
|
10
|
-
reference: string;
|
|
11
|
-
moduleName?: string;
|
|
12
|
-
content?: {
|
|
13
|
-
codeRef?: string;
|
|
14
|
-
fragmentPath?: string;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
4
|
+
import type { Editor } from 'mem-fs-editor';
|
|
5
|
+
import type { CommonChangeProperties } from '@sap-ux/adp-tooling';
|
|
17
6
|
/**
|
|
18
7
|
* Read changes from the file system and return them.
|
|
19
8
|
*
|
|
@@ -21,7 +10,7 @@ export interface FlexChange {
|
|
|
21
10
|
* @param logger logger instance
|
|
22
11
|
* @returns object with the file name as key and the file content as value
|
|
23
12
|
*/
|
|
24
|
-
export declare function readChanges(project: ReaderCollection, logger: Logger): Promise<Record<string,
|
|
13
|
+
export declare function readChanges(project: ReaderCollection, logger: Logger): Promise<Record<string, CommonChangeProperties>>;
|
|
25
14
|
/**
|
|
26
15
|
* Writes flex changes to the user's workspace.
|
|
27
16
|
*
|
|
@@ -29,13 +18,14 @@ export declare function readChanges(project: ReaderCollection, logger: Logger):
|
|
|
29
18
|
* @param data.fileName file name that is required for a valid change
|
|
30
19
|
* @param data.fileType file type that is required
|
|
31
20
|
* @param webappPath path to the webapp folder
|
|
21
|
+
* @param fs mem-fs editor
|
|
32
22
|
* @param logger logger instance
|
|
33
23
|
* @returns object with success flag and optional message
|
|
34
24
|
*/
|
|
35
25
|
export declare function writeChange(data: object & {
|
|
36
26
|
fileName?: string;
|
|
37
27
|
fileType?: string;
|
|
38
|
-
}, webappPath: string, logger: Logger): {
|
|
28
|
+
}, webappPath: string, fs: Editor, logger: Logger): {
|
|
39
29
|
success: boolean;
|
|
40
30
|
message?: string;
|
|
41
31
|
};
|
package/dist/base/flex.js
CHANGED
|
@@ -12,28 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.deleteChange = exports.writeChange = exports.readChanges = void 0;
|
|
13
13
|
const fs_1 = require("fs");
|
|
14
14
|
const path_1 = require("path");
|
|
15
|
-
/**
|
|
16
|
-
* Map of change type specific correction functions.
|
|
17
|
-
*/
|
|
18
|
-
const moduleNameContentMap = {
|
|
19
|
-
codeExt: (change) => { var _a, _b; return ((_b = (_a = change.content) === null || _a === void 0 ? void 0 : _a.codeRef) !== null && _b !== void 0 ? _b : '').replace('.js', ''); },
|
|
20
|
-
addXML: (change) => { var _a, _b; return (_b = (_a = change.content) === null || _a === void 0 ? void 0 : _a.fragmentPath) !== null && _b !== void 0 ? _b : ''; }
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Sets the moduleName property of the provided change to also support old changes with newer UI5 versions.
|
|
24
|
-
*
|
|
25
|
-
* @param change change to be fixed
|
|
26
|
-
* @param logger logger instance
|
|
27
|
-
*/
|
|
28
|
-
function tryFixChange(change, logger) {
|
|
29
|
-
try {
|
|
30
|
-
const prefix = change.reference.replace(/\./g, '/');
|
|
31
|
-
change.moduleName = `${prefix}/changes/${moduleNameContentMap[change.changeType](change)}`;
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
logger.warn('Could not fix missing module name.');
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
15
|
/**
|
|
38
16
|
* Read changes from the file system and return them.
|
|
39
17
|
*
|
|
@@ -48,9 +26,6 @@ function readChanges(project, logger) {
|
|
|
48
26
|
for (const file of files) {
|
|
49
27
|
try {
|
|
50
28
|
const change = JSON.parse(yield file.getString());
|
|
51
|
-
if (moduleNameContentMap[change.changeType] && !change.moduleName) {
|
|
52
|
-
tryFixChange(change, logger);
|
|
53
|
-
}
|
|
54
29
|
changes[`sap.ui.fl.${(0, path_1.parse)(file.getName()).name}`] = change;
|
|
55
30
|
logger.debug(`Read change from ${file.getPath()}`);
|
|
56
31
|
}
|
|
@@ -69,20 +44,17 @@ exports.readChanges = readChanges;
|
|
|
69
44
|
* @param data.fileName file name that is required for a valid change
|
|
70
45
|
* @param data.fileType file type that is required
|
|
71
46
|
* @param webappPath path to the webapp folder
|
|
47
|
+
* @param fs mem-fs editor
|
|
72
48
|
* @param logger logger instance
|
|
73
49
|
* @returns object with success flag and optional message
|
|
74
50
|
*/
|
|
75
|
-
function writeChange(data, webappPath, logger) {
|
|
51
|
+
function writeChange(data, webappPath, fs, logger) {
|
|
76
52
|
const fileName = data.fileName;
|
|
77
53
|
const fileType = data.fileType;
|
|
78
54
|
if (fileName && fileType) {
|
|
79
55
|
logger.debug(`Write change ${fileName}.${fileType}`);
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
(0, fs_1.mkdirSync)(path);
|
|
83
|
-
}
|
|
84
|
-
const filePath = (0, path_1.join)(path, fileName + '.' + fileType);
|
|
85
|
-
(0, fs_1.writeFileSync)(filePath, JSON.stringify(data, null, 2));
|
|
56
|
+
const filePath = (0, path_1.join)(webappPath, 'changes', fileName + '.' + fileType);
|
|
57
|
+
fs.writeJSON(filePath, data);
|
|
86
58
|
const message = `FILE_CREATED ${fileName}.${fileType}`;
|
|
87
59
|
return { success: true, message };
|
|
88
60
|
}
|
package/dist/base/flp.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/// <reference path="../../../../types/ui5.d.ts" />
|
|
2
2
|
import type { ReaderCollection } from '@ui5/fs';
|
|
3
|
+
import type { Editor as MemFsEditor } from 'mem-fs-editor';
|
|
3
4
|
import type { Router } from 'express';
|
|
4
|
-
import type { App, FlpConfig, MiddlewareConfig, RtaConfig, TestConfig } from '../types';
|
|
5
5
|
import type { Logger, ToolsLogger } from '@sap-ux/logger';
|
|
6
6
|
import type { MiddlewareUtils } from '@ui5/server';
|
|
7
7
|
import type { Manifest, UI5FlexLayer } from '@sap-ux/project-access';
|
|
8
|
-
import { type AdpPreviewConfig } from '@sap-ux/adp-tooling';
|
|
8
|
+
import { type AdpPreviewConfig, type CommonChangeProperties, type OperationType } from '@sap-ux/adp-tooling';
|
|
9
|
+
import type { App, FlpConfig, MiddlewareConfig, RtaConfig, TestConfig } from '../types';
|
|
9
10
|
/**
|
|
10
11
|
* Enhanced request handler that exposes a list of endpoints for the cds-plugin-ui5.
|
|
11
12
|
*/
|
|
@@ -53,6 +54,7 @@ export interface TemplateConfig {
|
|
|
53
54
|
};
|
|
54
55
|
locateReuseLibsScript?: boolean;
|
|
55
56
|
}
|
|
57
|
+
type OnChangeRequestHandler = (type: OperationType, change: CommonChangeProperties, fs: MemFsEditor, logger: Logger) => Promise<void>;
|
|
56
58
|
/**
|
|
57
59
|
* Class handling preview of a sandbox FLP.
|
|
58
60
|
*/
|
|
@@ -60,6 +62,7 @@ export declare class FlpSandbox {
|
|
|
60
62
|
private readonly project;
|
|
61
63
|
private readonly utils;
|
|
62
64
|
private readonly logger;
|
|
65
|
+
protected onChangeRequest: OnChangeRequestHandler | undefined;
|
|
63
66
|
protected templateConfig: TemplateConfig;
|
|
64
67
|
readonly config: FlpConfig;
|
|
65
68
|
readonly rta?: RtaConfig;
|
|
@@ -74,6 +77,12 @@ export declare class FlpSandbox {
|
|
|
74
77
|
* @param logger logger instance
|
|
75
78
|
*/
|
|
76
79
|
constructor(config: Partial<MiddlewareConfig>, project: ReaderCollection, utils: MiddlewareUtils, logger: Logger);
|
|
80
|
+
/**
|
|
81
|
+
* Registers a handler function to be called when a change request occurs.
|
|
82
|
+
*
|
|
83
|
+
* @param {OnChangeRequestHandler} handler - The function to be executed when a change request occurs.
|
|
84
|
+
*/
|
|
85
|
+
addOnChangeRequestHandler(handler: OnChangeRequestHandler): void;
|
|
77
86
|
/**
|
|
78
87
|
* Initialize the FLP sandbox router.
|
|
79
88
|
*
|
|
@@ -173,4 +182,5 @@ export declare class FlpSandbox {
|
|
|
173
182
|
* @param logger logger instance
|
|
174
183
|
*/
|
|
175
184
|
export declare function initAdp(rootProject: ReaderCollection, config: AdpPreviewConfig, flp: FlpSandbox, util: MiddlewareUtils, logger: ToolsLogger): Promise<void>;
|
|
185
|
+
export {};
|
|
176
186
|
//# sourceMappingURL=flp.d.ts.map
|
package/dist/base/flp.js
CHANGED
|
@@ -10,13 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.initAdp = exports.FlpSandbox = void 0;
|
|
13
|
+
const mem_fs_1 = require("mem-fs");
|
|
14
|
+
const mem_fs_editor_1 = require("mem-fs-editor");
|
|
13
15
|
const ejs_1 = require("ejs");
|
|
14
16
|
const fs_1 = require("fs");
|
|
15
17
|
const path_1 = require("path");
|
|
16
18
|
const express_1 = require("express");
|
|
17
|
-
const flex_1 = require("./flex");
|
|
18
|
-
const project_access_1 = require("@sap-ux/project-access");
|
|
19
19
|
const adp_tooling_1 = require("@sap-ux/adp-tooling");
|
|
20
|
+
const project_access_1 = require("@sap-ux/project-access");
|
|
21
|
+
const flex_1 = require("./flex");
|
|
20
22
|
const test_1 = require("./test");
|
|
21
23
|
const DEVELOPER_MODE_CONFIG = new Map([
|
|
22
24
|
// Run application in design time mode
|
|
@@ -114,6 +116,14 @@ class FlpSandbox {
|
|
|
114
116
|
logger.debug(`Config: ${JSON.stringify({ flp: this.config, rta: this.rta, test: this.test })}`);
|
|
115
117
|
this.router = (0, express_1.Router)();
|
|
116
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Registers a handler function to be called when a change request occurs.
|
|
121
|
+
*
|
|
122
|
+
* @param {OnChangeRequestHandler} handler - The function to be executed when a change request occurs.
|
|
123
|
+
*/
|
|
124
|
+
addOnChangeRequestHandler(handler) {
|
|
125
|
+
this.onChangeRequest = handler;
|
|
126
|
+
}
|
|
117
127
|
/**
|
|
118
128
|
* Initialize the FLP sandbox router.
|
|
119
129
|
*
|
|
@@ -321,16 +331,27 @@ class FlpSandbox {
|
|
|
321
331
|
* Create required routes for flex.
|
|
322
332
|
*/
|
|
323
333
|
createFlexHandler() {
|
|
334
|
+
const fs = (0, mem_fs_editor_1.create)((0, mem_fs_1.create)());
|
|
324
335
|
const api = `${PREVIEW_URL.api}/changes`;
|
|
325
336
|
this.router.use(api, (0, express_1.json)());
|
|
326
337
|
this.router.get(api, ((_req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
327
|
-
|
|
338
|
+
const changes = yield (0, flex_1.readChanges)(this.project, this.logger);
|
|
339
|
+
if (this.onChangeRequest) {
|
|
340
|
+
for (const change of Object.values(changes)) {
|
|
341
|
+
yield this.onChangeRequest('read', change, fs, this.logger);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
res.status(200).contentType('application/json').send(changes);
|
|
328
345
|
})));
|
|
329
346
|
this.router.post(api, ((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
330
347
|
try {
|
|
331
|
-
const
|
|
348
|
+
const change = req.body;
|
|
349
|
+
if (this.onChangeRequest) {
|
|
350
|
+
yield this.onChangeRequest('write', change, fs, this.logger);
|
|
351
|
+
}
|
|
352
|
+
const { success, message } = (0, flex_1.writeChange)(change, this.utils.getProject().getSourcePath(), fs, this.logger);
|
|
332
353
|
if (success) {
|
|
333
|
-
|
|
354
|
+
fs.commit(() => res.status(200).send(message));
|
|
334
355
|
}
|
|
335
356
|
else {
|
|
336
357
|
this.sendResponse(res, 'text/plain', 400, 'INVALID_DATA');
|
|
@@ -565,6 +586,7 @@ function initAdp(rootProject, config, flp, util, logger) {
|
|
|
565
586
|
const { name, manifest } = descriptor;
|
|
566
587
|
yield flp.init(manifest, name, adp.resources);
|
|
567
588
|
flp.router.use(adp.descriptor.url, adp.proxy.bind(adp));
|
|
589
|
+
flp.addOnChangeRequestHandler(adp.onChangeRequest.bind(adp));
|
|
568
590
|
flp.router.use((0, express_1.json)());
|
|
569
591
|
adp.addApis(flp.router);
|
|
570
592
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "sap/ui/dt/OverlayRegistry", "../control-utils", "../command-executor", "../api-handler", "./BaseDialog.controller"], function (MessageToast, JSONModel, OverlayRegistry, __ControlUtils, __CommandExecutor, ___api_handler, __BaseDialog) {
|
|
3
|
+
sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "sap/ui/dt/OverlayRegistry", "../control-utils", "../command-executor", "../api-handler", "./BaseDialog.controller", "../utils"], function (MessageToast, JSONModel, OverlayRegistry, __ControlUtils, __CommandExecutor, ___api_handler, __BaseDialog, ___utils) {
|
|
4
4
|
"use strict";
|
|
5
5
|
|
|
6
6
|
function _interopRequireDefault(obj) {
|
|
@@ -9,8 +9,8 @@ sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "sap/ui/dt/O
|
|
|
9
9
|
const ControlUtils = _interopRequireDefault(__ControlUtils);
|
|
10
10
|
const CommandExecutor = _interopRequireDefault(__CommandExecutor);
|
|
11
11
|
const getFragments = ___api_handler["getFragments"];
|
|
12
|
-
const writeFragment = ___api_handler["writeFragment"];
|
|
13
12
|
const BaseDialog = _interopRequireDefault(__BaseDialog);
|
|
13
|
+
const notifyUser = ___utils["notifyUser"];
|
|
14
14
|
/**
|
|
15
15
|
* @namespace open.ux.preview.client.adp.controllers
|
|
16
16
|
*/
|
|
@@ -74,7 +74,8 @@ sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "sap/ui/dt/O
|
|
|
74
74
|
fragmentName,
|
|
75
75
|
targetAggregation
|
|
76
76
|
};
|
|
77
|
-
await this.
|
|
77
|
+
await this.createFragmentChange(fragmentData);
|
|
78
|
+
notifyUser(`Note: The '${fragmentName}.fragment.xml' fragment will be created once you save the change.`, 8000);
|
|
78
79
|
this.handleDialogClose();
|
|
79
80
|
},
|
|
80
81
|
buildDialogData: async function _buildDialogData() {
|
|
@@ -162,28 +163,6 @@ sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "sap/ui/dt/O
|
|
|
162
163
|
}
|
|
163
164
|
return indexArray;
|
|
164
165
|
},
|
|
165
|
-
createNewFragment: async function _createNewFragment(fragmentData) {
|
|
166
|
-
const {
|
|
167
|
-
fragmentName,
|
|
168
|
-
index,
|
|
169
|
-
targetAggregation
|
|
170
|
-
} = fragmentData;
|
|
171
|
-
try {
|
|
172
|
-
await writeFragment({
|
|
173
|
-
fragmentName
|
|
174
|
-
});
|
|
175
|
-
MessageToast.show(`Fragment with name '${fragmentName}' was created.`);
|
|
176
|
-
} catch (e) {
|
|
177
|
-
// In case of error when creating a new fragment, we should not create a change file
|
|
178
|
-
MessageToast.show(e.message);
|
|
179
|
-
throw new Error(e.message);
|
|
180
|
-
}
|
|
181
|
-
await this.createFragmentChange({
|
|
182
|
-
fragmentName,
|
|
183
|
-
index,
|
|
184
|
-
targetAggregation
|
|
185
|
-
});
|
|
186
|
-
},
|
|
187
166
|
createFragmentChange: async function _createFragmentChange(fragmentData) {
|
|
188
167
|
const {
|
|
189
168
|
fragmentName,
|
|
@@ -23,8 +23,9 @@ import type ElementOverlay from 'sap/ui/dt/ElementOverlay';
|
|
|
23
23
|
|
|
24
24
|
import ControlUtils from '../control-utils';
|
|
25
25
|
import CommandExecutor from '../command-executor';
|
|
26
|
-
import { getFragments
|
|
26
|
+
import { getFragments } from '../api-handler';
|
|
27
27
|
import BaseDialog from './BaseDialog.controller';
|
|
28
|
+
import { notifyUser } from '../utils';
|
|
28
29
|
|
|
29
30
|
interface CreateFragmentProps {
|
|
30
31
|
fragmentName: string;
|
|
@@ -142,7 +143,9 @@ export default class AddFragment extends BaseDialog {
|
|
|
142
143
|
targetAggregation
|
|
143
144
|
};
|
|
144
145
|
|
|
145
|
-
await this.
|
|
146
|
+
await this.createFragmentChange(fragmentData);
|
|
147
|
+
|
|
148
|
+
notifyUser(`Note: The '${fragmentName}.fragment.xml' fragment will be created once you save the change.`, 8000);
|
|
146
149
|
|
|
147
150
|
this.handleDialogClose();
|
|
148
151
|
}
|
|
@@ -245,28 +248,6 @@ export default class AddFragment extends BaseDialog {
|
|
|
245
248
|
return indexArray;
|
|
246
249
|
}
|
|
247
250
|
|
|
248
|
-
/**
|
|
249
|
-
* Creates a new fragment for the specified control
|
|
250
|
-
*
|
|
251
|
-
* @param fragmentData Fragment Data
|
|
252
|
-
* @param fragmentData.index Index for XML Fragment placement
|
|
253
|
-
* @param fragmentData.fragmentName Fragment name
|
|
254
|
-
* @param fragmentData.targetAggregation Target aggregation for control
|
|
255
|
-
*/
|
|
256
|
-
private async createNewFragment(fragmentData: CreateFragmentProps): Promise<void> {
|
|
257
|
-
const { fragmentName, index, targetAggregation } = fragmentData;
|
|
258
|
-
try {
|
|
259
|
-
await writeFragment<unknown>({ fragmentName });
|
|
260
|
-
MessageToast.show(`Fragment with name '${fragmentName}' was created.`);
|
|
261
|
-
} catch (e) {
|
|
262
|
-
// In case of error when creating a new fragment, we should not create a change file
|
|
263
|
-
MessageToast.show(e.message);
|
|
264
|
-
throw new Error(e.message);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
await this.createFragmentChange({ fragmentName, index, targetAggregation });
|
|
268
|
-
}
|
|
269
|
-
|
|
270
251
|
/**
|
|
271
252
|
* Creates an addXML fragment command and pushes it to the command stack
|
|
272
253
|
*
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
sap.ui.define(["sap/ui/core/library", "sap/ui/core/mvc/Controller"], function (sap_ui_core_library, Controller) {
|
|
3
|
+
sap.ui.define(["sap/ui/core/library", "sap/ui/core/mvc/Controller", "../utils"], function (sap_ui_core_library, Controller, ___utils) {
|
|
4
4
|
"use strict";
|
|
5
5
|
|
|
6
6
|
const ValueState = sap_ui_core_library["ValueState"];
|
|
7
|
+
const matchesFragmentName = ___utils["matchesFragmentName"];
|
|
7
8
|
/**
|
|
8
9
|
* @namespace open.ux.preview.client.adp.controllers
|
|
9
10
|
*/
|
|
@@ -37,9 +38,25 @@ sap.ui.define(["sap/ui/core/library", "sap/ui/core/mvc/Controller"], function (s
|
|
|
37
38
|
updateDialogState(ValueState.Error, 'A fragment file name cannot contain more than 64 characters.');
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
41
|
+
const changeExists = this.checkForExistingChange(fragmentName);
|
|
42
|
+
if (changeExists) {
|
|
43
|
+
updateDialogState(ValueState.Error, 'Enter a different name. The fragment name entered matches the name of an unsaved fragment.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
40
46
|
updateDialogState(ValueState.Success);
|
|
41
47
|
this.model.setProperty('/newFragmentName', fragmentName);
|
|
42
48
|
},
|
|
49
|
+
checkForExistingChange: function _checkForExistingChange(fragmentName) {
|
|
50
|
+
const allCommands = this.rta.getCommandStack().getCommands();
|
|
51
|
+
return allCommands.some(command => {
|
|
52
|
+
if (command?.getProperty('name') === 'composite') {
|
|
53
|
+
const addXmlCommand = command.getCommands().find(c => c?.getProperty('name') === 'addXMLAtExtensionPoint');
|
|
54
|
+
return addXmlCommand && matchesFragmentName(addXmlCommand, fragmentName);
|
|
55
|
+
} else {
|
|
56
|
+
return matchesFragmentName(command, fragmentName);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
},
|
|
43
60
|
setEscapeHandler: function _setEscapeHandler() {
|
|
44
61
|
this.dialog.setEscapeHandler(_ref => {
|
|
45
62
|
let {
|
|
@@ -7,8 +7,10 @@ import { ValueState } from 'sap/ui/core/library';
|
|
|
7
7
|
import Controller from 'sap/ui/core/mvc/Controller';
|
|
8
8
|
import JSONModel from 'sap/ui/model/json/JSONModel';
|
|
9
9
|
import RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
|
|
10
|
+
import FlexCommand from 'sap/ui/rta/command/FlexCommand';
|
|
10
11
|
|
|
11
12
|
import CommandExecutor from '../command-executor';
|
|
13
|
+
import { matchesFragmentName } from '../utils';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* @namespace open.ux.preview.client.adp.controllers
|
|
@@ -45,7 +47,7 @@ export default abstract class BaseDialog extends Controller {
|
|
|
45
47
|
|
|
46
48
|
abstract setup(dialog: Dialog): Promise<void>;
|
|
47
49
|
|
|
48
|
-
abstract onCreateBtnPress(event: Event): Promise<void
|
|
50
|
+
abstract onCreateBtnPress(event: Event): Promise<void> | void;
|
|
49
51
|
|
|
50
52
|
abstract buildDialogData(): Promise<void>;
|
|
51
53
|
|
|
@@ -54,7 +56,7 @@ export default abstract class BaseDialog extends Controller {
|
|
|
54
56
|
*
|
|
55
57
|
* @param event Event
|
|
56
58
|
*/
|
|
57
|
-
onFragmentNameInputChange(event: Event) {
|
|
59
|
+
onFragmentNameInputChange(event: Event): void {
|
|
58
60
|
const input = event.getSource<Input>();
|
|
59
61
|
const beginBtn = this.dialog.getBeginButton();
|
|
60
62
|
|
|
@@ -94,10 +96,42 @@ export default abstract class BaseDialog extends Controller {
|
|
|
94
96
|
return;
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
const changeExists = this.checkForExistingChange(fragmentName);
|
|
100
|
+
|
|
101
|
+
if (changeExists) {
|
|
102
|
+
updateDialogState(
|
|
103
|
+
ValueState.Error,
|
|
104
|
+
'Enter a different name. The fragment name entered matches the name of an unsaved fragment.'
|
|
105
|
+
);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
97
109
|
updateDialogState(ValueState.Success);
|
|
98
110
|
this.model.setProperty('/newFragmentName', fragmentName);
|
|
99
111
|
}
|
|
100
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Checks for the existence of a change associated with a specific fragment name in the RTA command stack.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} fragmentName - The name of the fragment to check for existing changes.
|
|
117
|
+
* @returns {Promise<boolean>} A promise that resolves to `true` if a matching change is found, otherwise `false`.
|
|
118
|
+
*/
|
|
119
|
+
checkForExistingChange(fragmentName: string): boolean {
|
|
120
|
+
const allCommands = this.rta.getCommandStack().getCommands();
|
|
121
|
+
|
|
122
|
+
return allCommands.some((command: FlexCommand) => {
|
|
123
|
+
if (command?.getProperty('name') === 'composite') {
|
|
124
|
+
const addXmlCommand = command
|
|
125
|
+
.getCommands()
|
|
126
|
+
.find((c: FlexCommand) => c?.getProperty('name') === 'addXMLAtExtensionPoint');
|
|
127
|
+
|
|
128
|
+
return addXmlCommand && matchesFragmentName(addXmlCommand, fragmentName);
|
|
129
|
+
} else {
|
|
130
|
+
return matchesFragmentName(command, fragmentName);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
101
135
|
/**
|
|
102
136
|
* Sets custom function that fires when user presses escape key.
|
|
103
137
|
*/
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "../api-handler", "./BaseDialog.controller"], function (MessageToast, JSONModel, ___api_handler, __BaseDialog) {
|
|
3
|
+
sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "../api-handler", "./BaseDialog.controller", "../utils"], function (MessageToast, JSONModel, ___api_handler, __BaseDialog, ___utils) {
|
|
4
4
|
"use strict";
|
|
5
5
|
|
|
6
6
|
function _interopRequireDefault(obj) {
|
|
7
7
|
return obj && obj.__esModule && typeof obj.default !== "undefined" ? obj.default : obj;
|
|
8
8
|
}
|
|
9
9
|
const getFragments = ___api_handler["getFragments"];
|
|
10
|
-
const writeFragment = ___api_handler["writeFragment"];
|
|
11
10
|
const BaseDialog = _interopRequireDefault(__BaseDialog);
|
|
11
|
+
const notifyUser = ___utils["notifyUser"];
|
|
12
12
|
/**
|
|
13
13
|
* @namespace open.ux.preview.client.adp.controllers
|
|
14
14
|
*/
|
|
15
15
|
const ExtensionPoint = BaseDialog.extend("open.ux.preview.client.adp.controllers.ExtensionPoint", {
|
|
16
|
-
constructor: function _constructor(name, _overlays,
|
|
16
|
+
constructor: function _constructor(name, _overlays, rta, data) {
|
|
17
17
|
BaseDialog.prototype.constructor.call(this, name);
|
|
18
18
|
this.model = new JSONModel();
|
|
19
19
|
this.data = data;
|
|
20
|
+
this.rta = rta;
|
|
20
21
|
},
|
|
21
22
|
setup: async function _setup(dialog) {
|
|
22
23
|
this.dialog = dialog;
|
|
@@ -25,11 +26,12 @@ sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "../api-hand
|
|
|
25
26
|
this.dialog.setModel(this.model);
|
|
26
27
|
this.dialog.open();
|
|
27
28
|
},
|
|
28
|
-
onCreateBtnPress:
|
|
29
|
+
onCreateBtnPress: function _onCreateBtnPress(event) {
|
|
29
30
|
const source = event.getSource();
|
|
30
31
|
source.setEnabled(false);
|
|
31
32
|
const fragmentName = this.model.getProperty('/newFragmentName');
|
|
32
|
-
|
|
33
|
+
this.createExtensionPointFragmentChange(fragmentName);
|
|
34
|
+
notifyUser(`Note: The '${fragmentName}.fragment.xml' fragment will be created once you save the change.`, 8000);
|
|
33
35
|
this.handleDialogClose();
|
|
34
36
|
},
|
|
35
37
|
onExtensionPointHandler: function _onExtensionPointHandler(event) {
|
|
@@ -75,22 +77,10 @@ sap.ui.define(["sap/m/MessageToast", "sap/ui/model/json/JSONModel", "../api-hand
|
|
|
75
77
|
this.model.setProperty('/extensionPointList', list);
|
|
76
78
|
this.model.setProperty('/extensionListEnabled', enabled);
|
|
77
79
|
},
|
|
78
|
-
createNewFragment: async function _createNewFragment(fragmentName) {
|
|
79
|
-
try {
|
|
80
|
-
await writeFragment({
|
|
81
|
-
fragmentName
|
|
82
|
-
});
|
|
83
|
-
MessageToast.show(`Fragment with name '${fragmentName}' was created.`);
|
|
84
|
-
} catch (e) {
|
|
85
|
-
// In case of error when creating a new fragment, we should not create a change file
|
|
86
|
-
MessageToast.show(e.message);
|
|
87
|
-
throw new Error(e.message);
|
|
88
|
-
}
|
|
89
|
-
this.createExtensionPointFragmentChange(fragmentName);
|
|
90
|
-
},
|
|
91
80
|
createExtensionPointFragmentChange: function _createExtensionPointFragmentChange(fragmentName) {
|
|
92
81
|
const extensionPointName = this.model.getProperty('/extensionPointName');
|
|
93
82
|
const modifiedValue = {
|
|
83
|
+
fragment: `<core:FragmentDefinition xmlns:core='sap.ui.core'></core:FragmentDefinition>`,
|
|
94
84
|
fragmentPath: `fragments/${fragmentName}.fragment.xml`,
|
|
95
85
|
extensionPointName
|
|
96
86
|
};
|
|
@@ -16,9 +16,10 @@ import JSONModel from 'sap/ui/model/json/JSONModel';
|
|
|
16
16
|
/** sap.ui.rta */
|
|
17
17
|
import type RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
|
|
18
18
|
|
|
19
|
-
import { getFragments
|
|
19
|
+
import { getFragments } from '../api-handler';
|
|
20
20
|
import BaseDialog from './BaseDialog.controller';
|
|
21
21
|
import { ExtensionPointData, ExtensionPointInfo } from '../extension-point';
|
|
22
|
+
import { notifyUser } from '../utils';
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* @namespace open.ux.preview.client.adp.controllers
|
|
@@ -26,10 +27,11 @@ import { ExtensionPointData, ExtensionPointInfo } from '../extension-point';
|
|
|
26
27
|
export default class ExtensionPoint extends BaseDialog {
|
|
27
28
|
public readonly data: ExtensionPointData;
|
|
28
29
|
|
|
29
|
-
constructor(name: string, _overlays: UI5Element,
|
|
30
|
+
constructor(name: string, _overlays: UI5Element, rta: RuntimeAuthoring, data: ExtensionPointData) {
|
|
30
31
|
super(name);
|
|
31
32
|
this.model = new JSONModel();
|
|
32
33
|
this.data = data;
|
|
34
|
+
this.rta = rta;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/**
|
|
@@ -54,13 +56,15 @@ export default class ExtensionPoint extends BaseDialog {
|
|
|
54
56
|
*
|
|
55
57
|
* @param event Event
|
|
56
58
|
*/
|
|
57
|
-
|
|
59
|
+
onCreateBtnPress(event: Event): void {
|
|
58
60
|
const source = event.getSource<Button>();
|
|
59
61
|
source.setEnabled(false);
|
|
60
62
|
|
|
61
63
|
const fragmentName = this.model.getProperty('/newFragmentName');
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
this.createExtensionPointFragmentChange(fragmentName);
|
|
66
|
+
|
|
67
|
+
notifyUser(`Note: The '${fragmentName}.fragment.xml' fragment will be created once you save the change.`, 8000);
|
|
64
68
|
|
|
65
69
|
this.handleDialogClose();
|
|
66
70
|
}
|
|
@@ -127,24 +131,6 @@ export default class ExtensionPoint extends BaseDialog {
|
|
|
127
131
|
this.model.setProperty('/extensionListEnabled', enabled);
|
|
128
132
|
}
|
|
129
133
|
|
|
130
|
-
/**
|
|
131
|
-
* Creates a new fragment for the specified extension point
|
|
132
|
-
*
|
|
133
|
-
* @param fragmentName Fragment name
|
|
134
|
-
*/
|
|
135
|
-
private async createNewFragment(fragmentName: string): Promise<void> {
|
|
136
|
-
try {
|
|
137
|
-
await writeFragment<unknown>({ fragmentName });
|
|
138
|
-
MessageToast.show(`Fragment with name '${fragmentName}' was created.`);
|
|
139
|
-
} catch (e) {
|
|
140
|
-
// In case of error when creating a new fragment, we should not create a change file
|
|
141
|
-
MessageToast.show(e.message);
|
|
142
|
-
throw new Error(e.message);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
this.createExtensionPointFragmentChange(fragmentName);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
134
|
/**
|
|
149
135
|
* Creates add xml at extension point changes
|
|
150
136
|
*
|
|
@@ -153,6 +139,7 @@ export default class ExtensionPoint extends BaseDialog {
|
|
|
153
139
|
private createExtensionPointFragmentChange(fragmentName: string): void {
|
|
154
140
|
const extensionPointName = this.model.getProperty('/extensionPointName');
|
|
155
141
|
const modifiedValue = {
|
|
142
|
+
fragment: `<core:FragmentDefinition xmlns:core='sap.ui.core'></core:FragmentDefinition>`,
|
|
156
143
|
fragmentPath: `fragments/${fragmentName}.fragment.xml`,
|
|
157
144
|
extensionPointName
|
|
158
145
|
};
|
package/dist/client/adp/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
sap.ui.define([], function () {
|
|
3
|
+
sap.ui.define(["sap/m/MessageToast"], function (MessageToast) {
|
|
4
4
|
"use strict";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -26,10 +26,38 @@ sap.ui.define([], function () {
|
|
|
26
26
|
reject
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Checks if the fragment name associated with a command matches the specified fragment name.
|
|
32
|
+
*
|
|
33
|
+
* @param {FlexCommand} command - The command object containing the prepared change to be examined.
|
|
34
|
+
* @param {string} fragmentName - The name of the fragment to match against the command's change.
|
|
35
|
+
* @returns {boolean} Returns true if the command's change contains a fragment path that matches
|
|
36
|
+
* the specified fragment name; otherwise, returns false.
|
|
37
|
+
*/
|
|
38
|
+
function matchesFragmentName(command, fragmentName) {
|
|
39
|
+
const change = command.getPreparedChange().getDefinition();
|
|
40
|
+
return change.content?.fragmentPath?.includes(`${fragmentName}.fragment.xml`) || false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Displays a message to the user indicating that an XML fragment will be created upon saving a change.
|
|
45
|
+
*
|
|
46
|
+
* @param {string} message - The message to be shown in the message toast.
|
|
47
|
+
* @param {number} duration - The duration during which message toast will be active.
|
|
48
|
+
*/
|
|
49
|
+
function notifyUser(message) {
|
|
50
|
+
let duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5000;
|
|
51
|
+
MessageToast.show(message, {
|
|
52
|
+
duration
|
|
53
|
+
});
|
|
54
|
+
}
|
|
29
55
|
var __exports = {
|
|
30
56
|
__esModule: true
|
|
31
57
|
};
|
|
32
58
|
__exports.createDeferred = createDeferred;
|
|
59
|
+
__exports.matchesFragmentName = matchesFragmentName;
|
|
60
|
+
__exports.notifyUser = notifyUser;
|
|
33
61
|
return __exports;
|
|
34
62
|
});
|
|
35
63
|
//# sourceMappingURL=utils.js.map
|
package/dist/client/adp/utils.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import MessageToast from 'sap/m/MessageToast';
|
|
2
|
+
import type FlexCommand from 'sap/ui/rta/command/FlexCommand';
|
|
3
|
+
|
|
1
4
|
export interface Deferred<T> {
|
|
2
5
|
promise: Promise<T>;
|
|
3
6
|
resolve: (value: T | PromiseLike<T>) => void;
|
|
4
7
|
reject: (reason?: unknown) => void;
|
|
5
8
|
}
|
|
6
9
|
|
|
10
|
+
export interface FragmentChange {
|
|
11
|
+
content: {
|
|
12
|
+
fragmentPath: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
/**
|
|
8
17
|
* Defers the resolution of the promise, stores resolve/reject functions so that they can be accessed at a later stage.
|
|
9
18
|
*
|
|
@@ -26,3 +35,28 @@ export function createDeferred<T>(): Deferred<T> {
|
|
|
26
35
|
|
|
27
36
|
return { promise, resolve, reject };
|
|
28
37
|
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Checks if the fragment name associated with a command matches the specified fragment name.
|
|
41
|
+
*
|
|
42
|
+
* @param {FlexCommand} command - The command object containing the prepared change to be examined.
|
|
43
|
+
* @param {string} fragmentName - The name of the fragment to match against the command's change.
|
|
44
|
+
* @returns {boolean} Returns true if the command's change contains a fragment path that matches
|
|
45
|
+
* the specified fragment name; otherwise, returns false.
|
|
46
|
+
*/
|
|
47
|
+
export function matchesFragmentName(command: FlexCommand, fragmentName: string): boolean {
|
|
48
|
+
const change = command.getPreparedChange().getDefinition() as unknown as FragmentChange;
|
|
49
|
+
return change.content?.fragmentPath?.includes(`${fragmentName}.fragment.xml`) || false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Displays a message to the user indicating that an XML fragment will be created upon saving a change.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} message - The message to be shown in the message toast.
|
|
56
|
+
* @param {number} duration - The duration during which message toast will be active.
|
|
57
|
+
*/
|
|
58
|
+
export function notifyUser(message: string, duration: number = 5000) {
|
|
59
|
+
MessageToast.show(message, {
|
|
60
|
+
duration
|
|
61
|
+
});
|
|
62
|
+
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"bugs": {
|
|
10
10
|
"url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Apreview-middleware"
|
|
11
11
|
},
|
|
12
|
-
"version": "0.13.
|
|
12
|
+
"version": "0.13.20",
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"author": "@SAP/ux-tools-team",
|
|
15
15
|
"main": "dist/index.js",
|
|
@@ -23,10 +23,12 @@
|
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"ejs": "3.1.9",
|
|
26
|
+
"mem-fs": "2.1.0",
|
|
27
|
+
"mem-fs-editor": "9.4.0",
|
|
26
28
|
"@sap-ux/logger": "0.5.1",
|
|
27
|
-
"@sap-ux/adp-tooling": "0.9.
|
|
29
|
+
"@sap-ux/adp-tooling": "0.9.21",
|
|
28
30
|
"@sap-ux/control-property-editor-sources": "npm:@sap-ux/control-property-editor@0.4.17",
|
|
29
|
-
"@sap-ux/project-access": "1.19.
|
|
31
|
+
"@sap-ux/project-access": "1.19.12"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
34
|
"@types/ejs": "3.1.2",
|
|
@@ -34,13 +36,15 @@
|
|
|
34
36
|
"@types/prompts": "2.4.4",
|
|
35
37
|
"@types/supertest": "2.0.12",
|
|
36
38
|
"copyfiles": "2.4.1",
|
|
39
|
+
"@types/mem-fs": "1.1.2",
|
|
40
|
+
"@types/mem-fs-editor": "7.0.1",
|
|
37
41
|
"express": "4.19.2",
|
|
38
42
|
"npm-run-all": "4.1.5",
|
|
39
43
|
"nock": "13.4.0",
|
|
40
44
|
"supertest": "6.3.3",
|
|
41
45
|
"@sap-ux-private/playwright": "0.0.3",
|
|
42
46
|
"dotenv": "16.3.1",
|
|
43
|
-
"@private/preview-middleware-client": "npm:@sap-ux-private/preview-middleware-client@0.9.
|
|
47
|
+
"@private/preview-middleware-client": "npm:@sap-ux-private/preview-middleware-client@0.9.6",
|
|
44
48
|
"@sap-ux/axios-extension": "1.11.7",
|
|
45
49
|
"@sap-ux/store": "0.5.0",
|
|
46
50
|
"@sap-ux/i18n": "0.0.6"
|