@sapui5/sap.fe.test 1.101.0 → 1.102.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/sap/fe/test/.library +1 -1
- package/src/sap/fe/test/CollaborationClient.js +77 -0
- package/src/sap/fe/test/CollaborationClient.ts +105 -0
- package/src/sap/fe/test/FeMocks.js +1 -1
- package/src/sap/fe/test/FeMocks.ts +6 -2
- package/src/sap/fe/test/JestTemplatingHelper.js +51 -22
- package/src/sap/fe/test/JestTemplatingHelper.ts +46 -19
- package/src/sap/fe/test/ListReport.js +7 -15
- package/src/sap/fe/test/LocationUtil.js +12 -16
- package/src/sap/fe/test/ObjectPage.js +38 -6
- package/src/sap/fe/test/Shell.js +94 -34
- package/src/sap/fe/test/TemplatePage.js +14 -0
- package/src/sap/fe/test/UI5MockHelper.js +99 -18
- package/src/sap/fe/test/UI5MockHelper.ts +81 -14
- package/src/sap/fe/test/api/CollaborationAPI.js +215 -0
- package/src/sap/fe/test/api/CollaborationAPI.ts +240 -0
- package/src/sap/fe/test/api/DialogMassEditActions.js +115 -0
- package/src/sap/fe/test/api/DialogMassEditAssertions.js +174 -0
- package/src/sap/fe/test/api/DialogType.js +11 -2
- package/src/sap/fe/test/api/HeaderAssertions.js +76 -41
- package/src/sap/fe/test/api/TableAPI.js +30 -34
- package/src/sap/fe/test/api/TableActions.js +1 -1
- package/src/sap/fe/test/api/TableAssertions.js +51 -46
- package/src/sap/fe/test/builder/MacroFieldBuilder.js +161 -156
- package/src/sap/fe/test/builder/MdcTableBuilder.js +89 -12
- package/src/sap/fe/test/library.js +1 -1
- package/src/sap/fe/test/massEdit.js +0 -62
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* SAP UI development toolkit for HTML5 (SAPUI5)
|
|
3
|
+
* (c) Copyright 2009-2021 SAP SE. All rights reserved
|
|
4
|
+
*/
|
|
5
|
+
sap.ui.define(["sap/base/Log", "sap/fe/core/controllerextensions/collaboration/ActivityBase", "sap/fe/core/controllerextensions/collaboration/CollaborationCommon", "sap/fe/core/controllerextensions/editFlow/draft", "sap/ui/model/json/JSONModel"], function (Log, ActivityBase, CollaborationCommon, draft, JSONModel) {
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
var Activity = CollaborationCommon.Activity;
|
|
9
|
+
var initializeCollaboration = ActivityBase.initializeCollaboration;
|
|
10
|
+
var endCollaboration = ActivityBase.endCollaboration;
|
|
11
|
+
var broadcastCollaborationMessage = ActivityBase.broadcastCollaborationMessage;
|
|
12
|
+
|
|
13
|
+
var CollaborationAPI = {
|
|
14
|
+
_lastReceivedMessage: undefined,
|
|
15
|
+
_rootPath: "",
|
|
16
|
+
_oModel: undefined,
|
|
17
|
+
_lockedPropertyPath: "",
|
|
18
|
+
_internalModel: undefined,
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Open an existing collaborative draft with a new user, and creates a 'ghost client' for this user.
|
|
22
|
+
*
|
|
23
|
+
* @param oContext The context of the collaborative draft
|
|
24
|
+
* @param userID The ID of the user
|
|
25
|
+
* @param userName The name of the user
|
|
26
|
+
*/
|
|
27
|
+
enterDraft: function (oContext, userID, userName) {
|
|
28
|
+
var webSocketBaseURL = oContext.getModel().getMetaModel().getObject("/@com.sap.vocabularies.Common.v1.WebSocketBaseURL");
|
|
29
|
+
|
|
30
|
+
if (!webSocketBaseURL) {
|
|
31
|
+
Log.error("Cannot find WebSocketBaseURL annotation");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
var sDraftUUID = oContext.getProperty("DraftAdministrativeData/DraftUUID");
|
|
36
|
+
this._internalModel = new JSONModel({});
|
|
37
|
+
initializeCollaboration({
|
|
38
|
+
id: userID,
|
|
39
|
+
name: userName,
|
|
40
|
+
initialName: userName
|
|
41
|
+
}, webSocketBaseURL, sDraftUUID, this._internalModel, this._onMessageReceived.bind(this), true);
|
|
42
|
+
this._rootPath = oContext.getPath();
|
|
43
|
+
this._oModel = oContext.getModel();
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Checks if the ghost client has revieved a given message.
|
|
48
|
+
*
|
|
49
|
+
* @param message The message content to be looked for
|
|
50
|
+
* @returns True if the last recieved message matches the content
|
|
51
|
+
*/
|
|
52
|
+
checkReceived: function (message) {
|
|
53
|
+
if (!this._lastReceivedMessage) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var found = (!message.userID || message.userID === this._lastReceivedMessage.userID) && (!message.userAction || message.userAction === this._lastReceivedMessage.userAction) && (!message.clientContent || message.clientContent === this._lastReceivedMessage.clientContent);
|
|
58
|
+
this._lastReceivedMessage = undefined; // reset history to avoid finding the same message twice
|
|
59
|
+
|
|
60
|
+
return found;
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Closes the ghost client and removes the user from the collaborative draft.
|
|
65
|
+
*/
|
|
66
|
+
leaveDraft: function () {
|
|
67
|
+
if (this._internalModel) {
|
|
68
|
+
endCollaboration(this._internalModel);
|
|
69
|
+
|
|
70
|
+
this._internalModel.destroy();
|
|
71
|
+
|
|
72
|
+
this._internalModel = undefined;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Simulates that the user starts typing in an input (live change).
|
|
78
|
+
*
|
|
79
|
+
* @param sPropertyPath The path of the property being modified
|
|
80
|
+
*/
|
|
81
|
+
startLiveChange: function (sPropertyPath) {
|
|
82
|
+
if (this._internalModel) {
|
|
83
|
+
if (this._lockedPropertyPath) {
|
|
84
|
+
// Unlock previous property path
|
|
85
|
+
this.undoChange();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this._lockedPropertyPath = sPropertyPath;
|
|
89
|
+
broadcastCollaborationMessage(Activity.LiveChange, this._rootPath + "/" + sPropertyPath, this._internalModel);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Simulates that the user has modified a property.
|
|
95
|
+
*
|
|
96
|
+
* @param sPropertyPath The path of the property being modified
|
|
97
|
+
* @param value The new value of the property being modified
|
|
98
|
+
*/
|
|
99
|
+
updatePropertyValue: function (sPropertyPath, value) {
|
|
100
|
+
var _this = this;
|
|
101
|
+
|
|
102
|
+
if (this._internalModel) {
|
|
103
|
+
if (this._lockedPropertyPath !== sPropertyPath) {
|
|
104
|
+
this.startLiveChange(sPropertyPath);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
var oContextBinding = this._oModel.bindContext(this._rootPath, undefined, {
|
|
108
|
+
$$patchWithoutSideEffects: true,
|
|
109
|
+
$$groupId: "$auto",
|
|
110
|
+
$$updateGroupId: "$auto"
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
var oPropertyBinding = this._oModel.bindProperty(sPropertyPath, oContextBinding.getBoundContext());
|
|
114
|
+
|
|
115
|
+
oPropertyBinding.requestValue().then(function () {
|
|
116
|
+
oPropertyBinding.setValue(value);
|
|
117
|
+
oContextBinding.attachEventOnce("patchCompleted", function () {
|
|
118
|
+
broadcastCollaborationMessage(Activity.Change, _this._rootPath + "/" + sPropertyPath, _this._internalModel);
|
|
119
|
+
_this._lockedPropertyPath = "";
|
|
120
|
+
});
|
|
121
|
+
}).catch(function (err) {
|
|
122
|
+
Log.error(err);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Simulates that the user did an 'undo' (to be called after startLiveChange).
|
|
129
|
+
*/
|
|
130
|
+
undoChange: function () {
|
|
131
|
+
if (this._lockedPropertyPath) {
|
|
132
|
+
broadcastCollaborationMessage(Activity.Undo, this._rootPath + "/" + this._lockedPropertyPath, this._internalModel);
|
|
133
|
+
this._lockedPropertyPath = "";
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Simulates that the user has discarded the draft.
|
|
139
|
+
*/
|
|
140
|
+
discardDraft: function () {
|
|
141
|
+
var _this2 = this;
|
|
142
|
+
|
|
143
|
+
if (this._internalModel) {
|
|
144
|
+
var draftContext = this._getDraftContext();
|
|
145
|
+
|
|
146
|
+
draftContext.requestProperty("IsActiveEntity").then(function () {
|
|
147
|
+
draft.deleteDraft(draftContext);
|
|
148
|
+
}).then(function () {
|
|
149
|
+
broadcastCollaborationMessage(Activity.Discard, _this2._rootPath.replace("IsActiveEntity=false", "IsActiveEntity=true"), _this2._internalModel);
|
|
150
|
+
|
|
151
|
+
_this2._internalModel.destroy();
|
|
152
|
+
|
|
153
|
+
_this2._internalModel = undefined;
|
|
154
|
+
}).catch(function (err) {
|
|
155
|
+
Log.error(err);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Simulates that the user has deleted the draft.
|
|
162
|
+
*/
|
|
163
|
+
deleteDraft: function () {
|
|
164
|
+
var _this3 = this;
|
|
165
|
+
|
|
166
|
+
if (this._internalModel) {
|
|
167
|
+
var draftContext = this._getDraftContext();
|
|
168
|
+
|
|
169
|
+
var activeContext;
|
|
170
|
+
draftContext.requestProperty("IsActiveEntity").then(function () {
|
|
171
|
+
return draftContext.getModel().bindContext(_this3._rootPath + "/SiblingEntity").getBoundContext();
|
|
172
|
+
}).then(function (context) {
|
|
173
|
+
activeContext = context;
|
|
174
|
+
return context.requestCanonicalPath();
|
|
175
|
+
}).then(function () {
|
|
176
|
+
return draft.deleteDraft(draftContext);
|
|
177
|
+
}).then(function () {
|
|
178
|
+
activeContext.delete();
|
|
179
|
+
broadcastCollaborationMessage(Activity.Delete, _this3._rootPath, _this3._internalModel);
|
|
180
|
+
|
|
181
|
+
_this3._internalModel.destroy();
|
|
182
|
+
|
|
183
|
+
_this3._internalModel = undefined;
|
|
184
|
+
}).catch(function (err) {
|
|
185
|
+
Log.error(err);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
// /////////////////////////////
|
|
190
|
+
// Private methods
|
|
191
|
+
_getDraftContext: function () {
|
|
192
|
+
return this._oModel.bindContext(this._rootPath, undefined, {
|
|
193
|
+
$$patchWithoutSideEffects: true,
|
|
194
|
+
$$groupId: "$auto",
|
|
195
|
+
$$updateGroupId: "$auto"
|
|
196
|
+
}).getBoundContext();
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Callback of the ghost client when receiving a message on the web socket.
|
|
201
|
+
*
|
|
202
|
+
* @param oMessage The message
|
|
203
|
+
*/
|
|
204
|
+
_onMessageReceived: function (oMessage) {
|
|
205
|
+
oMessage.userAction = oMessage.userAction || oMessage.clientAction;
|
|
206
|
+
this._lastReceivedMessage = oMessage;
|
|
207
|
+
|
|
208
|
+
if (oMessage.userAction === Activity.Join) {
|
|
209
|
+
broadcastCollaborationMessage(Activity.JoinEcho, this._lockedPropertyPath ? this._rootPath + "/" + this._lockedPropertyPath : undefined, this._internalModel);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
return CollaborationAPI;
|
|
214
|
+
}, false);
|
|
215
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbGxhYm9yYXRpb25BUEkudHMiXSwibmFtZXMiOlsiQ29sbGFib3JhdGlvbkFQSSIsIl9sYXN0UmVjZWl2ZWRNZXNzYWdlIiwidW5kZWZpbmVkIiwiX3Jvb3RQYXRoIiwiX29Nb2RlbCIsIl9sb2NrZWRQcm9wZXJ0eVBhdGgiLCJfaW50ZXJuYWxNb2RlbCIsImVudGVyRHJhZnQiLCJvQ29udGV4dCIsInVzZXJJRCIsInVzZXJOYW1lIiwid2ViU29ja2V0QmFzZVVSTCIsImdldE1vZGVsIiwiZ2V0TWV0YU1vZGVsIiwiZ2V0T2JqZWN0IiwiTG9nIiwiZXJyb3IiLCJzRHJhZnRVVUlEIiwiZ2V0UHJvcGVydHkiLCJKU09OTW9kZWwiLCJpbml0aWFsaXplQ29sbGFib3JhdGlvbiIsImlkIiwibmFtZSIsImluaXRpYWxOYW1lIiwiX29uTWVzc2FnZVJlY2VpdmVkIiwiYmluZCIsImdldFBhdGgiLCJjaGVja1JlY2VpdmVkIiwibWVzc2FnZSIsImZvdW5kIiwidXNlckFjdGlvbiIsImNsaWVudENvbnRlbnQiLCJsZWF2ZURyYWZ0IiwiZW5kQ29sbGFib3JhdGlvbiIsImRlc3Ryb3kiLCJzdGFydExpdmVDaGFuZ2UiLCJzUHJvcGVydHlQYXRoIiwidW5kb0NoYW5nZSIsImJyb2FkY2FzdENvbGxhYm9yYXRpb25NZXNzYWdlIiwiQWN0aXZpdHkiLCJMaXZlQ2hhbmdlIiwidXBkYXRlUHJvcGVydHlWYWx1ZSIsInZhbHVlIiwib0NvbnRleHRCaW5kaW5nIiwiYmluZENvbnRleHQiLCIkJHBhdGNoV2l0aG91dFNpZGVFZmZlY3RzIiwiJCRncm91cElkIiwiJCR1cGRhdGVHcm91cElkIiwib1Byb3BlcnR5QmluZGluZyIsImJpbmRQcm9wZXJ0eSIsImdldEJvdW5kQ29udGV4dCIsInJlcXVlc3RWYWx1ZSIsInRoZW4iLCJzZXRWYWx1ZSIsImF0dGFjaEV2ZW50T25jZSIsIkNoYW5nZSIsImNhdGNoIiwiZXJyIiwiVW5kbyIsImRpc2NhcmREcmFmdCIsImRyYWZ0Q29udGV4dCIsIl9nZXREcmFmdENvbnRleHQiLCJyZXF1ZXN0UHJvcGVydHkiLCJkcmFmdCIsImRlbGV0ZURyYWZ0IiwiRGlzY2FyZCIsInJlcGxhY2UiLCJhY3RpdmVDb250ZXh0IiwiY29udGV4dCIsInJlcXVlc3RDYW5vbmljYWxQYXRoIiwiZGVsZXRlIiwiRGVsZXRlIiwib01lc3NhZ2UiLCJjbGllbnRBY3Rpb24iLCJKb2luIiwiSm9pbkVjaG8iXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQVVBLE1BQU1BLGdCQUFnQixHQUFHO0FBQ3hCQyxJQUFBQSxvQkFBb0IsRUFBRUMsU0FERTtBQUV4QkMsSUFBQUEsU0FBUyxFQUFFLEVBRmE7QUFHeEJDLElBQUFBLE9BQU8sRUFBRUYsU0FIZTtBQUl4QkcsSUFBQUEsbUJBQW1CLEVBQUUsRUFKRztBQUt4QkMsSUFBQUEsY0FBYyxFQUFFSixTQUxROztBQU94QjtBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNDSyxJQUFBQSxVQUFVLEVBQUUsVUFBVUMsUUFBVixFQUE2QkMsTUFBN0IsRUFBNkNDLFFBQTdDLEVBQStEO0FBQzFFLFVBQU1DLGdCQUF3QixHQUFHSCxRQUFRLENBQUNJLFFBQVQsR0FBb0JDLFlBQXBCLEdBQW1DQyxTQUFuQyxDQUE2QyxtREFBN0MsQ0FBakM7O0FBRUEsVUFBSSxDQUFDSCxnQkFBTCxFQUF1QjtBQUN0QkksUUFBQUEsR0FBRyxDQUFDQyxLQUFKLENBQVUseUNBQVY7QUFDQTtBQUNBOztBQUVELFVBQU1DLFVBQWtCLEdBQUdULFFBQVEsQ0FBQ1UsV0FBVCxDQUFxQixtQ0FBckIsQ0FBM0I7QUFDQSxXQUFLWixjQUFMLEdBQXNCLElBQUlhLFNBQUosQ0FBYyxFQUFkLENBQXRCO0FBRUFDLE1BQUFBLHVCQUF1QixDQUN0QjtBQUNDQyxRQUFBQSxFQUFFLEVBQUVaLE1BREw7QUFFQ2EsUUFBQUEsSUFBSSxFQUFFWixRQUZQO0FBR0NhLFFBQUFBLFdBQVcsRUFBRWI7QUFIZCxPQURzQixFQU10QkMs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b2cgZnJvbSBcInNhcC9iYXNlL0xvZ1wiO1xuaW1wb3J0IHtcblx0YnJvYWRjYXN0Q29sbGFib3JhdGlvbk1lc3NhZ2UsXG5cdGVuZENvbGxhYm9yYXRpb24sXG5cdGluaXRpYWxpemVDb2xsYWJvcmF0aW9uXG59IGZyb20gXCJzYXAvZmUvY29yZS9jb250cm9sbGVyZXh0ZW5zaW9ucy9jb2xsYWJvcmF0aW9uL0FjdGl2aXR5QmFzZVwiO1xuaW1wb3J0IHsgQWN0aXZpdHksIE1lc3NhZ2UgfSBmcm9tIFwic2FwL2ZlL2NvcmUvY29udHJvbGxlcmV4dGVuc2lvbnMvY29sbGFib3JhdGlvbi9Db2xsYWJvcmF0aW9uQ29tbW9uXCI7XG5pbXBvcnQgZHJhZnQgZnJvbSBcInNhcC9mZS9jb3JlL2NvbnRyb2xsZXJleHRlbnNpb25zL2VkaXRGbG93L2RyYWZ0XCI7XG5pbXBvcnQgQ29udGV4dCBmcm9tIFwic2FwL3VpL21vZGVsL0NvbnRleHRcIjtcbmltcG9ydCBKU09OTW9kZWwgZnJvbSBcInNhcC91aS9tb2RlbC9qc29uL0pTT05Nb2RlbFwiO1xuaW1wb3J0IE9EYXRhTW9kZWwgZnJvbSBcInNhcC91aS9tb2RlbC9vZGF0YS92NC9PRGF0YU1vZGVsXCI7XG5cbmNvbnN0IENvbGxhYm9yYXRpb25BUEkgPSB7XG5cdF9sYXN0UmVjZWl2ZWRNZXNzYWdlOiB1bmRlZmluZWQgYXMgTWVzc2FnZSB8IHVuZGVmaW5lZCxcblx0X3Jvb3RQYXRoOiBcIlwiLFxuXHRfb01vZGVsOiB1bmRlZmluZWQgYXMgT0RhdGFNb2RlbCB8IHVuZGVmaW5lZCxcblx0X2xvY2tlZFByb3BlcnR5UGF0aDogXCJcIixcblx0X2ludGVybmFsTW9kZWw6IHVuZGVmaW5lZCBhcyBKU09OTW9kZWwgfCB1bmRlZmluZWQsXG5cblx0LyoqXG5cdCAqIE9wZW4gYW4gZXhpc3RpbmcgY29sbGFib3JhdGl2ZSBkcmFmdCB3aXRoIGEgbmV3IHVzZXIsIGFuZCBjcmVhdGVzIGEgJ2dob3N0IGNsaWVudCcgZm9yIHRoaXMgdXNlci5cblx0ICpcblx0ICogQHBhcmFtIG9Db250ZXh0IFRoZSBjb250ZXh0IG9mIHRoZSBjb2xsYWJvcmF0aXZlIGRyYWZ0XG5cdCAqIEBwYXJhbSB1c2VySUQgVGhlIElEIG9mIHRoZSB1c2VyXG5cdCAqIEBwYXJhbSB1c2VyTmFtZSBUaGUgbmFtZSBvZiB0aGUgdXNlclxuXHQgKi9cblx0ZW50ZXJEcmFmdDogZnVuY3Rpb24gKG9Db250ZXh0OiBDb250ZXh0LCB1c2VySUQ6IHN0cmluZywgdXNlck5hbWU6IHN0cmluZykge1xuXHRcdGNvbnN0IHdlYlNvY2tldEJhc2VVUkw6IHN0cmluZyA9IG9Db250ZXh0LmdldE1vZGVsKCkuZ2V0TWV0YU1vZGVsKCkuZ2V0T2JqZWN0KFwiL0Bjb20uc2FwLnZvY2FidWxhcmllcy5Db21tb24udjEuV2ViU29ja2V0QmFzZVVSTFwiKTtcblxuXHRcdGlmICghd2ViU29ja2V0QmFzZVVSTCkge1xuXHRcdFx0TG9nLmVycm9yKFwiQ2Fubm90IGZpbmQgV2ViU29ja2V0QmFzZVVSTCBhbm5vdGF0aW9uXCIpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IHNEcmFmdFVVSUQ6IHN0cmluZyA9IG9Db250ZXh0LmdldFByb3BlcnR5KFwiRHJhZnRBZG1pbmlzdHJhdGl2ZURhdGEvRHJhZnRVVUlEXCIpO1xuXHRcdHRoaXMuX2ludGVybmFsTW9kZWwgPSBuZXcgSlNPTk1vZGVsKHt9KTtcblxuXHRcdGluaXRpYWxpemVDb2xsYWJvcmF0aW9uKFxuXHRcdFx0e1xuXHRcdFx0XHRpZDogdXNlcklELFxuXHRcdFx0XHRuYW1lOiB1c2VyTmFtZSxcblx0XHRcdFx0aW5pdGlhbE5hbWU6IHVzZXJOYW1lXG5cdFx0XHR9LFxuXHRcdFx0d2ViU29ja2V0QmFzZVVSTCxcblx0XHRcdHNEcmFmdFVVSUQsXG5cdFx0XHR0aGlzLl9pbnRlcm5hbE1vZGVsLFxuXHRcdFx0dGhpcy5fb25NZXNzYWdlUmVjZWl2ZWQuYmluZCh0aGlzKSxcblx0XHRcdHRydWVcblx0XHQpO1xuXG5cdFx0dGhpcy5fcm9vdFBhdGggPSBvQ29udGV4dC5nZXRQYXRoKCk7XG5cdFx0dGhpcy5fb01vZGVsID0gb0NvbnRleHQuZ2V0TW9kZWwoKSBhcyBPRGF0YU1vZGVsO1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgdGhlIGdob3N0IGNsaWVudCBoYXMgcmV2aWV2ZWQgYSBnaXZlbiBtZXNzYWdlLlxuXHQgKlxuXHQgKiBAcGFyYW0gbWVzc2FnZSBUaGUgbWVzc2FnZSBjb250ZW50IHRvIGJlIGxvb2tlZCBmb3Jcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgbGFzdCByZWNpZXZlZCBtZXNzYWdlIG1hdGNoZXMgdGhlIGNvbnRlbnRcblx0ICovXG5cdGNoZWNrUmVjZWl2ZWQ6IGZ1bmN0aW9uIChtZXNzYWdlOiBQYXJ0aWFsPE1lc3NhZ2U+KTogYm9vbGVhbiB7XG5cdFx0aWYgKCF0aGlzLl9sYXN0UmVjZWl2ZWRNZXNzYWdlKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZm91bmQgPVxuXHRcdFx0KCFtZXNzYWdlLnVzZXJJRCB8fCBtZXNzYWdlLnVzZXJJRCA9PT0gdGhpcy5fbGFzdFJlY2VpdmVkTWVzc2FnZS51c2VySUQpICYmXG5cdFx0XHQoIW1lc3NhZ2UudXNlckFjdGlvbiB8fCBtZXNzYWdlLnVzZXJBY3Rpb24gPT09IHRoaXMuX2xhc3RSZWNlaXZlZE1lc3NhZ2UudXNlckFjdGlvbikgJiZcblx0XHRcdCghbWVzc2FnZS5jbGllbnRDb250ZW50IHx8IG1lc3NhZ2UuY2xpZW50Q29udGVudCA9PT0gdGhpcy5fbGFzdFJlY2VpdmVkTWVzc2FnZS5jbGllbnRDb250ZW50KTtcblxuXHRcdHRoaXMuX2xhc3RSZWNlaXZlZE1lc3NhZ2UgPSB1bmRlZmluZWQ7IC8vIHJlc2V0IGhpc3RvcnkgdG8gYXZvaWQgZmluZGluZyB0aGUgc2FtZSBtZXNzYWdlIHR3aWNlXG5cblx0XHRyZXR1cm4gZm91bmQ7XG5cdH0sXG5cblx0LyoqXG5cdCAqIENsb3NlcyB0aGUgZ2hvc3QgY2xpZW50IGFuZCByZW1vdmVzIHRoZSB1c2VyIGZyb20gdGhlIGNvbGxhYm9yYXRpdmUgZHJhZnQuXG5cdCAqL1xuXHRsZWF2ZURyYWZ0OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2ludGVybmFsTW9kZWwpIHtcblx0XHRcdGVuZENvbGxhYm9yYXRpb24odGhpcy5faW50ZXJuYWxNb2RlbCk7XG5cdFx0XHR0aGlzLl9pbnRlcm5hbE1vZGVsLmRlc3Ryb3koKTtcblx0XHRcdHRoaXMuX2ludGVybmFsTW9kZWwgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHR9LFxuXG5cdC8qKlxuXHQgKiBTaW11bGF0ZXMgdGhhdCB0aGUgdXNlciBzdGFydHMgdHlwaW5nIGluIGFuIGlucHV0IChsaXZlIGNoYW5nZSkuXG5cdCAqXG5cdCAqIEBwYXJhbSBzUHJvcGVydHlQYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSBiZWluZyBtb2RpZmllZFxuXHQgKi9cblx0c3RhcnRMaXZlQ2hhbmdlOiBmdW5jdGlvbiAoc1Byb3BlcnR5UGF0aDogc3RyaW5nKSB7XG5cdFx0aWYgKHRoaXMuX2ludGVybmFsTW9kZWwpIHtcblx0XHRcdGlmICh0aGlzLl9sb2NrZWRQcm9wZXJ0eVBhdGgpIHtcblx0XHRcdFx0Ly8gVW5sb2NrIHByZXZpb3VzIHByb3BlcnR5IHBhdGhcblx0XHRcdFx0dGhpcy51bmRvQ2hhbmdlKCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLl9sb2NrZWRQcm9wZXJ0eVBhdGggPSBzUHJvcGVydHlQYXRoO1xuXHRcdFx0YnJvYWRjYXN0Q29sbGFib3JhdGlvbk1lc3NhZ2UoQWN0aXZpdHkuTGl2ZUNoYW5nZSwgdGhpcy5fcm9vdFBhdGggKyBcIi9cIiArIHNQcm9wZXJ0eVBhdGgsIHRoaXMuX2ludGVybmFsTW9kZWwpO1xuXHRcdH1cblx0fSxcblxuXHQvKipcblx0ICogU2ltdWxhdGVzIHRoYXQgdGhlIHVzZXIgaGFzIG1vZGlmaWVkIGEgcHJvcGVydHkuXG5cdCAqXG5cdCAqIEBwYXJhbSBzUHJvcGVydHlQYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSBiZWluZyBtb2RpZmllZFxuXHQgKiBAcGFyYW0gdmFsdWUgVGhlIG5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgYmVpbmcgbW9kaWZpZWRcblx0ICovXG5cdHVwZGF0ZVByb3BlcnR5VmFsdWU6IGZ1bmN0aW9uIChzUHJvcGVydHlQYXRoOiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcblx0XHRpZiAodGhpcy5faW50ZXJuYWxNb2RlbCkge1xuXHRcdFx0aWYgKHRoaXMuX2xvY2tlZFByb3BlcnR5UGF0aCAhPT0gc1Byb3BlcnR5UGF0aCkge1xuXHRcdFx0XHR0aGlzLnN0YXJ0TGl2ZUNoYW5nZShzUHJvcGVydHlQYXRoKTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3Qgb0NvbnRleHRCaW5kaW5nID0gdGhpcy5fb01vZGVsIS5iaW5kQ29udGV4dCh0aGlzLl9yb290UGF0aCwgdW5kZWZpbmVkLCB7XG5cdFx0XHRcdCQkcGF0Y2hXaXRob3V0U2lkZUVmZmVjdHM6IHRydWUsXG5cdFx0XHRcdCQkZ3JvdXBJZDogXCIkYXV0b1wiLFxuXHRcdFx0XHQkJHVwZGF0ZUdyb3VwSWQ6IFwiJGF1dG9cIlxuXHRcdFx0fSk7XG5cblx0XHRcdGNvbnN0IG9Qcm9wZXJ0eUJpbmRpbmcgPSB0aGlzLl9vTW9kZWwhLmJpbmRQcm9wZXJ0eShzUHJvcGVydHlQYXRoLCBvQ29udGV4dEJpbmRpbmcuZ2V0Qm91bmRDb250ZXh0KCkpO1xuXG5cdFx0XHRvUHJvcGVydHlCaW5kaW5nXG5cdFx0XHRcdC5yZXF1ZXN0VmFsdWUoKVxuXHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0b1Byb3BlcnR5QmluZGluZy5zZXRWYWx1ZSh2YWx1ZSk7XG5cdFx0XHRcdFx0b0NvbnRleHRCaW5kaW5nLmF0dGFjaEV2ZW50T25jZShcInBhdGNoQ29tcGxldGVkXCIsICgpID0+IHtcblx0XHRcdFx0XHRcdGJyb2FkY2FzdENvbGxhYm9yYXRpb25NZXNzYWdlKEFjdGl2aXR5LkNoYW5nZSwgdGhpcy5fcm9vdFBhdGggKyBcIi9cIiArIHNQcm9wZXJ0eVBhdGgsIHRoaXMuX2ludGVybmFsTW9kZWwhKTtcblx0XHRcdFx0XHRcdHRoaXMuX2xvY2tlZFByb3BlcnR5UGF0aCA9IFwiXCI7XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0pXG5cdFx0XHRcdC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG5cdFx0XHRcdFx0TG9nLmVycm9yKGVycik7XG5cdFx0XHRcdH0pO1xuXHRcdH1cblx0fSxcblxuXHQvKipcblx0ICogU2ltdWxhdGVzIHRoYXQgdGhlIHVzZXIgZGlkIGFuICd1bmRvJyAodG8gYmUgY2FsbGVkIGFmdGVyIHN0YXJ0TGl2ZUNoYW5nZSkuXG5cdCAqL1xuXHR1bmRvQ2hhbmdlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2xvY2tlZFByb3BlcnR5UGF0aCkge1xuXHRcdFx0YnJvYWRjYXN0Q29sbGFib3JhdGlvbk1lc3NhZ2UoQWN0aXZpdHkuVW5kbywgdGhpcy5fcm9vdFBhdGggKyBcIi9cIiArIHRoaXMuX2xvY2tlZFByb3BlcnR5UGF0aCwgdGhpcy5faW50ZXJuYWxNb2RlbCEpO1xuXHRcdFx0dGhpcy5fbG9ja2VkUHJvcGVydHlQYXRoID0gXCJcIjtcblx0XHR9XG5cdH0sXG5cblx0LyoqXG5cdCAqIFNpbXVsYXRlcyB0aGF0IHRoZSB1c2VyIGhhcyBkaXNjYXJkZWQgdGhlIGRyYWZ0LlxuXHQgKi9cblx0ZGlzY2FyZERyYWZ0OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2ludGVybmFsTW9kZWwpIHtcblx0XHRcdGNvbnN0IGRyYWZ0Q29udGV4dCA9IHRoaXMuX2dldERyYWZ0Q29udGV4dCgpO1xuXG5cdFx0XHRkcmFmdENvbnRleHRcblx0XHRcdFx0LnJlcXVlc3RQcm9wZXJ0eShcIklzQWN0aXZlRW50aXR5XCIpXG5cdFx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0XHRkcmFmdC5kZWxldGVEcmFmdChkcmFmdENvbnRleHQpO1xuXHRcdFx0XHR9KVxuXHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0YnJvYWRjYXN0Q29sbGFib3JhdGlvbk1lc3NhZ2UoXG5cdFx0XHRcdFx0XHRBY3Rpdml0eS5EaXNjYXJkLFxuXHRcdFx0XHRcdFx0dGhpcy5fcm9vdFBhdGgucmVwbGFjZShcIklzQWN0aXZlRW50aXR5PWZhbHNlXCIsIFwiSXNBY3RpdmVFbnRpdHk9dHJ1ZVwiKSxcblx0XHRcdFx0XHRcdHRoaXMuX2ludGVybmFsTW9kZWwhXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR0aGlzLl9pbnRlcm5hbE1vZGVsIS5kZXN0cm95KCk7XG5cdFx0XHRcdFx0dGhpcy5faW50ZXJuYWxNb2RlbCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKGZ1bmN0aW9uIChlcnI6IGFueSkge1xuXHRcdFx0XHRcdExvZy5lcnJvcihlcnIpO1xuXHRcdFx0XHR9KTtcblx0XHR9XG5cdH0sXG5cblx0LyoqXG5cdCAqIFNpbXVsYXRlcyB0aGF0IHRoZSB1c2VyIGhhcyBkZWxldGVkIHRoZSBkcmFmdC5cblx0ICovXG5cdGRlbGV0ZURyYWZ0OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2ludGVybmFsTW9kZWwpIHtcblx0XHRcdGNvbnN0IGRyYWZ0Q29udGV4dCA9IHRoaXMuX2dldERyYWZ0Q29udGV4dCgpO1xuXHRcdFx0bGV0IGFjdGl2ZUNvbnRleHQ6IENvbnRleHQ7XG5cblx0XHRcdGRyYWZ0Q29udGV4dFxuXHRcdFx0XHQucmVxdWVzdFByb3BlcnR5KFwiSXNBY3RpdmVFbnRpdHlcIilcblx0XHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdHJldHVybiBkcmFmdENvbnRleHRcblx0XHRcdFx0XHRcdC5nZXRNb2RlbCgpXG5cdFx0XHRcdFx0XHQuYmluZENvbnRleHQodGhpcy5fcm9vdFBhdGggKyBcIi9TaWJsaW5nRW50aXR5XCIpXG5cdFx0XHRcdFx0XHQuZ2V0Qm91bmRDb250ZXh0KCk7XG5cdFx0XHRcdH0pXG5cdFx0XHRcdC50aGVuKChjb250ZXh0OiBhbnkpID0+IHtcblx0XHRcdFx0XHRhY3RpdmVDb250ZXh0ID0gY29udGV4dDtcblx0XHRcdFx0XHRyZXR1cm4gY29udGV4dC5yZXF1ZXN0Q2Fub25pY2FsUGF0aCgpO1xuXHRcdFx0XHR9KVxuXHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0cmV0dXJuIGRyYWZ0LmRlbGV0ZURyYWZ0KGRyYWZ0Q29udGV4dCk7XG5cdFx0XHRcdH0pXG5cdFx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0XHQoYWN0aXZlQ29udGV4dCBhcyBhbnkpLmRlbGV0ZSgpO1xuXHRcdFx0XHRcdGJyb2FkY2FzdENvbGxhYm9yYXRpb25NZXNzYWdlKEFjdGl2aXR5LkRlbGV0ZSwgdGhpcy5fcm9vdFBhdGgsIHRoaXMuX2ludGVybmFsTW9kZWwhKTtcblx0XHRcdFx0XHR0aGlzLl9pbnRlcm5hbE1vZGVsIS5kZXN0cm95KCk7XG5cdFx0XHRcdFx0dGhpcy5faW50ZXJuYWxNb2RlbCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKGZ1bmN0aW9uIChlcnI6IGFueSkge1xuXHRcdFx0XHRcdExvZy5lcnJvcihlcnIpO1xuXHRcdFx0XHR9KTtcblx0XHR9XG5cdH0sXG5cblx0Ly8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblx0Ly8gUHJpdmF0ZSBtZXRob2RzXG5cblx0X2dldERyYWZ0Q29udGV4dDogZnVuY3Rpb24gKCk6IGFueSB7XG5cdFx0cmV0dXJuIHRoaXMuX29Nb2RlbCEuYmluZENvbnRleHQodGhpcy5fcm9vdFBhdGgsIHVuZGVmaW5lZCwge1xuXHRcdFx0JCRwYXRjaFdpdGhvdXRTaWRlRWZmZWN0czogdHJ1ZSxcblx0XHRcdCQkZ3JvdXBJZDogXCIkYXV0b1wiLFxuXHRcdFx0JCR1cGRhdGVHcm91cElkOiBcIiRhdXRvXCJcblx0XHR9KS5nZXRCb3VuZENvbnRleHQoKTtcblx0fSxcblxuXHQvKipcblx0ICogQ2FsbGJhY2sgb2YgdGhlIGdob3N0IGNsaWVudCB3aGVuIHJlY2VpdmluZyBhIG1lc3NhZ2Ugb24gdGhlIHdlYiBzb2NrZXQuXG5cdCAqXG5cdCAqIEBwYXJhbSBvTWVzc2FnZSBUaGUgbWVzc2FnZVxuXHQgKi9cblx0X29uTWVzc2FnZVJlY2VpdmVkOiBmdW5jdGlvbiAob01lc3NhZ2U6IE1lc3NhZ2UpIHtcblx0XHRvTWVzc2FnZS51c2VyQWN0aW9uID0gb01lc3NhZ2UudXNlckFjdGlvbiB8fCBvTWVzc2FnZS5jbGllbnRBY3Rpb247XG5cdFx0dGhpcy5fbGFzdFJlY2VpdmVkTWVzc2FnZSA9IG9NZXNzYWdlO1xuXG5cdFx0aWYgKG9NZXNzYWdlLnVzZXJBY3Rpb24gPT09IEFjdGl2aXR5LkpvaW4pIHtcblx0XHRcdGJyb2FkY2FzdENvbGxhYm9yYXRpb25NZXNzYWdlKFxuXHRcdFx0XHRBY3Rpdml0eS5Kb2luRWNobyxcblx0XHRcdFx0dGhpcy5fbG9ja2VkUHJvcGVydHlQYXRoID8gdGhpcy5fcm9vdFBhdGggKyBcIi9cIiArIHRoaXMuX2xvY2tlZFByb3BlcnR5UGF0aCA6IHVuZGVmaW5lZCxcblx0XHRcdFx0dGhpcy5faW50ZXJuYWxNb2RlbCFcblx0XHRcdCk7XG5cdFx0fVxuXHR9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBDb2xsYWJvcmF0aW9uQVBJO1xuIl19
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import Log from "sap/base/Log";
|
|
2
|
+
import {
|
|
3
|
+
broadcastCollaborationMessage,
|
|
4
|
+
endCollaboration,
|
|
5
|
+
initializeCollaboration
|
|
6
|
+
} from "sap/fe/core/controllerextensions/collaboration/ActivityBase";
|
|
7
|
+
import { Activity, Message } from "sap/fe/core/controllerextensions/collaboration/CollaborationCommon";
|
|
8
|
+
import draft from "sap/fe/core/controllerextensions/editFlow/draft";
|
|
9
|
+
import Context from "sap/ui/model/Context";
|
|
10
|
+
import JSONModel from "sap/ui/model/json/JSONModel";
|
|
11
|
+
import ODataModel from "sap/ui/model/odata/v4/ODataModel";
|
|
12
|
+
|
|
13
|
+
const CollaborationAPI = {
|
|
14
|
+
_lastReceivedMessage: undefined as Message | undefined,
|
|
15
|
+
_rootPath: "",
|
|
16
|
+
_oModel: undefined as ODataModel | undefined,
|
|
17
|
+
_lockedPropertyPath: "",
|
|
18
|
+
_internalModel: undefined as JSONModel | undefined,
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Open an existing collaborative draft with a new user, and creates a 'ghost client' for this user.
|
|
22
|
+
*
|
|
23
|
+
* @param oContext The context of the collaborative draft
|
|
24
|
+
* @param userID The ID of the user
|
|
25
|
+
* @param userName The name of the user
|
|
26
|
+
*/
|
|
27
|
+
enterDraft: function (oContext: Context, userID: string, userName: string) {
|
|
28
|
+
const webSocketBaseURL: string = oContext.getModel().getMetaModel().getObject("/@com.sap.vocabularies.Common.v1.WebSocketBaseURL");
|
|
29
|
+
|
|
30
|
+
if (!webSocketBaseURL) {
|
|
31
|
+
Log.error("Cannot find WebSocketBaseURL annotation");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const sDraftUUID: string = oContext.getProperty("DraftAdministrativeData/DraftUUID");
|
|
36
|
+
this._internalModel = new JSONModel({});
|
|
37
|
+
|
|
38
|
+
initializeCollaboration(
|
|
39
|
+
{
|
|
40
|
+
id: userID,
|
|
41
|
+
name: userName,
|
|
42
|
+
initialName: userName
|
|
43
|
+
},
|
|
44
|
+
webSocketBaseURL,
|
|
45
|
+
sDraftUUID,
|
|
46
|
+
this._internalModel,
|
|
47
|
+
this._onMessageReceived.bind(this),
|
|
48
|
+
true
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
this._rootPath = oContext.getPath();
|
|
52
|
+
this._oModel = oContext.getModel() as ODataModel;
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Checks if the ghost client has revieved a given message.
|
|
57
|
+
*
|
|
58
|
+
* @param message The message content to be looked for
|
|
59
|
+
* @returns True if the last recieved message matches the content
|
|
60
|
+
*/
|
|
61
|
+
checkReceived: function (message: Partial<Message>): boolean {
|
|
62
|
+
if (!this._lastReceivedMessage) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const found =
|
|
67
|
+
(!message.userID || message.userID === this._lastReceivedMessage.userID) &&
|
|
68
|
+
(!message.userAction || message.userAction === this._lastReceivedMessage.userAction) &&
|
|
69
|
+
(!message.clientContent || message.clientContent === this._lastReceivedMessage.clientContent);
|
|
70
|
+
|
|
71
|
+
this._lastReceivedMessage = undefined; // reset history to avoid finding the same message twice
|
|
72
|
+
|
|
73
|
+
return found;
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Closes the ghost client and removes the user from the collaborative draft.
|
|
78
|
+
*/
|
|
79
|
+
leaveDraft: function () {
|
|
80
|
+
if (this._internalModel) {
|
|
81
|
+
endCollaboration(this._internalModel);
|
|
82
|
+
this._internalModel.destroy();
|
|
83
|
+
this._internalModel = undefined;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Simulates that the user starts typing in an input (live change).
|
|
89
|
+
*
|
|
90
|
+
* @param sPropertyPath The path of the property being modified
|
|
91
|
+
*/
|
|
92
|
+
startLiveChange: function (sPropertyPath: string) {
|
|
93
|
+
if (this._internalModel) {
|
|
94
|
+
if (this._lockedPropertyPath) {
|
|
95
|
+
// Unlock previous property path
|
|
96
|
+
this.undoChange();
|
|
97
|
+
}
|
|
98
|
+
this._lockedPropertyPath = sPropertyPath;
|
|
99
|
+
broadcastCollaborationMessage(Activity.LiveChange, this._rootPath + "/" + sPropertyPath, this._internalModel);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Simulates that the user has modified a property.
|
|
105
|
+
*
|
|
106
|
+
* @param sPropertyPath The path of the property being modified
|
|
107
|
+
* @param value The new value of the property being modified
|
|
108
|
+
*/
|
|
109
|
+
updatePropertyValue: function (sPropertyPath: string, value: any) {
|
|
110
|
+
if (this._internalModel) {
|
|
111
|
+
if (this._lockedPropertyPath !== sPropertyPath) {
|
|
112
|
+
this.startLiveChange(sPropertyPath);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const oContextBinding = this._oModel!.bindContext(this._rootPath, undefined, {
|
|
116
|
+
$$patchWithoutSideEffects: true,
|
|
117
|
+
$$groupId: "$auto",
|
|
118
|
+
$$updateGroupId: "$auto"
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const oPropertyBinding = this._oModel!.bindProperty(sPropertyPath, oContextBinding.getBoundContext());
|
|
122
|
+
|
|
123
|
+
oPropertyBinding
|
|
124
|
+
.requestValue()
|
|
125
|
+
.then(() => {
|
|
126
|
+
oPropertyBinding.setValue(value);
|
|
127
|
+
oContextBinding.attachEventOnce("patchCompleted", () => {
|
|
128
|
+
broadcastCollaborationMessage(Activity.Change, this._rootPath + "/" + sPropertyPath, this._internalModel!);
|
|
129
|
+
this._lockedPropertyPath = "";
|
|
130
|
+
});
|
|
131
|
+
})
|
|
132
|
+
.catch(function (err) {
|
|
133
|
+
Log.error(err);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Simulates that the user did an 'undo' (to be called after startLiveChange).
|
|
140
|
+
*/
|
|
141
|
+
undoChange: function () {
|
|
142
|
+
if (this._lockedPropertyPath) {
|
|
143
|
+
broadcastCollaborationMessage(Activity.Undo, this._rootPath + "/" + this._lockedPropertyPath, this._internalModel!);
|
|
144
|
+
this._lockedPropertyPath = "";
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Simulates that the user has discarded the draft.
|
|
150
|
+
*/
|
|
151
|
+
discardDraft: function () {
|
|
152
|
+
if (this._internalModel) {
|
|
153
|
+
const draftContext = this._getDraftContext();
|
|
154
|
+
|
|
155
|
+
draftContext
|
|
156
|
+
.requestProperty("IsActiveEntity")
|
|
157
|
+
.then(() => {
|
|
158
|
+
draft.deleteDraft(draftContext);
|
|
159
|
+
})
|
|
160
|
+
.then(() => {
|
|
161
|
+
broadcastCollaborationMessage(
|
|
162
|
+
Activity.Discard,
|
|
163
|
+
this._rootPath.replace("IsActiveEntity=false", "IsActiveEntity=true"),
|
|
164
|
+
this._internalModel!
|
|
165
|
+
);
|
|
166
|
+
this._internalModel!.destroy();
|
|
167
|
+
this._internalModel = undefined;
|
|
168
|
+
})
|
|
169
|
+
.catch(function (err: any) {
|
|
170
|
+
Log.error(err);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Simulates that the user has deleted the draft.
|
|
177
|
+
*/
|
|
178
|
+
deleteDraft: function () {
|
|
179
|
+
if (this._internalModel) {
|
|
180
|
+
const draftContext = this._getDraftContext();
|
|
181
|
+
let activeContext: Context;
|
|
182
|
+
|
|
183
|
+
draftContext
|
|
184
|
+
.requestProperty("IsActiveEntity")
|
|
185
|
+
.then(() => {
|
|
186
|
+
return draftContext
|
|
187
|
+
.getModel()
|
|
188
|
+
.bindContext(this._rootPath + "/SiblingEntity")
|
|
189
|
+
.getBoundContext();
|
|
190
|
+
})
|
|
191
|
+
.then((context: any) => {
|
|
192
|
+
activeContext = context;
|
|
193
|
+
return context.requestCanonicalPath();
|
|
194
|
+
})
|
|
195
|
+
.then(() => {
|
|
196
|
+
return draft.deleteDraft(draftContext);
|
|
197
|
+
})
|
|
198
|
+
.then(() => {
|
|
199
|
+
(activeContext as any).delete();
|
|
200
|
+
broadcastCollaborationMessage(Activity.Delete, this._rootPath, this._internalModel!);
|
|
201
|
+
this._internalModel!.destroy();
|
|
202
|
+
this._internalModel = undefined;
|
|
203
|
+
})
|
|
204
|
+
.catch(function (err: any) {
|
|
205
|
+
Log.error(err);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
// /////////////////////////////
|
|
211
|
+
// Private methods
|
|
212
|
+
|
|
213
|
+
_getDraftContext: function (): any {
|
|
214
|
+
return this._oModel!.bindContext(this._rootPath, undefined, {
|
|
215
|
+
$$patchWithoutSideEffects: true,
|
|
216
|
+
$$groupId: "$auto",
|
|
217
|
+
$$updateGroupId: "$auto"
|
|
218
|
+
}).getBoundContext();
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Callback of the ghost client when receiving a message on the web socket.
|
|
223
|
+
*
|
|
224
|
+
* @param oMessage The message
|
|
225
|
+
*/
|
|
226
|
+
_onMessageReceived: function (oMessage: Message) {
|
|
227
|
+
oMessage.userAction = oMessage.userAction || oMessage.clientAction;
|
|
228
|
+
this._lastReceivedMessage = oMessage;
|
|
229
|
+
|
|
230
|
+
if (oMessage.userAction === Activity.Join) {
|
|
231
|
+
broadcastCollaborationMessage(
|
|
232
|
+
Activity.JoinEcho,
|
|
233
|
+
this._lockedPropertyPath ? this._rootPath + "/" + this._lockedPropertyPath : undefined,
|
|
234
|
+
this._internalModel!
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
export default CollaborationAPI;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ! SAP UI development toolkit for HTML5 (SAPUI5)
|
|
3
|
+
(c) Copyright 2009-2021 SAP SE. All rights reserved
|
|
4
|
+
|
|
5
|
+
*/
|
|
6
|
+
sap.ui.define(
|
|
7
|
+
["./DialogActions", "sap/fe/test/Utils", "sap/ui/test/OpaBuilder", "sap/fe/test/builder/FEBuilder"],
|
|
8
|
+
function (DialogActions, Utils, OpaBuilder, FEBuilder) {
|
|
9
|
+
"use strict";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Constructs a new DialogMassEditActions instance.
|
|
13
|
+
*
|
|
14
|
+
* @param {sap.fe.test.builder.DialogBuilder} oDialogBuilder The {@link sap.fe.test.builder.DialogBuilder} instance used to interact with the UI
|
|
15
|
+
* @param {string} [vDialogDescription] Description (optional) of the dialog to be used for logging messages
|
|
16
|
+
* @returns {sap.fe.test.api.DialogMassEditActions} The new instance
|
|
17
|
+
* @extends sap.fe.test.api.DialogActions
|
|
18
|
+
* @alias sap.fe.test.api.DialogMassEditActions
|
|
19
|
+
* @class
|
|
20
|
+
* @hideconstructor
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
var DialogMassEditActions = function (oDialogBuilder, vDialogDescription) {
|
|
24
|
+
return DialogActions.call(this, oDialogBuilder, vDialogDescription, 0);
|
|
25
|
+
};
|
|
26
|
+
DialogMassEditActions.prototype = Object.create(DialogActions.prototype);
|
|
27
|
+
DialogMassEditActions.prototype.constructor = DialogMassEditActions;
|
|
28
|
+
DialogMassEditActions.prototype.isAction = true;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A mass edit field identifier
|
|
32
|
+
*
|
|
33
|
+
* @typedef {object} MassEditFieldIdentifier
|
|
34
|
+
* @property {string} property The name of the property
|
|
35
|
+
* @name sap.fe.test.api.MassEditFieldIdentifier
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A mass edit field value
|
|
41
|
+
*
|
|
42
|
+
* @typedef {object} MassEditValue
|
|
43
|
+
* @property {string} dropDownText The dropdown text for the selection
|
|
44
|
+
* @property {string} rawText The raw text for the selection
|
|
45
|
+
* @name sap.fe.test.api.MassEditValue
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Changes the value of the defined filter field.
|
|
51
|
+
*
|
|
52
|
+
* @param {string | sap.fe.test.api.MassEditFieldIdentifier} vMassEditFieldIdentifier The identifier for the mass edit field
|
|
53
|
+
* @param {string | sap.fe.test.api.MassEditValue} vMassEditValue The new target value
|
|
54
|
+
* @param {object} [mState] The state of the mass edit field
|
|
55
|
+
* @param {object} [mProperties] The Properties of the mass edit field
|
|
56
|
+
* @returns {object} The result of the {@link sap.ui.test.Opa5#waitFor} function, to be used for chained statements
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
DialogMassEditActions.prototype.iChangeField = function (vMassEditFieldIdentifier, vMassEditValue, mState, mProperties) {
|
|
60
|
+
var that = this,
|
|
61
|
+
sProperty = Utils.isOfType(vMassEditFieldIdentifier, String) ? vMassEditFieldIdentifier : vMassEditFieldIdentifier.property,
|
|
62
|
+
vValue = vMassEditValue && (Utils.isOfType(vMassEditValue, String) ? { rawText: vMassEditValue } : vMassEditValue),
|
|
63
|
+
fieldRegEx = new RegExp("^MED(.*)" + sProperty + "$", "gi");
|
|
64
|
+
|
|
65
|
+
return that.prepareResult(
|
|
66
|
+
FEBuilder.create(this.getOpaInstance())
|
|
67
|
+
.isDialogElement()
|
|
68
|
+
.has(FEBuilder.Matchers.id(fieldRegEx))
|
|
69
|
+
.hasState(mState)
|
|
70
|
+
.hasProperties(mProperties)
|
|
71
|
+
.doPress()
|
|
72
|
+
.success(function (aSelect) {
|
|
73
|
+
var oRet,
|
|
74
|
+
oSelect = aSelect[0],
|
|
75
|
+
sControlType = oSelect.getMetadata().getName();
|
|
76
|
+
if (vValue.dropDownText) {
|
|
77
|
+
oRet = OpaBuilder.create()
|
|
78
|
+
.hasType("sap.ui.core.Item")
|
|
79
|
+
.has(OpaBuilder.Matchers.ancestor(oSelect[0], false))
|
|
80
|
+
.hasProperties({ text: vValue.dropDownText })
|
|
81
|
+
.doPress()
|
|
82
|
+
.description(
|
|
83
|
+
Utils.formatMessage(
|
|
84
|
+
"Value '{3}' selected for '{0}' in mass edit dialog '{1}'",
|
|
85
|
+
sProperty,
|
|
86
|
+
that.getIdentifier(),
|
|
87
|
+
vValue.dropDownText
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
.execute();
|
|
91
|
+
} else if (vValue.rawText && sControlType === "sap.m.ComboBox") {
|
|
92
|
+
oRet = OpaBuilder.create()
|
|
93
|
+
.hasId(oSelect.getId())
|
|
94
|
+
.doEnterText(vValue.rawText)
|
|
95
|
+
.description(
|
|
96
|
+
Utils.formatMessage(
|
|
97
|
+
"Value '{3}' entered for '{0}' in mass edit dialog '{1}'",
|
|
98
|
+
sProperty,
|
|
99
|
+
that.getIdentifier(),
|
|
100
|
+
vValue.rawText
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
.execute();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return oRet;
|
|
107
|
+
})
|
|
108
|
+
.description(Utils.formatMessage("Mass edit dropdown for '{0}' found in dialog '{1}'", sProperty, that.getIdentifier()))
|
|
109
|
+
.execute()
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return DialogMassEditActions;
|
|
114
|
+
}
|
|
115
|
+
);
|