<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="prism.css" />
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
    <script src="prism.js"></script>
    <script src="loanpro_connect.js"></script>
    <!-- Change the code in request_module.js to adjust the API request -->
    <script src="request_module.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
  </head>

  <body ng-app="simnangClients">
    <div ng-controller="requestController">
      <h1>Loan Search</h1>
      <!-- Either change your credentials in request_module.js or change then in the UI -->
      <auth-form></auth-form>
      <!-- This sets the form to use to show the request in the UI -->
      <send-form></send-form>
      <!-- This shows the response from the server -->
      <response-form></response-form>
    </div>
  </body>

</html>
var app = angular.module('simnangClients', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);
app.controller('loanproClient', ['$scope','$http', '$sce', function($scope,$http, $sce) {
  
  // default information for server, api path, and protocol (don't change)
  $scope.server = "loanpro.simnang.com"
  $scope.basePath = "/api/public/api/1/";
  $scope.protocl = "https";
  
  // holds authentication information for API calls
  $scope.api_auth = {
    tenant_id: 0,
    api_token: ''
  };
  
  // holds all api calls
  $scope.api_calls = [];
  
  // only set to false when you can guarantee that all requests can be sent at random orders and at the same time
  $scope.preserveOrder = true;
  
  // add API call to the queue
  $scope.queueAPICall = function(request){
    // default essentials
    var method = request.method || "GET";
    var uri = request.uri || "";
    var data = request.data || {};
    var query = request.query || {};
    var title = request.title || "";
    
    // add it with empty response info
    $scope.api_calls.push({
      response: "",
      responseFormatted: "",
      responseCode: "",
      responseClass: "",
      responseTitle: "",
      responseInfo: "",
      unreportedErr: false,
      uri: uri,
      title: title,
      data: data,
      query: query,
      method: method
    });
  };
  
  // serializes a URL query parameter object
  $scope.serializeQuery = function(qry) {
    var res = [];
    for(var qryKey in qry){
      if (qry.hasOwnProperty(qryKey)) {
        res.push(encodeURIComponent(qryKey) + "=" + encodeURIComponent(qry[qryKey]));
      }
    }
    return res.join("&");
  };
  
  $scope.dataStr = function(index){
    index = index || 0;
    if($scope.api_calls[index].method.toLowerCase() != "get" && JSON.stringify($scope.api_calls[index].data, null, 0).length > 2)
      return JSON.stringify($scope.api_calls[index].data, null, 0);
    return "";
  }
  
  $scope.dataLength = function(index){
    return $scope.dataStr(index).length;
  }
  
  $scope.sendRequest = function(index, callbackSuccess, callbackError){
    var call = $scope.api_calls[index];
    
    // generate the URL
    var url = $scope.protocl + "://" + $scope.server + $scope.basePath + call.uri;
    
    // Encode the GET parameters
    var encodedQuery = $scope.serializeQuery(call.query);
    if(encodedQuery)
      url += "?" + encodedQuery;
    // Send the Request
    if($scope.dataLength(index)){
      return $http({
          method: call.method,
          url: url,
          headers: {
            "Autopal-Instance-Id": $scope.api_auth.tenant_id,
            "Authorization": "Bearer " + $scope.api_auth.api_token,
            "Content-Type": "application/json"
          },
          data: call.data
        }).then(function (response) {
          // On success, call callback success passing in the order ID and the response
          callbackSuccess({callId: index, response: response});
          //resolve();
          return new Promise((resolve,reject) => {resolve('success');});
        }, function (response) {
          // On fail, cal the callback error passing in the order ID and the response
          callbackError({callId: index, response: response});
          return new Promise((resolve,reject) => {resolve('error');});
          //resolve();
        });
    }
    else{
      return $http({
          method: call.method,
          url: url,
          headers: {
            "Autopal-Instance-Id": $scope.api_auth.tenant_id,
            "Authorization": "Bearer " + $scope.api_auth.api_token,
            "Content-Type": "application/json"
          }
        }).then(function (response) {
          // On success, call callback success passing in the order ID and the response
          callbackSuccess({callId: index, response: response});
          //resolve();
          return new Promise((resolve,reject) => {resolve('success');});
        }, function (response) {
          // On fail, cal the callback error passing in the order ID and the response
          callbackError({callId: index, response: response});
          return new Promise((resolve,reject) => {resolve('error');});
          //resolve();
        });
    }
  }
  
  // sends all api requests in queue
  $scope.sendAPIRequests = function(callbackSuccess, callbackError){
    // Make sure we have callbacks
    callbackSuccess = callbackSuccess || $scope.showResponse;
    callbackError = callbackError || $scope.showError;
    for(var j = 0; j < $scope.api_calls.length; ++j){
      var call = $scope.api_calls[j];
      // Clear previous response info
      call.unreportedErr = false;
      call.response = "In Progress...";
      call.responseFormatted = "In Progress...";
      call.responseCode = "";
      call.responseClass =  "status_inprogress";
      call.responseTitle = "";
      call.responseInfo = "In Progress...";
    }
    if($scope.preserveOrder){
      var i = -1;
      var thenFunc = function(){
        i = i + 1;
        if(i < $scope.api_calls.length)
        {
          $scope.sendRequest(i, callbackSuccess, callbackError).then(thenFunc);
        }
      }
      thenFunc();
    }
    else{
      for(var k = 0; k < $scope.api_calls.length; ++k){
        var request = $scope.sendRequest(k, callbackSuccess, callbackError).then(()=>{});
      }
    }
  };
  
  // formats response status code to HTML
  $scope.formatStatus = function(status){
    // gets the status code in formats we need
    status = parseInt(status);
    var code = status;
    var name = $scope.http_codes[status.toString()];
    
    // default css class (in 300s)
    var css = "status_warn";
    
    // error status
    if(status < 200 || status > 300)
      css = "status_error"
    // success status
    else if(status < 300)
      css = "status_ok";
    
    // return class
    return css;
  };
  
  // default success callback
  $scope.showResponse = function(data){
    // parse data object
    var response = data.response;
    var id = data.callId;
    var call = $scope.api_calls[id];
    
    // if there's an error, flag it and sho it
    if(response.data.error){
      $scope.showError(data);
      call.unreportedErr = true;
      return;
    }
    
    // was an actual success, create the formatting
    call.response = JSON.stringify(response.data, null, 4);
    call.responseFormatted = $sce.trustAsHtml(Prism.highlight(call.response, Prism.languages.javascript));
    call.responseCode = response.status;
    call.responseClass = $scope.formatStatus(response.status);
    call.responseTitle = $scope.http_codes[response.status.toString()];
    call.responseInfo = "API call was successful.";
  }; 
  
  // default error callback
  $scope.showError = function(data){
    // parse data object
    var response = data.response;
    var id = data.callId;
    var call = $scope.api_calls[id];
    
    // fill in basic formatting
    call.response = JSON.stringify(response, null, 4);
    call.responseFormatted = $sce.trustAsHtml(Prism.highlight(call.response, Prism.languages.javascript));
    call.responseCode = response.status;
    call.responseClass = $scope.formatStatus(response.status);
    call.responseTitle = $scope.http_codes[response.status.toString()];
    
    // default info content
    call.responseInfo = "An error occurred, please check your request.";
    
    // try to get specific information for the info tab
    if(response.data && response.data.error){
      var error = response.data.error;
      call.responseInfo = JSON.stringify(response.data.error);
      // we have an error type, see if we can understand it
      if(error.type){
        // we know what entity exceptions are, print some information
        if(error.type == "EntityException"){
          call.responseInfo = "An error in the entity data has been detected. These are usually due to malformed requests or duplicates in unique ids. Below is the system description of the error.<br /><br/>"
        }
        // we know what transaction warnings are, print some information
        else if(error.type == "TransactionWarningException"){
          call.responseInfo = "A transaction warning has been found. Transaction warnings exist to prevent accidentally corrupt or duplicate data. Please verify your data. If you need to bypass, add '\"__ignoreWarnings\":true' to your data object. See <a href='https://help-loanpro.simnang.com/knowledge-base/api-bypassing-transactional-warnings/'>API - Bypassing Transaction Warnings</a> for more information. Warnings are listed below.<br/><br />";
        }
        
        // if we have warnings, print those
        if(response.data.warnings){
          call.responseInfo += "<pre>"+response.data.warnings.join("\r\n")+"</pre>";
        }
        // otherwise, print the general error message
        else{
          call.responseInfo += "<pre>"+error.message+"</pre>";
        }
      }
      // if we just have an error message, print that
      else if(error.message){
        if(error.message.value){
          call.responseInfo = "<pre>"+error.message.value+"</pre>";
        }
        else{
          call.responseInfo = "<pre>"+JSON.stringify(error.message)+"</pre>";
        }
      }
    }
    call.responseInfo = $sce.trustAsHtml(call.responseInfo);
  };
  
  // This is just for the status code parsing; it holds a reference of the various status codes that are used across websites
  $scope.http_codes = {'200' : 'OK','201' : 'Created','202' : 'Accepted','203' : 'Non-Authoritative Information','204' : 'No Content','205' : 'Reset Content','206' : 'Partial Content',
    '300' : 'Multiple Choices','301' : 'Moved Permanently','302' : 'Found','303' : 'See Other','304' : 'Not Modified','305' : 'Use Proxy','307' : 'Temporary Redirect',
    '400' : 'Bad Request','401' : 'Unauthorized','402' : 'Payment Required','403' : 'Forbidden','404' : 'Not Found','405' : 'Method Not Allowed','406' : 'Not Acceptable','407' : 'Proxy Authentication Required','408' : 'Request Timeout','409' : 'Conflict','410' : 'Gone','411' : 'Length Required','412' : 'Precondition Failed','413' : 'Request Entity Too Large','414' : 'Request-URI Too Long','415' : 'Unsupported Media Type','416' : 'Requested Range Not Satisfiable','417' : 'Expectation Failed',
    '500' : 'Internal Server Error','501' : 'Not Implemented','502' : 'Bad Gateway','503' : 'Service Unavailable','504' : 'Gateway Timeout','505' : 'HTTP Version Not Supported'
    };
  
}])
// this creates the auth-form directive for allowing credential changing at runtime
.directive('authForm',function(){
  return {
    template: '<h2>Authentication Form</h2><div>Tenant ID: <input type="number" ng-model="api_auth.tenant_id"/><br />API Key: <input type="password" ng-model="api_auth.api_token"/></div>'
  };
})
// this creates the response-form directive for showing responses
.directive('responseForm',function(){
  return {
    templateUrl: "response_form.html"
  };
})
// this creates the send-form directive for showing raw HTTP requests
.directive('sendForm', function(){
  return {
    templateUrl: 'send_request_form.html'
  };
});
/* Styles go here */
div{
  margin:10px 0px;
}

