Implement creator studio and upload updates

This commit is contained in:
2026-04-04 10:12:02 +02:00
parent 1da7d3bf88
commit 0b216b7ecd
15107 changed files with 31206 additions and 626514 deletions

View File

@@ -18,6 +18,8 @@ use App\Http\Controllers\StoryController;
use App\Http\Controllers\Web\HomeController;
use App\Http\Controllers\Web\FooterController;
use App\Http\Controllers\Web\BugReportController;
use App\Http\Controllers\RobotsTxtController;
use App\Http\Controllers\SitemapController;
use App\Http\Controllers\Web\StaffController;
use App\Http\Controllers\Web\RssFeedController;
use App\Http\Controllers\Web\ApplicationController;
@@ -39,7 +41,6 @@ use App\Http\Controllers\User\MonthlyCommentatorsController;
use App\Http\Controllers\User\ProfileCollectionController;
use App\Http\Controllers\User\SavedCollectionController;
use App\Http\Controllers\User\CollectionSavedLibraryController;
use App\Models\Artwork;
use App\Http\Controllers\Settings\CollectionAiController;
use App\Http\Controllers\Settings\CollectionInsightsController;
use App\Http\Controllers\Settings\CollectionManageController;
@@ -49,6 +50,11 @@ use Inertia\Inertia;
Route::get('/', [HomeController::class, 'index'])->name('index');
Route::get('/home', [HomeController::class, 'index']);
Route::get('/robots.txt', RobotsTxtController::class)->name('robots.txt');
Route::get('/sitemap.xml', [SitemapController::class, 'index'])->name('sitemap.index');
Route::get('/sitemaps/{name}.xml', [SitemapController::class, 'show'])
->where('name', '[A-Za-z0-9\-]+')
->name('sitemap.show');
// ── PUBLIC GALLERIES / LISTS ─────────────────────────────────────────────────
Route::get('/featured', [FeaturedArtworksController::class, 'index'])->name('featured');
@@ -222,6 +228,14 @@ Route::middleware('auth')->get('/following', function () {
})->name('following.redirect');
// ── ART / ARTWORKS ────────────────────────────────────────────────────────────
Route::get('/art/{id}/similar', \App\Http\Controllers\Web\SimilarArtworksPageController::class)
->whereNumber('id')
->name('art.similar');
Route::get('/art/{id}/similar-results', [\App\Http\Controllers\Web\SimilarArtworksPageController::class, 'results'])
->whereNumber('id')
->name('art.similar.results');
Route::get('/art/{id}/{slug?}', [ArtworkPageController::class, 'show'])
->where('id', '\d+')
->name('art.show');
@@ -367,12 +381,31 @@ Route::middleware(['auth'])->get('/settings/profile', [ProfileController::class
// ── STUDIO Pro (/studio/*) ────────────────────────────────────────────────────
Route::middleware(['auth', 'ensure.onboarding.complete'])->prefix('studio')->name('studio.')->group(function () {
Route::get('/', [StudioController::class, 'index'])->name('index');
Route::get('/content', [StudioController::class, 'content'])->name('content');
Route::get('/artworks', [StudioController::class, 'artworks'])->name('artworks');
Route::get('/artworks/drafts', [StudioController::class, 'drafts'])->name('drafts');
Route::get('/artworks/archived', [StudioController::class, 'archived'])->name('archived');
Route::get('/drafts', [StudioController::class, 'drafts'])->name('drafts');
Route::get('/scheduled', [StudioController::class, 'scheduled'])->name('scheduled');
Route::get('/calendar', [StudioController::class, 'calendar'])->name('calendar');
Route::get('/archived', [StudioController::class, 'archived'])->name('archived');
Route::get('/artworks/drafts', fn () => redirect()->route('studio.drafts', request()->query(), 302));
Route::get('/artworks/archived', fn () => redirect()->route('studio.archived', request()->query(), 302));
Route::get('/artworks/{id}/edit', [StudioController::class, 'edit'])->whereNumber('id')->name('artworks.edit');
Route::get('/artworks/{id}/analytics', [StudioController::class, 'analytics'])->whereNumber('id')->name('artworks.analytics');
Route::get('/analytics', [StudioController::class, 'analyticsOverview'])->name('analytics');
Route::get('/collections', [StudioController::class, 'collections'])->name('collections');
Route::get('/stories', [StudioController::class, 'stories'])->name('stories');
Route::get('/assets', [StudioController::class, 'assets'])->name('assets');
Route::get('/comments', [StudioController::class, 'comments'])->name('comments');
Route::get('/activity', [StudioController::class, 'activity'])->name('activity');
Route::get('/inbox', [StudioController::class, 'inbox'])->name('inbox');
Route::get('/challenges', [StudioController::class, 'challenges'])->name('challenges');
Route::get('/followers', [StudioController::class, 'followers'])->name('followers');
Route::get('/search', [StudioController::class, 'search'])->name('search');
Route::get('/growth', [StudioController::class, 'growth'])->name('growth');
Route::get('/profile', [StudioController::class, 'profile'])->name('profile');
Route::get('/featured', [StudioController::class, 'featured'])->name('featured');
Route::get('/preferences', [StudioController::class, 'preferences'])->name('preferences');
Route::get('/settings', [StudioController::class, 'settings'])->name('settings');
Route::get('/cards', [\App\Http\Controllers\Studio\StudioNovaCardsController::class, 'index'])->name('cards.index');
Route::get('/cards/create', [\App\Http\Controllers\Studio\StudioNovaCardsController::class, 'create'])->name('cards.create');
Route::post('/cards/remix/{id}', [\App\Http\Controllers\Studio\StudioNovaCardsController::class, 'remix'])->whereNumber('id')->name('cards.remix');
@@ -416,6 +449,11 @@ Route::get('/cards/{slug}-{id}', [\App\Http\Controllers\Web\NovaCardsController:
->whereNumber('id')
->name('cards.show');
// Internal render frame — accessed only by the Playwright Node renderer with a signed URL.
Route::get('/internal/nova-cards/render-frame/{uuid}', [\App\Http\Controllers\Internal\NovaCardRenderFrameController::class, 'show'])
->where('uuid', '[0-9a-f\-]{36}')
->name('nova-cards.render-frame');
Route::middleware('auth')->group(function () {
Route::post('/cards/{card}/comments', [\App\Http\Controllers\NovaCardCommentController::class, 'store'])
->whereNumber('card')
@@ -658,11 +696,8 @@ Route::get('/feed/search', [\App\Http\Controllers\Web\Posts\SearchFeedController
->name('feed.search');
// ── CONTENT BROWSER (artwork / category universal router) ─────────────────────
// Bind the artwork route parameter by slug when possible, but don't hard-fail.
// Some URLs that match this shape are actually nested category paths such as
// /skins/audio/blazemedia-pro, which should fall through to category handling.
Route::bind('artwork', function ($value) {
return Artwork::where('slug', $value)->first();
return $value;
});
Route::get('/{contentTypeSlug}/{categoryPath}/{artwork}', [BrowseGalleryController::class, 'showArtwork'])