Odyssey
ody_migr_client.prg
1 <?php
2 /**
3  * File: ody_migr_client.prg
4  * This file presents UI in for data migration from Mammoth to Odyssey.
5  */
6 
7 // **********************************************************************************************
8 // Top portion: import required libraries, check permissions and extract string queries and/or post data
9 // **********************************************************************************************
10 
11 $monLibrary = dirname(__FILE__) . "/../library";
12 $sharedLibrary = dirname(__FILE__) . "../../shared/library";
13 require_once("$monLibrary/cu_top.i");
14 require_once("$monLibrary/ck_hticket.i");
15 require_once("$sharedLibrary/commonJsFunctions.i");
16 
17 if (!CheckPerm($link, $Hu, basename($_SERVER['SCRIPT_NAME']), $_SERVER['REMOTE_ADDR'])) {
18  header("Location: /hcuadm/hcu_noperm.prg");
19  exit;
20 }
21 
22 $string = array("filter" => FILTER_SANITIZE_STRING);
23 $params = array("cu" => $string);
24 $vars = array("cu" => "");
25 HCU_ImportVars($vars, "", $params);
26 
27 $cu = HCU_array_key_value("cu", $vars);
28 $cu = $cu === false ? "" : trim($cu);
29 
30 // Credit Union is required so prevent the script from executing if it doesn't exist.
31 if ($cu == "") {
32  header("Location: /hcuadm/hcu_noperm.prg");
33  exit;
34 };
35 
36 // ********************************************************************************************
37 // Common to .prg and .data (if there is enough lines of code, put it in an include file.). Common functions to populate kendo DDLs.
38 // ********************************************************************************************
39 
40 function GetCurrentServer() {
41  if (getenv("DEVMODE") == "1") {
42  $serverHost = "localhost:8000";
43  } else {
44  $serverHost = trim(getenv("TICKET_DOMAIN"));
45  }
46  return "Odyssey (" . $serverHost . ")";
47 }
48 
49 
50 function IsDevMode() {
51  if(getenv("DEVMODE") == "1" && trim(getenv("TICKET_DOMAIN")) == "") {
52  return 1;
53  }
54  return 0;
55 }
56 
57 /**
58  * function GetOperationsList()
59 * This function returns the specified options for available data migration operations.
60  * First element is the default
61  */
62 function GetOperationsList() {
63  return array("migrate", "summary", "clean");
64 }
65 
66 /**
67  * function GetOperationsListOnlyMigrate()
68  * This function returns the specified migration task option (only migrate)
69  * for switchaccounts
70  * First (and the only) element is the default
71  */
72 function GetOperationsListOnlyMigrate() {
73  return array("migrate");
74 }
75 
76 // monitor lock file is required, so prevent the script from executing if it doesn't exist
77 $migrationMonitorLock = "/home/" . strtolower($cu) . "/tmp/.ody_migr_monitor_lock";
78 
79 // ***************************************************************************************
80 // Top of the web page
81 // ***************************************************************************************
82 
83 // Imports the front end libraries: kendo, bootstrap, JQuery as well as formulates the top part of the web page.
84 printMonitorPageTop("Data Migration from Mammoth [ " . strtoupper($cu) . "]", $homecuKendoVersion, $cloudfrontDomainName, $bootstrapVersion, $fontawesomeVersion, true);
85 
86 // Writes out the top header. Null means do not add anything to the options.
87 printMonitorPageMiddle("Data Migration from Mammoth [" . strtoupper($cu) . "]", null);
88 
89 // ****************************************************************************************
90 // Javascript code
91 // ****************************************************************************************
92 ?>
93 
94 <script type="text/javascript">
95 
96 // Following few settings prevent users from accidently refreshing and changing menu options
97 
98 // Press F5 with focus on anywhere in the page (Want to switch to any other menu options?)
99 window.onbeforeunload = function() {
100  return "Are you sure you want to refresh the page?";
101 };
102 
103 // Disable no back button
104 history.pushState(null, null, 'no-back-button');
105 window.addEventListener('popstate', function(event) {
106  history.pushState(null, null, 'no-back-button');
107 });
108 
109 
110 // Variable to be used to clear auto refresh log fetching
111 var fetchLogIntervalVar;
112 // wait for this many seconds before the first log fetch is called after executing migration script
113 var firstLogFetchOffsetTime = 2;
114 // Time interval to auto refresh log fetching (seconds)
115 var refreshWindow = 15;
116 // Hide progressbar after
117 var hideProgressBar = 4
118 // AJAX endpoint
119 var hcuadmOdyMigrServerURL = "/hcuadm/ody_migr_server.prg";
120 
121 // Needed for the wait windows.
122 <?php getShowWaitFunctions(); ?>
123 
124 /**
125  * Update multiple cleanup values with the list of completed categories
126  */
127 function updateAllDoneMultiCheckList(showHideWaitWindow){
128  if (showHideWaitWindow) {
129  showWaitWindow()
130  }
131  data_lock_list={
132  "post_purpose": "get_wip_done_list",
133  "cu": "<?php echo $cu; ?>"
134  };
135 
136  $.ajax({
137  type: "POST",
138  url: hcuadmOdyMigrServerURL,
139  data: data_lock_list,
140  dataType: "json", // returned data type expected from server
141  })
142  .done(function (response) {
143  var lockFiles = [];
144  if (response["success"] == true) {
145  lockFiles = response["done_list"];
146  // remove switchaccounts from list
147  var sa_index = lockFiles.indexOf("switchaccounts");
148  if (sa_index > -1) {
149  lockFiles.splice(sa_index, 1);
150  }
151  $("#deleteSelectedCategoriesBtn").html(" Clean Selected Categories")
152  }
153  else {
154  displayMessageAlert(response["message"], "add", "danger");
155  }
156 
157  // clean up the previously selected but not deleted values
158  $("#deleteAllCleanUpList").data("kendoMultiSelect").value([]);
159  // upload the updated data source
160  var ds = new kendo.data.DataSource({
161  data: lockFiles
162  });
163  $("#deleteAllCleanUpList").data("kendoMultiSelect").setDataSource(ds)
164 
165 
166  // enable/disable cleanup button based on the items on the multiple select box
167  if (lockFiles.length > 0) {
168  $("#deleteSelectedCategoriesBtn").prop('disabled', false);
169  } else {
170  $("#deleteSelectedCategoriesBtn").prop('disabled', true);
171  }
172 
173  })
174  .always(function (response) {
175  if (showHideWaitWindow) {
176  hideWaitWindow()
177  }
178  updateStartButtonVisibleStatus(showHideWaitWindow);
179  })
180 }
181 
182 /**
183  * function updateDataCategoriesList()
184  * This function updates data categories list for this $cu
185  */
186 function updateDataCategoriesList(showHideWaitWindow) {
187  if (showHideWaitWindow) {
188  showWaitWindow();
189  }
190  data_server_list={
191  "post_purpose": "update_categories_list",
192  "cu": "<?php echo $cu; ?>"
193  };
194 
195  $.ajax({
196  type: "POST",
197  url: hcuadmOdyMigrServerURL,
198  data: data_server_list,
199  dataType: "json", // returned data type expected from server
200  })
201  .done(function (response) {
202  var categories_list = [];
203  if (response["success"] == true) {
204  categories_list = response["categories_list"];
205  }
206  else {
207  displayMessageAlert(response["message"], "add", "danger");
208  }
209 
210  var categoriesDDL = $("#categoriesDDL").data("kendoDropDownList")
211  current_cat_value = categoriesDDL.value()
212  // update data source
213  var categories_data_source = new kendo.data.DataSource({
214  data: categories_list
215  });
216  categoriesDDL.setDataSource(categories_data_source)
217  if (categories_list.length > 0) {
218  // do not update already selected current category from the ddl
219  if (categories_list.includes(current_cat_value)) {
220  categoriesDDL.value(current_cat_value)
221  } else {
222  categoriesDDL.value(categories_list[0])
223  }
224  categoriesDDL.trigger("change")
225  }
226  }).always(function (response) {
227  if (showHideWaitWindow) {
228  hideWaitWindow();
229  }
230  })
231 }
232 
233 /**
234  * function populateServerList()
235  * This function populates servers for this $cu
236  */
237 function populateServerList(showHideWaitWindow) {
238  if(showHideWaitWindow) {
239  showWaitWindow()
240  }
241  data_server_list={
242  "post_purpose": "update_server_list",
243  "cu": "<?php echo $cu; ?>"
244  };
245 
246  $.ajax({
247  type: "POST",
248  url: hcuadmOdyMigrServerURL,
249  data: data_server_list,
250  dataType: "json", // returned data type expected from server
251  })
252  .done(function (response) {
253  server_list = [];
254  if (response["success"] == true) {
255  server_list = response["server_list"];
256 
257  var serversDDL = $("#serversDDL").data("kendoDropDownList")
258  // update data source
259  var server_data_source = new kendo.data.DataSource({
260  data: server_list
261  });
262 
263  serversDDL.setDataSource(server_data_source)
264 
265  if (server_list.length > 0) {
266  serversDDL.value(server_list[0])
267  serversDDL.trigger("change")
268  }
269  } else {
270  displayMessageAlert(response["message"], "add", "danger");
271  }
272 
273  }).always(function (response) {
274  if(showHideWaitWindow) {
275  showWaitWindow()
276  }
277  })
278 }
279 
280 
281 /**
282  * Utility function to reset and hide log monitoring div
283  */
284 function resetMonitorLogArea() {
285  $("#logs-textarea").html('')
286  $("#migration-status").hide()
287 }
288 
289 /**
290  * Utility function to enable log monitoring area
291  */
292 function setMonitorLogArea() {
293  $("#migration-status").show()
294  var currentDateTime = getCurrentDateTime();
295  // sanitize display message for log header
296  currentDateTime = currentDateTime.replace(/^\s\(|\)$/g, '');
297  $("#logs-display-datetime").html("<strong>" + currentDateTime + "</strong>");
298 }
299 
300 /**
301  * Utility function to update public_html embedded links
302  */
303  function updatePublicHtmlResources(server) {
304  if (server == "www4" || 1 == <?php echo IsDevMode(); ?>) {
305  displayMessageAlert("Updating `public_html` is not applicable in Dev Mode ('" + server + "').",
306  "add",
307  "success")
308  } else {
309  showWaitWindow();
310  data_fix_phtml = {
311  "post_purpose": "fix_public_html",
312  "cu": "<?php echo $cu; ?>",
313  "from" : server + ".homecu.net",
314  "to": "my.homecu.net"
315  };
316 
317  $.ajax({
318  type: "POST",
319  url: hcuadmOdyMigrServerURL,
320  data: data_fix_phtml,
321  dataType: "json", // returned data type expected from server
322  timeout: 0,
323  })
324  .done(function (response) {
325  msg = response["message"];
326  var alert_level;
327  if(response["success"]) {
328  alert_level = "success"
329  } else {
330  alert_level = "danger";
331  }
332  displayMessageAlert(msg, "add", alert_level);
333  })
334  .always(function (response) {
335  hideWaitWindow();
336  });
337  }
338 
339 }
340 
341 /**
342  * Utility function to clean up selected data categories.
343  */
344 function cleanUpSelectedCategories() {
345 
346  showWaitWindow()
347  resetIntervalAutoLogFetch()
348  // delete only the selected lock files
349  var deleteDoneList = $("#deleteAllCleanUpList").data("kendoMultiSelect").value()
350  if (deleteDoneList.length > 0) {
351  data_delete_lock_history = {
352  "post_purpose": "clean_all_categories",
353  "cu": "<?php echo $cu; ?>",
354  "delete_done_list": deleteDoneList
355  };
356 
357  $.ajax({
358  type: "POST",
359  url: hcuadmOdyMigrServerURL,
360  data: data_delete_lock_history,
361  dataType: "json",
362  timeout: 0 // some credit unions take more than a few minutes for cleanup
363  })
364  .done(function (response) {
365  msg = response["message"];
366  var alert_level;
367  if(response["success"]) {
368  alert_level = "success"
369  } else {
370  alert_level = "danger";
371  }
372  // reset log monitoring div
373  resetMonitorLogArea();
374  $("#progress-bar-container").removeClass('hidden');
375  $("#progress-bar-container").addClass('hidden');
376  // set form
377  setHtmlFormElements();
378  $("#runMigrationBtn").prop("disabled", false);
379  // display notification when called using "Delete History" button
380  displayMessageAlert(msg, "add", alert_level);
381  $("#finalMigrationStatusDiv").html("<u><b>" + msg + getCurrentDateTime() + "</b></u>");
382  })
383  .always(function (response) {
384  UpdateMigrationOptions(false)
385  hideWaitWindow()
386  });
387  } else {
388  displayMessageAlert("No category(ies) selected for clean up.", "add", "warning");
389  hideWaitWindow()
390  }
391 }
392 
393 /**
394  * function setUpOperationsDDL(opList)
395  * This function populate operations DDL with opList
396  */
397 function setUpOperationsDDL(cat_val, ev){
398  if (cat_val == "switchaccounts") {
399  opList = <?php echo HCU_JsonEncode(GetOperationsListOnlyMigrate()); ?>;
400  } else {
401  opList = <?php echo HCU_JsonEncode(GetOperationsList()); ?>;
402  }
403  // update data source for kendo-ui DDL instance for migration operations
404  var operations_data_source = new kendo.data.DataSource({
405  data: opList
406  });
407 
408  $("#operationsDDL").data("kendoDropDownList").setDataSource(operations_data_source)
409  // don't change the value when categories alue changes
410  if (ev != "cascade" && opList.length > 0) {
411  $("#operationsDDL").data("kendoDropDownList").value(opList[0])
412  }
413 }
414 
415 
416 /**
417  * This function updates the home banking informational text
418  */
419 function updateHomeBankingInfoText(showHideWaitWindow) {
420  if(showHideWaitWindow) {
421  showWaitWindow();
422  }
423  data_hb_info={
424  "post_purpose": "display_hb_info_text",
425  "cu": "<?php echo $cu; ?>"
426  };
427 
428  $.ajax({
429  type: "POST",
430  url: hcuadmOdyMigrServerURL,
431  data: data_hb_info,
432  dataType: "json", // returned data type expected from server
433  })
434  .done(function (response) {
435  var msg = response["message"];
436 
437  if (response["success"] == true) {
438  $("#cuadmin-no-info").removeClass("hidden").addClass("hidden");
439  $("#cuadmin-info").removeClass("hidden");
440 
441  if (response["show_offline_status"] == true) {
442  $("#cuadmin-offlinestat-info").removeClass("hidden");
443  $("#cuadmin-offline-status").text(response["offlinestat"]);
444  } else {
445  $("#cuadmin-offlinestat-info").removeClass("hidden").addClass("hidden");
446  }
447 
448  if(response["CU2_PROCRECUR"] == "CHECKED") {
449  $("#cuadmin-repeating-transfers").text("ON")
450  } else {
451  $("#cuadmin-repeating-transfers").text("OFF")
452  }
453 
454  if (response["CU2_ALLOW_MBR_ALERTS"] == "CHECKED") {
455  $("#cuadmin-alert-processing").text("ON")
456  } else {
457  $("#cuadmin-alert-processing").text("OFF")
458  }
459 
460  } else {
461  $("#cuadmin-info").addClass("hidden");
462  $("#cuadmin-no-info").removeClass("hidden");
463  $("#cuadmin-no-info").text(msg);
464 
465  }
466  }).always(function (response) {
467  if(showHideWaitWindow) {
468  hideWaitWindow();
469  }
470  })
471 }
472 
473 /**
474  * Update status of final migration criterions.
475  */
476 function updateFinalMigrCheckBox(showHideWaitWindow) {
477  if (showHideWaitWindow) {
478  showWaitWindow()
479  }
480  data_lock_unlock = {
481  "post_purpose": "get_final_migr_flag",
482  "cu": "<?php echo $cu; ?>"
483  };
484 
485  $.ajax({
486  type: "POST",
487  url: hcuadmOdyMigrServerURL,
488  data: data_lock_unlock,
489  dataType: "json", // returned data type expected from server
490  })
491  .done(function (response) {
492  if (response["success"] == true) {
493  $("#final-migration-label").removeClass("text-danger");
494  $("#final-migration-label").removeClass("text-success");
495 
496  if (response["final_migr_resp"]["show_final_migr_button"] == true) {
497  $("#final-migration").prop("disabled", false)
498  $("#final-migration-label").html("Ready for Final Migration!");
499  $("#final-migration-label").addClass("text-success");
500 
501  } else {
502  $("#final-migration").prop("disabled", true)
503  $("#final-migration-label").html("NOT Ready for Final Migration!");
504  $("#final-migration-label").addClass("text-danger");
505  }
506 
507  $("#final-migration").prop("checked", false)
508  // update input elements based on the changes in lock/unlock changes
509  handleFinalMigrationCheckboxClick()
510 
511  var true_fa = ' <i class="fa fa-check-square-o text-success"></i>';
512  var false_fa = ' <i class="fa fa-times-rectangle text-danger"></i>'
513 
514  if (response["final_migr_resp"]["SettingsAdminLocked"] == true) {
515  $("#final-mgr-settings-locked").html('1. Are <i>settings</i> & <i>admin</i> migrated & locked?' + true_fa);
516  } else {
517  $("#final-mgr-settings-locked").html('1. Are <i>settings</i> & <i>admin</i> migrated & locked?' + false_fa);
518  }
519 
520  if (response["final_migr_resp"]["memdata_gt0"] == true && response["final_migr_resp"]["memdata_is_clean"] == true) {
521  $("#final-mgr-memdata-ready").html('2. Is <i>memdata</i> ready?' + true_fa);
522  } else {
523  $("#final-mgr-memdata-ready").html('2. Is <i>memdata</i> ready?' + false_fa);
524  }
525  if (response["final_migr_resp"]["memdata_gt0"] == true) {
526  $("#final-mgr-memdata-gt0").html('Tested <i>memdata</i> at least once? <i class="text-success">Yes</i>');
527  } else {
528  $("#final-mgr-memdata-gt0").html('Tested <i>memdata</i> at least once? <i class="text-danger">No</i>');
529  }
530 
531  if (response["final_migr_resp"]["memdata_is_clean"] == true) {
532  $("#final-mgr-memdata-clean").html('Is <i>memdata</i> in clean state? <i class="text-success">Yes</i>');
533  } else {
534  $("#final-mgr-memdata-clean").html('Is <i>memdata</i> in clean state? <i class="text-danger">No</i>');
535  }
536 
537  if (response["final_migr_resp"]["memhist_gt0"] == true && response["final_migr_resp"]["memhist_is_clean"] == true) {
538  $("#final-mgr-memhist-ready").html('3. Is <i>memhist</i> ready?' + true_fa);
539  } else {
540  $("#final-mgr-memhist-ready").html('3. Is <i>memhist</i> ready?' + false_fa);
541  }
542 
543  if (response["final_migr_resp"]["memhist_gt0"] == true) {
544  $("#final-mgr-memhist-gt0").html('Tested <i>memhist</i> at least once? <i class="text-success">Yes</i>');
545  } else {
546  $("#final-mgr-memhist-gt0").html('Tested <i>memhist</i> at least once? <i class="text-danger">No</i>');
547  }
548 
549  if (response["final_migr_resp"]["memhist_is_clean"] == true) {
550  $("#final-mgr-memhist-clean").html('Is <i>memhist</i> in clean state? <i class="text-success">Yes</i>');
551  } else {
552  $("#final-mgr-memhist-clean").html('Is <i>memhist</i> in clean state? <i class="text-danger">No</i>');
553  }
554 
555  if (response["final_migr_resp"]["no_wip_exists"] == true) {
556  $("#final-mgr-nowip").html('4. Any in-progress migration(s)? <i class="text-success">No</i> ' + true_fa);
557  } else {
558  $("#final-mgr-nowip").html('4. Any in-progress migration(s)? <i class="text-danger">Yes</i> ' + false_fa);
559  }
560 
561  if ($("#check-switch-accounts").is(":checked")) {
562  $("#final-mgr-migrate-switchaccounts").html('Is <i>SWITCHACCOUNTS</i> part of final migration?' + ' <i class="text-success">Yes</i>');
563  } else {
564  $("#final-mgr-migrate-switchaccounts").html('Is <i>SWITCHACCOUNTS</i> part of final migration?' + ' <i class="text-danger">No</i>');
565  }
566  }
567  }).fail(function (response) {
568  $("#final-migration").prop("disabled", true)
569  })
570  .always(function (response) {
571  if (showHideWaitWindow) {
572  hideWaitWindow()
573  }
574  });
575 }
576 
577 /**
578  * Lock/unlock toggle Setting and Admin categories deletion
579  */
580 function lockUnlockCatGroupAction(cat_group, lock_or_unlock) {
581  showWaitWindow();
582  data_lock_unlock = {
583  "post_purpose": "lock_unlock_cat_group",
584  "cu": "<?php echo $cu; ?>",
585  "cat_group" : cat_group,
586  "lock_or_unlock": lock_or_unlock
587  };
588 
589  $.ajax({
590  type: "POST",
591  url: hcuadmOdyMigrServerURL,
592  data: data_lock_unlock,
593  dataType: "json", // returned data type expected from server
594  timeout: 60000,
595  })
596  .done(function (response) {
597  msg = response["message"];
598  var alert_level;
599  if(response["success"]) {
600  alert_level = "success"
601  } else {
602  alert_level = "danger";
603  }
604  displayMessageAlert(msg, "add", alert_level);
605  })
606  .always(function (response) {
607  hideWaitWindow();
608  });
609 
610 }
611 
612 /**
613  * Lock/unlock settings: change color to lock state
614  */
615 function changeBtnColorToLock(cat_group, btnId){
616  $(btnId).removeClass("btn-danger");
617  $(btnId).removeClass("btn-success");
618  $(btnId).html('<i class="fa fa-lock"></i> (Unlocked) Click to prevent ' + cat_group + ' deletion.');
619  $(btnId).addClass("btn-danger");
620 }
621 
622 /**
623  * Lock/unlock settings: change color to unlock state
624  */
625 function changeBtnColorToUnlock(cat_group, btnId){
626  $(btnId).removeClass("btn-danger");
627  $(btnId).removeClass("btn-success");
628  $(btnId).html('<i class="fa fa-unlock"></i> (Locked) Click to allow ' + cat_group + ' deletion.');
629  $(btnId).addClass("btn-success");
630 }
631 
632 /**
633  * Lock/unlock settings: toggle lock/unlock button states
634  */
635 function toggleLockUnlock(cat_group){
636  var btnId = "";
637  if (cat_group == "Settings") {
638  btnId = "#lockUnlockSettingsMigrationBtn";
639 
640  } else if (cat_group == "Admin"){
641  btnId = "#lockUnlockAdminMigrationBtn";
642  }
643 
644  if (btnId != "") {
645  $(btnId).click(function() {
646  // print the csv file to a new window
647 
648  if($(btnId).html().includes('Click to prevent ' + cat_group)) {
649  changeBtnColorToUnlock(cat_group, btnId);
650  lockUnlockCatGroupAction(cat_group, "lock");
651  } else {
652  changeBtnColorToLock(cat_group, btnId)
653  lockUnlockCatGroupAction(cat_group, "unlock");
654  }
655  updateFinalMigrCheckBox(true)
656  });
657  }
658 }
659 
660 /**
661  * setup html elements when ready for final migration
662  */
663 function handleFinalMigrationCheckboxClick() {
664  var serversddl = $("#serversDDL").data("kendoDropDownList");
665  var categoriesddl = $("#categoriesDDL").data("kendoDropDownList");
666  var operationsddl = $("#operationsDDL").data("kendoDropDownList");
667 
668  if ($("#final-migration").is(":checked")) {
669  $("#runMigrationBtn").html('<i class="fa fa-plug"></i> Start Final Migration')
670  serversddl.enable(false)
671  categoriesddl.enable(false)
672  operationsddl.enable(false)
673 
674  $("[name='username']").prop("disabled", false).removeClass("k-state-disabled");
675  $("[name='password']").prop("disabled", false).removeClass("k-state-disabled");
676  } else {
677  $("#runMigrationBtn").html('<i class="fa fa-plug"></i> Start')
678  serversddl.enable(true)
679  categoriesddl.enable(true)
680  operationsddl.enable(true)
681  categoriesddl.trigger("change");
682  operationsddl.trigger("change");
683 
684 
685  if (operationsddl.value() == "migrate") {
686  $("[name='username']").prop("disabled", false).removeClass("k-state-disabled");
687  $("[name='password']").prop("disabled", false).removeClass("k-state-disabled");
688  } else {
689  $("[name='username']").prop("disabled", true).addClass("k-state-disabled");
690  $("[name='password']").prop("disabled", true).addClass("k-state-disabled");
691  }
692  }
693 }
694 
695 /**
696  * Reset migration state: cleanup memdata and lock files
697  */
698 function resetMigrationState() {
699  showWaitWindow();
700  data_reset_migr_state = {
701  "post_purpose": "reset_migration_state",
702  "cu": "<?php echo $cu; ?>"
703  };
704 
705  $.ajax({
706  type: "POST",
707  url: hcuadmOdyMigrServerURL,
708  data: data_reset_migr_state,
709  dataType: "json", // returned data type expected from server
710  timeout: 0
711  })
712  .done(function (response) {
713  msg = response["message"];
714  var alert_level;
715  if(response["success"]) {
716  alert_level = "success"
717  showFinalMigrationElements(msg)
718  UpdateMigrationOptions(false)
719 
720  } else {
721  alert_level = "danger";
722  }
723  displayMessageAlert(msg, "add", alert_level);
724  })
725  .always(function (response) {
726  hideWaitWindow();
727  });
728 
729 
730 }
731 /**
732  * Display completed logs with no side effects.
733  */
734 function fetchCompletedLogHistory(category, operation) {
735  showWaitWindow()
736  var server = $("#serversDDL").data("kendoDropDownList").value();
737  data_log_history = {
738  "post_purpose": "fetch_log_history_only",
739  "cu": "<?php echo $cu; ?>",
740  "category": category,
741  "operation": operation
742  };
743  $.ajax({
744  type: "POST",
745  url: hcuadmOdyMigrServerURL,
746  data: data_log_history,
747  dataType: "json", // returned data type expected from server
748  async: "false"
749  })
750  .done(function (response) {
751  alert_msg = response["message"];
752  alert_level = "success";
753  var log_header_prefix = getAlertPrefix(category, operation, false);
754  $("#current-log-header").html(log_header_prefix)
755  if (response["success"] == true) {
756  var logs_content = response["log_content"]
757  var file_does_not_exist = response["does_not_exist"];
758  // if log file EXISTS
759  if (file_does_not_exist == false) {
760  setMonitorLogArea()
761  // iterate through each line of the log file
762  for (lg_index in logs_content) {
763  lg_line = logs_content[lg_index]
764  // if error
765  if (lg_line.includes("ERROR")) {
766  lg_line_color = "danger"
767  }
768  // if warning/critical
769  else if(lg_line.includes("WARNING")){
770  lg_line_color = "warning"
771  }
772  // normal log
773  else {
774  lg_line_color = "success"
775  }
776  // prepare display format of this particular log
777  lg_line = '<div class="text-' + lg_line_color + '"><i class="fa fa-chevron-circle-right"></i> '
778  + lg_line + '</div><br>'
779  // add log line to the log displaying div
780  if (lg_index == 0) {
781  $("#logs-textarea").html(lg_line)
782  } else {
783  $("#logs-textarea").append(lg_line)
784  }
785  }
786  }
787  } else {
788  alert_level = "danger";
789  }
790  displayMessageAlert(alert_msg, "add", alert_level);
791  })
792  .fail(function (response) {
793  console.log(response);
794  })
795  .always(function (response) {
796  hideWaitWindow();
797  });
798 }
799 
800 /**
801  * define handlers for click events of all the click-able
802  * elements in the Migration page
803  */
804 function handleClickEvents() {
805 
806  /**
807  * Anonymous jQuery function
808  * Event handler for delete history button in Migration Settings
809  */
810  <?php if(IsDevMode()) { ?>
811  $("#deleteSelectedCategoriesBtn").on("click", function() {
812  kendo.confirm("Are you sure you want to clean up selected categories?")
813  .then(
814  function () {
815  cleanUpSelectedCategories();
816  },
817  function() {
818  console.log("Cancel clean up selected categories action!")
819  })
820  })
821  <?php } ?>
822 
823  /**
824  * Anonymous jQuery function
825  * Event handler for delete history button in Migration Settings
826  */
827  $("#updatePublicHtml").on("click", function() {
828  server = $("#serversDDL").data("kendoDropDownList").value();
829  kendo.confirm("Are you sure you want to update public_html embedded links?")
830  .then(
831  function () {
832  updatePublicHtmlResources(server);
833  },
834  function() {
835  console.log("Cancel delete history action!")
836  })
837  })
838 
839  $("#accountCrossRefBtn").on("click", function() {
840  // print the csv file to a new window
841  window.open(hcuadmOdyMigrServerURL + "?get_purpose=acc_cross_ref&cu=<?php echo $cu; ?>", "Cross Account");
842  })
843 
844  toggleLockUnlock("Settings");
845  toggleLockUnlock("Admin");
846 
847  /*
848  * Anonymous jQuery function
849  * Event handler for fetching log for all the previously ran migration processes
850  */
851  $("#get-log-history").click(function() {
852  var option = $("#loghistoryDDL").data("kendoDropDownList").value();
853  var res = option.split("-");
854  var operation = res[0];
855  var category = res[1];
856  // fetch log
857  fetchCompletedLogHistory(category, operation);
858  });
859 
860 
861  /*
862  * Event handler for "Start" or "Start Final Migration" button.
863  * When enabled, and clicked, this event executes regular or final migration
864  * operation of all the available categories
865  */
866  $("#runMigrationBtn").on("click", function() {
867  if ($.homecuValidator.validate()) {
868  var server = $("#serversDDL").data("kendoDropDownList").value().trim();
869  var category = $("#categoriesDDL").data("kendoDropDownList").value().trim();
870  var operation = $("#operationsDDL").data("kendoDropDownList").value().trim();
871  var cu = "<?php echo strtoupper($cu); ?>";
872 
873  var confirmation_msg = "<b class='text-info'>[Regular Migration Operation] Please confirm that you want to perform '" + operation + "-" + category + "' for " + cu + ".</b>";
874  var is_final_migr = false;
875 
876  if ($("#final-migration").is(":checked")) {
877  is_final_migr = true;
878 
879  confirmation_msg = "<b class='text-info'>[Final Migration] Data categories to be migrated: 'memdata', 'memhist', ['loanapp']";
880 
881  if ($("#check-switch-accounts").is(":checked")) {
882  confirmation_msg += ", 'switchaccounts'";
883  }
884 
885  confirmation_msg += ". Credit Union: " + cu + ". Please confirm.</b>";
886  }
887 
888  if (server == "") {
889  displayMessageAlert("Invalid input. Source Server cannot be empty. ", "add", "danger")
890  } else {
891  kendo.confirm(confirmation_msg)
892  .then(function () {
893  var username = $("[name='username']").val().trim();
894  // base64 decode - to avoid passing raw password values
895  // inside the application
896  var password = btoa($("[name='password']").val().trim());
897 
898  var migr_initiated = true;
899  $("#runMigrationBtn").prop("disabled", true)
900 
901  // final migration operations (memdata + memhist)
902  if (is_final_migr == true) {
903  category = "memdata"
904  operation = "migrate"
905  showWaitWindow()
906  var initiateMigrationAjaxCallerObject = InitFinalMigrationOperation(server, username, password);
907  }
908  // regular one migration operation at a time
909  else {
910  if (category != "" && operation != "") {
911  var initiateMigrationAjaxCallerObject = InitMigrationOperation(server, operation, category, username, password);
912  } else {
913  migr_initiated = false;
914  displayMessageAlert("You must provide both data category and data operation input. ", "add", "danger")
915  }
916 
917  }
918  if (migr_initiated == true) {
919  initiateMigrationAjaxCallerObject
920  .done(function (response) {
921  var alert_prefix = getAlertPrefix(category, operation, true);
922  var alert_level;
923  var msg = response["message"]
924  if (response["success"] == true) {
925  if(is_final_migr == true) {
926  $("#final-migration-checklist-wrapper").css('display', 'none')
927  }
928  disableSettingsButtonsSetTo(true);
929  autoRefreshLog(category, operation, is_final_migr);
930  alert_level = "success";
931  } else {
932  updateStartButtonVisibleStatus(false)
933  alert_level = "danger";
934  }
935  displayMessageAlert(alert_prefix + msg, "add", alert_level)
936  })
937  }
938  },
939  function () {
940  updateStartButtonVisibleStatus(false)
941  });
942  }
943  } else {
944  displayMessageAlert("Invalid input. ", "add", "danger")
945  updateStartButtonVisibleStatus(false)
946  }
947 
948  });
949 
950  /*
951  * Anonymous jQuery function
952  * Event handler for migration settings button that toggles the text and shows/hides monitor UI access disable option.
953  */
954  $("#migration-settings").click(function() {
955  $('#check-migration').prop('checked', false);
956  $("#disable-migration-button").attr("disabled", "disabled");
957 
958  $(this).html($(this).html().includes("Show Settings") ? '<i class="fa fa-cogs"></i> Hide Settings': '<i class="fa fa-cogs"></i> Show Settings');
959  $("#settings").toggle();
960  });
961 
962  /*
963  * Anonymous jQuery function
964  * Event handler responsible for disabling the monitor UI .
965  */
966  $("#disable-migration-button").click(function() {
967  kendo.confirm("<b class='text-danger'> [DANGER ZONE]</b> This will lock the whole migration screen. If this is your first time, please contact a developer if you are unsure about this. Please do not proceed unless you are 200% sure. <br><br><b class='text-danger'>Confirming this means that we are past 'Go Live' day and data migrations have been fully completed for '<?php echo strtoupper($cu); ?>' credit union. </br>This ONLY deletes temporary files created during the MIGRATION process, and DOES NOT/MUST NOT touch anything related to PRODUCTION data on the DATABASE.</b> ")
968  .then(
969  function () {
970  resetIntervalAutoLogFetch()
971  disableMigrationMonitor()
972  })
973 
974  });
975 
976  /*
977  * Anonymous jQuery function
978  * Event handler for a checkbox to confirm the monitor UI disable operation.
979  */
980  $("#check-migration").click(function(){
981  if ($(this).is(":checked")) {
982  $("#disable-migration-button").removeAttr("disabled");
983  } else {
984  $("#disable-migration-button").attr("disabled", "disabled");
985  }
986  });
987 
988  /*
989  * Anonymous jQuery function
990  * Event handler for a checkbox to confirm the monitor UI disable operation.
991  */
992  $("#final-migration").click(function(){
993  handleFinalMigrationCheckboxClick()
994  });
995 
996  $("#check-switch-accounts").on("click", function() {
997  handleSwitchAccountsLoanAppsSetting("switchaccounts", "toggle_setting", true)
998  })
999 
1000  <?php if(IsDevMode()) { ?>
1001  $("#resetFinalMigration").click(function(){
1002  kendo.confirm("<b class='text-danger'> [DANGER ZONE]</b> Seeing this in PRODUCTION environment? This operation IS NOT INTENDED to be used in production environment. Please contact a developer. <br><br><b class='text-danger'>Consequences: This will DELETE EVERYTHING but settings and admin.</b> You will LOSE ALL Members, Switch Accounts, Loanapps and Member History data that you may have migrated earlier.")
1003  .then(
1004  function () {
1005  resetMigrationState()
1006  })
1007  });
1008  <?php } ?>
1009 
1010 }
1011 
1012 /**
1013  * This function sets up all the controls and includes event handlers for some important elements in the migration screen.
1014  */
1015 function SetUp() {
1016  // initialize kendo UI elements
1017  initializeKendoElements();
1018 
1019  // display migration UI
1020  $("#migrationDiv").removeClass("hidden");
1021  // setUp form validation - kendo-ui
1022  $.homecuValidator.setup({formValidate: "migrationDiv", formStatusField: "migrationStatusDiv"});
1023  // initial state of the containers, buttons and message holders
1024  $("#migrationDisableMsgDiv").addClass("hidden");
1025  $("#disable-migration-button").prop("disabled", true);
1026  $("#settings").hide();
1027 
1028  resetMonitorLogArea()
1029 
1030  // retrieve settings to whether or not to
1031  // migrate switchaccounts
1032  handleSwitchAccountsLoanAppsSetting("switchaccounts", "get_setting", false);
1033 
1034  // update servers data source
1035  populateServerList(false);
1036 
1037  // update operations data source
1038  setUpOperationsDDL("all", "init");
1039 
1040  // update categories data source
1041  updateDataCategoriesList(false);
1042 
1043  handleMigrationOnPageLoad(false)
1044 
1045  // define anonymous jquery functions to handle click events
1046  handleClickEvents()
1047 }
1048 
1049 /**
1050  * Utility function to clear/reset log fetch interval
1051  */
1052 function resetIntervalAutoLogFetch() {
1053  if (fetchLogIntervalVar != undefined) {
1054  clearInterval(fetchLogIntervalVar)
1055  fetchLogIntervalVar = undefined;
1056  }
1057 }
1058 
1059 /**
1060  * Main function that initiates log file sync.
1061  *
1062  * Mainly applies to in-progress or just started "migrate" operation. First log fetch is always
1063  * called after a few seconds after the migration script is executed to allow the migration
1064  * script to write initial logs in the appropriate log file.
1065  */
1066 function autoRefreshLog(category, operation, is_final_migr) {
1067  $("#runMigrationBtn").prop("disabled", true)
1068 
1069  <?php if(IsDevMode()) { ?>
1070  $("#resetFinalMigration").prop("disabled", true)
1071  <?php } ?>
1072 
1073  var final_migr_include_sa = false;
1074  // always include loanapps
1075  var final_migr_include_loanapps = true;
1076 
1077  // check whether or not to include switchaccounts in final migration
1078  if (is_final_migr) {
1079  if($("#check-switch-accounts").is(":checked")) {
1080  final_migr_include_sa = true;
1081  }
1082  }
1083 
1084  // applies to "migrate" operation
1085  var show_progressbar = true;
1086 
1087  // wait for firstLogFetchOffsetTime seconds to let the recent migration script start writing logs to a file,
1088  // otherwise it will read old log or throw error for not finding a file
1089  setTimeout( function() { fetchMigrationLog(show_progressbar,
1090  category,
1091  operation,
1092  is_final_migr,
1093  final_migr_include_sa,
1094  final_migr_include_loanapps); }, firstLogFetchOffsetTime * 1000 );
1095 
1096  var alert_msg = "Logs will be auto-refreshed every " + refreshWindow + " seconds until " + "'" + operation + "-" + category + "' completes!";
1097  if (is_final_migr) {
1098  displayMessageAlert("[Final Migration] " + alert_msg, "add", "success")
1099  } else {
1100  displayMessageAlert("[Regular Migration]" + alert_msg, "add", "success")
1101  }
1102  resetIntervalAutoLogFetch()
1103  // set time interval to periodically fetch log content
1104  fetchLogIntervalVar = setInterval( function() { fetchMigrationLog(show_progressbar,
1105  category,
1106  operation,
1107  is_final_migr,
1108  final_migr_include_sa,
1109  final_migr_include_loanapps); },
1110  refreshWindow * 1000 );
1111 }
1112 
1113 /**
1114  * Utility function to reload current page
1115 */
1116 function reloadPage() {
1117  location.reload();
1118 }
1119 
1120 /**
1121  * A function to disable migration monitor.
1122  *
1123  * The post request creates a '.ody_migr_monitor_lock' file in the /home/<cu>/tmp/ folder.
1124  *
1125  * * ****IMPORTANT: CAUTION CAUTION CAUTION****
1126  *
1127  * THIS AJAX CALL INVOKES A FUNCTION (in ody_migr_server.prg). PLEASE
1128  * DO NOT ADD ANY CODE THAT WILL DELETE ANY DATABASE RELATED DATA ON
1129  * BOTH THE CLIENT AND SERVER SIDES. AT THIS POINT, WE ARE DONE
1130  * MIGRATING PRODDUCTION DATA FROM MAMMOTH TO ODYSSEY AND WE CERTAINLY
1131  * DON'T WANT TO MESS AROUND WITH THE MIGRATED DATA ON THE DATABASE
1132  * AFTER THE FINAL DATA MIGRATION.
1133 */
1134 function disableMigrationMonitor() {
1135  var server = $("#serversDDL").data("kendoDropDownList").value();
1136  data_disable_monitor = {
1137  "post_purpose": "disable_monitor",
1138  "cu": "<?php echo $cu; ?>",
1139  "server": server
1140  };
1141 
1142  $.ajax({
1143  type: "POST",
1144  url: hcuadmOdyMigrServerURL,
1145  data: data_disable_monitor,
1146  dataType: "json", // returned data type expected from server
1147  })
1148  .done(function (response) {
1149  var msg;
1150  if (response["success"] == true) {
1151  msg = response["message"] + " Lock file location: '<?php echo $migrationMonitorLock; ?>'!"
1152  $("#migrationDiv").addClass("hidden");
1153  } else {
1154  msg = response["message"] + " Lock file's expected location is: '<?php echo $migrationMonitorLock; ?>'!"
1155  }
1156  $("#migrationDisableMsgDiv").text(msg)
1157  $("#migrationDisableMsgDiv").removeClass("hidden");
1158  })
1159  .fail(function (response) {
1160  console.log(response);
1161  })
1162 }
1163 
1164 /**
1165  * A function that creates and updates kendo-ui progress bar for in-progress migration.
1166  *
1167  * Only applies to "migrate" data migration operation.
1168  */
1169  function updateProgressBar(operation_value, category_value, progress_status, progress_text, update_pb_flag) {
1170  if(update_pb_flag) {
1171  if (operation_value == "migrate" && category_value =="memdata") {
1172  //$("#progress-bar-container").removeClass('hidden');
1173  if(progress_status["total"] == 0) {
1174  $("#progress-bar-text").html("<strong class='text-success'>Please wait, collecting progress stats... " + progress_text + "</strong>")
1175  }
1176  else {
1177  $("#progress-bar-container").removeClass('hidden');
1178  var progressbar = $("#progressbar").data("kendoProgressBar");
1179  if (progressbar == undefined) {
1180  $("#progressbar").kendoProgressBar({
1181  min: 0,
1182  max: progress_status["total"],
1183  type: "percent",
1184  orientation: "horizontal",
1185  complete: function(e) {
1186  $("#progress-bar-text").html("<strong class='text-success'>Migration completed! " + progress_text + "</strong>")
1187  },
1188  animation: {
1189  duration: 600
1190  }
1191  });
1192  progressbar = $("#progressbar").data("kendoProgressBar");
1193  }
1194  $("#progress-bar-text").html("<strong class='text-info'>Migration in-progress: " + progress_text + "</strong>")
1195  progressbar.value(progress_status["current"])
1196  }
1197  } else {
1198  //$("#progress-bar-container").removeClass('hidden');
1199  $("#progress-bar-container").addClass('hidden')
1200  }
1201  } else {
1202  //$("#progress-bar-container").removeClass('hidden');
1203  $("#progress-bar-container").addClass('hidden');
1204  }
1205 
1206 }
1207 
1208 /**
1209  * Switchaccount settings: update checked/unchecked status of the setting
1210  * using the lock file
1211  */
1212 function handleSwitchAccountsLoanAppsSetting(entity, action, showHideWaitWindow) {
1213  $("#check-switch-accounts").prop("disabled", true);
1214 
1215  if(showHideWaitWindow) {
1216  showWaitWindow()
1217  }
1218  data_sa_setting = {
1219  "post_purpose": "handle_switchaccounts_setting",
1220  "cu": "<?php echo $cu; ?>",
1221  "action": action, // get_setting or toggle_setting
1222  "entity": entity // switchaccounts
1223  }
1224  $.ajax({
1225  type: "POST",
1226  url: hcuadmOdyMigrServerURL,
1227  data: data_sa_setting,
1228  dataType: "json",
1229  async: false
1230  }).done(function (response) {
1231 
1232  if (entity == "switchaccounts") {
1233  var settingsElemId = $("#check-switch-accounts");
1234  }
1235 
1236  if (action == "get_setting") {
1237  if(response["success"] == true) {
1238  settingsElemId.prop('checked', response["include_or_not"])
1239  }
1240  } else { // toggle_setting
1241  if(response["success"] == true) {
1242  if(settingsElemId.is(":checked")) {
1243  if (entity == "switchaccounts") {
1244  displayMessageAlert("Settings Changed: Switch accounts INCLUDED in final migration.", "add", "success");
1245  $("#final-mgr-migrate-switchaccounts").html('Is <i>SWITCHACCOUNTS</i> part of final migration?' + ' <i class="text-success">Yes</i>');
1246  }
1247  } else {
1248  if (entity == "switchaccounts") {
1249  displayMessageAlert("Settings Changed: Switch accounts EXCLUDED in final migration.", "add", "success");
1250  $("#final-mgr-migrate-switchaccounts").html('Is <i>SWITCHACCOUNTS</i> part of final migration?' + ' <i class="text-danger">No</i>');
1251  }
1252  }
1253  }
1254  }
1255  }).always(function (response) {
1256  fetchWIPAndDoneList(false, false);
1257  updateDataCategoriesList(false);
1258  $("#check-switch-accounts").prop("disabled", false);
1259  if(showHideWaitWindow) {
1260  hideWaitWindow()
1261  }
1262  })
1263 }
1264 
1265 /**
1266  * This function disables (resets) html form elements used for execution migration.
1267  */
1268 function disableMigrationInputForm(){
1269  $("[name='username']").prop("disabled", true).addClass("k-state-disabled");
1270  $("[name='password']").prop("disabled", true).addClass("k-state-disabled");
1271  $("#serversDDL").data("kendoDropDownList").enable(false)
1272  $("#operationsDDL").data("kendoDropDownList").enable(false)
1273  $("#categoriesDDL").data("kendoDropDownList").enable(false)
1274  $("#wipDDL").data("kendoDropDownList").enable(false)
1275 }
1276 
1277 /**
1278  * This function sets html form elements used for execution migration.
1279  */
1280 function setHtmlFormElements(){
1281  $("[name='username']").prop("disabled", false).removeClass("k-state-disabled");
1282  $("[name='password']").prop("disabled", false).removeClass("k-state-disabled");
1283  $("#serversDDL").data("kendoDropDownList").enable(true)
1284  $("#operationsDDL").data("kendoDropDownList").value("migrate")
1285  $("#categoriesDDL").data("kendoDropDownList").value("settings")
1286  $.homecuValidator.setup({formValidate: "migrationDiv", formStatusField: "migrationStatusDiv"});
1287 }
1288 
1289 /**
1290  * enable/disable settings buttons
1291  */
1292 function disableSettingsButtonsSetTo(flag) {
1293  var settingsIds = ["lockUnlockSettingsMigrationBtn",
1294  "lockUnlockAdminMigrationBtn", "deleteSelectedCategoriesBtn",
1295  "check-switch-accounts", "runMigrationBtn"]
1296 
1297  for (settingIndex in settingsIds) {
1298  $("#" + settingsIds[settingIndex]).prop("disabled", flag)
1299  }
1300 }
1301 
1302 function getCurrentDateTime() {
1303  var now = new Date().toLocaleString("en-US", {timeZone: "America/Boise"});
1304  return " (Last displayed: " + now + " MST)";
1305 }
1306 
1307 /**
1308 * Display static message about the status of migration operations
1309 */
1310 function displayStaticMigrationStatus(is_final_migr, operation_value, category_value,
1311  migr_state) {
1312  if (migr_state == "inprogress") {
1313  migr_state = " is in progress";
1314  } else if (migr_state == "completed") {
1315  migr_state = " has completed";
1316  }
1317  var op_suffix = " '" + operation_value + "-" + category_value + "' " + migr_state + ". ";
1318  var msg_static = "[Regular Migration]" + op_suffix;
1319  if (is_final_migr) {
1320  var msg_static = "[Final Migration]" + op_suffix;
1321  }
1322  $("#finalMigrationStatusDiv").html("<u><b>" + msg_static + getCurrentDateTime() + "</b></u>");
1323 }
1324 
1325 /**
1326  * Show/enable final migration related elements
1327  */
1328 function showFinalMigrationElements(msg) {
1329  $("#finalMigrationStatusDiv").html("<u><b>" + msg + getCurrentDateTime() + "</b></u>");
1330  $("#final-migration-checklist-wrapper").css('display', 'block')
1331  setHtmlFormElements()
1332  disableSettingsButtonsSetTo(false)
1333 }
1334 
1335 /**
1336  * Hide/disable final migration related elements
1337  */
1338 function hideFinalMigrationElements(msg, final_migr_status) {
1339  FetchLogsHistoryList(false);
1340  fetchWIPAndDoneList(false, true)
1341 
1342  $("#finalMigrationStatusDiv").html("<u><b>" + msg + getCurrentDateTime() + "</b></u>");
1343  $("#final-migration-checklist-wrapper").css('display', 'none')
1344 
1345  updateHomeBankingInfoText(false);
1346  <?php if(IsDevMode()) { ?>
1347  $("#deleteAllCleanUpList").data("kendoMultiSelect").setDataSource([])
1348  <?php } ?>
1349  disableSettingsButtonsSetTo(true)
1350  disableMigrationInputForm()
1351  if (final_migr_status == "completed") {
1352  $("#accountCrossRefBtn").prop("disabled", false);
1353  $("#migration-settings").prop("disabled", false);
1354  <?php if(IsDevMode()) { ?>
1355  $("#resetFinalMigration").prop("disabled", false);
1356  <?php } ?>
1357  } else if (final_migr_status == "inprogress") {
1358  $("#accountCrossRefBtn").prop("disabled", true);
1359  }
1360 
1361 }
1362 
1363 /**
1364  * Handle regular or final migration process on page load
1365  */
1366 function handleMigrationOnPageLoad(showHideWaitWindow) {
1367  if(showHideWaitWindow) {
1368  showWaitWindow()
1369  }
1370  data_complete_onload = {
1371  "post_purpose": "manage_migration_state",
1372  "cu": "<?php echo $cu; ?>",
1373  "final_migration_when": "on_pageload"
1374  }
1375  $.ajax({
1376  type: "POST",
1377  url: hcuadmOdyMigrServerURL,
1378  data: data_complete_onload,
1379  dataType: "json",
1380  async: false
1381  }).done(function (response) {
1382  var msg = response["message"]
1383  if (response["success"] == true) {
1384 
1385  var final_migr_status = response["migr_status"]
1386  var migr_type = response["migr_type"]
1387 
1388  if (final_migr_status == "completed") {
1389  // this should be after completion of memhist of final migration
1390  hideFinalMigrationElements(msg, final_migr_status)
1391  }
1392 
1393  else if (final_migr_status == "inprogress") {
1394  var inprogress_op_cat = response["inprogress_category"]
1395  var op_cat_arr = inprogress_op_cat.split("-")
1396  var inprogress_operation= op_cat_arr[0];
1397  var inprogress_category = op_cat_arr[1];
1398  if (migr_type == "final") {
1399  hideFinalMigrationElements(msg, final_migr_status)
1400  autoRefreshLog(inprogress_category, inprogress_operation, true);
1401  } else {
1402  $("#final-migration-checklist-wrapper").css('display', 'block');
1403  autoRefreshLog(inprogress_category, inprogress_operation, false);
1404  }
1405  }
1406 
1407  else if (final_migr_status == "invalid") {
1408  hideFinalMigrationElements(msg, final_migr_status)
1409  displayMessageAlert(msg, "add", "danger")
1410  }
1411  // normalstart
1412  else {
1413  UpdateMigrationOptions(false)
1414  showFinalMigrationElements(msg)
1415  displayMessageAlert(msg, "add", "success")
1416  }
1417  } else {
1418  hideFinalMigrationElements(msg, "invalid")
1419  displayMessageAlert(msg, "add", "danger")
1420  }
1421  }).always(function (response) {
1422  if(showHideWaitWindow) {
1423  hideWaitWindow()
1424  }
1425  })
1426 }
1427 
1428 /**
1429  * Handle final migration process on completion
1430  */
1431 function wrapUpFinalMigration() {
1432  showWaitWindow()
1433  data_complete_final = {
1434  "post_purpose": "manage_migration_state",
1435  "cu": "<?php echo $cu; ?>",
1436  "final_migration_when": "on_completion"
1437  }
1438  $.ajax({
1439  type: "POST",
1440  url: hcuadmOdyMigrServerURL,
1441  data: data_complete_final,
1442  dataType: "json"
1443  })
1444  .done(function (response) {
1445  var msg = response["message"]
1446 
1447  if (response["success"] == false) {
1448  displayMessageAlert(msg, "add", "danger")
1449  } else {
1450  displayMessageAlert(msg, "add", "success")
1451  }
1452  hideFinalMigrationElements(response["message"], "completed")
1453 
1454  }).always(function (response) {
1455  displayMessageAlert("Completing FINAL Migration. ", "add", "success")
1456  $("#runMigrationBtn").html('<i class="fa fa-plug"></i> Start')
1457  $("#runMigrationBtn").prop("disabled", true)
1458  hideWaitWindow()
1459  })
1460 }
1461 
1462 function getAlertPrefix(category_value, operation_value, fetch_during_migration) {
1463  if (fetch_during_migration == true) {
1464  return "<b><u>["+ category_value.toUpperCase() + "-" + operation_value.toUpperCase() + "-" + "<?php echo strtoupper($cu); ?>" + "] </b></u>"
1465  } else {
1466  return "<b><u>[SHOWING LOG HISTORY]["+ category_value.toUpperCase() + "-" + operation_value.toUpperCase() + "-" + "<?php echo strtoupper($cu); ?>" + "] </b></u>"
1467  }
1468  }
1469 
1470 /**
1471  * Get next category to migrate for final migration
1472  * final_migr_include_loanapps is always configred to be true
1473  */
1474 function getNextFinalMigrationCategory(completed_category,
1475  final_migr_include_sa,
1476  final_migr_include_loanapps) {
1477  var next_migr = "memhist";
1478 
1479  if (completed_category == "memdata") {
1480  if (final_migr_include_sa) {
1481  next_migr = "switchaccounts";
1482  } else if (final_migr_include_loanapps) {
1483  next_migr = "loanapp";
1484  }
1485  // else { next_migr = memhist }
1486  } else if (completed_category == "switchaccounts") {
1487  if (final_migr_include_loanapps) {
1488  next_migr = "loanapp";
1489  }
1490  // else { next_migr = memhist }
1491  }
1492  // else { next_migr = memhist }
1493 
1494  return next_migr;
1495 }
1496 
1497 /**
1498  * Also migrate switchaccounts, loanapp as a part of final migration
1499  */
1500 function startMemhistAndSwitchAccsForFinalMigration(category) {
1501  data_memhist_sa_wip = {
1502  "post_purpose": "start_memhist_sa_wip_for_final_migration",
1503  "cu": "<?php echo $cu; ?>",
1504  "category": category,
1505  }
1506  $.ajax({
1507  type: "POST",
1508  url: hcuadmOdyMigrServerURL,
1509  data: data_memhist_sa_wip,
1510  dataType: "json",
1511  async: false
1512  })
1513  .done(function (response) {
1514  if (response["success"] == false) {
1515  displayMessageAlert(response["message"], "add", "danger")
1516  }
1517  })
1518 }
1519 
1520 /**
1521  * Main function to make a post request, read log file, parse log content, display logs in appropriate
1522  * containers and update migration progress.
1523  *
1524  * @param show_progressbar flag to display/update progressbar or not
1525  * @param category_value data migration category
1526  * @param operation_value data migration operation
1527 */
1528  function fetchMigrationLog(show_progressbar, category_value, operation_value,
1529  is_final_migr, final_migr_include_sa,
1530  final_migr_include_loanapps) {
1531 
1532  if (is_final_migr == false) {
1533  updateStartButtonVisibleStatus(false)
1534  }
1535 
1536  // show wait window
1537  showWaitWindow();
1538  // get alert prefix
1539  var alert_prefix = getAlertPrefix(category_value, operation_value, true);
1540  // update header of log monitoring area
1541  $("#current-log-header").html(alert_prefix)
1542 
1543  // data to post, post_purpose is part of every ajax call in this javascript file
1544  data_fetch_log = {
1545  "post_purpose": "fetch_log",
1546  "cu": "<?php echo $cu; ?>",
1547  "operation": operation_value,
1548  "category": category_value
1549  };
1550 
1551  error = false;
1552 
1553  // ajax call
1554  $.ajax({
1555  type: "POST",
1556  url: hcuadmOdyMigrServerURL,
1557  data: data_fetch_log,
1558  dataType: "json" // returned data type expected from server
1559  })
1560  .done(function(response) {
1561  alert_msg = alert_prefix + response["message"];
1562  var alert_level;
1563  warning = false;
1564 
1565  if (response["success"] == true) {
1566  // fetch response data
1567  var logs_content = response["log_report"]["log_content"]
1568  var end_of_migration = response["log_report"]["end_of_log"]
1569  var progress_status = response["log_report"]["progress_status"]
1570  var file_does_not_exist = response["log_report"]["does_not_exist"];
1571  var migration_status = "inprogress";
1572 
1573  // if log file EXISTS
1574  if (file_does_not_exist == false) {
1575 
1576  // halt on error
1577  halt_fetching = false
1578  // iterate through each line of the log file
1579  for (lg_index in logs_content) {
1580  lg_line = logs_content[lg_index]
1581 
1582  // if error
1583  if (lg_line.includes("ERROR")) {
1584  lg_line_color = "danger"
1585  error = true;
1586  var arr_lg_error = lg_line.split("::")
1587  alert_msg += "<br> "+ alert_prefix +"Encountered ERROR(S)! "
1588  + arr_lg_error[arr_lg_error.length-1].trim()
1589  migration_status = "encountered ERROR(s). Refer to the log file '" +
1590  operation_value + "-" + category_value + "'"
1591  halt_fetching = true
1592  }
1593  // if warning/critical
1594  else if(lg_line.includes("WARNING")){
1595  lg_line_color = "warning"
1596  warning = true;
1597  var arr_lg_warning = lg_line.split("::");
1598  var lg_line_warning = arr_lg_warning[arr_lg_warning.length - 1]
1599  if(!lg_line_warning.includes("Relaxing validation")) {
1600  alert_msg = alert_prefix + "WARNING(S)! " + lg_line_warning
1601  }
1602  }
1603  // normal log
1604  else {
1605  lg_line_color = "success"
1606  }
1607 
1608  if(lg_line.includes("MIGRATION DONE")){
1609  lg_line_color = "success"
1610  warning = false
1611  alert_msg = alert_prefix + "Migration operation '"
1612  + operation_value + "-" + category_value+"' COMPLETED! "
1613  }
1614 
1615 
1616  // prepare display format of this particular log
1617  lg_line = '<div class="text-' + lg_line_color + '"><i class="fa fa-chevron-circle-right"></i> '
1618  + lg_line + '</div><br>'
1619 
1620  // add log line to the log displaying div
1621  if (lg_index == 0) {
1622  $("#logs-textarea").html(lg_line)
1623  } else {
1624  $("#logs-textarea").append(lg_line)
1625  }
1626 
1627  // if error, reset log sync and delete work-in-progress lock file and terminate log fetching.
1628  if (halt_fetching) {
1629  resetIntervalAutoLogFetch()
1630  // also handle error encountered during final migration execution (eg. wrong password)
1631  deleteWIPMigrateLock(operation_value, category_value, is_final_migr);
1632 
1633  if (is_final_migr) {
1634  // if this is final migration, enable the migration elements
1635  // so that it can be executed again; lock files are handled
1636  // on the server side
1637  showFinalMigrationElements(migration_status);
1638  }
1639  break
1640  }
1641  }
1642  if (halt_fetching == false) {
1643  updateProgressBar(operation_value, category_value,
1644  progress_status, alert_prefix, show_progressbar)
1645  }
1646  // check if this migration already completed
1647  // wip file would already have marked as done
1648  if (end_of_migration == true) {
1649  // clear log interval if migration completed
1650  resetIntervalAutoLogFetch()
1651 
1652  // HANDLE Final Migration Part
1653  if (is_final_migr == true && operation_value == "migrate") {
1654  // Exec sequence: memdata -> switchaccounts (if configured) -> loanapp (if configured) -> memhist
1655 
1656  // do the following when memdata completes as a part of final migration
1657  if (category_value == "memdata") {
1658  setTimeout( function() { $("#progress-bar-container").addClass('hidden'); },
1659  hideProgressBar * 1000);
1660  }
1661 
1662  // do the following when memdata/switchaccounts/loanapp completes
1663  if (category_value == "memdata"
1664  || category_value == "switchaccounts"
1665  || category_value == "loanapp") {
1666 
1667  // select next migration category (switchaccounts/loanapp/memhist) to migrate next
1668  var next_migr = getNextFinalMigrationCategory(category_value,
1669  final_migr_include_sa,
1670  final_migr_include_loanapps);
1671 
1672  // create a wip file for next_migr
1673  startMemhistAndSwitchAccsForFinalMigration(next_migr);
1674 
1675  // always show log displaying div
1676  setMonitorLogArea();
1677 
1678  hideFinalMigrationElements("[Final Migration] 'migrate-" + category_value
1679  + "' completed. Starting 'migrate-" + next_migr + "'", "inprogress");
1680 
1681  // start fetching next_migr, set wip
1682  // start fetching next_migr logs after 3 seconds
1683  setTimeout( function() { autoRefreshLog(next_migr, operation_value, true); }, 3000);
1684  }
1685 
1686  // do the following when memhist completes
1687  else {
1688  hideWaitWindow()
1689  wrapUpFinalMigration()
1690  }
1691  }
1692  // HANDLE Regular one-at-a-time {migrate,summary,clean} Operations
1693  else {
1694  if (category_value == "memdata"
1695  && operation_value == "clean") {
1696  $("#accountCrossRefBtn").prop("disabled", true);
1697  }
1698  if (category_value == "memdata" && operation_value == "migrate") {
1699  setTimeout( function() { $("#progress-bar-container").addClass('hidden'); }, hideProgressBar * 1000)
1700  }
1701  displayStaticMigrationStatus(is_final_migr,
1702  operation_value,
1703  category_value,
1704  "completed")
1705  }
1706  } else {
1707  displayStaticMigrationStatus(is_final_migr, operation_value,
1708  category_value, migration_status)
1709  }
1710  }
1711  // if log file DOES NOT EXISTS
1712  else {
1713  // clear log interval if migration completed
1714  resetIntervalAutoLogFetch();
1715  deleteWIPMigrateLock(operation_value, category_value, is_final_migr);
1716  error = true;
1717  }
1718  }
1719  // response success = False
1720  else {
1721  error = true;
1722  deleteWIPMigrateLock(operation_value, category_value, is_final_migr);
1723  resetIntervalAutoLogFetch()
1724  }
1725  if (error == true) {
1726  alert_level = "danger";
1727  } else if (warning == true) {
1728  alert_level = "warning";
1729  } else {
1730  alert_level = "success";
1731  }
1732  // display log appropriate alert message after fetching log content
1733  displayMessageAlert(alert_msg, "add", alert_level)
1734  })
1735  .always(function() {
1736  // always show log displaying div
1737  setMonitorLogArea()
1738 
1739  if(is_final_migr == true && operation_value == "migrate") {
1740  fetchWIPAndDoneList(false, false);
1741  } else {
1742  // update migration options etc.
1743  UpdateMigrationOptions(false);
1744  }
1745 
1746  if(is_final_migr == true) {
1747  // if final migration encountered error (eg. execution with wrong
1748  // password, then enable the Start Button)
1749  if(error) {
1750  $("#runMigrationBtn").prop("disabled", false)
1751  } else {
1752  $("#runMigrationBtn").prop("disabled", true)
1753  }
1754 
1755  } else {
1756  $("#check-switch-accounts").prop("disabled", false)
1757  }
1758  // hide wait window
1759  hideWaitWindow()
1760  });
1761 }
1762 
1763 function InitFinalMigrationOperation(server, username, password) {
1764  // data to send as a post request
1765  data_execute_final_script = {
1766  "post_purpose": "execute_final_migration",
1767  "cu": "<?php echo $cu; ?>",
1768  "server": server,
1769  "username": username,
1770  "password": password
1771  };
1772 
1773  // return ajax caller instance
1774  return $.ajax({
1775  type: "POST",
1776  url: hcuadmOdyMigrServerURL,
1777  data: data_execute_final_script,
1778  dataType: "json",
1779  timeout: 120000
1780  })
1781 }
1782 
1783 
1784 /**
1785  * Main function that instantiates ajax post call to execute python migration script
1786  *
1787  * @param server Mammoth endpoint server
1788  * @param operation Data migration operation
1789  * @param data_category Data migration category
1790  * @param username Mammoth server credential: username
1791  * @param Password Mammoth server credential: password
1792  *
1793  * @return jquery.ajax instance for that call
1794 */
1795 function InitMigrationOperation(server, operation, data_category, username, password) {
1796  // data to send as a post request
1797  data_execute_script = {
1798  "post_purpose": "execute_script",
1799  "cu": "<?php echo $cu; ?>",
1800  "server": server,
1801  "operation": operation,
1802  "category": data_category,
1803  "username": username,
1804  "password": password
1805  };
1806 
1807  // return ajax caller instance
1808  return $.ajax({
1809  type: "POST",
1810  url: hcuadmOdyMigrServerURL,
1811  data: data_execute_script,
1812  dataType: "json"
1813  })
1814 }
1815 
1816 /**
1817 * A function that makes a ajax post request to delete work-in-progress lock file
1818 */
1819 function deleteWIPMigrateLock(operation, category, is_final_migr) {
1820  data_del_wip_file = {
1821  "post_purpose": "delete_wip",
1822  "cu": "<?php echo $cu; ?>",
1823  "operation": operation,
1824  "category": category,
1825  "is_final_migr": is_final_migr
1826  };
1827 
1828  $.ajax({
1829  type: "POST",
1830  url: hcuadmOdyMigrServerURL,
1831  data: data_del_wip_file,
1832  dataType: "json", // returned data type expected from server
1833  })
1834  .done(function (response) {
1835  var msg = response["message"];
1836  displayMessageAlert(msg, "append", "danger")
1837  })
1838  .fail(function (response) {
1839  console.log(response);
1840  });
1841 }
1842 
1843 /**
1844  * Update lock unlock button visibility based on completion of
1845  * related migration categories
1846  */
1847 function updateLockUnlockButton(cat_group, showHideWaitWindow) {
1848  if(showHideWaitWindow){
1849  showWaitWindow()
1850  }
1851  data_lockunlock = {
1852  "post_purpose": "display_lock_unlock_preventive_buttons",
1853  "cu": "<?php echo $cu; ?>",
1854  "cat_group": cat_group
1855  };
1856 
1857  var btnId = "";
1858  if (cat_group == "Settings") {
1859  btnId = "#lockUnlockSettingsMigrationBtn";
1860 
1861  } else if (cat_group == "Admin"){
1862  btnId = "#lockUnlockAdminMigrationBtn";
1863  }
1864 
1865  if (btnId != "") {
1866  $.ajax({
1867  type: "POST",
1868  url: hcuadmOdyMigrServerURL,
1869  data: data_lockunlock,
1870  dataType: "json",
1871  }).done(function (response) {
1872  var msg = response["message"];
1873  var locked = response["locked"];
1874 
1875  if (response["success"] == true) {
1876  if (response["show_btn"] == true) {
1877  $(btnId).prop("disabled", false)
1878 
1879  } else {
1880  $(btnId).prop("disabled", true)
1881  }
1882 
1883  if(locked) {
1884  changeBtnColorToUnlock(cat_group, btnId);
1885  } else {
1886  changeBtnColorToLock(cat_group, btnId);
1887  }
1888  }
1889 
1890  }).always(function (response) {
1891  if(showHideWaitWindow){
1892  hideWaitWindow()
1893  }
1894  })
1895  }
1896 }
1897 
1898 /**
1899  * Show/hide account cross reference download button based on
1900  * completion of 'migrate-memdata'
1901  */
1902 function updateAccountCrossRefDownloadButton(showHideWaitWindow) {
1903  if(showHideWaitWindow){
1904  showWaitWindow()
1905  }
1906  data_accref_dw = {
1907  "post_purpose": "display_accref_download",
1908  "cu": "<?php echo $cu; ?>"
1909  };
1910 
1911  $.ajax({
1912  type: "POST",
1913  url: hcuadmOdyMigrServerURL,
1914  data: data_accref_dw,
1915  dataType: "json", // returned data type expected from server
1916  }).done(function (response) {
1917  var msg = response["message"];
1918  if (response["success"] == true) {
1919  if (response["show_btn"] == true) {
1920  $("#accountCrossRefBtn").prop("disabled", false)
1921  } else {
1922  $("#accountCrossRefBtn").prop("disabled", true)
1923  }
1924  }
1925 
1926  }).always(function (response) {
1927  if(showHideWaitWindow){
1928  hideWaitWindow()
1929  }
1930  })
1931 }
1932 
1933 /**
1934  * Update summary area status display text
1935  */
1936  function updateSummary(done_list, is_final_migr_done) {
1937  var true_fa = '<i class="fa fa-check-square-o text-success"></i> ';
1938  var false_fa = '<i class="fa fa-times-rectangle text-danger"></i> ';
1939 
1940  if (done_list.includes("settings")) {
1941  $("#general-summary-settings").html(true_fa + "Settings");
1942  } else {
1943  $("#general-summary-settings").html(false_fa + "Settings");
1944  }
1945 
1946  if (done_list.includes("admin")) {
1947  $("#general-summary-admin").html(true_fa + "Admin");
1948  } else {
1949  $("#general-summary-admin").html(false_fa + "Admin");
1950  }
1951 
1952  if (done_list.includes("memdata")) {
1953  $("#general-summary-memdata").html(true_fa + "Member Data");
1954  } else {
1955  $("#general-summary-memdata").html(false_fa + "Member Data");
1956  }
1957 
1958  if ($("#check-switch-accounts").is(":checked")) {
1959  if (done_list.includes("switchaccounts")) {
1960  $("#general-summary-switch-accounts").html(true_fa + "Switch Accounts");
1961  } else {
1962  $("#general-summary-switch-accounts").html(false_fa + "Switch Accounts");
1963  }
1964  $("#general-summary-switch-accounts").removeClass("hidden");
1965 
1966  } else {
1967  $("#general-summary-switch-accounts").removeClass("hidden").addClass("hidden");
1968  }
1969 
1970  if(done_list.includes("loanapp")) {
1971  $("#general-summary-loanapps").html(true_fa + "Loan Apps");
1972  } else {
1973  $("#general-summary-loanapps").html(false_fa + "Loan Apps");
1974  }
1975 
1976  if (done_list.includes("memhist")) {
1977  $("#general-summary-memhist").html(true_fa + "Member History");
1978  } else {
1979  $("#general-summary-memhist").html(false_fa + "Member History");
1980  }
1981 
1982  if(is_final_migr_done == true) {
1983  $("#general-summary-final-migr").html(true_fa + "Did final migration run?");
1984  } else {
1985  $("#general-summary-final-migr").html(false_fa + "Did final migration run?");
1986  }
1987  }
1988 
1989 /**
1990  * A function that makes a ajax post request to fetch list of all
1991  * in-progress and completed migrations
1992  */
1993 function fetchWIPAndDoneList(showHideWaitWindow, is_part_of_final_migr) {
1994  if(showHideWaitWindow){
1995  showWaitWindow()
1996  }
1997  data_wip_done_list = {
1998  "post_purpose": "get_wip_done_list",
1999  "cu": "<?php echo $cu; ?>"
2000  };
2001 
2002  $.ajax({
2003  type: "POST",
2004  url: hcuadmOdyMigrServerURL,
2005  data: data_wip_done_list,
2006  async: false,
2007  dataType: "json", // returned data type expected from server
2008  })
2009  .done(function (response) {
2010  var msg = response["message"];
2011  if (response["success"] == true) {
2012  var done_list = response["done_list"];
2013  var wip_list = response["wip_list"];
2014  var is_final_migr_done = response["final_migr_done"]
2015 
2016  var wipDDL = $("#wipDDL").data("kendoDropDownList");
2017  var ds = new kendo.data.DataSource({
2018  data: wip_list
2019  });
2020 
2021  wipDDL.setDataSource(ds)
2022 
2023  if (wip_list.length > 0) {
2024  wipDDL.value(wip_list[0]);
2025  }
2026  wipDDL.enable(false)
2027 
2028  updateSummary(done_list, is_final_migr_done);
2029 
2030  } else {
2031  displayMessageAlert(msg, "add", "danger")
2032  }
2033  }).fail(function (response) {
2034  console.log(response);
2035  }).always(function (response) {
2036  if (is_part_of_final_migr == false) {
2037  updateStartButtonVisibleStatus(false)
2038  } else {
2039  $("#runMigrationBtn").prop("disabled", true);
2040  }
2041 
2042  if(showHideWaitWindow){
2043  hideWaitWindow()
2044  }
2045  });
2046 }
2047 
2048 /**
2049 * A function that makes a ajax post request to fetch list of all previously ran data migration options
2050 */
2051 function FetchLogsHistoryList(showHideWaitWindow) {
2052  if(showHideWaitWindow) {
2053  showWaitWindow()
2054  }
2055  data_wip_done_list = {
2056  "post_purpose": "get_logs_list",
2057  "cu": "<?php echo $cu; ?>"
2058  };
2059 
2060  $.ajax({
2061  type: "POST",
2062  url: hcuadmOdyMigrServerURL,
2063  data: data_wip_done_list,
2064  dataType: "json", // returned data type expected from server
2065  })
2066  .done(function (response) {
2067  var msg = response["message"];
2068  if (response["success"] == true) {
2069  var logs_list = response["logs_list"];
2070  var logsHistoryDDL = $("#loghistoryDDL").data("kendoDropDownList");
2071  // update data source
2072  var logshistory_data_source = new kendo.data.DataSource({
2073  data: logs_list
2074  });
2075  logsHistoryDDL.setDataSource(logshistory_data_source)
2076 
2077  if (logs_list.length > 0) {
2078  logsHistoryDDL.enable(true)
2079 
2080  logsHistoryDDL.value(logs_list[0])
2081  logsHistoryDDL.trigger("change")
2082 
2083  $("#get-log-history").prop("disabled", false)
2084  } else {
2085  $("#get-log-history").prop("disabled", true)
2086  logsHistoryDDL.enable(false)
2087  }
2088 
2089  } else {
2090  displayMessageAlert(msg, "append", "danger")
2091  }
2092  }).always(function (response) {
2093  if(showHideWaitWindow) {
2094  hideWaitWindow()
2095  }
2096  });
2097 }
2098 
2099 /**
2100  * Show/hide start button based on WIP category
2101  */
2102 function updateStartButtonVisibleStatus(showHideWaitWindow) {
2103  if(showHideWaitWindow) {
2104  showWaitWindow()
2105  }
2106  var wip = $("#wipDDL").data("kendoDropDownList").value();
2107  if (wip == "") {
2108  $("#runMigrationBtn").prop("disabled", false)
2109  <?php if(IsDevMode()) { ?>
2110  $("#resetFinalMigration").prop("disabled", false)
2111  $("#deleteSelectedCategoriesBtn").prop("disabled", false)
2112  <?php } ?>
2113 
2114  } else {
2115  $("#runMigrationBtn").prop("disabled", true)
2116  <?php if(IsDevMode()) { ?>
2117  $("#resetFinalMigration").prop("disabled", true)
2118  $("#deleteSelectedCategoriesBtn").prop("disabled", true)
2119  <?php } ?>
2120  }
2121 
2122  if(showHideWaitWindow) {
2123  hideWaitWindow()
2124  }
2125 
2126 }
2127 
2128 /**
2129  * Main function to update values to be displayed in In-progress Migrations, Completed Migrations and Logs History tabs in Migration Options section.
2130  */
2131 function UpdateMigrationOptions(showHideWaitWindow) {
2132  if (showHideWaitWindow) {
2133  showWaitWindow();
2134  }
2135 
2136  fetchWIPAndDoneList(false, false);
2137  updateAccountCrossRefDownloadButton(false);
2138  updateLockUnlockButton("Settings", false);
2139  updateLockUnlockButton("Admin", false);
2140  FetchLogsHistoryList(false);
2141  // update home banking status
2142  updateHomeBankingInfoText(false);
2143  <?php if(IsDevMode()) { ?>
2144  // update list of categories available for deletion
2145  updateAllDoneMultiCheckList(false)
2146  <?php } ?>
2147  // enable/disable final migration checkbox based on previously ran memdata and memhist migrations count
2148  updateFinalMigrCheckBox(false)
2149  updateStartButtonVisibleStatus(false)
2150  updateDataCategoriesList(false)
2151 
2152  if (showHideWaitWindow){
2153  hideWaitWindow()
2154  }
2155 }
2156 
2157 /**
2158  * Utility function to display message status and alerts
2159  */
2160 function displayMessageAlert(message, append_or_add, alert_level) {
2161  if (alert_level == "danger") {
2162  alert_level = "error"
2163  }
2164  msg_length = message.length
2165  message = message.substring(0, Math.min(msg_length - 1, 500));
2166  $("#migration-alert").getKendoNotification().show("<div class='notificationAlert'>" + message + "</div>", alert_level)
2167 }
2168 
2169 /**
2170  * Initialize KendoUIs in the migration screen
2171  */
2172 function initializeKendoElements() {
2173  $("#wipDDL").kendoDropDownList({
2174  dataSource: {
2175  data: []
2176  },
2177  noDataTemplate: "No IN PROGRESS migrations to show!"
2178  }).data("kendoDropDownList");
2179 
2180  $("#migration-alert").kendoNotification({
2181  autoHideAfter: 15000,
2182  button: true,
2183  width: 500,
2184  position: {
2185  pinned: true,
2186  top: 20,
2187  left: null,
2188  bottom: null,
2189  right: 20
2190  }
2191  });
2192 
2193  // kendo-ui DDL instance for servers
2194  $("#serversDDL").kendoDropDownList({
2195  dataSource: {
2196  data: []
2197  },
2198  noDataTemplate: "No Mammoth server endpoint to show!"
2199  }).data("kendoDropDownList");
2200 
2201  // kendo-ui DDL instance for migration operations
2202  $("#operationsDDL").kendoDropDownList({
2203  dataSource: {
2204  data: []
2205  },
2206  change: function(e){
2207  var serversddl = $("#serversDDL").data("kendoDropDownList");
2208  if (this.value() != 'migrate') {
2209  serversddl.enable(false)
2210  $("[name='username']").prop("disabled", true).addClass("k-state-disabled");
2211  $("[name='password']").prop("disabled", true).addClass("k-state-disabled");
2212  } else {
2213  serversddl.enable(true)
2214  $("[name='username']").prop("disabled", false).removeClass("k-state-disabled");
2215  $("[name='password']").prop("disabled", false).removeClass("k-state-disabled");
2216  }
2217  },
2218  noDataTemplate: "No migration operation to show!"
2219  }).data("kendoDropDownList");
2220 
2221  // kendo-ui DDL instance for categories
2222  $("#categoriesDDL").kendoDropDownList({
2223  dataSource: {
2224  data: []
2225  },
2226  cascade: function(e){
2227  setUpOperationsDDL(this.value(), "cascade");
2228  },
2229  noDataTemplate: "No data categories to show!"
2230  }).data("kendoDropDownList");
2231 
2232  <?php if(IsDevMode()) { ?>
2233  $("#deleteAllCleanUpList").kendoMultiSelect({
2234  dataSource: [],
2235  noDataTemplate: "No completed migration category(ies) to show!",
2236  change: function(e) {
2237  if(this.value().length > 0) {
2238  $("#deleteSelectedCategoriesBtn").html(" Clean Selected (" + this.value().length + ") Categories")
2239  } else {
2240  $("#deleteSelectedCategoriesBtn").html(" Clean Selected Categories")
2241  }
2242  }
2243  }).data("kendoMultiSelect");
2244  <?php } ?>
2245 
2246  $("#loghistoryDDL").kendoDropDownList({
2247  dataSource: {
2248  data: []
2249  },
2250  noDataTemplate: "No LOGS HISTORY to show!"
2251  }).data("kendoDropDownList");
2252 
2253 }
2254 
2255 /**
2256  * Main entrypoint for this javascript
2257  */
2258 function main() {
2259  // add tooltip using title attribute
2260  $("#migrationDiv").kendoTooltip({ filter: "a[title]" });
2261 
2262  // check for access permissions and proceed with necessary initialization if permitted
2263  data_check_monitor_lock = {
2264  "post_purpose": "check_monitor_lock",
2265  "cu": "<?php echo $cu; ?>"
2266  };
2267 
2268  showWaitWindow()
2269 
2270  $.ajax({
2271  type: "POST",
2272  url: hcuadmOdyMigrServerURL,
2273  data: data_check_monitor_lock,
2274  dataType: "json", // returned data type expected from server
2275  async: false
2276  }).done(function(response) {
2277  // lock it away, no permission
2278  lock_file = response["lock_file"]
2279  lock_file_exists = response["exists"]
2280 
2281  // if lock file exist, migrations creen access is not permitted
2282  if (lock_file_exists) {
2283  disabled_msg = "Sorry, migration is disabled. Lock file " + lock_file + " exists!";
2284  $("#migrationDisableMsgDiv").text(disabled_msg)
2285  $("#migrationDisableMsgDiv").removeClass("hidden");
2286 
2287  } else {
2288  // setup kendo ui controls and perform necessary initializations
2289  SetUp();
2290  }
2291  })
2292  .fail(function(response) {
2293  error_msg = "Something went wrong loading the migration page (possibly due to lock file mishandling!)";
2294  $("#migrationDisableMsgDiv").text(error_msg);
2295  $("#migrationDisableMsgDiv").removeClass("hidden");
2296  }).always(function(response) {
2297  // allow 2 seconds for initial setup
2298  setTimeout(function() { hideWaitWindow()}, 2000)
2299  });
2300 }
2301 
2302 /*
2303  * Main function that is called first when the webpage is opened.
2304  */
2305 $(document).ready(function() {
2306  main()
2307 });
2308 
2309 </script>
2310 
2311 <?php
2312 // ***********************************************************************************
2313 // Local style
2314 // ***********************************************************************************
2315 ?>
2316 
2317 <style>
2318 
2319 .notificationAlert {
2320  word-wrap: break-word;
2321  white-space: normal;
2322  margin: -18px 0 0 20px;
2323  }
2324 
2325 .local-max-width {
2326  max-width: 1000px;
2327 }
2328 
2329 .local-grid-cursor tbody {
2330  cursor: default;
2331 }
2332 
2333 .local-grid-cursor tbody tr td:eq(0) {
2334  cursor: pointer;
2335 }
2336 
2337 #logs-textarea {
2338  overflow: scroll;
2339  font-size: 12px;
2340  font-weight: bold;
2341  resize: none;
2342  width: 100%;
2343  height: 350px;
2344 }
2345 
2346 #migration-history-tabs{
2347  min-height: 450px;
2348 }
2349 
2350 #migration-settings-tab {
2351  min-height: 560px;
2352 }
2353 
2354 #progressbar {
2355  width: 100%;
2356 }
2357 </style>
2358 
2359 <?php
2360 // ***********************************************************************************
2361 // HTML of page
2362 // ***********************************************************************************
2363 ?>
2364 
2365 
2366  <div id="migrationDiv" class="container-fluid hcu-template form-horizontal hidden">
2367  <p></p>
2368 
2369  <div id="progress-bar-container" class="col-xs-12 well hidden">
2370  <div id="progress-bar-text" class="col-xs-12 form-group"></div>
2371  <div id="progressbar" class="col-xs-12"></div>
2372  </div>
2373 
2374  <div id="migration-alert"></div>
2375  <div id="migrationStatusDiv" class="col-xs-12 form-group"></div>
2376  <div id="finalMigrationStatusDiv" class="col-xs-12 text-danger text-center"></div>
2377 
2378  <div>
2379  <div id="migration-input" class="float-left col-xs-12 col-sm-6">
2380 
2381  <div class="panel panel-primary col-xs-12">
2382  <div class="form-group col-xs-12">
2383  <div class="page-header">
2384  <h1>Migration Input <small></small></h1>
2385  </div>
2386  </div>
2387 
2388  <div class="form-group">
2389  <label class="col-xs-12 col-sm-4">Target System</label>
2390  <div class="col-xs-12 col-sm-8"><b><i class="text-info"><?php echo GetCurrentServer();?></i></b></div>
2391  </div>
2392 
2393  <div class="form-group">
2394  <label class="col-xs-12 col-sm-4">Source Server <i class="text-info">(Mammoth)</i></label>
2395  <div class="col-xs-12 col-sm-8"><div id="serversDDL" class="hcu-all-100"></div></div>
2396  </div>
2397 
2398  <div class="form-group">
2399  <label class="col-xs-12 col-sm-4">Server Username</label>
2400  <div class="col-xs-12 col-sm-8"><input type="text" title="Enter username of the first credential that you use to login to the Monitor in Mammoth." class="k-input k-textbox hcu-all-100" name="username" maxlength="50"
2401  required validationMessage="Enter {0}" placeholder= "Enter Mammoth monitor username"></div>
2402  </div>
2403 
2404  <div class="form-group">
2405  <label class="col-xs-12 col-sm-4">Server Password</label>
2406  <div class="col-xs-12 col-sm-8"><input type="password" title="Enter password of the first credential that you use to login to the Monitor in Mammoth." class="k-input k-textbox hcu-all-100" name="password" maxlength="50"
2407  required validationMessage="Enter {0}" placeholder= "Enter Mammoth monitor password"></div>
2408  </div>
2409 
2410  <div class="form-group">
2411  <label class="col-xs-12 col-sm-4">Data Operation</label>
2412  <div class="col-xs-12 col-sm-8"><div id="operationsDDL" class="hcu-all-100"></div></div>
2413  </div>
2414 
2415  <div class="form-group">
2416  <label class="col-xs-12 col-sm-4">Data Category</label>
2417  <div class="col-xs-12 col-sm-8"><div id="categoriesDDL" class="hcu-all-100"></div></div>
2418  </div>
2419  <hr/>
2420  <div class="form-group">
2421  <div id="checkbox-alerts" class="col-xs-12 col-sm-6 float-left">
2422  <div id="cuadmin-info">
2423  <h4 class="text-info"><u><?php echo strtoupper($cu); ?> Banking Settings</u></h4>
2424  <h6 class="text-default">Home Banking -> Allow Repeating Transactions: <strong id="cuadmin-repeating-transfers" class="text-danger"></strong></h6>
2425  <h6 class="text-default">Home Banking -> Allow Member Alert Processing: <strong id="cuadmin-alert-processing" class="text-danger"></strong></h6>
2426  <h6 id="cuadmin-offlinestat-info" class="text-default hidden">Change Online Status -> Offline Status : <strong id="cuadmin-offline-status" class="text-danger"></strong></h6>
2427  </div>
2428  <div id="cuadmin-no-info" class="text-danger hidden"></div>
2429  <div id="migration-categories-summary">
2430  <hr>
2431  <h4 class="text-info"><u>Summary of Completion</u></h4>
2432  <h5><u>Settings</u></h5>
2433  <h6 id="general-summary-settings" class="text-default">N/A Settings</h6>
2434  <h6 id="general-summary-admin" class="text-default">N/A Admin </h6>
2435  <h5><u>Members</u></h5>
2436  <h6 id="general-summary-memdata" class="text-default">N/A Member Data</h6>
2437  <h6 id="general-summary-switch-accounts" class="text-default hidden">N/A Switch Accounts</h6>
2438  <h6 id="general-summary-loanapps" class="text-default">N/A Loan Apps</h6>
2439  <h6 id="general-summary-memhist" class="text-default">N/A Member History</h6>
2440  <h6 id="general-summary-final-migr" class="text-default">Did final migration run? N/A</h6>
2441 
2442  </br>
2443  <p><i>Note: Loan Apps migration migrates data of credit unions that have loan apps specific data on Mammoth. The ones with no corresponding loan related data on Mammoth are safely handled.</i></p>
2444  <i class="fa fa-check-square-o text-success"> Completed </i>
2445  <i class="fa fa-times-rectangle text-danger"> Not Completed</i>
2446  </br></br>
2447  </div>
2448  </div>
2449  <div class="col-xs-12 col-sm-6 float-right">
2450  <div class="col-xs-12 float-right text-right">
2451  <button type="button" id="runMigrationBtn" class="btn btn-primary"><i class="fa fa-plug"></i> Start</button>
2452  </div>
2453  <div class="clear"></div>
2454  <div class="col-xs-12 float-right text-right">
2455  <div id ="final-migration-checklist-wrapper" style="display: none;">
2456  <hr>
2457  <input class="form-check-input" type="checkbox" id="final-migration" title="settings and admin have alredy been migrated and updated. Also tested memdata and memhist should have been tested at least once." value="option1" disabled>
2458  <label id="final-migration-label" class="form-check-label text-danger text-right" for="final-migration">Ready for Final Migration?</label>
2459  <br/>
2460  <p class="text-danger"><i>Please refresh the page before starting final migration. </br>Final migration includes: memdata, [loanapp, switchaccounts] and memhist data categories.</i></p>
2461  <h6 id="final-mgr-settings-locked" class="text-info text-right">1. Are <i>settings</i> & <i>admin</i> migrated & locked? N/A</h6>
2462  <h6 id="final-mgr-memdata-ready" class="text-info text-right">2. Is <i>memdata</i> ready? N/A</h6>
2463  <h6 id="final-mgr-memdata-gt0" class="text-default text-right">Tested <i>memdata</i> at least once? N/A</h6>
2464  <h6 id="final-mgr-memdata-clean" class="text-default text-right">Is <i>memdata</i> in clean state? N/A</h6>
2465  <h6 id="final-mgr-memhist-ready" class="text-info text-right">3. Is <i>memhist</i> ready? N/A</h6>
2466  <h6 id="final-mgr-memhist-gt0"class="text-default text-right">Tested <i>memhist</i> at least once? N/A</h6>
2467  <h6 id="final-mgr-memhist-clean" class="text-default text-right">Is <i>memhist</i> in clean state? N/A</h6>
2468  <h6 id="final-mgr-nowip" class="text-default text-info">4. Any in-progress migration(s)? N/A</h6>
2469  </br>
2470  <h6 id="final-mgr-migrate-switchaccounts" class="text-danger text-right">Is <i>SWITCHACCOUNTS</i> part of final migration? N/A</h6>
2471  <h6><i>(configure from Migration Settings -> Settings:Support)</i></h6>
2472  </br>
2473  <i class="fa fa-check-square-o text-right text-success"> Satisfies. </i>
2474  <i class="fa fa-times-rectangle text-right text-danger"> Does not satisfy. </i>
2475  <div class="clear"></div>
2476  <br/><br/>
2477  </div>
2478  </div>
2479  <div class="clear"></div>
2480  </div>
2481  <div class="clear"></div>
2482  </div>
2483  </div>
2484  </div>
2485  </div>
2486 
2487  <div id="migration-sidebar" class="float-right col-xs-12 col-sm-6">
2488 
2489  <div id="migration-history-tabs" class="panel panel-primary col-xs-12">
2490  <div class="col-xs-12 form-group">
2491  <div class="page-header">
2492  <h1>Migration Settings <small></small></h1>
2493  </div>
2494  </div>
2495  <ul class="nav nav-tabs">
2496  <li class="active"><a data-toggle="tab" href="#migration-inprogress-tab">In-Progress Migration</a></li>
2497  <li><a data-toggle="tab" href="#migration-dev-settings-tab">Settings: Developers</a></li>
2498  <li><a data-toggle="tab" href="#migration-settings-tab">Settings: Support</a></li>
2499  </ul>
2500 
2501  <div class="tab-content">
2502  <div id="migration-inprogress-tab" class="tab-pane fade in active">
2503  <div class="page-header">
2504  <h4>In-Progress Migration</h4>
2505  </div>
2506 
2507  <div class="col-xs-12 col-sm-12">
2508  <div class="form-group">
2509  <div class="col-xs-12 col-sm-7 float-left">
2510  <div id="wipDDL" class="hcu-all-100"></div>
2511  </div>
2512  <div class="clear"></div>
2513  </div>
2514  </div>
2515 
2516  </div>
2517  <div id="migration-dev-settings-tab" class="tab-pane fade col-xs-12">
2518  <div>
2519  <br/>
2520  <i class="text-danger text-center">Please do not change settings here if you're not a part of the data migration team!</i>
2521  </div>
2522  <div class="float-left col-xs-12 col-sm-6">
2523  <div class="page-header">
2524  <h4> Logs History: Completed Migrations</h4>
2525  </div>
2526  <div class="col-xs-12 col-sm-12">
2527  <div class="form-group">
2528  <div class="col-xs-12 col-sm-7 float-left">
2529  <div id="loghistoryDDL" class="hcu-all-100"></div>
2530  </div>
2531  <div class="col-xs-12 col-sm-5 float-right">
2532  <button id="get-log-history" type="button" class="btn btn-info" disabled><i class="fa fa-get-pocket"></i> Fetch Log</button>
2533  </div>
2534  <div class="clear"></div>
2535  </div>
2536  </div>
2537  </div>
2538 
2539  <?php if(IsDevMode()) { ?>
2540  <div class="float-right col-xs-12 col-sm-6">
2541  <div class="page-header">
2542  <h4>Reset Migration State (Developer Tool)<small></small></h4>
2543  </div>
2544  <div>
2545  <p class="text-danger"><b>DANGER ZONE! Please contact a developer if you're seeing this in PRODUCTION environment. Consequences: This will DELETE EVERYTHING but settings and admin. </b>This is primarily used by developers to reset migration states with a single click during development and testing. This may take up to a couple minutes for larger CUs.</p>
2546  <button type="button" title="" id="resetFinalMigration" class="btn btn-danger" disabled><i class="fa fa-undo"></i> Reset (Final) Migration State</button>
2547  </div>
2548 
2549  <div class="page-header">
2550  <h4>Multiple Clean Up (Developer Tool)<small></small></h4>
2551  </div>
2552  <div>
2553  <p class="text-primary">Clean up multiple data categories.<br>(may take up to a couple minutes for larger CUs)</p>
2554  <select id="deleteAllCleanUpList" multiple="multiple"></select>
2555  <br/>
2556  <button type="button" id="deleteSelectedCategoriesBtn" title="" class="btn btn-danger"><i class="fa fa-trash"></i> Clean Selected Categories</button>
2557  <br/><br/>
2558  </div>
2559  </div>
2560  <?php }?>
2561 
2562  <div class="clear"></div>
2563  </div>
2564  <div id="migration-settings-tab" class="tab-pane fade col-xs-12">
2565  <div>
2566  <br/>
2567  <i class="text-danger">Please do not change settings here if you're not a part of the data migration team.</i>
2568  </div>
2569  <div class="clear"></div>
2570  <div class="float-left col-xs-12 col-sm-6">
2571  <div class="page-header">
2572  <h4>Settings Migration Deletion<small></small></h4>
2573  </div>
2574  <div >
2575  <p class="text-primary">Locked = Prevent deletion, Unlocked = Allow deletion</p>
2576  <button type="button" id="lockUnlockSettingsMigrationBtn" title="Allow/Dis-allow further migration of settings data category." class="btn btn-danger" disabled><i class="fa fa-lock"></i> Lock Settings Migration</button>
2577  <br/><br/>
2578  </div>
2579  <div class="page-header">
2580  <h4>Admin Migration Deletion<small></small></h4>
2581  </div>
2582  <div>
2583  <p class="text-primary">Locked = Prevent deletion, Unlocked = Allow deletion</p>
2584  <button type="button" id="lockUnlockAdminMigrationBtn" title="Allow/Dis-allow further migration of admin data category." class="btn btn-danger"><i class="fa fa-lock"></i> Lock Admin Migration</button>
2585  <br/><br/>
2586  </div>
2587 
2588  <div class="page-header">
2589  <h4>Disable Migration Screen In Monitor<small></small></h4>
2590  </div>
2591  <div>
2592  <p class="text-primary">Disable monitor access after completion of all migrations.</p>
2593  <button id="migration-settings" title="Use this setting to disable migration monitor after migration of all the data categories is completed." type="button" class="btn btn-info"><i class="fa fa-cogs"></i> Show Settings</button>
2594  <br/><br/>
2595  </div>
2596  <div id="settings" class="col-xs-12 form-group">
2597  <div class="form-check form-check-inline">
2598  <input class="form-check-input" type="checkbox" id="check-migration" value="option1">
2599  <label class="form-check-label text-danger" for="check-migration">I believe that all the data for all applicable categories have been migrated to Odyssey for <?php echo strtoupper($cu); ?>.</label>
2600  </div>
2601  <button id="disable-migration-button" type="button" title="Are you REALLY sure?" class="btn btn-danger"><i class="fa fa-ban"></i> Disable Migration Menu</button>
2602  <br/><br/>
2603  </div>
2604  </div>
2605 
2606  <div class="float-right col-xs-12 col-sm-6">
2607  <div class="page-header">
2608  <h4>Update <i>public_html</i> Embedded Links<small></small></h4>
2609  </div>
2610  <div>
2611  <p class="text-info">Have you already migrated the filesystem to Odyssey? </br>This updates links in the scripts in <b>/home/<?php echo $cu; ?>/public_html/</b> directory.</p>
2612  <button type="button" title="Have you already migrated the filesystem? This updates the embedded links the public_html directory. Eg. domain name update (www3.homecu.net -> my.homecu.net), calculator links, php script (.prg files) links, etc." id="updatePublicHtml" class="btn btn-info"><i class="fa fa-refresh"></i> Update</button>
2613  </div>
2614  <div class="page-header">
2615  <h4>Include Switch Accounts?<small></small></h4>
2616  </div>
2617  <div class="form-check form-check-inline">
2618  <input class="form-check-input" type="checkbox" id="check-switch-accounts"><label class="form-check-label text-info" for="check-switch-accounts">Check this only if SWITCH ACCOUNTS related data is to be include in the Final Migration.</label>
2619  </div>
2620 
2621  <div class="page-header">
2622  <h4>Account Cross Reference List<small></small></h4>
2623  </div>
2624  <div>
2625  <p class="text-primary">Download a list of Mammoth to Odyssey members mapping info.</p>
2626  <button type="button" title="'migrate-memdata' maintains a list of Mammoth's user_name to Odyssey's userid mappings information. Use this button to get the mapping -- save the content as a file when opened in another window. " id="accountCrossRefBtn" class="btn btn-info"><i class="fa fa-download"></i> Download</button>
2627  <br/><br/>
2628  </div>
2629  </div>
2630 
2631  <div class="clear"></div>
2632  </div>
2633  </div>
2634  </div>
2635 
2636  <div id="migration-status" class="col-xs-12">
2637  <div class="form-group panel panel-primary col-xs-12">
2638  <div class="page-header">
2639  <h1>Logs <small id="current-log-header"></small></h1>
2640  <p class="text-danger" id="logs-display-datetime"></p>
2641  </div>
2642  <div class="col-xs-12">
2643  <div id="logs-textarea" class="form-control"></div>
2644  </div>
2645  </div>
2646  </div>
2647  </div>
2648 
2649  <div class="clear"></div>
2650  </div>
2651 
2652  </div>
2653 
2654  <div class="container-fluid form-horizontal">
2655  <div class="form-group">&nbsp;</div>
2656  <div id="migrationDisableMsgDiv" class ="alert alert-danger hidden" role="alert"></div>
2657  </div>
2658 
2659 
2660 <?php
2661 // *************************************************************************************
2662 // Bottom of page
2663 // *************************************************************************************
2664 
2665 // Will print out the closing tags created in the printMonitorPageTop function.
2666 printMonitorPageBottom();
2667 exit;
def main(certificate_path, secret_id, region=None)