Added room selection for schedules
This commit is contained in:
parent
197d0d724a
commit
caa699ff05
|
@ -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');
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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."
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue