Skip to content
Open
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
85f8776
Removing role table from codebase
yannik131 Aug 25, 2026
6969cf0
further replacing roles with enum
yannik131 Aug 26, 2026
d8c9c82
further replacing roles with enum
yannik131 Aug 26, 2026
9f75cb6
Fixed remaining role tests
yannik131 Aug 26, 2026
daccf56
formatting
yannik131 Aug 26, 2026
0f62736
fixed linter errors
yannik131 Aug 26, 2026
fcaf783
made down() recreate FKs
yannik131 Aug 26, 2026
22157ad
Moved Role to Enums folder
yannik131 Aug 26, 2026
439e854
composer fix
yannik131 Aug 26, 2026
e5718e4
media_type enum and migration
yannik131 Aug 27, 2026
09beb1a
todo comments
yannik131 Aug 27, 2026
ee19c9b
replace MediaType with enum
yannik131 Aug 28, 2026
c67a0b2
replacing media type with enum
yannik131 Aug 28, 2026
bda4219
fixed tests (media type enum)
yannik131 Aug 28, 2026
d4988d1
fixed frontend bugs
yannik131 Aug 28, 2026
c110ea2
composer lint & fix
yannik131 Aug 29, 2026
6762396
Reversed enum folder creation
yannik131 Aug 29, 2026
91e3c41
shapes enum & migrations
yannik131 Aug 29, 2026
bf7101b
Deleted factories
yannik131 Aug 29, 2026
e73c747
Working on fixing shape tests
yannik131 Aug 29, 2026
c229549
fixed last failing shape test
yannik131 Aug 30, 2026
b84216d
visiblity enum was very easy
yannik131 Aug 30, 2026
b306951
composer lint
yannik131 Aug 30, 2026
888823e
Replacing report type with enum
yannik131 Aug 30, 2026
77d1b10
remaining report type replacements
yannik131 Aug 30, 2026
0b05f8e
fixed linter errors
yannik131 Aug 31, 2026
5e78462
fixed failing tests
yannik131 Aug 31, 2026
b2d43c1
renamed role migration
yannik131 Aug 31, 2026
01ecd5d
fixed name access
yannik131 Aug 31, 2026
ccb63ba
Use Rule::enum
yannik131 Sep 9, 2026
2f50442
Fix Role typo
yannik131 Sep 9, 2026
904762f
Use named argument
yannik131 Sep 9, 2026
ef8be76
Introduce EnumSerialization trait
yannik131 Sep 9, 2026
48608be
Apply linter
yannik131 Sep 9, 2026
bab6151
Rename migrations & map old to new
yannik131 Sep 10, 2026
9cd6c7a
Add EnumMigrationHelper to make code DRY
yannik131 Sep 10, 2026
ec93a0f
Drop fk constraint before updating values
yannik131 Sep 10, 2026
8a12695
Fix migration helper code ordering
yannik131 Sep 11, 2026
6a7b404
Remove Role eloquent wrapping
yannik131 Sep 11, 2026
d1e77b2
Update EnumMigrationHelper comment
yannik131 Sep 11, 2026
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
8 changes: 4 additions & 4 deletions app/Annotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,11 @@ abstract public function getFileIdAttribute();
/**
* The shape of this annotation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<Shape, $this>
* @return Shape
*/
public function shape()
public function getShapeAttribute()
{
return $this->belongsTo(Shape::class);
return Shape::from($this->shape_id);
}

/**
Expand All @@ -213,7 +213,7 @@ public function getPoints(): array
*/
public function getShape(): Shape
{
return $this->shape;
return Shape::from($this->shape_id);
}

/**
Expand Down
8 changes: 5 additions & 3 deletions app/Http/Controllers/Api/MediaTypeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class MediaTypeController extends Controller
* }
* ]
*
* @return \Illuminate\Database\Eloquent\Collection
* @return \Illuminate\Support\Collection<int, array>
*/
public function index()
{
return MediaType::all();
return collect(MediaType::cases())->map->toArray()->values();
}