body{
  font-family: "Trebuchet MS", Helvetica, sans-serif;
  font-size: 11pt;
}

.status_ok:before,.status_warn:before, .status_error:before{
  content: " "attr(code)": "attr(title);
}
.status_ok:before,.status_warn:before, .status_error:before, .status_inprogress:before{
  font-size: 12pt;
  margin: 5px;
  padding: 5px 10px;
  border-radius: 10px;
  color: white;
  font-weight: bold;
}

.unreported:before{
  content: attr(title);
}

.status_ok:before{
  background-color:#3d3;
}

.status_warn:before{
  background-color:#ea2;
}

.status_error:before{
  background-color:#f22;
}

.status_inprogress:before{
  background-color:#33d;
  content: "In Progress...";
}

.response{
  border: 1px solid #333;
  background: #f6f6f6;
  border-radius: 10px;
  padding: 15px;
  margin: 5px;
}

.request{
  border: 1px solid #333;
  background-color:#f6f6f6;
  padding:10px;
  display: inline-block;
  border-radius: 10px;
  margin: 5px;
  width:98%;
  font-family: "Fira Mono", "DejaVu Sans Mono", Menlo, Consolas, "Liberation Mono", Monaco, "Lucida Console", monospace;
}
<div ng-hide="api_calls.length < 2 || api_calls[0].response == ''">
  <uib-tabset active="0" justified="true">
    <uib-tab ng-repeat="call in api_calls track by $index" heading='{{(call.title == "")? "Response " + ($index + 1) : call.title + " Response" }}'>
      <div><h2>
        {{(call.title == "")? "Response " + ($index + 1) : call.title + " Response" }}
        <span class="status_error unreported" title="Error" ng-show="call.unreportedErr==true" ng-hide="call.unreportedErr==false"></span>
        <span ng-class="call.responseClass" code="{{call.responseCode}}" title="{{call.responseTitle}}"></span>
      </h2></div>
      <uib-tabset class="response" active="Raw" justified="true">
        <uib-tab index="0" heading="Raw">{{call.response}}</uib-tab>
        <uib-tab index="1" heading="Formatted"><pre ng-bind-html="call.responseFormatted"></pre></uib-tab>
        <uib-tab index="2" heading="Info"><div ng-bind-html="call.responseInfo"></div></uib-tab>
      </uib-tabset>
    </uib-tab>
  </uib-tabset>
