Add autosave draft system for partage form with HTMX-based session persistence

- New fragment endpoint POST/GET /partage/fragments/draft.php:
  saves all form fields to PHP session, excludes file/csrf/slug fields
  GET returns JSON for JS hydration on page load
  rotates both global CSRF and share CSRF tokens in sync

- form.php accepts optional $formExtraAttrs and $showAutosaveStatus:
  allows injecting HTMX attributes and 'Brouillon enregistré' indicator

- renderShareLinkForm adds hx-post with change/input debounce trigger,
  loads autosave-handler.js, hydrate fields from draft on page load

- Draft cleared on successful form submission in handleShareLinkSubmission

- autosave-handler.js now also updates share_link_token hidden input
  when rotating CSRF token (partage form uses both csrf_token and share_link_token)

- Added .autosave-status CSS to form.css (was admin.css-only)

- Updated fragment routing to accept GET requests (needed for draft hydration)
This commit is contained in:
Pontoporeia
2026-06-11 10:32:53 +02:00
parent 4b37a05be3
commit 99125cc8e3
33 changed files with 1388 additions and 806 deletions

View File

@@ -15,17 +15,26 @@ class PureLogicTest extends TestCase
// We need a TfeController instance to test protected methods.
// Use the anonymous subclass pattern.
$db = TestDatabase::getInstance();
return new class($db) extends TfeController {
public function exposedSplitJuryByRole(array $jury): array { return $this->splitJuryByRole($jury); }
public function exposedCollectCaptionPaths(array $files): array { return $this->collectCaptionPaths($files); }
return new class ($db) extends TfeController {
public function exposedSplitJuryByRole(array $jury): array
{
return $this->splitJuryByRole($jury);
}
public function exposedCollectCaptionPaths(array $files): array
{
return $this->collectCaptionPaths($files);
}
};
}
private function getThesisCreateController(): ThesisCreateController
{
$db = TestDatabase::getInstance();
return new class($db) extends ThesisCreateController {
public function exposedDetectFileType(string $mimeType, string $ext): string { return $this->detectFileType($mimeType, $ext); }
return new class ($db) extends ThesisCreateController {
public function exposedDetectFileType(string $mimeType, string $ext): string
{
return $this->detectFileType($mimeType, $ext);
}
};
}