4 * import_template_ui.php
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();
27 $profile_list = $templateService->getDefaultProfiles();
29 $none_message = xlt("Nothing to show for current actions.");
31 function getAuthUsers()
33 $response = sqlStatement("SELECT `pid`, Concat_Ws(', ', `lname`, `fname`) as ptname FROM `patient_data` WHERE `allow_patient_portal` = 'YES' ORDER BY `lname`");
36 ['pid' => '0', 'ptname' => 'All Patients'],
37 ['pid' => '-1', 'ptname' => 'Repository'],
39 while ($row = sqlFetchArray($response)) {
40 $result_data[] = $row;
49 <meta charset
="UTF-8">
50 <title
><?php
echo xlt('Portal'); ?
> |
<?php
echo xlt('Templates'); ?
></title
>
51 <meta name
="description" content
="Developed By sjpadgett@gmail.com">
52 <?php Header
::setupHeader(['datetime-picker', 'select2', 'ckeditor']); ?
>
54 const profiles
= <?php
echo js_escape($profile_list); ?
>;
57 let templateEdit
= function (id
, flag
= '') {
59 handleTemplate(id
, 'get', '', flag
);
63 let templateSave
= function () {
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?'); ?
>);
72 handleTemplate(id
, 'delete', '')
77 function getSendChecks() {
79 $
('input:checked[name=send]:checked').each(function () {
80 let isProfile
= this
.dataset
.send_profile
;
81 if (isProfile
== 'yes') {
82 checked
.push([$
(this
).val(),true]);
84 checked
.push($
(this
).val());
91 function updateCategory(id
) {
93 let url
= 'import_template.php';
94 let category
= event
.currentTarget
.value
;
95 const data
= new FormData();
96 data
.append('docid', id
);
97 data
.append('category', category
);
98 data
.append('mode', 'update_category');
102 }).then(rtn
=> rtn
.text()).then((rtn
) => {
104 await
asyncAlertMsg(rtn
, time
, 'success', 'lg');
105 })(2000).then(rtn
=> {
106 //document.edit_form.submit();
108 }).catch((error
) => {
109 console
.error('Error:', error
);
113 function sendTemplate(mode
= 'send', content
= '') {
114 top
.restoreSession();
115 let url
= 'import_template.php';
116 let ids
= $
('#selected_patients').select2('val');
117 let category
= $
('#template_category').val();
118 let checked
= getSendChecks();
119 const data
= new FormData();
120 data
.append('docid', JSON
.stringify(ids
));
121 data
.append('category', category
);
122 data
.append('checked', JSON
.stringify(checked
));
123 data
.append('mode', mode
);
124 data
.append('content', content
);
128 }).then(rtn
=> rtn
.text()).then((rtn
) => {
130 await
asyncAlertMsg(rtn
, time
, 'success', 'lg');
131 })(1000).then(rtn
=> {
132 document
.edit_form
.submit();
134 }).catch((error
) => {
135 console
.error('Error:', error
);
139 function handleTemplate(id
, mode
, content
= '', isDocument
= '') {
140 top
.restoreSession();
141 let libUrl
= 'import_template.php';
142 let renderUrl
= 'import_template.php?mode=editor_render_html&docid=' + id
;
144 if (document
.getElementById('is_modal').checked
&& mode
=== 'get') {
145 dialog
.popUp(renderUrl
, null, 'edit' + id
);
148 if (isDocument
== true) {
149 dialog
.popUp(renderUrl
, null, ('edit' + id
));
153 renderUrl +
= '&dialog=true';
154 dlgopen(renderUrl
, 'pop-editor', 'modal-lg', 850, '', '', {
156 {text: <?php echo xlj('Save'); ?>, close: false, style: 'success btn-sm', click: templateSave},
157 {text: <?php echo xlj('Dismiss'); ?>, style: 'danger btn-sm', close: true}
159 resolvePromiseOn
: 'show',
169 data
: {docid
: id
, mode
: mode
, content
: content
},
170 error
: function (qXHR
, textStatus
, errorThrow
) {
171 console
.log("There was an error");
172 alert(<?php
echo xlj("File Error") ?
> +
"\n" + id
)
174 success
: function (templateHtml
, textStatus
, jqXHR
) {
175 if (mode
=== 'save') {
177 } else if (mode
=== 'delete') {
185 $
('#fetch_files').on('click touchstart', function () {
188 $
('#fetch_files').change(function (e
) {
189 $
('#upload_submit').removeClass('d-none');
192 $
('.select-dropdown').select2({
193 placeholder
: xl("Type to search."),
194 minimumResultsForSearch
: 15,
197 closeOnSelect
: false,
198 <?php
require($GLOBALS['srcdir'] . '/js/xl/select2.js.php'); ?
>
201 $
('input:checkbox[name=send]').change(function () {
202 let checked
= getSendChecks();
203 if (checked
.length
> 0) {
204 $
('#send-button').removeClass('d-none');
205 $
('#category_group').addClass('d-none');
207 $
('#send-button').addClass('d-none');
208 $
('#category_group').removeClass('d-none');
212 $
('#selected_patients').on('select2:close', function (e
) {
213 let checked
= getSendChecks();
214 if (checked
.length
> 0) {
217 $
('#edit_form').submit();
220 $
('#upload-nav').on('hidden.bs.collapse', function () {
221 $
('#upload-nav-value').val('collapse');
223 $
('#upload-nav').on('show.bs.collapse', function () {
224 $
('#upload-nav-value').val('show');
225 //$('#edit_form').submit();
228 $
("#template_category").change(function () {
229 if (checkCategory()) {
230 $
("#edit_form").submit();
234 $
('#template-collapse').on('show.bs.collapse', function (e
) {
235 $
('#repository-collapse').collapse('hide');
236 $
('#profile_send_collapse').collapse('hide');
237 $
('#edit_form #all_state').val('show');
239 $
('#template-collapse').on('hidden.bs.collapse', function () {
240 $
('#edit_form #all_state').val('collapse');
243 $
('#profile_send_collapse').on('show.bs.collapse', function (e
) {
244 $
('#edit_form #profile_send_state').val('show');
246 $
('#profile_send_collapse').on('hidden.bs.collapse', function () {
247 $
('#edit_form #profile_send_state').val('collapse');
250 $
('#repository-collapse').on('show.bs.collapse', function (e
) {
251 $
('#edit_form #repository_send_state').val('show');
253 $
('#repository-collapse').on('hidden.bs.collapse', function () {
254 $
('#edit_form #repository_send_state').val('collapse');
258 let selCat
= $
('#template_category').find(':selected').text();
259 let ids
= $
('#selected_patients').find(':selected').each(function () {
260 selText +
= $
(this
).text() +
'; ';
262 $
('#upload_scope_category').empty().append(' ' +
xl('For Category') +
': ' + selCat
);
263 $
("#upload_scope").empty().append(xl('To Locations') +
': ' + selText
);
265 function checkCategory() {
266 let cat
= $
("#template_category").val();
267 let patient
= $
("#selected_patients").val();
271 $
(document
).on('select2:open', () => {
272 document
.querySelector('.select2-search__field').focus();
276 function popProfileDialog() {
277 top
.restoreSession();
278 let url
= './import_template.php?mode=renderProfile';
279 dlgopen(url
, 'pop-profile', 'modal-lg', 850, '', '', {
292 caption
-side
: top
!important
;
296 <body
class="body-top">
297 <div
class='container'>
298 <nav
class='nav navbar bg-light text-dark sticky-top'>
299 <span
class='title'><?php
echo xlt('Template Maintenance'); ?
></span
>
301 <div
class='btn-group ml-1'>
302 <button type
='button' class='btn btn-secondary' data
-toggle
='collapse' data
-target
='#help-panel'>
303 <?php
echo xlt('Help') ?
>
305 <button
class='btn btn-success' type
='button' onclick
="location.href='./patient/provider'">
306 <?php
echo xlt('Dashboard'); ?
>
311 <div
class='col col-12'>
313 <?php
include_once('./../Documentation/help_files/template_maintenance_help.php'); ?
>
314 <!-- Actions Scope to act on
-->
315 <nav
class='navbar navbar-dark bg-dark text-light sticky-top'>
316 <form id
="edit_form" name
="edit_form" class="row form-inline w-100" action
="" method
="get">
317 <a
class='navbar-brand ml-1'><?php
echo xlt('Scope'); ?
></a
>
318 <div
class="form-group">
319 <label
class='font-weight-bold mx-1' for='selected_patients'><?php
echo xlt('Location'); ?
></label
>
320 <select
class="form-control select-dropdown" id
="selected_patients" name
="selected_patients[]" multiple
>
322 $ppt = getAuthUsers();
323 foreach ($ppt as $pt) {
324 if ((is_array($patient) && !in_array($pt['pid'], $patient)) ||
empty($patient)) {
325 echo '<option value=' . attr($pt['pid']) . '>' . text($pt['ptname']) . '</option>';
327 echo "<option value='" . attr($pt['pid']) . "' selected='selected'>" . text($pt['ptname'] . ' ') . '</option>';
332 <a
class='btn-refresh ml-1' onclick
="$('#selected_patients').val(null).trigger('change');" role
="button"></a
>
334 $select_cat_options = '<option value="">' . xlt('General') . "</option>\n";
335 foreach ($category_list as $option_category) {
336 if (stripos($option_category['option_id'], 'repository') !== false) {
339 if ($category === $option_category['option_id']) {
340 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "' selected>" . text($option_category['title']) . "</option>\n";
342 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "'>" . text($option_category['title']) . "</option>\n";
346 <div
class="form-group" id
="category_group">
347 <label
class="font-weight-bold mx-1" for="template_category"><?php
echo xlt('Category'); ?
></label
>
348 <select
class="form-control" id
="template_category" name
="template_category">
349 <?php
echo $select_cat_options ?
>
353 <div
class='btn-group ml-1'>
354 <button type
='submit' class='btn btn-search btn-light'><?php
/*echo xlt('Refresh'); */ ?
></button
>
355 <button type
='button' id
="send-button" class='btn btn-transmit btn-success d-none' onclick
="return sendTemplate()">
356 <?php
echo xlt('Send'); ?
>
358 <button type
='button' id
="upload-nav-button" name
='upload-nav-button' class='btn btn-primary' data
-toggle
='collapse' data
-target
='#upload-nav'>
359 <?php
echo xlt('Files') ?
>
362 <div
class="ml-auto">
363 <label
class="form-check"><?php
echo xlt('Use Popout Editor'); ?
>
364 <input type
='checkbox' class='form-check-inline mx-1' id
='is_modal' name
='is_modal' checked
='checked' />
367 <input type
='hidden' id
='upload-nav-value' name
='upload-nav-value' value
='<?php echo attr($_REQUEST['upload
-nav
-value
'] ?? 'collapse
') ?>' />
368 <input type
='hidden' id
='persist_checks' name
='persist_checks' value
='' />
369 <input type
='hidden' id
='all_state' name
='all_state' value
='<?php echo attr($_REQUEST['all_state
'] ?? 'collapse
') ?>' />
370 <input type
='hidden' id
='profile_send_state' name
='profile_send_state' value
='<?php echo attr($_REQUEST['profile_send_state
'] ?? 'collapse
') ?>' />
371 <input type
='hidden' id
='repository_send_state' name
='repository_send_state' value
='<?php echo attr($_REQUEST['repository_send_state
'] ?? 'collapse
') ?>' />
375 <nav
class="collapse my-2 <?php echo attr($_REQUEST['upload-nav-value']) ?>" id
="upload-nav">
376 <div
class='col col-12'>
377 <form id
='form_upload' class='form-inline row' action
='import_template.php' method
='post' enctype
='multipart/form-data'>
380 <div id
='upload_scope_category'></div
>
381 <div
class='mb-2' id
='upload_scope'></div
>
383 <div
class='form-group col'>
384 <div
class='form-group'>
385 <input type
='file' class='btn btn-outline-info' id
="fetch_files" name
='template_files[]' multiple
/>
386 <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
>
389 <input type
='hidden' name
='upload_pid' value
='<?php echo attr(json_encode($patient)); ?>' />
390 <input type
='hidden' name
="template_category" value
='<?php echo attr($category); ?>' />
397 <div
class='col col-12'>
398 <h5
><i
class='fa fa-eye mr-1' data
-toggle
='collapse' data
-target
='#repository-collapse' role
='button' title
="<?php echo xlt('Click to expand or collapse Repository templates panel.'); ?>"></i
><?php
echo xlt('Template Repository') ?
></h5
>
400 <!-- Repository table
-->
401 <div
class='col col-12 table-responsive <?php echo attr($_REQUEST['repository_send_state
'] ?? 'collapse
') ?>' id
="repository-collapse">
404 $show_cat_flag = false;
405 if (!empty($category)) {
406 $templates = $templateService->getTemplateListByCategory($category, -1);
408 $templates = $templateService->getTemplateListAllCategories(-1);
410 echo "<table class='table table-sm table-striped table-bordered'>\n";
413 "<th style='width:5%'>" . xlt('Send') . "</th>" .
414 '<th>' . xlt('Category') . '</th>' .
415 "<th>" . xlt("Template Actions") . "</th>" .
416 "<th>" . xlt("Size") . "</th>" .
417 "<th>" . xlt("Last Modified") . "</th>" .
421 foreach ($templates as $cat => $files) {
423 $cat = xlt('Default');
425 foreach ($files as $file) {
426 $template_id = $file['id'];
427 $this_cat = $file['category'];
428 $notify_flag = false;
429 $select_cat_options = '<option value="">' . xlt('General') . "</option>\n";
430 foreach ($category_list as $option_category) {
431 if (stripos($option_category['option_id'], 'repository') !== false) {
434 if ($this_cat === $option_category['option_id']) {
435 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "' selected>" . text($option_category['title']) . "</option>\n";
437 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "'>" . text($option_category['title']) . "</option>\n";
441 if ($file['mime'] == 'application/pdf') {
442 $this_cat = xlt('PDF Document');
444 echo '<td>' . '*' . '</td>';
445 echo "<td>" . $this_cat . " Id: " . attr($template_id) . "</td>";
447 echo "<td><input type='checkbox' class='form-check-inline' name='send' value='" . attr($template_id) . "' /></td>";
448 echo '<td><select class="form-control form-control-sm" id="category_table' . attr($template_id) .
449 '" onchange="updateCategory(' . attr_js($template_id) . ')" value="' . attr($this_cat) . '">' .
450 $select_cat_options . '</select></td>';
453 '<button id="templateEdit' . attr($template_id) .
454 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ',' . attr_js($notify_flag) . ')" type="button">' . text($file['template_name']) .
456 '<button id="templateDelete' . attr($template_id) .
457 '" class="btn btn-sm btn-outline-danger float-right" onclick="templateDelete(' . attr_js($template_id) . ')" type="button">' . xlt("Delete") .
459 echo "<td>" . text($file['size']) . "</td>";
460 echo "<td>" . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . "</td>";
466 if (empty($template_id)) {
467 echo '<tr><td></td><td>' . $none_message . "</td></tr>\n";
475 <!-- Send Profiles
-->
477 <div
class='col col-12'>
479 <i
class='fa fa-eye mr-1' data
-toggle
='collapse' data
-target
='#profile_send_collapse' role
='button' title
="<?php echo xla('Click to expand or collapse Send Profile panel.'); ?>"></i
><?php
echo xlt('Send Profiles') ?
>
480 <span
class="mx-auto"><button
class="btn btn-sm btn-primary mb-1" onclick
="return popProfileDialog()"><?php
echo xlt('Manage Profiles') ?
></button
></span
>
483 <!-- Send Profiles table
-->
484 <div
class='col col-12 table-responsive <?php echo attr($_REQUEST['profile_send_state
'] ?: 'collapse
') ?>' id
="profile_send_collapse">
486 echo "<table class='table table-sm table-striped table-bordered'>\n";
489 "<th style='width: 5%'>" . xlt('Send') . '</th>' .
490 '<th style="min-width: 25%">' . xlt('Profile') . '</th>' .
491 '<th style="max-width: 65%">' . xlt('Assigned Templates') . '</th>' .
492 '<th>' . xlt('Total') . '</th>' .
495 foreach ($profile_list as $profile => $profiles) {
497 $profile_items_list = $templateService->getProfileListByProfile($profile);
498 if (empty($profile_items_list)) {
502 foreach ($profile_items_list as $key => $files) {
503 $total +
= count($files ??
[]);
504 foreach ($files as $file) {
505 $template_list .= $file['template_name'] . '; ';
508 $profile_esc = attr($profile);
510 echo "<td><input type='checkbox' class='form-check-inline' name='send' data-send_profile='yes' value='" . $profile_esc . "' /></td>";
511 echo '<td>' . text($profiles['title']) . '</td>';
512 echo '<td>' . text($template_list) . '</td>';
513 echo '<td>' . text($total) . '</td>';
516 if (empty($profile_list)) {
517 echo '<tr><td></td><td>' . $none_message . "</td></tr>\n";
526 <div
class='col col-12' data
-toggle
='collapse' data
-target
='#template-collapse'>
527 <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
>
529 <div
class='col col-12 table-responsive <?php echo attr($_REQUEST['all_state
'] ?: 'collapse
') ?>' id
='template-collapse'>
532 $show_cat_flag = false;
533 if (!empty($category)) {
534 $templates = $templateService->getTemplateListByCategory($category);
536 $templates = $templateService->getTemplateListAllCategories();
538 echo "<table class='table table-sm table-striped table-bordered'>\n";
539 /*echo '<caption role="button" data-toggle="collapse" data-target="#template-collapse"><h6>' .
540 xlt('All Patients Templates') .
544 /*'<th>' . xlt('Send') . '</th>' .*/
545 '<th>' . xlt('Category') . '</th>' .
546 '<th>' . xlt('Template Actions') . '</th>' .
547 '<th>' . xlt('Size') . '</th>' .
548 '<th>' . xlt('Last Modified') . '</th>' .
552 foreach ($templates as $cat => $files) {
554 $cat = xlt('Default');
556 foreach ($files as $file) {
557 $template_id = $file['id'];
559 /*echo "<td><input type='checkbox' class='form-check-inline' id='send' name='send' value='" . attr($template_id) . "' /></td>";*/
560 echo '<td>' . text(ucwords($cat)) . '</td><td>';
561 echo '<button id="templateEdit' . attr($template_id) .
562 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ')" type="button">' . text($file['template_name']) . '</button>' .
563 '<button id="templateDelete' . attr($template_id) .
564 '" class="btn btn-sm btn-outline-danger" onclick="templateDelete(' . attr_js($template_id) . ')" type="button">' . xlt('Delete') . '</button>';
565 echo '<td>' . text($file['size']) . '</td>';
566 echo '<td>' . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . '</td>';
573 echo '<tr><td>' . $none_message . "</td></tr>\n";
582 <div
class='col col-12 table-responsive'>
584 // by categories and patient pid.
586 $show_cat_flag = false;
588 // Category selected so get all of them for pid's
589 if (!empty($category) && !empty($patient)) {
590 $templates = $templateService->getTemplateCategoriesByPids($patient, $category);
591 } elseif (empty($patient)) {// All templates for all patients
592 $templates = $templateService->getTemplateCategoriesByPatient(0, $category);
593 } elseif (empty($category) && !empty($patient)) {
594 $templates = $templateService->getTemplateCategoriesByPids($patient);
596 echo "<table class='table table-sm table-striped table-bordered'>\n";
597 echo '<caption><h5>' . xlt("Patient Assigned Templates") . '</h5></caption>';
600 '<th>' . xlt('Patient') . '</th>' .
601 '<th>' . xlt('Category') . '</th>' .
602 '<th>' . xlt('Template Actions') .
603 '</th><th>' . xlt('Status') .
604 '</th><th>' . xlt('Size') .
605 '</th><th>' . xlt('Last Modified') . '</th>' .
609 foreach ($templates as $cat => $files) {
611 $cat = xlt('Default');
613 foreach ($files as $file) {
614 $template_id = $file['id'];
615 echo '<tr><td>' . text($file['location']) . '</td>';
616 echo '<td>' . text(ucwords($cat)) . '</td>';
618 '<button type="button" id="patientEdit' . attr($template_id) .
619 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ')">' .
620 text($file['template_name']) . "</button>\n" .
621 '<button type="button" id="patientDelete' . attr($template_id) .
622 '" class="btn btn-sm btn-outline-danger" onclick="templateDelete(' . attr_js($template_id) . ')">' . xlt('Delete') . "</button></td>\n";
623 echo '<td>' . text($file['status']) . '</td>';
624 echo '<td>' . text($file['size']) . '</td>';
625 echo '<td>' . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . '</td>';
630 echo '<tr><td>' . $none_message . "</td></tr>\n";