feat(models): add Label/Macro/MacroAssignment/ServiceMacro models and remove SongGroup

This commit is contained in:
Thorsten Bus 2026-05-03 22:27:21 +02:00
parent 2a02f65517
commit 846bd12f90
17 changed files with 289 additions and 95 deletions

42
app/Models/Label.php Normal file
View file

@ -0,0 +1,42 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Label extends Model
{
use HasFactory;
protected $fillable = [
'name',
'color',
'hidden_at',
'last_imported_at',
];
protected function casts(): array
{
return [
'hidden_at' => 'datetime',
'last_imported_at' => 'datetime',
];
}
public function songSlides(): HasMany
{
return $this->hasMany(SongSlide::class);
}
public function macroAssignments(): HasMany
{
return $this->hasMany(MacroAssignment::class);
}
public function isHidden(): bool
{
return $this->hidden_at !== null;
}
}

51
app/Models/Macro.php Normal file
View file

@ -0,0 +1,51 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Macro extends Model
{
use HasFactory;
protected $fillable = [
'uuid',
'name',
'color',
'trigger_on_startup',
'image_type',
'action_count',
'hidden_at',
'last_imported_at',
'last_imported_filename',
];
protected function casts(): array
{
return [
'trigger_on_startup' => 'boolean',
'hidden_at' => 'datetime',
'last_imported_at' => 'datetime',
];
}
public function collections(): BelongsToMany
{
return $this->belongsToMany(MacroCollection::class, 'macro_collection_macros')
->withPivot('order')
->orderBy('macro_collection_macros.order');
}
public function assignments(): HasMany
{
return $this->hasMany(MacroAssignment::class);
}
public function isHidden(): bool
{
return $this->hidden_at !== null;
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class MacroAssignment extends Model
{
protected $fillable = [
'part_type',
'macro_id',
'position',
'label_id',
'order',
];
public function macro(): BelongsTo
{
return $this->belongsTo(Macro::class);
}
public function label(): BelongsTo
{
return $this->belongsTo(Label::class);
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class MacroCollection extends Model
{
protected $fillable = [
'uuid',
'name',
'last_imported_at',
];
protected function casts(): array
{
return [
'last_imported_at' => 'datetime',
];
}
public function macros(): BelongsToMany
{
return $this->belongsToMany(Macro::class, 'macro_collection_macros')
->withPivot('order')
->orderBy('macro_collection_macros.order');
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ServiceMacroAssignment extends Model
{
protected $fillable = [
'service_id',
'part_type',
'macro_id',
'position',
'label_id',
'order',
];
public function service(): BelongsTo
{
return $this->belongsTo(Service::class);
}
public function macro(): BelongsTo
{
return $this->belongsTo(Macro::class);
}
public function label(): BelongsTo
{
return $this->belongsTo(Label::class);
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class ServiceMacroOverride extends Model
{
protected $fillable = [
'service_id',
'part_type',
];
public function service(): BelongsTo
{
return $this->belongsTo(Service::class);
}
public function assignments(): HasMany
{
return $this->hasMany(ServiceMacroAssignment::class, 'service_id', 'service_id')
->where('part_type', $this->part_type);
}
}

View file

@ -33,11 +33,6 @@ protected function casts(): array
]; ];
} }
public function groups(): HasMany
{
return $this->hasMany(SongGroup::class);
}
public function arrangements(): HasMany public function arrangements(): HasMany
{ {
return $this->hasMany(SongArrangement::class); return $this->hasMany(SongArrangement::class);

View file

@ -29,9 +29,9 @@ public function song(): BelongsTo
return $this->belongsTo(Song::class); return $this->belongsTo(Song::class);
} }
public function arrangementGroups(): HasMany public function arrangementLabels(): HasMany
{ {
return $this->hasMany(SongArrangementGroup::class); return $this->hasMany(SongArrangementLabel::class)->orderBy('order');
} }
public function serviceSongs(): HasMany public function serviceSongs(): HasMany

View file

@ -6,13 +6,13 @@
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
class SongArrangementGroup extends Model class SongArrangementLabel extends Model
{ {
use HasFactory; use HasFactory;
protected $fillable = [ protected $fillable = [
'song_arrangement_id', 'song_arrangement_id',
'song_group_id', 'label_id',
'order', 'order',
]; ];
@ -21,8 +21,8 @@ public function arrangement(): BelongsTo
return $this->belongsTo(SongArrangement::class, 'song_arrangement_id'); return $this->belongsTo(SongArrangement::class, 'song_arrangement_id');
} }
public function group(): BelongsTo public function label(): BelongsTo
{ {
return $this->belongsTo(SongGroup::class, 'song_group_id'); return $this->belongsTo(Label::class);
} }
} }

View file

@ -1,35 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class SongGroup extends Model
{
use HasFactory;
protected $fillable = [
'song_id',
'name',
'color',
'order',
];
public function song(): BelongsTo
{
return $this->belongsTo(Song::class);
}
public function slides(): HasMany
{
return $this->hasMany(SongSlide::class);
}
public function arrangementGroups(): HasMany
{
return $this->hasMany(SongArrangementGroup::class);
}
}

View file

@ -11,15 +11,15 @@ class SongSlide extends Model
use HasFactory; use HasFactory;
protected $fillable = [ protected $fillable = [
'song_group_id', 'label_id',
'order', 'order',
'text_content', 'text_content',
'text_content_translated', 'text_content_translated',
'notes', 'notes',
]; ];
public function group(): BelongsTo public function label(): BelongsTo
{ {
return $this->belongsTo(SongGroup::class, 'song_group_id'); return $this->belongsTo(Label::class);
} }
} }

