add shift calendar to angeltype view

This commit is contained in:
msquare 2017-11-24 12:01:19 +01:00
parent d8476f244d
commit 928e707015
11 changed files with 1098 additions and 889 deletions

View File

@ -1,5 +1,7 @@
<?php <?php
use Engelsystem\ShiftsFilter;
use Engelsystem\ShiftsFilterRenderer;
/** /**
* Text for Angeltype related links. * Text for Angeltype related links.
* *
@ -182,6 +184,14 @@ function angeltype_controller()
$user_angeltype = UserAngelType_by_User_and_AngelType($user, $angeltype); $user_angeltype = UserAngelType_by_User_and_AngelType($user, $angeltype);
$user_driver_license = UserDriverLicense($user['UID']); $user_driver_license = UserDriverLicense($user['UID']);
$members = Users_by_angeltype($angeltype); $members = Users_by_angeltype($angeltype);
$days = angeltype_controller_shiftsFilterDays($angeltype);
$shiftsFilter = angeltype_controller_shiftsFilter($angeltype, $days);
$shiftsFilterRenderer = new ShiftsFilterRenderer($shiftsFilter);
$shiftsFilterRenderer->enableDaySelection($days);
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
return [ return [
sprintf(_('Team %s'), $angeltype['name']), sprintf(_('Team %s'), $angeltype['name']),
@ -193,11 +203,60 @@ function angeltype_controller()
in_array('admin_angel_types', $privileges), in_array('admin_angel_types', $privileges),
$user_angeltype['supporter'], $user_angeltype['supporter'],
$user_driver_license, $user_driver_license,
$user $user,
$shiftsFilterRenderer,
$shiftCalendarRenderer
) )
]; ];
} }
/**
* On which days do shifts for this angeltype occur? Needed for shiftCalendar.
*
* @param Angeltype $angeltype
* @return array
*/
function angeltype_controller_shiftsFilterDays($angeltype) {
$all_shifts = Shifts_by_angeltype($angeltype);
$days = [];
foreach ($all_shifts as $shift) {
$day = date('Y-m-d', $shift['start']);
if (!in_array($day, $days)) {
$days[] = $day;
}
}
return $days;
}
/**
* Sets up the shift filter for the angeltype.
*
* @param Angeltype $angeltype
* @param array $days
* @return ShiftsFilter
*/
function angeltype_controller_shiftsFilter($angeltype, $days) {
global $privileges;
$request = request();
$shiftsFilter = new ShiftsFilter(
in_array('user_shifts_admin', $privileges),
Room_ids(),
[$angeltype['id']]
);
$selected_day = date('Y-m-d');
if (!empty($days)) {
$selected_day = $days[0];
}
if ($request->has('shifts_filter_day')) {
$selected_day = $request->input('shifts_filter_day');
}
$shiftsFilter->setStartTime(parse_date('Y-m-d H:i', $selected_day . ' 00:00'));
$shiftsFilter->setEndTime(parse_date('Y-m-d H:i', $selected_day . ' 23:59'));
return $shiftsFilter;
}
/** /**
* View a list of all angeltypes. * View a list of all angeltypes.
* *

View File

@ -13,6 +13,17 @@ function Rooms($show_all = false)
return DB::select('SELECT * FROM `Room`' . ($show_all ? '' : ' WHERE `show`=\'Y\'') . ' ORDER BY `Name`'); return DB::select('SELECT * FROM `Room`' . ($show_all ? '' : ' WHERE `show`=\'Y\'') . ' ORDER BY `Name`');
} }
/**
* Returns Room id array
*
* @return array
*/
function Room_ids()
{
$result = DB::select('SELECT `RID` FROM `Room`');
return select_array($result, 'RID', 'RID');
}
/** /**
* Delete a room * Delete a room
* *

View File

@ -4,6 +4,29 @@ use Engelsystem\Database\DB;
use Engelsystem\ShiftsFilter; use Engelsystem\ShiftsFilter;
use Engelsystem\ShiftSignupState; use Engelsystem\ShiftSignupState;
/**
* @param array $angeltype
* @return array
*/
function Shifts_by_angeltype($angeltype) {
return DB::select('
SELECT DISTINCT `Shifts`.* FROM `Shifts`
JOIN `NeededAngelTypes` ON `NeededAngelTypes`.`shift_id` = `Shifts`.`SID`
WHERE `NeededAngelTypes`.`angel_type_id` = ?
AND `NeededAngelTypes`.`count` > 0
AND `Shifts`.`PSID` IS NULL
UNION
SELECT DISTINCT `Shifts`.* FROM `Shifts`
JOIN `NeededAngelTypes` ON `NeededAngelTypes`.`room_id` = `Shifts`.`RID`
WHERE `NeededAngelTypes`.`angel_type_id` = ?
AND `NeededAngelTypes`.`count` > 0
AND NOT `Shifts`.`PSID` IS NULL
', [$angeltype['id'], $angeltype['id']]);
}
/** /**
* @param array $room * @param array $room
* @return array * @return array
@ -24,7 +47,7 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
FROM `Shifts` FROM `Shifts`
JOIN `Room` USING (`RID`) JOIN `Room` USING (`RID`)
JOIN `ShiftTypes` ON `ShiftTypes`.`id` = `Shifts`.`shifttype_id` JOIN `ShiftTypes` ON `ShiftTypes`.`id` = `Shifts`.`shifttype_id`
JOIN `NeededAngelTypes` ON `NeededAngelTypes`.`shift_id`=`Shifts`.`SID` JOIN `NeededAngelTypes` ON `NeededAngelTypes`.`shift_id` = `Shifts`.`SID`
WHERE `Shifts`.`RID` IN (' . implode(',', $shiftsFilter->getRooms()) . ') WHERE `Shifts`.`RID` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
AND `start` BETWEEN ? AND ? AND `start` BETWEEN ? AND ?
AND `NeededAngelTypes`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ') AND `NeededAngelTypes`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')

View File

@ -1,5 +1,31 @@
<?php <?php
/**
* Renders tabs from the array. Array key is tab name, array value is tab content.
*
* @param array $tabs
* @return string HTML
*/
function tabs($tabs)
{
$tab_header = [];
$tab_content = [];
foreach($tabs as $header => $content) {
$class = '';
if(count($tab_header) == 0) {
$class = 'active';
}
$tab_header[] = '<li role="presentation" class="' . $class . '">
<a href="#' . $header . '" aria-controls="' . $header . '" role="tab" data-toggle="tab">'
. $header . '</a></li>';
$tab_content[] = '<div role="tabpanel" class="tab-pane ' . $class . '" id="' . $header . '">' . $content . '</div>';
}
return div('', [
'<ul class="nav nav-tabs" role="tablist">' . join($tab_header) . '</ul>',
'<div class="tab-content">' . join($tab_content) . '</div>'
]);
}
/** /**
* Display muted (grey) text. * Display muted (grey) text.
* *

View File

@ -1,5 +1,7 @@
<?php <?php
use Engelsystem\ShiftsFilterRenderer;
use Engelsystem\ShiftCalendarRenderer;
/** /**
* AngelTypes * AngelTypes
*/ */
@ -320,36 +322,86 @@ function AngelType_view(
$admin_angeltypes, $admin_angeltypes,
$supporter, $supporter,
$user_driver_license, $user_driver_license,
$user $user,
ShiftsFilterRenderer $shiftsFilterRenderer,
ShiftCalendarRenderer $shiftCalendarRenderer
) { ) {
$page = [ return page_with_title(sprintf(_('Team %s'), $angeltype['name']), [
AngelType_view_buttons($angeltype, $user_angeltype, $admin_angeltypes, $supporter, $user_driver_license, $user), AngelType_view_buttons($angeltype, $user_angeltype, $admin_angeltypes, $supporter, $user_driver_license, $user),
msg() msg(),
]; tabs([
_('Info') => AngelType_view_info(
$angeltype,
$members,
$admin_user_angeltypes,
$admin_angeltypes,
$supporter
),
_('Shifts') => AngelType_view_shifts(
$angeltype,
$shiftsFilterRenderer,
$shiftCalendarRenderer
)
])
]);
}
/**
* @param Angeltype $angeltype
* @param ShiftsFilterRenderer $shiftsFilterRenderer
* @param ShiftCalendarRenderer $shiftCalendarRenderer
* @return string HTML
*/
function AngelType_view_shifts($angeltype, $shiftsFilterRenderer, $shiftCalendarRenderer)
{
$shifts = $shiftsFilterRenderer->render(page_link_to('angeltypes', [
'action' => 'view',
'angeltype_id' => $angeltype['id']
]));
$shifts .= $shiftCalendarRenderer->render();
return div('first', $shifts);
}
/**
* @param Angeltype $angeltype
* @param array $members
* @param bool $admin_user_angeltypes
* @param bool $admin_angeltypes
* @param bool $supporter
* @return string HTML
*/
function AngelType_view_info(
$angeltype,
$members,
$admin_user_angeltypes,
$admin_angeltypes,
$supporter
) {
$info = [];
if(AngelType_has_contact_info($angeltype)) { if(AngelType_has_contact_info($angeltype)) {
$page[] = AngelTypes_render_contact_info($angeltype); $info[] = AngelTypes_render_contact_info($angeltype);
} }
$page[] = '<h3>' . _('Description') . '</h3>'; $info[] = '<h3>' . _('Description') . '</h3>';
$parsedown = new Parsedown(); $parsedown = new Parsedown();
if ($angeltype['description'] != '') { if ($angeltype['description'] != '') {
$page[] = '<div class="well">' . $parsedown->parse($angeltype['description']) . '</div>'; $info[] = '<div class="well">' . $parsedown->parse($angeltype['description']) . '</div>';
} }
list($supporters, $members_confirmed, $members_unconfirmed) = AngelType_view_members( list($supporters, $members_confirmed, $members_unconfirmed) = AngelType_view_members(
$angeltype, $angeltype,
$members, $members,
$admin_user_angeltypes, $admin_user_angeltypes,
$admin_angeltypes $admin_angeltypes
); );
$table_headers = AngelType_view_table_headers($angeltype, $supporter, $admin_angeltypes); $table_headers = AngelType_view_table_headers($angeltype, $supporter, $admin_angeltypes);
if (count($supporters) > 0) { if (count($supporters) > 0) {
$page[] = '<h3>' . _('supporters') . '</h3>'; $info[] = '<h3>' . _('supporters') . '</h3>';
$page[] = table($table_headers, $supporters); $info[] = table($table_headers, $supporters);
} }
if (count($members_confirmed) > 0) { if (count($members_confirmed) > 0) {
$members_confirmed[] = [ $members_confirmed[] = [
'Nick' => _('Sum'), 'Nick' => _('Sum'),
@ -357,7 +409,7 @@ function AngelType_view(
'actions' => '' 'actions' => ''
]; ];
} }
if (count($members_unconfirmed) > 0) { if (count($members_unconfirmed) > 0) {
$members_unconfirmed[] = [ $members_unconfirmed[] = [
'Nick' => _('Sum'), 'Nick' => _('Sum'),
@ -365,40 +417,40 @@ function AngelType_view(
'actions' => '' 'actions' => ''
]; ];
} }
$page[] = '<h3>' . _('Members') . '</h3>'; $info[] = '<h3>' . _('Members') . '</h3>';
if ($admin_user_angeltypes) { if ($admin_user_angeltypes) {
$page[] = buttons([ $info[] = buttons([
button( button(
page_link_to( page_link_to(
'user_angeltypes', 'user_angeltypes',
['action' => 'add', 'angeltype_id' => $angeltype['id']] ['action' => 'add', 'angeltype_id' => $angeltype['id']]
), ),
_('Add'), _('Add'),
'add' 'add'
) )
]); ]);
} }
$page[] = table($table_headers, $members_confirmed); $info[] = table($table_headers, $members_confirmed);
if ($admin_user_angeltypes && $angeltype['restricted'] && count($members_unconfirmed) > 0) { if ($admin_user_angeltypes && $angeltype['restricted'] && count($members_unconfirmed) > 0) {
$page[] = '<h3>' . _('Unconfirmed') . '</h3>'; $info[] = '<h3>' . _('Unconfirmed') . '</h3>';
$page[] = buttons([ $info[] = buttons([
button( button(
page_link_to('user_angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype['id']]), page_link_to('user_angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype['id']]),
_('confirm all'), _('confirm all'),
'ok' 'ok'
), ),
button( button(
page_link_to('user_angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype['id']]), page_link_to('user_angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype['id']]),
_('deny all'), _('deny all'),
'cancel' 'cancel'
) )
]); ]);
$page[] = table($table_headers, $members_unconfirmed); $info[] = table($table_headers, $members_unconfirmed);
} }
return page_with_title(sprintf(_('Team %s'), $angeltype['name']), $page); return join($info);
} }
/** /**
@ -407,7 +459,8 @@ function AngelType_view(
* @param Anteltype $angeltype * @param Anteltype $angeltype
* @return string HTML * @return string HTML
*/ */
function AngelTypes_render_contact_info($angeltype) { function AngelTypes_render_contact_info($angeltype)
{
return heading(_('Contact'), 3) . description([ return heading(_('Contact'), 3) . description([
_('Name') => $angeltype['contact_name'], _('Name') => $angeltype['contact_name'],
_('DECT') => $angeltype['contact_dect'], _('DECT') => $angeltype['contact_dect'],

View File

@ -19,7 +19,10 @@ function Room_view($room, ShiftsFilterRenderer $shiftsFilterRenderer, ShiftCalen
} }
return page_with_title(glyph('map-marker') . $room['Name'], [ return page_with_title(glyph('map-marker') . $room['Name'], [
$shiftsFilterRenderer->render($room), $shiftsFilterRenderer->render(page_link_to('rooms', [
'action' => 'view',
'room_id' => $room['RID']
])),
$assignNotice, $assignNotice,
$shiftCalendarRenderer->render() $shiftCalendarRenderer->render()
]); ]);

View File

@ -143,7 +143,7 @@ class ShiftCalendarRenderer
public function render() public function render()
{ {
if (count($this->lanes) == 0) { if (count($this->lanes) == 0) {
return ''; return info(_('No shifts found.'), true);
} }
return div('shift-calendar', [ return div('shift-calendar', [
$this->renderTimeLane(), $this->renderTimeLane(),

View File

@ -39,21 +39,17 @@ class ShiftsFilterRenderer
/** /**
* Renders the filter. * Renders the filter.
* *
* @param array $room * @param string $page_link Link pointing to the actual page.
* @return string Generated HTML * @return string Generated HTML
*/ */
public function render($room) public function render($page_link)
{ {
$toolbar = []; $toolbar = [];
if ($this->daySelectionEnabled && !empty($this->days)) { if ($this->daySelectionEnabled && !empty($this->days)) {
$selected_day = date('Y-m-d', $this->shiftsFilter->getStartTime()); $selected_day = date('Y-m-d', $this->shiftsFilter->getStartTime());
$day_dropdown_items = []; $day_dropdown_items = [];
foreach ($this->days as $day) { foreach ($this->days as $day) {
$link = page_link_to('rooms', [ $link = $page_link . '&shifts_filter_day=' . $day;
'action' => 'view',
'room_id' => $room['RID'],
'shifts_filter_day' => $day,
]);
$day_dropdown_items[] = toolbar_item_link($link, '', $day); $day_dropdown_items[] = toolbar_item_link($link, '', $day);
} }
$toolbar[] = toolbar_dropdown('', $selected_day, $day_dropdown_items, 'active'); $toolbar[] = toolbar_dropdown('', $selected_day, $day_dropdown_items, 'active');

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,6 @@ $(document).ready(function () {
var timeLanes = $(".shift-calendar .time"); var timeLanes = $(".shift-calendar .time");
var headers = $(".shift-calendar .header"); var headers = $(".shift-calendar .header");
var topReference = $(".container-fluid .row"); var topReference = $(".container-fluid .row");
var top = headers.offset().top;
var left = 15;
timeLanes.css({ timeLanes.css({
"position": "relative", "position": "relative",
"z-index": 999 "z-index": 999
@ -18,6 +16,8 @@ $(document).ready(function () {
}); });
$(window).scroll( $(window).scroll(
function () { function () {
var top = headers.parent().offset().top;
var left = 15;
timeLanes.css({ timeLanes.css({
"left": Math.max(0, $(window).scrollLeft() - left) + "px" "left": Math.max(0, $(window).scrollLeft() - left) + "px"
}); });