/**
Expand All @@ -54,6 +54,8 @@ public function index()
*/
public function show($id)
{
return MediaType::findOrFail($id);
$mediaType = MediaType::tryFrom((int) $id);
abort_if($mediaType === null, 404);
return $mediaType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public function index(Request $request, $id, $name)
$this->authorize('update', $project);

$volumes = Volume::select('id', 'name', 'updated_at', 'media_type_id')
->with('mediaType')
// All volumes of other projects where the user has admin rights on.
->whereIn('id', fn ($query) => $query->select('volume_id')
->from('project_volume')
Expand All @@ -68,6 +67,7 @@ public function index(Request $request, $id, $name)
$volumes->each(function ($item) use ($hidden) {
$item->append('thumbnailUrl')
->append('thumbnailsUrl')
->setAttribute('media_type', $item->mediaType) // TODO compare with others for test, test index and fuzzy search
->makeHidden($hidden);
});

Expand Down
4 changes: 2 additions & 2 deletions app/Http/Controllers/Api/ReportsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ public function destroy($id)
* @apiGroup Reports
* @apiName IndexReports
* @apiPermission user
* @return \Illuminate\Database\Eloquent\Collection
* @return \Illuminate\Support\Collection
*/
public function index()
{
return ReportType::all();
return collect(ReportType::cases())->map->toArray()->values();
}
}
10 changes: 6 additions & 4 deletions app/Http/Controllers/Api/RoleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ class RoleController extends Controller
* }
* ]
*
* @return \Illuminate\Database\Eloquent\Collection
* @return \Illuminate\Support\Collection<int, array>
*/
public function index()
{
return Role::all();
return collect(Role::cases())->map->toArray()->values();
}

/**
Expand All @@ -56,8 +56,10 @@ public function index()
* @param int $id
* @return Role
*/
public function show($id)
public function show($id): Role
{
return Role::findOrFail($id);
$role = Role::tryFrom((int) $id);
abort_if($role === null, 404);
return $role;
}
}
8 changes: 5 additions & 3 deletions app/Http/Controllers/Api/ShapeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class ShapeController extends Controller
* }
* ]
*
* @return \Illuminate\Database\Eloquent\Collection
* @return \Illuminate\Support\Collection<int, array>
*/
public function index()
{
return Shape::all();
return collect(Shape::cases())->map->toArray()->values();
}

/**
Expand All @@ -54,6 +54,8 @@ public function index()
*/
public function show($id)
{
return Shape::findOrFail($id);
$shape = Shape::tryFrom((int) $id);
abort_if($shape === null, 404);
return $shape;
}
}
8 changes: 5 additions & 3 deletions app/Http/Controllers/Api/VisibilityController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class VisibilityController extends Controller
* }
* ]
*
* @return \Illuminate\Database\Eloquent\Collection
* @return \Illuminate\Support\Collection
*/
public function index()
{
return Visibility::all();
return collect(Visibility::cases())->map->toArray()->values();
}

/**
Expand All @@ -54,6 +54,8 @@ public function index()
*/
public function show($id)
{
return Visibility::findOrFail($id);
$visibility = Visibility::tryFrom((int) $id);
abort_if($visibility === null, 404);
return $visibility;
}
}
5 changes: 4 additions & 1 deletion app/Http/Controllers/Views/Admin/ExportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ public function index()
abort(404);
}

$mediaTypes = MediaType::pluck('id', 'name');
$mediaTypes = collect(MediaType::cases())->mapWithKeys(
fn (MediaType $mediaType)
=> [$mediaType->label() => $mediaType->value]
);

return view('export.index', compact('allowedExports', 'mediaTypes'));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function show(Request $request, $id)
})
->get();

$shapes = Shape::pluck('name', 'id');
$shapes = Shape::pluckById();

$annotationSessions = $image->volume->annotationSessions()
->select('id', 'name', 'starts_at', 'ends_at')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public function show(Request $request, $id)


$visibilities = collect([
Visibility::publicId() => Visibility::public()->name,
Visibility::privateId() => Visibility::private()->name,
Visibility::publicId() => Visibility::public()->label(),
Visibility::privateId() => Visibility::private()->label(),
]);

