Added room selection for schedules

This commit is contained in:
Igor Scheller 2023-12-27 03:18:05 +01:00 committed by msquare
parent 197d0d724a
commit caa699ff05
9 changed files with 185 additions and 41 deletions

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateScheduleLocationsTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('schedule_locations', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'schedules');
$this->references($table, 'locations');
$table->index(['schedule_id', 'location_id']);
});
$scheduleLocations = $connection
->table('schedule_shift')
->select(['schedules.id AS schedule_id', 'locations.id AS location_id'])
->leftJoin('schedules', 'schedules.id', 'schedule_shift.schedule_id')
->leftJoin('shifts', 'shifts.id', 'schedule_shift.shift_id')
->leftJoin('locations', 'locations.id', 'shifts.location_id')
->groupBy(['schedules.id', 'locations.id'])
->get();
foreach ($scheduleLocations as $scheduleLocation) {
$connection->table('schedule_locations')
->insert((array)$scheduleLocation);
}
}
/**
* Drops the table
*/
public function down(): void
{
$this->schema->drop('schedule_locations');
}
}

View File

@ -92,13 +92,14 @@ class ImportSchedule extends BaseController
{
$scheduleId = $request->getAttribute('schedule_id'); // optional
$schedule = ScheduleUrl::find($scheduleId);
$schedule = ScheduleUrl::findOrFail($scheduleId);
return $this->response->withView(
'admin/schedule/edit.twig',
[
'schedule' => $schedule,
'shift_types' => ShiftType::all()->pluck('name', 'id'),
'shift_types' => ShiftType::all()->sortBy('name')->pluck('name', 'id'),
'locations' => Location::all()->sortBy('name')->pluck('name', 'id'),
]
);
}
@ -114,6 +115,12 @@ class ImportSchedule extends BaseController
return $this->delete($schedule);
}
$locationsList = Location::all()->pluck('id');
$locationsValidation = [];
foreach ($locationsList as $id) {
$locationsValidation['location_' . $id] = 'optional|checked';
}
$data = $this->validate($request, [
'name' => 'required',
'url' => 'required',
@ -121,7 +128,7 @@ class ImportSchedule extends BaseController
'needed_from_shift_type' => 'optional|checked',
'minutes_before' => 'int',
'minutes_after' => 'int',
]);
] + $locationsValidation);
if (!ShiftType::find($data['shift_type'])) {
throw new ErrorException('schedule.import.invalid-shift-type');
@ -135,9 +142,22 @@ class ImportSchedule extends BaseController
$schedule->minutes_after = $data['minutes_after'];
$schedule->save();
$schedule->activeLocations()->detach();
$for = new Collection();
foreach ($locationsList as $id) {
if (!$data['location_' . $id]) {
continue;
}
$location = Location::find($id);
$schedule->activeLocations()->attach($location);
$for[] = $location->name;
}
$this->log->info(
'Schedule {name}: Url {url}, Shift Type {shift_type}, ({need}), minutes before/after {before}/{after}',
'Schedule {name}: Url {url}, Shift Type {shift_type}, ({need}), '
. 'minutes before/after {before}/{after}, for: {locations}',
[
'name' => $schedule->name,
'url' => $schedule->name,
@ -145,6 +165,7 @@ class ImportSchedule extends BaseController
'need' => $schedule->needed_from_shift_type ? 'from shift type' : 'from room',
'before' => $schedule->minutes_before,
'after' => $schedule->minutes_after,
'locations' => $for->implode(', '),
]
);
@ -509,6 +530,10 @@ class ImportSchedule extends BaseController
foreach ($schedule->getDay() as $day) {
foreach ($day->getRoom() as $room) {
if (!$scheduleUrl->activeLocations->where('name', $room->getName())->count()) {
continue;
}
foreach ($room->getEvent() as $event) {
$scheduleEvents[$event->getGuid()] = $event;

View File

@ -1441,6 +1441,9 @@ msgstr "Minuten vor Talk beginn hinzufügen"
msgid "schedule.minutes-after"
msgstr "Minuten nach Talk ende hinzufügen"
msgid "schedule.for_locations"
msgstr "Für Orte"
msgid "schedule.import.locations.add"
msgstr "Neue Orte"

View File

@ -163,6 +163,9 @@ msgstr "Add minutes before talk begins"
msgid "schedule.minutes-after"
msgstr "Add minutes after talk ends"
msgid "schedule.for_locations"
msgstr "For locations"
msgid "schedule.import.request_error"
msgstr "Unable to load schedule."

View File

@ -12,50 +12,63 @@
{% block row_content %}
{% if schedule and schedule.updated_at %}
<div class="col-md-12">
<p>{{ __('schedule.last_update', [schedule.updated_at.format(__('general.datetime'))]) }}</p>
<p>{{ __('schedule.last_update', [schedule.updated_at.format(__('general.datetime'))]) }}</p>
</div>
{% endif %}
<form method="post">
{{ csrf() }}
<div class="col-lg-12">
{{ f.input('name', __('schedule.name'), {
'required': true,
'value': schedule ? schedule.name : '',
}) }}
{{ f.input('url', __('schedule.url'), {
'type': 'url',
'required': true,
'value': schedule ? schedule.url : ''
}) }}
{{ f.select('shift_type', __('schedule.shift-type'), shift_types|default([]), {
'selected': schedule ? schedule.shift_type : '',
}) }}
{{ f.checkbox('needed_from_shift_type', __('schedule.needed-from-shift-type'), {
'checked': schedule ? schedule.needed_from_shift_type : '',
}) }}
{{ f.input('minutes_before', __('schedule.minutes-before'), {
'type': 'number',
'required': true,
'value': schedule ? schedule.minutes_before : 15
}) }}
{{ f.input('minutes_after', __('schedule.minutes-after'), {
'type': 'number',
'required': true,
'value': schedule ? schedule.minutes_after : 15
}) }}
{{ f.save(__('form.save')) }}
{% if schedule %}
{{ f.delete(__('form.delete'), {
'confirm_title': __('schedule.delete.title', [schedule.shifts|length])
<div class="row">
<div class="col-md-6">
{{ f.input('name', __('schedule.name'), {
'required': true,
'value': schedule ? schedule.name : '',
}) }}
{% endif %}
{{ f.input('url', __('schedule.url'), {
'type': 'url',
'required': true,
'value': schedule ? schedule.url : ''
}) }}
{{ f.select('shift_type', __('schedule.shift-type'), shift_types|default([]), {
'selected': schedule ? schedule.shift_type : '',
}) }}
{{ f.checkbox('needed_from_shift_type', __('schedule.needed-from-shift-type'), {
'checked': schedule ? schedule.needed_from_shift_type : '',
}) }}
{{ f.input('minutes_before', __('schedule.minutes-before'), {
'type': 'number',
'required': true,
'value': schedule ? schedule.minutes_before : 15
}) }}
{{ f.input('minutes_after', __('schedule.minutes-after'), {
'type': 'number',
'required': true,
'value': schedule ? schedule.minutes_after : 15
}) }}
{{ f.save(__('form.save')) }}
{% if schedule %}
{{ f.delete(__('form.delete'), {
'confirm_title': __('schedule.delete.title', [schedule.shifts|length])
}) }}
{% endif %}
</div>
<div class="col-md-6">
<h3>{{ __('schedule.for_locations') }}</h3>
<div class="row">
{% for id,name in locations %}
<div class="col-md-3">
{{ f.checkbox('location_' ~ id, name, {'checked': id in schedule.activeLocations.pluck('id')}) }}
</div>
{% endfor %}
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -6,9 +6,11 @@ namespace Engelsystem\Models;
use Carbon\Carbon;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Schedule;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Query\Builder as QueryBuilder;
@ -21,6 +23,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property-read Collection|Schedule[] $activeForSchedules
* @property-read Collection|NeededAngelType[] $neededAngelTypes
* @property-read Collection|Shift[] $shifts
*
@ -54,6 +57,11 @@ class Location extends BaseModel
'description',
];
public function activeForSchedules(): BelongsToMany
{
return $this->belongsToMany(Schedule::class, 'schedule_locations');
}
public function neededAngelTypes(): HasMany
{
return $this->hasMany(NeededAngelType::class);

View File

@ -6,9 +6,11 @@ namespace Engelsystem\Models\Shifts;
use Carbon\Carbon;
use Engelsystem\Models\BaseModel;
use Engelsystem\Models\Location;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Query\Builder as QueryBuilder;
@ -24,6 +26,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* @property Carbon $created_at
* @property Carbon $updated_at
*
* @property-read QueryBuilder|Location[] $activeLocations
* @property-read QueryBuilder|Collection|Shift[] $shifts
* @property-read QueryBuilder|Collection|ScheduleShift[] $scheduleShifts
* @property-read QueryBuilder|ShiftType $shiftType
@ -63,6 +66,11 @@ class Schedule extends BaseModel
'minutes_after',
];
public function activeLocations(): BelongsToMany
{
return $this->belongsToMany(Location::class, 'schedule_locations');
}
public function scheduleShifts(): HasMany
{
return $this->hasMany(ScheduleShift::class);

View File

@ -6,11 +6,27 @@ namespace Engelsystem\Test\Unit\Models;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Schedule;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Collection;
class LocationTest extends ModelTest
{
/**
* @covers \Engelsystem\Models\Location::activeForSchedules
*/
public function testActiveForSchedules(): void
{
$location = new Location(['name' => 'Test location']);
$location->save();
$schedule = Schedule::factory()->create();
$location->activeForSchedules()->attach($schedule);
$location = Location::find($location->id);
$this->assertCount(1, $location->activeForSchedules);
}
/**
* @covers \Engelsystem\Models\Location::shifts
*/

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit\Models\Shifts;
use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Schedule;
use Engelsystem\Models\Shifts\ScheduleShift;
use Engelsystem\Models\Shifts\Shift;
@ -22,6 +23,21 @@ class ScheduleTest extends ModelTest
'minutes_after' => 10,
];
/**
* @covers \Engelsystem\Models\Shifts\Schedule::activeLocations
*/
public function testActiveLocations(): void
{
$schedule = new Schedule($this->data);
$schedule->save();
$location = Location::factory()->create();
$schedule->activeLocations()->attach($location);
$schedule = Schedule::find($schedule->id);
$this->assertCount(1, $schedule->activeLocations);
}
/**
* @covers \Engelsystem\Models\Shifts\Schedule::scheduleShifts
*/