Add helper functions for question type inference and options management in question editor
This commit is contained in:
@@ -172,6 +172,65 @@
|
|||||||
const resetQuestionOptionsButton = document.getElementById('reset-question-options');
|
const resetQuestionOptionsButton = document.getElementById('reset-question-options');
|
||||||
const questionsContainer = document.getElementById('questions-container');
|
const questionsContainer = document.getElementById('questions-container');
|
||||||
|
|
||||||
|
// Helper: get options array from a question regardless of schema shape
|
||||||
|
function getQuestionOptions(question) {
|
||||||
|
if (!question) return [];
|
||||||
|
if (Array.isArray(question.enum)) return question.enum.slice();
|
||||||
|
if (question.items && Array.isArray(question.items.enum)) return question.items.enum.slice();
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper: infer a UI questionType from the schema if question.questionType is not present
|
||||||
|
function inferQuestionType(question) {
|
||||||
|
if (!question) return 'text';
|
||||||
|
if (question.type === 'array') return 'multiselect';
|
||||||
|
if (question.format === 'select2' && question.type === 'string' && Array.isArray(getQuestionOptions(question))) return 'dropdown-select';
|
||||||
|
if (question.format === 'select' && question.type === 'string') return 'dropdown';
|
||||||
|
if (question.format === 'radio' && question.type === 'string') return 'radio';
|
||||||
|
if (question.format === 'textarea') return 'textarea';
|
||||||
|
if (question.type === 'number') return 'number';
|
||||||
|
if (question.type === 'range') return 'range';
|
||||||
|
if (question.enum && Array.isArray(question.enum) && question.enum.length === 2) {
|
||||||
|
const opts = question.enum.map(String).map(s => s.toLowerCase());
|
||||||
|
if ((opts.includes('yes') && opts.includes('no'))) return 'yesno';
|
||||||
|
if ((opts.includes('true') && opts.includes('false'))) return 'truefalse';
|
||||||
|
}
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper: apply an options array to a question object according to the selected UI type
|
||||||
|
function applyOptionsToQuestion(question, optionsArray, selectedType) {
|
||||||
|
optionsArray = (optionsArray || []).filter(o => o !== '');
|
||||||
|
if (selectedType === 'multiselect') {
|
||||||
|
question.type = 'array';
|
||||||
|
question.items = question.items || { type: 'string', enum: [] };
|
||||||
|
question.items.enum = optionsArray.length ? optionsArray : (question.items.enum || []);
|
||||||
|
question.uniqueItems = true;
|
||||||
|
question.format = 'select2';
|
||||||
|
delete question.enum;
|
||||||
|
} else {
|
||||||
|
// convert array->single if present
|
||||||
|
if (question.type === 'array' && question.items && Array.isArray(question.items.enum)) {
|
||||||
|
question.enum = question.items.enum.slice();
|
||||||
|
delete question.items;
|
||||||
|
delete question.uniqueItems;
|
||||||
|
}
|
||||||
|
if (optionsArray.length) {
|
||||||
|
question.enum = optionsArray;
|
||||||
|
}
|
||||||
|
// ensure string type for single-select/other
|
||||||
|
if (question.enum && Array.isArray(question.enum)) {
|
||||||
|
question.type = 'string';
|
||||||
|
}
|
||||||
|
// set formats for some known selected types
|
||||||
|
if (selectedType === 'dropdown-select') question.format = 'select2';
|
||||||
|
else if (selectedType === 'dropdown') question.format = 'select';
|
||||||
|
else if (selectedType === 'radio') question.format = 'radio';
|
||||||
|
}
|
||||||
|
// always store the UI mapping
|
||||||
|
question.questionType = selectedType;
|
||||||
|
}
|
||||||
|
|
||||||
question_editor.updateProps({
|
question_editor.updateProps({
|
||||||
onChange: (updatedContent, previousContent, context) => {
|
onChange: (updatedContent, previousContent, context) => {
|
||||||
// Call the original onChange handler if it exists
|
// Call the original onChange handler if it exists
|
||||||
@@ -332,7 +391,7 @@
|
|||||||
description: description,
|
description: description,
|
||||||
questionType: selectedType, // Add questionType property
|
questionType: selectedType, // Add questionType property
|
||||||
};
|
};
|
||||||
} else if (selectedType === 'multiselect') {
|
} else if (selectedType === 'multiselect') {
|
||||||
newQuestion = {
|
newQuestion = {
|
||||||
type: "array",
|
type: "array",
|
||||||
items: {
|
items: {
|
||||||
@@ -390,172 +449,100 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
newQuestion.propertyOrder = current_question_number; // Set the property order
|
newQuestion.propertyOrder = current_question_number; // Set the property order
|
||||||
// Add the new question to the properties
|
// Add the new question to the properties
|
||||||
currentContent.properties[`question_${current_question_number}`] = newQuestion;
|
currentContent.properties[`question_${current_question_number}`] = newQuestion;
|
||||||
|
|
||||||
// Update the editor with the new question
|
// Update the editor with the new question
|
||||||
question_editor.update({ json: currentContent });
|
question_editor.update({ json: currentContent });
|
||||||
toastr.success(`New question added: ${title}`);
|
toastr.success(`New question added: ${title}`);
|
||||||
renderQuestions(); // Re-render the questions list
|
renderQuestions(); // Re-render the questions list
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderQuestions() {
|
function renderQuestions() {
|
||||||
questionsContainer.innerHTML = ''; // Clear the container
|
questionsContainer.innerHTML = ''; // Clear the container
|
||||||
|
|
||||||
|
try {
|
||||||
|
let currentContent;
|
||||||
try {
|
try {
|
||||||
let currentContent;
|
currentContent = JSON.parse(question_editor.get().text);
|
||||||
try {
|
} catch {
|
||||||
currentContent = JSON.parse(question_editor.get().text);
|
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
||||||
} catch {
|
}
|
||||||
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
if (!currentContent || !currentContent.properties) {
|
||||||
}
|
console.warn('No properties found in the current content.');
|
||||||
if (!currentContent || !currentContent.properties) {
|
return;
|
||||||
console.warn('No properties found in the current content.');
|
}
|
||||||
return;
|
const properties = currentContent.properties || {};
|
||||||
}
|
|
||||||
const properties = currentContent.properties || {};
|
|
||||||
|
|
||||||
// Sort questions by propertyOrder
|
// Sort questions by propertyOrder
|
||||||
const sortedKeys = Object.keys(properties).sort((a, b) => {
|
const sortedKeys = Object.keys(properties).sort((a, b) => {
|
||||||
const orderA = properties[a].propertyOrder !== undefined ? properties[a].propertyOrder : 1000;
|
const orderA = properties[a].propertyOrder !== undefined ? properties[a].propertyOrder : 1000;
|
||||||
const orderB = properties[b].propertyOrder !== undefined ? properties[b].propertyOrder : 1000;
|
const orderB = properties[b].propertyOrder !== undefined ? properties[b].propertyOrder : 1000;
|
||||||
return orderA - orderB;
|
return orderA - orderB;
|
||||||
});
|
});
|
||||||
|
|
||||||
sortedKeys.forEach((key, index) => {
|
sortedKeys.forEach((key, index) => {
|
||||||
const question = properties[key];
|
const question = properties[key];
|
||||||
const questionElement = document.createElement('div');
|
const questionElement = document.createElement('div');
|
||||||
questionElement.className = 'question-item';
|
questionElement.className = 'question-item';
|
||||||
questionElement.style.marginBottom = '10px';
|
questionElement.style.marginBottom = '10px';
|
||||||
questionElement.setAttribute('draggable', 'true'); // Make the element draggable
|
questionElement.setAttribute('draggable', 'true'); // Make the element draggable
|
||||||
questionElement.setAttribute('data-question-key', key);
|
questionElement.setAttribute('data-question-key', key);
|
||||||
questionElement.setAttribute('data-index', index);
|
questionElement.setAttribute('data-index', index);
|
||||||
|
|
||||||
questionElement.innerHTML = `
|
questionElement.innerHTML = `
|
||||||
<strong>${question.title || key}</strong>
|
<strong>${question.title || key}</strong>
|
||||||
<button type="button" class="btn btn-warning btn-sm edit-question-button" data-question-key="${key}" style="margin-left: 10px;">Edit</button>
|
<button type="button" class="btn btn-warning btn-sm edit-question-button" data-question-key="${key}" style="margin-left: 10px;">Edit</button>
|
||||||
<button type="button" class="btn btn-danger btn-sm delete-question-button" data-question-key="${key}" style="margin-left: 10px;">Delete</button>
|
<button type="button" class="btn btn-danger btn-sm delete-question-button" data-question-key="${key}" style="margin-left: 10px;">Delete</button>
|
||||||
`;
|
`;
|
||||||
questionsContainer.appendChild(questionElement);
|
questionsContainer.appendChild(questionElement);
|
||||||
|
|
||||||
// Add event listener to delete the question
|
// Add event listener to delete the question
|
||||||
questionElement.querySelector('.delete-question-button').addEventListener('click', (e) => {
|
questionElement.querySelector('.delete-question-button').addEventListener('click', (e) => {
|
||||||
const questionKey = e.target.getAttribute('data-question-key');
|
const questionKey = e.target.getAttribute('data-question-key');
|
||||||
deleteQuestion(questionKey);
|
deleteQuestion(questionKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add event listener to edit the question
|
// Add event listener to edit the question
|
||||||
questionElement.querySelector('.edit-question-button').addEventListener('click', (e) => {
|
questionElement.querySelector('.edit-question-button').addEventListener('click', (e) => {
|
||||||
const questionKey = e.target.getAttribute('data-question-key');
|
const questionKey = e.target.getAttribute('data-question-key');
|
||||||
editQuestion(questionKey);
|
editQuestion(questionKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add drag-and-drop event listeners
|
// Add drag-and-drop event listeners
|
||||||
questionElement.addEventListener('dragstart', handleDragStart);
|
questionElement.addEventListener('dragstart', handleDragStart);
|
||||||
questionElement.addEventListener('dragover', handleDragOver);
|
questionElement.addEventListener('dragover', handleDragOver);
|
||||||
questionElement.addEventListener('drop', handleDrop);
|
questionElement.addEventListener('drop', handleDrop);
|
||||||
questionElement.addEventListener('dragend', handleDragEnd);
|
questionElement.addEventListener('dragend', handleDragEnd);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error rendering questions:', error);
|
console.error('Error rendering questions:', error);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Drag-and-drop event handlers
|
// Drag-and-drop event handlers
|
||||||
let draggedElement = null;
|
let draggedElement = null;
|
||||||
|
|
||||||
function handleDragStart(e) {
|
function handleDragStart(e) {
|
||||||
draggedElement = this;
|
draggedElement = this;
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
e.dataTransfer.setData('text/html', this.outerHTML);
|
e.dataTransfer.setData('text/html', this.outerHTML);
|
||||||
this.classList.add('dragging');
|
this.classList.add('dragging');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDragOver(e) {
|
function handleDragOver(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.dataTransfer.dropEffect = 'move';
|
e.dataTransfer.dropEffect = 'move';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleDrop(e) {
|
function handleDrop(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (draggedElement !== this) {
|
if (draggedElement !== this) {
|
||||||
const draggedIndex = parseInt(draggedElement.getAttribute('data-index'));
|
const draggedIndex = parseInt(draggedElement.getAttribute('data-index'));
|
||||||
const targetIndex = parseInt(this.getAttribute('data-index'));
|
const targetIndex = parseInt(this.getAttribute('data-index'));
|
||||||
|
|
||||||
try {
|
|
||||||
let currentContent;
|
|
||||||
try {
|
|
||||||
currentContent = JSON.parse(question_editor.get().text);
|
|
||||||
} catch {
|
|
||||||
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
|
||||||
}
|
|
||||||
const properties = currentContent.properties || {};
|
|
||||||
const keys = Object.keys(properties);
|
|
||||||
|
|
||||||
// Sort keys by propertyOrder
|
|
||||||
const sortedKeys = keys.sort((a, b) => {
|
|
||||||
const orderA = properties[a].propertyOrder !== undefined ? properties[a].propertyOrder : Infinity;
|
|
||||||
const orderB = properties[b].propertyOrder !== undefined ? properties[b].propertyOrder : Infinity;
|
|
||||||
return orderA - orderB;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Move the dragged question to the target position
|
|
||||||
const draggedKey = sortedKeys.splice(draggedIndex, 1)[0]; // Remove dragged key
|
|
||||||
sortedKeys.splice(targetIndex, 0, draggedKey); // Insert dragged key at target position
|
|
||||||
|
|
||||||
// Reassign propertyOrder to ensure uniqueness and correct order
|
|
||||||
sortedKeys.forEach((key, index) => {
|
|
||||||
properties[key].propertyOrder = index + 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Assign propertyOrder to any questions without it
|
|
||||||
keys.forEach((key) => {
|
|
||||||
if (properties[key].propertyOrder === undefined) {
|
|
||||||
properties[key].propertyOrder = sortedKeys.length + 1;
|
|
||||||
sortedKeys.push(key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
currentContent.properties = properties;
|
|
||||||
question_editor.update({ json: currentContent });
|
|
||||||
toastr.success('Questions reordered successfully.');
|
|
||||||
renderQuestions(); // Re-render the questions list
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error reordering questions:', error);
|
|
||||||
toastr.error('Failed to reorder questions.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDragEnd() {
|
|
||||||
this.classList.remove('dragging');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to delete a question
|
|
||||||
function deleteQuestion(questionKey) {
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
currentContent = JSON.parse(question_editor.get().text);
|
|
||||||
} catch {
|
|
||||||
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
|
||||||
}
|
|
||||||
if (currentContent.properties && currentContent.properties[questionKey]) {
|
|
||||||
delete currentContent.properties[questionKey]; // Remove the question
|
|
||||||
question_editor.update({ json: currentContent }); // Update the editor
|
|
||||||
toastr.success(`Question "${questionKey}" has been deleted.`);
|
|
||||||
renderQuestions(); // Re-render the questions list
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error deleting question:', error);
|
|
||||||
toastr.error('Failed to delete the question.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Initial render of questions
|
|
||||||
renderQuestions();
|
|
||||||
|
|
||||||
function editQuestion(questionKey) {
|
|
||||||
try {
|
try {
|
||||||
let currentContent;
|
let currentContent;
|
||||||
try {
|
try {
|
||||||
@@ -564,96 +551,169 @@
|
|||||||
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
||||||
}
|
}
|
||||||
const properties = currentContent.properties || {};
|
const properties = currentContent.properties || {};
|
||||||
const question = properties[questionKey];
|
const keys = Object.keys(properties);
|
||||||
|
|
||||||
if (question) {
|
// Sort keys by propertyOrder
|
||||||
|
const sortedKeys = keys.sort((a, b) => {
|
||||||
|
const orderA = properties[a].propertyOrder !== undefined ? properties[a].propertyOrder : Infinity;
|
||||||
|
const orderB = properties[b].propertyOrder !== undefined ? properties[b].propertyOrder : Infinity;
|
||||||
|
return orderA - orderB;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Move the dragged question to the target position
|
||||||
|
const draggedKey = sortedKeys.splice(draggedIndex, 1)[0]; // Remove dragged key
|
||||||
|
sortedKeys.splice(targetIndex, 0, draggedKey); // Insert dragged key at target position
|
||||||
|
|
||||||
|
// Reassign propertyOrder to ensure uniqueness and correct order
|
||||||
|
sortedKeys.forEach((key, index) => {
|
||||||
|
properties[key].propertyOrder = index + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assign propertyOrder to any questions without it
|
||||||
|
keys.forEach((key) => {
|
||||||
|
if (properties[key].propertyOrder === undefined) {
|
||||||
|
properties[key].propertyOrder = sortedKeys.length + 1;
|
||||||
|
sortedKeys.push(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentContent.properties = properties;
|
||||||
|
question_editor.update({ json: currentContent });
|
||||||
|
toastr.success('Questions reordered successfully.');
|
||||||
|
renderQuestions(); // Re-render the questions list
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error reordering questions:', error);
|
||||||
|
toastr.error('Failed to reorder questions.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDragEnd() {
|
||||||
|
this.classList.remove('dragging');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to delete a question
|
||||||
|
function deleteQuestion(questionKey) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
currentContent = JSON.parse(question_editor.get().text);
|
||||||
|
} catch {
|
||||||
|
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
||||||
|
}
|
||||||
|
if (currentContent.properties && currentContent.properties[questionKey]) {
|
||||||
|
delete currentContent.properties[questionKey]; // Remove the question
|
||||||
|
question_editor.update({ json: currentContent }); // Update the editor
|
||||||
|
toastr.success(`Question "${questionKey}" has been deleted.`);
|
||||||
|
renderQuestions(); // Re-render the questions list
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error deleting question:', error);
|
||||||
|
toastr.error('Failed to delete the question.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Initial render of questions
|
||||||
|
renderQuestions();
|
||||||
|
|
||||||
|
function editQuestion(questionKey) {
|
||||||
|
try {
|
||||||
|
let currentContent;
|
||||||
|
try {
|
||||||
|
currentContent = JSON.parse(question_editor.get().text);
|
||||||
|
} catch {
|
||||||
|
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
||||||
|
}
|
||||||
|
const properties = currentContent.properties || {};
|
||||||
|
const question = properties[questionKey];
|
||||||
|
|
||||||
|
if (question) {
|
||||||
// Populate the form fields with the question's data
|
// Populate the form fields with the question's data
|
||||||
questionTitleInput.value = question.title || '';
|
questionTitleInput.value = question.title || '';
|
||||||
questionDescriptionInput.value = question.description || '';
|
questionDescriptionInput.value = question.description || '';
|
||||||
questionTypeSelect.value = question.questionType || 'text';
|
questionTypeSelect.value = question.questionType || 'text';
|
||||||
|
|
||||||
// Clear existing options and populate them if applicable
|
// Clear existing options and populate them if applicable
|
||||||
while (questionOptionsContainer.firstChild) {
|
while (questionOptionsContainer.firstChild) {
|
||||||
questionOptionsContainer.removeChild(questionOptionsContainer.firstChild);
|
questionOptionsContainer.removeChild(questionOptionsContainer.firstChild);
|
||||||
}
|
}
|
||||||
if (question.enum) {
|
// Support both single-select (question.enum) and multiselect (question.items.enum)
|
||||||
question.enum.forEach((option, index) => {
|
const enumList = getQuestionOptions(question) || [];
|
||||||
const optionInput = document.createElement('div');
|
if (enumList.length) {
|
||||||
optionInput.className = 'option-input';
|
enumList.forEach((option, index) => {
|
||||||
optionInput.style.marginBottom = '5px';
|
const optionInput = document.createElement('div');
|
||||||
optionInput.innerHTML = `
|
optionInput.className = 'option-input';
|
||||||
|
optionInput.style.marginBottom = '5px';
|
||||||
|
optionInput.innerHTML = `
|
||||||
<input type="text" class="form-control option-field" value="${option}" placeholder="Option ${index + 1}" style="display: inline-block; width: 90%;">
|
<input type="text" class="form-control option-field" value="${option}" placeholder="Option ${index + 1}" style="display: inline-block; width: 90%;">
|
||||||
<button type="button" class="btn btn-danger btn-sm remove-option-button" style="display: inline-block; width: 8%;">×</button>
|
<button type="button" class="btn btn-danger btn-sm remove-option-button" style="display: inline-block; width: 8%;">×</button>
|
||||||
`;
|
`;
|
||||||
questionOptionsContainer.appendChild(optionInput);
|
questionOptionsContainer.appendChild(optionInput);
|
||||||
|
// Add event listener to remove the option
|
||||||
// Add event listener to remove the option
|
optionInput.querySelector('.remove-option-button').addEventListener('click', () => {
|
||||||
optionInput.querySelector('.remove-option-button').addEventListener('click', () => {
|
questionOptionsContainer.removeChild(optionInput);
|
||||||
questionOptionsContainer.removeChild(optionInput);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
optionsConfigurator.style.display = 'block';
|
});
|
||||||
} else {
|
optionsConfigurator.style.display = 'block';
|
||||||
optionsConfigurator.style.display = 'none';
|
} else {
|
||||||
}
|
optionsConfigurator.style.display = 'none';
|
||||||
|
}
|
||||||
|
// If questionType is not set, infer it from the schema
|
||||||
|
questionTypeSelect.value = question.questionType || inferQuestionType(question);
|
||||||
|
|
||||||
// Update the "Add New Question" button to save changes
|
// Update the "Add New Question" button to save changes
|
||||||
addNewQuestionButton.textContent = 'Save Changes';
|
addNewQuestionButton.textContent = 'Save Changes';
|
||||||
addNewQuestionButton.onclick = () => {
|
addNewQuestionButton.onclick = () => {
|
||||||
saveEditedQuestion(questionKey);
|
saveEditedQuestion(questionKey);
|
||||||
};
|
};
|
||||||
document.getElementById('add-question-block').open = true; // Open the question block
|
document.getElementById('add-question-block').open = true; // Open the question block
|
||||||
document.getElementById('add-question-block').scrollIntoView({ behavior: 'smooth', block: "center" }); // Scroll to the question block
|
document.getElementById('add-question-block').scrollIntoView({ behavior: 'smooth', block: "center" }); // Scroll to the question block
|
||||||
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error editing question:', error);
|
|
||||||
toastr.error('Failed to edit the question.');
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error editing question:', error);
|
||||||
|
toastr.error('Failed to edit the question.');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function saveEditedQuestion(questionKey) {
|
function saveEditedQuestion(questionKey) {
|
||||||
|
try {
|
||||||
|
let currentContent;
|
||||||
try {
|
try {
|
||||||
let currentContent;
|
currentContent = JSON.parse(question_editor.get().text);
|
||||||
try {
|
} catch {
|
||||||
currentContent = JSON.parse(question_editor.get().text);
|
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
||||||
} catch {
|
}
|
||||||
currentContent = JSON.parse(JSON.stringify(question_editor.get().json));
|
const properties = currentContent.properties || {};
|
||||||
}
|
const question = properties[questionKey];
|
||||||
const properties = currentContent.properties || {};
|
|
||||||
const question = properties[questionKey];
|
|
||||||
|
|
||||||
if (question) {
|
if (question) {
|
||||||
// Update the question with the new values from the form
|
// Update the question with the new values from the form
|
||||||
question.title = questionTitleInput.value || `Question ${questionKey}`;
|
question.title = questionTitleInput.value || `Question ${questionKey}`;
|
||||||
question.description = questionDescriptionInput.value || '';
|
question.description = questionDescriptionInput.value || '';
|
||||||
question.format = questionTypeSelect.value;
|
question.format = questionTypeSelect.value;
|
||||||
|
|
||||||
// Update the options if applicable
|
// Update the options if applicable
|
||||||
if (question.enum) {
|
const newOptions = questionOptionsContainer ? Array.from(questionOptionsContainer.querySelectorAll('.option-field')).map((input) => input.value.trim()).filter((option) => option !== '') : [];
|
||||||
question.enum = Array.from(questionOptionsContainer.querySelectorAll('.option-field'))
|
const selectedType = questionTypeSelect ? questionTypeSelect.value : null;
|
||||||
.map((input) => input.value.trim())
|
applyOptionsToQuestion(question, newOptions, selectedType);
|
||||||
.filter((option) => option !== ''); // Exclude empty options
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the editor with the modified question
|
// Update the editor with the modified question
|
||||||
currentContent.properties[questionKey] = question;
|
currentContent.properties[questionKey] = question;
|
||||||
question_editor.update({ json: currentContent });
|
try { question_editor.update({ json: currentContent }); } catch (e) { console.warn('Failed to update editor after saveEditedQuestion', e); }
|
||||||
|
|
||||||
toastr.success(`Question "${question.title}" updated successfully.`);
|
toastr.success(`Question "${question.title}" updated successfully.`);
|
||||||
renderQuestions(); // Re-render the questions list
|
renderQuestions(); // Re-render the questions list
|
||||||
|
|
||||||
// Reset the "Add New Question" button
|
// Reset the "Add New Question" button
|
||||||
addNewQuestionButton.textContent = 'Add New Question';
|
addNewQuestionButton.textContent = 'Add New Question';
|
||||||
addNewQuestionButton.onclick = addNewQuestion;
|
addNewQuestionButton.onclick = addNewQuestion;
|
||||||
resetQuestion(); // Reset the question options
|
resetQuestion(); // Reset the question options
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error saving edited question:', error);
|
|
||||||
toastr.error('Failed to save the question.');
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving edited question:', error);
|
||||||
|
toastr.error('Failed to save the question.');
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user