FHIR Resource Profile Customizer

FHIR Resource Profile Customizer

Profile Metadata

Add Custom Constraints

Current Profile Constraints

FHIR Resource Profile Definition

Profile Name:
Base Resource:
Date Generated:
Total Constraints:

Element Constraints Table

Element Base Card. Profile Card. Base Type Profile Type Base Description Constraint/Notes

No custom constraints defined.

"; } appState.customConstraints.forEach(function(constraint) { var item = document.createElement("div"); item.className = "fpc-constraint-item"; item.innerHTML = ` ${constraint.elementName}: ${constraint.min}..${constraint.max} (${constraint.notes.substring(0, 40)}...) `; constraintListDiv.appendChild(item); }); } function renderDashboardTab() { var baseResourceName = appState.baseResource; var baseElements = baseResourceData[baseResourceName] || []; var constraints = appState.customConstraints; // Metadata Display dispProfileName.textContent = appState.profileName; dispBaseResource.textContent = baseResourceName; dispProfileDate.textContent = appState.profileDate; dispTotalConstraints.textContent = constraints.length; // Render Table tableBody.innerHTML = ""; // Combine base elements and constraints, ensuring all base elements are listed baseElements.forEach(function(baseEl) { var constraint = constraints.find(function(c) { return c.elementName === baseEl.name; }); var profileMin = constraint ? constraint.min : baseEl.baseMin; var profileMax = constraint ? constraint.max : baseEl.baseMax; var profileType = constraint ? (constraint.type || baseEl.baseType) : baseEl.baseType; var notes = constraint ? constraint.notes : ''; // Check for override var minOverride = profileMin !== baseEl.baseMin; var maxOverride = profileMax !== baseEl.baseMax; var typeOverride = profileType !== baseEl.baseType; var minClass = minOverride ? 'fpc-override' : 'fpc-cardinality'; var maxClass = maxOverride ? 'fpc-override' : 'fpc-cardinality'; var typeClass = typeOverride ? 'fpc-override' : ''; var tr = document.createElement("tr"); tr.innerHTML = ` ${baseEl.name} ${baseEl.baseMin}..${baseEl.baseMax} ${profileMin}..${profileMax} ${baseEl.baseType} ${profileType} ${baseEl.baseDesc} ${notes} `; tableBody.appendChild(tr); }); if (baseElements.length === 0) { tableBody.innerHTML = "ERROR: No base elements found for the selected resource."; } } // --- Event Handlers --- // Update State on Resource Change baseResourceSelect.addEventListener('change', function() { appState.baseResource = baseResourceSelect.value; loadBaseElements(appState.baseResource); // Note: For a real tool, you might clear constraints here, but we keep them for the mock. }); // Update Dashboard Button updateBtn.addEventListener("click", function() { appState.profileName = profileNameInput.value || "Untitled Profile"; appState.profileDate = profileDateInput.value || new Date().toISOString().split('T')[0]; appState.baseResource = baseResourceSelect.value; saveState(); renderDashboardTab(); showTab(1); // Switch to Dashboard }); // Add Constraint addConstraintBtn.addEventListener("click", function() { var elementName = elementSelect.value; var min = minInput.value.trim(); var max = maxInput.value.trim(); var type = typeInput.value.trim(); var notes = notesInput.value.trim(); if (!elementName || !min || !max) { alert("Please select an Element Name and define Min/Max Cardinality."); return; } if (appState.customConstraints.some(function(c) { return c.elementName === elementName; })) { alert("A constraint for this element already exists. Remove the old one first."); return; } var newId = appState.customConstraints.length > 0 ? appState.customConstraints[appState.customConstraints.length - 1].id + 1 : 1; var newConstraint = { id: newId, elementName: elementName, min: min, max: max, type: type, notes: notes }; appState.customConstraints.push(newConstraint); saveState(); renderConfigTab(); // Clear form (except selects) minInput.value = ""; maxInput.value = ""; typeInput.value = ""; notesInput.value = ""; elementSelect.value = ""; }); // Remove Constraint (Event Delegation) toolContainer.addEventListener("click", function(e) { if (e.target.classList.contains("fpc-remove-btn")) { var id = parseInt(e.target.dataset.id); appState.customConstraints = appState.customConstraints.filter(function(c) { return c.id !== id; }); saveState(); renderConfigTab(); } }); // --- PDF Download --- pdfBtn.addEventListener("click", function() { var jsPDF = window.jspdf.jsPDF; var titleSlug = profileNameInput.value.replace(/[^a-zA-Z0-9\s]/g, '').replace(/\s/g, '_').substring(0, 30) || 'FHIR_Profile'; var fileName = `${titleSlug}.pdf`; // Temporarily adjust minimum table width for PDF quality var table = document.getElementById('fpc-profile-table'); var originalMinWidth = table.style.minWidth; table.style.minWidth = '1200px'; html2canvas(exportArea, { scale: 2, useCORS: true, backgroundColor: '#ffffff' }).then(function(canvas) { // Restore styles table.style.minWidth = originalMinWidth; var imgData = canvas.toDataURL('image/png'); var doc = new jsPDF({ orientation: 'l', // Landscape is better for wide tables unit: 'pt', format: 'a3' // Use A3 for maximum table fit }); var pdfWidth = doc.internal.pageSize.getWidth(); var pdfHeight = doc.internal.pageSize.getHeight(); var imgProps = doc.getImageProperties(imgData); var imgWidth = imgProps.width; var imgHeight = imgProps.height; var margin = 40; var usableWidth = pdfWidth - (2 * margin); var ratio = usableWidth / imgWidth; var scaledHeight = imgHeight * ratio; // Handle multi-page if content exceeds page height if (scaledHeight > pdfHeight - (2 * margin)) { var pageHeight = pdfHeight - (2 * margin); var heightLeft = scaledHeight; var position = 0; while (heightLeft > 0) { doc.addImage(imgData, 'PNG', margin, position + margin, usableWidth, scaledHeight); heightLeft -= pageHeight; position -= pageHeight; if (heightLeft > 0) { doc.addPage(); } } } else { // Single page doc.addImage(imgData, 'PNG', margin, margin, usableWidth, scaledHeight); } doc.save(fileName); }).catch(function(err) { // Restore styles even if PDF fails table.style.minWidth = originalMinWidth; console.error("FPC PDF Error:", err); // alert("An error occurred while generating the PDF."); // Per spec }); }); // --- Local Storage --- function saveState() { try { localStorage.setItem("fpcAppState", JSON.stringify(appState)); } catch (e) { console.warn("FPC: Could not save state."); } } function loadState() { try { var storedState = localStorage.getItem("fpcAppState"); if (storedState) appState = JSON.parse(storedState); } catch (e) { console.warn("FPC: Could not load state."); } } // --- Initial Load --- loadState(); renderConfigTab(); renderDashboardTab(); showTab(0); });
Scroll to Top