Odyssey
cutrustvendor.prg
1 <?php
2  /*
3  * Script: cutrustvendor.v2
4  *
5  * Purpose: This script will show the Trusted Vendors setup in the system.
6  * These values will come form the custrustedmaster table.
7  * Needs the ability for A
8  * loans. This includes their hash key that is used to access the loan
9  * system. Also, will show the current list of loans, with the ability
10  * for new loan, edit loan, copy loan.
11  *
12  * SPB, 10/6/2015-- Added version 2 with kendo.
13  */
14 
15 $monLibrary= dirname(__FILE__) . "/../library";
16 require_once("$monLibrary/cu_top.i");
17 require_once("$monLibrary/ck_hticket.i");
18 require_once("$monLibrary/monitorView.i");
19 require_once("$sharedLibrary/commonJsFunctions.i");
20 
21  if (!CheckPerm($link, $Hu, basename($_SERVER['SCRIPT_NAME']), $_SERVER['REMOTE_ADDR'])) {
22  // ** Permissions failed
23  // ** redirect to new page
24  header("Location: /hcuadm/hcu_noperm.prg");
25  exit;
26  }
27 
28 // Globals
29 $dataFile= "cutrustvendor.data";
30 $dataPath= "/hcuadm/$dataFile";
31 $showSQL= false;
32 
33 printMonitorPageTop("Trusted Vendors", $homecuKendoVersion, $cloudfrontDomainName);
34 ?>
35 
36 <style>
37 
38  .popupForm .grid_12 {
39  margin-bottom: 5px;
40  }
41 
42  .k-grid tbody .k-button {
43  min-width: 20px !important; /* override */
44  }
45 
46  #defaultValueGrid thead {
47  display: none;
48  }
49 
50  #defaultValueGrid tbody tr {
51  height: 50px;
52  }
53 
54  #defaultValueGrid .k-grid-customDelete {
55  position: relative;
56  left: -5px;
57  }
58 
59  .homecu-formStatus {
60  margin: 5px;
61  padding: 5px;
62  }
63 
64  #accordion {
65  border-color: rgb(204, 204, 204);
66  background-color: rgb(238, 238, 238);
67  border-radius: 6px;
68  color: rgb(51, 131, 187) !important;
69  display: block;
70  font-family: 'Trebuchet MS', 'Lucida Grande', Verdana, Arial, sans-serif;
71  font-size: 11px;
72  font-weight: bold;
73  }
74 
75  #deleteDialogWindow .message {
76  text-align: center;
77  }
78 
79  #deleteDialogWindow .k-edit-buttons {
80  text-align: center;
81  }
82 
83  .k-context-menu .k-item, .k-context-menu {
84  width: 150px !important;
85  }
86 
87  .k-edit-form-container {
88  width: auto !important;
89  }
90 </style>
91 
92 <script type="text/javascript">
93 
94 <?php
95 // Include common functions
96 getErrorsAreShownFunction();
97 getSetupDeleteConfirmDialogFunction();
98 getAddMinifiedActionStyleFunction();
99 getParseCrudGridFunction();
100 getEscapeHTMLFunction();
101 getShowSQLFunction($showSQL);
102 getSetupValidatorInGridFunction();
103 getUseValidatorInGridFunction();
104 getShowWaitFunctions();
105 getAddErrorFunction();
106 getContextMenuForDoubleLevelGrid();
107 ?>
108 
109 <?php /* Initializes the accordion. */ ?>
110 function initAccordion()
111 {
112  var accordion= $("#accordion").kendoPanelBar({}).data("kendoPanelBar");
113 }
114 
115 <?php /* Initializes the grid. */ ?>
116 var fullContextMenu= null;
117 var detailRecords= [];
118 function initGrid()
119 {
120  var optionDDLData= [];
121  var typeDDLData= [];
122  var fieldTypeDDLData= [];
123  var serverOptions= [];
124  var initialized= false;
125 
126  var openDetails= [];
127 
128  var grid= $("#grid").kendoGrid({
129  dataSource: {
130  transport: {
131  read: {
132  url: "<?php echo $dataPath; ?>?operation=readTrustedVendors",
133  dataType: "json",
134  type: "POST"
135  },
136  create: {
137  url: "<?php echo $dataPath; ?>?operation=createTrustedId",
138  dataType: "json",
139  type: "POST"
140  },
141  update: {
142  url: "<?php echo $dataPath; ?>?operation=updateTrustedId",
143  dataType: "json",
144  type: "POST"
145  },
146  parameterMap: function(data, type) {
147  showWaitWindow();
148  if (type == "read")
149  return {};
150  else
151  return {features: data.features, trustedId: data.trustedId, typeValue: data.typeValue, vendorName: data.vendorName, detailsEncoded: data.detailsEncoded}
152  }
153  },
154  schema: {
155  model: {
156  id: "trustedId",
157  fields: {
158  trustedId: {type: "string"},
159  vendorName: {type: "string"},
160  typeValue: {type: "string"},
161  typeText: {type: "string"}
162  }
163  },
164  parse: function (data)
165  {
166  hideWaitWindow();
167  if (data.operation == "read")
168  {
169  optionDDLData= data.optionDDL;
170  typeDDLData= data.typeDDL;
171  fieldTypeDDLData= data.fieldTypeDDL;
172  serverOptions= data.serverOptions;
173  detailRecords= new kendo.data.ObservableArray(data.detailRecords);
174 
175  }
176  return parseCrudGrid(data);
177  }
178  }
179  },
180  columns: [
181  {field: "trustedId", title: "Trusted ID", attributes: {"class" : "trustedId"}},
182  {field: "vendorName", title: "Vendor"},
183  {field: "typeText", title: "Type"}
184  ],
185  sortable: true,
186  filterable: {extra: false},
187  toolbar: [{name: "create", text: ""}],
188  detailTemplate: "<div class=\"detailGrid\"></div>",
189  detailInit: function (eOuter) {
190  if (eOuter.data.trustedId == "HOMECUSERVICE" && eOuter.data.vendorName == "HOMECU")
191  initServerMasterGrid(eOuter, serverOptions, detailRecords);
192  else
193  initDetailGrid(eOuter, fieldTypeDDLData, detailRecords);
194  },
195  editable: {
196  mode: "popup",
197  template: kendo.template($("#popupTemplate").html()),
198  window: {
199  draggable: false,
200  resizable: false,
201  title: "<span class='gridWindowTitle'></span>",
202  actions: [],
203  width: 1300
204  }
205  },
206  edit: function (eOuter) {
207  setupValidatorInGrid(eOuter, false);
208 
209  var typeDDL= $("#typeDDL").kendoDropDownList({
210  dataSource: {
211  data: typeDDLData
212  },
213  dataTextField: "text",
214  dataValueField: "value",
215  filter: "startswith",
216  change: function () {
217  eOuter.model.typeValue= this.value();
218  eOuter.model.typeText= this.text();
219  eOuter.model.dirty= true;
220  }
221  }).data("kendoDropDownList");
222 
223  if (eOuter.model.isNew())
224  {
225  $(".gridWindowTitle").text("Add Trusted Vendor");
226  $("#nameLabel").remove();
227 
228  $(".nameInput").blur(function () {
229  $(this).val($(this).val().replace(/\s+/g, ""));
230  addTrustedIdDuplicateError(eOuter, $(this).val(), eOuter.model.uid, false);
231  });
232 
233  eOuter.model.typeValue= typeDDL.value();
234  }
235  else
236  {
237  $(".gridWindowTitle").text("Edit Trusted Vendor");
238  $(".nameInput").remove();
239 
240  // Initialize DDLs
241  typeDDL.value(eOuter.model.typeValue);
242  }
243 
244  initMasterDetailsAtOnceTable(eOuter, fieldTypeDDLData, detailRecords);
245  },
246  save: function (eOuter) {
247  useValidatorInGrid(eOuter, false);
248 
249  if (eOuter.model.isNew())
250  addTrustedIdDuplicateError(eOuter, $(".nameInput").val(), eOuter.model.uid, true);
251  if (eOuter.model.detailsChanged)
252  {
253  var data= $("#masterDetailAtOnceGrid").data("kendoGrid").dataSource.data();
254  detailRecords= $.grep(detailRecords, function(n,i) { return n.trustedId != eOuter.model.trustedId; });
255  for (var i=0; i!= data.length; i++)
256  {
257  var record= data[i];
258  record.trustedId= eOuter.model.trustedId.replace(/\s+/g, "");
259  detailRecords.push(record); // Update detail records to reflect changes here.
260  }
261 
262  eOuter.model.detailsEncoded= kendo.stringify(data);
263  }
264  },
265  dataBound: function () {
266  fullContextMenu.gridDatabound (true, initialized, this);
267  if (!initialized)
268  {
269  addMinifiedActionStyle("#grid", true);
270  initialized= true;
271  }
272  var keys= Object.keys(openDetails);
273  for (var i=0; i!=keys.length; i++)
274  {
275  this.expandRow($(".trustedId").filter(function (index) { return $(this).text() == keys[i]; }).parent());
276  }
277  },
278  cancel: function (eOuter) {
279  grid.cancelRow();
280  fullContextMenu.gridCancel(eOuter, this, true);
281  eOuter.preventDefault();
282  return false;
283  },
284  detailExpand: function (eOuter) {
285  openDetails[$(eOuter.masterRow).find(".trustedId").text()]= true;
286  $(eOuter.detailRow).find(".detailGrid").data("kendoGrid").dataSource.read();
287  },
288  detailCollapse: function (eOuter) {
289  delete openDetails[$(eOuter.masterRow).find(".trustedId").text()];
290  }
291  }).data("kendoGrid");
292 
293  fullContextMenu= new getFullContextMenu(grid, "contextMenu", "trustedId", "detailName");
294  fullContextMenu.setOptionFuncs(null, detailOptionFunc, additionalSelectOptionFunc); // Master options are default.
295  fullContextMenu.setDeleteOptions("<?php echo $dataPath; ?>", "removeTrustedId", "removeTrustedDetail", function(isMaster, dataItemForDelete) {
296  if (isMaster)
297  {
298  var data= grid.dataSource.data().slice(0);
299  data= $.grep(data, function(n,i) { return n.trustedId != dataItemForDelete.trustedId; });
300  detailRecords= $.grep(detailRecords, function(n,i) { return n.trustedId != dataItemForDelete.trustedId; });
301  $(".detailGrid:visible").each(function () { $(this).data("kendoGrid").dataSource.read(); });
302  grid.dataSource.data(data);
303  }
304  else
305  {
306  detailRecords= $.grep(detailRecords, function(n,i) { return n.trustedId == dataItemForDelete.trustedId && n.detailName == dataItemForDelete.detailName;}, true);
307  $(".detailGrid:visible").each(function () { $(this).data("kendoGrid").dataSource.read(); });
308  }
309  }, function(dataItem) {
310  return $.grep(detailRecords, function(n,i) { n.trustedId == dataItem.trustedId; }).length;
311  });
312 }
313 
314 function detailOptionFunc(options, dataItem)
315 {
316  options.push({text: "Edit", cssClass: "editLi"});
317  options.push({text: "Delete", cssClass: "deleteLi"});
318 
319  if (dataItem.trustedId == "HOMECUSERVICE") // Only allow reorder on regular trustedIds. The HOMECUSERVICE one is supposed to be sorted alphabetically.
320  return;
321 
322  var data= $.grep(detailRecords, function(n,i) { return n.trustedId == dataItem.trustedId; });
323  data.sort(function(a,b) { return a.displayOrder - b.displayOrder; });
324 
325  if (data.length >= 2) // Will need at least two tasks for move before and move after to make sense.
326  {
327  var moveBeforeChoices= [];
328  var moveAfterChoices= [];
329  this.taskIndex= -1;
330  for (var i=0; i!= data.length; i++)
331  {
332  moveBeforeChoices.push({text: data[i].detailName, cssClass: "moveBeforeChoiceLi task_"+i});
333  moveAfterChoices.push({text: data[i].detailName, cssClass: "moveAfterChoiceLi task_"+i});
334  if (data[i].detailName == dataItem.detailName)
335  this.taskIndex= i;
336  }
337 
338  if (data.length == 2)
339  {
340  this.taskIndex == 0 ? moveBeforeChoices= [] : moveBeforeChoices.splice(this.taskIndex, 1);
341  this.taskIndex == 1 ? moveAfterChoices= [] : moveAfterChoices.splice(this.taskIndex, 1);
342  }
343  else
344  {
345  moveBeforeChoices.splice(this.taskIndex, 2);
346  this.taskIndex == 0 ? moveAfterChoices.splice(0, 1) : moveAfterChoices.splice(this.taskIndex-1, 2);
347  }
348 
349  if (moveBeforeChoices.length > 0)
350  options.push({text: "Move before...", items: moveBeforeChoices, cssClass: "moveBeforeLi"});
351  if (moveAfterChoices.length > 0)
352  options.push({text: "Move after...", items: moveAfterChoices, cssClass: "moveAfterLi"});
353  }
354 }
355 
356 function additionalSelectOptionFunc(item, tr, grid, dataItem)
357 {
358  if ($(item).hasClass("moveAfterChoiceLi") || $(item).hasClass("moveBeforeChoiceLi"))
359  {
360  var classes= $(item).attr("class").split(/\s+/);
361  var moveTaskId= 0;
362  for(var i=0; i!= classes.length; i++)
363  {
364  var parts= classes[i].split(/_/);
365  if (parts[0].trim() == "task")
366  {
367  moveTaskId= Number(parts[1]);
368  break;
369  }
370  }
371 
372  if ($(item).hasClass("moveAfterChoiceLi"))
373  moveTaskId++;
374  $.post("<?php echo $dataPath; ?>?operation=reorderTrustedDetail", {position: moveTaskId, trustedId: dataItem.trustedId, detailName: dataItem.detailName},
375  function (data) {
376  hideWaitWindow();
377  showSQL(data);
378  if (!errorsAreShown(data, "formValidateMainDiv"))
379  {
380  detailRecords= $.grep(detailRecords, function(n,i) { return n.trustedId != dataItem.trustedId; });
381  for(var i=0, length= data.record.length; i!= length; i++)
382  {
383  detailRecords.push(data.record[i]);
384  }
385  grid.dataSource.read();
386  $("#grid").data("kendoGrid").expandRow($(tr).closest(".k-detail-row").prev()); // The outer grid collapses normally but need to still show the grid changed.
387  }
388  });
389  }
390 }
391 
392 <?php /* Initializes the bottom-level grid when the trustedId = HOMECUSERVICE. */ ?>
393 function initServerMasterGrid(eOuter, serverOptions)
394 {
395  var detailGridInitialized= false;
396 
397  var detailGrid= eOuter.detailRow.find(".detailGrid").kendoGrid({
398  dataSource: {
399  transport: {
400  read: function (options) {
401  options.success(detailRecords);
402  },
403  create: function (options) {
404  var parameters= {detailName: options.data.detailName, defaultMessage: options.data.defaultMessage, defaultValue: options.data.defaultValue};
405  showWaitWindow();
406  $.post("<?php echo $dataPath; ?>?operation=addServerProperty", parameters,
407  function(data) {
408  hideWaitWindow();
409  showSQL(data);
410 
411  if (!errorsAreShown(data, "formValidatePopupDetailDiv"))
412  {
413  options.success(data.record);
414  }
415  });
416  },
417  update: function (options) {
418  var parameters= {detailName: options.data.detailName, defaultMessage: options.data.defaultMessage, defaultValue: options.data.defaultValue};
419  showWaitWindow();
420  $.post("<?php echo $dataPath; ?>?operation=updateServerProperty", parameters, function (data) {
421  hideWaitWindow();
422  showSQL(data);
423 
424  if (!errorsAreShown(data, "formValidatePopupDetailDiv"))
425  {
426  options.success(data.record);
427  }
428  });
429  }
430  },
431  schema: {
432  model: {
433  id: "detailName",
434  fields: {
435  detailName: {type: "string"},
436  defaultMessage: {type: "string"},
437  defaultValue: {type: "string"},
438  trustedId: {type: "string", defaultValue: eOuter.data.trustedId}
439  }
440  }
441  },
442  sort: {field: "detailName", dir: "asc"},
443  filter: {field: "trustedId", operator: "eq", value: eOuter.data.trustedId}
444  },
445  editable: {
446  mode: "popup",
447  template: kendo.template($("#popupTemplateServerProperties").html()),
448  window: {
449  draggable: false,
450  resizable: false,
451  title: "<span class='gridWindowTitle'></span>",
452  actions: [],
453  width: 400,
454  autoFocus: false
455  }
456  },
457  columns: [
458  {field: "detailName", title: "Description"},
459  {field: "defaultValue", title: "Default Value", values: serverOptions},
460  {field: "defaultMessage", title: "Default Message"}
461  ],
462  sortable: true,
463  filterable: {extra: false},
464  edit: function (eInner) {
465  setupValidatorInGrid(eInner, true);
466 
467  var serverOptionsDDL= $("#serverOptionsDDL").kendoDropDownList({
468  dataSource: {
469  data: serverOptions
470  },
471  dataTextField: "text",
472  dataValueField: "value",
473  filter: "startswith",
474  change: function () {
475  eInner.model.defaultValue= this.value();
476  eInner.model.dirty= true;
477  }
478  }).data("kendoDropDownList");
479 
480  $("#serverMessageInput").blur(function () {
481  eInner.model.defaultMessage= $(this).val();
482  eInner.model.dirty= true;
483  });
484 
485  if (eInner.model.isNew())
486  {
487  $(".gridWindowTitle").text("Add Detail");
488  $("#nameLabel").remove();
489 
490  $(".nameInput").blur(function () {
491  $(this).val($(this).val().replace(/\s+/g, ""));
492  addPropertyDuplicateError(eInner, $(this).val(), eOuter.data.trustedId, eInner.model.uid, false, detailGrid);
493  addNoMsgError(eInner, $(this).val(), false);
494  });
495 
496  eInner.model.defaultValue= serverOptionsDDL.value();
497  }
498  else
499  {
500  $(".gridWindowTitle").text("Update Detail");
501  $(".nameInput").remove();
502 
503  serverOptionsDDL.value(eInner.model.defaultValue);
504  $("#serverMessageInput").val(eInner.model.defaultMessage);
505  }
506 
507  $("#serverMessageInput").focus();
508  },
509  save: function (eInner) {
510  useValidatorInGrid(eInner, true);
511 
512  if (eInner.model.isNew())
513  {
514  addPropertyDuplicateError(eInner, $(".nameInput").val(), eOuter.data.trustedId, eInner.model.uid, true, detailGrid);
515  addNoMsgError(eInner, $(".nameInput").val(), true);
516  }
517  eInner.model.detailName= eInner.model.detailName.replace(/\s+/g, "");
518 
519  },
520  dataBound: function (eInner)
521  {
522  var gridElement= eOuter.detailRow.find(".detailGrid");
523  fullContextMenu.gridDatabound (false, detailGridInitialized, this);
524  if (!detailGridInitialized)
525  {
526  addMinifiedActionStyle(gridElement);
527  detailGridInitialized= true;
528  }
529  },
530  cancel: function (eInner) {
531  this.cancelChanges();
532  fullContextMenu.gridCancel(eInner, this, false);
533  eInner.preventDefault();
534  return false;
535  }
536  }).data("kendoGrid");
537 
538  fullContextMenu.addToDetailGrid (eOuter.data.trustedId, detailGrid);
539 }
540 
541 <?php /* Initializes the bottom-level grid when trustedId is not HOMECUSERVICE. */ ?>
542 function initDetailGrid(eOuter, fieldTypeDDLData)
543 {
544  var detailGridInitialized= false;
545 
546  var detailGrid= eOuter.detailRow.find(".detailGrid").kendoGrid({
547  dataSource: {
548  transport: {
549  read: function (options) {
550  options.success(detailRecords);
551  },
552  create: function (options) {
553  var parameters= {trustedId: eOuter.data.trustedId, detailName: options.data.detailName, fieldType: options.data.fieldType, defaultValue: options.data.defaultValue,
554  defaultMessage: options.data.defaultMessage};
555  showWaitWindow();
556  $.post("<?php echo $dataPath; ?>?operation=addTrustedDetail", parameters,
557  function(data) {
558  hideWaitWindow();
559  showSQL(data);
560 
561  if (!errorsAreShown(data, "formValidatePopupDetailDiv"))
562  {
563  options.success(data.record);
564  detailRecords.push(data.record[0]);
565  }
566  });
567  },
568  update: function (options) {
569  var parameters= {trustedId: eOuter.data.trustedId, detailName: options.data.detailName, fieldType: options.data.fieldType, defaultValue: options.data.defaultValue,
570  defaultMessage: options.data.defaultMessage};
571  showWaitWindow();
572  $.post("<?php echo $dataPath; ?>?operation=updateTrustedDetail", parameters, function (data) {
573  hideWaitWindow();
574  showSQL(data);
575 
576  if (!errorsAreShown(data, "formValidatePopupDetailDiv"))
577  {
578  options.success(data.record);
579  }
580  });
581  }
582  },
583  schema: {
584  model: {
585  id: "detailName",
586  fields: {
587  detailName: {type: "string"},
588  fieldType: {type: "string"},
589  fieldTypeText: {type: "string"},
590  defaultValue: {type: "string"},
591  defaultMessage: {type: "string"},
592  trustedId: {type: "string"},
593  displayOrder: {type: "number"}
594  }
595  }
596  },
597  sort: {field: "displayOrder", dir: "asc"},
598  filter: {field: "trustedId", operator: "eq", value: eOuter.data.trustedId}
599  },
600  editable: {
601  mode: "popup",
602  template: kendo.template($("#popupTemplateDetail").html()),
603  window: {
604  draggable: false,
605  resizable: false,
606  title: "<span class='gridWindowTitle'></span>",
607  actions: [],
608  width: 400,
609  autoFocus: false
610  }
611  },
612  columns: [
613  {field: "detailName", title: "Title"},
614  {field: "fieldType", title: "Field Type", values: fieldTypeDDLData, width: "10%"},
615  {field: "defaultValue", title: "Default Value"},
616  {field: "defaultMessage", title: "Description"}
617  ],
618  sortable: true,
619  filterable: {extra: false},
620  edit: function (eInner) {
621  setupValidatorInGrid(eInner, true);
622 
623  $("#defaultValueTextInput").blur(function () {
624  eInner.model.dirty= true;
625  eInner.model.defaultValue= $(this).val();
626  });
627 
628  $("#defaultValueBooleanInput").click(function () {
629  eInner.model.dirty= true;
630  eInner.model.defaultValue= $(this).prop("checked") ? "Y" : "N";
631  });
632 
633  var defaultValueNumericInput= $("#defaultValueNumericInput").kendoNumericTextBox({
634  change: function () {
635  eInner.model.dirty= true;
636  eInner.model.defaultValue= this.value();
637  }
638  }).data("kendoNumericTextBox");
639 
640  var index= 0;
641  var inEditCell= false;
642  var defaultValueGrid= $("#defaultValueGrid").kendoGrid({
643  dataSource: {
644  data: [],
645  schema: {
646  model: {
647  id: "index",
648  fields: {
649  index: {type: "number"},
650  value: {type: "string"}
651  }
652  }
653  }
654  },
655  columns: [
656  {field: "index", hidden: true},
657  {command: [{name: "customDelete", text: "", iconClass: "k-icon k-i-delete", click: function(e) {
658  eInner.model.dirty= true;
659  getDefaultValueFromGrid(eInner, e, defaultValueGrid, true);
660  return false;
661  }}], width: "45px"},
662  {field: "value"}
663  ],
664  toolbar: [{name: "create", text: ""}],
665  editable: {
666  mode: "incell",
667  confirmation: false
668  },
669  edit: function (eGrid) {
670  if (eGrid.model.isNew())
671  eGrid.model.index= ++index;
672  },
673  save: function (eGrid) {
674  eInner.model.dirty= true;
675  getDefaultValueFromGrid(eInner, eGrid, this, false);
676  },
677  dataBound: function () {
678  addMinifiedActionStyle("#defaultValueGrid", true);
679  }
680  }).data("kendoGrid");
681 
682  var detailTypeDDL= $("#detailTypeDDL").kendoDropDownList({
683  dataSource: fieldTypeDDLData,
684  dataTextField: "text",
685  dataValueField: "value",
686  filter: "startswith",
687  change: function () {
688  eInner.model.dirty= true;
689  eInner.model.fieldType= this.value();
690  fieldTypeChange(eInner, defaultValueGrid, defaultValueNumericInput, eInner.model.fieldType, true);
691  }
692  }).data("kendoDropDownList");
693 
694  if (eInner.model.isNew())
695  {
696  $(".gridWindowTitle").text("Add Detail");
697  $("#nameLabel").remove();
698 
699  $(".nameInput").blur(function () {
700  $(this).val($(this).val().replace(/\s+/g, ""));
701  addPropertyDuplicateError(eInner, $(this).val(), eOuter.data.trustedId, eInner.model.uid, false, detailGrid);
702  });
703 
704  fieldTypeChange(eInner, defaultValueGrid, defaultValueNumericInput, "string", false);
705  eInner.model.fieldType= "string";
706  }
707  else
708  {
709  $(".gridWindowTitle").text("Update Detail");
710  $(".nameInput").remove();
711  detailTypeDDL.value(eInner.model.fieldType);
712  fieldTypeChange(eInner, defaultValueGrid, defaultValueNumericInput, eInner.model.fieldType, false);
713  }
714  },
715  save: function (eInner) {
716  useValidatorInGrid(eInner, true);
717 
718  if (eInner.model.isNew())
719  addPropertyDuplicateError(eInner, $(".nameInput").val(), eOuter.data.trustedId, eInner.model.uid, true, detailGrid);
720  eInner.model.detailName= eInner.model.detailName.replace(/\s+/g, "");
721  },
722  dataBound: function (eInner)
723  {
724  var gridElement= eOuter.detailRow.find(".detailGrid");
725  fullContextMenu.gridDatabound (false, detailGridInitialized, this);
726  if (!detailGridInitialized)
727  {
728  addMinifiedActionStyle(gridElement);
729  detailGridInitialized= true;
730  }
731  },
732  cancel: function (eInner) {
733  this.cancelChanges();
734  fullContextMenu.gridCancel(eInner, this, false);
735  eInner.preventDefault();
736  return false;
737  }
738  }).data("kendoGrid");
739 
740  fullContextMenu.addToDetailGrid (eOuter.data.trustedId, detailGrid);
741 }
742 
743 <?php /* This gets the detault value from the grid when the field type is "list." */ ?>
744 function getDefaultValueFromGrid(eInner, eGrid, grid, isDeleting)
745 {
746  eInner.model.dirty= true;
747  var data= grid.dataSource.data();
748 
749  if (isDeleting)
750  {
751  var deletingIndex= Number($(eGrid.target).closest("tr").find("td:eq(0)").text());
752  data= $.grep(data, function(n,i) { return n.index != deletingIndex; });
753  grid.dataSource.data(data);
754  }
755  var defaultValueArray= [];
756  for (var i=0; i!= data.length; i++)
757  {
758  if (!isDeleting && data[i].index == eGrid.model.index)
759  defaultValueArray.push(eGrid.values.value);
760  else
761  defaultValueArray.push(data[i].value);
762  }
763  eInner.model.defaultValue= kendo.stringify(defaultValueArray);
764 }
765 
766 <?php /* This changes the input when the field type changes so when it is Boolean, a checkbox shows; when it is Numeric, a NumericTextBox shows; etc. */ ?>
767 function fieldTypeChange(eInner, defaultValueGrid, defaultValueNumericInput, newValue, updateModel)
768 {
769  switch(newValue)
770  {
771  case "digits":
772  $("#defaultValueTextDiv").hide();
773  $("#defaultValueBooleanDiv").hide();
774  $("#defaultValueNumericDiv").show();
775  $("#defaultValueListDiv").hide();
776 
777  if (updateModel)
778  {
779  defaultValueNumericInput.value(0);
780  eInner.model.defaultValue= "0";
781  }
782  else
783  {
784  defaultValueNumericInput.value(eInner.model.defaultValue);
785  }
786 
787  defaultValueNumericInput.focus();
788  break;
789  case "string":
790  $("#defaultValueTextDiv").show();
791  $("#defaultValueBooleanDiv").hide();
792  $("#defaultValueNumericDiv").hide();
793  $("#defaultValueListDiv").hide();
794 
795  if (updateModel)
796  {
797  $("#defaultValueTextInput").val(null);
798  eInner.model.defaultValue= "";
799  }
800  else
801  {
802  $("#defaultValueTextInput").val(eInner.model.defaultValue);
803  }
804 
805  $("#defaultValueTextInput").focus();
806  break;
807  case "boolean":
808  $("#defaultValueTextDiv").hide();
809  $("#defaultValueBooleanDiv").show();
810  $("#defaultValueNumericDiv").hide();
811  $("#defaultValueListDiv").hide();
812 
813  if (updateModel)
814  {
815  $("#defaultValueBooleanInput").prop("checked", false);
816  eInner.model.defaultValue= "N";
817  }
818  else
819  {
820  $("#defaultValueBooleanInput").prop("checked", eInner.model.defaultValue == "Y");
821  }
822 
823  $("#defaultValueBooleanInput").focus();
824  break;
825  case "list":
826  $("#defaultValueTextDiv").hide();
827  $("#defaultValueBooleanDiv").hide();
828  $("#defaultValueNumericDiv").hide();
829  $("#defaultValueListDiv").show();
830 
831  if (updateModel)
832  {
833  defaultValueGrid.dataSource.data([]);
834  eInner.model.defaultValue= "[]";
835  }
836  else
837  {
838  var defaultValueDecoded= [];
839  if (eInner.model.defaultValue != null)
840  {
841  var defaultValue= eInner.model.defaultValue.replace(/\\"/g, '"'); // unescape here so JSON is valid.
842  defaultValueDecoded= JSON && JSON.parse(defaultValue) || $.parseJSON(defaultValue);
843  }
844 
845  var gridData= [];
846  for(var i=0; i!= defaultValueDecoded.length; i++)
847  {
848  gridData.push({index: i, value: defaultValueDecoded[i]});
849  }
850  defaultValueGrid.dataSource.data(gridData);
851  }
852 
853  // TODO: focus?
854  break;
855  }
856 }
857 
858 <?php /* This prevents user from entering a duplicate trusted id. This is also prevented at the database level. */ ?>
859 function addTrustedIdDuplicateError(e, trustedId, uid, onSave)
860 {
861  var data= $("#grid").data("kendoGrid").dataSource.data();
862  var hasDuplicates= $.grep(data, function (n,i) { return n.trustedId == trustedId && n.uid != uid; }).length > 0;
863 
864  if (hasDuplicates)
865  addError(e, "trustedId", onSave, "duplicate");
866 }
867 
868 <?php /* This prevents user from entering in a duplicate property within a trusted id. Before, a duplicate property would overwrite the previous value but the user won't know until a refresh. */ ?>
869 function addPropertyDuplicateError(e, property, trustedId, uid, onSave, grid)
870 {
871  var data= grid.dataSource.data();
872  var hasDuplicates= $.grep(data, function (n,i) { return n.detailName == property && n.uid != uid && n.trustedId == trustedId; }).length > 0;
873 
874  if (hasDuplicates)
875  addError(e, "detailName", onSave, "duplicate", "formValidatePopupDetailDiv");
876 }
877 
878 <?php /* This prevents user from entering in a server property with _MSG in it since that is reserved for the messages per property. */ ?>
879 function addNoMsgError(e, property, onSave)
880 {
881  var hasMsg= property.indexOf("_MSG") != -1;
882 
883  if (hasMsg)
884  addError(e, "detailName", onSave, "nomsg", "formValidatePopupDetailDiv");
885 }
886 
887 function initMasterDetailsAtOnceTable(eOuter, fieldTypes)
888 {
889  var deleteTr= null;
890  var deleteConfirm= $("<div id='masterDetailsDelete'></div>").kendoWindow({
891  content: {template: $("#deleteConfirmTemplate").html()},
892  draggable: false,
893  visible: false,
894  actions: [],
895  modal: true,
896  title: "Confirm deletion",
897  width: 400,
898  height: 125,
899  resizable: false
900  }).data("kendoWindow");
901 
902  $("#masterDetailsDelete .deleteConfirmContinueBtn").click(function () {
903  atOnceGrid.removeRow(deleteTr);
904  deleteConfirm.close();
905  return false;
906  });
907 
908  $("#masterDetailsDelete .deleteConfirmContinueBtn").click(function() {
909  deleteConfirm.close();
910  return false;
911  })
912 
913  var atOnceGrid= $("#masterDetailAtOnceGrid").kendoGrid({
914  dataSource: {
915  data: $.grep(detailRecords, function(n,i) { return n.trustedId == eOuter.model.trustedId; }),
916  schema: {
917  model: {
918  id: "detailName",
919  fields: {
920  detailName: {type: "string"},
921  fieldType: {type: "string", defaultValue: "string"},
922  fieldTypeText: {type: "string", defaultValue: "String"},
923  defaultValue: {type: "string"},
924  defaultMessage: {type: "string"},
925  trustedId: {type: "string", defaultValue: eOuter.model.trustedId}
926  }
927  }
928  }
929  },
930  columns: [
931  {command: [{name: "customDelete", text: "", iconClass: "k-icon k-delete", click: function(e) {
932  deleteTr= $(e.target).closest("tr");
933  deleteConfirm.open().center();
934  }}], width: "50px"},
935  {field: "detailName", title: "Name", editor: function(container, options) {
936  var input= $("<input type='text' class='k-input k-textbox' name='"+ options.field + "'>").appendTo(container).blur(function() {
937  var value= $(this).val().replace(/\s+/g, "");
938  $(this).val(value);
939  options.model.detailName= value;
940  });
941  }},
942  {field: "fieldTypeText", title: "Type", editor: function(container, options) {
943  var ddl= $("<div></div>").appendTo(container).kendoDropDownList({
944  dataSource: {
945  data: fieldTypes
946  },
947  dataTextField: "text",
948  dataValueField: "value",
949  filter: "startswith",
950  value: options.model.fieldType,
951  change: function () {
952  switch(this.value())
953  {
954  case "digits":
955  options.model.defaultValue= 0;
956  break;
957  case "boolean":
958  options.model.defaultValue= "N";
959  break;
960  case "list":
961  case "string":
962  default:
963  options.model.defaultValue= "";
964  break;
965  }
966  options.model.fieldType= this.value();
967  options.model.fieldTypeText= this.text();
968  $(container).parent().find("td:eq(2)").text(options.model.defaultValue);
969  }
970  }).data("kendoDropDownList");
971  }},
972  {field: "defaultValue", title: "Value", editor: function(container, options) {
973  switch(options.model.fieldType)
974  {
975  case "digits":
976  var input= $("<input name='" + options.field + "'>").appendTo(container).kendoNumericTextBox({});
977  break;
978  case "boolean":
979  var input= $("<input type='checkbox'>").appendTo(container).click(function () {
980  options.model.defaultValue= $(this).prop("checked") ? "Y" : "N";
981  });
982  if (options.model.defaultValue == "Y")
983  $(input).prop("checked", true);
984  break;
985  case "list":
986  case "string":
987  default:
988  var input= $("<textarea name='" + options.field + "' class='k-input' type='text' style='width: 100%;' row=15 col=40></textarea>").appendTo(container);
989  }
990  }},
991  {field: "defaultMessage", title: "Message", editor: function(container, options) {
992  var input= $("<textarea name='" + options.field + "' class='k-input' type='text' style='width: 100%;' row=15 col=40></textarea>").appendTo(container);
993  }}
994  ],
995  toolbar: [{name: "create", text: ""}],
996  editable: {
997  confirmation: false
998  },
999  dataBound: function () {
1000  addMinifiedActionStyle("#masterDetailAtOnceGrid", true);
1001  },
1002  save: function () {
1003  eOuter.model.detailsChanged= true;
1004  },
1005  height: 250
1006  }).data("kendoGrid");
1007 
1008  $("#masterDetailAtOnceGrid").on("blur", "[name='detailName']", function() {
1009  $(this).val($(this).val().replace(/\s+/g, ""));
1010  });
1011 }
1012 
1013 $(document).ready(function () {
1014  initAccordion();
1015  initGrid();
1016 });
1017 </script>
1018 
1019 <script id="popupTemplate" type="text/x-kendo-template">
1020  <div id="formValidatePopupDiv" class="homecu-formStatus k-block k-error-colored" style="display:none;"></div>
1021  <form id="popupForm" class="popupForm" data-role="validator" novalidate>
1022  <div class="container_12">
1023  <div class="grid_12">
1024  <div class="grid_2 alpha">
1025  <label>Id:</label>
1026  </div>
1027  <div class="grid_4">
1028  <div id="nameLabel">#: trustedId #</div>
1029  <input type="text" class="k-input nameInput" name="trustedId" required data-required-msg="Id is required" data-duplicate-msg="trusted Id needs to be unique"
1030  maxlength=20 style="width:100%">
1031  </div>
1032  <div class="grid_1 omega">
1033  <span data-for='trustedId' class='k-invalid-msg'></span>
1034  </div>
1035  </div>
1036  <div class="grid_12">
1037  <div class="grid_2 alpha">
1038  <label>Vendor:</label>
1039  </div>
1040  <div class="grid_4">
1041  <input name="vendorName" type="text" class="k-input" required data-required-msg="Vendor is required" maxlength=15 style="width:100%">
1042  </div>
1043  <div class="grid_1 omega">
1044  <span data-for='vendorName' class='k-invalid-msg'></span>
1045  </div>
1046  </div>
1047  <div class="grid_12">
1048  <div class="grid_2 alpha">
1049  <label>Type:</label>
1050  </div>
1051  <div class="grid_4">
1052  <div id="typeDDL" style="width:100%"></div>
1053  </div>
1054  <div class="grid_1 omega">
1055  &nbsp;
1056  </div>
1057  </div>
1058  <div class="grid_12">
1059  <div class="grid_2 alpha">
1060  <label>Details:</label>
1061  </div>
1062  <div class="grid_10">
1063  <div id="masterDetailAtOnceGrid"></div>
1064  </div>
1065  </div>
1066  </div>
1067  </form>
1068 </script>
1069 <script id="popupTemplateServerProperties" type="text/x-kendo-template">
1070  <div id="formValidatePopupDetailDiv" class="homecu-formStatus k-block k-error-colored" style="display:none;"></div>
1071  <form id="popupFormDetail" class="popupForm" data-role="validator" novalidate>
1072  <div class="container_12">
1073  <div class="grid_12">
1074  <div class="grid_4 alpha">
1075  <label>Id:</label>
1076  </div>
1077  <div class="grid_7">
1078  <div id="nameLabel">#: detailName #</div>
1079  <input type="text" class="k-input nameInput" name="detailName" required data-required-msg="Id is required" data-duplicate-msg="Property needs to be unique"
1080  maxlength=20 style="width:100%" data-nomsg-msg="Property cannot have _MSG in its name">
1081  </div>
1082  <div class="grid_1 omega">
1083  <span data-for='detailName' class='k-invalid-msg'></span>
1084  </div>
1085  </div>
1086  <div class="grid_12">
1087  <div class="grid_4 alpha">
1088  <label>Default Value:</label>
1089  </div>
1090  <div class="grid_7">
1091  <div id="serverOptionsDDL"></div>
1092  </div>
1093  </div>
1094  <div class="grid_12">
1095  <div class="grid_4 alpha">
1096  <label>Default Message:</label>
1097  </div>
1098  <div class="grid_7">
1099  <textarea class="k-input" type="text" id="serverMessageInput" style="width: 100%; height: 100px" row=15 col=40></textarea>
1100  </div>
1101  </div>
1102  </div>
1103  </form>
1104 </script>
1105 <script id="popupTemplateDetail" type="text/x-kendo-template">
1106  <div id="formValidatePopupDetailDiv" class="homecu-formStatus k-block k-error-colored" style="display:none;"></div>
1107  <form id="popupFormDetail" class="popupForm" data-role="validator" novalidate>
1108  <div class="container_12">
1109  <div class="grid_12">
1110  <div class="grid_4 alpha">
1111  <label>Id:</label>
1112  </div>
1113  <div class="grid_7">
1114  <div id="nameLabel">#: detailName #</div>
1115  <input type="text" class="k-input nameInput" name="detailName" required data-required-msg="Id is required" data-duplicate-msg="Property needs to be unique"
1116  maxlength=20 style="width:100%">
1117  </div>
1118  <div class="grid_1 omega">
1119  <span data-for='detailName' class='k-invalid-msg'></span>
1120  </div>
1121  </div>
1122  <div class="grid_12">
1123  <div class="grid_4 alpha">
1124  <label>Field Type:</label>
1125  </div>
1126  <div class="grid_7">
1127  <div id="detailTypeDDL"></div>
1128  </div>
1129  <div class="grid_1 omega">
1130  &nbsp;
1131  </div>
1132  </div>
1133  <div class="grid_12">
1134  <div class="grid_4 alpha">
1135  <label>Default Value:</label>
1136  </div>
1137  <div class="grid_7">
1138  <div id="defaultValueTextDiv" style="display: none;">
1139  <textarea class="k-input" type="text" id="defaultValueTextInput" style="width: 100%; height: 100px" row=15 col=40></textarea>
1140  </div>
1141  <div id="defaultValueBooleanDiv" style="display: none;">
1142  <input type="checkbox" id="defaultValueBooleanInput">
1143  </div>
1144  <div id="defaultValueNumericDiv" style="display:none;">
1145  <input id="defaultValueNumericInput">
1146  </div>
1147  <div id="defaultValueListDiv" style="display: none;">
1148  <div id="defaultValueGrid" style="width: 100%"></div>
1149  </div>
1150  </div>
1151  <div class="grid_1 omega">
1152  &nbsp;
1153  </div>
1154  </div>
1155  <div class="grid_12">
1156  <div class="grid_4 alpha">
1157  <label>Description:</label>
1158  </div>
1159  <div class="grid_7">
1160  <textarea class="k-input" type="text" name="defaultMessage" style="width: 100%; height: 100px" row=15 col=40></textarea>
1161  </div>
1162  <div class="grid_1 omega">
1163  &nbsp;
1164  </div>
1165  </div>
1166  </div>
1167  </form>
1168 </script>
1169 <script id="deleteConfirmTemplate" type="text/x-kendo-template">
1170  <div class="k-edit-form-container">
1171  <div class="container_12">
1172  <div class="grid_12 message">Are you sure that you want to delete? <span id="detailDeleteMsg" style="display:none;">This will also delete <span>1</span> detail(s) as well.</div>
1173  </div>
1174  <div class="k-edit-buttons k-state-default">
1175  <a class="k-button k-button-icontext deleteConfirmContinueBtn" href="\#">
1176  <span class="k-icon k-i-check"></span>
1177  Continue
1178  </a>
1179  <a class="k-button k-button-icontext deleteConfirmCancelBtn" href="\#">
1180  <span class="k-icon k-i-cancel"></span>
1181  Cancel
1182  </a>
1183  </div>
1184  </div>
1185 </script>
1186 
1187 <?php printMonitorPageMiddle("Trusted Vendors"); ?>
1188 
1189  <div id="trustedListDiv" class="container_12">
1190  <div class="grid_12">
1191  <ul id="accordion">
1192  <li><span style='color: rgb(51, 131, 187);'>Looking for something?</span>
1193  <ul>
1194  <li>
1195  <p>
1196  Are you trying to change the service status for a HOMECU Vendor?<br/>
1197  This table maintains the default settings for each vendor in the cutrustedmaster table.<br/>
1198  All homecu services are listed under the HOMECUSERVICE Trusted ID <br/>
1199  To change the service, you must use the 'Service Settings' on the server menu<br/>
1200  <a href='https://www.homecu.net/hcuadm/servindex.prg?rowid=www3' target='_blank'>www3</a>
1201  <a href='https://www.homecu.net/hcuadm/servindex.prg?rowid=www5' target='_blank'>www5</a>
1202  <a href='https://www.homecu.net/hcuadm/servindex.prg?rowid=www6' target='_blank'>www6</a>
1203  </p>
1204  </ul>
1205  </li>
1206  </ul>
1207  </div>
1208  <div class="grid_12">
1209  &nbsp;
1210  </div>
1211  <div class="grid_12">
1212  <div id="sqlOutput"></div>
1213  </div>
1214  <div class="grid_12">
1215  <div id="formValidateMainDiv" class="k-block k-error-colored" style="display:none;"></div>
1216  </div>
1217  <div class="grid_12">
1218  <div id="grid"></div>
1219  </div>
1220  </div>
1221  </div>
1222  <div id='hideSubmitWait' style='position:relative; left:-2000px;top:-2000px;'>
1223  <div id='homecuSubmitWait' class='k-block' >
1224  <div class='k-loading-image'></div>
1225  </div>
1226  </div>
1227  <input type="hidden" id="invalidRequestClientSide">
1228  <input type="hidden" id="invalidRequestServerSide">
1229 
1230 <?php printMonitorPageBottom(); ?>