LP1790727: Add a daily schedule view of existing bookings user/sandbergja/lp1790727_booking_daily_schedule_for_feedback
authorJane Sandberg <sandbej@linnbenton.edu>
Tue, 4 Sep 2018 21:31:57 +0000 (14:31 -0700)
committerJane Sandberg <sandbej@linnbenton.edu>
Tue, 4 Sep 2018 22:35:44 +0000 (15:35 -0700)
Signed-off-by: Jane Sandberg <sandbej@linnbenton.edu>
Open-ILS/src/templates/staff/booking/t_daily_schedule.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/css/booking.css.tt2 [new file with mode: 0644]
Open-ILS/src/templates/staff/navbar.tt2
Open-ILS/src/templates/staff/share/print_templates/t_booking_daily_schedule.tt2 [new file with mode: 0644]
Open-ILS/web/js/ui/default/staff/booking/app.js

diff --git a/Open-ILS/src/templates/staff/booking/t_daily_schedule.tt2 b/Open-ILS/src/templates/staff/booking/t_daily_schedule.tt2
new file mode 100644 (file)
index 0000000..f6b7612
--- /dev/null
@@ -0,0 +1,55 @@
+<h1>[% l('Daily Schedule') %]</h1>
+<div class="bg-info">
+  <div class="row">
+    <div class="col-sm-2">
+      <label>[% l('Library') %] <eg-org-selector selected="context_ou" onchange="handle_changed_ou" sticky-setting="booking.daily_schedule.context_ou"></eg-org-selector></label>
+    </div>
+    <div class="col-sm-2">
+      <label>[% l('Resource') %] <select class="form-control" ng-model="resource" ng-options="resource.id() as resource.barcode() for resource in resource_list"></select></label>
+    </div>
+    <div class="col-sm-2">
+      <label>[% l('Date') %] <eg-date-input ng-model="date"></eg-date-input></label>
+    </div>
+    <div class="col-sm-2">
+      <button class="btn btn-default" ng-hide="show_advanced" ng-click="show_advanced=true">[% l('Show advanced options') %]</button>
+      <button class="btn btn-default" ng-show="show_advanced" ng-click="show_advanced=false">[% l('Hide advanced options') %]</button>
+    </div>
+    <div class="col-sm-2 pull-right">
+      <button class="btn btn-default" ng-disabled="!resource" ng-click="print_schedule()">[% l('Print') %]</button>
+    </div>
+  </div>
+  <div class="row" ng-show="show_advanced">
+    <div class="col-md-2 checkbox checkbox-inline">
+      <label><input type="checkbox" ng-model="show_names" ng-change="on_show_names_changed()" value="">[% l('Show patron names') %]</label>
+    </div>
+    <div class="col-md-4 checkbox checkbox-inline">
+      <div class="row">
+        <label><div uib-timepicker id="start" show-time-picker hide-date-picker ng-model="startTime"></div>[% l('Start of displayed day') %]</label>
+        <label><div uib-timepicker id="end" show-time-picker hide-date-picker ng-model="endTime"></div>[% l('End of displayed day') %]</label>
+      </div>
+      <div class="row" ng-if="startTime >= endTime"><span class="bg-warning">[% l('Make sure the start time is before the end time') %]</span></div>
+    </div>
+  </div>
+</div>
+<div ng-show="resource" id="schedule">
+  <h2>{{date | date:date_format}}</h2>
+  <div ng-repeat="sched in schedule">
+    <div class="row schedule-row">
+      <div class="col-sm-3">{{sched.row|date:time_format}}</div>
+      <div ng-if="sched.reservations.length" class="col-sm-9 bg-primary" ng-class="{'ends-early': sched.reservations[sched.reservations.length-1].ends_early, 'starts-late': sched.reservations[0].starts_late}">
+        <div ng-repeat="r in sched.reservations">
+          <span ng-if="r.start_time">
+            <span ng-if="show_names">[% l('[_1], [_2] [_3]', 
+              '{{r.patron.family_name()}}',
+              '{{r.patron.first_given_name()}}',
+              '{{r.patron.second_given_name()}}') %]</span>
+            <span ng-if="!show_names">[% l('Busy') %]</span>
+            <span> ({{r.start_time | egOrgDate:'h:mm':context_ou}} - {{r.end_time | egOrgDate: 'h:mm':context_ou}})</span>
+            <span ng-if="!$last">[% l(', ') %]</span>
+          </span>
+          <span ng-if="r.continuation">[% l('...') %]</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/Open-ILS/src/templates/staff/css/booking.css.tt2 b/Open-ILS/src/templates/staff/css/booking.css.tt2
new file mode 100644 (file)
index 0000000..9be08be
--- /dev/null
@@ -0,0 +1,17 @@
+.schedule-row {
+  border-top: 1px dotted #777;
+  height: 30px;
+}
+
+.bg-primary {
+  height: 30px;
+}
+
+.start-after {
+  top: 5px;
+}
+
+.end-before {
+  bottom: 5px;
+}
+
index d3033d7..4bee097 100644 (file)
               [% l('Return Reservations') %]
             </a>
           </li>
