diff --git a/includes/view/ShiftCalendarRenderer.php b/includes/view/ShiftCalendarRenderer.php
index 89c1be4c..151a39e0 100644
--- a/includes/view/ShiftCalendarRenderer.php
+++ b/includes/view/ShiftCalendarRenderer.php
@@ -19,6 +19,11 @@ class ShiftCalendarRenderer {
* Distance between two shifts in pixels
*/
const MARGIN = 5;
+
+ /**
+ * Seconds added to the start and end time
+ */
+ const TIME_MARGIN = 1800;
private $lanes;
@@ -71,7 +76,7 @@ class ShiftCalendarRenderer {
}
// If all lanes for this room are busy, create a new lane and add shift to it
if ($shift_added == false) {
- $newLane = new ShiftCalendarLane("", $this->getFirstBlockStartTime(), $this->getBlocksPerSlot());
+ $newLane = new ShiftCalendarLane($header, $this->getFirstBlockStartTime(), $this->getBlocksPerSlot());
if (! $newLane->addShift($shift)) {
engelsystem_error("Unable to add shift to new lane.");
}
@@ -170,7 +175,7 @@ class ShiftCalendarRenderer {
return div('tick day');
}
return div('tick day', [
- date('Y-m-dH:i', $time)
+ date('m-dH:i', $time)
]);
} elseif ($time % (60 * 60) == 0) {
if (! $label) {
@@ -206,7 +211,7 @@ class ShiftCalendarRenderer {
$start_time = $shift['start'];
}
}
- return ShiftCalendarRenderer::SECONDS_PER_ROW * floor(($start_time - 60 * 60) / ShiftCalendarRenderer::SECONDS_PER_ROW);
+ return ShiftCalendarRenderer::SECONDS_PER_ROW * floor(($start_time - ShiftCalendarRenderer::TIME_MARGIN) / ShiftCalendarRenderer::SECONDS_PER_ROW);
}
private function calcLastBlockEndTime($shifts) {
@@ -216,7 +221,7 @@ class ShiftCalendarRenderer {
$end_time = $shift['end'];
}
}
- return ShiftCalendarRenderer::SECONDS_PER_ROW * ceil(($end_time + 60 * 60) / ShiftCalendarRenderer::SECONDS_PER_ROW);
+ return ShiftCalendarRenderer::SECONDS_PER_ROW * ceil(($end_time + ShiftCalendarRenderer::TIME_MARGIN) / ShiftCalendarRenderer::SECONDS_PER_ROW);
}
private function calcBlocksPerSlot() {
diff --git a/includes/view/Shifts_view.php b/includes/view/Shifts_view.php
index 7ad580f4..629f6b2a 100644
--- a/includes/view/Shifts_view.php
+++ b/includes/view/Shifts_view.php
@@ -50,7 +50,7 @@ function Shift_view($shift, $shifttype, $room, $angeltypes_source, $user_shifts,
return page_with_title($shift['name'] . ' %c', [
msg(),
- Shift_collides($shift, $user_shifts) ? info(_('This shift collides with one of your shifts.'), true) : '',
+ $shift_signup_state->getState() == ShiftSignupState::COLLIDES ? info(_('This shift collides with one of your shifts.'), true) : '',
$shift_signup_state->getState() == ShiftSignupState::SIGNED_UP ? info(_('You are signed up for this shift.'), true) : '',
($shift_admin || $admin_shifttypes || $admin_rooms) ? buttons([
$shift_admin ? button(shift_edit_link($shift), glyph('pencil') . _('edit')) : '',
diff --git a/includes/view/User_view.php b/includes/view/User_view.php
index 6cd48899..09509c3d 100644
--- a/includes/view/User_view.php
+++ b/includes/view/User_view.php
@@ -297,6 +297,20 @@ function User_view($user_source, $admin_user_privilege, $freeloader, $user_angel
return page_with_title(' ' . htmlspecialchars($user_source['Nick']) . ' ' . $user_name . '', [
msg(),
+ div('row space-top', [
+ div('col-md-12', [
+ buttons([
+ $admin_user_privilege ? button(page_link_to('admin_user') . '&id=' . $user_source['UID'], glyph("edit") . _("edit")) : '',
+ $admin_user_privilege ? button(user_driver_license_edit_link($user_source), glyph("road") . _("driving license")) : '',
+ ($admin_user_privilege && ! $user_source['Gekommen']) ? button(page_link_to('admin_arrive') . '&arrived=' . $user_source['UID'], _("arrived")) : '',
+ $admin_user_privilege ? button(page_link_to('users') . '&action=edit_vouchers&user_id=' . $user_source['UID'], glyph('cutlery') . _('Edit vouchers')) : '',
+ $its_me ? button(page_link_to('user_settings'), glyph('list-alt') . _("Settings")) : '',
+ $its_me ? button(page_link_to('ical') . '&key=' . $user_source['api_key'], glyph('calendar') . _("iCal Export")) : '',
+ $its_me ? button(page_link_to('shifts_json_export') . '&key=' . $user_source['api_key'], glyph('export') . _("JSON Export")) : '',
+ $its_me ? button(page_link_to('user_myshifts') . '&reset', glyph('repeat') . _('Reset API key')) : ''
+ ])
+ ])
+ ]),
div('row', [
div('col-md-3', [
'
',
@@ -322,20 +336,6 @@ function User_view($user_source, $admin_user_privilege, $freeloader, $user_angel
User_groups_render($user_groups)
])
]),
- div('row space-top', [
- div('col-md-12', [
- buttons([
- $admin_user_privilege ? button(page_link_to('admin_user') . '&id=' . $user_source['UID'], glyph("edit") . _("edit")) : '',
- $admin_user_privilege ? button(user_driver_license_edit_link($user_source), glyph("road") . _("driving license")) : '',
- ($admin_user_privilege && ! $user_source['Gekommen']) ? button(page_link_to('admin_arrive') . '&arrived=' . $user_source['UID'], _("arrived")) : '',
- $admin_user_privilege ? button(page_link_to('users') . '&action=edit_vouchers&user_id=' . $user_source['UID'], glyph('cutlery') . _('Edit vouchers')) : '',
- $its_me ? button(page_link_to('user_settings'), glyph('list-alt') . _("Settings")) : '',
- $its_me ? button(page_link_to('ical') . '&key=' . $user_source['api_key'], glyph('calendar') . _("iCal Export")) : '',
- $its_me ? button(page_link_to('shifts_json_export') . '&key=' . $user_source['api_key'], glyph('export') . _("JSON Export")) : '',
- $its_me ? button(page_link_to('user_myshifts') . '&reset', glyph('repeat') . _('Reset API key')) : ''
- ])
- ])
- ]),
($its_me || $admin_user_privilege) ? '' . _("Shifts") . '
' : '',
($its_me || $admin_user_privilege) ? table([
'date' => _("Day"),
diff --git a/public/css/theme0.css b/public/css/theme0.css
index 02bdeb7f..bc8e639f 100644
--- a/public/css/theme0.css
+++ b/public/css/theme0.css
@@ -6757,12 +6757,14 @@ body {
}
.shift-calendar .lane {
background: #f9f9f9;
- min-width: 300px;
- width: 300px;
flex-grow: 1;
+ min-width: 280px;
+ width: 280px;
+ flex-shrink: 1;
}
.shift-calendar .lane .header {
background: #ffffff;
+ border-bottom: 1px solid #dddddd;
height: 30px;
padding: 5px;
}
@@ -6781,9 +6783,11 @@ body {
padding-left: 5px;
}
.shift-calendar .lane.time {
- min-width: 100px;
- width: 100px;
+ border-right: 1px solid #dddddd;
flex-grow: 0;
+ min-width: 50px;
+ width: 50px;
+ flex-shrink: 0;
}
.shift-calendar .shift {
margin: 0 5px 5px 0;
diff --git a/public/css/theme1.css b/public/css/theme1.css
index d9cf7b73..39f8e7a6 100644
--- a/public/css/theme1.css
+++ b/public/css/theme1.css
@@ -6780,12 +6780,14 @@ body {
}
.shift-calendar .lane {
background: #080808;
- min-width: 300px;
- width: 300px;
flex-grow: 1;
+ min-width: 280px;
+ width: 280px;
+ flex-shrink: 1;
}
.shift-calendar .lane .header {
background: #222222;
+ border-bottom: 1px solid #282828;
height: 30px;
padding: 5px;
}
@@ -6804,9 +6806,11 @@ body {
padding-left: 5px;
}
.shift-calendar .lane.time {
- min-width: 100px;
- width: 100px;
+ border-right: 1px solid #282828;
flex-grow: 0;
+ min-width: 50px;
+ width: 50px;
+ flex-shrink: 0;
}
.shift-calendar .shift {
margin: 0 5px 5px 0;
diff --git a/public/css/theme2.css b/public/css/theme2.css
index 4b6b1d67..4e13c1bc 100644
--- a/public/css/theme2.css
+++ b/public/css/theme2.css
@@ -6757,12 +6757,14 @@ body {
}
.shift-calendar .lane {
background: #f9f9f9;
- min-width: 300px;
- width: 300px;
flex-grow: 1;
+ min-width: 280px;
+ width: 280px;
+ flex-shrink: 1;
}
.shift-calendar .lane .header {
background: #ffffff;
+ border-bottom: 1px solid #dddddd;
height: 30px;
padding: 5px;
}
@@ -6781,9 +6783,11 @@ body {
padding-left: 5px;
}
.shift-calendar .lane.time {
- min-width: 100px;
- width: 100px;
+ border-right: 1px solid #dddddd;
flex-grow: 0;
+ min-width: 50px;
+ width: 50px;
+ flex-shrink: 0;
}
.shift-calendar .shift {
margin: 0 5px 5px 0;
diff --git a/public/css/theme3.css b/public/css/theme3.css
index dd65c030..c20c1059 100644
--- a/public/css/theme3.css
+++ b/public/css/theme3.css
@@ -6766,12 +6766,14 @@ body {
}
.shift-calendar .lane {
background: #f9f9f9;
- min-width: 300px;
- width: 300px;
flex-grow: 1;
+ min-width: 280px;
+ width: 280px;
+ flex-shrink: 1;
}
.shift-calendar .lane .header {
background: #ffffff;
+ border-bottom: 1px solid #dddddd;
height: 30px;
padding: 5px;
}
@@ -6790,9 +6792,11 @@ body {
padding-left: 5px;
}
.shift-calendar .lane.time {
- min-width: 100px;
- width: 100px;
+ border-right: 1px solid #dddddd;
flex-grow: 0;
+ min-width: 50px;
+ width: 50px;
+ flex-shrink: 0;
}
.shift-calendar .shift {
margin: 0 5px 5px 0;
diff --git a/public/js/shift-calendar.js b/public/js/shift-calendar.js
new file mode 100644
index 00000000..357b69ff
--- /dev/null
+++ b/public/js/shift-calendar.js
@@ -0,0 +1,30 @@
+/**
+ * Enables the fixed headers and time lane for the shift-calendar.
+ */
+$(document).ready(
+ function() {
+ var time_lanes = $(".shift-calendar .time");
+ var headers = $(".shift-calendar .header");
+ var top_reference = $(".container-fluid .row");
+ var top = headers.offset().top;
+ var left = 15;
+ time_lanes.css({
+ "position" : "relative",
+ "z-index" : 1000
+ });
+ headers.css({
+ "position" : "relative",
+ "z-index" : 900
+ });
+ $(window).scroll(
+ function() {
+ time_lanes.css({
+ "left" : Math.max(0, $(window).scrollLeft() - left) + "px"
+ });
+ headers.css({
+ "top" : Math.max(0, $(window).scrollTop() - top
+ + top_reference.offset().top)
+ + "px"
+ });
+ });
+ });
\ No newline at end of file
diff --git a/templates/layout.html b/templates/layout.html
index a311be67..f6ae0273 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -48,5 +48,6 @@
});
+