Rename rooms to locations

This commit is contained in:
Igor Scheller 2023-10-15 19:25:55 +02:00 committed by msquare
parent a31534d9b7
commit 7f6e1ff18e
56 changed files with 642 additions and 556 deletions

View File

@ -163,14 +163,14 @@ $route->addGroup(
}
);
// Rooms
// Locations
$route->addGroup(
'/rooms',
'/locations',
function (RouteCollector $route): void {
$route->get('', 'Admin\\RoomsController@index');
$route->post('', 'Admin\\RoomsController@delete');
$route->get('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@edit');
$route->post('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@save');
$route->get('', 'Admin\\LocationsController@index');
$route->post('', 'Admin\\LocationsController@delete');
$route->get('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@edit');
$route->post('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@save');
}
);

View File

@ -4,13 +4,13 @@ declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Illuminate\Database\Eloquent\Factories\Factory;
class RoomFactory extends Factory
class LocationFactory extends Factory
{
/** @var string */
protected $model = Room::class; // phpcs:ignore
protected $model = Location::class; // phpcs:ignore
public function definition(): array
{

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Factories\Factory;
@ -17,11 +17,11 @@ class NeededAngelTypeFactory extends Factory
public function definition(): array
{
$forRoom = $this->faker->boolean();
$forLocation = $this->faker->boolean();
return [
'room_id' => $forRoom ? Room::factory() : null,
'shift_id' => $forRoom ? null : Shift::factory(),
'location_id' => $forLocation ? Location::factory() : null,
'shift_id' => $forLocation ? null : Shift::factory(),
'angel_type_id' => AngelType::factory(),
'count' => $this->faker->numberBetween(1, 5),
];

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftType;
use Engelsystem\Models\User\User;
@ -25,7 +25,7 @@ class ShiftFactory extends Factory
'start' => $start,
'end' => $this->faker->dateTimeInInterval($start, '+3 hours'),
'shift_type_id' => ShiftType::factory(),
'room_id' => Room::factory(),
'location_id' => Location::factory(),
'transaction_id' => $this->faker->optional()->uuid(),
'created_by' => User::factory(),
'updated_by' => $this->faker->optional(.3)->boolean() ? User::factory() : null,

View File

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class RenameRoomsToLocations extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->rename('rooms', 'locations');
$this->schema->table('shifts', function (Blueprint $table): void {
$table->renameColumn('room_id', 'location_id');
});
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
$table->renameColumn('room_id', 'location_id');
});
$db = $this->schema->getConnection();
$db->table('privileges')->where('name', 'admin_rooms')->update([
'name' => 'admin_locations',
'description' => 'Manage locations',
]);
$db->table('privileges')->where('name', 'view_rooms')->update([
'name' => 'view_locations',
'description' => 'User can view locations',
]);
$db->table('privileges')->where('name', 'schedule.import')->update([
'description' => 'Import locations and shifts from schedule.xml',
]);
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->rename('locations', 'rooms');
$this->schema->table('shifts', function (Blueprint $table): void {
$table->renameColumn('location_id', 'room_id');
});
$this->schema->table('needed_angel_types', function (Blueprint $table): void {
$table->renameColumn('location_id', 'room_id');
});
$db = $this->schema->getConnection();
$db->table('privileges')->where('name', 'admin_locations')->update([
'name' => 'admin_rooms',
'description' => 'Räume administrieren',
]);
$db->table('privileges')->where('name', 'view_locations')->update([
'name' => 'view_rooms',
'description' => 'User can view rooms',
]);
$db->table('privileges')->where('name', 'schedule.import')->update([
'description' => 'Import rooms and shifts from schedule.xml',
]);
}
}

View File

@ -2,7 +2,7 @@
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftsFilter;
use Engelsystem\ShiftsFilterRenderer;
@ -243,13 +243,13 @@ function angeltype_controller_shiftsFilterDays(AngelType $angeltype)
function angeltype_controller_shiftsFilter(AngelType $angeltype, $days)
{
$request = request();
$roomIds = Room::query()
$locationIds = Location::query()
->select('id')
->pluck('id')
->toArray();
$shiftsFilter = new ShiftsFilter(
auth()->can('user_shifts_admin'),
$roomIds,
$locationIds,
[$angeltype->id]
);
$selected_day = date('Y-m-d');

View File

@ -1,29 +1,29 @@
<?php
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\ShiftsFilter;
use Engelsystem\ShiftsFilterRenderer;
/**
* Room controllers for managing everything room related.
* Location controllers for managing everything location related.
*/
/**
* View a room with its shifts.
* View a location with its shifts.
*
* @return array
*/
function room_controller(): array
function location_controller(): array
{
if (!auth()->can('view_rooms')) {
if (!auth()->can('view_locations')) {
throw_redirect(page_link_to());
}
$request = request();
$room = load_room();
$location = load_location();
$all_shifts = $room->shifts->sortBy('start');
$all_shifts = $location->shifts->sortBy('start');
$days = [];
foreach ($all_shifts as $shift) {
$day = $shift->start->format('Y-m-d');
@ -34,7 +34,7 @@ function room_controller(): array
$shiftsFilter = new ShiftsFilter(
true,
[$room->id],
[$location->id],
AngelType::query()->get('id')->pluck('id')->toArray()
);
$selected_day = date('Y-m-d');
@ -53,17 +53,17 @@ function room_controller(): array
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
return [
$room->name,
Room_view($room, $shiftsFilterRenderer, $shiftCalendarRenderer),
$location->name,
location_view($location, $shiftsFilterRenderer, $shiftCalendarRenderer),
];
}
/**
* Dispatch different room actions.
* Dispatch different location actions.
*
* @return array
*/
function rooms_controller(): array
function locations_controller(): array
{
$request = request();
$action = $request->input('action');
@ -72,36 +72,36 @@ function rooms_controller(): array
}
return match ($action) {
'view' => room_controller(),
'list' => throw_redirect(page_link_to('admin/rooms')),
default => throw_redirect(page_link_to('admin/rooms')),
'view' => location_controller(),
'list' => throw_redirect(page_link_to('admin/locations')),
default => throw_redirect(page_link_to('admin/locations')),
};
}
/**
* @param Room $room
* @param Location $location
* @return string
*/
function room_link(Room $room)
function location_link(Location $location)
{
return page_link_to('rooms', ['action' => 'view', 'room_id' => $room->id]);
return page_link_to('locations', ['action' => 'view', 'location_id' => $location->id]);
}
/**
* Loads room by request param room_id
* Loads location by request param location_id
*
* @return Room
* @return Location
*/
function load_room()
function load_location()
{
if (!test_request_int('room_id')) {
if (!test_request_int('location_id')) {
throw_redirect(page_link_to());
}
$room = Room::find(request()->input('room_id'));
if (!$room) {
$location = Location::find(request()->input('location_id'));
if (!$location) {
throw_redirect(page_link_to());
}
return $room;
return $location;
}

View File

@ -1,8 +1,8 @@
<?php
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Location;
use Engelsystem\Models\News;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\ShiftsFilter;
@ -15,22 +15,22 @@ function public_dashboard_controller()
{
$filter = null;
if (request()->get('filtered')) {
$requestRooms = check_request_int_array('rooms');
$requestLocations = check_request_int_array('locations');
$requestAngelTypes = check_request_int_array('types');
if (!$requestRooms && !$requestAngelTypes) {
if (!$requestLocations && !$requestAngelTypes) {
$sessionFilter = collect(session()->get('shifts-filter', []));
$requestRooms = $sessionFilter->get('rooms', []);
$requestLocations = $sessionFilter->get('locations', []);
$requestAngelTypes = $sessionFilter->get('types', []);
}
$angelTypes = collect(unrestricted_angeltypes());
$rooms = $requestRooms ?: Room::orderBy('name')->get()->pluck('id')->toArray();
$locations = $requestLocations ?: Location::orderBy('name')->get()->pluck('id')->toArray();
$angelTypes = $requestAngelTypes ?: $angelTypes->pluck('id')->toArray();
$filterValues = [
'userShiftsAdmin' => false,
'filled' => [],
'rooms' => $rooms,
'locations' => $locations,
'types' => $angelTypes,
'startTime' => null,
'endTime' => null,
@ -87,7 +87,7 @@ function public_dashboard_controller_free_shift(Shift $shift, ShiftsFilter $filt
'duration' => round(($shift->end->timestamp - $shift->start->timestamp) / 3600),
'shifttype_name' => $shift->shiftType->name,
'title' => $shift->title,
'room_name' => $shift->room->name,
'location_name' => $shift->location->name,
'needed_angels' => public_dashboard_needed_angels($shift->neededAngels, $filter),
];

View File

@ -120,10 +120,10 @@ function shift_entry_create_controller_admin(Shift $shift, ?AngelType $angeltype
}
$angeltypes_select = $angeltypes->pluck('name', 'id')->toArray();
$room = $shift->room;
$location = $shift->location;
return [
ShiftEntry_create_title(),
ShiftEntry_create_view_admin($shift, $room, $angeltype, $angeltypes_select, $signup_user, $users_select),
ShiftEntry_create_view_admin($shift, $location, $angeltype, $angeltypes_select, $signup_user, $users_select),
];
}
@ -167,10 +167,10 @@ function shift_entry_create_controller_supporter(Shift $shift, AngelType $angelt
$users_select[$u->id] = $u->displayName;
}
$room = $shift->room;
$location = $shift->location;
return [
ShiftEntry_create_title(),
ShiftEntry_create_view_supporter($shift, $room, $angeltype, $signup_user, $users_select),
ShiftEntry_create_view_supporter($shift, $location, $angeltype, $signup_user, $users_select),
];
}
@ -250,10 +250,10 @@ function shift_entry_create_controller_user(Shift $shift, AngelType $angeltype):
throw_redirect(shift_link($shift));
}
$room = $shift->room;
$location = $shift->location;
return [
ShiftEntry_create_title(),
ShiftEntry_create_view_user($shift, $room, $angeltype, $comment),
ShiftEntry_create_view_user($shift, $location, $angeltype, $comment),
];
}

View File

@ -1,8 +1,8 @@
<?php
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\ScheduleShift;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftType;
@ -67,9 +67,9 @@ function shift_edit_controller()
));
}
$rooms = [];
foreach (Room::orderBy('name')->get() as $room) {
$rooms[$room->id] = $room->name;
$locations = [];
foreach (Location::orderBy('name')->get() as $location) {
$locations[$location->id] = $location->name;
}
$angeltypes = AngelType::all()->pluck('name', 'id')->toArray();
$shifttypes = ShiftType::all()->pluck('name', 'id')->toArray();
@ -84,7 +84,7 @@ function shift_edit_controller()
$shifttype_id = $shift->shift_type_id;
$title = $shift->title;
$description = $shift->description;
$rid = $shift->room_id;
$rid = $shift->location_id;
$start = $shift->start;
$end = $shift->end;
@ -97,7 +97,7 @@ function shift_edit_controller()
if (
$request->has('rid')
&& preg_match('/^\d+$/', $request->input('rid'))
&& isset($rooms[$request->input('rid')])
&& isset($locations[$request->input('rid')])
) {
$rid = $request->input('rid');
} else {
@ -154,7 +154,7 @@ function shift_edit_controller()
$shift->shift_type_id = $shifttype_id;
$shift->title = $title;
$shift->description = $description;
$shift->room_id = $rid;
$shift->location_id = $rid;
$shift->start = $start;
$shift->end = $end;
$shift->updatedBy()->associate(auth()->user());
@ -210,7 +210,7 @@ function shift_edit_controller()
form([
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
form_text('title', __('title.title'), $title),
form_select('rid', __('Location:'), $rooms, $rid),
form_select('rid', __('Location:'), $locations, $rid),
form_text('start', __('Start:'), $start->format('Y-m-d H:i')),
form_text('end', __('End:'), $end->format('Y-m-d H:i')),
form_textarea('description', __('Additional description'), $description),
@ -255,7 +255,7 @@ function shift_delete_controller()
'name' => $shift->shiftType->name,
'title' => $shift->title,
'type' => $entry->angelType->name,
'room' => $shift->room,
'location' => $shift->location,
'freeloaded' => $entry->freeloaded,
]);
}
@ -312,7 +312,7 @@ function shift_controller()
}
$shifttype = $shift->shiftType;
$room = $shift->room;
$location = $shift->location;
/** @var AngelType[] $angeltypes */
$angeltypes = AngelType::all();
$user_shifts = Shifts_by_user($user->id);
@ -344,7 +344,7 @@ function shift_controller()
return [
$shift->shiftType->name,
Shift_view($shift, $shifttype, $room, $angeltypes, $shift_signup_state),
Shift_view($shift, $shifttype, $location, $angeltypes, $shift_signup_state),
];
}

View File

