Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beobachtungsaufträge #147

Merged
merged 35 commits into from
Oct 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
80e38d2
Define Model & Relationsships
allanbenelli Sep 4, 2020
35b3f66
migration: table and foreign keys
allanbenelli Sep 4, 2020
72368ce
prepare controller with index, edit & destroy
allanbenelli Sep 4, 2020
5f50be5
prepare routes
allanbenelli Sep 4, 2020
ae0ec53
view:index new part and translations
allanbenelli Sep 4, 2020
7968bd8
add order_desc and change to entity
allanbenelli Sep 4, 2020
0d497d5
adjusted view
allanbenelli Sep 4, 2020
1977b19
controller rules
allanbenelli Sep 4, 2020
ff3d442
rechanged models but still not working
allanbenelli Sep 5, 2020
6aca874
navigation linking
allanbenelli Sep 15, 2020
35fcacd
fix column naming, create orders
allanbenelli Sep 15, 2020
beae5f9
overwiev and create observation_group
allanbenelli Sep 15, 2020
5d883dd
edit observation order view
allanbenelli Sep 15, 2020
aa33f2f
edit and save observation order finished
allanbenelli Sep 15, 2020
36f2b58
for cosinus, don't mind about test
allanbenelli Sep 23, 2020
e7278ff
cosinus commit to peerfix
allanbenelli Sep 25, 2020
5dbd53b
fix blocknumber bug in observationassignment table
allanbenelli Sep 25, 2020
1646c02
base on course
allanbenelli Sep 25, 2020
92db07c
button success logic, but obs count wrong
allanbenelli Sep 25, 2020
05e6f73
course model return view for crib
allanbenelli Sep 26, 2020
13a4368
Revert file permissions
carlobeltrame Oct 2, 2020
e83ea1b
Get it running with the latest Vue components updates
carlobeltrame Oct 2, 2020
4eeb83f
Make trainer perspective selectable on crib view
carlobeltrame Oct 2, 2020
5cdff43
Rename observation orders to observation assignments
carlobeltrame Oct 2, 2020
05a2937
Fix plural names of fields
carlobeltrame Oct 2, 2020
db8fc99
Rename order_name to name
carlobeltrame Oct 2, 2020
a076eae
Add tests for observation assignments
carlobeltrame Oct 2, 2020
a646315
Redesign a little with help from @manuelmeister
carlobeltrame Oct 2, 2020
cce590a
Add test for the mother of all queries
carlobeltrame Oct 2, 2020
689ff4c
Load observation assignments only in the course that they belong to
carlobeltrame Oct 2, 2020
107eff6
Improve layout and only show stuff related to observation assignments…
carlobeltrame Oct 5, 2020
3dd4c94
Include a multi-participant observation in the test for the mother query
carlobeltrame Oct 5, 2020
d6750f5
Automatically return to crib after creating an observation from there
carlobeltrame Oct 5, 2020
ec86cc8
Adapt E2E test to changed translation
carlobeltrame Oct 7, 2020
4b9e5e1
Allow to select entire days for observation assignments
carlobeltrame Oct 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions app/Http/Controllers/BlockListController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
namespace App\Http\Controllers;

use App\Models\Course;
use App\Models\User;
use App\Util\HtmlString;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;

class BlockListController extends Controller
{
Expand All @@ -20,14 +23,24 @@ public function index(Course $course)
}

/**
* Display the crib page which visualizes connections between blocks and requirements.
* Display the crib page which visualizes connections between blocks and requirements, as well as observation assignments.
*
* @param Request $request
* @param Course $course
* @param User $user
* @return Response
*/
public function crib(Course $course)
public function crib(Request $request, Course $course, User $user)
{
return view('crib', ['blockManagementLink' => $this->blockManagementLink($course, 't.views.crib.here')]);
$userId = $user->id ?? Auth::id();
$request->session()->flash('return_url', $request->url());
return view('crib', [
'blockManagementLink' => $this->blockManagementLink($course, 't.views.crib.here'),
'showObservationAssignments' => $course->observationAssignments()->count(),
'userId' => $userId,
'trainerObservationAssignments' => $course->observationAssignmentsPerUserAndPerBlock()[$userId] ?? [],
'neededObservations' => 1,
]);
}

/**
Expand Down
109 changes: 109 additions & 0 deletions app/Http/Controllers/ObservationAssignmentController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

namespace App\Http\Controllers;

use App\Http\Requests\ObservationAssignmentRequest;
use App\Models\Course;
use App\Models\ObservationAssignment;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redirect;


class ObservationAssignmentController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
return view('admin.observationAssignments.index');
}


/**
* Store a newly created resource in storage.
*
* @param ObservationAssignmentRequest $request
* @param Course $course

* @return RedirectResponse
*/
public function store(ObservationAssignmentRequest $request, Course $course)
{
$data = $request->validated();

DB::transaction(function() use ($request,$course, $data){

$observationAssignment = ObservationAssignment::create(array_merge($data, ['course_id' => $course->id]));

$observationAssignment->participants()->attach(array_filter(explode(',', $data['participants'])));
$observationAssignment->blocks()->attach(array_filter(explode(',', $data['blocks'])));
$observationAssignment->users()->attach(array_filter(explode(',', $data['users'])));

$request->session()->flash('alert-success', __('t.views.admin.observation_assignments.create_success'));
});

return Redirect::route('admin.observationAssignments', ['course' => $course->id]);

}


