From 344c1b42a250c1b69e640ea5bb9305e61169f80c Mon Sep 17 00:00:00 2001 From: Wojtek Date: Fri, 16 Oct 2026 21:08:28 +0200 Subject: [PATCH] Add bulk selection for filtered set questions --- README.md | 2 +- .../language/en-GB/com_testquestions.ini | 2 ++ .../sql/updates/mysql/1.43.19.sql | 1 + .../com_testquestions/tmpl/set/edit.php | 33 +++++++++++++++++-- com_testquestions.xml | 2 +- 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 administrator/components/com_testquestions/sql/updates/mysql/1.43.19.sql diff --git a/README.md b/README.md index fcf0dea..ff8fe93 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,6 @@ Szkielet komponentu Joomla 6 do gromadzenia pytań testowych. ## Instalacja -W Joomla wybierz **System → Install → Install from Folder** i wskaż ten katalog. Manifestem instalacyjnym jest `com_testquestions.xml` (wersja 1.43.18). +W Joomla wybierz **System → Install → Install from Folder** i wskaż ten katalog. Manifestem instalacyjnym jest `com_testquestions.xml` (wersja 1.43.19). Po instalacji komponent jest dostępny w panelu administratora jako **Pytania testowe**. diff --git a/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini b/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini index e7bd0d4..5fb5e3c 100644 --- a/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini +++ b/administrator/components/com_testquestions/language/en-GB/com_testquestions.ini @@ -105,8 +105,10 @@ COM_TESTQUESTIONS_SET_QUESTIONS="Pytania w zestawie" COM_TESTQUESTIONS_SET_QUESTION_COUNT="Liczba pytań" COM_TESTQUESTIONS_SET_SEARCH="Szukaj zestawów..." COM_TESTQUESTIONS_SET_CATEGORY_FILTER="Filtruj pytania według kategorii" +COM_TESTQUESTIONS_SET_CHOOSE_CATEGORY="Wybierz kategorię" COM_TESTQUESTIONS_SET_ID_FILTER="Filtruj pytania według ID" COM_TESTQUESTIONS_SET_ID_FILTER_HINT="Wpisz ID, np. 12, 34, 56" +COM_TESTQUESTIONS_SET_SELECT_ALL_VISIBLE="Zaznacz wszystkie widoczne pytania" COM_TESTQUESTIONS_SET_ALL_CATEGORIES="Wszystkie kategorie" COM_TESTQUESTIONS_UNCATEGORIZED="Bez kategorii" COM_TESTQUESTIONS_SET_SHOW_DETAILS="Pokaż odpowiedzi" diff --git a/administrator/components/com_testquestions/sql/updates/mysql/1.43.19.sql b/administrator/components/com_testquestions/sql/updates/mysql/1.43.19.sql new file mode 100644 index 0000000..bd5fafe --- /dev/null +++ b/administrator/components/com_testquestions/sql/updates/mysql/1.43.19.sql @@ -0,0 +1 @@ +-- Wydanie 1.43.19: usprawniono filtrowanie i zaznaczanie pytań w edycji zestawu. diff --git a/administrator/components/com_testquestions/tmpl/set/edit.php b/administrator/components/com_testquestions/tmpl/set/edit.php index 96c52f1..ea5f65d 100644 --- a/administrator/components/com_testquestions/tmpl/set/edit.php +++ b/administrator/components/com_testquestions/tmpl/set/edit.php @@ -96,6 +96,7 @@ HTMLHelper::_('behavior.formvalidator');
+
+ + +
questions as $question) : ?> id, array_map('intval', (array) $this->item->question_ids), true)) continue; ?> @@ -186,12 +191,25 @@ document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () { const filter = document.getElementById('set-question-category'); const idFilter = document.getElementById('set-question-ids'); + const selectVisible = document.getElementById('set-question-select-visible'); const rows = document.querySelectorAll('.set-available-question-row'); - if (!filter || !idFilter) { + if (!filter || !idFilter || !selectVisible) { return; } + const visibleRows = function () { + return Array.from(rows).filter(function (row) { return !row.classList.contains('d-none'); }); + }; + + const updateSelectVisible = function () { + const checkboxes = visibleRows().map(function (row) { return row.querySelector('input[type="checkbox"]'); }); + const checkedCount = checkboxes.filter(function (checkbox) { return checkbox.checked; }).length; + selectVisible.checked = checkboxes.length > 0 && checkedCount === checkboxes.length; + selectVisible.indeterminate = checkedCount > 0 && checkedCount < checkboxes.length; + selectVisible.disabled = checkboxes.length === 0; + }; + const applyFilters = function () { const requestedIds = idFilter.value .split(',') @@ -199,14 +217,25 @@ document.addEventListener('DOMContentLoaded', function () { .filter(function (value) { return value !== ''; }); rows.forEach(function (row) { - const matchesCategory = filter.value === '' || row.dataset.category === filter.value; + const matchesCategory = filter.value !== '__choose' && (filter.value === '' || row.dataset.category === filter.value); const matchesId = requestedIds.length === 0 || requestedIds.includes(row.dataset.id); row.classList.toggle('d-none', !matchesCategory || !matchesId); }); + updateSelectVisible(); }; filter.addEventListener('change', applyFilters); idFilter.addEventListener('input', applyFilters); + selectVisible.addEventListener('change', function () { + visibleRows().forEach(function (row) { + row.querySelector('input[type="checkbox"]').checked = selectVisible.checked; + }); + updateSelectVisible(); + }); + rows.forEach(function (row) { + row.querySelector('input[type="checkbox"]').addEventListener('change', updateSelectVisible); + }); + applyFilters(); });