forms-angular 0.12.0-beta.17 → 0.12.0-beta.170
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 +1223 -657
- package/dist/client/forms-angular.min.js +1 -1
- package/dist/client/index.d.ts +118 -49
- package/dist/server/data_form.js +1408 -943
- 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,119 @@ 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
|
+
if (scope.$parent.subDoc && scope.$parent.subDoc[attrib]) {
|
|
115
|
+
// Support for use in directives in arrays
|
|
116
|
+
watchExpression = workString + 'subDoc.' + attrib;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
if (typeof workScope['$index'] !== "undefined") {
|
|
120
|
+
var splitAttrib = attrib.split('.');
|
|
121
|
+
attrib = splitAttrib.pop();
|
|
122
|
+
attrib = splitAttrib.join('.') + '[' + workScope['$index'] + '].' + attrib;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
attrib = '.' + attrib;
|
|
126
|
+
}
|
|
127
|
+
watchExpression = workString + 'record' + attrib;
|
|
128
|
+
}
|
|
129
|
+
scope.$watch(watchExpression, function (newVal) {
|
|
130
|
+
if (newVal) {
|
|
131
|
+
if (/^[a-f0-9]{24}/.test(newVal.toString())) {
|
|
132
|
+
newVal = newVal.slice(0, 24);
|
|
133
|
+
}
|
|
134
|
+
else if (newVal.id && /^[a-f0-9]{24}/.test(newVal.id)) {
|
|
135
|
+
newVal = newVal.id.slice(0, 24);
|
|
136
|
+
}
|
|
137
|
+
else if (scope.$parent["f_" + attrs['fld'] + "Options"]) {
|
|
138
|
+
// extract from lookups
|
|
139
|
+
var i = scope.$parent["f_" + attrs['fld'] + "Options"].indexOf(newVal);
|
|
140
|
+
if (i > -1) {
|
|
141
|
+
newVal = scope.$parent["f_" + attrs['fld'] + "_ids"][i];
|
|
80
142
|
}
|
|
81
143
|
else {
|
|
82
|
-
|
|
144
|
+
newVal = undefined;
|
|
83
145
|
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
newVal = undefined;
|
|
149
|
+
}
|
|
150
|
+
if (newVal) {
|
|
151
|
+
scope['link'] = routingService.buildUrl(ref + '/' + form + (newVal.id || newVal) + '/edit' + linktab);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
scope['link'] = undefined;
|
|
155
|
+
}
|
|
87
156
|
}
|
|
88
|
-
|
|
89
|
-
|
|
157
|
+
else {
|
|
158
|
+
scope['link'] = undefined;
|
|
159
|
+
}
|
|
160
|
+
}, true);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
if (attrs['text'] && attrs['text'].length > 0) {
|
|
164
|
+
scope['text'] = attrs['text'];
|
|
165
|
+
}
|
|
166
|
+
var index = scope['$parent']['$index'];
|
|
167
|
+
scope.$watch('dataSrc()', function (newVal) {
|
|
168
|
+
if (newVal) {
|
|
169
|
+
if (typeof index !== 'undefined' && angular.isArray(newVal)) {
|
|
170
|
+
newVal = newVal[index];
|
|
171
|
+
}
|
|
172
|
+
scope['link'] = routingService.buildUrl(ref + '/' + form + newVal + '/edit' + linktab);
|
|
173
|
+
if (!scope['text']) {
|
|
174
|
+
SubmissionsService.getListAttributes(ref, newVal).then(function (response) {
|
|
175
|
+
var data = response.data;
|
|
176
|
+
if (data.success === false) {
|
|
177
|
+
scope['text'] = data.err;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
scope['text'] = data.list;
|
|
181
|
+
}
|
|
182
|
+
}, function (response) {
|
|
183
|
+
scope['text'] = 'Error ' + response.status + ': ' + response.data;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}, true);
|
|
188
|
+
}
|
|
90
189
|
},
|
|
190
|
+
controller: "LinkCtrl",
|
|
91
191
|
template: function (element, attrs) {
|
|
92
|
-
|
|
192
|
+
function handleAnchor(contents) {
|
|
193
|
+
return "<a ng-click=\"checkNotModal()\" ng-href=\"{{ link || '#' }}\" class=\"fng-link\">" + contents + "</a>";
|
|
194
|
+
}
|
|
195
|
+
var retVal;
|
|
196
|
+
if (attrs.readonly) {
|
|
197
|
+
retVal = '<span class="fng-link">{{text}}</span>';
|
|
198
|
+
}
|
|
199
|
+
else if (attrs['text'] && unescape(attrs['text']) !== attrs['text']) {
|
|
200
|
+
retVal = handleAnchor(unescape(attrs['text']));
|
|
201
|
+
// retVal = '<a href="{{ link }}" class="fng-link">{{text}}</a>';
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
retVal = handleAnchor('{{text}}');
|
|
205
|
+
}
|
|
206
|
+
return retVal;
|
|
93
207
|
}
|
|
94
208
|
};
|
|
95
209
|
}
|
|
@@ -146,7 +260,7 @@ var fng;
|
|
|
146
260
|
// <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
|
|
147
261
|
// </div>
|
|
148
262
|
//
|
|
149
|
-
// Inline
|
|
263
|
+
// Inline or stacked
|
|
150
264
|
// <div class="form-group">
|
|
151
265
|
// <label class="sr-only" for="exampleInputEmail2">Email address</label>
|
|
152
266
|
// <input type="email" class="form-control" id="exampleInputEmail2" placeholder="Enter email">
|
|
@@ -165,7 +279,7 @@ var fng;
|
|
|
165
279
|
// <input type="text" placeholder="Type something…">
|
|
166
280
|
// <span class="help-block">Example block-level help text here.</span>
|
|
167
281
|
//
|
|
168
|
-
// Inline
|
|
282
|
+
// Inline or Stacked
|
|
169
283
|
// <input type="text" class="input-small" placeholder="Email">
|
|
170
284
|
var subkeys = [];
|
|
171
285
|
var tabsSetup = tabsSetupState.N;
|
|
@@ -206,7 +320,7 @@ var fng;
|
|
|
206
320
|
var lastPart = compoundName.slice(root.length + 1);
|
|
207
321
|
if (options.index) {
|
|
208
322
|
modelString += root + '[' + options.index + '].' + lastPart;
|
|
209
|
-
idString = 'f_' + modelString.slice(modelBase.length).replace(/(\.|\[
|
|
323
|
+
idString = 'f_' + modelString.slice(modelBase.length).replace(/(\.|\[|]\.)/g, '-');
|
|
210
324
|
}
|
|
211
325
|
else {
|
|
212
326
|
modelString += root;
|
|
@@ -228,18 +342,33 @@ var fng;
|
|
|
228
342
|
var allInputsVars = formMarkupHelper.allInputsVars(scope, fieldInfo, options, modelString, idString, nameString);
|
|
229
343
|
var common = allInputsVars.common;
|
|
230
344
|
var value;
|
|
231
|
-
var requiredStr = (isRequired || fieldInfo.required) ? ' required' : '';
|
|
232
345
|
isRequired = isRequired || fieldInfo.required;
|
|
233
|
-
var requiredStr = isRequired ? ' required' : '';
|
|
346
|
+
var requiredStr = isRequired ? ' required ' : '';
|
|
234
347
|
var enumInstruction;
|
|
348
|
+
function handleReadOnlyDisabled(readonly) {
|
|
349
|
+
var retVal = '';
|
|
350
|
+
if (readonly) {
|
|
351
|
+
// despite the option being "readonly", we should use disabled and ng-disabled rather than their readonly
|
|
352
|
+
// equivalents (which give controls the appearance of being read-only, but don't actually prevent user
|
|
353
|
+
// interaction)
|
|
354
|
+
if (typeof readonly === "boolean") {
|
|
355
|
+
retVal = " disabled ";
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
retVal = " ng-disabled=\"" + readonly + "\" ";
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return retVal;
|
|
362
|
+
}
|
|
235
363
|
switch (fieldInfo.type) {
|
|
236
364
|
case 'select':
|
|
237
365
|
if (fieldInfo.select2) {
|
|
238
366
|
value = '<input placeholder="fng-select2 has been removed" readonly>';
|
|
239
367
|
}
|
|
240
368
|
else {
|
|
241
|
-
common += (fieldInfo.readonly
|
|
369
|
+
common += handleReadOnlyDisabled(fieldInfo.readonly);
|
|
242
370
|
common += fieldInfo.add ? (' ' + fieldInfo.add + ' ') : '';
|
|
371
|
+
common += " aria-label=\"" + (fieldInfo.label && fieldInfo.label !== "" ? fieldInfo.label : fieldInfo.name) + "\" ";
|
|
243
372
|
value = '<select ' + common + 'class="' + allInputsVars.formControl.trim() + allInputsVars.compactClass + allInputsVars.sizeClassBS2 + '" ' + requiredStr + '>';
|
|
244
373
|
if (!isRequired) {
|
|
245
374
|
value += '<option></option>';
|
|
@@ -268,25 +397,31 @@ var fng;
|
|
|
268
397
|
}
|
|
269
398
|
break;
|
|
270
399
|
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, '"') + '"';
|
|
400
|
+
value = '<fng-link model="' + modelString + '" ref="' + fieldInfo.ref + '"';
|
|
276
401
|
if (fieldInfo.form) {
|
|
277
402
|
value += ' form="' + fieldInfo.form + '"';
|
|
278
403
|
}
|
|
279
|
-
if (fieldInfo.
|
|
280
|
-
value += '
|
|
404
|
+
if (fieldInfo.linktab) {
|
|
405
|
+
value += ' linktab="' + fieldInfo.linktab + '"';
|
|
406
|
+
}
|
|
407
|
+
if (fieldInfo.linktext) {
|
|
408
|
+
value += ' text="' + fieldInfo.linktext + '"';
|
|
281
409
|
}
|
|
282
410
|
if (fieldInfo.readonly) {
|
|
283
|
-
|
|
411
|
+
if (typeof fieldInfo.readonly === "boolean") {
|
|
412
|
+
value += " readonly=\"true\"";
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
value += " ng-readonly=\"" + fieldInfo.readonly + "\"";
|
|
416
|
+
}
|
|
284
417
|
}
|
|
285
418
|
value += '></fng-link>';
|
|
286
419
|
break;
|
|
287
420
|
case 'radio':
|
|
288
421
|
value = '';
|
|
289
|
-
common += requiredStr
|
|
422
|
+
common += requiredStr;
|
|
423
|
+
common += handleReadOnlyDisabled(fieldInfo.readonly);
|
|
424
|
+
common += fieldInfo.add ? (' ' + fieldInfo.add + ' ') : '';
|
|
290
425
|
var separateLines = options.formstyle === 'vertical' || (options.formstyle !== 'inline' && !fieldInfo.inlineRadio);
|
|
291
426
|
if (angular.isArray(fieldInfo.options)) {
|
|
292
427
|
if (options.subschema) {
|
|
@@ -296,8 +431,7 @@ var fng;
|
|
|
296
431
|
var thisCommon_1;
|
|
297
432
|
angular.forEach(fieldInfo.options, function (optValue, idx) {
|
|
298
433
|
thisCommon_1 = common.replace('id="', 'id="' + idx + '-');
|
|
299
|
-
value +=
|
|
300
|
-
value += ' value="' + optValue + '">' + optValue;
|
|
434
|
+
value += "<input " + thisCommon_1 + " type=\"radio\" aria-label=\"" + optValue + "\" value=\"" + optValue + "\">" + optValue;
|
|
301
435
|
if (separateLines) {
|
|
302
436
|
value += '<br />';
|
|
303
437
|
}
|
|
@@ -312,18 +446,16 @@ var fng;
|
|
|
312
446
|
}
|
|
313
447
|
enumInstruction = generateEnumInstructions();
|
|
314
448
|
value += '<' + tagType + ' ng-repeat="option in ' + enumInstruction.repeat + '">';
|
|
315
|
-
value +=
|
|
316
|
-
value += enumInstruction.label || enumInstruction.value;
|
|
317
|
-
value += ' }} </' + tagType + '> ';
|
|
449
|
+
value += "<input " + common.replace('id="', 'id="{{$index}}-') + " type=\"radio\" aria-label=\"" + enumInstruction.value + "\" value=\"{{ " + enumInstruction.value + " }}\"> {{ " + (enumInstruction.label || enumInstruction.value) + " }} </" + tagType + "> ";
|
|
318
450
|
}
|
|
319
451
|
break;
|
|
320
452
|
case 'checkbox':
|
|
321
|
-
common += requiredStr
|
|
453
|
+
common += requiredStr;
|
|
454
|
+
common += handleReadOnlyDisabled(fieldInfo.readonly);
|
|
455
|
+
common += fieldInfo.add ? (' ' + fieldInfo.add + ' ') : '';
|
|
456
|
+
value = formMarkupHelper.generateSimpleInput(common, fieldInfo, options);
|
|
322
457
|
if (cssFrameworkService.framework() === 'bs3') {
|
|
323
|
-
value = '<div class="checkbox"
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
value = formMarkupHelper.generateSimpleInput(common, fieldInfo, options);
|
|
458
|
+
value = '<div class="checkbox">' + value + '</div>';
|
|
327
459
|
}
|
|
328
460
|
break;
|
|
329
461
|
default:
|
|
@@ -338,12 +470,13 @@ var fng;
|
|
|
338
470
|
}
|
|
339
471
|
}
|
|
340
472
|
if (fieldInfo.editor === 'ckEditor') {
|
|
473
|
+
console.log('Deprecation Warning: "editor" property deprecated - use "add"');
|
|
341
474
|
common += 'ckeditor = "" ';
|
|
342
475
|
if (cssFrameworkService.framework() === 'bs3') {
|
|
343
476
|
allInputsVars.sizeClassBS3 = 'col-xs-12';
|
|
344
477
|
}
|
|
345
478
|
}
|
|
346
|
-
value = '<textarea ' + common + '
|
|
479
|
+
value = '<textarea ' + common + '></textarea>';
|
|
347
480
|
}
|
|
348
481
|
else {
|
|
349
482
|
value = formMarkupHelper.generateSimpleInput(common, fieldInfo, options);
|
|
@@ -363,6 +496,9 @@ var fng;
|
|
|
363
496
|
case 'inline':
|
|
364
497
|
result = 'form-inline';
|
|
365
498
|
break;
|
|
499
|
+
case 'stacked':
|
|
500
|
+
result = 'form-stacked';
|
|
501
|
+
break;
|
|
366
502
|
case 'horizontalCompact':
|
|
367
503
|
result = 'form-horizontal compact';
|
|
368
504
|
break;
|
|
@@ -390,7 +526,7 @@ var fng;
|
|
|
390
526
|
if (tabNo >= 0) {
|
|
391
527
|
// TODO Figure out tab history updates (check for other tab-history-todos)
|
|
392
528
|
// 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 + '"';
|
|
529
|
+
result.before = '<uib-tab deselect="tabDeselect($event, $selectedIndex)" select="updateQueryForTab(\'' + info.title + '\')" heading="' + info.title + '"';
|
|
394
530
|
if (tabNo > 0) {
|
|
395
531
|
result.before += 'active="tabs[' + tabNo + '].active"';
|
|
396
532
|
}
|
|
@@ -451,6 +587,41 @@ var fng;
|
|
|
451
587
|
}
|
|
452
588
|
return result;
|
|
453
589
|
};
|
|
590
|
+
var generateInlineHeaders = function (instructionsArray, options, model, evenWhenEmpty) {
|
|
591
|
+
// "column" headers for nested schemas that use formStyle: "inline" will only line up with their respective
|
|
592
|
+
// controls when widths are applied to both the cg_f_xxxx and col_label_xxxx element using css.
|
|
593
|
+
// Likely, the widths will need to be the same, so consider using the following:
|
|
594
|
+
// div[id$="_f_<collection>_<field>"] {
|
|
595
|
+
// width: 100px;
|
|
596
|
+
// }
|
|
597
|
+
// one column can grow to the remaining available width thus:
|
|
598
|
+
// div[id$="_f_<collection>_<field>"] {
|
|
599
|
+
// flex-grow: 1;
|
|
600
|
+
// }
|
|
601
|
+
var hideWhenEmpty = evenWhenEmpty ? "" : "ng-hide=\"!" + model + " || " + model + ".length === 0\"";
|
|
602
|
+
var res = "<div class=\"inline-col-headers\" style=\"display:flex\" " + hideWhenEmpty + ">";
|
|
603
|
+
for (var _i = 0, instructionsArray_1 = instructionsArray; _i < instructionsArray_1.length; _i++) {
|
|
604
|
+
var info = instructionsArray_1[_i];
|
|
605
|
+
// need to call this now to ensure the id is set. will probably be (harmlessly) called again later.
|
|
606
|
+
inferMissingProperties(info, options);
|
|
607
|
+
res += '<div ';
|
|
608
|
+
info.showWhen = info.showWhen || info.showwhen; // deal with use within a directive
|
|
609
|
+
if (info.showWhen) {
|
|
610
|
+
if (typeof info.showWhen === 'string') {
|
|
611
|
+
res += 'ng-show="' + info.showWhen + '"';
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
res += 'ng-show="' + formMarkupHelper.generateNgShow(info.showWhen, model) + '"';
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (info.id && typeof info.id.replace === "function") {
|
|
618
|
+
res += ' id="col_label_' + info.id.replace(/\./g, '-') + '"';
|
|
619
|
+
}
|
|
620
|
+
res += " class=\"inline-col-header\"><label for=\"" + info.id + "\" class=\"control-label\">" + info.label + "</label></div>";
|
|
621
|
+
}
|
|
622
|
+
res += "</div>";
|
|
623
|
+
return res;
|
|
624
|
+
};
|
|
454
625
|
var handleField = function (info, options) {
|
|
455
626
|
var fieldChrome = formMarkupHelper.fieldChrome(scope, info, options);
|
|
456
627
|
var template = fieldChrome.template;
|
|
@@ -473,7 +644,8 @@ var fng;
|
|
|
473
644
|
formstyle: options.formstyle,
|
|
474
645
|
subkey: schemaDefName + '_subkey',
|
|
475
646
|
subkeyno: arraySel,
|
|
476
|
-
subschemaroot: info.name
|
|
647
|
+
subschemaroot: info.name,
|
|
648
|
+
suppressNestingWarning: info.suppressNestingWarning
|
|
477
649
|
});
|
|
478
650
|
template += topAndTail.after;
|
|
479
651
|
}
|
|
@@ -481,7 +653,9 @@ var fng;
|
|
|
481
653
|
}
|
|
482
654
|
else {
|
|
483
655
|
if (options.subschema) {
|
|
484
|
-
|
|
656
|
+
if (!options.suppressNestingWarning) {
|
|
657
|
+
console.log('Attempts at supporting deep nesting have been removed - will hopefully be re-introduced at a later date');
|
|
658
|
+
}
|
|
485
659
|
}
|
|
486
660
|
else {
|
|
487
661
|
var model = (options.model || 'record') + '.' + info.name;
|
|
@@ -503,14 +677,18 @@ var fng;
|
|
|
503
677
|
}
|
|
504
678
|
}
|
|
505
679
|
/* Array body */
|
|
680
|
+
if (info.formStyle === "inline" && info.inlineHeaders) {
|
|
681
|
+
template += generateInlineHeaders(info.schema, options, model, info.inlineHeaders === "always");
|
|
682
|
+
}
|
|
506
683
|
template += '<ol class="sub-doc"' + (info.sortable ? " ui-sortable=\"sortableOptions\" ng-model=\"" + model + "\"" : '') + '>';
|
|
507
684
|
template += '<li ng-form class="' + (cssFrameworkService.framework() === 'bs2' ? 'row-fluid ' : '') +
|
|
508
|
-
|
|
685
|
+
(info.inlineHeaders ? 'width-controlled ' : '') +
|
|
686
|
+
convertFormStyleToClass(info.formStyle) + ' ' + (info.ngClass ? "ng-class:" + info.ngClass : "") + '" name="form_' + niceName + '{{$index}}" class="sub-doc well" id="' + info.id + 'List_{{$index}}" ' +
|
|
509
687
|
' ng-repeat="subDoc in ' + model + ' track by $index">';
|
|
510
688
|
if (cssFrameworkService.framework() === 'bs2') {
|
|
511
689
|
template += '<div class="row-fluid sub-doc">';
|
|
512
690
|
}
|
|
513
|
-
if (
|
|
691
|
+
if (info.noRemove !== true || info.customSubDoc) {
|
|
514
692
|
template += ' <div class="sub-doc-btns">';
|
|
515
693
|
if (typeof info.customSubDoc == 'string') {
|
|
516
694
|
template += info.customSubDoc;
|
|
@@ -533,31 +711,64 @@ var fng;
|
|
|
533
711
|
}
|
|
534
712
|
template += '</div> ';
|
|
535
713
|
}
|
|
714
|
+
var parts = void 0;
|
|
715
|
+
if (info.subDocContainerType) {
|
|
716
|
+
var containerType = scope[info.subDocContainerType] || info.subDocContainerType;
|
|
717
|
+
var containerProps = Object.assign({ containerType: containerType }, info.subDocContainerProps);
|
|
718
|
+
parts = containerInstructions(containerProps);
|
|
719
|
+
}
|
|
720
|
+
if (parts === null || parts === void 0 ? void 0 : parts.before) {
|
|
721
|
+
template += parts.before;
|
|
722
|
+
}
|
|
536
723
|
template += processInstructions(info.schema, false, {
|
|
537
724
|
subschema: 'true',
|
|
538
725
|
formstyle: info.formStyle,
|
|
539
726
|
model: options.model,
|
|
540
|
-
subschemaroot: info.name
|
|
727
|
+
subschemaroot: info.name,
|
|
728
|
+
suppressNestingWarning: info.suppressNestingWarning
|
|
541
729
|
});
|
|
730
|
+
if (parts === null || parts === void 0 ? void 0 : parts.after) {
|
|
731
|
+
template += parts.after;
|
|
732
|
+
}
|
|
542
733
|
if (cssFrameworkService.framework() === 'bs2') {
|
|
543
734
|
template += ' </div>';
|
|
544
735
|
}
|
|
545
736
|
template += '</li>';
|
|
546
737
|
template += '</ol>';
|
|
547
738
|
/* Array footer */
|
|
548
|
-
if (info.noAdd !== true || typeof info.customFooter == 'string') {
|
|
739
|
+
if (info.noAdd !== true || typeof info.customFooter == 'string' || info.noneIndicator) {
|
|
549
740
|
var footer = '';
|
|
550
741
|
if (typeof info.customFooter == 'string') {
|
|
551
742
|
footer = info.customFooter;
|
|
552
743
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
template += '<div class="row schema-foot"><div class="col-sm-offset-3">' + footer + '</div></div>';
|
|
744
|
+
var hideCond = '';
|
|
745
|
+
var indicatorShowCond = model + ".length == 0";
|
|
746
|
+
if (info.noAdd === true) {
|
|
747
|
+
indicatorShowCond = "ng-show=\"" + indicatorShowCond + "\"";
|
|
558
748
|
}
|
|
559
749
|
else {
|
|
560
|
-
|
|
750
|
+
hideCond = info.noAdd ? "ng-hide=\"" + info.noAdd + "\"" : '';
|
|
751
|
+
indicatorShowCond = info.noAdd ? "ng-show=\"" + info.noAdd + " && " + indicatorShowCond + "\"" : '';
|
|
752
|
+
footer += "<button " + hideCond + " id=\"add_" + info.id + "_btn\" class=\"add-btn btn btn-default btn-xs btn-mini\" ng-click=\"add('" + info.name + "',$event)\">\n <i class=\"' + formMarkupHelper.glyphClass() + '-plus\"></i> \n Add\n </button>";
|
|
753
|
+
}
|
|
754
|
+
if (info.noneIndicator) {
|
|
755
|
+
footer += "<span " + indicatorShowCond + " class=\"none_indicator\" id=\"no_" + info.id + "_indicator\">None</span>";
|
|
756
|
+
// hideCond for the schema-foot is if there's no add button and no indicator
|
|
757
|
+
hideCond = model + ".length > 0";
|
|
758
|
+
if (info.noAdd === true) {
|
|
759
|
+
hideCond = "ng-hide=\"" + hideCond + "\"";
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
hideCond = info.noAdd ? "ng-hide=\"" + info.noAdd + " && " + hideCond + "\"" : '';
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (footer !== '') {
|
|
766
|
+
if (cssFrameworkService.framework() === 'bs3') {
|
|
767
|
+
template += "<div " + hideCond + " class=\"row schema-foot\"><div class=\"col-sm-offset-3\">" + footer + "</div></div>";
|
|
768
|
+
}
|
|
769
|
+
else {
|
|
770
|
+
template += "<div " + hideCond + " class = \"schema-foot \">" + footer + "</div>";
|
|
771
|
+
}
|
|
561
772
|
}
|
|
562
773
|
}
|
|
563
774
|
}
|
|
@@ -569,8 +780,8 @@ var fng;
|
|
|
569
780
|
var controlDivClasses = formMarkupHelper.controlDivClasses(options);
|
|
570
781
|
if (info.array) {
|
|
571
782
|
controlDivClasses.push('fng-array');
|
|
572
|
-
if (options.formstyle === 'inline') {
|
|
573
|
-
throw new Error('Cannot use arrays in an inline form');
|
|
783
|
+
if (options.formstyle === 'inline' || options.formstyle === 'stacked') {
|
|
784
|
+
throw new Error('Cannot use arrays in an inline or stacked form');
|
|
574
785
|
}
|
|
575
786
|
template += formMarkupHelper.label(scope, info, info.type !== 'link', options);
|
|
576
787
|
template += formMarkupHelper.handleArrayInputAndControlDiv(generateInput(info, info.type === 'link' ? null : 'arrayItem.x', true, info.id + '_{{$index}}', options), controlDivClasses, info, options);
|
|
@@ -578,25 +789,27 @@ var fng;
|
|
|
578
789
|
else {
|
|
579
790
|
// Single fields here
|
|
580
791
|
template += formMarkupHelper.label(scope, info, null, options);
|
|
581
|
-
if (options.required) {
|
|
582
|
-
console.log("********* Options required - found it ********");
|
|
583
|
-
}
|
|
584
792
|
template += formMarkupHelper.handleInputAndControlDiv(generateInput(info, null, options.required, info.id, options), controlDivClasses);
|
|
585
793
|
}
|
|
586
794
|
}
|
|
587
795
|
template += fieldChrome.closeTag;
|
|
588
796
|
return template;
|
|
589
797
|
};
|
|
590
|
-
var inferMissingProperties = function (info) {
|
|
798
|
+
var inferMissingProperties = function (info, options) {
|
|
591
799
|
// infer missing values
|
|
592
800
|
info.type = info.type || 'text';
|
|
593
801
|
if (info.id) {
|
|
594
|
-
if (typeof info.id === 'number' ||
|
|
802
|
+
if (typeof info.id === 'number' || info.id.match(/^[0-9]/)) {
|
|
595
803
|
info.id = '_' + info.id;
|
|
596
804
|
}
|
|
597
805
|
}
|
|
598
806
|
else {
|
|
599
|
-
|
|
807
|
+
if (options && options.noid) {
|
|
808
|
+
info.id = null;
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
info.id = 'f_' + info.name.replace(/\./g, '_');
|
|
812
|
+
}
|
|
600
813
|
}
|
|
601
814
|
info.label = (info.label !== undefined) ? (info.label === null ? '' : info.label) : $filter('titleCase')(info.name.split('.').slice(-1)[0]);
|
|
602
815
|
};
|
|
@@ -607,7 +820,11 @@ var fng;
|
|
|
607
820
|
if (instructionsArray) {
|
|
608
821
|
for (var anInstruction = 0; anInstruction < instructionsArray.length; anInstruction++) {
|
|
609
822
|
var info = instructionsArray[anInstruction];
|
|
610
|
-
if (
|
|
823
|
+
if (options.viewform) {
|
|
824
|
+
info = angular.copy(info);
|
|
825
|
+
info.readonly = true;
|
|
826
|
+
}
|
|
827
|
+
if (anInstruction === 0 && topLevel && !options.schema.match(/\$_schema_/) && typeof info.add !== 'object') {
|
|
611
828
|
info.add = info.add ? ' ' + info.add + ' ' : '';
|
|
612
829
|
if (info.add.indexOf('ui-date') === -1 && !options.noautofocus && !info.containerType) {
|
|
613
830
|
info.add = info.add + 'autofocus ';
|
|
@@ -616,9 +833,10 @@ var fng;
|
|
|
616
833
|
var callHandleField = true;
|
|
617
834
|
if (info.directive) {
|
|
618
835
|
var directiveName = info.directive;
|
|
619
|
-
var newElement =
|
|
836
|
+
var newElement = info.customHeader || "";
|
|
837
|
+
newElement += '<' + directiveName + ' model="' + (options.model || 'record') + '"';
|
|
620
838
|
var thisElement = element[0];
|
|
621
|
-
inferMissingProperties(info);
|
|
839
|
+
inferMissingProperties(info, options);
|
|
622
840
|
for (var i = 0; i < thisElement.attributes.length; i++) {
|
|
623
841
|
var thisAttr = thisElement.attributes[i];
|
|
624
842
|
switch (thisAttr.nodeName) {
|
|
@@ -654,7 +872,9 @@ var fng;
|
|
|
654
872
|
break;
|
|
655
873
|
case 'object':
|
|
656
874
|
for (var subAdd in info.add) {
|
|
657
|
-
|
|
875
|
+
if (info.add.hasOwnProperty(subAdd)) {
|
|
876
|
+
newElement += ' ' + subAdd + '="' + info.add[subAdd].toString().replace(/"/g, '"') + '"';
|
|
877
|
+
}
|
|
658
878
|
}
|
|
659
879
|
break;
|
|
660
880
|
default:
|
|
@@ -663,13 +883,21 @@ var fng;
|
|
|
663
883
|
break;
|
|
664
884
|
case directiveCamel:
|
|
665
885
|
for (var subProp in info[prop]) {
|
|
666
|
-
|
|
886
|
+
if (info[prop].hasOwnProperty(subProp)) {
|
|
887
|
+
newElement += " " + info.directive + "-" + subProp + "=\"";
|
|
888
|
+
if (typeof info[prop][subProp] === 'string') {
|
|
889
|
+
newElement += info[prop][subProp].replace(/"/g, '"') + "\"";
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
newElement += JSON.stringify(info[prop][subProp]).replace(/"/g, '"') + "\"";
|
|
893
|
+
}
|
|
894
|
+
}
|
|
667
895
|
}
|
|
668
896
|
break;
|
|
669
897
|
default:
|
|
670
898
|
if (info[prop]) {
|
|
671
899
|
if (typeof info[prop] === 'string') {
|
|
672
|
-
newElement += ' fng-fld-' + prop + '="' + info[prop].
|
|
900
|
+
newElement += ' fng-fld-' + prop + '="' + info[prop].replace(/"/g, '"') + '"';
|
|
673
901
|
}
|
|
674
902
|
else {
|
|
675
903
|
newElement += ' fng-fld-' + prop + '="' + JSON.stringify(info[prop]).replace(/"/g, '"') + '"';
|
|
@@ -685,6 +913,7 @@ var fng;
|
|
|
685
913
|
}
|
|
686
914
|
}
|
|
687
915
|
newElement += 'ng-model="' + info.name + '"></' + directiveName + '>';
|
|
916
|
+
newElement += (info.customFooter || "");
|
|
688
917
|
result += newElement;
|
|
689
918
|
callHandleField = false;
|
|
690
919
|
}
|
|
@@ -721,9 +950,7 @@ var fng;
|
|
|
721
950
|
else if (options.subkey) {
|
|
722
951
|
// 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
952
|
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
|
-
})) {
|
|
953
|
+
if (_.find(objectToSearch, function (value, key) { return scope[options.subkey].path + '.' + key === info.name; })) {
|
|
727
954
|
callHandleField = false;
|
|
728
955
|
}
|
|
729
956
|
}
|
|
@@ -731,7 +958,7 @@ var fng;
|
|
|
731
958
|
// if (groupId) {
|
|
732
959
|
// scope['showHide' + groupId] = true;
|
|
733
960
|
// }
|
|
734
|
-
inferMissingProperties(info);
|
|
961
|
+
inferMissingProperties(info, options);
|
|
735
962
|
result += handleField(info, options);
|
|
736
963
|
}
|
|
737
964
|
}
|
|
@@ -745,8 +972,9 @@ var fng;
|
|
|
745
972
|
var unwatch = scope.$watch(attrs.schema, function (newValue) {
|
|
746
973
|
if (newValue) {
|
|
747
974
|
var newArrayValue = angular.isArray(newValue) ? newValue : [newValue]; // otherwise some old tests stop working for no real reason
|
|
748
|
-
if (newArrayValue.length > 0) {
|
|
975
|
+
if (newArrayValue.length > 0 && typeof unwatch === "function") {
|
|
749
976
|
unwatch();
|
|
977
|
+
unwatch = null;
|
|
750
978
|
var elementHtml = '';
|
|
751
979
|
var recordAttribute = attrs.model || 'record'; // By default data comes from scope.record
|
|
752
980
|
var theRecord = scope[recordAttribute];
|
|
@@ -760,12 +988,13 @@ var fng;
|
|
|
760
988
|
var customAttrs = '';
|
|
761
989
|
for (var thisAttr in attrs) {
|
|
762
990
|
if (attrs.hasOwnProperty(thisAttr)) {
|
|
763
|
-
if (thisAttr[0] !== '$' && ['name', 'formstyle', 'schema', 'subschema', 'model'].indexOf(thisAttr) === -1) {
|
|
991
|
+
if (thisAttr[0] !== '$' && ['name', 'formstyle', 'schema', 'subschema', 'model', 'viewform'].indexOf(thisAttr) === -1) {
|
|
764
992
|
customAttrs += ' ' + attrs.$attr[thisAttr] + '="' + attrs[thisAttr] + '"';
|
|
765
993
|
}
|
|
766
994
|
}
|
|
767
995
|
}
|
|
768
|
-
|
|
996
|
+
var tag = attrs.forceform ? 'ng-form' : 'form';
|
|
997
|
+
elementHtml = "<" + tag + " name=\"" + scope.topLevelFormName + "\" class=\"" + convertFormStyleToClass(attrs.formstyle) + "\" novalidate " + customAttrs + ">";
|
|
769
998
|
}
|
|
770
999
|
if (theRecord === scope.topLevelFormName) {
|
|
771
1000
|
throw new Error('Model and Name must be distinct - they are both ' + theRecord);
|
|
@@ -781,10 +1010,12 @@ var fng;
|
|
|
781
1010
|
// If we have modelControllers we need to let them know when we have form + data
|
|
782
1011
|
var sharedData = scope[attrs.shared || 'sharedData'];
|
|
783
1012
|
var modelControllers_1 = sharedData ? sharedData.modelControllers : [];
|
|
784
|
-
if (subkeys.length > 0 || modelControllers_1.length > 0) {
|
|
1013
|
+
if ((subkeys.length > 0 || modelControllers_1.length > 0) && !scope.phaseWatcher) {
|
|
785
1014
|
var unwatch2 = scope.$watch('phase', function (newValue) {
|
|
786
|
-
|
|
1015
|
+
scope.phaseWatcher = true;
|
|
1016
|
+
if (newValue === 'ready' && typeof unwatch2 === "function") {
|
|
787
1017
|
unwatch2();
|
|
1018
|
+
unwatch2 = null;
|
|
788
1019
|
// Tell the 'model controllers' that the form and data are there
|
|
789
1020
|
for (var i = 0; i < modelControllers_1.length; i++) {
|
|
790
1021
|
if (modelControllers_1[i].onAllReady) {
|
|
@@ -813,7 +1044,7 @@ var fng;
|
|
|
813
1044
|
arrayOffset = scope[arrayToProcess[thisOffset].selectFunc](theRecord, info);
|
|
814
1045
|
}
|
|
815
1046
|
else if (arrayToProcess[thisOffset].keyList) {
|
|
816
|
-
// We are
|
|
1047
|
+
// We are choosing the array element by matching one or more keys
|
|
817
1048
|
var thisSubkeyList = arrayToProcess[thisOffset].keyList;
|
|
818
1049
|
for (arrayOffset = 0; arrayOffset < dataVal.length; arrayOffset++) {
|
|
819
1050
|
matching = true;
|
|
@@ -867,7 +1098,7 @@ var fng;
|
|
|
867
1098
|
}
|
|
868
1099
|
});
|
|
869
1100
|
}
|
|
870
|
-
$rootScope.$broadcast('formInputDone');
|
|
1101
|
+
$rootScope.$broadcast('formInputDone', attrs.name);
|
|
871
1102
|
if (formGenerator.updateDataDependentDisplay && theRecord && Object.keys(theRecord).length > 0) {
|
|
872
1103
|
// If this is not a test force the data dependent updates to the DOM
|
|
873
1104
|
formGenerator.updateDataDependentDisplay(theRecord, null, true, scope);
|
|
@@ -916,7 +1147,7 @@ var fng;
|
|
|
916
1147
|
/*@ngInject*/
|
|
917
1148
|
SearchCtrl.$inject = ["$scope", "$http", "$location", "routingService"];
|
|
918
1149
|
function SearchCtrl($scope, $http, $location, routingService) {
|
|
919
|
-
var
|
|
1150
|
+
var lastSearchSent;
|
|
920
1151
|
var _isNotMobile;
|
|
921
1152
|
_isNotMobile = (function () {
|
|
922
1153
|
var check = false;
|
|
@@ -971,9 +1202,15 @@ var fng;
|
|
|
971
1202
|
};
|
|
972
1203
|
$scope.selectResult = function (resultNo) {
|
|
973
1204
|
var result = $scope.results[resultNo];
|
|
974
|
-
var newURL
|
|
975
|
-
if (result.
|
|
976
|
-
newURL
|
|
1205
|
+
var newURL;
|
|
1206
|
+
if (result.url) {
|
|
1207
|
+
newURL = result.url.replace('|id|', result.id);
|
|
1208
|
+
}
|
|
1209
|
+
else {
|
|
1210
|
+
newURL = routingService.prefix() + '/' + result.resource + '/' + result.id + '/edit';
|
|
1211
|
+
if (result.resourceTab) {
|
|
1212
|
+
newURL += '/' + result.resourceTab;
|
|
1213
|
+
}
|
|
977
1214
|
}
|
|
978
1215
|
$location.url(newURL);
|
|
979
1216
|
};
|
|
@@ -992,12 +1229,12 @@ var fng;
|
|
|
992
1229
|
};
|
|
993
1230
|
$scope.$watch('searchTarget', function (newValue) {
|
|
994
1231
|
if (newValue && newValue.length > 0) {
|
|
995
|
-
|
|
996
|
-
$http.get('/api/search?q=' + newValue).then(function (response) {
|
|
1232
|
+
lastSearchSent = $scope.testTime || new Date().valueOf();
|
|
1233
|
+
$http.get('/api/search?q=' + newValue + '&sentAt=' + lastSearchSent).then(function (response) {
|
|
997
1234
|
var data = response.data;
|
|
998
1235
|
// Check that we haven't fired off a subsequent request, in which
|
|
999
1236
|
// case we are no longer interested in these results
|
|
1000
|
-
if (
|
|
1237
|
+
if (!data.timestamps || !data.timestamps.sentAt || Number.parseInt(data.timestamps.sentAt) === lastSearchSent) {
|
|
1001
1238
|
if ($scope.searchTarget.length > 0) {
|
|
1002
1239
|
$scope.results = data.results;
|
|
1003
1240
|
$scope.moreCount = data.moreCount;
|
|
@@ -1064,6 +1301,21 @@ var fng;
|
|
|
1064
1301
|
})(fng || (fng = {}));
|
|
1065
1302
|
/// <reference path="../../../../node_modules/@types/angular/index.d.ts" />
|
|
1066
1303
|
var fng;
|
|
1304
|
+
(function (fng) {
|
|
1305
|
+
var filters;
|
|
1306
|
+
(function (filters) {
|
|
1307
|
+
/*@ngInject*/
|
|
1308
|
+
function extractTimestampFromMongoID() {
|
|
1309
|
+
return function (id) {
|
|
1310
|
+
var timestamp = id.substring(0, 8);
|
|
1311
|
+
return new Date(parseInt(timestamp, 16) * 1000);
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
filters.extractTimestampFromMongoID = extractTimestampFromMongoID;
|
|
1315
|
+
})(filters = fng.filters || (fng.filters = {}));
|
|
1316
|
+
})(fng || (fng = {}));
|
|
1317
|
+
/// <reference path="../../../../node_modules/@types/angular/index.d.ts" />
|
|
1318
|
+
var fng;
|
|
1067
1319
|
(function (fng) {
|
|
1068
1320
|
var filters;
|
|
1069
1321
|
(function (filters) {
|
|
@@ -1244,6 +1496,7 @@ var fng;
|
|
|
1244
1496
|
controllerName += 'Ctrl';
|
|
1245
1497
|
locals.$scope = sharedData.modelControllers[level] = localScope;
|
|
1246
1498
|
var parentScope = localScope.$parent;
|
|
1499
|
+
parentScope.items = parentScope.items || [];
|
|
1247
1500
|
var addMenuOptions = function (array) {
|
|
1248
1501
|
angular.forEach(array, function (value) {
|
|
1249
1502
|
if (value.divider) {
|
|
@@ -1275,6 +1528,11 @@ var fng;
|
|
|
1275
1528
|
locals.$scope.contextMenuPromise.then(function (array) { return addMenuOptions(array); });
|
|
1276
1529
|
}
|
|
1277
1530
|
}
|
|
1531
|
+
if (sharedData.modelNameDisplayPromise) {
|
|
1532
|
+
sharedData.modelNameDisplayPromise.then(function (value) {
|
|
1533
|
+
parentScope.modelNameDisplay = value;
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1278
1536
|
}
|
|
1279
1537
|
catch (error) {
|
|
1280
1538
|
// Check to see if error is no such controller - don't care
|
|
@@ -1304,7 +1562,7 @@ var fng;
|
|
|
1304
1562
|
routing: 'ngroute',
|
|
1305
1563
|
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
1564
|
};
|
|
1307
|
-
var postActions = ['edit'];
|
|
1565
|
+
var postActions = ['edit', 'view'];
|
|
1308
1566
|
var builtInRoutes = [
|
|
1309
1567
|
{
|
|
1310
1568
|
route: '/analyse/:model/:reportSchemaName',
|
|
@@ -1314,12 +1572,19 @@ var fng;
|
|
|
1314
1572
|
{ route: '/analyse/:model', state: 'analyse::model', templateUrl: 'base-analysis.html' },
|
|
1315
1573
|
{ route: '/:model/:id/edit', state: 'model::edit', templateUrl: 'base-edit.html' },
|
|
1316
1574
|
{ route: '/:model/:id/edit/:tab', state: 'model::edit::tab', templateUrl: 'base-edit.html' },
|
|
1575
|
+
{ route: '/:model/:id/view', state: 'model::edit', templateUrl: 'base-view.html' },
|
|
1576
|
+
{ route: '/:model/:id/view/:tab', state: 'model::view::tab', templateUrl: 'base-view.html' },
|
|
1317
1577
|
{ route: '/:model/new', state: 'model::new', templateUrl: 'base-edit.html' },
|
|
1318
1578
|
{ route: '/:model', state: 'model::list', templateUrl: 'base-list.html' },
|
|
1579
|
+
{ route: '/:model/viewonly', state: 'model::view', templateUrl: 'base-list-view.html' },
|
|
1580
|
+
// Non default form (subset of fields etc)
|
|
1319
1581
|
{ route: '/:model/:form/:id/edit', state: 'model::form::edit', templateUrl: 'base-edit.html' },
|
|
1320
1582
|
{ route: '/:model/:form/:id/edit/:tab', state: 'model::form::edit::tab', templateUrl: 'base-edit.html' },
|
|
1583
|
+
{ route: '/:model/:form/:id/view', state: 'model::form::view', templateUrl: 'base-view.html' },
|
|
1584
|
+
{ route: '/:model/:form/:id/view/:tab', state: 'model::form::view::tab', templateUrl: 'base-view.html' },
|
|
1321
1585
|
{ route: '/:model/:form/new', state: 'model::form::new', templateUrl: 'base-edit.html' },
|
|
1322
|
-
{ route: '/:model/:form', state: 'model::form::list', templateUrl: 'base-list.html' }
|
|
1586
|
+
{ route: '/:model/:form', state: 'model::form::list', templateUrl: 'base-list.html' },
|
|
1587
|
+
{ route: '/:model/:form/viewonly', state: 'model::form::list::view', templateUrl: 'base-list-view.html' } // list page with edit links to non default form
|
|
1323
1588
|
];
|
|
1324
1589
|
var _routeProvider, _stateProvider;
|
|
1325
1590
|
var lastRoute = null;
|
|
@@ -1373,6 +1638,12 @@ var fng;
|
|
|
1373
1638
|
case 'edit':
|
|
1374
1639
|
urlStr = modelString + formString + '/' + id + '/edit' + tabString;
|
|
1375
1640
|
break;
|
|
1641
|
+
case 'view':
|
|
1642
|
+
urlStr = modelString + formString + '/' + id + '/view' + tabString;
|
|
1643
|
+
break;
|
|
1644
|
+
case 'read':
|
|
1645
|
+
urlStr = modelString + formString + '/' + id + '/read' + tabString;
|
|
1646
|
+
break;
|
|
1376
1647
|
case 'new':
|
|
1377
1648
|
urlStr = modelString + formString + '/new' + tabString;
|
|
1378
1649
|
break;
|
|
@@ -1455,8 +1726,9 @@ var fng;
|
|
|
1455
1726
|
lastObject.modelName = locationSplit[1];
|
|
1456
1727
|
var lastParts_1 = [locationSplit[locationParts - 1], locationSplit[locationParts - 2]];
|
|
1457
1728
|
var newPos = lastParts_1.indexOf('new');
|
|
1729
|
+
var viewonlyPos = lastParts_1.indexOf('viewonly');
|
|
1458
1730
|
var actionPos = void 0;
|
|
1459
|
-
if (newPos === -1) {
|
|
1731
|
+
if (newPos === -1 && viewonlyPos === -1) {
|
|
1460
1732
|
actionPos = postActions.reduce(function (previousValue, currentValue) {
|
|
1461
1733
|
var pos = lastParts_1.indexOf(currentValue);
|
|
1462
1734
|
return pos > -1 ? pos : previousValue;
|
|
@@ -1466,10 +1738,13 @@ var fng;
|
|
|
1466
1738
|
lastObject.id = locationSplit[locationParts];
|
|
1467
1739
|
}
|
|
1468
1740
|
}
|
|
1469
|
-
else {
|
|
1741
|
+
else if (newPos !== -1) {
|
|
1470
1742
|
lastObject.newRecord = true;
|
|
1471
1743
|
locationParts -= (1 + newPos);
|
|
1472
1744
|
}
|
|
1745
|
+
else {
|
|
1746
|
+
locationParts -= (1 + viewonlyPos);
|
|
1747
|
+
}
|
|
1473
1748
|
if (actionPos === 1 || newPos === 1) {
|
|
1474
1749
|
lastObject.tab = lastParts_1[0];
|
|
1475
1750
|
}
|
|
@@ -1480,34 +1755,6 @@ var fng;
|
|
|
1480
1755
|
}
|
|
1481
1756
|
return lastObject;
|
|
1482
1757
|
};
|
|
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
1758
|
},
|
|
1512
1759
|
buildUrl: function (path) {
|
|
1513
1760
|
var url = config.html5Mode ? '' : '#';
|
|
@@ -1524,46 +1771,25 @@ var fng;
|
|
|
1524
1771
|
},
|
|
1525
1772
|
redirectTo: function () {
|
|
1526
1773
|
return function (operation, scope, location, id, tab) {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
if (
|
|
1530
|
-
|
|
1774
|
+
location.search({}); // Lose any search parameters
|
|
1775
|
+
var urlStr;
|
|
1776
|
+
if (operation === 'onDelete') {
|
|
1777
|
+
if (config.onDelete) {
|
|
1778
|
+
if (config.onDelete === 'new') {
|
|
1779
|
+
urlStr = _buildOperationUrl(config.prefix, 'new', scope.modelName, scope.formName, id, tab);
|
|
1780
|
+
}
|
|
1781
|
+
else {
|
|
1782
|
+
urlStr = config.onDelete;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
else {
|
|
1786
|
+
urlStr = _buildOperationUrl(config.prefix, 'list', scope.modelName, scope.formName, id, tab);
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
else {
|
|
1790
|
+
urlStr = _buildOperationUrl(config.prefix, operation, scope.modelName, scope.formName, id, tab);
|
|
1531
1791
|
}
|
|
1532
|
-
var urlStr = _buildOperationUrl(config.prefix, operation, scope.modelName, scope.formName, id, tab);
|
|
1533
1792
|
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
1793
|
};
|
|
1568
1794
|
}
|
|
1569
1795
|
};
|
|
@@ -1585,7 +1811,7 @@ var fng;
|
|
|
1585
1811
|
* All methods should be state-less
|
|
1586
1812
|
*
|
|
1587
1813
|
*/
|
|
1588
|
-
function formGenerator($location, $timeout, $filter,
|
|
1814
|
+
function formGenerator($location, $timeout, $filter, routingService, recordHandler) {
|
|
1589
1815
|
function handleSchema(description, source, destForm, destList, prefix, doRecursion, $scope, ctrlState) {
|
|
1590
1816
|
function handletabInfo(tabName, thisInst) {
|
|
1591
1817
|
var tabTitle = angular.copy(tabName);
|
|
@@ -1611,50 +1837,55 @@ var fng;
|
|
|
1611
1837
|
}
|
|
1612
1838
|
tab.content.push(thisInst);
|
|
1613
1839
|
}
|
|
1840
|
+
if (typeof $scope.onSchemaFetch === "function") {
|
|
1841
|
+
$scope.onSchemaFetch(description, source);
|
|
1842
|
+
}
|
|
1614
1843
|
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
|
-
}
|
|
1844
|
+
if (source.hasOwnProperty(field)) {
|
|
1845
|
+
if (field === '_id') {
|
|
1846
|
+
if (destList && source['_id'].options && source['_id'].options.list) {
|
|
1847
|
+
handleListInfo(destList, source['_id'].options.list, field);
|
|
1638
1848
|
}
|
|
1639
1849
|
}
|
|
1640
|
-
else {
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1850
|
+
else if (source.hasOwnProperty(field)) {
|
|
1851
|
+
var mongooseType = source[field], mongooseOptions = mongooseType.options || {};
|
|
1852
|
+
var formData = mongooseOptions.form || {};
|
|
1853
|
+
if (mongooseType.schema && !formData.hidden) {
|
|
1854
|
+
if (doRecursion && destForm) {
|
|
1855
|
+
var schemaSchema = [];
|
|
1856
|
+
handleSchema('Nested ' + field, mongooseType.schema, schemaSchema, null, field + '.', true, $scope, ctrlState);
|
|
1857
|
+
var sectionInstructions = basicInstructions(field, formData, prefix);
|
|
1858
|
+
sectionInstructions.schema = schemaSchema;
|
|
1859
|
+
if (formData.tab) {
|
|
1860
|
+
handletabInfo(formData.tab, sectionInstructions);
|
|
1647
1861
|
}
|
|
1648
1862
|
if (formData.order !== undefined) {
|
|
1649
|
-
destForm.splice(formData.order, 0,
|
|
1863
|
+
destForm.splice(formData.order, 0, sectionInstructions);
|
|
1650
1864
|
}
|
|
1651
1865
|
else {
|
|
1652
|
-
destForm.push(
|
|
1866
|
+
destForm.push(sectionInstructions);
|
|
1653
1867
|
}
|
|
1654
1868
|
}
|
|
1655
1869
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1870
|
+
else {
|
|
1871
|
+
if (destForm && !formData.hidden) {
|
|
1872
|
+
var formInstructions = basicInstructions(field, formData, prefix);
|
|
1873
|
+
if (handleConditionals(formInstructions.showIf, formInstructions.name, $scope) && field !== 'options') {
|
|
1874
|
+
var formInst = handleFieldType(formInstructions, mongooseType, mongooseOptions, $scope, ctrlState);
|
|
1875
|
+
if (formInst.tab) {
|
|
1876
|
+
handletabInfo(formInst.tab, formInst);
|
|
1877
|
+
}
|
|
1878
|
+
if (formData.order !== undefined) {
|
|
1879
|
+
destForm.splice(formData.order, 0, formInst);
|
|
1880
|
+
}
|
|
1881
|
+
else {
|
|
1882
|
+
destForm.push(formInst);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
if (destList && mongooseOptions.list) {
|
|
1887
|
+
handleListInfo(destList, mongooseOptions.list, field);
|
|
1888
|
+
}
|
|
1658
1889
|
}
|
|
1659
1890
|
}
|
|
1660
1891
|
}
|
|
@@ -1678,6 +1909,9 @@ var fng;
|
|
|
1678
1909
|
// console.log($scope.tabs[0]['title'])
|
|
1679
1910
|
// $location.hash($scope.tabs[0]['title']);
|
|
1680
1911
|
// }
|
|
1912
|
+
if (typeof $scope.onSchemaProcessed === "function") {
|
|
1913
|
+
$scope.onSchemaProcessed(description, description.slice(0, 5) === 'Main ' ? $scope.baseSchema() : destForm);
|
|
1914
|
+
}
|
|
1681
1915
|
if (destList && destList.length === 0) {
|
|
1682
1916
|
handleEmptyList(description, destList, destForm, source);
|
|
1683
1917
|
}
|
|
@@ -1686,23 +1920,23 @@ var fng;
|
|
|
1686
1920
|
function performLookupSelect() {
|
|
1687
1921
|
formInstructions.options = recordHandler.suffixCleanId(formInstructions, 'Options');
|
|
1688
1922
|
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
|
-
|
|
1923
|
+
if (!formInstructions.hidden) {
|
|
1924
|
+
if (mongooseOptions.ref) {
|
|
1925
|
+
recordHandler.setUpLookupOptions(mongooseOptions.ref, formInstructions, $scope, ctrlState, handleSchema);
|
|
1926
|
+
}
|
|
1927
|
+
else if (mongooseOptions.lookupListRef) {
|
|
1928
|
+
recordHandler.setUpLookupListOptions(mongooseOptions.lookupListRef, formInstructions, $scope, ctrlState);
|
|
1929
|
+
formInstructions.lookupListRef = mongooseOptions.lookupListRef;
|
|
1930
|
+
}
|
|
1931
|
+
else if (mongooseOptions.internalRef) {
|
|
1932
|
+
recordHandler.handleInternalLookup($scope, formInstructions, mongooseOptions.internalRef);
|
|
1933
|
+
formInstructions.internalRef = mongooseOptions.internalRef;
|
|
1934
|
+
}
|
|
1935
|
+
else if (mongooseOptions.customLookupOptions) {
|
|
1936
|
+
// nothing to do - call setUpCustomLookupOptions() when ready to provide id and option arrays
|
|
1937
|
+
}
|
|
1938
|
+
else {
|
|
1939
|
+
throw new Error("No supported select lookup type found in " + formInstructions.name);
|
|
1706
1940
|
}
|
|
1707
1941
|
}
|
|
1708
1942
|
}
|
|
@@ -1736,13 +1970,22 @@ var fng;
|
|
|
1736
1970
|
}
|
|
1737
1971
|
else if (mongooseType.instance === 'ObjectID') {
|
|
1738
1972
|
formInstructions.ref = mongooseOptions.ref;
|
|
1739
|
-
if (formInstructions.link
|
|
1740
|
-
formInstructions.
|
|
1741
|
-
|
|
1973
|
+
if (formInstructions.link) {
|
|
1974
|
+
if (formInstructions.link.linkOnly) {
|
|
1975
|
+
formInstructions.type = 'link';
|
|
1976
|
+
formInstructions.linktext = formInstructions.link.text;
|
|
1977
|
+
}
|
|
1978
|
+
else if (formInstructions.link.label) {
|
|
1979
|
+
formInstructions.linklabel = true;
|
|
1980
|
+
}
|
|
1981
|
+
else {
|
|
1982
|
+
console.log('Unsupported link setup');
|
|
1983
|
+
}
|
|
1742
1984
|
formInstructions.form = formInstructions.link.form;
|
|
1985
|
+
formInstructions.linktab = formInstructions.link.linktab;
|
|
1743
1986
|
delete formInstructions.link;
|
|
1744
1987
|
}
|
|
1745
|
-
|
|
1988
|
+
if (formInstructions.type !== 'link') {
|
|
1746
1989
|
formInstructions.type = 'select';
|
|
1747
1990
|
if (formInstructions.select2 || (mongooseOptions.form && mongooseOptions.form.select2)) {
|
|
1748
1991
|
console.log('support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select');
|
|
@@ -1754,16 +1997,18 @@ var fng;
|
|
|
1754
1997
|
}
|
|
1755
1998
|
else if (mongooseType.instance === 'Date') {
|
|
1756
1999
|
if (!formInstructions.type) {
|
|
2000
|
+
formInstructions.intType = 'date';
|
|
1757
2001
|
if (formInstructions.readonly) {
|
|
1758
2002
|
formInstructions.type = 'text';
|
|
1759
2003
|
}
|
|
1760
2004
|
else if (formInstructions.directive) {
|
|
1761
|
-
formInstructions.type = 'text';
|
|
2005
|
+
formInstructions.type = 'text';
|
|
1762
2006
|
}
|
|
1763
2007
|
else {
|
|
1764
2008
|
try {
|
|
1765
2009
|
formInstructions.add = formInstructions.add || '';
|
|
1766
|
-
|
|
2010
|
+
// Check whether DatePicker is installed
|
|
2011
|
+
angular.module('ui.date').requires;
|
|
1767
2012
|
formInstructions.type = 'text';
|
|
1768
2013
|
formInstructions.add += ' ui-date ui-date-format ';
|
|
1769
2014
|
// formInstructions.add += ' ui-date ui-date-format datepicker-popup-fix ';
|
|
@@ -1776,10 +2021,10 @@ var fng;
|
|
|
1776
2021
|
}
|
|
1777
2022
|
}
|
|
1778
2023
|
else if (mongooseType.instance.toLowerCase() === 'boolean') {
|
|
1779
|
-
formInstructions.type = 'checkbox';
|
|
2024
|
+
formInstructions.type = formInstructions.type || 'checkbox';
|
|
1780
2025
|
}
|
|
1781
2026
|
else if (mongooseType.instance === 'Number') {
|
|
1782
|
-
formInstructions.type = 'number';
|
|
2027
|
+
formInstructions.type = formInstructions.type || 'number';
|
|
1783
2028
|
if (mongooseOptions.min !== undefined) {
|
|
1784
2029
|
formInstructions.add = 'min="' + mongooseOptions.min + '" ' + (formInstructions.add || '');
|
|
1785
2030
|
}
|
|
@@ -1799,11 +2044,17 @@ var fng;
|
|
|
1799
2044
|
if (mongooseOptions.readonly) {
|
|
1800
2045
|
formInstructions['readonly'] = true;
|
|
1801
2046
|
}
|
|
2047
|
+
if (mongooseType.defaultValue !== undefined) {
|
|
2048
|
+
formInstructions.defaultValue = mongooseType.defaultValue;
|
|
2049
|
+
}
|
|
2050
|
+
else if (mongooseType.options && mongooseType.options.default !== undefined) {
|
|
2051
|
+
console.log('No support for default with no value, yet');
|
|
2052
|
+
}
|
|
1802
2053
|
return formInstructions;
|
|
1803
2054
|
}
|
|
1804
|
-
function getArrayFieldToExtend(fieldName, $scope) {
|
|
2055
|
+
function getArrayFieldToExtend(fieldName, $scope, modelOverride) {
|
|
1805
2056
|
var fieldParts = fieldName.split('.');
|
|
1806
|
-
var arrayField = $scope.record;
|
|
2057
|
+
var arrayField = modelOverride || $scope.record;
|
|
1807
2058
|
for (var i = 0, l = fieldParts.length; i < l; i++) {
|
|
1808
2059
|
if (!arrayField[fieldParts[i]]) {
|
|
1809
2060
|
if (i === l - 1) {
|
|
@@ -1920,6 +2171,9 @@ var fng;
|
|
|
1920
2171
|
generateEditUrl: function generateEditUrl(obj, $scope) {
|
|
1921
2172
|
return routingService.buildUrl($scope.modelName + '/' + ($scope.formName ? $scope.formName + '/' : '') + obj._id + '/edit');
|
|
1922
2173
|
},
|
|
2174
|
+
generateViewUrl: function generateViewUrl(obj, $scope) {
|
|
2175
|
+
return routingService.buildUrl($scope.modelName + '/' + ($scope.formName ? $scope.formName + '/' : '') + obj._id + '/view');
|
|
2176
|
+
},
|
|
1923
2177
|
generateNewUrl: function generateNewUrl($scope) {
|
|
1924
2178
|
return routingService.buildUrl($scope.modelName + '/' + ($scope.formName ? $scope.formName + '/' : '') + 'new');
|
|
1925
2179
|
},
|
|
@@ -2004,25 +2258,44 @@ var fng;
|
|
|
2004
2258
|
}
|
|
2005
2259
|
return forceNextTime;
|
|
2006
2260
|
},
|
|
2007
|
-
add: function add(fieldName, $event, $scope) {
|
|
2008
|
-
var
|
|
2009
|
-
|
|
2010
|
-
|
|
2261
|
+
add: function add(fieldName, $event, $scope, modelOverride) {
|
|
2262
|
+
var _a;
|
|
2263
|
+
// check that target element is visible. May not be reliable - see https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom
|
|
2264
|
+
if ($event.target.offsetParent) {
|
|
2265
|
+
var arrayField = getArrayFieldToExtend(fieldName, $scope, modelOverride);
|
|
2266
|
+
var schemaElement = $scope.formSchema.find(function (f) { return f.name === fieldName; }); // In case someone is using the formSchema directly
|
|
2267
|
+
var subSchema = schemaElement ? schemaElement.schema : null;
|
|
2268
|
+
var obj = subSchema ? $scope.setDefaults(subSchema, fieldName + '.') : {};
|
|
2269
|
+
if (typeof ((_a = $scope.dataEventFunctions) === null || _a === void 0 ? void 0 : _a.onInitialiseNewSubDoc) === "function") {
|
|
2270
|
+
$scope.dataEventFunctions.onInitialiseNewSubDoc(fieldName, subSchema, obj);
|
|
2271
|
+
}
|
|
2272
|
+
arrayField.push(obj);
|
|
2273
|
+
$scope.setFormDirty($event);
|
|
2274
|
+
}
|
|
2011
2275
|
},
|
|
2012
|
-
unshift: function unshift(fieldName, $event, $scope) {
|
|
2013
|
-
var arrayField = getArrayFieldToExtend(fieldName, $scope);
|
|
2276
|
+
unshift: function unshift(fieldName, $event, $scope, modelOverride) {
|
|
2277
|
+
var arrayField = getArrayFieldToExtend(fieldName, $scope, modelOverride);
|
|
2014
2278
|
arrayField.unshift({});
|
|
2015
2279
|
$scope.setFormDirty($event);
|
|
2016
2280
|
},
|
|
2017
|
-
remove: function remove(fieldName, value, $event, $scope) {
|
|
2281
|
+
remove: function remove(fieldName, value, $event, $scope, modelOverride) {
|
|
2018
2282
|
// Remove an element from an array
|
|
2019
|
-
var
|
|
2020
|
-
var
|
|
2021
|
-
|
|
2022
|
-
|
|
2283
|
+
var arrayField = getArrayFieldToExtend(fieldName, $scope, modelOverride);
|
|
2284
|
+
var err;
|
|
2285
|
+
if (typeof $scope.dataEventFunctions.onDeleteSubDoc === "function") {
|
|
2286
|
+
var schemaElement = $scope.formSchema.find(function (f) {
|
|
2287
|
+
return f.name === fieldName;
|
|
2288
|
+
});
|
|
2289
|
+
var subSchema = schemaElement ? schemaElement.schema : null;
|
|
2290
|
+
err = $scope.dataEventFunctions.onDeleteSubDoc(fieldName, subSchema, arrayField, value);
|
|
2291
|
+
}
|
|
2292
|
+
if (err) {
|
|
2293
|
+
$scope.showError(err);
|
|
2294
|
+
}
|
|
2295
|
+
else {
|
|
2296
|
+
arrayField.splice(value, 1);
|
|
2297
|
+
$scope.setFormDirty($event);
|
|
2023
2298
|
}
|
|
2024
|
-
arrayField.splice(value, 1);
|
|
2025
|
-
$scope.setFormDirty($event);
|
|
2026
2299
|
},
|
|
2027
2300
|
hasError: function hasError(formName, name, index, $scope) {
|
|
2028
2301
|
var result = false;
|
|
@@ -2034,7 +2307,7 @@ var fng;
|
|
|
2034
2307
|
// Cannot assume that directives will use the same methods
|
|
2035
2308
|
if (form) {
|
|
2036
2309
|
var field_1 = form[name];
|
|
2037
|
-
if (field_1 && field_1.$invalid) {
|
|
2310
|
+
if (field_1 && field_1.$invalid && !field_1.$$attr.readonly) {
|
|
2038
2311
|
if (field_1.$dirty) {
|
|
2039
2312
|
result = true;
|
|
2040
2313
|
}
|
|
@@ -2074,6 +2347,9 @@ var fng;
|
|
|
2074
2347
|
$scope.generateEditUrl = function (obj) {
|
|
2075
2348
|
return formGeneratorInstance.generateEditUrl(obj, $scope);
|
|
2076
2349
|
};
|
|
2350
|
+
$scope.generateViewUrl = function (obj) {
|
|
2351
|
+
return formGeneratorInstance.generateViewUrl(obj, $scope);
|
|
2352
|
+
};
|
|
2077
2353
|
$scope.generateNewUrl = function () {
|
|
2078
2354
|
return formGeneratorInstance.generateNewUrl($scope);
|
|
2079
2355
|
};
|
|
@@ -2081,7 +2357,7 @@ var fng;
|
|
|
2081
2357
|
return recordHandlerInstance.scrollTheList($scope);
|
|
2082
2358
|
};
|
|
2083
2359
|
$scope.getListData = function (record, fieldName) {
|
|
2084
|
-
return recordHandlerInstance.getListData(
|
|
2360
|
+
return recordHandlerInstance.getListData(record, fieldName, $scope.listSchema, $scope);
|
|
2085
2361
|
};
|
|
2086
2362
|
$scope.setPristine = function (clearErrors) {
|
|
2087
2363
|
if (clearErrors) {
|
|
@@ -2103,17 +2379,17 @@ var fng;
|
|
|
2103
2379
|
console.log('setFormDirty called without an event (fine in a unit test)');
|
|
2104
2380
|
}
|
|
2105
2381
|
};
|
|
2106
|
-
$scope.add = function (fieldName, $event) {
|
|
2107
|
-
return formGeneratorInstance.add(fieldName, $event, $scope);
|
|
2382
|
+
$scope.add = function (fieldName, $event, modelOverride) {
|
|
2383
|
+
return formGeneratorInstance.add(fieldName, $event, $scope, modelOverride);
|
|
2108
2384
|
};
|
|
2109
2385
|
$scope.hasError = function (form, name, index) {
|
|
2110
2386
|
return formGeneratorInstance.hasError(form, name, index, $scope);
|
|
2111
2387
|
};
|
|
2112
|
-
$scope.unshift = function (fieldName, $event) {
|
|
2113
|
-
return formGeneratorInstance.unshift(fieldName, $event, $scope);
|
|
2388
|
+
$scope.unshift = function (fieldName, $event, modelOverride) {
|
|
2389
|
+
return formGeneratorInstance.unshift(fieldName, $event, $scope, modelOverride);
|
|
2114
2390
|
};
|
|
2115
|
-
$scope.remove = function (fieldName, value, $event) {
|
|
2116
|
-
return formGeneratorInstance.remove(fieldName, value, $event, $scope);
|
|
2391
|
+
$scope.remove = function (fieldName, value, $event, modelOverride) {
|
|
2392
|
+
return formGeneratorInstance.remove(fieldName, value, $event, $scope, modelOverride);
|
|
2117
2393
|
};
|
|
2118
2394
|
$scope.baseSchema = function () {
|
|
2119
2395
|
return ($scope.tabs.length ? $scope.tabs : $scope.formSchema);
|
|
@@ -2128,7 +2404,7 @@ var fng;
|
|
|
2128
2404
|
};
|
|
2129
2405
|
}
|
|
2130
2406
|
services.formGenerator = formGenerator;
|
|
2131
|
-
formGenerator.$inject = ["$location", "$timeout", "$filter", "
|
|
2407
|
+
formGenerator.$inject = ["$location", "$timeout", "$filter", "routingService", "recordHandler"];
|
|
2132
2408
|
})(services = fng.services || (fng.services = {}));
|
|
2133
2409
|
})(fng || (fng = {}));
|
|
2134
2410
|
/// <reference path="../../index.d.ts" />
|
|
@@ -2137,8 +2413,8 @@ var fng;
|
|
|
2137
2413
|
var services;
|
|
2138
2414
|
(function (services) {
|
|
2139
2415
|
/*@ngInject*/
|
|
2140
|
-
formMarkupHelper.$inject = ["cssFrameworkService", "inputSizeHelper", "addAllService"];
|
|
2141
|
-
function formMarkupHelper(cssFrameworkService, inputSizeHelper, addAllService) {
|
|
2416
|
+
formMarkupHelper.$inject = ["cssFrameworkService", "inputSizeHelper", "addAllService", "$filter"];
|
|
2417
|
+
function formMarkupHelper(cssFrameworkService, inputSizeHelper, addAllService, $filter) {
|
|
2142
2418
|
function generateNgShow(showWhen, model) {
|
|
2143
2419
|
function evaluateSide(side) {
|
|
2144
2420
|
var result = side;
|
|
@@ -2166,11 +2442,15 @@ var fng;
|
|
|
2166
2442
|
}
|
|
2167
2443
|
return evaluateSide(showWhen.lhs) + conditionSymbols[conditionPos] + evaluateSide(showWhen.rhs);
|
|
2168
2444
|
}
|
|
2169
|
-
var isHorizontalStyle = function isHorizontalStyle(formStyle) {
|
|
2170
|
-
|
|
2445
|
+
var isHorizontalStyle = function isHorizontalStyle(formStyle, includeStacked) {
|
|
2446
|
+
var exclude = ['vertical', 'inline'];
|
|
2447
|
+
if (!includeStacked) {
|
|
2448
|
+
exclude.push('stacked');
|
|
2449
|
+
}
|
|
2450
|
+
return (!formStyle || formStyle === 'undefined' || !exclude.includes(formStyle));
|
|
2171
2451
|
};
|
|
2172
2452
|
function glyphClass() {
|
|
2173
|
-
return (cssFrameworkService.framework() === 'bs2'
|
|
2453
|
+
return (cssFrameworkService.framework() === 'bs2' ? 'icon' : 'glyphicon glyphicon');
|
|
2174
2454
|
}
|
|
2175
2455
|
return {
|
|
2176
2456
|
isHorizontalStyle: isHorizontalStyle,
|
|
@@ -2188,7 +2468,9 @@ var fng;
|
|
|
2188
2468
|
insert += 'ng-show="' + generateNgShow(info.showWhen, options.model) + '"';
|
|
2189
2469
|
}
|
|
2190
2470
|
}
|
|
2191
|
-
|
|
2471
|
+
if (info.id && typeof info.id.replace === "function") {
|
|
2472
|
+
insert += ' id="cg_' + info.id.replace(/\./g, '-') + '"';
|
|
2473
|
+
}
|
|
2192
2474
|
if (cssFrameworkService.framework() === 'bs3') {
|
|
2193
2475
|
classes += ' form-group';
|
|
2194
2476
|
if (options.formstyle === 'vertical' && info.size !== 'block-level') {
|
|
@@ -2213,7 +2495,7 @@ var fng;
|
|
|
2213
2495
|
closeTag += '</div>';
|
|
2214
2496
|
}
|
|
2215
2497
|
else {
|
|
2216
|
-
if (isHorizontalStyle(options.formstyle)) {
|
|
2498
|
+
if (isHorizontalStyle(options.formstyle, true)) {
|
|
2217
2499
|
template += '<div' + addAllService.addAll(scope, 'Group', 'control-group', options);
|
|
2218
2500
|
closeTag = '</div>';
|
|
2219
2501
|
}
|
|
@@ -2227,11 +2509,13 @@ var fng;
|
|
|
2227
2509
|
},
|
|
2228
2510
|
label: function label(scope, fieldInfo, addButtonMarkup, options) {
|
|
2229
2511
|
var labelHTML = '';
|
|
2230
|
-
if ((cssFrameworkService.framework() === 'bs3' || (options.formstyle
|
|
2512
|
+
if ((cssFrameworkService.framework() === 'bs3' || (!['inline', 'stacked'].includes(options.formstyle) && fieldInfo.label !== '')) || addButtonMarkup) {
|
|
2231
2513
|
labelHTML = '<label';
|
|
2232
2514
|
var classes = 'control-label';
|
|
2233
|
-
if (isHorizontalStyle(options.formstyle)) {
|
|
2234
|
-
|
|
2515
|
+
if (isHorizontalStyle(options.formstyle, false)) {
|
|
2516
|
+
if (!fieldInfo.linklabel) {
|
|
2517
|
+
labelHTML += ' for="' + fieldInfo.id + '"';
|
|
2518
|
+
}
|
|
2235
2519
|
if (typeof fieldInfo.labelDefaultClass !== 'undefined') {
|
|
2236
2520
|
// Override default label class (can be empty)
|
|
2237
2521
|
classes += ' ' + fieldInfo.labelDefaultClass;
|
|
@@ -2240,7 +2524,7 @@ var fng;
|
|
|
2240
2524
|
classes += ' col-sm-3';
|
|
2241
2525
|
}
|
|
2242
2526
|
}
|
|
2243
|
-
else if (options.formstyle
|
|
2527
|
+
else if (['inline', 'stacked'].includes(options.formstyle)) {
|
|
2244
2528
|
labelHTML += ' for="' + fieldInfo.id + '"';
|
|
2245
2529
|
classes += ' sr-only';
|
|
2246
2530
|
}
|
|
@@ -2249,6 +2533,17 @@ var fng;
|
|
|
2249
2533
|
labelHTML += ' <i id="add_' + fieldInfo.id + '" ng-click="add(\'' + fieldInfo.name + '\',$event)" class="' + glyphClass() + '-plus-sign"></i>';
|
|
2250
2534
|
}
|
|
2251
2535
|
labelHTML += '</label>';
|
|
2536
|
+
if (fieldInfo.linklabel) {
|
|
2537
|
+
var value = '<fng-link fld="' + fieldInfo.name + '" ref="' + fieldInfo.ref + '" text="' + escape(labelHTML) + '"';
|
|
2538
|
+
if (fieldInfo.form) {
|
|
2539
|
+
value += ' form="' + fieldInfo.form + '"';
|
|
2540
|
+
}
|
|
2541
|
+
if (fieldInfo.linktab) {
|
|
2542
|
+
value += ' linktab="' + fieldInfo.linktab + '"';
|
|
2543
|
+
}
|
|
2544
|
+
value += '></fng-link>';
|
|
2545
|
+
labelHTML = value;
|
|
2546
|
+
}
|
|
2252
2547
|
}
|
|
2253
2548
|
return labelHTML;
|
|
2254
2549
|
},
|
|
@@ -2268,14 +2563,17 @@ var fng;
|
|
|
2268
2563
|
else {
|
|
2269
2564
|
sizeClassBS2 = (fieldInfo.size ? ' input-' + fieldInfo.size : '');
|
|
2270
2565
|
}
|
|
2271
|
-
if (options.formstyle
|
|
2566
|
+
if (['inline', 'stacked'].includes(options.formstyle)) {
|
|
2272
2567
|
placeHolder = placeHolder || fieldInfo.label;
|
|
2273
2568
|
}
|
|
2274
|
-
common = 'ng-model="' + modelString + '"' + (idString ? ' id="' + idString + '" name="' + idString + '" ' : ' name="' + nameString + '" ');
|
|
2569
|
+
common = 'data-ng-model="' + modelString + '"' + (idString ? ' id="' + idString + '" name="' + idString + '" ' : ' name="' + nameString + '" ');
|
|
2275
2570
|
common += (placeHolder ? ('placeholder="' + placeHolder + '" ') : '');
|
|
2276
2571
|
if (fieldInfo.popup) {
|
|
2277
2572
|
common += 'title="' + fieldInfo.popup + '" ';
|
|
2278
2573
|
}
|
|
2574
|
+
if (fieldInfo.ariaLabel) {
|
|
2575
|
+
common += 'aria-label="' + fieldInfo.ariaLabel + '" ';
|
|
2576
|
+
}
|
|
2279
2577
|
common += addAllService.addAll(scope, 'Field', null, options);
|
|
2280
2578
|
return {
|
|
2281
2579
|
common: common,
|
|
@@ -2286,28 +2584,36 @@ var fng;
|
|
|
2286
2584
|
};
|
|
2287
2585
|
},
|
|
2288
2586
|
inputChrome: function inputChrome(value, fieldInfo, options, markupVars) {
|
|
2289
|
-
if (cssFrameworkService.framework() === 'bs3' && isHorizontalStyle(options.formstyle) && fieldInfo.type !== 'checkbox') {
|
|
2587
|
+
if (cssFrameworkService.framework() === 'bs3' && isHorizontalStyle(options.formstyle, true) && fieldInfo.type !== 'checkbox') {
|
|
2290
2588
|
value = '<div class="bs3-input ' + markupVars.sizeClassBS3 + '">' + value + '</div>';
|
|
2291
2589
|
}
|
|
2292
2590
|
// Hack to cope with inline help in directives
|
|
2293
2591
|
var inlineHelp = (fieldInfo.helpInline || '') + (fieldInfo.helpinline || '');
|
|
2294
2592
|
if (inlineHelp.length > 0) {
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2593
|
+
var helpMarkup = cssFrameworkService.framework() === 'bs2' ? { el: 'span', cl: 'help-inline' } : { el: 'div', cl: 'help-block' };
|
|
2594
|
+
value += "<" + helpMarkup.el + " class=\"" + helpMarkup.cl + "\">" + inlineHelp + "</" + helpMarkup.el + ">";
|
|
2595
|
+
}
|
|
2596
|
+
if (!options.noid) {
|
|
2597
|
+
value += "<div ng-if=\"" + (options.name || 'myForm') + "['" + fieldInfo.id + "'].$dirty\" class=\"help-block\">" +
|
|
2598
|
+
(" <div ng-messages=\"" + (options.name || 'myForm') + "['" + fieldInfo.id + "'].$error\">") +
|
|
2599
|
+
' <div ng-messages-include="error-messages.html">' +
|
|
2600
|
+
' </div>' +
|
|
2601
|
+
' </div>' +
|
|
2602
|
+
'</div>';
|
|
2603
|
+
}
|
|
2304
2604
|
if (fieldInfo.help) {
|
|
2305
|
-
value += '<
|
|
2605
|
+
value += '<div class="help-block">' + fieldInfo.help + '</div>';
|
|
2306
2606
|
}
|
|
2307
2607
|
return value;
|
|
2308
2608
|
},
|
|
2309
2609
|
generateSimpleInput: function generateSimpleInput(common, fieldInfo, options) {
|
|
2310
|
-
var result = '<input ' + common + 'type="' + fieldInfo.type + '"';
|
|
2610
|
+
var result = '<input ' + common + 'type="' + fieldInfo.type + '" ';
|
|
2611
|
+
if (!fieldInfo.label && !fieldInfo.ariaLabel) {
|
|
2612
|
+
result += "aria-label=\"" + fieldInfo.name.replace(/\./g, ' ') + "\" ";
|
|
2613
|
+
}
|
|
2614
|
+
else if (options.subschema) {
|
|
2615
|
+
result += "aria-label=\"" + (fieldInfo.label ? ($filter('titleCase')(options.subschemaroot) + ' ' + fieldInfo.label) : (fieldInfo.popup || fieldInfo.name.replace(/\./g, ' '))) + "\" ";
|
|
2616
|
+
}
|
|
2311
2617
|
if (options.formstyle === 'inline' && cssFrameworkService.framework() === 'bs2' && !fieldInfo.size) {
|
|
2312
2618
|
result += 'class="input-small"';
|
|
2313
2619
|
}
|
|
@@ -2316,7 +2622,7 @@ var fng;
|
|
|
2316
2622
|
},
|
|
2317
2623
|
controlDivClasses: function controlDivClasses(options) {
|
|
2318
2624
|
var result = [];
|
|
2319
|
-
if (isHorizontalStyle(options.formstyle)) {
|
|
2625
|
+
if (isHorizontalStyle(options.formstyle, false)) {
|
|
2320
2626
|
result.push(cssFrameworkService.framework() === 'bs2' ? 'controls' : 'col-sm-9');
|
|
2321
2627
|
}
|
|
2322
2628
|
return result;
|
|
@@ -2350,7 +2656,13 @@ var fng;
|
|
|
2350
2656
|
if (fieldInfo.add) {
|
|
2351
2657
|
result += ' ' + fieldInfo.add + ' ';
|
|
2352
2658
|
}
|
|
2353
|
-
result += requiredStr
|
|
2659
|
+
result += requiredStr;
|
|
2660
|
+
if (fieldInfo.readonly) {
|
|
2661
|
+
result += " " + (typeof fieldInfo.readOnly === 'boolean' ? 'readonly' : 'ng-readonly="' + fieldInfo.readonly + '"') + " ";
|
|
2662
|
+
}
|
|
2663
|
+
else {
|
|
2664
|
+
result += ' ';
|
|
2665
|
+
}
|
|
2354
2666
|
return result;
|
|
2355
2667
|
}
|
|
2356
2668
|
};
|
|
@@ -2506,23 +2818,29 @@ var fng;
|
|
|
2506
2818
|
*
|
|
2507
2819
|
*/
|
|
2508
2820
|
/*@ngInject*/
|
|
2509
|
-
recordHandler.$inject = ["$
|
|
2510
|
-
function recordHandler($
|
|
2821
|
+
recordHandler.$inject = ["$location", "$window", "$filter", "$timeout", "routingService", "cssFrameworkService", "SubmissionsService", "SchemasService"];
|
|
2822
|
+
function recordHandler($location, $window, $filter, $timeout, routingService, cssFrameworkService, SubmissionsService, SchemasService) {
|
|
2511
2823
|
// TODO: Put this in a service
|
|
2512
2824
|
var makeMongoId = function (rnd) {
|
|
2513
2825
|
if (rnd === void 0) { rnd = function (r16) { return Math.floor(r16).toString(16); }; }
|
|
2514
|
-
return rnd(Date.now() / 1000) +
|
|
2826
|
+
return rnd(Date.now() / 1000) + " ".repeat(16).replace(/./g, function () { return rnd(Math.random() * 16); });
|
|
2515
2827
|
};
|
|
2828
|
+
function _handleCancel(resp) {
|
|
2829
|
+
if (["cancel", "backdrop click", "escape key press"].indexOf(resp) === -1) {
|
|
2830
|
+
throw resp;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2516
2833
|
var suffixCleanId = function suffixCleanId(inst, suffix) {
|
|
2517
|
-
return (inst.id ||
|
|
2834
|
+
return (inst.id || "f_" + inst.name).replace(/\./g, "_") + suffix;
|
|
2518
2835
|
};
|
|
2519
|
-
var walkTree = function (object, fieldname, element) {
|
|
2836
|
+
var walkTree = function (object, fieldname, element, insertIntermediateObjects) {
|
|
2520
2837
|
// Walk through subdocs to find the required key
|
|
2521
2838
|
// for instance walkTree(master,'address.street.number',element)
|
|
2522
2839
|
// called by getData and setData
|
|
2840
|
+
if (insertIntermediateObjects === void 0) { insertIntermediateObjects = false; }
|
|
2523
2841
|
// element is used when accessing in the context of a input, as the id (like exams-2-grader)
|
|
2524
2842
|
// 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(
|
|
2843
|
+
var parts = fieldname.split("."), higherLevels = parts.length - 1, workingRec = object;
|
|
2526
2844
|
for (var i = 0; i < higherLevels; i++) {
|
|
2527
2845
|
if (!workingRec) {
|
|
2528
2846
|
throw new Error("walkTree failed: Object = " + object + ", fieldname = " + fieldname + ", i = " + i);
|
|
@@ -2533,18 +2851,21 @@ var fng;
|
|
|
2533
2851
|
});
|
|
2534
2852
|
}
|
|
2535
2853
|
else {
|
|
2854
|
+
if (insertIntermediateObjects && !workingRec[parts[i]]) {
|
|
2855
|
+
workingRec[parts[i]] = {};
|
|
2856
|
+
}
|
|
2536
2857
|
workingRec = workingRec[parts[i]];
|
|
2537
2858
|
}
|
|
2538
|
-
if (angular.isArray(workingRec) && typeof element !==
|
|
2539
|
-
if (element.scope && typeof element.scope ===
|
|
2859
|
+
if (angular.isArray(workingRec) && typeof element !== "undefined") {
|
|
2860
|
+
if (element.scope && typeof element.scope === "function") {
|
|
2540
2861
|
// If we come across an array we need to find the correct position, if we have an element
|
|
2541
2862
|
workingRec = workingRec[element.scope().$index];
|
|
2542
2863
|
}
|
|
2543
|
-
else if (typeof element ===
|
|
2864
|
+
else if (typeof element === "number") {
|
|
2544
2865
|
workingRec = workingRec[element];
|
|
2545
2866
|
}
|
|
2546
2867
|
else {
|
|
2547
|
-
throw new Error(
|
|
2868
|
+
throw new Error("Unsupported element type in walkTree " + fieldname);
|
|
2548
2869
|
}
|
|
2549
2870
|
}
|
|
2550
2871
|
if (!workingRec) {
|
|
@@ -2557,15 +2878,20 @@ var fng;
|
|
|
2557
2878
|
};
|
|
2558
2879
|
};
|
|
2559
2880
|
var setData = function setData(object, fieldname, element, value) {
|
|
2560
|
-
var leafData = walkTree(object, fieldname, element);
|
|
2881
|
+
var leafData = walkTree(object, fieldname, element, !!value);
|
|
2561
2882
|
if (leafData.lastObject && leafData.key) {
|
|
2562
|
-
if (
|
|
2563
|
-
|
|
2564
|
-
leafData.lastObject
|
|
2883
|
+
if (value) {
|
|
2884
|
+
if (angular.isArray(leafData.lastObject)) {
|
|
2885
|
+
for (var i = 0; i < leafData.lastObject.length; i++) {
|
|
2886
|
+
leafData.lastObject[i][leafData.key] = value[i];
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
else {
|
|
2890
|
+
leafData.lastObject[leafData.key] = value;
|
|
2565
2891
|
}
|
|
2566
2892
|
}
|
|
2567
2893
|
else {
|
|
2568
|
-
leafData.lastObject[leafData.key]
|
|
2894
|
+
delete leafData.lastObject[leafData.key];
|
|
2569
2895
|
}
|
|
2570
2896
|
}
|
|
2571
2897
|
};
|
|
@@ -2584,11 +2910,17 @@ var fng;
|
|
|
2584
2910
|
}
|
|
2585
2911
|
return retVal;
|
|
2586
2912
|
};
|
|
2587
|
-
var updateRecordWithLookupValues = function (schemaElement, $scope, ctrlState) {
|
|
2913
|
+
var updateRecordWithLookupValues = function (schemaElement, $scope, ctrlState, ignoreDirty) {
|
|
2914
|
+
if (ignoreDirty === void 0) { ignoreDirty = false; }
|
|
2588
2915
|
// Update the master and the record with the lookup values, master first
|
|
2589
|
-
if (!$scope.topLevelFormName || $scope[$scope.topLevelFormName].$pristine) {
|
|
2916
|
+
if (!$scope.topLevelFormName || ($scope[$scope.topLevelFormName] && (ignoreDirty || $scope[$scope.topLevelFormName].$pristine))) {
|
|
2590
2917
|
updateObject(schemaElement.name, ctrlState.master, function (value) {
|
|
2591
|
-
|
|
2918
|
+
if (typeof value == "object" && value.id) {
|
|
2919
|
+
return value;
|
|
2920
|
+
}
|
|
2921
|
+
else {
|
|
2922
|
+
return convertForeignKeys(schemaElement, value, $scope[suffixCleanId(schemaElement, "Options")], $scope[suffixCleanId(schemaElement, "_ids")]);
|
|
2923
|
+
}
|
|
2592
2924
|
});
|
|
2593
2925
|
// Then copy the converted keys from master into record
|
|
2594
2926
|
var newVal = getData(ctrlState.master, schemaElement.name);
|
|
@@ -2599,38 +2931,29 @@ var fng;
|
|
|
2599
2931
|
};
|
|
2600
2932
|
// Split a field name into the next level and all following levels
|
|
2601
2933
|
function splitFieldName(aFieldName) {
|
|
2602
|
-
var nesting = aFieldName.split(
|
|
2934
|
+
var nesting = aFieldName.split("."), result = [nesting[0]];
|
|
2603
2935
|
if (nesting.length > 1) {
|
|
2604
|
-
result.push(nesting.slice(1).join(
|
|
2936
|
+
result.push(nesting.slice(1).join("."));
|
|
2605
2937
|
}
|
|
2606
2938
|
return result;
|
|
2607
2939
|
}
|
|
2608
|
-
var getListData = function getListData(
|
|
2940
|
+
var getListData = function getListData(record, fieldName, listSchema, $scope) {
|
|
2609
2941
|
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
|
-
}
|
|
2942
|
+
var retVal = getData(record, fieldName) || "";
|
|
2620
2943
|
if (retVal && listSchema) {
|
|
2621
2944
|
// 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[
|
|
2945
|
+
var schemaElm = _.find(listSchema, function (elm) { return (elm["name"] === fieldName); });
|
|
2623
2946
|
if (schemaElm) {
|
|
2624
|
-
switch (schemaElm[
|
|
2947
|
+
switch (schemaElm["params"]) {
|
|
2625
2948
|
case undefined:
|
|
2626
2949
|
break;
|
|
2627
|
-
case
|
|
2950
|
+
case "timestamp":
|
|
2628
2951
|
var timestamp = retVal.toString().substring(0, 8);
|
|
2629
2952
|
var date = new Date(parseInt(timestamp, 16) * 1000);
|
|
2630
|
-
retVal = date.toLocaleDateString() +
|
|
2953
|
+
retVal = date.toLocaleDateString() + " " + date.toLocaleTimeString();
|
|
2631
2954
|
break;
|
|
2632
2955
|
default:
|
|
2633
|
-
retVal = $scope.dataEventFunctions[schemaElm[
|
|
2956
|
+
retVal = $scope.dataEventFunctions[schemaElm["params"]](record);
|
|
2634
2957
|
}
|
|
2635
2958
|
}
|
|
2636
2959
|
}
|
|
@@ -2647,7 +2970,7 @@ var fng;
|
|
|
2647
2970
|
if (angular.isArray(theValue)) {
|
|
2648
2971
|
for (var i = theValue.length - 1; i >= 0; i--) {
|
|
2649
2972
|
var type = typeof theValue[i];
|
|
2650
|
-
if (type ===
|
|
2973
|
+
if (type === "undefined" || (type === "object" && Object.keys(theValue[i]).length === 0)) {
|
|
2651
2974
|
theValue.splice(i, 1);
|
|
2652
2975
|
}
|
|
2653
2976
|
}
|
|
@@ -2669,8 +2992,8 @@ var fng;
|
|
|
2669
2992
|
}
|
|
2670
2993
|
// Set up the lookup lists (value and id) on the scope for an internal lookup. Called by convertToAngularModel and $watch
|
|
2671
2994
|
function setUpInternalLookupLists($scope, options, ids, newVal, valueAttrib) {
|
|
2672
|
-
var optionsArray = (typeof options ===
|
|
2673
|
-
var idsArray = (typeof ids ===
|
|
2995
|
+
var optionsArray = (typeof options === "string" ? $scope[options] : options);
|
|
2996
|
+
var idsArray = (typeof ids === "string" ? $scope[ids] : ids);
|
|
2674
2997
|
optionsArray.length = 0;
|
|
2675
2998
|
idsArray.length = 0;
|
|
2676
2999
|
if (!!newVal && (newVal.length > 0)) {
|
|
@@ -2692,10 +3015,10 @@ var fng;
|
|
|
2692
3015
|
result = true;
|
|
2693
3016
|
}
|
|
2694
3017
|
else if (!aSchema.directive) {
|
|
2695
|
-
if (aSchema.type ===
|
|
3018
|
+
if (aSchema.type === "text") {
|
|
2696
3019
|
result = true;
|
|
2697
3020
|
}
|
|
2698
|
-
else if (aSchema.type ===
|
|
3021
|
+
else if (aSchema.type === "select" && !aSchema.ids) {
|
|
2699
3022
|
result = true;
|
|
2700
3023
|
}
|
|
2701
3024
|
}
|
|
@@ -2705,7 +3028,7 @@ var fng;
|
|
|
2705
3028
|
function getConversionObject(scope, entryName, schemaName) {
|
|
2706
3029
|
var conversions = scope.conversions;
|
|
2707
3030
|
if (schemaName) {
|
|
2708
|
-
conversions = conversions
|
|
3031
|
+
conversions = getData(conversions, schemaName) || {};
|
|
2709
3032
|
}
|
|
2710
3033
|
return conversions[entryName];
|
|
2711
3034
|
}
|
|
@@ -2716,37 +3039,58 @@ var fng;
|
|
|
2716
3039
|
for (var i = 0; i < schema.length; i++) {
|
|
2717
3040
|
var schemaEntry = schema[i];
|
|
2718
3041
|
var fieldName = schemaEntry.name.slice(prefixLength);
|
|
3042
|
+
if (!fieldName.length) {
|
|
3043
|
+
fieldName = schemaEntry.name.split('.').pop();
|
|
3044
|
+
}
|
|
2719
3045
|
var fieldValue = getData(anObject, fieldName);
|
|
3046
|
+
if (schemaEntry.intType === 'date' && typeof fieldValue === 'string') {
|
|
3047
|
+
setData(anObject, fieldName, null, new Date(fieldValue));
|
|
3048
|
+
}
|
|
2720
3049
|
if (schemaEntry.schema) {
|
|
2721
3050
|
if (fieldValue) {
|
|
2722
3051
|
for (var j = 0; j < fieldValue.length; j++) {
|
|
2723
|
-
fieldValue[j] = convertToAngularModel(schemaEntry.schema, fieldValue[j],
|
|
3052
|
+
fieldValue[j] = convertToAngularModel(schemaEntry.schema, fieldValue[j], 1 + fieldName.length, $scope, fieldName, master, j);
|
|
2724
3053
|
}
|
|
2725
3054
|
}
|
|
2726
3055
|
}
|
|
2727
3056
|
else {
|
|
2728
|
-
if (schemaEntry.
|
|
2729
|
-
setUpInternalLookupLists($scope, schemaEntry.options, schemaEntry.ids, master[schemaEntry.
|
|
3057
|
+
if (schemaEntry.internalRef) {
|
|
3058
|
+
setUpInternalLookupLists($scope, schemaEntry.options, schemaEntry.ids, master[schemaEntry.internalRef.property], schemaEntry.internalRef.value);
|
|
2730
3059
|
}
|
|
2731
3060
|
// Convert {array:['item 1']} to {array:[{x:'item 1'}]}
|
|
2732
|
-
var thisField = getListData(
|
|
2733
|
-
if (schemaEntry.array &&
|
|
3061
|
+
var thisField = getListData(anObject, fieldName, null, $scope);
|
|
3062
|
+
if (schemaEntry.array &&
|
|
3063
|
+
simpleArrayNeedsX(schemaEntry) &&
|
|
3064
|
+
thisField &&
|
|
3065
|
+
!(thisField.length > 0 && thisField[0].x) // Don't keep on coverting
|
|
3066
|
+
) {
|
|
2734
3067
|
for (var k = 0; k < thisField.length; k++) {
|
|
2735
3068
|
thisField[k] = { x: thisField[k] };
|
|
2736
3069
|
}
|
|
2737
3070
|
}
|
|
2738
3071
|
// Convert {lookup:'012abcde'} to {lookup:'List description for 012abcde'}
|
|
2739
|
-
var idList = $scope[suffixCleanId(schemaEntry,
|
|
3072
|
+
var idList = $scope[suffixCleanId(schemaEntry, "_ids")];
|
|
2740
3073
|
var thisConversion = void 0;
|
|
2741
3074
|
if (fieldValue && idList && idList.length > 0) {
|
|
2742
|
-
if (fieldName.indexOf(
|
|
2743
|
-
throw new Error(
|
|
3075
|
+
if (fieldName.indexOf(".") !== -1) {
|
|
3076
|
+
throw new Error("Trying to directly assign to a nested field 332");
|
|
2744
3077
|
} // Not sure that this can happen, but put in a runtime test
|
|
2745
|
-
|
|
3078
|
+
if (
|
|
3079
|
+
/*
|
|
3080
|
+
Check we are starting with an ObjectId (ie not being called because of $watch on conversion, with a
|
|
3081
|
+
converted value, which would cause an exception)
|
|
3082
|
+
*/
|
|
3083
|
+
fieldValue.toString().match(/^[a-f0-9]{24}$/) &&
|
|
3084
|
+
/*
|
|
3085
|
+
We are not suppressing conversions
|
|
3086
|
+
*/
|
|
3087
|
+
(!schemaEntry.internalRef || !schemaEntry.internalRef.noConvert)) {
|
|
3088
|
+
anObject[fieldName] = convertForeignKeys(schemaEntry, fieldValue, $scope[suffixCleanId(schemaEntry, "Options")], idList);
|
|
3089
|
+
}
|
|
2746
3090
|
}
|
|
2747
3091
|
else if (schemaEntry.select2) {
|
|
2748
3092
|
// Do nothing with these - handled elsewhere (and deprecated)
|
|
2749
|
-
console.log(
|
|
3093
|
+
console.log("fng-select2 is deprecated - use fng-ui-select instead");
|
|
2750
3094
|
void (schemaEntry.select2);
|
|
2751
3095
|
}
|
|
2752
3096
|
else if (fieldValue && (thisConversion = getConversionObject($scope, fieldName, schemaName)) &&
|
|
@@ -2755,7 +3099,7 @@ var fng;
|
|
|
2755
3099
|
thisConversion.fngajax(fieldValue, schemaEntry, function (updateEntry, value) {
|
|
2756
3100
|
// Update the master and (preserving pristine if appropriate) the record
|
|
2757
3101
|
setData(master, updateEntry.name, offset, value);
|
|
2758
|
-
preservePristine(angular.element(
|
|
3102
|
+
preservePristine(angular.element("#" + updateEntry.id), function () {
|
|
2759
3103
|
setData($scope.record, updateEntry.name, offset, value);
|
|
2760
3104
|
});
|
|
2761
3105
|
});
|
|
@@ -2814,7 +3158,7 @@ var fng;
|
|
|
2814
3158
|
else {
|
|
2815
3159
|
var index = valuesArray.indexOf(textToConvert);
|
|
2816
3160
|
if (index === -1) {
|
|
2817
|
-
throw new Error(
|
|
3161
|
+
throw new Error("convertListValueToId: Invalid data - value " + textToConvert + " not found in " + valuesArray + " processing " + fname);
|
|
2818
3162
|
}
|
|
2819
3163
|
return idsArray[index];
|
|
2820
3164
|
}
|
|
@@ -2822,7 +3166,7 @@ var fng;
|
|
|
2822
3166
|
var preservePristine = function preservePristine(element, fn) {
|
|
2823
3167
|
// stop the form being set to dirty when a fn is called
|
|
2824
3168
|
// Use when the record (and master) need to be updated by lookup values displayed asynchronously
|
|
2825
|
-
var modelController = element.inheritedData(
|
|
3169
|
+
var modelController = element.inheritedData("$ngModelController");
|
|
2826
3170
|
var isClean = (modelController && modelController.$pristine);
|
|
2827
3171
|
if (isClean) {
|
|
2828
3172
|
// fake it to dirty here and reset after call to fn
|
|
@@ -2834,18 +3178,21 @@ var fng;
|
|
|
2834
3178
|
}
|
|
2835
3179
|
};
|
|
2836
3180
|
var convertIdToListValue = function convertIdToListValue(id, idsArray, valuesArray, fname) {
|
|
2837
|
-
if (typeof (id) ===
|
|
3181
|
+
if (typeof (id) === "object") {
|
|
2838
3182
|
id = id.id;
|
|
2839
3183
|
}
|
|
2840
3184
|
var index = idsArray.indexOf(id);
|
|
2841
3185
|
if (index === -1) {
|
|
2842
|
-
|
|
3186
|
+
index = valuesArray.indexOf(id); // This can get called twice - second time with converted value (not sure how atm) so protect against that...
|
|
3187
|
+
if (index === -1) {
|
|
3188
|
+
throw new Error("convertIdToListValue: Invalid data - id " + id + " not found in " + idsArray + " processing " + fname);
|
|
3189
|
+
}
|
|
2843
3190
|
}
|
|
2844
3191
|
return valuesArray[index];
|
|
2845
3192
|
};
|
|
2846
3193
|
var processServerData = function processServerData(recordFromServer, $scope, ctrlState) {
|
|
2847
3194
|
ctrlState.master = convertToAngularModel($scope.formSchema, recordFromServer, 0, $scope);
|
|
2848
|
-
$scope.phase =
|
|
3195
|
+
$scope.phase = "ready";
|
|
2849
3196
|
$scope.cancel();
|
|
2850
3197
|
};
|
|
2851
3198
|
function convertOldToNew(ref, val, attrib, newVals, oldVals) {
|
|
@@ -2864,102 +3211,123 @@ var fng;
|
|
|
2864
3211
|
var listOnly = (!$scope.id && !$scope.newRecord);
|
|
2865
3212
|
// passing null for formSchema parameter prevents all the work being done when we are just after the list data,
|
|
2866
3213
|
// but should be removed when/if formschemas are cached
|
|
2867
|
-
formGeneratorInstance.handleSchema(
|
|
3214
|
+
formGeneratorInstance.handleSchema("Main " + $scope.modelName, schema, listOnly ? null : $scope.formSchema, $scope.listSchema, "", true, $scope, ctrlState);
|
|
3215
|
+
function processLookupHandlers(newValue, oldValue) {
|
|
3216
|
+
// If we have any internal lookups then update the references
|
|
3217
|
+
$scope.internalLookups.forEach(function (lkp) {
|
|
3218
|
+
var newVal = newValue[lkp.ref.property];
|
|
3219
|
+
var oldVal = oldValue[lkp.ref.property];
|
|
3220
|
+
setUpInternalLookupLists($scope, lkp.lookupOptions, lkp.lookupIds, newVal, lkp.ref.value);
|
|
3221
|
+
// now change the looked-up values that matched the old to the new
|
|
3222
|
+
if ((newVal && newVal.length > 0) || (oldVal && oldVal.length > 0)) {
|
|
3223
|
+
lkp.handlers.forEach(function (h) {
|
|
3224
|
+
if (h.possibleArray) {
|
|
3225
|
+
var arr = getData($scope.record, h.possibleArray, null);
|
|
3226
|
+
if (arr && arr.length > 0) {
|
|
3227
|
+
arr.forEach(function (a) { return convertOldToNew(lkp.ref, a, h.lastPart, newVal, oldVal); });
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
else if (angular.isArray($scope.record[h.lastPart])) {
|
|
3231
|
+
$scope.record[h.lastPart].forEach(function (a) {
|
|
3232
|
+
convertOldToNew(lkp.ref, a, "x", newVal, oldVal);
|
|
3233
|
+
});
|
|
3234
|
+
}
|
|
3235
|
+
else {
|
|
3236
|
+
convertOldToNew(lkp.ref, $scope.record, h.lastPart, newVal, oldVal);
|
|
3237
|
+
}
|
|
3238
|
+
});
|
|
3239
|
+
}
|
|
3240
|
+
});
|
|
3241
|
+
// If we have any list lookups then update the references
|
|
3242
|
+
$scope.listLookups.forEach(function (lkp) {
|
|
3243
|
+
function extractIdVal(obj, idString) {
|
|
3244
|
+
var retVal = obj[idString];
|
|
3245
|
+
if (retVal && retVal.id) {
|
|
3246
|
+
retVal = retVal.id;
|
|
3247
|
+
}
|
|
3248
|
+
return retVal;
|
|
3249
|
+
}
|
|
3250
|
+
function blankListLookup(inst) {
|
|
3251
|
+
setData($scope.record, inst.name);
|
|
3252
|
+
}
|
|
3253
|
+
var idString = lkp.ref.id.slice(1);
|
|
3254
|
+
if (idString.includes(".")) {
|
|
3255
|
+
throw new Error("No support for nested list lookups yet - " + JSON.stringify(lkp.ref));
|
|
3256
|
+
}
|
|
3257
|
+
var newVal = extractIdVal(newValue, idString);
|
|
3258
|
+
var oldVal = extractIdVal(oldValue, idString);
|
|
3259
|
+
if (newVal !== oldVal) {
|
|
3260
|
+
lkp.handlers.forEach(function (h) {
|
|
3261
|
+
$scope[h.formInstructions.options].length = 0;
|
|
3262
|
+
$scope[h.formInstructions.ids].length = 0;
|
|
3263
|
+
});
|
|
3264
|
+
if (newVal) {
|
|
3265
|
+
SubmissionsService.readRecord(lkp.ref.collection, newVal).then(function (response) {
|
|
3266
|
+
lkp.handlers.forEach(function (h) {
|
|
3267
|
+
var optionsList = $scope[h.formInstructions.options];
|
|
3268
|
+
var idList = $scope[h.formInstructions.ids];
|
|
3269
|
+
var data = response.data[lkp.ref.property] || [];
|
|
3270
|
+
for (var i = 0; i < data.length; i++) {
|
|
3271
|
+
var option = data[i][lkp.ref.value];
|
|
3272
|
+
var pos = _.sortedIndex(optionsList, option);
|
|
3273
|
+
// handle dupes
|
|
3274
|
+
if (optionsList[pos] === option) {
|
|
3275
|
+
option = option + " (" + data[i]._id + ")";
|
|
3276
|
+
pos = _.sortedIndex(optionsList, option);
|
|
3277
|
+
}
|
|
3278
|
+
optionsList.splice(pos, 0, option);
|
|
3279
|
+
idList.splice(pos, 0, data[i]._id);
|
|
3280
|
+
}
|
|
3281
|
+
if (Object.keys(oldValue).length === 0) {
|
|
3282
|
+
// Not sure how safe this is, but the record is fresh so I think it's OK...
|
|
3283
|
+
updateRecordWithLookupValues(h.formInstructions, $scope, ctrlState, true);
|
|
3284
|
+
}
|
|
3285
|
+
else {
|
|
3286
|
+
// Here we are reacting to a change in the lookup pointer in the record.
|
|
3287
|
+
// We need to blank our lookup field as it will not exist
|
|
3288
|
+
blankListLookup(h.formInstructions);
|
|
3289
|
+
}
|
|
3290
|
+
});
|
|
3291
|
+
});
|
|
3292
|
+
}
|
|
3293
|
+
else {
|
|
3294
|
+
lkp.handlers.forEach(function (h) {
|
|
3295
|
+
blankListLookup(h.formInstructions);
|
|
3296
|
+
});
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
});
|
|
3300
|
+
}
|
|
3301
|
+
function notifyReady() {
|
|
3302
|
+
$scope.phase = "ready";
|
|
3303
|
+
$scope.cancel();
|
|
3304
|
+
processLookupHandlers($scope.record, {});
|
|
3305
|
+
}
|
|
2868
3306
|
if (listOnly) {
|
|
2869
3307
|
ctrlState.allowLocationChange = true;
|
|
2870
3308
|
}
|
|
2871
3309
|
else {
|
|
2872
3310
|
var force = true;
|
|
2873
3311
|
if (!$scope.newRecord) {
|
|
2874
|
-
$scope.dropConversionWatcher = $scope.$watchCollection(
|
|
3312
|
+
$scope.dropConversionWatcher = $scope.$watchCollection("conversions", function (newValue, oldValue) {
|
|
2875
3313
|
if (newValue !== oldValue && $scope.originalData) {
|
|
2876
3314
|
processServerData($scope.originalData, $scope, ctrlState);
|
|
2877
3315
|
}
|
|
2878
3316
|
});
|
|
2879
3317
|
}
|
|
2880
|
-
$scope.$watch(
|
|
3318
|
+
$scope.$watch("record", function (newValue, oldValue) {
|
|
2881
3319
|
if (newValue !== oldValue) {
|
|
2882
3320
|
if (Object.keys(oldValue).length > 0 && $scope.dropConversionWatcher) {
|
|
2883
3321
|
$scope.dropConversionWatcher(); // Don't want to convert changed data
|
|
2884
3322
|
$scope.dropConversionWatcher = null;
|
|
2885
3323
|
}
|
|
2886
3324
|
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
|
-
});
|
|
3325
|
+
processLookupHandlers(newValue, oldValue);
|
|
2958
3326
|
}
|
|
2959
3327
|
}, true);
|
|
2960
3328
|
if ($scope.id) {
|
|
2961
3329
|
// Going to read a record
|
|
2962
|
-
if (typeof $scope.dataEventFunctions.onBeforeRead ===
|
|
3330
|
+
if (typeof $scope.dataEventFunctions.onBeforeRead === "function") {
|
|
2963
3331
|
$scope.dataEventFunctions.onBeforeRead($scope.id, function (err) {
|
|
2964
3332
|
if (err) {
|
|
2965
3333
|
$scope.showError(err);
|
|
@@ -2975,99 +3343,125 @@ var fng;
|
|
|
2975
3343
|
}
|
|
2976
3344
|
else {
|
|
2977
3345
|
// New record
|
|
2978
|
-
ctrlState.
|
|
3346
|
+
ctrlState.allowLocationChange = false;
|
|
3347
|
+
ctrlState.master = $scope.setDefaults($scope.formSchema);
|
|
2979
3348
|
var passedRecord = $scope.initialiseNewRecord || $location.$$search.r;
|
|
2980
3349
|
if (passedRecord) {
|
|
2981
3350
|
try {
|
|
2982
|
-
ctrlState.master
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
$scope[$scope.topLevelFormName]
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3351
|
+
Object.assign(ctrlState.master, JSON.parse(passedRecord));
|
|
3352
|
+
if (!$scope["newRecordsStartPristine"]) {
|
|
3353
|
+
// Although this is a new record we are making it dirty from the url so we need to $setDirty
|
|
3354
|
+
$scope.$on("fngCancel", function () {
|
|
3355
|
+
$timeout(function () {
|
|
3356
|
+
if ($scope[$scope.topLevelFormName]) {
|
|
3357
|
+
$scope[$scope.topLevelFormName].$setDirty();
|
|
3358
|
+
}
|
|
3359
|
+
}, 1000); // Has to fire after the setPristime timeout.
|
|
3360
|
+
});
|
|
3361
|
+
}
|
|
2991
3362
|
}
|
|
2992
3363
|
catch (e) {
|
|
2993
|
-
console.log(
|
|
3364
|
+
console.log("Error parsing specified record : " + e.message);
|
|
2994
3365
|
}
|
|
2995
3366
|
}
|
|
2996
|
-
if (typeof $scope.dataEventFunctions.onInitialiseNewRecord ===
|
|
3367
|
+
if (typeof $scope.dataEventFunctions.onInitialiseNewRecord === "function") {
|
|
3368
|
+
console.log("onInitialiseNewRecord is deprecated - use the async version - onNewRecordInit(data,cb)");
|
|
2997
3369
|
$scope.dataEventFunctions.onInitialiseNewRecord(ctrlState.master);
|
|
2998
3370
|
}
|
|
2999
|
-
$scope.
|
|
3000
|
-
|
|
3371
|
+
if (typeof $scope.dataEventFunctions.onNewRecordInit === "function") {
|
|
3372
|
+
$scope.dataEventFunctions.onNewRecordInit(ctrlState.master, function (err) {
|
|
3373
|
+
if (err) {
|
|
3374
|
+
$scope.showError(err);
|
|
3375
|
+
}
|
|
3376
|
+
else {
|
|
3377
|
+
notifyReady();
|
|
3378
|
+
}
|
|
3379
|
+
});
|
|
3380
|
+
}
|
|
3381
|
+
else {
|
|
3382
|
+
notifyReady();
|
|
3383
|
+
}
|
|
3001
3384
|
}
|
|
3002
3385
|
}
|
|
3003
3386
|
}
|
|
3004
3387
|
function handleError($scope) {
|
|
3005
3388
|
return function (response) {
|
|
3006
3389
|
if ([200, 400].indexOf(response.status) !== -1) {
|
|
3007
|
-
var errorMessage =
|
|
3390
|
+
var errorMessage = "";
|
|
3008
3391
|
for (var errorField in response.data.errors) {
|
|
3009
3392
|
if (response.data.errors.hasOwnProperty(errorField)) {
|
|
3010
|
-
errorMessage +=
|
|
3393
|
+
errorMessage += "<li><b>" + $filter("titleCase")(errorField) + ": </b> ";
|
|
3011
3394
|
switch (response.data.errors[errorField].type) {
|
|
3012
|
-
case
|
|
3013
|
-
errorMessage +=
|
|
3395
|
+
case "enum":
|
|
3396
|
+
errorMessage += "You need to select from the list of values";
|
|
3014
3397
|
break;
|
|
3015
3398
|
default:
|
|
3016
3399
|
errorMessage += response.data.errors[errorField].message;
|
|
3017
3400
|
break;
|
|
3018
3401
|
}
|
|
3019
|
-
errorMessage +=
|
|
3402
|
+
errorMessage += "</li>";
|
|
3020
3403
|
}
|
|
3021
3404
|
}
|
|
3022
3405
|
if (errorMessage.length > 0) {
|
|
3023
|
-
errorMessage = response.data.message +
|
|
3406
|
+
errorMessage = response.data.message + "<br /><ul>" + errorMessage + "</ul>";
|
|
3024
3407
|
}
|
|
3025
3408
|
else {
|
|
3026
|
-
errorMessage = response.data.message ||
|
|
3409
|
+
errorMessage = response.data.message || response.data.err || "Error! Sorry - No further details available.";
|
|
3027
3410
|
}
|
|
3028
3411
|
$scope.showError(errorMessage);
|
|
3029
3412
|
}
|
|
3030
3413
|
else {
|
|
3031
|
-
$scope.showError(response.status +
|
|
3414
|
+
$scope.showError(response.status + " " + JSON.stringify(response.data));
|
|
3032
3415
|
}
|
|
3033
3416
|
};
|
|
3034
3417
|
}
|
|
3035
3418
|
function handleIncomingData(data, $scope, ctrlState) {
|
|
3036
3419
|
ctrlState.allowLocationChange = false;
|
|
3037
|
-
$scope.phase =
|
|
3038
|
-
if (typeof $scope.dataEventFunctions.onAfterRead ===
|
|
3420
|
+
$scope.phase = "reading";
|
|
3421
|
+
if (typeof $scope.dataEventFunctions.onAfterRead === "function") {
|
|
3039
3422
|
$scope.dataEventFunctions.onAfterRead(data);
|
|
3040
3423
|
}
|
|
3041
3424
|
$scope.originalData = data;
|
|
3042
3425
|
processServerData(data, $scope, ctrlState);
|
|
3043
3426
|
}
|
|
3427
|
+
function addArrayLookupToLookupList($scope, formInstructions, ref, lookups) {
|
|
3428
|
+
var nameElements = formInstructions.name.split(".");
|
|
3429
|
+
var refHandler = lookups.find(function (lkp) {
|
|
3430
|
+
return lkp.ref.property === ref.property && lkp.ref.value === ref.value;
|
|
3431
|
+
});
|
|
3432
|
+
var thisHandler = {
|
|
3433
|
+
formInstructions: formInstructions,
|
|
3434
|
+
lastPart: nameElements.pop(),
|
|
3435
|
+
possibleArray: nameElements.join(".")
|
|
3436
|
+
};
|
|
3437
|
+
if (!refHandler) {
|
|
3438
|
+
refHandler = {
|
|
3439
|
+
ref: ref,
|
|
3440
|
+
lookupOptions: [],
|
|
3441
|
+
lookupIds: [],
|
|
3442
|
+
handlers: []
|
|
3443
|
+
};
|
|
3444
|
+
lookups.push(refHandler);
|
|
3445
|
+
}
|
|
3446
|
+
refHandler.handlers.push(thisHandler);
|
|
3447
|
+
$scope[formInstructions.options] = refHandler.lookupOptions;
|
|
3448
|
+
$scope[formInstructions.ids] = refHandler.lookupIds;
|
|
3449
|
+
}
|
|
3044
3450
|
return {
|
|
3045
3451
|
readRecord: function readRecord($scope, ctrlState) {
|
|
3046
|
-
|
|
3047
|
-
|
|
3452
|
+
$scope.readingRecord = SubmissionsService.readRecord($scope.modelName, $scope.id);
|
|
3453
|
+
$scope.readingRecord
|
|
3048
3454
|
.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
|
-
// }
|
|
3455
|
+
var data = angular.copy(response.data);
|
|
3456
|
+
handleIncomingData(data, $scope, ctrlState);
|
|
3457
|
+
}, function (error) {
|
|
3458
|
+
if (error.status === 404) {
|
|
3459
|
+
$location.path("/404");
|
|
3066
3460
|
}
|
|
3067
3461
|
else {
|
|
3068
|
-
|
|
3462
|
+
$scope.handleHttpError(error);
|
|
3069
3463
|
}
|
|
3070
|
-
}
|
|
3464
|
+
});
|
|
3071
3465
|
},
|
|
3072
3466
|
scrollTheList: function scrollTheList($scope) {
|
|
3073
3467
|
var pagesLoaded = $scope.pagesLoaded;
|
|
@@ -3087,31 +3481,38 @@ var fng;
|
|
|
3087
3481
|
$scope.recordList = $scope.recordList.concat(data);
|
|
3088
3482
|
}
|
|
3089
3483
|
else {
|
|
3090
|
-
console.log(
|
|
3484
|
+
console.log("DEBUG: infinite scroll component asked for a page twice - the model was " + $scope.modelName);
|
|
3091
3485
|
}
|
|
3092
3486
|
}
|
|
3093
3487
|
else {
|
|
3094
|
-
$scope.showError(data,
|
|
3488
|
+
$scope.showError(data, "Invalid query");
|
|
3095
3489
|
}
|
|
3096
3490
|
}, $scope.handleHttpError);
|
|
3097
3491
|
},
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
SubmissionsService.deleteRecord(model, id)
|
|
3492
|
+
deleteRecord: function deleteRecord(id, $scope, ctrlState) {
|
|
3493
|
+
SubmissionsService.deleteRecord($scope.modelName, id)
|
|
3101
3494
|
.then(function () {
|
|
3102
|
-
if (typeof $scope.dataEventFunctions.onAfterDelete ===
|
|
3495
|
+
if (typeof $scope.dataEventFunctions.onAfterDelete === "function") {
|
|
3103
3496
|
$scope.dataEventFunctions.onAfterDelete(ctrlState.master);
|
|
3104
3497
|
}
|
|
3105
|
-
routingService.redirectTo()(
|
|
3498
|
+
routingService.redirectTo()("onDelete", $scope, $location);
|
|
3499
|
+
}, function (err) {
|
|
3500
|
+
if (err.status === 404) {
|
|
3501
|
+
// Someone already deleted it
|
|
3502
|
+
routingService.redirectTo()("onDelete", $scope, $location);
|
|
3503
|
+
}
|
|
3504
|
+
else {
|
|
3505
|
+
$scope.showError(err.statusText + " (" + err.status + ") while deleting record<br />" + err.data, 'Error deleting record');
|
|
3506
|
+
}
|
|
3106
3507
|
});
|
|
3107
3508
|
},
|
|
3108
3509
|
updateDocument: function updateDocument(dataToSave, options, $scope, ctrlState) {
|
|
3109
|
-
$scope.phase =
|
|
3510
|
+
$scope.phase = "updating";
|
|
3110
3511
|
SubmissionsService.updateRecord($scope.modelName, $scope.id, dataToSave)
|
|
3111
3512
|
.then(function (response) {
|
|
3112
3513
|
var data = response.data;
|
|
3113
3514
|
if (data.success !== false) {
|
|
3114
|
-
if (typeof $scope.dataEventFunctions.onAfterUpdate ===
|
|
3515
|
+
if (typeof $scope.dataEventFunctions.onAfterUpdate === "function") {
|
|
3115
3516
|
$scope.dataEventFunctions.onAfterUpdate(data, ctrlState.master);
|
|
3116
3517
|
}
|
|
3117
3518
|
if (options.redirect) {
|
|
@@ -3130,19 +3531,20 @@ var fng;
|
|
|
3130
3531
|
}
|
|
3131
3532
|
}, $scope.handleHttpError);
|
|
3132
3533
|
},
|
|
3133
|
-
createNew: function createNew(dataToSave, options, $scope) {
|
|
3534
|
+
createNew: function createNew(dataToSave, options, $scope, ctrlState) {
|
|
3134
3535
|
SubmissionsService.createRecord($scope.modelName, dataToSave)
|
|
3135
3536
|
.then(function (response) {
|
|
3136
3537
|
var data = response.data;
|
|
3137
3538
|
if (data.success !== false) {
|
|
3138
|
-
|
|
3539
|
+
ctrlState.allowLocationChange = true;
|
|
3540
|
+
if (typeof $scope.dataEventFunctions.onAfterCreate === "function") {
|
|
3139
3541
|
$scope.dataEventFunctions.onAfterCreate(data);
|
|
3140
3542
|
}
|
|
3141
3543
|
if (options.redirect) {
|
|
3142
3544
|
$window.location = options.redirect;
|
|
3143
3545
|
}
|
|
3144
3546
|
else {
|
|
3145
|
-
routingService.redirectTo()(
|
|
3547
|
+
routingService.redirectTo()("edit", $scope, $location, data._id);
|
|
3146
3548
|
}
|
|
3147
3549
|
}
|
|
3148
3550
|
else {
|
|
@@ -3160,9 +3562,9 @@ var fng;
|
|
|
3160
3562
|
.then(function (response) {
|
|
3161
3563
|
var data = response.data;
|
|
3162
3564
|
var listInstructions = [];
|
|
3163
|
-
handleSchema(
|
|
3565
|
+
handleSchema("Lookup " + lookupCollection, data, null, listInstructions, "", false, $scope, ctrlState);
|
|
3164
3566
|
var dataRequest;
|
|
3165
|
-
if (typeof schemaElement.filter !==
|
|
3567
|
+
if (typeof schemaElement.filter !== "undefined" && schemaElement.filter) {
|
|
3166
3568
|
dataRequest = SubmissionsService.getPagedAndFilteredList(lookupCollection, schemaElement.filter);
|
|
3167
3569
|
}
|
|
3168
3570
|
else {
|
|
@@ -3170,25 +3572,30 @@ var fng;
|
|
|
3170
3572
|
}
|
|
3171
3573
|
dataRequest
|
|
3172
3574
|
.then(function (response) {
|
|
3173
|
-
var data = response.data;
|
|
3575
|
+
var data = angular.copy(response.data);
|
|
3174
3576
|
if (data) {
|
|
3175
3577
|
for (var i = 0; i < data.length; i++) {
|
|
3176
|
-
var option =
|
|
3578
|
+
var option = "";
|
|
3177
3579
|
for (var j = 0; j < listInstructions.length; j++) {
|
|
3178
3580
|
var thisVal = data[i][listInstructions[j].name];
|
|
3179
|
-
option += thisVal ? thisVal +
|
|
3581
|
+
option += thisVal ? thisVal + " " : "";
|
|
3180
3582
|
}
|
|
3181
3583
|
option = option.trim();
|
|
3182
3584
|
var pos = _.sortedIndex(optionsList, option);
|
|
3183
3585
|
// handle dupes (ideally people will use unique indexes to stop them but...)
|
|
3184
3586
|
if (optionsList[pos] === option) {
|
|
3185
|
-
option = option +
|
|
3587
|
+
option = option + " (" + data[i]._id + ")";
|
|
3186
3588
|
pos = _.sortedIndex(optionsList, option);
|
|
3187
3589
|
}
|
|
3188
3590
|
optionsList.splice(pos, 0, option);
|
|
3189
3591
|
idList.splice(pos, 0, data[i]._id);
|
|
3190
3592
|
}
|
|
3191
|
-
|
|
3593
|
+
if ($scope.readingRecord) {
|
|
3594
|
+
$scope.readingRecord
|
|
3595
|
+
.then(function () {
|
|
3596
|
+
updateRecordWithLookupValues(schemaElement, $scope, ctrlState);
|
|
3597
|
+
});
|
|
3598
|
+
}
|
|
3192
3599
|
}
|
|
3193
3600
|
});
|
|
3194
3601
|
});
|
|
@@ -3196,31 +3603,9 @@ var fng;
|
|
|
3196
3603
|
setUpLookupListOptions: function setUpLookupListOptions(ref, formInstructions, $scope, ctrlState) {
|
|
3197
3604
|
var optionsList = $scope[formInstructions.options] = [];
|
|
3198
3605
|
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
|
|
3606
|
+
if (ref.id[0] === "$") {
|
|
3607
|
+
// id of document that contains out lookup list comes from record, so we need to deal with in $watch by adding it to listLookups
|
|
3608
|
+
addArrayLookupToLookupList($scope, formInstructions, ref, $scope.listLookups);
|
|
3224
3609
|
}
|
|
3225
3610
|
else {
|
|
3226
3611
|
// we can do it now
|
|
@@ -3231,7 +3616,7 @@ var fng;
|
|
|
3231
3616
|
var pos = _.sortedIndex(optionsList, option);
|
|
3232
3617
|
// handle dupes
|
|
3233
3618
|
if (optionsList[pos] === option) {
|
|
3234
|
-
option = option +
|
|
3619
|
+
option = option + " (" + data[i]._id + ")";
|
|
3235
3620
|
pos = _.sortedIndex(optionsList, option);
|
|
3236
3621
|
}
|
|
3237
3622
|
optionsList.splice(pos, 0, option);
|
|
@@ -3242,27 +3627,7 @@ var fng;
|
|
|
3242
3627
|
}
|
|
3243
3628
|
},
|
|
3244
3629
|
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;
|
|
3630
|
+
addArrayLookupToLookupList($scope, formInstructions, ref, $scope.internalLookups);
|
|
3266
3631
|
},
|
|
3267
3632
|
preservePristine: preservePristine,
|
|
3268
3633
|
// Reverse the process of convertToAngularModel
|
|
@@ -3279,48 +3644,54 @@ var fng;
|
|
|
3279
3644
|
}
|
|
3280
3645
|
return retVal;
|
|
3281
3646
|
}
|
|
3282
|
-
|
|
3283
|
-
var
|
|
3284
|
-
var
|
|
3285
|
-
|
|
3647
|
+
var _loop_1 = function () {
|
|
3648
|
+
var schemaI = schema[i];
|
|
3649
|
+
var fieldname = schemaI.name.slice(prefixLength);
|
|
3650
|
+
var thisField = getListData(anObject, fieldname, null, $scope);
|
|
3651
|
+
if (schemaI.schema) {
|
|
3286
3652
|
if (thisField) {
|
|
3287
3653
|
for (var j = 0; j < thisField.length; j++) {
|
|
3288
|
-
thisField[j] = convertToMongoModel(
|
|
3654
|
+
thisField[j] = convertToMongoModel(schemaI.schema, thisField[j], 1 + fieldname.length, $scope, fieldname);
|
|
3289
3655
|
}
|
|
3290
3656
|
}
|
|
3291
3657
|
}
|
|
3292
3658
|
else {
|
|
3293
3659
|
// Convert {array:[{x:'item 1'}]} to {array:['item 1']}
|
|
3294
|
-
if (
|
|
3660
|
+
if (schemaI.array && simpleArrayNeedsX(schemaI) && thisField) {
|
|
3295
3661
|
for (var k = 0; k < thisField.length; k++) {
|
|
3296
3662
|
thisField[k] = thisField[k].x;
|
|
3297
3663
|
}
|
|
3298
3664
|
}
|
|
3299
3665
|
// Convert {lookup:'List description for 012abcde'} to {lookup:'012abcde'}
|
|
3300
|
-
var
|
|
3301
|
-
|
|
3302
|
-
if (idList && idList.length > 0) {
|
|
3666
|
+
var idList_1 = $scope[suffixCleanId(schemaI, "_ids")];
|
|
3667
|
+
if (idList_1 && idList_1.length > 0) {
|
|
3303
3668
|
updateObject(fieldname, anObject, function (value) {
|
|
3304
|
-
return convertToForeignKeys(
|
|
3669
|
+
return convertToForeignKeys(schemaI, value, $scope[suffixCleanId(schemaI, "Options")], idList_1);
|
|
3305
3670
|
});
|
|
3306
3671
|
}
|
|
3307
|
-
else
|
|
3308
|
-
var
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
newVal =
|
|
3312
|
-
if (
|
|
3313
|
-
|
|
3314
|
-
|
|
3672
|
+
else {
|
|
3673
|
+
var thisConversion = getConversionObject($scope, fieldname, schemaName);
|
|
3674
|
+
if (thisConversion) {
|
|
3675
|
+
var lookup = getData(anObject, fieldname, null);
|
|
3676
|
+
var newVal = void 0;
|
|
3677
|
+
if (schemaI.array) {
|
|
3678
|
+
newVal = [];
|
|
3679
|
+
if (lookup) {
|
|
3680
|
+
for (var n = 0; n < lookup.length; n++) {
|
|
3681
|
+
newVal[n] = convertLookup(lookup[n], thisConversion);
|
|
3682
|
+
}
|
|
3315
3683
|
}
|
|
3316
3684
|
}
|
|
3685
|
+
else {
|
|
3686
|
+
newVal = convertLookup(lookup, thisConversion);
|
|
3687
|
+
}
|
|
3688
|
+
setData(anObject, fieldname, null, newVal);
|
|
3317
3689
|
}
|
|
3318
|
-
else {
|
|
3319
|
-
newVal = convertLookup(lookup, thisConversion);
|
|
3320
|
-
}
|
|
3321
|
-
setData(anObject, fieldname, null, newVal);
|
|
3322
3690
|
}
|
|
3323
3691
|
}
|
|
3692
|
+
};
|
|
3693
|
+
for (var i = 0; i < schema.length; i++) {
|
|
3694
|
+
_loop_1();
|
|
3324
3695
|
}
|
|
3325
3696
|
return anObject;
|
|
3326
3697
|
},
|
|
@@ -3330,7 +3701,7 @@ var fng;
|
|
|
3330
3701
|
$scope.handleHttpError = handleError($scope);
|
|
3331
3702
|
$scope.cancel = function () {
|
|
3332
3703
|
angular.copy(ctrlState.master, $scope.record);
|
|
3333
|
-
$scope.$broadcast(
|
|
3704
|
+
$scope.$broadcast("fngCancel", $scope);
|
|
3334
3705
|
// Let call backs etc resolve in case they dirty form, then clean it
|
|
3335
3706
|
$timeout($scope.setPristine);
|
|
3336
3707
|
};
|
|
@@ -3339,15 +3710,21 @@ var fng;
|
|
|
3339
3710
|
// scope.$emit('showErrorMessage', {title: 'Your error Title', body: 'The body of the error message'});
|
|
3340
3711
|
// or
|
|
3341
3712
|
// scope.$broadcast('showErrorMessage', {title: 'Your error Title', body: 'The body of the error message'});
|
|
3342
|
-
$scope.$on(
|
|
3343
|
-
|
|
3713
|
+
$scope.$on("showErrorMessage", function (event, args) {
|
|
3714
|
+
if (!event.defaultPrevented) {
|
|
3715
|
+
event.defaultPrevented = true;
|
|
3716
|
+
$scope.showError(args.body, args.title);
|
|
3717
|
+
}
|
|
3344
3718
|
});
|
|
3345
3719
|
$scope.showError = function (error, alertTitle) {
|
|
3346
|
-
$scope.alertTitle = alertTitle ? alertTitle :
|
|
3347
|
-
if (typeof error ===
|
|
3720
|
+
$scope.alertTitle = alertTitle ? alertTitle : "Error!";
|
|
3721
|
+
if (typeof error === "string") {
|
|
3348
3722
|
$scope.errorMessage = error;
|
|
3349
3723
|
}
|
|
3350
|
-
else if (error
|
|
3724
|
+
else if (!error) {
|
|
3725
|
+
$scope.errorMessage = "An error occurred - that's all we got. Sorry.";
|
|
3726
|
+
}
|
|
3727
|
+
else if (error.message && typeof error.message === "string") {
|
|
3351
3728
|
$scope.errorMessage = error.message;
|
|
3352
3729
|
}
|
|
3353
3730
|
else if (error.data && error.data.message) {
|
|
@@ -3361,16 +3738,35 @@ var fng;
|
|
|
3361
3738
|
$scope.errorMessage = error;
|
|
3362
3739
|
}
|
|
3363
3740
|
}
|
|
3741
|
+
$scope.errorHideTimer = window.setTimeout(function () {
|
|
3742
|
+
$scope.dismissError();
|
|
3743
|
+
$scope.$digest();
|
|
3744
|
+
}, 3500 + (1000 * ($scope.alertTitle + $scope.errorMessage).length / 50));
|
|
3745
|
+
$scope.errorVisible = true;
|
|
3746
|
+
window.setTimeout(function () {
|
|
3747
|
+
$scope.$digest();
|
|
3748
|
+
});
|
|
3749
|
+
};
|
|
3750
|
+
$scope.clearTimeout = function () {
|
|
3751
|
+
if ($scope.errorHideTimer) {
|
|
3752
|
+
clearTimeout($scope.errorHideTimer);
|
|
3753
|
+
delete $scope.errorHideTimer;
|
|
3754
|
+
}
|
|
3364
3755
|
};
|
|
3365
3756
|
$scope.dismissError = function () {
|
|
3757
|
+
$scope.clearTimeout;
|
|
3758
|
+
$scope.errorVisible = false;
|
|
3366
3759
|
delete $scope.errorMessage;
|
|
3367
3760
|
delete $scope.alertTitle;
|
|
3368
3761
|
};
|
|
3762
|
+
$scope.stickError = function () {
|
|
3763
|
+
clearTimeout($scope.errorHideTimer);
|
|
3764
|
+
};
|
|
3369
3765
|
$scope.prepareForSave = function (cb) {
|
|
3370
3766
|
//Convert the lookup values into ids
|
|
3371
3767
|
var dataToSave = recordHandlerInstance.convertToMongoModel($scope.formSchema, angular.copy($scope.record), 0, $scope);
|
|
3372
3768
|
if ($scope.id) {
|
|
3373
|
-
if (typeof $scope.dataEventFunctions.onBeforeUpdate ===
|
|
3769
|
+
if (typeof $scope.dataEventFunctions.onBeforeUpdate === "function") {
|
|
3374
3770
|
$scope.dataEventFunctions.onBeforeUpdate(dataToSave, ctrlState.master, function (err) {
|
|
3375
3771
|
if (err) {
|
|
3376
3772
|
cb(err);
|
|
@@ -3385,7 +3781,7 @@ var fng;
|
|
|
3385
3781
|
}
|
|
3386
3782
|
}
|
|
3387
3783
|
else {
|
|
3388
|
-
if (typeof $scope.dataEventFunctions.onBeforeCreate ===
|
|
3784
|
+
if (typeof $scope.dataEventFunctions.onBeforeCreate === "function") {
|
|
3389
3785
|
$scope.dataEventFunctions.onBeforeCreate(dataToSave, function (err) {
|
|
3390
3786
|
if (err) {
|
|
3391
3787
|
cb(err);
|
|
@@ -3404,22 +3800,24 @@ var fng;
|
|
|
3404
3800
|
options = options || {};
|
|
3405
3801
|
$scope.prepareForSave(function (err, dataToSave) {
|
|
3406
3802
|
if (err) {
|
|
3407
|
-
if (err !==
|
|
3408
|
-
$
|
|
3803
|
+
if (err !== "_update_handled_") {
|
|
3804
|
+
$timeout(function () {
|
|
3805
|
+
$scope.showError(err);
|
|
3806
|
+
});
|
|
3409
3807
|
}
|
|
3410
3808
|
}
|
|
3411
3809
|
else if ($scope.id) {
|
|
3412
3810
|
recordHandlerInstance.updateDocument(dataToSave, options, $scope, ctrlState);
|
|
3413
3811
|
}
|
|
3414
3812
|
else {
|
|
3415
|
-
recordHandlerInstance.createNew(dataToSave, options, $scope);
|
|
3813
|
+
recordHandlerInstance.createNew(dataToSave, options, $scope, ctrlState);
|
|
3416
3814
|
}
|
|
3417
3815
|
});
|
|
3418
3816
|
};
|
|
3419
3817
|
$scope.newClick = function () {
|
|
3420
|
-
routingService.redirectTo()(
|
|
3818
|
+
routingService.redirectTo()("new", $scope, $location);
|
|
3421
3819
|
};
|
|
3422
|
-
$scope.$on(
|
|
3820
|
+
$scope.$on("$locationChangeStart", function (event, next) {
|
|
3423
3821
|
// let changed = !$scope.isCancelDisabled();
|
|
3424
3822
|
// let curPath = window.location.href.split('/');
|
|
3425
3823
|
// let nextPath = next.split('/');
|
|
@@ -3438,21 +3836,12 @@ var fng;
|
|
|
3438
3836
|
if (!ctrlState.allowLocationChange && !$scope.isCancelDisabled()) {
|
|
3439
3837
|
event.preventDefault();
|
|
3440
3838
|
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'
|
|
3839
|
+
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>",
|
|
3840
|
+
controller: "SaveChangesModalCtrl",
|
|
3841
|
+
backdrop: "static"
|
|
3454
3842
|
});
|
|
3455
|
-
modalInstance.result
|
|
3843
|
+
modalInstance.result
|
|
3844
|
+
.then(function (result) {
|
|
3456
3845
|
if (result) {
|
|
3457
3846
|
$scope.save({ redirect: next, allowChange: true }); // save changes
|
|
3458
3847
|
}
|
|
@@ -3460,7 +3849,8 @@ var fng;
|
|
|
3460
3849
|
ctrlState.allowLocationChange = true;
|
|
3461
3850
|
$window.location = next;
|
|
3462
3851
|
}
|
|
3463
|
-
})
|
|
3852
|
+
})
|
|
3853
|
+
.catch(_handleCancel);
|
|
3464
3854
|
}
|
|
3465
3855
|
});
|
|
3466
3856
|
$scope.deleteClick = function () {
|
|
@@ -3471,85 +3861,168 @@ var fng;
|
|
|
3471
3861
|
}
|
|
3472
3862
|
else {
|
|
3473
3863
|
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'
|
|
3864
|
+
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>",
|
|
3865
|
+
controller: "SaveChangesModalCtrl",
|
|
3866
|
+
backdrop: "static"
|
|
3486
3867
|
});
|
|
3487
3868
|
confirmDelete = modalInstance.result;
|
|
3488
3869
|
}
|
|
3489
3870
|
confirmDelete.then(function (result) {
|
|
3871
|
+
function doTheDeletion() {
|
|
3872
|
+
recordHandlerInstance.deleteRecord($scope.id, $scope, ctrlState);
|
|
3873
|
+
}
|
|
3490
3874
|
if (result) {
|
|
3491
|
-
if (typeof $scope.dataEventFunctions.onBeforeDelete ===
|
|
3875
|
+
if (typeof $scope.dataEventFunctions.onBeforeDelete === "function") {
|
|
3492
3876
|
$scope.dataEventFunctions.onBeforeDelete(ctrlState.master, function (err) {
|
|
3493
3877
|
if (err) {
|
|
3494
|
-
if (err !==
|
|
3878
|
+
if (err !== "_delete_handled_") {
|
|
3495
3879
|
$scope.showError(err);
|
|
3496
3880
|
}
|
|
3497
3881
|
}
|
|
3498
3882
|
else {
|
|
3499
|
-
|
|
3883
|
+
doTheDeletion();
|
|
3500
3884
|
}
|
|
3501
3885
|
});
|
|
3502
3886
|
}
|
|
3503
3887
|
else {
|
|
3504
|
-
|
|
3888
|
+
doTheDeletion();
|
|
3505
3889
|
}
|
|
3506
3890
|
}
|
|
3507
|
-
})
|
|
3891
|
+
})
|
|
3892
|
+
.catch(_handleCancel);
|
|
3508
3893
|
}
|
|
3509
3894
|
};
|
|
3510
3895
|
$scope.isCancelDisabled = function () {
|
|
3511
|
-
if (
|
|
3896
|
+
if ($scope[$scope.topLevelFormName] && $scope[$scope.topLevelFormName].$pristine) {
|
|
3897
|
+
return true;
|
|
3898
|
+
}
|
|
3899
|
+
else if (typeof $scope.disableFunctions.isCancelDisabled === "function") {
|
|
3512
3900
|
return $scope.disableFunctions.isCancelDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3513
3901
|
}
|
|
3514
3902
|
else {
|
|
3515
|
-
return
|
|
3903
|
+
return false;
|
|
3516
3904
|
}
|
|
3517
3905
|
};
|
|
3518
3906
|
$scope.isSaveDisabled = function () {
|
|
3519
|
-
|
|
3520
|
-
|
|
3907
|
+
$scope.whyDisabled = undefined;
|
|
3908
|
+
var pristine = false;
|
|
3909
|
+
function generateWhyDisabledMessage(form, subFormName) {
|
|
3910
|
+
form.$$controls.forEach(function (c) {
|
|
3911
|
+
if (c.$invalid) {
|
|
3912
|
+
if (c.$$controls) {
|
|
3913
|
+
// nested form
|
|
3914
|
+
generateWhyDisabledMessage(c, c.$name);
|
|
3915
|
+
}
|
|
3916
|
+
else {
|
|
3917
|
+
$scope.whyDisabled += "<br /><strong>";
|
|
3918
|
+
if (subFormName) {
|
|
3919
|
+
$scope.whyDisabled += subFormName + ' ';
|
|
3920
|
+
}
|
|
3921
|
+
if (cssFrameworkService.framework() === "bs2" &&
|
|
3922
|
+
c.$$element &&
|
|
3923
|
+
c.$$element.parent() &&
|
|
3924
|
+
c.$$element.parent().parent() &&
|
|
3925
|
+
c.$$element.parent().parent().find("label") &&
|
|
3926
|
+
c.$$element.parent().parent().find("label").text()) {
|
|
3927
|
+
$scope.whyDisabled += c.$$element.parent().parent().find("label").text();
|
|
3928
|
+
}
|
|
3929
|
+
else if (cssFrameworkService.framework() === "bs3" &&
|
|
3930
|
+
c.$$element &&
|
|
3931
|
+
c.$$element.parent() &&
|
|
3932
|
+
c.$$element.parent().parent() &&
|
|
3933
|
+
c.$$element.parent().parent().parent() &&
|
|
3934
|
+
c.$$element.parent().parent().parent().find("label") &&
|
|
3935
|
+
c.$$element.parent().parent().parent().find("label").text()) {
|
|
3936
|
+
$scope.whyDisabled += c.$$element.parent().parent().parent().find("label").text();
|
|
3937
|
+
}
|
|
3938
|
+
else {
|
|
3939
|
+
$scope.whyDisabled += c.$name;
|
|
3940
|
+
}
|
|
3941
|
+
$scope.whyDisabled += "</strong>: ";
|
|
3942
|
+
if (c.$error) {
|
|
3943
|
+
for (var type in c.$error) {
|
|
3944
|
+
if (c.$error.hasOwnProperty(type)) {
|
|
3945
|
+
switch (type) {
|
|
3946
|
+
case "required":
|
|
3947
|
+
$scope.whyDisabled += "Field missing required value. ";
|
|
3948
|
+
break;
|
|
3949
|
+
case "pattern":
|
|
3950
|
+
$scope.whyDisabled += "Field does not match required pattern. ";
|
|
3951
|
+
break;
|
|
3952
|
+
default:
|
|
3953
|
+
$scope.whyDisabled += type + ". ";
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
});
|
|
3961
|
+
}
|
|
3962
|
+
if ($scope[$scope.topLevelFormName]) {
|
|
3963
|
+
if ($scope[$scope.topLevelFormName].$invalid) {
|
|
3964
|
+
$scope.whyDisabled = 'The form data is invalid:';
|
|
3965
|
+
generateWhyDisabledMessage($scope[$scope.topLevelFormName]);
|
|
3966
|
+
}
|
|
3967
|
+
else if ($scope[$scope.topLevelFormName].$pristine) {
|
|
3968
|
+
// Don't have disabled message - should be obvious from Cancel being disabled,
|
|
3969
|
+
// and the message comes up when the Save button is clicked.
|
|
3970
|
+
pristine = true;
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3973
|
+
else {
|
|
3974
|
+
$scope.whyDisabled = "Top level form name invalid";
|
|
3975
|
+
}
|
|
3976
|
+
if (pristine || !!$scope.whyDisabled) {
|
|
3977
|
+
return true;
|
|
3978
|
+
}
|
|
3979
|
+
else if (typeof $scope.disableFunctions.isSaveDisabled !== "function") {
|
|
3980
|
+
return false;
|
|
3521
3981
|
}
|
|
3522
3982
|
else {
|
|
3523
|
-
|
|
3983
|
+
var retVal = $scope.disableFunctions.isSaveDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3984
|
+
if (typeof retVal === "string") {
|
|
3985
|
+
$scope.whyDisabled = retVal;
|
|
3986
|
+
}
|
|
3987
|
+
else {
|
|
3988
|
+
$scope.whyDisabled = "An application level user-specified function is inhibiting saving the record";
|
|
3989
|
+
}
|
|
3990
|
+
return !!retVal;
|
|
3524
3991
|
}
|
|
3525
3992
|
};
|
|
3526
3993
|
$scope.isDeleteDisabled = function () {
|
|
3527
|
-
if (
|
|
3994
|
+
if (!$scope.id) {
|
|
3995
|
+
return true;
|
|
3996
|
+
}
|
|
3997
|
+
else if (typeof $scope.disableFunctions.isDeleteDisabled === "function") {
|
|
3528
3998
|
return $scope.disableFunctions.isDeleteDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3529
3999
|
}
|
|
3530
4000
|
else {
|
|
3531
|
-
return
|
|
4001
|
+
return false;
|
|
3532
4002
|
}
|
|
3533
4003
|
};
|
|
3534
4004
|
$scope.isNewDisabled = function () {
|
|
3535
|
-
if (typeof $scope.disableFunctions.isNewDisabled ===
|
|
4005
|
+
if (typeof $scope.disableFunctions.isNewDisabled === "function") {
|
|
3536
4006
|
return $scope.disableFunctions.isNewDisabled($scope.record, ctrlState.master, $scope[$scope.topLevelFormName]);
|
|
3537
4007
|
}
|
|
3538
4008
|
else {
|
|
3539
4009
|
return false;
|
|
3540
4010
|
}
|
|
3541
4011
|
};
|
|
3542
|
-
$scope.
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
4012
|
+
$scope.setDefaults = function (formSchema, base) {
|
|
4013
|
+
if (base === void 0) { base = ''; }
|
|
4014
|
+
var retVal = {};
|
|
4015
|
+
formSchema.forEach(function (s) {
|
|
4016
|
+
if (s.defaultValue !== undefined) {
|
|
4017
|
+
retVal[s.name.replace(base, '')] = s.defaultValue;
|
|
4018
|
+
}
|
|
4019
|
+
});
|
|
4020
|
+
return retVal;
|
|
3548
4021
|
};
|
|
3549
4022
|
$scope.getVal = function (expression, index) {
|
|
3550
|
-
if (expression.indexOf(
|
|
4023
|
+
if (expression.indexOf("$index") === -1 || typeof index !== "undefined") {
|
|
3551
4024
|
expression = expression.replace(/\$index/g, index);
|
|
3552
|
-
return $scope.$eval(
|
|
4025
|
+
return $scope.$eval("record." + expression);
|
|
3553
4026
|
}
|
|
3554
4027
|
//else {
|
|
3555
4028
|
// Used to show error here, but angular seems to call before record is populated sometimes
|
|
@@ -3563,6 +4036,30 @@ var fng;
|
|
|
3563
4036
|
}
|
|
3564
4037
|
}
|
|
3565
4038
|
};
|
|
4039
|
+
$scope.setUpCustomLookupOptions = function (schemaElement, ids, options, baseScope) {
|
|
4040
|
+
for (var _i = 0, _a = [$scope, baseScope]; _i < _a.length; _i++) {
|
|
4041
|
+
var scope = _a[_i];
|
|
4042
|
+
if (scope) {
|
|
4043
|
+
// need to be accessible on our scope for generation of the select options, and - for nested schemas -
|
|
4044
|
+
// on baseScope for the conversion back to ids done by prepareForSave
|
|
4045
|
+
scope[schemaElement.ids] = ids;
|
|
4046
|
+
scope[schemaElement.options] = options;
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
var data = getData($scope.record, schemaElement.name);
|
|
4050
|
+
if (!data) {
|
|
4051
|
+
return;
|
|
4052
|
+
}
|
|
4053
|
+
if (angular.isArray(data)) {
|
|
4054
|
+
for (var i = 0; i < data.length; i++) {
|
|
4055
|
+
data[i] = convertIdToListValue(data[i], ids, options, schemaElement.name);
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
else {
|
|
4059
|
+
data = convertIdToListValue(data, ids, options, schemaElement.name);
|
|
4060
|
+
}
|
|
4061
|
+
setData($scope.record, schemaElement.name, undefined, data);
|
|
4062
|
+
};
|
|
3566
4063
|
},
|
|
3567
4064
|
fillFormFromBackendCustomSchema: fillFormFromBackendCustomSchema,
|
|
3568
4065
|
fillFormWithBackendSchema: function fillFormWithBackendSchema($scope, formGeneratorInstance, recordHandlerInstance, ctrlState) {
|
|
@@ -3602,6 +4099,7 @@ var fng;
|
|
|
3602
4099
|
/*@ngInject*/
|
|
3603
4100
|
SubmissionsService.$inject = ["$http", "$cacheFactory"];
|
|
3604
4101
|
function SubmissionsService($http, $cacheFactory) {
|
|
4102
|
+
var useCacheForGetAll = true;
|
|
3605
4103
|
/*
|
|
3606
4104
|
generate a query string for a filtered and paginated query for submissions.
|
|
3607
4105
|
options consists of the following:
|
|
@@ -3659,11 +4157,7 @@ var fng;
|
|
|
3659
4157
|
// };
|
|
3660
4158
|
// },
|
|
3661
4159
|
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');
|
|
4160
|
+
return $http.get('/api/' + ref + '/' + id + '/list');
|
|
3667
4161
|
},
|
|
3668
4162
|
readRecord: function (modelName, id) {
|
|
3669
4163
|
// TODO Figure out tab history updates (check for other tab-history-todos)
|
|
@@ -3679,7 +4173,7 @@ var fng;
|
|
|
3679
4173
|
},
|
|
3680
4174
|
getAll: function (modelName, _options) {
|
|
3681
4175
|
var options = angular.extend({
|
|
3682
|
-
cache:
|
|
4176
|
+
cache: useCacheForGetAll
|
|
3683
4177
|
}, _options);
|
|
3684
4178
|
return $http.get('/api/' + modelName, options);
|
|
3685
4179
|
},
|
|
@@ -3696,6 +4190,15 @@ var fng;
|
|
|
3696
4190
|
createRecord: function (modelName, dataToSave) {
|
|
3697
4191
|
$cacheFactory.get('$http').remove('/api/' + modelName);
|
|
3698
4192
|
return $http.post('/api/' + modelName, dataToSave);
|
|
4193
|
+
},
|
|
4194
|
+
useCache: function (val) {
|
|
4195
|
+
useCacheForGetAll = val;
|
|
4196
|
+
},
|
|
4197
|
+
getCache: function () {
|
|
4198
|
+
return !!$cacheFactory.get('$http');
|
|
4199
|
+
},
|
|
4200
|
+
clearCache: function () {
|
|
4201
|
+
$cacheFactory.get('$http').removeAll();
|
|
3699
4202
|
}
|
|
3700
4203
|
};
|
|
3701
4204
|
}
|
|
@@ -3721,6 +4224,7 @@ var fng;
|
|
|
3721
4224
|
fngInvalidRequired: 'fng-invalid-required',
|
|
3722
4225
|
allowLocationChange: true // Set when the data arrives..
|
|
3723
4226
|
};
|
|
4227
|
+
$scope.errorVisible = false;
|
|
3724
4228
|
angular.extend($scope, routingService.parsePathFunc()($location.$$path));
|
|
3725
4229
|
// Load context menu. For /person/client/:id/edit we need
|
|
3726
4230
|
// to load PersonCtrl and PersonClientCtrl
|
|
@@ -3735,17 +4239,33 @@ var fng;
|
|
|
3735
4239
|
$rootScope.$broadcast('fngFormLoadStart', $scope);
|
|
3736
4240
|
formGenerator.decorateScope($scope, formGenerator, recordHandler, $scope.sharedData);
|
|
3737
4241
|
recordHandler.decorateScope($scope, $uibModal, recordHandler, ctrlState);
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
$scope.sharedData.modelControllers[i].onBaseCtrlReady
|
|
4242
|
+
function processTheForm() {
|
|
4243
|
+
recordHandler.fillFormWithBackendSchema($scope, formGenerator, recordHandler, ctrlState);
|
|
4244
|
+
// Tell the 'model controllers' that they can start fiddling with baseScope
|
|
4245
|
+
for (var i = 0; i < $scope.sharedData.modelControllers.length; i++) {
|
|
4246
|
+
if ($scope.sharedData.modelControllers[i].onBaseCtrlReady) {
|
|
4247
|
+
$scope.sharedData.modelControllers[i].onBaseCtrlReady($scope);
|
|
4248
|
+
}
|
|
3743
4249
|
}
|
|
4250
|
+
$scope.$on('$destroy', function () {
|
|
4251
|
+
$scope.sharedData.modelControllers.forEach(function (value) { return value.$destroy(); });
|
|
4252
|
+
$rootScope.$broadcast('fngControllersUnloaded');
|
|
4253
|
+
});
|
|
4254
|
+
}
|
|
4255
|
+
//Check that we are ready
|
|
4256
|
+
if (typeof fng.formsAngular.beforeProcess === "function") {
|
|
4257
|
+
fng.formsAngular.beforeProcess($scope, function (err) {
|
|
4258
|
+
if (err) {
|
|
4259
|
+
$scope.showError(err.message, 'Error preparing to process form');
|
|
4260
|
+
}
|
|
4261
|
+
else {
|
|
4262
|
+
processTheForm();
|
|
4263
|
+
}
|
|
4264
|
+
});
|
|
4265
|
+
}
|
|
4266
|
+
else {
|
|
4267
|
+
processTheForm();
|
|
3744
4268
|
}
|
|
3745
|
-
$scope.$on('$destroy', function () {
|
|
3746
|
-
$scope.sharedData.modelControllers.forEach(function (value) { return value.$destroy(); });
|
|
3747
|
-
$rootScope.$broadcast('fngControllersUnloaded');
|
|
3748
|
-
});
|
|
3749
4269
|
}
|
|
3750
4270
|
controllers.BaseCtrl = BaseCtrl;
|
|
3751
4271
|
})(controllers = fng.controllers || (fng.controllers = {}));
|
|
@@ -3801,13 +4321,17 @@ var fng;
|
|
|
3801
4321
|
var controllers;
|
|
3802
4322
|
(function (controllers) {
|
|
3803
4323
|
/*@ngInject*/
|
|
3804
|
-
NavCtrl.$inject = ["$scope", "$location", "$filter", "routingService", "cssFrameworkService"];
|
|
3805
|
-
function NavCtrl($scope, $location, $filter, routingService, cssFrameworkService) {
|
|
4324
|
+
NavCtrl.$inject = ["$rootScope", "$scope", "$location", "$filter", "routingService", "cssFrameworkService"];
|
|
4325
|
+
function NavCtrl($rootScope, $scope, $location, $filter, routingService, cssFrameworkService) {
|
|
3806
4326
|
function clearContextMenu() {
|
|
3807
4327
|
$scope.items = [];
|
|
3808
4328
|
$scope.contextMenu = undefined;
|
|
3809
4329
|
}
|
|
4330
|
+
$rootScope.navScope = $scope; // Lets plugins access menus
|
|
3810
4331
|
clearContextMenu();
|
|
4332
|
+
$scope.toggleCollapsed = function () {
|
|
4333
|
+
$scope.collapsed = !$scope.collapsed;
|
|
4334
|
+
};
|
|
3811
4335
|
/* 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
4336
|
$scope.isCollapsed = true;
|
|
3813
4337
|
$scope.showShortcuts = false;
|
|
@@ -3835,8 +4359,8 @@ var fng;
|
|
|
3835
4359
|
}
|
|
3836
4360
|
}
|
|
3837
4361
|
function filter(event) {
|
|
3838
|
-
var tagName = (event.target
|
|
3839
|
-
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
|
|
4362
|
+
var tagName = (event.target).tagName;
|
|
4363
|
+
return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA' || tagName == "DIV" && event.target.classList.contains('ck-editor__editable'));
|
|
3840
4364
|
}
|
|
3841
4365
|
//console.log(event.keyCode, event.ctrlKey, event.shiftKey, event.altKey, event.metaKey);
|
|
3842
4366
|
if (event.keyCode === 191 && (filter(event) || (event.ctrlKey && !event.altKey && !event.metaKey))) {
|
|
@@ -3865,7 +4389,7 @@ var fng;
|
|
|
3865
4389
|
else if (event.keyCode === 45 && event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey) {
|
|
3866
4390
|
deferredBtnClick('newButton'); // Ctrl+Shift+Ins creates New record
|
|
3867
4391
|
}
|
|
3868
|
-
else if (event.keyCode === 88 && event.ctrlKey && event.shiftKey && event.altKey && !event.metaKey) {
|
|
4392
|
+
else if (event.keyCode === 88 && event.ctrlKey && event.shiftKey && !event.altKey && !event.metaKey) {
|
|
3869
4393
|
deferredBtnClick('deleteButton'); // Ctrl+Shift+X deletes record
|
|
3870
4394
|
}
|
|
3871
4395
|
};
|
|
@@ -3881,6 +4405,11 @@ var fng;
|
|
|
3881
4405
|
};
|
|
3882
4406
|
$scope.$on('fngControllersLoaded', function (evt, sharedData, modelName) {
|
|
3883
4407
|
$scope.contextMenu = sharedData.dropDownDisplay || sharedData.modelNameDisplay || $filter('titleCase')(modelName, false);
|
|
4408
|
+
if (sharedData.dropDownDisplayPromise) {
|
|
4409
|
+
sharedData.dropDownDisplayPromise.then(function (value) {
|
|
4410
|
+
$scope.contextMenu = value;
|
|
4411
|
+
});
|
|
4412
|
+
}
|
|
3884
4413
|
});
|
|
3885
4414
|
$scope.$on('fngControllersUnloaded', function (evt) {
|
|
3886
4415
|
clearContextMenu();
|
|
@@ -3896,28 +4425,59 @@ var fng;
|
|
|
3896
4425
|
}
|
|
3897
4426
|
else {
|
|
3898
4427
|
// 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
|
-
|
|
4428
|
+
var args = item.args || [];
|
|
4429
|
+
var fn = item.fn;
|
|
4430
|
+
if (typeof fn === "function") {
|
|
4431
|
+
switch (args.length) {
|
|
4432
|
+
case 0:
|
|
4433
|
+
fn();
|
|
4434
|
+
break;
|
|
4435
|
+
case 1:
|
|
4436
|
+
fn(args[0]);
|
|
4437
|
+
break;
|
|
4438
|
+
case 2:
|
|
4439
|
+
fn(args[0], args[1]);
|
|
4440
|
+
break;
|
|
4441
|
+
case 3:
|
|
4442
|
+
fn(args[0], args[1], args[2]);
|
|
4443
|
+
break;
|
|
4444
|
+
case 4:
|
|
4445
|
+
fn(args[0], args[1], args[2], args[3]);
|
|
4446
|
+
break;
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4449
|
+
else if (fn) {
|
|
4450
|
+
throw new Error("Incorrect menu setup");
|
|
3916
4451
|
}
|
|
3917
4452
|
}
|
|
3918
4453
|
};
|
|
3919
4454
|
$scope.isHidden = function (index) {
|
|
3920
|
-
|
|
4455
|
+
function explicitlyHidden(item) {
|
|
4456
|
+
return item.isHidden ? item.isHidden() : false;
|
|
4457
|
+
}
|
|
4458
|
+
var dividerHide = false;
|
|
4459
|
+
// Hide a divider if it appears under another
|
|
4460
|
+
if ($scope.items[index].divider) {
|
|
4461
|
+
if (index === 0) {
|
|
4462
|
+
dividerHide = true;
|
|
4463
|
+
}
|
|
4464
|
+
else {
|
|
4465
|
+
var foundVisible = false;
|
|
4466
|
+
var check = index - 1;
|
|
4467
|
+
while (check >= 0 && !dividerHide && !foundVisible) {
|
|
4468
|
+
if ($scope.items[check].divider) {
|
|
4469
|
+
dividerHide = true;
|
|
4470
|
+
}
|
|
4471
|
+
else if (!explicitlyHidden($scope.items[check])) {
|
|
4472
|
+
foundVisible = true;
|
|
4473
|
+
}
|
|
4474
|
+
else {
|
|
4475
|
+
--check;
|
|
4476
|
+
}
|
|
4477
|
+
}
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
return dividerHide || explicitlyHidden($scope.items[index]);
|
|
3921
4481
|
};
|
|
3922
4482
|
$scope.isDisabled = function (index) {
|
|
3923
4483
|
return $scope.items[index].isDisabled ? $scope.items[index].isDisabled() : false;
|
|
@@ -3976,6 +4536,7 @@ var fng;
|
|
|
3976
4536
|
])
|
|
3977
4537
|
.controller('BaseCtrl', fng.controllers.BaseCtrl)
|
|
3978
4538
|
.controller('SaveChangesModalCtrl', fng.controllers.SaveChangesModalCtrl)
|
|
4539
|
+
.controller('LinkCtrl', fng.controllers.LinkCtrl)
|
|
3979
4540
|
.controller('ModelCtrl', fng.controllers.ModelCtrl)
|
|
3980
4541
|
.controller('NavCtrl', fng.controllers.NavCtrl)
|
|
3981
4542
|
.directive('modelControllerDropdown', fng.directives.modelControllerDropdown)
|
|
@@ -3987,6 +4548,7 @@ var fng;
|
|
|
3987
4548
|
.directive('fngNakedDate', fng.directives.fngNakedDate)
|
|
3988
4549
|
.filter('camelCase', fng.filters.camelCase)
|
|
3989
4550
|
.filter('titleCase', fng.filters.titleCase)
|
|
4551
|
+
.filter('extractTimestampFromMongoID', fng.filters.extractTimestampFromMongoID)
|
|
3990
4552
|
.service('addAllService', fng.services.addAllService)
|
|
3991
4553
|
.provider('cssFrameworkService', fng.services.cssFrameworkService)
|
|
3992
4554
|
.provider('routingService', fng.services.routingService)
|
|
@@ -4002,11 +4564,15 @@ var fng;
|
|
|
4002
4564
|
// expose the library
|
|
4003
4565
|
var formsAngular = fng.formsAngular;
|
|
4004
4566
|
|
|
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
|
|
4567
|
+
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');
|
|
4568
|
+
$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');
|
|
4569
|
+
$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');
|
|
4570
|
+
$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');
|
|
4571
|
+
$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');
|
|
4572
|
+
$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');
|
|
4573
|
+
$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
4574
|
$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');}]);
|
|
4575
|
+
$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');
|
|
4576
|
+
$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');
|
|
4577
|
+
$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');
|
|
4578
|
+
$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');}]);
|