Skip to content

Commit

Permalink
Improve room stats page style and features
Browse files Browse the repository at this point in the history
* Template style boost and clean up
* Displays pending bookings in the table
* Allows occupancy stats since ever
  • Loading branch information
OmeGak committed Jul 18, 2014
1 parent d8d87ec commit e6e4ae0
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
${ _('Interior') }
</td>
<td align="left" class="thumbnail">
<a href="${ room.large_photo_url }" nofollow="lightbox" title="${ room.photo_id }">
<a href="${ room.large_photo_url }" nofollow="lightbox">
<img border="1" src="${ room.small_photo_url }" alt="${ _('Room picture') }"/>
</a>
</td>
Expand Down
257 changes: 140 additions & 117 deletions indico/MaKaC/webinterface/tpls/RoomBookingRoomStats.tpl
Original file line number Diff line number Diff line change
@@ -1,142 +1,165 @@
<table cellpadding="0" cellspacing="0" border="0" width="80%">
<tr>
<td class="bottomvtab" width="100%">
<table width="100%" cellpadding="0" cellspacing="0" class="htab" border="0">
<tr>
<td class="maincell">
<span class="formTitle" style="border-bottom-width: 0px">Room</span><br />
<br />
<table width="96%" align="left" border="0">
<!-- LOCATION -->
<tr>
<td width="24%" class="titleUpCellTD"><span class="titleCellFormat">Location</span></td>
<td width="76%">
<table width="100%">
<tr>
<td class="subFieldWidth" align="right" valign="top"><small>Location&nbsp;&nbsp;</small></td>
<td align="left" class="blacktext">${ room.location.name }</td>
</tr>
<tr>
<td class="subFieldWidth" align="right" valign="top"><small>Name&nbsp;&nbsp;</small></td>
<td align="left" class="blacktext">${ room.name }</td>
</tr>
<tr>
<td align="right" valign="top"><small>Site&nbsp;&nbsp;</small></td>
<td align="left" class="blacktext">${ room.site }</td>
</tr>
<tr>
<td align="right" valign="top"><small>Building&nbsp;&nbsp;</small></td>
<td align="left" class="blacktext"><a href="https://maps.cern.ch/mapsearch/mapsearch.htm?no=[${ room.building }]" title="Show on map">${ room.building }</a></td>
</tr>
<tr>
<td align="right" valign="top"><small>Floor&nbsp;&nbsp;</small></td>
<td align="left" class="blacktext">${ room.floor }</td>
</tr>
<tr>
<td align="right" valign="top"><small>Room&nbsp;&nbsp;</small></td>
<td align="left" class="blacktext">${ room.number }</td>
</tr>
</table>
</td>
<td width="20%" align="right" class="thumbnail">
% if room.has_photo:
<a href="${ room.large_photo_url }" nofollow="lightbox" title="${ room.photo_id }">
<img border="1px" height="100" src="${ room.small_photo_url }" alt="${ str( room.photo_id ) }"/>
</a>
% endif
</td>
</tr>
<tr><td>&nbsp;</td></tr>
<tr>
<td width="24%" class="titleUpCellTD"><span class="titleCellFormat">Stats</span></td>
<td width="76%">
<!-- ============== Key Performance Indicators ================= -->
<!-- =========================================================== -->
<a name="kpi"></a>
<table width="80%" align="center" border="0" style="border-left: 1px solid #777777">
<h2 class="page-title">
${ _('Room statistics') }
</h2>