</div>

<div ng-hide="api_calls.length != 1 || api_calls[0].response == ''">
  <div ng-init="call = api_calls[0]">
    <h2 ng-hide="">{{(call.title == "")? "Response" : call.title + " Response" }}
          <span class="status_error unreported" title="Error" ng-show="call.unreportedErr==true" ng-hide="call.unreportedErr==false"></span>
          <span ng-class="call.responseClass" code="{{call.responseCode}}" title="{{call.responseTitle}}"></span>
    </h2>
  </div>
  <uib-tabset class="response" active="Raw" justified="true">
    <uib-tab index="0" heading="Raw">{{call.response}}</uib-tab>
    <uib-tab index="1" heading="Formatted"><pre ng-bind-html="call.responseFormatted"></pre></uib-tab>
    <uib-tab index="2" heading="Info"><div ng-bind-html="call.responseInfo"></div></uib-tab>
  </uib-tabset>
</div>
/* http://prismjs.com/download.html?themes=prism-coy&languages=css+clike+javascript+json&plugins=line-highlight+line-numbers */
var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function(e){var t=n.util.type(e);switch(t){case"Object":var a={};for(var r in e)e.hasOwnProperty(r)&&(a[r]=n.util.clone(e[r]));return a;case"Array":return e.map&&e.map(function(e){return n.util.clone(e)})}return e}},languages:{extend:function(e,t){var a=n.util.clone(n.languages[e]);for(var r in t)a[r]=t[r];return a},insertBefore:function(e,t,a,r){r=r||n.languages;var l=r[e];if(2==arguments.length){a=arguments[1];for(var i in a)a.hasOwnProperty(i)&&(l[i]=a[i]);return l}var o={};for(var s in l)if(l.hasOwnProperty(s)){if(s==t)for(var i in a)a.hasOwnProperty(i)&&(o[i]=a[i]);o[s]=l[s]}return n.languages.DFS(n.languages,function(t,n){n===r[e]&&t!=e&&(this[t]=o)}),r[e]=o},DFS:function(e,t,a,r){r=r||{};for(var l in e)e.hasOwnProperty(l)&&(t.call(e,l,e[l],a||l),"Object"!==n.util.type(e[l])||r[n.util.objId(e[l])]?"Array"!==n.util.type(e[l])||r[n.util.objId(e[l])]||(r[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,l,r)):(r[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,null,r)))}},plugins:{},highlightAll:function(e,t){var a={callback:t,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};n.hooks.run("before-highlightall",a);for(var r,l=a.elements||document.querySelectorAll(a.selector),i=0;r=l[i++];)n.highlightElement(r,e===!0,a.callback)},highlightElement:function(t,a,r){for(var l,i,o=t;o&&!e.test(o.className);)o=o.parentNode;o&&(l=(o.className.match(e)||[,""])[1].toLowerCase(),i=n.languages[l]),t.className=t.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,o=t.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var s=t.textContent,u={element:t,language:l,grammar:i,code:s};if(n.hooks.run("before-sanity-check",u),!u.code||!u.grammar)return u.code&&(u.element.textContent=u.code),n.hooks.run("complete",u),void 0;if(n.hooks.run("before-highlight",u),a&&_self.Worker){var g=new Worker(n.filename);g.onmessage=function(e){u.highlightedCode=e.data,n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(u.element),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},g.postMessage(JSON.stringify({language:u.language,code:u.code,immediateClose:!0}))}else u.highlightedCode=n.highlight(u.code,u.grammar,u.language),n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(t),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},highlight:function(e,t,r){var l=n.tokenize(e,t);return a.stringify(n.util.encode(l),r)},tokenize:function(e,t){var a=n.Token,r=[e],l=t.rest;if(l){for(var i in l)t[i]=l[i];delete t.rest}e:for(var i in t)if(t.hasOwnProperty(i)&&t[i]){var o=t[i];o="Array"===n.util.type(o)?o:[o];for(var s=0;s<o.length;++s){var u=o[s],g=u.inside,c=!!u.lookbehind,h=!!u.greedy,f=0,d=u.alias;if(h&&!u.pattern.global){var p=u.pattern.toString().match(/[imuy]*$/)[0];u.pattern=RegExp(u.pattern.source,p+"g")}u=u.pattern||u;for(var m=0,y=0;m<r.length;y+=r[m].length,++m){var v=r[m];if(r.length>e.length)break e;if(!(v instanceof a)){u.lastIndex=0;var b=u.exec(v),k=1;if(!b&&h&&m!=r.length-1){if(u.lastIndex=y,b=u.exec(e),!b)break;for(var w=b.index+(c?b[1].length:0),_=b.index+b[0].length,P=m,A=y,j=r.length;j>P&&_>A;++P)A+=r[P].length,w>=A&&(++m,y=A);if(r[m]instanceof a||r[P-1].greedy)continue;k=P-m,v=e.slice(y,A),b.index-=y}if(b){c&&(f=b[1].length);var w=b.index+f,b=b[0].slice(f),_=w+b.length,x=v.slice(0,w),O=v.slice(_),S=[m,k];x&&S.push(x);var N=new a(i,g?n.tokenize(b,g):b,d,b,h);S.push(N),O&&S.push(O),Array.prototype.splice.apply(r,S)}}}}}return r},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,l=0;r=a[l++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var l={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==l.type&&(l.attributes.spellcheck="true"),e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,"&quot;")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+"</"+l.tag+">"},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,l=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),l&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,!document.addEventListener||n.manual||r.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
Prism.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<style[\w\W]*?>)[\w\W]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag));
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/};
Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<script[\w\W]*?>)[\w\W]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript;
Prism.languages.json={property:/"(?:\\.|[^\\"])*"(?=\s*:)/gi,string:/"(?!:)(?:\\.|[^\\"])*"(?!:)/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/g,punctuation:/[{}[\]);,]/g,operator:/:/g,"boolean":/\b(true|false)\b/gi,"null":/\bnull\b/gi},Prism.languages.jsonp=Prism.languages.json;
!function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){for(var o,a=n.replace(/\s+/g,"").split(","),d=+e.getAttribute("data-line-offset")||0,l=r()?parseInt:parseFloat,c=l(getComputedStyle(e).lineHeight),s=0;o=a[s++];){o=o.split("-");var u=+o[0],m=+o[1]||u,h=document.createElement("div");h.textContent=Array(m-u+2).join(" \n"),h.setAttribute("aria-hidden","true"),h.className=(i||"")+" line-highlight",t(e,"line-numbers")||(h.setAttribute("data-start",u),m>u&&h.setAttribute("data-end",m)),h.style.top=(u-d-1)*c+"px",t(e,"line-numbers")?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML="&nbsp;<br />&nbsp;",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function(e){var t=e.element.parentNode,r=t&&t.getAttribute("data-line");t&&r&&/pre/i.test(t.nodeName)&&(clearTimeout(o),n(t,r),o=setTimeout(i,1))}),window.addEventListener&&window.addEventListener("hashchange",i)}}();
!function(){"undefined"!=typeof self&&self.Prism&&self.document&&Prism.hooks.add("complete",function(e){if(e.code){var t=e.element.parentNode,s=/\s*\bline-numbers\b\s*/;if(t&&/pre/i.test(t.nodeName)&&(s.test(t.className)||s.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){s.test(e.element.className)&&(e.element.className=e.element.className.replace(s,"")),s.test(t.className)||(t.className+=" line-numbers");var n,a=e.code.match(/\n(?!$)/g),l=a?a.length+1:1,r=new Array(l+1);r=r.join("<span></span>"),n=document.createElement("span"),n.setAttribute("aria-hidden","true"),n.className="line-numbers-rows",n.innerHTML=r,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(n)}}})}();
/* http://prismjs.com/download.html?themes=prism-coy&languages=css+clike+javascript+json&plugins=line-highlight+line-numbers */
/**
 * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML
 * Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics);
 * @author Tim  Shedor
 */

code[class*="language-"],
pre[class*="language-"] {
	color: black;
	background: none;
	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
	text-align: left;
	white-space: pre;
	word-spacing: normal;
	word-break: normal;
	word-wrap: normal;
	line-height: 1.5;

	-moz-tab-size: 4;
	-o-tab-size: 4;
	tab-size: 4;

	-webkit-hyphens: none;
	-moz-hyphens: none;
	-ms-hyphens: none;
	hyphens: none;
}

/* Code blocks */
pre[class*="language-"] {
	position: relative;
	margin: .5em 0;
	box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
	border-left: 10px solid #358ccb;
	background-color: #fdfdfd;
	background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
	background-size: 3em 3em;
	background-origin: content-box;
	overflow: visible;
	padding: 0;
}

code[class*="language"] {
	max-height: inherit;
	height: 100%;
	padding: 0 1em;
	display: block;
	overflow: auto;
}

/* Margin bottom to accomodate shadow */
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
	background-color: #fdfdfd;
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
	margin-bottom: 1em;
}

