| 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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483 |
1×
1×
1×
83×
1×
83×
83×
83×
83×
83×
83×
83×
83×
83×
2×
83×
2×
2×
83×
2×
2×
83×
83×
83×
79×
4×
83×
83×
83×
83×
83×
83×
1×
59×
59×
59×
5×
5×
54×
9×
9×
59×
59×
14×
14×
14×
14×
14×
1×
50×
50×
1×
16×
16×
1×
13×
4×
13×
8×
4×
5×
1×
5×
5×
1×
24×
24×
1×
21×
21×
21×
1×
21×
21×
1×
2×
1×
5×
5×
1×
19×
19×
1×
16×
16×
16×
1×
16×
1×
2×
1×
5×
1×
1×
1×
1×
1×
5×
1×
8×
1×
79×
79×
1×
4×
4×
1×
19×
1×
55×
8×
8×
47×
1×
8×
8×
8×
8×
8×
8×
1×
55×
9×
9×
9×
9×
9×
6×
46×
1×
9×
6×
9×
9×
9×
1×
5×
5×
3×
3×
3×
2×
2×
1×
5×
5×
5×
5×
3×
3×
3×
2×
2×
1×
9×
9×
9×
6×
3×
3×
1×
3×
1×
3×
1×
3×
3×
3×
1×
3×
3×
9×
3×
3×
1×
3×
3×
3×
1×
2×
2×
1×
2×
2×
1×
6×
6×
6×
1×
3×
3×
1×
3×
3×
3×
3×
3×
| /**
* @ngdoc service
* @name app.crud.crudHelper
* @description
* Adds CRUD functionality to a controller
*
*/
(function () {
'use strict';
angular
.module('app.crud')
.factory('crudHelper', factory);
/** @ngInject */
function factory($log, modalConfirm, $q,
$filter, loadingHelper, errorsHelper, toastrHelper, authHelper,
waitingState, crudResource, editInProgress, autoFocus, animationTimers) {
return activate;
/**
* @ngdoc function
* @name activate
* @methodOf app.crud.crudHelper
* @description
* Adds members to a controller:
* * beginWait()
* * entityList
* * editEntity
* * newEntity
* @param {Object} vm
* Controller instance
* @param {Object} options
* Controller specific information and callbacks
* * response array
* * resourceName
* * prepareToCreateEntity()
* * prepareToUpdateEntity()
* * beforeShowNewEntity()
* * beforeShowEditEntity()
* * getEntityDisplayName()
* * makeEntityBody()
* * scope
* * entityKind
* * errorsMap
*/
function activate(vm, options) {
var response = options.response;
var errorsMap = options.errorsMap;
var scope = options.scope;
// Aggregate functionality from other helpers
authHelper(vm, scope);
loadingHelper(vm);
toastrHelper(vm, scope);
errorsHelper(vm, errorsMap);
// initialize instance properties
/**
* @ngdoc function
* @name beginWait
* @methodOf app.crud.crudHelper
* @description
* Begins application waiting state
* @returns {Function}
* Ends application waiting state
*/
vm.beginWait = waitingState.beginWait;
/**
* @ngdoc property
* @name entityList
* @propertyOf app.crud.crudHelper
* @description
* Object to manage a list of entities
*/
vm.entityList = {
deleteItem: deleteEntity,
hidingItem: hidingEntity,
animatingItem: animatingEntity,
entitys: [],
kind: options.entityKind,
allowDelete: function () {
return vm.loggedIn;
}
};
/**
* @ngdoc property
* @name editEntity
* @propertyOf app.crud.crudHelper
* @description
* Object to edit a particular entity
*/
vm.editEntity = {
form: null,
errors: null,
cancel: cancelEditEntity,
submit: submitEditEntity,
ok: 'Save',
entity: null,
show: showEditEntity,
showingForm: showingEditEntityForm,
allow: function () {
return vm.loggedIn;
},
clearErrors: function (names) {
vm.clearErrors(vm.editEntity.errors, names);
}
};
/**
* @ngdoc property
* @name editEntity
* @propertyOf app.crud.crudHelper
* @description
* Object to create a new entity
*/
vm.newEntity = {
form: null,
errors: null,
cancel: cancelNewEntity,
submit: submitNewEntity,
ok: 'Add',
entity: null,
show: showNewEntity,
showingForm: showingNewEntityForm,
showing: false,
allow: function () {
return vm.loggedIn;
},
clearErrors: function (names) {
vm.clearErrors(vm.newEntity.errors, names);
}
};
// Allow new and edit operations to be cancelled
editInProgress.registerOnQueryState(scope, getEditorState);
editInProgress.registerOnClose(scope, closeEditors);
if (angular.isArray(response))
entityLoadingHasCompleted(response);
else
entityLoadHasFailed(response);
// Unique identifiers
var CRUD = 'crud';
var REFOCUS = 'refocus';
// Flags used to animate forms
var hideEditForm = false;
var hideNewForm = false;
var hiddenEntity = null;
var animatedEntity = null;
// Provide information used to cancel editing
function getEditorState(event, data) {
var editing = false;
var message;
if (vm.editEntity.entity && vm.editEntity.form && !vm.editEntity.form.$pristine) {
editing = true;
message = 'You have unsaved edits of ' + options.getEntityDisplayName(vm.editEntity.entity) +
'. Do you want to discard your edits?';
} else if (vm.newEntity.entity && vm.newEntity.form && !vm.newEntity.form.$pristine) {
editing = true;
message = 'You are adding a new ' + options.entityKind +
'. Do you want to discard your input?';
}
data.name = CRUD;
if (editing) {
data.labels.text = message;
data.labels.title = 'Confirm Discard Edits';
data.pristine = false;
data.autoFocus = REFOCUS;
data.autoFocusScope = options.scope;
}
}
// Method to close editors. May be called to close new form when edit button is clicked.
// May also be called when leaving view.
function closeEditors(event, state, defer) {
Eif (state.name == CRUD) {
// add promises to array parameter
defer.push(resetNewEntity(), resetEditEntity());
}
}
//
// Methods called from view
//
function deleteEntity(entity, confirmDelete) {
vm.clearToast();
editInProgress.closeEditors().then(del);
function del() {
if (angular.isUndefined(confirmDelete))
confirmDelete = true;
if (confirmDelete) {
modalConfirm.confirm({
title: 'Confirm Delete', message: 'Are you sure that you want to delete "' +
options.getEntityDisplayName(entity) + '"?'
})
.then(function () {
removeEntity(entity)
});
}
else {
removeEntity(entity)
}
}
}
function submitNewEntity() {
var submitEntity = options.prepareToCreateEntity(vm.newEntity.entity);
createEntity(submitEntity);
}
function showNewEntity() {
vm.clearToast();
editInProgress.closeEditors().then(
show
);
function show() {
hideNewForm = false;
vm.newEntity.entity = {};
options.beforeShowNewEntity().then(showEntity);
function showEntity() {
vm.newEntity.showing = true;
// new entity form should have an element with the following attribute.
// fe-auto-focus='refocus'
autoFocus(options.scope, REFOCUS);
}
}
}
function cancelNewEntity() {
resetNewEntity();
}
function submitEditEntity() {
var submit = options.prepareToUpdateEntity(vm.editEntity.entity);
updateEntity(submit);
}
function showEditEntity(entity) {
vm.clearToast();
editInProgress.closeEditors().then(
show
);
function show() {
hideEditForm = false;
// Edit a copy, so can discard unless click Save
vm.editEntity.entity = angular.copy(entity);
options.beforeShowEditEntity().then(showEntity);
function showEntity() {
// new entity form should have an element with the following attribute.
// fe-auto-focus='refocus'
autoFocus(options.scope, REFOCUS);
}
}
}
function cancelEditEntity() {
resetEditEntity();
}
function editingEntity(entity) {
return vm.editEntity.entity && (vm.editEntity.entity.id == entity.id);
}
function hidingEntity(entity) {
return hiddenEntity === entity.id;
}
function animatingEntity(entity) {
return animatedEntity === entity.id;
}
function showingEditEntityForm(entity) {
return editingEntity(entity) && !hideEditForm;
}
function showingNewEntityForm() {
return vm.newEntity.showing && !hideNewForm;
}
//
// Methods called after load
//
function entityLoadingHasCompleted(response) {
vm.entityList.entitys = response;
vm.loading.hasCompleted();
}
function entityLoadHasFailed(response) {
$log.error('data error ' + response.status + " " + response.statusText);
vm.loading.hasFailed(response);
}
//
// Internal methods
//
function getResource() {
return crudResource.getResource(options.resourceName)
}
function resetNewEntity() {
if (vm.newEntity.showing) {
// Trigger animation
hideNewForm = true;
// Return promise
return animationTimers.delayOut().then(hide);
}
else
return $q.resolve();
function hide() {
Eif (vm.newEntity.form) {
vm.newEntity.form.$setPristine();
}
vm.newEntity.showing = false;
vm.newEntity.entity = null;
vm.newEntity.errors = null;
hideNewForm = false;
}
}
function resetEditEntity() {
if (vm.editEntity.entity) {
// Trigger animation
hideEditForm = true;
// Keep entity hidden until form is hidden
hiddenEntity = vm.editEntity.entity.id;
// Return promise
return animationTimers.delayOut().then(function () {
clear();
if (!animatedEntity)
hiddenEntity = null;
});
}
else
return $q.resolve();
function clear() {
if (vm.editEntity.form) {
vm.editEntity.form.$setPristine();
}
vm.editEntity.entity = null;
vm.editEntity.errors = null;
hideEditForm = false;
}
}
function createEntity(entity) {
var body = options.makeEntityBody(entity);
getResource().save(body,
function (response) {
var newEntity = angular.copy(entity);
angular.merge(newEntity, response);
entityCreated(newEntity);
},
function (response) {
$log.error('create error ' + response.status + " " + response.statusText);
entityCreateError(entity, response);
}
);
}
function updateEntity(entity) {
var id = entity.id;
var key = {id: id};
var body = options.makeEntityBody(entity);
getResource().update(key, body,
function (response) {
var updatedEntity = angular.copy(entity);
angular.merge(updatedEntity, response);
entityUpdated(updatedEntity);
},
function (response) {
$log.error('update error ' + response.status + " " + response.statusText);
entityUpdateError(entity, response);
}
);
}
function removeEntity(entity) {
var id = entity.id;
var key = {id: id};
getResource().remove(key,
function () {
entityRemoved(entity);
},
function (response) {
$log.error('remove entity error ' + response.status + " " + response.statusText);
entityRemoveError(entity, response);
}
);
}
function entityCreated(entity) {
resetNewEntity().then(insert);
function insert() {
vm.entityList.entitys.splice(0, 0, entity);
}
}
function entityUpdated(entity) {
// Animate change to entity
hiddenEntity = vm.editEntity.entity.id;
animatedEntity = vm.editEntity.entity.id;
resetEditEntity().then(replace).finally(show);
function replace() {
var id = entity.id;
var found = $filter('filter')(vm.entityList.entitys, function (o) {
return o.id === id;
});
Eif (found && found.length === 1) {
angular.copy(entity, found[0]);
}
}
function show() {
hiddenEntity = null;
animationTimers.delayIn().then(function () {
animatedEntity = null;
});
}
}
function entityCreateError(entity, response) {
vm.showHttpErrorToast(response.status);
vm.newEntity.errors = vm.errorsOfResponse(response);
}
function entityUpdateError(entity, response) {
vm.showHttpErrorToast(response.status);
vm.editEntity.errors = vm.errorsOfResponse(response);
}
function entityRemoved(entity) {
var i = vm.entityList.entitys.indexOf(entity);
Eif (i >= 0) {
vm.entityList.entitys.splice(i, 1);
}
}
function entityRemoveError(entity, response) {
Eif (!vm.showHttpErrorToast(response.status)) {
showErrorToast()
}
function showErrorToast() {
var message = "";
var errors = vm.errorsOfResponse(response);
Eif (errors && errors.other && errors.other[0])
message = errors.other[0];
vm.showToast(message, "Unable to Delete");
}
}
}
}
})
();
|