/**
* Show the form for editing the specified resource.
* @param Course $course
* @param ObservationAssignment $observationAssignment
* @return \Illuminate\Http\Response
*/
public function edit(Course $course, ObservationAssignment $observationAssignment)
{
return view('admin.observationAssignments.edit', ['observationAssignment' => $observationAssignment]);
}

/**
* Update the specified resource in storage.
*
*
* @param ObservationAssignmentRequest $request
* @param Course $course
* @param ObservationAssignment $observationAssignment
* @return RedirectResponse
*/
public function update(ObservationAssignmentRequest $request, Course $course, ObservationAssignment $observationAssignment)
{
DB::transaction(function () use ($request, $course, $observationAssignment) {
$data = $request->validated();

$observationAssignment->update($data);
$observationAssignment->participants()->detach(null);
$observationAssignment->participants()->attach(array_filter(explode(',', $data['participants'])));
$observationAssignment->blocks()->detach(null);
$observationAssignment->blocks()->attach(array_filter(explode(',', $data['blocks'])));
$observationAssignment->users()->detach(null);
$observationAssignment->users()->attach(array_filter(explode(',', $data['users'])));
$request->session()->flash('alert-success', __('t.views.admin.observation_assignments.edit_success'));
});
return Redirect::route('admin.observationAssignments', ['course' => $course->id]);

}

/**
* Remove the specified resource from storage.
*
* @param Request $request
* @param Course $course
* @param ObservationAssignment $observationAssignment
* @return RedirectResponse
*
*/
public function destroy(Request $request, Course $course, ObservationAssignment $observationAssignment)
{
$observationAssignment->delete();
$request->session()->flash('alert-success', __('t.views.admin.observation_assignments.delete_success'));
return Redirect::route('admin.observationAssignments', ['course' => $course->id]);

}
}
15 changes: 11 additions & 4 deletions app/Http/Controllers/ObservationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ObservationController extends Controller {
* @return Response
*/
public function create(Request $request) {
$this->rememberPreviouslyActiveView($request);
return view('observation.new', ['participants' => $request->input('participant'), 'block' => $request->input('block')]);
}

Expand All @@ -51,13 +52,14 @@ public function store(ObservationRequest $request, Course $course) {
$participant = $observation->participants()->first();
$route = route('participants.detail', ['course' => $course->id, 'participant' => $participant->id]);
$flash->s(" <a href=\"{$route}\">")
->__('t.views.observations.back_to_participant', ['name' => $participant->scout_name])
->__('t.views.observations.go_to_participant', ['name' => $participant->scout_name])
->s(' <i class="fas fa-arrow-right"></i></a>');
}

$request->session()->flash('alert-success', $flash);
});

return Redirect::route('observation.new', ['course' => $course->id, 'participant' => $data['participants'], 'block' => $data['block']]);
return $this->redirectToPreviouslyActiveView($request, $course, collect([]), route('observation.new', ['course' => $course->id, 'participant' => $data['participants'], 'block' => $data['block']]));
}

/**
Expand All @@ -80,6 +82,7 @@ public function edit(Request $request, Course $course, Observation $observation)
*/
protected function rememberPreviouslyActiveView(Request $request) {
$returnTo = $this->extractPathParameter(URL::previous(), 'participants.detail', 'participant');
$request->session()->keep(['return_url']);
$request->session()->flash('participant_before_edit', $request->session()->get('participant_before_edit', $returnTo));
}

