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:
@@ -0,0 +1,45 @@
|
||||
.tl_checkbox_wizard.survey-assigned-members-checkbox-wizard {
|
||||
column-count: 4;
|
||||
column-gap: 1.5rem;
|
||||
}
|
||||
|
||||
.tl_checkbox_wizard.survey-assigned-members-checkbox-wizard > span {
|
||||
display: block;
|
||||
break-inside: avoid;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
.tl_checkbox_wizard.survey-assigned-members-checkbox-wizard .drag-handle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tl_checkbox_wizard.survey-assigned-members-checkbox-wizard label {
|
||||
display: inline;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
body.survey-question-list-page .parent_view > .tl_header .tl_content_right {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.survey-question-list-page.survey-question-list-clipboard-active .parent_view > .tl_header .tl_content_right {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-width: 1400px) {
|
||||
.tl_checkbox_wizard.survey-assigned-members-checkbox-wizard {
|
||||
column-count: 3;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.tl_checkbox_wizard.survey-assigned-members-checkbox-wizard {
|
||||
column-count: 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.tl_checkbox_wizard.survey-assigned-members-checkbox-wizard {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
(function () {
|
||||
function isSurveyListPage() {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
|
||||
return params.get('do') === 'survey_bundle_surveys';
|
||||
}
|
||||
|
||||
function isSurveyQuestionListPage() {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
|
||||
return params.get('do') === 'survey_bundle_surveys' && params.get('table') === 'tl_survey_content' && !params.get('act');
|
||||
}
|
||||
|
||||
function toggleQuestionListClass() {
|
||||
document.body.classList.toggle('survey-question-list-page', isSurveyQuestionListPage());
|
||||
document.body.classList.toggle('survey-question-list-clipboard-active', isSurveyQuestionListPage() && hasQuestionListClipboardState());
|
||||
}
|
||||
|
||||
function hasQuestionListClipboardState() {
|
||||
if (!isSurveyQuestionListPage()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (document.querySelector('#paste_hint')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Array.from(document.querySelectorAll('button')).some(function (button) {
|
||||
return (button.textContent || '').trim() === 'Ablage leeren';
|
||||
});
|
||||
}
|
||||
|
||||
function getSearchSelect() {
|
||||
return document.querySelector('select[name="tl_search"]');
|
||||
}
|
||||
|
||||
function getSearchForm(select) {
|
||||
return select ? select.closest('form') : null;
|
||||
}
|
||||
|
||||
function removeIdOption(select) {
|
||||
if (!select) {
|
||||
return;
|
||||
}
|
||||
|
||||
var idOption = select.querySelector('option[value="id"]');
|
||||
|
||||
if (!idOption) {
|
||||
return;
|
||||
}
|
||||
|
||||
var wasSelected = idOption.selected;
|
||||
idOption.remove();
|
||||
|
||||
if (wasSelected) {
|
||||
var fallback = select.querySelector('option[value="title"]') || select.options[0];
|
||||
|
||||
if (fallback) {
|
||||
fallback.selected = true;
|
||||
select.value = fallback.value;
|
||||
select.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeIdChoicesUi() {
|
||||
document.querySelectorAll('.choices__item[data-value="id"]').forEach(function (node) {
|
||||
node.remove();
|
||||
});
|
||||
|
||||
document.querySelectorAll('.choices__item--choice[data-value="id"]').forEach(function (node) {
|
||||
node.remove();
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeSearchField() {
|
||||
toggleQuestionListClass();
|
||||
|
||||
if (!isSurveyListPage()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var select = getSearchSelect();
|
||||
|
||||
if (!select) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeIdOption(select);
|
||||
removeIdChoicesUi();
|
||||
|
||||
var form = getSearchForm(select);
|
||||
|
||||
if (form && !form.dataset.surveySearchNormalized) {
|
||||
form.dataset.surveySearchNormalized = '1';
|
||||
form.addEventListener('submit', function () {
|
||||
if (select.value === 'id') {
|
||||
var fallback = select.querySelector('option[value="title"]') || select.options[0];
|
||||
|
||||
if (fallback) {
|
||||
select.value = fallback.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', normalizeSearchField);
|
||||
document.addEventListener('turbo:load', normalizeSearchField);
|
||||
|
||||
var observer = new MutationObserver(function () {
|
||||
normalizeSearchField();
|
||||
});
|
||||
|
||||
observer.observe(document.documentElement, { childList: true, subtree: true });
|
||||
})();
|
||||
@@ -0,0 +1,110 @@
|
||||
(function () {
|
||||
function ensureSortIconStyles() {
|
||||
if (document.getElementById('survey-question-sort-icon-theme')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var style = document.createElement('style');
|
||||
style.id = 'survey-question-sort-icon-theme';
|
||||
style.textContent = [
|
||||
'.survey-sort-icon{width:1.14rem !important;height:1.52rem !important;color:#58a6da !important;background:none !important;transform:translateY(1px) !important;}',
|
||||
'.survey-sort-icon::before,.survey-sort-icon::after{content:none !important;}',
|
||||
'.survey-sort-icon svg{display:block !important;width:100% !important;height:100% !important;transform:translateY(4px);}',
|
||||
'.survey-sort-icon svg path:first-child{transform:translateY(1.4px);transform-box:fill-box;transform-origin:center;}',
|
||||
'.survey-sort-icon svg path:nth-child(2){transform:translateY(-1.4px);transform-box:fill-box;transform-origin:center;}',
|
||||
'.survey-sort-icon svg path[stroke]{stroke-width:2px;}'
|
||||
].join('');
|
||||
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
function initSurveyQuestionSorting() {
|
||||
ensureSortIconStyles();
|
||||
|
||||
if (typeof Sortable !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
var sortableList = document.querySelector('[data-survey-question-sortable]');
|
||||
var orderForm = document.querySelector('[data-survey-question-order-shell]');
|
||||
var orderInput = document.querySelector('[data-survey-question-order-input]');
|
||||
|
||||
if (!sortableList || !orderForm || !orderInput || sortableList._surveyQuestionSortable) {
|
||||
return;
|
||||
}
|
||||
|
||||
var getOrderedIds = function () {
|
||||
return Array.from(sortableList.querySelectorAll('[data-survey-question-item]')).map(function (item) {
|
||||
return item.getAttribute('data-question-id') || '';
|
||||
}).filter(function (value) {
|
||||
return value !== '';
|
||||
});
|
||||
};
|
||||
|
||||
var initialOrder = getOrderedIds().join(',');
|
||||
|
||||
var updateOrderField = function () {
|
||||
orderInput.value = getOrderedIds().join(',');
|
||||
};
|
||||
|
||||
var updateQuestionIndices = function () {
|
||||
sortableList.querySelectorAll('[data-survey-question-item]').forEach(function (item, index) {
|
||||
var indexNode = item.querySelector('.survey-accordion-index');
|
||||
|
||||
if (indexNode) {
|
||||
indexNode.textContent = (index + 1) + '.';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var updateSaveVisibility = function () {
|
||||
var currentOrder = getOrderedIds().join(',');
|
||||
var isDirty = currentOrder !== initialOrder;
|
||||
|
||||
orderForm.hidden = !isDirty;
|
||||
orderForm.classList.toggle('is-visible', isDirty);
|
||||
updateOrderField();
|
||||
};
|
||||
|
||||
sortableList.querySelectorAll('[data-survey-question-sort-handle]').forEach(function (handle) {
|
||||
handle.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
});
|
||||
});
|
||||
|
||||
updateQuestionIndices();
|
||||
updateOrderField();
|
||||
updateSaveVisibility();
|
||||
|
||||
sortableList._surveyQuestionSortable = Sortable.create(sortableList, {
|
||||
animation: 180,
|
||||
draggable: '[data-survey-question-item]',
|
||||
handle: '[data-survey-question-sort-handle]',
|
||||
ghostClass: 'sortable-ghost',
|
||||
forceFallback: true,
|
||||
fallbackTolerance: 3,
|
||||
onStart: function (event) {
|
||||
if (event.item) {
|
||||
event.item.classList.add('is-reordering');
|
||||
}
|
||||
},
|
||||
onEnd: function (event) {
|
||||
if (event.item) {
|
||||
event.item.classList.remove('is-reordering');
|
||||
}
|
||||
|
||||
updateQuestionIndices();
|
||||
updateSaveVisibility();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initSurveyQuestionSorting, { once: true });
|
||||
} else {
|
||||
initSurveyQuestionSorting();
|
||||
}
|
||||
|
||||
window.addEventListener('load', initSurveyQuestionSorting, { once: true });
|
||||
})();
|
||||
Reference in New Issue
Block a user