Studio: make grid checkbox rectangular and commit table changes

This commit is contained in:
2026-03-01 08:43:48 +01:00
parent 211dc58884
commit e3ca845a6d
89 changed files with 7323 additions and 475 deletions

View File

@@ -86,7 +86,7 @@ class Artwork extends Model
*/
public function getThumbAttribute(): string
{
return $this->thumbUrl('md') ?? '/gfx/sb_join.jpg';
return $this->thumbUrl('md') ?? 'https://files.skinbase.org/default/missing_md.webp';
}
/**
@@ -261,6 +261,8 @@ class Artwork extends Model
'engagement_velocity' => (float) ($stat?->engagement_velocity ?? 0),
'shares_count' => (int) ($stat?->shares_count ?? 0),
'comments_count' => (int) ($stat?->comments_count ?? 0),
// ── Rising / Heat fields ────────────────────────────────────────────────────
'heat_score' => (float) ($stat?->heat_score ?? 0),
'awards' => [
'gold' => $awardStat?->gold_count ?? 0,
'silver' => $awardStat?->silver_count ?? 0,

View File

@@ -0,0 +1,53 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* App\Models\ArtworkMetricSnapshotHourly
*
* Stores hourly totals for artwork metrics. Deltas are computed by
* subtracting the previous hour's snapshot from the current one.
*
* @property int $id
* @property int $artwork_id
* @property \Illuminate\Support\Carbon $bucket_hour
* @property int $views_count
* @property int $downloads_count
* @property int $favourites_count
* @property int $comments_count
* @property int $shares_count
* @property \Illuminate\Support\Carbon $created_at
*/
class ArtworkMetricSnapshotHourly extends Model
{
protected $table = 'artwork_metric_snapshots_hourly';
public $timestamps = false;
protected $fillable = [
'artwork_id',
'bucket_hour',
'views_count',
'downloads_count',
'favourites_count',
'comments_count',
'shares_count',
];
protected $casts = [
'bucket_hour' => 'datetime',
'views_count' => 'integer',
'downloads_count' => 'integer',
'favourites_count' => 'integer',
'comments_count' => 'integer',
'shares_count' => 'integer',
];
public function artwork(): BelongsTo
{
return $this->belongsTo(Artwork::class, 'artwork_id');
}
}

View File

@@ -34,6 +34,14 @@ class ArtworkStats extends Model
'shares_24h',
'comments_24h',
'favourites_24h',
// Rising / Heat columns
'heat_score',
'heat_score_updated_at',
'views_1h',
'favourites_1h',
'comments_1h',
'shares_1h',
'downloads_1h',
];
public function artwork(): BelongsTo

View File

@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* Precomputed recommendation list for an artwork.
*
* @property int $id
* @property int $artwork_id
* @property string $rec_type similar_hybrid|similar_visual|similar_tags|similar_behavior
* @property array $recs Ordered array of artwork IDs
* @property string $model_version e.g. "sim_v1"
* @property \Carbon\Carbon $computed_at
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*
* @property-read Artwork $artwork
*/
final class RecArtworkRec extends Model
{
protected $table = 'rec_artwork_recs';
protected $fillable = [
'artwork_id',
'rec_type',
'recs',
'model_version',
'computed_at',
];
protected $casts = [
'artwork_id' => 'integer',
'recs' => 'array',
'computed_at' => 'datetime',
];
// ── Relations ──────────────────────────────────────────────────────────
public function artwork(): BelongsTo
{
return $this->belongsTo(Artwork::class, 'artwork_id');
}
}

54
app/Models/RecEvent.php Normal file
View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* Recommendation event log entry.
*
* @property int $id
* @property int|null $user_id
* @property string|null $session_id
* @property string $event_type view|favourite|download
* @property int $artwork_id
* @property \Carbon\Carbon $created_at
*
* @property-read User|null $user
* @property-read Artwork $artwork
*/
final class RecEvent extends Model
{
protected $table = 'rec_events';
public $timestamps = false;
protected $fillable = [
'user_id',
'session_id',
'event_type',
'artwork_id',
'created_at',
];
protected $casts = [
'user_id' => 'integer',
'artwork_id' => 'integer',
'created_at' => 'datetime',
];
// ── Relations ──────────────────────────────────────────────────────────
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function artwork(): BelongsTo
{
return $this->belongsTo(Artwork::class);
}
}

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* Item-item co-occurrence pair for behavior-based similarity.
*
* @property int $a_artwork_id
* @property int $b_artwork_id
* @property float $weight
* @property \Carbon\Carbon $updated_at
*
* @property-read Artwork $artworkA
* @property-read Artwork $artworkB
*/
final class RecItemPair extends Model
{
protected $table = 'rec_item_pairs';
public $incrementing = false;
public $timestamps = false;
protected $fillable = [
'a_artwork_id',
'b_artwork_id',
'weight',
'updated_at',
];
protected $casts = [
'a_artwork_id' => 'integer',
'b_artwork_id' => 'integer',
'weight' => 'double',
'updated_at' => 'datetime',
];
// ── Relations ──────────────────────────────────────────────────────────
public function artworkA(): BelongsTo
{
return $this->belongsTo(Artwork::class, 'a_artwork_id');
}
public function artworkB(): BelongsTo
{
return $this->belongsTo(Artwork::class, 'b_artwork_id');
}
}