-
Notifications
You must be signed in to change notification settings - Fork 62
/
CrudService.js
419 lines (393 loc) · 17 KB
/
CrudService.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
/**
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This is a generic service for handling CRUD requests between widgets and the repository. By default
* all URLs will be encoded unless [encodeURIs]{@link module:alfresco/core/CoreXhr#encodeURIs}
* is configured to be false.
*
* @module alfresco/services/CrudService
* @extends module:alfresco/services/BaseService
* @mixes module:alfresco/core/CoreXhr
* @author Dave Draper
*/
define(["dojo/_base/declare",
"alfresco/services/BaseService",
"alfresco/core/CoreXhr",
"alfresco/core/topics",
"service/constants/Default",
"alfresco/dialogs/AlfDialog",
"dojo/_base/lang",
"dojo/_base/array",
"alfresco/util/urlUtils"],
function(declare, BaseService, CoreXhr, topics, AlfConstants, AlfDialog, lang, array, urlUtils) {
return declare([BaseService, CoreXhr], {
/**
* An array of the i18n files to use with this service.
*
* @instance
* @type {object[]}
* @default [{i18nFile: "./i18n/CrudService.properties"}]
*/
i18nRequirements: [{i18nFile: "./i18n/CrudService.properties"}],
/**
* @instance
* @since 1.0.32
*/
registerSubscriptions: function alfresco_services_CrudService__registerSubscriptions() {
this.alfSubscribe("ALF_CRUD_GET_ALL", lang.hitch(this, this.onGetAll));
this.alfSubscribe("ALF_CRUD_GET_ONE", lang.hitch(this, this.onGetOne));
this.alfSubscribe("ALF_CRUD_CREATE", lang.hitch(this, this.onCreate));
this.alfSubscribe("ALF_CRUD_UPDATE", lang.hitch(this, this.onUpdate));
this.alfSubscribe("ALF_CRUD_DELETE", lang.hitch(this, this.onDelete));
},
/**
* This is called whenever a create, update or delete operation is performed to ensure that
* any associated list views are refreshed. It does this by publishing on the "ALF_DOCLIST_RELOAD_DATA"
* topic (for historical reasons - a more generic topic should be used in the future).
*
* @instance
* @param {object} response The response from the original XHR request.
* @param {object} originalRequestConfig The configuration passed to the original XHR request.
* @fires module:alfresco/core/topics#DISPLAY_NOTIFICATION
*/
refreshRequest: function alfresco_services_CrudService__refreshRequest(response, originalRequestConfig) {
var responseTopic = lang.getObject("alfTopic", false, originalRequestConfig);
if (responseTopic) {
this.alfPublish(responseTopic + "_SUCCESS", response);
} else {
this.alfLog("warn", "It was not possible to publish requested CRUD data because the 'responseTopic' attribute was not set on the original request", response, originalRequestConfig);
}
var message = lang.getObject("successMessage", false, originalRequestConfig);
if (!message) {
message = "crudservice.generic.success.message";
}
this.alfServicePublish(topics.DISPLAY_NOTIFICATION, {
message: this.message(message)
});
var noRefresh = lang.getObject("data.noRefresh", false, originalRequestConfig);
if (noRefresh !== true)
{
// See AKU-1020
// Check the original request for a "createdItemKey" attribute, this will be passed on in
// the reload data request to give the list an opportunity to select the created item...
var payload = null;
if (originalRequestConfig.createdItemKey)
{
var itemKey = lang.getObject(originalRequestConfig.createdItemKey, false, response);
if (itemKey)
{
payload = {
focusItemKey: itemKey
};
}
}
this.alfPublish("ALF_DOCLIST_RELOAD_DATA", payload, false, false, originalRequestConfig.responseScope);
}
},
/**
* This function is called to get the URL from the payload provided and will issue a warning if one
* is not found. This is called from all the CRUD handling functions. The payload is expected to contain
* a 'url' attribute that maps to a Repository WebScript. This function will automatically prefix it
* with the appropriate proxy stem.
*
* @instance
* @param {object} payload
* @returns {string} The URL to use to make the CRUD request or null if no 'url' attribute was provided.
*/
getUrlFromPayload: function alfresco_services_CrudService__getUrlFromPayload(payload) {
var url = lang.getObject("url", false, payload);
if (!url)
{
this.alfLog("warn", "A request was made to service a CRUD request but no 'url' attribute was provided on the payload", payload, this);
}
else
{
var urlType = payload.urlType;
if (!urlType || urlType === "PROXY")
{
url = AlfConstants.PROXY_URI + url;
}
else if (urlType === "SHARE")
{
url = AlfConstants.URL_SERVICECONTEXT + url;
}
else if (urlType === "FULL")
{
// No action, leave the URL as it is.
}
else
{
this.alfLog("warn", "An unknown URL type was requested, using provided URL", payload, this);
}
}
return url;
},
/**
* This is a utility function for cloning a payload and removing attributes that should not be
* passed onto the [serviceXhr] {@link module:alfresco/core/CoreXhr#serviceXhr} function
*
* @param {object} payload The payload to clone
* @returns {object} The cloned payload
*/
clonePayload: function alfresco_services_CrudService__clonePayload(payload) {
return this.alfCleanFrameworkAttributes(payload, false, ["url","createdItemKey"]);
},
/**
* @instance
* @see module:alfresco/util/urlUtils#addQueryParameter
*/
addQueryParameter: function alfresco_services_CrudService__addQueryParameter() {
return urlUtils.addQueryParameter.apply(urlUtils, arguments);
},
/**
* Makes a GET request to the Repository using the 'url' attribute provided in the payload passed
* in the publication on the topic that this function subscribes to. The 'url' is expected to be a
* Repository WebScript URL and should not include the Repository proxy stem.
*
* @instance
* @param {object} payload
*/
onGetAll: function alfresco_services_CrudService__onGetAll(payload) {
var url = this.getUrlFromPayload(payload);
if (payload.pageSize)
{
url = this.addQueryParameter(url, "pageSize", payload.pageSize);
}
if (payload.page)
{
url = this.addQueryParameter(url, "page", payload.page);
}
if (payload.page && payload.pageSize)
{
var startIndex = (payload.page - 1) * payload.pageSize;
url = this.addQueryParameter(url, "startIndex", startIndex);
}
if (payload.dataFilters)
{
url = urlUtils.addFilterQueryParameters(url, payload);
}
var config = {
url: url,
responseScope: payload.alfResponseScope,
data: this.clonePayload(payload),
alfTopic: payload.alfResponseTopic || null,
method: "GET"
};
if (payload.preventCache)
{
config.preventCache = payload.preventCache;
}
if (url)
{
this.serviceXhr(config);
}
},
/**
* TODO: This needs to be completed.
*
* @instance
* @param {object} payload
*/
onGetOne: function alfresco_services_CrudService__onGetOne(payload) {
// TODO: Need to append the identifier to specify the object to retrieve
var url = this.getUrlFromPayload(payload);
if (url) {
this.serviceXhr({
url: url,
responseScope: payload.alfResponseScope,
data: this.clonePayload(payload),
method: "GET"
});
}
},
/**
* Creates a new item via the supplied URL. The payload needs to contain both a 'url' attribute
* (that indicates the REST API to call) and a 'data' attribute (that defines the object to be
* created).
*
* @instance
* @param {object} payload
*/
onCreate: function alfresco_services_CrudService__onCreate(payload) {
var url = this.getUrlFromPayload(payload);
this.serviceXhr({
url: url,
createdItemKey: payload.createdItemKey,
responseScope: payload.alfResponseScope,
data: this.clonePayload(payload),
method: "POST",
alfTopic: payload.alfResponseTopic,
successMessage: this.message(payload.successMessage || "crudservice.generic.success.message"),
successCallback: this.refreshRequest,
failureMessage: this.message(payload.failureMessage || "crudservice.generic.failure.message"),
failureCallback: this.failureCallback,
callbackScope: this
});
},
/**
*
* @instance
* @param {object} payload
*/
onUpdate: function alfresco_services_CrudService__onUpdate(payload) {
var url = this.getUrlFromPayload(payload);
this.serviceXhr({
url: url,
responseScope: payload.alfResponseScope,
data: this.clonePayload(payload),
method: "PUT",
alfTopic: payload.alfResponseTopic,
successMessage: this.message(payload.successMessage || "crudservice.generic.success.message"),
successCallback: this.refreshRequest,
failureMessage: this.message(payload.failureMessage || "crudservice.generic.failure.message"),
failureCallback: this.failureCallback,
callbackScope: this
});
},
/**
* Handles delete requests. If the supplied payload contains an attribute "requiresConfirmation"
* that is set to true, then a dialog will be displayed prompting the user to confirm the delete
* action. The payload can optionally contain localized messages for the dialog title, prompt
* and button labels.
*
* @instance
* @param {object} payload
*/
onDelete: function alfresco_services_CrudService__onDelete(payload) {
// TODO: Need to determine whether or not the ID should be provided in the payload or
// as part of the URL.
var url = this.getUrlFromPayload(payload);
if (url !== null)
{
if (payload.requiresConfirmation === true)
{
this.requestDeleteConfirmation(url, payload);
}
else
{
this.performDelete(url, payload);
}
}
},
/**
* Called from [onDelete]{@link module:alfresco/services/CrudService#onDelete} when user confirmation
* for the delete action is required. Displays a dialog prompting the user to confirm the action.
* The dialog title, prompt and button labels can all be configured via the attributes on the
* supplied payload.
*
* @instance
* @param {string} url The URL to use to perform the delete
* @param {object} payload The original request payload.
*/
requestDeleteConfirmation: function alfresco_services_CrudService__requestDeleteConfirmation(url, payload) {
var responseTopic = this.generateUuid();
this._deleteHandle = this.alfSubscribe(responseTopic, lang.hitch(this, this.onDeleteConfirmation), true);
var title = payload.confirmationTitle || "crudservice.generic.delete.title";
var prompt = payload.confirmationPrompt || "crudservice.generic.delete.prompt";
var confirmButtonLabel = payload.confirmationButtonLabel || "crudservice.generic.delete.confirmationButtonLabel";
var cancelButtonLabel = payload.cancellationButtonLabel || "crudservice.generic.delete.cancellationButtonLabel";
this.alfServicePublish(topics.CREATE_DIALOG, {
dialogId: "ALF_CRUD_SERVICE_DELETE_CONFIRMATION_DIALOG",
dialogTitle: this.message(title),
textContent: this.message(prompt),
widgetsButtons: [
{
id: "ALF_CRUD_SERVICE_DELETE_CONFIRMATION_DIALOG_CONFIRM",
name: "alfresco/buttons/AlfButton",
config: {
label: this.message(confirmButtonLabel),
publishTopic: responseTopic,
publishPayload: {
url: url,
responseScope: payload.alfResponseScope,
responseTopic: payload.responseTopic,
successMessage: this.message(payload.successMessage || "crudservice.generic.success.message"),
failureMessage: this.message(payload.failureMessage || "crudservice.generic.failure.message")
}
}
},
{
id: "ALF_CRUD_SERVICE_DELETE_CONFIRMATION_DIALOG_CANCEL",
name: "alfresco/buttons/AlfButton",
config: {
label: this.message(cancelButtonLabel),
publishTopic: "close"
}
}
]
});
},
/**
* Handles the actual deletion, this is abstracted to a separate function so that it can be called from
* both [onDelete]{@link module:alfresco/services/CrudService#onDelete} and
* [onDeleteConfirmation]{@link module:alfresco/services/CrudService#onDeleteConfirmation} depending upon
* whether or not the user needs to confirm the delete action.
*
* @instance
* @param {string} url The URL to use to perform the delete
* @param {object} payload The original payload
*/
performDelete: function alfresco_services_CrudService__performDelete(url, payload) {
this.serviceXhr({
url: url,
method: "DELETE",
responseScope: payload.alfResponseScope,
data: this.clonePayload(payload),
alfTopic: payload.responseTopic,
successMessage: this.message(payload.successMessage || "crudservice.generic.success.message"),
successCallback: this.refreshRequest,
failureMessage: this.message(payload.failureMessage || "crudservice.generic.failure.message"),
failureCallback: this.failureCallback,
callbackScope: this
});
},
/**
* This function is called when the user confirms that they wish to peform the delete action.
*
* @instance
* @param {object} payload An object containing the deletion details.
*/
onDeleteConfirmation: function alfresco_services_CrudService__onDeleteConfirmation(payload) {
this.alfUnsubscribeSaveHandles([this._deleteHandle]);
this.performDelete(payload.url, payload);
},
/**
* This is called whenever a create, update or delete operation fails. It will generate a notification
* with a message (optionally supplied as failureMessage in the payload).
*
* @instance
* @param {object} response The response from the original XHR request.
* @param {object} originalRequestConfig The configuration passed to the original XHR request.
*/
failureCallback: function alfresco_services_CrudService__failureCallback(response, originalRequestConfig) {
// Publish failure topic as necessary
if (originalRequestConfig.alfTopic) {
this.alfPublish(originalRequestConfig.alfTopic + "_FAILURE", {
requestConfig: originalRequestConfig,
response: response
});
}
// Get the failure message and display a notification
var message = originalRequestConfig.failureMessage || this.message("crudservice.generic.failure.message");
this.alfPublish("ALF_DISPLAY_PROMPT", {
message: this.message(message)
});
}
});
});