chore: ci mariadb stuff - added 11.1 and removed 10.9 (#6834)
[openemr.git] / portal / import_template_ui.php
blob32aec6c66c9dd9b44054e3b4f39279fc4b8f560a
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-2022 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\Common\Acl\AclMain;
18 use OpenEMR\Common\Csrf\CsrfUtils;
19 use OpenEMR\Core\Header;
20 use OpenEMR\Events\Messaging\SendNotificationEvent;
21 use OpenEMR\Services\DocumentTemplates\DocumentTemplateService;
22 use OpenEMR\Services\PatientPortalService;
23 use OpenEMR\Services\QuestionnaireService;
25 if (!(isset($GLOBALS['portal_onsite_two_enable'])) || !($GLOBALS['portal_onsite_two_enable'])) {
26 echo xlt('Patient Portal is turned off');
27 exit;
30 // Service
31 $eventDispatcher = $GLOBALS['kernel']->getEventDispatcher();
32 $portalService = new PatientPortalService();
33 // auto allow if a portal user else must be an admin
34 $authUploadTemplates = $portalService::authPortalUser('admin', 'forms');
36 $templateService = new DocumentTemplateService();
37 $from_demo_pid = $_GET['from_demo_pid'] ?? '0';
38 $patient = $_REQUEST['selected_patients'] ?? null;
39 $patient = $patient ?: ($_REQUEST['upload_pid'] ?? 0);
40 // our lists
41 $category = $_REQUEST['template_category'] ?? '';
42 $category_list = $templateService->fetchDefaultCategories();
43 $profile_list = $templateService->fetchDefaultProfiles();
44 $group_list = $templateService->fetchDefaultGroups();
45 // for empty lists
46 $none_message = xlt("Nothing to show for current actions.");
47 // init status array
48 $audit_status_blank = array(
49 'audit_id' => null,
50 'pid' => null,
51 'create_date' => null,
52 'doc_type' => null,
53 'id' => null,
54 'facility' => null,
55 'provider' => null,
56 'encounter' => null,
57 'patient_signed_status' => null,
58 'patient_signed_time' => null,
59 'authorize_signed_time' => null,
60 'accept_signed_status' => null,
61 'authorizing_signator' => null,
62 'review_date' => null,
63 'denial_reason' => null,
64 'authorized_signature' => null,
65 'patient_signature' => null,
66 'full_document' => null,
67 'file_name' => null,
68 'file_path' => null,
69 'template_data' => null,
70 'date' => null,
71 'patient_id' => null,
72 'activity' => null,
73 'require_audit' => null,
74 'pending_action' => null,
75 'action_taken' => null,
76 'status' => null,
77 'narrative' => null,
78 'table_action' => null,
79 'table_args' => null,
80 'action_user' => null,
81 'action_taken_time' => null,
82 'checksum' => null,
85 <!DOCTYPE html>
86 <head>
87 <meta charset="UTF-8">
88 <title><?php echo xlt('Portal'); ?> | <?php echo xlt('Templates'); ?></title>
89 <meta name="description" content="Developed By sjpadgett@gmail.com">
90 <?php Header::setupHeader(['datetime-picker', 'select2', 'ckeditor']); ?>
91 <script>
92 const profiles = <?php echo js_escape($profile_list); ?>;
93 let currentEdit = "";
94 let editor;
95 let callBackCmd = null;
97 <?php
98 $eventDispatcher->dispatch(new SendNotificationEvent($pid ?? 0, ['is_onetime' => 1]), SendNotificationEvent::JAVASCRIPT_READY_NOTIFICATION_POST);
100 // a callback from dlgclose(fn) in render form
101 function doImportSubmit() {
102 // todo add message to user
103 top.restoreSession();
104 document.getElementById('form_upload').submit();
105 return false;
108 function resolveImport(mode = 'render_import') {
109 if (mode === 'render_import') {
110 const file = document.getElementById("fetch_files").files.item(0);
111 if (file.name.toLowerCase().indexOf('.json') === -1 && file.type !== 'application/json') {
112 return false;
115 top.restoreSession();
116 let callBack = '';
117 let url = './questionnaire_render.php?mode=' + encodeURIComponent(mode);
118 dlgopen(url, 'pop-questionnaire', 'modal-lg', 850, '', '', {
119 allowDrag: true,
120 allowResize: true,
121 sizeHeight: 'full',
122 resolvePromiseOn: 'close',
123 }).then(() => {
124 // set callBackCmd from iframe then eval here
125 // currently using callback from dlgclose();
126 return false;
130 let questionnaireViewCurrent = function (encounter, flag = '') {
131 currentEdit = encounter;
132 alertMsg(xl("New coming feature. View patient progress with the completion of the form with the ability to send a secure notification to patient."), 6000, 'success')
133 return false;
136 let templateEdit = function (id, flag = '') {
137 currentEdit = id;
138 handleTemplate(id, 'get', '', flag);
139 return false;
142 let templateSave = function () {
143 let markup = CKEDITOR.instances.templateContent.getData();
144 handleTemplate(currentEdit, 'save', markup);
147 let templateDelete = function (id, template = '') {
148 let delok = confirm(<?php echo xlj('You are about to delete a template'); ?> +
149 ": " + "\n" + <?php echo xlj('Is this Okay?'); ?>);
150 if (delok === true) {
151 handleTemplate(id, 'delete', '', false, template, <?php echo js_escape(CsrfUtils::collectCsrfToken('import-template-delete')); ?>)
153 return false;
156 function getSendChecks() {
157 let checked = [];
158 $('input:checked[name=send]:checked').each(function () {
159 let isProfile = this.dataset.send_profile;
160 if (isProfile == 'yes') {
161 checked.push([$(this).val(), true]);
162 } else {
163 checked.push($(this).val());
166 console.log(checked)
167 return checked;
170 function getSendCheckProfiles() {
171 let checked = [];
172 $('input:checked[name=send_profile]:checked').each(
173 function () {
174 let isProfile = this.dataset.send_profile;
175 if (isProfile == 'yes') {
176 checked.push($(this).val());
179 console.log(checked)
180 return checked;
183 function updateCategory(id) {
184 top.restoreSession();
185 let url = 'import_template.php';
186 let category = event.currentTarget.value;
187 const data = new FormData();
188 data.append('docid', id);
189 data.append('category', category);
190 data.append('mode', 'update_category');
191 fetch(url, {
192 method: 'POST',
193 body: data,
194 }).then(rtn => rtn.text()).then((rtn) => {
195 (async (time) => {
196 await asyncAlertMsg(rtn, time, 'success', 'lg');
197 })(2000).then(rtn => {
198 //document.edit_form.submit();
200 }).catch((error) => {
201 console.error('Error:', error);
205 function sendTemplate(mode = 'send', content = '') {
206 top.restoreSession();
207 let url = 'import_template.php';
208 let ids = $('#selected_patients').select2('val');
209 let category = $('#template_category').val();
210 let checked = getSendChecks();
211 const data = new FormData();
212 data.append('docid', JSON.stringify(ids));
213 data.append('category', category);
214 data.append('checked', JSON.stringify(checked));
215 data.append('mode', mode);
216 data.append('content', content);
217 fetch(url, {
218 method: 'POST',
219 body: data,
220 }).then(rtn => rtn.text()).then((rtn) => {
221 (async (time) => {
222 await asyncAlertMsg(rtn, time, 'success', 'lg');
223 })(1500).then(rtn => {
224 document.edit_form.submit();
226 }).catch((error) => {
227 console.error('Error:', error);
231 function sendProfiles() {
232 top.restoreSession();
233 let mode = 'send_profiles'
234 let url = 'import_template.php';
235 let checked = getSendCheckProfiles();
236 const data = new FormData();
237 data.append('checked', JSON.stringify(checked));
238 data.append('mode', mode);
239 fetch(url, {
240 method: 'POST',
241 body: data,
242 }).then(rtn => rtn.text()).then((rtn) => {
243 (async (time) => {
244 await asyncAlertMsg(rtn, time, 'success', 'lg');
245 })(1500).then(rtn => {
246 document.edit_form.submit();
248 }).catch((error) => {
249 console.error('Error:', error);
253 function handleTemplate(id, mode, content = '', isDocument = '', template = '', csrf = '') {
254 top.restoreSession();
255 let libUrl = 'import_template.php';
256 let renderUrl = 'import_template.php?mode=editor_render_html&docid=' + id;
258 if (document.getElementById('is_modal').checked && mode === 'get') {
259 dialog.popUp(renderUrl, null, 'edit' + id);
260 return false;
262 if (isDocument == true) {
263 dialog.popUp(renderUrl, null, ('edit' + id));
264 return false;
266 if (mode == 'get') {
267 renderUrl += '&dialog=true';
268 dlgopen(renderUrl, 'pop-editor', 'modal-lg', 850, '', '', {
269 resolvePromiseOn: 'show',
270 allowDrag: true,
271 allowResize: true,
272 sizeHeight: 'full'
275 $.ajax({
276 type: "POST",
277 url: libUrl,
278 data: {docid: id, mode: mode, content: content, template: template, csrf_token_form: csrf},
279 error: function (qXHR, textStatus, errorThrow) {
280 console.log("There was an error");
281 alert(<?php echo xlj("File Error") ?> +"\n" + id)
283 success: function (templateHtml, textStatus, jqXHR) {
284 document.edit_form.submit();
289 function popProfileDialog() {
290 top.restoreSession();
291 let url = './import_template.php?mode=render_profile';
292 dlgopen(url, 'pop-profile', 'modal-lg', 850, '', '', {
293 allowDrag: true,
294 allowResize: true,
295 sizeHeight: 'full',
299 function popPatientDialog() {
300 top.restoreSession();
301 let url = './lib/patient_groups.php';
302 dlgopen(url, 'pop-profile', 'modal-lg', 850, '', '', {
303 allowDrag: true,
304 allowResize: true,
305 sizeHeight: 'full'
309 function popGroupsDialog() {
310 let url = './lib/patient_groups.php?render_group_assignments=true';
311 dlgopen(url, 'pop-groups', 'modal-lg', 850, '', '', {
312 allowDrag: true,
313 allowResize: true,
314 sizeHeight: 'full',
318 function createBlankTemplate() {
319 top.restoreSession();
320 let name = prompt(xl('Enter a valid name for this new template.') + "\n" + xl("For example: Pain Assessment"));
321 if (name === null) {
322 return false;
324 if (name === "") {
325 alert(xl('A name must be entered. Try again.'));
326 createBlankTemplate();
328 $("#upload_name").val(name);
329 return true;
332 $(function () {
333 let ourSelect = $('.select-questionnaire');
334 ourSelect.select2({
335 multiple: false,
336 placeholder: xl('Type to search Questionnaire Repository.'),
337 theme: 'bootstrap4',
338 dropdownAutoWidth: true,
339 width: 'resolve',
340 closeOnSelect: true,
341 <?php require($GLOBALS['srcdir'] . '/js/xl/select2.js.php'); ?>
343 $(document).on('select2:open', () => {
344 document.querySelector('.select2-search__field').focus();
346 ourSelect.on("change", function (e) {
347 let data = $('#select_item').select2('data');
348 if (data) {
349 document.getElementById('upload_name').value = data[0].text;
351 $('#repository-submit').removeClass('d-none');
354 $("#repository-submit").on("click", function (e) {
355 top.restoreSession();
356 let data = $('#select_item').select2('data');
357 if (data) {
358 document.getElementById('upload_name').value = data[0].text;
359 } else {
360 alert(xl("Missing Template name."))
361 return false;
363 return true;
366 $('.select-dropdown').removeClass('d-none');
367 $('.select-dropdown').select2({
368 multiple: true,
369 placeholder: xl('Type to search.'),
370 theme: 'bootstrap4',
371 dropdownAutoWidth: true,
372 width: 'resolve',
373 closeOnSelect: false,
374 <?php require($GLOBALS['srcdir'] . '/js/xl/select2.js.php'); ?>
377 $('#fetch_files').on('click touchstart', function () {
378 $(this).val('');
381 $('#fetch_files').change(function (e) {
382 const file = document.getElementById("fetch_files").files.item(0);
383 const fileName = file.name;
384 let howManyFiles = document.getElementById("fetch_files").files.length;
385 $('#upload_submit').removeClass('d-none');
386 if (howManyFiles === 1 && document.getElementById("upload_scope").checked) {
387 if (fileName.toLowerCase().indexOf('.json') > 0 || file.type === 'application/json') {
388 $('#upload_submit_questionnaire').removeClass('d-none');
389 resolveImport();
391 } else {
392 if (fileName.toLowerCase().indexOf('.json') > 0 || file.type === 'application/json') {
393 document.getElementById("upload_submit_questionnaire").type = 'submit';
394 document.getElementById("upload_submit_questionnaire").removeAttribute("onclick");
395 document.getElementById("upload_submit_questionnaire").innerText = xl("Questionnaires Repository All")
396 $('#upload_submit_questionnaire').removeClass('d-none');
399 return false;
402 $('input:checkbox[name=send]').change(function () {
403 let checked = getSendChecks();
404 if (checked.length > 0) {
405 $('#send-button').removeClass('d-none');
406 $('#category_group').addClass('d-none');
407 $('#send-profile-hide').addClass('d-none');
408 } else {
409 $('#send-button').addClass('d-none');
410 $('#category_group').removeClass('d-none');
414 $('input:checkbox[name=send_profile]').change(function () {
415 $('#send-profile-hide').removeClass('d-none');
416 $('#category_group').addClass('d-none');
417 $('input:checkbox[name=send]').addClass('d-none');
420 $('#selected_patients').on('select2:close', function () {
421 let checked = getSendChecks();
422 if (checked.length > 0) {
423 return false;
425 $('#edit_form').submit();
428 $('#upload-nav').on('hidden.bs.collapse', function () {
429 $('#upload-nav-value').val('collapse');
431 $('#upload-nav').on('show.bs.collapse', function () {
432 $('#upload-nav-value').val('show');
433 //$('#edit_form').submit();
436 $("#template_category").change(function () {
437 $('#edit_form').submit();
440 $('#template-collapse').on('show.bs.collapse', function () {
441 $('#edit_form #all_state').val('show');
443 $('#template-collapse').on('hidden.bs.collapse', function () {
444 $('#edit_form #all_state').val('collapse');
447 $('#assigned_collapse').on('show.bs.collapse', function () {
448 $('#repository-collapse').collapse('hide');
449 $('#template-collapse').collapse('hide');
450 $('#edit_form #assigned_state').val('show');
452 $('#assigned_collapse').on('hidden.bs.collapse', function () {
453 $('#edit_form #assigned_state').val('collapse');
456 $('#repository-collapse').on('show.bs.collapse', function () {
457 $('#edit_form #repository_send_state').val('show');
459 $('#repository-collapse').on('hidden.bs.collapse', function () {
460 $('#edit_form #repository_send_state').val('collapse');
463 let selText = '';
464 let selCat = $('#template_category').find(':selected').text();
465 let ids = $('#selected_patients').find(':selected').each(function () {
466 selText += $(this).text() + '; ';
468 $('#upload_scope_category').empty().append(' ' + xl('For Category') + ': ' + selCat);
470 $(document).on('select2:open', () => {
471 document.querySelector('.select2-search__field').focus();
475 </script>
476 <style>
477 caption {
478 caption-side: top !important;
480 </style>
481 </head>
482 <body class="body-top">
483 <div class='container-xl'>
484 <nav class='nav navbar bg-light text-dark sticky-top'>
485 <span class='title'><?php echo xlt('Template Maintenance'); ?></span>
486 <div class="ml-auto">
487 <label class="form-check"><?php echo xlt('Full Editor'); ?>
488 <input type='checkbox' class='form-check-inline mx-1' id='is_modal' name='is_modal' checked='checked' />
489 </label>
490 </div>
491 <div class='btn-group ml-1'>
492 <button type='button' class='btn btn-secondary' data-toggle='collapse' data-target='#help-panel'>
493 <?php echo xlt('Help') ?>
494 </button>
495 <button class='btn btn-success' type='button' onclick="location.href='./patient/provider'">
496 <?php echo xlt('Dashboard'); ?>
497 </button>
498 </div>
499 </nav>
500 <div class='col col-12'>
501 <hr />
502 <?php include_once('./../Documentation/help_files/template_maintenance_help.php'); ?>
503 <!-- Actions Scope to act on -->
504 <nav class='navbar navbar-dark bg-dark text-light sticky-top'>
505 <form id="edit_form" name="edit_form" class="row form-inline w-100" action="" method="get">
506 <a class='navbar-brand ml-1'><?php echo xlt('Scope'); ?></a>
507 <div class="form-group">
508 <label class='font-weight-bold mx-1' for='selected_patients'><?php echo xlt('Location'); ?></label>
509 <?PHP
510 $ppt = $templateService->fetchPortalAuthUsers();
511 $auth = '';
512 foreach ($ppt as $pt) {
513 if (!empty($from_demo_pid)) {
514 $patient = [$from_demo_pid];
516 if ((is_array($patient) && !in_array($pt['pid'], $patient)) || empty($patient)) {
517 $auth .= '<option value=' . attr($pt['pid']) . '>' . text($pt['ptname']) . '</option>';
518 } else {
519 $auth .= "<option value='" . attr($pt['pid']) . "' selected='selected'>" . text($pt['ptname'] . ' ') . '</option>';
523 <select class="form-control select-dropdown d-none" id="selected_patients" name="selected_patients[]" multiple="multiple">
524 <?php echo $auth ?>
525 </select>
526 <a class='btn btn-refresh bg-dark text-primary mx-1' onclick="$('#selected_patients').val(null).trigger('change');" role="button"></a>
527 </div>
528 <?php
529 $select_cat_options = '<option value="">' . xlt('General') . "</option>\n";
530 foreach ($category_list as $option_category) {
531 if (stripos($option_category['option_id'], 'repository') !== false) {
532 continue;
534 if ($category === $option_category['option_id']) {
535 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "' selected>" . text($option_category['title']) . "</option>\n";
536 } else {
537 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "'>" . text($option_category['title']) . "</option>\n";
541 <div class="input-group" id="category_group">
542 <label class="font-weight-bold mx-1" for="template_category"><?php echo xlt('Category'); ?></label>
543 <select class="form-control" id="template_category" name="template_category">
544 <?php echo $select_cat_options ?>
545 </select>
546 </div>
547 <div class="form-group">
548 <div class='btn-group ml-1'>
549 <button type='submit' class='btn btn-search btn-primary'><i class="btn-refresh"></i></button>
550 <button type='button' id="send-button" class='btn btn-transmit btn-success d-none' onclick="return sendTemplate()">
551 <?php echo xlt('Send'); ?>
552 </button>
553 <button type='button' class='btn btn-primary' onclick='return popProfileDialog()'><?php echo xlt('Profiles') ?></button>
554 <button type='button' class='btn btn-primary' onclick='return popPatientDialog()'><?php echo xlt('Groups') ?></button>
555 <button type='button' class='btn btn-primary' onclick='return popGroupsDialog()'><?php echo xlt('Assign') ?></button>
556 </div>
557 </div>
558 <input type='hidden' id='upload-nav-value' name='upload-nav-value' value='<?php echo attr($_REQUEST['upload-nav-value'] ?? 'collapse') ?>' />
559 <input type='hidden' id='persist_checks' name='persist_checks' value='' />
560 <input type='hidden' id='all_state' name='all_state' value='<?php echo attr($_REQUEST['all_state'] ?? 'collapse') ?>' />
561 <input type='hidden' id='assigned_state' name='assigned_state' value='<?php echo attr($_REQUEST['assigned_state'] ?? 'collapse') ?>' />
562 <input type='hidden' id='repository_send_state' name='repository_send_state' value='<?php echo attr($_REQUEST['repository_send_state'] ?? 'collapse') ?>' />
563 </form>
564 </nav>
565 <!-- Upload -->
566 <nav class="collapse my-2 <?php echo attr($_REQUEST['upload-nav-value'] ?? '') ?>" id="upload-nav">
567 <div class='col col-12'>
568 <?php if ($authUploadTemplates) { ?>
569 <form id='form_upload' class='form-inline row' action='import_template.php' method='post' enctype='multipart/form-data'>
570 <input type="hidden" name="csrf_token_form" id="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken('import-template-upload')); ?>" />
571 <hr />
572 <div class='col'>
573 <div id='upload_scope_category'></div>
574 <div class="input-group">
575 <label class="form-check"><?php echo xlt('If questionnaire import, use Questionnaire tool'); ?>
576 <input type="checkbox" class='form-check-inline ml-1' id='upload_scope' checked>
577 </div>
578 </div>
579 <div class='form-group col'>
580 <input type='file' class='btn btn-outline-info mr-1 mt-1' id="fetch_files" name='template_files[]' multiple />
581 <div class="mt-1">
582 <button class='btn btn-outline-success d-none' type='submit' name='upload_submit' id='upload_submit' title="<?php echo xla("Import a template file or if a Questionnaire then auto create a questionnaire template."); ?>">
583 <i class='fa fa-upload mr-1' aria-hidden='true'></i><?php echo xlt("Templates"); ?></button>
584 <button class='btn btn-outline-success d-none' type='button' name='upload_submit_questionnaire' id='upload_submit_questionnaire' title="<?php echo xla("Import to the questionnaire repository for later use in encounters or FHIR API"); ?>" onclick="return resolveImport();">
585 <i class='fa fa-upload mr-1' aria-hidden='true'></i><?php echo xlt("Questionnaires Repository"); ?></button>
586 <button type='button' id='render-nav-button' name='render-nav-button' class='btn btn-save btn-outline-primary' onclick="return resolveImport('render_import_manual');" title="<?php echo xla('Used to cut and paste Questionnaire or LHC Form json. Will then convert and import to questionnaire repository.') ?>"><?php echo xlt('Manual Questionnaire') ?></button>
587 <button type='submit' id='blank-nav-button' name='blank-nav-button' class='btn btn-save btn-outline-primary' onclick="return createBlankTemplate();" title="<?php echo xla('Use this to create a new empty template for use with built in editor.') ?>"><?php echo xlt('New Empty Template') ?></button>
588 </div>
589 </div>
590 <div class="mt-2">
591 <div class="text-center m-0 p-0"><small class="my-1 font-weight-bolder font-italic"><?php echo xlt("Shows all existing Questionnaires available from repository. Select to automatically create template."); ?></small></div>
592 <div class="input-group input-group-append">
593 <select class="select-questionnaire" type="text" id="select_item" name="select_item" autocomplete="off" role="combobox" aria-expanded="false" title="<?php echo xla('Items that are already an existing template will be overwritten if selected.') ?>">
594 <option value=""></option>
595 <?php
596 $qService = new QuestionnaireService();
597 $q_list = $qService->getQuestionnaireList(false);
598 $repository_item = $_POST['select_item'] ?? null;
599 foreach ($q_list as $item) {
600 $id = attr($item['id']);
601 if ($id == $repository_item) {
602 echo "<option selected value='$id'>" . text($item['name']) . "</option>";
603 continue;
605 echo "<option value='$id'>" . text($item['name']) . "</option>";
608 </select>
609 <button type='submit' id='repository-submit' name='repository-submit' class='btn btn-save btn-success d-none' value="true"><?php echo xlt('Create') ?></button>
610 </div>
611 </div>
612 <input type='hidden' name='upload_pid' value='<?php echo attr(json_encode([-1])); ?>' />
613 <input type='hidden' name="template_category" value='<?php echo attr($category); ?>' />
614 <input type='hidden' name='upload_name' id='upload_name' value='<?php echo attr(json_encode([-1])); ?>' />
615 <input type="hidden" id="q_mode" name="q_mode" value="" />
616 <input type="hidden" id="lform" name="lform" value="" />
617 <input type="hidden" id="questionnaire" name="questionnaire" value="" />
618 </form>
619 <?php } else { ?>
620 <div class="alert alert-danger"><?php echo xlt("Not Authorized to Upload Templates") ?></div>
621 <?php } ?>
622 </div>
623 </nav>
624 <hr />
625 <!-- Repository -->
626 <div class='row'>
627 <div class='col col-12'>
628 <div class="h5"><i class='fa fa-eye mr-1' data-toggle='collapse' data-target='#repository-collapse' role='button' title="<?php echo xla('Click to expand or collapse Repository templates panel.'); ?>"></i><?php echo xlt('Template Repository') ?>
629 <span>
630 <button type='button' id='upload-nav-button' name='upload-nav-button' class='btn btn-sm btn-primary' data-toggle='collapse' data-target='#upload-nav'>
631 <i class='fa fa-upload mr-1' aria-hidden='true'></i><?php echo xlt('Upload') ?></button>
632 </span>
633 </div>
634 </div>
635 <!-- Repository table -->
636 <div class='col col-12 table-responsive <?php echo attr($_REQUEST['repository_send_state'] ?? 'collapse') ?>' id="repository-collapse">
637 <?php
638 $templates = [];
639 $show_cat_flag = false;
640 if (!empty($category)) {
641 $templates = $templateService->getTemplateListByCategory($category, -1);
642 } else {
643 $templates = $templateService->getTemplateListAllCategories(-1);
645 echo "<table class='table table-sm table-striped table-bordered'>\n";
646 echo "<thead>\n";
647 echo "<tr>\n" .
648 "<th style='width:5%'>" . xlt('Send') . "</th>" .
649 '<th>' . xlt('Category') . '</th>' .
650 "<th>" . xlt("Template Actions") . "</th>" .
651 "<th>" . xlt("Size") . "</th>" .
652 "<th>" . xlt("Last Modified") . "</th>" .
653 "</tr>\n";
654 echo "</thead>\n";
655 echo "<tbody>\n";
656 foreach ($templates as $cat => $files) {
657 if (empty($cat)) {
658 $cat = xlt('General');
660 foreach ($files as $file) {
661 $template_id = $file['id'];
662 $this_cat = $file['category'];
663 $notify_flag = false;
664 $select_cat_options = '<option value="">' . xlt('General') . "</option>\n";
665 foreach ($category_list as $option_category) {
666 if (stripos($option_category['option_id'], 'repository') !== false) {
667 continue;
669 if ($this_cat === $option_category['option_id']) {
670 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "' selected>" . text($option_category['title']) . "</option>\n";
671 } else {
672 $select_cat_options .= "<option value='" . attr($option_category['option_id']) . "'>" . text($option_category['title']) . "</option>\n";
675 echo "<tr>";
676 if ($file['mime'] == 'application/pdf') {
677 $this_cat = xlt('PDF Document');
678 $notify_flag = true;
679 echo '<td>' . '*' . '</td>';
680 echo "<td>" . $this_cat . " Id: " . attr($template_id) . "</td>";
681 } else {
682 echo "<td><input type='checkbox' class='form-check-inline' name='send' value='" . attr($template_id) . "' /></td>";
683 echo '<td><select class="form-control form-control-sm" id="category_table' . attr($template_id) .
684 '" onchange="updateCategory(' . attr_js($template_id) . ')" value="' . attr($this_cat) . '">' .
685 $select_cat_options . '</select></td>';
687 echo '<td>' .
688 '<button id="templateEdit' . attr($template_id) .
689 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ',' . attr_js($notify_flag) . ')" type="button">' . text($file['template_name']) .
690 '</button>';
691 if ($authUploadTemplates) {
692 echo '<button id="templateDelete' . attr($template_id) .
693 '" class="btn btn-sm btn-outline-danger float-right" onclick="templateDelete(' . attr_js($template_id) . ',' . attr_js($file['template_name']) . ')" type="button">' . xlt("Delete") .
694 '</button>';
696 echo "</td>";
697 echo "<td>" . text($file['size']) . "</td>";
698 echo "<td>" . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . "</td>";
699 echo "</tr>";
701 <?php
704 if (empty($template_id)) {
705 echo '<tr><td></td><td>' . $none_message . "</td></tr>\n";
707 echo "</tbody>\n";
708 echo "</table>\n";
710 <div>
711 <?php
712 echo "<table class='table table-sm table-striped table-bordered'>\n";
713 echo '<caption>' . xlt('Profiles in Portal') . "</caption>";
714 echo "<thead>\n";
715 echo "<tr>\n" .
716 "<th>" . xlt('Active') . "<button type='button' id='send-profile-hide' class='btn btn-sm ml-1 py-0 btn-transmit btn-success d-none' onclick='return sendProfiles()'>" . xlt('Update') . "</button></th>" .
717 '<th style="min-width: 25%">' . xlt('Profile') . '</th>' .
718 '<th>' . xlt('Assigned Templates') . '</th>' .
719 '<th>' . xlt('Assigned Groups') . '</th>' .
720 "</tr>\n";
721 echo "</thead>\n";
722 foreach ($profile_list as $profile => $profiles) {
723 $template_list = '';
724 $group_list_text = '';
725 $group_items_list = $templateService->getPatientGroupsByProfile($profile);
726 $profile_items_list = $templateService->getTemplateListByProfile($profile);
727 if (empty($profile_items_list)) {
728 continue;
730 $total = 0;
731 foreach ($profile_items_list as $key => $files) {
732 $total += count($files ?? []);
733 foreach ($files as $file) {
734 if (is_array($file)) {
735 $template_list .= $file['template_name'] . ', ';
739 $template_list = substr($template_list, 0, -2);
740 $profile_esc = attr($profile);
741 foreach ($group_items_list as $key => $groups) {
742 foreach ($groups as $group) {
743 if (is_array($group)) {
744 $group_list_text .= $group_list[$group['member_of']]['title'] . ', ';
748 $group_list_text = substr($group_list_text, 0, -2);
749 $send = 'send';
750 if (!empty($group_list_text)) {
751 $send = 'send_profile';
753 echo '<tr>';
754 $is_checked = '';
755 if ((int)$templateService->fetchProfileStatus($profiles['option_id']) === 1) {
756 $is_checked = 'checked';
758 echo "<td><input type='checkbox' class='form-check-inline' $is_checked name='" . attr($send) . "' data-send_profile='yes' value='" . $profile_esc . "' /></td>";
759 echo '<td>' . text($profiles['title']) . '</td>';
760 echo '<td><em>' . text($template_list) . '</em></td>';
761 echo '<td><em>' . text($group_list_text) . '</em></td>';
762 echo '</tr>';
764 if (empty($profile_list)) {
765 echo '<tr><td></td><td>' . $none_message . "</td></tr>\n";
767 echo "</tbody>\n";
768 echo "</table>\n";
770 </div>
771 </div>
772 </div>
773 <!-- All Patients -->
774 <hr />
775 <div class='row'>
776 <div class='col col-12' data-toggle='collapse' data-target='#template-collapse'>
777 <h5><i class='fa fa-eye mr-1' role='button' title="<?php echo xla('Click to expand or collapse All active patient templates panel.'); ?>"></i><?php echo '' . xlt('Default Patient Templates') . '' ?></h5>
778 </div>
779 <div class='col col-12 table-responsive <?php echo attr(($_REQUEST['all_state'] ?? '') ?: 'collapse') ?>' id='template-collapse'>
780 <?php
781 $templates = [];
782 $show_cat_flag = false;
783 if (!empty($category)) {
784 $templates = $templateService->getTemplateListByCategory($category);
785 } else {
786 $templates = $templateService->getTemplateListAllCategories();
788 echo "<table class='table table-sm table-striped table-bordered'>\n";
789 echo "<thead>\n";
790 echo "<tr>\n" .
791 '<th>' . xlt('Category') . '</th>' .
792 '<th>' . xlt('Template Actions') . '</th>' .
793 '<th>' . xlt('Size') . '</th>' .
794 '<th>' . xlt('Created') . '</th>' .
795 '<th>' . xlt('Last Modified') . '</th>' .
796 "</tr>\n";
797 echo "</thead>\n";
798 echo "<tbody>\n";
799 foreach ($templates as $cat => $files) {
800 if (empty($cat)) {
801 $cat = xlt('General');
803 foreach ($files as $file) {
804 $template_id = $file['id'];
805 echo '<tr>';
806 /*echo "<td><input type='checkbox' class='form-check-inline' id='send' name='send' value='" . attr($template_id) . "' /></td>";*/
807 echo '<td>' . text(ucwords($cat)) . '</td><td>';
808 echo '<button id="templateEdit' . attr($template_id) .
809 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ')" type="button">' . text($file['template_name']) . '</button>';
810 if ($authUploadTemplates) {
811 echo '<button id="templateDelete' . attr($template_id) .
812 '" class="btn btn-sm btn-outline-danger" onclick="templateDelete(' . attr_js($template_id) . ')" type="button">' . xlt('Delete') . '</button>';
814 echo '<td>' . text($file['size']) . '</td>';
815 echo '<td>' . text(date('m/d/Y H:i:s', strtotime($file['modified_date']))) . '</td>';
816 echo '</tr>';
818 <?php
821 if (empty($files)) {
822 echo '<tr><td>' . $none_message . "</td></tr>\n";
824 echo "</tbody>\n";
825 echo "</table>\n";
827 </div>
828 </div>
829 <hr />
830 <div class='row'>
831 <div class='col col-12'>
832 <div class='h5'>
833 <i class='fa fa-eye mr-1' data-toggle='collapse' data-target='#assigned_collapse' role='button' title="<?php echo xla('Click to expand or collapse Assigned Patients panel.'); ?>"></i><?php echo xlt('Patient Assigned Templates') ?>
834 </div>
835 </div>
836 <!-- Assigned table -->
837 <div class='col col-12 table-responsive <?php echo attr(($_REQUEST['assigned_state'] ?? '') ?: 'collapse') ?>' id="assigned_collapse">
838 <?php
839 // by categories and patient pid.
840 $templates = [];
841 $show_cat_flag = false;
842 if (is_array($patient) && $patient[0] === '0') {// All templates for all patients
843 $patient_templates = $templateService->getPortalAssignedTemplates(0, $category, false);
844 } else {// Category selected so get all of them for pid's
845 $patient_templates = $templateService->getTemplateCategoriesByPids($patient, $category);
847 echo "<table class='table table-sm table-bordered'>\n";
848 echo "<tbody>";
849 $idcnt = 0;
850 foreach ($patient_templates as $name => $templates) {
851 $count = 0;
852 $fetched_groups = $fetch_pid = null;
853 foreach ($templates as $c => $t) {
854 if (is_array($t)) {
855 $fetch_pid = $t[0]['pid'];
856 if (empty($fetched_groups)) {
857 $fetched_groups = str_replace('|', ', ', $t[0]['patient_groups'] ?? '');
859 $count += count($t);
863 echo "<tr><td class='h6 font-weight-bolder bg-light text-dark' data-toggle='collapse' data-target='" .
864 attr('#id' . ++$idcnt) . "' role='button'>" . text($name) .
865 " (" . text($count . ' ' . xl('Templates')) . ") in " . text($fetched_groups) . "</td></tr>";
866 echo "<td class='collapse' id='" . attr('id' . $idcnt) . "'><table class='table table-sm table-striped table-bordered'>\n";
867 //echo '<caption><h5>' . text($name) . '</h5></caption>';
868 echo "<thead>\n";
869 echo "<tr>\n" .
870 '<th>' . xlt('Category') . '</th>' .
871 '<th>' . xlt('Profile') . '</th>' .
872 '<th>' . xlt('Template Actions') . '</th>' .
873 '<th>' . xlt('Status') . '</th>' .
874 '<th>' . xlt('Last Action') . '</th>' .
875 '<th>' . xlt('Next Due') . '</th>' .
876 "</tr>\n";
877 echo "</thead>\n";
878 echo "<tbody>\n";
879 foreach ($templates as $cat => $files) {
880 if (empty($cat)) {
881 $cat = xlt('General');
883 foreach ($files as $file) {
884 $template_id = $file['id'];
886 $audit_status = $audit_status_blank;
887 $audit_status_fetch = $templateService->fetchPatientDocumentStatus($file['pid'], $file['id']);
888 if (is_array($audit_status_fetch)) {
889 $audit_status = array_merge($audit_status_blank, $file, $audit_status_fetch);
890 } else {
891 $audit_status = array_merge($audit_status_blank, $file);
893 $last_date = $audit_status['create_date'] ?? '' ?: $file['modified_date'] ?? '';
894 $next_due = $templateService->showTemplateFromEvent($file, true);
895 $action_status = '';
896 if ($next_due > 1) {
897 if ($audit_status['denial_reason'] === 'In Review') {
898 $action_status = xl('Scheduled but Needs Review');
899 } else {
900 $action_status = xl('Scheduled');
902 $next_due = date('m/d/Y', $next_due);
903 } elseif ($next_due === 1 || ($next_due === true && ($file['recurring'] ?? 0))) {
904 if ($audit_status['denial_reason'] === 'In Review') {
905 $action_status = xl('In audit. Needs Review');
906 } else {
907 $action_status = xl('Recurring');
909 $next_due = xl('Active');
910 } elseif ($next_due === 0) {
911 $action_status = xl('Completed');
912 $next_due = xl('Inactive');
913 } elseif ($next_due === true && empty($file['recurring'] ?? 0)) {
914 $next_due = xl('Active');
916 echo '<tr><td>' . text(ucwords($cat)) . '</td>';
917 echo '<td>' . text($profile_list[$file['profile']]['title'] ?? '') . '</td>';
918 echo '<td>' .
919 '<button type="button" id="patientEdit' . attr($template_id) .
920 '" class="btn btn-sm btn-outline-primary" onclick="templateEdit(' . attr_js($template_id) . ')" title="' . xla("Click to edit in editor.") . '">' .
921 text($file['template_name']) . "</button>\n";
922 if ($authUploadTemplates && $cat == 'questionnaire' && !empty($audit_status['encounter'])) {
923 echo '<button type="button" id="patientView' . attr($template_id) .
924 '" class="btn btn-sm btn-outline-success" onclick="questionnaireViewCurrent(' . attr_js($audit_status['encounter']) . ')">' .
925 xlt("View") . "</button>\n";
927 if ($authUploadTemplates && empty($file['member_of']) && !empty($file['status'])) {
928 echo '<button type="button" id="patientDelete' . attr($template_id) .
929 '" class="btn btn-sm btn-outline-danger" onclick="templateDelete(' . attr_js($template_id) . ')">' . xlt('Delete') . "</button>\n";
931 // onetime button for template.
932 $file['onetime_period'] = "P2D";
933 $file['is_onetime'] = 1;
934 $file['audit_id'] = 0;
935 if ($audit_status['denial_reason'] == 'In Review' || $audit_status['denial_reason'] == 'Editing') {
936 $file['audit_id'] = $audit_status['audit_id'] ?? 0;
938 $e_pid = $fetch_pid ?: $file['pid'];
939 if (!empty($e_pid)) {
940 $eventDispatcher->dispatch(new SendNotificationEvent($e_pid, $file), SendNotificationEvent::ACTIONS_RENDER_NOTIFICATION_POST);
943 echo '</td><td>' . text($action_status) . '</td>';
944 echo '<td>' . text(date('m/d/Y H:i:s', strtotime($last_date))) . '</td>';
945 echo '<td>' . text($next_due) . '</td>';
946 echo "</tr>\n";
949 echo "</tbody>\n";
950 echo "</table></td>\n";
952 if (empty($templates)) {
953 echo '<tr><td>' . xlt('Multi Select Patients or All Patients using toolbar Location') . "</td></tr>\n";
955 echo "</tbody>\n";
956 echo "</table>\n";
958 </div>
959 </div>
960 <hr />
961 </div>
962 </div>
963 </body>
964 </html>