/* Inline code */
:not(pre) > code[class*="language-"] {
	position: relative;
	padding: .2em;
	border-radius: 0.3em;
	color: #c92c2c;
	border: 1px solid rgba(0, 0, 0, 0.1);
	display: inline;
	white-space: normal;
}

pre[class*="language-"]:before,
pre[class*="language-"]:after {
	content: '';
	z-index: -2;
	display: block;
	position: absolute;
	bottom: 0.75em;
	left: 0.18em;
	width: 40%;
	height: 20%;
	max-height: 13em;
	box-shadow: 0px 13px 8px #979797;
	-webkit-transform: rotate(-2deg);
	-moz-transform: rotate(-2deg);
	-ms-transform: rotate(-2deg);
	-o-transform: rotate(-2deg);
	transform: rotate(-2deg);
}

:not(pre) > code[class*="language-"]:after,
pre[class*="language-"]:after {
	right: 0.75em;
	left: auto;
	-webkit-transform: rotate(2deg);
	-moz-transform: rotate(2deg);
	-ms-transform: rotate(2deg);
	-o-transform: rotate(2deg);
	transform: rotate(2deg);
}

.token.comment,
.token.block-comment,
.token.prolog,
.token.doctype,
.token.cdata {
	color: #7D8B99;
}

.token.punctuation {
	color: #5F6364;
}

