Add project listing selector, confirmed revision and private 3MF renders

This commit is contained in:
2026-11-08 18:49:32 +00:00
parent e62b6800a6
commit 4e675510fd
29 changed files with 3394 additions and 14 deletions
@@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use App\Models\ProjectFile;
use App\Models\ProjectFileRender;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<ProjectFileRender>
*/
class ProjectFileRenderFactory extends Factory
{
/**
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'project_file_id' => ProjectFile::factory(),
'renderer' => ProjectFileRender::RENDERER_SVG,
'mime_type' => 'image/svg+xml',
'storage_key' => fake()->unique()->uuid().'.svg',
'width' => 512,
'height' => 512,
'triangle_count' => 2,
'instance_count' => 1,
'alt_text' => 'Numeric 3D render preview.',
'byte_size' => 256,
'sha256' => hash('sha256', fake()->unique()->uuid()),
'generated_by' => User::factory()->create(['role' => 'admin'])->id,
'generated_at' => now(),
];
}
}
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('projects', function (Blueprint $table): void {
$table->foreignId('current_revision_id')->nullable()->after('stage')
->constrained('project_revisions')->nullOnDelete();
$table->unsignedInteger('lock_version')->default(0)->after('archived_at');
});
}
public function down(): void
{
Schema::table('projects', function (Blueprint $table): void {
$table->dropConstrainedForeignId('current_revision_id');
$table->dropColumn('lock_version');
});
}
};
@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('project_file_renders', function (Blueprint $table): void {
$table->id();
$table->foreignId('project_file_id')->unique()->constrained('project_files')->cascadeOnDelete();
$table->string('renderer');
$table->string('mime_type');
$table->string('storage_key')->unique();
$table->unsignedInteger('width');
$table->unsignedInteger('height');
$table->unsignedInteger('triangle_count');
$table->unsignedInteger('instance_count');
$table->text('alt_text');
$table->unsignedBigInteger('byte_size');
$table->string('sha256', 64);
// Legacy users.id is signed INT, not bigint.
$table->integer('generated_by');
$table->foreign('generated_by')->references('id')->on('users')->restrictOnDelete();
$table->timestamp('generated_at');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('project_file_renders');
}
};