<table>
<tr>
<td colspan="5" class="groupTitle">Key Performance Indicators</td>
</tr>
<tr>
<td class="titleUpCellTD" style="width: 100px;"><span class="titleCellFormat">Average occupancy</span></td>
<td bgcolor="white" valign="top" class="blacktext" style="padding-left: 12px;">
<table>
<tr>
<form action="${ url_for('rooms.roomBooking-roomStats', roomLocation=room.location.name, roomID=room.id) }">
<td bgcolor="white" valign="top" style="padding-left: 12px;">
<select name="period" onChange="this.form.submit();">
% if period=="pastmonth":
<option value="pastmonth" selected> past 30 days
<option value="thisyear"> from beginning of this year
% endif
% if period=="thisyear":
<option value="pastmonth"> past 30 days
<option value="thisyear" selected> from beginning of this year
<td>
% if room.has_photo:
<a href="${ room.large_photo_url }" nofollow="lightbox">
<img border="1px" height="100" src="${ room.small_photo_url }"/>
</a>
% endif
</select>
</td>
</form>
</tr>
<tr>
<td>
<span style="background-color: #C9FFC9; font-weight: bold;">
${ '{0:.02f}%'.format(occupancy) }
</span>
${inlineContextHelp('Average room occupancy over the selected period during working hours (8H30-17H30, Monday-Friday including holidays).' )}
</td>
</tr>
</table>
</td>
</tr>
<tr><td>&nbsp;</td></tr>
<tr>
<td class="titleUpCellTD" style="width: 100px;"><span class="titleCellFormat">Bookings</span></td>
<td bgcolor="white" valign="top" class="blacktext" style="padding-left: 12px;">
</td>
<td>
<table>
<tr>
<td>Total:</td>
<td>
${ room.reservations.count() }
${inlineContextHelp('Total number of bookings including archival, cancelled and rejected.' )}
</td>
</tr>
<tr>
<td align="right" valign="top">
${ ('Location') }
</td>
<td align="left" class="blacktext">
${ room.location.name }
</td>
</tr>
<tr>
<td align="right" valign="top">${ _('Name') }</td>
<td align="left" class="blacktext">${ room.name }</td>
</tr>
<tr>
<td align="right" valign="top">${ _('Site') }</td>
<td align="left" class="blacktext">${ room.site }</td>
</tr>
<tr>
<td align="right" valign="top">${ _('Building') }</td>
<td align="left" class="blacktext">
<a href="https://maps.cern.ch/mapsearch/mapsearch.htm?no=[${ room.building }]" title="Show on map">
${ room.building }
</a>
</td>
</tr>
<tr>
<td align="right" valign="top">${ _('Floor') }</td>
<td align="left" class="blacktext">${ room.floor }</td>
</tr>
<tr>
<td align="right" valign="top">${ _('Room') }</td>
<td align="left" class="blacktext">${ room.number }</td>
</tr>
</table>
<br />
<table>
</td>
</tr>
</table>


<h2 class="group-title">
${ _('Key Performance Indicators') }
</h2>

<div class="i-box-group horz">
<div class="i-box titled">
<div class="i-box-header">
<div class="i-box-title">
${ _('Booking stats') }
</div>
</div>
<div class="i-box-content">
<table class="booking-stats" cellspacing="0">
<tr>
<td style="width: 70px;"></td>
<td style="width: 70px;">Valid</td>
<td style="width: 70px;">Cancelled</td>
<td style="width: 70px;">Rejected</td>
<td></td>
<td>${ _('Valid') }</td>
<td>${ _('Pending') }</td>
<td>${ _('Cancelled') }</td>
<td>${ _('Rejected') }</td>
<td>${ _('Total') }</td>
</tr>
<tr>
<td>${ _('Active') }</td>
<td><span style="background-color: #C9FFC9; font-weight: bold;">${ stats['active']['valid'] }</span></td>
<td class="active-valid">
${ stats['active']['valid'] }
</td>
<td>${ stats['active']['pending'] }</td>
<td>${ stats['active']['cancelled'] }</td>
<td>${ stats['active']['rejected'] }</td>
<td>
${ stats['active']['valid'] + \
stats['active']['cancelled'] + \
stats['active']['rejected'] }
</td>
</tr>
<tr>
<td>${ _('Archived') }</td>
<td>${ stats['archived']['valid'] }</td>
<td>${ stats['archived']['pending'] }</td>
<td>${ stats['archived']['cancelled'] }</td>
<td>${ stats['archived']['rejected'] }</td>
<td>
${ stats['archived']['valid'] + \
stats['archived']['cancelled'] + \
stats['archived']['rejected'] }
</td>
</tr>
<tr>
<td>${ _('Total') }</td>
<td>${ stats['active']['valid'] + stats['archived']['valid'] }</td>
<td>${ stats['active']['pending'] + stats['archived']['pending'] }</td>
<td>${ stats['active']['cancelled'] + stats['archived']['cancelled'] }</td>
<td>${ stats['active']['rejected'] + stats['archived']['rejected'] }</td>
<td class="total-bookings">
${ stats['active']['valid'] + stats['archived']['valid'] + \
stats['active']['pending'] + stats['archived']['pending'] + \
stats['active']['cancelled'] + stats['archived']['cancelled'] + \
stats['active']['rejected'] + stats['archived']['rejected'] }
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</div>
</div>
<div class="i-box titled" style="width:500px">
<div class="i-box-header">
<div class="i-box-title">
${ _('Occupancy') }
</div>
<div class="i-box-buttons toolbar thin">
<div class="group i-selection">
% for key, text in period_options:
<% checked = 'checked' if period == key else '' %>
<input type="radio" id="${ key }" name="period" value="${ key }" ${ checked }>
<label for="${ key }" class="i-button">${ text }</label>
% endfor
</div>
</div>
</div>
<div class="i-box-content">
<table class="occupancy-stats" cellspacing="0">
<tr>
<td class="occupancy-period">
${ _('Average room occupancy in weekdays from 8:30 to 17:30') }
% if period == 'pastmonth':
${ _('over the past 30 days') }.
% elif period == 'thisyear':
${ _('since the beginning of this year') }.
% else:
${ _('since the first booking ever registered') }.
% endif
</td>
<td class="occupancy-value">
${ '{0:.02f}'.format(occupancy) }<small>%</small>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</table>
</div>
</div>
</div>