.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.function-name,
.token.constant,
.token.symbol,
.token.deleted {
	color: #c92c2c;
}

.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.function,
.token.builtin,
.token.inserted {
	color: #2f9c0a;
}

.token.operator,
.token.entity,
.token.url,
.token.variable {
	color: #a67f59;
	background: rgba(255, 255, 255, 0.5);
}

.token.atrule,
.token.attr-value,
.token.keyword,
.token.class-name {
	color: #1990b8;
}

.token.regex,
.token.important {
	color: #e90;
}

.language-css .token.string,
.style .token.string {
	color: #a67f59;
	background: rgba(255, 255, 255, 0.5);
}

.token.important {
	font-weight: normal;
}

.token.bold {
	font-weight: bold;
}
.token.italic {
	font-style: italic;
}

.token.entity {
	cursor: help;
}

.namespace {
	opacity: .7;
}

@media screen and (max-width: 767px) {
	pre[class*="language-"]:before,
	pre[class*="language-"]:after {
		bottom: 14px;
		box-shadow: none;
	}

}

/* Plugin styles */
.token.tab:not(:empty):before,
.token.cr:before,
.token.lf:before {
	color: #e0d7d1;
}

/* Plugin styles: Line Numbers */
pre[class*="language-"].line-numbers {
	padding-left: 0;
}