+          <li>
+            <a href="./booking/daily_schedule" target="_self">
+              <span class="glyphicon glyphicon-list-alt"></span>
+              [% l('Daily Schedule') %]
+            </a>
+          </li>
         </ul>
       </li>
 
diff --git a/Open-ILS/src/templates/staff/share/print_templates/t_booking_daily_schedule.tt2 b/Open-ILS/src/templates/staff/share/print_templates/t_booking_daily_schedule.tt2
new file mode 100644 (file)
index 0000000..dfacb24
--- /dev/null
@@ -0,0 +1,20 @@
+<h3>{{barcode}} - {{date | date:date_format}}</h3>
+<table>
+  <tr ng-repeat="sched in schedule" style="border-top: 1px dotted black;">
+    <td style="padding: 5px 10px 5px 10px;">{{sched.row|date:time_format}}</td>
+    <td ng-style="sched.reservations.length && {'border-left': '3px solid black', 'border-right': '3px solid black', 'font-weight': 'bold', 'padding': '5px 10px 5px 10px'}">
+      <span ng-repeat="r in sched.reservations">
+        <span ng-if="r.start_time">
+          <span ng-if="show_names">[% l('[_1], [_2] [_3]',
+            '{{r.patron.family_name()}}',
+            '{{r.patron.first_given_name()}}',
+            '{{r.patron.second_given_name()}}') %]</span>
+          <span ng-if="!show_names">[% l('Busy') %]</span>
+          <span> ({{r.start_time | egOrgDate:'h:mm':context_ou}} - {{r.end_time | egOrgDate: 'h:mm':context_ou}})</span>
+        </span>
+        <span ng-if="r.continuation">...</span>
+        </div>
+      </div>
+    </td>
+  </tr>
+</table>
index 5f116d1..c1d8ce1 100644 (file)
@@ -17,6 +17,13 @@ angular.module('egBooking',
         resolve : resolver
     });
 
+    // daily view
+    $routeProvider.when('/booking/daily_schedule', {
+        templateUrl: './booking/t_daily_schedule',
+        controller: 'BookingDailyScheduleCtrl',
+        resolve : resolver
+    });
+
     // default page 
     $routeProvider.otherwise({
         templateUrl : './t_splash',
@@ -24,6 +31,135 @@ angular.module('egBooking',
     });
 }])
 
