Add survey question drag-sort and backend assets

- Frontend editor: drag-to-sort questions with dedicated sort assets/JS
- Backend list/search refinements for tl_survey and tl_survey_content
- Repository helpers for survey/question/editor queries
- Translations and AI handover notes update
This commit is contained in:
Jürgen Mummert
2026-06-14 09:13:07 +02:00
parent 79c4402aee
commit 1b16675ae9
23 changed files with 928 additions and 40 deletions
+35 -4
View File
@@ -97,6 +97,16 @@ final class SurveyEditorService
$this->surveyRepository->touch((int) $survey->id);
}
/**
* @param list<int> $orderedQuestionIds
*/
public function reorderQuestions(SurveyModel $survey, array $orderedQuestionIds): void
{
$this->assertUnlocked($survey);
$this->surveyQuestionRepository->reorderQuestions((int) $survey->id, $orderedQuestionIds);
$this->surveyRepository->touch((int) $survey->id);
}
public function deleteSurvey(SurveyModel $survey): void
{
$this->surveyRepository->deleteCascade((int) $survey->id);
@@ -108,8 +118,9 @@ final class SurveyEditorService
$sourceSurveyId = (int) $survey->id;
$memberIds = $this->surveyEditorRepository->findMemberIdsBySurvey($sourceSurveyId);
$duplicate = $this->surveyRepository->create($actorMemberId ?? (int) ($survey->createdBy ?? 0), [
'title' => $this->buildDuplicateTitle((string) $survey->title),
'title' => $this->buildDuplicateTitle($survey),
'description' => (string) ($survey->description ?? ''),
'internalNote' => (string) ($survey->internalNote ?? ''),
'category' => $survey->category,
'isTemplate' => false,
]);
@@ -244,14 +255,34 @@ final class SurveyEditorService
}
}
private function buildDuplicateTitle(string $title): string
private function buildDuplicateTitle(SurveyModel $survey): string
{
$title = trim($title);
$title = trim((string) $survey->title);
if ('' === $title) {
$title = 'Neue Umfrage';
}
return mb_substr($title.' - Kopie', 0, 255);
$baseTitle = trim((string) preg_replace('/ - Kopie(?: \d+)?$/u', '', $title));
if ('' === $baseTitle) {
$baseTitle = 'Neue Umfrage';
}
for ($copyNumber = 1; ; ++$copyNumber) {
$suffix = 1 === $copyNumber ? ' - Kopie' : sprintf(' - Kopie %d', $copyNumber);
$candidate = $this->buildDuplicateTitleCandidate($baseTitle, $suffix);
if (!$this->surveyRepository->titleExists($candidate, (int) $survey->id)) {
return $candidate;
}
}
}
private function buildDuplicateTitleCandidate(string $baseTitle, string $suffix): string
{
$maxBaseLength = max(0, 255 - mb_strlen($suffix));
return mb_substr($baseTitle, 0, $maxBaseLength).$suffix;
}
}