Display Facility Name in Fancy style calendar and use color coding
[openemr.git] / interface / main / calendar / modules / PostCalendar / pntemplates / default / views / day / fancy_template.html
blobae184383f630d901eb4114e127e23ec7e91642e2
1 [-*Smarty*-]
2 [-*********************************************************************************-]
3 [-* Copyright (C) 2005-2006 Rod Roark <rod@sunsetsystems.com> and others *-]
4 [-* Copyright (C) 2008 CHEMED (Nethanel Vilensky) <techsupport@chemedhealth.org> *-]
5 [-* *-]
6 [-* This program is free software; you can redistribute it and/or *-]
7 [-* modify it under the terms of the GNU General Public License *-]
8 [-* as published by the Free Software Foundation; either version 2 *-]
9 [-* of the License, or (at your option) any later version. *-]
10 [-*********************************************************************************-]
12 [-if $PRINT_VIEW == 1-]
13 [-* The new calendar interface is not printed correctly by Firefox (because of abs. positioned DOM elements) *-]
14 [-* so we have to use the older interface instead *-]
15 [-include file="$TPL_NAME/views/day/orig_default.html"-]
16 [-else-]
18 [-config_load file="default.conf"-]
19 [-*Load the Language Definitions*-]
20 [-config_load file="lang.$USER_LANG"-]
21 [-include file="$TPL_NAME/views/header.html"-]
22 [-* we want to include out stylesheet for this view*-]
23 [-fetch file="$TPL_STYLE_PATH/day.css" assign="css"-]
24 [-eval var=$css-]
26 [-*Main Navigation*-]
27 [-include file="$TPL_NAME/views/global/navigation.html"-]
29 [-assign var="dayname" value=$DATE|date_format:"%w"-]
30 [-assign var="day" value=$DATE|date_format:"%d"|string_format:"%1d"-]
31 [-assign var="month" value=$DATE|date_format:"%m"|string_format:"%1d"-]
32 [-assign var="year" value=$DATE|date_format:"%Y"|string_format:"%4d"-]
34 [-pc_sort_events var="S_EVENTS" sort="time" order="asc" value=$A_EVENTS-]
36 <div class='cal_labels'> [-* START Column labels *-]
37 [-foreach from=$providers item=provider-]
38 <div class='cal_column_line_label'></div>
39 <div class='cal_column_label'>[-$provider.lname-]</div>
40 [-/foreach-]
41 </div> [-* END Column labels *-]
44 <div class='cal_container'> [-* Main scrollable container *-]
46 [-php-]
48 //Used for sorting the event later
49 function compareEvents($a,$b) {
50 $start_a = $a['start_slot'];
51 $start_b = $b['start_slot'];
52 $end_a = $a['end_slot'];
53 $end_b = $b['end_slot'];
54 $dur_a = $a['data']['duration'];
55 $dur_b = $b['data']['duration'];
56 $cat_a = $a['data']['catid'];
57 $cat_b = $b['data']['catid'];
59 //IN-OUT events are always the lowest in the list and show up right-most in the UI
60 if (($cat_a == '2') || ($cat_a == '3') || ($cat_a == '4') || ($cat_a == '8') || ($cat_a == '11')) {
61 return 1;
63 if (($cat_b == '2') || ($cat_b == '3') || ($cat_b == '4') || ($cat_b == '8') || ($cat_b == '11')) {
64 return -1;
67 if (($start_a == $start_b) &&
68 ($end_a == $end_b) &&
69 ($dur_a == $dur_b)) {return 0;} //Events are alike
71 if ($start_a == $start_b) { //Events start together
72 if ($dur_a != $dur_b) { //Simply sort by duration
73 return ($dur_a > $dur_b) ? -1 : 1;
74 } else {
75 return 0;
79 if ($start_a < $start_b) { //a starts earlier than b
80 if ($end_a >= $end_b) { //events share slots
81 if ($dur_a != $dur_b) { //Simply sort by duration
82 return ($dur_a > $dur_b) ? -1 : 1;
83 } else {
84 return 0;
86 } else { //events do not share slots and $a is earlier than $b
87 return -1;
91 if ($start_b < $start_a) { //b starts earlier than a
92 if ($end_b >= $end_a) { //events share slots
93 if ($dur_a != $dur_b) { //Simply sort by duration
94 return ($dur_a > $dur_b) ? -1 : 1;
95 } else {
96 return 0;
98 } else { //events do not share slots and $b is earlier than $a
99 return 1;
104 //Configuration
107 ------------------------ <= $calendar_width => -------------------------------------------
108 |<= $line_label_width => | <= $column_width => ||... |... |
109 ------------------------------------------------------------------------------------------
110 |... | ... ||... |... |
111 ------------------------------------------------------------------------------------------
113 In a couple of places I am adding +1 to sizes. This is to account for extra 1px wide border around elements.
116 $day_start_y = 30; //Used for multiday display
118 $start_hour = $GLOBALS['schedule_start'];
119 $end_hour = $GLOBALS['schedule_end'];
121 $slot_minutes = $GLOBALS['calendar_interval'];
123 if ($PRINT_VIEW != 1) {
124 $container_width = $_SESSION['pc_framewidth'] - 20;
125 } else {
126 $container_width = 900; //Make it fit to a landscape letter-sized paper
129 $line_height = 80;
131 $line_label_width = 40;
132 $scrollbar_width = 30;
134 $calendar_width = $container_width - $scrollbar_width;
136 $columns = count($providers);
137 $column_width = ($calendar_width / $columns) - $line_label_width;
139 $hour_slots = 60 / $slot_minutes;
140 $hour_height = $hour_slots * $slot_height;
142 $slots_count = ($end_hour - $start_hour) * $hour_slots + 1; //How many slots will we have per day
143 $calendar_height = $line_height * ($slots_count + 1) + 20;
145 //Generate columns (each column is a provider)
146 // ['count'] how many columns we have altogether
147 // ['pid']['index'] which column is it counting from the left (0 based)
148 // ['pid']['x'] how far from the left edge the column starts (in pixels)
149 $columns = array('count' => 0);
150 foreach ($providers as $provider) {
151 $pid = $provider['id'];
152 $columns[$pid]['index'] = $columns['count']++;
153 $columns[$pid]['x'] = (($columns[$pid]['index'] + 1) * ($line_label_width + 1)) + ($column_width * $columns[$pid]['index']);
156 //Re-Index categories array to make it more usefull
157 $categories = array();
158 foreach ($A_CATEGORY as $category) {
159 $categories[$category['id']] = $category;
162 //For each day...
163 foreach ($A_EVENTS as $date => $event_list) {
165 //Generate labels and positions for all the calendar lines
166 $lines = array(); //This will hold metadata for each visual calendar line
167 $hour = $start_hour;
168 $minutes = 0;
170 for ($i = 1; $i <= $slots_count; $i++) {
171 $lines[$i] = array();
172 $lines[$i]['index'] = $i;
173 $lines[$i]['ampm'] = $hour >= 12 ? '2' : '1'; //For the links
174 $lines[$i]['ampm_char'] = $hour >= 12 ? 'pm' : 'am'; //Visual representation
175 $lines[$i]['hour'] = $hour > 12 ? $hour - 12 : $hour;
176 $lines[$i]['min'] = $minutes;
177 $lines[$i]['date'] = $date;
178 $lines[$i]['label'] = $lines[$i]['hour'].":".str_pad($minutes, 2, '0', STR_PAD_LEFT).'&nbsp;<br />'.$lines[$i]['ampm_char'].'&nbsp;';
179 $lines[$i]['y'] = ($i-1) * ($line_height + 1) + $day_start_y; //Where to absolutely position the line
181 //Go to the next slot
182 $minutes += $slot_minutes;
183 if (($i % $hour_slots) == 0) { //New hour starts
184 $hour++;
185 $minutes = 0;
189 $arr_events = $S_EVENTS[$date];
191 $events = array(); //Temporary array for enumerating the events
192 $slots = array(); //This is the map of slots showing how many events share the slot and the CSS style for IN-OUT events
193 $provstat = array(); //Used to gray out the slots for which the provider is not available (out of office)
195 //Initialize the slot map with defaul values
196 // ['adj'] Used for adjusting the chip's width and position from the left column edge (see further below)
197 // ['n'] How many events share the same slot
198 // ['provstat'] CSS style name as a visual cue that provider is available or not
199 foreach($providers as $provider) {
200 $slots[$provider['id']] = array();
201 for ($i = 1; $i <= $slots_count; $i++) {
202 $slots[$provider['id']][$i] = array('adj' => 0, 'n' => 0, 'provstat' => 'cal_slot_out');
206 //Go through all the events for the day
207 list($slotkey, $slotevent) = each($arr_events);
208 for (; isset($slotkey); list($slotkey, $slotevent) = each($arr_events)) {
209 $starth = substr($slotevent['startTime'], 0, 2);
210 $startm = substr($slotevent['startTime'], 3, 2);
211 $providerid = $slotevent['aid'];
213 $start_slot = ($starth - $start_hour) * $hour_slots + floor($startm / $slot_minutes) + 1;
214 $durminutes = ceil($slotevent['duration'] / 60); //Convert from seconds to minutes
216 //$durslots is the amount of slots the chip touches, even if it does not fill a complete slot
217 $durslots = ceil((($startm % $slot_minutes) + $durminutes) / $slot_minutes);
218 if ($durslots == 0) { //Event should take up at least one slot
219 $durslots = 1;
220 $durminutes = $slot_minutes;
223 if (($start_slot + $durslots) > $slots_count) { //Event should not be longer than visible calendar
224 $durslots = $slots_count - $start_slot + 1;
225 $durminutes = $durslots * $slot_minutes;
228 $end_slot = $start_slot + $durslots;
230 //Events such as IN, OUT etc. require special handling (setting the CSS class name in the $slots map)
231 if ($slotevent['catid'] == 2) {
232 for ($i = $start_slot; $i <= $slots_count; $i++) {
233 $slots[$providerid][$i]['provstat'] = 'cal_slot_in';
237 if ($slotevent['catid'] == 3) {
238 for ($i = $start_slot; $i <= $slots_count; $i++) {
239 $slots[$providerid][$i]['provstat'] = 'cal_slot_out';
243 if ($slotevent['catid'] == 4) {
244 for ($i = $start_slot; $i < $start_slot + $durslots; $i++) {
245 $slots[$providerid][$i]['provstat'] = 'cal_slot_out';
249 if ($slotevent['catid'] == 8) {
250 for ($i = $start_slot; $i < $start_slot + $durslots; $i++) {
251 $slots[$providerid][$i]['provstat'] = 'cal_slot_out';
254 //END special events handling
256 //Mark slots as taken and count the chips in each slot
257 for ($i = $start_slot; $i < $end_slot; $i++) {
258 $slots[$providerid][$i]['n']++;
261 //Calculate event chip dimensions
262 $x = $columns[$providerid]['x'];
263 $y = $lines[$start_slot]['y'];
264 $w = $column_width;
265 $h = $durslots * ($line_height + 1) - 2;
267 $slotevent['duration'] = $durminutes; //Convert from seconds to minutes
269 //Add event to the list for rendering
270 //attaching the category and event data from the database
271 if ($slotevent['eid'] != '') { //For some reason empty $slotevent sometimes exist. TODO: Figure out why
272 $events[$providerid][] = array(
273 'left' => $x,
274 'top' => $y,
275 'width' => $w,
276 'height' => $h,
277 'start_slot' => $start_slot,
278 'end_slot' => $end_slot,
279 'category' => $categories[$slotevent['catid']],
280 'data' => $slotevent
286 $ready_events = array(); //This array will hold events with fully adjusted position
289 list($providerid, $events_list) = each($events);
290 for (; isset($providerid); list($providerid, $events_list) = each($events)) {
292 /* Sorting debug: foreach ($events_list as $ev) {
293 print('ID: '.$ev['data']['eid'].'&nbsp;');
294 print('Start: '.$ev['start_slot'].'&nbsp;End:'.$ev['end_slot'].'&nbsp;');
295 print('Duration: '.$ev['data']['duration'].'&nbsp;');
296 print('Top: '.$ev['top'].'&nbsp;Left:'.$ev['left'].'&nbsp;');
297 print('---------------<br />');
299 print "#########################################################################Sorting...<br />";*/
301 //Sort events so that they as much as possible do NOT overlap
302 usort($events_list, "compareEvents");
304 /* Sorting debug: foreach ($events_list as $ev) {
305 print('ID: '.$ev['data']['eid'].'&nbsp;');
306 print('Start: '.$ev['start_slot'].'&nbsp;End:'.$ev['end_slot'].'&nbsp;');
307 print('Duration: '.$ev['data']['duration'].'&nbsp;');
308 print('Top: '.$ev['top'].'&nbsp;Left:'.$ev['left'].'&nbsp;');
309 print('---------------<br />');
311 exit;*/
313 if (!isset($ready_events[$providerid])) {$ready_events[$providerid] = array();}
314 foreach ($events_list as $event) {
315 $neighbors = 1;
316 //Find the max neccesary width divisor (how thin to make this chip)
317 //by going over each slot the chip overlays and seeing how many others are there
318 for ($i = $event['start_slot']; $i < $event['end_slot']; $i++) {
319 if ($slots[$providerid][$i]['n'] > $neighbors) {$neighbors = $slots[$providerid][$i]['n'];}
320 $slots[$providerid][$i]['adj']++;
322 //Adjust chip position and width (the magic number 3 adjusts for chip borders and the space between chips)
323 $event['width'] = floor(($column_width - ($neighbors * 3)) / $neighbors);
324 $event['left'] = $event['left'] + (($event['width'] + 3) * ($slots[$providerid][$event['start_slot']]['adj'] - 1));
325 $ready_events[$providerid][] = $event;
327 //usort($ready_events[$providerid], "compareEvents");
331 //Marshall some variables to Smarty engine
332 $this->assign('container_width', $container_width);
333 $this->assign('calendar_width', $calendar_width);
334 $this->assign('date', $date);
335 $this->assign_by_ref('lines', $lines);
336 $this->assign('line_height', $line_height);
337 $this->assign('hour_height', $hour_height);
338 $this->assign('line_label_width', $line_label_width);
339 $this->assign('column_width', $column_width);
340 $this->assign_by_ref('events', $ready_events);
341 $this->assign_by_ref('slots', $slots);
342 $this->assign('date_label_y', $day_start_y - 30);
343 $this->assign('calendar_height', $calendar_height);
345 [-/php-]
348 <div class='cal_underlay'>
349 <div class='cal_date_label' style='top: [-$date_label_y-]'>[-php-]echo dateformat(strtotime($date),true); [-/php-]</div>
350 [-foreach from=$lines item=line-] [-* START Lines *-]
351 <div class='cal_line' style='top: [-$line.y-]px;'>
352 [-foreach from=$providers item=provider-] [-* START Columns (Providers) *-]
353 <div class='cal_line_label' onClick="javascript:newEvt([-$line.ampm-], [-$line.hour-], [-$line.min-], [-$line.date|date_format:'%Y%m%d'-], [-$provider.id-], 0)">
354 [-*<a href="javascript:newEvt([-$line.ampm-], [-$line.hour-], [-$line.min-], [-$line.date|date_format:'%Y%m%d'-], [-$provider.id-], 0)">*-]
355 [-$line.label-]&nbsp;
356 [-*</a>*-]
357 </div> [-* Line label (hour:min) *-]
359 [-assign var=pid value=$provider.id-]
360 [-assign var=lineindex value=$line.index-]
361 <div class='cal_slot [-$slots.$pid.$lineindex.provstat-]'>&nbsp;</div>
362 [-*php-]print_r($slots);Exit;[-/php*-]
363 [-/foreach-] [-* END Columns (Providers) *-]
364 </div>
365 [-/foreach-] [-* END Lines *-]
366 </div>
368 <div class='cal_overlay'> [-* START Events overlay *-]
369 [-* We should access $events through $provider.id index to only show events for selected providers *-]
370 [-foreach from=$providers item=provider-] [-* START Columns (Providers) *-]
371 [-assign var=pid value=$provider.id-]
372 [-assign var=column value=$events.$pid-]
373 [-foreach from=$column item=event-] [-* START Events *-]
374 [-if $event.data.catid eq 2 || $event.data.catid eq 3 || $event.data.catid eq 4 || $event.data.catid eq 8 || $event.data.catid eq 11-]
375 <div class='cal_event_na' style='top: [-$event.top-]px;
376 left: [-$event.left-]px;
377 width: [-$event.width-]px;
378 height: [-$event.height-]px;'>
379 <a href='javascript:oldEvt([-$date|date_format:"%Y%m%d"-], [-$event.data.eid-])'>
380 [-if $event.data.catid eq 2-]
381 [-php-] xl('IN','e'); [-/php-]
382 [-elseif $event.data.catid eq 3-]
383 [-php-] xl('OUT','e'); [-/php-]
384 [-elseif $event.data.catid eq 4-]
385 [-php-] xl('VACATION','e'); [-/php-]
386 [-elseif $event.data.catid eq 8-]
387 [-php-] xl('LUNCH','e'); [-/php-]
388 [-elseif $event.data.catid eq 11-]
389 [-php-] xl('RESERVED','e'); [-/php-]
390 [-else-]
391 [-php-] xl('Not Available','e'); [-/php-]
392 [-/if-]
393 </a>
394 </div>
395 [-else-]
396 <div class='cal_event' style='top: [-$event.top-]px;
397 left: [-$event.left-]px;
398 width: [-$event.width-]px;
399 height: [-$event.height-]px;
400 background-color: [-$event.category.color-];'>
402 <span class='cal_event_status'>[-$event.data.apptstatus-]</span>
403 <a href='javascript:oldEvt([-$date|date_format:"%Y%m%d"-], [-$event.data.eid-])'>
404 [-$event.data.startTime|date_format:"%I:%M %p"-]
405 </a>
406 </p>
408 <p><font color="[-$event.data.facility.color-]">
409 [-$event.data.facility.name-]
410 </font></p>
412 <p>[-$event.data.duration-][-php-] xl('min','e'); [-/php-]</p>
414 [-if $event.data.pid gt 0-]
415 <p><a href='javascript:goPid([-$event.data.pid-])'>[-$event.data.patient_name|default:'No name'-]</a></p>
416 <p>[-if $event.data.patient_dob ne ''-][-php-] xl('Age','e'); [-/php-]: [-$event.data.patient_age-][-/if-]</p>
417 [-/if-]
418 [-if $event.data.title ne ''-]<p>[-$event.data.title|escape-]</p>[-/if-]
419 [-if $event.data.hometext ne ''-]<p>([-$event.data.hometext|escape-])</p>[-/if-]
421 </div>
422 [-/if-]
423 [-/foreach-] [-* END Events *-]
424 [-/foreach-] [-* END Columns (Providers) *-]
425 </div> [-* END Events overlay *-]
428 [-php-]
429 //For multiday display we have to make the calendar larger
430 $day_start_y += ($line_height * ($slots_count+1)) + 50;
431 $calendar_height += $calendar_height;
434 [-/php-]
435 </div> [-* END Main scrollable container *-]
436 <style>
438 margin: 0px 0px 0px 2px;
439 padding: 0px;
442 .cal_container {
443 [-if $PRINT_VIEW != 1-]
444 position: absolute;
445 top: 80px;
446 [-else-]
447 position: relative;
448 top: 60px;
449 [-/if-]
450 left: 2px;
451 width: [-$container_width-]px;
452 [-if $PRINT_VIEW != 1-]
453 height: 82%; /* Unfortunately there is no way to reliably get a viewport height. */
454 overflow-y: scroll;
455 [-else-]
456 height: [-$calendar_height-]px;
457 overflow: visible;
458 [-/if-]
459 border: solid 1px #A2BBDD;
460 padding: 0px;
461 margin: 0px;
464 .cal_underlay {
465 position: absolute;
466 height: 100%;
467 width: 100%;
468 top: 0px;
469 left: 0px;
470 padding: 0px;
471 margin: 0px;
474 .cal_overlay {
475 position: absolute;
476 top: 0px;
477 left: 0px;
478 padding: 0px;
479 margin: 0px;
483 .cal_line {
484 position: absolute;
485 width: 100%;
486 height: [-$line_height-]px;
487 border-bottom: solid 1px #CCCCCC;
488 padding: 0px;
489 margin: 0px;
492 .cal_slot {
493 width: [-$column_width-]px;
494 height: 100%;
495 float: left;
496 border-left: solid 1px #CCCCCC;
497 padding: 0px;
498 margin: 0px;
501 .cal_slot_in {
502 background-color: #FFFFFF;
504 .cal_slot_out {
505 background-color: #EEEEEE;
508 .cal_line_label {
509 width: [-$line_label_width-]px;
510 height: [-$line_height-]px;
511 float: left;
512 background-color: #E8EEF7;
513 color: #333399;
514 font-family: Arial, Helvetica, sans-serif;
515 font-size: 12px;
516 font-weight: normal;
517 text-align: right;
518 vertical-align: top;
519 padding: 0px 0px 0px 0px;
520 margin: 0px;
523 .cal_column_line_label {
524 width: [-$line_label_width-]px;
525 height: 100%;
526 float: left;
527 padding: 0px;
528 margin: 0px;
529 background-color: #E8EEF7;
530 color: #333399;
531 font-family: Arial, Helvetica, sans-serif;
532 font-size: 12px;
533 font-weight: normal;
534 text-align: right;
535 vertical-align: top;
536 padding: 0px 0px 0px 0px;
537 margin: 0px;
541 .cal_labels {
542 position: absolute;
543 width: [-$container_width-]px;
544 height: 20px;
545 border: solid 1px #CCCCCC;
546 padding: 0px;
547 margin: 0px;
548 [-if $PRINT_VIEW != 1-]
549 top: 57px;
550 [-else-]
551 top: 20px;
552 [-/if-]
555 .cal_column_label {
556 top: 80px;
557 left: 0px;
558 width: [-$column_width-]px;
559 height: 100%;
560 float: left;
561 border-left: solid 1px #CCCCCC;
562 text-align: center;
563 font-weight: bold;
564 padding: 0px;
565 margin: 0px;
568 .cal_date_label {
569 position: absolute;
570 left: 0px;
571 width: 100%;
572 height: 20;
573 text-align: center;
574 font-weight: bold;
575 padding: 0px;
576 margin: 0px;
577 background-color: #B0C4DE;
580 .cal_event {
581 position: absolute;
582 font-size: 9px;
583 border-top: solid 1px #EEEEEE;
584 border-bottom: solid 1px #000000;
585 border-left: solid 1px #EEEEEE;
586 border-right: solid 1px #000000;
587 padding: 0px;
588 margin: 0px;
589 z-index: 1;
590 background-color: #FFFFFF;
591 font-family: Arial, Helvetica, sans-serif;
592 font-style: italic;
593 font-weight: normal;
594 font-size: 11px;
595 overflow: hidden;
598 .cal_event_na {
599 position: absolute;
600 font-size: 9px;
601 padding: 2px;
602 z-index: 1;
603 margin: 0px;
604 font-family: Arial, Helvetica, sans-serif;
605 font-style: italic;
606 font-weight: bold;
607 font-size: 14px;
610 .cal_event_status {
611 background-color: #E8EEF7;
612 color: #000000;
613 font-family: Courier, mono;
614 font-size: 14px;
615 font-style: normal;
616 font-weight: bold;
617 float: right;
618 border-left: solid 1px #CCCCCC;
619 border-bottom: solid 1px #CCCCCC;
620 margin: 0px;
621 padding: 0px 1px 0px 2px;
623 </style>
625 </body>
626 </html>
627 [-/if-]