View file

@ -0,0 +1,21 @@
<?php
namespace Database\Factories;
use App\Models\Label;
use Illuminate\Database\Eloquent\Factories\Factory;
class LabelFactory extends Factory
{
protected $model = Label::class;
public function definition(): array
{
return [
'name' => $this->faker->unique()->words(2, true),
'color' => sprintf('#%06X', mt_rand(0, 0xFFFFFF)),
'hidden_at' => null,
'last_imported_at' => null,
];
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use App\Models\Macro;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class MacroFactory extends Factory
{
protected $model = Macro::class;
public function definition(): array
{
return [
'uuid' => strtoupper(Str::uuid()->toString()),
'name' => $this->faker->words(3, true),
'color' => sprintf('#%06X', mt_rand(0, 0xFFFFFF)),
'trigger_on_startup' => false,
'image_type' => 0,
'action_count' => 0,
'hidden_at' => null,
'last_imported_at' => null,
'last_imported_filename' => null,
];
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace Database\Factories;
use App\Models\SongArrangement;
use App\Models\SongArrangementGroup;
use App\Models\SongGroup;
use Illuminate\Database\Eloquent\Factories\Factory;
class SongArrangementGroupFactory extends Factory
{
protected $model = SongArrangementGroup::class;
public function definition(): array
{
return [
'song_arrangement_id' => SongArrangement::factory(),
'song_group_id' => SongGroup::factory(),
'order' => $this->faker->numberBetween(1, 12),
];
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace Database\Factories;
use App\Models\Label;
use App\Models\SongArrangement;
use App\Models\SongArrangementLabel;
use Illuminate\Database\Eloquent\Factories\Factory;
class SongArrangementLabelFactory extends Factory
{
protected $model = SongArrangementLabel::class;
public function definition(): array
{
return [
'song_arrangement_id' => SongArrangement::factory(),
'label_id' => Label::factory(),
'order' => $this->faker->numberBetween(0, 10),
];
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace Database\Factories;
use App\Models\Song;
use App\Models\SongGroup;
use Illuminate\Database\Eloquent\Factories\Factory;
class SongGroupFactory extends Factory
{
protected $model = SongGroup::class;
public function definition(): array
{
return [
'song_id' => Song::factory(),
'name' => $this->faker->randomElement(['Verse 1', 'Verse 2', 'Chorus', 'Bridge']),
'color' => $this->faker->hexColor(),
'order' => $this->faker->numberBetween(1, 10),
];
}
}

View file

@ -2,7 +2,7 @@
namespace Database\Factories; namespace Database\Factories;
use App\Models\SongGroup; use App\Models\Label;
use App\Models\SongSlide; use App\Models\SongSlide;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
@ -13,7 +13,7 @@ class SongSlideFactory extends Factory
public function definition(): array public function definition(): array
{ {
return [ return [
'song_group_id' => SongGroup::factory(), 'label_id' => Label::factory(),
'order' => $this->faker->numberBetween(1, 12), 'order' => $this->faker->numberBetween(1, 12),
'text_content' => implode("\n", $this->faker->sentences(3)), 'text_content' => implode("\n", $this->faker->sentences(3)),
'text_content_translated' => $this->faker->optional()->sentence(), 'text_content_translated' => $this->faker->optional()->sentence(),