Odyssey
AppAdm.prg
1 <?php
2 /**
3  * @package AppAdm.prg
4  * Shows loans from admin
5  */
6 
7 require_once(dirname(__FILE__) . "/AppAdm.data");
8 
9 $parameters = array("operation" => "", "searchIn" => "", "lookFor" => "", "withStatus" => "", "rangeType" => "", "fromDate" => "", "toDate" => "",
10  "limit" => "", "offset" => "", "sortBy" => "", "userId" => "", "loanids" => "");
11 $string = array("filter" => FILTER_SANITIZE_STRING);
12 $json = array("filter" => FILTER_DEFAULT);
13 HCU_ImportVars($parameters, "", array("operation" => $string, "searchIn" => $string, "lookFor" => $string, "withStatus" => $string, "rangeType" => $string,
14  "loanids" => $json, "fromDate" => $string, "toDate" => $string, "limit" => $string, "offset" => $string,
15  "sortBy" => $string, "userId" => $string, "lockSetting" => $string, "email" => $string, "password" => $string,
16  "confirm" => $string));
17 
18 $operation = HCU_array_key_value("operation", $parameters);
19 $operation = $operation === false ? "" : trim($operation);
20 if ($operation != "") {
21  switch($operation) {
22  case "readLoanApps":
23  $returnArray = ReadLoanApps($dbh, $Cu, $parameters, false);
24  break;
25  case "deleteLoans":
26  $returnArray = DeleteLoanApps($dbh, $Cu, $parameters);
27  break;
28  case "readApplicantSearch":
29  $returnArray = ReadApplicantSearch($dbh, $Cu, $parameters);
30  break;
31  case "readApplicant":
32  $returnArray = ReadApplicant($dbh, $Cu, $parameters);
33  break;
34  case "saveApplicant":
35  $returnArray = SaveApplicant($dbh, $Cu, $parameters);
36  break;
37  default: // Won't get here
38  $returnArray = array("status" => "999", "error" => "Operation not specified: '$operation'");
39  }
40 
41  header('Content-type: application/json');
42  print HCU_JsonEncode($returnArray);
43 } else {
44  PrintPage("$menu_link?ft=$ft");
45 }
46 exit;
47 
48 /**************************
49 JAVASCRIPT CODE
50 **************************/
51 
52 /**
53  * function PrintPage($self)
54  * Print out the page
55  *
56  * @param $self -- the url to this page.
57  */
58 function PrintPage($self)
59 {
60  // 05-19 when we gave AppAdm.prg it's own flow and its own exit, we basically hijacked the
61  // functionality of main.prg that output the metisMenu command and the JS logout timer.
62  // Within PrintPage we longer has access to these variables. Globals should be
63  // discouraged, but we need them here to fix the problem.
64  global $SYSENV;
65  global $frm_login;
66  global $menu_link;
67 ?>
68  <script type="text/javascript">
69  <?php // Library javascript functions
70  getShowWaitFunctions(); ?>
71 
72  <?php
73  /**
74  * function InitTabs()
75  * Sets up the tabs.
76  */
77  ?>
78  function InitTabs() {
79 
80  <?php
81  /**
82  * Anonymous function
83  * Click event to switch to the tab whence clicked.
84  */
85  ?>
86  $(".tabTitles").on("click", "[data-name]:not(.selected)", function() {
87  var name = $(this).attr("data-name");
88 
89  switch (name) {
90  case "loanApps":
91  ActivateLoanApps();
92  break;
93  case "applicant":
94  ActivateApplicantTab();
95  break;
96  }
97  var prevThis = $(".tabTitles [data-name].selected");
98  var prevName = $(prevThis).attr("data-name");
99  $(prevThis).removeClass("selected");
100  $(this).addClass("selected");
101  $(".tabContents[data-name='" + prevName + "']").hide();
102  $(".tabContents[data-name='" + name + "']").show();
103  });
104 
105  InitApplicant();
106  InitLoanApps();
107  ActivateApplicantTab();
108  }
109 
110  <?php
111  /**
112  * function ActivateApplicantTab()
113  * This sets up the validator and other stuff when activated.
114  */
115  ?>
116  function ActivateApplicantTab() {
117 
118  SetupApplicantValidation("applicantFullForm");
119 
120  $("#searchInApplicantDDL").data("kendoDropDownList").select(0);
121  $("[name='lookForApplicant']").val(null);
122  $("#applicantSearchDiv").show();
123  $("#applicantGridDiv").hide();
124  $("#applicantManagementDiv").hide();
125 
126  <?php // Also reset this to search when coming back. ?>
127  $("#applicantFullForm").data("action", "search");
128  }
129 
130  function SetupApplicantValidation(id) {
131  $.homecuValidator.setup({formValidate: id, formStatusField: "applicantFormValidateDiv", homecuCustomRules: {
132  <?php
133  /**
134  * function validatelookfor
135  * This validates the search text input when username is selected in the searchInDDL.
136  * All other searchInDDL options use the $.homecuValidator pattern matching.
137  */
138  ?>
139  validatelookfor: function(input) {
140  if (!$(input).is("[name='lookForApplicant']")) {
141  return true;
142  }
143  var searchIn = $("#searchInApplicantDDL").data("kendoDropDownList").value().trim();
144  var value = $(input).val().trim();
145 
146  if (searchIn != "" && value == "") {
147  $(input).attr("data-validatelookfor-msg", "Search string is required.");
148  return false;
149  }
150 
151  switch(searchIn) {
152  case "username":
153  if (value.search(/\"/) >= 0 ) {
154  $(input).attr("data-validatelookfor-msg", "Username contains invalid characters.");
155  return false;
156  }
157  break;
158  }
159 
160  return true;
161  },
162  matchPassword: function(input) {
163  if (!$(input).is("[name='confirm']")) {
164  return true;
165  }
166  var password = $("[name='password']").val().trim();
167  var confirm = $(input).val().trim();
168 
169  if (password != "" && password != confirm) {
170  $(input).attr("data-matchPassword-msg", "Passwords don't match.");
171  return false;
172  }
173 
174  return true;
175  },
176  password: function(input) {
177  if (!$(input).is("[name='password']")) {
178  return true;
179  }
180 
181  var password = $(input).val().trim();
182  var length = password.length;
183 
184  <?php // If the password is not set, then don't validate it. It isn't being changed. ?>
185  if (password == "") {
186  return true;
187  }
188 
189  if (length < 6 || length > 20) {
190  $(input).attr("data-password-msg", "Password must be from 6 to 20 characters long.");
191  return false;
192  }
193 
194  if (!/\d/.test(password) && !/\D/.test(password)) {
195  $(input).attr("data-password-msg", "Password must contain both number and letter characters.");
196  return false;
197  }
198 
199  if (/"/.test(password)) {
200  $(input).attr("data-password-msg", "There are invalid characters in the password.");
201  return false;
202  }
203  return true;
204  }
205  }});
206  }
207 
208  <?php
209  /**
210  * function InitApplicant()
211  * Initializes the applicant tab.
212  */
213  ?>
214  function InitApplicant() {
215  var template = $("#applicantTemplate").html();
216  $(".tabContents[data-name='applicant']").html(template);
217 
218  InitApplicantSearchBar();
219  InitApplicantGrid();
220  }
221 
222  <?php
223  /**
224  * function InitApplicantSearchBar()
225  * This initializes the applicant search bar.
226  */
227  ?>
228  function InitApplicantSearchBar() {
229 
230  <?php
231  /**
232  * @var searchInApplicantDDL
233  * This is a dropdownlist for selecting what to search for.
234  */
235  ?>
236  $("#searchInApplicantDDL").kendoDropDownList({
237  dataSource: <?php echo HCU_JsonEncode(GetApplicantSearchInData()); ?>,
238  dataTextField: "text",
239  dataValueField: "value",
240  change: function() {
241  var searchIn = this.value();
242 
243  var lookFor = $("[name='lookForApplicant']");
244  $(lookFor).data("searchIn", searchIn);
245 
246  switch(searchIn) {
247  case "email":
248  $(lookFor).attr("homecu-match", "email");
249  $(lookFor).attr("data-homecuCustomMatch-msg", "Email address is invalid.");
250  break;
251  case "account":
252  $(lookFor).attr("homecu-match", "number");
253  $(lookFor).attr("data-homecuCustomMatch-msg", "Account must be a number.");
254  break;
255  case "username":
256  case "":
257  default:
258  $(lookFor).attr("homecu-match", "");
259  break;
260  }
261  }
262  });
263 
264  <?php
265  /**
266  * This submits the form.
267  */
268  ?>
269  $("#applicantFullForm").on("submit", function(e) {
270 
271  var applicantSubmitSwitch = $("#applicantFullForm").data("action");
272  if (applicantSubmitSwitch == "search") {
273  if ($.homecuValidator.validate()) {
274  $("#applicantGrid").data("kendoGrid").dataSource.query({page: 1, pageSize: pageSize});
275  $(".applicantManagementDiv").hide();
276  $(".applicantGridDiv").show();
277  <?php // Make sure to reset the page number when the filter changes. ?>
278  }
279  } else if (applicantSubmitSwitch == "save") {
280  if ($.homecuValidator.validate()) {
281  var parameters = {};
282  parameters.operation = "saveApplicant";
283 
284  parameters.userId = $(".userIdLabel").text().trim();
285 
286  parameters.lockSetting = "noChange";
287  if ($(".lockAccount").hasClass("currentUnlocked")) {
288  if ($(".lockAccount").hasClass("originalUnlocked")) {
289  parameters.lockSetting = "noChange";
290  } else {
291  parameters.lockSetting = "setUnlocked";
292  }
293  } else if ($(".lockAccount").hasClass("currentLocked")) {
294  if ($(".lockAccount").hasClass("originalLocked")) {
295  parameters.lockSetting = "noChange";
296  } else {
297  parameters.lockSetting = "setLocked";
298  }
299  }
300 
301  if ($("[name='password']:visible").length > 0) {
302  parameters.password = $("[name='password']").val().trim();
303  } else {
304  parameters.password = "";
305  }
306 
307  if ($("[name='confirm']:visible").length > 0) {
308  parameters.confirm = $("[name='confirm']").val().trim();
309  } else {
310  parameters.confirm = "";
311  }
312 
313  if ($("[name='email']:visible").length > 0) {
314  parameters.email = $("[name='email']").val().trim();
315  } else {
316  parameters.email = "";
317  }
318 
319  viewDs.read(parameters);
320  }
321  }
322 
323  e.preventDefault();
324  return false;
325  });
326 
327  <?php // When "enter" happens on an input, make sure that it submits correctly. ?>
328  $("#applicantFullForm").on("focus", "[name='lookForApplicant']", function() {
329  $("#applicantFullForm").data("action", "search");
330  });
331 
332  $("#applicantFullForm").on("focus", "[name='email'], [name='confirm'], [name='password']", function() {
333  $("#applicantFullForm").data("action", "save");
334  });
335 
336  $("#applicantFullForm").on("click", ".lockAccount a", function() {
337  $("#applicantFullForm").data("action", "save");
338 
339  var lockAccount = $(this).closest(".lockAccount");
340  if ($(lockAccount).hasClass("currentLocked")) {
341  $(lockAccount).removeClass("currentLocked").addClass("currentUnlocked").removeClass("notRealChange");
342  } else {
343  $(lockAccount).removeClass("currentUnlocked").addClass("currentLocked").removeClass("notRealChange");
344  }
345  return false;
346  });
347 
348  $("#applicantFullForm").on("click", "#applicantSearchBtn", function() {
349  $("#applicantFullForm").data("action", "search");
350  $("#applicantFullForm").submit();
351  return false;
352  });
353 
354  $("#applicantFullForm").on("click", "#applicantSaveBtn", function() {
355  $("#applicantFullForm").data("action", "save");
356  $("#applicantFullForm").submit();
357  return false;
358  });
359 
360  $("#applicantFullForm").on("click", ".gotoLoans", function() {
361 
362  var prevThis = $(".tabTitles [data-name].selected");
363  var prevName = $(prevThis).attr("data-name");
364  var name = "loanApps";
365  $(prevThis).removeClass("selected");
366  $(".tabTitles [data-name='" + name + "']").addClass("selected");
367  $(".tabContents[data-name='" + prevName + "']").hide();
368  $(".tabContents[data-name='" + name + "']").show();
369 
370  ActivateLoanApps($(".userIdLabel").text().trim());
371  return false;
372  });
373  }
374 
375  <?php
376  /**
377  * function InitApplicantGrid()
378  * This initializes the applicant grid and also a datasource.
379  */
380  ?>
381  var viewDs = null;
382  function InitApplicantGrid() {
383  <?php
384  /**
385  * @var grid
386  * this is the grid for the applicant grid.
387  */
388  ?>
389  var grid = $("#applicantGrid").kendoGrid({
390  autoBind: false,
391  dataSource: {
392  transport: {
393  read: {
394  url: "<?php echo $self; ?>&operation=readApplicantSearch",
395  dataType: "json",
396  type: "POST"
397  },
398  <?php
399  /**
400  * function parameterMap
401  * Read:
402  * - Applies the parameters in the search bar to the data call.
403  * Delete:
404  * - Adds all the checked records to the loanids.
405  * - Restores the search bar to the results currently shown in the grid.
406  * - Applies the parameters in the search bar to the data call.
407  */
408  ?>
409  parameterMap: function(data, type) {
410  showWaitWindow();
411 
412  data.lookFor = $("[name='lookForApplicant']").val().trim();
413  data.searchIn = $("#searchInApplicantDDL").data("kendoDropDownList").value();
414 
415  <?php // Sort will be custom as well. ?>
416  delete data.sort;
417 
418  <?php // Pagination ?>
419  data.limit = data.pageSize;
420  data.offset = data.skip;
421  delete data.pageSize;
422  delete data.skip;
423  delete data.page;
424  delete data.take;
425 
426  return data;
427  }
428  },
429  schema: {
430  model: {
431  id: "lnId",
432  fields: {
433  lnId: {type: "number"},
434  email: {type: "string"},
435  failedAttempts: {type: "number"},
436  loginType: {type: "string"},
437  username: {type: "string"},
438  accountnumber: {type: "string"}
439  }
440  },
441  data: "data",
442  total: "total",
443  <?php
444  /**
445  * function parse
446  * Checks the results of the data call.
447  * If failure, show error.
448  * If successful with info, show info.
449  */
450  ?>
451  parse: function (data) {
452  hideWaitWindow();
453 
454  if (data.status != "000") {
455  $.homecuValidator.displayMessage(data.error, $.homecuValidator.settings.statusError);
456  } else if (data.info != null) {
457  $.homecuValidator.displayMessage(data.info, $.homecuValidator.settings.statusInfo);
458  }
459 
460  return data.gridData;
461  }
462  },
463  serverSorting: true,
464  serverPaging: true,
465  pageSize: pageSize,
466  sortable: false
467  },
468  columns: [
469  {template: "<a href='\\#' class='viewBtn'>View</a>", headerTemplate: ""},
470  {field: "email", headerTemplate: "Email"},
471  {field: "loginType", headerTemplate: "Login Type"},
472  {field: "failedAttempts", headerTemplate: "Failed Attempts"},
473  {field: "accountnumber", headerTemplate: "Account #"},
474  {field: "username", headerTemplate: "Username"}
475  ],
476  noRecords: {
477  template: "<tr class='noRecordsDiv'><td colspan='4'>No Records Found</td></tr>"
478  },
479  scrollable: false,
480  sortable: false,
481  pageable: {
482  alwaysVisible: false <?php // Do not show pagination when there are 30 or less results. ?>
483  }
484  }).data("kendoGrid");
485 
486  <?php
487  /**
488  * @var viewDs
489  * This creates a datasource for usage when viewing/saving an applicant.
490  */
491  ?>
492  viewDs = new kendo.data.DataSource({
493  transport: {
494  read: {
495  url: "<?php echo $self; ?>",
496  dataType: "json",
497  type: "POST",
498  data: {
499  operation: "readApplicant"
500  }
501  },
502  parameterMap: function(data, type) {
503  showWaitWindow();
504 
505  return data;
506  }
507  },
508  schema: {
509  parse: function (data) {
510  hideWaitWindow();
511 
512  if (data.status != "000") {
513  $.homecuValidator.displayMessage(data.error, $.homecuValidator.settings.statusError);
514  } else if (data.info != null) {
515  $.homecuValidator.displayMessage(data.info, $.homecuValidator.settings.statusInfo);
516  }
517 
518  if (data.type == "read") {
519 
520  var template = kendo.template($("#applicantMaintenanceTemplate").html());
521  template = template(data.applicantData);
522 
523  $(".applicantManagementDiv").html(template);
524 
525  $(".applicantGridDiv").hide();
526  $(".applicantManagementDiv").show();
527 
528  $("#applicantFullForm").data("action", "save");
529  <?php // I'm also assuming that an "enter" at this point means update. ?>
530  SetupApplicantValidation("applicantFullForm");
531  }
532 
533  return [];
534  }
535  }
536  });
537 
538  $("#applicantGrid").on("click", ".viewBtn", function() {
539  var grid = $("#applicantGrid").data("kendoGrid");
540  var tr = $(this).closest("tr");
541  var dataItem = grid.dataItem($(tr));
542 
543  viewDs.read({userId: dataItem.lnId});
544  });
545  }
546 
547  <?php
548  /**
549  * function ActivateLoanApps(userId)
550  *
551  * @param userId -- optional userId to show loans for that user.
552  * Code to execute when loan app tab is shown.
553  */
554  ?>
555  function ActivateLoanApps(userId) {
556  $.homecuValidator.setup({formValidate: "appLoanSearchForm", formStatusField: "appLoanFormValidateDiv", homecuCustomRules: {
557 
558  <?php
559  /**
560  * function validatelookfor
561  * This validates the search text input when name or ssn is selected in the searchInDDL.
562  * All other searchInDDL options use the $.homecuValidator pattern matching.
563  */
564  ?>
565  validatelookfor: function(input) {
566  if (!$(input).is("[name='lookFor']")) {
567  return true;
568  }
569  var searchIn = $(input).data("searchIn");
570  searchIn = searchIn == null ? "" : searchIn.trim();
571  var value = $(input).val().trim();
572 
573  if (searchIn != "" && value == "") {
574  $(input).attr("data-validatelookfor-msg", "Search string is required.");
575  return false;
576  }
577 
578  switch(searchIn) {
579  case "name":
580  if (value.search(/\"/) >= 0 ) {
581  $(input).attr("data-validatelookfor-msg", "Name contains invalid characters.");
582  return false;
583  }
584  break;
585  case "ssn":
586  var allNbrs = /^\d*$/;
587  var ssnTest = /^\d{3}-\d{2}-\d{4}$/;
588  if (allNbrs.test(value) && value.length == 9) {
589  value = (value.substr(0,3) + '-' + value.substr(3,2) + '-' + value.substr(5,4));
590  }
591  if (!ssnTest.test(value)) {
592  $(input).attr("data-validatelookfor-msg", "SSN has invalid format.");
593  return false;
594  }
595 
596  $(input).val(value);
597  break;
598  }
599 
600  return true;
601  }
602  }});
603 
604  $("#searchInDDL").data("kendoDropDownList").value("");
605  $("#lookForDiv").hide();
606  $("[name='lookFor']").val(null);
607  $("#statusDDL").data("kendoDropDownList").value("");
608  $("#rangeTypeDDL").data("kendoDropDownList").value("");
609  $("#fromToSearch").hide();
610  $("[name='fromDate']").data("kendoDatePicker").value(null);
611  $("[name='toDate']").data("kendoDatePicker").value(null);
612 
613  if (userId == null) {
614  $("#forUserIdMsg").hide();
615  $("#loanAppGrid").data("kendoGrid").dataSource.read();
616  } else {
617  $("#forUserIdMsg span").text(userId);
618  $("#forUserIdMsg").show();
619  $("#loanAppGrid").data("kendoGrid").dataSource.read({userId: userId});
620  }
621 
622  }
623 
624  <?php
625  /**
626  * function InitLoanApps()
627  * Initializes the loan app tab.
628  */
629  ?>
630  function InitLoanApps() {
631 
632  var template = $("#loanAppTemplate").html();
633  $(".tabContents[data-name='loanApps']").html(template);
634 
635  InitLoanAppGrid();
636  InitLoanAppSearchBar();
637  InitLoanAppClickEvents();
638  }
639 
640  <?php
641  /**
642  * function InitLoanAppSearchBar()
643  * Initializes the search bar.
644  */
645  ?>
646  function InitLoanAppSearchBar() {
647 
648  <?php
649  /**
650  * @var fromDatePicker
651  * For setting the from date in a range.
652  */
653  ?>
654  var fromDatePicker = $("[name='fromDate']").kendoDatePicker({
655  format: "MM/dd/yyyy" <?php // Add zeroes so that MTB looks okay. ?>
656  }).data("kendoDatePicker");
657 
658  <?php
659  /**
660  * @var toDatePicker
661  * For setting the to date in a range.
662  */
663  ?>
664  var toDatePicker = $("[name='toDate']").kendoDatePicker({
665  format: "MM/dd/yyyy" <?php // Add zeroes so that MTB looks okay. ?>
666  }).data("kendoDatePicker");
667 
668  <?php
669  /**
670  * @var rangeTypeDDL
671  * For filtering on a range.
672  * If on "select...", from and to date pickers are not visible.
673  * If on other options, they are visible and required.
674  */
675  ?>
676  var rangeTypeDDL = $("#rangeTypeDDL").kendoDropDownList({
677  dataSource: <?php echo HCU_JsonEncode(GetRangeTypeData()); ?>,
678  dataTextField: "text",
679  dataValueField: "value",
680  change: function() {
681  switch(this.value()) {
682  case "":
683  $("#fromToSearch").hide();
684  $("[name='fromDate']").prop("required", false);
685  $("[name='toDate']").prop("required", false);
686  fromDatePicker.value(null);
687  toDatePicker.value(null);
688  break;
689  default:
690  if ($("#fromToSearch:visible").length == 0) { <?php // Only care if it isn't visible (ALL) ?>
691  $("[name='fromDate']").prop("required", true);
692  $("[name='toDate']").prop("required", true);
693  $("#fromToSearch").show();
694  }
695  break;
696  }
697 
698  // 05-19 set placeholders when changing unless value is populated
699  SetElementPlaceholders($("#fromDate"), 'from-' + this.value(), placeholder_map);
700  SetElementPlaceholders($("#toDate"), 'to-' + this.value(), placeholder_map);
701  }
702  }).data("kendoDropDownList");
703 
704  rangeTypeDDL.select(0);
705 
706  <?php
707  /**
708  * @var searchInDDL
709  * For searching a value in a column.
710  * If on "select...", search for text input is not visible.
711  * If on other options, search for text input is visible and is required.
712  * Text input is validated based on the value selected here.
713  */
714  ?>
715  var placeholder_map = {
716  'email' : 'Enter the borrower email address in the format account@server.com|net|etc.',
717  'dob' : 'Enter the DOB in any date format: MM/YY/YYYY, M.D.YY, etc.',
718  'ssn' : 'Enter the SSN in the format NNN-NN-NNNN.',
719  'name' : 'Enter the last name of the primary borrower.',
720  'account' : 'Enter the loan account number.',
721  'from-submit' : 'Beginning range of apps submitted.',
722  'from-start' : 'Beginning range of apps started.',
723  'from-modified' : 'Beginning range of apps last modified.',
724  'to-submit' : 'Ending range of apps submitted.',
725  'to-start' : 'Ending range of apps started.',
726  'to-modified' : 'Ending range of apps last modified.'
727  };
728 
729  var searchInDDL = $("#searchInDDL").kendoDropDownList({
730  dataSource: <?php echo HCU_JsonEncode(GetSearchInData()); ?>,
731  dataTextField: "text",
732  dataValueField: "value",
733  change: function() {
734 
735  var searchIn = this.value();
736  // 05-19 set placeholders when changing unless value is populated
737  SetElementPlaceholders($("#lookForDiv input"), searchIn, placeholder_map);
738 
739  switch(searchIn) {
740  case "":
741  $("#lookForDiv").hide();
742  break;
743  default:
744  if ($("#lookForDiv:visible").length == 0) { <?php // Only care if it isn't visible (ALL) ?>
745  $("[name='lookFor']").val(null);
746  $("#lookForDiv").show();
747  }
748  break;
749  }
750 
751  var lookFor = $("[name='lookFor']");
752  $(lookFor).data("searchIn", searchIn);
753 
754  switch(searchIn) {
755  case "email":
756  lookFor.attr("homecu-match", "email");
757  lookFor.attr("data-homecuCustomMatch-msg", "Email address is invalid.");
758  break;
759  case "dob":
760  lookFor.attr("homecu-match", "dateOpenFormat");
761  lookFor.attr("data-homecuCustomMatch-msg", "Date is invalid.");
762  break;
763  case "account":
764  lookFor.attr("homecu-match", "number");
765  lookFor.attr("data-homecuCustomMatch-msg", "Account must be a number.");
766  break;
767  case "loan":
768  lookFor.attr("homecu-match", "number");
769  lookFor.attr("data-homecuCustomMatch-msg", "Loan must be a number.");
770  break;
771  case "name":
772  case "ssn":
773  case "":
774  default:
775  lookFor.attr("homecu-match", "");
776  break;
777  }
778  }
779  }).data("kendoDropDownList");
780 
781  searchInDDL.select(0);
782 
783  <?php
784  /**
785  * @var statusDDL
786  * When not "status...", filters the grid to only that status type.
787  */
788  ?>
789  var statusDDL = $("#statusDDL").kendoDropDownList({
790  dataSource: <?php echo HCU_JsonEncode(GetWithStatusData()); ?>,
791  dataTextField: "text",
792  dataValueField: "value"
793  }).data("kendoDropDownList");
794 
795  statusDDL.select(0);
796 
797  <?php
798  /**
799  * @var sortByDDl
800  * Each option corresponds to a sort option for the grid.
801  * The default and first option is to sort by most recent first.
802  */
803  ?>
804  var sortByDDL = $("#sortByDDL").kendoDropDownList({
805  dataSource: <?php echo HCU_JsonEncode(GetSortByData()); ?>,
806  dataTextField: "text",
807  dataValueField: "value"
808  }).data("kendoDropDownList");
809 
810  sortByDDL.select(0);
811  }
812 
813  <?php
814  /**
815  * function InitLoanAppClickEvents()
816  * Initializes all the click events for the loan app tab.
817  */
818  ?>
819  function InitLoanAppClickEvents() {
820 
821  $("#appLoanSearchForm").on("submit", function(e) {
822  if ($.homecuValidator.validate()) {
823  $("#forUserIdMsg").hide();
824  $("#loanAppGrid").data("kendoGrid").dataSource.query({page: 1, pageSize: pageSize});
825  <?php // Make sure to reset the page number when the filter changes. ?>
826  }
827 
828  e.preventDefault();
829  return false;
830  });
831 
832  <?php printCheckboxEvents("#loanAppGrid"); ?>
833 
834  var inThisEvent = false;
835 
836  <?php
837  /**
838  * Anonymous function
839  * If any checkboxes are clicked, update action dropdownlist.
840  * Rules:
841  * 1) If one row is checked, options are "View Application" and "Delete."
842  * 2) If two or more rows are checked, the option is "View Application."
843  * 3) If no rows are checked, action dropdownlist is disabled.
844  */
845  ?>
846  $("#loanAppGrid").on("click", ".allCheckbox, .rowCheckbox", function() {
847  if (inThisEvent) { <?php // Prevent this logic from being executed more than once. ?>
848  return;
849  }
850  inThisEvent = true;
851  var actionDDL = $("#actionDDL").data("kendoDropDownList");
852 
853  var checkedList = $("#loanAppGrid .rowCheckbox:checked");
854  var numChecked = $(checkedList).length;
855  var list = [{value: "", text: "Action"}];
856 
857  switch (numChecked) {
858  case 0:
859  actionDDL.enable(false);
860  break;
861  case 1:
862  actionDDL.enable(true);
863  list.push({value: "delete", text: "Delete"});
864  list.push({value: "view", text: "View Application"});
865  break;
866  default:
867  actionDDL.enable(true);
868  list.push({value: "delete", text: "Delete"});
869  break;
870  }
871 
872  actionDDL.dataSource.data(list);
873  actionDDL.select(0);
874 
875  inThisEvent = false;
876  });
877 
878  <?php
879  /**
880  * Anonymous function
881  * Make it so that if the tr is clicked, it is as if the checkbox was clicked.
882  */
883  ?>
884  $("#loanAppGrid").on("click", "tbody tr", function(e) {
885  if ($(e.target).is(".rowCheckbox")) {
886  return;
887  }
888 
889  $(this).find(".rowCheckbox").click();
890  });
891 
892  <?php
893  /**
894  * Anonymous function
895  * Make it so that if the header is clicked, it is as if the all checkbox was clicked.
896  */
897  ?>
898  $("#loanAppGrid").on("click", "thead tr", function(e) {
899  if ($(e.target).is(".allCheckbox")) {
900  return;
901  }
902 
903  $(this).find(".allCheckbox").click();
904  });
905 
906  $("#loanAppGrid").on("click", ".printBtn", function(e) {
907  OpenPrintView();
908  });
909  }
910 
911  var isInitial = true;
912  var pageSize = 30;
913 
914  <?php
915  /**
916  * function InitLoanAppGrid()
917  * Initializes the loan app grid.
918  */
919  ?>
920  function InitLoanAppGrid() {
921  <?php
922  /**
923  * @var grid
924  * This shows all the loans from users in the credit union.
925  * The filtering and sorting in the search bar is applied here.
926  */
927  ?>
928  var grid = $("#loanAppGrid").kendoGrid({
929  autoBind: false,
930  dataSource: {
931  transport: {
932  read: {
933  url: "<?php echo $self; ?>&operation=readLoanApps",
934  dataType: "json",
935  type: "POST"
936  },
937  <?php
938  /**
939  * function parameterMap
940  * Read:
941  * - Applies the parameters in the search bar to the data call.
942  * Delete:
943  * - Adds all the checked records to the loanids.
944  * - Restores the search bar to the results currently shown in the grid.
945  * - Applies the parameters in the search bar to the data call.
946  */
947  ?>
948  parameterMap: function(data, type) {
949  showWaitWindow();
950 
951  if (isInitial) { <?php // Start out with the default filter. ?>
952  isInitial = false;
953  } else if (data.operation == "deleteLoans") {
954  var gridData = $("#loanAppGrid").data("kendoGrid").dataSource.data();
955  var loanids = [];
956  for(var i = 0; i != gridData.length; i++) {
957  if (gridData[i].checked) {
958  loanids.push(gridData[i].respid);
959  }
960  }
961  data.loanids = kendo.stringify(loanids);
962 
963  RestoreGridSnapshot(gridSnapshot);
964  } else {
965  gridSnapshot = CreateGridSnapshot();
966  }
967  <?php // I'm pretty sure that data is not a complex object so the "deep" parameter doesn't matter. ?>
968  data = $.extend({}, data, gridSnapshot);
969 
970  <?php // Retain the date object in the snapshot but format as a string for the data call. ?>
971  data.fromDate = data.fromDate == null ? "" : kendo.toString(data.fromDate, "MM/dd/yyyy");
972  data.toDate = data.toDate == null ? "" : kendo.toString(data.toDate, "MM/dd/yyyy");
973 
974  <?php // Sort will be custom as well. ?>
975  delete data.sort;
976 
977  <?php // Pagination ?>
978  data.limit = data.pageSize;
979  data.offset = data.skip;
980  delete data.pageSize;
981  delete data.skip;
982  delete data.page;
983  delete data.take;
984 
985  return data;
986  }
987  },
988  schema: {
989  model: {
990  id: "respid",
991  fields: {
992  respid: {type: "number"},
993  loanappid: {type: "number"},
994  start: {type: "date"},
995  account: {type: "string"},
996  status: {type: "string"},
997  dob: {type: "string"},
998  title: {type: "string"},
999  ssn: {type: "string"},
1000  email: {type: "string"},
1001  checked: {type: "boolean"},
1002  name: {type: "string"},
1003  userid: {type: "number"}
1004  }
1005  },
1006  data: "data",
1007  total: "total",
1008  <?php
1009  /**
1010  * function parse
1011  * Checks the results of the data call.
1012  * If failure, show error.
1013  * If successful with info, show info.
1014  */
1015  ?>
1016  parse: function (data) {
1017  hideWaitWindow();
1018 
1019  if (data.status != "000") {
1020  $.homecuValidator.displayMessage(data.error, $.homecuValidator.settings.statusError);
1021  } else if (data.info != null) {
1022  $.homecuValidator.displayMessage(data.info, $.homecuValidator.settings.statusInfo);
1023  }
1024 
1025  <?php // Uncheck all checkbox. Will still be checked if delete deletes all loans. ?>
1026  $("#loanAppGrid .allCheckbox").prop("checked", false);
1027 
1028  return data.gridData;
1029  }
1030  },
1031  serverSorting: true,
1032  serverPaging: true,
1033  pageSize: pageSize,
1034  sortable: false
1035  },
1036  columns: [
1037  {headerTemplate: "<input type='checkbox' class='allCheckbox'>", width: "45px"},
1038  {headerTemplate: "Started <br> Account #"},
1039  {headerTemplate: "Status <br> Birth Date"},
1040  {headerTemplate: "Type <br> SSN"},
1041  {headerTemplate: "Email <br> Name"}
1042  ],
1043  noRecords: {
1044  template: "<tr class='noRecordsDiv'><td colspan='4'>No Records Found</td></tr>"
1045  },
1046  scrollable: false,
1047  sortable: false,
1048  toolbar: "<div id='actionDDL'></div>&nbsp;&nbsp;&nbsp;<i class='fa fa-print fa-xs printBtn'></i>",
1049  pageable: {
1050  alwaysVisible: false <?php // Do not show pagination when there are 30 or less results. ?>
1051  },
1052  rowTemplate: $("#loanAppRowTemplate").html()
1053  }).data("kendoGrid");
1054 
1055  <?php
1056  /**
1057  * @var actionDDL
1058  * The action to do for the selected rows in the grid.
1059  * Rules:
1060  * 1) If one row is checked, options are "View Application" and "Delete."
1061  * 2) If two or more rows are checked, the option is "View Application."
1062  * 3) If no rows are checked, action dropdownlist is disabled.
1063  * Actions:
1064  * "Delete": open up confirmation. If true, remove selected loans.
1065  * "View Application": show loan in new window (or tab.)
1066  */
1067  ?>
1068  var actionDDL = $("#actionDDL").kendoDropDownList({
1069  dataSource: [{value: "", text: "Action"}],
1070  dataTextField: "text",
1071  dataValueField: "value",
1072  change: function(e) {
1073  var text = this.value();
1074  switch(text) {
1075  case "":
1076  break; <?php // Do nothing. This is the prompt. ?>
1077  case "delete":
1078  ConfirmDelete();
1079  break;
1080  case "view":
1081  OpenLoanAppView();
1082  break;
1083  }
1084  }
1085  }).data("kendoDropDownList");
1086 
1087  actionDDL.select(0);
1088  actionDDL.enable(false);
1089  }
1090 
1091  var gridSnapshot = {};
1092 
1093  <?php
1094  /**
1095  * function CreateGridSnapshot()
1096  * Saves the current status of the search bar.
1097  * This is used for deleting. Delete uses the previous search criteria.
1098  *
1099  * @return snapshot -- the saved values of the search bar.
1100  */
1101  ?>
1102  function CreateGridSnapshot() {
1103  var snapshot = {};
1104  var rangeType = $("#rangeTypeDDL").data("kendoDropDownList").value();
1105  var fromDate = $("[name='fromDate']").data("kendoDatePicker").value();
1106  var toDate = $("[name='toDate']").data("kendoDatePicker").value();
1107  fromDate = fromDate == null || rangeType == "" ? null : fromDate;
1108  toDate = toDate == null || rangeType == "" ? null : toDate;
1109 
1110  snapshot.rangeType = rangeType;
1111  snapshot.fromDate = fromDate;
1112  snapshot.toDate = toDate;
1113  snapshot.lookFor = $("[name='lookFor']").val().trim();
1114  snapshot.withStatus = $("#statusDDL").data("kendoDropDownList").value();
1115  snapshot.searchIn = $("#searchInDDL").data("kendoDropDownList").value();
1116  snapshot.sortBy = $("#sortByDDL").data("kendoDropDownList").value();
1117 
1118  return snapshot;
1119  }
1120 
1121  <?php
1122  /**
1123  * function RestoreGridSnapshot(snapshot)
1124  * Takes the saved snapshot and applies the values to the search bar controls.
1125  *
1126  * @param snapshot -- the snapshot to restore.
1127  */
1128  ?>
1129  function RestoreGridSnapshot(snapshot) {
1130  <?php // == null is equal to === null || === undefined. Setting a control to undefined does nothing but setting it to null clears it. ?>
1131  var fromDate = snapshot.fromDate == null ? null : snapshot.fromDate;
1132  var toDate = snapshot.toDate == null ? null : snapshot.toDate;
1133  var rangeType = snapshot.rangeType == null ? "" : snapshot.rangeType.trim();
1134  var lookFor = snapshot.lookFor == null ? "" : snapshot.lookFor.trim();
1135  var withStatus = snapshot.withStatus == null ? "" : snapshot.withStatus.trim();
1136  var searchIn = snapshot.searchIn == null ? "" : snapshot.searchIn.trim();
1137  var sortBy = snapshot.sortBy == null ? "startAD" : snapshot.sortBy.trim();
1138 
1139  <?php // Actual VALUES reset. ?>
1140  $("[name='fromDate']").data("kendoDatePicker").value(fromDate);
1141  $("[name='toDate']").data("kendoDatePicker").value(toDate);
1142  $("#rangeTypeDDL").data("kendoDropDownList").value(rangeType);
1143  $("[name='lookFor']").val(lookFor);
1144  $("#statusDDL").data("kendoDropDownList").value(withStatus);
1145  $("#searchInDDL").data("kendoDropDownList").value(searchIn);
1146  $("#sortByDDL").data("kendoDropDownList").value(sortBy);
1147 
1148  <?php // Need to also preserve hidden/shown DIVs. ?>
1149  if (searchIn == "") {
1150  $("#lookForDiv").hide();
1151  } else {
1152  $("#lookForDiv").show();
1153  }
1154  if (rangeType == "") {
1155  $("#fromToSearch").hide();
1156  } else {
1157  $("#fromToSearch").show();
1158  }
1159  }
1160 
1161  <?php
1162  /**
1163  * function ConfirmDelete()
1164  * Confirms the delete.
1165  */
1166  ?>
1167  function ConfirmDelete() {
1168  var confirmDeleteDialog = $("#confirmDeleteDialog").data("kendoDialog");
1169  if (confirmDeleteDialog == null) {
1170 
1171  <?php
1172  /**
1173  * @var confirmDeleteDialog
1174  * The confirmation dialog.
1175  * On "No":
1176  * Reset the action dropdownlist. Keep the rows checked.
1177  * On "Yes":
1178  * Delete loans and refresh grid when done (one action).
1179  */
1180  ?>
1181  confirmDeleteDialog = $("<div id='confirmDeleteDialog'></div>").appendTo("body").kendoDialog({
1182  actions: [
1183  {text: "No", action: function() {
1184  confirmDeleteDialog.close();
1185  var actionDDL = $("#actionDDL").data("kendoDropDownList");
1186  actionDDL.value("");
1187  return false;
1188  }},
1189  {text: "Yes", primary: true, action: function() {
1190  $("#loanAppGrid").data("kendoGrid").dataSource.query({page: 1, pageSize: pageSize,
1191  operation: "deleteLoans"}); <?php // Make sure to reset the page number when the filter changes. ?>
1192  confirmDeleteDialog.close();
1193  var actionDDL = $("#actionDDL").data("kendoDropDownList");
1194  actionDDL.value("");
1195  return false;
1196  }}
1197  ],
1198  open: function() {
1199  if (window.activeWindows != null) {
1200  window.activeWindows.push(this);
1201  }
1202  },
1203  close: function() {
1204  if (window.activeWindows != null) {
1205  window.activeWindows.pop();
1206  }
1207  },
1208  visible: false,
1209  modal: true,
1210  minWidth: 600,
1211  title: "Confirm Deletion"
1212  }).data("kendoDialog");
1213  }
1214 
1215  var template = kendo.template($("#loanAppDeleteTemplate").html());
1216  var gridData = $("#loanAppGrid").data("kendoGrid").dataSource.data();
1217  var selectedLoans = $.grep(gridData, function(n,i) { return n.checked != null && n.checked; });
1218 
1219  confirmDeleteDialog.content(template({selectedLoans: selectedLoans})).open().center();
1220  }
1221 
1222  <?php
1223  /**
1224  * function OpenPrintView()
1225  * Opens a new window (or tab) with only the data from the grid for printing.
1226  */
1227  ?>
1228  function OpenPrintView() {
1229  var gridHTML = $("#loanAppGrid").clone();
1230  $(gridHTML).removeClass("pointerGrid");
1231  $(gridHTML).find(".k-grid-toolbar, colgroup col:eq(0), .checkboxTD, thead tr th:eq(0)").remove();
1232  gridHTML = $(gridHTML).prop("outerHTML");
1233  $("#printForm [name='shell']").val("<br><div class='container-fluid'>" + gridHTML + "</div>");
1234  $("#printForm [name='title']").val("View Loan App Grid");
1235  $("#printForm").submit();
1236  }
1237 
1238  <?php
1239  /**
1240  * function OpenLoanAppView()
1241  * Opens a new window (or tab) with the contents of the selected loan.
1242  */
1243  ?>
1244  function OpenLoanAppView() {
1245  var grid = $("#loanAppGrid").data("kendoGrid");
1246  var gridData = grid.dataSource.data();
1247  var url = "";
1248  for(var i = 0; i != gridData.length; i++) {
1249  var record = gridData[i];
1250  if (record.checked != null && record.checked) {
1251  if (url == "") {
1252  url = "main.prg?ft=802&view=" + record.respid + "&app=" + record.userid;
1253  }
1254  gridData[i].checked = false;
1255  }
1256  }
1257 
1258  if (url != "") {
1259  window.open(url, "_blank");
1260 
1261  <?php // Need to remove checkboxes. ?>
1262  grid.dataSource.data(gridData);
1263  $("#loanAppGrid .allCheckbox").prop("checked", false);
1264 
1265  $("#actionDDL").data("kendoDropDownList").value("");
1266  }
1267  }
1268 
1269  /**
1270  * For above, update the placeholder attribute for any element associated with a select list.
1271  * @param obj object target element object
1272  * @param selected string select list value, associated with map above
1273  * @param map object(array)
1274  * @return void
1275  */
1276  function SetElementPlaceholders(obj, selected, map)
1277  {
1278  if (! obj.length || obj.val() !== '') {
1279  return;
1280  }
1281  obj.attr('placeholder', map[selected]);
1282 
1283  }
1284 
1285  var activeWindows = [];
1286  $(document).ready(function() {
1287  $('#list-menu').metisMenu();
1288  InitTabs();
1289  InitTimeoutDialog();
1290  <?php printClickOverlayEvent(); ?>
1291  });
1292 
1293  /**
1294  * Per review, wrap and init by document ready.
1295  * @return void
1296  */
1297  function InitTimeoutDialog()
1298  {
1299  <?php if (!$frm_login) { ?>
1300  $.timeoutDialog({
1301  timeout: <?php echo intval($SYSENV["ticket"]["inactive"]) - 60;?>,
1302  countdown: 60,
1303  title : 'Your session is about to expire!',
1304  message : 'You will be logged out in {0} seconds.',
1305  question: 'Do you want to stay signed in?',
1306  keep_alive_button_text: 'Yes, Keep me signed in',
1307  sign_out_button_text: 'No, Sign me out',
1308 
1309  logout_redirect_url: '<?php echo $menu_link; ?>?ft=70',
1310  keep_alive_url: '<?php echo $menu_link; ?>?ft=999',
1311  restart_on_yes: true,
1312  cookie_name: 'aTicket',
1313  dialog_width: 350
1314  });
1315  <?php } ?>
1316  }
1317 
1318  </script>
1319 <?php
1320 /**********************************
1321  KENDO TEMPLATES
1322  **********************************/
1323 ?>
1324 
1325  <?php
1326  /**
1327  * @var applicantTemplate
1328  * This is the template for the applicant tab.
1329  */
1330  ?>
1331  <script type="text/x-kendo-template" id="applicantTemplate">
1332  <div id="applicantFormValidateDiv" style="display:none"></div>
1333  <form class="container-fluid" id="applicantFullForm" data-action="search">
1334  <div class="well well-sm container-fluid applicantSearchDiv restrictWidthDiv">
1335  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1336  <div class="container-fluid">
1337  <div class="row hcuSpacer">
1338  <label class="col-xs-12 col-sm-4">Search In</label>
1339  <div class="col-xs-12 col-sm-8">
1340  <div id="searchInApplicantDDL" class="hcu-all-100"></div>
1341  </div>
1342  </div>
1343  <div class="row hcuSpacer">
1344  <label class="col-xs-12 col-sm-4">Look For</label>
1345  <div class="col-xs-12 col-sm-8">
1346  <input type="text" class="k-input k-textbox hcu-all-100" name="lookForApplicant"
1347  homecu-match="email"
1348  data-homecuCustomMatch-msg="Email address is invalid.">
1349  </div>
1350  </div>
1351  </div>
1352  </div>
1353  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1354  <div class="container hcu-all-100">
1355  <div class="row">
1356  <div class="col-xs-12">
1357  <a href="\\#" class="k-button k-primary floatRight" id="applicantSearchBtn">Search</a>
1358  </div>
1359  </div>
1360  </div>
1361  </div>
1362  </div>
1363 
1364  <div class="applicantGridDiv" style="display:none;">
1365  <div id="applicantGrid"></div>
1366  </div>
1367  <div class="applicantManagementDiv" style="display:none;">
1368 
1369  </div>
1370  <button type="submit" style="display:none;"></button>
1371  </form>
1372  </script>
1373 
1374  <?php
1375  /**
1376  * @var loanAppTemplate
1377  * This is the template for the loan app tab.
1378  */
1379  ?>
1380  <script type="text/x-kendo-template" id="loanAppTemplate">
1381  <div id="appLoanFormValidateDiv" class="k-block k-error-colored formValidateDiv" style="display:none"></div>
1382  <div class="container-fluid">
1383  <form id="appLoanSearchForm"><div class="well well-sm container-fluid appLoanDiv"><div>
1384  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1385  <div class="container-fluid">
1386  <div class="row hcuSpacer">
1387  <label class="col-xs-12 col-sm-4">Search In</label>
1388  <div class="col-xs-12 col-sm-8"><div id="searchInDDL" class="hcu-all-100"></div></div>
1389  </div>
1390  <div class="row hcuSpacer" id="lookForDiv" style="display:none;">
1391  <label class="col-xs-12 col-sm-4">Look For</label>
1392  <div class="col-xs-12 col-sm-8">
1393  <input type="text" class="k-input k-textbox hcu-all-100" name="lookFor" data-email-msg="Search is not valid email." placeholder="Select from the list above.">
1394  </div>
1395  </div>
1396  </div>
1397  </div>
1398  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1399  <div class="container-fluid">
1400  <div class="row hcuSpacer">
1401  <label class="col-xs-12 col-sm-4">Show Loans with Status</label>
1402  <div class="col-xs-12 col-sm-8"><div id="statusDDL" class="hcu-all-100"></div></div>
1403  </div>
1404  </div>
1405  </div>
1406  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1407  <div class="container-fluid">
1408  <div class="row hcuSpacer"><label class="col-xs-12 col-sm-4">Show</label>
1409  <div class="col-xs-12 col-sm-8"><div id="rangeTypeDDL" class="hcu-all-100"></div></div>
1410  </div>
1411  <div id="fromToSearch" style="display:none;" class="row hcuSpacer"><label class="col-xs-12 col-sm-4">From</label>
1412  <div class="col-xs-12 col-sm-8">
1413  <?php // Because they are kendo controls, inline styles show up differently then CSS rules (not even with !important). ?>
1414  <input type="text" id="fromDate" name="fromDate" style="width: 40%; float: left;" homecu-match="date"
1415  data-homecuCustomMatch-msg="From date is invalid." data-required-msg="From date is required." placeholder="From date">
1416  <label>To</label>
1417  <input type="text" id="toDate" name="toDate" style="width: 40%; float: right;" homecu-match="date"
1418  data-homecuCustomMatch-msg="To date is invalid."
1419  data-required-msg="To date is required." homecu-dategtvalue="fromDate" homecu-dategttype="field"
1420  data-homecuCustomDateGTValue-msg="To date must be past from date." placeholder="Enter to date.">
1421  </div>
1422  </div>
1423  </div>
1424  </div>
1425  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1426  <div class="container-fluid">
1427  <div class="row hcuSpacer">
1428  <label class="col-xs-12 col-sm-4">Sort By</label>
1429  <div class="col-xs-12 col-sm-8"><div id="sortByDDL" class="hcu-all-100"></div></div>
1430  </div>
1431  </div>
1432  </div>
1433 
1434  <div class="col-xs-12 hcuSpacer hcu-no-padding"><div class="container hcu-all-100"><div class="row"><div class="col-xs-12">
1435  <button type="submit" class="k-button k-primary floatRight" id="loanAppSearchBtn">Search</button>
1436  </div></div></div></div>
1437  </div></div></form>
1438 
1439  <div class="small vsgSecondary" style="display:none;" id="forUserIdMsg">Showing loans for loan app user <span></span>.</div>
1440  <div id="loanAppGrid" class="hcu-all-100 pointerGrid"></div>
1441  <form id="auditPrintForm" method="post" action="shell.prg" target="auditPrint">
1442  <input type="hidden" name="shell" value="">
1443  <input type="hidden" name="title" value="">
1444  </form>
1445  </div>
1446  </script>
1447 
1448  <?php
1449  /**
1450  * @var loanAppRowTemplate
1451  * This is the template for a row in the loan app grid.
1452  */
1453  ?>
1454  <script type="text/x-kendo-template" id="loanAppRowTemplate">
1455  <tr data-uid='#: uid #'>
1456  <td class="checkboxTD">
1457  <input type='checkbox' class='rowCheckbox'>
1458  </td>
1459  <td>
1460  #= kendo.toString(start, "d") # <br>
1461  #: account #
1462  </td>
1463  <td>
1464  #: status # <br>
1465  #: dob #
1466  </td>
1467  <td>
1468  #: title # <br>
1469  #: ssn #
1470  </td>
1471  <td>
1472  #: email # <br>
1473  #: name #
1474  </td>
1475  </tr>
1476  </script>
1477 
1478  <?php
1479  /**
1480  * @var loanAppDeleteTemplate
1481  * This is the template for the delete confirm dialog.
1482  */
1483  ?>
1484  <script type="text/x-kendo-template" id="loanAppDeleteTemplate">
1485  <div class="container-fluid">
1486  <div class="row">
1487  <div class="container-fluid">
1488  <div class="row hcu-no-padding">
1489  <div class="col-xs-3 hcu-no-padding"><label>Name</label></div>
1490  <div class="col-xs-3 hcu-no-padding"><label>Started On</label></div>
1491  <div class="col-xs-3 hcu-no-padding"><label>Type</label></div>
1492  <div class="col-xs-3 hcu-no-padding"><label>Email</label></div>
1493  </div>
1494  </div>
1495  </div>
1496  # for (var i = 0; i != selectedLoans.length; i++) {
1497  var rec = selectedLoans[i]; #
1498  <div class="row hcuSpacer">
1499  <div class="container-fluid">
1500  <div class="row well well-sm hcu-no-padding">
1501  <div class="col-xs-3 hcu-no-padding">#: rec.name #</div>
1502  <div class="col-xs-3 hcu-no-padding">#= kendo.toString(rec.start, "g") #</div>
1503  <div class="col-xs-3 hcu-no-padding">#: rec.title #</div>
1504  <div class="col-xs-3 hcu-no-padding">#: rec.email #</div>
1505  </div>
1506  </div>
1507  </div>
1508  # } #
1509  <div class="row">&nbsp;</div>
1510  <div class="row hcuSpacer">
1511  <div class="container-fluid">
1512  <div class="row">
1513  # var thes = selectedLoans.length == 1 ? "this" : "these";
1514  var es = selectedLoans.length == 1 ? "application" : "applications"; #
1515  Are you sure you want to delete #: thes # loan #: es #?
1516  </div>
1517  </div>
1518  </div>
1519  </div>
1520  </script>
1521 
1522  <?php
1523  /**
1524  * @var applicantMaintenanceTemplate
1525  * This is the template for the applicant maintenance screen-ish.
1526  */
1527  ?>
1528  <script type="text/x-kendo-template" id="applicantMaintenanceTemplate">
1529  <div class="container-fluid">
1530  <div class="h4 hcuSpacer">
1531  Attributes
1532  </div>
1533  </div>
1534 
1535  # var loanText = ""; var loanLink = "";
1536  switch (numLoanApps) {
1537  case 0:
1538  loanText = "loans";
1539  loanLink = "";
1540  break;
1541  case 1:
1542  loanText = "loan";
1543  loanLink = "(<a href='\\#' class='gotoLoans'>Go to loans</a>)";
1544  break;
1545  default:
1546  loanText = "loans";
1547  loanLink = "(<a href='\\#' class='gotoLoans'>Go to loans</a>)";
1548  break;
1549  } #
1550 
1551  <div class="well well-sm container-fluid restrictWidthDiv">
1552  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1553  <div class="container-fluid">
1554  <div class="row hcuSpacer">
1555  <label class="col-xs-12">Applicant ID&nbsp;</label>
1556  <div class="col-xs-12 admIndent userIdLabel">#: lnId #</div>
1557  </div>
1558  <div class="row hcuSpacer">
1559  <label class="col-xs-12">Login Type&nbsp;</label>
1560  <div class="col-xs-12 admIndent">#: loginType #</div>
1561  </div>
1562  <div class="row hcuSpacer">
1563  <label class="col-xs-12">Account \\#&nbsp;</label>
1564  <div class="col-xs-12 admIndent"># if (accountnumber == "") { # N/A # } else { # #: accountnumber # # } #</div>
1565  </div>
1566  <div class="row hcuSpacer">
1567  <label class="col-xs-12">Username&nbsp;</label>
1568  <div class="col-xs-12 admIndent"># if (username == "") { # N/A # } else { # #: username # # } #</div>
1569  </div>
1570  <div class="row hcuSpacer">
1571  <label class="col-xs-12">Number of Loans&nbsp;</label>
1572  <div class="col-xs-12 admIndent">#: numLoanApps # #= loanText # #= loanLink #</div>
1573  </div>
1574  </div>
1575  </div>
1576  </div>
1577 
1578  <div class="container-fluid">
1579  <div class="h4 hcuSpacer">
1580  Settings
1581  </div>
1582  </div>
1583 
1584  # var lockedClasses = isLocked ? "originalLocked currentLocked" : "originalUnlocked currentUnlocked"; #
1585 
1586  <div class="well well-sm container-fluid restrictWidthDiv">
1587  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1588  <div class="container-fluid">
1589  <div class="row hcuSpacer">
1590  <label class="col-xs-12 col-sm-4">Lock User</label>
1591  <div class="col-xs-12 col-sm-8">
1592  <div class="lockAccount #: lockedClasses # admAlignBottom">
1593  <span class="text col-xs-4 col-md-3 hcu-no-padding"></span>
1594  <span class="col-xs-5 col-md-1 hcu-no-padding">(<a href="\\#"></a>)</span>
1595  </div>
1596  </div>
1597  </div>
1598  # if (canChangeLogin) { #
1599  <div class="row hcuSpacer">
1600  <label class="col-xs-12 col-sm-4">Email</label>
1601  <div class="col-xs-12 col-sm-8">
1602  <input class="k-input k-textbox hcu-all-100" name="email" value="#: email #" type="text" data-homecuCustomMatch-msg="Email is invalid."
1603  homecu-match="email">
1604  </div>
1605  </div>
1606  <div class="row hcuSpacer">
1607  <label class="col-xs-12 col-sm-4">Enter Password</label>
1608  <div class="col-xs-12 col-sm-8">
1609  <input id="password" name="password" type="password" maxlength="255" class="hcu-all-100 k-input k-textbox">
1610  </div>
1611  </div>
1612  <div class="row hcuSpacer">
1613  <label class="col-xs-12 col-sm-4">Confirm</label>
1614  <div class="col-xs-12 col-sm-8">
1615  <input id="confirm" name="confirm" type="password" maxlength="255" class="hcu-all-100 k-input k-textbox">
1616  </div>
1617  </div>
1618  # } #
1619  <div class="row hcuSpacer">
1620  <div class="col-xs-12">
1621  <a href="\\#" class="k-button k-primary floatRight" id="applicantSaveBtn">Save</a>
1622  </div>
1623  </div>
1624  </div>
1625  </div>
1626  </div>
1627 
1628  <div class="container-fluid">
1629  <div class="h4 hcuSpacer">
1630  Security Questions
1631  </div>
1632  </div>
1633  <div class="well well-sm container-fluid restrictWidthDiv">
1634  <div class="col-xs-12 hcuSpacer hcu-no-padding">
1635  <div class="container-fluid">
1636  <div class="row hcuSpacer">
1637  <label class="col-xs-12">Confidence Word&nbsp;</label>
1638  <div class="col-xs-12 admIndent">#: confidence #</div>
1639  </div>
1640  <hr>
1641  # if (securityQuestions.length == 0) { #
1642  <div class="row hcuSpacer">
1643  (No Security Questions Found.)
1644  </div>
1645  # } else {
1646  for (var i = 0; i != securityQuestions.length; i++) {
1647  var secrec = securityQuestions[i]; #
1648  <div class="row hcuSpacer">
1649  <label class="col-xs-12">#: secrec.question #&nbsp;</label>
1650  <div class="col-xs-12 admIndent">#: secrec.answer #</div>
1651  </div>
1652  # }
1653  } #
1654  </div>
1655  </div>
1656  </div>
1657  </script>
1658 
1659 <?php
1660 /*********************************
1661 STYLES
1662 **********************************/
1663 ?>
1664 
1665  <style>
1666  .appLoanDiv > div, .applicantSearchDiv > div {
1667  max-width: 950px;
1668  }
1669 
1670  .restrictWidthDiv > * {
1671  max-width: 950px;
1672  }
1673 
1674  #fromToSearch > div {
1675  text-align: center;
1676  }
1677 
1678  .printBtn {
1679  cursor: pointer;
1680  }
1681  </style>
1682 
1683 <?php
1684 /********************************
1685 HTML
1686 *********************************/
1687 ?>
1688 
1689  <div class="container-fluid" id="appAdmDiv">
1690  <div>
1691  <div class="errorDiv"></div>
1692  <h2>Online Loan Applications</h2>
1693  <div>&nbsp;</div>
1694  <div class=" tabTitles row adm-no-horz-margin">
1695  <div class="col-xs-2 selected" data-name="applicant"><div><i class="fa fa-user fa-6">
1696  <div class="hidden-xs hidden-sm text">&nbsp;Applicant</div></i></div></div>
1697  <div class="col-xs-2 lastChild" data-name="loanApps"><div><i class="fa fa-tasks fa-6">
1698  <div class="hidden-xs hidden-sm text">&nbsp;Loan Apps</div></i></div></div>
1699  </div>
1700  <div>
1701  <div class="form-group tabContents" data-name="applicant"></div>
1702  <div class="form-group tabContents" data-name="loanApps" style="display:none;"></div>
1703  </div>
1704  </div>
1705  </div>
1706 
1707  <form id="printForm" method="post" action="shell.prg" target="printWindow">
1708  <input type="hidden" name="shell" value="">
1709  <input type="hidden" name="title" value="">
1710  </form>
1711 <?php }
def main(certificate_path, secret_id, region=None)