forms-angular 0.12.0-beta.167 → 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.
@@ -121,7 +121,10 @@ var fng;
121
121
  attrib = splitAttrib.pop();
122
122
  attrib = splitAttrib.join('.') + '[' + workScope['$index'] + '].' + attrib;
123
123
  }
124
- watchExpression = workString + 'record.' + attrib;
124
+ else {
125
+ attrib = '.' + attrib;
126
+ }
127
+ watchExpression = workString + 'record' + attrib;
125
128
  }
126
129
  scope.$watch(watchExpression, function (newVal) {
127
130
  if (newVal) {
@@ -449,6 +452,7 @@ var fng;
449
452
  case 'checkbox':
450
453
  common += requiredStr;
451
454
  common += handleReadOnlyDisabled(fieldInfo.readonly);
455
+ common += fieldInfo.add ? (' ' + fieldInfo.add + ' ') : '';
452
456
  value = formMarkupHelper.generateSimpleInput(common, fieldInfo, options);
453
457
  if (cssFrameworkService.framework() === 'bs3') {
454
458
  value = '<div class="checkbox">' + value + '</div>';
@@ -522,7 +526,7 @@ var fng;
522
526
  if (tabNo >= 0) {
523
527
  // TODO Figure out tab history updates (check for other tab-history-todos)
524
528
  // result.before = '<uib-tab deselect="tabDeselect($event, $selectedIndex)" select="updateQueryForTab(\'' + info.title + '\')" heading="' + info.title + '"'
525
- 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 + '"';
526
530
  if (tabNo > 0) {
527
531
  result.before += 'active="tabs[' + tabNo + '].active"';
528
532
  }
@@ -707,6 +711,15 @@ var fng;
707
711
  }
708
712
  template += '</div> ';
709
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
+ }
710
723
  template += processInstructions(info.schema, false, {
711
724
  subschema: 'true',
712
725
  formstyle: info.formStyle,
@@ -714,6 +727,9 @@ var fng;
714
727
  subschemaroot: info.name,
715
728
  suppressNestingWarning: info.suppressNestingWarning
716
729
  });
730
+ if (parts === null || parts === void 0 ? void 0 : parts.after) {
731
+ template += parts.after;
732
+ }
717
733
  if (cssFrameworkService.framework() === 'bs2') {
718
734
  template += ' </div>';
719
735
  }
@@ -726,7 +742,7 @@ var fng;
726
742
  footer = info.customFooter;
727
743
  }
728
744
  var hideCond = '';
729
- var indicatorShowCond = options.model + "." + info.name + ".length == 0";
745
+ var indicatorShowCond = model + ".length == 0";
730
746
  if (info.noAdd === true) {
731
747
  indicatorShowCond = "ng-show=\"" + indicatorShowCond + "\"";
732
748
  }
@@ -738,7 +754,7 @@ var fng;
738
754
  if (info.noneIndicator) {
739
755
  footer += "<span " + indicatorShowCond + " class=\"none_indicator\" id=\"no_" + info.id + "_indicator\">None</span>";
740
756
  // hideCond for the schema-foot is if there's no add button and no indicator
741
- hideCond = options.model + "." + info.name + ".length > 0";
757
+ hideCond = model + ".length > 0";
742
758
  if (info.noAdd === true) {
743
759
  hideCond = "ng-hide=\"" + hideCond + "\"";
744
760
  }
@@ -817,7 +833,8 @@ var fng;
817
833
  var callHandleField = true;
818
834
  if (info.directive) {
819
835
  var directiveName = info.directive;
820
- var newElement = '<' + directiveName + ' model="' + (options.model || 'record') + '"';
836
+ var newElement = info.customHeader || "";
837
+ newElement += '<' + directiveName + ' model="' + (options.model || 'record') + '"';
821
838
  var thisElement = element[0];
822
839
  inferMissingProperties(info, options);
823
840
  for (var i = 0; i < thisElement.attributes.length; i++) {
@@ -896,6 +913,7 @@ var fng;
896
913
  }
897
914
  }
898
915
  newElement += 'ng-model="' + info.name + '"></' + directiveName + '>';
916
+ newElement += (info.customFooter || "");
899
917
  result += newElement;
900
918
  callHandleField = false;
901
919
  }
@@ -4556,5 +4574,5 @@ $templateCache.put('error-display-bs3.html','<div id="display-error" ng-show="er
4556
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');
4557
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');
4558
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');
4559
- $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');
4560
- $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');}]);
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');}]);
@@ -1 +1 @@
1
- var fng;!function(e){(e.directives||(e.directives={})).modelControllerDropdown=function(){return{restrict:"AE",replace:!0,template:'<li ng-show="items.length > 0" class="mcdd" uib-dropdown> <a href="#" uib-dropdown-toggle> {{contextMenu}} <b class="caret"></b> </a> <ul class="uib-dropdown-menu dropdown-menu"> <li ng-repeat="choice in items" ng-hide="isHidden($index)" ng-class="dropdownClass($index)"> <a ng-show="choice.text" class="dropdown-option" ng-href="{{choice.url || choice.urlFunc()}}" ng-click="doClick($index, $event)"> {{choice.text}} </a> </li> </ul></li>'}}}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"E",templateUrl:"error-display-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.errorDisplay=n}(fng=fng||{}),function(e){var t;function n(a){a.checkNotModal=function(){for(var e,t=a.element[0],n=!1,r={preventDefault:angular.noop,stopPropagation:angular.noop,target:1,currentTarget:1};(e=t.parentNode)?"function"==typeof e.getAttribute&&e.getAttribute("uib-modal-window")?(angular.element(t).scope().close(r),n=!0):t=e:n=!0,!n;);}}t=e.controllers||(e.controllers={}),n.$inject=["$scope"],t.LinkCtrl=n}(fng=fng||{}),function(e){var t;function n(p,m){return{restrict:"E",scope:{dataSrc:"&model"},link:function(n,e,r){var a=r.ref,t=r.text&&unescape(r.text)!==r.text,o=r.form,i=r.linktab;if(n.readonly=r.readonly,n.element=e,o=o?o+"/":"",i=i?"/"+i:"",t){for(var s=n,l="";"function"!=typeof s.baseSchema&&s.$parent;){if(void 0!==s.$index)throw new Error("No support for $index at this level - "+l);s=s.$parent,l+="$parent."}var c,d=r.fld;if(n.$parent.subDoc&&n.$parent.subDoc[d])c=l+"subDoc."+d;else{if(void 0!==s.$index){var u=d.split(".");d=u.pop(),d=u.join(".")+"["+s.$index+"]."+d}c=l+"record."+d}n.$watch(c,function(e){if(e){if(/^[a-f0-9]{24}/.test(e.toString()))e=e.slice(0,24);else if(e.id&&/^[a-f0-9]{24}/.test(e.id))e=e.id.slice(0,24);else if(n.$parent["f_"+r.fld+"Options"]){var t=n.$parent["f_"+r.fld+"Options"].indexOf(e);e=-1<t?n.$parent["f_"+r.fld+"_ids"][t]:void 0}else e=void 0;n.link=e?p.buildUrl(a+"/"+o+(e.id||e)+"/edit"+i):void 0}else n.link=void 0},!0)}else{r.text&&0<r.text.length&&(n.text=r.text);var f=n.$parent.$index;n.$watch("dataSrc()",function(e){e&&(void 0!==f&&angular.isArray(e)&&(e=e[f]),n.link=p.buildUrl(a+"/"+o+e+"/edit"+i),n.text||m.getListAttributes(a,e).then(function(e){var t=e.data;!1===t.success?n.text=t.err:n.text=t.list},function(e){n.text="Error "+e.status+": "+e.data}))},!0)}},controller:"LinkCtrl",template:function(e,t){function n(e){return'<a ng-click="checkNotModal()" ng-href="{{ link || \'#\' }}" class="fng-link">'+e+"</a>"}return t.readonly?'<span class="fng-link">{{text}}</span>':t.text&&unescape(t.text)!==t.text?n(unescape(t.text)):n("{{text}}")}}}t=e.directives||(e.directives={}),n.$inject=["routingService","SubmissionsService"],t.fngLink=n}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"A",templateUrl:"form-button-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.formButtons=n}(fng=fng||{}),function(e){var t,O,n;function r(c,d,N,E,L,u,A){return{restrict:"EA",link:function(k,x,s){function h(t,e,n,r,a){function o(){var e;if(angular.isArray(k[t.options]))e={repeat:t.options,value:"option"};else{if(!k[t.options]||!angular.isArray(k[t.options].values))throw new Error("Invalid enumeration setup in field "+t.name);e=angular.isArray(k[t.options].labels)?{repeat:t.options+".values",value:t.options+".values[$index]",label:t.options+".labels[$index]"}:{repeat:t.options+".values",value:t.options+".values[$index]"}}return e}var i;if(!e){var s=(a.model||"record")+".";if(e=s,a.subschema&&-1!==t.name.indexOf(".")){var l=t.name,c=a.subschemaroot,d=l.slice(c.length+1);a.index?r="f_"+(e+=c+"["+a.index+"]."+d).slice(s.length).replace(/(\.|\[|]\.)/g,"-"):(e+=c,a.subkey?(r=e.slice(s.length).replace(/\./g,"-")+"-subkey"+a.subkeyno+"-"+d,e+="[$_arrayOffset_"+c.replace(/\./g,"_")+"_"+a.subkeyno+"]."+d):(e+="[$index]."+d,r=null,i=l.replace(/\./g,"-")))}else e+=t.name}var u,f,p=A.allInputsVars(k,t,a,e,r,i),m=p.common,h=(n=n||t.required)?" required ":"";function v(e){var t="";return e&&(t="boolean"==typeof e?" disabled ":' ng-disabled="'+e+'" '),t}switch(t.type){case"select":t.select2?u='<input placeholder="fng-select2 has been removed" readonly>':(m+=v(t.readonly),m+=t.add?" "+t.add+" ":"",m+=' aria-label="'+(t.label&&""!==t.label?t.label:t.name)+'" ',u="<select "+m+'class="'+p.formControl.trim()+p.compactClass+p.sizeClassBS2+'" '+h+">",n||(u+="<option></option>"),angular.isArray(t.options)?angular.forEach(t.options,function(e){_.isObject(e)?u+='<option value="'+(e.val||e.id)+'">'+(e.label||e.text)+"</option>":u+="<option>"+e+"</option>"}):(f=o(),u+='<option ng-repeat="option in '+f.repeat+'"',f.label?u+=' value="{{'+f.value+'}}"> {{ '+f.label+" }} </option> ":u+=">{{"+f.value+"}}</option> "),u+="</select>");break;case"link":u='<fng-link model="'+e+'" ref="'+t.ref+'"',t.form&&(u+=' form="'+t.form+'"'),t.linktab&&(u+=' linktab="'+t.linktab+'"'),t.linktext&&(u+=' text="'+t.linktext+'"'),t.readonly&&("boolean"==typeof t.readonly?u+=' readonly="true"':u+=' ng-readonly="'+t.readonly+'"'),u+="></fng-link>";break;case"radio":u="",m+=h,m+=v(t.readonly),m+=t.add?" "+t.add+" ":"";var g="vertical"===a.formstyle||"inline"!==a.formstyle&&!t.inlineRadio;if(angular.isArray(t.options)){var b;a.subschema&&(m=(m=m.replace('name="','name="{{$index}}-')).replace('id="','id="{{$index}}-')),angular.forEach(t.options,function(e,t){b=m.replace('id="','id="'+t+"-"),u+="<input "+b+' type="radio" aria-label="'+e+'" value="'+e+'">'+e,g&&(u+="<br />")})}else{var y=g?"div":"span";a.subschema&&(m=m.replace("$index","$parent.$index").replace('name="','name="{{$parent.$index}}-').replace('id="','id="{{$parent.$index}}-')),f=o(),u+="<"+y+' ng-repeat="option in '+f.repeat+'">',u+="<input "+m.replace('id="','id="{{$index}}-')+' type="radio" aria-label="'+f.value+'" value="{{ '+f.value+' }}"> {{ '+(f.label||f.value)+" }} </"+y+"> "}break;case"checkbox":m+=h,m+=v(t.readonly),u=A.generateSimpleInput(m,t,a),"bs3"===L.framework()&&(u='<div class="checkbox">'+u+"</div>");break;default:m+=A.addTextInputMarkup(p,t,h),u="textarea"===t.type?(t.rows&&("auto"===t.rows?m+='msd-elastic="\n" class="ng-animate" ':m+='rows = "'+t.rows+'" '),"ckEditor"===t.editor&&(console.log('Deprecation Warning: "editor" property deprecated - use "add"'),m+='ckeditor = "" ',"bs3"===L.framework()&&(p.sizeClassBS3="col-xs-12")),"<textarea "+m+"></textarea>"):A.generateSimpleInput(m,t,a)}return A.inputChrome(u,t,a,p)}function v(e){var t;switch(e){case"horizontal":t="form-horizontal";break;case"vertical":t="";break;case"inline":t="form-inline";break;case"stacked":t="form-stacked";break;case"horizontalCompact":default:t="form-horizontal compact"}return t}function $(e){var t={before:"",after:""};if("function"==typeof e.containerType)t=e.containerType(e);else switch(e.containerType){case"tab":for(var n=-1,r=0;r<k.tabs.length;r++)if(k.tabs[r].title===e.title){n=r;break}0<=n?(t.before="<uib-tab select=\"updateQueryForTab('"+e.title+'\')" heading="'+e.title+'"',0<n&&(t.before+='active="tabs['+n+'].active"'),t.before+=">",t.after="</uib-tab>"):(t.before="<p>Error! Tab "+e.title+" not found in tab list</p>",t.after="");break;case"tabset":t.before="<uib-tabset>",t.after="</uib-tabset>";break;case"well":t.before='<div class="well">',e.title&&(t.before+="<h4>"+e.title+"</h4>"),t.after="</div>";break;case"well-large":t.before='<div class="well well-lg well-large">',t.after="</div>";break;case"well-small":t.before='<div class="well well-sm well-small">',t.after="</div>";break;case"fieldset":t.before="<fieldset>",e.title&&(t.before+="<legend>"+e.title+"</legend>"),t.after="</fieldset>";break;case void 0:case null:case"":break;default:if(t.before='<div class="'+e.containerType+'">',e.title){var a=e.titleTagOrClass||"h4";a.match(/h[1-6]/)?t.before+="<"+a+">"+e.title+"</"+a+">":t.before+='<p class="'+a+'">'+e.title+"</p>"}t.after="</div>"}return t}function C(e,t){var n=A.fieldChrome(k,e,t),r=n.template;if(e.schema){var a=e.name.replace(/\./g,"_"),o="$_schema_"+a;if(k[o]=e.schema,e.schema)if(e.subkey){e.subkey.path=e.name,k[o+"_subkey"]=e.subkey;for(var i=angular.isArray(e.subkey)?e.subkey:[e.subkey],s=0;s<i.length;s++){var l=$(i[s]);r+=l.before,r+=F(e.schema,null,{subschema:"true",formstyle:t.formstyle,subkey:o+"_subkey",subkeyno:s,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),r+=l.after}w.push(e)}else if(t.subschema)t.suppressNestingWarning||console.log("Attempts at supporting deep nesting have been removed - will hopefully be re-introduced at a later date");else{var c=(t.model||"record")+"."+e.name;if("string"==typeof e.customHeader)r+=e.customHeader;else{var d="";e.unshift&&(d='<button id="unshift_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini form-btn" ng-click="unshift(\''+e.name+'\',$event)"><i class="'+A.glyphClass()+'-plus"></i> Add</button>'),"bs3"===L.framework()?r+='<div class="row schema-head"><div class="col-sm-offset-3">'+e.label+d+"</div></div>":r+='<div class="schema-head">'+e.label+d+"</div>"}if("inline"===e.formStyle&&e.inlineHeaders&&(r+=function(e,t,n,r){for(var a='<div class="inline-col-headers" style="display:flex" '+(r?"":'ng-hide="!'+n+" || "+n+'.length === 0"')+">",o=0,i=e;o<i.length;o++){var s=i[o];D(s,t),a+="<div ",s.showWhen=s.showWhen||s.showwhen,s.showWhen&&("string"==typeof s.showWhen?a+='ng-show="'+s.showWhen+'"':a+='ng-show="'+A.generateNgShow(s.showWhen,n)+'"'),s.id&&"function"==typeof s.id.replace&&(a+=' id="col_label_'+s.id.replace(/\./g,"-")+'"'),a+=' class="inline-col-header"><label for="'+s.id+'" class="control-label">'+s.label+"</label></div>"}return a+="</div>"}(e.schema,t,c,"always"===e.inlineHeaders)),r+='<ol class="sub-doc"'+(e.sortable?' ui-sortable="sortableOptions" ng-model="'+c+'"':"")+">",r+='<li ng-form class="'+("bs2"===L.framework()?"row-fluid ":"")+(e.inlineHeaders?"width-controlled ":"")+v(e.formStyle)+" "+(e.ngClass?"ng-class:"+e.ngClass:"")+'" name="form_'+a+'{{$index}}" class="sub-doc well" id="'+e.id+'List_{{$index}}" ng-repeat="subDoc in '+c+' track by $index">',"bs2"===L.framework()&&(r+='<div class="row-fluid sub-doc">'),!0===e.noRemove&&!e.customSubDoc||(r+=' <div class="sub-doc-btns">',"string"==typeof e.customSubDoc&&(r+=e.customSubDoc),!0!==e.noRemove&&(r+="<button "+(e.noRemove?'ng-hide="'+e.noRemove+'"':"")+' name="remove_'+e.id+'_btn" ng-click="remove(\''+e.name+"', $index, $event)\"",e.remove?r+=' class="remove-btn btn btn-mini btn-default btn-xs form-btn"><i class="'+A.glyphClass()+'-minus"></i> Remove':(r+=' style="position: relative; z-index: 20;" type="button" class="close pull-right">',"bs3"===L.framework()?r+='<span aria-hidden="true">×</span><span class="sr-only">Close</span>':r+="<span>×</span>"),r+="</button>"),r+="</div> "),r+=F(e.schema,!1,{subschema:"true",formstyle:e.formStyle,model:t.model,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),"bs2"===L.framework()&&(r+=" </div>"),r+="</li>",r+="</ol>",!0!==e.noAdd||"string"==typeof e.customFooter||e.noneIndicator){var u="";"string"==typeof e.customFooter&&(u=e.customFooter);var f="",p=t.model+"."+e.name+".length == 0";!0===e.noAdd?p='ng-show="'+p+'"':(f=e.noAdd?'ng-hide="'+e.noAdd+'"':"",p=e.noAdd?'ng-show="'+e.noAdd+" && "+p+'"':"",u+="<button "+f+' id="add_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini" ng-click="add(\''+e.name+"',$event)\">\n <i class=\"' + formMarkupHelper.glyphClass() + '-plus\"></i> \n Add\n </button>"),e.noneIndicator&&(u+="<span "+p+' class="none_indicator" id="no_'+e.id+'_indicator">None</span>',f=t.model+"."+e.name+".length > 0",f=!0===e.noAdd?'ng-hide="'+f+'"':e.noAdd?'ng-hide="'+e.noAdd+" && "+f+'"':""),""!==u&&("bs3"===L.framework()?r+="<div "+f+' class="row schema-foot"><div class="col-sm-offset-3">'+u+"</div></div>":r+="<div "+f+' class = "schema-foot ">'+u+"</div>")}}}else{var m=A.controlDivClasses(t);if(e.array){if(m.push("fng-array"),"inline"===t.formstyle||"stacked"===t.formstyle)throw new Error("Cannot use arrays in an inline or stacked form");r+=A.label(k,e,"link"!==e.type,t),r+=A.handleArrayInputAndControlDiv(h(e,"link"===e.type?null:"arrayItem.x",!0,e.id+"_{{$index}}",t),m,e,t)}else r+=A.label(k,e,null,t),r+=A.handleInputAndControlDiv(h(e,null,t.required,e.id,t),m)}return r+=n.closeTag}var w=[],S=O.N,D=function(e,t){e.type=e.type||"text",e.id?"number"!=typeof e.id&&!e.id.match(/^[0-9]/)||(e.id="_"+e.id):t&&t.noid?e.id=null:e.id="f_"+e.name.replace(/\./g,"_"),e.label=void 0!==e.label?null===e.label?"":e.label:N("titleCase")(e.name.split(".").slice(-1)[0])},F=function(e,t,n){var r="";if(e)for(var a=0;a<e.length;a++){var o=e[a];n.viewform&&((o=angular.copy(o)).readonly=!0),0===a&&t&&!n.schema.match(/\$_schema_/)&&"object"!=typeof o.add&&(o.add=o.add?" "+o.add+" ":"",-1!==o.add.indexOf("ui-date")||n.noautofocus||o.containerType||(o.add=o.add+"autofocus "));var i=!0;if(o.directive){var s=o.directive,l="<"+s+' model="'+(n.model||"record")+'"',c=x[0];D(o,n);for(var d=0;d<c.attributes.length;d++){var u=c.attributes[d];switch(u.nodeName){case"class":var f=u.value.replace("ng-scope","");0<f.length&&(l+=' class="'+f+'"');break;case"schema":var p=("bespoke_"+o.name).replace(/\./g,"_");k[p]=angular.copy(o),delete k[p].directive,l+=' schema="'+p+'"';break;default:l+=" "+u.nodeName+'="'+u.value+'"'}}l+=" ";var m=N("camelCase")(o.directive);for(var h in o)if(o.hasOwnProperty(h))switch(h){case"directive":case"schema":break;case"add":switch(typeof o.add){case"string":l+=" "+o.add;break;case"object":for(var v in o.add)o.add.hasOwnProperty(v)&&(l+=" "+v+'="'+o.add[v].toString().replace(/"/g,"&quot;")+'"');break;default:throw new Error("Invalid add property of type "+typeof o.add+" in directive "+o.name)}break;case m:for(var g in o[h])o[h].hasOwnProperty(g)&&(l+=" "+o.directive+"-"+g+'="',"string"==typeof o[h][g]?l+=o[h][g].replace(/"/g,"&quot;")+'"':l+=JSON.stringify(o[h][g]).replace(/"/g,"&quot;")+'"');break;default:o[h]&&("string"==typeof o[h]?l+=" fng-fld-"+h+'="'+o[h].replace(/"/g,"&quot;")+'"':l+=" fng-fld-"+h+'="'+JSON.stringify(o[h]).replace(/"/g,"&quot;")+'"')}for(h in n)n.hasOwnProperty(h)&&"$"!==h[0]&&void 0!==n[h]&&(l+=" fng-opt-"+h+'="'+n[h].toString().replace(/"/g,"&quot;")+'"');r+=l+='ng-model="'+o.name+'"></'+s+">",i=!1}else if(o.containerType){var b=$(o);switch(o.containerType){case"tab":if(S===O.N){S=O.Forced,r+='<uib-tabset active="activeTabNo">';var y=_.findIndex(k.tabs,function(e){return e.active});k.activeTabNo=0<=y?y:0}r+=b.before,r+=F(o.content,null,n),r+=b.after;break;case"tabset":S=O.Y,r+=b.before,r+=F(o.content,null,n),r+=b.after;break;default:r+=b.before,r+=F(o.content,null,n),r+=b.after}i=!1}else if(n.subkey){var w=angular.isArray(k[n.subkey])?k[n.subkey][0].keyList:k[n.subkey].keyList;_.find(w,function(e,t){return k[n.subkey].path+"."+t===o.name})&&(i=!1)}i&&(D(o,n),r+=C(o,n))}else console.log("Empty array passed to processInstructions"),r="";return r},l=k.$watch(s.schema,function(e){if(e){var t=angular.isArray(e)?e:[e];if(0<t.length&&"function"==typeof l){l(),l=null;var n="",r=s.model||"record",g=k[r];if(g=g||{},!s.subschema&&!s.model||s.forceform){k.topLevelFormName=s.name||"myForm";var a="";for(var o in s)s.hasOwnProperty(o)&&"$"!==o[0]&&-1===["name","formstyle","schema","subschema","model","viewform"].indexOf(o)&&(a+=" "+s.$attr[o]+'="'+s[o]+'"');n="<"+(s.forceform?"ng-form":"form")+' name="'+k.topLevelFormName+'" class="'+v(s.formstyle)+'" novalidate '+a+">"}else n="";if(g===k.topLevelFormName)throw new Error("Model and Name must be distinct - they are both "+g);n+=F(t,!0,s),S===O.Forced&&(n+="</uib-tabset>"),n+=s.subschema?"":"</form>",x.replaceWith(c(n)(k));var i=k[s.shared||"sharedData"],b=i?i.modelControllers:[];if((0<w.length||0<b.length)&&!k.phaseWatcher)var y=k.$watch("phase",function(e){if(k.phaseWatcher=!0,"ready"===e&&"function"==typeof y){y(),y=null;for(var t=0;t<b.length;t++)b[t].onAllReady&&b[t].onAllReady(k);for(var n=0;n<w.length;n++){for(var r,a,o=w[n],i=angular.isArray(o.subkey)?o.subkey:[o.subkey],s=o.name.split("."),l=g;1<s.length;)l=l[s.shift()]||{};l=l[s[0]]=l[s[0]]||[];for(var c=0;c<i.length;c++){if(i[c].selectFunc){if(!k[i[c].selectFunc]||"function"!=typeof k[i[c].selectFunc])throw new Error("Subkey function "+i[c].selectFunc+" is not properly set up");r=k[i[c].selectFunc](g,o)}else{if(!i[c].keyList)throw new Error("Invalid subkey setup for "+o.name);var d=i[c].keyList;for(r=0;r<l.length;r++){for(var u in a=!0,d)if(d.hasOwnProperty(u)&&l[r][u]!==d[u]&&(void 0===l[r][u]||!l[r][u].text||l[r][u].text!==d[u])){a=!1;break}if(a)break}if(!a)switch(i[c].onNotFound){case"error":var f="Cannot find matching "+(i[c].title||i[c].path);E(function(){k.showError(f,"Unable to set up form correctly")}),r=-1;break;case"create":default:var p=o.name.split("."),m=p.pop(),h=p.join("."),v=g;h&&(v=v[h]),r=v[m].push(d)-1}}k["$_arrayOffset_"+o.name.replace(/\./g,"_")+"_"+c]=r}}}});d.$broadcast("formInputDone",s.name),u.updateDataDependentDisplay&&g&&0<Object.keys(g).length&&u.updateDataDependentDisplay(g,null,!0,k)}}},!0)}}}t=e.directives||(e.directives={}),r.$inject=["$compile","$rootScope","$filter","$timeout","cssFrameworkService","formGenerator","formMarkupHelper"],(n=O=O||{})[n.Y=0]="Y",n[n.N=1]="N",n[n.Forced=2]="Forced",t.formInput=r}(fng=fng||{}),function(e){(e.directives||(e.directives={})).fngNakedDate=function(){return{restrict:"A",require:"ngModel",link:function(e,t,n,r){r.$parsers.push(function(e){if(e)return e.toString()}),r.$formatters.push(function(e){if(e)return new Date(e)})}}}}(fng=fng||{}),function(e){var t;function n(r,t,a,o){var n,e,i,s;s=!1,i=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(i)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(i.substr(0,4)))&&(s=!0),e=!s,r.searchPlaceholder=e?"Ctrl + / to Search":"Search",r.handleKey=function(e){if(27===e.keyCode&&r.searchTarget&&0<r.searchTarget.length)r.searchTarget="";else if(0<r.results.length)switch(e.keyCode){case 38:0<r.focus&&r.setFocus(r.focus-1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 40:r.results.length>r.focus+1&&r.setFocus(r.focus+1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 13:null!=r.focus&&r.selectResult(r.focus)}},r.setFocus=function(e){null!==r.focus&&delete r.results[r.focus].focussed,r.results[e].focussed=!0,r.focus=e},r.selectResult=function(e){var t,n=r.results[e];n.url?t=n.url.replace("|id|",n.id):(t=o.prefix()+"/"+n.resource+"/"+n.id+"/edit",n.resourceTab&&(t+="/"+n.resourceTab)),a.url(t)},r.resultClass=function(e){var t="search-result";return r.results&&r.results[e].focussed&&(t+=" focus"),t};function l(){r.moreCount=0,r.errorClass="",r.results=[],r.focus=null}r.$watch("searchTarget",function(e){e&&0<e.length?(n=r.testTime||(new Date).valueOf(),t.get("/api/search?q="+e+"&sentAt="+n).then(function(e){var t=e.data;t.timestamps&&t.timestamps.sentAt&&Number.parseInt(t.timestamps.sentAt)!==n||(0<r.searchTarget.length?(r.results=t.results,r.moreCount=t.moreCount,0<t.results.length&&(r.errorClass="",r.setFocus(0)),r.errorClass=0===r.results.length?"error has-error":""):l())},function(e){console.log("Error in searchbox.js : "+e.data+" (status="+e.status+")")})):l()},!0),r.$on("$routeChangeStart",function(){r.searchTarget=""})}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.SearchCtrl=n}(fng=fng||{}),function(t){var e;function n(e){return{restrict:"AE",templateUrl:"search-"+e.framework()+".html",controller:t.controllers.SearchCtrl}}e=t.directives||(t.directives={}),n.$inject=["cssFrameworkService"],e.globalSearch=n}(fng=fng||{}),function(e){(e.filters||(e.filters={})).camelCase=function(){return function(e){return e.replace(/([\:\-\_]+(.))/g,function(e,t,n,r){return r?n.toUpperCase():n})}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).extractTimestampFromMongoID=function(){return function(e){var t=e.substring(0,8);return new Date(1e3*parseInt(t,16))}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).titleCase=function(){return function(e,t){return e&&(e=e.replace(/(_|\.)/g," ").replace(/[A-Z]/g," $&").trim().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()}),e=t?e.replace(/\s/g,""):e.replace(/\s{2,}/g," ")),e}}}(fng=fng||{}),function(e){(e.services||(e.services={})).addAllService=function(){function r(e,t,r,n){var a,o,i=[],s=[];if(r="addAll"+r,"string"==typeof n)for(a=n.split(" "),o=0;o<a.length;o++)s.push(a[o]);if(!function e(t){for(var n in t)n===r&&i.push(t[n]),"$parent"===n&&e(t[n])}(e),void 0!==t[r]&&"string"==typeof t[r])for(a=t[r].split(" "),o=0;o<a.length;o++)0===a[o].indexOf("class=")?s.push(a[o].substring(6,a[o].length)):i.push(a[o]);return(n=0<s.length?' class="'+s.join(" ")+'" ':" ")+(0<i.length?i.join(" ")+" ":"")}this.getAddAllGroupOptions=function(e,t,n){return r(e,t,"Group",n)},this.getAddAllFieldOptions=function(e,t,n){return r(e,t,"Field",n)},this.getAddAllLabelOptions=function(e,t,n){return r(e,t,"Label",n)},this.addAll=function(e,t,n,r){return this["getAddAll"+t+"Options"](e,r,n)||[]}}}(fng=fng||{}),function(e){(e.services||(e.services={})).cssFrameworkService=function(){var n={framework:"bs3"};return{setOptions:function(e){angular.extend(n,e)},$get:function(){return{framework:function(){return n.framework},setFrameworkForDemoWebsite:function(e){n.framework=e},span:function(e){var t;switch(n.framework){case"bs2":t="span"+Math.floor(e);break;case"bs3":t="col-xs-"+Math.floor(e)}return t},offset:function(e){var t;switch(n.framework){case"bs2":t="offset"+Math.floor(e);break;case"bs3":t="col-lg-offset-"+Math.floor(e)}return t},rowFluid:function(){var e;switch(n.framework){case"bs2":e="row-fluid";break;case"bs3":e="row"}return e}}}}}}(fng=fng||{}),function(e){function t(c){return{loadControllerAndMenu:function(e,t,n,r,a){var o,i={};t+="Ctrl",i.$scope=e.modelControllers[n]=a;var s=a.$parent;s.items=s.items||[];function l(e){angular.forEach(e,function(e){e.divider?r=!0:e[o]&&(r&&(r=!1,s.items.push({divider:!0})),s.items.push(e))})}try{c(t,i),o=s.newRecord?"creating":s.id?"editing":"listing",angular.isObject(i.$scope.contextMenu)&&(l(i.$scope.contextMenu),i.$scope.contextMenuPromise&&i.$scope.contextMenuPromise.then(function(e){return l(e)})),e.modelNameDisplayPromise&&e.modelNameDisplayPromise.then(function(e){s.modelNameDisplay=e})}catch(e){/is not a function, got undefined/.test(e.message)||/\[\$controller:ctrlreg\] The controller with the name/.test(e.message)||console.log("Unable to instantiate "+t+" - "+e.message)}}}}((e.services||(e.services={})).fngModelCtrlService=t).$inject=["$controller"]}(fng=fng||{}),function(e){var t;function n(n,t){var a,r,s={hashPrefix:"",html5Mode:!1,routing:"ngroute",prefix:""},l=["edit","view"],o=[{route:"/analyse/:model/:reportSchemaName",state:"analyse::model::report",templateUrl:"base-analysis.html"},{route:"/analyse/:model",state:"analyse::model",templateUrl:"base-analysis.html"},{route:"/:model/:id/edit",state:"model::edit",templateUrl:"base-edit.html"},{route:"/:model/:id/edit/:tab",state:"model::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:id/view",state:"model::edit",templateUrl:"base-view.html"},{route:"/:model/:id/view/:tab",state:"model::view::tab",templateUrl:"base-view.html"},{route:"/:model/new",state:"model::new",templateUrl:"base-edit.html"},{route:"/:model",state:"model::list",templateUrl:"base-list.html"},{route:"/:model/viewonly",state:"model::view",templateUrl:"base-list-view.html"},{route:"/:model/:form/:id/edit",state:"model::form::edit",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/edit/:tab",state:"model::form::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/view",state:"model::form::view",templateUrl:"base-view.html"},{route:"/:model/:form/:id/view/:tab",state:"model::form::view::tab",templateUrl:"base-view.html"},{route:"/:model/:form/new",state:"model::form::new",templateUrl:"base-edit.html"},{route:"/:model/:form",state:"model::form::list",templateUrl:"base-list.html"},{route:"/:model/:form/viewonly",state:"model::form::list::view",templateUrl:"base-list-view.html"}],c=null,d={};function i(e){var t=e;return s.templateFolder&&(t="/"!==s.templateFolder[s.templateFolder.length-1]?s.templateFolder+"/"+t:s.templateFolder+t),t}function u(e,n,r){void 0===n&&(n=""),n=n||"",angular.forEach(e,function(e){a.when(n+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))}),s.variantsForDemoWebsite&&angular.forEach(s.variantsForDemoWebsite,function(t){angular.forEach(e,function(e){a.when(n+t+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))})})}function f(e,t,n){void 0===t&&(t=""),t=t||"",angular.forEach(e,function(e){r.state(e.state,angular.extend(e.options||{url:t+e.route,templateUrl:e.templateUrl},n))})}function p(e,t,n,r,a,o){var i,s=r?"/"+r:"",l=e+"/"+n,c=o?"/"+o:"";switch(t){case"list":i=l+s;break;case"edit":i=l+s+"/"+a+"/edit"+c;break;case"view":i=l+s+"/"+a+"/view"+c;break;case"read":i=l+s+"/"+a+"/read"+c;break;case"new":i=l+s+"/new"+c}return i}function m(e,t){switch(s.routing){case"ngroute":a=n.get("$routeProvider"),e&&u(e),u(t,s.prefix,s.add2fngRoutes);break;case"uirouter":r=n.get("$stateProvider"),e&&f(s.fixedRoutes),f(t,s.prefix,s.add2fngRoutes)}}return{start:function(e){angular.extend(s,e),s.prefix[0]&&"/"!==s.prefix[0]&&(s.prefix="/"+s.prefix),t.html5Mode(s.html5Mode),""!==s.hashPrefix?t.hashPrefix(s.hashPrefix):s.html5Mode||t.hashPrefix(""),m(s.fixedRoutes,o)},addRoutes:function(e,t){m(e,t)},registerAction:function(e){l.push(e)},$get:function(){return{router:function(){return s.routing},prefix:function(){return s.prefix},parsePathFunc:function(){return function(e){if(e!==c){c=e,d={newRecord:!1},0<s.prefix.length&&0===e.indexOf(s.prefix)&&(e=e.slice(s.prefix.length));var t=e.split("/");s.variants&&-1!==s.variants.indexOf(t[1])&&(d.variant=t[1],t.shift());var n=t.length;if("analyse"===t[1])d.analyse=!0,d.modelName=t[2],d.reportSchemaName=4<=n?t[3]:null;else{d.modelName=t[1];var r=[t[n-1],t[n-2]],a=r.indexOf("new"),o=r.indexOf("viewonly"),i=void 0;-1===a&&-1===o?-1!==(i=l.reduce(function(e,t){var n=r.indexOf(t);return-1<n?n:e},-1))&&(n-=2+i,d.id=t[n]):-1!==a?(d.newRecord=!0,n-=1+a):n-=1+o,1!==i&&1!==a||(d.tab=r[0]),2<n&&(d.formName=t[2])}}return d}},buildUrl:function(e){var t=s.html5Mode?"":"#";return t+=s.hashPrefix,(t+=s.prefix)[0]&&(t+="/"),t+="/"===e[0]?e.slice(1):e},buildOperationUrl:function(e,t,n,r,a){return p(s.prefix,e,t,n,r,a)},redirectTo:function(){return function(e,t,n,r,a){var o;n.search({}),o="onDelete"===e?s.onDelete?"new"===s.onDelete?p(s.prefix,"new",t.modelName,t.formName,r,a):s.onDelete:p(s.prefix,"list",t.modelName,t.formName,r,a):p(s.prefix,e,t.modelName,t.formName,r,a),n.path(o)}}}}}}t=e.services||(e.services={}),n.$inject=["$injector","$locationProvider"],t.routingService=n}(fng=fng||{}),function(e){function t(e,t,o,n,i){function g(e,t,n,r,a,o,i,s){function l(e,t){var n=angular.copy(e),r=_.find(i.tabs,function(e){return e.title===n});if(!r){if(0===i.tabs.length&&0<i.formSchema.length){i.tabs.push({title:"Main",content:[],active:"Main"===i.tab||!i.tab}),r=i.tabs[0];for(var a=0;a<i.formSchema.length;a++)r.content.push(i.formSchema[a])}r=i.tabs[i.tabs.push({title:n,containerType:"tab",content:[],active:n===i.tab})-1]}r.content.push(t)}for(var c in"function"==typeof i.onSchemaFetch&&i.onSchemaFetch(e,t),t)if(t.hasOwnProperty(c))if("_id"===c)r&&t._id.options&&t._id.options.list&&w(r,t._id.options.list,c);else if(t.hasOwnProperty(c)){var d=t[c],u=d.options||{},f=u.form||{};if(d.schema&&!f.hidden){if(o&&n){var p=[];g("Nested "+c,d.schema,p,null,c+".",!0,i,s);var m=y(c,f,a);m.schema=p,f.tab&&l(f.tab,m),void 0!==f.order?n.splice(f.order,0,m):n.push(m)}}else{if(n&&!f.hidden){var h=y(c,f,a);if(x(h.showIf,h.name,i)&&"options"!==c){var v=b(h,d,u,i,s);v.tab&&l(v.tab,v),void 0!==f.order?n.splice(f.order,0,v):n.push(v)}}r&&u.list&&w(r,u.list,c)}}"function"==typeof i.onSchemaProcessed&&i.onSchemaProcessed(e,"Main "===e.slice(0,5)?i.baseSchema():n),r&&0===r.length&&k(e,r,n,t)}function b(t,e,n,r,a){if(e.caster&&(t.array=!0,e=e.caster,angular.extend(n,e.options),e.options&&e.options.form&&angular.extend(t,e.options.form)),"String"===e.instance)n.enum?(t.type=t.type||"select",t.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):(t.options=i.suffixCleanId(t,"Options"),r[t.options]=n.enum)):(t.type||(t.type=-1!==t.name.toLowerCase().indexOf("password")?"password":"text"),n.match&&(t.add='pattern="'+n.match+'" '+(t.add||"")));else if("ObjectID"===e.instance)t.ref=n.ref,t.link&&(t.link.linkOnly?(t.type="link",t.linktext=t.link.text):t.link.label?t.linklabel=!0:console.log("Unsupported link setup"),t.form=t.link.form,t.linktab=t.link.linktab,delete t.link),"link"!==t.type&&(t.type="select",t.select2||n.form&&n.form.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):t.directive&&(t.noLookup||t[o("camelCase")(t.directive)]&&t[o("camelCase")(t.directive)].fngAjax)||function(){if(t.options=i.suffixCleanId(t,"Options"),t.ids=i.suffixCleanId(t,"_ids"),!t.hidden)if(n.ref)i.setUpLookupOptions(n.ref,t,r,a,g);else if(n.lookupListRef)i.setUpLookupListOptions(n.lookupListRef,t,r,a),t.lookupListRef=n.lookupListRef;else if(n.internalRef)i.handleInternalLookup(r,t,n.internalRef),t.internalRef=n.internalRef;else if(!n.customLookupOptions)throw new Error("No supported select lookup type found in "+t.name)}());else if("Date"===e.instance){if(!t.type)if(t.intType="date",t.readonly)t.type="text";else if(t.directive)t.type="text";else try{t.add=t.add||"",angular.module("ui.date").requires,t.type="text",t.add+=" ui-date ui-date-format "}catch(e){t.type="date",t.add+=' fng-naked-date="x" '}}else if("boolean"===e.instance.toLowerCase())t.type=t.type||"checkbox";else{if("Number"!==e.instance)throw new Error("Field "+t.name+" is of unsupported type "+e.instance);t.type=t.type||"number",void 0!==n.min&&(t.add='min="'+n.min+'" '+(t.add||"")),void 0!==n.max&&(t.add='max="'+n.max+'" '+(t.add||"")),t.step&&(t.add='step="'+t.step+'" '+(t.add||""))}return n.required&&(t.required=!0),n.readonly&&(t.readonly=!0),void 0!==e.defaultValue?t.defaultValue=e.defaultValue:e.options&&void 0!==e.options.default&&console.log("No support for default with no value, yet"),t}function c(e,t,n){for(var r=e.split("."),a=n||t.record,o=0,i=r.length;o<i;o++)a[r[o]]||(a[r[o]]=o===i-1?[]:{}),a=a[r[o]];return a}function v(e,r){function t(e){var t=e;if("string"==typeof e&&"$"===e.slice(0,1)){var n=e.split(".");switch(n.length){case 1:t=i.getListData(r,e.slice(1));break;case 2:t=i.getListData(r,n[1]);break;default:throw new Error("Unsupported showIf format")}}return t}var n,a=t(e.lhs),o=t(e.rhs);switch(e.comp){case"eq":n=a===o;break;case"ne":n=a!==o;break;default:throw new Error("Unsupported comparator "+e.comp)}return n}var y=function(e,t,n){return t.name=n+e,t},w=function(e,t,n){"object"==typeof t?(t.name=n,e.push(t)):e.push({name:n})},k=function(e,t,n,r){if(n){for(var a=0,o=n.length;a<o;a++)if("text"===n[a].type){t.push({name:n[a].name});break}0===t.length&&0!==n.length&&t.push({name:n[0].name})}if(0===t.length){for(var i in r)if("_id"!==i&&r.hasOwnProperty(i)){t.push({name:i});break}if(0===t.length)throw new Error("Unable to generate a title for "+e)}},x=function(e,r,a){var o=0;function t(e){if("string"==typeof e&&"$"===e.slice(0,1)){var t=e.slice(1),n=a.dataDependencies[t]||[];n.push(r),a.dataDependencies[t]=n,o+=1}}var n=!0;return e&&(t(e.lhs),t(e.rhs),0!==o||v(e,void 0)||(n=!1)),n};return{generateEditUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/edit")},generateViewUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/view")},generateNewUrl:function(e){return n.buildUrl(e.modelName+"/"+(e.formName?e.formName+"/":"")+"new")},handleFieldType:b,handleSchema:g,updateDataDependentDisplay:function(e,t,n,r){var a,o,i,s,l,c;for(var d in r.dataDependencies)if(r.dataDependencies.hasOwnProperty(d)){var u=d.split(".");if(1===u.length){if(n||!t||e[d]!==t[d])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var f=a[o];for(i=0;i<r.formSchema.length;i+=1)r.formSchema[i].name===f&&(l=angular.element(document.querySelector("#cg_"+r.formSchema[i].id)),v(r.formSchema[i].showIf,e)?l.removeClass("ng-hide"):l.addClass("ng-hide"))}}else{if(2!==u.length)throw new Error("You can only go down one level of subdocument with showIf");if(void 0===c&&(c=!0),e[u[0]])for(s=0;s<e[u[0]].length;s++)if(n||!t||!t[u[0]]||!t[u[0]][s]||e[u[0]][s][u[1]]!==t[u[0]][s][u[1]])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var p=a[o].split(".");if(2!==p.length)throw new Error("Conditional display must control dependent fields at same level ");for(i=0;i<r.formSchema.length;i+=1)if(r.formSchema[i].name===p[0])for(var m=r.formSchema[i].schema,h=0;h<m.length;h++)m[h].name===a[o]&&(0===(l=angular.element(document.querySelector("#f_"+p[0]+"List_"+s+" #cg_f_"+a[o].replace(".","_")))).length?l=angular.element(document.querySelector("#f_elements-"+s+"-"+p[1])):c=!1,0<l.length&&(v(r.formSchema[i].schema[h].showIf,e[u[0]][s])?l.show():l.hide()))}}}return c},add:function(t,e,n,r){var a;if(e.target.offsetParent){var o=c(t,n,r),i=n.formSchema.find(function(e){return e.name===t}),s=i?i.schema:null,l=s?n.setDefaults(s,t+"."):{};"function"==typeof(null===(a=n.dataEventFunctions)||void 0===a?void 0:a.onInitialiseNewSubDoc)&&n.dataEventFunctions.onInitialiseNewSubDoc(t,s,l),o.push(l),n.setFormDirty(e)}},unshift:function(e,t,n,r){c(e,n,r).unshift({}),n.setFormDirty(t)},remove:function(t,e,n,r,a){var o,i=c(t,r,a);if("function"==typeof r.dataEventFunctions.onDeleteSubDoc){var s=r.formSchema.find(function(e){return e.name===t}),l=s?s.schema:null;o=r.dataEventFunctions.onDeleteSubDoc(t,l,i,e)}o?r.showError(o):(i.splice(e,1),r.setFormDirty(n))},hasError:function(e,t,n,r){var a=!1;if(r){var o=r[r.topLevelFormName];if("null"!==e&&(o=o[e.replace("$index",n)]),o){var i=o[t];i&&i.$invalid&&!i.$$attr.readonly&&(i.$dirty?a=!0:angular.forEach(i.$validators,function(e,t){"required"!==t&&i.$error[t]&&(a=!0)}))}}else console.log("hasError called with no scope! ",e,t,n);return a},decorateScope:function(a,o,n,e){a.record=e.record,a.phase="init",a.disableFunctions=e.disableFunctions,a.dataEventFunctions=e.dataEventFunctions,a.topLevelFormName=void 0,a.formSchema=[],a.tabs=[],a.listSchema=[],a.recordList=[],a.dataDependencies={},a.internalLookups=[],a.listLookups=[],a.conversions={},a.pageSize=60,a.pagesLoaded=0,(e.baseScope=a).generateEditUrl=function(e){return o.generateEditUrl(e,a)},a.generateViewUrl=function(e){return o.generateViewUrl(e,a)},a.generateNewUrl=function(){return o.generateNewUrl(a)},a.scrollTheList=function(){return n.scrollTheList(a)},a.getListData=function(e,t){return n.getListData(e,t,a.listSchema,a)},a.setPristine=function(e){e&&a.dismissError(),a[a.topLevelFormName]&&a[a.topLevelFormName].$setPristine()},a.skipCols=function(e){return 0<e?"col-md-offset-3":""},a.setFormDirty=function(e){e?angular.element(e.target).inheritedData("$formController").$setDirty():console.log("setFormDirty called without an event (fine in a unit test)")},a.add=function(e,t,n){return o.add(e,t,a,n)},a.hasError=function(e,t,n){return o.hasError(e,t,n,a)},a.unshift=function(e,t,n){return o.unshift(e,t,a,n)},a.remove=function(e,t,n,r){return o.remove(e,t,n,a,r)},a.baseSchema=function(){return a.tabs.length?a.tabs:a.formSchema}}}}((e.services||(e.services={})).formGenerator=t).$inject=["$location","$timeout","$filter","routingService","recordHandler"]}(fng=fng||{}),function(e){var t;function n(f,p,m,a){function d(e,t){var n=["vertical","inline"];return t||n.push("stacked"),!e||"undefined"===e||!n.includes(e)}function s(){return"bs2"===f.framework()?"icon":"glyphicon glyphicon"}return{isHorizontalStyle:d,fieldChrome:function(e,t,n){var r=t.classes||"",a="",o="",i="";if(t.showWhen=t.showWhen||t.showwhen,t.showWhen&&("string"==typeof t.showWhen?i+='ng-show="'+t.showWhen+'"':i+='ng-show="'+function(e,a){function t(e){var t=e;if("string"==typeof e)if("$"===e.slice(0,1)){t=(a||"record")+".";var n=e.slice(1).split(".");if(1<n.length){var r=n.pop();t+=n.join(".")+"[$index]."+r}else t+=e.slice(1)}else t="'"+e+"'";return t}var n=["eq","ne","gt","gte","lt","lte"].indexOf(e.comp);if(-1===n)throw new Error("Invalid comparison in showWhen");return t(e.lhs)+["===","!==",">",">=","<","<="][n]+t(e.rhs)}(t.showWhen,n.model)+'"'),t.id&&"function"==typeof t.id.replace&&(i+=' id="cg_'+t.id.replace(/\./g,"-")+'"'),"bs3"===f.framework()){var s;r+=" form-group","vertical"===n.formstyle&&"block-level"!==t.size&&(a+='<div class="row">',r+=" col-sm-"+p.sizeAsNumber(t.size),o+="</div>");var l=null,c=t.name.split(".");s=n&&void 0!==n.subkeyno?n.subschemaroot.replace(/\./g,"-")+"-subkey"+n.subkeyno+"-"+c[c.length-1]:n.subschema?(l="form_"+c.slice(0,-1).join("_")+"$index",t.name.replace(/\./g,"-")):"f_"+t.name.replace(/\./g,"_"),a+="<div"+m.addAll(e,"Group",r,n)+" ng-class=\"{'has-error': hasError('"+l+"','"+s+"', $index)}\"",o+="</div>"}else o=d(n.formstyle,!0)?(a+="<div"+m.addAll(e,"Group","control-group",n),"</div>"):(a+="<span ","</span>");return{template:a+=(i||"")+">",closeTag:o}},label:function(e,t,n,r){var a="";if("bs3"===f.framework()||!["inline","stacked"].includes(r.formstyle)&&""!==t.label||n){a="<label";var o="control-label";if(d(r.formstyle,!1)?(t.linklabel||(a+=' for="'+t.id+'"'),void 0!==t.labelDefaultClass?o+=" "+t.labelDefaultClass:"bs3"===f.framework()&&(o+=" col-sm-3")):["inline","stacked"].includes(r.formstyle)&&(a+=' for="'+t.id+'"',o+=" sr-only"),a+=m.addAll(e,"Label",null,r)+' class="'+o+'">'+t.label,n&&(a+=' <i id="add_'+t.id+'" ng-click="add(\''+t.name+'\',$event)" class="'+s()+'-plus-sign"></i>'),a+="</label>",t.linklabel){var i='<fng-link fld="'+t.name+'" ref="'+t.ref+'" text="'+escape(a)+'"';t.form&&(i+=' form="'+t.form+'"'),t.linktab&&(i+=' linktab="'+t.linktab+'"'),a=i+="></fng-link>"}}return a},glyphClass:s,allInputsVars:function(e,t,n,r,a,o){var i,s=t.placeHolder,l="",c="",d="",u="";return"bs3"===f.framework()?(l=-1===["horizontal","vertical","inline"].indexOf(n.formstyle)?" input-sm":"",c="col-sm-"+p.sizeAsNumber(t.size),u=" form-control"):d=t.size?" input-"+t.size:"",["inline","stacked"].includes(n.formstyle)&&(s=s||t.label),i='data-ng-model="'+r+'"'+(a?' id="'+a+'" name="'+a+'" ':' name="'+o+'" '),i+=s?'placeholder="'+s+'" ':"",t.popup&&(i+='title="'+t.popup+'" '),t.ariaLabel&&(i+='aria-label="'+t.ariaLabel+'" '),{common:i+=m.addAll(e,"Field",null,n),sizeClassBS3:c,sizeClassBS2:d,compactClass:l,formControl:u}},inputChrome:function(e,t,n,r){"bs3"===f.framework()&&d(n.formstyle,!0)&&"checkbox"!==t.type&&(e='<div class="bs3-input '+r.sizeClassBS3+'">'+e+"</div>");var a=(t.helpInline||"")+(t.helpinline||"");if(0<a.length){var o="bs2"===f.framework()?{el:"span",cl:"help-inline"}:{el:"div",cl:"help-block"};e+="<"+o.el+' class="'+o.cl+'">'+a+"</"+o.el+">"}return n.noid||(e+='<div ng-if="'+(n.name||"myForm")+"['"+t.id+'\'].$dirty" class="help-block"> <div ng-messages="'+(n.name||"myForm")+"['"+t.id+'\'].$error"> <div ng-messages-include="error-messages.html"> </div> </div></div>'),t.help&&(e+='<div class="help-block">'+t.help+"</div>"),e},generateSimpleInput:function(e,t,n){var r="<input "+e+'type="'+t.type+'" ';return t.label||t.ariaLabel?n.subschema&&(r+='aria-label="'+(t.label?a("titleCase")(n.subschemaroot)+" "+t.label:t.popup||t.name.replace(/\./g," "))+'" '):r+='aria-label="'+t.name.replace(/\./g," ")+'" ',"inline"!==n.formstyle||"bs2"!==f.framework()||t.size||(r+='class="input-small"'),r+=" />"},controlDivClasses:function(e){var t=[];return d(e.formstyle,!1)&&t.push("bs2"===f.framework()?"controls":"col-sm-9"),t},handleInputAndControlDiv:function(e,t){return 0<t.length&&(e='<div class="'+t.join(" ")+'">'+e+"</div>"),e},handleArrayInputAndControlDiv:function(e,t,n,r){var a="<div ";return"bs3"===f.framework()&&(a+='ng-class="skipCols($index)" '),a+='class="'+t.join(" ")+'" id="'+n.id+'List" ',a+='ng-repeat="arrayItem in '+(r.model||"record")+"."+n.name+' track by $index">',a+=e,"link"!==n.type&&(a+="<i ng-click=\"remove('"+n.name+'\',$index,$event)" id="remove_'+n.id+'_{{$index}}" class="'+s()+'-minus-sign"></i>'),a+="</div>"},addTextInputMarkup:function(e,t,n){var r="",a=e.formControl.trim()+e.compactClass+e.sizeClassBS2+(t.class?" "+t.class:"");return 0!==a.length&&(r+='class="'+a+'"'),t.add&&(r+=" "+t.add+" "),r+=n,t.readonly?r+=" "+("boolean"==typeof t.readOnly?"readonly":'ng-readonly="'+t.readonly+'"')+" ":r+=" ",r}}}t=e.services||(e.services={}),n.$inject=["cssFrameworkService","inputSizeHelper","addAllService","$filter"],t.formMarkupHelper=n}(fng=fng||{}),function(e){(e.services||(e.services={})).inputSizeHelper=function(){var t=[1,2,4,6,8,10,12],n=["mini","small","medium","large","xlarge","xxlarge","block-level"];return{sizeMapping:t,sizeDescriptions:n,defaultSizeOffset:2,sizeAsNumber:function(e){return t[e?n.indexOf(e):2]}}}}(fng=fng||{}),function(e){var t;function n(b){return{extractFromAttr:function(e,t){function n(e){var t=e.replace(/&quot;/g,'"');return"true"===t?t=!0:"false"===t?t=!1:!isNaN(parseFloat(t))&&isFinite(t)&&(t=parseFloat(t)),t}var r={},a={formStyle:e.formstyle},o={},i=t?t.length:0;for(var s in e)e.hasOwnProperty(s)&&("fngFld"===s.slice(0,6)?r[s.slice(6).toLowerCase()]=n(e[s]):"fngOpt"===s.slice(0,6)?a[s.slice(6).toLowerCase()]=n(e[s]):t&&s.slice(0,i)===t&&(o[_.kebabCase(s.slice(i))]=n(e[s])));return{info:r,options:a,directiveOptions:o}},buildInputMarkup:function(e,t,n,r,a,o,i){var s,l,c,d=b.fieldChrome(e,n,r,' id="cg_'+n.id+'"'),u=b.controlDivClasses(r),f=d.template+b.label(e,n,a,r);if(c=a?(s="arrayItem"+(o?".x":""),l=n.id+"_{{$index}}",n.name+"_{{$index}}"):(s=t+"."+n.name,l=n.id,n.name),r.subschema&&-1!==n.name.indexOf(".")){var p=t+".",m=n.name,h=r.subschemaroot,v=m.slice(h.length+1);s=p,r.index?l="f_"+(s+=h+"["+r.index+"]."+v).slice(p.length).replace(/(\.|\[|\]\.)/g,"-"):(s+=h,r.subkey?(l=s.slice(p.length).replace(/\./g,"-")+"-subkey"+r.subkeyno+"-"+v,s+="[$_arrayOffset_"+h.replace(/\./g,"_")+"_"+r.subkeyno+"]."+v):(s+="[$index]."+v,l=null,c=m.replace(/\./g,"-")))}var g=b.allInputsVars(e,n,r,s,l,c);return g.modelString=s,f+=b["handle"+(a?"Array":"")+"InputAndControlDiv"](b.inputChrome(i(g),n,r,g),u,n,r),f+=d.closeTag},findIdInSchemaAndFlagNeedX:function e(t,n){for(var r=!1,a=0;a<t.length;a++){var o=t[a];if(o.id===n){r=o.needsX=!0;break}if(o.schema&&e(o.schema,n)){r=!0;break}}return r}}}t=e.services||(e.services={}),n.$inject=["formMarkupHelper"],t.pluginHelper=n}(fng=fng||{}),function(e){var t;function n(l,o,a,d,i,s,p,e){var c=function(e){return void 0===e&&(e=function(e){return Math.floor(e).toString(16)}),e(Date.now()/1e3)+" ".repeat(16).replace(/./g,function(){return e(16*Math.random())})};function u(e){if(-1===["cancel","backdrop click","escape key press"].indexOf(e))throw e}function b(e,t){return(e.id||"f_"+e.name).replace(/\./g,"_")+t}function f(e,t,n,r){void 0===r&&(r=!1);for(var a=t.split("."),o=a.length-1,i=e,s=0;s<o;s++){if(!i)throw new Error("walkTree failed: Object = "+e+", fieldname = "+t+", i = "+s);if(i=angular.isArray(i)?_.map(i,function(e){return e[a[s]]}):(r&&!i[a[s]]&&(i[a[s]]={}),i[a[s]]),angular.isArray(i)&&void 0!==n)if(n.scope&&"function"==typeof n.scope)i=i[n.scope().$index];else{if("number"!=typeof n)throw new Error("Unsupported element type in walkTree "+t);i=i[n]}if(!i)break}return{lastObject:i,key:i?a[o]:void 0}}function y(e,t,n,r){var a=f(e,t,n,!!r);if(a.lastObject&&a.key)if(r)if(angular.isArray(a.lastObject))for(var o=0;o<a.lastObject.length;o++)a.lastObject[o][a.key]=r[o];else a.lastObject[a.key]=r;else delete a.lastObject[a.key]}function m(t,n,e,r){if(void 0===r&&(r=!1),!n.topLevelFormName||n[n.topLevelFormName]&&(r||n[n.topLevelFormName].$pristine)){x(t.name,e.master,function(e){return"object"==typeof e&&e.id?e:S(t,e,n[b(t,"Options")],n[b(t,"_ids")])});var a=w(e.master,t.name);a&&y(n.record,t.name,void 0,a)}}var w=function(e,t,n){var r,a=f(e,t,n);return a.lastObject&&a.key&&(r=angular.isArray(a.lastObject)?_.map(a.lastObject,function(e){return e[a.key]}):a.lastObject[a.key]),r};function k(e,t,n,r){void 0===n&&(n=null);var a=w(e,t)||"";if(a&&n){var o=_.find(n,function(e){return e.name===t});if(o)switch(o.params){case void 0:break;case"timestamp":var i=a.toString().substring(0,8),s=new Date(1e3*parseInt(i,16));a=s.toLocaleDateString()+" "+s.toLocaleTimeString();break;default:a=r.dataEventFunctions[o.params](e)}}return a}function x(e,t,n){var r,a,o=(r=e.split("."),a=[r[0]],1<r.length&&a.push(r.slice(1).join(".")),a);if(1<o.length)!function(e,t,n){if(void 0!==t)if(angular.isArray(t))for(var r=0;r<t.length;r++)x(e,t[r],n);else x(e,t,n)}(o[1],t[o[0]],n);else if(t[o[0]]){var i=t[o[0]];if(angular.isArray(i))for(var s=i.length-1;0<=s;s--){var l=typeof i[s];("undefined"==l||"object"==l&&0===Object.keys(i[s]).length)&&i.splice(s,1)}t[o[0]]=n(i)}}function v(e,t,n,r,a){var o="string"==typeof t?e[t]:t,i="string"==typeof n?e[n]:n;o.length=0,i.length=0,r&&0<r.length&&r.forEach(function(e){var t=e[a];t&&0<t.length&&(o.push(t),e._id||(e._id=c()),i.push(e._id))})}var $=function(e){var t=!1;return e.needsX?t=!0:e.directive||("text"===e.type?t=!0:"select"!==e.type||e.ids||(t=!0)),t};function C(e,t,n){var r=e.conversions;return n&&(r=w(r,n)||{}),r[t]}var g=function(e,t,n,r,a,o,i){o=o||t;for(var s=0;s<e.length;s++){var l=e[s],c=l.name.slice(n);c.length||(c=l.name.split(".").pop());var d=w(t,c);if("date"===l.intType&&"string"==typeof d&&y(t,c,null,new Date(d)),l.schema){if(d)for(var u=0;u<d.length;u++)d[u]=g(l.schema,d[u],1+c.length,r,c,o,u)}else{l.internalRef&&v(r,l.options,l.ids,o[l.internalRef.property],l.internalRef.value);var f=k(t,c,null,r);if(l.array&&$(l)&&f&&!(0<f.length&&f[0].x))for(var p=0;p<f.length;p++)f[p]={x:f[p]};var m=r[b(l,"_ids")],h=void 0;if(d&&m&&0<m.length){if(-1!==c.indexOf("."))throw new Error("Trying to directly assign to a nested field 332");!d.toString().match(/^[a-f0-9]{24}$/)||l.internalRef&&l.internalRef.noConvert||(t[c]=S(l,d,r[b(l,"Options")],m))}else l.select2?(console.log("fng-select2 is deprecated - use fng-ui-select instead"),l.select2):d&&(h=C(r,c,a))&&h.fngajax&&!h.noconvert&&h.fngajax(d,l,function(e,t){y(o,e.name,i,t),F(angular.element("#"+e.id),function(){y(r.record,e.name,i,t)})})}}return t};function S(e,t,n,r){if(e.array){for(var a=[],o=!e.directive||$(e),i=0;i<t.length;i++){var s=t[i];s&&s.x&&(s=s.x);var l=N(s,r,n,e.name);o&&(l={x:l}),a.push(l)}return a}return e.select2?{id:t,text:N(t,r,n,e.name)}:N(t,r,n,e.name)}function D(e,t,n,r){var a=_.isObject(e)?e.x||e.text:e;if(a&&a.match(/^[0-9a-f]{24}$/))return a;var o=t.indexOf(a);if(-1===o)throw new Error("convertListValueToId: Invalid data - value "+a+" not found in "+t+" processing "+r);return n[o]}function h(e,t,n){n.master=g(t.formSchema,e,0,t),t.phase="ready",t.cancel()}var F=function(e,t){var n=e.inheritedData("$ngModelController"),r=n&&n.$pristine;r&&(n.$pristine=!1),t(),r&&(n.$pristine=!0)},N=function(e,t,n,r){"object"==typeof e&&(e=e.id);var a=t.indexOf(e);if(-1===a&&-1===(a=n.indexOf(e)))throw new Error("convertIdToListValue: Invalid data - id "+e+" not found in "+t+" processing "+r);return n[a]};function E(t,n,r,e,a){if(a&&0<a.length&&a.length===e.length&&n[r]){var o=a.findIndex(function(e){return e[t.value]===n[r]});if(-1<o){var i=e[o][t.value];i&&(n[r]=i)}}}function L(e,u,n,t,f){var r=!u.id&&!u.newRecord;function a(o,d){u.internalLookups.forEach(function(n){var r=o[n.ref.property],a=d[n.ref.property];v(u,n.lookupOptions,n.lookupIds,r,n.ref.value),(r&&0<r.length||a&&0<a.length)&&n.handlers.forEach(function(t){if(t.possibleArray){var e=w(u.record,t.possibleArray,null);e&&0<e.length&&e.forEach(function(e){return E(n.ref,e,t.lastPart,r,a)})}else angular.isArray(u.record[t.lastPart])?u.record[t.lastPart].forEach(function(e){E(n.ref,e,"x",r,a)}):E(n.ref,u.record,t.lastPart,r,a)})}),u.listLookups.forEach(function(l){function e(e,t){var n=e[t];return n&&n.id&&(n=n.id),n}function c(e){y(u.record,e.name)}var t=l.ref.id.slice(1);if(t.includes("."))throw new Error("No support for nested list lookups yet - "+JSON.stringify(l.ref));var n=e(o,t);n!==e(d,t)&&(l.handlers.forEach(function(e){u[e.formInstructions.options].length=0,u[e.formInstructions.ids].length=0}),n?p.readRecord(l.ref.collection,n).then(function(s){l.handlers.forEach(function(e){for(var t=u[e.formInstructions.options],n=u[e.formInstructions.ids],r=s.data[l.ref.property]||[],a=0;a<r.length;a++){var o=r[a][l.ref.value],i=_.sortedIndex(t,o);t[i]===o&&(o=o+" ("+r[a]._id+")",i=_.sortedIndex(t,o)),t.splice(i,0,o),n.splice(i,0,r[a]._id)}0===Object.keys(d).length?m(e.formInstructions,u,f,!0):c(e.formInstructions)})}):l.handlers.forEach(function(e){c(e.formInstructions)}))})}function o(){u.phase="ready",u.cancel(),a(u.record,{})}if(n.handleSchema("Main "+u.modelName,e,r?null:u.formSchema,u.listSchema,"",!0,u,f),r)f.allowLocationChange=!0;else{var i=!0;if(u.newRecord||(u.dropConversionWatcher=u.$watchCollection("conversions",function(e,t){e!==t&&u.originalData&&h(u.originalData,u,f)})),u.$watch("record",function(e,t){e!==t&&(0<Object.keys(t).length&&u.dropConversionWatcher&&(u.dropConversionWatcher(),u.dropConversionWatcher=null),i=n.updateDataDependentDisplay(e,t,i,u),a(e,t))},!0),u.id)"function"==typeof u.dataEventFunctions.onBeforeRead?u.dataEventFunctions.onBeforeRead(u.id,function(e){e?u.showError(e):t.readRecord(u,f)}):t.readRecord(u,f);else{f.allowLocationChange=!1,f.master=u.setDefaults(u.formSchema);var s=u.initialiseNewRecord||l.$$search.r;if(s)try{Object.assign(f.master,JSON.parse(s)),u.newRecordsStartPristine||u.$on("fngCancel",function(){d(function(){u[u.topLevelFormName]&&u[u.topLevelFormName].$setDirty()},1e3)})}catch(e){console.log("Error parsing specified record : "+e.message)}"function"==typeof u.dataEventFunctions.onInitialiseNewRecord&&(console.log("onInitialiseNewRecord is deprecated - use the async version - onNewRecordInit(data,cb)"),u.dataEventFunctions.onInitialiseNewRecord(f.master)),"function"==typeof u.dataEventFunctions.onNewRecordInit?u.dataEventFunctions.onNewRecordInit(f.master,function(e){e?u.showError(e):o()}):o()}}}function t(r){return function(e){if(-1!==[200,400].indexOf(e.status)){var t="";for(var n in e.data.errors)if(e.data.errors.hasOwnProperty(n)){switch(t+="<li><b>"+a("titleCase")(n)+": </b> ",e.data.errors[n].type){case"enum":t+="You need to select from the list of values";break;default:t+=e.data.errors[n].message}t+="</li>"}t=0<t.length?e.data.message+"<br /><ul>"+t+"</ul>":e.data.message||e.data.err||"Error! Sorry - No further details available.",r.showError(t)}else r.showError(e.status+" "+JSON.stringify(e.data))}}function A(e,t,n){n.allowLocationChange=!1,t.phase="reading","function"==typeof t.dataEventFunctions.onAfterRead&&t.dataEventFunctions.onAfterRead(e),t.originalData=e,h(e,t,n)}function r(e,t,n,r){var a=t.name.split("."),o=r.find(function(e){return e.ref.property===n.property&&e.ref.value===n.value}),i={formInstructions:t,lastPart:a.pop(),possibleArray:a.join(".")};o||(o={ref:n,lookupOptions:[],lookupIds:[],handlers:[]},r.push(o)),o.handlers.push(i),e[t.options]=o.lookupOptions,e[t.ids]=o.lookupIds}return{readRecord:function(t,n){t.readingRecord=p.readRecord(t.modelName,t.id),t.readingRecord.then(function(e){A(angular.copy(e.data),t,n)},function(e){404===e.status?l.path("/404"):t.handleHttpError(e)})},scrollTheList:function(n){var r=n.pagesLoaded;p.getPagedAndFilteredList(n.modelName,{aggregate:l.$$search.a,find:l.$$search.f,limit:n.pageSize,skip:r*n.pageSize,order:l.$$search.o}).then(function(e){var t=e.data;angular.isArray(t)?r===n.pagesLoaded?(n.pagesLoaded++,n.recordList=n.recordList.concat(t)):console.log("DEBUG: infinite scroll component asked for a page twice - the model was "+n.modelName):n.showError(t,"Invalid query")},n.handleHttpError)},deleteRecord:function(e,t,n){p.deleteRecord(t.modelName,e).then(function(){"function"==typeof t.dataEventFunctions.onAfterDelete&&t.dataEventFunctions.onAfterDelete(n.master),i.redirectTo()("onDelete",t,l)},function(e){404===e.status?i.redirectTo()("onDelete",t,l):t.showError(e.statusText+" ("+e.status+") while deleting record<br />"+e.data,"Error deleting record")})},updateDocument:function(e,n,r,a){r.phase="updating",p.updateRecord(r.modelName,r.id,e).then(function(e){var t=e.data;!1!==t.success?("function"==typeof r.dataEventFunctions.onAfterUpdate&&r.dataEventFunctions.onAfterUpdate(t,a.master),n.redirect?(n.allowChange&&(a.allowLocationChange=!0),o.location=n.redirect):(A(t,r,a),r.setPristine(!1))):r.showError(t)},r.handleHttpError)},createNew:function(e,n,r,a){p.createRecord(r.modelName,e).then(function(e){var t=e.data;!1!==t.success?(a.allowLocationChange=!0,"function"==typeof r.dataEventFunctions.onAfterCreate&&r.dataEventFunctions.onAfterCreate(t),n.redirect?o.location=n.redirect:i.redirectTo()("edit",r,l,t._id)):r.showError(t)},r.handleHttpError)},getListData:k,suffixCleanId:b,setData:y,setUpLookupOptions:function(n,l,c,d,r){var u=c[l.options]=[],f=c[l.ids]=[];e.getSchema(n).then(function(e){var t=e.data,s=[];r("Lookup "+n,t,null,s,"",!1,c,d),(void 0!==l.filter&&l.filter?p.getPagedAndFilteredList(n,l.filter):p.getAll(n)).then(function(e){var t=angular.copy(e.data);if(t){for(var n=0;n<t.length;n++){for(var r="",a=0;a<s.length;a++){var o=t[n][s[a].name];r+=o?o+" ":""}r=r.trim();var i=_.sortedIndex(u,r);u[i]===r&&(r=r+" ("+t[n]._id+")",i=_.sortedIndex(u,r)),u.splice(i,0,r),f.splice(i,0,t[n]._id)}c.readingRecord&&c.readingRecord.then(function(){m(l,c,d)})}})})},setUpLookupListOptions:function(o,i,s,l){var c=s[i.options]=[],d=s[i.ids]=[];"$"===o.id[0]?r(s,i,o,s.listLookups):p.readRecord(o.collection,s.$eval(o.id)).then(function(e){for(var t=e.data[o.property],n=0;n<t.length;n++){var r=t[n][o.value],a=_.sortedIndex(c,r);c[a]===r&&(r=r+" ("+t[n]._id+")",a=_.sortedIndex(c,r)),c.splice(a,0,r),d.splice(a,0,t[n]._id)}m(i,s,l)})},handleInternalLookup:function(e,t,n){r(e,t,n,e.internalLookups)},preservePristine:F,convertToMongoModel:function d(u,f,p,m,h){function v(e,t){var n;return t&&t.fngajax?e&&(n=e.id||e):e&&(n=e.text||(e.x?e.x.text:e)),n}function e(){var t=u[g],e=t.name.slice(p),n=k(f,e,null,m);if(t.schema){if(n)for(var r=0;r<n.length;r++)n[r]=d(t.schema,n[r],1+e.length,m,e)}else{if(t.array&&$(t)&&n)for(var a=0;a<n.length;a++)n[a]=n[a].x;var o=m[b(t,"_ids")];if(o&&0<o.length)x(e,f,function(e){return function(e,t,n,r){if(e.array){for(var a=[],o=0;o<t.length;o++)a.push(D(t[o],n,r,e.name));return a}return D(t,n,r,e.name)}(t,e,m[b(t,"Options")],o)});else{var i=C(m,e,h);if(i){var s=w(f,e,null),l=void 0;if(t.array){if(l=[],s)for(var c=0;c<s.length;c++)l[c]=v(s[c],i)}else l=v(s,i);y(f,e,null,l)}}}}for(var g=0;g<u.length;g++)e();return f},convertIdToListValue:N,handleError:t,decorateScope:function(c,n,r,a){c.handleHttpError=t(c),c.cancel=function(){angular.copy(a.master,c.record),c.$broadcast("fngCancel",c),d(c.setPristine)},c.$on("showErrorMessage",function(e,t){e.defaultPrevented||(e.defaultPrevented=!0,c.showError(t.body,t.title))}),c.showError=function(t,e){if(c.alertTitle=e||"Error!","string"==typeof t)c.errorMessage=t;else if(t)if(t.message&&"string"==typeof t.message)c.errorMessage=t.message;else if(t.data&&t.data.message)c.errorMessage=t.data.message;else try{c.errorMessage=JSON.stringify(t)}catch(e){c.errorMessage=t}else c.errorMessage="An error occurred - that's all we got. Sorry.";c.errorHideTimer=window.setTimeout(function(){c.dismissError(),c.$digest()},3500+1e3*(c.alertTitle+c.errorMessage).length/50),c.errorVisible=!0,window.setTimeout(function(){c.$digest()})},c.clearTimeout=function(){c.errorHideTimer&&(clearTimeout(c.errorHideTimer),delete c.errorHideTimer)},c.dismissError=function(){c.clearTimeout,c.errorVisible=!1,delete c.errorMessage,delete c.alertTitle},c.stickError=function(){clearTimeout(c.errorHideTimer)},c.prepareForSave=function(t){var n=r.convertToMongoModel(c.formSchema,angular.copy(c.record),0,c);c.id?"function"==typeof c.dataEventFunctions.onBeforeUpdate?c.dataEventFunctions.onBeforeUpdate(n,a.master,function(e){e?t(e):t(null,n)}):t(null,n):"function"==typeof c.dataEventFunctions.onBeforeCreate?c.dataEventFunctions.onBeforeCreate(n,function(e){e?t(e):t(null,n)}):t(null,n)},c.save=function(n){n=n||{},c.prepareForSave(function(e,t){e?"_update_handled_"!==e&&d(function(){c.showError(e)}):c.id?r.updateDocument(t,n,c,a):r.createNew(t,n,c,a)})},c.newClick=function(){i.redirectTo()("new",c,l)},c.$on("$locationChangeStart",function(e,t){a.allowLocationChange||c.isCancelDisabled()||(e.preventDefault(),n.open({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>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result.then(function(e){e?c.save({redirect:t,allowChange:!0}):(a.allowLocationChange=!0,o.location=t)}).catch(u))}),c.deleteClick=function(){if(c.record._id){var e=void 0;if(c.unconfirmedDelete)e=Promise.resolve(!0);else e=n.open({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>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result;e.then(function(e){function t(){r.deleteRecord(c.id,c,a)}e&&("function"==typeof c.dataEventFunctions.onBeforeDelete?c.dataEventFunctions.onBeforeDelete(a.master,function(e){e?"_delete_handled_"!==e&&c.showError(e):t()}):t())}).catch(u)}},c.isCancelDisabled=function(){return!(!c[c.topLevelFormName]||!c[c.topLevelFormName].$pristine)||"function"==typeof c.disableFunctions.isCancelDisabled&&c.disableFunctions.isCancelDisabled(c.record,a.master,c[c.topLevelFormName])},c.isSaveDisabled=function(){c.whyDisabled=void 0;var e=!1;if(c[c.topLevelFormName]?c[c.topLevelFormName].$invalid?(c.whyDisabled="The form data is invalid:",function n(e,r){e.$$controls.forEach(function(e){if(e.$invalid)if(e.$$controls)n(e,e.$name);else if(c.whyDisabled+="<br /><strong>",r&&(c.whyDisabled+=r+" "),"bs2"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().find("label")&&e.$$element.parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().find("label").text():"bs3"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().parent()&&e.$$element.parent().parent().parent().find("label")&&e.$$element.parent().parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().parent().find("label").text():c.whyDisabled+=e.$name,c.whyDisabled+="</strong>: ",e.$error)for(var t in e.$error)if(e.$error.hasOwnProperty(t))switch(t){case"required":c.whyDisabled+="Field missing required value. ";break;case"pattern":c.whyDisabled+="Field does not match required pattern. ";break;default:c.whyDisabled+=t+". "}})}(c[c.topLevelFormName])):c[c.topLevelFormName].$pristine&&(e=!0):c.whyDisabled="Top level form name invalid",e||c.whyDisabled)return!0;if("function"!=typeof c.disableFunctions.isSaveDisabled)return!1;var t=c.disableFunctions.isSaveDisabled(c.record,a.master,c[c.topLevelFormName]);return c.whyDisabled="string"==typeof t?t:"An application level user-specified function is inhibiting saving the record",!!t},c.isDeleteDisabled=function(){return!c.id||"function"==typeof c.disableFunctions.isDeleteDisabled&&c.disableFunctions.isDeleteDisabled(c.record,a.master,c[c.topLevelFormName])},c.isNewDisabled=function(){return"function"==typeof c.disableFunctions.isNewDisabled&&c.disableFunctions.isNewDisabled(c.record,a.master,c[c.topLevelFormName])},c.setDefaults=function(e,t){void 0===t&&(t="");var n={};return e.forEach(function(e){void 0!==e.defaultValue&&(n[e.name.replace(t,"")]=e.defaultValue)}),n},c.getVal=function(e,t){if(-1===e.indexOf("$index")||void 0!==t)return e=e.replace(/\$index/g,t),c.$eval("record."+e)},c.sortableOptions={update:function(){c.topLevelFormName&&c[c.topLevelFormName].$setDirty()}},c.setUpCustomLookupOptions=function(e,t,n,r){for(var a=0,o=[c,r];a<o.length;a++){var i=o[a];i&&(i[e.ids]=t,i[e.options]=n)}var s=w(c.record,e.name);if(s){if(angular.isArray(s))for(var l=0;l<s.length;l++)s[l]=N(s[l],t,n,e.name);else s=N(s,t,n,e.name);y(c.record,e.name,void 0,s)}}},fillFormFromBackendCustomSchema:L,fillFormWithBackendSchema:function(t,n,r,a){e.getSchema(t.modelName,t.formName).then(function(e){L(e.data,t,n,r,a)},t.handleHttpError)}}}t=e.services||(e.services={}),n.$inject=["$location","$window","$filter","$timeout","routingService","cssFrameworkService","SubmissionsService","SchemasService"],t.recordHandler=n}(fng=fng||{}),function(e){var t;function n(n){return{getSchema:function(e,t){return n.get("/api/schema/"+e+(t?"/"+t:""),{cache:!0})}}}t=e.services||(e.services={}),n.$inject=["$http"],t.SchemasService=n}(fng=fng||{}),function(e){var t;function n(r,a){function n(e){function t(e,t){void 0!==t&&""!==t&&("object"==typeof t&&(t=JSON.stringify(t)),""===n?n="?":n+="&",n+=e+"="+t)}var n="";return t("l",e.limit),t("f",e.find),t("a",e.aggregate),t("o",e.order),t("s",e.skip),n}var o=!0;return{getListAttributes:function(e,t){return r.get("/api/"+e+"/"+t+"/list")},readRecord:function(e,t){return r.get("/api/"+e+"/"+t)},getAll:function(e,t){var n=angular.extend({cache:o},t);return r.get("/api/"+e,n)},getPagedAndFilteredList:function(e,t){return r.get("/api/"+e+n(t))},deleteRecord:function(e,t){return r.delete("/api/"+e+"/"+t)},updateRecord:function(e,t,n){return a.get("$http").remove("/api/"+e),r.post("/api/"+e+"/"+t,n)},createRecord:function(e,t){return a.get("$http").remove("/api/"+e),r.post("/api/"+e,t)},useCache:function(e){o=e},getCache:function(){return!!a.get("$http")},clearCache:function(){a.get("$http").removeAll()}}}t=e.services||(e.services={}),n.$inject=["$http","$cacheFactory"],t.SubmissionsService=n}(fng=fng||{}),function(f){var e;function t(t,n,e,r,a,o,i,s,l){t.sharedData={record:{},disableFunctions:{},dataEventFunctions:{},modelControllers:[]};var c={master:{},fngInvalidRequired:"fng-invalid-required",allowLocationChange:!0};t.errorVisible=!1,angular.extend(t,i.parsePathFunc()(e.$$path));var d=r("titleCase")(t.modelName,!0);function u(){l.fillFormWithBackendSchema(t,s,l,c);for(var e=0;e<t.sharedData.modelControllers.length;e++)t.sharedData.modelControllers[e].onBaseCtrlReady&&t.sharedData.modelControllers[e].onBaseCtrlReady(t);t.$on("$destroy",function(){t.sharedData.modelControllers.forEach(function(e){return e.$destroy()}),n.$broadcast("fngControllersUnloaded")})}o.loadControllerAndMenu(t.sharedData,d,0,!1,t.$new()),t.formName&&o.loadControllerAndMenu(t.sharedData,d+r("titleCase")(t.formName,!0),1,!1,t.$new()),n.$broadcast("fngControllersLoaded",t.sharedData,t.modelName),t.modelNameDisplay=t.sharedData.modelNameDisplay||r("titleCase")(t.modelName),n.$broadcast("fngFormLoadStart",t),s.decorateScope(t,s,l,t.sharedData),l.decorateScope(t,a,l,c),"function"==typeof f.formsAngular.beforeProcess?f.formsAngular.beforeProcess(t,function(e){e?t.showError(e.message,"Error preparing to process form"):u()}):u()}e=f.controllers||(f.controllers={}),t.$inject=["$scope","$rootScope","$location","$filter","$uibModal","fngModelCtrlService","routingService","formGenerator","recordHandler"],e.BaseCtrl=t}(fng=fng||{}),function(e){var t;function n(e,t){e.yes=function(){t.close(!0)},e.no=function(){t.close(!1)},e.cancel=function(){t.dismiss("cancel")}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$uibModalInstance"],t.SaveChangesModalCtrl=n}(fng=fng||{}),function(e){var t;function n(t,e,n,r){t.models=[],e.get("/api/models").then(function(e){t.models=e.data},function(){n.path("/404")}),t.newUrl=function(e){return r.buildUrl(e+"/new")},t.listUrl=function(e){return r.buildUrl(e)}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.ModelCtrl=n}(fng=fng||{}),function(e){var t;function n(e,i,t,r,n,a){function o(){i.items=[],i.contextMenu=void 0}e.navScope=i,o(),i.toggleCollapsed=function(){i.collapsed=!i.collapsed},i.isCollapsed=!0,i.showShortcuts=!1,i.shortcuts=[{key:"?",act:"Show shortcuts"},{key:"/",act:"Jump to search"},{key:"Ctrl+Shift+S",act:"Save the current record"},{key:"Ctrl+Shift+Esc",act:"Cancel changes on the current record"},{key:"Ctrl+Shift+Ins",act:"Create a new record"},{key:"Ctrl+Shift+X",act:"Delete the current record"}],i.markupShortcut=function(e){return'<span class="key">'+e.split("+").join('</span> + <span class="key">')+"</span>"},i.globalShortcuts=function(n){function e(e){var t=document.getElementById(e);t&&(t.disabled||setTimeout(function(){t.click()}),n.preventDefault())}if(191===n.keyCode&&(!("INPUT"==(a=(r=n).target.tagName)||"SELECT"==a||"TEXTAREA"==a||"DIV"==a&&r.target.classList.contains("ck-editor__editable"))||n.ctrlKey&&!n.altKey&&!n.metaKey))if(n.ctrlKey||!n.shiftKey){var t=document.getElementById("searchinput");t&&(t.focus(),n.preventDefault())}else i.showShortcuts=!0;else 83===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("saveButton"):27===n.keyCode&&(n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey||i.showShortcuts)?n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("cancelButton"):i.showShortcuts=!1:45===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("newButton"):88===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey&&e("deleteButton");var r,a},i.css=function(e,t){return"function"==typeof a[e]?a[e](t):"error text-error"},i.$on("fngControllersLoaded",function(e,t,n){i.contextMenu=t.dropDownDisplay||t.modelNameDisplay||r("titleCase")(n,!1),t.dropDownDisplayPromise&&t.dropDownDisplayPromise.then(function(e){i.contextMenu=e})}),i.$on("fngControllersUnloaded",function(e){o()}),i.doClick=function(e,t){var n=angular.element(t.target),r=i.items[e];if(r.divider||n.parent().hasClass("disabled"))t.preventDefault();else if(r.broadcast)i.$broadcast(r.broadcast);else{var a=r.args||[],o=r.fn;if("function"==typeof o)switch(a.length){case 0:o();break;case 1:o(a[0]);break;case 2:o(a[0],a[1]);break;case 3:o(a[0],a[1],a[2]);break;case 4:o(a[0],a[1],a[2],a[3])}else if(o)throw new Error("Incorrect menu setup")}},i.isHidden=function(e){function t(e){return!!e.isHidden&&e.isHidden()}var n=!1;if(i.items[e].divider)if(0===e)n=!0;else for(var r=!1,a=e-1;0<=a&&!n&&!r;)i.items[a].divider?n=!0:t(i.items[a])?--a:r=!0;return n||t(i.items[e])},i.isDisabled=function(e){return!!i.items[e].isDisabled&&i.items[e].isDisabled()},i.buildUrl=function(e){return n.buildUrl(e)},i.dropdownClass=function(e){var t="";return i.items[e].divider?t="divider":i.isDisabled(e)&&(t="disabled"),t}}t=e.controllers||(e.controllers={}),n.$inject=["$rootScope","$scope","$location","$filter","routingService","cssFrameworkService"],t.NavCtrl=n}(fng=fng||{}),function(e){e.formsAngular=angular.module("formsAngular",["ngSanitize","ngMessages","ui.bootstrap","infinite-scroll","monospaced.elastic"]).controller("BaseCtrl",e.controllers.BaseCtrl).controller("SaveChangesModalCtrl",e.controllers.SaveChangesModalCtrl).controller("LinkCtrl",e.controllers.LinkCtrl).controller("ModelCtrl",e.controllers.ModelCtrl).controller("NavCtrl",e.controllers.NavCtrl).directive("modelControllerDropdown",e.directives.modelControllerDropdown).directive("errorDisplay",e.directives.errorDisplay).directive("fngLink",e.directives.fngLink).directive("formInput",e.directives.formInput).directive("formButtons",e.directives.formButtons).directive("globalSearch",e.directives.globalSearch).directive("fngNakedDate",e.directives.fngNakedDate).filter("camelCase",e.filters.camelCase).filter("titleCase",e.filters.titleCase).filter("extractTimestampFromMongoID",e.filters.extractTimestampFromMongoID).service("addAllService",e.services.addAllService).provider("cssFrameworkService",e.services.cssFrameworkService).provider("routingService",e.services.routingService).factory("fngModelCtrlService",e.services.fngModelCtrlService).factory("formGenerator",e.services.formGenerator).factory("formMarkupHelper",e.services.formMarkupHelper).factory("inputSizeHelper",e.services.inputSizeHelper).factory("pluginHelper",e.services.pluginHelper).factory("recordHandler",e.services.recordHandler).factory("SchemasService",e.services.SchemasService).factory("SubmissionsService",e.services.SubmissionsService)}(fng=fng||{});var formsAngular=fng.formsAngular;angular.module("formsAngular").run(["$templateCache",function(e){e.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'),e.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\x3c!-- <pre>--\x3e\n \x3c!--Record--\x3e\n \x3c!--{{ record | json }}--\x3e\n \x3c!--formSchema--\x3e\n \x3c!--{{ formSchema | json }}--\x3e\n\x3c!-- </pre>--\x3e\n</div>\n'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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')}]);
1
+ var fng;!function(e){(e.directives||(e.directives={})).modelControllerDropdown=function(){return{restrict:"AE",replace:!0,template:'<li ng-show="items.length > 0" class="mcdd" uib-dropdown> <a href="#" uib-dropdown-toggle> {{contextMenu}} <b class="caret"></b> </a> <ul class="uib-dropdown-menu dropdown-menu"> <li ng-repeat="choice in items" ng-hide="isHidden($index)" ng-class="dropdownClass($index)"> <a ng-show="choice.text" class="dropdown-option" ng-href="{{choice.url || choice.urlFunc()}}" ng-click="doClick($index, $event)"> {{choice.text}} </a> </li> </ul></li>'}}}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"E",templateUrl:"error-display-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.errorDisplay=n}(fng=fng||{}),function(e){var t;function n(a){a.checkNotModal=function(){for(var e,t=a.element[0],n=!1,r={preventDefault:angular.noop,stopPropagation:angular.noop,target:1,currentTarget:1};(e=t.parentNode)?"function"==typeof e.getAttribute&&e.getAttribute("uib-modal-window")?(angular.element(t).scope().close(r),n=!0):t=e:n=!0,!n;);}}t=e.controllers||(e.controllers={}),n.$inject=["$scope"],t.LinkCtrl=n}(fng=fng||{}),function(e){var t;function n(p,m){return{restrict:"E",scope:{dataSrc:"&model"},link:function(n,e,r){var a=r.ref,t=r.text&&unescape(r.text)!==r.text,o=r.form,i=r.linktab;if(n.readonly=r.readonly,n.element=e,o=o?o+"/":"",i=i?"/"+i:"",t){for(var s=n,l="";"function"!=typeof s.baseSchema&&s.$parent;){if(void 0!==s.$index)throw new Error("No support for $index at this level - "+l);s=s.$parent,l+="$parent."}var c,d=r.fld;if(n.$parent.subDoc&&n.$parent.subDoc[d])c=l+"subDoc."+d;else{if(void 0!==s.$index){var u=d.split(".");d=u.pop(),d=u.join(".")+"["+s.$index+"]."+d}else d="."+d;c=l+"record"+d}n.$watch(c,function(e){if(e){if(/^[a-f0-9]{24}/.test(e.toString()))e=e.slice(0,24);else if(e.id&&/^[a-f0-9]{24}/.test(e.id))e=e.id.slice(0,24);else if(n.$parent["f_"+r.fld+"Options"]){var t=n.$parent["f_"+r.fld+"Options"].indexOf(e);e=-1<t?n.$parent["f_"+r.fld+"_ids"][t]:void 0}else e=void 0;n.link=e?p.buildUrl(a+"/"+o+(e.id||e)+"/edit"+i):void 0}else n.link=void 0},!0)}else{r.text&&0<r.text.length&&(n.text=r.text);var f=n.$parent.$index;n.$watch("dataSrc()",function(e){e&&(void 0!==f&&angular.isArray(e)&&(e=e[f]),n.link=p.buildUrl(a+"/"+o+e+"/edit"+i),n.text||m.getListAttributes(a,e).then(function(e){var t=e.data;!1===t.success?n.text=t.err:n.text=t.list},function(e){n.text="Error "+e.status+": "+e.data}))},!0)}},controller:"LinkCtrl",template:function(e,t){function n(e){return'<a ng-click="checkNotModal()" ng-href="{{ link || \'#\' }}" class="fng-link">'+e+"</a>"}return t.readonly?'<span class="fng-link">{{text}}</span>':t.text&&unescape(t.text)!==t.text?n(unescape(t.text)):n("{{text}}")}}}t=e.directives||(e.directives={}),n.$inject=["routingService","SubmissionsService"],t.fngLink=n}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"A",templateUrl:"form-button-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.formButtons=n}(fng=fng||{}),function(e){var t,I,n;function r(c,d,E,L,A,u,O){return{restrict:"EA",link:function(k,x,s){function b(t,e,n,r,a){function o(){var e;if(angular.isArray(k[t.options]))e={repeat:t.options,value:"option"};else{if(!k[t.options]||!angular.isArray(k[t.options].values))throw new Error("Invalid enumeration setup in field "+t.name);e=angular.isArray(k[t.options].labels)?{repeat:t.options+".values",value:t.options+".values[$index]",label:t.options+".labels[$index]"}:{repeat:t.options+".values",value:t.options+".values[$index]"}}return e}var i;if(!e){var s=(a.model||"record")+".";if(e=s,a.subschema&&-1!==t.name.indexOf(".")){var l=t.name,c=a.subschemaroot,d=l.slice(c.length+1);a.index?r="f_"+(e+=c+"["+a.index+"]."+d).slice(s.length).replace(/(\.|\[|]\.)/g,"-"):(e+=c,a.subkey?(r=e.slice(s.length).replace(/\./g,"-")+"-subkey"+a.subkeyno+"-"+d,e+="[$_arrayOffset_"+c.replace(/\./g,"_")+"_"+a.subkeyno+"]."+d):(e+="[$index]."+d,r=null,i=l.replace(/\./g,"-")))}else e+=t.name}var u,f,p=O.allInputsVars(k,t,a,e,r,i),m=p.common,h=(n=n||t.required)?" required ":"";function v(e){var t="";return e&&(t="boolean"==typeof e?" disabled ":' ng-disabled="'+e+'" '),t}switch(t.type){case"select":t.select2?u='<input placeholder="fng-select2 has been removed" readonly>':(m+=v(t.readonly),m+=t.add?" "+t.add+" ":"",m+=' aria-label="'+(t.label&&""!==t.label?t.label:t.name)+'" ',u="<select "+m+'class="'+p.formControl.trim()+p.compactClass+p.sizeClassBS2+'" '+h+">",n||(u+="<option></option>"),angular.isArray(t.options)?angular.forEach(t.options,function(e){_.isObject(e)?u+='<option value="'+(e.val||e.id)+'">'+(e.label||e.text)+"</option>":u+="<option>"+e+"</option>"}):(f=o(),u+='<option ng-repeat="option in '+f.repeat+'"',f.label?u+=' value="{{'+f.value+'}}"> {{ '+f.label+" }} </option> ":u+=">{{"+f.value+"}}</option> "),u+="</select>");break;case"link":u='<fng-link model="'+e+'" ref="'+t.ref+'"',t.form&&(u+=' form="'+t.form+'"'),t.linktab&&(u+=' linktab="'+t.linktab+'"'),t.linktext&&(u+=' text="'+t.linktext+'"'),t.readonly&&("boolean"==typeof t.readonly?u+=' readonly="true"':u+=' ng-readonly="'+t.readonly+'"'),u+="></fng-link>";break;case"radio":u="",m+=h,m+=v(t.readonly),m+=t.add?" "+t.add+" ":"";var g="vertical"===a.formstyle||"inline"!==a.formstyle&&!t.inlineRadio;if(angular.isArray(t.options)){var b;a.subschema&&(m=(m=m.replace('name="','name="{{$index}}-')).replace('id="','id="{{$index}}-')),angular.forEach(t.options,function(e,t){b=m.replace('id="','id="'+t+"-"),u+="<input "+b+' type="radio" aria-label="'+e+'" value="'+e+'">'+e,g&&(u+="<br />")})}else{var y=g?"div":"span";a.subschema&&(m=m.replace("$index","$parent.$index").replace('name="','name="{{$parent.$index}}-').replace('id="','id="{{$parent.$index}}-')),f=o(),u+="<"+y+' ng-repeat="option in '+f.repeat+'">',u+="<input "+m.replace('id="','id="{{$index}}-')+' type="radio" aria-label="'+f.value+'" value="{{ '+f.value+' }}"> {{ '+(f.label||f.value)+" }} </"+y+"> "}break;case"checkbox":m+=h,m+=v(t.readonly),m+=t.add?" "+t.add+" ":"",u=O.generateSimpleInput(m,t,a),"bs3"===A.framework()&&(u='<div class="checkbox">'+u+"</div>");break;default:m+=O.addTextInputMarkup(p,t,h),u="textarea"===t.type?(t.rows&&("auto"===t.rows?m+='msd-elastic="\n" class="ng-animate" ':m+='rows = "'+t.rows+'" '),"ckEditor"===t.editor&&(console.log('Deprecation Warning: "editor" property deprecated - use "add"'),m+='ckeditor = "" ',"bs3"===A.framework()&&(p.sizeClassBS3="col-xs-12")),"<textarea "+m+"></textarea>"):O.generateSimpleInput(m,t,a)}return O.inputChrome(u,t,a,p)}function w(e){var t;switch(e){case"horizontal":t="form-horizontal";break;case"vertical":t="";break;case"inline":t="form-inline";break;case"stacked":t="form-stacked";break;case"horizontalCompact":default:t="form-horizontal compact"}return t}function $(e){var t={before:"",after:""};if("function"==typeof e.containerType)t=e.containerType(e);else switch(e.containerType){case"tab":for(var n=-1,r=0;r<k.tabs.length;r++)if(k.tabs[r].title===e.title){n=r;break}0<=n?(t.before='<uib-tab deselect="tabDeselect($event, $selectedIndex)" select="updateQueryForTab(\''+e.title+'\')" heading="'+e.title+'"',0<n&&(t.before+='active="tabs['+n+'].active"'),t.before+=">",t.after="</uib-tab>"):(t.before="<p>Error! Tab "+e.title+" not found in tab list</p>",t.after="");break;case"tabset":t.before="<uib-tabset>",t.after="</uib-tabset>";break;case"well":t.before='<div class="well">',e.title&&(t.before+="<h4>"+e.title+"</h4>"),t.after="</div>";break;case"well-large":t.before='<div class="well well-lg well-large">',t.after="</div>";break;case"well-small":t.before='<div class="well well-sm well-small">',t.after="</div>";break;case"fieldset":t.before="<fieldset>",e.title&&(t.before+="<legend>"+e.title+"</legend>"),t.after="</fieldset>";break;case void 0:case null:case"":break;default:if(t.before='<div class="'+e.containerType+'">',e.title){var a=e.titleTagOrClass||"h4";a.match(/h[1-6]/)?t.before+="<"+a+">"+e.title+"</"+a+">":t.before+='<p class="'+a+'">'+e.title+"</p>"}t.after="</div>"}return t}function C(e,t){var n=O.fieldChrome(k,e,t),r=n.template;if(e.schema){var a=e.name.replace(/\./g,"_"),o="$_schema_"+a;if(k[o]=e.schema,e.schema)if(e.subkey){e.subkey.path=e.name,k[o+"_subkey"]=e.subkey;for(var i=angular.isArray(e.subkey)?e.subkey:[e.subkey],s=0;s<i.length;s++){var l=$(i[s]);r+=l.before,r+=N(e.schema,null,{subschema:"true",formstyle:t.formstyle,subkey:o+"_subkey",subkeyno:s,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),r+=l.after}S.push(e)}else if(t.subschema)t.suppressNestingWarning||console.log("Attempts at supporting deep nesting have been removed - will hopefully be re-introduced at a later date");else{var c=(t.model||"record")+"."+e.name;if("string"==typeof e.customHeader)r+=e.customHeader;else{var d="";e.unshift&&(d='<button id="unshift_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini form-btn" ng-click="unshift(\''+e.name+'\',$event)"><i class="'+O.glyphClass()+'-plus"></i> Add</button>'),"bs3"===A.framework()?r+='<div class="row schema-head"><div class="col-sm-offset-3">'+e.label+d+"</div></div>":r+='<div class="schema-head">'+e.label+d+"</div>"}"inline"===e.formStyle&&e.inlineHeaders&&(r+=function(e,t,n,r){for(var a='<div class="inline-col-headers" style="display:flex" '+(r?"":'ng-hide="!'+n+" || "+n+'.length === 0"')+">",o=0,i=e;o<i.length;o++){var s=i[o];F(s,t),a+="<div ",s.showWhen=s.showWhen||s.showwhen,s.showWhen&&("string"==typeof s.showWhen?a+='ng-show="'+s.showWhen+'"':a+='ng-show="'+O.generateNgShow(s.showWhen,n)+'"'),s.id&&"function"==typeof s.id.replace&&(a+=' id="col_label_'+s.id.replace(/\./g,"-")+'"'),a+=' class="inline-col-header"><label for="'+s.id+'" class="control-label">'+s.label+"</label></div>"}return a+="</div>"}(e.schema,t,c,"always"===e.inlineHeaders)),r+='<ol class="sub-doc"'+(e.sortable?' ui-sortable="sortableOptions" ng-model="'+c+'"':"")+">",r+='<li ng-form class="'+("bs2"===A.framework()?"row-fluid ":"")+(e.inlineHeaders?"width-controlled ":"")+w(e.formStyle)+" "+(e.ngClass?"ng-class:"+e.ngClass:"")+'" name="form_'+a+'{{$index}}" class="sub-doc well" id="'+e.id+'List_{{$index}}" ng-repeat="subDoc in '+c+' track by $index">',"bs2"===A.framework()&&(r+='<div class="row-fluid sub-doc">'),!0===e.noRemove&&!e.customSubDoc||(r+=' <div class="sub-doc-btns">',"string"==typeof e.customSubDoc&&(r+=e.customSubDoc),!0!==e.noRemove&&(r+="<button "+(e.noRemove?'ng-hide="'+e.noRemove+'"':"")+' name="remove_'+e.id+'_btn" ng-click="remove(\''+e.name+"', $index, $event)\"",e.remove?r+=' class="remove-btn btn btn-mini btn-default btn-xs form-btn"><i class="'+O.glyphClass()+'-minus"></i> Remove':(r+=' style="position: relative; z-index: 20;" type="button" class="close pull-right">',"bs3"===A.framework()?r+='<span aria-hidden="true">×</span><span class="sr-only">Close</span>':r+="<span>×</span>"),r+="</button>"),r+="</div> ");var u=void 0;if(e.subDocContainerType){var f=k[e.subDocContainerType]||e.subDocContainerType,p=Object.assign({containerType:f},e.subDocContainerProps);u=$(p)}if(null!=u&&u.before&&(r+=u.before),r+=N(e.schema,!1,{subschema:"true",formstyle:e.formStyle,model:t.model,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),null!=u&&u.after&&(r+=u.after),"bs2"===A.framework()&&(r+=" </div>"),r+="</li>",r+="</ol>",!0!==e.noAdd||"string"==typeof e.customFooter||e.noneIndicator){var m="";"string"==typeof e.customFooter&&(m=e.customFooter);var h="",v=c+".length == 0";!0===e.noAdd?v='ng-show="'+v+'"':(h=e.noAdd?'ng-hide="'+e.noAdd+'"':"",v=e.noAdd?'ng-show="'+e.noAdd+" && "+v+'"':"",m+="<button "+h+' id="add_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini" ng-click="add(\''+e.name+"',$event)\">\n <i class=\"' + formMarkupHelper.glyphClass() + '-plus\"></i> \n Add\n </button>"),e.noneIndicator&&(m+="<span "+v+' class="none_indicator" id="no_'+e.id+'_indicator">None</span>',h=c+".length > 0",h=!0===e.noAdd?'ng-hide="'+h+'"':e.noAdd?'ng-hide="'+e.noAdd+" && "+h+'"':""),""!==m&&("bs3"===A.framework()?r+="<div "+h+' class="row schema-foot"><div class="col-sm-offset-3">'+m+"</div></div>":r+="<div "+h+' class = "schema-foot ">'+m+"</div>")}}}else{var g=O.controlDivClasses(t);if(e.array){if(g.push("fng-array"),"inline"===t.formstyle||"stacked"===t.formstyle)throw new Error("Cannot use arrays in an inline or stacked form");r+=O.label(k,e,"link"!==e.type,t),r+=O.handleArrayInputAndControlDiv(b(e,"link"===e.type?null:"arrayItem.x",!0,e.id+"_{{$index}}",t),g,e,t)}else r+=O.label(k,e,null,t),r+=O.handleInputAndControlDiv(b(e,null,t.required,e.id,t),g)}return r+=n.closeTag}var S=[],D=I.N,F=function(e,t){e.type=e.type||"text",e.id?"number"!=typeof e.id&&!e.id.match(/^[0-9]/)||(e.id="_"+e.id):t&&t.noid?e.id=null:e.id="f_"+e.name.replace(/\./g,"_"),e.label=void 0!==e.label?null===e.label?"":e.label:E("titleCase")(e.name.split(".").slice(-1)[0])},N=function(e,t,n){var r="";if(e)for(var a=0;a<e.length;a++){var o=e[a];n.viewform&&((o=angular.copy(o)).readonly=!0),0===a&&t&&!n.schema.match(/\$_schema_/)&&"object"!=typeof o.add&&(o.add=o.add?" "+o.add+" ":"",-1!==o.add.indexOf("ui-date")||n.noautofocus||o.containerType||(o.add=o.add+"autofocus "));var i=!0;if(o.directive){var s=o.directive,l=o.customHeader||"";l+="<"+s+' model="'+(n.model||"record")+'"';var c=x[0];F(o,n);for(var d=0;d<c.attributes.length;d++){var u=c.attributes[d];switch(u.nodeName){case"class":var f=u.value.replace("ng-scope","");0<f.length&&(l+=' class="'+f+'"');break;case"schema":var p=("bespoke_"+o.name).replace(/\./g,"_");k[p]=angular.copy(o),delete k[p].directive,l+=' schema="'+p+'"';break;default:l+=" "+u.nodeName+'="'+u.value+'"'}}l+=" ";var m=E("camelCase")(o.directive);for(var h in o)if(o.hasOwnProperty(h))switch(h){case"directive":case"schema":break;case"add":switch(typeof o.add){case"string":l+=" "+o.add;break;case"object":for(var v in o.add)o.add.hasOwnProperty(v)&&(l+=" "+v+'="'+o.add[v].toString().replace(/"/g,"&quot;")+'"');break;default:throw new Error("Invalid add property of type "+typeof o.add+" in directive "+o.name)}break;case m:for(var g in o[h])o[h].hasOwnProperty(g)&&(l+=" "+o.directive+"-"+g+'="',"string"==typeof o[h][g]?l+=o[h][g].replace(/"/g,"&quot;")+'"':l+=JSON.stringify(o[h][g]).replace(/"/g,"&quot;")+'"');break;default:o[h]&&("string"==typeof o[h]?l+=" fng-fld-"+h+'="'+o[h].replace(/"/g,"&quot;")+'"':l+=" fng-fld-"+h+'="'+JSON.stringify(o[h]).replace(/"/g,"&quot;")+'"')}for(h in n)n.hasOwnProperty(h)&&"$"!==h[0]&&void 0!==n[h]&&(l+=" fng-opt-"+h+'="'+n[h].toString().replace(/"/g,"&quot;")+'"');l+='ng-model="'+o.name+'"></'+s+">",r+=l+=o.customFooter||"",i=!1}else if(o.containerType){var b=$(o);switch(o.containerType){case"tab":if(D===I.N){D=I.Forced,r+='<uib-tabset active="activeTabNo">';var y=_.findIndex(k.tabs,function(e){return e.active});k.activeTabNo=0<=y?y:0}r+=b.before,r+=N(o.content,null,n),r+=b.after;break;case"tabset":D=I.Y,r+=b.before,r+=N(o.content,null,n),r+=b.after;break;default:r+=b.before,r+=N(o.content,null,n),r+=b.after}i=!1}else if(n.subkey){var w=angular.isArray(k[n.subkey])?k[n.subkey][0].keyList:k[n.subkey].keyList;_.find(w,function(e,t){return k[n.subkey].path+"."+t===o.name})&&(i=!1)}i&&(F(o,n),r+=C(o,n))}else console.log("Empty array passed to processInstructions"),r="";return r},l=k.$watch(s.schema,function(e){if(e){var t=angular.isArray(e)?e:[e];if(0<t.length&&"function"==typeof l){l(),l=null;var n="",r=s.model||"record",g=k[r];if(g=g||{},!s.subschema&&!s.model||s.forceform){k.topLevelFormName=s.name||"myForm";var a="";for(var o in s)s.hasOwnProperty(o)&&"$"!==o[0]&&-1===["name","formstyle","schema","subschema","model","viewform"].indexOf(o)&&(a+=" "+s.$attr[o]+'="'+s[o]+'"');n="<"+(s.forceform?"ng-form":"form")+' name="'+k.topLevelFormName+'" class="'+w(s.formstyle)+'" novalidate '+a+">"}else n="";if(g===k.topLevelFormName)throw new Error("Model and Name must be distinct - they are both "+g);n+=N(t,!0,s),D===I.Forced&&(n+="</uib-tabset>"),n+=s.subschema?"":"</form>",x.replaceWith(c(n)(k));var i=k[s.shared||"sharedData"],b=i?i.modelControllers:[];if((0<S.length||0<b.length)&&!k.phaseWatcher)var y=k.$watch("phase",function(e){if(k.phaseWatcher=!0,"ready"===e&&"function"==typeof y){y(),y=null;for(var t=0;t<b.length;t++)b[t].onAllReady&&b[t].onAllReady(k);for(var n=0;n<S.length;n++){for(var r,a,o=S[n],i=angular.isArray(o.subkey)?o.subkey:[o.subkey],s=o.name.split("."),l=g;1<s.length;)l=l[s.shift()]||{};l=l[s[0]]=l[s[0]]||[];for(var c=0;c<i.length;c++){if(i[c].selectFunc){if(!k[i[c].selectFunc]||"function"!=typeof k[i[c].selectFunc])throw new Error("Subkey function "+i[c].selectFunc+" is not properly set up");r=k[i[c].selectFunc](g,o)}else{if(!i[c].keyList)throw new Error("Invalid subkey setup for "+o.name);var d=i[c].keyList;for(r=0;r<l.length;r++){for(var u in a=!0,d)if(d.hasOwnProperty(u)&&l[r][u]!==d[u]&&(void 0===l[r][u]||!l[r][u].text||l[r][u].text!==d[u])){a=!1;break}if(a)break}if(!a)switch(i[c].onNotFound){case"error":var f="Cannot find matching "+(i[c].title||i[c].path);L(function(){k.showError(f,"Unable to set up form correctly")}),r=-1;break;case"create":default:var p=o.name.split("."),m=p.pop(),h=p.join("."),v=g;h&&(v=v[h]),r=v[m].push(d)-1}}k["$_arrayOffset_"+o.name.replace(/\./g,"_")+"_"+c]=r}}}});d.$broadcast("formInputDone",s.name),u.updateDataDependentDisplay&&g&&0<Object.keys(g).length&&u.updateDataDependentDisplay(g,null,!0,k)}}},!0)}}}t=e.directives||(e.directives={}),r.$inject=["$compile","$rootScope","$filter","$timeout","cssFrameworkService","formGenerator","formMarkupHelper"],(n=I=I||{})[n.Y=0]="Y",n[n.N=1]="N",n[n.Forced=2]="Forced",t.formInput=r}(fng=fng||{}),function(e){(e.directives||(e.directives={})).fngNakedDate=function(){return{restrict:"A",require:"ngModel",link:function(e,t,n,r){r.$parsers.push(function(e){if(e)return e.toString()}),r.$formatters.push(function(e){if(e)return new Date(e)})}}}}(fng=fng||{}),function(e){var t;function n(r,t,a,o){var n,e,i,s;s=!1,i=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(i)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(i.substr(0,4)))&&(s=!0),e=!s,r.searchPlaceholder=e?"Ctrl + / to Search":"Search",r.handleKey=function(e){if(27===e.keyCode&&r.searchTarget&&0<r.searchTarget.length)r.searchTarget="";else if(0<r.results.length)switch(e.keyCode){case 38:0<r.focus&&r.setFocus(r.focus-1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 40:r.results.length>r.focus+1&&r.setFocus(r.focus+1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 13:null!=r.focus&&r.selectResult(r.focus)}},r.setFocus=function(e){null!==r.focus&&delete r.results[r.focus].focussed,r.results[e].focussed=!0,r.focus=e},r.selectResult=function(e){var t,n=r.results[e];n.url?t=n.url.replace("|id|",n.id):(t=o.prefix()+"/"+n.resource+"/"+n.id+"/edit",n.resourceTab&&(t+="/"+n.resourceTab)),a.url(t)},r.resultClass=function(e){var t="search-result";return r.results&&r.results[e].focussed&&(t+=" focus"),t};function l(){r.moreCount=0,r.errorClass="",r.results=[],r.focus=null}r.$watch("searchTarget",function(e){e&&0<e.length?(n=r.testTime||(new Date).valueOf(),t.get("/api/search?q="+e+"&sentAt="+n).then(function(e){var t=e.data;t.timestamps&&t.timestamps.sentAt&&Number.parseInt(t.timestamps.sentAt)!==n||(0<r.searchTarget.length?(r.results=t.results,r.moreCount=t.moreCount,0<t.results.length&&(r.errorClass="",r.setFocus(0)),r.errorClass=0===r.results.length?"error has-error":""):l())},function(e){console.log("Error in searchbox.js : "+e.data+" (status="+e.status+")")})):l()},!0),r.$on("$routeChangeStart",function(){r.searchTarget=""})}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.SearchCtrl=n}(fng=fng||{}),function(t){var e;function n(e){return{restrict:"AE",templateUrl:"search-"+e.framework()+".html",controller:t.controllers.SearchCtrl}}e=t.directives||(t.directives={}),n.$inject=["cssFrameworkService"],e.globalSearch=n}(fng=fng||{}),function(e){(e.filters||(e.filters={})).camelCase=function(){return function(e){return e.replace(/([\:\-\_]+(.))/g,function(e,t,n,r){return r?n.toUpperCase():n})}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).extractTimestampFromMongoID=function(){return function(e){var t=e.substring(0,8);return new Date(1e3*parseInt(t,16))}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).titleCase=function(){return function(e,t){return e&&(e=e.replace(/(_|\.)/g," ").replace(/[A-Z]/g," $&").trim().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()}),e=t?e.replace(/\s/g,""):e.replace(/\s{2,}/g," ")),e}}}(fng=fng||{}),function(e){(e.services||(e.services={})).addAllService=function(){function r(e,t,r,n){var a,o,i=[],s=[];if(r="addAll"+r,"string"==typeof n)for(a=n.split(" "),o=0;o<a.length;o++)s.push(a[o]);if(!function e(t){for(var n in t)n===r&&i.push(t[n]),"$parent"===n&&e(t[n])}(e),void 0!==t[r]&&"string"==typeof t[r])for(a=t[r].split(" "),o=0;o<a.length;o++)0===a[o].indexOf("class=")?s.push(a[o].substring(6,a[o].length)):i.push(a[o]);return(n=0<s.length?' class="'+s.join(" ")+'" ':" ")+(0<i.length?i.join(" ")+" ":"")}this.getAddAllGroupOptions=function(e,t,n){return r(e,t,"Group",n)},this.getAddAllFieldOptions=function(e,t,n){return r(e,t,"Field",n)},this.getAddAllLabelOptions=function(e,t,n){return r(e,t,"Label",n)},this.addAll=function(e,t,n,r){return this["getAddAll"+t+"Options"](e,r,n)||[]}}}(fng=fng||{}),function(e){(e.services||(e.services={})).cssFrameworkService=function(){var n={framework:"bs3"};return{setOptions:function(e){angular.extend(n,e)},$get:function(){return{framework:function(){return n.framework},setFrameworkForDemoWebsite:function(e){n.framework=e},span:function(e){var t;switch(n.framework){case"bs2":t="span"+Math.floor(e);break;case"bs3":t="col-xs-"+Math.floor(e)}return t},offset:function(e){var t;switch(n.framework){case"bs2":t="offset"+Math.floor(e);break;case"bs3":t="col-lg-offset-"+Math.floor(e)}return t},rowFluid:function(){var e;switch(n.framework){case"bs2":e="row-fluid";break;case"bs3":e="row"}return e}}}}}}(fng=fng||{}),function(e){function t(c){return{loadControllerAndMenu:function(e,t,n,r,a){var o,i={};t+="Ctrl",i.$scope=e.modelControllers[n]=a;var s=a.$parent;s.items=s.items||[];function l(e){angular.forEach(e,function(e){e.divider?r=!0:e[o]&&(r&&(r=!1,s.items.push({divider:!0})),s.items.push(e))})}try{c(t,i),o=s.newRecord?"creating":s.id?"editing":"listing",angular.isObject(i.$scope.contextMenu)&&(l(i.$scope.contextMenu),i.$scope.contextMenuPromise&&i.$scope.contextMenuPromise.then(function(e){return l(e)})),e.modelNameDisplayPromise&&e.modelNameDisplayPromise.then(function(e){s.modelNameDisplay=e})}catch(e){/is not a function, got undefined/.test(e.message)||/\[\$controller:ctrlreg\] The controller with the name/.test(e.message)||console.log("Unable to instantiate "+t+" - "+e.message)}}}}((e.services||(e.services={})).fngModelCtrlService=t).$inject=["$controller"]}(fng=fng||{}),function(e){var t;function n(n,t){var a,r,s={hashPrefix:"",html5Mode:!1,routing:"ngroute",prefix:""},l=["edit","view"],o=[{route:"/analyse/:model/:reportSchemaName",state:"analyse::model::report",templateUrl:"base-analysis.html"},{route:"/analyse/:model",state:"analyse::model",templateUrl:"base-analysis.html"},{route:"/:model/:id/edit",state:"model::edit",templateUrl:"base-edit.html"},{route:"/:model/:id/edit/:tab",state:"model::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:id/view",state:"model::edit",templateUrl:"base-view.html"},{route:"/:model/:id/view/:tab",state:"model::view::tab",templateUrl:"base-view.html"},{route:"/:model/new",state:"model::new",templateUrl:"base-edit.html"},{route:"/:model",state:"model::list",templateUrl:"base-list.html"},{route:"/:model/viewonly",state:"model::view",templateUrl:"base-list-view.html"},{route:"/:model/:form/:id/edit",state:"model::form::edit",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/edit/:tab",state:"model::form::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/view",state:"model::form::view",templateUrl:"base-view.html"},{route:"/:model/:form/:id/view/:tab",state:"model::form::view::tab",templateUrl:"base-view.html"},{route:"/:model/:form/new",state:"model::form::new",templateUrl:"base-edit.html"},{route:"/:model/:form",state:"model::form::list",templateUrl:"base-list.html"},{route:"/:model/:form/viewonly",state:"model::form::list::view",templateUrl:"base-list-view.html"}],c=null,d={};function i(e){var t=e;return s.templateFolder&&(t="/"!==s.templateFolder[s.templateFolder.length-1]?s.templateFolder+"/"+t:s.templateFolder+t),t}function u(e,n,r){void 0===n&&(n=""),n=n||"",angular.forEach(e,function(e){a.when(n+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))}),s.variantsForDemoWebsite&&angular.forEach(s.variantsForDemoWebsite,function(t){angular.forEach(e,function(e){a.when(n+t+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))})})}function f(e,t,n){void 0===t&&(t=""),t=t||"",angular.forEach(e,function(e){r.state(e.state,angular.extend(e.options||{url:t+e.route,templateUrl:e.templateUrl},n))})}function p(e,t,n,r,a,o){var i,s=r?"/"+r:"",l=e+"/"+n,c=o?"/"+o:"";switch(t){case"list":i=l+s;break;case"edit":i=l+s+"/"+a+"/edit"+c;break;case"view":i=l+s+"/"+a+"/view"+c;break;case"read":i=l+s+"/"+a+"/read"+c;break;case"new":i=l+s+"/new"+c}return i}function m(e,t){switch(s.routing){case"ngroute":a=n.get("$routeProvider"),e&&u(e),u(t,s.prefix,s.add2fngRoutes);break;case"uirouter":r=n.get("$stateProvider"),e&&f(s.fixedRoutes),f(t,s.prefix,s.add2fngRoutes)}}return{start:function(e){angular.extend(s,e),s.prefix[0]&&"/"!==s.prefix[0]&&(s.prefix="/"+s.prefix),t.html5Mode(s.html5Mode),""!==s.hashPrefix?t.hashPrefix(s.hashPrefix):s.html5Mode||t.hashPrefix(""),m(s.fixedRoutes,o)},addRoutes:function(e,t){m(e,t)},registerAction:function(e){l.push(e)},$get:function(){return{router:function(){return s.routing},prefix:function(){return s.prefix},parsePathFunc:function(){return function(e){if(e!==c){c=e,d={newRecord:!1},0<s.prefix.length&&0===e.indexOf(s.prefix)&&(e=e.slice(s.prefix.length));var t=e.split("/");s.variants&&-1!==s.variants.indexOf(t[1])&&(d.variant=t[1],t.shift());var n=t.length;if("analyse"===t[1])d.analyse=!0,d.modelName=t[2],d.reportSchemaName=4<=n?t[3]:null;else{d.modelName=t[1];var r=[t[n-1],t[n-2]],a=r.indexOf("new"),o=r.indexOf("viewonly"),i=void 0;-1===a&&-1===o?-1!==(i=l.reduce(function(e,t){var n=r.indexOf(t);return-1<n?n:e},-1))&&(n-=2+i,d.id=t[n]):-1!==a?(d.newRecord=!0,n-=1+a):n-=1+o,1!==i&&1!==a||(d.tab=r[0]),2<n&&(d.formName=t[2])}}return d}},buildUrl:function(e){var t=s.html5Mode?"":"#";return t+=s.hashPrefix,(t+=s.prefix)[0]&&(t+="/"),t+="/"===e[0]?e.slice(1):e},buildOperationUrl:function(e,t,n,r,a){return p(s.prefix,e,t,n,r,a)},redirectTo:function(){return function(e,t,n,r,a){var o;n.search({}),o="onDelete"===e?s.onDelete?"new"===s.onDelete?p(s.prefix,"new",t.modelName,t.formName,r,a):s.onDelete:p(s.prefix,"list",t.modelName,t.formName,r,a):p(s.prefix,e,t.modelName,t.formName,r,a),n.path(o)}}}}}}t=e.services||(e.services={}),n.$inject=["$injector","$locationProvider"],t.routingService=n}(fng=fng||{}),function(e){function t(e,t,o,n,i){function g(e,t,n,r,a,o,i,s){function l(e,t){var n=angular.copy(e),r=_.find(i.tabs,function(e){return e.title===n});if(!r){if(0===i.tabs.length&&0<i.formSchema.length){i.tabs.push({title:"Main",content:[],active:"Main"===i.tab||!i.tab}),r=i.tabs[0];for(var a=0;a<i.formSchema.length;a++)r.content.push(i.formSchema[a])}r=i.tabs[i.tabs.push({title:n,containerType:"tab",content:[],active:n===i.tab})-1]}r.content.push(t)}for(var c in"function"==typeof i.onSchemaFetch&&i.onSchemaFetch(e,t),t)if(t.hasOwnProperty(c))if("_id"===c)r&&t._id.options&&t._id.options.list&&w(r,t._id.options.list,c);else if(t.hasOwnProperty(c)){var d=t[c],u=d.options||{},f=u.form||{};if(d.schema&&!f.hidden){if(o&&n){var p=[];g("Nested "+c,d.schema,p,null,c+".",!0,i,s);var m=y(c,f,a);m.schema=p,f.tab&&l(f.tab,m),void 0!==f.order?n.splice(f.order,0,m):n.push(m)}}else{if(n&&!f.hidden){var h=y(c,f,a);if(x(h.showIf,h.name,i)&&"options"!==c){var v=b(h,d,u,i,s);v.tab&&l(v.tab,v),void 0!==f.order?n.splice(f.order,0,v):n.push(v)}}r&&u.list&&w(r,u.list,c)}}"function"==typeof i.onSchemaProcessed&&i.onSchemaProcessed(e,"Main "===e.slice(0,5)?i.baseSchema():n),r&&0===r.length&&k(e,r,n,t)}function b(t,e,n,r,a){if(e.caster&&(t.array=!0,e=e.caster,angular.extend(n,e.options),e.options&&e.options.form&&angular.extend(t,e.options.form)),"String"===e.instance)n.enum?(t.type=t.type||"select",t.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):(t.options=i.suffixCleanId(t,"Options"),r[t.options]=n.enum)):(t.type||(t.type=-1!==t.name.toLowerCase().indexOf("password")?"password":"text"),n.match&&(t.add='pattern="'+n.match+'" '+(t.add||"")));else if("ObjectID"===e.instance)t.ref=n.ref,t.link&&(t.link.linkOnly?(t.type="link",t.linktext=t.link.text):t.link.label?t.linklabel=!0:console.log("Unsupported link setup"),t.form=t.link.form,t.linktab=t.link.linktab,delete t.link),"link"!==t.type&&(t.type="select",t.select2||n.form&&n.form.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):t.directive&&(t.noLookup||t[o("camelCase")(t.directive)]&&t[o("camelCase")(t.directive)].fngAjax)||function(){if(t.options=i.suffixCleanId(t,"Options"),t.ids=i.suffixCleanId(t,"_ids"),!t.hidden)if(n.ref)i.setUpLookupOptions(n.ref,t,r,a,g);else if(n.lookupListRef)i.setUpLookupListOptions(n.lookupListRef,t,r,a),t.lookupListRef=n.lookupListRef;else if(n.internalRef)i.handleInternalLookup(r,t,n.internalRef),t.internalRef=n.internalRef;else if(!n.customLookupOptions)throw new Error("No supported select lookup type found in "+t.name)}());else if("Date"===e.instance){if(!t.type)if(t.intType="date",t.readonly)t.type="text";else if(t.directive)t.type="text";else try{t.add=t.add||"",angular.module("ui.date").requires,t.type="text",t.add+=" ui-date ui-date-format "}catch(e){t.type="date",t.add+=' fng-naked-date="x" '}}else if("boolean"===e.instance.toLowerCase())t.type=t.type||"checkbox";else{if("Number"!==e.instance)throw new Error("Field "+t.name+" is of unsupported type "+e.instance);t.type=t.type||"number",void 0!==n.min&&(t.add='min="'+n.min+'" '+(t.add||"")),void 0!==n.max&&(t.add='max="'+n.max+'" '+(t.add||"")),t.step&&(t.add='step="'+t.step+'" '+(t.add||""))}return n.required&&(t.required=!0),n.readonly&&(t.readonly=!0),void 0!==e.defaultValue?t.defaultValue=e.defaultValue:e.options&&void 0!==e.options.default&&console.log("No support for default with no value, yet"),t}function c(e,t,n){for(var r=e.split("."),a=n||t.record,o=0,i=r.length;o<i;o++)a[r[o]]||(a[r[o]]=o===i-1?[]:{}),a=a[r[o]];return a}function v(e,r){function t(e){var t=e;if("string"==typeof e&&"$"===e.slice(0,1)){var n=e.split(".");switch(n.length){case 1:t=i.getListData(r,e.slice(1));break;case 2:t=i.getListData(r,n[1]);break;default:throw new Error("Unsupported showIf format")}}return t}var n,a=t(e.lhs),o=t(e.rhs);switch(e.comp){case"eq":n=a===o;break;case"ne":n=a!==o;break;default:throw new Error("Unsupported comparator "+e.comp)}return n}var y=function(e,t,n){return t.name=n+e,t},w=function(e,t,n){"object"==typeof t?(t.name=n,e.push(t)):e.push({name:n})},k=function(e,t,n,r){if(n){for(var a=0,o=n.length;a<o;a++)if("text"===n[a].type){t.push({name:n[a].name});break}0===t.length&&0!==n.length&&t.push({name:n[0].name})}if(0===t.length){for(var i in r)if("_id"!==i&&r.hasOwnProperty(i)){t.push({name:i});break}if(0===t.length)throw new Error("Unable to generate a title for "+e)}},x=function(e,r,a){var o=0;function t(e){if("string"==typeof e&&"$"===e.slice(0,1)){var t=e.slice(1),n=a.dataDependencies[t]||[];n.push(r),a.dataDependencies[t]=n,o+=1}}var n=!0;return e&&(t(e.lhs),t(e.rhs),0!==o||v(e,void 0)||(n=!1)),n};return{generateEditUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/edit")},generateViewUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/view")},generateNewUrl:function(e){return n.buildUrl(e.modelName+"/"+(e.formName?e.formName+"/":"")+"new")},handleFieldType:b,handleSchema:g,updateDataDependentDisplay:function(e,t,n,r){var a,o,i,s,l,c;for(var d in r.dataDependencies)if(r.dataDependencies.hasOwnProperty(d)){var u=d.split(".");if(1===u.length){if(n||!t||e[d]!==t[d])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var f=a[o];for(i=0;i<r.formSchema.length;i+=1)r.formSchema[i].name===f&&(l=angular.element(document.querySelector("#cg_"+r.formSchema[i].id)),v(r.formSchema[i].showIf,e)?l.removeClass("ng-hide"):l.addClass("ng-hide"))}}else{if(2!==u.length)throw new Error("You can only go down one level of subdocument with showIf");if(void 0===c&&(c=!0),e[u[0]])for(s=0;s<e[u[0]].length;s++)if(n||!t||!t[u[0]]||!t[u[0]][s]||e[u[0]][s][u[1]]!==t[u[0]][s][u[1]])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var p=a[o].split(".");if(2!==p.length)throw new Error("Conditional display must control dependent fields at same level ");for(i=0;i<r.formSchema.length;i+=1)if(r.formSchema[i].name===p[0])for(var m=r.formSchema[i].schema,h=0;h<m.length;h++)m[h].name===a[o]&&(0===(l=angular.element(document.querySelector("#f_"+p[0]+"List_"+s+" #cg_f_"+a[o].replace(".","_")))).length?l=angular.element(document.querySelector("#f_elements-"+s+"-"+p[1])):c=!1,0<l.length&&(v(r.formSchema[i].schema[h].showIf,e[u[0]][s])?l.show():l.hide()))}}}return c},add:function(t,e,n,r){var a;if(e.target.offsetParent){var o=c(t,n,r),i=n.formSchema.find(function(e){return e.name===t}),s=i?i.schema:null,l=s?n.setDefaults(s,t+"."):{};"function"==typeof(null===(a=n.dataEventFunctions)||void 0===a?void 0:a.onInitialiseNewSubDoc)&&n.dataEventFunctions.onInitialiseNewSubDoc(t,s,l),o.push(l),n.setFormDirty(e)}},unshift:function(e,t,n,r){c(e,n,r).unshift({}),n.setFormDirty(t)},remove:function(t,e,n,r,a){var o,i=c(t,r,a);if("function"==typeof r.dataEventFunctions.onDeleteSubDoc){var s=r.formSchema.find(function(e){return e.name===t}),l=s?s.schema:null;o=r.dataEventFunctions.onDeleteSubDoc(t,l,i,e)}o?r.showError(o):(i.splice(e,1),r.setFormDirty(n))},hasError:function(e,t,n,r){var a=!1;if(r){var o=r[r.topLevelFormName];if("null"!==e&&(o=o[e.replace("$index",n)]),o){var i=o[t];i&&i.$invalid&&!i.$$attr.readonly&&(i.$dirty?a=!0:angular.forEach(i.$validators,function(e,t){"required"!==t&&i.$error[t]&&(a=!0)}))}}else console.log("hasError called with no scope! ",e,t,n);return a},decorateScope:function(a,o,n,e){a.record=e.record,a.phase="init",a.disableFunctions=e.disableFunctions,a.dataEventFunctions=e.dataEventFunctions,a.topLevelFormName=void 0,a.formSchema=[],a.tabs=[],a.listSchema=[],a.recordList=[],a.dataDependencies={},a.internalLookups=[],a.listLookups=[],a.conversions={},a.pageSize=60,a.pagesLoaded=0,(e.baseScope=a).generateEditUrl=function(e){return o.generateEditUrl(e,a)},a.generateViewUrl=function(e){return o.generateViewUrl(e,a)},a.generateNewUrl=function(){return o.generateNewUrl(a)},a.scrollTheList=function(){return n.scrollTheList(a)},a.getListData=function(e,t){return n.getListData(e,t,a.listSchema,a)},a.setPristine=function(e){e&&a.dismissError(),a[a.topLevelFormName]&&a[a.topLevelFormName].$setPristine()},a.skipCols=function(e){return 0<e?"col-md-offset-3":""},a.setFormDirty=function(e){e?angular.element(e.target).inheritedData("$formController").$setDirty():console.log("setFormDirty called without an event (fine in a unit test)")},a.add=function(e,t,n){return o.add(e,t,a,n)},a.hasError=function(e,t,n){return o.hasError(e,t,n,a)},a.unshift=function(e,t,n){return o.unshift(e,t,a,n)},a.remove=function(e,t,n,r){return o.remove(e,t,n,a,r)},a.baseSchema=function(){return a.tabs.length?a.tabs:a.formSchema}}}}((e.services||(e.services={})).formGenerator=t).$inject=["$location","$timeout","$filter","routingService","recordHandler"]}(fng=fng||{}),function(e){var t;function n(f,p,m,a){function d(e,t){var n=["vertical","inline"];return t||n.push("stacked"),!e||"undefined"===e||!n.includes(e)}function s(){return"bs2"===f.framework()?"icon":"glyphicon glyphicon"}return{isHorizontalStyle:d,fieldChrome:function(e,t,n){var r=t.classes||"",a="",o="",i="";if(t.showWhen=t.showWhen||t.showwhen,t.showWhen&&("string"==typeof t.showWhen?i+='ng-show="'+t.showWhen+'"':i+='ng-show="'+function(e,a){function t(e){var t=e;if("string"==typeof e)if("$"===e.slice(0,1)){t=(a||"record")+".";var n=e.slice(1).split(".");if(1<n.length){var r=n.pop();t+=n.join(".")+"[$index]."+r}else t+=e.slice(1)}else t="'"+e+"'";return t}var n=["eq","ne","gt","gte","lt","lte"].indexOf(e.comp);if(-1===n)throw new Error("Invalid comparison in showWhen");return t(e.lhs)+["===","!==",">",">=","<","<="][n]+t(e.rhs)}(t.showWhen,n.model)+'"'),t.id&&"function"==typeof t.id.replace&&(i+=' id="cg_'+t.id.replace(/\./g,"-")+'"'),"bs3"===f.framework()){var s;r+=" form-group","vertical"===n.formstyle&&"block-level"!==t.size&&(a+='<div class="row">',r+=" col-sm-"+p.sizeAsNumber(t.size),o+="</div>");var l=null,c=t.name.split(".");s=n&&void 0!==n.subkeyno?n.subschemaroot.replace(/\./g,"-")+"-subkey"+n.subkeyno+"-"+c[c.length-1]:n.subschema?(l="form_"+c.slice(0,-1).join("_")+"$index",t.name.replace(/\./g,"-")):"f_"+t.name.replace(/\./g,"_"),a+="<div"+m.addAll(e,"Group",r,n)+" ng-class=\"{'has-error': hasError('"+l+"','"+s+"', $index)}\"",o+="</div>"}else o=d(n.formstyle,!0)?(a+="<div"+m.addAll(e,"Group","control-group",n),"</div>"):(a+="<span ","</span>");return{template:a+=(i||"")+">",closeTag:o}},label:function(e,t,n,r){var a="";if("bs3"===f.framework()||!["inline","stacked"].includes(r.formstyle)&&""!==t.label||n){a="<label";var o="control-label";if(d(r.formstyle,!1)?(t.linklabel||(a+=' for="'+t.id+'"'),void 0!==t.labelDefaultClass?o+=" "+t.labelDefaultClass:"bs3"===f.framework()&&(o+=" col-sm-3")):["inline","stacked"].includes(r.formstyle)&&(a+=' for="'+t.id+'"',o+=" sr-only"),a+=m.addAll(e,"Label",null,r)+' class="'+o+'">'+t.label,n&&(a+=' <i id="add_'+t.id+'" ng-click="add(\''+t.name+'\',$event)" class="'+s()+'-plus-sign"></i>'),a+="</label>",t.linklabel){var i='<fng-link fld="'+t.name+'" ref="'+t.ref+'" text="'+escape(a)+'"';t.form&&(i+=' form="'+t.form+'"'),t.linktab&&(i+=' linktab="'+t.linktab+'"'),a=i+="></fng-link>"}}return a},glyphClass:s,allInputsVars:function(e,t,n,r,a,o){var i,s=t.placeHolder,l="",c="",d="",u="";return"bs3"===f.framework()?(l=-1===["horizontal","vertical","inline"].indexOf(n.formstyle)?" input-sm":"",c="col-sm-"+p.sizeAsNumber(t.size),u=" form-control"):d=t.size?" input-"+t.size:"",["inline","stacked"].includes(n.formstyle)&&(s=s||t.label),i='data-ng-model="'+r+'"'+(a?' id="'+a+'" name="'+a+'" ':' name="'+o+'" '),i+=s?'placeholder="'+s+'" ':"",t.popup&&(i+='title="'+t.popup+'" '),t.ariaLabel&&(i+='aria-label="'+t.ariaLabel+'" '),{common:i+=m.addAll(e,"Field",null,n),sizeClassBS3:c,sizeClassBS2:d,compactClass:l,formControl:u}},inputChrome:function(e,t,n,r){"bs3"===f.framework()&&d(n.formstyle,!0)&&"checkbox"!==t.type&&(e='<div class="bs3-input '+r.sizeClassBS3+'">'+e+"</div>");var a=(t.helpInline||"")+(t.helpinline||"");if(0<a.length){var o="bs2"===f.framework()?{el:"span",cl:"help-inline"}:{el:"div",cl:"help-block"};e+="<"+o.el+' class="'+o.cl+'">'+a+"</"+o.el+">"}return n.noid||(e+='<div ng-if="'+(n.name||"myForm")+"['"+t.id+'\'].$dirty" class="help-block"> <div ng-messages="'+(n.name||"myForm")+"['"+t.id+'\'].$error"> <div ng-messages-include="error-messages.html"> </div> </div></div>'),t.help&&(e+='<div class="help-block">'+t.help+"</div>"),e},generateSimpleInput:function(e,t,n){var r="<input "+e+'type="'+t.type+'" ';return t.label||t.ariaLabel?n.subschema&&(r+='aria-label="'+(t.label?a("titleCase")(n.subschemaroot)+" "+t.label:t.popup||t.name.replace(/\./g," "))+'" '):r+='aria-label="'+t.name.replace(/\./g," ")+'" ',"inline"!==n.formstyle||"bs2"!==f.framework()||t.size||(r+='class="input-small"'),r+=" />"},controlDivClasses:function(e){var t=[];return d(e.formstyle,!1)&&t.push("bs2"===f.framework()?"controls":"col-sm-9"),t},handleInputAndControlDiv:function(e,t){return 0<t.length&&(e='<div class="'+t.join(" ")+'">'+e+"</div>"),e},handleArrayInputAndControlDiv:function(e,t,n,r){var a="<div ";return"bs3"===f.framework()&&(a+='ng-class="skipCols($index)" '),a+='class="'+t.join(" ")+'" id="'+n.id+'List" ',a+='ng-repeat="arrayItem in '+(r.model||"record")+"."+n.name+' track by $index">',a+=e,"link"!==n.type&&(a+="<i ng-click=\"remove('"+n.name+'\',$index,$event)" id="remove_'+n.id+'_{{$index}}" class="'+s()+'-minus-sign"></i>'),a+="</div>"},addTextInputMarkup:function(e,t,n){var r="",a=e.formControl.trim()+e.compactClass+e.sizeClassBS2+(t.class?" "+t.class:"");return 0!==a.length&&(r+='class="'+a+'"'),t.add&&(r+=" "+t.add+" "),r+=n,t.readonly?r+=" "+("boolean"==typeof t.readOnly?"readonly":'ng-readonly="'+t.readonly+'"')+" ":r+=" ",r}}}t=e.services||(e.services={}),n.$inject=["cssFrameworkService","inputSizeHelper","addAllService","$filter"],t.formMarkupHelper=n}(fng=fng||{}),function(e){(e.services||(e.services={})).inputSizeHelper=function(){var t=[1,2,4,6,8,10,12],n=["mini","small","medium","large","xlarge","xxlarge","block-level"];return{sizeMapping:t,sizeDescriptions:n,defaultSizeOffset:2,sizeAsNumber:function(e){return t[e?n.indexOf(e):2]}}}}(fng=fng||{}),function(e){var t;function n(b){return{extractFromAttr:function(e,t){function n(e){var t=e.replace(/&quot;/g,'"');return"true"===t?t=!0:"false"===t?t=!1:!isNaN(parseFloat(t))&&isFinite(t)&&(t=parseFloat(t)),t}var r={},a={formStyle:e.formstyle},o={},i=t?t.length:0;for(var s in e)e.hasOwnProperty(s)&&("fngFld"===s.slice(0,6)?r[s.slice(6).toLowerCase()]=n(e[s]):"fngOpt"===s.slice(0,6)?a[s.slice(6).toLowerCase()]=n(e[s]):t&&s.slice(0,i)===t&&(o[_.kebabCase(s.slice(i))]=n(e[s])));return{info:r,options:a,directiveOptions:o}},buildInputMarkup:function(e,t,n,r,a,o,i){var s,l,c,d=b.fieldChrome(e,n,r,' id="cg_'+n.id+'"'),u=b.controlDivClasses(r),f=d.template+b.label(e,n,a,r);if(c=a?(s="arrayItem"+(o?".x":""),l=n.id+"_{{$index}}",n.name+"_{{$index}}"):(s=t+"."+n.name,l=n.id,n.name),r.subschema&&-1!==n.name.indexOf(".")){var p=t+".",m=n.name,h=r.subschemaroot,v=m.slice(h.length+1);s=p,r.index?l="f_"+(s+=h+"["+r.index+"]."+v).slice(p.length).replace(/(\.|\[|\]\.)/g,"-"):(s+=h,r.subkey?(l=s.slice(p.length).replace(/\./g,"-")+"-subkey"+r.subkeyno+"-"+v,s+="[$_arrayOffset_"+h.replace(/\./g,"_")+"_"+r.subkeyno+"]."+v):(s+="[$index]."+v,l=null,c=m.replace(/\./g,"-")))}var g=b.allInputsVars(e,n,r,s,l,c);return g.modelString=s,f+=b["handle"+(a?"Array":"")+"InputAndControlDiv"](b.inputChrome(i(g),n,r,g),u,n,r),f+=d.closeTag},findIdInSchemaAndFlagNeedX:function e(t,n){for(var r=!1,a=0;a<t.length;a++){var o=t[a];if(o.id===n){r=o.needsX=!0;break}if(o.schema&&e(o.schema,n)){r=!0;break}}return r}}}t=e.services||(e.services={}),n.$inject=["formMarkupHelper"],t.pluginHelper=n}(fng=fng||{}),function(e){var t;function n(l,o,a,d,i,s,p,e){var c=function(e){return void 0===e&&(e=function(e){return Math.floor(e).toString(16)}),e(Date.now()/1e3)+" ".repeat(16).replace(/./g,function(){return e(16*Math.random())})};function u(e){if(-1===["cancel","backdrop click","escape key press"].indexOf(e))throw e}function b(e,t){return(e.id||"f_"+e.name).replace(/\./g,"_")+t}function f(e,t,n,r){void 0===r&&(r=!1);for(var a=t.split("."),o=a.length-1,i=e,s=0;s<o;s++){if(!i)throw new Error("walkTree failed: Object = "+e+", fieldname = "+t+", i = "+s);if(i=angular.isArray(i)?_.map(i,function(e){return e[a[s]]}):(r&&!i[a[s]]&&(i[a[s]]={}),i[a[s]]),angular.isArray(i)&&void 0!==n)if(n.scope&&"function"==typeof n.scope)i=i[n.scope().$index];else{if("number"!=typeof n)throw new Error("Unsupported element type in walkTree "+t);i=i[n]}if(!i)break}return{lastObject:i,key:i?a[o]:void 0}}function y(e,t,n,r){var a=f(e,t,n,!!r);if(a.lastObject&&a.key)if(r)if(angular.isArray(a.lastObject))for(var o=0;o<a.lastObject.length;o++)a.lastObject[o][a.key]=r[o];else a.lastObject[a.key]=r;else delete a.lastObject[a.key]}function m(t,n,e,r){if(void 0===r&&(r=!1),!n.topLevelFormName||n[n.topLevelFormName]&&(r||n[n.topLevelFormName].$pristine)){x(t.name,e.master,function(e){return"object"==typeof e&&e.id?e:S(t,e,n[b(t,"Options")],n[b(t,"_ids")])});var a=w(e.master,t.name);a&&y(n.record,t.name,void 0,a)}}var w=function(e,t,n){var r,a=f(e,t,n);return a.lastObject&&a.key&&(r=angular.isArray(a.lastObject)?_.map(a.lastObject,function(e){return e[a.key]}):a.lastObject[a.key]),r};function k(e,t,n,r){void 0===n&&(n=null);var a=w(e,t)||"";if(a&&n){var o=_.find(n,function(e){return e.name===t});if(o)switch(o.params){case void 0:break;case"timestamp":var i=a.toString().substring(0,8),s=new Date(1e3*parseInt(i,16));a=s.toLocaleDateString()+" "+s.toLocaleTimeString();break;default:a=r.dataEventFunctions[o.params](e)}}return a}function x(e,t,n){var r,a,o=(r=e.split("."),a=[r[0]],1<r.length&&a.push(r.slice(1).join(".")),a);if(1<o.length)!function(e,t,n){if(void 0!==t)if(angular.isArray(t))for(var r=0;r<t.length;r++)x(e,t[r],n);else x(e,t,n)}(o[1],t[o[0]],n);else if(t[o[0]]){var i=t[o[0]];if(angular.isArray(i))for(var s=i.length-1;0<=s;s--){var l=typeof i[s];("undefined"==l||"object"==l&&0===Object.keys(i[s]).length)&&i.splice(s,1)}t[o[0]]=n(i)}}function v(e,t,n,r,a){var o="string"==typeof t?e[t]:t,i="string"==typeof n?e[n]:n;o.length=0,i.length=0,r&&0<r.length&&r.forEach(function(e){var t=e[a];t&&0<t.length&&(o.push(t),e._id||(e._id=c()),i.push(e._id))})}var $=function(e){var t=!1;return e.needsX?t=!0:e.directive||("text"===e.type?t=!0:"select"!==e.type||e.ids||(t=!0)),t};function C(e,t,n){var r=e.conversions;return n&&(r=w(r,n)||{}),r[t]}var g=function(e,t,n,r,a,o,i){o=o||t;for(var s=0;s<e.length;s++){var l=e[s],c=l.name.slice(n);c.length||(c=l.name.split(".").pop());var d=w(t,c);if("date"===l.intType&&"string"==typeof d&&y(t,c,null,new Date(d)),l.schema){if(d)for(var u=0;u<d.length;u++)d[u]=g(l.schema,d[u],1+c.length,r,c,o,u)}else{l.internalRef&&v(r,l.options,l.ids,o[l.internalRef.property],l.internalRef.value);var f=k(t,c,null,r);if(l.array&&$(l)&&f&&!(0<f.length&&f[0].x))for(var p=0;p<f.length;p++)f[p]={x:f[p]};var m=r[b(l,"_ids")],h=void 0;if(d&&m&&0<m.length){if(-1!==c.indexOf("."))throw new Error("Trying to directly assign to a nested field 332");!d.toString().match(/^[a-f0-9]{24}$/)||l.internalRef&&l.internalRef.noConvert||(t[c]=S(l,d,r[b(l,"Options")],m))}else l.select2?(console.log("fng-select2 is deprecated - use fng-ui-select instead"),l.select2):d&&(h=C(r,c,a))&&h.fngajax&&!h.noconvert&&h.fngajax(d,l,function(e,t){y(o,e.name,i,t),F(angular.element("#"+e.id),function(){y(r.record,e.name,i,t)})})}}return t};function S(e,t,n,r){if(e.array){for(var a=[],o=!e.directive||$(e),i=0;i<t.length;i++){var s=t[i];s&&s.x&&(s=s.x);var l=N(s,r,n,e.name);o&&(l={x:l}),a.push(l)}return a}return e.select2?{id:t,text:N(t,r,n,e.name)}:N(t,r,n,e.name)}function D(e,t,n,r){var a=_.isObject(e)?e.x||e.text:e;if(a&&a.match(/^[0-9a-f]{24}$/))return a;var o=t.indexOf(a);if(-1===o)throw new Error("convertListValueToId: Invalid data - value "+a+" not found in "+t+" processing "+r);return n[o]}function h(e,t,n){n.master=g(t.formSchema,e,0,t),t.phase="ready",t.cancel()}var F=function(e,t){var n=e.inheritedData("$ngModelController"),r=n&&n.$pristine;r&&(n.$pristine=!1),t(),r&&(n.$pristine=!0)},N=function(e,t,n,r){"object"==typeof e&&(e=e.id);var a=t.indexOf(e);if(-1===a&&-1===(a=n.indexOf(e)))throw new Error("convertIdToListValue: Invalid data - id "+e+" not found in "+t+" processing "+r);return n[a]};function E(t,n,r,e,a){if(a&&0<a.length&&a.length===e.length&&n[r]){var o=a.findIndex(function(e){return e[t.value]===n[r]});if(-1<o){var i=e[o][t.value];i&&(n[r]=i)}}}function L(e,u,n,t,f){var r=!u.id&&!u.newRecord;function a(o,d){u.internalLookups.forEach(function(n){var r=o[n.ref.property],a=d[n.ref.property];v(u,n.lookupOptions,n.lookupIds,r,n.ref.value),(r&&0<r.length||a&&0<a.length)&&n.handlers.forEach(function(t){if(t.possibleArray){var e=w(u.record,t.possibleArray,null);e&&0<e.length&&e.forEach(function(e){return E(n.ref,e,t.lastPart,r,a)})}else angular.isArray(u.record[t.lastPart])?u.record[t.lastPart].forEach(function(e){E(n.ref,e,"x",r,a)}):E(n.ref,u.record,t.lastPart,r,a)})}),u.listLookups.forEach(function(l){function e(e,t){var n=e[t];return n&&n.id&&(n=n.id),n}function c(e){y(u.record,e.name)}var t=l.ref.id.slice(1);if(t.includes("."))throw new Error("No support for nested list lookups yet - "+JSON.stringify(l.ref));var n=e(o,t);n!==e(d,t)&&(l.handlers.forEach(function(e){u[e.formInstructions.options].length=0,u[e.formInstructions.ids].length=0}),n?p.readRecord(l.ref.collection,n).then(function(s){l.handlers.forEach(function(e){for(var t=u[e.formInstructions.options],n=u[e.formInstructions.ids],r=s.data[l.ref.property]||[],a=0;a<r.length;a++){var o=r[a][l.ref.value],i=_.sortedIndex(t,o);t[i]===o&&(o=o+" ("+r[a]._id+")",i=_.sortedIndex(t,o)),t.splice(i,0,o),n.splice(i,0,r[a]._id)}0===Object.keys(d).length?m(e.formInstructions,u,f,!0):c(e.formInstructions)})}):l.handlers.forEach(function(e){c(e.formInstructions)}))})}function o(){u.phase="ready",u.cancel(),a(u.record,{})}if(n.handleSchema("Main "+u.modelName,e,r?null:u.formSchema,u.listSchema,"",!0,u,f),r)f.allowLocationChange=!0;else{var i=!0;if(u.newRecord||(u.dropConversionWatcher=u.$watchCollection("conversions",function(e,t){e!==t&&u.originalData&&h(u.originalData,u,f)})),u.$watch("record",function(e,t){e!==t&&(0<Object.keys(t).length&&u.dropConversionWatcher&&(u.dropConversionWatcher(),u.dropConversionWatcher=null),i=n.updateDataDependentDisplay(e,t,i,u),a(e,t))},!0),u.id)"function"==typeof u.dataEventFunctions.onBeforeRead?u.dataEventFunctions.onBeforeRead(u.id,function(e){e?u.showError(e):t.readRecord(u,f)}):t.readRecord(u,f);else{f.allowLocationChange=!1,f.master=u.setDefaults(u.formSchema);var s=u.initialiseNewRecord||l.$$search.r;if(s)try{Object.assign(f.master,JSON.parse(s)),u.newRecordsStartPristine||u.$on("fngCancel",function(){d(function(){u[u.topLevelFormName]&&u[u.topLevelFormName].$setDirty()},1e3)})}catch(e){console.log("Error parsing specified record : "+e.message)}"function"==typeof u.dataEventFunctions.onInitialiseNewRecord&&(console.log("onInitialiseNewRecord is deprecated - use the async version - onNewRecordInit(data,cb)"),u.dataEventFunctions.onInitialiseNewRecord(f.master)),"function"==typeof u.dataEventFunctions.onNewRecordInit?u.dataEventFunctions.onNewRecordInit(f.master,function(e){e?u.showError(e):o()}):o()}}}function t(r){return function(e){if(-1!==[200,400].indexOf(e.status)){var t="";for(var n in e.data.errors)if(e.data.errors.hasOwnProperty(n)){switch(t+="<li><b>"+a("titleCase")(n)+": </b> ",e.data.errors[n].type){case"enum":t+="You need to select from the list of values";break;default:t+=e.data.errors[n].message}t+="</li>"}t=0<t.length?e.data.message+"<br /><ul>"+t+"</ul>":e.data.message||e.data.err||"Error! Sorry - No further details available.",r.showError(t)}else r.showError(e.status+" "+JSON.stringify(e.data))}}function A(e,t,n){n.allowLocationChange=!1,t.phase="reading","function"==typeof t.dataEventFunctions.onAfterRead&&t.dataEventFunctions.onAfterRead(e),t.originalData=e,h(e,t,n)}function r(e,t,n,r){var a=t.name.split("."),o=r.find(function(e){return e.ref.property===n.property&&e.ref.value===n.value}),i={formInstructions:t,lastPart:a.pop(),possibleArray:a.join(".")};o||(o={ref:n,lookupOptions:[],lookupIds:[],handlers:[]},r.push(o)),o.handlers.push(i),e[t.options]=o.lookupOptions,e[t.ids]=o.lookupIds}return{readRecord:function(t,n){t.readingRecord=p.readRecord(t.modelName,t.id),t.readingRecord.then(function(e){A(angular.copy(e.data),t,n)},function(e){404===e.status?l.path("/404"):t.handleHttpError(e)})},scrollTheList:function(n){var r=n.pagesLoaded;p.getPagedAndFilteredList(n.modelName,{aggregate:l.$$search.a,find:l.$$search.f,limit:n.pageSize,skip:r*n.pageSize,order:l.$$search.o}).then(function(e){var t=e.data;angular.isArray(t)?r===n.pagesLoaded?(n.pagesLoaded++,n.recordList=n.recordList.concat(t)):console.log("DEBUG: infinite scroll component asked for a page twice - the model was "+n.modelName):n.showError(t,"Invalid query")},n.handleHttpError)},deleteRecord:function(e,t,n){p.deleteRecord(t.modelName,e).then(function(){"function"==typeof t.dataEventFunctions.onAfterDelete&&t.dataEventFunctions.onAfterDelete(n.master),i.redirectTo()("onDelete",t,l)},function(e){404===e.status?i.redirectTo()("onDelete",t,l):t.showError(e.statusText+" ("+e.status+") while deleting record<br />"+e.data,"Error deleting record")})},updateDocument:function(e,n,r,a){r.phase="updating",p.updateRecord(r.modelName,r.id,e).then(function(e){var t=e.data;!1!==t.success?("function"==typeof r.dataEventFunctions.onAfterUpdate&&r.dataEventFunctions.onAfterUpdate(t,a.master),n.redirect?(n.allowChange&&(a.allowLocationChange=!0),o.location=n.redirect):(A(t,r,a),r.setPristine(!1))):r.showError(t)},r.handleHttpError)},createNew:function(e,n,r,a){p.createRecord(r.modelName,e).then(function(e){var t=e.data;!1!==t.success?(a.allowLocationChange=!0,"function"==typeof r.dataEventFunctions.onAfterCreate&&r.dataEventFunctions.onAfterCreate(t),n.redirect?o.location=n.redirect:i.redirectTo()("edit",r,l,t._id)):r.showError(t)},r.handleHttpError)},getListData:k,suffixCleanId:b,setData:y,setUpLookupOptions:function(n,l,c,d,r){var u=c[l.options]=[],f=c[l.ids]=[];e.getSchema(n).then(function(e){var t=e.data,s=[];r("Lookup "+n,t,null,s,"",!1,c,d),(void 0!==l.filter&&l.filter?p.getPagedAndFilteredList(n,l.filter):p.getAll(n)).then(function(e){var t=angular.copy(e.data);if(t){for(var n=0;n<t.length;n++){for(var r="",a=0;a<s.length;a++){var o=t[n][s[a].name];r+=o?o+" ":""}r=r.trim();var i=_.sortedIndex(u,r);u[i]===r&&(r=r+" ("+t[n]._id+")",i=_.sortedIndex(u,r)),u.splice(i,0,r),f.splice(i,0,t[n]._id)}c.readingRecord&&c.readingRecord.then(function(){m(l,c,d)})}})})},setUpLookupListOptions:function(o,i,s,l){var c=s[i.options]=[],d=s[i.ids]=[];"$"===o.id[0]?r(s,i,o,s.listLookups):p.readRecord(o.collection,s.$eval(o.id)).then(function(e){for(var t=e.data[o.property],n=0;n<t.length;n++){var r=t[n][o.value],a=_.sortedIndex(c,r);c[a]===r&&(r=r+" ("+t[n]._id+")",a=_.sortedIndex(c,r)),c.splice(a,0,r),d.splice(a,0,t[n]._id)}m(i,s,l)})},handleInternalLookup:function(e,t,n){r(e,t,n,e.internalLookups)},preservePristine:F,convertToMongoModel:function d(u,f,p,m,h){function v(e,t){var n;return t&&t.fngajax?e&&(n=e.id||e):e&&(n=e.text||(e.x?e.x.text:e)),n}function e(){var t=u[g],e=t.name.slice(p),n=k(f,e,null,m);if(t.schema){if(n)for(var r=0;r<n.length;r++)n[r]=d(t.schema,n[r],1+e.length,m,e)}else{if(t.array&&$(t)&&n)for(var a=0;a<n.length;a++)n[a]=n[a].x;var o=m[b(t,"_ids")];if(o&&0<o.length)x(e,f,function(e){return function(e,t,n,r){if(e.array){for(var a=[],o=0;o<t.length;o++)a.push(D(t[o],n,r,e.name));return a}return D(t,n,r,e.name)}(t,e,m[b(t,"Options")],o)});else{var i=C(m,e,h);if(i){var s=w(f,e,null),l=void 0;if(t.array){if(l=[],s)for(var c=0;c<s.length;c++)l[c]=v(s[c],i)}else l=v(s,i);y(f,e,null,l)}}}}for(var g=0;g<u.length;g++)e();return f},convertIdToListValue:N,handleError:t,decorateScope:function(c,n,r,a){c.handleHttpError=t(c),c.cancel=function(){angular.copy(a.master,c.record),c.$broadcast("fngCancel",c),d(c.setPristine)},c.$on("showErrorMessage",function(e,t){e.defaultPrevented||(e.defaultPrevented=!0,c.showError(t.body,t.title))}),c.showError=function(t,e){if(c.alertTitle=e||"Error!","string"==typeof t)c.errorMessage=t;else if(t)if(t.message&&"string"==typeof t.message)c.errorMessage=t.message;else if(t.data&&t.data.message)c.errorMessage=t.data.message;else try{c.errorMessage=JSON.stringify(t)}catch(e){c.errorMessage=t}else c.errorMessage="An error occurred - that's all we got. Sorry.";c.errorHideTimer=window.setTimeout(function(){c.dismissError(),c.$digest()},3500+1e3*(c.alertTitle+c.errorMessage).length/50),c.errorVisible=!0,window.setTimeout(function(){c.$digest()})},c.clearTimeout=function(){c.errorHideTimer&&(clearTimeout(c.errorHideTimer),delete c.errorHideTimer)},c.dismissError=function(){c.clearTimeout,c.errorVisible=!1,delete c.errorMessage,delete c.alertTitle},c.stickError=function(){clearTimeout(c.errorHideTimer)},c.prepareForSave=function(t){var n=r.convertToMongoModel(c.formSchema,angular.copy(c.record),0,c);c.id?"function"==typeof c.dataEventFunctions.onBeforeUpdate?c.dataEventFunctions.onBeforeUpdate(n,a.master,function(e){e?t(e):t(null,n)}):t(null,n):"function"==typeof c.dataEventFunctions.onBeforeCreate?c.dataEventFunctions.onBeforeCreate(n,function(e){e?t(e):t(null,n)}):t(null,n)},c.save=function(n){n=n||{},c.prepareForSave(function(e,t){e?"_update_handled_"!==e&&d(function(){c.showError(e)}):c.id?r.updateDocument(t,n,c,a):r.createNew(t,n,c,a)})},c.newClick=function(){i.redirectTo()("new",c,l)},c.$on("$locationChangeStart",function(e,t){a.allowLocationChange||c.isCancelDisabled()||(e.preventDefault(),n.open({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>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result.then(function(e){e?c.save({redirect:t,allowChange:!0}):(a.allowLocationChange=!0,o.location=t)}).catch(u))}),c.deleteClick=function(){if(c.record._id){var e=void 0;if(c.unconfirmedDelete)e=Promise.resolve(!0);else e=n.open({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>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result;e.then(function(e){function t(){r.deleteRecord(c.id,c,a)}e&&("function"==typeof c.dataEventFunctions.onBeforeDelete?c.dataEventFunctions.onBeforeDelete(a.master,function(e){e?"_delete_handled_"!==e&&c.showError(e):t()}):t())}).catch(u)}},c.isCancelDisabled=function(){return!(!c[c.topLevelFormName]||!c[c.topLevelFormName].$pristine)||"function"==typeof c.disableFunctions.isCancelDisabled&&c.disableFunctions.isCancelDisabled(c.record,a.master,c[c.topLevelFormName])},c.isSaveDisabled=function(){c.whyDisabled=void 0;var e=!1;if(c[c.topLevelFormName]?c[c.topLevelFormName].$invalid?(c.whyDisabled="The form data is invalid:",function n(e,r){e.$$controls.forEach(function(e){if(e.$invalid)if(e.$$controls)n(e,e.$name);else if(c.whyDisabled+="<br /><strong>",r&&(c.whyDisabled+=r+" "),"bs2"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().find("label")&&e.$$element.parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().find("label").text():"bs3"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().parent()&&e.$$element.parent().parent().parent().find("label")&&e.$$element.parent().parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().parent().find("label").text():c.whyDisabled+=e.$name,c.whyDisabled+="</strong>: ",e.$error)for(var t in e.$error)if(e.$error.hasOwnProperty(t))switch(t){case"required":c.whyDisabled+="Field missing required value. ";break;case"pattern":c.whyDisabled+="Field does not match required pattern. ";break;default:c.whyDisabled+=t+". "}})}(c[c.topLevelFormName])):c[c.topLevelFormName].$pristine&&(e=!0):c.whyDisabled="Top level form name invalid",e||c.whyDisabled)return!0;if("function"!=typeof c.disableFunctions.isSaveDisabled)return!1;var t=c.disableFunctions.isSaveDisabled(c.record,a.master,c[c.topLevelFormName]);return c.whyDisabled="string"==typeof t?t:"An application level user-specified function is inhibiting saving the record",!!t},c.isDeleteDisabled=function(){return!c.id||"function"==typeof c.disableFunctions.isDeleteDisabled&&c.disableFunctions.isDeleteDisabled(c.record,a.master,c[c.topLevelFormName])},c.isNewDisabled=function(){return"function"==typeof c.disableFunctions.isNewDisabled&&c.disableFunctions.isNewDisabled(c.record,a.master,c[c.topLevelFormName])},c.setDefaults=function(e,t){void 0===t&&(t="");var n={};return e.forEach(function(e){void 0!==e.defaultValue&&(n[e.name.replace(t,"")]=e.defaultValue)}),n},c.getVal=function(e,t){if(-1===e.indexOf("$index")||void 0!==t)return e=e.replace(/\$index/g,t),c.$eval("record."+e)},c.sortableOptions={update:function(){c.topLevelFormName&&c[c.topLevelFormName].$setDirty()}},c.setUpCustomLookupOptions=function(e,t,n,r){for(var a=0,o=[c,r];a<o.length;a++){var i=o[a];i&&(i[e.ids]=t,i[e.options]=n)}var s=w(c.record,e.name);if(s){if(angular.isArray(s))for(var l=0;l<s.length;l++)s[l]=N(s[l],t,n,e.name);else s=N(s,t,n,e.name);y(c.record,e.name,void 0,s)}}},fillFormFromBackendCustomSchema:L,fillFormWithBackendSchema:function(t,n,r,a){e.getSchema(t.modelName,t.formName).then(function(e){L(e.data,t,n,r,a)},t.handleHttpError)}}}t=e.services||(e.services={}),n.$inject=["$location","$window","$filter","$timeout","routingService","cssFrameworkService","SubmissionsService","SchemasService"],t.recordHandler=n}(fng=fng||{}),function(e){var t;function n(n){return{getSchema:function(e,t){return n.get("/api/schema/"+e+(t?"/"+t:""),{cache:!0})}}}t=e.services||(e.services={}),n.$inject=["$http"],t.SchemasService=n}(fng=fng||{}),function(e){var t;function n(r,a){function n(e){function t(e,t){void 0!==t&&""!==t&&("object"==typeof t&&(t=JSON.stringify(t)),""===n?n="?":n+="&",n+=e+"="+t)}var n="";return t("l",e.limit),t("f",e.find),t("a",e.aggregate),t("o",e.order),t("s",e.skip),n}var o=!0;return{getListAttributes:function(e,t){return r.get("/api/"+e+"/"+t+"/list")},readRecord:function(e,t){return r.get("/api/"+e+"/"+t)},getAll:function(e,t){var n=angular.extend({cache:o},t);return r.get("/api/"+e,n)},getPagedAndFilteredList:function(e,t){return r.get("/api/"+e+n(t))},deleteRecord:function(e,t){return r.delete("/api/"+e+"/"+t)},updateRecord:function(e,t,n){return a.get("$http").remove("/api/"+e),r.post("/api/"+e+"/"+t,n)},createRecord:function(e,t){return a.get("$http").remove("/api/"+e),r.post("/api/"+e,t)},useCache:function(e){o=e},getCache:function(){return!!a.get("$http")},clearCache:function(){a.get("$http").removeAll()}}}t=e.services||(e.services={}),n.$inject=["$http","$cacheFactory"],t.SubmissionsService=n}(fng=fng||{}),function(f){var e;function t(t,n,e,r,a,o,i,s,l){t.sharedData={record:{},disableFunctions:{},dataEventFunctions:{},modelControllers:[]};var c={master:{},fngInvalidRequired:"fng-invalid-required",allowLocationChange:!0};t.errorVisible=!1,angular.extend(t,i.parsePathFunc()(e.$$path));var d=r("titleCase")(t.modelName,!0);function u(){l.fillFormWithBackendSchema(t,s,l,c);for(var e=0;e<t.sharedData.modelControllers.length;e++)t.sharedData.modelControllers[e].onBaseCtrlReady&&t.sharedData.modelControllers[e].onBaseCtrlReady(t);t.$on("$destroy",function(){t.sharedData.modelControllers.forEach(function(e){return e.$destroy()}),n.$broadcast("fngControllersUnloaded")})}o.loadControllerAndMenu(t.sharedData,d,0,!1,t.$new()),t.formName&&o.loadControllerAndMenu(t.sharedData,d+r("titleCase")(t.formName,!0),1,!1,t.$new()),n.$broadcast("fngControllersLoaded",t.sharedData,t.modelName),t.modelNameDisplay=t.sharedData.modelNameDisplay||r("titleCase")(t.modelName),n.$broadcast("fngFormLoadStart",t),s.decorateScope(t,s,l,t.sharedData),l.decorateScope(t,a,l,c),"function"==typeof f.formsAngular.beforeProcess?f.formsAngular.beforeProcess(t,function(e){e?t.showError(e.message,"Error preparing to process form"):u()}):u()}e=f.controllers||(f.controllers={}),t.$inject=["$scope","$rootScope","$location","$filter","$uibModal","fngModelCtrlService","routingService","formGenerator","recordHandler"],e.BaseCtrl=t}(fng=fng||{}),function(e){var t;function n(e,t){e.yes=function(){t.close(!0)},e.no=function(){t.close(!1)},e.cancel=function(){t.dismiss("cancel")}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$uibModalInstance"],t.SaveChangesModalCtrl=n}(fng=fng||{}),function(e){var t;function n(t,e,n,r){t.models=[],e.get("/api/models").then(function(e){t.models=e.data},function(){n.path("/404")}),t.newUrl=function(e){return r.buildUrl(e+"/new")},t.listUrl=function(e){return r.buildUrl(e)}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.ModelCtrl=n}(fng=fng||{}),function(e){var t;function n(e,i,t,r,n,a){function o(){i.items=[],i.contextMenu=void 0}e.navScope=i,o(),i.toggleCollapsed=function(){i.collapsed=!i.collapsed},i.isCollapsed=!0,i.showShortcuts=!1,i.shortcuts=[{key:"?",act:"Show shortcuts"},{key:"/",act:"Jump to search"},{key:"Ctrl+Shift+S",act:"Save the current record"},{key:"Ctrl+Shift+Esc",act:"Cancel changes on the current record"},{key:"Ctrl+Shift+Ins",act:"Create a new record"},{key:"Ctrl+Shift+X",act:"Delete the current record"}],i.markupShortcut=function(e){return'<span class="key">'+e.split("+").join('</span> + <span class="key">')+"</span>"},i.globalShortcuts=function(n){function e(e){var t=document.getElementById(e);t&&(t.disabled||setTimeout(function(){t.click()}),n.preventDefault())}if(191===n.keyCode&&(!("INPUT"==(a=(r=n).target.tagName)||"SELECT"==a||"TEXTAREA"==a||"DIV"==a&&r.target.classList.contains("ck-editor__editable"))||n.ctrlKey&&!n.altKey&&!n.metaKey))if(n.ctrlKey||!n.shiftKey){var t=document.getElementById("searchinput");t&&(t.focus(),n.preventDefault())}else i.showShortcuts=!0;else 83===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("saveButton"):27===n.keyCode&&(n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey||i.showShortcuts)?n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("cancelButton"):i.showShortcuts=!1:45===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("newButton"):88===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey&&e("deleteButton");var r,a},i.css=function(e,t){return"function"==typeof a[e]?a[e](t):"error text-error"},i.$on("fngControllersLoaded",function(e,t,n){i.contextMenu=t.dropDownDisplay||t.modelNameDisplay||r("titleCase")(n,!1),t.dropDownDisplayPromise&&t.dropDownDisplayPromise.then(function(e){i.contextMenu=e})}),i.$on("fngControllersUnloaded",function(e){o()}),i.doClick=function(e,t){var n=angular.element(t.target),r=i.items[e];if(r.divider||n.parent().hasClass("disabled"))t.preventDefault();else if(r.broadcast)i.$broadcast(r.broadcast);else{var a=r.args||[],o=r.fn;if("function"==typeof o)switch(a.length){case 0:o();break;case 1:o(a[0]);break;case 2:o(a[0],a[1]);break;case 3:o(a[0],a[1],a[2]);break;case 4:o(a[0],a[1],a[2],a[3])}else if(o)throw new Error("Incorrect menu setup")}},i.isHidden=function(e){function t(e){return!!e.isHidden&&e.isHidden()}var n=!1;if(i.items[e].divider)if(0===e)n=!0;else for(var r=!1,a=e-1;0<=a&&!n&&!r;)i.items[a].divider?n=!0:t(i.items[a])?--a:r=!0;return n||t(i.items[e])},i.isDisabled=function(e){return!!i.items[e].isDisabled&&i.items[e].isDisabled()},i.buildUrl=function(e){return n.buildUrl(e)},i.dropdownClass=function(e){var t="";return i.items[e].divider?t="divider":i.isDisabled(e)&&(t="disabled"),t}}t=e.controllers||(e.controllers={}),n.$inject=["$rootScope","$scope","$location","$filter","routingService","cssFrameworkService"],t.NavCtrl=n}(fng=fng||{}),function(e){e.formsAngular=angular.module("formsAngular",["ngSanitize","ngMessages","ui.bootstrap","infinite-scroll","monospaced.elastic"]).controller("BaseCtrl",e.controllers.BaseCtrl).controller("SaveChangesModalCtrl",e.controllers.SaveChangesModalCtrl).controller("LinkCtrl",e.controllers.LinkCtrl).controller("ModelCtrl",e.controllers.ModelCtrl).controller("NavCtrl",e.controllers.NavCtrl).directive("modelControllerDropdown",e.directives.modelControllerDropdown).directive("errorDisplay",e.directives.errorDisplay).directive("fngLink",e.directives.fngLink).directive("formInput",e.directives.formInput).directive("formButtons",e.directives.formButtons).directive("globalSearch",e.directives.globalSearch).directive("fngNakedDate",e.directives.fngNakedDate).filter("camelCase",e.filters.camelCase).filter("titleCase",e.filters.titleCase).filter("extractTimestampFromMongoID",e.filters.extractTimestampFromMongoID).service("addAllService",e.services.addAllService).provider("cssFrameworkService",e.services.cssFrameworkService).provider("routingService",e.services.routingService).factory("fngModelCtrlService",e.services.fngModelCtrlService).factory("formGenerator",e.services.formGenerator).factory("formMarkupHelper",e.services.formMarkupHelper).factory("inputSizeHelper",e.services.inputSizeHelper).factory("pluginHelper",e.services.pluginHelper).factory("recordHandler",e.services.recordHandler).factory("SchemasService",e.services.SchemasService).factory("SubmissionsService",e.services.SubmissionsService)}(fng=fng||{});var formsAngular=fng.formsAngular;angular.module("formsAngular").run(["$templateCache",function(e){e.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'),e.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\x3c!-- <pre>--\x3e\n \x3c!--Record--\x3e\n \x3c!--{{ record | json }}--\x3e\n \x3c!--formSchema--\x3e\n \x3c!--{{ formSchema | json }}--\x3e\n\x3c!-- </pre>--\x3e\n</div>\n'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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'),e.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')}]);
@@ -157,6 +157,8 @@ declare module fng {
157
157
  formstyle?: formStyle; // (only valid on a sub schema) sets style of sub form.
158
158
  sortable? : boolean | string; // Allows drag and drop sorting of arrays - requires angular-ui-sortable
159
159
  ngClass?: string; // Allows for conditional per-item styling through the addition of an ng-class expression to the class list of li elements created for each item in the array
160
+ subDocContainerType?: 'fieldset' | 'well' | 'well-large' | 'well-small' | string | ((info) => {before: '', after: ''}); // allows each element in the array to be nested in a container
161
+ subDocContainerProps?: any; // the parameters that will be passed if subDocContainerType is a function
160
162
 
161
163
  /*
162
164
  The next section relates to the display of sub documents
@@ -321,7 +323,6 @@ declare module fng {
321
323
  unconfirmedDelete: boolean;
322
324
  getVal: any;
323
325
  sortableOptions: any;
324
- tabDeselect: any;
325
326
  tabs?: Array<any>; // In the case of forms that contain a tab set
326
327
  tab?: string; // title of the active tab - from the route
327
328
  activeTabNo?: number;
@@ -369,6 +370,7 @@ declare module fng {
369
370
  onSchemaFetch?: (description: string, source: IFieldViewInfo[]) => void;
370
371
  onSchemaProcessed?: (description: string, formSchema: IFormInstruction[]) => void;
371
372
  updateQueryForTab?: (tab: string) => void;
373
+ tabDeselect?: ($event: any, $selectedIndex: number) => void;
372
374
  setUpCustomLookupOptions?: (schemaElement: IFormInstruction, ids: string[], options: string[], baseScope: any) => void;
373
375
  }
374
376
 
@@ -246,6 +246,7 @@ var FormsAngular = /** @class */ (function () {
246
246
  };
247
247
  ;
248
248
  FormsAngular.prototype.internalSearch = function (req, resourcesToSearch, includeResourceInResults, limit, callback) {
249
+ var _a, _b, _c, _d;
249
250
  if (typeof req.query === 'undefined') {
250
251
  req.query = {};
251
252
  }
@@ -278,9 +279,29 @@ var FormsAngular = /** @class */ (function () {
278
279
  if (filter) {
279
280
  filter = JSON.parse(filter);
280
281
  }
282
+ // See if we are narrowing down the resources
283
+ var collectionName;
284
+ var collectionNameLower;
285
+ var colonPos = searchFor.indexOf(':');
286
+ switch (colonPos) {
287
+ case -1:
288
+ // Original behaviour = do nothing different
289
+ break;
290
+ case 0:
291
+ // "Special search" - yet to be implemented
292
+ break;
293
+ default:
294
+ collectionName = searchFor.slice(0, colonPos);
295
+ collectionNameLower = collectionName.toLowerCase();
296
+ searchFor = searchFor.slice(colonPos + 1, 999);
297
+ if (searchFor === '') {
298
+ searchFor = '?';
299
+ }
300
+ break;
301
+ }
281
302
  for (var i = 0; i < resourceCount; i++) {
282
303
  var resource = resourcesToSearch[i];
283
- if (resourceCount === 1 || resource.options.searchImportance !== false) {
304
+ if (resourceCount === 1 || (resource.options.searchImportance !== false && (!collectionName || collectionName === resource.resourceName || ((_b = (_a = resource.options) === null || _a === void 0 ? void 0 : _a.synonyms) === null || _b === void 0 ? void 0 : _b.find(function (s) { var _a; return ((_a = s.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === collectionNameLower; }))))) {
284
305
  var schema = resource.model.schema;
285
306
  var indexedFields = [];
286
307
  for (var j = 0; j < schema._indexes.length; j++) {
@@ -302,8 +323,14 @@ var FormsAngular = /** @class */ (function () {
302
323
  if (indexedFields.length === 0) {
303
324
  console.log('ERROR: Searching on a collection with no indexes ' + resource.resourceName);
304
325
  }
326
+ var synonymObj = (_d = (_c = resource.options) === null || _c === void 0 ? void 0 : _c.synonyms) === null || _d === void 0 ? void 0 : _d.find(function (s) { return s.name.toLowerCase() === collectionNameLower; });
327
+ var synonymFilter = synonymObj === null || synonymObj === void 0 ? void 0 : synonymObj.filter;
305
328
  for (var m = 0; m < indexedFields.length; m++) {
306
- searches.push({ resource: resource, field: indexedFields[m] });
329
+ var searchObj = { resource: resource, field: indexedFields[m] };
330
+ if (synonymFilter) {
331
+ searchObj.filter = synonymFilter;
332
+ }
333
+ searches.push(searchObj);
307
334
  }
308
335
  }
309
336
  }
@@ -330,98 +357,94 @@ var FormsAngular = /** @class */ (function () {
330
357
  searchCriteria = { $regex: '^(' + modifiedSearchStr + ')', $options: 'i' };
331
358
  }
332
359
  var handleSearchResultsFromIndex = function (err, docs, item, cb) {
333
- if (!err && docs && docs.length > 0) {
334
- async.map(docs, function (aDoc, cbdoc) {
335
- return __awaiter(this, void 0, void 0, function () {
336
- function handleResultsInList() {
337
- if (multiMatchPossible) {
338
- resultObject.matched = resultObject.matched || [];
339
- // record the index of string that matched, so we don't count it against another field
340
- for (var i = 0; i < searchStrings.length; i++) {
341
- if (aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
342
- resultObject.matched.push(i);
343
- break;
344
- }
345
- }
360
+ function handleSingleSearchResult(aDoc, cbdoc) {
361
+ var thisId = aDoc._id.toString(), resultObject, resultPos;
362
+ function handleResultsInList() {
363
+ if (multiMatchPossible) {
364
+ resultObject.matched = resultObject.matched || [];
365
+ // record the index of string that matched, so we don't count it against another field
366
+ for (var i = 0; i < searchStrings.length; i++) {
367
+ if (aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
368
+ resultObject.matched.push(i);
369
+ break;
346
370
  }
347
- resultObject.searchImportance = item.resource.options.searchImportance || 99;
348
- if (item.resource.options.localisationData) {
349
- resultObject.resource = translate(resultObject.resource, item.resource.options.localisationData, "resource");
350
- resultObject.resourceText = translate(resultObject.resourceText, item.resource.options.localisationData, "resourceText");
351
- resultObject.resourceTab = translate(resultObject.resourceTab, item.resource.options.localisationData, "resourceTab");
371
+ }
372
+ }
373
+ resultObject.searchImportance = item.resource.options.searchImportance || 99;
374
+ if (item.resource.options.localisationData) {
375
+ resultObject.resource = translate(resultObject.resource, item.resource.options.localisationData, "resource");
376
+ resultObject.resourceText = translate(resultObject.resourceText, item.resource.options.localisationData, "resourceText");
377
+ resultObject.resourceTab = translate(resultObject.resourceTab, item.resource.options.localisationData, "resourceTab");
378
+ }
379
+ results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
380
+ cbdoc(null);
381
+ }
382
+ // Do we already have them in the list?
383
+ for (resultPos = results.length - 1; resultPos >= 0; resultPos--) {
384
+ if (results[resultPos].id.toString() === thisId) {
385
+ break;
386
+ }
387
+ }
388
+ if (resultPos >= 0) {
389
+ resultObject = Object.assign({}, results[resultPos]);
390
+ // If they have already matched then improve their weighting
391
+ if (multiMatchPossible) {
392
+ // record the index of string that matched, so we don't count it against another field
393
+ for (var i = 0; i < searchStrings.length; i++) {
394
+ if (!resultObject.matched.includes(i) && aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
395
+ resultObject.matched.push(i);
396
+ resultObject.addHits = Math.max((resultObject.addHits || 9) - 1, 0);
397
+ // remove it from current position
398
+ results.splice(resultPos, 1);
399
+ // and re-insert where appropriate
400
+ results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
401
+ break;
352
402
  }
353
- results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
354
- cbdoc(null);
355
403
  }
356
- var thisId, resultObject, resultPos, i, addHits_1, specialListingFormat;
357
- return __generator(this, function (_a) {
358
- switch (_a.label) {
359
- case 0:
360
- thisId = aDoc._id.toString();
361
- for (resultPos = results.length - 1; resultPos >= 0; resultPos--) {
362
- if (results[resultPos].id.toString() === thisId) {
363
- break;
364
- }
365
- }
366
- if (!(resultPos >= 0)) return [3 /*break*/, 1];
367
- resultObject = Object.assign({}, results[resultPos]);
368
- // If they have already matched then improve their weighting
369
- if (multiMatchPossible) {
370
- // record the index of string that matched, so we don't count it against another field
371
- for (i = 0; i < searchStrings.length; i++) {
372
- if (!resultObject.matched.includes(i) && aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
373
- resultObject.matched.push(i);
374
- resultObject.addHits = Math.max((resultObject.addHits || 9) - 1, 0);
375
- // remove it from current position
376
- results.splice(resultPos, 1);
377
- // and re-insert where appropriate
378
- results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
379
- break;
380
- }
381
- }
382
- }
383
- cbdoc(null);
384
- return [3 /*break*/, 4];
385
- case 1:
386
- if (multiMatchPossible)
387
- // If they match the whole search phrase in one index they get smaller addHits (so they sort higher)
388
- if (aDoc[item.field].toLowerCase().indexOf(searchFor) === 0) {
389
- addHits_1 = 7;
390
- }
391
- specialListingFormat = item.resource.options.searchResultFormat;
392
- if (!specialListingFormat) return [3 /*break*/, 3];
393
- return [4 /*yield*/, specialListingFormat.apply(aDoc)];
394
- case 2:
395
- resultObject = _a.sent();
396
- resultObject.addHits = addHits_1;
397
- handleResultsInList();
398
- return [3 /*break*/, 4];
399
- case 3:
400
- that.getListFields(item.resource, aDoc, function (err, description) {
401
- if (err) {
402
- cbdoc(err);
403
- }
404
- else {
405
- resultObject = {
406
- id: aDoc._id,
407
- weighting: 9999,
408
- addHits: addHits_1,
409
- text: description
410
- };
411
- if (resourceCount > 1 || includeResourceInResults) {
412
- resultObject.resource = resultObject.resourceText = item.resource.resourceName;
413
- }
414
- handleResultsInList();
415
- }
416
- });
417
- _a.label = 4;
418
- case 4: return [2 /*return*/];
404
+ }
405
+ cbdoc(null);
406
+ }
407
+ else {
408
+ // Otherwise add them new...
409
+ var addHits_1;
410
+ if (multiMatchPossible)
411
+ // If they match the whole search phrase in one index they get smaller addHits (so they sort higher)
412
+ if (aDoc[item.field].toLowerCase().indexOf(searchFor) === 0) {
413
+ addHits_1 = 7;
414
+ }
415
+ // Use special listings format if defined
416
+ var specialListingFormat = item.resource.options.searchResultFormat;
417
+ if (specialListingFormat) {
418
+ specialListingFormat.apply(aDoc, [req])
419
+ .then(function (resultObj) {
420
+ resultObject = resultObj;
421
+ resultObject.addHits = addHits_1;
422
+ handleResultsInList();
423
+ });
424
+ }
425
+ else {
426
+ that.getListFields(item.resource, aDoc, function (err, description) {
427
+ if (err) {
428
+ cbdoc(err);
429
+ }
430
+ else {
431
+ resultObject = {
432
+ id: aDoc._id,
433
+ weighting: 9999,
434
+ addHits: addHits_1,
435
+ text: description
436
+ };
437
+ if (resourceCount > 1 || includeResourceInResults) {
438
+ resultObject.resource = resultObject.resourceText = item.resource.resourceName;
439
+ }
440
+ handleResultsInList();
419
441
  }
420
442
  });
421
- });
422
- }, function (err) {
423
- cb(err);
424
- });
443
+ }
444
+ }
445
+ }
446
+ if (!err && docs && docs.length > 0) {
447
+ async.map(docs, handleSingleSearchResult, cb);
425
448
  }
426
449
  else {
427
450
  cb(err);
@@ -429,13 +452,14 @@ var FormsAngular = /** @class */ (function () {
429
452
  };
430
453
  this.searchFunc(searches, function (item, cb) {
431
454
  var searchDoc = {};
432
- if (filter) {
433
- that.hackVariables(filter);
434
- extend(searchDoc, filter);
435
- if (filter[item.field]) {
455
+ var searchFilter = filter || item.filter;
456
+ if (searchFilter) {
457
+ that.hackVariables(searchFilter);
458
+ extend(searchDoc, searchFilter);
459
+ if (searchFilter[item.field]) {
436
460
  delete searchDoc[item.field];
437
461
  var obj1 = {}, obj2 = {};
438
- obj1[item.field] = filter[item.field];
462
+ obj1[item.field] = searchFilter[item.field];
439
463
  obj2[item.field] = searchCriteria;
440
464
  searchDoc['$and'] = [obj1, obj2];
441
465
  }
@@ -690,7 +714,7 @@ var FormsAngular = /** @class */ (function () {
690
714
  reportSchema = JSON.parse(req.query.r);
691
715
  break;
692
716
  default:
693
- return [2 /*return*/, self.renderError(new mongoose_1.Error('Invalid "r" parameter'), null, req, res, next)];
717
+ return [2 /*return*/, self.renderError(new mongoose_1.Error('Invalid "r" parameter'), null, req, res)];
694
718
  }
695
719
  }
696
720
  else {
@@ -717,7 +741,7 @@ var FormsAngular = /** @class */ (function () {
717
741
  schemaCopy.params = schemaCopy.params || [];
718
742
  self.reportInternal(req, req.resource, schemaCopy, function (err, result) {
719
743
  if (err) {
720
- self.renderError(err, null, req, res, next);
744
+ self.renderError(err, null, req, res);
721
745
  }
722
746
  else {
723
747
  res.send(result);
@@ -936,8 +960,8 @@ var FormsAngular = /** @class */ (function () {
936
960
  else {
937
961
  // TODO - this ref func can probably be done away with now that list fields can have ref
938
962
  var j_1 = 0;
939
- async.whilst(function () {
940
- return j_1 < findResults.length;
963
+ async.whilst(function (cbtest) {
964
+ cbtest(null, j_1 < findResults.length);
941
965
  }, function (cbres) {
942
966
  var theResult = findResults[j_1];
943
967
  translateObject.translations[j_1] = translateObject.translations[j_1] || {};
@@ -1092,7 +1116,7 @@ var FormsAngular = /** @class */ (function () {
1092
1116
  var self_1 = this;
1093
1117
  this.filteredFind(req.resource, req, aggregationParam, findParam, projectParam, orderParam, limitParam, skipParam, function (err, docs) {
1094
1118
  if (err) {
1095
- return self_1.renderError(err, null, req, res, next);
1119
+ return self_1.renderError(err, null, req, res);
1096
1120
  }
1097
1121
  else {
1098
1122
  res.send(docs);
@@ -1164,7 +1188,7 @@ var FormsAngular = /** @class */ (function () {
1164
1188
  function doAggregation(queryObj, cb) {
1165
1189
  if (aggregationParam) {
1166
1190
  aggregationParam = that.sanitisePipeline(aggregationParam, hiddenFields, queryObj);
1167
- resource.model.aggregate(aggregationParam, function (err, aggregationResults) {
1191
+ void resource.model.aggregate(aggregationParam, function (err, aggregationResults) {
1168
1192
  if (err) {
1169
1193
  throw err;
1170
1194
  }
@@ -1282,6 +1306,7 @@ var FormsAngular = /** @class */ (function () {
1282
1306
  var hiddenFields = this.generateHiddenFields(resource, false);
1283
1307
  hiddenFields.__v = false;
1284
1308
  that.doFindFunc(req, resource, function (err, queryObj) {
1309
+ var _a;
1285
1310
  if (err) {
1286
1311
  cb(err);
1287
1312
  }
@@ -1303,7 +1328,7 @@ var FormsAngular = /** @class */ (function () {
1303
1328
  else {
1304
1329
  crit = idSel;
1305
1330
  }
1306
- cb(null, resource.model.findOne(crit).select(that.generateProjection(hiddenFields, req.query.p)));
1331
+ cb(null, resource.model.findOne(crit).select(that.generateProjection(hiddenFields, (_a = req.query) === null || _a === void 0 ? void 0 : _a.p)));
1307
1332
  }
1308
1333
  });
1309
1334
  };
@@ -31,6 +31,8 @@ declare module fngServer {
31
31
  [pathName: string]: Path;
32
32
  }
33
33
 
34
+ export type ISearchResultFormatter = () => Promise<ISearchResult>;
35
+
34
36
  export interface ResourceOptions {
35
37
  suppressDeprecatedMessage?: boolean;
36
38
  onRemove?: (doc, req, cb) => void;
@@ -40,11 +42,12 @@ declare module fngServer {
40
42
  findFunc?: (req, cb) => void,
41
43
  getOrgCriteria?: (userOrganisation: string) => Promise<any>
42
44
  idIsList?: IIdIsList,
43
- searchResultFormat?: ISearchResult,
45
+ searchResultFormat?: ISearchResultFormatter,
44
46
  searchOrder?: any,
45
47
  listOrder?: any,
46
48
  onAccess?: (req, cb) => void,
47
49
  searchFunc?: SearchFunc;
50
+ synonyms? : {name: string, filter?: any}[], // name must be lower case
48
51
  // below here are autogenerated
49
52
  listFields?: { field: string }[]; // added after preprocess
50
53
  dependents?: { resource: Resource, keys: string[]} []; // can be added by generateDependencyList
@@ -62,12 +65,15 @@ declare module fngServer {
62
65
  callback: (err: Error, docs?: any[]) => void
63
66
  ) => void;
64
67
 
65
- interface Resource {
66
- resourceName: string;
68
+ interface ResourceExport {
67
69
  model?: Model<any>; // TODO TS Get rid of the ? here
68
70
  options?: ResourceOptions;
69
71
  }
70
72
 
73
+ interface Resource extends ResourceExport {
74
+ resourceName: string;
75
+ }
76
+
71
77
  interface ListParams {
72
78
  ref: Boolean; // The object is this a lookup?
73
79
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "author": "Mark Chapman <support@forms-angular.org>",
4
4
  "description": "A form builder that sits on top of Angular.js, Twitter Bootstrap, jQuery UI, Angular-UI, Express and Mongoose. Opinionated or what?",
5
5
  "homepage": "http://forms-angular.org",
6
- "version": "0.12.0-beta.167",
6
+ "version": "0.12.0-beta.170",
7
7
  "engines": {
8
8
  "node": ">=8.x",
9
9
  "npm": ">=5.x"
@@ -12,7 +12,6 @@
12
12
  "build": "If this is not a production install we need bootstrap less files for building, and use bower to load them. Couldn't figure out how to load two versions of same library with npm - PRs welcome."
13
13
  },
14
14
  "scripts": {
15
- "pretest": "npm run build",
16
15
  "test": "gulp test",
17
16
  "tidy": "find . -name '*.js' -not -path '**/node_modules/**' -and -not -path '**/website/**' -and -not -path '**/test/**' -and -not -path '**/models/**' -and -not -name 'gulpfile.js' -and -not -name 'index.js' -and -not -name 'Gruntfile.js' -and -not -name '*.conf.js' -delete && find . -name '*.map' -not -path '**/node_modules/**' -delete",
18
17
  "build": "if [ -d 'node_modules/bower' ]; then npx bower install --config.directory=node_modules --production jquery@2.0.3 bootstrap-2-3-2=git://github.com/twbs/bootstrap.git#v2.3.2 bootstrap-3-4-0=git://github.com/twbs/bootstrap.git#v3.4.0; fi && gulp build"
@@ -47,8 +46,8 @@
47
46
  "angular-messages": "1.8.2",
48
47
  "angular-sanitize": "1.8.2",
49
48
  "angular-ui-bootstrap": "1.3.2 || 2.5.6",
50
- "angular-ui-grid": "4.10.2",
51
- "async": "3.2.0",
49
+ "angular-ui-grid": "4.11.0",
50
+ "async": "3.2.1",
52
51
  "lodash": "^4.17.21",
53
52
  "ng-infinite-scroll": "1.3.0",
54
53
  "node.extend": "2.0.2"
@@ -58,9 +57,9 @@
58
57
  "mongoose": "^5.10"
59
58
  },
60
59
  "devDependencies": {
61
- "@types/angular": "1.8.1",
62
- "@types/lodash": "4.14.170",
63
- "@types/node": "^14.17.3",
60
+ "@types/angular": "1.8.3",
61
+ "@types/lodash": "4.14.176",
62
+ "@types/node": "^14.17.32",
64
63
  "angular-mocks": "1.8.2",
65
64
  "body-parser": "1.19.0",
66
65
  "bower": "^1.8.12",
@@ -70,7 +69,7 @@
70
69
  "gulp-angular-templatecache": "3.0.0",
71
70
  "gulp-clean-css": "4.3.0",
72
71
  "gulp-concat": "2.6.1",
73
- "gulp-less": "4.0.1",
72
+ "gulp-less": "5.0.0",
74
73
  "gulp-mocha": "8.0.0",
75
74
  "gulp-ng-annotate": "2.1.0",
76
75
  "gulp-rename": "2.0.0",
@@ -78,19 +77,19 @@
78
77
  "gulp-typescript": "5.0.1",
79
78
  "gulp-uglify": "3.0.2",
80
79
  "gulp-umd": "2.0.0",
81
- "jasmine-core": "3.7.1",
82
- "karma": "^6.3.4",
80
+ "jasmine-core": "3.10.1",
81
+ "karma": "^6.3.6",
83
82
  "karma-chrome-launcher": "3.1.0",
84
83
  "karma-firefox-launcher": "^2.1.1",
85
84
  "karma-jasmine": "4.0.1",
86
85
  "karma-junit-reporter": "2.0.1",
87
86
  "karma-ng-html2js-preprocessor": "1.0.0",
88
87
  "matchdep": "2.0.0",
89
- "mocha": "^9.0.1",
88
+ "mocha": "^9.1.3",
90
89
  "mongoose": "^5.13.10",
91
- "prettier": "2.3.1",
90
+ "prettier": "2.4.1",
92
91
  "pump": "3.0.0",
93
- "typescript": "4.3.2"
92
+ "typescript": "4.4.4"
94
93
  },
95
94
  "license": "MIT"
96
95
  }