pre[class*="language-"].line-numbers code {
	padding-left: 3.8em;
}

pre[class*="language-"].line-numbers .line-numbers-rows {
	left: 0;
}

/* Plugin styles: Line Highlight */
pre[class*="language-"][data-line] {
	padding-top: 0;
	padding-bottom: 0;
	padding-left: 0;
}
pre[data-line] code {
	position: relative;
	padding-left: 4em;
}
pre .line-highlight {
	margin-top: 0;
}

pre[data-line] {
	position: relative;
	padding: 1em 0 1em 3em;
}

.line-highlight {
	position: absolute;
	left: 0;
	right: 0;
	padding: inherit 0;
	margin-top: 1em; /* Same as .prism’s padding-top */

	background: hsla(24, 20%, 50%,.08);
	background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));

	pointer-events: none;

	line-height: inherit;
	white-space: pre;
}

	.line-highlight:before,
	.line-highlight[data-end]:after {
		content: attr(data-start);
		position: absolute;
		top: .4em;
		left: .6em;
		min-width: 1em;
		padding: 0 .5em;
		background-color: hsla(24, 20%, 50%,.4);
		color: hsl(24, 20%, 95%);
		font: bold 65%/1.5 sans-serif;
		text-align: center;
		vertical-align: .3em;
		border-radius: 999px;
		text-shadow: none;
		box-shadow: 0 1px white;
	}

	.line-highlight[data-end]:after {
		content: attr(data-end);
		top: auto;
		bottom: .4em;
	}

