Odyssey
mBroadcastEmail.prg
1 <?php
2 /**
3  * FILE: mBroadcastEmail.prg
4  * This is a global monitor file for downloading & sending email to CUs.
5  */
6 
7 $monLibrary = dirname(__FILE__) . "/../library";
8 $monIncludes = dirname(__FILE__) . "/../includes";
9 $sharedLibrary = dirname(__FILE__) . "/../../shared/library";
10 require_once("$monLibrary/cu_top.i");
11 require_once("$monLibrary/ck_hticket.i");
12 require_once("$sharedLibrary/commonJsFunctions.i");
13 require_once("$sharedLibrary/errormail.i");
14 require_once("./mBroadcastEmail.data");
15 
16 if (!CheckPerm($link, $Hu, basename($_SERVER['SCRIPT_NAME']), $_SERVER['REMOTE_ADDR'])) {
17  // ** Permissions failed
18  // ** redirect to new page
19  header("Location: /hcuadm/hcu_noperm.prg");
20  exit;
21 }
22 
23 $string = array("filter" => FILTER_SANITIZE_STRING);
24 $stringNoEncodeQuote = array("filter" => FILTER_SANITIZE_STRING, "options" => array("flags" => FILTER_FLAG_NO_ENCODE_QUOTES));
25 $array = array("filter" => FILTER_DEFAULT);
26 $html = array("filter" => FILTER_SANITIZE_SPECIAL_CHARS);
27 $parameters = array();
28 HCU_ImportVars($SYSENV, "IMPORTS", array("operation" => $string, "filteredServers" => $array, "filteredCus" => $array,
29  "body" => $html, "fromEmail" => $string, "subject" => $stringNoEncodeQuote,
30  "fromName" => $stringNoEncodeQuote, "testEmail" => $string));
31 
32 $operation = HCU_array_key_value("operation", $SYSENV["IMPORTS"]);
33 $operation = $operation === false ? "" : trim($operation);
34 $self = "/hcuadm/mBroadcastEmail.prg";
35 
36 if ($operation != "") {
37  $isJson = true;
38  switch ($operation) {
39  case "readSetup":
40  $returnArray = ReadSetup($dbh, $SYSENV);
41  break;
42  case "downloadCSV":
43  $isJson = false;
44  DownloadCSV($dbh, $SYSENV);
45  break;
46  case "sendTestEmail":
47  $returnArray = SendTestEmail($dbh, $SYSENV);
48  break;
49  case "sendEmails":
50  $returnArray = SendEmails($dbh, $SYSENV);
51  break;
52  default: // Won't get here
53  $returnArray = array("status" => "001", "error" => "Operation not specified: '$operation'");
54  break;
55  }
56 
57  if ($isJson) {
58  header('Content-type: application/json');
59  print HCU_JsonEncode($returnArray);
60  }
61 
62 } else {
63  PrintMainPage($self);
64 }
65 
66 /**
67  * function PrintMainPage($self)
68  * Prints the page
69  *
70  * @param $self -- the relative URL to this script.
71  * @return void
72  */
73 function PrintMainPage($self) {
74  $title = "Broadcast Emails";
75  printMonitorPageTop($title, GetHomecuKendoVersion("monitor"), GetCloudFrontDomainName(), GetHomecuBootstrapVersion(), GetFontawesomeVersion(), true);
76  printMonitorPageMiddle($title, null);
77 
78  $cloudfrontDomainName = GetCloudFrontDomainName();
79  $tinymceVersion = GetTinyMCEVersion ();
80  ?>
81  <script type="text/javascript" src="https://<?php echo $cloudfrontDomainName; ?>/homecu/js/tinymce/<?php echo $tinymceVersion; ?>/tinymce.min.js"></script>
82  <script type="text/javascript" src="https://<?php echo $cloudfrontDomainName; ?>/homecu/js/tinymce/homecuchar.plugin.js"></script>
83 
84  <?php
85  /**
86  * The Javascript portion of the page.
87  */
88  ?>
89  <script type="text/javascript">
90  <?php
91  // Library javascript functions
92  getShowWaitFunctions();
93  ?>
94 
95  <?php
96  /**
97  * function InitPage()
98  * Initializes the page. In this case, it is creating the kendo grid, and click events for the buttons.
99  */
100  ?>
101  function InitPage() {
102  $.homecuValidator.setup({formValidate: 'form', formStatusField: 'formValidateDiv', homecuCustomRules: {
103  validateemail: function(input) {
104  if (!$(input).is("[name='fromEmail_input']:visible, [name='testEmail']:visible")) {
105  return true;
106  }
107  var name = $(input).attr("name").trim();
108  var value = $(input).val().trim();
109  var label = name == "fromEmail_input" ? "from email" : "test email";
110  if (value == "" && name == "fromEmail_input") {
111  $(input).attr("data-validateemail-msg", "The " + label + " is required.");
112  return false;
113  }
114  var pattern = $.homecuValidator.patterns.email;
115  if (value != "" && !pattern.test(value)) {
116  $(input).attr("data-validateemail-msg", "The " + label + " is invalid.");
117  return false;
118  }
119 
120  return true;
121  }
122  }});
123  var tinyFocused = false;
124 
125  <?php
126  /**
127  * @var tinymce -- a global for setting up the email part.
128  */
129  ?>
130  var toolbar1 = "code newdocument | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify" +
131  "| fontselect fontsizeselect | bullist numlist";
132  var toolbar2 = "outdent indent blockquote | undo redo | link unlink image | preview | forecolor backcolor | removeformat | homecuchar | nonbreaking";
133  tinymce.init({
134  selector: "#emailBody",
135  relative_urls: false,
136  remove_script_host : false,
137  plugins: [
138  "advlist autolink link image lists preview anchor pagebreak",
139  "searchreplace visualblocks visualchars code insertdatetime nonbreaking",
140  "table contextmenu directionality template textcolor homecuchar paste textcolor"
141  ],
142  toolbar1: toolbar1,
143  toolbar2: toolbar2,
144  toolbar3: "",
145  menubar : false,
146  toolbar_items_size: "small",
147  valid_children : "+body[style]",
148  auto_focus: "emailBody",
149  init_instance_callback: function (editor) {
150  $("#emailBody_ifr").attr("tabindex", -1); <?php // Prevent browser from stopping at a field that doesn't do anything. ?>
151 
152  editor.on("click", function(e) {
153  tinymce.execCommand('mceFocus',true,'emailBody');
154  tinyFocused = true;
155  });
156  }
157  });
158 
159  <?php
160  /**
161  * Anonymous function
162  * Make sure that tinymce is focused when the underlying control is focused.
163  */
164  ?>
165  $("#emailBodyDiv").focus(function() {
166  if (!tinyFocused) {
167  tinymce.execCommand('mceFocus',true,'emailBody');
168  tinyFocused = true;
169  }
170  });
171 
172  <?php
173  /**
174  * Anonymous function
175  * Make sure that tinymce is blurred when the underlying control is blurred.
176  */
177  ?>
178  $("#emailBodyDiv").blur(function() {
179  if (tinyFocused) {
180  tinymce.execCommand('mceFocus',false,'emailBody');
181  tinyFocused = false;
182  }
183  });
184 
185  <?php
186  /**
187  * @var fromEmailDDL -- This is a list of all approved emails. This comes from the list in the SES role in the cuadmnotify table.
188  */
189  ?>
190  var fromEmailCombobox = $("#fromEmailCombobox").kendoComboBox({
191  dataSource: []
192  }).data("kendoComboBox");
193 
194  <?php
195  /**
196  * @var cuListMultiselect -- User can select individual CUs to send emails or download email list.
197  */
198  ?>
199  var cuListMultiselect = $("#cuListMultiselect").kendoMultiSelect({
200  dataSource: []
201  }).data("kendoMultiSelect");
202 
203  <?php
204  /**
205  * @var serverMultiselect -- User can select individual servers to send emails or download email list.
206  */
207  ?>
208  var serverMultiselect = $("#serverMultiselect").kendoMultiSelect({
209  dataSource: []
210  }).data("kendoMultiSelect");
211 
212  <?php
213  /**
214  * @var actionDropdownlist -- values "email" or "download"
215  */
216  ?>
217  var actionDropdownlist = $("#actionDropdownlist").kendoDropDownList({
218  dataSource: [],
219  dataTextField: "text",
220  dataValueField: "value",
221  change: function () {
222  if (this.value() == "email") {
223  $("#emailOptionsDiv").show();
224  $("#emailBodyDiv").show();
225  } else {
226  $("#emailOptionsDiv").hide();
227  $("#emailBodyDiv").hide();
228  }
229  }
230  }).data("kendoDropDownList");
231 
232  everythingDataSource.read({operation: "readSetup"});
233 
234  <?php
235  /**
236  * When the okay is clicked, either download the CSV file or open the preview window for sending emails.
237  * If the action is to send emails, also check the test email field. If set, send a test email.
238  * Before doing any action however, check to see if validation is successful.
239  */
240  ?>
241  $(".okayBtn").click(function() {
242  if ($.homecuValidator.validate()) {
243  var action = $("#actionDropdownlist").data("kendoDropDownList").value();
244  var filteredServers = kendo.stringify($("#serverMultiselect").data("kendoMultiSelect").value());
245  var filteredCus = kendo.stringify($("#cuListMultiselect").data("kendoMultiSelect").value());
246  switch(action) {
247  case "email":
248  var testEmail = $("[name='testEmail']").val().trim();
249  <?php // Now the only time that something happens here is if there is a test email. ?>
250  if (testEmail != "") {
251  var parameters = {};
252  parameters.operation = "sendTestEmail";
253  parameters.fromEmail = $("#fromEmailCombobox").data("kendoComboBox").value().trim();
254  parameters.fromName = $("[name='fromName']").val().trim();
255  parameters.subject = $("[name='subject']").val().trim();
256  parameters.testEmail = $("[name='testEmail']").val().trim();
257  parameters.body = tinyMCE.activeEditor.getContent();
258 
259  everythingDataSource.read(parameters);
260  }
261  OpenPreviewWindow();
262  break;
263  case "download":
264  $("#downloadCSVForm [name='filteredCus']").val(filteredCus);
265  $("#downloadCSVForm [name='filteredServers']").val(filteredServers);
266  $("#downloadCSVForm").submit();
267  break;
268  }
269 
270  } else {
271  $("#pageContents").animate({ scrollTop: 0 }, { duration: 500 } );
272  }
273  });
274  }
275 
276  var everythingDataSource = null;
277 
278  <?php
279  /**
280  * function InitDataSource
281  * This initializes the dataSource that everyone uses. As per standards, it is preferable to use a DataSource versus $.post.
282  */
283  ?>
284  function InitDataSource() {
285 
286  <?php
287  /**
288  * @var everythingDataSource -- Uses this versus $.post directly.
289  */
290  ?>
291  everythingDataSource = new kendo.data.DataSource({
292  transport: {
293  read: {
294  url: "<?php echo $self; ?>",
295  dataType: "json",
296  type: "POST"
297  },
298  parameterMap: function(data, type) {
299  showWaitWindow();
300  return data;
301  }
302  },
303  schema: {
304  parse: function(results) {
305  hideWaitWindow();
306  if (results.status !== "000") {
307  $.homecuValidator.displayMessage(results.error, $.homecuValidator.settings.statusError );
308  } else if (results.info != null && results.info != "") {
309  $.homecuValidator.displayMessage(results.info, $.homecuValidator.settings.statusInfo );
310  }
311 
312  switch(results.action) {
313  case "read":
314  $("#fromEmailCombobox").data("kendoComboBox").dataSource.data(results.data.emailList);
315  $("#serverMultiselect").data("kendoMultiSelect").dataSource.data(results.data.servers);
316  $("#cuListMultiselect").data("kendoMultiSelect").dataSource.data(results.data.cuList);
317  $("#actionDropdownlist").data("kendoDropDownList").dataSource.data(results.data.actions);
318  break;
319  case "preview":
320  break;
321  }
322 
323  return [];
324  }
325  }
326  });
327  }
328 
329  <?php
330  /**
331  * function OpenPreviewWindow()
332  * Opens up the preview window for sending emails.
333  */
334  ?>
335  function OpenPreviewWindow() {
336  var dialog = $("#previewWindow").data("kendoDialog");
337 
338  if (dialog == null) {
339 
340  <?php
341  /**
342  * @var dialog -- The kendo dialog for previewing the email before sending.
343  */
344  ?>
345  dialog = $("<div id='previewWindow'></div>").appendTo("body").kendoDialog({
346  title: "Preview",
347  actions: [
348  {text: "Send Email", primary: true, action: function() {
349 
350  var parameters = {};
351  parameters.operation = "sendEmails";
352  parameters.fromEmail = $("#fromEmailCombobox").data("kendoComboBox").value().trim();
353  parameters.fromName = $("[name='fromName']").val().trim();
354  parameters.subject = $("[name='subject']").val().trim();
355  parameters.body = tinyMCE.activeEditor.getContent();
356  parameters.filteredServers = kendo.stringify($("#serverMultiselect").data("kendoMultiSelect").value());
357  parameters.filteredCus = kendo.stringify($("#cuListMultiselect").data("kendoMultiSelect").value());
358  everythingDataSource.read(parameters);
359  }},
360  {text: "Cancel"}
361  ],
362  visible: false,
363  open: function() {
364  if (window.activeWindows != null) {
365  window.activeWindows.push(this);
366  }
367  var maxHeight1 = 600;
368  var maxHeight2 = $(window).height() - 150;
369  var maxHeight = maxHeight2 >= maxHeight1 ? maxHeight1 : maxHeight2;
370  var maxWidth1 = 800;
371  var maxWidth2 = $(window).width() - 75;
372  var maxWidth = maxWidth2 >= maxWidth1 ? maxWidth1 : maxWidth2;
373  $("#previewWindow").css({maxHeight: maxHeight, maxWidth: maxWidth});
374  },
375  close: function() {
376  if (window.activeWindows != null) {
377  window.activeWindows.pop();
378  }
379  }
380  }).data("kendoDialog");
381  }
382 
383  var template = kendo.template($("#previewTemplate").html());
384 
385  var previewData = {};
386  previewData.testEmail = $("[name='testEmail']").val().trim();
387  previewData.fromEmail = $("#fromEmailCombobox").data("kendoComboBox").value();
388  previewData.fromName = $("[name='fromName']").val().trim();
389  previewData.subject = $("[name='subject']").val().trim();
390  previewData.emailBody = tinyMCE.activeEditor.getContent();
391 
392  dialog.content(template(previewData)).open();
393  }
394 
395  var activeWindows = [];
396  $(document).ready(function() {
397  InitDataSource();
398  InitPage();
399  <?php printClickOverlayEvent(); ?>
400  });
401  </script>
402 
403  <?php
404  /**
405  * @var previewTemplate
406  * This is a template for the preview window.
407  */
408  ?>
409  <script type="text/x-kendo-template" id="previewTemplate">
410  <div class="container hcu-all-100 hcu-no-padding">
411  # if (testEmail != "") { #
412  <div class="col-xs-12 hcu-no-padding">
413  <label class="col-xs-12 k-info-colored">Check email for <b>#: testEmail #</b> to view test message.</label>
414  </div>
415  <div class="col-xs-12">&nbsp;</div>
416  # } #
417  <div class="col-xs-12 hcu-no-padding">
418  <div id='previewValidateDiv' class='k-block k-error-colored col-xs-12' style='display:none;'></div>
419  </div>
420  <div class="col-xs-12">&nbsp;</div>
421  <div class="col-xs-12 col-sm-4 hcu-no-padding">
422  <label class="col-xs-4 col-sm-12">From</label>
423  <div class="col-xs-8 col-sm-12"><div class="admIndent">#: fromName # <div class="visible-xs-block"><br></div> (#: fromEmail #)</div></div>
424  </div>
425  <div class="visible-xs-block col-xs-12">&nbsp;</div>
426  <div class="visible-xs-block col-xs-12">&nbsp;</div>
427  <div class="col-xs-12 col-sm-4 hcu-no-padding">
428  <label class="col-xs-4 col-sm-12">Subject</label>
429  <div class="col-xs-8 col-sm-12"><div class="admIndent">#: subject #</div></div>
430  </div>
431  <div class="col-xs-12">&nbsp;</div>
432  <div class="col-xs-12 hcu-no-padding">
433  <label class="col-xs-12">Body of Email</label>
434  <div class="col-xs-12"><div id="previewEmailDiv">#= emailBody #</div></div>
435  </div>
436  </div>
437  </script>
438 
439  <?php
440  /**
441  * The HTML part of the page.
442  */
443  ?>
444  <form id="form" class="broadcastEmailsForm">
445  <div class="container hcu-all-100 hcu-template vsgPrimary">
446  <div class="row">
447  <div class="col-xs-12 notificationRow"></div>
448  </div>
449  <div class="col-xs-12">
450  <div class="row">
451  <div id="formValidateDiv" class="k-block k-error-colored formValidateDiv" style="display:none;"></div>
452  </div>
453  </div>
454  <div class="well sm-well col-xs-12">
455  <div class="row">
456  <div class="col-xs-12 col-sm-1 hcu-no-padding-nonmobile">
457  <label>Action</label>
458  </div>
459  <div class="col-xs-12 col-sm-5">
460  <div id="actionDropdownlist" class="hcu-all-100"></div>
461  </div>
462  </div>
463  </div>
464  <div class="well sm-well col-xs-12">
465  <div class="row hcuSpacer">
466  <div class="h4 col-xs-12">Filter Options</div>
467  </div>
468  <div class="row">
469  <div class="col-xs-12 col-sm-1 hcu-no-padding-nonmobile">
470  <label>Credit Union(s)</label>
471  </div>
472  <div class="col-xs-12 col-sm-5">
473  <div id="cuListMultiselect" class="hcu-all-100"></div>
474  <p class="small vsgSecondary">Empty means all credit unions.</p>
475  </div>
476  </div>
477  <div class="row">
478  <div class="col-xs-12 col-sm-1 hcu-no-padding-nonmobile">
479  <label>Server(s)</label>
480  </div>
481  <div class="col-xs-12 col-sm-5">
482  <div id="serverMultiselect" class="hcu-all-100"></div>
483  <p class="small vsgSecondary">Empty means all servers.</p>
484  </div>
485  </div>
486  </div>
487  <div class="well sm-well col-xs-12" id="emailOptionsDiv">
488  <div class="row hcuSpacer">
489  <div class="h4 col-xs-12">Email Options</div>
490  </div>
491  <div class="row hcuSpacer">
492  <div class="col-xs-12 col-sm-2 col-md-1 hcu-no-padding-nonmobile">
493  <label>From Email</label>
494  </div>
495  <div class="col-xs-12 col-sm-5">
496  <input type="text" class="hcu-all-100" name="fromEmail" id="fromEmailCombobox">
497  <p class="small vsgSecondary">This email must be verified through AWS SES. You are allowed to write an email in.</p>
498  </div>
499  </div>
500 
501  <div class="row hcuSpacer">
502  <div class="col-xs-12 col-sm-2 col-md-1 hcu-no-padding-nonmobile">
503  <label>From Name</label>
504  </div>
505  <div class="col-xs-12 col-sm-5">
506  <input type="text" class="k-input k-textbox hcu-all-100" name="fromName">
507  </div>
508  </div>
509 
510  <div class="row hcuSpacer">
511  <div class="col-xs-12 col-sm-2 col-md-1 hcu-no-padding-nonmobile">
512  <label>Subject</label>
513  </div>
514  <div class="col-xs-12 col-sm-5">
515  <input type="text" class="k-input k-textbox hcu-all-100" name="subject">
516  </div>
517  </div>
518 
519  <div class="row hcuSpacer">
520  <div class="col-xs-12 col-sm-1 hcu-no-padding-nonmobile">
521  <label>Test Email</label>
522  </div>
523  <div class="col-xs-12 col-sm-5">
524  <input type="text" class="k-input k-textbox hcu-all-100" name="testEmail">
525  <p class="small vsgSecondary">If this is not empty, then it will send an email here in the preview step.</p>
526  </div>
527  </div>
528  </div>
529  <div class="well sm-well col-xs-12" id="emailBodyDiv">
530  <div class="row hcuSpacer">
531  <div class="h4 col-xs-12">Email Body</div>
532  </div>
533  <div class="row hcuSpacer" id="emailBodyDiv" tabindex="0">
534  <div class="col-xs-12">
535  <textarea id="emailBody" name="emailBody" class="hcu-all-100"></textarea>
536  </div>
537  </div>
538  </div>
539  <div class="col-xs-12">
540  <div class="k-state-default row">
541  <a class="okayBtn k-button k-primary" href="#"><i class="fa fa-check"></i>Okay</a>
542  </div>
543  </div>
544  </div>
545  </form>
546  <form id="downloadCSVForm" action="<?php echo $self; ?>" method="post" target="_blank" style="display:none;">
547  <input type="hidden" name="operation" value="downloadCSV">
548  <input type="hidden" name="filteredCus" value="[]">
549  <input type="hidden" name="filteredServers" value="[]">
550  </form>
551 
552 <?php printMonitorPageBottom();
553 }