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 @@ }); + diff --git a/themes/base.less b/themes/base.less index 3cef3d11..19a52e76 100644 --- a/themes/base.less +++ b/themes/base.less @@ -35,10 +35,6 @@ body { } .shift-calendar { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-itmes: stretch; display: flex; flex-direction: row; flex-wrap: nowrap; @@ -48,12 +44,13 @@ body { .lane { background: @table-bg-accent; flex-grow: 1; - min-width: 300px; - width: 300px; - flex-grow: 1; + min-width: 280px; + width: 280px; + flex-shrink: 1; .header { background: @panel-bg; + border-bottom: 1px solid @table-border-color; height: 30px; padding: 5px; } @@ -77,10 +74,11 @@ body { } .lane.time { + border-right: 1px solid @table-border-color; flex-grow: 0; - min-width: 100px; - width: 100px; - flex-grow: 0; + min-width: 50px; + width: 50px; + flex-shrink: 0; } .shift {