Fancified the template selector

This commit is contained in:
Nathan Schneider
2025-05-12 22:44:24 -06:00
parent 41aeffa81b
commit 8aabd66666
3 changed files with 279 additions and 131 deletions

View File

@ -82,6 +82,7 @@ document.addEventListener('DOMContentLoaded', function() {
/* Hide template selector */
.protocol-template-selector { display: none !important; }
.template-body { display: none !important; }
/* Expand all sections */
.stage-body { display: block !important; }
@ -235,13 +236,8 @@ document.addEventListener('DOMContentLoaded', function() {
// Populate the template selector
populateTemplateSelector(templates);
// Add template selection event handler
if (protocolTemplateSelect) {
protocolTemplateSelect.addEventListener('change', handleTemplateSelection);
console.log('Template selector event handler attached');
} else {
console.error('Template select element not found');
}
// Template selection is now handled by buttons in the template options
console.log('Template selection will be handled by buttons in the template options');
} else {
console.error('Templates not available after loading script');
}
@ -261,13 +257,8 @@ document.addEventListener('DOMContentLoaded', function() {
// Populate the template selector
populateTemplateSelector(templates);
// Add template selection event handler
if (protocolTemplateSelect) {
protocolTemplateSelect.addEventListener('change', handleTemplateSelection);
console.log('Template selector event handler attached');
} else {
console.error('Template select element not found');
}
// Template selection is now handled by buttons in the template options
console.log('Template selection will be handled by buttons in the template options');
})
.catch(importError => {
console.error('ES module import also failed:', importError);
@ -279,25 +270,47 @@ document.addEventListener('DOMContentLoaded', function() {
}
}
// Function to populate the template selector dropdown
// Function to populate the template selector with cards
function populateTemplateSelector(templatesList) {
if (!protocolTemplateSelect || !templatesList || templatesList.length === 0) {
console.error('Cannot populate template selector - missing element or templates');
if (!templatesList || templatesList.length === 0) {
console.error('Cannot populate template selector - missing templates');
return;
}
console.log('Populating template selector with', templatesList.length, 'templates');
// Clear all existing options
while (protocolTemplateSelect.options.length > 0) {
protocolTemplateSelect.remove(0);
// Find the template options container
const templateOptionsContainer = document.querySelector('.template-options');
if (!templateOptionsContainer) {
console.error('Template options container not found');
return;
}
// Add the default "Create Your Own" option
const defaultOption = document.createElement('option');
defaultOption.value = "";
defaultOption.textContent = "-- Create Your Own Protocol --";
protocolTemplateSelect.appendChild(defaultOption);
// Clear existing template options
templateOptionsContainer.innerHTML = '';
// Create the "Create Your Own" option first
const createYourOwnOption = document.createElement('div');
createYourOwnOption.className = 'template-option';
createYourOwnOption.setAttribute('data-template-id', '');
const createYourOwnBtn = document.createElement('button');
createYourOwnBtn.className = 'template-select-btn';
createYourOwnBtn.textContent = 'Create Your Own Protocol';
createYourOwnBtn.setAttribute('type', 'button');
const createYourOwnDesc = document.createElement('p');
createYourOwnDesc.className = 'template-description';
createYourOwnDesc.textContent = 'Start with a blank protocol and build it from scratch.';
createYourOwnOption.appendChild(createYourOwnBtn);
createYourOwnOption.appendChild(createYourOwnDesc);
createYourOwnOption.addEventListener('click', function() {
console.log('Create your own option clicked');
clearAllFields();
});
templateOptionsContainer.appendChild(createYourOwnOption);
// Verify templates have required properties
let validTemplateCount = 0;
@ -310,67 +323,143 @@ document.addEventListener('DOMContentLoaded', function() {
});
console.log(`Found ${validTemplateCount} valid templates out of ${templatesList.length} total`);
// Add template options
// Add template options as cards
templatesList.forEach(template => {
const option = document.createElement('option');
option.value = template.id;
option.textContent = template.title;
protocolTemplateSelect.appendChild(option);
console.log('Added template option:', template.title, 'with ID:', template.id);
if (!template.id || !template.title || !template.description) {
return; // Skip invalid templates
}
// Debugging template structure
const templateOption = document.createElement('div');
templateOption.className = 'template-option';
templateOption.setAttribute('data-template-id', template.id);
// Make the entire card clickable
templateOption.addEventListener('click', function() {
// For debugging
console.log('Template option clicked for:', template.id);
// Find and apply the template
const selectedTemplate = templates.find(t => t.id === template.id);
if (selectedTemplate) {
applyTemplate(selectedTemplate);
// Close the template section after selection
const templateSection = document.querySelector('.protocol-template-selector');
if (templateSection) {
const templateBody = templateSection.querySelector('.template-body');
const toggleBtn = templateSection.querySelector('.toggle-btn');
if (templateBody && toggleBtn) {
templateBody.style.display = 'none';
toggleBtn.textContent = '+';
}
}
} else {
console.error('Template not found:', template.id);
}
});
const selectButton = document.createElement('button');
selectButton.className = 'template-select-btn';
selectButton.textContent = template.title;
selectButton.setAttribute('type', 'button');
const description = document.createElement('p');
description.className = 'template-description';
description.textContent = template.description;
templateOption.appendChild(selectButton);
templateOption.appendChild(description);
templateOptionsContainer.appendChild(templateOption);
console.log('Added template option:', template.title, 'with ID:', template.id);
console.log(' > Description:', template.description ? template.description.substring(0, 50) + '...' : 'MISSING');
console.log(' > Has data:', template.data ? 'Yes' : 'No');
console.log(' > Has stages:', template.data?.stages ? 'Yes - ' + Object.keys(template.data.stages).length + ' stages' : 'No');
});
// We've already set up the click handler for "Create Your Own" when creating it
}
// Handle template selection
function handleTemplateSelection() {
const selectedTemplateId = this.value;
console.log('Template selection changed to:', selectedTemplateId);
// Function to apply a template by ID
function applyTemplateById(templateId) {
console.log('Applying template by ID:', templateId);
if (selectedTemplateId) {
if (templateId) {
// Find the selected template from our loaded templates
const selectedTemplate = templates.find(t => t.id === selectedTemplateId);
const selectedTemplate = templates.find(t => t.id === templateId);
if (selectedTemplate) {
console.log('Found template:', selectedTemplate.title);
applyTemplate(selectedTemplate);
} else {
console.error('Template not found:', selectedTemplateId);
}
} else {
// Clear all fields if "Create Your Own" is selected
document.querySelectorAll('textarea').forEach(textarea => {
textarea.value = '';
});
// Reset protocol data
protocol = {
metadata: {
communityName: "",
summary: ""
},
stages: {}
};
// Collapse all sections
stageContents.forEach(content => {
content.style.display = 'none';
const toggleBtn = content.parentElement.querySelector('.toggle-btn');
if (toggleBtn) {
toggleBtn.textContent = '+';
// Close the template section after selection
const templateSection = document.querySelector('.protocol-template-selector');
if (templateSection) {
const templateBody = templateSection.querySelector('.template-body');
const toggleBtn = templateSection.querySelector('.toggle-btn');
if (templateBody && toggleBtn) {
templateBody.style.display = 'none';
toggleBtn.textContent = '+';
}
}
});
// Update preview mode if active
if (previewModeActive) {
markComponentsWithContent();
} else {
console.error('Template not found:', templateId);
}
}
}
// Function to clear all fields
function clearAllFields() {
// Clear all textareas
document.querySelectorAll('textarea').forEach(textarea => {
textarea.value = '';
});
// Clear community name input
if (communityNameInput) {
communityNameInput.value = '';
}
// Clear protocol summary
if (protocolSummaryTextarea) {
protocolSummaryTextarea.value = '';
}
// Reset protocol data
protocol = {
metadata: {
communityName: "",
summary: ""
},
stages: {}
};
// Collapse all sections
stageContents.forEach(content => {
content.style.display = 'none';
const toggleBtn = content.parentElement.querySelector('.toggle-btn');
if (toggleBtn) {
toggleBtn.textContent = '+';
}
});
// Close the template section after clearing
const templateSection = document.querySelector('.protocol-template-selector');
if (templateSection) {
const templateBody = templateSection.querySelector('.template-body');
const toggleBtn = templateSection.querySelector('.toggle-btn');
if (templateBody && toggleBtn) {
templateBody.style.display = 'none';
toggleBtn.textContent = '+';
}
}
// Update preview mode if active
if (previewModeActive) {
markComponentsWithContent();
}
console.log('All fields cleared');
}
// Function to apply a template to the form
function applyTemplate(selectedTemplate) {
if (!selectedTemplate) {
@ -498,7 +587,6 @@ document.addEventListener('DOMContentLoaded', function() {
const moduleSelects = document.querySelectorAll('.module-select');
console.log('Found module selects:', moduleSelects.length);
const protocolTemplateSelect = document.getElementById('protocol-template');
const communityNameInput = document.getElementById('community-name');
const protocolSummaryTextarea = document.getElementById('protocol-summary');
@ -509,27 +597,10 @@ document.addEventListener('DOMContentLoaded', function() {
const importJsonInput = document.getElementById('import-json');
const importBtn = document.getElementById('import-btn');
// Function to initialize the template selector
// This function is no longer needed with the new template UI
// Keeping an empty function to avoid errors if it's called elsewhere
function initializeTemplateSelector(templatesList) {
if (!protocolTemplateSelect || !templatesList || templatesList.length === 0) {
return;
}
// Clear existing options
while (protocolTemplateSelect.options.length > 1) {
protocolTemplateSelect.remove(1);
}
// Add template options
templatesList.forEach(template => {
const option = document.createElement('option');
option.value = template.id;
option.textContent = template.title;
protocolTemplateSelect.appendChild(option);
});
// Add template selection event handler
protocolTemplateSelect.addEventListener('change', handleTemplateSelection);
console.log('initializeTemplateSelector is deprecated, using new UI instead');
}
// Hide module selectors since we're using templates directly
@ -931,15 +1002,18 @@ document.addEventListener('DOMContentLoaded', function() {
}
}
// If the imported protocol has template information, select that template
if (protocol.templateId && protocolTemplateSelect) {
protocolTemplateSelect.value = protocol.templateId;
// Update template description
if (protocol.templateDescription && templateDescription) {
templateDescription.textContent = protocol.templateDescription;
templateDescription.style.display = 'block';
}
// If the imported protocol has template information, highlight the template
if (protocol.templateId) {
// Highlight the selected template option
const templateOptions = document.querySelectorAll('.template-option');
templateOptions.forEach(option => {
const templateId = option.getAttribute('data-template-id');
if (templateId === protocol.templateId) {
option.classList.add('selected');
} else {
option.classList.remove('selected');
}
});
// Expand all sections
stageContents.forEach(content => {
@ -950,14 +1024,10 @@ document.addEventListener('DOMContentLoaded', function() {
}
});
} else {
// If no template, reset the template selector
if (protocolTemplateSelect) {
protocolTemplateSelect.value = '';
}
if (templateDescription) {
templateDescription.textContent = '';
templateDescription.style.display = 'none';
}
// If no template, remove any highlights
document.querySelectorAll('.template-option').forEach(option => {
option.classList.remove('selected');
});
}
// Update preview mode if active