diff --git a/static/css/main.css b/static/css/main.css index b553f58..c7e1875 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -738,25 +738,65 @@ input:checked + .toggle-slider:before { } .protocol-template-selector { - padding: 2rem; border-bottom: 1px solid var(--border-color); background-color: rgba(0, 0, 0, 0.02); } -.protocol-template-selector label { - display: block; - margin-bottom: 0.75rem; - font-weight: 500; - font-size: 1.1rem; +.protocol-template-selector .stage-header { + background-color: rgba(0, 0, 0, 0.02); } -.protocol-template-select { - width: 100%; - padding: 0.75rem; +.template-body { + padding: 0 2rem 2rem; +} + +.template-options { + display: flex; + flex-direction: column; + gap: 1rem; + padding-top: 1rem; +} + +.template-option { border: 1px solid var(--border-color); - font-family: inherit; - background-color: var(--light-color); - margin-bottom: 1rem; + padding: 1.5rem; + background-color: white; + border-radius: 4px; + transition: border-color 0.3s, box-shadow 0.3s; + cursor: pointer; + position: relative; +} + +.template-option:hover { + border-color: #aaa; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.template-option.selected { + border-color: var(--dark-color); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); +} + +.template-select-btn { + display: block; + font-size: 1.2rem; + font-weight: 600; + margin-bottom: 0.75rem; + color: var(--dark-color); + background: none; + border: none; + padding: 0; + text-align: left; + cursor: inherit; +} + +/* Remove the underline effect */ + +.template-description { + font-size: 0.95rem; + color: var(--secondary-color); + margin: 0; + line-height: 1.4; } .protocol-metadata { @@ -773,11 +813,11 @@ input:checked + .toggle-slider:before { margin-bottom: 0; } -.metadata-field label { - display: block; - margin-bottom: 0.75rem; - font-weight: 500; - font-size: 1.1rem; +.metadata-field h2 { + font-size: 1.4rem; + margin: 0 0 0.75rem 0; + color: var(--dark-color); + font-weight: 600; } .metadata-field input[type="text"] { @@ -786,6 +826,8 @@ input:checked + .toggle-slider:before { border: 1px solid var(--border-color); font-family: inherit; background-color: var(--light-color); + font-size: 1.25rem; /* Larger font size for community name */ + font-weight: 500; } .metadata-field textarea { diff --git a/static/js/builder.js b/static/js/builder.js index 7f4efbd..c5523cb 100644 --- a/static/js/builder.js +++ b/static/js/builder.js @@ -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 diff --git a/themes/dispute-protocol-theme/layouts/_default/builder.html b/themes/dispute-protocol-theme/layouts/_default/builder.html index 24d334a..676dd7d 100644 --- a/themes/dispute-protocol-theme/layouts/_default/builder.html +++ b/themes/dispute-protocol-theme/layouts/_default/builder.html @@ -7,22 +7,32 @@