@ -5,7 +5,7 @@ namespace Engelsystem\Events\Listener;
use Carbon\Carbon;
use Engelsystem\Helpers\Shifts;
use Engelsystem\Mail\EngelsystemMailer;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
use Psr\Log\LoggerInterface;
@ -25,7 +25,7 @@ class Shift
string $name,
string $title,
string $type,
Room $room,
Location $location,
bool $freeloaded
): void {
if ($freeloaded || $start > Carbon::now()) {
@ -44,7 +44,7 @@ class Shift
$name,
$title,
$type,
$room->name,
$location->name,
$start->format(__('Y-m-d H:i')),
$end->format(__('Y-m-d H:i'))
);
@ -63,7 +63,7 @@ class Shift
string $name,
string $title,
string $type,
Room $room,
Location $location,
bool $freeloaded
): void {
if (!$user->settings->email_shiftinfo) {
@ -79,7 +79,7 @@ class Shift
'title' => $title,
'start' => $start,
'end' => $end,
'room' => $room,
'location' => $location,
'freeloaded' => $freeloaded,
'username' => $user->displayName,
]

View File

@ -24,7 +24,7 @@ $includeFiles = [
__DIR__ . '/../includes/view/AngelTypes_view.php',
__DIR__ . '/../includes/view/EventConfig_view.php',
__DIR__ . '/../includes/view/PublicDashboard_view.php',
__DIR__ . '/../includes/view/Rooms_view.php',
__DIR__ . '/../includes/view/Locations_view.php',
__DIR__ . '/../includes/view/ShiftCalendarLane.php',
__DIR__ . '/../includes/view/ShiftCalendarRenderer.php',
__DIR__ . '/../includes/view/ShiftCalendarShiftRenderer.php',
@ -40,7 +40,7 @@ $includeFiles = [
__DIR__ . '/../includes/controller/angeltypes_controller.php',
__DIR__ . '/../includes/controller/event_config_controller.php',
__DIR__ . '/../includes/controller/public_dashboard_controller.php',
__DIR__ . '/../includes/controller/rooms_controller.php',
__DIR__ . '/../includes/controller/locations_controller.php',
__DIR__ . '/../includes/controller/shift_entries_controller.php',
__DIR__ . '/../includes/controller/shifts_controller.php',
__DIR__ . '/../includes/controller/shifttypes_controller.php',

View File

@ -11,8 +11,8 @@ function mail_shift_change(Shift $old_shift, Shift $new_shift)
$shiftEntries = $old_shift->shiftEntries()
->with(['user', 'user.settings'])
->get();
$old_room = $old_shift->room;
$new_room = $new_shift->room;
$old_location = $old_shift->location;
$new_location = $new_shift->location;
$noticeable_changes = false;
@ -51,8 +51,8 @@ function mail_shift_change(Shift $old_shift, Shift $new_shift)
$noticeable_changes = true;
}
if ($old_shift->room_id != $new_shift->room_id) {
$message .= sprintf(__('* Shift Location changed from %s to %s'), $old_room->name, $new_room->name) . "\n";
if ($old_shift->location_id != $new_shift->location_id) {
$message .= sprintf(__('* Shift Location changed from %s to %s'), $old_location->name, $new_location->name) . "\n";
$noticeable_changes = true;
}
@ -67,7 +67,7 @@ function mail_shift_change(Shift $old_shift, Shift $new_shift)
$message .= $new_shift->shiftType->name . "\n";
$message .= $new_shift->title . "\n";
$message .= $new_shift->start->format(__('Y-m-d H:i')) . ' - ' . $new_shift->end->format(__('H:i')) . "\n";
$message .= $new_room->name . "\n\n";
$message .= $new_location->name . "\n\n";
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $new_shift->id]) . "\n";
foreach ($shiftEntries as $shiftEntry) {
@ -89,13 +89,11 @@ function mail_shift_assign(User $user, Shift $shift)
return;
}
$room = $shift->room;
$message = __('You have been assigned to a Shift:') . "\n";
$message .= $shift->shiftType->name . "\n";
$message .= $shift->title . "\n";
$message .= $shift->start->format(__('Y-m-d H:i')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
$message .= $room->name . "\n\n";
$message .= $shift->location->name . "\n\n";
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $shift->id]) . "\n";
engelsystem_email_to_user($user, __('Assigned to Shift'), $message, true);
@ -107,13 +105,11 @@ function mail_shift_removed(User $user, Shift $shift)
return;
}
$room = $shift->room;
$message = __('You have been removed from a Shift:') . "\n";
$message .= $shift->shiftType->name . "\n";
$message .= $shift->title . "\n";
$message .= $shift->start->format(__('Y-m-d H:i')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
$message .= $room->name . "\n";
$message .= $shift->location->name . "\n";
engelsystem_email_to_user($user, __('Removed from Shift'), $message, true);
}

View File