Expand All @@ -90,15 +93,19 @@ protected function rememberPreviouslyActiveView(Request $request) {
* @param Request $request
* @param Course $course
* @param Collection $returnOptions a collection of participant ids that are legal to be viewed
* @param string|null $fallback
* @return RedirectResponse
*/
protected function redirectToPreviouslyActiveView(Request $request, Course $course, Collection $returnOptions) {
protected function redirectToPreviouslyActiveView(Request $request, Course $course, Collection $returnOptions, $fallback = null) {
if ($request->session()->has('return_url')) return Redirect::to($request->session()->get('return_url'));

$returnTo = $request->session()->get('participant_before_edit');
if (!$returnOptions->contains($returnTo)) {
$returnTo = $returnOptions->first();
}

return Redirect::to(route('participants.detail', ['course' => $course->id, 'participant' => $returnTo]));
if ($returnTo) return Redirect::to(route('participants.detail', ['course' => $course->id, 'participant' => $returnTo]));
return Redirect::to($fallback ?? URL::previous());
}

/**
Expand Down
3 changes: 0 additions & 3 deletions app/Http/Controllers/ParticipantDetailController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@

namespace App\Http\Controllers;

use App\Models\Category;
use App\Models\Course;
use App\Models\Observation;
use App\Models\Participant;
use App\Models\Quali;
use App\Models\Requirement;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

Expand Down
38 changes: 38 additions & 0 deletions app/Http/Requests/ObservationAssignmentRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Http\Requests;

use App\Models\Trainer;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Lang;


class ObservationAssignmentRequest extends FormRequest {
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() {
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules() {
return [
'name' => 'required|max:1023',
'blocks' => 'required|regex:/^\d+(,\d+)*$/|allExistInCourse',
'participants' => 'required|regex:/^\d+(,\d+)*$/|allExistInCourse',
'users' => 'required|regex:/^\d+(,\d+)*$/|allExistInCourse:' . Trainer::class . ',user_id'
];
}


public function attributes() {
return Lang::get('t.models.observation_assignment');
}
}
48 changes: 48 additions & 0 deletions app/Models/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
* @property Collection $requirement_ids
* @property Course $course
* @property Observation[] $observations
* @property ObservationAssignment[] $observationAssignments
* @property Collection $requirements
* @property Collection $requirementIds
* @property int $num_observations
*/
Expand Down Expand Up @@ -61,6 +63,52 @@ public function course() {
public function observations() {
return $this->hasMany('App\Models\Observation');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function observationsWithParticipants(){

return $this->hasMany('App\Models\Observation')->with('participants');

}


public function observationsMultipleParticipantsId(){

return $this->hasMany('App\Models\Observation')->with('participants:id');


}
public function observationsMultipleParticipants(){
return $this->observationsMultipleParticipantsId();

foreach ($o as $obs){
$obj=array_push($obs->participants->map(function ($o){
return $o->pluck('id');
}));
}
return $obj;
$obj->participants->map(function ($participant){return $participant->pluck('id');});
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function observationAssignments() {
return $this->belongsToMany('App\Models\ObservationAssignment', 'observation_assignment_blocks')->with('users', 'participants');
}


public function observationAssignmentsPerUser() {
return $this->course->participants()->select(['users.id as user_id', 'participants.*'])->distinct()
->join('observation_assignment_participants', 'participants.id', 'observation_assignment_participants.participant_id')
->join('observation_assignment_users', 'observation_assignment_participants.observation_assignment_id', 'observation_assignment_users.observation_assignment_id')
->join('observation_assignment_blocks', 'observation_assignment_participants.observation_assignment_id', 'observation_assignment_blocks.observation_assignment_id')
->join('users', 'users.id', 'observation_assignment_users.user_id')
->join('trainers', 'users.id', 'trainers.user_id')
->mergeConstraintsFrom($this->course->users()->getQuery())
->where('observation_assignment_blocks.block_id', $this->id)->get()
->groupBy('user_id');
}

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
Expand Down
47 changes: 47 additions & 0 deletions app/Models/Course.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Models;

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

/**
* @property int $id
Expand All @@ -25,6 +26,8 @@ class Course extends Model {
* @var array
*/
protected $fillable = ['name', 'course_number', 'archived'];
protected $observationAssignments;


/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
Expand Down Expand Up @@ -60,7 +63,51 @@ public function participantGroups()
{
return $this->hasMany('App\Models\ParticipantGroup', 'course_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function observationAssignments()
{
return $this->hasMany('App\Models\ObservationAssignment', 'course_id');
}

public function observationAssignmentsPerUserAndPerBlock() {
if (!$this->observationAssignments) {
$observationAssignmentsQuery = ObservationAssignment::select([
'users.id as user_id',
'observation_assignment_blocks.block_id as block_id',
DB::raw('COUNT(DISTINCT observations.id) as observation_count'),
'participants.id as participant_id'
])->distinct()
->join('observation_assignment_participants', 'observation_assignments.id', 'observation_assignment_participants.observation_assignment_id')
->join('observation_assignment_users', 'observation_assignments.id', 'observation_assignment_users.observation_assignment_id')
->join('observation_assignment_blocks', 'observation_assignments.id', 'observation_assignment_blocks.observation_assignment_id')
->join('users', 'users.id', 'observation_assignment_users.user_id')
->join('participants', 'participants.id', 'observation_assignment_participants.participant_id')
->leftJoin('observations_participants', 'participants.id', 'observations_participants.participant_id')
->leftJoin('observations', function($join) {
$join->on('observations.id', 'observations_participants.observation_id');
$join->on('observations.block_id', 'observation_assignment_blocks.block_id');
$join->on('observations.user_id', 'users.id');
})
->join('trainers', 'users.id', 'trainers.user_id')
->mergeConstraintsFrom($this->users()->getQuery())
->groupBy('user_id', 'block_id', 'participant_id');

$this->observationAssignments = $this->participants()->select([
'query.user_id as user_id',
'query.block_id as block_id',
'query.observation_count as observation_count',
'participants.*'
])->joinSub($observationAssignmentsQuery, 'query', function ($join) {
$join->on('participants.id', 'query.participant_id');
})->get()
->groupBy('user_id')
->map->groupBy('block_id');
}

return $this->observationAssignments;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
Expand Down
Loading