Add ordinary set ordering and random frontend questions

This commit is contained in:
Wojtek
2026-10-16 11:27:37 +02:00
parent 96e8a4a0f5
commit 89ed65a406
6 changed files with 55 additions and 7 deletions
+1 -1
View File
@@ -30,6 +30,6 @@ Szkielet komponentu Joomla 6 do gromadzenia pytań testowych.
## Instalacja ## Instalacja
W Joomla wybierz **System → Install → Install from Folder** i wskaż ten katalog. Manifestem instalacyjnym jest `com_testquestions.xml` (wersja 1.39.0). W Joomla wybierz **System → Install → Install from Folder** i wskaż ten katalog. Manifestem instalacyjnym jest `com_testquestions.xml` (wersja 1.40.0).
Po instalacji komponent jest dostępny w panelu administratora jako **Pytania testowe**. Po instalacji komponent jest dostępny w panelu administratora jako **Pytania testowe**.
@@ -58,6 +58,7 @@ COM_TESTQUESTIONS_SET_ADD_VARIANT="Dodaj wariant"
COM_TESTQUESTIONS_SET_PARENT="Zestaw nadrzędny" COM_TESTQUESTIONS_SET_PARENT="Zestaw nadrzędny"
COM_TESTQUESTIONS_SET_NO_VARIANTS="Brak wariantów" COM_TESTQUESTIONS_SET_NO_VARIANTS="Brak wariantów"
COM_TESTQUESTIONS_SET_MULTI_QUESTIONS_INFO="Pytania są dodawane w poszczególnych wariantach zestawu." COM_TESTQUESTIONS_SET_MULTI_QUESTIONS_INFO="Pytania są dodawane w poszczególnych wariantach zestawu."
COM_TESTQUESTIONS_SET_REORDER_INFO="Przeciągnij pytania, aby zmienić ich kolejność."
COM_TESTQUESTIONS_SET_SAVE="Zapisz" COM_TESTQUESTIONS_SET_SAVE="Zapisz"
COM_TESTQUESTIONS_SET_SAVE_AND_CLOSE="Zapisz i zamknij" COM_TESTQUESTIONS_SET_SAVE_AND_CLOSE="Zapisz i zamknij"
COM_TESTQUESTIONS_SET_VARIANT_DURATION_INFO="Czas testu jest pobierany z zestawu nadrzędnego." COM_TESTQUESTIONS_SET_VARIANT_DURATION_INFO="Czas testu jest pobierany z zestawu nadrzędnego."
@@ -0,0 +1 @@
-- No database changes required for version 1.40.0.
@@ -8,6 +8,7 @@ use Joomla\CMS\Router\Route;
HTMLHelper::_('behavior.formvalidator'); HTMLHelper::_('behavior.formvalidator');
?> ?>
<form action="<?php echo Route::_('index.php?option=com_testquestions&view=set&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate"> <form action="<?php echo Route::_('index.php?option=com_testquestions&view=set&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate">
<?php $canOrderQuestions = !$this->isVariant && (string) $this->item->set_type === 'ordinary'; ?>
<fieldset class="adminform"> <fieldset class="adminform">
<?php echo $this->form->renderField('parent_id'); ?> <?php echo $this->form->renderField('parent_id'); ?>
<?php if ($this->isVariant) : ?> <?php if ($this->isVariant) : ?>
@@ -51,10 +52,14 @@ HTMLHelper::_('behavior.formvalidator');
<?php if (!((string) $this->item->set_type === 'multi' && (int) $this->item->parent_id === 0)) : ?> <?php if (!((string) $this->item->set_type === 'multi' && (int) $this->item->parent_id === 0)) : ?>
<fieldset class="mb-3"> <fieldset class="mb-3">
<legend><?php echo \Joomla\CMS\Language\Text::_('COM_TESTQUESTIONS_SET_SELECTED_QUESTIONS'); ?></legend> <legend><?php echo \Joomla\CMS\Language\Text::_('COM_TESTQUESTIONS_SET_SELECTED_QUESTIONS'); ?></legend>
<div id="set-selected-question-list" class="border rounded p-3"> <?php if ($canOrderQuestions) : ?>
<?php foreach ($this->questions as $question) : ?> <div class="form-text mb-2"><?php echo \Joomla\CMS\Language\Text::_('COM_TESTQUESTIONS_SET_REORDER_INFO'); ?></div>
<?php if (!in_array((int) $question->id, array_map('intval', (array) $this->item->question_ids), true)) continue; ?> <?php endif; ?>
<div class="form-check set-question-row"> <div id="set-selected-question-list" class="border rounded p-3" data-sortable="<?php echo $canOrderQuestions ? '1' : '0'; ?>">
<?php $questionsById = []; foreach ($this->questions as $availableQuestion) : $questionsById[(int) $availableQuestion->id] = $availableQuestion; endforeach; ?>
<?php foreach ((array) $this->item->question_ids as $selectedQuestionId) : ?>
<?php $question = $questionsById[(int) $selectedQuestionId] ?? null; if (!$question) continue; ?>
<div class="form-check set-question-row"<?php echo $canOrderQuestions ? ' draggable="true"' : ''; ?>>
<input class="form-check-input" type="checkbox" name="jform[question_ids][]" value="<?php echo (int) $question->id; ?>" id="set-question-<?php echo (int) $question->id; ?>" checked> <input class="form-check-input" type="checkbox" name="jform[question_ids][]" value="<?php echo (int) $question->id; ?>" id="set-question-<?php echo (int) $question->id; ?>" checked>
<label class="form-check-label" for="set-question-<?php echo (int) $question->id; ?>"> <label class="form-check-label" for="set-question-<?php echo (int) $question->id; ?>">
<span class="badge bg-secondary"><?php echo $this->escape($question->category_title ?: \Joomla\CMS\Language\Text::_('COM_TESTQUESTIONS_UNCATEGORIZED')); ?></span> <span class="badge bg-secondary"><?php echo $this->escape($question->category_title ?: \Joomla\CMS\Language\Text::_('COM_TESTQUESTIONS_UNCATEGORIZED')); ?></span>
@@ -124,6 +129,47 @@ HTMLHelper::_('behavior.formvalidator');
<?php echo HTMLHelper::_('form.token'); ?> <?php echo HTMLHelper::_('form.token'); ?>
</form> </form>
<script> <script>
document.addEventListener('DOMContentLoaded', function () {
const list = document.getElementById('set-selected-question-list');
if (!list || list.dataset.sortable !== '1') {
return;
}
let dragged = null;
list.querySelectorAll('.set-question-row[draggable="true"]').forEach(function (row) {
row.addEventListener('dragstart', function (event) {
dragged = row;
row.classList.add('opacity-50');
event.dataTransfer.effectAllowed = 'move';
});
row.addEventListener('dragend', function () {
row.classList.remove('opacity-50');
dragged = null;
});
row.addEventListener('dragover', function (event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
});
row.addEventListener('drop', function (event) {
event.preventDefault();
if (!dragged || dragged === row) {
return;
}
const rect = row.getBoundingClientRect();
const insertAfter = event.clientY > rect.top + rect.height / 2;
list.insertBefore(dragged, insertAfter ? row.nextSibling : row);
});
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
const filter = document.getElementById('set-question-category'); const filter = document.getElementById('set-question-category');
const rows = document.querySelectorAll('.set-available-question-row'); const rows = document.querySelectorAll('.set-available-question-row');
+1 -1
View File
@@ -4,7 +4,7 @@
<creationDate>2026-10-14</creationDate> <creationDate>2026-10-14</creationDate>
<author>Komponent</author> <author>Komponent</author>
<license>GNU General Public License version 2 or later</license> <license>GNU General Public License version 2 or later</license>
<version>1.39.0</version> <version>1.40.0</version>
<description>COM_TESTQUESTIONS_DESCRIPTION</description> <description>COM_TESTQUESTIONS_DESCRIPTION</description>
<element>com_testquestions</element> <element>com_testquestions</element>
<namespace path="src">Komponent\Component\Testquestions</namespace> <namespace path="src">Komponent\Component\Testquestions</namespace>
@@ -81,7 +81,7 @@ class SetModel extends BaseDatabaseModel
->innerJoin($db->quoteName('#__testquestions_questions', 'q') . ' ON q.id = sq.question_id') ->innerJoin($db->quoteName('#__testquestions_questions', 'q') . ' ON q.id = sq.question_id')
->where('sq.set_id = ' . $setId) ->where('sq.set_id = ' . $setId)
->where('q.published = 1') ->where('q.published = 1')
->order('sq.ordering ASC, q.id ASC') ->order('RAND()')
)->loadObjectList(); )->loadObjectList();
} }