pre.line-numbers {
	position: relative;
	padding-left: 3.8em;
	counter-reset: linenumber;
}

pre.line-numbers > code {
	position: relative;
}

.line-numbers .line-numbers-rows {
	position: absolute;
	pointer-events: none;
	top: 0;
	font-size: 100%;
	left: -3.8em;
	width: 3em; /* works for line-numbers below 1000 lines */
	letter-spacing: -1px;
	border-right: 1px solid #999;

	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;

}

	.line-numbers-rows > span {
		pointer-events: none;
		display: block;
		counter-increment: linenumber;
	}

		.line-numbers-rows > span:before {
			content: counter(linenumber);
			color: #999;
			display: block;
			padding-right: 0.8em;
			text-align: right;
		}
<div>
  <div ng-hide="api_calls.length < 2">
  <uib-tabset active="0" justified="true">
    <uib-tab ng-repeat="call in api_calls track by $index" heading='{{(call.title == "")? "Request " + ($index + 1) : call.title + " Request" }}'>
      <h2>{{(call.title == "")? "Request " + ($index + 1) : call.title + " Request" }} </h2>
      <pre class="request">{{call.method + " " + basePath + call.uri + ((serializeQuery(call.query))?"?" + serializeQuery(call.query) : "")}} HTTP/1.1
Host: {{server}}
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Autopal-Instance-ID: {{api_auth.tenant_id}}
Authorization: Bearer {{api_auth.api_token}}
Connection: keep-alive
{{ ((dataLength($index))? "Content-Type: application/json;charset=UTF-8\r\nContent-Length: " + dataLength($index) + "\r\n\r\n" : "") }}{{ dataStr($index) }}
</pre>
      </uib-tab>
  </uib-tabset>
  </div>
  <div ng-hide="api_calls.length != 1">
    <h2>{{(call.title == "")? "Request" : call.title + " Request" }} </h2>
    <pre class="request">{{call.method + " " + basePath + call.uri + ((serializeQuery(call.query))?"?" + serializeQuery(call.query) : "")}} HTTP/1.1
