Art: drag pieces into a new order
Each gallery tile gets a small drag handle (top-left, ✱). Grab it and drop it anywhere among the others - the tile moves live as you drag over neighbours, then the new order is saved automatically on drop. - Artwork gets a `position` column; the gallery lists by position (was upload date). New uploads land after everything else. - New POST /art/reorder endpoint takes an ordered list of ids (one shared CSRF token, "reorder-art") and rewrites positions 1..n. - Migration backfills position from the existing upload-date order via ROW_NUMBER(), then drops the bootstrap default so it matches the Doctrine mapping. - New Stimulus controller (art-reorder): native HTML5 drag/drop, no library. dragover live-reorders the DOM by comparing cursor x to the hovered tile's midpoint; dragend posts the resulting id order and shows a small "Saving order… / Order saved" status pill. Verified: schema validate clean: a throwaway script exercised persist+reload of a reordered set against the real DB, and a live browser check dispatched real DragEvents through the actual Stimulus controller and confirmed the exact POST payload it sent. phpunit 9/9. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20260915151210 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add artwork.position for the drag-to-reorder gallery, backfilled by upload date';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE artwork ADD position INT NOT NULL DEFAULT 0');
|
||||
|
||||
// Backfill existing rows so the gallery keeps its current (upload-date) order
|
||||
// until someone drags a piece; new uploads get their position in PHP.
|
||||
$this->addSql(<<<'SQL'
|
||||
UPDATE artwork a
|
||||
JOIN (
|
||||
SELECT id, ROW_NUMBER() OVER (ORDER BY uploaded_at ASC, id ASC) AS rn
|
||||
FROM artwork
|
||||
) ranked ON ranked.id = a.id
|
||||
SET a.position = ranked.rn
|
||||
SQL);
|
||||
|
||||
// Drop the bootstrap default now that every row has a real position;
|
||||
// the mapping has no default, so schema:validate expects none either.
|
||||
$this->addSql('ALTER TABLE artwork CHANGE position position INT NOT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE artwork DROP position');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user