fix and chore: pinned maennchen/zipstream-php version to work with arm7 and updated...
[openemr.git] / portal / import_template.php
blobf959d506a6d65266284c29fb12d23dc4a2a9bea3
1 <?php
3 /**
4 * import_template.php
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Jerry Padgett <sjpadgett@gmail.com>
9 * @copyright Copyright (c) 2016-2023 Jerry Padgett <sjpadgett@gmail.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 require_once("../interface/globals.php");
15 use OpenEMR\Common\Acl\AclMain;
16 use OpenEMR\Common\Csrf\CsrfUtils;
17 use OpenEMR\Core\Header;
18 use OpenEMR\Services\DocumentTemplates\DocumentTemplateService;
19 use OpenEMR\Services\QuestionnaireService;
21 if (!(isset($GLOBALS['portal_onsite_two_enable'])) || !($GLOBALS['portal_onsite_two_enable'])) {
22 echo xlt('Patient Portal is turned off');
23 exit;
26 $authUploadTemplates = AclMain::aclCheckCore('admin', 'forms');
28 $templateService = new DocumentTemplateService();
30 $patient = json_decode($_POST['upload_pid'] ?? '');
32 $template_content = null;
34 if (($_POST['mode'] ?? null) === 'save_profiles') {
35 $profiles = json_decode($_POST['profiles'], true);
36 $rtn = $templateService->saveAllProfileTemplates($profiles);
37 if ($rtn) {
38 echo xlt("Profiles successfully saved.");
39 } else {
40 echo xlt('Error! Profiles save failed. Check your Profile lists.');
42 exit;
45 if (($_REQUEST['mode'] ?? null) === 'render_profile') {
46 echo renderProfileHtml();
47 exit;
50 if (($_REQUEST['mode'] ?? null) === 'getPdf') {
51 if ($_REQUEST['docid']) {
52 $template = $templateService->fetchTemplate($_REQUEST['docid']);
53 echo "data:application/pdf;base64," . base64_encode($template['template_content']);
54 exit();
56 die(xlt('Invalid File'));
59 if (($_POST['mode'] ?? null) === 'get') {
60 if ($_REQUEST['docid']) {
61 $template = $templateService->fetchTemplate($_POST['docid']);
62 echo $template['template_content'];
63 exit();
65 die(xlt('Invalid File'));
68 if (($_POST['mode'] ?? null) === 'send_profiles') {
69 if (!empty($_POST['checked'])) {
70 $profiles = json_decode($_POST['checked']) ?: [];
71 $last_id = $templateService->setProfileActiveStatus($profiles);
72 if ($last_id) {
73 echo xlt('Profile Templates Successfully set to Active in portal.');
74 } else {
75 echo xlt('Error. Problem setting one or more profiles.');
77 exit;
79 die(xlt('Invalid Request'));
82 if (($_POST['mode'] ?? null) === 'send') {
83 if (!empty($_POST['docid'])) {
84 $pids_array = json_decode($_POST['docid']) ?: ['0'];
85 // profiles are in an array with flag to indicate a group of template id's
86 $ids = json_decode($_POST['checked']) ?: [];
87 $master_ids = [];
88 foreach ($ids as $id) {
89 if (is_array($id)) {
90 if ($id[1] !== true) {
91 continue;
93 $profile = $id[0];
94 // get all template ids for this profile
95 $rtn_ids = sqlStatement('SELECT `template_id` as id FROM `document_template_profiles` WHERE `profile` = ? AND `template_id` > "0"', array($profile));
96 while ($rtn_id = sqlFetchArray($rtn_ids)) {
97 $master_ids[$rtn_id['id']] = $profile;
99 continue;
101 $master_ids[$id] = '';
103 $last_id = $templateService->sendTemplate($pids_array, $master_ids, $_POST['category']);
104 if ($last_id) {
105 echo xlt('Templates Successfully sent to Locations.');
106 } else {
107 echo xlt('Error. Problem sending one or more templates.');
109 exit;
111 die(xlt('Invalid Request'));
114 if (($_POST['mode'] ?? null) === 'save') {
115 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"], 'import-template-save')) {
116 CsrfUtils::csrfNotVerified();
118 if (!$authUploadTemplates) {
119 die(xlt('Not authorized to edit template'));
121 if ($_POST['docid']) {
122 if (stripos($_POST['content'], "<?php") === false) {
123 $template = $templateService->updateTemplateContent($_POST['docid'], $_POST['content']);
124 if ($_POST['service'] === 'window') {
125 echo "<script>if (typeof parent.dlgopen === 'undefined') window.close(); else parent.dlgclose();</script>";
127 } else {
128 die(xlt('Invalid Content'));
130 } else {
131 die(xlt('Invalid File'));
133 } elseif (($_POST['mode'] ?? null) === 'delete') {
134 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"], 'import-template-delete')) {
135 CsrfUtils::csrfNotVerified();
137 if (!$authUploadTemplates) {
138 die(xlt('Not authorized to delete template'));
140 if ($_POST['docid']) {
141 $template = $templateService->deleteTemplate($_POST['docid'], ($_POST['template'] ?? null));
142 exit($template);
144 die(xlt('Invalid File'));
145 } elseif (($_POST['mode'] ?? null) === 'update_category') {
146 if ($_POST['docid']) {
147 $template = $templateService->updateTemplateCategory($_POST['docid'], $_POST['category']);
148 echo xlt('Template Category successfully changed to new Category') . ' ' . text($_POST['category']);
149 exit;
151 die(xlt('Invalid Request Parameters'));
154 if (isset($_POST['blank-nav-button'])) {
155 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"], 'import-template-upload')) {
156 CsrfUtils::csrfNotVerified();
158 if (!$authUploadTemplates) {
159 xlt("Not Authorized to Upload Templates");
160 exit;
162 $is_blank = isset($_POST['blank-nav-button']);
163 $upload_name = $_POST['upload_name'] ?? '';
164 $category = $_POST['template_category'] ?? '';
165 $patient = '-1';
166 if (!empty($upload_name)) {
167 $name = preg_replace("/[^A-Z0-9.]/i", " ", $upload_name);
168 try {
169 $content = "{ParseAsHTML}";
170 $success = $templateService->insertTemplate($patient, $category, $upload_name, $content, 'application/text');
171 if (!$success) {
172 header('refresh:3;url= import_template_ui.php');
173 echo "<h4 style='color:red;'>" . xlt("New template save failed. Try again.") . "</h4>";
174 exit;
176 } catch (Exception $e) {
177 header('refresh:3;url= import_template_ui.php');
178 echo '<h3>' . xlt('Error') . "</h3><h4 style='color:red;'>" .
179 text($e->getMessage()) . '</h4>';
180 exit;
183 header("location: " . $_SERVER['HTTP_REFERER']);
184 die();
187 if (isset($_REQUEST['q_mode']) && !empty($_REQUEST['q_mode'])) {
188 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"], 'import-template-upload')) {
189 CsrfUtils::csrfNotVerified();
191 if (!$authUploadTemplates) {
192 xlt("Not Authorized to Upload Templates");
193 exit;
195 $id = 0;
196 $q = $_POST['questionnaire'] ?? '';
197 $l = $_POST['lform'] ?? '';
198 if (!empty($q)) {
199 $service = new QuestionnaireService();
200 try {
201 $id = $service->saveQuestionnaireResource($q, null, null, null, $l);
202 } catch (Exception $e) {
203 header('refresh:3;url= import_template_ui.php');
204 echo '<h3>' . xlt('Error') . "</h3><h4 style='color:red;'>" .
205 text($e->getMessage()) . '</h4>';
206 exit;
208 if (empty($id)) {
209 header('refresh:3;url= import_template_ui.php');
210 echo '<h3>' . xlt('Error') . "</h3><h4 style='color:red;'>" .
211 xlt("Import failed to save.") . '</h4>';
212 exit;
215 header("location: " . $_SERVER['HTTP_REFERER']);
216 die();
219 // templates file import
220 if ((count($_FILES['template_files']['name'] ?? []) > 0) && !empty($_FILES['template_files']['name'][0] ?? '')) {
221 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"], 'import-template-upload')) {
222 CsrfUtils::csrfNotVerified();
224 if (!$authUploadTemplates) {
225 xlt("Not Authorized to Upload Templates");
226 exit;
228 // so it is a template file import. create record(s).
229 $import_files = $_FILES["template_files"];
230 $total = count($_FILES['template_files']['name']);
231 for ($i = 0; $i < $total; $i++) {
232 if ($_FILES['template_files']['error'][$i] !== UPLOAD_ERR_OK) {
233 header('refresh:3;url= import_template_ui.php');
234 echo '<h3>' . xlt('Error') . "</h3><h4 style='color:red;'>" .
235 xlt('An error occurred: Missing file to upload. Returning to form.') . '</h4>';
236 exit;
238 // parse out what we need
239 $name = preg_replace("/[^A-Z0-9.]/i", " ", $_FILES['template_files']['name'][$i]);
240 if (preg_match("/(.*)\.(php|php7|php8|doc|docx)$/i", $name) !== 0) {
241 die(xlt('Invalid file type.'));
243 $parts = pathinfo($name);
244 $name = ucwords(strtolower($parts["filename"]));
245 if (empty($patient)) {
246 $patient = ['-1'];
248 // get em and dispose
249 try {
250 $success = $templateService->uploadTemplate($name, $_POST['template_category'], $_FILES['template_files']['tmp_name'][$i], $patient, isset($_POST['upload_submit_questionnaire']));
251 if (!$success) {
252 echo "<p>" . xlt("Unable to save files. Use back button!") . "</p>";
253 exit;
255 } catch (Exception $e) {
256 header('refresh:3;url= import_template_ui.php');
257 echo '<h3>' . xlt('Error') . "</h3><h4 style='color:red;'>" .
258 text($e->getMessage()) . '</h4>';
259 exit;
262 header("location: " . $_SERVER['HTTP_REFERER']);
263 die();
266 if (isset($_POST['repository-submit']) && !empty($_POST['upload_name'] ?? '')) {
267 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"], 'import-template-upload')) {
268 CsrfUtils::csrfNotVerified();
270 if (!$authUploadTemplates) {
271 xlt("Not Authorized to Upload Templates");
272 exit;
274 $selected_q = (int)($_POST['select_item'] ?? 0);
275 $upload_name = $_POST['upload_name'] ?? '';
276 $category = $_POST['template_category'] ?? '';
277 if (empty($category)) {
278 $category = 'questionnaire';
280 if (empty($patient) || $patient === [-1]) {
281 $patient = '-1';
283 if (!empty($upload_name)) {
284 // will use same name as questionnaire from repository
285 try {
286 $content = "{ParseAsHTML}{Questionnaire:$selected_q}" . "\n";
287 $mimetype = 'application/text';
288 $success = $templateService->insertTemplate($patient, $category, $upload_name, $content, 'application/text');
289 if (!$success) {
290 header('refresh:3;url= import_template_ui.php');
291 echo "<h4 style='color:red;'>" . xlt("New template save failed. Try again.") . "</h4>";
292 exit;
294 } catch (Exception $e) {
295 header('refresh:3;url= import_template_ui.php');
296 echo '<h3>' . xlt('Error') . "</h3><h4 style='color:red;'>" .
297 text($e->getMessage()) . '</h4>';
298 exit;
301 header("location: " . $_SERVER['HTTP_REFERER']);
302 die();
305 if (($_REQUEST['mode'] ?? '') === 'editor_render_html') {
306 if ($_REQUEST['docid']) {
307 $content = $templateService->fetchTemplate($_REQUEST['docid']);
308 $template_content = $content['template_content'];
309 if ($content['mime'] === 'application/pdf') {
310 $content = "<iframe width='100%' height='100%' src='data:application/pdf;base64, " .
311 attr(base64_encode($template_content)) . "'></iframe>";
312 echo $content;
313 exit;
315 renderEditorHtml($_REQUEST['docid'], $template_content);
316 } else {
317 die(xlt('Invalid File'));
319 } elseif (!empty($_GET['templateHtml'] ?? null)) {
320 renderEditorHtml($_REQUEST['docid'], $_GET['templateHtml']);
324 * @param $template_id
325 * @param $content
327 function renderEditorHtml($template_id, $content)
329 global $authUploadTemplates;
331 $lists = [
332 '{ParseAsHTML}', '{ParseAsText}', '{styleBlockStart}', '{styleBlockEnd}', '{SignaturesRequired}', '{TextInput}', '{sizedTextInput:120px}', '{smTextInput}', '{TextBox:03x080}', '{CheckMark}', '{ynRadioGroup}', '{TrueFalseRadioGroup}', '{DatePicker}', '{DateTimePicker}', '{StandardDatePicker}', '{CurrentDate:"global"}', '{CurrentTime}', '{DOS}', '{ReferringDOC}', '{PatientID}', '{PatientName}', '{PatientSex}', '{PatientDOB}', '{PatientPhone}', '{Address}', '{City}', '{State}', '{Zip}', '{PatientSignature}', '{AdminSignature}', '{WitnessSignature}', '{AcknowledgePdf:pdf name or id:title}', '{EncounterForm:LBF}', '{Questionnaire:name or id}', '{Medications}', '{ProblemList}', '{Allergies}', '{ChiefComplaint}', '{DEM: }', '{HIS: }', '{LBF: }', '{GRP}{/GRP}'
335 <!DOCTYPE html>
336 <html>
337 <head>
338 <?php Header::setupHeader(['ckeditor']); ?>
339 </head>
340 <style>
341 input:focus,
342 input:active {
343 outline: 0 !important;
344 -webkit-appearance: none;
345 box-shadow: none !important;
348 .list-group-item {
349 font-size: .9rem;
352 .cke_contents {
353 height: 78vh !important;
355 </style>
356 <body>
357 <div class="container-fluid">
358 <div class="row">
359 <div class="col-10 px-1 sticky-top">
360 <form class="sticky-top" action='./import_template.php' method='post'>
361 <input type="hidden" name="csrf_token_form" id="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken('import-template-save')); ?>" />
362 <input type="hidden" name="docid" value="<?php echo attr($template_id) ?>">
363 <input type='hidden' name='mode' value="save">
364 <input type='hidden' name='service' value='window'>
365 <textarea cols='80' rows='10' id='templateContent' name='content'><?php echo text($content) ?></textarea>
366 <div class="row btn-group mt-1 float-right">
367 <div class='col btn-group mt-1 float-right'>
368 <?php if ($authUploadTemplates) { ?>
369 <button type="submit" class="btn btn-sm btn-primary"><?php echo xlt("Save"); ?></button>
370 <?php } else { ?>
371 <button disabled title="<?php echo xla("Not Authorized to Edit Templates") ?>" type="submit" class="btn btn-sm btn-primary"><?php echo xlt("Save"); ?></button>
372 <?php } ?>
373 <button type='button' class='btn btn-sm btn-secondary' onclick='parent.window.close() || parent.dlgclose()'><?php echo xlt('Cancel'); ?></button>
374 </div>
375 </div>
376 </form>
377 </div>
378 <div class="col-sm-2 px-0">
379 <div class='h4'><?php echo xlt("Directives") ?></div>
380 <ul class='list-group list-group-flush pl-1 mb-5'>
381 <?php
382 foreach ($lists as $list) {
383 echo '<input class="list-group-item p-1" value="' . attr($list) . '">';
386 </ul>
387 </div>
388 </div>
389 </div>
390 </body>
391 <script>
392 let isDialog = false;
393 let height = 550;
394 let max = 680;
395 <?php if (!empty($_REQUEST['dialog'] ?? '')) { ?>
396 isDialog = true;
397 height = 425;
398 max = 600;
399 <?php } ?>
400 let editor = '';
401 document.addEventListener('DOMContentLoaded', function () {
402 document.querySelectorAll('.list-group-item').forEach(item => {
403 item.addEventListener('mouseup', event => {
404 let input = event.currentTarget;
405 input.focus();
406 input.select();
409 editor = CKEDITOR.instances['templateContent'];
410 if (editor) {
411 editor.destroy(true);
413 CKEDITOR.disableAutoInline = true;
414 CKEDITOR.config.extraPlugins = "preview,save,docprops,justify";
415 CKEDITOR.config.allowedContent = true;
416 //CKEDITOR.config.fullPage = true;
417 CKEDITOR.config.height = height;
418 CKEDITOR.config.width = '100%';
419 CKEDITOR.config.resize_dir = 'both';
420 CKEDITOR.config.resize_minHeight = max / 2;
421 CKEDITOR.config.resize_maxHeight = max;
422 CKEDITOR.config.resize_minWidth = '50%';
423 CKEDITOR.config.resize_maxWidth = '100%';
424 CKEDITOR.config.enterMode = CKEDITOR.ENTER_BR;
425 CKEDITOR.config.shiftEnterMode = CKEDITOR.ENTER_P;
426 CKEDITOR.config.autoParagraph = false;
427 editor = CKEDITOR.replace('templateContent', {
428 removeButtons: 'PasteFromWord'
431 </script>
432 </html>
433 <?php }
438 function renderProfileHtml()
440 global $templateService;
442 $category_list = $templateService->fetchDefaultCategories();
443 $profile_list = $templateService->fetchDefaultProfiles();
445 <!DOCTYPE html>
446 <html>
447 <head>
448 <?php
449 if (empty($GLOBALS['openemr_version'] ?? null)) {
450 Header::setupHeader(['opener', 'sortablejs']);
451 } else {
452 Header::setupHeader(['opener']); ?>
453 <script src="<?php echo $GLOBALS['web_root']; ?>/portal/public/assets/sortablejs/Sortable.min.js?v=<?php echo $GLOBALS['v_js_includes']; ?>"></script>
454 <?php } ?>
455 </head>
456 <style>
457 body {
458 overflow: hidden;
461 .list-group-item {
462 cursor: move;
465 strong {
466 font-weight: 600;
469 .col-height {
470 max-height: 95vh;
471 overflow-y: auto;
472 overflow-x: hidden;
474 </style>
475 <script>
476 const profiles = <?php echo js_escape($profile_list); ?>;
477 document.addEventListener('DOMContentLoaded', function () {
478 // init drag and drop
479 let repository = document.getElementById('drag_repository');
480 Sortable.create(repository, {
481 group: {
482 name: 'repo',
483 handle: '.move-handle',
484 pull: 'clone'
486 sort: true,
487 animation: 150,
488 onAdd: function (evt) {
489 let el = evt.item;
490 el.parentNode.removeChild(el);
494 Object.keys(profiles).forEach(key => {
495 let profileEl = profiles[key]['option_id']
496 let id = document.getElementById(profileEl);
497 Sortable.create(id, {
498 group: {
499 name: 'repo',
500 delay: 1000,
501 handle: '.move-handle',
502 put: (to, from, dragEl, event) => {
503 for (let i = 0; i < to.el.children.length; i++) {
504 if (to.el.children[i].getAttribute('data-id') === dragEl.getAttribute('data-id')) {
505 return false
508 return true
511 onAdd: function (evt) {
512 let el = evt.item;
513 el.getElementsByTagName('form')[0].classList.remove("d-none");
515 animation: 150
519 top.restoreSession();
520 function submitProfiles() {
521 top.restoreSession();
522 let target = document.getElementById('edit-profiles');
523 let profileTarget = target.querySelectorAll('ul');
524 let formTarget = target.querySelectorAll('form');
525 let profileArray = [];
526 let listData = {};
527 profileTarget.forEach((ulItem, index) => {
528 let lists = ulItem.querySelectorAll('li');
529 lists.forEach((item, index) => {
530 //console.log({index, item})
531 let pform = item.getElementsByTagName('form')[0];
532 let formData = $(pform).serializeArray();
533 listData = {
534 'form': formData,
535 'profile': ulItem.dataset.profile,
536 'id': item.dataset.id,
537 'category': item.dataset.category,
538 'name': item.dataset.name
540 profileArray.push(listData);
543 const data = new FormData();
544 data.append('profiles', JSON.stringify(profileArray));
545 data.append('mode', 'save_profiles');
546 fetch('./import_template.php', {
547 method: 'POST',
548 body: data,
549 }).then(rtn => rtn.text()).then((rtn) => {
550 (async (time) => {
551 await asyncAlertMsg(rtn, time, 'success', 'lg');
552 })(1000).then(rtn => {
553 opener.document.edit_form.submit();
554 dlgclose();
556 }).catch((error) => {
557 console.error('Error:', error);
560 </script>
561 <body>
562 <div class='container-fluid'>
563 <?php
564 // exclude templates sent to all patients(defaults)
565 $templates = $templateService->getTemplateListAllCategories(-1, true);
566 //$templates = $templateService->getTemplateListUnique(); // Reserved TBD future use
568 <div class='row'>
569 <div class='col-6 col-height'>
570 <nav id='disposeProfile' class='navbar navbar-light bg-light sticky-top'>
571 <div class='btn-group'>
572 <button class='btn btn-primary btn-save btn-sm' onclick='return submitProfiles();'><?php echo xlt('Save Profiles'); ?></button>
573 <button class='btn btn-secondary btn-cancel btn-sm' onclick='dlgclose();'><?php echo xlt('Quit'); ?></button>
574 </div>
575 </nav>
576 <div class="border-left border-right">
577 <div class='bg-dark text-light py-1 mb-2 text-center'><?php echo xlt('Available Templates'); ?></div>
578 <ul id='drag_repository' class='list-group mx-2 mb-2'>
579 <?php
580 foreach ($templates as $cat => $files) {
581 if (empty($cat)) {
582 $cat = xlt('General');
584 foreach ($files as $file) {
585 $template_id = attr($file['id']);
586 $title = $category_list[$cat]['title'] ?: $cat;
587 $title_esc = attr($title);
588 $this_name = attr($file['template_name']);
589 if ($file['mime'] === 'application/pdf') {
590 continue;
592 /* The drag container */
593 echo "<li class='list-group-item px-1 py-1 mb-1 bg-primary' data-id='$template_id' data-name='$this_name' data-category='$title_esc'>" .
594 "<strong>" . text($file['template_name']) .
595 '</strong>' . ' ' . xlt('in category') . ' ' .
596 '<strong>' . text($title) . '</strong>';
598 <form class='form form-inline bg-light text-dark py-1 pl-1 d-none'>
599 <div class='input-group-sm input-group-prepend'>
600 <label class="form-check-inline d-none"><?php echo xlt('OneTime') ?>
601 <input name="onetimeIsOkay" type='checkbox' class="input-control-sm ml-1 mt-1" title="<?php echo xla('Enable Auto Portal log in for presenting document to patient.') ?>" />
602 </label>
603 </div>
604 <label class='font-weight-bold mr-1 d-none'><?php echo xlt('Notify') ?></label>
605 <div class='input-group-sm input-group-prepend d-none'>
606 <input name="notify_days" type="text" style="width: 50px;" class='input-control-sm ml-1' placeholder="<?php echo xla('days') ?>" value="" />
607 <label class="mx-1"><?php echo xlt('Days') ?></label>
608 </div>
609 <div class='input-group-sm input-group-prepend'>
610 <select name="notify_when" class='input-control-sm mx-1 d-none'>
611 <option value=""><?php echo xlt('Unassigned'); ?></option>
612 <option value="new"><?php echo xlt('New'); ?></option>
613 <option value='before_appointment'><?php echo xlt('Before Appointment'); ?></option>
614 <option value='after_appointment'><?php echo xlt('After Appointment'); ?></option>
615 <option value="before_expires"><?php echo xlt('Before Expires'); ?></option>
616 <option value="in_edit"><?php echo xlt('In Edit'); ?></option>
617 </select>
618 </div>
619 <div class='input-group-sm input-group-prepend'>
620 <label class="form-check-inline"><?php echo xlt('Recurring') ?>
621 <input name="recurring" type='checkbox' class="input-control-sm ml-1 mt-1" />
622 </label>
623 </div>
624 <div class='input-group-sm input-group-prepend'>
625 <label><?php echo xlt('On') ?></label>
626 <select name="when" class='input-control-sm mx-1'>
627 <!--<option value=""><?php /*echo xlt('Unassigned') */ ?></option>-->
628 <option value="completed"><?php echo xlt('Completed') ?></option>
629 <option value='always'><?php echo xlt('Always') ?></option>
630 <option value='once'><?php echo xlt('One time') ?></option>
631 </select>
632 </div>
633 <div class='input-group-sm input-group-prepend'>
634 <label><?php echo xlt('Every') ?></label>
635 <input name="days" type="text" style="width: 50px;" class='input-control-sm ml-1' placeholder="<?php echo xla('days') ?>" value="" />
636 <label class="mx-1"><?php echo xlt('Days') ?></label>
637 </div>
638 </form>
639 <?php
640 echo '</li>' . "\n";
644 </ul>
645 </div>
646 </div>
647 <div class='col-6 col-height'>
648 <div id="edit-profiles" class='control-group mx-1 border-left border-right'>
649 <?php
650 foreach ($profile_list as $profile => $profiles) {
651 $profile_items_list = $templateService->getTemplateListByProfile($profile);
652 $profile_esc = attr($profile);
654 <div class='bg-dark text-light mb-1 py-1 pl-1'><?php echo xlt($profiles['title']) ?></div>
655 <?php
656 echo "<ul id='$profile_esc' class='list-group mx-2 mb-2' data-profile='$profile_esc'>\n";
657 foreach ($profile_items_list as $cat => $files) {
658 if (empty($cat)) {
659 $cat = xlt('General');
661 foreach ($files as $file) {
662 $template_id = attr($file['id']);
663 $this_cat = attr($file['category']);
664 $title = $category_list[$file['category']]['title'] ?: $cat;
665 $this_name = attr($file['template_name']);
666 $events = $templateService->fetchTemplateEvent($profile, $template_id);
667 $recurring = attr($events['recurring'] ?? '');
668 $trigger = attr($events['event_trigger'] ?? ''); // max 32 char
669 $notify_trigger = attr($events['notify_trigger'] ?? ''); // max 32 char
670 $days = attr($events['period'] ?? '');
671 $notify_days = attr($events['notify_period'] ?? '');
672 if ($file['mime'] === 'application/pdf') {
673 continue;
676 <li class='list-group-item bg-warning text-light px-1 py-1 mb-1' data-id="<?php echo $template_id; ?>" data-name="<?php echo $this_name; ?>" data-category="<?php echo $this_cat; ?>"><span class="p-1 font-weight-bold"><?php echo text($file['template_name']) . ' ' . xlt('in category') . ' ' . text($title); ?></span>
677 <!-- Notice! The notify event input is patched out until I get around to it. -->
678 <form class='form form-inline bg-light text-dark py-1 pl-1'>
679 <div class='input-group-sm input-group-prepend d-none'>
680 <label class="form-check-inline"><?php echo xlt('OneTime') ?>
681 <input name="onetimeIsOkay" type='checkbox' class="input-control-sm ml-1 mt-1" title="<?php echo xla('Enable Auto Portal log in for presenting document to patient.') ?>" />
682 </label>
683 </div>
684 <label class='font-weight-bold mr-1 d-none'><?php echo xlt('Notify') ?></label>
685 <div class='input-group-sm input-group-prepend d-none'>
686 <input name="notify_days" type="text" style="width: 50px;" class='input-control-sm ml-1' placeholder="<?php echo xla('days') ?>" value="<?php echo $notify_days ?>" />
687 <label class="mx-1"><?php echo xlt('Days') ?></label>
688 </div>
689 <div class='input-group-sm input-group-prepend d-none'>
690 <select name="notify_when" class='input-control-sm mx-1'>
691 <option value=""><?php echo xlt('Unassigned'); ?></option>
692 <option <?php echo $notify_trigger === 'new' ? 'selected' : ''; ?> value="new"><?php echo xlt('New'); ?></option>
693 <option <?php echo $notify_trigger === 'before_appointment' ? 'selected' : ''; ?> value='before_appointment'><?php echo xlt('Before Appointment'); ?></option>
694 <option <?php echo $notify_trigger === 'after_appointment' ? 'selected' : ''; ?> value='after_appointment'><?php echo xlt('After Appointment'); ?></option>
695 <option <?php echo $notify_trigger === 'before_expires' ? 'selected' : ''; ?> value="before_expires"><?php echo xlt('Before Expires'); ?></option>
696 <option <?php echo $notify_trigger === 'in_edit' ? 'selected' : ''; ?> value="in_edit"><?php echo xlt('In Edit'); ?></option>
697 </select>
698 </div>
699 <div class='input-group-sm input-group-prepend'>
700 <label class="form-check-inline"><?php echo xlt('Recurring') ?>
701 <input <?php echo $recurring ? 'checked' : '' ?> name="recurring" type='checkbox' class="input-control-sm ml-1 mt-1" />
702 </label>
703 </div>
704 <div class='input-group-sm input-group-prepend'>
705 <label><?php echo xlt('On') ?></label>
706 <select name="when" class='input-control-sm mx-1'>
707 <!--<option value=""><?php /*echo xlt('Unassigned') */ ?></option>-->
708 <option <?php echo $trigger === 'completed' ? 'selected' : ''; ?> value="completed"><?php echo xlt('Completed') ?></option>
709 <option <?php echo $trigger === 'always' ? 'selected' : ''; ?> value='always'><?php echo xlt('Always') ?></option>
710 <option <?php echo $trigger === 'once' ? 'selected' : ''; ?> value='once'><?php echo xlt('One time') ?></option>
711 <option <?php echo $trigger === '30:90:365' ? 'selected' : ''; ?> value='30:90:365'><?php echo xlt('30-90-365') ?></option>
712 </select>
713 </div>
714 <div class='input-group-sm input-group-prepend'>
715 <label><?php echo xlt('Every') ?></label>
716 <input name="days" type="text" style="width: 50px;" class='input-control-sm ml-1' placeholder="<?php echo xla('days') ?>" value="<?php echo $days ?>" />
717 <label class="mx-1" for="<?php echo $profile_esc ?>-days"><?php echo xlt('Days') ?></label>
718 </div>
719 </form>
720 </li>
721 <?php
724 echo "</ul>\n";
727 </div>
728 </div>
729 </div>
730 </div>
731 <hr />
732 </body>
733 </html>
734 <?php }