Revamp document templates (#4705)
[openemr.git] / portal / import_template_ui.php
blobe938ac41c2cf9a917ff262e352597d8ff7a38daa
1 <?php
3 /**
4 * import_template_ui.php
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Jerry Padgett <sjpadgett@gmail.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2016-2021 Jerry Padgett <sjpadgett@gmail.com>
11 * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 require_once("../interface/globals.php");
17 use OpenEMR\Core\Header;
18 use OpenEMR\Services\DocumentTemplates\DocumentTemplateService;
20 $templateService = new DocumentTemplateService();
22 $patient = $_REQUEST['selected_patients'] ?? null;
23 $patient = $patient ?: ($_REQUEST['upload_pid'] ?? 0);
25 $category = $_REQUEST['template_category'] ?? '';
26 $category_list = $templateService->getDefaultCategories();
28 $none_message = xlt("Nothing to show for current actions.");
30 function getAuthUsers()
32 $response = sqlStatement("SELECT `pid`, Concat_Ws(', ', `lname`, `fname`) as ptname FROM `patient_data` WHERE `allow_patient_portal` = 'YES' ORDER BY `lname`");
34 $result_data = array(
35 ['pid' => '0', 'ptname' => 'All Patients'],
36 ['pid' => '-1', 'ptname' => 'Repository'],
38 while ($row = sqlFetchArray($response)) {
39 $result_data[] = $row;
42 return $result_data;
46 <!DOCTYPE html>
47 <head>
48 <meta charset="UTF-8">
49 <title><?php echo xlt('Portal'); ?> | <?php echo xlt('Templates'); ?></title>
50 <meta name="description" content="Developed By sjpadgett@gmail.com">
51 <?php Header::setupHeader(['datetime-picker', 'select2', 'ckeditor']); ?>
53 <script>
54 let currentEdit = "";
55 let editor;
56 let templateEdit = function (id, flag = '') {
57 currentEdit = id;
58 handleTemplate(id, 'get', '', flag);
59 return false;
62 let templateSave = function () {
63 //let editor = CKEDITOR.instances.templateContent;
64 let markup = CKEDITOR.instances.templateContent.getData();
65 handleTemplate(currentEdit, 'save', markup);
68 let templateDelete = function (id) {
69 let delok = confirm(<?php echo xlj('You are about to delete a template'); ?> +
70 ": " + "\n" + <?php echo xlj('Is this Okay?'); ?>);
71 if (delok === true) {
72 handleTemplate(id, 'delete', '')
74 return false;
77 function getSendChecks() {
78 let checked = [];
79 $('input:checked[name=send]:checked').each(function () {
80 checked.push($(this).val());
81 });
82 return checked;
85 function updateCategory(id) {
86 top.restoreSession();
87 let url = 'import_template.php';
88 let category = event.currentTarget.value;
89 const data = new FormData();
90 data.append('docid', id);
91 data.append('category', category);
92 data.append('mode', 'update_category');
93 fetch(url, {
94 method: 'POST',
95 body: data,
96 }).then(rtn => rtn.text()).then((rtn) => {
97 (async (time) => {
98 await asyncAlertMsg(rtn, time, 'success', 'lg');
99 })(2000).then(rtn => {
100 //document.edit_form.submit();
102 }).catch((error) => {
103 console.error('Error:', error);
107 function sendTemplate(mode = 'send', content = '') {
108 top.restoreSession();
109 let url = 'import_template.php';
110 let ids = $('#selected_patients').select2('val');
111 let category = $('#template_category').val();
112 let checked = getSendChecks();
113 const data = new FormData();
114 data.append('docid', JSON.stringify(ids));
115 data.append('category', category);
116 data.append('checked', JSON.stringify(checked));
117 data.append('mode', mode);
118 data.append('content', content);
119 fetch(url, {
120 method: 'POST',
121 body: data,
122 }).then(rtn => rtn.text()).then((rtn) => {
123 (async (time) => {
124 await asyncAlertMsg(rtn, time, 'success', 'lg');
125 })(1000).then(rtn => {
126 document.edit_form.submit();
128 }).catch((error) => {
129 console.error('Error:', error);
133 function handleTemplate(id, mode, content = '', isDocument = '') {
134 top.restoreSession();
135 let libUrl = 'import_template.php';
136 let renderUrl = 'import_template.php?mode=editor_render_html&docid=' + id;
138 if (document.getElementById('is_modal').checked) {
139 dialog.popUp(renderUrl, null, 'edit' + id);
140 return false;
142 if (isDocument == true) {
143 dialog.popUp(renderUrl, null, ('edit' + id));
144 return false;
146 if (mode == 'get') {
147 renderUrl += '&dialog=true';
148 dlgopen(renderUrl, 'pop-editor', 'modal-lg', 850, '', '', {
149 /*buttons: [
150 {text: <?php echo xlj('Save'); ?>, close: false, style: 'success btn-sm', click: templateSave},
151 {text: <?php echo xlj('Dismiss'); ?>, style: 'danger btn-sm', close: true}
152 ],*/
153 resolvePromiseOn: 'show',
154 allowDrag: true,
155 allowResize: true,
156 sizeHeight: 'full',
157 //onClosed: 'reload'
160 $.ajax({
161 type: "POST",
162 url: libUrl,
163 data: {docid: id, mode: mode, content: content},
164 error: function (qXHR, textStatus, errorThrow) {
165 console.log("There was an error");
166 alert(<?php echo xlj("File Error") ?> +"\n" + id)
168 success: function (templateHtml, textStatus, jqXHR) {
169 if (mode === 'save') {
170 location.reload();
171 } else if (mode === 'delete') {
172 location.reload();
178 $(function () {
179 $('#fetch_files').on('click touchstart', function () {
180 $(this).val('');
182 $('#fetch_files').change(function (e) {
183 $('#upload_submit').removeClass('d-none');
186 $('.select-dropdown').select2({
187 placeholder: xl("Type to search."),
188 minimumResultsForSearch: 15,
189 theme: 'bootstrap4',
190 width: 'resolve',
191 closeOnSelect: false,
192 <?php require($GLOBALS['srcdir'] . '/js/xl/select2.js.php'); ?>
195 $('input:checkbox[name=send]').change(function () {
196 let checked = getSendChecks();
197 if (checked.length > 0) {
198 $('#send-button').removeClass('d-none');
199 $('#category_group').addClass('d-none');
200 } else {
201 $('#send-button').addClass('d-none');
202 $('#category_group').removeClass('d-none');
206 let select_focus = false;
207 /* Can't use if we want multi selects for locations. so ??? */
208 /* $('#selected_patients').change(function () {
209 if (checkCategory()) {
210 select_focus = true;
211 $('#edit_form').submit();
213 });*/
214 $('#selected_patients').on('select2:close', function (e) {
215 $('#edit_form').submit();
218 $('#upload-nav').on('hidden.bs.collapse', function () {
219 $('#upload-nav-value').val('hidden');
221 $('#upload-nav').on('show.bs.collapse', function () {
222 $('#upload-nav-value').val('show');
223 //$('#edit_form').submit();
226 $("#template_category").change(function () {
227 if (checkCategory()) {
228 $("#edit_form").submit();
232 let selText = '';
233 let selCat = $('#template_category').find(':selected').text();
234 let ids = $('#selected_patients').find(':selected').each(function () {
235 selText += $(this).text() + '; ';
237 $('#upload_scope_category').empty().append(' ' + xl('For Category') + ': ' + selCat);
238 $("#upload_scope").empty().append(xl('To Locations') + ': ' + selText);
240 function checkCategory() {
241 let cat = $("#template_category").val();
242 let patient = $("#selected_patients").val();
243 return true;
247 $(document).on('select2:open', () => {
248 document.querySelector('.select2-search__field').focus();
250 </script>
251 <style>
252 .modal.modal-wide .modal-dialog {
253 width: 55%;
256 .modal-wide .modal-body {
257 overflow-y: auto;
260 caption {
261 caption-side: top !important;
263 </style>
264 </head>
265 <body class="body-top">
266 <div class='container'>
267 <div class='col col-12'>
268 <div class='ml-0 mt-2'><span class="title"><?php echo xlt('Template Maintenance'); ?></span>
269 <span>
270 <div class='btn-group ml-1'>
271 <button type='button' class='btn btn-secondary' data-toggle='collapse' data-target='#help-panel'>
272 <?php echo xlt('Help') ?>
273 </button>
274 <button class='btn btn-success' type='button' onclick="location.href='./patient/provider'">
275 <?php echo xlt('Dashboard'); ?>
276 </button>
277 </div>
278 </span>
279 </div>
280 <hr />
281 <?php include_once('./../Documentation/help_files/template_maintenace_help.php'); ?>
282 <!-- Actions Scope to act on -->
283 <nav class='navbar navbar-dark bg-dark text-light sticky-top'>
284 <form id="edit_form" name="edit_form" class="row form-inline w-100" action="" method="get">
285 <a class='navbar-brand ml-1'><?php echo xlt('Scope'); ?></a>
286 <div class="form-group">
287 <label class='font-weight-bold mx-1' for='selected_patients'><?php echo xlt('Location'); ?></label>
288 <select class="form-control select-dropdown" id="selected_patients" name="selected_patients[]" multiple>
289 <?PHP
290 $ppt = getAuthUsers();
291 foreach ($ppt as $pt) {
292 if ((is_array($patient) && !in_array($pt['pid'], $patient)) || empty($patient)) {
293 echo '<option value=' . attr($pt['pid']) . '>' . text($pt['ptname']) . '</option>';
294 } else {
295 echo "<option value='" . attr($pt['pid']) . "' selected='selected'>" . text($pt['ptname'] . ' ') . '</option>';
299 </select>
300 <a class='btn-refresh ml-1' onclick="$('#selected_patients').val(null).trigger('change');" role="button"></a>
301 <?php
302 $select_cat_options = '<option value="">' . xlt('General') . "</option>\n";
303 foreach ($category_list as $option_category) {
304 if (stripos($option_category['option_id'], 'repository') !== false) {
305 continue;
307 if ($category === $option_category['option_id']) {
308 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "' selected>" . text($option_category['title']) . "</option>\n";
309 } else {
310 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "'>" . text($option_category['title']) . "</option>\n";
314 <div class="form-group" id="category_group">
315 <label class="font-weight-bold mx-1" for="template_category"><?php echo xlt('Category'); ?></label>
316 <select class="form-control" id="template_category" name="template_category">
317 <?php echo $select_cat_options ?>
318 </select>
319 </div>
320 </div>
321 <div class='btn-group ml-1'>
322 <button type='submit' class='btn btn-search btn-light'><?php /*echo xlt('Refresh'); */ ?></button>
323 <button type='button' id="send-button" class='btn btn-transmit btn-success d-none' onclick="return sendTemplate()">
324 <?php echo xlt('Send'); ?>
325 </button>
326 <button type='button' id="upload-nav-button" name='upload-nav-button' class='btn btn-primary' data-toggle='collapse' data-target='#upload-nav'>
327 <?php echo xlt('Files') ?>
328 </button>
329 </div>
330 <div class="ml-auto">
331 <label class="form-check"><?php echo xlt('Use Popout Editor'); ?>
332 <input type='checkbox' class='form-check-inline mx-1' id='is_modal' name='is_modal' checked='checked' />
333 </label>
334 </div>
335 <input type='hidden' id='upload-nav-value' name='upload-nav-value' value='<?php echo attr($_REQUEST['upload-nav-value']) ?? 'hidden' ?>' />
336 </form>
337 </nav>
338 <!-- Upload -->
339 <nav class="collapse my-2 <?php echo attr($_REQUEST['upload-nav-value']) ?>" id="upload-nav">
340 <div class='col col-12'>
341 <form id='form_upload' class='form-inline row' action='import_template.php' method='post' enctype='multipart/form-data'>
342 <hr />
343 <div class='col'>
344 <div id='upload_scope_category'></div>
345 <div class='mb-2' id='upload_scope'></div>
346 </div>
347 <div class='form-group col'>
348 <div class='form-group'>
349 <input type='file' class='btn btn-outline-info' id="fetch_files" name='template_files[]' multiple />
350 <button class='btn btn-outline-success d-none' type='submit' name='upload_submit' id='upload_submit'><i class='fa fa-upload' aria-hidden='true'></i></button>
351 </div>
352 </div>
353 <input type='hidden' name='upload_pid' value='<?php echo attr(json_encode($patient)); ?>' />
354 <input type='hidden' name="template_category" value='<?php echo attr($category); ?>' />
355 </form>
356 </div>
357 </nav>
358 <hr />
359 <div class='row'>
360 <div class='col col-12' data-toggle='collapse' data-target='#repository-collapse'>
361 <h5><i class='fa fa-eye mr-1' role='button' title="<?php echo xlt('Click to expand or collapse Repository templates panel.'); ?>"></i><?php echo xlt('Template Repository') ?></h5>
362 </div>
363 <!-- Repository table -->
364 <div class='col col-12 table-responsive collapse show' id="repository-collapse">
365 <?php
366 $templates = [];
367 $show_cat_flag = false;
368 if (!empty($category)) {
369 $templates = $templateService->getTemplateListByCategory($category, -1);
370 //$templates = $templateService->getTemplateListAllCategories(-1);
371 } else {
372 $templates = $templateService->getTemplateListAllCategories(-1);
374 echo "<table class='table table-sm table-striped table-bordered'>\n";
375 /* echo '<caption role="button" data-toggle="collapse" data-target="#repository-collapse" title="' .
376 xlt('Click to expand or collapse Repository templates panel.') .
377 '"><h5>' . xlt('Repository Available Templates') . '</h5></caption>';*/
378 echo "<thead>\n";
379 echo "<tr>\n" .
380 "<th>" . xlt('Send') . "</th>" .
381 '<th>' . xlt('Category') . '</th>' .
382 "<th>" . xlt("Template Actions") . "</th>" .
383 "<th>" . xlt("Size") . "</th>" .
384 "<th>" . xlt("Last Modified") . "</th>" .
385 "</tr>\n";
386 echo "</thead>\n";
387 echo "<tbody>\n";
388 foreach ($templates as $cat => $files) {
389 if (empty($cat)) {
390 $cat = xlt('Default');
392 foreach ($files as $file) {
393 $template_id = $file['id'];
394 $this_cat = $file['category'];
395 $notify_flag = false;
396 $select_cat_options = '<option value="">' . xlt('General') . "</option>\n";
397 foreach ($category_list as $option_category) {
398 if (stripos($option_category['option_id'], 'repository') !== false) {
399 continue;
401 if ($this_cat === $option_category['option_id']) {
402 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "' selected>" . text($option_category['title']) . "</option>\n";
403 } else {
404 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "'>" . text($option_category['title']) . "</option>\n";
407 echo "<tr>";
408 if ($file['mime'] == 'application/pdf') {
409 $this_cat = xlt('PDF Document');
410 $notify_flag = true;
411 echo '<td>' . '*' . '</td>';
412 echo "<td>" . $this_cat . " Id: " . attr($template_id) . "</td>";
413 } else {
414 echo "<td><input type='checkbox' class='form-check-inline' id='send' name='send' value='" . attr($template_id) . "' /></td>";
415 echo '<td><select class="form-control form-control-sm" id="category_table' . attr($template_id) .
416 '" onchange="updateCategory(' . attr_js($template_id) . ')" value="' . attr($this_cat) . '">' .
417 $select_cat_options . '</select></td>';
419 echo '<td>' .
420 '<button id="templateEdit' . attr($template_id) .
421 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ',' . attr_js($notify_flag) . ')" type="button">' . text($file['template_name']) . /*' '. attr($template_id) .*/
422 '</button>' .
423 '<button id="templateDelete' . attr($template_id) .
424 '" class="btn btn-sm btn-outline-danger float-right" onclick="templateDelete(' . attr_js($template_id) . ')" type="button">' . xlt("Delete") .
425 '</button></td>';
426 echo "<td>" . text($file['size']) . "</td>";
427 echo "<td>" . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . "</td>";
428 echo "</tr>";
430 <?php
433 if (empty($template_id)) {
434 echo '<tr><td>' . $none_message . "</td></tr>\n";
436 echo "</tbody>\n";
437 echo "</table>\n";
439 </div>
440 </div>
441 <div class='row'>
442 <div class='col col-12' data-toggle='collapse' data-target='#template-collapse'>
443 <h5><i class='fa fa-eye mr-1' role='button' title="<?php echo xlt('Click to expand or collapse All active patient templates panel.'); ?>"></i><?php echo '' . xlt('All Patient Templates') . '' ?></h5>
444 </div>
445 <div class='col col-12 table-responsive collapse show' id='template-collapse'>
446 <?php
447 $templates = [];
448 $show_cat_flag = false;
449 if (!empty($category)) {
450 $templates = $templateService->getTemplateListByCategory($category);
451 } else {
452 $templates = $templateService->getTemplateListAllCategories();
454 echo "<table class='table table-sm table-striped table-bordered'>\n";
455 /*echo '<caption role="button" data-toggle="collapse" data-target="#template-collapse"><h6>' .
456 xlt('All Patients Templates') .
457 '</h6></caption>';*/
458 echo "<thead>\n";
459 echo "<tr>\n" .
460 /*'<th>' . xlt('Send') . '</th>' .*/
461 '<th>' . xlt('Category') . '</th>' .
462 '<th>' . xlt('Template Actions') . '</th>' .
463 '<th>' . xlt('Size') . '</th>' .
464 '<th>' . xlt('Last Modified') . '</th>' .
465 "</tr>\n";
466 echo "</thead>\n";
467 echo "<tbody>\n";
468 foreach ($templates as $cat => $files) {
469 if (empty($cat)) {
470 $cat = xlt('Default');
472 foreach ($files as $file) {
473 $template_id = $file['id'];
474 echo '<tr>';
475 /*echo "<td><input type='checkbox' class='form-check-inline' id='send' name='send' value='" . attr($template_id) . "' /></td>";*/
476 echo '<td>' . text(ucwords($cat)) . '</td><td>';
477 echo '<button id="templateEdit' . attr($template_id) .
478 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ')" type="button">' . text($file['template_name']) . '</button>' .
479 /*'<button id="sendTemplate' . attr($template_id) .
480 '" class="btn btn-sm btn-outline-success" onclick="templateSend(' . attr_js($template_id) . ')" type="button">' . xlt('Send') . '</button>' .*/
481 '<button id="templateDelete' . attr($template_id) .
482 '" class="btn btn-sm btn-outline-danger" onclick="templateDelete(' . attr_js($template_id) . ')" type="button">' . xlt('Delete') . '</button>';
483 echo '<td>' . text($file['size']) . '</td>';
484 echo '<td>' . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . '</td>';
485 echo '</tr>';
487 <?php
490 if (empty($files)) {
491 echo '<tr><td>' . $none_message . "</td></tr>\n";
493 echo "</tbody>\n";
494 echo "</table>\n";
496 </div>
497 </div>
498 <div class='row'>
499 <div class='col col-12 table-responsive'>
500 <?php
501 // by categories and patient pid.
502 $templates = [];
503 $show_cat_flag = false;
505 // Category selected so get all of them for pids
506 if (!empty($category) && !empty($patient)) {
507 $templates = $templateService->getTemplateCategoriesByPids($patient, $category);
508 } elseif (empty($patient)) {// All templates for all patients
509 $templates = $templateService->getTemplateCategoriesByPatient(0, $category);
510 } elseif (empty($category) && !empty($patient)) {
511 $templates = $templateService->getTemplateCategoriesByPids($patient);
513 echo "<table class='table table-sm table-striped table-bordered'>\n";
514 echo '<caption><h5>' . xlt("Patient Assigned Templates") . '</h5></caption>';
515 echo "<thead>\n";
516 echo "<tr>\n" .
517 '<th>' . xlt('Patient') . '</th>' .
518 '<th>' . xlt('Category') . '</th>' .
519 '<th>' . xlt('Template Actions') .
520 '</th><th>' . xlt('Status') .
521 '</th><th>' . xlt('Size') .
522 '</th><th>' . xlt('Last Modified') . '</th>' .
523 "</tr>\n";
524 echo "</thead>\n";
525 echo "<tbody>\n";
526 foreach ($templates as $cat => $files) {
527 if (empty($cat)) {
528 $cat = xlt('Default');
530 foreach ($files as $file) {
531 $template_id = $file['id'];
532 echo '<tr><td>' . text($file['location']) . '</td>';
533 echo '<td>' . text(ucwords($cat)) . '</td>';
534 echo '<td>' .
535 '<button type="button" id="patientEdit' . attr($template_id) .
536 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ')">' .
537 text($file['template_name']) . "</button>\n" .
538 '<button type="button" id="patientDelete' . attr($template_id) .
539 '" class="btn btn-sm btn-outline-danger" onclick="templateDelete(' . attr_js($template_id) . ')">' . xlt('Delete') . "</button></td>\n";
540 echo '<td>' . text($file['status']) . '</td>';
541 echo '<td>' . text($file['size']) . '</td>';
542 echo '<td>' . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . '</td>';
543 echo "</tr>\n";
546 if (empty($files)) {
547 echo '<tr><td>' . $none_message . "</td></tr>\n";
549 echo "</tbody>\n";
550 echo "</table>\n";
552 </div>
553 </div>
554 </div>
555 </div>
556 </body>
557 </html>