Files
TheRock/build_tools/manifest_diff_report_template.html
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

809 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Commit Diff Report</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/* Status colors (consolidated) */
:root {
--status-added-bg: #d4edda;
--status-added-border: #28a745;
--status-added-text: #155724;
--status-removed-bg: #f8d7da;
--status-removed-border: #dc3545;
--status-removed-text: #721c24;
--status-reverted-bg: #fff3cd;
--status-reverted-border: #ffc107;
--status-reverted-text: #856404;
--status-unchanged-text: #6c757d;
}
/* === Tables (base) === */
.report-table, .commit-history-table {
width: 100%;
border-collapse: collapse;
border: 1px solid #ccc;
font-family: Verdana, sans-serif;
font-size: 14px;
table-layout: fixed;
}
.commit-history-table {
margin-top: 8px;
}
.report-table th {
padding: 8px;
border: 1px solid #ccc;
text-align: left;
background-color: #f1f1f1;
}
.commit-history-table th {
padding: 8px;
border: 1px solid #ccc;
text-align: left;
background-color: #f8f9fa;
}
/* Column widths for report table */
.report-table th:first-child,
.report-table td:first-child {
width: 180px;
}
.report-table td, .commit-history-table td {
padding: 8px;
border: 1px solid #ccc;
}
.report-table td {
vertical-align: top;
}
.commit-history-table .date-col, .commit-history-table .author-col {
font-size: 12px;
}
.commit-history-table .date-col {
color: #666;
}
.commit-history-table .author-col {
color: #555;
}
.commit-history-table .project-col {
font-weight: bold;
}
.commit-history-table .message-col {
font-size: 13px;
}
/* === Commit styling === */
.commit-badge {
display: inline-block;
background-color: #1976D2;
color: #fff;
padding: 2px 8px;
font-family: Verdana, sans-serif;
font-size: 12px;
border-radius: 2px;
}
.commit-badge-link {
text-decoration: none;
}
.commit-item {
margin-bottom: 8px;
border-left: 3px solid #1976D2;
padding-left: 8px;
}
.commit-meta {
color: #666;
font-size: 11px;
margin-top: 2px;
}
.commit-list {
max-height: 160px;
overflow-y: auto;
padding: 4px;
border: 1px solid #ccc;
font-family: Verdana, sans-serif;
font-size: 13px;
line-height: 1.4;
background-color: #f9f9f9;
}
.no-commits {
text-align: center;
padding: 8px;
color: #888;
font-style: italic;
}
.summary-category.removed {
background-color: transparent;
text-align: left;
}
/* === Commit list variants (by status) === */
.commit-list.reverted-bg {
background-color: var(--status-reverted-bg);
}
.commit-list.newly-added-bg {
background-color: var(--status-added-bg);
}
.commit-list.removed-bg {
background-color: var(--status-removed-bg);
}
.removed-message {
color: var(--status-removed-text);
font-weight: bold;
text-align: center;
padding: 8px;
}
/* === Superrepo / banners === */
.superrepo-status-banner {
padding: 12px 16px;
margin-bottom: 12px;
border-radius: 4px;
font-size: 14px;
}
.superrepo-status-banner.added {
background-color: var(--status-added-bg);
border-left: 4px solid var(--status-added-border);
color: var(--status-added-text);
}
.superrepo-status-banner.removed {
background-color: var(--status-removed-bg);
border-left: 4px solid var(--status-removed-border);
color: var(--status-removed-text);
}
.superrepo-status-banner.reverted {
background-color: var(--status-reverted-bg);
border-left: 4px solid var(--status-reverted-border);
color: var(--status-reverted-text);
}
.replaced-submodules {
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid rgba(0,0,0,0.1);
font-size: 13px;
}
.replaced-submodules code {
background-color: rgba(0,0,0,0.05);
padding: 2px 4px;
border-radius: 3px;
font-size: 12px;
}
/* Removed submodules banner in Other Components section */
.removed-submodules-banner {
background-color: var(--status-removed-bg);
border-left: 4px solid var(--status-removed-border);
color: var(--status-removed-text);
padding: 12px 16px;
margin-bottom: 12px;
border-radius: 4px;
font-size: 14px;
}
.removed-submodules-banner code {
background-color: rgba(0,0,0,0.05);
padding: 2px 4px;
border-radius: 3px;
font-size: 12px;
word-break: break-word;
}
.reverted-header {
background-color: var(--status-reverted-bg);
padding: 8px;
border-radius: 4px;
margin-bottom: 8px;
border-left: 3px solid var(--status-reverted-border);
}
.newly-added-header {
color: var(--status-added-text);
font-weight: bold;
padding: 8px;
margin-bottom: 8px;
border-bottom: 1px solid rgba(0,0,0,0.1);
}
/* Generator: superrepo REMOVED / No components messages */
.removed, .unchanged {
color: var(--status-unchanged-text);
padding: 8px 0;
}
/* === Summary === */
.summary-container {
background-color: #ffffff;
padding: 16px;
margin-bottom: 3em;
box-shadow: 0 2px 5px rgba(0,0,0,0.16), 0 2px 10px rgba(0,0,0,0.12);
}
.summary-title {
text-align: center;
color: #1976D2;
font-size: 2.2em;
font-weight: bold;
margin-bottom: 16px;
}
.summary-note {
text-align: center;
color: #666;
font-size: 0.9em;
margin-bottom: 20px;
padding: 8px;
background-color: #f8f9fa;
border-radius: 4px;
border-left: 4px solid #17a2b8;
}
/* Ensure individual superrepo containers don't inherit note styling */
#rocm-libraries-superrepo-container,
#rocm-systems-superrepo-container {
background-color: #ffffff !important;
border-left: none !important;
font-size: inherit !important;
}
.summary-section {
margin-bottom: 8px;
padding: 16px;
}
.summary-section h2 {
color: #1976D2;
margin-top: 0;
margin-bottom: 16px;
font-size: 1.5em;
}
.summary-category {
margin-bottom: 16px;
}
.summary-category h3 {
margin-bottom: 8px;
}
.summary-category.added h3 {
color: var(--status-added-border);
}
.summary-category.removed h3 {
color: var(--status-removed-border);
}
.summary-category.changed h3 {
color: var(--status-reverted-border);
}
.summary-category.unchanged h3 {
color: var(--status-unchanged-text);
}
.summary-list {
margin: 0;
padding-left: 20px;
}
.summary-list li {
color: var(--status-unchanged-text);
margin-bottom: 4px;
}
/* === Column utilities === */
.col-date { width: 80px; }
.col-sha { width: 60px; }
.col-author { width: 120px; }
.col-projects { width: 150px; }
/* === Filter controls === */
.filter-container {
background-color: #fff3cd;
border: 1px solid #ffeaa7;
border-left: 4px solid #f39c12;
border-radius: 4px;
padding: 16px;
margin-bottom: 2em;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.filter-title {
color: #856404;
font-weight: bold;
font-size: 1.1em;
margin-bottom: 12px;
display: flex;
align-items: center;
}
.filter-controls {
display: flex;
flex-wrap: wrap;
gap: 16px;
align-items: center;
}
.filter-group {
display: flex;
align-items: center;
gap: 8px;
}
.filter-checkbox {
width: 18px;
height: 18px;
cursor: pointer;
}
.filter-label {
color: #856404;
font-weight: 500;
cursor: pointer;
user-select: none;
}
.filter-divider {
height: 20px;
width: 1px;
background-color: #ddd;
margin: 0 8px;
}
/* === Hide/show utilities === */
.hidden {
display: none !important;
}
/* === Filter selective / dropdown === */
.selective-filter {
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid #e0e0e0;
}
.selective-filter-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.filter-dropdown {
min-width: 200px;
padding: 6px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
background-color: white;
cursor: pointer;
}
.filter-dropdown:focus {
outline: none;
border-color: #f39c12;
box-shadow: 0 0 0 2px rgba(243, 156, 18, 0.2);
}
.add-button {
padding: 6px 12px;
background-color: #f39c12;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
}
.add-button:hover {
background-color: #d68910;
}
.add-button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.selected-items {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 8px;
}
.selected-item {
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 16px;
padding: 4px 12px;
font-size: 13px;
display: flex;
align-items: center;
gap: 6px;
}
.selected-item .remove-btn {
background: #dc3545;
color: white;
border: none;
border-radius: 50%;
width: 16px;
height: 16px;
font-size: 12px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
.selected-item .remove-btn:hover {
background: #c82333;
}
.clear-all {
background: none;
border: none;
color: #dc3545;
text-decoration: underline;
cursor: pointer;
font-size: 13px;
}
.clear-all:hover {
color: #c82333;
}
</style>
</head>
<body style="margin:0; padding:0; background-color:#f1f1f1; font-family:'Segoe UI', sans-serif;">
<!-- Header -->
<div style="padding:32px 16px; margin-bottom:16px; text-align:center; background-color:#1976D2; color:#ffffff; font-size:2em; font-weight:600; letter-spacing:1px;">
ROCm CI Infra Report
</div>
<!-- TheRock Commit Range -->
<div style="padding:16px; margin-bottom:16px; text-align:center; background-color:#f8f9fa; color:#495057; font-size:1.4em; font-weight:500; border:1px solid #dee2e6; border-radius:6px; box-shadow:0 1px 3px rgba(0,0,0,0.08);">
TheRock Commit Range: <code style="background-color:#e9ecef; color:#495057; padding:4px 8px; border-radius:4px; font-family:monospace; border:1px solid #ced4da;"><span id="therock-start-commit">START_COMMIT</span></code> &rarr; <code style="background-color:#e9ecef; color:#495057; padding:4px 8px; border-radius:4px; font-family:monospace; border:1px solid #ced4da;"><span id="therock-end-commit">END_COMMIT</span></code>
</div>
<!-- Container -->
<div style="margin: 2em auto; max-width: 1200px;">
<!-- Report Information -->
<div style="background-color:#e8f5e8; padding:12px; margin-bottom:2em; box-shadow:0 2px 5px rgba(0,0,0,0.16); border-radius:4px; border-left:4px solid #28a745;">
<div style="color:#155724; font-weight:bold; margin-bottom:8px;">&#128203; Report Information</div>
<div style="color:#155724; font-size:0.9em; margin-bottom:6px;">All commits in this report are ordered from <strong>newest to oldest</strong>.</div>
<div style="color:#155724; font-size:0.9em;"><strong>Note on Unassigned Commits:</strong> Some commits may appear as "unassigned" - these are typically root-level changes that don't belong to a specific project component. These may also be commits from CK that are being handled through the merge commits.</div>
</div>
<!-- Filter Controls -->
<div class="filter-container">
<div class="filter-title">
&#128269; Report Filters &amp; Display Options
</div>
<div class="filter-controls">
<div class="filter-group">
<input type="checkbox" id="toggle-summaries" class="filter-checkbox" checked>
<label for="toggle-summaries" class="filter-label">Show Summary Sections</label>
</div>
<div class="filter-divider"></div>
<div class="filter-group">
<input type="checkbox" id="toggle-commit-history" class="filter-checkbox" checked>
<label for="toggle-commit-history" class="filter-label">Show Commit History Tables</label>
</div>
<div class="filter-divider"></div>
<div class="filter-group">
<input type="checkbox" id="toggle-component-tables" class="filter-checkbox" checked>
<label for="toggle-component-tables" class="filter-label">Show Component Tables</label>
</div>
<div class="filter-divider"></div>
<div class="filter-group">
<input type="checkbox" id="toggle-unchanged" class="filter-checkbox">
<label for="toggle-unchanged" class="filter-label">Hide Unchanged Components</label>
</div>
</div>
<!-- Selective Filtering -->
<div class="selective-filter">
<div class="selective-filter-header">
<input type="checkbox" id="enable-selective-filter" class="filter-checkbox">
<label for="enable-selective-filter" class="filter-label">Filter by Selected Components/Submodules Only</label>
<div class="filter-divider"></div>
<select id="component-dropdown" class="filter-dropdown" disabled>
<option value="">Select a component or submodule...</option>
</select>
<button id="add-component" class="add-button" disabled>Add</button>
<button id="clear-all" class="clear-all" style="display:none;">Clear All</button>
</div>
<div id="selected-items" class="selected-items"></div>
</div>
</div>
<!-- Submodule Changes Summary -->
<div id="submodule-summary" class="summary-container">
<div class="summary-title">Submodule Changes Summary</div>
<div class="summary-note">
<strong>Note:</strong> This summary shows only the direct submodules found in TheRock repository (start and end commits).
</div>
<div id="submodule-content"></div>
</div>
<!-- Superrepo Components Summary -->
<div id="superrepo-summary" class="summary-container">
<div class="summary-title">Superrepo Components Summary</div>
<div class="summary-note">
<strong>Note:</strong> This summary shows component-level changes within ROCm-Libraries and ROCm-Systems superrepos.
Each component represents a project or library within the superrepo structure.
</div>
<div id="superrepo-content"></div>
</div>
<!-- Commit Diff Job Container for ROCm-Libraries Superrepo -->
<div id="rocm-libraries-superrepo-container" style="background-color:#ffffff; padding:16px; margin-bottom:3em; box-shadow:0 2px 5px rgba(0,0,0,0.16), 0 2px 10px rgba(0,0,0,0.12);">
<div style="text-align:center; color:#1976D2; font-size:2.2em; font-weight:bold;">ROCm-Libraries Superrepo Component Commit Diff</div>
<div style="text-align:center; color:#3a3a3a;">Start Commit: <span id="commit-diff-start-rocm-libraries-superrepo"></span> &nbsp; End Commit: <span id="commit-diff-end-rocm-libraries-superrepo"></span></div>
<div id="commit-diff-job-content-rocm-libraries-superrepo" style="margin-top:8px;">
</div>
</div>
<!-- Commit Diff Job Container for ROCm-Systems Superrepo -->
<div id="rocm-systems-superrepo-container" style="background-color:#ffffff; padding:16px; margin-bottom:3em; box-shadow:0 2px 5px rgba(0,0,0,0.16), 0 2px 10px rgba(0,0,0,0.12);">
<div style="text-align:center; color:#1976D2; font-size:2.2em; font-weight:bold;">ROCm-Systems Superrepo Component Commit Diff</div>
<div style="text-align:center; color:#3a3a3a;">Start Commit: <span id="commit-diff-start-rocm-systems-superrepo"></span> &nbsp; End Commit: <span id="commit-diff-end-rocm-systems-superrepo"></span></div>
<div id="commit-diff-job-content-rocm-systems-superrepo" style="margin-top:8px;">
</div>
</div>
<!-- Commit Diff Job Container for Other Components -->
<div id="non-superrepo-container" style="background-color:#ffffff; padding:16px; margin-bottom:3em; box-shadow:0 2px 5px rgba(0,0,0,0.16), 0 2px 10px rgba(0,0,0,0.12);">
<div style="text-align:center; color:#1976D2; font-size:2.2em; font-weight:bold;">Other Component Commit Diff</div>
<div style="text-align:center; color:#3a3a3a;">Start Commit: <span id="commit-diff-start-non-superrepo"></span> &nbsp; End Commit: <span id="commit-diff-end-non-superrepo"></span></div>
<div id="commit-diff-job-content-non-superrepo" style="margin-top:8px;">
</div>
</div>
</div>
<script>
const SELECTOR_COMMIT_HISTORY_TABLES = '.commit-history-table';
const SELECTOR_COMMIT_HISTORY_SECTIONS = '.section-title';
const SELECTOR_REPORT_TABLE = '.report-table';
const SELECTOR_COMPONENT_ROW = '.report-table tr.component-row';
const SELECTOR_SUMMARY_CONTAINERS = '#submodule-summary, #superrepo-summary';
const SELECTOR_UNCHANGED_ROW = '.unchanged-row';
function validateTemplate() {
const requiredIds = [
'toggle-summaries', 'toggle-commit-history', 'toggle-component-tables', 'toggle-unchanged',
'enable-selective-filter', 'component-dropdown', 'add-component', 'clear-all', 'selected-items'
];
for (const id of requiredIds) {
const el = document.getElementById(id);
if (!el) {
throw new Error('Expected element #' + id + ' not found in report template');
}
}
}
function setupSectionToggles() {
const summariesToggle = document.getElementById('toggle-summaries');
const commitHistoryToggle = document.getElementById('toggle-commit-history');
const componentTablesToggle = document.getElementById('toggle-component-tables');
const unchangedToggle = document.getElementById('toggle-unchanged');
if (!summariesToggle) {
throw new Error('Expected element #toggle-summaries not found in report template');
}
if (!commitHistoryToggle) {
throw new Error('Expected element #toggle-commit-history not found in report template');
}
if (!componentTablesToggle) {
throw new Error('Expected element #toggle-component-tables not found in report template');
}
if (!unchangedToggle) {
throw new Error('Expected element #toggle-unchanged not found in report template');
}
summariesToggle.addEventListener('change', function() {
document.querySelectorAll(SELECTOR_SUMMARY_CONTAINERS).forEach(container => {
if (this.checked) {
container.classList.remove('hidden');
} else {
container.classList.add('hidden');
}
});
});
commitHistoryToggle.addEventListener('change', function() {
document.querySelectorAll(SELECTOR_COMMIT_HISTORY_TABLES).forEach(table => {
if (this.checked) {
table.classList.remove('hidden');
} else {
table.classList.add('hidden');
}
});
document.querySelectorAll(SELECTOR_COMMIT_HISTORY_SECTIONS).forEach(section => {
if (this.checked) {
section.classList.remove('hidden');
} else {
section.classList.add('hidden');
}
});
});
componentTablesToggle.addEventListener('change', function() {
document.querySelectorAll(SELECTOR_REPORT_TABLE).forEach(table => {
if (this.checked) {
table.classList.remove('hidden');
} else {
table.classList.add('hidden');
}
});
});
unchangedToggle.addEventListener('change', function() {
document.querySelectorAll(SELECTOR_UNCHANGED_ROW).forEach(row => {
if (this.checked) {
row.classList.add('hidden');
} else {
row.classList.remove('hidden');
}
});
});
}
function setupSelectiveFiltering() {
const selectiveFilterCheckbox = document.getElementById('enable-selective-filter');
const componentDropdown = document.getElementById('component-dropdown');
const addButton = document.getElementById('add-component');
const clearAllButton = document.getElementById('clear-all');
const selectedItemsContainer = document.getElementById('selected-items');
if (!selectiveFilterCheckbox) {
throw new Error('Expected element #enable-selective-filter not found in report template');
}
if (!componentDropdown) {
throw new Error('Expected element #component-dropdown not found in report template');
}
if (!addButton) {
throw new Error('Expected element #add-component not found in report template');
}
if (!clearAllButton) {
throw new Error('Expected element #clear-all not found in report template');
}
if (!selectedItemsContainer) {
throw new Error('Expected element #selected-items not found in report template');
}
const selectedComponents = new Set();
function getAllComponentRows() {
return document.querySelectorAll(SELECTOR_COMPONENT_ROW);
}
function showAllComponentRows() {
getAllComponentRows().forEach(row => {
row.classList.remove('hidden');
});
}
function populateDropdown() {
const components = new Set();
getAllComponentRows().forEach(row => {
const name = row.dataset.component;
if (name) {
components.add(name);
}
});
componentDropdown.innerHTML = '<option value="">Select a component or submodule...</option>';
Array.from(components).sort().forEach(component => {
const option = document.createElement('option');
option.value = component;
option.textContent = component;
componentDropdown.appendChild(option);
});
}
function applySelectiveFilter() {
if (!selectiveFilterCheckbox.checked || selectedComponents.size === 0) {
showAllComponentRows();
return;
}
getAllComponentRows().forEach(row => {
const name = row.dataset.component;
if (selectedComponents.has(name)) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
}
});
}
function renderSelectedItems() {
selectedItemsContainer.innerHTML = '';
selectedComponents.forEach(component => {
const item = document.createElement('div');
item.className = 'selected-item';
item.innerHTML = '<span>' + component + '</span>' +
'<button class="remove-btn" data-component="' + component.replace(/"/g, '&quot;') + '">×</button>';
selectedItemsContainer.appendChild(item);
});
clearAllButton.style.display = selectedComponents.size > 0 ? 'inline-block' : 'none';
selectedItemsContainer.querySelectorAll('.remove-btn').forEach(btn => {
btn.addEventListener('click', function() {
const component = this.dataset.component;
selectedComponents.delete(component);
renderSelectedItems();
applySelectiveFilter();
});
});
}
selectiveFilterCheckbox.addEventListener('change', function() {
const isEnabled = this.checked;
componentDropdown.disabled = !isEnabled;
addButton.disabled = !isEnabled;
if (isEnabled) {
populateDropdown();
applySelectiveFilter();
} else {
showAllComponentRows();
}
});
addButton.addEventListener('click', function() {
const selectedValue = componentDropdown.value;
if (selectedValue && !selectedComponents.has(selectedValue)) {
selectedComponents.add(selectedValue);
renderSelectedItems();
applySelectiveFilter();
componentDropdown.value = '';
}
});
clearAllButton.addEventListener('click', function() {
selectedComponents.clear();
renderSelectedItems();
applySelectiveFilter();
});
componentDropdown.addEventListener('keypress', function(e) {
if (e.key === 'Enter' && this.value) {
addButton.click();
}
});
}
document.addEventListener('DOMContentLoaded', function() {
validateTemplate();
setupSectionToggles();
setupSelectiveFiltering();
});
</script>
</body>
</html>