@ -23,19 +23,19 @@ function NeededAngelTypes_by_shift($shiftId)
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
WHERE `shift_id` = ?
ORDER BY `room_id` DESC',
ORDER BY `location_id` DESC',
[$shiftId]
);
// Use settings from room
// Use settings from location
if (count($needed_angeltypes_source) == 0) {
$needed_angeltypes_source = Db::select('
SELECT `needed_angel_types`.*, `angel_types`.`name`, `angel_types`.`restricted`
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
JOIN `shifts` ON `shifts`.`room_id` = `needed_angel_types`.`room_id`
JOIN `shifts` ON `shifts`.`location_id` = `needed_angel_types`.`location_id`
WHERE `shifts`.`id` = ?
ORDER BY `room_id` DESC
ORDER BY `location_id` DESC
', [$shiftId]);
}

View File

@ -15,7 +15,7 @@ function ShiftEntry_onCreate(ShiftEntry $shiftEntry): void
'User ' . User_Nick_render($shiftEntry->user, true)
. ' signed up for shift ' . $shiftEntry->shift->title
. ' (' . $shift->shiftType->name . ')'
. ' at ' . $shift->room->name
. ' at ' . $shift->location->name
. ' from ' . $shift->start->format('Y-m-d H:i')
. ' to ' . $shift->end->format('Y-m-d H:i')
. ' as ' . $shiftEntry->angelType->name
@ -33,14 +33,14 @@ function ShiftEntry_onDelete(ShiftEntry $shiftEntry)
$signout_user = $shiftEntry->user;
$shift = Shift($shiftEntry->shift);
$shifttype = $shift->shiftType;
$room = $shift->room;
$location = $shift->location;
$angeltype = $shiftEntry->angelType;
engelsystem_log(
'Shift signout: ' . User_Nick_render($signout_user, true)
. ' from shift ' . $shift->title
. ' (' . $shifttype->name . ')'
. ' at ' . $room->name
. ' at ' . $location->name
. ' from ' . $shift->start->format('Y-m-d H:i')
. ' to ' . $shift->end->format('Y-m-d H:i')
. ' as ' . $angeltype->name

View File

@ -44,10 +44,10 @@ class ShiftsFilter
* ShiftsFilter constructor.
*
* @param bool $user_shifts_admin
* @param int[] $rooms
* @param int[] $locations
* @param int[] $angelTypes
*/
public function __construct($user_shifts_admin = false, private $rooms = [], $angelTypes = [])
public function __construct($user_shifts_admin = false, private $locations = [], $angelTypes = [])
{
$this->types = $angelTypes;
@ -68,7 +68,7 @@ class ShiftsFilter
return [
'userShiftsAdmin' => $this->userShiftsAdmin,
'filled' => $this->filled,
'rooms' => $this->rooms,
'locations' => $this->locations,
'types' => $this->types,
'startTime' => $this->startTime,
'endTime' => $this->endTime,
@ -80,12 +80,12 @@ class ShiftsFilter
*/
public function sessionImport($data)
{
$this->userShiftsAdmin = $data['userShiftsAdmin'];
$this->filled = $data['filled'];
$this->rooms = $data['rooms'];
$this->types = $data['types'];
$this->startTime = $data['startTime'];
$this->endTime = $data['endTime'];
$this->userShiftsAdmin = $data['userShiftsAdmin'] ?? false;
$this->filled = $data['filled'] ?? [];
$this->locations = $data['locations'] ?? [];
$this->types = $data['types'] ?? [];
$this->startTime = $data['startTime'] ?? null;
$this->endTime = $data['endTime'] ?? null;
}
/**
@ -163,20 +163,20 @@ class ShiftsFilter
/**
* @return int[]
*/
public function getRooms()
public function getLocations()
{
if (count($this->rooms) == 0) {
if (count($this->locations) == 0) {
return [0];
}
return $this->rooms;
return $this->locations;
}
/**
* @param int[] $rooms
* @param int[] $locations
*/
public function setRooms($rooms)
public function setLocations($locations)
{
$this->rooms = $rooms;
$this->locations = $locations;
}
/**

View File

@ -29,7 +29,7 @@ function Shifts_by_angeltype(AngelType $angeltype)
UNION
SELECT DISTINCT `shifts`.* FROM `shifts`
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id` = `shifts`.`room_id`
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id` = `shifts`.`location_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `needed_angel_types`.`angel_type_id` = ?
AND NOT s.shift_id IS NULL
@ -60,7 +60,7 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_id`=`shifts`.`id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
AND s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION
@ -68,10 +68,10 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE (`end` > ? AND `start` < ?)
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND `freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
AND NOT s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`
ORDER BY `tmp`.`start`
', [
@ -97,32 +97,32 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
{
$sql = '
SELECT * FROM (
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `rooms`.`name` AS `room_name`
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
FROM `shifts`
JOIN `rooms` ON `shifts`.`room_id` = `rooms`.`id`
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id` = `shifts`.`id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND `start` BETWEEN ? AND ?
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
AND s.shift_id IS NULL
UNION
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `rooms`.`name` AS `room_name`
SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
FROM `shifts`
JOIN `rooms` ON `shifts`.`room_id` = `rooms`.`id`
JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND `start` BETWEEN ? AND ?
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
AND NOT s.shift_id IS NULL
) AS tmp_shifts
ORDER BY `room_name`, `start`
ORDER BY `location_name`, `start`
';
$shiftsData = Db::select(
@ -161,7 +161,7 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id`=`shifts`.`id`
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND shifts.`start` BETWEEN ? AND ?
AND s.shift_id IS NULL
@ -175,10 +175,10 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
`angel_types`.`restricted`,
`angel_types`.`shift_self_signup`
FROM `shifts`
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND shifts.`start` BETWEEN ? AND ?
AND NOT s.shift_id IS NULL
';
@ -228,7 +228,7 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
`angel_types`.`restricted`,
`angel_types`.`shift_self_signup`
FROM `shifts`
JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `shifts`.`id`=?
@ -252,7 +252,7 @@ function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
{
return ShiftEntry::with('user')
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
->whereIn('shifts.room_id', $shiftsFilter->getRooms())
->whereIn('shifts.location_id', $shiftsFilter->getLocations())
->whereBetween('start', [$shiftsFilter->getStart(), $shiftsFilter->getEnd()])
->get();
}
@ -510,8 +510,8 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
$shiftsData = Db::select(
'
SELECT
`rooms`.*,
`rooms`.name AS Name,
`locations`.*,
`locations`.name AS Name,
`shift_types`.`id` AS `shifttype_id`,
`shift_types`.`name`,
`shift_entries`.`id` as shift_entry_id,
@ -525,7 +525,7 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
FROM `shift_entries`
JOIN `shifts` ON (`shift_entries`.`shift_id` = `shifts`.`id`)
JOIN `shift_types` ON (`shift_types`.`id` = `shifts`.`shift_type_id`)
JOIN `rooms` ON (`shifts`.`room_id` = `rooms`.`id`)
JOIN `locations` ON (`shifts`.`location_id` = `locations`.`id`)
WHERE shift_entries.`user_id` = ?
ORDER BY `start`
',

View File

@ -24,7 +24,7 @@ function stats_currently_working(ShiftsFilter $filter = null)
)) AS `count`
FROM `shifts`
WHERE (`end` >= NOW() AND `start` <= NOW())
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '')
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '')
);
return $result['count'] ?: '-';
@ -49,18 +49,18 @@ function stats_hours_to_work(ShiftsFilter $filter = null)
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `shifts`.`end` >= NOW()
AND s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION ALL
SELECT
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
(SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE shifts.`end` >= NOW()
AND NOT s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`
'
);
@ -103,7 +103,7 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
AND s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION ALL
@ -114,7 +114,7 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
WHERE `angel_types`.`show_on_dashboard`=TRUE
AND `needed_angel_types`.`room_id`=`shifts`.`room_id`
AND `needed_angel_types`.`location_id`=`shifts`.`location_id`
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
) - (
SELECT COUNT(*)
@ -131,7 +131,7 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `end` > NOW() AND `start` < ?
AND NOT s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`', [
$in3hours,
$in3hours,
@ -185,7 +185,7 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE shifts.`end` > ? AND shifts.`start` < ?
AND s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION ALL
@ -196,7 +196,7 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
WHERE `angel_types`.`show_on_dashboard`=TRUE
AND `needed_angel_types`.`room_id`=`shifts`.`room_id`
AND `needed_angel_types`.`location_id`=`shifts`.`location_id`
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
) - (
SELECT COUNT(*) FROM `shift_entries`
@ -212,7 +212,7 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE `end` > ? AND `start` < ?
AND NOT s.shift_id IS NULL
' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`', [
$night_start,
$night_end,

View File

@ -4,7 +4,7 @@ use Engelsystem\Database\Db;
use Engelsystem\Helpers\Carbon;
use Engelsystem\Http\Exceptions\HttpForbidden;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Schedule;
use Engelsystem\Models\Shifts\Shift;
@ -44,8 +44,8 @@ function admin_shifts()
$shift_over_midnight = true;
// Locations laden
$rooms = Room::orderBy('name')->get();
$room_array = $rooms->pluck('name', 'id')->toArray();
$locations = Location::orderBy('name')->get();
$location_array = $locations->pluck('name', 'id')->toArray();
// Load angeltypes
/** @var AngelType[] $types */
@ -85,14 +85,14 @@ function admin_shifts()
// Auswahl der sichtbaren Locations für die Schichten
if (
$request->has('rid')
&& preg_match('/^\d+$/', $request->input('rid'))
&& isset($room_array[$request->input('rid')])
$request->has('lid')
&& preg_match('/^\d+$/', $request->input('lid'))
&& isset($location_array[$request->input('lid')])
) {
$rid = $request->input('rid');
$lid = $request->input('lid');
} else {
$valid = false;
$rid = $rooms->first()->id;
$lid = $locations->first()->id;
error(__('Please select a location.'));
}
@ -208,7 +208,7 @@ function admin_shifts()
// Alle Eingaben in Ordnung
if ($valid) {
if ($angelmode == 'location') {
$needed_angel_types = NeededAngelType::whereRoomId($rid)
$needed_angel_types = NeededAngelType::whereLocationId($lid)
->pluck('count', 'angel_type_id')
->toArray() + $needed_angel_types;
}
@ -218,7 +218,7 @@ function admin_shifts()
$shifts[] = [
'start' => $start,
'end' => $end,
'room_id' => $rid,
'location_id' => $lid,
'title' => $title,
'shift_type_id' => $shifttype_id,
'description' => $description,
@ -238,7 +238,7 @@ function admin_shifts()
$shifts[] = [
'start' => $shift_start,
'end' => $shift_end,
'room_id' => $rid,
'location_id' => $lid,
'title' => $title,
'shift_type_id' => $shifttype_id,
'description' => $description,
@ -299,7 +299,7 @@ function admin_shifts()
$shifts[] = [
'start' => $interval_start,
'end' => $interval_end,
'room_id' => $rid,
'location_id' => $lid,
'title' => $title,
'shift_type_id' => $shifttype_id,
'description' => $description,
@ -330,7 +330,7 @@ function admin_shifts()
. '</span>'
. ', ' . round($end->copy()->diffInMinutes($start) / 60, 2) . 'h'
. '<br>'
. Room_name_render(Room::find($shift['room_id'])),
. location_name_render(Location::find($shift['location_id'])),
'title' =>
ShiftType_name_render(ShiftType::find($shifttype_id))
. ($shift['title'] ? '<br />' . $shift['title'] : ''),
@ -367,7 +367,7 @@ function admin_shifts()
form_hidden('shifttype_id', $shifttype_id),
form_hidden('description', $description),
form_hidden('title', $title),
form_hidden('rid', $rid),
form_hidden('lid', $lid),
form_hidden('start', $request->input('start')),
form_hidden('end', $request->input('end')),
form_hidden('mode', $mode),
@ -434,9 +434,9 @@ function admin_shifts()
$session->remove('admin_shifts_types');
}
$rid = null;
if ($request->has('rid')) {
$rid = $request->input('rid');
$lid = null;
if ($request->has('lid')) {
$lid = $request->input('lid');
}
$angel_types = '';
foreach ($types as $type) {
@ -467,7 +467,7 @@ function admin_shifts()
div('col-md-6 col-xl-5', [
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
form_text('title', __('title.title'), $title),
form_select('rid', __('Location'), $room_array, $rid),
form_select('lid', __('Location'), $location_array, $lid),
]),
div('col-md-6 col-xl-7', [
form_textarea('description', __('Additional description'), $description),
@ -599,7 +599,7 @@ function admin_shifts_history(): string
'name' => $shift->shiftType->name,
'title' => $shift->title,
'type' => $entry->angelType->name,
'room' => $shift->room,
'location' => $shift->location,
'freeloaded' => $entry->freeloaded,
]);
}

View File

@ -16,7 +16,7 @@ use Engelsystem\Helpers\Schedule\XmlParser;
use Engelsystem\Helpers\Uuid;
use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Models\Room as RoomModel;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Schedule as ScheduleUrl;
use Engelsystem\Models\Shifts\ScheduleShift;
use Engelsystem\Models\Shifts\Shift;
@ -179,7 +179,7 @@ class ImportSchedule extends BaseController
[
'schedule_id' => $scheduleUrl->id,
'schedule' => $schedule,
'rooms' => [
'locations' => [
'add' => $newRooms,
],
'shifts' => [
@ -218,15 +218,15 @@ class ImportSchedule extends BaseController
$this->log('Started schedule "{name}" import', ['name' => $scheduleUrl->name]);
foreach ($newRooms as $room) {
$this->createRoom($room);
$this->createLocation($room);
}
$rooms = $this->getAllRooms();
$locations = $this->getAllLocations();
foreach ($newEvents as $event) {
$this->createEvent(
$event,
$shiftType,
$rooms
$locations
->where('name', $event->getRoom()->getName())
->first(),
$scheduleUrl
@ -237,7 +237,7 @@ class ImportSchedule extends BaseController
$this->updateEvent(
$event,
$shiftType,
$rooms
$locations
->where('name', $event->getRoom()->getName())
->first()
);
@ -255,11 +255,11 @@ class ImportSchedule extends BaseController
return redirect($this->url, 303);
}
protected function createRoom(Room $room): void
protected function createLocation(Room $room): void
{
$roomModel = new RoomModel();
$roomModel->name = $room->getName();
$roomModel->save();
$location = new Location();
$location->name = $room->getName();
$location->save();
$this->log('Created schedule location "{location}"', ['location' => $room->getName()]);
}
@ -269,12 +269,12 @@ class ImportSchedule extends BaseController
$shiftEntries = $this->db
->table('shift_entries')
->select([
'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'rooms.id AS room_id',
'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'locations.id AS location_id',
'shifts.start', 'shifts.end', 'shift_entries.user_id', 'shift_entries.freeloaded',
])
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
->join('schedule_shift', 'shifts.id', 'schedule_shift.shift_id')
->join('rooms', 'rooms.id', 'shifts.room_id')
->join('locations', 'locations.id', 'shifts.location_id')
->join('angel_types', 'angel_types.id', 'shift_entries.angel_type_id')
->join('shift_types', 'shift_types.id', 'shifts.shift_type_id')
->where('schedule_shift.guid', $event->getGuid())
@ -288,13 +288,13 @@ class ImportSchedule extends BaseController
'name' => $shiftEntry->name,
'title' => $shiftEntry->title,
'type' => $shiftEntry->type,
'room' => RoomModel::find($shiftEntry->room_id),
'location' => Location::find($shiftEntry->location_id),
'freeloaded' => $shiftEntry->freeloaded,
]);
}
}
protected function createEvent(Event $event, int $shiftTypeId, RoomModel $room, ScheduleUrl $scheduleUrl): void
protected function createEvent(Event $event, int $shiftTypeId, Location $location, ScheduleUrl $scheduleUrl): void
{
$user = auth()->user();
$eventTimeZone = Carbon::now()->timezone;
@ -304,7 +304,7 @@ class ImportSchedule extends BaseController
$shift->shift_type_id = $shiftTypeId;
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
$shift->room()->associate($room);
$shift->location()->associate($location);
$shift->url = $event->getUrl() ?? '';
$shift->transaction_id = Uuid::uuidBy($scheduleUrl->id, '5c4ed01e');
$shift->createdBy()->associate($user);
@ -319,7 +319,7 @@ class ImportSchedule extends BaseController
'Created schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
[
'shift' => $shift->title,
'location' => $shift->room->name,
'location' => $shift->location->name,
'from' => $shift->start->format(DateTimeInterface::RFC3339),
'to' => $shift->end->format(DateTimeInterface::RFC3339),
'guid' => $scheduleShift->guid,
@ -327,7 +327,7 @@ class ImportSchedule extends BaseController
);
}
protected function updateEvent(Event $event, int $shiftTypeId, RoomModel $room): void
protected function updateEvent(Event $event, int $shiftTypeId, Location $location): void
{
$user = auth()->user();
$eventTimeZone = Carbon::now()->timezone;
@ -339,7 +339,7 @@ class ImportSchedule extends BaseController
$shift->shift_type_id = $shiftTypeId;
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
$shift->room()->associate($room);
$shift->location()->associate($location);
$shift->url = $event->getUrl() ?? '';
$shift->updatedBy()->associate($user);
$shift->save();
@ -348,7 +348,7 @@ class ImportSchedule extends BaseController
'Updated schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
[
'shift' => $shift->title,
'location' => $shift->room->name,
'location' => $shift->location->name,
'from' => $shift->start->format(DateTimeInterface::RFC3339),
'to' => $shift->end->format(DateTimeInterface::RFC3339),
'guid' => $scheduleShift->guid,
@ -367,7 +367,7 @@ class ImportSchedule extends BaseController
'Deleted schedule shift "{shift}" in {location} ({from} {to}, {guid})',
[
'shift' => $shift->title,
'location' => $shift->room->name,
'location' => $shift->location->name,
'from' => $shift->start->format(DateTimeInterface::RFC3339),
'to' => $shift->end->format(DateTimeInterface::RFC3339),
'guid' => $scheduleShift->guid,
@ -377,7 +377,7 @@ class ImportSchedule extends BaseController
/**
* @param Request $request
* @return Event[]|Room[]|RoomModel[]
* @return Event[]|Room[]|Location[]
* @throws ErrorException
*/
protected function getScheduleData(Request $request)
@ -420,10 +420,10 @@ class ImportSchedule extends BaseController
protected function newRooms(array $scheduleRooms): array
{
$newRooms = [];
$allRooms = $this->getAllRooms();
$allLocations = $this->getAllLocations();
foreach ($scheduleRooms as $room) {
if ($allRooms->where('name', $room->getName())->count()) {
if ($allLocations->where('name', $room->getName())->count()) {
continue;
}
@ -456,7 +456,7 @@ class ImportSchedule extends BaseController
$scheduleEvents = [];
/** @var Event[] $deleteEvents */
$deleteEvents = [];
$rooms = $this->getAllRooms();
$locations = $this->getAllLocations();
$eventTimeZone = Carbon::now()->timezone;
foreach ($schedule->getDay() as $day) {
@ -480,16 +480,16 @@ class ImportSchedule extends BaseController
foreach ($existingShifts as $shift) {
$guid = $shift->guid;
/** @var Shift $shift */
$shift = Shift::with('room')->find($shift->shift_id);
$shift = Shift::with('location')->find($shift->shift_id);
$event = $scheduleEvents[$guid];
$room = $rooms->where('name', $event->getRoom()->getName())->first();
$location = $locations->where('name', $event->getRoom()->getName())->first();
if (
$shift->title != $event->getTitle()
|| $shift->shift_type_id != $shiftType
|| $shift->start != $event->getDate()
|| $shift->end != $event->getEndDate()
|| $shift->room_id != ($room->id ?? '')
|| $shift->location_id != ($location->id ?? '')
|| $shift->url != ($event->getUrl() ?? '')
) {
$changeEvents[$guid] = $event;
@ -514,13 +514,13 @@ class ImportSchedule extends BaseController
protected function eventFromScheduleShift(ScheduleShift $scheduleShift): Event
{
/** @var Shift $shift */
$shift = Shift::with('room')->find($scheduleShift->shift_id);
$shift = Shift::with('location')->find($scheduleShift->shift_id);
$duration = $shift->start->diff($shift->end);
return new Event(
$scheduleShift->guid,
0,
new Room($shift->room->name),
new Room($shift->location->name),
$shift->title,
'',
'n/a',
@ -534,11 +534,11 @@ class ImportSchedule extends BaseController
}
/**
* @return RoomModel[]|Collection
* @return Location[]|Collection
*/
protected function getAllRooms(): Collection
protected function getAllLocations(): Collection
{
return RoomModel::all();
return Location::all();
}
/**

View File

@ -51,7 +51,7 @@ function user_myshifts()
/** @var ShiftEntry $shiftEntry */
$shiftEntry = ShiftEntry::where('id', $shift_entry_id)
->where('user_id', $shifts_user->id)
->with(['shift', 'shift.shiftType', 'shift.room', 'user'])
->with(['shift', 'shift.shiftType', 'shift.location', 'user'])
->first();
if (!empty($shiftEntry)) {
$shift = $shiftEntry->shift;
@ -97,7 +97,7 @@ function user_myshifts()
return ShiftEntry_edit_view(
$shifts_user,
$shift->start->format(__('Y-m-d H:i')) . ', ' . shift_length($shift),
$shift->room->name,
$shift->location->name,
$shift->shiftType->name,
$shiftEntry->angelType->name,
$shiftEntry->user_comment,

View File

@ -3,7 +3,7 @@
use Engelsystem\Database\Db;
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\UserAngelType;
@ -107,40 +107,40 @@ function update_ShiftsFilter(ShiftsFilter $shiftsFilter, $user_shifts_admin, $da
{
$shiftsFilter->setUserShiftsAdmin($user_shifts_admin);
$shiftsFilter->setFilled(check_request_int_array('filled', $shiftsFilter->getFilled()));
$shiftsFilter->setRooms(check_request_int_array('rooms', $shiftsFilter->getRooms()));
$shiftsFilter->setLocations(check_request_int_array('locations', $shiftsFilter->getLocations()));
$shiftsFilter->setTypes(check_request_int_array('types', $shiftsFilter->getTypes()));
update_ShiftsFilter_timerange($shiftsFilter, $days);
}
/**
* @return Room[]|Collection
* @return Location[]|Collection
*/
function load_rooms(bool $onlyWithActiveShifts = false)
function load_locations(bool $onlyWithActiveShifts = false)
{
$rooms = Room::orderBy('name');
$locations = Location::orderBy('name');
if ($onlyWithActiveShifts) {
$roomIdsFromAngelType = NeededAngelType::query()
->whereNotNull('room_id')
->select('room_id');
$locationIdsFromAngelType = NeededAngelType::query()
->whereNotNull('location_id')
->select('location_id');
$roomIdsFromShift = Shift::query()
$locationIdsFromShift = Shift::query()
->leftJoin('needed_angel_types', 'shifts.id', 'needed_angel_types.shift_id')
->whereNotNull('needed_angel_types.shift_id')
->select('shifts.room_id');
->select('shifts.location_id');
$rooms->whereIn('id', $roomIdsFromAngelType)
->orWhereIn('id', $roomIdsFromShift);
$locations->whereIn('id', $locationIdsFromAngelType)
->orWhereIn('id', $locationIdsFromShift);
}
$rooms = $rooms->get();
$locations = $locations->get();
if ($rooms->isEmpty()) {
if ($locations->isEmpty()) {
error(__('The administration has not configured any locations yet.'));
throw_redirect(page_link_to('/'));
}
return $rooms;
return $locations;
}
/**
@ -233,7 +233,7 @@ function view_user_shifts()
$session = session();
$days = load_days();
$rooms = load_rooms(true);
$locations = load_locations(true);
$types = load_types();
$ownAngelTypes = [];
@ -250,8 +250,8 @@ function view_user_shifts()
}
if (!$session->has('shifts-filter')) {
$room_ids = $rooms->pluck('id')->toArray();
$shiftsFilter = new ShiftsFilter(auth()->can('user_shifts_admin'), $room_ids, $ownAngelTypes);
$location_ids = $locations->pluck('id')->toArray();
$shiftsFilter = new ShiftsFilter(auth()->can('user_shifts_admin'), $location_ids, $ownAngelTypes);
$session->set('shifts-filter', $shiftsFilter->sessionExport());
}
@ -297,10 +297,10 @@ function view_user_shifts()
view(__DIR__ . '/../../resources/views/pages/user-shifts.html', [
'title' => shifts_title(),
'add_link' => auth()->can('admin_shifts') ? $link : '',
'room_select' => make_select(
$rooms,
$shiftsFilter->getRooms(),
'rooms',
'location_select' => make_select(
$locations,
$shiftsFilter->getLocations(),
'locations',
icon('pin-map-fill') . __('Locations')
),
'start_select' => html_select_key(

View File

@ -1,7 +1,7 @@
<?php
use Engelsystem\Models\Location;
use Engelsystem\Models\Question;
use Engelsystem\Models\Room;
use Engelsystem\UserHintsRenderer;
/**
@ -79,7 +79,7 @@ function make_navigation()
$menu[] = toolbar_item_link(page_link_to($menu_page), '', $title, $menu_page == $page);
}
$menu = make_room_navigation($menu);
$menu = make_location_navigation($menu);
$admin_menu = [];
$admin_pages = [
@ -92,7 +92,7 @@ function make_navigation()
'admin/questions' => ['Answer questions', 'question.edit'],
'shifttypes' => 'Shifttypes',
'admin_shifts' => 'Create shifts',
'admin/rooms' => ['room.rooms', 'admin_rooms'],
'admin/locations' => ['location.locations', 'admin_locations'],
'admin_groups' => 'Grouprights',
'admin/schedule' => ['schedule.import', 'schedule.import'],
'admin/logs' => ['log.log', 'admin_log'],
@ -142,31 +142,36 @@ function menu_is_allowed(string $page, $options)
}
/**
* Adds room navigation to the given menu.
* Adds location navigation to the given menu.
*
* @param string[] $menu Rendered menu
* @return string[]
*/
function make_room_navigation($menu)
function make_location_navigation($menu)
{
if (!auth()->can('view_rooms')) {
if (!auth()->can('view_locations')) {
return $menu;
}
// Get a list of all rooms
$rooms = Room::orderBy('name')->get();
$room_menu = [];
if (auth()->can('admin_rooms')) {
$room_menu[] = toolbar_dropdown_item(page_link_to('admin/rooms'), __('Manage locations'), false, 'list');
// Get a list of all locations
$locations = Location::orderBy('name')->get();
$location_menu = [];
if (auth()->can('admin_locations')) {
$location_menu[] = toolbar_dropdown_item(
page_link_to('admin/locations'),
__('Manage locations'),
false,
'list'
);
}
if (count($room_menu) > 0) {
$room_menu[] = toolbar_dropdown_item_divider();
if (count($location_menu) > 0) {
$location_menu[] = toolbar_dropdown_item_divider();
}
foreach ($rooms as $room) {
$room_menu[] = toolbar_dropdown_item(room_link($room), $room->name, false, 'pin-map-fill');
foreach ($locations as $location) {
$location_menu[] = toolbar_dropdown_item(location_link($location), $location->name, false, 'pin-map-fill');
}
if (count($room_menu) > 0) {
$menu[] = toolbar_dropdown(__('Locations'), $room_menu);
if (count($location_menu) > 0) {
$menu[] = toolbar_dropdown(__('Locations'), $location_menu);
}
return $menu;
}

View File

@ -1,17 +1,17 @@
<?php
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\ShiftCalendarRenderer;
use Engelsystem\ShiftsFilterRenderer;
/**
*
* @param Room $room
* @param Location $location
* @param ShiftsFilterRenderer $shiftsFilterRenderer
* @param ShiftCalendarRenderer $shiftCalendarRenderer
* @return string
*/
function Room_view(Room $room, ShiftsFilterRenderer $shiftsFilterRenderer, ShiftCalendarRenderer $shiftCalendarRenderer)
function location_view(Location $location, ShiftsFilterRenderer $shiftsFilterRenderer, ShiftCalendarRenderer $shiftCalendarRenderer)
{
$user = auth()->user();
@ -21,33 +21,33 @@ function Room_view(Room $room, ShiftsFilterRenderer $shiftsFilterRenderer, Shift
}
$description = '';
if ($room->description) {
if ($location->description) {
$description = '<h3>' . __('general.description') . '</h3>';
$parsedown = new Parsedown();
$description .= $parsedown->parse($room->description);
$description .= $parsedown->parse($location->description);
}
$dect = '';
if (config('enable_dect') && $room->dect) {
if (config('enable_dect') && $location->dect) {
$dect = heading(__('Contact'), 3)
. description([__('general.dect') => sprintf('<a href="tel:%s">%1$s</a>', $room->dect)]);
. description([__('general.dect') => sprintf('<a href="tel:%s">%1$s</a>', $location->dect)]);
}
$tabs = [];
if ($room->map_url) {
$tabs[__('room.map_url')] = sprintf(
if ($location->map_url) {
$tabs[__('location.map_url')] = sprintf(
'<div class="map">'
. '<iframe style="width: 100%%; min-height: 400px; border: 0 none;" src="%s"></iframe>'
. '</div>',
$room->map_url
$location->map_url
);
}
$tabs[__('Shifts')] = div('first', [
$shiftsFilterRenderer->render(page_link_to('rooms', [
$shiftsFilterRenderer->render(page_link_to('locations', [
'action' => 'view',
'room_id' => $room->id,
]), ['rooms' => [$room->id]]),
'location_id' => $location->id,
]), ['locations' => [$location->id]]),
$shiftCalendarRenderer->render(),
]);
@ -57,15 +57,15 @@ function Room_view(Room $room, ShiftsFilterRenderer $shiftsFilterRenderer, Shift
$selected_tab = count($tabs) - 1;
}
$link = button(page_link_to('admin/rooms'), icon('chevron-left'), 'btn-sm');
$link = button(page_link_to('admin/locations'), icon('chevron-left'), 'btn-sm');
return page_with_title(
(auth()->can('admin_rooms') ? $link . ' ' : '') .
icon('pin-map-fill') . $room->name,
(auth()->can('admin_locations') ? $link . ' ' : '') .
icon('pin-map-fill') . $location->name,
[
$assignNotice,
auth()->can('admin_rooms') ? buttons([
auth()->can('admin_locations') ? buttons([
button(
page_link_to('admin/rooms/edit/' . $room->id),
page_link_to('admin/locations/edit/' . $location->id),
icon('pencil') . __('edit')
),
]) : '',
@ -79,14 +79,14 @@ function Room_view(Room $room, ShiftsFilterRenderer $shiftsFilterRenderer, Shift
/**
*
* @param Room $room
* @param Location $location
* @return string
*/
function Room_name_render(Room $room)
function location_name_render(Location $location)
{
if (auth()->can('view_rooms')) {
return '<a href="' . room_link($room) . '">' . icon('pin-map-fill') . $room->name . '</a>';
if (auth()->can('view_locations')) {
return '<a href="' . location_link($location) . '">' . icon('pin-map-fill') . $location->name . '</a>';
}
return icon('pin-map-fill') . $room->name;
return icon('pin-map-fill') . $location->name;
}

View File

@ -58,7 +58,7 @@ function public_dashboard_view($stats, $free_shifts, $highlighted_news)
}
$isFiltered = request()->get('filtered');
$filter = collect(session()->get('shifts-filter'))->only(['rooms', 'types'])->toArray();
$filter = collect(session()->get('shifts-filter'))->only(['locations', 'types'])->toArray();
return page([
div('wrapper', [
div('public-dashboard', [
@ -98,7 +98,7 @@ function public_dashboard_shift_render($shift)
$panel_body .= ' (' . $shift['title'] . ')';
}
$panel_body .= '<br>' . icon('pin-map-fill') . $shift['room_name'];
$panel_body .= '<br>' . icon('pin-map-fill') . $shift['location_name'];
foreach ($shift['needed_angels'] as $needed_angels) {
$panel_body .= '<br>' . icon('person')

View File

@ -62,28 +62,28 @@ class ShiftCalendarRenderer
}
/**
* Assigns the shifts to different lanes per room if they collide
* Assigns the shifts to different lanes per location if they collide
*
* @param Shift[] $shifts The shifts to assign
* @return array Returns an array that assigns a room_id to an array of ShiftCalendarLane containing the shifts
* @return array Returns an array that assigns a location_id to an array of ShiftCalendarLane containing the shifts
*/
private function assignShiftsToLanes($shifts)
{
// array that assigns a room id to a list of lanes (per room)
// array that assigns a location id to a list of lanes (per location)
$lanes = [];
foreach ($shifts as $shift) {
$room = $shift->room;
$header = Room_name_render($room);
if (!isset($lanes[$room->id])) {
// initialize room with one lane
$lanes[$room->id] = [
$location = $shift->location;
$header = location_name_render($location);
if (!isset($lanes[$location->id])) {
// initialize location with one lane
$lanes[$location->id] = [
new ShiftCalendarLane($header),
];
}
// Try to add the shift to the existing lanes for this room
// Try to add the shift to the existing lanes for this location
$shift_added = false;
foreach ($lanes[$room->id] as $lane) {
foreach ($lanes[$location->id] as $lane) {
/** @var ShiftCalendarLane $lane */
if ($lane->shiftFits($shift)) {
$lane->addShift($shift);
@ -91,11 +91,11 @@ class ShiftCalendarRenderer
break;
}
}
// If all lanes for this room are busy, create a new lane and add shift to it
// If all lanes for this location are busy, create a new lane and add shift to it
if (!$shift_added) {
$newLane = new ShiftCalendarLane($header);
$newLane->addShift($shift);
$lanes[$room->id][] = $newLane;
$lanes[$location->id][] = $newLane;
}
}
@ -154,8 +154,8 @@ class ShiftCalendarRenderer
private function renderShiftLanes()
{
$html = '';
foreach ($this->lanes as $room_lanes) {
foreach ($room_lanes as $lane) {
foreach ($this->lanes as $location_lanes) {
foreach ($location_lanes as $lane) {
$html .= $this->renderLane($lane);
}
}

View File

@ -43,8 +43,6 @@ class ShiftCalendarShiftRenderer
$blocks = ceil(($shift->end->timestamp - $shift->start->timestamp) / ShiftCalendarRenderer::SECONDS_PER_ROW);
$blocks = max(1, $blocks);
$room = $shift->room;
return [
$blocks,
div(
@ -57,7 +55,7 @@ class ShiftCalendarShiftRenderer
$this->renderShiftHead($shift, $class, $shift_signup_state->getFreeEntries()),
div('card-body ' . $this->classBg(), [
$info_text,
Room_name_render($room),
location_name_render($shift->location),
]),
$shifts_row,
]

View File

@ -1,7 +1,7 @@
<?php
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\User\User;
@ -75,7 +75,7 @@ function ShiftEntry_delete_title()
* Admin puts user into shift.
*
* @param Shift $shift
* @param Room $room
* @param Location $location
* @param AngelType $angeltype
* @param array $angeltypes_select
* @param User $signup_user
@ -84,7 +84,7 @@ function ShiftEntry_delete_title()
*/
function ShiftEntry_create_view_admin(
Shift $shift,
Room $room,
Location $location,
AngelType $angeltype,
$angeltypes_select,
$signup_user,
@ -95,7 +95,7 @@ function ShiftEntry_create_view_admin(
ShiftEntry_create_title() . ': ' . $shift->shiftType->name
. ' <small title="' . $start . '" data-countdown-ts="' . $shift->start->timestamp . '">%c</small>',
[
Shift_view_header($shift, $room),
Shift_view_header($shift, $location),
info(__('Do you want to sign up the following user for this shift?'), true),
form([
form_select('angeltype_id', __('Angeltype'), $angeltypes_select, $angeltype->id),
@ -110,20 +110,25 @@ function ShiftEntry_create_view_admin(
* Supporter puts user into shift.
*
* @param Shift $shift
* @param Room $room
* @param Location $location
* @param AngelType $angeltype
* @param User $signup_user
* @param array $users_select
* @return string
*/
function ShiftEntry_create_view_supporter(Shift $shift, Room $room, AngelType $angeltype, $signup_user, $users_select)
{
function ShiftEntry_create_view_supporter(
Shift $shift,
Location $location,
AngelType $angeltype,
$signup_user,
$users_select
) {
$start = $shift->start->format(__('Y-m-d H:i'));
return page_with_title(
ShiftEntry_create_title() . ': ' . $shift->shiftType->name
. ' <small title="' . $start . '" data-countdown-ts="' . $shift->start->timestamp . '">%c</small>',
[
Shift_view_header($shift, $room),
Shift_view_header($shift, $location),
info(sprintf(
__('Do you want to sign up the following user for this shift as %s?'),
$angeltype->name
@ -140,19 +145,19 @@ function ShiftEntry_create_view_supporter(Shift $shift, Room $room, AngelType $a
* User joining a shift.
*
* @param Shift $shift
* @param Room $room
* @param Location $location
* @param AngelType $angeltype
* @param string $comment
* @return string
*/
function ShiftEntry_create_view_user(Shift $shift, Room $room, AngelType $angeltype, $comment)
function ShiftEntry_create_view_user(Shift $shift, Location $location, AngelType $angeltype, $comment)
{
$start = $shift->start->format(__('Y-m-d H:i'));
return page_with_title(
ShiftEntry_create_title() . ': ' . $shift->shiftType->name
. ' <small title="' . $start . '" data-countdown-ts="' . $shift->start->timestamp . '">%c</small>',
[
Shift_view_header($shift, $room),
Shift_view_header($shift, $location),
info(sprintf(__('Do you want to sign up for this shift as %s?'), $angeltype->name), true),
form([
form_textarea('comment', __('Comment (for your eyes only):'), $comment),

View File

@ -1,7 +1,7 @@
<?php
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
use Engelsystem\Models\Shifts\ShiftType;
@ -14,10 +14,10 @@ use Illuminate\Support\Collection;
* Renders the basic shift view header.
*
* @param Shift $shift
* @param Room $room
* @param Location $location
* @return string HTML
*/
function Shift_view_header(Shift $shift, Room $room)
function Shift_view_header(Shift $shift, Location $location)
{
return div('row', [
div('col-sm-3 col-xs-6', [
@ -46,7 +46,7 @@ function Shift_view_header(Shift $shift, Room $room)
]),
div('col-sm-3 col-xs-6', [
'<h4>' . __('Location') . '</h4>',
'<p class="lead">' . Room_name_render($room) . '</p>',
'<p class="lead">' . location_name_render($location) . '</p>',
]),
]);
}
@ -109,16 +109,21 @@ function Shift_signup_button_render(Shift $shift, AngelType $angeltype)
/**
* @param Shift $shift
* @param ShiftType $shifttype
* @param Room $room
* @param Location $location
* @param AngelType[]|Collection $angeltypes_source
* @param ShiftSignupState $shift_signup_state
* @return string
*/
function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_source, ShiftSignupState $shift_signup_state)
{
function Shift_view(
Shift $shift,
ShiftType $shifttype,
Location $location,
$angeltypes_source,
ShiftSignupState $shift_signup_state
) {
$shift_admin = auth()->can('admin_shifts');
$user_shift_admin = auth()->can('user_shifts_admin');
$admin_rooms = auth()->can('admin_rooms');
$admin_locations = auth()->can('admin_locations');
$admin_shifttypes = auth()->can('shifttypes');
$parsedown = new Parsedown();
@ -166,12 +171,12 @@ function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_
}
$buttons = [];
if ($shift_admin || $admin_shifttypes || $admin_rooms) {
if ($shift_admin || $admin_shifttypes || $admin_locations) {
$buttons = [
$shift_admin ? button(shift_edit_link($shift), icon('pencil') . __('edit')) : '',
$shift_admin ? button(shift_delete_link($shift), icon('trash') . __('delete')) : '',
$admin_shifttypes ? button(shifttype_link($shifttype), $shifttype->name) : '',
$admin_rooms ? button(room_link($room), icon('pin-map-fill') . $room->name) : '',
$admin_locations ? button(location_link($location), icon('pin-map-fill') . $location->name) : '',
];
}
$buttons[] = button(
@ -180,7 +185,7 @@ function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_
);
$content[] = buttons($buttons);
$content[] = Shift_view_header($shift, $room);
$content[] = Shift_view_header($shift, $location);
$content[] = div('row', [
div('col-sm-6', [
'<h2>' . __('Needed angels') . '</h2>',

View File

@ -313,7 +313,7 @@ function User_view_myshift(Shift $shift, $user_source, $its_me)
. ' - '
. $shift->end->format(__('H:i')),
'duration' => sprintf('%.2f', ($shift->end->timestamp - $shift->start->timestamp) / 3600) . '&nbsp;h',
'room' => Room_name_render($shift->room),
'location' => location_name_render($shift->location),
'shift_info' => $shift_info,
'comment' => '',
];
@ -404,7 +404,7 @@ function User_view_myshifts(
$myshifts_table[] = [
'date' => '<b>' . __('Sum:') . '</b>',
'duration' => '<b>' . sprintf('%.2f', round($timeSum / 3600, 2)) . '&nbsp;h</b>',
'room' => '',
'location' => '',
'shift_info' => '',
'comment' => '',
'actions' => '',
@ -413,7 +413,7 @@ function User_view_myshifts(
$myshifts_table[] = [
'date' => '<b>' . ($goodie_tshirt ? __('Your t-shirt score') : __('Your goodie score')) . '&trade;:</b>',
'duration' => '<b>' . $tshirt_score . '</b>',
'room' => '',
'location' => '',
'shift_info' => '',
'comment' => '',
'actions' => '',
@ -451,7 +451,7 @@ function User_view_worklog(Worklog $worklog, $admin_user_worklog_privilege)
return [
'date' => icon('calendar-event') . date(__('Y-m-d'), $worklog->worked_at->timestamp),
'duration' => sprintf('%.2f', $worklog->hours) . ' h',
'room' => '',
'location' => '',
'shift_info' => __('Work log entry'),
'comment' => $worklog->comment . '<br>'
. sprintf(
@ -515,7 +515,7 @@ function User_view(
$myshifts_table = div('table-responsive', table([
'date' => __('Day & Time'),
'duration' => __('Duration'),
'room' => __('Location'),
'location' => __('Location'),
'shift_info' => __('Name & Workmates'),
'comment' => __('worklog.comment'),
'actions' => __('Action'),

View File

@ -266,10 +266,10 @@ msgstr "Arbeitseinsatz erfolgreich bearbeitet."
msgid "worklog.delete.success"
msgstr "Arbeitseinsatz erfolgreich gelöscht."
msgid "room.edit.success"
msgid "location.edit.success"
msgstr "Ort erfolgreich bearbeitet."
msgid "room.delete.success"
msgid "location.delete.success"
msgstr "Ort erfolgreich gelöscht."
msgid "validation.name.exists"

View File

@ -1565,7 +1565,7 @@ msgstr "Minuten vor Talk beginn hinzufügen"
msgid "schedule.minutes-after"
msgstr "Minuten nach Talk ende hinzufügen"
msgid "schedule.import.rooms.add"
msgid "schedule.import.locations.add"
msgstr "Neue Orte"
msgid "schedule.import.shifts.add"
@ -1583,7 +1583,7 @@ msgstr "Zeit"
msgid "schedule.import.shift.type"
msgstr "Typ"
msgid "schedule.import.shift.room"
msgid "schedule.import.shift.location"
msgstr "Ort"
msgid "shifts_history.schedule"
@ -1964,22 +1964,22 @@ msgstr "Wenn ausgewählt, können nur Admins und Mitglieder des Engeltyps auf de
msgid "registration.register"
msgstr "Registrieren"
msgid "room.rooms"
msgid "location.locations"
msgstr "Orte"
msgid "room.map_url"
msgid "location.map_url"
msgstr "Karte"
msgid "room.required_angels"
msgid "location.required_angels"
msgstr "Benötigte Engel"
msgid "room.map_url.info"
msgid "location.map_url.info"
msgstr "Die Karte wird auf der Ort-Seite als iframe eingebettet."
msgid "room.create.title"
msgid "location.create.title"
msgstr "Ort erstellen"
msgid "room.edit.title"
msgid "location.edit.title"
msgstr "Ort bearbeiten"
msgid "event.day"

View File

@ -265,10 +265,10 @@ msgstr "Work log successfully updated."
msgid "worklog.delete.success"
msgstr "Work log successfully deleted."
msgid "room.edit.success"
msgid "location.edit.success"
msgstr "Location edited successfully."
msgid "room.delete.success"
msgid "location.delete.success"
msgstr "Location successfully deleted."
msgid "validation.name.exists"

View File

@ -133,7 +133,7 @@ msgstr "Add minutes after talk ends"
msgid "schedule.import.request_error"
msgstr "Unable to load schedule."
msgid "schedule.import.rooms.add"
msgid "schedule.import.locations.add"
msgstr "Locations to create"
msgid "schedule.import.shifts.add"
@ -154,7 +154,7 @@ msgstr "Type"
msgid "title.title"
msgstr "Title"
msgid "schedule.import.shift.room"
msgid "schedule.import.shift.location"
msgstr "Location"
msgid "shifts_history.schedule"
@ -552,22 +552,22 @@ msgstr "If checked only admins and members of the angeltype "
msgid "registration.register"
msgstr "Register"
msgid "room.rooms"
msgid "location.locations"
msgstr "Locations"
msgid "room.map_url"
msgid "location.map_url"
msgstr "Map"
msgid "room.required_angels"
msgid "location.required_angels"
msgstr "Required angels"
msgid "room.map_url.info"
msgid "location.map_url.info"
msgstr "The map will be embedded on the location page as an iframe."
msgid "room.create.title"
msgid "location.create.title"
msgstr "Create location"
msgid "room.edit.title"
msgid "location.edit.title"
msgstr "Edit location"
msgid "event.day"

View File

View File

@ -1,40 +1,40 @@
{% extends 'admin/rooms/index.twig' %}
{% extends 'admin/locations/index.twig' %}
{% import 'macros/base.twig' as m %}
{% import 'macros/form.twig' as f %}
{% block title %}{{ room ? __('room.edit.title') : __('room.create.title') }}{% endblock %}
{% block title %}{{ location ? __('location.edit.title') : __('location.create.title') }}{% endblock %}
{% block row_content %}
<form method="post">
{{ csrf() }}
{{ f.hidden('id', room ? room.id : '') }}
{{ f.hidden('id', location ? location.id : '') }}
<div class="row">
<div class="col-lg-6">
{{ f.input('name', __('general.name'), {
'required': true,
'required_icon': true,
'value': f.formData('room', room ? room.name : ''),
'value': f.formData('location', location ? location.name : ''),
}) }}
{{ f.input('dect', __('general.dect'), {
'value': f.formData('dect', room ? room.dect : ''),
'value': f.formData('dect', location ? location.dect : ''),
}) }}
{{ f.input('map_url', __('room.map_url'), {
{{ f.input('map_url', __('location.map_url'), {
'type': 'url',
'value': f.formData('map_url', room ? room.map_url : ''),
'info': __('room.map_url.info'),
'value': f.formData('map_url', location ? location.map_url : ''),
'info': __('location.map_url.info'),
}) }}
{{ f.textarea('description', __('general.description'), {
'value': f.formData('description', room ? room.description : ''),
'value': f.formData('description', location ? location.description : ''),
'rows': 5,
'info': __('form.markdown')
}) }}
</div>
<div class="col-lg-6">
<h4>{{ __('room.required_angels') }}</h4>
<h4>{{ __('location.required_angels') }}</h4>
{% for types in angel_types.chunk(3) %}
<div class="row">
{% for angel_type in types %}
@ -56,7 +56,7 @@
<div class="col-md-12">
<div class="btn-group">
{{ f.submit(__('form.save'), {'icon_left': 'save'}) }}
{% if room %}
{% if location %}
{{ f.submit(__('form.delete'), {'name': 'delete', 'btn_type': 'danger', 'icon_left': 'trash'}) }}
{% endif %}
</div>

View File

@ -2,19 +2,19 @@
{% import 'macros/base.twig' as m %}
{% import 'macros/form.twig' as f %}
{% block title %}{{ __('room.rooms') }}{% endblock %}
{% block title %}{{ __('location.locations') }}{% endblock %}
{% block content %}
<div class="container">
<h1>
{% if not is_index|default(false) %}
{{ m.button(m.icon('chevron-left'), room ? url('/rooms', {'action': 'view', 'room_id': room.id}) : url('/admin/rooms'), 'secondary', 'sm') }}
{{ m.button(m.icon('chevron-left'), location ? url('/locations', {'action': 'view', 'location_id': location.id}) : url('/admin/locations'), 'secondary', 'sm') }}
{% endif %}
{{ block('title') }}
{% if is_index|default(false) %}
{{ m.button(m.icon('plus-lg'), url('/admin/rooms/edit'), 'secondary') }}
{{ m.button(m.icon('plus-lg'), url('/admin/locations/edit'), 'secondary') }}
{% endif %}
</h1>
@ -30,33 +30,33 @@
<tr>
<th>{{ __('general.name') }}</th>
<th>{{ __('general.dect') }}</th>
<th>{{ __('room.map_url') }}</th>
<th>{{ __('location.map_url') }}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for room in rooms %}
{% for location in locations %}
<tr>
<td>
{{ m.icon('pin-map-fill') }}
<a href="{{ url('/rooms', {'action': 'view', 'room_id': room.id}) }}">
{{ room.name }}
<a href="{{ url('/locations', {'action': 'view', 'location_id': location.id}) }}">
{{ location.name }}
</a>
</td>
<td>{{ m.iconBool(room.dect) }}</td>
<td>{{ m.iconBool(location.dect) }}</td>
<td>{{ m.iconBool(room.map_url) }}</td>
<td>{{ m.iconBool(location.map_url) }}</td>
<td>
<div class="d-flex ms-auto">
{{ m.button(m.icon('pencil'), url('admin/rooms/edit/' ~ room.id), null, 'sm', __('form.edit')) }}
{{ m.button(m.icon('pencil'), url('admin/locations/edit/' ~ location.id), null, 'sm', __('form.edit')) }}
<form method="post" class="ps-1">
{{ csrf() }}
{{ f.hidden('id', room.id) }}
{{ f.hidden('id', location.id) }}
{{ f.button(m.icon('trash'), {'title': __('form.delete'), 'name': 'delete', 'type': 'submit', 'btn_type': 'danger', 'size': 'sm'}) }}
</form>

View File

@ -14,8 +14,8 @@
<div class="col-lg-12">
<p>{{ __('schedule.import.load.info', [schedule.conference.title, schedule.version]) }}</p>
<h2>{{ __('schedule.import.rooms.add') }}</h2>
{{ _self.roomsTable(rooms.add) }}
<h2>{{ __('schedule.import.locations.add') }}</h2>
{{ _self.locationsTable(locations.add) }}
<h2>{{ __('schedule.import.shifts.add') }}</h2>
{{ _self.shiftsTable(shifts.add) }}
@ -32,7 +32,7 @@
{% endblock %}
{% macro roomsTable(rooms) %}
{% macro locationsTable(locations) %}
<div class="table-responsive">
<table class="table table-striped">
<thead>
@ -42,9 +42,9 @@
</thead>
<tbody>
{% for room in rooms %}
{% for location in locations %}
<tr>
<td>{{ room.name }}</td>
<td>{{ location.name }}</td>
</tr>
{% endfor %}
</tbody>
@ -60,7 +60,7 @@
<th>{{ __('schedule.import.shift.dates') }}</th>
<th>{{ __('schedule.import.shift.type') }}</th>
<th>{{ __('title.title') }}</th>
<th>{{ __('schedule.import.shift.room') }}</th>
<th>{{ __('schedule.import.shift.location') }}</th>
</tr>
</thead>

View File

@ -13,7 +13,7 @@ DTEND:{{ entry.shift.end.utc().format(dateFormat) }}
STATUS:CONFIRMED
TRANSP:OPAQUE
SUMMARY:{{ (entry.shift.shiftType.name ~ ' (' ~ entry.shift.title ~ ')') | replace(replacement) | raw }}
LOCATION:{{ entry.shift.room.name | replace(replacement) | raw }}
LOCATION:{{ entry.shift.location.name | replace(replacement) | raw }}
DESCRIPTION:{{
(
entry.shift.shiftType.description

View File

@ -8,7 +8,7 @@
{{ name }}
{{ title }}
{{ start.format(__('Y-m-d H:i')) }} - {{ end.format(__('Y-m-d H:i')) }}
{{ room.name }}
{{ location.name }}
{% if start <= date() and not freeloaded %}
{{ __('notification.shift.deleted.worklog') }}

View File

@ -66,7 +66,7 @@
<div class="collapse show d-print-none" id="collapseShiftsFilterSelect">
<div class="row">
<div class="col col-12 col-sm-4 col-md-12 col-lg-5 col-xl-4 col-xxl-4">%room_select%</div>
<div class="col col-12 col-sm-4 col-md-12 col-lg-5 col-xl-4 col-xxl-4">%location_select%</div>
<div class="col col-12 col-sm-5 col-md-12 col-lg-7 col-xl-5 col-xxl-4">%type_select%</div>
<div class="col col-12 col-sm-3 col-md-12 col-lg-5 col-xl-3 col-xxl-4">%filled_select%</div>
</div>

View File

@ -12,23 +12,23 @@ use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Http\Validation\Validator;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Illuminate\Database\Eloquent\Collection;
use Psr\Log\LoggerInterface;
class RoomsController extends BaseController
class LocationsController extends BaseController
{
use HasUserNotifications;
/** @var array<string> */
protected array $permissions = [
'admin_rooms',
'admin_locations',
];
public function __construct(
protected LoggerInterface $log,
protected Room $room,
protected Location $location,
protected Redirector $redirect,
protected Response $response
) {
@ -36,31 +36,31 @@ class RoomsController extends BaseController
public function index(): Response
{
$rooms = $this->room
$locations = $this->location
->orderBy('name')
->get();
return $this->response->withView(
'admin/rooms/index',
['rooms' => $rooms, 'is_index' => true]
'admin/locations/index',
['locations' => $locations, 'is_index' => true]
);
}
public function edit(Request $request): Response
{
$roomId = (int) $request->getAttribute('room_id');
$locationId = (int) $request->getAttribute('location_id');
$room = $this->room->find($roomId);
$location = $this->location->find($locationId);
return $this->showEdit($room);
return $this->showEdit($location);
}
public function save(Request $request): Response
{
$roomId = (int) $request->getAttribute('room_id');
$locationId = (int) $request->getAttribute('location_id');
/** @var Room $room */
$room = $this->room->findOrNew($roomId);
/** @var Location $location */
$location = $this->location->findOrNew($locationId);
/** @var Collection|AngelType[] $angelTypes */
$angelTypes = AngelType::all();
$validation = [];
@ -82,17 +82,17 @@ class RoomsController extends BaseController
] + $validation
);
if (Room::whereName($data['name'])->where('id', '!=', $room->id)->exists()) {
if (Location::whereName($data['name'])->where('id', '!=', $location->id)->exists()) {
throw new ValidationException((new Validator())->addErrors(['name' => ['validation.name.exists']]));
}
$room->name = $data['name'];
$room->description = $data['description'];
$room->dect = $data['dect'];
$room->map_url = $data['map_url'];
$location->name = $data['name'];
$location->description = $data['description'];
$location->dect = $data['dect'];
$location->map_url = $data['map_url'];
$room->save();
$room->neededAngelTypes()->getQuery()->delete();
$location->save();
$location->neededAngelTypes()->getQuery()->delete();
$angelsInfo = '';
foreach ($angelTypes as $angelType) {
@ -103,7 +103,7 @@ class RoomsController extends BaseController
$neededAngelType = new NeededAngelType();
$neededAngelType->room()->associate($room);
$neededAngelType->location()->associate($location);
$neededAngelType->angelType()->associate($angelType);
$neededAngelType->count = $data['angel_type_' . $angelType->id];
@ -116,17 +116,17 @@ class RoomsController extends BaseController
$this->log->info(
'Updated location "{name}": {description} {dect} {map_url} {angels}',
[
'name' => $room->name,
'description' => $room->description,
'dect' => $room->dect,
'map_url' => $room->map_url,
'name' => $location->name,
'description' => $location->description,
'dect' => $location->dect,
'map_url' => $location->map_url,
'angels' => $angelsInfo,
]
);
$this->addNotification('room.edit.success');
$this->addNotification('location.edit.success');
return $this->redirect->to('/admin/rooms');
return $this->redirect->to('/admin/locations');
}
public function delete(Request $request): Response
@ -136,9 +136,9 @@ class RoomsController extends BaseController
'delete' => 'checked',
]);
$room = $this->room->findOrFail($data['id']);
$location = $this->location->findOrFail($data['id']);
$shifts = $room->shifts;
$shifts = $location->shifts;
foreach ($shifts as $shift) {
foreach ($shift->shiftEntries as $entry) {
event('shift.entry.deleting', [
@ -148,27 +148,31 @@ class RoomsController extends BaseController
'name' => $shift->shiftType->name,
'title' => $shift->title,
'type' => $entry->angelType->name,
'room' => $room,
'location' => $location,
'freeloaded' => $entry->freeloaded,
]);
}
}
$room->delete();
$location->delete();
$this->log->info('Deleted location {location}', ['location' => $room->name]);
$this->addNotification('room.delete.success');
$this->log->info('Deleted location {location}', ['location' => $location->name]);
$this->addNotification('location.delete.success');
return $this->redirect->to('/admin/rooms');
return $this->redirect->to('/admin/locations');
}
protected function showEdit(?Room $room): Response
protected function showEdit(?Location $location): Response
{
$angeltypes = AngelType::all()
->sortBy('name');
return $this->response->withView(
'admin/rooms/edit',
['room' => $room, 'angel_types' => $angeltypes, 'needed_angel_types' => $room?->neededAngelTypes]
'admin/locations/edit',
[
'location' => $location,
'angel_types' => $angeltypes,
'needed_angel_types' => $location?->neededAngelTypes,
]
);
}
}

View File

@ -95,12 +95,12 @@ class FeedController extends BaseController
// Talk URL
'URL' => $shift->url,
// Room id
'RID' => $shift->room->id,
// Room name
'Name' => $shift->room->name,
// Location (room) id
'RID' => $shift->location->id,
// Location (room) name
'Name' => $shift->location->name,
// Location map url
'map_url' => $shift->room->map_url,
'map_url' => $shift->location->map_url,
// Start timestamp
/** @deprecated start_date should be used */
@ -159,7 +159,7 @@ class FeedController extends BaseController
->shiftEntries()
->leftJoin('shifts', 'shifts.id', 'shift_entries.shift_id')
->orderBy('shifts.start')
->with(['shift', 'shift.room', 'shift.shiftType'])
->with(['shift', 'shift.location', 'shift.shiftType'])
->get(['*', 'shift_entries.id']);
}
}

View File

@ -132,7 +132,7 @@ class Controller extends BaseController
] + $userTshirtSizes,
'locales' => ['type' => 'gauge', 'help' => 'The locales users have configured'] + $userLocales,
'themes' => ['type' => 'gauge', 'help' => 'The themes users have configured'] + $userThemes,
'rooms' => ['type' => 'gauge', $this->stats->rooms()],
'locations' => ['type' => 'gauge', $this->stats->locations()],
'shifts' => ['type' => 'gauge', $this->stats->shifts()],
'announcements' => [
'type' => 'gauge',

View File

@ -14,7 +14,7 @@ use Engelsystem\Models\News;
use Engelsystem\Models\NewsComment;
use Engelsystem\Models\OAuth;
use Engelsystem\Models\Question;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\User\License;
use Engelsystem\Models\User\PasswordReset;
@ -291,9 +291,9 @@ class Stats
);
}
public function rooms(): int
public function locations(): int
{
return Room::query()
return Location::query()
->count();
}

View File

@ -20,7 +20,7 @@ class LegacyMiddleware implements MiddlewareInterface
'admin_event_config',
'angeltypes',
'public_dashboard',
'rooms',
'locations',
'shift_entries',
'shifts',
'users',
@ -98,8 +98,8 @@ class LegacyMiddleware implements MiddlewareInterface
case 'admin_event_config':
list($title, $content) = event_config_edit_controller();
return [$title, $content];
case 'rooms':
return rooms_controller();
case 'locations':
return locations_controller();
case 'user_myshifts':
$title = myshifts_title();
$content = user_myshifts();

View File

@ -24,15 +24,15 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property-read Collection|NeededAngelType[] $neededAngelTypes
* @property-read Collection|Shift[] $shifts
*
* @method static QueryBuilder|Room[] whereId($value)
* @method static QueryBuilder|Room[] whereName($value)
* @method static QueryBuilder|Room[] whereMapUrl($value)
* @method static QueryBuilder|Room[] whereDect($value)
* @method static QueryBuilder|Room[] whereDescription($value)
* @method static QueryBuilder|Room[] whereCreatedAt($value)
* @method static QueryBuilder|Room[] whereUpdatedAt($value)
* @method static QueryBuilder|Location[] whereId($value)
* @method static QueryBuilder|Location[] whereName($value)
* @method static QueryBuilder|Location[] whereMapUrl($value)
* @method static QueryBuilder|Location[] whereDect($value)
* @method static QueryBuilder|Location[] whereDescription($value)
* @method static QueryBuilder|Location[] whereCreatedAt($value)
* @method static QueryBuilder|Location[] whereUpdatedAt($value)
*/
class Room extends BaseModel
class Location extends BaseModel
{
use HasFactory;

View File

@ -6,24 +6,24 @@ namespace Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\BaseModel;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Query\Builder as QueryBuilder;
/**
* @property int $id
* @property int|null $room_id
* @property int|null $location_id
* @property int|null $shift_id
* @property int $angel_type_id
* @property int $count
*
* @property-read Room|null $room
* @property-read Location|null $location
* @property-read Shift|null $shift
* @property-read AngelType $angelType
*
* @method static QueryBuilder|NeededAngelType[] whereId($value)
* @method static QueryBuilder|NeededAngelType[] whereRoomId($value)
* @method static QueryBuilder|NeededAngelType[] whereLocationId($value)
* @method static QueryBuilder|NeededAngelType[] whereShiftId($value)
* @method static QueryBuilder|NeededAngelType[] whereAngelTypeId($value)
* @method static QueryBuilder|NeededAngelType[] whereCount($value)
@ -34,21 +34,21 @@ class NeededAngelType extends BaseModel
/** @var array<string, null> default attributes */
protected $attributes = [ // phpcs:ignore
'room_id' => null,
'location_id' => null,
'shift_id' => null,
];
/** @var array<string> */
protected $fillable = [ // phpcs:ignore
'room_id',
'location_id',
'shift_id',
'angel_type_id',
'count',
];
public function room(): BelongsTo
public function location(): BelongsTo
{
return $this->belongsTo(Room::class);
return $this->belongsTo(Location::class);
}
public function shift(): BelongsTo

View File

@ -6,7 +6,7 @@ namespace Engelsystem\Models\Shifts;
use Carbon\Carbon;
use Engelsystem\Models\BaseModel;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
@ -23,7 +23,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property Carbon $start
* @property Carbon $end
* @property int $shift_type_id
* @property int $room_id
* @property int $location_id
* @property string $transaction_id
* @property int $created_by
* @property int|null $updated_by
@ -34,7 +34,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property-read Schedule $schedule
* @property-read Collection|ShiftEntry[] $shiftEntries
* @property-read ShiftType $shiftType
* @property-read Room $room
* @property-read Location $location
* @property-read User $createdBy
* @property-read User|null $updatedBy
*
@ -45,7 +45,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @method static QueryBuilder|Shift[] whereStart($value)
* @method static QueryBuilder|Shift[] whereEnd($value)
* @method static QueryBuilder|Shift[] whereShiftTypeId($value)
* @method static QueryBuilder|Shift[] whereRoomId($value)
* @method static QueryBuilder|Shift[] whereLocationId($value)
* @method static QueryBuilder|Shift[] whereTransactionId($value)
* @method static QueryBuilder|Shift[] whereCreatedBy($value)
* @method static QueryBuilder|Shift[] whereUpdatedBy($value)
@ -70,7 +70,7 @@ class Shift extends BaseModel
/** @var array<string, string> */
protected $casts = [ // phpcs:ignore
'shift_type_id' => 'integer',
'room_id' => 'integer',
'location_id' => 'integer',
'created_by' => 'integer',
'updated_by' => 'integer',
'start' => 'datetime',
@ -85,7 +85,7 @@ class Shift extends BaseModel
'start',
'end',
'shift_type_id',
'room_id',
'location_id',
'transaction_id',
'created_by',
'updated_by',
@ -111,9 +111,9 @@ class Shift extends BaseModel
return $this->belongsTo(ShiftType::class);
}
public function room(): BelongsTo
public function location(): BelongsTo
{
return $this->belongsTo(Room::class);
return $this->belongsTo(Location::class);
}
public function createdBy(): BelongsTo

View File

@ -4,14 +4,14 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit\Controllers\Admin;
use Engelsystem\Controllers\Admin\RoomsController;
use Engelsystem\Controllers\Admin\LocationsController;
use Engelsystem\Events\EventDispatcher;
use Engelsystem\Helpers\Carbon;
use Engelsystem\Http\Exceptions\ValidationException;
use Engelsystem\Http\Redirector;
use Engelsystem\Http\Validation\Validator;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
@ -19,26 +19,26 @@ use Engelsystem\Models\User\User;
use Engelsystem\Test\Unit\Controllers\ControllerTest;
use PHPUnit\Framework\MockObject\MockObject;
class RoomsControllerTest extends ControllerTest
class LocationsControllerTest extends ControllerTest
{
protected Redirector|MockObject $redirect;
/**
* @covers \Engelsystem\Controllers\Admin\RoomsController::__construct
* @covers \Engelsystem\Controllers\Admin\RoomsController::index
* @covers \Engelsystem\Controllers\Admin\LocationsController::__construct
* @covers \Engelsystem\Controllers\Admin\LocationsController::index
*/
public function testIndex(): void
{
/** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class);
Room::factory(5)->create();
/** @var LocationsController $controller */
$controller = $this->app->make(LocationsController::class);
Location::factory(5)->create();
$this->response->expects($this->once())
->method('withView')
->willReturnCallback(function (string $view, array $data) {
$this->assertEquals('admin/rooms/index', $view);
$this->assertEquals('admin/locations/index', $view);
$this->assertTrue($data['is_index'] ?? false);
$this->assertCount(5, $data['rooms'] ?? []);
$this->assertCount(5, $data['locations'] ?? []);
return $this->response;
});
@ -46,48 +46,52 @@ class RoomsControllerTest extends ControllerTest
}
/**
* @covers \Engelsystem\Controllers\Admin\RoomsController::edit
* @covers \Engelsystem\Controllers\Admin\RoomsController::showEdit
* @covers \Engelsystem\Controllers\Admin\LocationsController::edit
* @covers \Engelsystem\Controllers\Admin\LocationsController::showEdit
*/
public function testEdit(): void
{
/** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class);
/** @var Room $room */
$room = Room::factory()->create();
/** @var LocationsController $controller */
$controller = $this->app->make(LocationsController::class);
/** @var Location $location */
$location = Location::factory()->create();
$angelTypes = AngelType::factory(3)->create();
(new NeededAngelType(['room_id' => $room->id, 'angel_type_id' => $angelTypes[0]->id, 'count' => 3]))->save();
(new NeededAngelType([
'location_id' => $location->id,
'angel_type_id' => $angelTypes[0]->id,
'count' => 3,
]))->save();
$this->response->expects($this->once())
->method('withView')
->willReturnCallback(function (string $view, array $data) use ($room) {
$this->assertEquals('admin/rooms/edit', $view);
$this->assertEquals($room->id, $data['room']?->id);
->willReturnCallback(function (string $view, array $data) use ($location) {
$this->assertEquals('admin/locations/edit', $view);
$this->assertEquals($location->id, $data['location']?->id);
$this->assertCount(3, $data['angel_types'] ?? []);
$this->assertCount(1, $data['needed_angel_types'] ?? []);
return $this->response;
});
$this->request = $this->request->withAttribute('room_id', 1);
$this->request = $this->request->withAttribute('location_id', 1);
$controller->edit($this->request);
}
/**
* @covers \Engelsystem\Controllers\Admin\RoomsController::edit
* @covers \Engelsystem\Controllers\Admin\RoomsController::showEdit
* @covers \Engelsystem\Controllers\Admin\LocationsController::edit
* @covers \Engelsystem\Controllers\Admin\LocationsController::showEdit
*/
public function testEditNew(): void
{
/** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class);
/** @var LocationsController $controller */
$controller = $this->app->make(LocationsController::class);
AngelType::factory(3)->create();
$this->response->expects($this->once())
->method('withView')
->willReturnCallback(function (string $view, array $data) {
$this->assertEquals('admin/rooms/edit', $view);
$this->assertEmpty($data['room'] ?? []);
$this->assertEquals('admin/locations/edit', $view);
$this->assertEmpty($data['location'] ?? []);
$this->assertCount(3, $data['angel_types'] ?? []);
$this->assertEmpty($data['needed_angel_types'] ?? []);
return $this->response;
@ -97,16 +101,16 @@ class RoomsControllerTest extends ControllerTest
}
/**
* @covers \Engelsystem\Controllers\Admin\RoomsController::save
* @covers \Engelsystem\Controllers\Admin\LocationsController::save
*/
public function testSave(): void
{
/** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class);
/** @var LocationsController $controller */
$controller = $this->app->make(LocationsController::class);
$controller->setValidator(new Validator());
AngelType::factory(3)->create();
$this->setExpects($this->redirect, 'to', ['/admin/rooms']);
$this->setExpects($this->redirect, 'to', ['/admin/locations']);
$this->request = $this->request->withParsedBody([
'name' => 'Testlocation',
@ -120,10 +124,10 @@ class RoomsControllerTest extends ControllerTest
$controller->save($this->request);
$this->assertTrue($this->log->hasInfoThatContains('Updated location'));
$this->assertHasNotification('room.edit.success');
$this->assertCount(1, Room::whereName('Testlocation')->get());
$this->assertHasNotification('location.edit.success');
$this->assertCount(1, Location::whereName('Testlocation')->get());
$neededAngelType = NeededAngelType::whereRoomId(1)
$neededAngelType = NeededAngelType::whereLocationId(1)
->where('angel_type_id', 2)
->where('count', 3)
->get();
@ -131,14 +135,14 @@ class RoomsControllerTest extends ControllerTest
}
/**
* @covers \Engelsystem\Controllers\Admin\RoomsController::save
* @covers \Engelsystem\Controllers\Admin\LocationsController::save
*/
public function testSaveUniqueName(): void
{
/** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class);
/** @var LocationsController $controller */
$controller = $this->app->make(LocationsController::class);
$controller->setValidator(new Validator());
Room::factory()->create(['name' => 'Testlocation']);
Location::factory()->create(['name' => 'Testlocation']);
$this->request = $this->request->withParsedBody([
'name' => 'Testlocation',
@ -149,16 +153,16 @@ class RoomsControllerTest extends ControllerTest
}
/**
* @covers \Engelsystem\Controllers\Admin\RoomsController::save
* @covers \Engelsystem\Controllers\Admin\RoomsController::delete
* @covers \Engelsystem\Controllers\Admin\LocationsController::save
* @covers \Engelsystem\Controllers\Admin\LocationsController::delete
*/
public function testSaveDelete(): void
{
/** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class);
/** @var LocationsController $controller */
$controller = $this->app->make(LocationsController::class);
$controller->setValidator(new Validator());
/** @var Room $room */
$room = Room::factory()->create();
/** @var Location $location */
$location = Location::factory()->create();
$this->request = $this->request->withParsedBody([
'id' => '1',
@ -166,36 +170,36 @@ class RoomsControllerTest extends ControllerTest
]);
$controller->save($this->request);
$this->assertEmpty(Room::find($room->id));
$this->assertEmpty(Location::find($location->id));
}
/**
* @covers \Engelsystem\Controllers\Admin\RoomsController::delete
* @covers \Engelsystem\Controllers\Admin\LocationsController::delete
*/
public function testDelete(): void
{
/** @var EventDispatcher|MockObject $dispatcher */
$dispatcher = $this->createMock(EventDispatcher::class);
$this->app->instance('events.dispatcher', $dispatcher);
/** @var RoomsController $controller */
$controller = $this->app->make(RoomsController::class);
/** @var LocationsController $controller */
$controller = $this->app->make(LocationsController::class);
$controller->setValidator(new Validator());
/** @var Room $room */
$room = Room::factory()->create();
/** @var Location $location */
$location = Location::factory()->create();
/** @var Shift $shift */
$shift = Shift::factory()->create(['room_id' => $room->id, 'start' => Carbon::create()->subHour()]);
$shift = Shift::factory()->create(['location_id' => $location->id, 'start' => Carbon::create()->subHour()]);
/** @var User $user */
$user = User::factory()->create(['name' => 'foo', 'email' => 'lorem@ipsum']);
/** @var ShiftEntry $shiftEntry */
ShiftEntry::factory()->create(['shift_id' => $shift->id, 'user_id' => $user->id]);
$this->setExpects($this->redirect, 'to', ['/admin/rooms'], $this->response);
$this->setExpects($this->redirect, 'to', ['/admin/locations'], $this->response);
$dispatcher->expects($this->once())
->method('dispatch')
->willReturnCallback(function (string $event, array $data) use ($room, $user) {
->willReturnCallback(function (string $event, array $data) use ($location, $user) {
$this->assertEquals('shift.entry.deleting', $event);
$this->assertEquals($room->id, $data['room']->id);
$this->assertEquals($location->id, $data['location']->id);
$this->assertEquals($user->id, $data['user']->id);
return [];
@ -205,9 +209,9 @@ class RoomsControllerTest extends ControllerTest
$controller->delete($this->request);
$this->assertNull(Room::find($room->id));
$this->assertNull(Location::find($location->id));
$this->assertTrue($this->log->hasInfoThatContains('Deleted location'));
$this->assertHasNotification('room.delete.success');
$this->assertHasNotification('location.delete.success');
}
public function setUp(): void

View File

@ -13,7 +13,7 @@ use Engelsystem\Models\News;
use Engelsystem\Models\NewsComment;
use Engelsystem\Models\OAuth;
use Engelsystem\Models\Question;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
use Engelsystem\Models\User\License;
@ -198,17 +198,17 @@ class StatsTest extends TestCase
}
/**
* @covers \Engelsystem\Controllers\Metrics\Stats::rooms
* @covers \Engelsystem\Controllers\Metrics\Stats::locations
*/
public function testRooms(): void
public function testLocations(): void
{
(new Room(['name' => 'Location 1']))->save();
(new Room(['name' => 'Second location']))->save();
(new Room(['name' => 'Another location']))->save();
(new Room(['name' => 'Old location']))->save();
(new Location(['name' => 'Location 1']))->save();
(new Location(['name' => 'Second location']))->save();
(new Location(['name' => 'Another location']))->save();
(new Location(['name' => 'Old location']))->save();
$stats = new Stats($this->database);
$this->assertEquals(4, $stats->rooms());
$this->assertEquals(4, $stats->locations());
}
/**

View File

@ -9,7 +9,7 @@ use Engelsystem\Models\Message;
use Engelsystem\Models\News;
use Engelsystem\Models\NewsComment;
use Engelsystem\Models\Question;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Schedule;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
@ -42,7 +42,7 @@ class FactoriesTest extends TestCase
[PasswordReset::class],
[PersonalData::class],
[Question::class],
[Room::class],
[Location::class],
[Schedule::class],
[ShiftEntry::class],
[Settings::class],
@ -65,7 +65,7 @@ class FactoriesTest extends TestCase
* @covers \Database\Factories\Engelsystem\Models\User\PasswordResetFactory
* @covers \Database\Factories\Engelsystem\Models\User\PersonalDataFactory
* @covers \Database\Factories\Engelsystem\Models\QuestionFactory
* @covers \Database\Factories\Engelsystem\Models\RoomFactory
* @covers \Database\Factories\Engelsystem\Models\LocationFactory
* @covers \Database\Factories\Engelsystem\Models\Shifts\ScheduleFactory
* @covers \Database\Factories\Engelsystem\Models\User\SettingsFactory
* @covers \Database\Factories\Engelsystem\Models\Shifts\ShiftFactory

View File

@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Test\Unit\Models;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Collection;
class LocationTest extends ModelTest
{
/**
* @covers \Engelsystem\Models\Location::shifts
*/
public function testShifts(): void
{
$location = new Location(['name' => 'Test location']);
$location->save();
/** @var Shift $shift */
Shift::factory()->create(['location_id' => 1]);
$location = Location::find(1);
$this->assertCount(1, $location->shifts);
}
/**
* @covers \Engelsystem\Models\Location::neededAngelTypes
*/
public function testNeededAngelTypes(): void
{
/** @var Collection|Location[] $shifts */
$shifts = Location::factory(3)->create();
$this->assertCount(0, Location::find(1)->neededAngelTypes);
(NeededAngelType::factory()->make(['location_id' => $shifts[0]->id, 'shift_id' => null]))->save();
(NeededAngelType::factory()->make(['location_id' => $shifts[0]->id, 'shift_id' => null]))->save();
(NeededAngelType::factory()->make(['location_id' => $shifts[1]->id, 'shift_id' => null]))->save();
(NeededAngelType::factory()->make(['location_id' => $shifts[2]->id, 'shift_id' => null]))->save();
$this->assertCount(2, Location::find(1)->neededAngelTypes);
$this->assertEquals(1, Location::find(1)->neededAngelTypes[0]->id);
$this->assertEquals(2, Location::find(1)->neededAngelTypes[1]->id);
$this->assertEquals(3, Location::find(2)->neededAngelTypes->first()->id);
$this->assertEquals(4, Location::find(3)->neededAngelTypes->first()->id);
}
}

View File

@ -1,50 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Test\Unit\Models;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Collection;
class RoomTest extends ModelTest
{
/**
* @covers \Engelsystem\Models\Room::shifts
*/
public function testShifts(): void
{
$room = new Room(['name' => 'Test location']);
$room->save();
/** @var Shift $shift */
Shift::factory()->create(['room_id' => 1]);
$room = Room::find(1);
$this->assertCount(1, $room->shifts);
}
/**
* @covers \Engelsystem\Models\Room::neededAngelTypes
*/
public function testNeededAngelTypes(): void
{
/** @var Collection|Room[] $shifts */
$shifts = Room::factory(3)->create();
$this->assertCount(0, Room::find(1)->neededAngelTypes);
(NeededAngelType::factory()->make(['room_id' => $shifts[0]->id, 'shift_id' => null]))->save();
(NeededAngelType::factory()->make(['room_id' => $shifts[0]->id, 'shift_id' => null]))->save();
(NeededAngelType::factory()->make(['room_id' => $shifts[1]->id, 'shift_id' => null]))->save();
(NeededAngelType::factory()->make(['room_id' => $shifts[2]->id, 'shift_id' => null]))->save();
$this->assertCount(2, Room::find(1)->neededAngelTypes);
$this->assertEquals(1, Room::find(1)->neededAngelTypes[0]->id);
$this->assertEquals(2, Room::find(1)->neededAngelTypes[1]->id);
$this->assertEquals(3, Room::find(2)->neededAngelTypes->first()->id);
$this->assertEquals(4, Room::find(3)->neededAngelTypes->first()->id);
}
}

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Test\Unit\Models\ModelTest;
@ -13,28 +13,28 @@ use Engelsystem\Test\Unit\Models\ModelTest;
class NeededAngelTypeTest extends ModelTest
{
/**
* @covers \Engelsystem\Models\Shifts\NeededAngelType::room
* @covers \Engelsystem\Models\Shifts\NeededAngelType::location
* @covers \Engelsystem\Models\Shifts\NeededAngelType::shift
* @covers \Engelsystem\Models\Shifts\NeededAngelType::angelType
*/
public function testShift(): void
{
/** @var Room $room */
$room = Room::factory()->create();
/** @var Location $location */
$location = Location::factory()->create();
/** @var Shift $shift */
$shift = Shift::factory()->create();
/** @var AngelType $angelType */
$angelType = AngelType::factory()->create();
$model = new NeededAngelType();
$model->room()->associate($room);
$model->location()->associate($location);
$model->shift()->associate($shift);
$model->angelType()->associate($angelType);
$model->count = 3;
$model->save();
$model = NeededAngelType::find(1);
$this->assertEquals($room->id, $model->room->id);
$this->assertEquals($location->id, $model->location->id);
$this->assertEquals($shift->id, $model->shift->id);
$this->assertEquals($angelType->id, $model->angelType->id);
$this->assertEquals(3, $model->count);

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit\Models\Shifts;
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\Room;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Schedule;
use Engelsystem\Models\Shifts\ScheduleShift;
@ -20,7 +20,7 @@ class ShiftTest extends ModelTest
{
/**
* @covers \Engelsystem\Models\Shifts\Shift::shiftType
* @covers \Engelsystem\Models\Shifts\Shift::room
* @covers \Engelsystem\Models\Shifts\Shift::location
* @covers \Engelsystem\Models\Shifts\Shift::createdBy
* @covers \Engelsystem\Models\Shifts\Shift::updatedBy
*/
@ -32,8 +32,8 @@ class ShiftTest extends ModelTest
$user2 = User::factory()->create();
/** @var ShiftType $shiftType */
$shiftType = ShiftType::factory()->create();
/** @var Room $room */
$room = Room::factory()->create();
/** @var Location $location */
$location = Location::factory()->create();
$model = new Shift([
'title' => 'Test shift',
@ -42,7 +42,7 @@ class ShiftTest extends ModelTest
'start' => Carbon::now(),
'end' => Carbon::now(),
'shift_type_id' => $shiftType->id,
'room_id' => $room->id,
'location_id' => $location->id,
'transaction_id' => '',
'created_by' => $user1->id,
'updated_by' => $user2->id,
@ -52,7 +52,7 @@ class ShiftTest extends ModelTest
$model = Shift::find(1);
$this->assertEquals($shiftType->id, $model->shiftType->id);
$this->assertEquals($room->id, $model->room->id);
$this->assertEquals($location->id, $model->location->id);
$this->assertEquals($user1->id, $model->createdBy->id);
$this->assertEquals($user2->id, $model->updatedBy->id);
}
@ -67,10 +67,10 @@ class ShiftTest extends ModelTest
$this->assertCount(0, Shift::find(1)->neededAngelTypes);
(NeededAngelType::factory()->make(['shift_id' => $shifts[0]->id, 'room_id' => null]))->save();
(NeededAngelType::factory()->make(['shift_id' => $shifts[0]->id, 'room_id' => null]))->save();
(NeededAngelType::factory()->make(['shift_id' => $shifts[1]->id, 'room_id' => null]))->save();
(NeededAngelType::factory()->make(['shift_id' => $shifts[2]->id, 'room_id' => null]))->save();
(NeededAngelType::factory()->make(['shift_id' => $shifts[0]->id, 'location_id' => null]))->save();
(NeededAngelType::factory()->make(['shift_id' => $shifts[0]->id, 'location_id' => null]))->save();
(NeededAngelType::factory()->make(['shift_id' => $shifts[1]->id, 'location_id' => null]))->save();
(NeededAngelType::factory()->make(['shift_id' => $shifts[2]->id, 'location_id' => null]))->save();
$this->assertCount(2, Shift::find(1)->neededAngelTypes);
$this->assertEquals(1, Shift::find(1)->neededAngelTypes[0]->id);