return view('label-trees.show.members', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ protected function showMasterLabelTree(LabelTree $tree, User $user)
}

$visibilities = collect([
Visibility::publicId() => Visibility::public()->name,
Visibility::privateId() => Visibility::private()->name,
Visibility::publicId() => Visibility::public()->label(),
Visibility::privateId() => Visibility::private()->label(),
]);

return view('label-trees.show.projects', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function create(Request $request)
$upstreamLabelTree = null;
}

$selectedVisibility = (int) old('visibility_id') ?: $visibilities[0]->id;
$selectedVisibility = (int) old('visibility_id') ?: $visibilities[0]->value;

return view('label-trees.create', compact(
'visibilities',
Expand All @@ -94,8 +94,8 @@ protected function showMasterLabelTree(LabelTree $tree, User $user)
->get();

$visibilities = collect([
Visibility::publicId() => Visibility::public()->name,
Visibility::privateId() => Visibility::private()->name,
Visibility::publicId() => Visibility::public()->label(),
Visibility::privateId() => Visibility::private()->label(),
]);

return view('label-trees.show.labels', [
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Views/Projects/LargoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function index(Request $request, $id)
$patchUrlTemplate = Storage::disk(config('largo.patch_storage_disk'))
->url(':prefix/:id.'.config('largo.patch_format'));

$shapes = Shape::pluck('name', 'id');
$shapes = Shape::pluckById();

return view('largo.project', [
'project' => $project,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ protected function show(Request $request, $id)
->wherePivot('pinned', true)
->count();

$types = ReportType::when($hasImageVolume, fn ($q) => $q->where('name', 'like', 'Image%'))
->when($hasVideoVolume, fn ($q) => $q->orWhere('name', 'like', 'Video%'))
->orderBy('name', 'asc')
->get();

$types = ReportType::getSortedTypes($hasImageVolume, $hasVideoVolume);

$hasExportArea = $project->imageVolumes()
->whereNotNull('attrs->export_area')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ public function show(Request $request, $id)

$volumes = $project->volumes()
->select('id', 'name', 'updated_at', 'media_type_id')
->with('mediaType')
->orderBy('created_at', 'desc')
->get();
->get()
->each(function ($item) {
$item->setAttribute('media_type', $item->mediaType); // TODO no test
});


$totalImages = Image::whereIn('images.volume_id', fn ($query) => $query->select('volume_id')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function show(Request $request, $id)
Role::expert(),
Role::editor(),
Role::guest(),
]);
])->map->toArray();

$roleOrder = [
Role::guestId(),
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Views/Projects/ProjectsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ protected function show(Request $request, $id)
$hidden = ['doi'];
$volumes = $project->volumes()
->select('id', 'name', 'updated_at', 'media_type_id')
->with('mediaType')
->orderBy('created_at', 'desc')
->get()
->each(function ($item) use ($hidden) {
$item->append('thumbnailUrl')
->append('thumbnailsUrl')
->setAttribute('media_type', $item->mediaType) // TODO no test for this
->makeHidden($hidden);
});

Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Views/Videos/VideoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function show(Request $request, $id)
$user = $request->user();
$volume = $video->volume;

$shapes = Shape::where('name', '!=', 'Ellipse')->pluck('name', 'id');
$shapes = Shape::pluckById(Shape::ellipse());

if ($user->can('sudo')) {
// Global admins have no restrictions.
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Views/Volumes/LargoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function index(Request $request, $id)
$patchUrlTemplate = Storage::disk(config('largo.patch_storage_disk'))
->url(':prefix/:id.'.config('largo.patch_format'));

$shapes = Shape::pluck('name', 'id');
$shapes = Shape::pluckById();

if (!$volume->isVideoVolume()) {
$wholeframeId = Shape::wholeFrameId();
Expand Down
6 changes: 3 additions & 3 deletions app/Http/Controllers/Views/Volumes/VolumeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function index(Request $request, $id)
$thumbUriTemplate = thumbnail_url(':uuid', config('videos.thumbnail_storage_disk'));
}

$type = $volume->mediaType->name;
$type = $volume->mediaType->label();

return view('volumes.show', compact(
'volume',
Expand All @@ -102,7 +102,7 @@ public function edit(Request $request, $id)
$this->authorize('update', $volume);
$sessions = $volume->annotationSessions()->with('users')->get();
$projects = $this->getProjects($request->user(), $volume);
$type = $volume->mediaType->name;
$type = $volume->mediaType->label();

$parsers = collect(ParserFactory::$parsers[$type] ?? [])
->map(fn ($class) => [
Expand All @@ -114,7 +114,7 @@ public function edit(Request $request, $id)
return view('volumes.edit', [
'projects' => $projects,
'volume' => $volume,
'mediaTypes' => MediaType::all(),
'mediaTypes' => collect(MediaType::cases())->map->toArray(),
'annotationSessions' => $sessions,
'today' => Carbon::today(),
'type' => $type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ public function show(Request $request, $id)
$volume = Volume::findOrFail($id);
$this->authorize('access', $volume);
$sessions = $volume->annotationSessions()->orderBy('starts_at', 'desc')->get();
$types = ReportType::when($volume->isImageVolume(), fn ($q) => $q->where('name', 'like', 'Image%'))
->when($volume->isVideoVolume(), fn ($q) => $q->where('name', 'like', 'Video%'))
->orderBy('name', 'asc')
->get();
$types = ReportType::getSortedTypes($volume->isImageVolume(), $volume->isVideoVolume());

$user = $request->user();

Expand Down
3 changes: 2 additions & 1 deletion app/Http/Requests/StoreImageAnnotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Biigle\Rules\AnnotationPoints;
use Biigle\Shape;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class StoreImageAnnotation extends FormRequest
{
Expand Down Expand Up @@ -52,7 +53,7 @@ function ($attribute, $value, $fail) {
},
],
'confidence' => 'required|numeric|between:0,1',
'shape_id' => 'required|integer|exists:shapes,id',
'shape_id' => ['required', 'integer', Rule::in(Shape::pluckById()->keys()->all())],
Comment thread
yannik131 marked this conversation as resolved.
Outdated
'points' => [
'bail',
'required',
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Requests/StoreImageAnnotations.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function authorize()
public function rules()
{
// Image annotations cannot have the whole frame shape.
$shapeIds = Shape::whereKeyNot(Shape::wholeFrameId())->pluck('id');
$shapeIds = Shape::pluckById(Shape::wholeFrame())->keys();
Comment thread
yannik131 marked this conversation as resolved.
Outdated

return [
'*.image_id' => 'required|integer',
Expand Down
4 changes: 3 additions & 1 deletion app/Http/Requests/StoreLabelTree.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use Biigle\LabelTree;
use Biigle\Project;
use Biigle\Visibility;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class StoreLabelTree extends FormRequest
{
Expand Down Expand Up @@ -41,7 +43,7 @@ public function rules()
{
return [
'name' => 'required|max:256',
'visibility_id' => 'required|integer|exists:visibilities,id',
'visibility_id' => ['required', 'integer', Rule::in(array_column(Visibility::cases(), 'value'))],
'project_id' => 'integer|exists:projects,id',
'upstream_label_tree_id' => 'integer|exists:label_trees,id',
];
Expand Down
7 changes: 3 additions & 4 deletions app/Http/Requests/StorePendingVolume.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ public function authorize(): bool
*/
public function rules(): array
{

$rules = [
'media_type' => ['required', Rule::in(array_keys(MediaType::INSTANCES))],
'media_type' => ['required', Rule::in(MediaType::labels())],
'metadata_parser' => [
'required_with:metadata_file',
],
Expand Down Expand Up @@ -108,8 +107,8 @@ protected function prepareForValidation()
{
// Allow a string as media_type to be more conventient.
$type = $this->input('media_type');
if (in_array($type, array_keys(MediaType::INSTANCES))) {
$this->merge(['media_type_id' => MediaType::$type()->id]);
if (in_array($type, MediaType::labels())) {
$this->merge(['media_type_id' => MediaType::fromLabel(strtoupper($type))->value]);
}
}
}
Loading