Initial commit: Pireon Admin — headless admin panel and public API
Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer collective, backed by the Pireon OAuth identity server. The public site is a separate, server-rendered application consuming /api/public/v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
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('categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
/*
|
||||
* Translatable columns hold a JSON map of locale => value, e.g.
|
||||
* {"es": "Servicios", "en": "Services", "ca": "Serveis"}.
|
||||
* spatie/laravel-translatable casts these transparently.
|
||||
*
|
||||
* `jsonb` rather than `json`: Postgres cannot compare a `json`
|
||||
* value for equality, so any `select distinct` touching one fails
|
||||
* outright — and Filament's relationship selects emit exactly
|
||||
* that. On MySQL it is still `json` and on SQLite still `text`,
|
||||
* so nothing else changes.
|
||||
*/
|
||||
$table->jsonb('name');
|
||||
$table->jsonb('slug');
|
||||
$table->jsonb('description')->nullable();
|
||||
|
||||
$table->string('color', 7)->nullable();
|
||||
$table->unsignedInteger('position')->default(0);
|
||||
$table->boolean('is_visible')->default(true);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->index('position');
|
||||
});
|
||||
|
||||
Schema::create('pages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->foreignId('category_id')->nullable()
|
||||
->constrained()->nullOnDelete();
|
||||
$table->foreignId('author_id')->nullable()
|
||||
->constrained('users')->nullOnDelete();
|
||||
|
||||
$table->jsonb('title');
|
||||
// Slugs live inside JSON, so uniqueness cannot be a DB constraint.
|
||||
// It is enforced per locale by App\Rules\UniqueTranslatedSlug.
|
||||
$table->jsonb('slug');
|
||||
$table->jsonb('excerpt')->nullable();
|
||||
$table->jsonb('body')->nullable();
|
||||
$table->jsonb('meta_title')->nullable();
|
||||
$table->jsonb('meta_description')->nullable();
|
||||
|
||||
$table->string('status', 20)->default('draft');
|
||||
$table->string('featured_image')->nullable();
|
||||
$table->boolean('is_featured')->default(false);
|
||||
$table->timestamp('published_at')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
$table->index(['status', 'published_at']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('pages');
|
||||
Schema::dropIfExists('categories');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user