<script>
$(function(){
$('input[name=period]').on('change', function(e) {
var url_template = ${ url_rule_to_js('rooms.roomBooking-roomStats') | n,j };
location.href = build_url(url_template, {
roomLocation: ${ room.location.name | n, j},
roomID: ${ room.id | n, j },
period: this.value
});
});
});
</script>
45 changes: 45 additions & 0 deletions indico/htdocs/sass/modules/_roombooking.scss
Original file line number Diff line number Diff line change
Expand Up @@ -287,3 +287,48 @@ a.weekday {
.nested-1 {
color: $dark-gray;
}

table.booking-stats {
td {
padding: 5px;
}

td:not(:first-child) {
text-align: right;
}

td:first-child,
tr:first-child td,
tr:last-child td:last-child {
font-weight: bold;
}

tr:last-child td {
border-top: 1px solid $gray;
}

td:last-child {
border-left: 1px solid $gray;
}

.active-valid {
color: $green;
font-weight: bold;
}
}

table.occupancy-stats {
width: 100%;

td.occupancy-period {
font-size: 1.1em;
}

td.occupancy-value {
color: $dark-gray;
font-size: 3em;
font-weight: bold;
padding-left: 25px;
text-align: right;
}
}
2 changes: 2 additions & 0 deletions indico/modules/rb/controllers/user/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ def _checkParams(self):
self._start = self._end - relativedelta(months=1)
elif self._occupancy_period == 'thisyear':
self._start = date(self._end.year, 1, 1)
elif self._occupancy_period == 'sinceever':
self._start = Reservation.find().first().start_date.date()
else:
raise IndicoError('Invalid period specified')

Expand Down
2 changes: 2 additions & 0 deletions indico/modules/rb/models/reservations.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ def __table_args__(cls):

# relationships

# XXX: is this needed anymore?
# attributes = db.relationship(
# 'ReservationAttribute',
# backref='reservation',
Expand All @@ -241,6 +242,7 @@ def __table_args__(cls):
occurrences = db.relationship(
'ReservationOccurrence',
backref='reservation',
# XXX: does this still happen?
# This breaks update() with synchronize_session
# order_by='ReservationOccurrence.start',
cascade='all, delete-orphan',
Expand Down
2 changes: 2 additions & 0 deletions indico/modules/rb/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ def compose_rooms_stats(rooms):
return {
'active': {
'valid': reservations.filter(Reservation.is_valid, ~Reservation.is_archived).count(),
'pending': reservations.filter(Reservation.is_pending, ~Reservation.is_archived).count(),
'cancelled': reservations.filter(Reservation.is_cancelled, ~Reservation.is_archived).count(),
'rejected': reservations.filter(Reservation.is_rejected, ~Reservation.is_archived).count(),
},
'archived': {
'valid': reservations.filter(Reservation.is_valid, Reservation.is_archived).count(),
'pending': reservations.filter(Reservation.is_pending, Reservation.is_archived).count(),
'cancelled': reservations.filter(Reservation.is_cancelled, Reservation.is_archived).count(),
'rejected': reservations.filter(Reservation.is_rejected, Reservation.is_archived).count()
}
Expand Down
5 changes: 5 additions & 0 deletions indico/modules/rb/views/user/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,9 @@ def _setCurrentMenuItem(self):
self._roomSearchOpt.setActive(True)

def _getBody(self, params):
params['period_options'] = [
('pastmonth', _('Past month')),
('thisyear', _('This year')),
('sinceever', _('Since ever'))
]
return WTemplated('RoomBookingRoomStats').getHTML(params)

0 comments on commit e6e4ae0

Please sign in to comment.