Host: {{server}}
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Autopal-Instance-ID: {{api_auth.tenant_id}}
Authorization: Bearer {{api_auth.api_token}}
Connection: keep-alive
{{ ((dataLength())? "Content-Type: application/json;charset=UTF-8\r\nContent-Length: " + dataLength() + "\r\n\r\n" : "") }}{{ dataStr() }}
</pre>
  </div>
  <button ng-click="sendAPIRequests();">Send</button>
</div>

app.controller('requestController', ['$scope','$http', '$sce', '$controller', function($scope,$http, $sce, $controller) {
  $controller('loanproClient', {$scope: $scope, $http: $http, $sce: $sce});
  
  // Change the following to match your credentials
  $scope.api_auth.tenant_id = 5200243;
  $scope.api_auth.api_token = "cc0199330033f963007b07e75f1b7fb6b7025887";
  
  $scope.queueAPICall({
    uri:"Loans/Autopal.Search()",
    method: "POST",
    data: {
      "query": {
        "bool": {
          "must": [
            {
              "bool": {
                "must": [
                  {
                    "query_string": {
                      "query": "*100*",
                      "fields": [
                        "title",
                        "displayId",
                        "collateral.vin",
                        "collateral.color",
                        "collateral.gpsCode",
                        "collateral.licensePlate",
                        "collateralInfo",
                        "primaryCustomerName",
                        "secondaryCustomerName",
                        "primaryCustomerAddress.city",
                        "primaryCustomerAddress.zipcode",
                        "primaryCustomerAddress.state",
                        "secondaryCustomerAddress.city",
                        "secondaryCustomerAddress.zipcode",
                        "secondaryCustomerAddress.state",
                        "primaryPhone",
                        "secondaryPhone",
                        "loanInsurance.companyName",
                        "loanInsurance.insured",
                        "loanInsurance.policyNumber",
                        "loanInsurance.agentName",
                        "customFields"
                      ]
                    }
                  },
                  {
                    "nested": {
                      "path": "customers",
                      "query": {
                        "bool": {
                          "should": [
                            {
                              "query_string": {
                                "query": "*John*",
                                "fields": [
                                  "firstName",
                                  "middleName",
                                  "lastName",
                                  "email",
                                  "ssn",
                                  "customId",
                                  "accessUserName",
                                  "companyName"
                                ]
                              }
                            }
                          ]
                        }
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      },
      "aggs": {
        "sum_loanamount": {
          "sum": {
            "field": "loanAmount"
          }
        },
        "avg_loanamount": {
          "avg": {
            "field": "loanAmount"
          }
        },
        "sum_payoff": {
          "sum": {
            "field": "payoff"
          }
        },
        "avg_payoff": {
          "avg": {
            "field": "payoff"
          }
        },
        "avg_loanage": {
          "avg": {
            "field": "loanAge"
          }
        },
        "avg_dayspastdue": {
          "avg": {
            "field": "daysPastDue"
          }
        },
        "sum_amountdue": {
          "sum": {
            "field": "amountDue"
          }
        },
        "avg_amountdue": {
          "avg": {
            "field": "amountDue"
          }
        },
        "sum_principalbalance": {
          "sum": {
            "field": "principalBalance"
          }
        },
        "avg_principalbalance": {
          "avg": {
            "field": "principalBalance"
          }
        },
        "avg_loanrecency": {
          "avg": {
            "field": "loanRecency"
          }
        },
        "sum_lastpaymentamount": {
          "sum": {
            "field": "lastPaymentAmount"
          }
        },
        "avg_lastpaymentamount": {
          "avg": {
            "field": "lastPaymentAmount"
          }
        },
        "sum_nextpaymentamount": {
          "sum": {
            "field": "nextPaymentAmount"
          }
        },
        "avg_nextpaymentamount": {
          "avg": {
            "field": "nextPaymentAmount"
          }
        }
      }
    },
    query: {
      $top:25,
      $start:0,
      $orderby:"id asc",
      $expand: "Collateral,Customers"
    }
  });
  
}]);