diff --git a/app/Models/User.php b/app/Models/User.php index 4f597117..d8ba8414 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -355,6 +355,21 @@ class User extends Authenticatable */ protected static function bootSearchable(): void { + // Register the SearchableScope so that the Builder::searchable() macro + // is available (needed for scout:import and manual ::searchable() calls). + // We intentionally skip static::observe(new ModelObserver) so that + // User saves/deletes do not auto-enqueue Scout sync jobs. + static::addGlobalScope(new \Laravel\Scout\SearchableScope); + + $whenBootedCallback = function () { + (new static)->registerSearchableMacros(); + }; + + if (method_exists(static::class, 'whenBooted')) { + static::whenBooted($whenBootedCallback); + } else { + $whenBootedCallback(); + } } /** diff --git a/resources/js/components/Studio/StudioContentBrowser.jsx b/resources/js/components/Studio/StudioContentBrowser.jsx index 9526002e..21a42cab 100644 --- a/resources/js/components/Studio/StudioContentBrowser.jsx +++ b/resources/js/components/Studio/StudioContentBrowser.jsx @@ -554,7 +554,7 @@ export default function StudioContentBrowser({ {items.length > 0 ? ( viewMode === 'grid' ? ( -
+
{items.map((item) => )}
) : ( diff --git a/scripts/deploy-production.sh b/scripts/deploy-production.sh index cf96d8bc..fefbe159 100644 --- a/scripts/deploy-production.sh +++ b/scripts/deploy-production.sh @@ -16,6 +16,7 @@ local_build_command="${LOCAL_BUILD_COMMAND:-}" run_local_build=1 run_remote_migrations=1 run_db_sync=0 +run_meilisearch_setup=0 db_sync_source="" legacy_db_sync_mode=0 force_db_sync=0 @@ -37,6 +38,7 @@ Options: Must equal 'replace production db from local' when running non-interactively. --with-db Legacy alias for --with-db-from=local. --force-db-sync Legacy extra confirmation flag for --with-db. + --with-meilisearch Sync index settings then reimport all searchable models. --no-maintenance Skip php artisan down/up during deploy. --help Show this help. @@ -157,6 +159,9 @@ while [[ $# -gt 0 ]]; do --confirm-db-sync-phrase=*) db_sync_confirm_phrase="${1#*=}" ;; + --with-meilisearch) + run_meilisearch_setup=1 + ;; --no-maintenance) skip_maintenance=1 ;; @@ -235,6 +240,7 @@ echo "Running remote Composer and Artisan steps..." COMPOSER_BIN="$(printf '%q' "$composer_bin")" \ RUN_REMOTE_MIGRATIONS="$run_remote_migrations" \ SKIP_MAINTENANCE="$skip_maintenance" \ + RUN_MEILISEARCH_SETUP="$run_meilisearch_setup" \ 'bash -s' <<'EOF' set -euo pipefail @@ -263,6 +269,18 @@ fi "$PHP_BIN" artisan view:cache "$PHP_BIN" artisan queue:restart || true +if [[ "$RUN_MEILISEARCH_SETUP" -eq 1 ]]; then + echo "Importing searchable models into Meilisearch (auto-creates indexes)..." + "$PHP_BIN" artisan scout:import "App\\Models\\Artwork" + "$PHP_BIN" artisan scout:import "App\\Models\\User" + "$PHP_BIN" artisan scout:import "App\\Models\\Group" + "$PHP_BIN" artisan scout:import "App\\Models\\Post" + "$PHP_BIN" artisan scout:import "App\\Models\\Message" + echo "Syncing Meilisearch index settings..." + "$PHP_BIN" artisan scout:sync-index-settings + echo "Meilisearch setup complete." +fi + if [[ "$SKIP_MAINTENANCE" -eq 0 ]]; then "$PHP_BIN" artisan up trap - EXIT diff --git a/scripts/fix_artworks_updated_at.php b/scripts/fix_artworks_updated_at.php new file mode 100644 index 00000000..7a93baa7 --- /dev/null +++ b/scripts/fix_artworks_updated_at.php @@ -0,0 +1,44 @@ +make(Illuminate\Contracts\Console\Kernel::class)->bootstrap(); + +$options = getopt('', ['dry-run']); +$isDryRun = array_key_exists('dry-run', $options); + +use Illuminate\Support\Facades\DB; + +// Count rows that need updating +$total = DB::table('artworks') + ->whereColumn('updated_at', '!=', 'created_at') + ->orWhereNull('updated_at') + ->count(); + +if ($total === 0) { + fwrite(STDOUT, "Nothing to do: all artworks already have updated_at = created_at.\n"); + exit(0); +} + +fwrite(STDOUT, sprintf("Rows to fix: %d%s\n", $total, $isDryRun ? ' (dry-run, no changes written)' : '')); + +if ($isDryRun) { + exit(0); +} + +// Single bulk UPDATE — fast even on large tables, uses the existing index on created_at +$affected = DB::statement('UPDATE artworks SET updated_at = created_at WHERE updated_at != created_at OR updated_at IS NULL'); + +fwrite(STDOUT, sprintf("Done. updated_at synced to created_at for %d rows.\n", $total));