forms-angular 0.12.0-beta.18 → 0.12.0-beta.182
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/client/forms-angular-bs-common.less +44 -4
- package/dist/client/forms-angular-bs2-specific.less +1 -1
- package/dist/client/forms-angular-bs3-specific.less +1 -1
- package/dist/client/forms-angular-with-bs2.css +2 -2
- package/dist/client/forms-angular-with-bs3.css +3 -3
- package/dist/client/forms-angular-with-bs3.less +1 -1
- package/dist/client/forms-angular.js +1261 -666
- package/dist/client/forms-angular.min.js +1 -1
- package/dist/client/index.d.ts +118 -49
- package/dist/server/data_form.js +1427 -942
- package/dist/server/index.d.ts +101 -0
- package/package.json +40 -41
- package/CHANGELOG.md +0 -255
|
@@ -9,12 +9,12 @@ var fng;
|
|
|
9
9
|
restrict: 'AE',
|
|
10
10
|
replace: true,
|
|
11
11
|
template: '<li ng-show="items.length > 0" class="mcdd" uib-dropdown>' +
|
|
12
|
-
' <a uib-dropdown-toggle>' +
|
|
12
|
+
' <a href="#" uib-dropdown-toggle>' +
|
|
13
13
|
' {{contextMenu}} <b class="caret"></b>' +
|
|
14
14
|
' </a>' +
|
|
15
15
|
' <ul class="uib-dropdown-menu dropdown-menu">' +
|
|
16
16
|
' <li ng-repeat="choice in items" ng-hide="isHidden($index)" ng-class="dropdownClass($index)">' +
|
|
17
|
-
' <a ng-show="choice.text" class="dropdown-option" ng-href="{{choice.url}}" ng-click="doClick($index, $event)">' +
|
|
17
|
+
' <a ng-show="choice.text" class="dropdown-option" ng-href="{{choice.url || choice.urlFunc()}}" ng-click="doClick($index, $event)">' +
|
|
18
18
|
' {{choice.text}}' +
|
|
19
19
|
' </a>' +
|
|
20
20
|
' </li>' +
|
|
@@ -31,16 +31,11 @@ var fng;
|
|
|
31
31
|
var directives;
|
|
32
32
|
(function (directives) {
|
|
33
33
|
/*@ngInject*/
|
|
34
|
-
|
|
34
|
+
errorDisplay.$inject = ["cssFrameworkService"];
|
|
35
|
+
function errorDisplay(cssFrameworkService) {
|
|
35
36
|
return {
|
|
36
37
|
restrict: 'E',
|
|
37
|
-
|
|
38
|
-
' <div class="alert alert-error col-lg-offset-3 offset3 col-lg-6 col-xs-12 span6 alert-warning alert-dismissable">' +
|
|
39
|
-
' <button type="button" class="close" ng-click="dismissError()">×</button>' +
|
|
40
|
-
' <h4>{{alertTitle}}</h4>' +
|
|
41
|
-
' <div ng-bind-html="errorMessage"></div>' +
|
|
42
|
-
' </div>' +
|
|
43
|
-
'</div>'
|
|
38
|
+
templateUrl: 'error-display-' + cssFrameworkService.framework() + '.html'
|
|
44
39
|
};
|
|
45
40
|
}
|
|
46
41
|
directives.errorDisplay = errorDisplay;
|
|
@@ -48,6 +43,44 @@ var fng;
|
|
|
48
43
|
})(fng || (fng = {}));
|
|
49
44
|
/// <reference path="../../../../node_modules/@types/angular/index.d.ts" />
|
|
50
45
|
var fng;
|
|
46
|
+
(function (fng) {
|
|
47
|
+
var controllers;
|
|
48
|
+
(function (controllers) {
|
|
49
|
+
/*@ngInject*/
|
|
50
|
+
LinkCtrl.$inject = ["$scope"];
|
|
51
|
+
function LinkCtrl($scope) {
|
|
52
|
+
/**
|
|
53
|
+
* In the event that the link is part of a form that belongs to a (ui-bootstrap) modal,
|
|
54
|
+
* close the modal
|
|
55
|
+
*/
|
|
56
|
+
$scope.checkNotModal = function () {
|
|
57
|
+
var elm = $scope.element[0];
|
|
58
|
+
var parentNode;
|
|
59
|
+
var finished = false;
|
|
60
|
+
var fakeEvt = {
|
|
61
|
+
preventDefault: angular.noop,
|
|
62
|
+
stopPropagation: angular.noop,
|
|
63
|
+
target: 1,
|
|
64
|
+
currentTarget: 1
|
|
65
|
+
};
|
|
66
|
+
do {
|
|
67
|
+
parentNode = elm.parentNode;
|
|
68
|
+
if (!parentNode) {
|
|
69
|
+
finished = true;
|
|
70
|
+
}
|
|
71
|
+
else if (typeof parentNode.getAttribute === "function" && parentNode.getAttribute('uib-modal-window')) {
|
|
72
|
+
angular.element(elm).scope().close(fakeEvt);
|
|
73
|
+
finished = true;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
elm = parentNode;
|
|
77
|
+
}
|
|
78
|
+
} while (!finished);
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
controllers.LinkCtrl = LinkCtrl;
|
|
82
|
+
})(controllers = fng.controllers || (fng.controllers = {}));
|
|
83
|
+
})(fng || (fng = {}));
|
|
51
84
|
(function (fng) {
|
|
52
85
|
var directives;
|
|
53
86
|
(function (directives) {
|
|
@@ -58,38 +91,124 @@ var fng;
|
|
|
58
91
|
restrict: 'E',
|
|
59
92
|
scope: { dataSrc: '&model' },
|
|
60
93
|
link: function (scope, element, attrs) {
|
|
61
|
-
var ref =
|
|
94
|
+
var ref = attrs['ref'];
|
|
95
|
+
var isLabel = attrs['text'] && (unescape(attrs['text']) !== attrs['text']);
|
|
62
96
|
var form = attrs['form'];
|
|
97
|
+
var linktab = attrs['linktab'];
|
|
63
98
|
scope['readonly'] = attrs['readonly'];
|
|
99
|
+
scope['element'] = element;
|
|
64
100
|
form = form ? form + '/' : '';
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
linktab = linktab ? '/' + linktab : '';
|
|
102
|
+
if (isLabel) {
|
|
103
|
+
var workScope = scope;
|
|
104
|
+
var workString = '';
|
|
105
|
+
while (typeof workScope['baseSchema'] !== "function" && workScope.$parent) {
|
|
106
|
+
if (typeof workScope['$index'] !== "undefined") {
|
|
107
|
+
throw new Error('No support for $index at this level - ' + workString);
|
|
108
|
+
}
|
|
109
|
+
workScope = workScope.$parent;
|
|
110
|
+
workString = workString + '$parent.';
|
|
111
|
+
}
|
|
112
|
+
var attrib = attrs['fld'];
|
|
113
|
+
var watchExpression;
|
|
114
|
+
var splitAttrib = attrib.split('.');
|
|
115
|
+
if (scope.$parent.subDoc && (scope.$parent.subDoc[attrib] || scope.$parent.subDoc[splitAttrib[splitAttrib.length - 1]])) {
|
|
116
|
+
// Support for use in directives in arrays
|
|
117
|
+
if (scope.$parent.subDoc[attrib]) {
|
|
118
|
+
watchExpression = workString + 'subDoc.' + attrib;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
watchExpression = workString + 'subDoc.' + splitAttrib[splitAttrib.length - 1];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
if (typeof workScope['$index'] !== "undefined") {
|
|
126
|
+
attrib = splitAttrib.pop();
|
|
127
|
+
attrib = splitAttrib.join('.') + '[' + workScope['$index'] + '].' + attrib;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
attrib = '.' + attrib;
|
|
131
|
+
}
|
|
132
|
+
watchExpression = workString + 'record' + attrib;
|
|
133
|
+
}
|
|
134
|
+
scope.$watch(watchExpression, function (newVal) {
|
|
135
|
+
if (newVal) {
|
|
136
|
+
if (/^[a-f0-9]{24}/.test(newVal.toString())) {
|
|
137
|
+
newVal = newVal.slice(0, 24);
|
|
138
|
+
}
|
|
139
|
+
else if (newVal.id && /^[a-f0-9]{24}/.test(newVal.id)) {
|
|
140
|
+
newVal = newVal.id.slice(0, 24);
|
|
141
|
+
}
|
|
142
|
+
else if (scope.$parent["f_" + attrs['fld'] + "Options"]) {
|
|
143
|
+
// extract from lookups
|
|
144
|
+
var i = scope.$parent["f_" + attrs['fld'] + "Options"].indexOf(newVal);
|
|
145
|
+
if (i > -1) {
|
|
146
|
+
newVal = scope.$parent["f_" + attrs['fld'] + "_ids"][i];
|
|
80
147
|
}
|
|
81
148
|
else {
|
|
82
|
-
|
|
149
|
+
newVal = undefined;
|
|
83
150
|
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
newVal = undefined;
|
|
154
|
+
}
|
|
155
|
+
if (newVal) {
|
|
156
|
+
scope['link'] = routingService.buildUrl(ref + '/' + form + (newVal.id || newVal) + '/edit' + linktab);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
scope['link'] = undefined;
|
|
160
|
+
}
|
|
87
161
|
}
|
|
88
|
-
|
|
89
|
-
|
|
162
|
+
else {
|
|
163
|
+
scope['link'] = undefined;
|
|
164
|
+
}
|
|
165
|
+
}, true);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
if (attrs['text'] && attrs['text'].length > 0) {
|
|
169
|
+
scope['text'] = attrs['text'];
|
|
170
|
+
}
|
|
171
|
+
var index = scope['$parent']['$index'];
|
|
172
|
+
scope.$watch('dataSrc()', function (newVal) {
|
|
173
|
+
if (newVal) {
|
|
174
|
+
if (typeof index !== 'undefined' && angular.isArray(newVal)) {
|
|
175
|
+
newVal = newVal[index];
|
|
176
|
+
}
|
|
177
|
+
scope['link'] = routingService.buildUrl(ref + '/' + form + newVal + '/edit' + linktab);
|
|
178
|
+
if (!scope['text']) {
|
|
179
|
+
SubmissionsService.getListAttributes(ref, newVal).then(function (response) {
|
|
180
|
+
var data = response.data;
|
|
181
|
+
if (data.success === false) {
|
|
182
|
+
scope['text'] = data.err;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
scope['text'] = data.list;
|
|
186
|
+
}
|
|
187
|
+
}, function (response) {
|
|
188
|
+
scope['text'] = 'Error ' + response.status + ': ' + response.data;
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}, true);
|
|
193
|
+
}
|
|
90
194
|
},
|
|
195
|
+
controller: "LinkCtrl",
|
|
91
196
|
template: function (element, attrs) {
|
|
92
|
-
|
|
197
|
+
function handleAnchor(contents) {
|
|
198
|
+
return "<a ng-click=\"checkNotModal()\" ng-href=\"{{ link || '#' }}\" class=\"fng-link\">".concat(contents, "</a>");
|
|
199
|
+
}
|
|
200
|
+
var retVal;
|
|
201
|
+
if (attrs.readonly) {
|
|
202
|
+
retVal = '<span class="fng-link">{{text}}</span>';
|
|
203
|
+
}
|
|
204
|
+
else if (attrs['text'] && unescape(attrs['text']) !== attrs['text']) {
|
|
205
|
+
retVal = handleAnchor(unescape(attrs['text']));
|
|
206
|
+
// retVal = '<a href="{{ link }}" class="fng-link">{{text}}</a>';
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
retVal = handleAnchor('{{text}}');
|
|
210
|
+
}
|
|
211
|
+
return retVal;
|
|
93
212
|
}
|
|
94
213
|
};
|
|
95
214
|
}
|
|
@@ -146,7 +265,7 @@ var fng;
|
|
|
146
265
|
// <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
|
|
147
266
|
// </div>
|
|
148
267
|
//
|
|
149
|
-
// Inline
|
|
268
|
+
// Inline or stacked
|
|
150
269
|
// <div class="form-group">
|
|
151
270
|
// <label class="sr-only" for="exampleInputEmail2">Email address</label>
|
|
152
271
|
// <input type="email" class="form-control" id="exampleInputEmail2" placeholder="Enter email">
|
|
@@ -165,7 +284,7 @@ var fng;
|
|
|
165
284
|
// <input type="text" placeholder="Type something…">
|
|
166
285
|
// <span class="help-block">Example block-level help text here.</span>
|
|
167
286
|
//
|
|
168
|
-
// Inline
|
|
287
|
+
// Inline or Stacked
|
|
169
288
|
// <input type="text" class="input-small" placeholder="Email">
|
|
170
289
|
var subkeys = [];
|
|
171
290
|
var tabsSetup = tabsSetupState.N;
|
|
@@ -206,7 +325,7 @@ var fng;
|
|
|
206
325
|
var lastPart = compoundName.slice(root.length + 1);
|
|
207
326
|
if (options.index) {
|
|
208
327
|
modelString += root + '[' + options.index + '].' + lastPart;
|
|
209
|
-
idString = 'f_' + modelString.slice(modelBase.length).replace(/(\.|\[
|
|
328
|
+
idString = 'f_' + modelString.slice(modelBase.length).replace(/(\.|\[|]\.)/g, '-');
|
|
210
329
|
}
|
|
211
330
|
else {
|
|
212
331
|
modelString += root;
|
|
@@ -228,18 +347,33 @@ var fng;
|
|
|
228
347
|
var allInputsVars = formMarkupHelper.allInputsVars(scope, fieldInfo, options, modelString, idString, nameString);
|
|
229
348
|
var common = allInputsVars.common;
|
|
230
349
|
var value;
|
|
231
|
-
var requiredStr = (isRequired || fieldInfo.required) ? ' required' : '';
|
|
232
350
|
isRequired = isRequired || fieldInfo.required;
|
|
233
|
-
var requiredStr = isRequired ? ' required' : '';
|
|
351
|
+
var requiredStr = isRequired ? ' required ' : '';
|
|
234
352
|
var enumInstruction;
|
|
353
|
+
function handleReadOnlyDisabled(readonly) {
|
|
354
|
+
var retVal = '';
|
|
355
|
+
if (readonly) {
|
|
356
|
+
// despite the option being "readonly", we should use disabled and ng-disabled rather than their readonly
|
|
357
|
+
// equivalents (which give controls the appearance of being read-only, but don't actually prevent user
|
|
358
|
+
// interaction)
|
|
359
|
+
if (typeof readonly === "boolean") {
|
|
360
|
+
retVal = " disabled ";
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
retVal = " ng-disabled=\"".concat(readonly, "\" ");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return retVal;
|
|
367
|
+
}
|
|
235
368
|
switch (fieldInfo.type) {
|
|
236
369
|
case 'select':
|
|
237
370
|
if (fieldInfo.select2) {
|
|
238
371
|
value = '<input placeholder="fng-select2 has been removed" readonly>';
|
|
239
372
|
}
|
|
240
373
|
else {
|
|
241
|
-
common += (fieldInfo.readonly
|
|
374
|
+
common += handleReadOnlyDisabled(fieldInfo.readonly);
|
|
242
375
|
common += fieldInfo.add ? (' ' + fieldInfo.add + ' ') : '';
|
|
376
|
+
common += " aria-label=\"".concat(fieldInfo.label && fieldInfo.label !== "" ? fieldInfo.label : fieldInfo.name, "\" ");
|
|
243
377
|
value = '<select ' + common + 'class="' + allInputsVars.formControl.trim() + allInputsVars.compactClass + allInputsVars.sizeClassBS2 + '" ' + requiredStr + '>';
|
|
244
378
|
if (!isRequired) {
|
|
245
379
|
value += '<option></option>';
|
|
@@ -268,25 +402,31 @@ var fng;
|
|
|
268
402
|
}
|
|
269
403
|
break;
|
|
270
404
|
case 'link':
|
|
271
|
-
|
|
272
|
-
fieldInfo.ref = { type: 'lookup', collection: fieldInfo.ref };
|
|
273
|
-
console.warn("Support for string type \"ref\" property is deprecated - use ref:" + JSON.stringify(fieldInfo.ref));
|
|
274
|
-
}
|
|
275
|
-
value = '<fng-link model="' + modelString + '" ref="' + JSON.stringify(fieldInfo.ref).replace(/"/g, '"') + '"';
|
|
405
|
+
value = '<fng-link model="' + modelString + '" ref="' + fieldInfo.ref + '"';
|
|
276
406
|
if (fieldInfo.form) {
|
|
277
407
|
value += ' form="' + fieldInfo.form + '"';
|
|
278
408
|
}
|
|
279
|
-
if (fieldInfo.
|
|
280
|
-
value += '
|
|
409
|
+
if (fieldInfo.linktab) {
|
|
410
|
+
value += ' linktab="' + fieldInfo.linktab + '"';
|
|
411
|
+
}
|
|
412
|
+
if (fieldInfo.linktext) {
|
|
413
|
+
value += ' text="' + fieldInfo.linktext + '"';
|
|
281
414
|
}
|
|
282
415
|
if (fieldInfo.readonly) {
|
|
283
|
-
|
|
416
|
+
if (typeof fieldInfo.readonly === "boolean") {
|
|
417
|
+
value += " readonly=\"true\"";
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
value += " ng-readonly=\"".concat(fieldInfo.readonly, "\"");
|
|
421
|
+
}
|
|
284
422
|
}
|
|
285
423
|
value += '></fng-link>';
|
|
286
424
|
break;
|
|
287
425
|
case 'radio':
|
|
288
426
|
value = '';
|
|
289
|
-
common += requiredStr
|
|
427
|
+
common += requiredStr;
|
|
428
|
+
common += handleReadOnlyDisabled(fieldInfo.readonly);
|
|
429
|
+
common += fieldInfo.add ? (' ' + fieldInfo.add + ' ') : '';
|
|
290
430
|
var separateLines = options.formstyle === 'vertical' || (options.formstyle !== 'inline' && !fieldInfo.inlineRadio);
|
|
291
431
|
if (angular.isArray(fieldInfo.options)) {
|
|
292
432
|
if (options.subschema) {
|
|
@@ -296,8 +436,7 @@ var fng;
|
|
|
296
436
|
var thisCommon_1;
|
|
297
437
|
angular.forEach(fieldInfo.options, function (optValue, idx) {
|
|
298
438
|
thisCommon_1 = common.replace('id="', 'id="' + idx + '-');
|
|
299
|
-
value +=
|
|
300
|
-
value += ' value="' + optValue + '">' + optValue;
|
|
439
|
+
value += "<input ".concat(thisCommon_1, " type=\"radio\" aria-label=\"").concat(optValue, "\" value=\"").concat(optValue, "\">").concat(optValue);
|
|
301
440
|
if (separateLines) {
|
|
302
441
|
value += '<br />';
|
|
303
442
|
}
|
|
@@ -312,18 +451,16 @@ var fng;
|
|
|
312
451
|
}
|
|
313
452
|
enumInstruction = generateEnumInstructions();
|
|
314
453
|
value += '<' + tagType + ' ng-repeat="option in ' + enumInstruction.repeat + '">';
|
|
315
|
-
value +=
|
|
316
|
-
value += enumInstruction.label || enumInstruction.value;
|
|
317
|
-
value += ' }} </' + tagType + '> ';
|
|
454
|
+
value += "<input ".concat(common.replace('id="', 'id="{{$index}}-'), " type=\"radio\" aria-label=\"").concat(enumInstruction.value, "\" value=\"{{ ").concat(enumInstruction.value, " }}\"> {{ ").concat(enumInstruction.label || enumInstruction.value, " }} </").concat(tagType, "> ");
|
|
318
455
|
}
|
|
319
456
|
break;
|
|
320
457
|
case 'checkbox':
|
|
321
|
-
common += requiredStr
|
|
458
|
+
common += requiredStr;
|
|
459
|
+
common += handleReadOnlyDisabled(fieldInfo.readonly);
|
|
460
|
+
common += fieldInfo.add ? (' ' + fieldInfo.add + ' ') : '';
|
|
461
|
+
value = formMarkupHelper.generateSimpleInput(common, fieldInfo, options);
|
|
322
462
|
if (cssFrameworkService.framework() === 'bs3') {
|
|
323
|
-
value = '<div class="checkbox"
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
value = formMarkupHelper.generateSimpleInput(common, fieldInfo, options);
|
|
463
|
+
value = '<div class="checkbox">' + value + '</div>';
|
|
327
464
|
}
|
|
328
465
|
break;
|
|
329
466
|
default:
|
|
@@ -338,12 +475,13 @@ var fng;
|
|
|
338
475
|
}
|
|
339
476
|
}
|
|
340
477
|
if (fieldInfo.editor === 'ckEditor') {
|
|
478
|
+
console.log('Deprecation Warning: "editor" property deprecated - use "add"');
|
|
341
479
|
common += 'ckeditor = "" ';
|
|
342
480
|
if (cssFrameworkService.framework() === 'bs3') {
|
|
343
481
|
allInputsVars.sizeClassBS3 = 'col-xs-12';
|
|
344
482
|
}
|
|
345
483
|
}
|
|
346
|
-
value = '<textarea ' + common + '
|
|
484
|
+
value = '<textarea ' + common + '></textarea>';
|
|
347
485
|
}
|
|
348
486
|
else {
|
|
349
487
|
value = formMarkupHelper.generateSimpleInput(common, fieldInfo, options);
|
|
@@ -363,6 +501,9 @@ var fng;
|
|
|
363
501
|
case 'inline':
|
|
364
502
|
result = 'form-inline';
|
|
365
503
|
break;
|
|
504
|
+
case 'stacked':
|
|
505
|
+
result = 'form-stacked';
|
|
506
|
+
break;
|
|
366
507
|
case 'horizontalCompact':
|
|
367
508
|
result = 'form-horizontal compact';
|
|
368
509
|
break;
|
|
@@ -390,7 +531,7 @@ var fng;
|
|
|
390
531
|
if (tabNo >= 0) {
|
|
391
532
|
// TODO Figure out tab history updates (check for other tab-history-todos)
|
|
392
533
|
// result.before = '<uib-tab deselect="tabDeselect($event, $selectedIndex)" select="updateQueryForTab(\'' + info.title + '\')" heading="' + info.title + '"'
|
|
393
|
-
result.before = '<uib-tab select="updateQueryForTab(\'' + info.title + '\')" heading="' + info.title + '"';
|
|
534
|
+
result.before = '<uib-tab deselect="tabDeselect($event, $selectedIndex)" select="updateQueryForTab(\'' + info.title + '\')" heading="' + info.title + '"';
|
|
394
535
|
if (tabNo > 0) {
|
|
395
536
|
result.before += 'active="tabs[' + tabNo + '].active"';
|
|
396
537
|
}
|
|
@@ -451,6 +592,41 @@ var fng;
|
|
|
451
592
|
}
|
|
452
593
|
return result;
|
|
453
594
|
};
|
|
595
|
+
var generateInlineHeaders = function (instructionsArray, options, model, evenWhenEmpty) {
|
|
596
|
+
// "column" headers for nested schemas that use formStyle: "inline" will only line up with their respective
|
|
597
|
+
// controls when widths are applied to both the cg_f_xxxx and col_label_xxxx element using css.
|
|
598
|
+
// Likely, the widths will need to be the same, so consider using the following:
|
|
599
|
+
// div[id$="_f_<collection>_<field>"] {
|
|
600
|
+
// width: 100px;
|
|
601
|
+
// }
|
|
602
|
+
// one column can grow to the remaining available width thus:
|
|
603
|
+
// div[id$="_f_<collection>_<field>"] {
|
|
604
|
+
// flex-grow: 1;
|
|
605
|
+
// }
|
|
606
|
+
var hideWhenEmpty = evenWhenEmpty ? "" : "ng-hide=\"!".concat(model, " || ").concat(model, ".length === 0\"");
|
|
607
|
+
var res = "<div class=\"inline-col-headers\" style=\"display:flex\" ".concat(hideWhenEmpty, ">");
|
|
608
|
+
for (var _i = 0, instructionsArray_1 = instructionsArray; _i < instructionsArray_1.length; _i++) {
|
|
609
|
+
var info = instructionsArray_1[_i];
|
|
610
|
+
// need to call this now to ensure the id is set. will probably be (harmlessly) called again later.
|
|
611
|
+
inferMissingProperties(info, options);
|
|
612
|
+
res += '<div ';
|
|
613
|
+
info.showWhen = info.showWhen || info.showwhen; // deal with use within a directive
|
|
614
|
+
if (info.showWhen) {
|
|
615
|
+
if (typeof info.showWhen === 'string') {
|
|
616
|
+
res += 'ng-show="' + info.showWhen + '"';
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
res += 'ng-show="' + formMarkupHelper.generateNgShow(info.showWhen, model) + '"';
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (info.id && typeof info.id.replace === "function") {
|
|
623
|
+
res += ' id="col_label_' + info.id.replace(/\./g, '-') + '"';
|
|
624
|
+
}
|
|
625
|
+
res += " class=\"inline-col-header\"><label for=\"".concat(info.id, "\" class=\"control-label\">").concat(info.label, "</label></div>");
|
|
626
|
+
}
|
|
627
|
+
res += "</div>";
|
|
628
|
+
return res;
|
|
629
|
+
};
|
|
454
630
|
var handleField = function (info, options) {
|
|
455
631
|
var fieldChrome = formMarkupHelper.fieldChrome(scope, info, options);
|
|
456
632
|
var template = fieldChrome.template;
|
|
@@ -473,7 +649,8 @@ var fng;
|
|
|
473
649
|
formstyle: options.formstyle,
|
|
474
650
|
subkey: schemaDefName + '_subkey',
|
|
475
651
|
subkeyno: arraySel,
|
|
476
|
-
subschemaroot: info.name
|
|
652
|
+
subschemaroot: info.name,
|
|
653
|
+
suppressNestingWarning: info.suppressNestingWarning
|
|
477
654
|
});
|
|
478
655
|
template += topAndTail.after;
|
|
479
656
|
}
|
|
@@ -481,7 +658,9 @@ var fng;
|
|
|
481
658
|
}
|
|
482
659
|
else {
|
|
483
660
|
if (options.subschema) {
|
|
484
|
-
|
|
661
|
+
if (!options.suppressNestingWarning) {
|
|
662
|
+
console.log('Attempts at supporting deep nesting have been removed - will hopefully be re-introduced at a later date');
|
|
663
|
+
}
|
|
485
664
|
}
|
|
486
665
|
else {
|
|
487
666
|
var model = (options.model || 'record') + '.' + info.name;
|
|
@@ -503,20 +682,24 @@ var fng;
|
|
|
503
682
|
}
|
|
504
683
|
}
|
|
505
684
|
/* Array body */
|
|
506
|
-
|
|
685
|
+
if (info.formStyle === "inline" && info.inlineHeaders) {
|
|
686
|
+
template += generateInlineHeaders(info.schema, options, model, info.inlineHeaders === "always");
|
|
687
|
+
}
|
|
688
|
+
template += '<ol class="sub-doc"' + (info.sortable ? " ui-sortable=\"sortableOptions\" ng-model=\"".concat(model, "\"") : '') + '>';
|
|
507
689
|
template += '<li ng-form class="' + (cssFrameworkService.framework() === 'bs2' ? 'row-fluid ' : '') +
|
|
508
|
-
|
|
690
|
+
(info.inlineHeaders ? 'width-controlled ' : '') +
|
|
691
|
+
convertFormStyleToClass(info.formStyle) + ' ' + (info.ngClass ? "ng-class:" + info.ngClass : "") + '" name="form_' + niceName + '{{$index}}" class="sub-doc well" id="' + info.id + 'List_{{$index}}" ' +
|
|
509
692
|
' ng-repeat="subDoc in ' + model + ' track by $index">';
|
|
510
693
|
if (cssFrameworkService.framework() === 'bs2') {
|
|
511
694
|
template += '<div class="row-fluid sub-doc">';
|
|
512
695
|
}
|
|
513
|
-
if (
|
|
696
|
+
if (info.noRemove !== true || info.customSubDoc) {
|
|
514
697
|
template += ' <div class="sub-doc-btns">';
|
|
515
698
|
if (typeof info.customSubDoc == 'string') {
|
|
516
699
|
template += info.customSubDoc;
|
|
517
700
|
}
|
|
518
701
|
if (info.noRemove !== true) {
|
|
519
|
-
template += "<button "
|
|
702
|
+
template += "<button ".concat(info.noRemove ? 'ng-hide="' + info.noRemove + '"' : '', " name=\"remove_").concat(info.id, "_btn\" ng-click=\"remove('").concat(info.name, "', $index, $event)\"");
|
|
520
703
|
if (info.remove) {
|
|
521
704
|
template += ' class="remove-btn btn btn-mini btn-default btn-xs form-btn"><i class="' + formMarkupHelper.glyphClass() + '-minus"></i> Remove';
|
|
522
705
|
}
|
|
@@ -533,31 +716,64 @@ var fng;
|
|
|
533
716
|
}
|
|
534
717
|
template += '</div> ';
|
|
535
718
|
}
|
|
719
|
+
var parts = void 0;
|
|
720
|
+
if (info.subDocContainerType) {
|
|
721
|
+
var containerType = scope[info.subDocContainerType] || info.subDocContainerType;
|
|
722
|
+
var containerProps = Object.assign({ containerType: containerType }, info.subDocContainerProps);
|
|
723
|
+
parts = containerInstructions(containerProps);
|
|
724
|
+
}
|
|
725
|
+
if (parts === null || parts === void 0 ? void 0 : parts.before) {
|
|
726
|
+
template += parts.before;
|
|
727
|
+
}
|
|
536
728
|
template += processInstructions(info.schema, false, {
|
|
537
729
|
subschema: 'true',
|
|
538
730
|
formstyle: info.formStyle,
|
|
539
731
|
model: options.model,
|
|
540
|
-
subschemaroot: info.name
|
|
732
|
+
subschemaroot: info.name,
|
|
733
|
+
suppressNestingWarning: info.suppressNestingWarning
|
|
541
734
|
});
|
|
735
|
+
if (parts === null || parts === void 0 ? void 0 : parts.after) {
|
|
736
|
+
template += parts.after;
|
|
737
|
+
}
|
|
542
738
|
if (cssFrameworkService.framework() === 'bs2') {
|
|
543
739
|
template += ' </div>';
|
|
544
740
|
}
|
|
545
741
|
template += '</li>';
|
|
546
742
|
template += '</ol>';
|
|
547
743
|
/* Array footer */
|
|
548
|
-
if (info.noAdd !== true || typeof info.customFooter == 'string') {
|
|
744
|
+
if (info.noAdd !== true || typeof info.customFooter == 'string' || info.noneIndicator) {
|
|
549
745
|
var footer = '';
|
|
550
746
|
if (typeof info.customFooter == 'string') {
|
|
551
747
|
footer = info.customFooter;
|
|
552
748
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
template += '<div class="row schema-foot"><div class="col-sm-offset-3">' + footer + '</div></div>';
|
|
749
|
+
var hideCond = '';
|
|
750
|
+
var indicatorShowCond = "".concat(model, ".length == 0");
|
|
751
|
+
if (info.noAdd === true) {
|
|
752
|
+
indicatorShowCond = "ng-show=\"".concat(indicatorShowCond, "\"");
|
|
558
753
|
}
|
|
559
754
|
else {
|
|
560
|
-
|
|
755
|
+
hideCond = info.noAdd ? "ng-hide=\"".concat(info.noAdd, "\"") : '';
|
|
756
|
+
indicatorShowCond = info.noAdd ? "ng-show=\"".concat(info.noAdd, " && ").concat(indicatorShowCond, "\"") : '';
|
|
757
|
+
footer += "<button ".concat(hideCond, " id=\"add_").concat(info.id, "_btn\" class=\"add-btn btn btn-default btn-xs btn-mini\" ng-click=\"add('").concat(info.name, "',$event)\">\n <i class=\"' + formMarkupHelper.glyphClass() + '-plus\"></i> \n Add\n </button>");
|
|
758
|
+
}
|
|
759
|
+
if (info.noneIndicator) {
|
|
760
|
+
footer += "<span ".concat(indicatorShowCond, " class=\"none_indicator\" id=\"no_").concat(info.id, "_indicator\">None</span>");
|
|
761
|
+
// hideCond for the schema-foot is if there's no add button and no indicator
|
|
762
|
+
hideCond = "".concat(model, ".length > 0");
|
|
763
|
+
if (info.noAdd === true) {
|
|
764
|
+
hideCond = "ng-hide=\"".concat(hideCond, "\"");
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
hideCond = info.noAdd ? "ng-hide=\"".concat(info.noAdd, " && ").concat(hideCond, "\"") : '';
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
if (footer !== '') {
|
|
771
|
+
if (cssFrameworkService.framework() === 'bs3') {
|
|
772
|
+
template += "<div ".concat(hideCond, " class=\"row schema-foot\"><div class=\"col-sm-offset-3\">").concat(footer, "</div></div>");
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
template += "<div ".concat(hideCond, " class = \"schema-foot \">").concat(footer, "</div>");
|
|
776
|
+
}
|
|
561
777
|
}
|
|
562
778
|
}
|
|
563
779
|
}
|
|
@@ -569,8 +785,8 @@ var fng;
|
|
|
569
785
|
var controlDivClasses = formMarkupHelper.controlDivClasses(options);
|
|
570
786
|
if (info.array) {
|
|
571
787
|
controlDivClasses.push('fng-array');
|
|
572
|
-
if (options.formstyle === 'inline') {
|
|
573
|
-
throw new Error('Cannot use arrays in an inline form');
|
|
788
|
+
if (options.formstyle === 'inline' || options.formstyle === 'stacked') {
|
|
789
|
+
throw new Error('Cannot use arrays in an inline or stacked form');
|
|
574
790
|
}
|
|
575
791
|
template += formMarkupHelper.label(scope, info, info.type !== 'link', options);
|
|
576
792
|
template += formMarkupHelper.handleArrayInputAndControlDiv(generateInput(info, info.type === 'link' ? null : 'arrayItem.x', true, info.id + '_{{$index}}', options), controlDivClasses, info, options);
|
|
@@ -578,25 +794,27 @@ var fng;
|
|
|
578
794
|
else {
|
|
579
795
|
// Single fields here
|
|
580
796
|
template += formMarkupHelper.label(scope, info, null, options);
|
|
581
|
-
if (options.required) {
|
|
582
|
-
console.log("********* Options required - found it ********");
|
|
583
|
-
}
|
|
584
797
|
template += formMarkupHelper.handleInputAndControlDiv(generateInput(info, null, options.required, info.id, options), controlDivClasses);
|
|
585
798
|
}
|
|
586
799
|
}
|
|
587
800
|
template += fieldChrome.closeTag;
|
|
588
801
|
return template;
|
|
589
802
|
};
|
|
590
|
-
var inferMissingProperties = function (info) {
|
|
803
|
+
var inferMissingProperties = function (info, options) {
|
|
591
804
|
// infer missing values
|
|
592
805
|
info.type = info.type || 'text';
|
|
593
806
|
if (info.id) {
|
|
594
|
-
if (typeof info.id === 'number' ||
|
|
807
|
+
if (typeof info.id === 'number' || info.id.match(/^[0-9]/)) {
|
|
595
808
|
info.id = '_' + info.id;
|
|
596
809
|
}
|
|
597
810
|
}
|
|
598
811
|
else {
|
|
599
|
-
|
|
812
|
+
if (options && options.noid) {
|
|
813
|
+
info.id = null;
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
info.id = 'f_' + info.name.replace(/\./g, '_');
|
|
817
|
+
}
|
|
600
818
|
}
|
|
601
819
|
info.label = (info.label !== undefined) ? (info.label === null ? '' : info.label) : $filter('titleCase')(info.name.split('.').slice(-1)[0]);
|
|
602
820
|
};
|
|
@@ -607,7 +825,11 @@ var fng;
|
|
|
607
825
|
if (instructionsArray) {
|
|
608
826
|
for (var anInstruction = 0; anInstruction < instructionsArray.length; anInstruction++) {
|
|
609
827
|
var info = instructionsArray[anInstruction];
|
|
610
|
-
if (
|
|
828
|
+
if (options.viewform) {
|
|
829
|
+
info = angular.copy(info);
|
|
830
|
+
info.readonly = true;
|
|
831
|
+
}
|
|
832
|
+
if (anInstruction === 0 && topLevel && !options.schema.match(/\$_schema_/) && typeof info.add !== 'object') {
|
|
611
833
|
info.add = info.add ? ' ' + info.add + ' ' : '';
|
|
612
834
|
if (info.add.indexOf('ui-date') === -1 && !options.noautofocus && !info.containerType) {
|
|
613
835
|
info.add = info.add + 'autofocus ';
|
|
@@ -616,9 +838,10 @@ var fng;
|
|
|
616
838
|
var callHandleField = true;
|
|
617
839
|
if (info.directive) {
|
|
618
840
|
var directiveName = info.directive;
|
|
619
|
-
var newElement =
|
|
841
|
+
var newElement = info.customHeader || "";
|
|
842
|
+
newElement += '<' + directiveName + ' model="' + (options.model || 'record') + '"';
|
|
620
843
|
var thisElement = element[0];
|
|
621
|
-
inferMissingProperties(info);
|
|
844
|
+
inferMissingProperties(info, options);
|
|
622
845
|
for (var i = 0; i < thisElement.attributes.length; i++) {
|
|
623
846
|
var thisAttr = thisElement.attributes[i];
|
|
624
847
|
switch (thisAttr.nodeName) {
|
|
@@ -654,7 +877,9 @@ var fng;
|
|
|
654
877
|
break;
|
|
655
878
|
case 'object':
|
|
656
879
|
for (var subAdd in info.add) {
|
|
657
|
-
|
|
880
|
+
if (info.add.hasOwnProperty(subAdd)) {
|
|
881
|
+
newElement += ' ' + subAdd + '="' + info.add[subAdd].toString().replace(/"/g, '"') + '"';
|
|
882
|
+
}
|
|
658
883
|
}
|
|
659
884
|
break;
|
|
660
885
|
default:
|
|
@@ -663,13 +888,21 @@ var fng;
|
|
|
663
888
|
break;
|
|
664
889
|
case directiveCamel:
|
|
665
890
|
for (var subProp in info[prop]) {
|
|
666
|
-
|
|
891
|
+
if (info[prop].hasOwnProperty(subProp)) {
|
|
892
|
+
newElement += " ".concat(info.directive, "-").concat(subProp, "=\"");
|
|
893
|
+
if (typeof info[prop][subProp] === 'string') {
|
|
894
|
+
newElement += "".concat(info[prop][subProp].replace(/"/g, '"'), "\"");
|
|
895
|
+
}
|
|
896
|
+
else {
|
|
897
|
+
newElement += "".concat(JSON.stringify(info[prop][subProp]).replace(/"/g, '"'), "\"");
|
|
898
|
+
}
|
|
899
|
+
}
|
|
667
900
|
}
|
|
668
901
|
break;
|
|
669
902
|
default:
|
|
670
903
|
if (info[prop]) {
|
|
671
904
|
if (typeof info[prop] === 'string') {
|
|
672
|
-
newElement += ' fng-fld-' + prop + '="' + info[prop].
|
|
905
|
+
newElement += ' fng-fld-' + prop + '="' + info[prop].replace(/"/g, '"') + '"';
|
|
673
906
|
}
|
|
674
907
|
else {
|
|
675
908
|
newElement += ' fng-fld-' + prop + '="' + JSON.stringify(info[prop]).replace(/"/g, '"') + '"';
|
|
@@ -685,6 +918,7 @@ var fng;
|
|
|
685
918
|
}
|
|
686
919
|
}
|
|
687
920
|
newElement += 'ng-model="' + info.name + '"></' + directiveName + '>';
|
|
921
|
+
newElement += (info.customFooter || "");
|
|
688
922
|
result += newElement;
|
|
689
923
|
callHandleField = false;
|
|
690
924
|
}
|
|
@@ -721,9 +955,7 @@ var fng;
|
|
|
721
955
|
else if (options.subkey) {
|
|
722
956
|
// Don't display fields that form part of the subkey, as they should not be edited (because in these circumstances they form some kind of key)
|
|
723
957
|
var objectToSearch = angular.isArray(scope[options.subkey]) ? scope[options.subkey][0].keyList : scope[options.subkey].keyList;
|
|
724
|
-
if (_.find(objectToSearch, function (value, key) {
|
|
725
|
-
return scope[options.subkey].path + '.' + key === info.name;
|
|
726
|
-
})) {
|
|
958
|
+
if (_.find(objectToSearch, function (value, key) { return scope[options.subkey].path + '.' + key === info.name; })) {
|
|
727
959
|
callHandleField = false;
|
|
728
960
|
}
|
|
729
961
|
}
|
|
@@ -731,7 +963,7 @@ var fng;
|
|
|
731
963
|
// if (groupId) {
|
|
732
964
|
// scope['showHide' + groupId] = true;
|
|
733
965
|
// }
|
|
734
|
-
inferMissingProperties(info);
|
|
966
|
+
inferMissingProperties(info, options);
|
|
735
967
|
result += handleField(info, options);
|
|
736
968
|
}
|
|
737
969
|
}
|
|
@@ -745,8 +977,9 @@ var fng;
|
|
|
745
977
|
var unwatch = scope.$watch(attrs.schema, function (newValue) {
|
|
746
978
|
if (newValue) {
|
|
747
979
|
var newArrayValue = angular.isArray(newValue) ? newValue : [newValue]; // otherwise some old tests stop working for no real reason
|
|
748
|
-
if (newArrayValue.length > 0) {
|
|
980
|
+
if (newArrayValue.length > 0 && typeof unwatch === "function") {
|
|
749
981
|
unwatch();
|
|
982
|
+
unwatch = null;
|
|
750
983
|
var elementHtml = '';
|
|
751
984
|
var recordAttribute = attrs.model || 'record'; // By default data comes from scope.record
|
|
752
985
|
var theRecord = scope[recordAttribute];
|
|
@@ -760,12 +993,13 @@ var fng;
|
|
|
760
993
|
var customAttrs = '';
|
|
761
994
|
for (var thisAttr in attrs) {
|
|
762
995
|
if (attrs.hasOwnProperty(thisAttr)) {
|
|
763
|
-
if (thisAttr[0] !== '$' && ['name', 'formstyle', 'schema', 'subschema', 'model'].indexOf(thisAttr) === -1) {
|
|
996
|
+
if (thisAttr[0] !== '$' && ['name', 'formstyle', 'schema', 'subschema', 'model', 'viewform'].indexOf(thisAttr) === -1) {
|
|
764
997
|
customAttrs += ' ' + attrs.$attr[thisAttr] + '="' + attrs[thisAttr] + '"';
|
|
765
998
|
}
|
|
766
999
|
}
|
|
767
1000
|
}
|
|
768
|
-
|
|
1001
|
+
var tag = attrs.forceform ? 'ng-form' : 'form';
|
|
1002
|
+
elementHtml = "<".concat(tag, " name=\"").concat(scope.topLevelFormName, "\" class=\"").concat(convertFormStyleToClass(attrs.formstyle), "\" novalidate ").concat(customAttrs, ">");
|
|
769
1003
|
}
|
|
770
1004
|
if (theRecord === scope.topLevelFormName) {
|
|
771
1005
|
throw new Error('Model and Name must be distinct - they are both ' + theRecord);
|
|
@@ -781,10 +1015,12 @@ var fng;
|
|
|
781
1015
|
// If we have modelControllers we need to let them know when we have form + data
|
|
782
1016
|
var sharedData = scope[attrs.shared || 'sharedData'];
|
|
783
1017
|
var modelControllers_1 = sharedData ? sharedData.modelControllers : [];
|
|
784
|
-
if (subkeys.length > 0 || modelControllers_1.length > 0) {
|
|
1018
|
+
if ((subkeys.length > 0 || modelControllers_1.length > 0) && !scope.phaseWatcher) {
|
|
785
1019
|
var unwatch2 = scope.$watch('phase', function (newValue) {
|
|
786
|
-
|
|
1020
|
+
scope.phaseWatcher = true;
|
|
1021
|
+
if (newValue === 'ready' && typeof unwatch2 === "function") {
|
|
787
1022
|
unwatch2();
|
|
1023
|
+
unwatch2 = null;
|
|
788
1024
|
// Tell the 'model controllers' that the form and data are there
|
|
789
1025
|
for (var i = 0; i < modelControllers_1.length; i++) {
|
|
790
1026
|
if (modelControllers_1[i].onAllReady) {
|
|
@@ -813,7 +1049,7 @@ var fng;
|
|
|
813
1049
|
arrayOffset = scope[arrayToProcess[thisOffset].selectFunc](theRecord, info);
|
|
814
1050
|
}
|
|
815
1051
|
else if (arrayToProcess[thisOffset].keyList) {
|
|
816
|
-
// We are
|
|
1052
|
+
// We are choosing the array element by matching one or more keys
|
|
817
1053
|
var thisSubkeyList = arrayToProcess[thisOffset].keyList;
|
|
818
1054
|
for (arrayOffset = 0; arrayOffset < dataVal.length; arrayOffset++) {
|
|
819
1055
|
matching = true;
|
|
@@ -867,7 +1103,7 @@ var fng;
|
|
|
867
1103
|
}
|
|
868
1104
|
});
|
|
869
1105
|
}
|
|
870
|
-
$rootScope.$broadcast('formInputDone');
|
|
1106
|
+
$rootScope.$broadcast('formInputDone', attrs.name);
|
|
871
1107
|
if (formGenerator.updateDataDependentDisplay && theRecord && Object.keys(theRecord).length > 0) {
|
|
872
1108
|
// If this is not a test force the data dependent updates to the DOM
|
|
873
1109
|
formGenerator.updateDataDependentDisplay(theRecord, null, true, scope);
|
|
@@ -916,7 +1152,7 @@ var fng;
|
|
|
916
1152
|
/*@ngInject*/
|
|
917
1153
|
SearchCtrl.$inject = ["$scope", "$http", "$location", "routingService"];
|
|
918
1154
|
function SearchCtrl($scope, $http, $location, routingService) {
|
|
919
|
-
var
|
|
1155
|
+
var lastSearchSent;
|
|
920
1156
|
var _isNotMobile;
|
|
921
1157
|
_isNotMobile = (function () {
|
|
922
1158
|
var check = false;
|
|
@@ -971,9 +1207,15 @@ var fng;
|
|
|
971
1207
|
};
|
|
972
1208
|
$scope.selectResult = function (resultNo) {
|
|
973
1209
|
var result = $scope.results[resultNo];
|
|
974
|
-
var newURL
|
|
975
|
-
if (result.
|
|
976
|
-
newURL
|
|
1210
|
+
var newURL;
|
|
1211
|
+
if (result.url) {
|
|
1212
|
+
newURL = result.url.replace('|id|', result.id);
|
|
1213
|
+
}
|
|
1214
|
+
else {
|
|
1215
|
+
newURL = routingService.prefix() + '/' + result.resource + '/' + result.id + '/edit';
|
|
1216
|
+
if (result.resourceTab) {
|
|
1217
|
+
newURL += '/' + result.resourceTab;
|
|
1218
|
+
}
|
|
977
1219
|
}
|
|
978
1220
|
$location.url(newURL);
|
|
979
1221
|
};
|
|
@@ -992,12 +1234,12 @@ var fng;
|
|
|
992
1234
|
};
|
|
993
1235
|
$scope.$watch('searchTarget', function (newValue) {
|
|
994
1236
|
if (newValue && newValue.length > 0) {
|
|
995
|
-
|
|
996
|
-
$http.get('/api/search?q=' + newValue).then(function (response) {
|
|
1237
|
+
lastSearchSent = $scope.testTime || new Date().valueOf();
|
|
1238
|
+
$http.get('/api/search?q=' + newValue + '&sentAt=' + lastSearchSent).then(function (response) {
|
|
997
1239
|
var data = response.data;
|
|
998
1240
|
// Check that we haven't fired off a subsequent request, in which
|
|
999
1241
|
// case we are no longer interested in these results
|
|
1000
|
-
if (
|
|
1242
|
+
if (!data.timestamps || !data.timestamps.sentAt || Number.parseInt(data.timestamps.sentAt) === lastSearchSent) {
|
|
1001
1243
|
if ($scope.searchTarget.length > 0) {
|
|
1002
1244
|
$scope.results = data.results;
|
|
1003
1245
|
$scope.moreCount = data.moreCount;
|
|
@@ -1064,6 +1306,21 @@ var fng;
|
|
|
1064
1306
|
})(fng || (fng = {}));
|
|
1065
1307
|
/// <reference path="../../../../node_modules/@types/angular/index.d.ts" />
|
|
1066
1308
|
var fng;
|
|
1309
|
+
(function (fng) {
|
|
1310
|
+
var filters;
|
|
1311
|
+
(function (filters) {
|
|
1312
|
+
/*@ngInject*/
|
|
1313
|
+
function extractTimestampFromMongoID() {
|
|
1314
|
+
return function (id) {
|
|
1315
|
+
var timestamp = id.substring(0, 8);
|
|
1316
|
+
return new Date(parseInt(timestamp, 16) * 1000);
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
filters.extractTimestampFromMongoID = extractTimestampFromMongoID;
|
|
1320
|
+
})(filters = fng.filters || (fng.filters = {}));
|
|
1321
|
+
})(fng || (fng = {}));
|
|
1322
|
+
/// <reference path="../../../../node_modules/@types/angular/index.d.ts" />
|
|
1323
|
+
var fng;
|
|
1067
1324
|
(function (fng) {
|
|
1068
1325
|
var filters;
|
|
1069
1326
|
(function (filters) {
|
|
@@ -1244,6 +1501,7 @@ var fng;
|
|
|
1244
1501
|
controllerName += 'Ctrl';
|
|
1245
1502
|
locals.$scope = sharedData.modelControllers[level] = localScope;
|
|
1246
1503
|
var parentScope = localScope.$parent;
|
|
1504
|
+
parentScope.items = parentScope.items || [];
|
|
1247
1505
|
var addMenuOptions = function (array) {
|
|
1248
1506
|
angular.forEach(array, function (value) {
|
|
1249
1507
|
if (value.divider) {
|
|
@@ -1275,6 +1533,11 @@ var fng;
|
|
|
1275
1533
|
locals.$scope.contextMenuPromise.then(function (array) { return addMenuOptions(array); });
|
|
1276
1534
|
}
|
|
1277
1535
|
}
|
|
1536
|
+
if (sharedData.modelNameDisplayPromise) {
|
|
1537
|
+
sharedData.modelNameDisplayPromise.then(function (value) {
|
|
1538
|
+
parentScope.modelNameDisplay = value;
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1278
1541
|
}
|
|
1279
1542
|
catch (error) {
|
|
1280
1543
|
// Check to see if error is no such controller - don't care
|
|
@@ -1304,7 +1567,7 @@ var fng;
|
|
|
1304
1567
|
routing: 'ngroute',
|
|
1305
1568
|
prefix: '' // How do we want to prefix our routes? If not empty string then first character must be slash (which is added if not)
|
|
1306
1569
|
};
|
|
1307
|
-
var postActions = ['edit'];
|
|
1570
|
+
var postActions = ['edit', 'view'];
|
|
1308
1571
|
var builtInRoutes = [
|
|
1309
1572
|
{
|
|
1310
1573
|
route: '/analyse/:model/:reportSchemaName',
|
|
@@ -1314,12 +1577,19 @@ var fng;
|
|
|
1314
1577
|
{ route: '/analyse/:model', state: 'analyse::model', templateUrl: 'base-analysis.html' },
|
|
1315
1578
|
{ route: '/:model/:id/edit', state: 'model::edit', templateUrl: 'base-edit.html' },
|
|
1316
1579
|
{ route: '/:model/:id/edit/:tab', state: 'model::edit::tab', templateUrl: 'base-edit.html' },
|
|
1580
|
+
{ route: '/:model/:id/view', state: 'model::edit', templateUrl: 'base-view.html' },
|
|
1581
|
+
{ route: '/:model/:id/view/:tab', state: 'model::view::tab', templateUrl: 'base-view.html' },
|
|
1317
1582
|
{ route: '/:model/new', state: 'model::new', templateUrl: 'base-edit.html' },
|
|
1318
1583
|
{ route: '/:model', state: 'model::list', templateUrl: 'base-list.html' },
|
|
1584
|
+
{ route: '/:model/viewonly', state: 'model::view', templateUrl: 'base-list-view.html' },
|
|
1585
|
+
// Non default form (subset of fields etc)
|
|
1319
1586
|
{ route: '/:model/:form/:id/edit', state: 'model::form::edit', templateUrl: 'base-edit.html' },
|
|
1320
1587
|
{ route: '/:model/:form/:id/edit/:tab', state: 'model::form::edit::tab', templateUrl: 'base-edit.html' },
|
|
1588
|
+
{ route: '/:model/:form/:id/view', state: 'model::form::view', templateUrl: 'base-view.html' },
|
|
1589
|
+
{ route: '/:model/:form/:id/view/:tab', state: 'model::form::view::tab', templateUrl: 'base-view.html' },
|
|
1321
1590
|
{ route: '/:model/:form/new', state: 'model::form::new', templateUrl: 'base-edit.html' },
|
|
1322
|
-
{ route: '/:model/:form', state: 'model::form::list', templateUrl: 'base-list.html' }
|
|
1591
|
+
{ route: '/:model/:form', state: 'model::form::list', templateUrl: 'base-list.html' },
|
|
1592
|
+
{ route: '/:model/:form/viewonly', state: 'model::form::list::view', templateUrl: 'base-list-view.html' } // list page with edit links to non default form
|
|
1323
1593
|
];
|
|
1324
1594
|
var _routeProvider, _stateProvider;
|
|
1325
1595
|
var lastRoute = null;
|
|
@@ -1373,6 +1643,12 @@ var fng;
|
|
|
1373
1643
|
case 'edit':
|
|
1374
1644
|
urlStr = modelString + formString + '/' + id + '/edit' + tabString;
|
|
1375
1645
|
break;
|
|
1646
|
+
case 'view':
|
|
1647
|
+
urlStr = modelString + formString + '/' + id + '/view' + tabString;
|
|
1648
|
+
break;
|
|
1649
|
+
case 'read':
|
|
1650
|
+
urlStr = modelString + formString + '/' + id + '/read' + tabString;
|
|
1651
|
+
break;
|
|
1376
1652
|
case 'new':
|
|
1377
1653
|
urlStr = modelString + formString + '/new' + tabString;
|
|
1378
1654
|
break;
|
|
@@ -1455,8 +1731,9 @@ var fng;
|
|
|
1455
1731
|
lastObject.modelName = locationSplit[1];
|
|
1456
1732
|
var lastParts_1 = [locationSplit[locationParts - 1], locationSplit[locationParts - 2]];
|
|
1457
1733
|
var newPos = lastParts_1.indexOf('new');
|
|
1734
|
+
var viewonlyPos = lastParts_1.indexOf('viewonly');
|
|
1458
1735
|
var actionPos = void 0;
|
|
1459
|
-
if (newPos === -1) {
|
|
1736
|
+
if (newPos === -1 && viewonlyPos === -1) {
|
|
1460
1737
|
actionPos = postActions.reduce(function (previousValue, currentValue) {
|
|
1461
1738
|
var pos = lastParts_1.indexOf(currentValue);
|
|
1462
1739
|
return pos > -1 ? pos : previousValue;
|
|
@@ -1466,10 +1743,13 @@ var fng;
|
|
|
1466
1743
|
lastObject.id = locationSplit[locationParts];
|
|
1467
1744
|
}
|
|
1468
1745
|
}
|
|
1469
|
-
else {
|
|
1746
|
+
else if (newPos !== -1) {
|
|
1470
1747
|
lastObject.newRecord = true;
|
|
1471
1748
|
locationParts -= (1 + newPos);
|
|
1472
1749
|
}
|
|
1750
|
+
else {
|
|
1751
|
+
locationParts -= (1 + viewonlyPos);
|
|
1752
|
+
}
|
|
1473
1753
|
if (actionPos === 1 || newPos === 1) {
|
|
1474
1754
|
lastObject.tab = lastParts_1[0];
|
|
1475
1755
|
}
|
|
@@ -1480,34 +1760,6 @@ var fng;
|
|
|
1480
1760
|
}
|
|
1481
1761
|
return lastObject;
|
|
1482
1762
|
};
|
|
1483
|
-
///**
|
|
1484
|
-
// * DominicBoettger wrote:
|
|
1485
|
-
// *
|
|
1486
|
-
// * Parser for the states provided by ui.router
|
|
1487
|
-
// */
|
|
1488
|
-
//'use strict';
|
|
1489
|
-
//formsAngular.factory('$stateParse', [function () {
|
|
1490
|
-
//
|
|
1491
|
-
// var lastObject = {};
|
|
1492
|
-
//
|
|
1493
|
-
// return function (state) {
|
|
1494
|
-
// if (state.current && state.current.name) {
|
|
1495
|
-
// lastObject = {newRecord: false};
|
|
1496
|
-
// lastObject.modelName = state.params.model;
|
|
1497
|
-
// if (state.current.name === 'model::list') {
|
|
1498
|
-
// lastObject = {index: true};
|
|
1499
|
-
// lastObject.modelName = state.params.model;
|
|
1500
|
-
// } else if (state.current.name === 'model::edit') {
|
|
1501
|
-
// lastObject.id = state.params.id;
|
|
1502
|
-
// } else if (state.current.name === 'model::new') {
|
|
1503
|
-
// lastObject.newRecord = true;
|
|
1504
|
-
// } else if (state.current.name === 'model::analyse') {
|
|
1505
|
-
// lastObject.analyse = true;
|
|
1506
|
-
// }
|
|
1507
|
-
// }
|
|
1508
|
-
// return lastObject;
|
|
1509
|
-
// };
|
|
1510
|
-
//}]);
|
|
1511
1763
|
},
|
|
1512
1764
|
buildUrl: function (path) {
|
|
1513
1765
|
var url = config.html5Mode ? '' : '#';
|
|
@@ -1524,46 +1776,25 @@ var fng;
|
|
|
1524
1776
|
},
|
|
1525
1777
|
redirectTo: function () {
|
|
1526
1778
|
return function (operation, scope, location, id, tab) {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
if (
|
|
1530
|
-
|
|
1779
|
+
location.search({}); // Lose any search parameters
|
|
1780
|
+
var urlStr;
|
|
1781
|
+
if (operation === 'onDelete') {
|
|
1782
|
+
if (config.onDelete) {
|
|
1783
|
+
if (config.onDelete === 'new') {
|
|
1784
|
+
urlStr = _buildOperationUrl(config.prefix, 'new', scope.modelName, scope.formName, id, tab);
|
|
1785
|
+
}
|
|
1786
|
+
else {
|
|
1787
|
+
urlStr = config.onDelete;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
else {
|
|
1791
|
+
urlStr = _buildOperationUrl(config.prefix, 'list', scope.modelName, scope.formName, id, tab);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
else {
|
|
1795
|
+
urlStr = _buildOperationUrl(config.prefix, operation, scope.modelName, scope.formName, id, tab);
|
|
1531
1796
|
}
|
|
1532
|
-
var urlStr = _buildOperationUrl(config.prefix, operation, scope.modelName, scope.formName, id, tab);
|
|
1533
1797
|
location.path(urlStr);
|
|
1534
|
-
// break;
|
|
1535
|
-
// case 'uirouter' :
|
|
1536
|
-
// var formString = scope.formName ? ('/' + scope.formName) : '';
|
|
1537
|
-
// var modelString = config.prefix + '/' + scope.modelName;
|
|
1538
|
-
// console.log('form schemas not supported with ui-router');
|
|
1539
|
-
// switch (operation) {
|
|
1540
|
-
// case 'list' :
|
|
1541
|
-
// location.path(modelString + formString);
|
|
1542
|
-
// break;
|
|
1543
|
-
// case 'edit' :
|
|
1544
|
-
// location.path(modelString + formString + '/' + id + '/edit');
|
|
1545
|
-
// break;
|
|
1546
|
-
// case 'new' :
|
|
1547
|
-
// location.path(modelString + formString + '/new');
|
|
1548
|
-
// break;
|
|
1549
|
-
// }
|
|
1550
|
-
// switch (operation) {
|
|
1551
|
-
// case 'list' :
|
|
1552
|
-
// $state.go('model::list', { model: model });
|
|
1553
|
-
// break;
|
|
1554
|
-
// case 'edit' :
|
|
1555
|
-
// location.path('/' + scope.modelName + formString + '/' + id + '/edit');
|
|
1556
|
-
// break;
|
|
1557
|
-
// case 'new' :
|
|
1558
|
-
// location.path('/' + scope.modelName + formString + '/new');
|
|
1559
|
-
// break;
|
|
1560
|
-
// }
|
|
1561
|
-
// break;
|
|
1562
|
-
//
|
|
1563
|
-
//
|
|
1564
|
-
// // edit: $state.go('model::edit', {id: data._id, model: $scope.modelName });
|
|
1565
|
-
// // new: $state.go('model::new', {model: $scope.modelName});
|
|
1566
|
-
// break;
|
|
1567
1798
|
};
|
|
1568
1799
|
}
|
|
1569
1800
|
};
|
|
@@ -1585,7 +1816,7 @@ var fng;
|
|
|
1585
1816
|
* All methods should be state-less
|
|
1586
1817
|
*
|
|
1587
1818
|
*/
|
|
1588
|
-
function formGenerator($location, $timeout, $filter,
|
|
1819
|
+
function formGenerator($location, $timeout, $filter, routingService, recordHandler) {
|
|
1589
1820
|
function handleSchema(description, source, destForm, destList, prefix, doRecursion, $scope, ctrlState) {
|
|
1590
1821
|
function handletabInfo(tabName, thisInst) {
|
|
1591
1822
|
var tabTitle = angular.copy(tabName);
|
|
@@ -1611,50 +1842,55 @@ var fng;
|
|
|
1611
1842
|
}
|
|
1612
1843
|
tab.content.push(thisInst);
|
|
1613
1844
|
}
|
|
1845
|
+
if (typeof $scope.onSchemaFetch === "function") {
|
|
1846
|
+
$scope.onSchemaFetch(description, source);
|
|
1847
|
+
}
|
|
1614
1848
|
for (var field in source) {
|
|
1615
|
-
if (field
|
|
1616
|
-
if (
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
}
|
|
1620
|
-
else if (source.hasOwnProperty(field)) {
|
|
1621
|
-
var mongooseType = source[field], mongooseOptions = mongooseType.options || {};
|
|
1622
|
-
var formData = mongooseOptions.form || {};
|
|
1623
|
-
if (mongooseType.schema && !formData.hidden) {
|
|
1624
|
-
if (doRecursion && destForm) {
|
|
1625
|
-
var schemaSchema = [];
|
|
1626
|
-
handleSchema('Nested ' + field, mongooseType.schema, schemaSchema, null, field + '.', true, $scope, ctrlState);
|
|
1627
|
-
var sectionInstructions = basicInstructions(field, formData, prefix);
|
|
1628
|
-
sectionInstructions.schema = schemaSchema;
|
|
1629
|
-
if (formData.tab) {
|
|
1630
|
-
handletabInfo(formData.tab, sectionInstructions);
|
|
1631
|
-
}
|
|
1632
|
-
if (formData.order !== undefined) {
|
|
1633
|
-
destForm.splice(formData.order, 0, sectionInstructions);
|
|
1634
|
-
}
|
|
1635
|
-
else {
|
|
1636
|
-
destForm.push(sectionInstructions);
|
|
1637
|
-
}
|
|
1849
|
+
if (source.hasOwnProperty(field)) {
|
|
1850
|
+
if (field === '_id') {
|
|
1851
|
+
if (destList && source['_id'].options && source['_id'].options.list) {
|
|
1852
|
+
handleListInfo(destList, source['_id'].options.list, field);
|
|
1638
1853
|
}
|
|
1639
1854
|
}
|
|
1640
|
-
else {
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1855
|
+
else if (source.hasOwnProperty(field)) {
|
|
1856
|
+
var mongooseType = source[field], mongooseOptions = mongooseType.options || {};
|
|
1857
|
+
var formData = mongooseOptions.form || {};
|
|
1858
|
+
if (mongooseType.schema && !formData.hidden) {
|
|
1859
|
+
if (doRecursion && destForm) {
|
|
1860
|
+
var schemaSchema = [];
|
|
1861
|
+
handleSchema('Nested ' + field, mongooseType.schema, schemaSchema, null, field + '.', true, $scope, ctrlState);
|
|
1862
|
+
var sectionInstructions = basicInstructions(field, formData, prefix);
|
|
1863
|
+
sectionInstructions.schema = schemaSchema;
|
|
1864
|
+
if (formData.tab) {
|
|
1865
|
+
handletabInfo(formData.tab, sectionInstructions);
|
|
1647
1866
|
}
|
|
1648
1867
|
if (formData.order !== undefined) {
|
|
1649
|
-
destForm.splice(formData.order, 0,
|
|
1868
|
+
destForm.splice(formData.order, 0, sectionInstructions);
|
|
1650
1869
|
}
|
|
1651
1870
|
else {
|
|
1652
|
-
destForm.push(
|
|
1871
|
+
destForm.push(sectionInstructions);
|
|
1653
1872
|
}
|
|
1654
1873
|
}
|
|
1655
1874
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1875
|
+
else {
|
|
1876
|
+
if (destForm && !formData.hidden) {
|
|
1877
|
+
var formInstructions = basicInstructions(field, formData, prefix);
|
|
1878
|
+
if (handleConditionals(formInstructions.showIf, formInstructions.name, $scope) && field !== 'options') {
|
|
1879
|
+
var formInst = handleFieldType(formInstructions, mongooseType, mongooseOptions, $scope, ctrlState);
|
|
1880
|
+
if (formInst.tab) {
|
|
1881
|
+
handletabInfo(formInst.tab, formInst);
|
|
1882
|
+
}
|
|
1883
|
+
if (formData.order !== undefined) {
|
|
1884
|
+
destForm.splice(formData.order, 0, formInst);
|
|
1885
|
+
}
|
|
1886
|
+
else {
|
|
1887
|
+
destForm.push(formInst);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
if (destList && mongooseOptions.list) {
|
|
1892
|
+
handleListInfo(destList, mongooseOptions.list, field);
|
|
1893
|
+
}
|
|
1658
1894
|
}
|
|
1659
1895
|
}
|
|
1660
1896
|
}
|
|
@@ -1678,6 +1914,9 @@ var fng;
|
|
|
1678
1914
|
// console.log($scope.tabs[0]['title'])
|
|
1679
1915
|
// $location.hash($scope.tabs[0]['title']);
|
|
1680
1916
|
// }
|
|
1917
|
+
if (typeof $scope.onSchemaProcessed === "function") {
|
|
1918
|
+
$scope.onSchemaProcessed(description, description.slice(0, 5) === 'Main ' ? $scope.baseSchema() : destForm);
|
|
1919
|
+
}
|
|
1681
1920
|
if (destList && destList.length === 0) {
|
|
1682
1921
|
handleEmptyList(description, destList, destForm, source);
|
|
1683
1922
|
}
|
|
@@ -1686,23 +1925,23 @@ var fng;
|
|
|
1686
1925
|
function performLookupSelect() {
|
|
1687
1926
|
formInstructions.options = recordHandler.suffixCleanId(formInstructions, 'Options');
|
|
1688
1927
|
formInstructions.ids = recordHandler.suffixCleanId(formInstructions, '_ids');
|
|
1689
|
-
if (!formInstructions.hidden
|
|
1690
|
-
if (
|
|
1691
|
-
mongooseOptions.ref
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1928
|
+
if (!formInstructions.hidden) {
|
|
1929
|
+
if (mongooseOptions.ref) {
|
|
1930
|
+
recordHandler.setUpLookupOptions(mongooseOptions.ref, formInstructions, $scope, ctrlState, handleSchema);
|
|
1931
|
+
}
|
|
1932
|
+
else if (mongooseOptions.lookupListRef) {
|
|
1933
|
+
recordHandler.setUpLookupListOptions(mongooseOptions.lookupListRef, formInstructions, $scope, ctrlState);
|
|
1934
|
+
formInstructions.lookupListRef = mongooseOptions.lookupListRef;
|
|
1935
|
+
}
|
|
1936
|
+
else if (mongooseOptions.internalRef) {
|
|
1937
|
+
recordHandler.handleInternalLookup($scope, formInstructions, mongooseOptions.internalRef);
|
|
1938
|
+
formInstructions.internalRef = mongooseOptions.internalRef;
|
|
1939
|
+
}
|
|
1940
|
+
else if (mongooseOptions.customLookupOptions) {
|
|
1941
|
+
// nothing to do - call setUpCustomLookupOptions() when ready to provide id and option arrays
|
|
1942
|
+
}
|
|
1943
|
+
else {
|
|
1944
|
+
throw new Error("No supported select lookup type found in ".concat(formInstructions.name));
|
|
1706
1945
|
}
|
|
1707
1946
|
}
|
|
1708
1947
|
}
|
|
@@ -1736,13 +1975,22 @@ var fng;
|
|
|
1736
1975
|
}
|
|
1737
1976
|
else if (mongooseType.instance === 'ObjectID') {
|
|
1738
1977
|
formInstructions.ref = mongooseOptions.ref;
|
|
1739
|
-
if (formInstructions.link
|
|
1740
|
-
formInstructions.
|
|
1741
|
-
|
|
1978
|
+
if (formInstructions.link) {
|
|
1979
|
+
if (formInstructions.link.linkOnly) {
|
|
1980
|
+
formInstructions.type = 'link';
|
|
1981
|
+
formInstructions.linktext = formInstructions.link.text;
|
|
1982
|
+
}
|
|
1983
|
+
else if (formInstructions.link.label) {
|
|
1984
|
+
formInstructions.linklabel = true;
|
|
1985
|
+
}
|
|
1986
|
+
else {
|
|
1987
|
+
console.log('Unsupported link setup');
|
|
1988
|
+
}
|
|
1742
1989
|
formInstructions.form = formInstructions.link.form;
|
|
1990
|
+
formInstructions.linktab = formInstructions.link.linktab;
|
|
1743
1991
|
delete formInstructions.link;
|
|
1744
1992
|
}
|
|
1745
|
-
|
|
1993
|
+
if (formInstructions.type !== 'link') {
|
|
1746
1994
|
formInstructions.type = 'select';
|
|
1747
1995
|
if (formInstructions.select2 || (mongooseOptions.form && mongooseOptions.form.select2)) {
|
|
1748
1996
|
console.log('support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select');
|
|
@@ -1754,16 +2002,18 @@ var fng;
|
|
|
1754
2002
|
}
|
|
1755
2003
|
else if (mongooseType.instance === 'Date') {
|
|
1756
2004
|
if (!formInstructions.type) {
|
|
2005
|
+
formInstructions.intType = 'date';
|
|
1757
2006
|
if (formInstructions.readonly) {
|
|
1758
2007
|
formInstructions.type = 'text';
|
|
1759
2008
|
}
|
|
1760
2009
|
else if (formInstructions.directive) {
|
|
1761
|
-
formInstructions.type = 'text';
|
|
2010
|
+
formInstructions.type = 'text';
|
|
1762
2011
|
}
|
|
1763
2012
|
else {
|
|
1764
2013
|
try {
|
|
1765
2014
|
formInstructions.add = formInstructions.add || '';
|
|
1766
|
-
|
|
2015
|
+
// Check whether DatePicker is installed
|
|
2016
|
+
angular.module('ui.date').requires;
|
|
1767
2017
|
formInstructions.type = 'text';
|
|
1768
2018
|
formInstructions.add += ' ui-date ui-date-format ';
|
|
1769
2019
|
// formInstructions.add += ' ui-date ui-date-format datepicker-popup-fix ';
|
|
@@ -1776,10 +2026,10 @@ var fng;
|
|
|
1776
2026
|
}
|
|
1777
2027
|
}
|
|
1778
2028
|
else if (mongooseType.instance.toLowerCase() === 'boolean') {
|
|
1779
|
-
formInstructions.type = 'checkbox';
|
|
2029
|
+
formInstructions.type = formInstructions.type || 'checkbox';
|
|
1780
2030
|
}
|
|
1781
2031
|
else if (mongooseType.instance === 'Number') {
|
|
1782
|
-
formInstructions.type = 'number';
|
|
2032
|
+
formInstructions.type = formInstructions.type || 'number';
|
|
1783
2033
|
if (mongooseOptions.min !== undefined) {
|
|
1784
2034
|
formInstructions.add = 'min="' + mongooseOptions.min + '" ' + (formInstructions.add || '');
|
|
1785
2035
|
}
|
|
@@ -1799,11 +2049,17 @@ var fng;
|
|
|
1799
2049
|
if (mongooseOptions.readonly) {
|
|
1800
2050
|
formInstructions['readonly'] = true;
|
|
1801
2051
|
}
|
|
2052
|
+
if (mongooseType.defaultValue !== undefined) {
|
|
2053
|
+
formInstructions.defaultValue = mongooseType.defaultValue;
|
|
2054
|
+
}
|
|
2055
|
+
else if (mongooseType.options && mongooseType.options.default !== undefined) {
|
|
2056
|
+
console.log('No support for default with no value, yet');
|
|
2057
|
+
}
|
|
1802
2058
|
return formInstructions;
|
|
1803
2059
|
}
|
|
1804
|
-
function getArrayFieldToExtend(fieldName, $scope) {
|
|
2060
|
+
function getArrayFieldToExtend(fieldName, $scope, modelOverride) {
|
|
1805
2061
|
var fieldParts = fieldName.split('.');
|
|
1806
|
-
var arrayField = $scope.record;
|
|
2062
|
+
var arrayField = modelOverride || $scope.record;
|
|
1807
2063
|
for (var i = 0, l = fieldParts.length; i < l; i++) {
|
|
1808
2064
|
if (!arrayField[fieldParts[i]]) {
|
|
1809
2065
|
if (i === l - 1) {
|
|
@@ -1920,6 +2176,9 @@ var fng;
|
|
|
1920
2176
|
generateEditUrl: function generateEditUrl(obj, $scope) {
|
|
1921
2177
|
return routingService.buildUrl($scope.modelName + '/' + ($scope.formName ? $scope.formName + '/' : '') + obj._id + '/edit');
|
|
1922
2178
|
},
|
|
2179
|
+
generateViewUrl: function generateViewUrl(obj, $scope) {
|
|
2180
|
+
return routingService.buildUrl($scope.modelName + '/' + ($scope.formName ? $scope.formName + '/' : '') + obj._id + '/view');
|
|
2181
|
+
},
|
|
1923
2182
|
generateNewUrl: function generateNewUrl($scope) {
|
|
1924
2183
|
return routingService.buildUrl($scope.modelName + '/' + ($scope.formName ? $scope.formName + '/' : '') + 'new');
|
|
1925
2184
|
},
|
|
@@ -2004,25 +2263,44 @@ var fng;
|
|
|
2004
2263
|
}
|
|
2005
2264
|
return forceNextTime;
|
|
2006
2265
|
},
|
|
2007
|
-
add: function add(fieldName, $event, $scope) {
|
|
2008
|
-
var
|
|
2009
|
-
|
|
2010
|
-
|
|
2266
|
+
add: function add(fieldName, $event, $scope, modelOverride) {
|
|
2267
|
+
var _a;
|
|
2268
|
+
// check that target element is visible. May not be reliable - see https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom
|
|
2269
|
+
if ($event.target.offsetParent) {
|
|
2270
|
+
var arrayField = getArrayFieldToExtend(fieldName, $scope, modelOverride);
|
|
2271
|
+
var schemaElement = $scope.formSchema.find(function (f) { return f.name === fieldName; }); // In case someone is using the formSchema directly
|
|
2272
|
+
var subSchema = schemaElement ? schemaElement.schema : null;
|
|
2273
|
+
var obj = subSchema ? $scope.setDefaults(subSchema, fieldName + '.') : {};
|
|
2274
|
+
if (typeof ((_a = $scope.dataEventFunctions) === null || _a === void 0 ? void 0 : _a.onInitialiseNewSubDoc) === "function") {
|
|
2275
|
+
$scope.dataEventFunctions.onInitialiseNewSubDoc(fieldName, subSchema, obj);
|
|
2276
|
+
}
|
|
2277
|
+
arrayField.push(obj);
|
|
2278
|
+
$scope.setFormDirty($event);
|
|
2279
|
+
}
|
|
2011
2280
|
},
|
|
2012
|
-
unshift: function unshift(fieldName, $event, $scope) {
|
|
2013
|
-
var arrayField = getArrayFieldToExtend(fieldName, $scope);
|
|
2281
|
+
unshift: function unshift(fieldName, $event, $scope, modelOverride) {
|
|
2282
|
+
var arrayField = getArrayFieldToExtend(fieldName, $scope, modelOverride);
|
|
2014
2283
|
arrayField.unshift({});
|
|
2015
2284
|
$scope.setFormDirty($event);
|
|
2016
2285
|
},
|
|
2017
|
-
remove: function remove(fieldName, value, $event, $scope) {
|
|
2286
|
+
remove: function remove(fieldName, value, $event, $scope, modelOverride) {
|
|
2018
2287
|
// Remove an element from an array
|
|
2019
|
-
var
|
|
2020
|
-
var
|
|
2021
|
-
|
|
2022
|
-
|
|
2288
|
+
var arrayField = getArrayFieldToExtend(fieldName, $scope, modelOverride);
|
|
2289
|
+
var err;
|
|
2290
|
+
if (typeof $scope.dataEventFunctions.onDeleteSubDoc === "function") {
|
|
2291
|
+
var schemaElement = $scope.formSchema.find(function (f) {
|
|
2292
|
+
return f.name === fieldName;
|
|
2293
|
+
});
|
|
2294
|
+
var subSchema = schemaElement ? schemaElement.schema : null;
|
|
2295
|
+
err = $scope.dataEventFunctions.onDeleteSubDoc(fieldName, subSchema, arrayField, value);
|
|
2296
|
+
}
|
|
2297
|
+
if (err) {
|
|
2298
|
+
$scope.showError(err);
|
|
2299
|
+
}
|
|
2300
|
+
else {
|
|
2301
|
+
arrayField.splice(value, 1);
|
|
2302
|
+
$scope.setFormDirty($event);
|
|
2023
2303
|
}
|
|
2024
|
-
arrayField.splice(value, 1);
|
|
2025
|
-
$scope.setFormDirty($event);
|
|
2026
2304
|
},
|
|
2027
2305
|
hasError: function hasError(formName, name, index, $scope) {
|
|
2028
2306
|
var result = false;
|
|
@@ -2034,7 +2312,7 @@ var fng;
|
|
|
2034
2312
|
// Cannot assume that directives will use the same methods
|
|
2035
2313
|
if (form) {
|
|
2036
2314
|
var field_1 = form[name];
|
|
2037
|
-
if (field_1 && field_1.$invalid) {
|
|
2315
|
+
if (field_1 && field_1.$invalid && !field_1.$$attr.readonly) {
|
|
2038
2316
|
if (field_1.$dirty) {
|
|
2039
2317
|
result = true;
|
|
2040
2318
|
}
|
|
@@ -2074,6 +2352,9 @@ var fng;
|
|
|
2074
2352
|
$scope.generateEditUrl = function (obj) {
|
|
2075
2353
|
return formGeneratorInstance.generateEditUrl(obj, $scope);
|
|
2076
2354
|
};
|
|
2355
|
+
$scope.generateViewUrl = function (obj) {
|
|
2356
|
+
return formGeneratorInstance.generateViewUrl(obj, $scope);
|
|
2357
|
+
};
|
|
2077
2358
|
$scope.generateNewUrl = function () {
|
|
2078
2359
|
return formGeneratorInstance.generateNewUrl($scope);
|
|
2079
2360
|
};
|
|
@@ -2081,7 +2362,7 @@ var fng;
|
|
|
2081
2362
|
return recordHandlerInstance.scrollTheList($scope);
|
|
2082
2363
|
};
|
|
2083
2364
|
$scope.getListData = function (record, fieldName) {
|
|
2084
|
-
return recordHandlerInstance.getListData(
|
|
2365
|
+
return recordHandlerInstance.getListData(record, fieldName, $scope.listSchema, $scope);
|
|
2085
2366
|
};
|
|
2086
2367
|
$scope.setPristine = function (clearErrors) {
|
|
2087
2368
|
if (clearErrors) {
|
|
@@ -2103,17 +2384,17 @@ var fng;
|
|
|
2103
2384
|
console.log('setFormDirty called without an event (fine in a unit test)');
|
|
2104
2385
|
}
|
|
2105
2386
|
};
|
|
2106
|
-
$scope.add = function (fieldName, $event) {
|
|
2107
|
-
return formGeneratorInstance.add(fieldName, $event, $scope);
|
|
2387
|
+
$scope.add = function (fieldName, $event, modelOverride) {
|
|
2388
|
+
return formGeneratorInstance.add(fieldName, $event, $scope, modelOverride);
|
|
2108
2389
|
};
|
|
2109
2390
|
$scope.hasError = function (form, name, index) {
|
|
2110
2391
|
return formGeneratorInstance.hasError(form, name, index, $scope);
|
|
2111
2392
|
};
|
|
2112
|
-
$scope.unshift = function (fieldName, $event) {
|
|
2113
|
-
return formGeneratorInstance.unshift(fieldName, $event, $scope);
|
|
2393
|
+
$scope.unshift = function (fieldName, $event, modelOverride) {
|
|
2394
|
+
return formGeneratorInstance.unshift(fieldName, $event, $scope, modelOverride);
|
|
2114
2395
|
};
|
|
2115
|
-
$scope.remove = function (fieldName, value, $event) {
|
|
2116
|
-
return formGeneratorInstance.remove(fieldName, value, $event, $scope);
|
|
2396
|
+
$scope.remove = function (fieldName, value, $event, modelOverride) {
|
|
2397
|
+
return formGeneratorInstance.remove(fieldName, value, $event, $scope, modelOverride);
|
|
2117
2398
|
};
|
|
2118
2399
|
$scope.baseSchema = function () {
|
|
2119
2400
|
return ($scope.tabs.length ? $scope.tabs : $scope.formSchema);
|
|
@@ -2128,7 +2409,7 @@ var fng;
|
|
|
2128
2409
|
};
|
|
2129
2410
|
}
|
|
2130
2411
|
services.formGenerator = formGenerator;
|
|
2131
|
-
formGenerator.$inject = ["$location", "$timeout", "$filter", "
|
|
2412
|
+
formGenerator.$inject = ["$location", "$timeout", "$filter", "routingService", "recordHandler"];
|
|
2132
2413
|
})(services = fng.services || (fng.services = {}));
|
|
2133
2414
|
})(fng || (fng = {}));
|
|
2134
2415
|
/// <reference path="../../index.d.ts" />
|
|
@@ -2137,8 +2418,8 @@ var fng;
|
|
|
2137
2418
|
var services;
|
|
2138
2419
|
(function (services) {
|
|
2139
2420
|
/*@ngInject*/
|
|
2140
|
-
formMarkupHelper.$inject = ["cssFrameworkService", "inputSizeHelper", "addAllService"];
|
|
2141
|
-
function formMarkupHelper(cssFrameworkService, inputSizeHelper, addAllService) {
|
|
2421
|
+
formMarkupHelper.$inject = ["cssFrameworkService", "inputSizeHelper", "addAllService", "$filter"];
|
|
2422
|
+
function formMarkupHelper(cssFrameworkService, inputSizeHelper, addAllService, $filter) {
|
|
2142
2423
|
function generateNgShow(showWhen, model) {
|
|
2143
2424
|
function evaluateSide(side) {
|
|
2144
2425
|
var result = side;
|
|
@@ -2166,11 +2447,15 @@ var fng;
|
|
|
2166
2447
|
}
|
|
2167
2448
|
return evaluateSide(showWhen.lhs) + conditionSymbols[conditionPos] + evaluateSide(showWhen.rhs);
|
|
2168
2449
|
}
|
|
2169
|
-
var isHorizontalStyle = function isHorizontalStyle(formStyle) {
|
|
2170
|
-
|
|
2450
|
+
var isHorizontalStyle = function isHorizontalStyle(formStyle, includeStacked) {
|
|
2451
|
+
var exclude = ['vertical', 'inline'];
|
|
2452
|
+
if (!includeStacked) {
|
|
2453
|
+
exclude.push('stacked');
|
|
2454
|
+
}
|
|
2455
|
+
return (!formStyle || formStyle === 'undefined' || !exclude.includes(formStyle));
|
|
2171
2456
|
};
|
|
2172
2457
|
function glyphClass() {
|
|
2173
|
-
return (cssFrameworkService.framework() === 'bs2'
|
|
2458
|
+
return (cssFrameworkService.framework() === 'bs2' ? 'icon' : 'glyphicon glyphicon');
|
|
2174
2459
|
}
|
|
2175
2460
|
return {
|
|
2176
2461
|
isHorizontalStyle: isHorizontalStyle,
|
|
@@ -2188,7 +2473,9 @@ var fng;
|
|
|
2188
2473
|
insert += 'ng-show="' + generateNgShow(info.showWhen, options.model) + '"';
|
|
2189
2474
|
}
|
|
2190
2475
|
}
|
|
2191
|
-
|
|
2476
|
+
if (info.id && typeof info.id.replace === "function") {
|
|
2477
|
+
insert += ' id="cg_' + info.id.replace(/\./g, '-') + '"';
|
|
2478
|
+
}
|
|
2192
2479
|
if (cssFrameworkService.framework() === 'bs3') {
|
|
2193
2480
|
classes += ' form-group';
|
|
2194
2481
|
if (options.formstyle === 'vertical' && info.size !== 'block-level') {
|
|
@@ -2213,7 +2500,7 @@ var fng;
|
|
|
2213
2500
|
closeTag += '</div>';
|
|
2214
2501
|
}
|
|
2215
2502
|
else {
|
|
2216
|
-
if (isHorizontalStyle(options.formstyle)) {
|
|
2503
|
+
if (isHorizontalStyle(options.formstyle, true)) {
|
|
2217
2504
|
template += '<div' + addAllService.addAll(scope, 'Group', 'control-group', options);
|
|
2218
2505
|
closeTag = '</div>';
|
|
2219
2506
|
}
|
|
@@ -2227,11 +2514,13 @@ var fng;
|
|
|
2227
2514
|
},
|
|
2228
2515
|
label: function label(scope, fieldInfo, addButtonMarkup, options) {
|
|
2229
2516
|
var labelHTML = '';
|
|
2230
|
-
if ((cssFrameworkService.framework() === 'bs3' || (options.formstyle
|
|
2517
|
+
if ((cssFrameworkService.framework() === 'bs3' || (!['inline', 'stacked'].includes(options.formstyle) && fieldInfo.label !== '')) || addButtonMarkup) {
|
|
2231
2518
|
labelHTML = '<label';
|
|
2232
2519
|
var classes = 'control-label';
|
|
2233
|
-
if (isHorizontalStyle(options.formstyle)) {
|
|
2234
|
-
|
|
2520
|
+
if (isHorizontalStyle(options.formstyle, false)) {
|
|
2521
|
+
if (!fieldInfo.linklabel) {
|
|
2522
|
+
labelHTML += ' for="' + fieldInfo.id + '"';
|
|
2523
|
+
}
|
|
2235
2524
|
if (typeof fieldInfo.labelDefaultClass !== 'undefined') {
|
|
2236
2525
|
// Override default label class (can be empty)
|
|
2237
2526
|
classes += ' ' + fieldInfo.labelDefaultClass;
|
|
@@ -2240,7 +2529,7 @@ var fng;
|
|
|
2240
2529
|
classes += ' col-sm-3';
|
|
2241
2530
|
}
|
|
2242
2531
|
}
|
|
2243
|
-
else if (options.formstyle
|
|
2532
|
+
else if (['inline', 'stacked'].includes(options.formstyle)) {
|
|
2244
2533
|
labelHTML += ' for="' + fieldInfo.id + '"';
|
|
2245
2534
|
classes += ' sr-only';
|
|
2246
2535
|
}
|
|
@@ -2249,6 +2538,17 @@ var fng;
|
|
|
2249
2538
|
labelHTML += ' <i id="add_' + fieldInfo.id + '" ng-click="add(\'' + fieldInfo.name + '\',$event)" class="' + glyphClass() + '-plus-sign"></i>';
|
|
2250
2539
|
}
|
|
2251
2540
|
labelHTML += '</label>';
|
|
2541
|
+
if (fieldInfo.linklabel) {
|
|
2542
|
+
var value = '<fng-link fld="' + fieldInfo.name + '" ref="' + fieldInfo.ref + '" text="' + escape(labelHTML) + '"';
|
|
2543
|
+
if (fieldInfo.form) {
|
|
2544
|
+
value += ' form="' + fieldInfo.form + '"';
|
|
2545
|
+
}
|
|
2546
|
+
if (fieldInfo.linktab) {
|
|
2547
|
+
value += ' linktab="' + fieldInfo.linktab + '"';
|
|
2548
|
+
}
|
|
2549
|
+
value += '></fng-link>';
|
|
2550
|
+
labelHTML = value;
|
|
2551
|
+
}
|
|
2252
2552
|
}
|
|
2253
2553
|
return labelHTML;
|
|
2254
2554
|
},
|
|
@@ -2268,14 +2568,17 @@ var fng;
|
|
|
2268
2568
|
else {
|
|
2269
2569
|
sizeClassBS2 = (fieldInfo.size ? ' input-' + fieldInfo.size : '');
|
|
2270
2570
|
}
|
|
2271
|
-
if (options.formstyle
|
|
2571
|
+
if (['inline', 'stacked'].includes(options.formstyle)) {
|
|
2272
2572
|
placeHolder = placeHolder || fieldInfo.label;
|
|
2273
2573
|
}
|
|
2274
|
-
common = 'ng-model="' + modelString + '"' + (idString ? ' id="' + idString + '" name="' + idString + '" ' : ' name="' + nameString + '" ');
|
|
2574
|
+
common = 'data-ng-model="' + modelString + '"' + (idString ? ' id="' + idString + '" name="' + idString + '" ' : ' name="' + nameString + '" ');
|
|
2275
2575
|
common += (placeHolder ? ('placeholder="' + placeHolder + '" ') : '');
|
|
2276
2576
|
if (fieldInfo.popup) {
|
|
2277
2577
|
common += 'title="' + fieldInfo.popup + '" ';
|
|
2278
2578
|
}
|
|
2579
|
+
if (fieldInfo.ariaLabel) {
|
|
2580
|
+
common += 'aria-label="' + fieldInfo.ariaLabel + '" ';
|
|
2581
|
+
}
|
|
2279
2582
|
common += addAllService.addAll(scope, 'Field', null, options);
|
|
2280
2583
|
return {
|
|
2281
2584
|
common: common,
|
|
@@ -2286,28 +2589,36 @@ var fng;
|
|
|
2286
2589
|
};
|
|
2287
2590
|
},
|
|
2288
2591
|
inputChrome: function inputChrome(value, fieldInfo, options, markupVars) {
|
|
2289
|
-
if (cssFrameworkService.framework() === 'bs3' && isHorizontalStyle(options.formstyle) && fieldInfo.type !== 'checkbox') {
|
|
2592
|
+
if (cssFrameworkService.framework() === 'bs3' && isHorizontalStyle(options.formstyle, true) && fieldInfo.type !== 'checkbox') {
|
|
2290
2593
|
value = '<div class="bs3-input ' + markupVars.sizeClassBS3 + '">' + value + '</div>';
|
|
2291
2594
|
}
|
|
2292
2595
|
// Hack to cope with inline help in directives
|
|
2293
2596
|
var inlineHelp = (fieldInfo.helpInline || '') + (fieldInfo.helpinline || '');
|
|
2294
2597
|
if (inlineHelp.length > 0) {
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2598
|
+
var helpMarkup = cssFrameworkService.framework() === 'bs2' ? { el: 'span', cl: 'help-inline' } : { el: 'div', cl: 'help-block' };
|
|
2599
|
+
value += "<".concat(helpMarkup.el, " class=\"").concat(helpMarkup.cl, "\">").concat(inlineHelp, "</").concat(helpMarkup.el, ">");
|
|
2600
|
+
}
|
|
2601
|
+
if (!options.noid) {
|
|
2602
|
+
value += "<div ng-if=\"".concat((options.name || 'myForm'), "['").concat(fieldInfo.id, "'].$dirty\" class=\"help-block\">") +
|
|
2603
|
+
" <div ng-messages=\"".concat((options.name || 'myForm'), "['").concat(fieldInfo.id, "'].$error\">") +
|
|
2604
|
+
' <div ng-messages-include="error-messages.html">' +
|
|
2605
|
+
' </div>' +
|
|
2606
|
+
' </div>' +
|
|
2607
|
+
'</div>';
|
|
2608
|
+
}
|
|
2304
2609
|
if (fieldInfo.help) {
|
|
2305
|
-
value += '<
|
|
2610
|
+
value += '<div class="help-block">' + fieldInfo.help + '</div>';
|
|
2306
2611
|
}
|
|
2307
2612
|
return value;
|
|
2308
2613
|
},
|
|
2309
2614
|
generateSimpleInput: function generateSimpleInput(common, fieldInfo, options) {
|
|
2310
|
-
var result = '<input ' + common + 'type="' + fieldInfo.type + '"';
|
|
2615
|
+
var result = '<input ' + common + 'type="' + fieldInfo.type + '" ';
|
|
2616
|
+
if (!fieldInfo.label && !fieldInfo.ariaLabel) {
|
|
2617
|
+
result += "aria-label=\"".concat(fieldInfo.name.replace(/\./g, ' '), "\" ");
|
|
2618
|
+
}
|
|
2619
|
+
else if (options.subschema) {
|
|
2620
|
+
result += "aria-label=\"".concat(fieldInfo.label ? ($filter('titleCase')(options.subschemaroot) + ' ' + fieldInfo.label) : (fieldInfo.popup || fieldInfo.name.replace(/\./g, ' ')), "\" ");
|
|
2621
|
+
}
|
|
2311
2622
|
if (options.formstyle === 'inline' && cssFrameworkService.framework() === 'bs2' && !fieldInfo.size) {
|
|
2312
2623
|
result += 'class="input-small"';
|
|
2313
2624
|
}
|
|
@@ -2316,7 +2627,7 @@ var fng;
|
|
|
2316
2627
|
},
|
|
2317
2628
|
controlDivClasses: function controlDivClasses(options) {
|
|
2318
2629
|
var result = [];
|
|
2319
|
-
if (isHorizontalStyle(options.formstyle)) {
|
|
2630
|
+
if (isHorizontalStyle(options.formstyle, false)) {
|
|
2320
2631
|
result.push(cssFrameworkService.framework() === 'bs2' ? 'controls' : 'col-sm-9');
|
|
2321
2632
|
}
|
|
2322
2633
|
return result;
|
|
@@ -2350,7 +2661,13 @@ var fng;
|
|
|
2350
2661
|
if (fieldInfo.add) {
|
|
2351
2662
|
result += ' ' + fieldInfo.add + ' ';
|
|
2352
2663
|
}
|
|
2353
|
-
result += requiredStr
|
|
2664
|
+
result += requiredStr;
|
|
2665
|
+
if (fieldInfo.readonly) {
|
|
2666
|
+
result += " ".concat(typeof fieldInfo.readOnly === 'boolean' ? 'readonly' : 'ng-readonly="' + fieldInfo.readonly + '"', " ");
|
|
2667
|
+
}
|
|
2668
|
+
else {
|
|
2669
|
+
result += ' ';
|
|
2670
|
+
}
|
|
2354
2671
|
return result;
|
|
2355
2672
|
}
|
|
2356
2673
|
};
|
|
@@ -2506,26 +2823,32 @@ var fng;
|
|
|
2506
2823
|
*
|
|
2507
2824
|
*/
|
|
2508
2825
|
/*@ngInject*/
|
|
2509
|
-
recordHandler.$inject = ["$
|
|
2510
|
-
function recordHandler($
|
|
2826
|
+
recordHandler.$inject = ["$location", "$window", "$filter", "$timeout", "routingService", "cssFrameworkService", "SubmissionsService", "SchemasService"];
|
|
2827
|
+
function recordHandler($location, $window, $filter, $timeout, routingService, cssFrameworkService, SubmissionsService, SchemasService) {
|
|
2511
2828
|
// TODO: Put this in a service
|
|
2512
2829
|
var makeMongoId = function (rnd) {
|
|
2513
2830
|
if (rnd === void 0) { rnd = function (r16) { return Math.floor(r16).toString(16); }; }
|
|
2514
|
-
return rnd(Date.now() / 1000) +
|
|
2831
|
+
return rnd(Date.now() / 1000) + " ".repeat(16).replace(/./g, function () { return rnd(Math.random() * 16); });
|
|
2515
2832
|
};
|
|
2833
|
+
function _handleCancel(resp) {
|
|
2834
|
+
if (["cancel", "backdrop click", "escape key press"].indexOf(resp) === -1) {
|
|
2835
|
+
throw resp;
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2516
2838
|
var suffixCleanId = function suffixCleanId(inst, suffix) {
|
|
2517
|
-
return (inst.id ||
|
|
2839
|
+
return (inst.id || "f_" + inst.name).replace(/\./g, "_") + suffix;
|
|
2518
2840
|
};
|
|
2519
|
-
var walkTree = function (object, fieldname, element) {
|
|
2841
|
+
var walkTree = function (object, fieldname, element, insertIntermediateObjects) {
|
|
2520
2842
|
// Walk through subdocs to find the required key
|
|
2521
2843
|
// for instance walkTree(master,'address.street.number',element)
|
|
2522
2844
|
// called by getData and setData
|
|
2845
|
+
if (insertIntermediateObjects === void 0) { insertIntermediateObjects = false; }
|
|
2523
2846
|
// element is used when accessing in the context of a input, as the id (like exams-2-grader)
|
|
2524
2847
|
// gives us the element of an array (one level down only for now). Leaving element blank returns the whole array
|
|
2525
|
-
var parts = fieldname.split(
|
|
2848
|
+
var parts = fieldname.split("."), higherLevels = parts.length - 1, workingRec = object;
|
|
2526
2849
|
for (var i = 0; i < higherLevels; i++) {
|
|
2527
2850
|
if (!workingRec) {
|
|
2528
|
-
throw new Error("walkTree failed: Object = "
|
|
2851
|
+
throw new Error("walkTree failed: Object = ".concat(object, ", fieldname = ").concat(fieldname, ", i = ").concat(i));
|
|
2529
2852
|
}
|
|
2530
2853
|
if (angular.isArray(workingRec)) {
|
|
2531
2854
|
workingRec = _.map(workingRec, function (obj) {
|
|
@@ -2533,18 +2856,21 @@ var fng;
|
|
|
2533
2856
|
});
|
|
2534
2857
|
}
|
|
2535
2858
|
else {
|
|
2859
|
+
if (insertIntermediateObjects && !workingRec[parts[i]]) {
|
|
2860
|
+
workingRec[parts[i]] = {};
|
|
2861
|
+
}
|
|
2536
2862
|
workingRec = workingRec[parts[i]];
|
|
2537
2863
|
}
|
|
2538
|
-
if (angular.isArray(workingRec) && typeof element !==
|
|
2539
|
-
if (element.scope && typeof element.scope ===
|
|
2864
|
+
if (angular.isArray(workingRec) && typeof element !== "undefined") {
|
|
2865
|
+
if (element.scope && typeof element.scope === "function") {
|
|
2540
2866
|
// If we come across an array we need to find the correct position, if we have an element
|
|
2541
2867
|
workingRec = workingRec[element.scope().$index];
|
|
2542
2868
|
}
|
|
2543
|
-
else if (typeof element ===
|
|
2869
|
+
else if (typeof element === "number") {
|
|
2544
2870
|
workingRec = workingRec[element];
|
|
2545
2871
|
}
|
|
2546
2872
|
else {
|
|
2547
|
-
throw new Error(
|
|
2873
|
+
throw new Error("Unsupported element type in walkTree " + fieldname);
|
|
2548
2874
|
}
|
|
2549
2875
|
}
|
|
2550
2876
|
if (!workingRec) {
|
|
@@ -2557,15 +2883,20 @@ var fng;
|
|
|
2557
2883
|
};
|
|
2558
2884
|
};
|
|
2559
2885
|
var setData = function setData(object, fieldname, element, value) {
|
|
2560
|
-
var leafData = walkTree(object, fieldname, element);
|
|
2886
|
+
var leafData = walkTree(object, fieldname, element, !!value);
|
|
2561
2887
|
if (leafData.lastObject && leafData.key) {
|
|
2562
|
-
if (
|
|
2563
|
-
|
|
2564
|
-
leafData.lastObject
|
|
2888
|
+
if (value) {
|
|
2889
|
+
if (angular.isArray(leafData.lastObject)) {
|
|
2890
|
+
for (var i = 0; i < leafData.lastObject.length; i++) {
|
|
2891
|
+
leafData.lastObject[i][leafData.key] = value[i];
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2894
|
+
else {
|
|
2895
|
+
leafData.lastObject[leafData.key] = value;
|
|
2565
2896
|
}
|
|
2566
2897
|
}
|
|
2567
2898
|
else {
|
|
2568
|
-
leafData.lastObject[leafData.key]
|
|
2899
|
+
delete leafData.lastObject[leafData.key];
|
|
2569
2900
|
}
|
|
2570
2901
|
}
|
|
2571
2902
|
};
|
|
@@ -2584,11 +2915,17 @@ var fng;
|
|
|
2584
2915
|
}
|
|
2585
2916
|
return retVal;
|
|
2586
2917
|
};
|
|
2587
|
-
var updateRecordWithLookupValues = function (schemaElement, $scope, ctrlState) {
|
|
2918
|
+
var updateRecordWithLookupValues = function (schemaElement, $scope, ctrlState, ignoreDirty) {
|
|
2919
|
+
if (ignoreDirty === void 0) { ignoreDirty = false; }
|
|
2588
2920
|
// Update the master and the record with the lookup values, master first
|
|
2589
|
-
if (!$scope.topLevelFormName || $scope[$scope.topLevelFormName].$pristine) {
|
|
2921
|
+
if (!$scope.topLevelFormName || ($scope[$scope.topLevelFormName] && (ignoreDirty || $scope[$scope.topLevelFormName].$pristine))) {
|
|
2590
2922
|
updateObject(schemaElement.name, ctrlState.master, function (value) {
|
|
2591
|
-
|
|
2923
|
+
if (typeof value == "object" && value.id) {
|
|
2924
|
+
return value;
|
|
2925
|
+
}
|
|
2926
|
+
else {
|
|
2927
|
+
return convertForeignKeys(schemaElement, value, $scope[suffixCleanId(schemaElement, "Options")], $scope[suffixCleanId(schemaElement, "_ids")]);
|
|
2928
|
+
}
|
|
2592
2929
|
});
|
|
2593
2930
|
// Then copy the converted keys from master into record
|
|
2594
2931
|
var newVal = getData(ctrlState.master, schemaElement.name);
|
|
@@ -2599,38 +2936,29 @@ var fng;
|
|
|
2599
2936
|
};
|
|
2600
2937
|
// Split a field name into the next level and all following levels
|
|
2601
2938
|
function splitFieldName(aFieldName) {
|
|
2602
|
-
var nesting = aFieldName.split(
|
|
2939
|
+
var nesting = aFieldName.split("."), result = [nesting[0]];
|
|
2603
2940
|
if (nesting.length > 1) {
|
|
2604
|
-
result.push(nesting.slice(1).join(
|
|
2941
|
+
result.push(nesting.slice(1).join("."));
|
|
2605
2942
|
}
|
|
2606
2943
|
return result;
|
|
2607
2944
|
}
|
|
2608
|
-
var getListData = function getListData(
|
|
2945
|
+
var getListData = function getListData(record, fieldName, listSchema, $scope) {
|
|
2609
2946
|
if (listSchema === void 0) { listSchema = null; }
|
|
2610
|
-
var retVal = record;
|
|
2611
|
-
var nests = fieldName.split('.');
|
|
2612
|
-
for (var i = 0; i < nests.length; i++) {
|
|
2613
|
-
if (retVal !== undefined && retVal !== null && nests && nests[i]) {
|
|
2614
|
-
retVal = retVal[nests[i]];
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
if (retVal === undefined) {
|
|
2618
|
-
retVal = '';
|
|
2619
|
-
}
|
|
2947
|
+
var retVal = getData(record, fieldName) || "";
|
|
2620
2948
|
if (retVal && listSchema) {
|
|
2621
2949
|
// Convert list fields as per instructions in params (ideally should be the same as what is found in data_form getListFields
|
|
2622
|
-
var schemaElm = _.find(listSchema, function (elm) { return (elm[
|
|
2950
|
+
var schemaElm = _.find(listSchema, function (elm) { return (elm["name"] === fieldName); });
|
|
2623
2951
|
if (schemaElm) {
|
|
2624
|
-
switch (schemaElm[
|
|
2952
|
+
switch (schemaElm["params"]) {
|
|
2625
2953
|
case undefined:
|
|
2626
2954
|
break;
|
|
2627
|
-
case
|
|
2955
|
+
case "timestamp":
|
|
2628
2956
|
var timestamp = retVal.toString().substring(0, 8);
|
|
2629
2957
|
var date = new Date(parseInt(timestamp, 16) * 1000);
|
|
2630
|
-
retVal = date.toLocaleDateString() +
|
|
2958
|
+
retVal = date.toLocaleDateString() + " " + date.toLocaleTimeString();
|
|
2631
2959
|
break;
|
|
2632
2960
|
default:
|
|
2633
|
-
retVal = $scope.dataEventFunctions[schemaElm[
|
|
2961
|
+
retVal = $scope.dataEventFunctions[schemaElm["params"]](record);
|
|
2634
2962
|
}
|
|
2635
2963
|
}
|
|
2636
2964
|
}
|
|
@@ -2647,7 +2975,7 @@ var fng;
|
|
|
2647
2975
|
if (angular.isArray(theValue)) {
|
|
2648
2976
|
for (var i = theValue.length - 1; i >= 0; i--) {
|
|
2649
2977
|
var type = typeof theValue[i];
|
|
2650
|
-
if (type ===
|
|
2978
|
+
if (type === "undefined" || (type === "object" && Object.keys(theValue[i]).length === 0)) {
|
|
2651
2979
|
theValue.splice(i, 1);
|
|
2652
2980
|
}
|
|
2653
2981
|
}
|
|
@@ -2669,8 +2997,8 @@ var fng;
|
|
|
2669
2997
|
}
|
|
2670
2998
|
// Set up the lookup lists (value and id) on the scope for an internal lookup. Called by convertToAngularModel and $watch
|
|
2671
2999
|
function setUpInternalLookupLists($scope, options, ids, newVal, valueAttrib) {
|
|
2672
|
-
var optionsArray = (typeof options ===
|
|
2673
|
-
var idsArray = (typeof ids ===
|
|
3000
|
+
var optionsArray = (typeof options === "string" ? $scope[options] : options);
|
|
3001
|
+
var idsArray = (typeof ids === "string" ? $scope[ids] : ids);
|
|
2674
3002
|
optionsArray.length = 0;
|
|
2675
3003
|
idsArray.length = 0;
|
|
2676
3004
|
if (!!newVal && (newVal.length > 0)) {
|
|
@@ -2692,10 +3020,10 @@ var fng;
|
|
|
2692
3020
|
result = true;
|
|
2693
3021
|
}
|
|
2694
3022
|
else if (!aSchema.directive) {
|
|
2695
|
-
if (aSchema.type ===
|
|
3023
|
+
if (aSchema.type === "text") {
|
|
2696
3024
|
result = true;
|
|
2697
3025
|
}
|
|
2698
|
-
else if (aSchema.type ===
|
|
3026
|
+
else if (aSchema.type === "select" && !aSchema.ids) {
|
|
2699
3027
|
result = true;
|
|
2700
3028
|
}
|
|
2701
3029
|
}
|
|
@@ -2705,7 +3033,7 @@ var fng;
|
|
|
2705
3033
|
function getConversionObject(scope, entryName, schemaName) {
|
|
2706
3034
|
var conversions = scope.conversions;
|
|
2707
3035
|
if (schemaName) {
|
|
2708
|
-
conversions = conversions
|
|
3036
|
+
conversions = getData(conversions, schemaName) || {};
|
|
2709
3037
|
}
|
|
2710
3038
|
return conversions[entryName];
|
|
2711
3039
|
}
|
|
@@ -2716,37 +3044,58 @@ var fng;
|
|
|
2716
3044
|
for (var i = 0; i < schema.length; i++) {
|
|
2717
3045
|
var schemaEntry = schema[i];
|
|
2718
3046
|
var fieldName = schemaEntry.name.slice(prefixLength);
|
|
3047
|
+
if (!fieldName.length) {
|
|
3048
|
+
fieldName = schemaEntry.name.split('.').pop();
|
|
3049
|
+
}
|
|
2719
3050
|
var fieldValue = getData(anObject, fieldName);
|
|
3051
|
+
if (schemaEntry.intType === 'date' && typeof fieldValue === 'string') {
|
|
3052
|
+
setData(anObject, fieldName, null, new Date(fieldValue));
|
|
3053
|
+
}
|
|
2720
3054
|
if (schemaEntry.schema) {
|
|
2721
3055
|
if (fieldValue) {
|
|
2722
3056
|
for (var j = 0; j < fieldValue.length; j++) {
|
|
2723
|
-
fieldValue[j] = convertToAngularModel(schemaEntry.schema, fieldValue[j],
|
|
3057
|
+
fieldValue[j] = convertToAngularModel(schemaEntry.schema, fieldValue[j], 1 + fieldName.length, $scope, fieldName, master, j);
|
|
2724
3058
|
}
|
|
2725
3059
|
}
|
|
2726
3060
|
}
|
|
2727
3061
|
else {
|
|
2728
|
-
if (schemaEntry.
|
|
2729
|
-
setUpInternalLookupLists($scope, schemaEntry.options, schemaEntry.ids, master[schemaEntry.
|
|
3062
|
+
if (schemaEntry.internalRef) {
|
|
3063
|
+
setUpInternalLookupLists($scope, schemaEntry.options, schemaEntry.ids, master[schemaEntry.internalRef.property], schemaEntry.internalRef.value);
|
|
2730
3064
|
}
|
|
2731
3065
|
// Convert {array:['item 1']} to {array:[{x:'item 1'}]}
|
|
2732
|
-
var thisField = getListData(
|
|
2733
|
-
if (schemaEntry.array &&
|
|
3066
|
+
var thisField = getListData(anObject, fieldName, null, $scope);
|
|
3067
|
+
if (schemaEntry.array &&
|
|
3068
|
+
simpleArrayNeedsX(schemaEntry) &&
|
|
3069
|
+
thisField &&
|
|
3070
|
+
!(thisField.length > 0 && thisField[0].x) // Don't keep on coverting
|
|
3071
|
+
) {
|
|
2734
3072
|
for (var k = 0; k < thisField.length; k++) {
|
|
2735
3073
|
thisField[k] = { x: thisField[k] };
|
|
2736
3074
|
}
|
|
2737
3075
|
}
|
|
2738
3076
|
// Convert {lookup:'012abcde'} to {lookup:'List description for 012abcde'}
|
|
2739
|
-
var idList = $scope[suffixCleanId(schemaEntry,
|
|
3077
|
+
var idList = $scope[suffixCleanId(schemaEntry, "_ids")];
|
|
2740
3078
|
var thisConversion = void 0;
|
|
2741
3079
|
if (fieldValue && idList && idList.length > 0) {
|
|
2742
|
-
if (fieldName.indexOf(
|
|
2743
|
-
throw new Error(
|
|
3080
|
+
if (fieldName.indexOf(".") !== -1) {
|
|
3081
|
+
throw new Error("Trying to directly assign to a nested field 332");
|
|
2744
3082
|
} // Not sure that this can happen, but put in a runtime test
|
|
2745
|
-
|
|
3083
|
+
if (
|
|
3084
|
+
/*
|
|
3085
|
+
Check we are starting with an ObjectId (ie not being called because of $watch on conversion, with a
|
|
3086
|
+
converted value, which would cause an exception)
|
|
3087
|
+
*/
|
|
3088
|
+
fieldValue.toString().match(/^[a-f0-9]{24}$/) &&
|
|
3089
|
+
/*
|
|
3090
|
+
We are not suppressing conversions
|
|
3091
|
+
*/
|
|
3092
|
+
(!schemaEntry.internalRef || !schemaEntry.internalRef.noConvert)) {
|
|
3093
|
+
anObject[fieldName] = convertForeignKeys(schemaEntry, fieldValue, $scope[suffixCleanId(schemaEntry, "Options")], idList);
|
|
3094
|
+
}
|
|
2746
3095
|
}
|
|
2747
3096
|
else if (schemaEntry.select2) {
|
|
2748
3097
|
// Do nothing with these - handled elsewhere (and deprecated)
|
|
2749
|
-
console.log(
|
|
3098
|
+
console.log("fng-select2 is deprecated - use fng-ui-select instead");
|
|
2750
3099
|
void (schemaEntry.select2);
|
|
2751
3100
|
}
|
|
2752
3101
|
else if (fieldValue && (thisConversion = getConversionObject($scope, fieldName, schemaName)) &&
|
|
@@ -2755,7 +3104,7 @@ var fng;
|
|
|
2755
3104
|
thisConversion.fngajax(fieldValue, schemaEntry, function (updateEntry, value) {
|
|
2756
3105
|
// Update the master and (preserving pristine if appropriate) the record
|
|
2757
3106
|
setData(master, updateEntry.name, offset, value);
|
|
2758
|
-
preservePristine(angular.element(
|
|
3107
|
+
preservePristine(angular.element("#" + updateEntry.id), function () {
|
|
2759
3108
|
setData($scope.record, updateEntry.name, offset, value);
|
|
2760
3109
|
});
|
|
2761
3110
|
});
|
|
@@ -2768,9 +3117,9 @@ var fng;
|
|
|
2768
3117
|
// Called when the model is read and when the lookups are read
|
|
2769
3118
|
// No support for nested schemas here as it is called from convertToAngularModel which does that
|
|
2770
3119
|
function convertForeignKeys(schemaElement, input, values, ids) {
|
|
2771
|
-
if (schemaElement.array) {
|
|
3120
|
+
if (schemaElement.array || angular.isArray(input)) {
|
|
2772
3121
|
var returnArray = [];
|
|
2773
|
-
var needsX = !schemaElement.directive || simpleArrayNeedsX(schemaElement);
|
|
3122
|
+
var needsX = schemaElement.array && (!schemaElement.directive || simpleArrayNeedsX(schemaElement));
|
|
2774
3123
|
for (var j = 0; j < input.length; j++) {
|
|
2775
3124
|
var val = input[j];
|
|
2776
3125
|
if (val && val.x) {
|
|
@@ -2814,7 +3163,7 @@ var fng;
|
|
|
2814
3163
|
else {
|
|
2815
3164
|
var index = valuesArray.indexOf(textToConvert);
|
|
2816
3165
|
if (index === -1) {
|
|
2817
|
-
throw new Error(
|
|
3166
|
+
throw new Error("convertListValueToId: Invalid data - value " + textToConvert + " not found in " + valuesArray + " processing " + fname);
|
|
2818
3167
|
}
|
|
2819
3168
|
return idsArray[index];
|
|
2820
3169
|
}
|
|
@@ -2822,7 +3171,7 @@ var fng;
|
|
|
2822
3171
|
var preservePristine = function preservePristine(element, fn) {
|
|
2823
3172
|
// stop the form being set to dirty when a fn is called
|
|
2824
3173
|
// Use when the record (and master) need to be updated by lookup values displayed asynchronously
|
|
2825
|
-
var modelController = element.inheritedData(
|
|
3174
|
+
var modelController = element.inheritedData("$ngModelController");
|
|
2826
3175
|
var isClean = (modelController && modelController.$pristine);
|
|
2827
3176
|
if (isClean) {
|
|
2828
3177
|
// fake it to dirty here and reset after call to fn
|
|
@@ -2834,18 +3183,21 @@ var fng;
|
|
|
2834
3183
|
}
|
|
2835
3184
|
};
|
|
2836
3185
|
var convertIdToListValue = function convertIdToListValue(id, idsArray, valuesArray, fname) {
|
|
2837
|
-
if (typeof (id) ===
|
|
3186
|
+
if (typeof (id) === "object") {
|
|
2838
3187
|
id = id.id;
|
|
2839
3188
|
}
|
|
2840
3189
|
var index = idsArray.indexOf(id);
|
|
2841
3190
|
if (index === -1) {
|
|
2842
|
-
|
|
3191
|
+
index = valuesArray.indexOf(id); // This can get called twice - second time with converted value (not sure how atm) so protect against that...
|
|
3192
|
+
if (index === -1) {
|
|
3193
|
+
throw new Error("convertIdToListValue: Invalid data - id " + id + " not found in " + idsArray + " processing " + fname);
|
|
3194
|
+
}
|
|
2843
3195
|
}
|
|
2844
3196
|
return valuesArray[index];
|
|
2845
3197
|
};
|
|
2846
3198
|
var processServerData = function processServerData(recordFromServer, $scope, ctrlState) {
|
|
2847
3199
|
ctrlState.master = convertToAngularModel($scope.formSchema, recordFromServer, 0, $scope);
|
|
2848
|
-
$scope.phase =
|
|
3200
|
+
$scope.phase = "ready";
|
|
2849
3201
|
$scope.cancel();
|
|
2850
3202
|
};
|
|
2851
3203
|
function convertOldToNew(ref, val, attrib, newVals, oldVals) {
|
|
@@ -2864,102 +3216,123 @@ var fng;
|
|
|
2864
3216
|
var listOnly = (!$scope.id && !$scope.newRecord);
|
|
2865
3217
|
// passing null for formSchema parameter prevents all the work being done when we are just after the list data,
|
|
2866
3218
|
// but should be removed when/if formschemas are cached
|
|
2867
|
-
formGeneratorInstance.handleSchema(
|
|
3219
|
+
formGeneratorInstance.handleSchema("Main " + $scope.modelName, schema, listOnly ? null : $scope.formSchema, $scope.listSchema, "", true, $scope, ctrlState);
|
|
3220
|
+
function processLookupHandlers(newValue, oldValue) {
|
|
3221
|
+
// If we have any internal lookups then update the references
|
|
3222
|
+
$scope.internalLookups.forEach(function (lkp) {
|
|
3223
|
+
var newVal = newValue[lkp.ref.property];
|
|
3224
|
+
var oldVal = oldValue[lkp.ref.property];
|
|
3225
|
+
setUpInternalLookupLists($scope, lkp.lookupOptions, lkp.lookupIds, newVal, lkp.ref.value);
|
|
3226
|
+
// now change the looked-up values that matched the old to the new
|
|
3227
|
+
if ((newVal && newVal.length > 0) || (oldVal && oldVal.length > 0)) {
|
|
3228
|
+
lkp.handlers.forEach(function (h) {
|
|
3229
|
+
if (h.possibleArray) {
|
|
3230
|
+
var arr = getData($scope.record, h.possibleArray, null);
|
|
3231
|
+
if (arr && arr.length > 0) {
|
|
3232
|
+
arr.forEach(function (a) { return convertOldToNew(lkp.ref, a, h.lastPart, newVal, oldVal); });
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
else if (angular.isArray($scope.record[h.lastPart])) {
|
|
3236
|
+
$scope.record[h.lastPart].forEach(function (a) {
|
|
3237
|
+
convertOldToNew(lkp.ref, a, "x", newVal, oldVal);
|
|
3238
|
+
});
|
|
3239
|
+
}
|
|
3240
|
+
else {
|
|
3241
|
+
convertOldToNew(lkp.ref, $scope.record, h.lastPart, newVal, oldVal);
|
|
3242
|
+
}
|
|
3243
|
+
});
|
|
3244
|
+
}
|
|
3245
|
+
});
|
|
3246
|
+
// If we have any list lookups then update the references
|
|
3247
|
+
$scope.listLookups.forEach(function (lkp) {
|
|
3248
|
+
function extractIdVal(obj, idString) {
|
|
3249
|
+
var retVal = obj[idString];
|
|
3250
|
+
if (retVal && retVal.id) {
|
|
3251
|
+
retVal = retVal.id;
|
|
3252
|
+
}
|
|
3253
|
+
return retVal;
|
|
3254
|
+
}
|
|
3255
|
+
function blankListLookup(inst) {
|
|
3256
|
+
setData($scope.record, inst.name);
|
|
3257
|
+
}
|
|
3258
|
+
var idString = lkp.ref.id.slice(1);
|
|
3259
|
+
if (idString.includes(".")) {
|
|
3260
|
+
throw new Error("No support for nested list lookups yet - ".concat(JSON.stringify(lkp.ref)));
|
|
3261
|
+
}
|
|
3262
|
+
var newVal = extractIdVal(newValue, idString);
|
|
3263
|
+
var oldVal = extractIdVal(oldValue, idString);
|
|
3264
|
+
if (newVal !== oldVal) {
|
|
3265
|
+
lkp.handlers.forEach(function (h) {
|
|
3266
|
+
$scope[h.formInstructions.options].length = 0;
|
|
3267
|
+
$scope[h.formInstructions.ids].length = 0;
|
|
3268
|
+
});
|
|
3269
|
+
if (newVal) {
|
|
3270
|
+
SubmissionsService.readRecord(lkp.ref.collection, newVal).then(function (response) {
|
|
3271
|
+
lkp.handlers.forEach(function (h) {
|
|
3272
|
+
var optionsList = $scope[h.formInstructions.options];
|
|
3273
|
+
var idList = $scope[h.formInstructions.ids];
|
|
3274
|
+
var data = response.data[lkp.ref.property] || [];
|
|
3275
|
+
for (var i = 0; i < data.length; i++) {
|
|
3276
|
+
var option = data[i][lkp.ref.value];
|
|
3277
|
+
var pos = _.sortedIndex(optionsList, option);
|
|
3278
|
+
// handle dupes
|
|
3279
|
+
if (optionsList[pos] === option) {
|
|
3280
|
+
option = option + " (" + data[i]._id + ")";
|
|
3281
|
+
pos = _.sortedIndex(optionsList, option);
|
|
3282
|
+
}
|
|
3283
|
+
optionsList.splice(pos, 0, option);
|
|
3284
|
+
idList.splice(pos, 0, data[i]._id);
|
|
3285
|
+
}
|
|
3286
|
+
if (Object.keys(oldValue).length === 0) {
|
|
3287
|
+
// Not sure how safe this is, but the record is fresh so I think it's OK...
|
|
3288
|
+
updateRecordWithLookupValues(h.formInstructions, $scope, ctrlState, true);
|
|
3289
|
+
}
|
|
3290
|
+
else {
|
|
3291
|
+
// Here we are reacting to a change in the lookup pointer in the record.
|
|
3292
|
+
// We need to blank our lookup field as it will not exist
|
|
3293
|
+
blankListLookup(h.formInstructions);
|
|
3294
|
+
}
|
|
3295
|
+
});
|
|
3296
|
+
});
|
|
3297
|
+
}
|
|
3298
|
+
else {
|
|
3299
|
+
lkp.handlers.forEach(function (h) {
|
|
3300
|
+
blankListLookup(h.formInstructions);
|
|
3301
|
+
});
|
|
3302
|
+
}
|
|
3303
|
+
}
|
|
3304
|
+
});
|
|
3305
|
+
}
|
|
3306
|
+
function notifyReady() {
|
|
3307
|
+
$scope.phase = "ready";
|
|
3308
|
+
$scope.cancel();
|
|
3309
|
+
processLookupHandlers($scope.record, {});
|
|
3310
|
+
}
|
|
2868
3311
|
if (listOnly) {
|
|
2869
3312
|
ctrlState.allowLocationChange = true;
|
|
2870
3313
|
}
|
|
2871
3314
|
else {
|
|
2872
3315
|
var force = true;
|
|
2873
3316
|
if (!$scope.newRecord) {
|
|
2874
|
-
$scope.dropConversionWatcher = $scope.$watchCollection(
|
|
3317
|
+
$scope.dropConversionWatcher = $scope.$watchCollection("conversions", function (newValue, oldValue) {
|
|
2875
3318
|
if (newValue !== oldValue && $scope.originalData) {
|
|
2876
3319
|
processServerData($scope.originalData, $scope, ctrlState);
|
|
2877
3320
|
}
|
|
2878
3321
|
});
|
|
2879
3322
|
}
|
|
2880
|
-
$scope.$watch(
|
|
3323
|
+
$scope.$watch("record", function (newValue, oldValue) {
|
|
2881
3324
|
if (newValue !== oldValue) {
|
|
2882
3325
|
if (Object.keys(oldValue).length > 0 && $scope.dropConversionWatcher) {
|
|
2883
3326
|
$scope.dropConversionWatcher(); // Don't want to convert changed data
|
|
2884
3327
|
$scope.dropConversionWatcher = null;
|
|
2885
3328
|
}
|
|
2886
3329
|
force = formGeneratorInstance.updateDataDependentDisplay(newValue, oldValue, force, $scope);
|
|
2887
|
-
|
|
2888
|
-
$scope.internalLookups.forEach(function (lkp) {
|
|
2889
|
-
var newVal = newValue[lkp.ref.property];
|
|
2890
|
-
var oldVal = oldValue[lkp.ref.property];
|
|
2891
|
-
setUpInternalLookupLists($scope, lkp.lookupOptions, lkp.lookupIds, newVal, lkp.ref.value);
|
|
2892
|
-
// now change the looked-up values that matched the old to the new
|
|
2893
|
-
if ((newVal && newVal.length > 0) || (oldVal && oldVal.length > 0)) {
|
|
2894
|
-
lkp.handlers.forEach(function (h) {
|
|
2895
|
-
if (h.possibleArray) {
|
|
2896
|
-
var arr = getData($scope.record, h.possibleArray, null);
|
|
2897
|
-
if (arr && arr.length > 0) {
|
|
2898
|
-
arr.forEach(function (a) { return convertOldToNew(lkp.ref, a, h.lastPart, newVal, oldVal); });
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2901
|
-
else if (angular.isArray($scope.record[h.lastPart])) {
|
|
2902
|
-
$scope.record[h.lastPart].forEach(function (a) {
|
|
2903
|
-
convertOldToNew(lkp.ref, a, 'x', newVal, oldVal);
|
|
2904
|
-
});
|
|
2905
|
-
}
|
|
2906
|
-
else {
|
|
2907
|
-
convertOldToNew(lkp.ref, $scope.record, h.lastPart, newVal, oldVal);
|
|
2908
|
-
}
|
|
2909
|
-
});
|
|
2910
|
-
}
|
|
2911
|
-
});
|
|
2912
|
-
// If we have any list lookups then update the references
|
|
2913
|
-
$scope.listLookups.forEach(function (lkp) {
|
|
2914
|
-
function extractIdVal(obj, idString) {
|
|
2915
|
-
var retVal = obj[idString];
|
|
2916
|
-
if (retVal && retVal.id) {
|
|
2917
|
-
retVal = retVal.id;
|
|
2918
|
-
}
|
|
2919
|
-
return retVal;
|
|
2920
|
-
}
|
|
2921
|
-
var idString = lkp.ref.id.slice(1);
|
|
2922
|
-
if (idString.includes('.')) {
|
|
2923
|
-
throw new Error("No support for nested list lookups yet - " + JSON.stringify(lkp.ref));
|
|
2924
|
-
}
|
|
2925
|
-
var newVal = extractIdVal(newValue, idString);
|
|
2926
|
-
var oldVal = extractIdVal(oldValue, idString);
|
|
2927
|
-
if (newVal !== oldVal) {
|
|
2928
|
-
if (newVal) {
|
|
2929
|
-
SubmissionsService.readRecord(lkp.ref.collection, newVal).then(function (response) {
|
|
2930
|
-
lkp.handlers.forEach(function (h) {
|
|
2931
|
-
var optionsList = $scope[h.formInstructions.options];
|
|
2932
|
-
var idList = $scope[h.formInstructions.ids];
|
|
2933
|
-
var data = response.data[lkp.ref.property];
|
|
2934
|
-
for (var i = 0; i < data.length; i++) {
|
|
2935
|
-
var option = data[i][lkp.ref.value];
|
|
2936
|
-
var pos = _.sortedIndex(optionsList, option);
|
|
2937
|
-
// handle dupes
|
|
2938
|
-
if (optionsList[pos] === option) {
|
|
2939
|
-
option = option + ' (' + data[i]._id + ')';
|
|
2940
|
-
pos = _.sortedIndex(optionsList, option);
|
|
2941
|
-
}
|
|
2942
|
-
optionsList.splice(pos, 0, option);
|
|
2943
|
-
idList.splice(pos, 0, data[i]._id);
|
|
2944
|
-
}
|
|
2945
|
-
updateRecordWithLookupValues(h.formInstructions, $scope, ctrlState);
|
|
2946
|
-
});
|
|
2947
|
-
});
|
|
2948
|
-
}
|
|
2949
|
-
else {
|
|
2950
|
-
lkp.handlers.forEach(function (h) {
|
|
2951
|
-
$scope[h.formInstructions.options].length = 0;
|
|
2952
|
-
$scope[h.formInstructions.ids].length = 0;
|
|
2953
|
-
updateRecordWithLookupValues(h.formInstructions, $scope, ctrlState);
|
|
2954
|
-
});
|
|
2955
|
-
}
|
|
2956
|
-
}
|
|
2957
|
-
});
|
|
3330
|
+
processLookupHandlers(newValue, oldValue);
|
|
2958
3331
|
}
|
|
2959
3332
|
}, true);
|
|
2960
3333
|
if ($scope.id) {
|
|
2961
3334
|
// Going to read a record
|
|
2962
|
-
if (typeof $scope.dataEventFunctions.onBeforeRead ===
|
|
3335
|
+
if (typeof $scope.dataEventFunctions.onBeforeRead === "function") {
|
|
2963
3336
|
$scope.dataEventFunctions.onBeforeRead($scope.id, function (err) {
|
|
2964
3337
|
if (err) {
|
|
2965
3338
|
$scope.showError(err);
|
|
@@ -2975,99 +3348,125 @@ var fng;
|
|
|
2975
3348
|
}
|
|
2976
3349
|
else {
|
|
2977
3350
|
// New record
|
|
2978
|
-
ctrlState.
|
|
3351
|
+
ctrlState.allowLocationChange = false;
|
|
3352
|
+
ctrlState.master = $scope.setDefaults($scope.formSchema);
|
|
2979
3353
|
var passedRecord = $scope.initialiseNewRecord || $location.$$search.r;
|
|
2980
3354
|
if (passedRecord) {
|
|
2981
3355
|
try {
|
|
2982
|
-
ctrlState.master
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
$scope[$scope.topLevelFormName]
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3356
|
+
Object.assign(ctrlState.master, JSON.parse(passedRecord));
|
|
3357
|
+
if (!$scope["newRecordsStartPristine"]) {
|
|
3358
|
+
// Although this is a new record we are making it dirty from the url so we need to $setDirty
|
|
3359
|
+
$scope.$on("fngCancel", function () {
|
|
3360
|
+
$timeout(function () {
|
|
3361
|
+
if ($scope[$scope.topLevelFormName]) {
|
|
3362
|
+
$scope[$scope.topLevelFormName].$setDirty();
|
|
3363
|
+
}
|
|
3364
|
+
}, 1000); // Has to fire after the setPristime timeout.
|
|
3365
|
+
});
|
|
3366
|
+
}
|
|
2991
3367
|
}
|
|
2992
3368
|
catch (e) {
|
|
2993
|
-
console.log(
|
|
3369
|
+
console.log("Error parsing specified record : " + e.message);
|
|
2994
3370
|
}
|
|
2995
3371
|
}
|
|
2996
|
-
if (typeof $scope.dataEventFunctions.onInitialiseNewRecord ===
|
|
3372
|
+
if (typeof $scope.dataEventFunctions.onInitialiseNewRecord === "function") {
|
|
3373
|
+
console.log("onInitialiseNewRecord is deprecated - use the async version - onNewRecordInit(data,cb)");
|
|
2997
3374
|
$scope.dataEventFunctions.onInitialiseNewRecord(ctrlState.master);
|
|
2998
3375
|
}
|
|
2999
|
-
$scope.
|
|
3000
|
-
|
|
3376
|
+
if (typeof $scope.dataEventFunctions.onNewRecordInit === "function") {
|
|
3377
|
+
$scope.dataEventFunctions.onNewRecordInit(ctrlState.master, function (err) {
|
|
3378
|
+
if (err) {
|
|
3379
|
+
$scope.showError(err);
|
|
3380
|
+
}
|
|
3381
|
+
else {
|
|
3382
|
+
notifyReady();
|
|
3383
|
+
}
|
|
3384
|
+
});
|
|
3385
|
+
}
|
|
3386
|
+
else {
|
|
3387
|
+
notifyReady();
|
|
3388
|
+
}
|
|
3001
3389
|
}
|
|
3002
3390
|
}
|
|
3003
3391
|
}
|
|
3004
3392
|
function handleError($scope) {
|
|
3005
3393
|
return function (response) {
|
|
3006
3394
|
if ([200, 400].indexOf(response.status) !== -1) {
|
|
3007
|
-
var errorMessage =
|
|
3395
|
+
var errorMessage = "";
|
|
3008
3396
|
for (var errorField in response.data.errors) {
|
|
3009
3397
|
if (response.data.errors.hasOwnProperty(errorField)) {
|
|
3010
|
-
errorMessage +=
|
|
3398
|
+
errorMessage += "<li><b>" + $filter("titleCase")(errorField) + ": </b> ";
|
|
3011
3399
|
switch (response.data.errors[errorField].type) {
|
|
3012
|
-
case
|
|
3013
|
-
errorMessage +=
|
|
3400
|
+
case "enum":
|
|
3401
|
+
errorMessage += "You need to select from the list of values";
|
|
3014
3402
|
break;
|
|
3015
3403
|
default:
|
|
3016
3404
|
errorMessage += response.data.errors[errorField].message;
|
|
3017
3405
|
break;
|
|
3018
3406
|
}
|
|
3019
|
-
errorMessage +=
|
|
3407
|
+
errorMessage += "</li>";
|
|
3020
3408
|
}
|
|
3021
3409
|
}
|
|
3022
3410
|
if (errorMessage.length > 0) {
|
|
3023
|
-
errorMessage = response.data.message +
|
|
3411
|
+
errorMessage = (response.data.message || response.data._message) + "<br /><ul>" + errorMessage + "</ul>";
|
|
3024
3412
|
}
|
|
3025
3413
|
else {
|
|
3026
|
-
errorMessage = response.data.message ||
|
|
3414
|
+
errorMessage = response.data.message || response.data._message || response.data.err || "Error! Sorry - No further details available.";
|
|
3027
3415
|
}
|
|
3028
3416
|
$scope.showError(errorMessage);
|
|
3029
3417
|
}
|
|
3030
3418
|
else {
|
|
3031
|
-
$scope.showError(response.status +
|
|
3419
|
+
$scope.showError(response.status + " " + JSON.stringify(response.data));
|
|
3032
3420
|
}
|
|
3033
3421
|
};
|
|
3034
3422
|
}
|
|
3035
3423
|
function handleIncomingData(data, $scope, ctrlState) {
|
|
3036
3424
|
ctrlState.allowLocationChange = false;
|
|
3037
|
-
$scope.phase =
|
|
3038
|
-
if (typeof $scope.dataEventFunctions.onAfterRead ===
|
|
3425
|
+
$scope.phase = "reading";
|
|
3426
|
+
if (typeof $scope.dataEventFunctions.onAfterRead === "function") {
|
|
3039
3427
|
$scope.dataEventFunctions.onAfterRead(data);
|
|
3040
3428
|
}
|
|
3041
3429
|
$scope.originalData = data;
|
|
3042
3430
|
processServerData(data, $scope, ctrlState);
|
|
3043
3431
|
}
|
|
3432
|
+
function addArrayLookupToLookupList($scope, formInstructions, ref, lookups) {
|
|
3433
|
+
var nameElements = formInstructions.name.split(".");
|
|
3434
|
+
var refHandler = lookups.find(function (lkp) {
|
|
3435
|
+
return lkp.ref.property === ref.property && lkp.ref.value === ref.value;
|
|
3436
|
+
});
|
|
3437
|
+
var thisHandler = {
|
|
3438
|
+
formInstructions: formInstructions,
|
|
3439
|
+
lastPart: nameElements.pop(),
|
|
3440
|
+
possibleArray: nameElements.join(".")
|
|
3441
|
+
};
|
|
3442
|
+
if (!refHandler) {
|
|
3443
|
+
refHandler = {
|
|
3444
|
+
ref: ref,
|
|
3445
|
+
lookupOptions: [],
|
|
3446
|
+
lookupIds: [],
|
|
3447
|
+
handlers: []
|
|
3448
|
+
};
|
|
3449
|
+
lookups.push(refHandler);
|
|
3450
|
+
}
|
|
3451
|
+
refHandler.handlers.push(thisHandler);
|
|
3452
|
+
$scope[formInstructions.options] = refHandler.lookupOptions;
|
|
3453
|
+
$scope[formInstructions.ids] = refHandler.lookupIds;
|
|
3454
|
+
}
|
|
3044
3455
|
return {
|
|
3045
3456
|
readRecord: function readRecord($scope, ctrlState) {
|
|
3046
|
-
|
|
3047
|
-
|
|
3457
|
+
$scope.readingRecord = SubmissionsService.readRecord($scope.modelName, $scope.id);
|
|
3458
|
+
$scope.readingRecord
|
|
3048
3459
|
.then(function (response) {
|
|
3049
|
-
var data = response.data;
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
//
|
|
3055
|
-
// ctrlState.allowLocationChange = false;
|
|
3056
|
-
// $scope.phase = 'ready';
|
|
3057
|
-
// $scope.record = angular.copy(response.data);
|
|
3058
|
-
// ctrlState.master = angular.copy(response.master);
|
|
3059
|
-
// if (response.changed) {
|
|
3060
|
-
// $timeout(() => {
|
|
3061
|
-
// $scope[$scope.topLevelFormName].$setDirty();
|
|
3062
|
-
// });
|
|
3063
|
-
// } else {
|
|
3064
|
-
// $timeout($scope.setPristine);
|
|
3065
|
-
// }
|
|
3460
|
+
var data = angular.copy(response.data);
|
|
3461
|
+
handleIncomingData(data, $scope, ctrlState);
|
|
3462
|
+
}, function (error) {
|
|
3463
|
+
if (error.status === 404) {
|
|
3464
|
+
$location.path("/404");
|
|
3066
3465
|
}
|
|
3067
3466
|
else {
|
|
3068
|
-
|
|
3467
|
+
$scope.handleHttpError(error);
|
|
3069
3468
|
}
|
|
3070
|
-
}
|
|
3469
|
+
});
|
|
3071
3470
|
},
|
|
3072
3471
|
scrollTheList: function scrollTheList($scope) {
|
|
3073
3472
|
var pagesLoaded = $scope.pagesLoaded;
|
|
@@ -3087,31 +3486,38 @@ var fng;
|
|
|
3087
3486
|
$scope.recordList = $scope.recordList.concat(data);
|
|
3088
3487
|
}
|
|
3089
3488
|
else {
|
|
3090
|
-
console.log(
|
|
3489
|
+
console.log("DEBUG: infinite scroll component asked for a page twice - the model was " + $scope.modelName);
|
|
3091
3490
|
}
|
|
3092
3491
|
}
|
|
3093
3492
|
else {
|
|
3094
|
-
$scope.showError(data,
|
|
3493
|
+
$scope.showError(data, "Invalid query");
|
|
3095
3494
|
}
|
|
3096
3495
|
}, $scope.handleHttpError);
|
|
3097
3496
|
},
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
SubmissionsService.deleteRecord(model, id)
|
|
3497
|
+
deleteRecord: function deleteRecord(id, $scope, ctrlState) {
|
|
3498
|
+
SubmissionsService.deleteRecord($scope.modelName, id)
|
|
3101
3499
|
.then(function () {
|
|
3102
|
-
if (typeof $scope.dataEventFunctions.onAfterDelete ===
|
|
3500
|
+
if (typeof $scope.dataEventFunctions.onAfterDelete === "function") {
|
|
3103
3501
|
$scope.dataEventFunctions.onAfterDelete(ctrlState.master);
|
|
3104
3502
|
}
|
|
3105
|
-
routingService.redirectTo()(
|
|
3503
|
+
routingService.redirectTo()("onDelete", $scope, $location);
|
|
3504
|
+
}, function (err) {
|
|
3505
|
+
if (err.status === 404) {
|
|
3506
|
+
// Someone already deleted it
|
|
3507
|
+
routingService.redirectTo()("onDelete", $scope, $location);
|
|
3508
|
+
}
|
|
3509
|
+
else {
|
|
3510
|
+
$scope.showError("".concat(err.statusText, " (").concat(err.status, ") while deleting record<br />").concat(err.data), 'Error deleting record');
|
|
3511
|
+
}
|
|
3106
3512
|
});
|
|
3107
3513
|
},
|
|
3108
3514
|
updateDocument: function updateDocument(dataToSave, options, $scope, ctrlState) {
|
|
3109
|
-
$scope.phase =
|
|
3515
|
+
$scope.phase = "updating";
|
|
3110
3516
|
SubmissionsService.updateRecord($scope.modelName, $scope.id, dataToSave)
|
|
3111
3517
|
.then(function (response) {
|
|
3112
3518
|
var data = response.data;
|
|
3113
3519
|
if (data.success !== false) {
|
|
3114
|
-
if (typeof $scope.dataEventFunctions.onAfterUpdate ===
|
|
3520
|
+
if (typeof $scope.dataEventFunctions.onAfterUpdate === "function") {
|
|
3115
3521
|
$scope.dataEventFunctions.onAfterUpdate(data, ctrlState.master);
|
|
3116
3522
|
}
|
|
3117
3523
|
if (options.redirect) {
|
|
@@ -3130,19 +3536,20 @@ var fng;
|
|
|
3130
3536
|
}
|
|
3131
3537
|
}, $scope.handleHttpError);
|
|
3132
3538
|
},
|
|
3133
|
-
createNew: function createNew(dataToSave, options, $scope) {
|
|
3539
|
+
createNew: function createNew(dataToSave, options, $scope, ctrlState) {
|
|
3134
3540
|
SubmissionsService.createRecord($scope.modelName, dataToSave)
|
|
3135
3541
|
.then(function (response) {
|
|
3136
3542
|
var data = response.data;
|
|
3137
3543
|
if (data.success !== false) {
|
|
3138
|
-
|
|
3544
|
+
ctrlState.allowLocationChange = true;
|
|
3545
|
+
if (typeof $scope.dataEventFunctions.onAfterCreate === "function") {
|
|
3139
3546
|
$scope.dataEventFunctions.onAfterCreate(data);
|
|
3140
3547
|
}
|
|
3141
3548
|
if (options.redirect) {
|
|
3142
3549
|
$window.location = options.redirect;
|
|
3143
3550
|
}
|
|
3144
3551
|
else {
|
|
3145
|
-
routingService.redirectTo()(
|
|
3552
|
+
routingService.redirectTo()("edit", $scope, $location, data._id);
|
|
3146
3553
|
}
|
|
3147
3554
|
}
|
|
3148
3555
|
else {
|
|
@@ -3160,9 +3567,9 @@ var fng;
|
|
|
3160
3567
|
.then(function (response) {
|
|
3161
3568
|
var data = response.data;
|
|
3162
3569
|
var listInstructions = [];
|
|
3163
|
-
handleSchema(
|
|
3570
|
+
handleSchema("Lookup " + lookupCollection, data, null, listInstructions, "", false, $scope, ctrlState);
|
|
3164
3571
|
var dataRequest;
|
|
3165
|
-
if (typeof schemaElement.filter !==
|
|
3572
|
+
if (typeof schemaElement.filter !== "undefined" && schemaElement.filter) {
|
|
3166
3573
|
dataRequest = SubmissionsService.getPagedAndFilteredList(lookupCollection, schemaElement.filter);
|
|
3167
3574
|
}
|
|
3168
3575
|
else {
|
|
@@ -3170,25 +3577,30 @@ var fng;
|
|
|
3170
3577
|
}
|
|
3171
3578
|
dataRequest
|
|
3172
3579
|
.then(function (response) {
|
|
3173
|
-
var data = response.data;
|
|
3580
|
+
var data = angular.copy(response.data);
|
|
3174
3581
|
if (data) {
|
|
3175
3582
|
for (var i = 0; i < data.length; i++) {
|
|
3176
|
-
var option =
|
|
3583
|
+
var option = "";
|
|
3177
3584
|
for (var j = 0; j < listInstructions.length; j++) {
|
|
3178
3585
|
var thisVal = data[i][listInstructions[j].name];
|
|
3179
|
-
option += thisVal ? thisVal +
|
|
3586
|
+
option += thisVal ? thisVal + " " : "";
|
|
3180
3587
|
}
|
|
3181
3588
|
option = option.trim();
|
|
3182
3589
|
var pos = _.sortedIndex(optionsList, option);
|
|
3183
3590
|
// handle dupes (ideally people will use unique indexes to stop them but...)
|
|
3184
3591
|
if (optionsList[pos] === option) {
|
|
3185
|
-
option = option +
|
|
3592
|
+
option = option + " (" + data[i]._id + ")";
|
|
3186
3593
|
pos = _.sortedIndex(optionsList, option);
|
|
3187
3594
|
}
|
|
3188
3595
|
optionsList.splice(pos, 0, option);
|
|
3189
3596
|
idList.splice(pos, 0, data[i]._id);
|
|
3190
3597
|
}
|
|
3191
|
-
|
|
3598
|
+
if ($scope.readingRecord) {
|
|
3599
|
+
$scope.readingRecord
|
|
3600
|
+
.then(function () {
|
|
3601
|
+
updateRecordWithLookupValues(schemaElement, $scope, ctrlState);
|
|
3602
|
+
});
|
|
3603
|
+
}
|
|
3192
3604
|
}
|
|
3193
3605
|
});
|
|
3194
3606
|
});
|
|
@@ -3196,31 +3608,9 @@ var fng;
|
|
|
3196
3608
|
setUpLookupListOptions: function setUpLookupListOptions(ref, formInstructions, $scope, ctrlState) {
|
|
3197
3609
|
var optionsList = $scope[formInstructions.options] = [];
|
|
3198
3610
|
var idList = $scope[formInstructions.ids] = [];
|
|
3199
|
-
if (ref.id[0] ===
|
|
3200
|
-
// id of document
|
|
3201
|
-
|
|
3202
|
-
var nameElements = formInstructions.name.split('.');
|
|
3203
|
-
var refHandler = $scope.listLookups.find(function (lkp) {
|
|
3204
|
-
return lkp.ref.property === ref.property && lkp.ref.value === ref.value;
|
|
3205
|
-
});
|
|
3206
|
-
var thisHandler = {
|
|
3207
|
-
formInstructions: formInstructions,
|
|
3208
|
-
lastPart: nameElements.pop(),
|
|
3209
|
-
possibleArray: nameElements.join('.')
|
|
3210
|
-
};
|
|
3211
|
-
if (!refHandler) {
|
|
3212
|
-
refHandler = {
|
|
3213
|
-
ref: ref,
|
|
3214
|
-
lookupOptions: [],
|
|
3215
|
-
lookupIds: [],
|
|
3216
|
-
handlers: []
|
|
3217
|
-
};
|
|
3218
|
-
$scope.listLookups.push(refHandler);
|
|
3219
|
-
}
|
|
3220
|
-
refHandler.handlers.push(thisHandler);
|
|
3221
|
-
$scope[formInstructions.options] = refHandler.lookupOptions;
|
|
3222
|
-
$scope[formInstructions.ids] = refHandler.lookupIds;
|
|
3223
|
-
// TODO DRY this and handleInternalLookup below
|
|
3611
|
+
if (ref.id[0] === "$") {
|
|
3612
|
+
// id of document that contains out lookup list comes from record, so we need to deal with in $watch by adding it to listLookups
|
|
3613
|
+
addArrayLookupToLookupList($scope, formInstructions, ref, $scope.listLookups);
|
|
3224
3614
|
}
|
|
3225
3615
|
else {
|
|
3226
3616
|
// we can do it now
|
|
@@ -3231,7 +3621,7 @@ var fng;
|
|
|
3231
3621
|
var pos = _.sortedIndex(optionsList, option);
|
|
3232
3622
|
// handle dupes
|
|
3233
3623
|
if (optionsList[pos] === option) {
|
|
3234
|
-
option = option +
|
|
3624
|
+
option = option + " (" + data[i]._id + ")";
|
|
3235
3625
|
pos = _.sortedIndex(optionsList, option);
|
|
3236
3626
|
}
|
|
3237
3627
|
optionsList.splice(pos, 0, option);
|
|
@@ -3242,27 +3632,7 @@ var fng;
|
|
|
3242
3632
|
}
|
|
3243
3633
|
},
|
|
3244
3634
|
handleInternalLookup: function handleInternalLookup($scope, formInstructions, ref) {
|
|
3245
|
-
|
|
3246
|
-
var refHandler = $scope.internalLookups.find(function (lkp) {
|
|
3247
|
-
return lkp.ref.property === ref.property && lkp.ref.value === ref.value;
|
|
3248
|
-
});
|
|
3249
|
-
var thisHandler = {
|
|
3250
|
-
formInstructions: formInstructions,
|
|
3251
|
-
lastPart: nameElements.pop(),
|
|
3252
|
-
possibleArray: nameElements.join('.')
|
|
3253
|
-
};
|
|
3254
|
-
if (!refHandler) {
|
|
3255
|
-
refHandler = {
|
|
3256
|
-
ref: ref,
|
|
3257
|
-
lookupOptions: [],
|
|
3258
|
-
lookupIds: [],
|
|
3259
|
-
handlers: []
|
|
3260
|
-
};
|
|
3261
|
-
$scope.internalLookups.push(refHandler);
|
|
3262
|
-
}
|
|
3263
|
-
refHandler.handlers.push(thisHandler);
|
|
3264
|
-
$scope[formInstructions.options] = refHandler.lookupOptions;
|
|
3265
|
-
$scope[formInstructions.ids] = refHandler.lookupIds;
|
|
3635
|
+
addArrayLookupToLookupList($scope, formInstructions, ref, $scope.internalLookups);
|
|
3266
3636
|
},
|
|
3267
3637
|
preservePristine: preservePristine,
|
|
3268
3638
|
// Reverse the process of convertToAngularModel
|
|
@@ -3279,48 +3649,54 @@ var fng;
|
|
|
3279
3649
|
}
|
|
3280
3650
|
return retVal;
|
|
3281
3651
|
}
|
|
3282
|
-
|
|
3283
|
-
var
|
|
3284
|
-
var
|
|
3285
|
-
|
|
3652
|
+
var _loop_1 = function () {
|
|
3653
|
+
var schemaI = schema[i];
|
|
3654
|
+
var fieldname = schemaI.name.slice(prefixLength);
|
|
3655
|
+
var thisField = getListData(anObject, fieldname, null, $scope);
|
|
3656
|
+
if (schemaI.schema) {
|
|
3286
3657
|
if (thisField) {
|
|
3287
3658
|
for (var j = 0; j < thisField.length; j++) {
|
|
3288
|
-
thisField[j] = convertToMongoModel(
|
|
3659
|
+
thisField[j] = convertToMongoModel(schemaI.schema, thisField[j], 1 + fieldname.length, $scope, fieldname);
|
|
3289
3660
|
}
|
|
3290
3661
|
}
|
|
3291
3662
|
}
|
|
3292
3663
|
else {
|
|
3293
3664
|
// Convert {array:[{x:'item 1'}]} to {array:['item 1']}
|
|
3294
|
-
if (
|
|
3665
|
+
if (schemaI.array && simpleArrayNeedsX(schemaI) && thisField) {
|
|
3295
3666
|
for (var k = 0; k < thisField.length; k++) {
|
|
3296
3667
|
thisField[k] = thisField[k].x;
|
|
3297
3668
|
}
|
|
3298
3669
|
}
|
|
3299
3670
|
// Convert {lookup:'List description for 012abcde'} to {lookup:'012abcde'}
|
|
3300
|
-
var
|
|
3301
|
-
|
|
3302
|
-
if (idList && idList.length > 0) {
|
|
3671
|
+
var idList_1 = $scope[suffixCleanId(schemaI, "_ids")];
|
|
3672
|
+
if (idList_1 && idList_1.length > 0) {
|
|
3303
3673
|
updateObject(fieldname, anObject, function (value) {
|
|
3304
|
-
return convertToForeignKeys(
|
|
3674
|
+
return convertToForeignKeys(schemaI, value, $scope[suffixCleanId(schemaI, "Options")], idList_1);
|
|
3305
3675
|
});
|
|
3306
3676
|
}
|
|
3307
|
-
else
|
|
3308
|
-
var
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
newVal =
|
|
3312
|
-
if (
|
|
3313
|
-
|
|
3314
|
-
|
|
3677
|
+
else {
|
|
3678
|
+
var thisConversion = getConversionObject($scope, fieldname, schemaName);
|
|
3679
|
+
if (thisConversion) {
|
|
3680
|
+
var lookup = getData(anObject, fieldname, null);
|
|
3681
|
+
var newVal = void 0;
|
|
3682
|
+
if (schemaI.array) {
|
|
3683
|
+
newVal = [];
|
|
3684
|
+
if (lookup) {
|
|
3685
|
+
for (var n = 0; n < lookup.length; n++) {
|
|
3686
|
+
newVal[n] = convertLookup(lookup[n], thisConversion);
|
|
3687
|
+
}
|
|
3315
3688
|
}
|
|
3316
3689
|
}
|
|
3690
|
+
else {
|
|
3691
|
+
newVal = convertLookup(lookup, thisConversion);
|
|
3692
|
+
}
|
|
3693
|
+
setData(anObject, fieldname, null, newVal);
|
|
3317
3694
|
}
|
|
3318
|
-
else {
|
|
3319
|
-
newVal = convertLookup(lookup, thisConversion);
|
|
3320
|
-
}
|
|
3321
|
-
setData(anObject, fieldname, null, newVal);
|
|
3322
3695
|
}
|
|
3323
3696
|
}
|
|
3697
|
+
};
|
|
3698
|
+
for (var i = 0; i < schema.length; i++) {
|
|
3699
|
+
_loop_1();
|
|
3324
3700
|
}
|
|
3325
3701
|
return anObject;
|
|
3326
3702
|
},
|
|
@@ -3330,7 +3706,7 @@ var fng;
|
|
|
3330
3706
|
$scope.handleHttpError = handleError($scope);
|
|
3331
3707
|
$scope.cancel = function () {
|
|
3332
3708
|
angular.copy(ctrlState.master, $scope.record);
|
|
3333
|
-
$scope.$broadcast(
|
|
3709
|
+
$scope.$broadcast("fngCancel", $scope);
|
|
3334
3710
|
// Let call backs etc resolve in case they dirty form, then clean it
|
|
3335
3711
|
$timeout($scope.setPristine);
|
|
3336
3712
|
};
|
|
@@ -3339,15 +3715,21 @@ var fng;
|
|
|
3339
3715
|
// scope.$emit('showErrorMessage', {title: 'Your error Title', body: 'The body of the error message'});
|
|
3340
3716
|
// or
|
|
3341
3717
|
// scope.$broadcast('showErrorMessage', {title: 'Your error Title', body: 'The body of the error message'});
|
|
3342
|
-
$scope.$on(
|
|
3343
|
-
|
|
3718
|
+
$scope.$on("showErrorMessage", function (event, args) {
|
|
3719
|
+
if (!event.defaultPrevented) {
|
|
3720
|
+
event.defaultPrevented = true;
|
|
3721
|
+
$scope.showError(args.body, args.title);
|
|
3722
|
+
}
|
|
3344
3723
|
});
|
|
3345
3724
|
$scope.showError = function (error, alertTitle) {
|
|
3346
|
-
$scope.alertTitle = alertTitle ? alertTitle :
|
|
3347
|
-
if (typeof error ===
|
|
3725
|
+
$scope.alertTitle = alertTitle ? alertTitle : "Error!";
|
|
3726
|
+
if (typeof error === "string") {
|
|
3348
3727
|
$scope.errorMessage = error;
|
|
3349
3728
|
}
|
|
3350
|
-
else if (error
|
|
3729
|
+
else if (!error) {
|
|
3730
|
+
$scope.errorMessage = "An error occurred - that's all we got. Sorry.";
|
|
3731
|
+
}
|
|
3732
|
+
else if (error.message && typeof error.message === "string") {
|
|
3351
3733
|
$scope.errorMessage = error.message;
|
|
3352
3734
|
}
|
|
3353
3735
|
else if (error.data && error.data.message) {
|
|
@@ -3361,16 +3743,35 @@ var fng;
|
|
|
3361
3743
|
$scope.errorMessage = error;
|
|
3362
3744
|
}
|
|
3363
3745
|
}
|
|
3746
|
+
$scope.errorHideTimer = window.setTimeout(function () {
|
|
3747
|
+
$scope.dismissError();
|
|
3748
|
+
$scope.$digest();
|
|
3749
|
+
}, 3500 + (1000 * ($scope.alertTitle + $scope.errorMessage).length / 50));
|
|
3750
|
+
$scope.errorVisible = true;
|
|
3751
|
+
window.setTimeout(function () {
|
|
3752
|
+
$scope.$digest();
|
|
3753
|
+
});
|
|
3754
|
+
};
|
|
3755
|
+
$scope.clearTimeout = function () {
|
|
3756
|
+
if ($scope.errorHideTimer) {
|
|
3757
|
+
clearTimeout($scope.errorHideTimer);
|
|
3758
|
+
delete $scope.errorHideTimer;
|
|
3759
|
+
}
|
|
3364
3760
|
};
|
|
3365
3761
|
$scope.dismissError = function () {
|
|
3762
|
+
$scope.clearTimeout;
|
|
3763
|
+
$scope.errorVisible = false;
|
|
3366
3764
|
delete $scope.errorMessage;
|
|
3367
3765
|
delete $scope.alertTitle;
|
|
3368
3766
|
};
|
|
3767
|
+
$scope.stickError = function () {
|
|
3768
|
+
clearTimeout($scope.errorHideTimer);
|
|
3769
|
+
};
|
|
3369
3770
|
$scope.prepareForSave = function (cb) {
|
|
3370
3771
|
//Convert the lookup values into ids
|
|
3371
3772
|
var dataToSave = recordHandlerInstance.convertToMongoModel($scope.formSchema, angular.copy($scope.record), 0, $scope);
|
|
3372
3773
|
if ($scope.id) {
|
|
3373
|
-
if (typeof $scope.dataEventFunctions.onBeforeUpdate ===
|
|
3774
|
+
if (typeof $scope.dataEventFunctions.onBeforeUpdate === "function") {
|
|
3374
3775
|
$scope.dataEventFunctions.onBeforeUpdate(dataToSave, ctrlState.master, function (err) {
|
|
3375
3776
|
if (err) {
|
|
3376
3777
|
cb(err);
|
|
@@ -3385,7 +3786,7 @@ var fng;
|
|
|
3385
3786
|
}
|
|
3386
3787
|
}
|
|
3387
3788
|
else {
|
|
3388
|
-
if (typeof $scope.dataEventFunctions.onBeforeCreate ===
|
|
3789
|
+
if (typeof $scope.dataEventFunctions.onBeforeCreate === "function") {
|
|
3389
3790
|
$scope.dataEventFunctions.onBeforeCreate(dataToSave, function (err) {
|
|
3390
3791
|
if (err) {
|
|
3391
3792
|
cb(err);
|
|
@@ -3404,22 +3805,24 @@ var fng;
|
|
|
3404
3805
|
options = options || {};
|
|
3405
3806
|
$scope.prepareForSave(function (err, dataToSave) {
|
|
3406
3807
|
if (err) {
|
|
3407
|
-
if (err !==
|
|
3408
|
-
$
|
|
3808
|
+
if (err !== "_update_handled_") {
|
|
3809
|
+
$timeout(function () {
|
|
3810
|
+
$scope.showError(err);
|
|
3811
|
+
});
|
|
3409
3812
|
}
|
|
3410
3813
|
}
|
|
3411
3814
|
else if ($scope.id) {
|
|
3412
3815
|
recordHandlerInstance.updateDocument(dataToSave, options, $scope, ctrlState);
|
|
3413
3816
|
}
|
|
3414
3817
|
else {
|
|
3415
|
-
recordHandlerInstance.createNew(dataToSave, options, $scope);
|
|
3818
|
+
recordHandlerInstance.createNew(dataToSave, options, $scope, ctrlState);
|
|
3416
3819
|
}
|
|
3417
3820
|
});
|
|
3418
3821
|
};
|
|
3419
3822
|
$scope.newClick = function () {
|
|
3420
|
-
routingService.redirectTo()(
|
|
3823
|
+
routingService.redirectTo()("new", $scope, $location);
|
|
3421
3824
|
};
|
|
3422
|
-
$scope.$on(
|
|
3825
|
+
$scope.$on("$locationChangeStart", function (event, next) {
|
|
3423
3826
|
// let changed = !$scope.isCancelDisabled();
|
|
3424
3827
|
// let curPath = window.location.href.split('/');
|
|
3425
3828
|
// let nextPath = next.split('/');
|
|
@@ -3438,21 +3841,12 @@ var fng;
|
|
|
3438
3841
|
if (!ctrlState.allowLocationChange && !$scope.isCancelDisabled()) {
|
|
3439
3842
|
event.preventDefault();
|
|
3440
3843
|
var modalInstance = $uibModal.open({
|
|
3441
|
-
template:
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
'<div class="modal-body">' +
|
|
3445
|
-
' <p>Would you like to save your changes?</p>' +
|
|
3446
|
-
'</div>' +
|
|
3447
|
-
'<div class="modal-footer">' +
|
|
3448
|
-
' <button class="btn btn-primary dlg-yes" ng-click="yes()">Yes</button>' +
|
|
3449
|
-
' <button class="btn btn-warning dlg-no" ng-click="no()">No</button>' +
|
|
3450
|
-
' <button class="btn dlg-cancel" ng-click="cancel()">Cancel</button>' +
|
|
3451
|
-
'</div>',
|
|
3452
|
-
controller: 'SaveChangesModalCtrl',
|
|
3453
|
-
backdrop: 'static'
|
|
3844
|
+
template: "<div class=\"modal-header\">\n <h3>Record modified</h3>\n</div>\n<div class=\"modal-body\">\n <p>Would you like to save your changes?</p>\n</div>\n<div class=\"modal-footer\">\n <button class=\"btn btn-primary dlg-yes\" ng-click=\"yes()\">Yes</button>\n <button class=\"btn btn-warning dlg-no\" ng-click=\"no()\">No</button>\n <button class=\"btn dlg-cancel\" ng-click=\"cancel()\">Cancel</button>\n</div>",
|
|
3845
|
+
controller: "SaveChangesModalCtrl",
|
|
3846
|
+
backdrop: "static"
|
|
3454
3847
|
});
|
|
3455
|
-
modalInstance.result
|
|
3848
|
+
modalInstance.result
|
|
3849
|
+
.then(function (result) {
|
|
3456
3850
|
if (result) {
|
|
3457
3851
|
$scope.save({ redirect: next, allowChange: true }); // save changes
|
|
3458
3852
|
}
|
|
@@ -3460,7 +3854,8 @@ var fng;
|
|
|
3460
3854
|
ctrlState.allowLocationChange = true;
|
|
3461
3855
|
$window.location = next;
|
|
3462
3856
|
}
|
|
3463
|
-
})
|
|
3857
|
+
})
|
|
3858
|
+
.catch(_handleCancel);
|
|
3464
3859
|
}
|
|
3465
3860
|
});
|
|
3466
3861
|
$scope.deleteClick = function () {
|
|
@@ -3471,85 +3866,168 @@ var fng;
|
|
|
3471
3866
|
}
|
|
3472
3867
|
else {
|
|
3473
3868
|
var modalInstance = $uibModal.open({
|
|
3474
|
-
template:
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
'<div class="modal-body">' +
|
|
3478
|
-
' <p>Are you sure you want to delete this record?</p>' +
|
|
3479
|
-
'</div>' +
|
|
3480
|
-
'<div class="modal-footer">' +
|
|
3481
|
-
' <button class="btn btn-primary dlg-no" ng-click="cancel()">No</button>' +
|
|
3482
|
-
' <button class="btn btn-warning dlg-yes" ng-click="yes()">Yes</button>' +
|
|
3483
|
-
'</div>',
|
|
3484
|
-
controller: 'SaveChangesModalCtrl',
|
|
3485
|
-
backdrop: 'static'
|
|
3869
|
+
template: "<div class=\"modal-header\">\n <h3>Delete Item</h3>\n</div>\n<div class=\"modal-body\">\n <p>Are you sure you want to delete this record?</p>\n</div>\n<div class=\"modal-footer\">\n <button class=\"btn btn-primary dlg-no\" ng-click=\"cancel()\">No</button>\n <button class=\"btn btn-warning dlg-yes\" ng-click=\"yes()\">Yes</button>\n</div>",
|
|
3870
|
+
controller: "SaveChangesModalCtrl",
|
|
3871
|
+
backdrop: "static"
|
|
3486
3872
|
});
|
|
3487
3873
|
confirmDelete = modalInstance.result;
|
|
3488
3874
|
}
|
|
3489
3875
|
confirmDelete.then(function (result) {
|
|
3876
|
+
function doTheDeletion() {
|
|
3877
|
+
recordHandlerInstance.deleteRecord($scope.id, $scope, ctrlState);
|
|
3878
|
+
}
|
|
3490
3879
|
if (result) {
|
|
3491
|
-
if (typeof $scope.dataEventFunctions.onBeforeDelete ===
|
|
3880
|
+
if (typeof $scope.dataEventFunctions.onBeforeDelete === "function") {
|
|
3492
3881
|
$scope.dataEventFunctions.onBeforeDelete(ctrlState.master, function (err) {
|
|
3493
3882
|
if (err) {
|
|
3494
|
-
if (err !==
|
|
3883
|
+
if (err !== "_delete_handled_") {
|
|
3495
3884
|
$scope.showError(err);
|
|
3496
3885
|
}
|
|
3497
3886
|
}
|
|
3498
3887
|
else {
|
|
3499
|
-
|
|
3888
|
+
doTheDeletion();
|
|
3500
3889
|
}
|
|
3501
3890
|
});
|
|
3502
3891
|
}
|
|
3503
3892
|
else {
|
|
3504
|
-
|
|
3893
|
+
doTheDeletion();
|
|
3505
3894
|
}
|
|
3506
3895
|
}
|
|
3507
|
-
})
|
|
3896
|
+
})
|
|
3897
|
+
.catch(_handleCancel);
|
|
3508
3898
|
}
|
|
3509
3899
|
};
|
|
3510
3900
|
$scope.isCancelDisabled = function () {
|
|
3511
|
-
if (
|
|
3901
|
+
if ($scope[$scope.topLevelFormName] && $scope[$scope.topLevelFormName].$pristine) {
|
|
3902
|
+
return true;
|
|
3903
|
+
}
|
|
3904
|
+
else if (typeof $scope.disableFunctions.isCancelDisabled === "function") {
|
|
3512
3905
|
return $scope.disableFunctions.isCancelDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3513
3906
|
}
|
|
3514
3907
|
else {
|
|
3515
|
-
return
|
|
3908
|
+
return false;
|
|
3516
3909
|
}
|
|
3517
3910
|
};
|
|
3518
3911
|
$scope.isSaveDisabled = function () {
|
|
3519
|
-
|
|
3520
|
-
|
|
3912
|
+
$scope.whyDisabled = undefined;
|
|
3913
|
+
var pristine = false;
|
|
3914
|
+
function generateWhyDisabledMessage(form, subFormName) {
|
|
3915
|
+
form.$$controls.forEach(function (c) {
|
|
3916
|
+
if (c.$invalid) {
|
|
3917
|
+
if (c.$$controls) {
|
|
3918
|
+
// nested form
|
|
3919
|
+
generateWhyDisabledMessage(c, c.$name);
|
|
3920
|
+
}
|
|
3921
|
+
else {
|
|
3922
|
+
$scope.whyDisabled += "<br /><strong>";
|
|
3923
|
+
if (subFormName) {
|
|
3924
|
+
$scope.whyDisabled += subFormName + ' ';
|
|
3925
|
+
}
|
|
3926
|
+
if (cssFrameworkService.framework() === "bs2" &&
|
|
3927
|
+
c.$$element &&
|
|
3928
|
+
c.$$element.parent() &&
|
|
3929
|
+
c.$$element.parent().parent() &&
|
|
3930
|
+
c.$$element.parent().parent().find("label") &&
|
|
3931
|
+
c.$$element.parent().parent().find("label").text()) {
|
|
3932
|
+
$scope.whyDisabled += c.$$element.parent().parent().find("label").text();
|
|
3933
|
+
}
|
|
3934
|
+
else if (cssFrameworkService.framework() === "bs3" &&
|
|
3935
|
+
c.$$element &&
|
|
3936
|
+
c.$$element.parent() &&
|
|
3937
|
+
c.$$element.parent().parent() &&
|
|
3938
|
+
c.$$element.parent().parent().parent() &&
|
|
3939
|
+
c.$$element.parent().parent().parent().find("label") &&
|
|
3940
|
+
c.$$element.parent().parent().parent().find("label").text()) {
|
|
3941
|
+
$scope.whyDisabled += c.$$element.parent().parent().parent().find("label").text();
|
|
3942
|
+
}
|
|
3943
|
+
else {
|
|
3944
|
+
$scope.whyDisabled += c.$name;
|
|
3945
|
+
}
|
|
3946
|
+
$scope.whyDisabled += "</strong>: ";
|
|
3947
|
+
if (c.$error) {
|
|
3948
|
+
for (var type in c.$error) {
|
|
3949
|
+
if (c.$error.hasOwnProperty(type)) {
|
|
3950
|
+
switch (type) {
|
|
3951
|
+
case "required":
|
|
3952
|
+
$scope.whyDisabled += "Field missing required value. ";
|
|
3953
|
+
break;
|
|
3954
|
+
case "pattern":
|
|
3955
|
+
$scope.whyDisabled += "Field does not match required pattern. ";
|
|
3956
|
+
break;
|
|
3957
|
+
default:
|
|
3958
|
+
$scope.whyDisabled += type + ". ";
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
});
|
|
3966
|
+
}
|
|
3967
|
+
if ($scope[$scope.topLevelFormName]) {
|
|
3968
|
+
if ($scope[$scope.topLevelFormName].$invalid) {
|
|
3969
|
+
$scope.whyDisabled = 'The form data is invalid:';
|
|
3970
|
+
generateWhyDisabledMessage($scope[$scope.topLevelFormName]);
|
|
3971
|
+
}
|
|
3972
|
+
else if ($scope[$scope.topLevelFormName].$pristine) {
|
|
3973
|
+
// Don't have disabled message - should be obvious from Cancel being disabled,
|
|
3974
|
+
// and the message comes up when the Save button is clicked.
|
|
3975
|
+
pristine = true;
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
else {
|
|
3979
|
+
$scope.whyDisabled = "Top level form name invalid";
|
|
3980
|
+
}
|
|
3981
|
+
if (pristine || !!$scope.whyDisabled) {
|
|
3982
|
+
return true;
|
|
3983
|
+
}
|
|
3984
|
+
else if (typeof $scope.disableFunctions.isSaveDisabled !== "function") {
|
|
3985
|
+
return false;
|
|
3521
3986
|
}
|
|
3522
3987
|
else {
|
|
3523
|
-
|
|
3988
|
+
var retVal = $scope.disableFunctions.isSaveDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3989
|
+
if (typeof retVal === "string") {
|
|
3990
|
+
$scope.whyDisabled = retVal;
|
|
3991
|
+
}
|
|
3992
|
+
else {
|
|
3993
|
+
$scope.whyDisabled = "An application level user-specified function is inhibiting saving the record";
|
|
3994
|
+
}
|
|
3995
|
+
return !!retVal;
|
|
3524
3996
|
}
|
|
3525
3997
|
};
|
|
3526
3998
|
$scope.isDeleteDisabled = function () {
|
|
3527
|
-
if (
|
|
3999
|
+
if (!$scope.id) {
|
|
4000
|
+
return true;
|
|
4001
|
+
}
|
|
4002
|
+
else if (typeof $scope.disableFunctions.isDeleteDisabled === "function") {
|
|
3528
4003
|
return $scope.disableFunctions.isDeleteDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3529
4004
|
}
|
|
3530
4005
|
else {
|
|
3531
|
-
return
|
|
4006
|
+
return false;
|
|
3532
4007
|
}
|
|
3533
4008
|
};
|
|
3534
4009
|
$scope.isNewDisabled = function () {
|
|
3535
|
-
if (typeof $scope.disableFunctions.isNewDisabled ===
|
|
4010
|
+
if (typeof $scope.disableFunctions.isNewDisabled === "function") {
|
|
3536
4011
|
return $scope.disableFunctions.isNewDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3537
4012
|
}
|
|
3538
4013
|
else {
|
|
3539
4014
|
return false;
|
|
3540
4015
|
}
|
|
3541
4016
|
};
|
|
3542
|
-
$scope.
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
4017
|
+
$scope.setDefaults = function (formSchema, base) {
|
|
4018
|
+
if (base === void 0) { base = ''; }
|
|
4019
|
+
var retVal = {};
|
|
4020
|
+
formSchema.forEach(function (s) {
|
|
4021
|
+
if (s.defaultValue !== undefined) {
|
|
4022
|
+
retVal[s.name.replace(base, '')] = s.defaultValue;
|
|
4023
|
+
}
|
|
4024
|
+
});
|
|
4025
|
+
return retVal;
|
|
3548
4026
|
};
|
|
3549
4027
|
$scope.getVal = function (expression, index) {
|
|
3550
|
-
if (expression.indexOf(
|
|
4028
|
+
if (expression.indexOf("$index") === -1 || typeof index !== "undefined") {
|
|
3551
4029
|
expression = expression.replace(/\$index/g, index);
|
|
3552
|
-
return $scope.$eval(
|
|
4030
|
+
return $scope.$eval("record." + expression);
|
|
3553
4031
|
}
|
|
3554
4032
|
//else {
|
|
3555
4033
|
// Used to show error here, but angular seems to call before record is populated sometimes
|
|
@@ -3563,6 +4041,23 @@ var fng;
|
|
|
3563
4041
|
}
|
|
3564
4042
|
}
|
|
3565
4043
|
};
|
|
4044
|
+
$scope.setUpCustomLookupOptions = function (schemaElement, ids, options, baseScope) {
|
|
4045
|
+
for (var _i = 0, _a = [$scope, baseScope]; _i < _a.length; _i++) {
|
|
4046
|
+
var scope = _a[_i];
|
|
4047
|
+
if (scope) {
|
|
4048
|
+
// need to be accessible on our scope for generation of the select options, and - for nested schemas -
|
|
4049
|
+
// on baseScope for the conversion back to ids done by prepareForSave
|
|
4050
|
+
scope[schemaElement.ids] = ids;
|
|
4051
|
+
scope[schemaElement.options] = options;
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
var data = getData($scope.record, schemaElement.name);
|
|
4055
|
+
if (!data) {
|
|
4056
|
+
return;
|
|
4057
|
+
}
|
|
4058
|
+
data = convertForeignKeys(schemaElement, data, options, ids);
|
|
4059
|
+
setData($scope.record, schemaElement.name, undefined, data);
|
|
4060
|
+
};
|
|
3566
4061
|
},
|
|
3567
4062
|
fillFormFromBackendCustomSchema: fillFormFromBackendCustomSchema,
|
|
3568
4063
|
fillFormWithBackendSchema: function fillFormWithBackendSchema($scope, formGeneratorInstance, recordHandlerInstance, ctrlState) {
|
|
@@ -3595,13 +4090,45 @@ var fng;
|
|
|
3595
4090
|
})(services = fng.services || (fng.services = {}));
|
|
3596
4091
|
})(fng || (fng = {}));
|
|
3597
4092
|
/// <reference path="../../../../node_modules/@types/angular/index.d.ts" />
|
|
4093
|
+
var ExpirationCache = /** @class */ (function () {
|
|
4094
|
+
function ExpirationCache(timeout) {
|
|
4095
|
+
if (timeout === void 0) { timeout = 60 * 1000; }
|
|
4096
|
+
this.store = new Map();
|
|
4097
|
+
this.timeout = timeout;
|
|
4098
|
+
}
|
|
4099
|
+
ExpirationCache.prototype.get = function (key) {
|
|
4100
|
+
// this.store.has(key) ? console.log(`cache hit`) : console.log(`cache miss`);
|
|
4101
|
+
return this.store.get(key);
|
|
4102
|
+
};
|
|
4103
|
+
ExpirationCache.prototype.put = function (key, val) {
|
|
4104
|
+
var _this = this;
|
|
4105
|
+
this.store.set(key, val);
|
|
4106
|
+
// remove it once it's expired
|
|
4107
|
+
setTimeout(function () {
|
|
4108
|
+
// console.log(`removing expired key ${key}`);
|
|
4109
|
+
_this.remove(key);
|
|
4110
|
+
}, this.timeout);
|
|
4111
|
+
};
|
|
4112
|
+
ExpirationCache.prototype.remove = function (key) {
|
|
4113
|
+
this.store.delete(key);
|
|
4114
|
+
};
|
|
4115
|
+
ExpirationCache.prototype.removeAll = function () {
|
|
4116
|
+
this.store = new Map();
|
|
4117
|
+
};
|
|
4118
|
+
ExpirationCache.prototype.delete = function () {
|
|
4119
|
+
//no op here because this is standalone, not a part of $cacheFactory
|
|
4120
|
+
};
|
|
4121
|
+
return ExpirationCache;
|
|
4122
|
+
}());
|
|
3598
4123
|
var fng;
|
|
3599
4124
|
(function (fng) {
|
|
3600
4125
|
var services;
|
|
3601
4126
|
(function (services) {
|
|
3602
4127
|
/*@ngInject*/
|
|
3603
|
-
SubmissionsService.$inject = ["$http"
|
|
3604
|
-
function SubmissionsService($http
|
|
4128
|
+
SubmissionsService.$inject = ["$http"];
|
|
4129
|
+
function SubmissionsService($http) {
|
|
4130
|
+
var useCacheForGetAll = true;
|
|
4131
|
+
var expCache = new ExpirationCache();
|
|
3605
4132
|
/*
|
|
3606
4133
|
generate a query string for a filtered and paginated query for submissions.
|
|
3607
4134
|
options consists of the following:
|
|
@@ -3659,11 +4186,7 @@ var fng;
|
|
|
3659
4186
|
// };
|
|
3660
4187
|
// },
|
|
3661
4188
|
getListAttributes: function (ref, id) {
|
|
3662
|
-
|
|
3663
|
-
ref = { type: 'lookup', collection: ref };
|
|
3664
|
-
console.warn("Support for string type \"ref\" property is deprecated - use ref:" + JSON.stringify(ref));
|
|
3665
|
-
}
|
|
3666
|
-
return $http.get('/api/' + ref.collection + '/' + id + '/list');
|
|
4189
|
+
return $http.get('/api/' + ref + '/' + id + '/list', { cache: expCache });
|
|
3667
4190
|
},
|
|
3668
4191
|
readRecord: function (modelName, id) {
|
|
3669
4192
|
// TODO Figure out tab history updates (check for other tab-history-todos)
|
|
@@ -3679,7 +4202,7 @@ var fng;
|
|
|
3679
4202
|
},
|
|
3680
4203
|
getAll: function (modelName, _options) {
|
|
3681
4204
|
var options = angular.extend({
|
|
3682
|
-
cache:
|
|
4205
|
+
cache: useCacheForGetAll ? expCache : false
|
|
3683
4206
|
}, _options);
|
|
3684
4207
|
return $http.get('/api/' + modelName, options);
|
|
3685
4208
|
},
|
|
@@ -3690,12 +4213,21 @@ var fng;
|
|
|
3690
4213
|
return $http.delete('/api/' + model + '/' + id);
|
|
3691
4214
|
},
|
|
3692
4215
|
updateRecord: function (modelName, id, dataToSave) {
|
|
3693
|
-
|
|
4216
|
+
expCache.remove('/api/' + modelName);
|
|
3694
4217
|
return $http.post('/api/' + modelName + '/' + id, dataToSave);
|
|
3695
4218
|
},
|
|
3696
4219
|
createRecord: function (modelName, dataToSave) {
|
|
3697
|
-
|
|
4220
|
+
expCache.remove('/api/' + modelName);
|
|
3698
4221
|
return $http.post('/api/' + modelName, dataToSave);
|
|
4222
|
+
},
|
|
4223
|
+
useCache: function (val) {
|
|
4224
|
+
useCacheForGetAll = val;
|
|
4225
|
+
},
|
|
4226
|
+
getCache: function () {
|
|
4227
|
+
return !!expCache;
|
|
4228
|
+
},
|
|
4229
|
+
clearCache: function () {
|
|
4230
|
+
expCache.removeAll();
|
|
3699
4231
|
}
|
|
3700
4232
|
};
|
|
3701
4233
|
}
|
|
@@ -3721,6 +4253,7 @@ var fng;
|
|
|
3721
4253
|
fngInvalidRequired: 'fng-invalid-required',
|
|
3722
4254
|
allowLocationChange: true // Set when the data arrives..
|
|
3723
4255
|
};
|
|
4256
|
+
$scope.errorVisible = false;
|
|
3724
4257
|
angular.extend($scope, routingService.parsePathFunc()($location.$$path));
|
|
3725
4258
|
// Load context menu. For /person/client/:id/edit we need
|
|
3726
4259
|
// to load PersonCtrl and PersonClientCtrl
|
|
@@ -3735,17 +4268,33 @@ var fng;
|
|
|
3735
4268
|
$rootScope.$broadcast('fngFormLoadStart', $scope);
|
|
3736
4269
|
formGenerator.decorateScope($scope, formGenerator, recordHandler, $scope.sharedData);
|
|
3737
4270
|
recordHandler.decorateScope($scope, $uibModal, recordHandler, ctrlState);
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
$scope.sharedData.modelControllers[i].onBaseCtrlReady
|
|
4271
|
+
function processTheForm() {
|
|
4272
|
+
recordHandler.fillFormWithBackendSchema($scope, formGenerator, recordHandler, ctrlState);
|
|
4273
|
+
// Tell the 'model controllers' that they can start fiddling with baseScope
|
|
4274
|
+
for (var i = 0; i < $scope.sharedData.modelControllers.length; i++) {
|
|
4275
|
+
if ($scope.sharedData.modelControllers[i].onBaseCtrlReady) {
|
|
4276
|
+
$scope.sharedData.modelControllers[i].onBaseCtrlReady($scope);
|
|
4277
|
+
}
|
|
3743
4278
|
}
|
|
4279
|
+
$scope.$on('$destroy', function () {
|
|
4280
|
+
$scope.sharedData.modelControllers.forEach(function (value) { return value.$destroy(); });
|
|
4281
|
+
$rootScope.$broadcast('fngControllersUnloaded');
|
|
4282
|
+
});
|
|
4283
|
+
}
|
|
4284
|
+
//Check that we are ready
|
|
4285
|
+
if (typeof fng.formsAngular.beforeProcess === "function") {
|
|
4286
|
+
fng.formsAngular.beforeProcess($scope, function (err) {
|
|
4287
|
+
if (err) {
|
|
4288
|
+
$scope.showError(err.message, 'Error preparing to process form');
|
|
4289
|
+
}
|
|
4290
|
+
else {
|
|
4291
|
+
processTheForm();
|
|
4292
|
+
}
|
|
4293
|
+
});
|
|
4294
|
+
}
|
|
4295
|
+
else {
|
|
4296
|
+
processTheForm();
|
|
3744
4297
|
}
|
|
3745
|
-
$scope.$on('$destroy', function () {
|
|
3746
|
-
$scope.sharedData.modelControllers.forEach(function (value) { return value.$destroy(); });
|
|
3747
|
-
$rootScope.$broadcast('fngControllersUnloaded');
|
|
3748
|
-
});
|
|
3749
4298
|
}
|
|
3750
4299
|
controllers.BaseCtrl = BaseCtrl;
|
|
3751
4300
|
})(controllers = fng.controllers || (fng.controllers = {}));
|
|
@@ -3801,13 +4350,17 @@ var fng;
|
|
|
3801
4350
|
var controllers;
|
|
3802
4351
|
(function (controllers) {
|
|
3803
4352
|
/*@ngInject*/
|
|
3804
|
-
NavCtrl.$inject = ["$scope", "$location", "$filter", "routingService", "cssFrameworkService"];
|
|
3805
|
-
function NavCtrl($scope, $location, $filter, routingService, cssFrameworkService) {
|
|
4353
|
+
NavCtrl.$inject = ["$rootScope", "$scope", "$location", "$filter", "routingService", "cssFrameworkService"];
|
|
4354
|
+
function NavCtrl($rootScope, $scope, $location, $filter, routingService, cssFrameworkService) {
|
|
3806
4355
|
function clearContextMenu() {
|
|
3807
4356
|
$scope.items = [];
|
|
3808
4357
|
$scope.contextMenu = undefined;
|
|
3809
4358
|
}
|
|
4359
|
+
$rootScope.navScope = $scope; // Lets plugins access menus
|
|
3810
4360
|
clearContextMenu();
|
|
4361
|
+
$scope.toggleCollapsed = function () {
|
|
4362
|
+
$scope.collapsed = !$scope.collapsed;
|
|
4363
|
+
};
|
|
3811
4364
|
/* isCollapsed and showShortcuts are used to control how the menu is displayed in a responsive environment and whether the shortcut keystrokes help should be displayed */
|
|
3812
4365
|
$scope.isCollapsed = true;
|
|
3813
4366
|
$scope.showShortcuts = false;
|
|
@@ -3835,8 +4388,8 @@ var fng;
|
|
|
3835
4388
|
}
|
|
3836
4389
|
}
|
|
3837
4390
|
function filter(event) {
|
|
3838
|
-
var tagName = (event.target
|
|
3839
|
-
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
|
4391
|
+
var tagName = (event.target).tagName;
|
|
4392
|
+
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA' || tagName == "DIV" && event.target.classList.contains('ck-editor__editable'));
|
|
3840
4393
|
}
|
|
3841
4394
|
//console.log(event.keyCode, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
|
3842
4395
|
if (event.keyCode === 191 && (filter(event) || (event.ctrlKey && !event.altKey && !event.metaKey))) {
|
|
@@ -3865,7 +4418,7 @@ var fng;
|
|
|
3865
4418
|
else if (event.keyCode === 45 && event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey) {
|
|
3866
4419
|
deferredBtnClick('newButton'); // Ctrl+Shift+Ins creates New record
|
|
3867
4420
|
}
|
|
3868
|
-
else if (event.keyCode === 88 && event.ctrlKey && event.shiftKey && event.altKey && !event.metaKey) {
|
|
4421
|
+
else if (event.keyCode === 88 && event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey) {
|
|
3869
4422
|
deferredBtnClick('deleteButton'); // Ctrl+Shift+X deletes record
|
|
3870
4423
|
}
|
|
3871
4424
|
};
|
|
@@ -3881,6 +4434,11 @@ var fng;
|
|
|
3881
4434
|
};
|
|
3882
4435
|
$scope.$on('fngControllersLoaded', function (evt, sharedData, modelName) {
|
|
3883
4436
|
$scope.contextMenu = sharedData.dropDownDisplay || sharedData.modelNameDisplay || $filter('titleCase')(modelName, false);
|
|
4437
|
+
if (sharedData.dropDownDisplayPromise) {
|
|
4438
|
+
sharedData.dropDownDisplayPromise.then(function (value) {
|
|
4439
|
+
$scope.contextMenu = value;
|
|
4440
|
+
});
|
|
4441
|
+
}
|
|
3884
4442
|
});
|
|
3885
4443
|
$scope.$on('fngControllersUnloaded', function (evt) {
|
|
3886
4444
|
clearContextMenu();
|
|
@@ -3896,28 +4454,59 @@ var fng;
|
|
|
3896
4454
|
}
|
|
3897
4455
|
else {
|
|
3898
4456
|
// Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
|
|
3899
|
-
var args = item.args || []
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
4457
|
+
var args = item.args || [];
|
|
4458
|
+
var fn = item.fn;
|
|
4459
|
+
if (typeof fn === "function") {
|
|
4460
|
+
switch (args.length) {
|
|
4461
|
+
case 0:
|
|
4462
|
+
fn();
|
|
4463
|
+
break;
|
|
4464
|
+
case 1:
|
|
4465
|
+
fn(args[0]);
|
|
4466
|
+
break;
|
|
4467
|
+
case 2:
|
|
4468
|
+
fn(args[0], args[1]);
|
|
4469
|
+
break;
|
|
4470
|
+
case 3:
|
|
4471
|
+
fn(args[0], args[1], args[2]);
|
|
4472
|
+
break;
|
|
4473
|
+
case 4:
|
|
4474
|
+
fn(args[0], args[1], args[2], args[3]);
|
|
4475
|
+
break;
|
|
4476
|
+
}
|
|
4477
|
+
}
|
|
4478
|
+
else if (fn) {
|
|
4479
|
+
throw new Error("Incorrect menu setup");
|
|
3916
4480
|
}
|
|
3917
4481
|
}
|
|
3918
4482
|
};
|
|
3919
4483
|
$scope.isHidden = function (index) {
|
|
3920
|
-
|
|
4484
|
+
function explicitlyHidden(item) {
|
|
4485
|
+
return item.isHidden ? item.isHidden() : false;
|
|
4486
|
+
}
|
|
4487
|
+
var dividerHide = false;
|
|
4488
|
+
// Hide a divider if it appears under another
|
|
4489
|
+
if ($scope.items[index].divider) {
|
|
4490
|
+
if (index === 0) {
|
|
4491
|
+
dividerHide = true;
|
|
4492
|
+
}
|
|
4493
|
+
else {
|
|
4494
|
+
var foundVisible = false;
|
|
4495
|
+
var check = index - 1;
|
|
4496
|
+
while (check >= 0 && !dividerHide && !foundVisible) {
|
|
4497
|
+
if ($scope.items[check].divider) {
|
|
4498
|
+
dividerHide = true;
|
|
4499
|
+
}
|
|
4500
|
+
else if (!explicitlyHidden($scope.items[check])) {
|
|
4501
|
+
foundVisible = true;
|
|
4502
|
+
}
|
|
4503
|
+
else {
|
|
4504
|
+
--check;
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
}
|
|
4509
|
+
return dividerHide || explicitlyHidden($scope.items[index]);
|
|
3921
4510
|
};
|
|
3922
4511
|
$scope.isDisabled = function (index) {
|
|
3923
4512
|
return $scope.items[index].isDisabled ? $scope.items[index].isDisabled() : false;
|
|
@@ -3976,6 +4565,7 @@ var fng;
|
|
|
3976
4565
|
])
|
|
3977
4566
|
.controller('BaseCtrl', fng.controllers.BaseCtrl)
|
|
3978
4567
|
.controller('SaveChangesModalCtrl', fng.controllers.SaveChangesModalCtrl)
|
|
4568
|
+
.controller('LinkCtrl', fng.controllers.LinkCtrl)
|
|
3979
4569
|
.controller('ModelCtrl', fng.controllers.ModelCtrl)
|
|
3980
4570
|
.controller('NavCtrl', fng.controllers.NavCtrl)
|
|
3981
4571
|
.directive('modelControllerDropdown', fng.directives.modelControllerDropdown)
|
|
@@ -3987,6 +4577,7 @@ var fng;
|
|
|
3987
4577
|
.directive('fngNakedDate', fng.directives.fngNakedDate)
|
|
3988
4578
|
.filter('camelCase', fng.filters.camelCase)
|
|
3989
4579
|
.filter('titleCase', fng.filters.titleCase)
|
|
4580
|
+
.filter('extractTimestampFromMongoID', fng.filters.extractTimestampFromMongoID)
|
|
3990
4581
|
.service('addAllService', fng.services.addAllService)
|
|
3991
4582
|
.provider('cssFrameworkService', fng.services.cssFrameworkService)
|
|
3992
4583
|
.provider('routingService', fng.services.routingService)
|
|
@@ -4002,11 +4593,15 @@ var fng;
|
|
|
4002
4593
|
// expose the library
|
|
4003
4594
|
var formsAngular = fng.formsAngular;
|
|
4004
4595
|
|
|
4005
|
-
angular.module('formsAngular').run(['$templateCache', function($templateCache) {$templateCache.put('base-analysis.html','<div ng-controller="AnalysisCtrl">\n <div class="container-fluid page-header report-header">\n <div ng-class="css(\'rowFluid\')">\n <div class="header-lhs col-xs-7 span7">\n <h1>{{
|
|
4006
|
-
$templateCache.put('base-edit.html','<div ng-controller="BaseCtrl">\n <div ng-class="css(\'rowFluid\')" class="page-header edit-header">\n <div class="header-lhs col-sm-8 span8">\n <
|
|
4007
|
-
$templateCache.put('base-list.html','<div ng-controller="BaseCtrl">\n <div ng-class="css(\'rowFluid\')" class="page-header list-header">\n <div class="header-lhs col-sm-8 span8">\n <h1>{{modelNameDisplay}}</h1>\n </div>\n
|
|
4596
|
+
angular.module('formsAngular').run(['$templateCache', function($templateCache) {$templateCache.put('base-analysis.html','<div ng-controller="AnalysisCtrl">\n <error-display></error-display>\n <div class="container-fluid page-header report-header">\n <div ng-class="css(\'rowFluid\')">\n <div class="header-lhs col-xs-7 span7">\n <h1>{{ titleWithSubstitutions }}</h1>\n </div>\n <div class="header-rhs col-xs-5 span5">\n <form-input schema="paramSchema" name="paramForm" ng-show="paramSchema" formstyle="horizontalCompact"></form-input>\n </div>\n </div>\n </div>\n <div class="container-fluid page-body report-body">\n <div class="row-fluid report-grow">\n <div class="gridStyle" style="height:100%;" ui-grid="gridOptions" ui-grid-selection ui-grid-resize-columns></div>\n </div>\n </div>\n</div>\n');
|
|
4597
|
+
$templateCache.put('base-edit.html','<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header edit-header">\n <div class="header-lhs col-sm-8 span8">\n <h1 id="header-text">{{modelNameDisplay}} :\n <span id="header-data-desc">\n <span ng-show="!!editFormHeader" >{{ editFormHeader() }}</span>\n <span ng-hide="!!editFormHeader" ng-repeat="field in listSchema" ng-bind-html="getListData(record, field.name) + \' \'"></span>\n </span>\n </h1>\n </div>\n <div class="header-rhs col-sm-2 span2">\n <div form-buttons></div>\n </div>\n </div>\n <div class="container-fluid page-body edit-body">\n <form-input name="baseForm" schema="baseSchema()" formstyle="compact"></form-input>\n </div>\n<!-- <pre>-->\n <!--Record-->\n <!--{{ record | json }}-->\n <!--formSchema-->\n <!--{{ formSchema | json }}-->\n<!-- </pre>-->\n</div>\n');
|
|
4598
|
+
$templateCache.put('base-list-view.html','<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header list-header">\n <div class="header-lhs col-sm-8 span8">\n <h1>{{modelNameDisplay}}</h1>\n </div>\n </div>\n <div class="page-body list-body">\n <div ng-class="css(\'rowFluid\')" infinite-scroll="scrollTheList()">\n <a ng-repeat="record in recordList" ng-href="{{generateViewUrl(record)}}">\n <div class="list-item">\n <div ng-class="css(\'span\',12/listSchema.length)" ng-repeat="field in listSchema">{{getListData(record, field.name)}} </div>\n </div>\n </a>\n </div>\n </div>\n</div>\n');
|
|
4599
|
+
$templateCache.put('base-list.html','<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header list-header">\n <div class="header-lhs col-sm-8 span8">\n <h1>{{modelNameDisplay}}</h1>\n </div>\n <div class="header-rhs col-sm-2 span2">\n <a ng-href="{{generateNewUrl()}}"><button id="newBtn" class="btn btn-default"><i class="icon-plus"></i> New</button></a>\n </div>\n </div>\n <div class="page-body list-body">\n <div ng-class="css(\'rowFluid\')" infinite-scroll="scrollTheList()">\n <a ng-repeat="record in recordList" ng-href="{{generateEditUrl(record)}}">\n <div class="list-item">\n <div ng-class="css(\'span\',12/listSchema.length)" ng-repeat="field in listSchema">{{getListData(record, field.name)}} </div>\n </div>\n </a>\n </div>\n </div>\n</div>\n');
|
|
4600
|
+
$templateCache.put('base-view.html','<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header edit-header">\n <div class="header-lhs col-sm-8 span8">\n <h1 id="header-text">{{modelNameDisplay}} :\n <span ng-repeat="field in listSchema" ng-bind-html="getListData(record, field.name) + \' \'"></span>\n </h1>\n </div>\n </div>\n <div class="container-fluid page-body edit-body">\n <form-input name="baseForm" schema="baseSchema()" formstyle="compact" viewform="true"></form-input>\n </div>\n</div>\n');
|
|
4601
|
+
$templateCache.put('error-display-bs2.html','<div id="display-error" ng-show="errorVisible" class="row-fluid ng-hide">\n <div class="alert alert-error offset1 span10">\n <button type="button" id="err-hide" class="close" ng-click="dismissError()"><i class="icon-remove"></i></button>\n <button type="button" id="err-pin" class="close" ng-click="stickError()"><i class="icon-eye-open"></i></button>\n <h4 id="err-title">{{alertTitle}}</h4>\n <div id="err-msg" ng-bind-html="errorMessage"></div>\n </div>\n</div>\n');
|
|
4602
|
+
$templateCache.put('error-display-bs3.html','<div id="display-error" ng-show="errorVisible" class="row ng-hide">\n <div class="alert alert-error col-md-offset-1 col-md-10 alert-danger">\n <button type="button" id="err-hide" class="close" ng-click="dismissError()"><i class="glyphicon glyphicon-remove"></i></button>\n <button type="button" id="err-pin" class="close" ng-click="stickError()"><i class="glyphicon glyphicon-pushpin"></i></button>\n <h4 id="err-title">{{alertTitle}}</h4>\n <div id="err-msg" ng-bind-html="errorMessage"></div>\n </div>\n</div>\n');
|
|
4008
4603
|
$templateCache.put('error-messages.html','<div ng-message="required">A value is required for this field</div>\n<div ng-message="minlength">Too few characters entered</div>\n<div ng-message="maxlength">Too many characters entered</div>\n<div ng-message="min">That value is too small</div>\n<div ng-message="max">That value is too large</div>\n<div ng-message="email">You need to enter a valid email address</div>\n<div ng-message="pattern">This field does not match the expected pattern</div>\n');
|
|
4009
|
-
$templateCache.put('form-button-bs2.html','<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-mini btn-primary form-btn" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="icon-ok"></i> Save</button>\n <button id="cancelButton" class="btn btn-mini btn-warning form-btn" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="icon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-mini btn-success form-btn" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="icon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-mini btn-danger form-btn" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="icon-minus"></i> Delete</button>\n </div>\n</div>\n');
|
|
4010
|
-
$templateCache.put('form-button-bs3.html','<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-primary form-btn btn-xs" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="glyphicon glyphicon-ok"></i> Save</button>\n <button id="cancelButton" class="btn btn-warning form-btn btn-xs" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="glyphicon glyphicon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-success form-btn btn-xs" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="glyphicon glyphicon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-danger form-btn btn-xs" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="glyphicon glyphicon-minus"></i> Delete</button>\n </div>\n</div>\n');
|
|
4011
|
-
$templateCache.put('search-bs2.html','<form class="navbar-search pull-right">\n <div id="search-cg" class="control-group" ng-class="errorClass">\n <input type="text" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)">{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');
|
|
4012
|
-
$templateCache.put('search-bs3.html','<form class="pull-right navbar-form">\n <div id="search-cg" class="form-group" ng-class="errorClass">\n <input type="text" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query form-control" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)" title={{result.additional}}>{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');}]);
|
|
4604
|
+
$templateCache.put('form-button-bs2.html','<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-mini btn-primary form-btn" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="icon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-mini btn-warning form-btn" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="icon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-mini btn-success form-btn" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="icon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-mini btn-danger form-btn" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="icon-minus"></i> Delete</button>\n </div>\n</div>\n');
|
|
4605
|
+
$templateCache.put('form-button-bs3.html','<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-primary form-btn btn-xs" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="glyphicon glyphicon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-warning form-btn btn-xs" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="glyphicon glyphicon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-success form-btn btn-xs" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="glyphicon glyphicon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-danger form-btn btn-xs" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="glyphicon glyphicon-minus"></i> Delete</button>\n </div>\n</div>\n');
|
|
4606
|
+
$templateCache.put('search-bs2.html','<form class="navbar-search pull-right">\n <div id="search-cg" class="control-group" ng-class="errorClass">\n <input type="text" spellcheck="false" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)">{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');
|
|
4607
|
+
$templateCache.put('search-bs3.html','<form class="pull-right navbar-form">\n <div id="search-cg" class="form-group" ng-class="errorClass">\n <input type="text" spellcheck="false" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query form-control" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)" title={{result.additional}}>{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');}]);
|