+.controller('BookingDailyScheduleCtrl',
+    ['$scope', 'egCore', 'egOrgDateFilter',
+        function($scope, egCore, egOrgDateFilter) {
+            $scope.context_ou = egCore.org.get(egCore.auth.user().ws_ou());
+            $scope.date = new Date();
+            $scope.date.setHours(0, 0, 0, 0);
+            $scope.startTime = new Date($scope.date.getTime() + egCore.date.intervalToSeconds('9 hours'));
+            $scope.endTime = new Date($scope.date.getTime() + egCore.date.intervalToSeconds('17 hours'));
+
+            $scope.date_format = 'mediumDate';
+            egCore.org.settings(['format.date']).then(function(set) {
+                if (set['format.date']) $scope.date_format = set['format.date'];
+            });
+            $scope.time_format = 'shortTime';
+            $scope.resource_list = [];
+            egCore.hatch.getItem('booking.daily_schedule.resource_id')
+                .then(function(resource_id){
+                    if (resource_id) $scope.resource = resource_id;
+            });  
+
+            egCore.hatch.getItem('booking.daily_schedule.show_names')
+                .then(function(show_names){
+                    if (show_names) $scope.show_names = show_names; 
+                });    
+            $scope.on_show_names_changed = function(){
+                egCore.hatch.setItem('booking.daily_schedule.show_names', $scope.show_names);
+            }
+
+            $scope.$watch('startTime',function(newValue,oldValue){
+                $scope.fix_date(newValue);
+                $scope.populate_display();
+            });
+            $scope.$watch('endTime',function(newValue,oldValue){
+                $scope.fix_date(newValue);
+                $scope.populate_display();
+            });
+            $scope.$watch('resource',function(newValue,oldValue){
+                $scope.populate_display();
+                egCore.hatch.setItem('booking.daily_schedule.resource_id', $scope.resource); 
+            });
+            $scope.$watch('date',function(newValue,oldValue){
+                if ($scope.resource) {
+                    $scope.populate_display();
+                }
+                    $scope.guess_display_times();
+                    $scope.fix_date($scope.startTime);
+                    $scope.fix_date($scope.endTime);
+            });
+
+            $scope.fix_date = function(time) {
+                time.setFullYear($scope.date.getFullYear(), $scope.date.getMonth(), $scope.date.getDate());
+                time.setSeconds(0);
+            }
+
+            $scope.populate_display = function() {
+                if ($scope.resource) {
+                    egCore.pcrud.search('bresv',
+                    {target_resource: $scope.resource,
+                    start_time: {"<": egOrgDateFilter($scope.endTime, 'yyyy-MM-dd HH:mm:ss', $scope.context_ou)},
+                    end_time: {">": egOrgDateFilter($scope.startTime, 'yyyy-MM-dd HH:mm:ss', $scope.context_ou)}},
+                    {flesh: 1, flesh_fields: {'bresv' : ['usr']}}, {atomic: true}).then(
+                        function(response) {
+                          $scope.schedule = []
+                          var start_distance_from_half_hour = ($scope.startTime.getMinutes() % 30);
+                          var current_working_time = new Date($scope.startTime.getTime());
+                          $scope.fix_date(current_working_time);
+                          var working_end_time = new Date($scope.endTime.getTime());
+                          $scope.fix_date(working_end_time);
+                          var next_working_time = new Date(current_working_time.getTime());
+                          do {
+                            next_working_time.setMinutes(current_working_time.getMinutes() + ((current_working_time.getMinutes() % 30) ? (30 - (current_working_time.getMinutes() % 30)) : 30));
+                            var reservations = [];
+                            angular.forEach(response, function (r) {
+                                rs = new Date(r.start_time());
+                                re = new Date(r.end_time());
+                                if ((rs < next_working_time) && (re > current_working_time)) {
+                                    reservation = {patron: r.usr(), end_time: re};
+                                    reservation.continuation = (rs < current_working_time) ? true : false;
+                                    reservation.ends_early = (re < next_working_time) ? true : false;
+                                    reservation.starts_late = (rs > current_working_time) ? true : false;
+                                    reservation.start_time = (rs >= current_working_time) ? rs : undefined;
+                                    reservations.push(reservation);
+                                }}) 
+                            $scope.schedule.push({'row': current_working_time.getTime(), 'reservations': reservations});
+                            current_working_time.setTime(next_working_time.getTime());
+                          } while (current_working_time < working_end_time)
+            })}};
+
+            $scope.print_schedule =  function() {
+                print_data = { schedule: $scope.schedule,
+                    show_names: $scope.show_names,
+                    time_format: $scope.time_format,
+                    date_format: $scope.date_format,
+                    date: $scope.date,
+                    barcode: egCore.idl.toHash($scope.resource_list).find(r => {return r.id == $scope.resource}).barcode }
+                return egCore.print.print({
+                   template : 'booking_daily_schedule',
+                   scope: print_data
+                });
+            }
+
+            $scope.get_booking_resources = function() {
+                egCore.pcrud.search('brsrc', {owner: $scope.context_ou.id()}, {}, {atomic: true})
+                .then(function(list) {
+                    $scope.resource_list = list;
+                });
+            };
+
+            $scope.handle_changed_ou = function () {
+                $scope.guess_display_times();
+                $scope.get_booking_resources();
+            }
+
+            $scope.guess_display_times = function() {
+                var selected_day = $scope.date.getDay();
+                egCore.pcrud.retrieve('aouhoo', $scope.context_ou.id()).then(function(hours){
+                    $scope.hours = hours;
+                    selected_day_eg_style = (selected_day + 6) % 7;
+                    o = ($scope.$eval("hours.dow_" + selected_day_eg_style + "_open()")).split(':');
+                    c = ($scope.$eval("hours.dow_" + selected_day_eg_style + "_close()")).split(':');
+                    $scope.startTime = new Date($scope.date.getTime());
+                    $scope.startTime.setSeconds(egCore.date.intervalToSeconds(o[0] + ' hours') + egCore.date.intervalToSeconds(o[1] + ' minutes'));
+                    $scope.endTime = new Date($scope.date.getTime());
+                    $scope.endTime.setSeconds(egCore.date.intervalToSeconds(c[0] + ' hours') + egCore.date.intervalToSeconds(c[1] + ' minutes'));
+                });
+            }
+
+}])
+
 .controller('EmbedBookingCtl', 
        ['$scope','$routeParams','$location','egCore',
 function($scope , $routeParams , $location , egCore) {
@@ -43,4 +179,3 @@ function($scope , $routeParams , $location , egCore) {
     console.log('Loading Booking URL: ' + $scope.booking_url);
 
 }])
-