diff --git a/docs/changelog/assets/css/app.css b/docs/changelog/assets/css/app.css
index 31de425f3..f90987681 100644
--- a/docs/changelog/assets/css/app.css
+++ b/docs/changelog/assets/css/app.css
@@ -63,23 +63,28 @@ body {
top: 0;
background-color: var(--color-webex-blue);
color: white;
- padding: 1.25rem; /* 20px */
+ padding: 1.25rem;
+ /* 20px */
margin: 0;
- text-align: left; /* Align the title text to the left */
+ text-align: left;
+ /* Align the title text to the left */
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
font-size: 1.5rem;
- z-index: 1000; /* Ensure the header is above other content */
+ z-index: 1000;
+ /* Ensure the header is above other content */
}
#body {
flex: 1;
- padding: 1.25rem; /* 20px */
+ padding: 1.25rem;
+ /* 20px */
}
#footer {
background-color: var(--color-background);
text-align: center;
- padding: 0.625rem; /* 10px */
+ padding: 0.625rem;
+ /* 10px */
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.2);
}
@@ -96,12 +101,14 @@ body {
/* Rest of the CSS for form and results remains the same */
form#search-form {
- padding: 0.625rem; /* 10px */
+ padding: 0.625rem;
+ /* 10px */
}
label {
display: block;
- margin-bottom: 0.5rem; /* 8px */
+ margin-bottom: 0.5rem;
+ /* 8px */
color: #333;
}
@@ -118,11 +125,14 @@ select {
button {
background-color: var(--color-webex-blue);
color: white;
- padding: 0.625rem 1.25rem; /* 10px 20px */
+ padding: 0.625rem 1.25rem;
+ /* 10px 20px */
border: none;
- border-radius: 0.25rem; /* 4px */
+ border-radius: 0.25rem;
+ /* 4px */
cursor: pointer;
- font-size: 1rem; /* 16px */
+ font-size: 1rem;
+ /* 16px */
transition: background-color 0.3s;
}
@@ -143,7 +153,8 @@ td {
th,
td {
- padding: 0.625rem; /* 10px */
+ padding: 0.625rem;
+ /* 10px */
text-align: left;
}
@@ -153,79 +164,103 @@ th {
.search-container {
background: white;
- border-radius: 0.5rem; /* 8px */
+ border-radius: 0.5rem;
+ /* 8px */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin: auto;
width: 100%;
- padding: 1.25rem; /* 20px */
- box-sizing: border-box; /* Include padding in the width calculation */
+ padding: 1.25rem;
+ /* 20px */
+ box-sizing: border-box;
+ /* Include padding in the width calculation */
}
.form-row {
display: flex;
flex-wrap: wrap;
- margin-bottom: 1.25rem; /* 20px */
+ margin-bottom: 1.25rem;
+ /* 20px */
}
.form-group {
- flex: 1 1 25%; /* Each form group will take up half the width of the form-row */
- padding: 0 0.625rem; /* 10px */
+ flex: 1 1 25%;
+ /* Each form group will take up half the width of the form-row */
+ padding: 0 0.625rem;
+ /* 10px */
box-sizing: border-box;
}
.full-width {
- margin: 0 0.625rem; /* 10px */
+ margin: 0 0.625rem;
+ /* 10px */
}
.results-container {
width: 100%;
background: white;
- padding: 1.25rem; /* 20px */
- border-radius: 0.5rem; /* 8px */
+ padding: 1.25rem;
+ /* 20px */
+ border-radius: 0.5rem;
+ /* 8px */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin: auto;
- margin-top: 1.25rem; /* 20px */
+ margin-top: 1.25rem;
+ /* 20px */
}
/* Responsive styles */
@media (max-width: 48rem) {
+
/* 768px */
.form-group {
- flex: 1 1 100%; /* Each form group will take up the full width on smaller screens */
- padding: 0 0.625rem; /* 10px */
+ flex: 1 1 100%;
+ /* Each form group will take up the full width on smaller screens */
+ padding: 0 0.625rem;
+ /* 10px */
}
}
.changelog-item {
- padding-bottom: 1.25rem; /* 20px */
- margin-bottom: 1.25rem; /* 20px */
- border-bottom: 0.1875rem solid #e4e5e6; /* 3px */
+ padding-bottom: 1.25rem;
+ /* 20px */
+ margin-bottom: 1.25rem;
+ /* 20px */
+ border-bottom: 0.1875rem solid #e4e5e6;
+ /* 3px */
}
.changelog-item h2,
.changelog-item h3 {
color: #333;
- margin-bottom: 0.625rem; /* 10px */
+ margin-bottom: 0.625rem;
+ /* 10px */
}
.changelog-item .commits {
- margin-top: 1.25rem; /* 20px */
- margin-bottom: 1.25rem; /* 20px */
+ margin-top: 1.25rem;
+ /* 20px */
+ margin-bottom: 1.25rem;
+ /* 20px */
}
.changelog-item .commits ul {
- margin-top: 0.625rem; /* 10px */
+ margin-top: 0.625rem;
+ /* 10px */
list-style-type: none;
padding: 0;
- max-height: 12.5rem; /* 200px */
+ max-height: 12.5rem;
+ /* 200px */
overflow: scroll;
}
.changelog-item .commits ul li {
background-color: #eee;
- margin-bottom: 0.3125rem; /* 5px */
- padding: 0.625rem; /* 10px */
- border-radius: 0.1875rem; /* 3px */
+ margin-bottom: 0.3125rem;
+ /* 5px */
+ padding: 0.625rem;
+ /* 10px */
+ border-radius: 0.1875rem;
+ /* 3px */
word-wrap: break-word;
}
@@ -261,7 +296,8 @@ th {
.changelog-item th,
.changelog-item td {
- padding: 0.625rem; /* 10px */
+ padding: 0.625rem;
+ /* 10px */
text-align: left;
}
@@ -280,19 +316,23 @@ th {
.copy-button {
display: inline;
position: absolute;
- margin-left: 0.3125rem; /* 5px */
+ margin-left: 0.3125rem;
+ /* 5px */
cursor: pointer;
right: 0;
}
.copy-button img {
- width: 1.25rem; /* 20px */
+ width: 1.25rem;
+ /* 20px */
height: auto;
- margin-right: 0.3125rem; /* 5px */
+ margin-right: 0.3125rem;
+ /* 5px */
}
footer {
- margin: 1.25rem 0; /* 20px 0px */
+ margin: 1.25rem 0;
+ /* 20px 0px */
}
footer .copyright {
@@ -302,10 +342,13 @@ footer .copyright {
.alert-info {
background-color: #f0f9ff;
- border-left: 0.375rem solid var(--color-webex-blue); /* 6px */
+ border-left: 0.375rem solid var(--color-webex-blue);
+ /* 6px */
color: #333;
- padding: 0.625rem; /* 10px */
- margin-bottom: 1.25rem; /* 20px */
+ padding: 0.625rem;
+ /* 10px */
+ margin-bottom: 1.25rem;
+ /* 20px */
}
.alert-info p.note {
@@ -326,8 +369,10 @@ footer .copyright {
/* Mode Toggle Buttons */
.mode-toggle {
display: flex;
- gap: 0.625rem; /* 10px */
- margin-bottom: 1.25rem; /* 20px */
+ gap: 0.625rem;
+ /* 10px */
+ margin-bottom: 1.25rem;
+ /* 20px */
}
.mode-toggle button {
@@ -338,7 +383,8 @@ footer .copyright {
color: var(--color-webex-blue);
cursor: pointer;
transition: all 0.3s;
- border-radius: 0.25rem; /* 4px */
+ border-radius: 0.25rem;
+ /* 4px */
font-weight: 500;
}
@@ -356,9 +402,97 @@ footer .copyright {
display: none !important;
}
+/* Version Comparison: make form box full width (equal to Note box above) and expand height */
+#changelog-form-row.comparison-view-active #comparison-form-column {
+ width: 100% !important;
+ max-width: 100% !important;
+ flex: 0 0 100%;
+}
+
+#changelog-form-row.comparison-view-active #comparison-helper-column {
+ display: none;
+}
+
+#changelog-form-row.comparison-view-active #comparison-form-column .search-container {
+ min-height: 20rem;
+ padding: 1.75rem 1.5rem;
+ overflow: visible;
+}
+
+#changelog-form-row.comparison-view-active #comparison-form-column {
+ overflow: visible;
+}
+
+/* Let the package dropdown list show all options (avoid clipping) */
+#comparison-form #comparison-package-row {
+ overflow: visible;
+}
+
+#comparison-form select#comparison-package-select {
+ max-height: none;
+}
+
+#comparison-form-column select {
+ position: relative;
+ z-index: 10;
+}
+
+#comparison-form-column select:focus {
+ z-index: 11;
+}
+
+/* Comparison form: package first, version row with clear buttons */
+#comparison-form .comparison-package-full-width {
+ flex: 1 1 100%;
+}
+
+#comparison-form .required-asterisk {
+ color: var(--color-danger);
+}
+
+#comparison-form .select-with-clear {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+#comparison-form .select-with-clear select.full-width {
+ flex: 1;
+ margin: 0;
+}
+
+.btn-clear-circle {
+ flex-shrink: 0;
+ width: 2.25rem;
+ height: 2.25rem;
+ padding: 0;
+ border-radius: 50%;
+ border: 1px solid #ccc;
+ background-color: #f5f5f5;
+ color: var(--color-danger);
+ font-size: 1.5rem;
+ line-height: 1;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ transition: background-color 0.2s, color 0.2s;
+}
+
+.btn-clear-circle:hover:not(:disabled) {
+ background-color: #ffe0e0;
+ color: var(--color-danger-hover);
+}
+
+.btn-clear-circle:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
/* Comparison Form */
#comparison-form {
- margin-top: 1.25rem; /* 20px */
+ margin-top: 1.25rem;
+ /* 20px */
}
/* Comparison Results Table */
@@ -376,7 +510,8 @@ footer .copyright {
width: 100%;
border-collapse: collapse;
margin-top: 0;
- font-size: 0.875rem; /* 14px */
+ font-size: 0.875rem;
+ /* 14px */
}
.comparison-table th,
@@ -405,36 +540,48 @@ footer .copyright {
/* Color Coding for Changes */
.comparison-table tr.version-changed {
- background-color: #fff3cd; /* Yellow - version changed */
- border-left: 0.25rem solid #ffc107; /* 4px */
+ background-color: #fff3cd;
+ /* Yellow - version changed */
+ border-left: 0.25rem solid #ffc107;
+ /* 4px */
}
.comparison-table tr.only-in-a {
- background-color: #f8d7da; /* Red - removed in B */
- border-left: 0.25rem solid #dc3545; /* 4px */
+ background-color: #f8d7da;
+ /* Red - removed in B */
+ border-left: 0.25rem solid #dc3545;
+ /* 4px */
}
.comparison-table tr.only-in-b {
- background-color: #d4edda; /* Green - added in B */
- border-left: 0.25rem solid #28a745; /* 4px */
+ background-color: #d4edda;
+ /* Green - added in B */
+ border-left: 0.25rem solid #28a745;
+ /* 4px */
}
.comparison-table tr.unchanged {
- background-color: #ffffff; /* White - no change */
+ background-color: #ffffff;
+ /* White - no change */
}
/* Comparison Summary */
.comparison-summary {
background: linear-gradient(135deg, #e7f3ff 0%, #f0f9ff 100%);
- padding: 1.5625rem; /* 25px */
- border-radius: 0.5rem; /* 8px */
- margin-bottom: 1.25rem; /* 20px */
- border-left: 0.3125rem solid var(--color-webex-blue); /* 5px */
+ padding: 1.5625rem;
+ /* 25px */
+ border-radius: 0.5rem;
+ /* 8px */
+ margin-bottom: 1.25rem;
+ /* 20px */
+ border-left: 0.3125rem solid var(--color-webex-blue);
+ /* 5px */
}
.comparison-summary h3 {
margin-top: 0;
- margin-bottom: 0.9375rem; /* 15px */
+ margin-bottom: 0.9375rem;
+ /* 15px */
color: var(--color-webex-blue);
font-size: 1.5em;
}
@@ -442,8 +589,10 @@ footer .copyright {
.summary-stats {
display: flex;
flex-wrap: wrap;
- gap: 0.9375rem; /* 15px */
- margin-top: 0.9375rem; /* 15px */
+ gap: 0.9375rem;
+ /* 15px */
+ margin-top: 0.9375rem;
+ /* 15px */
}
.stat-item {
@@ -455,22 +604,26 @@ footer .copyright {
}
.stat-item.changed {
- border-left: 0.25rem solid #ffc107; /* 4px */
+ border-left: 0.25rem solid #ffc107;
+ /* 4px */
}
.stat-item.unchanged {
- border-left: 0.25rem solid #6c757d; /* 4px */
+ border-left: 0.25rem solid #6c757d;
+ /* 4px */
}
.stat-item.added {
- border-left: 0.25rem solid #28a745; /* 4px */
+ border-left: 0.25rem solid #28a745;
+ /* 4px */
}
.stat-item.removed {
- border-left: 0.25rem solid #dc3545; /* 4px */
+ border-left: 0.25rem solid #dc3545;
+ /* 4px */
}
.stat-item strong {
font-size: 1.2em;
color: #333;
-}
+}
\ No newline at end of file
diff --git a/docs/changelog/assets/js/app.js b/docs/changelog/assets/js/app.js
index 6368c66d1..98bcc8286 100644
--- a/docs/changelog/assets/js/app.js
+++ b/docs/changelog/assets/js/app.js
@@ -50,6 +50,9 @@ const compareButton = document.getElementById('compare-button');
const clearComparisonButton = document.getElementById('clear-comparison-button');
const copyComparisonLinkBtn = document.getElementById('copy-comparison-link');
const comparisonHelper = document.getElementById('comparison-helper');
+const clearVersionABtn = document.getElementById('clear-version-a-btn');
+const clearVersionBBtn = document.getElementById('clear-version-b-btn');
+const changelogFormRow = document.getElementById('changelog-form-row');
// DOM elements - Shared
const helperSection = document.getElementById('helper-section');
@@ -71,8 +74,8 @@ const uiVisibilityStates = {
hidden: ['comparisonForm', 'comparisonResults', 'comparisonHelper'],
},
comparison: {
- visible: ['comparisonForm', 'comparisonHelper'],
- hidden: ['searchForm', 'searchResults', 'helperSection', 'comparisonResults'],
+ visible: ['comparisonForm'],
+ hidden: ['searchForm', 'searchResults', 'helperSection', 'comparisonResults', 'comparisonHelper'],
},
};
@@ -95,6 +98,10 @@ function updateUIVisibility(viewState) {
const el = uiViewElements[key];
if (el) el.classList.remove('hide');
});
+ if (changelogFormRow) {
+ if (viewState === 'comparison') changelogFormRow.classList.add('comparison-view-active');
+ else changelogFormRow.classList.remove('comparison-view-active');
+ }
}
// Initialize UI to search view on load (single source of truth for visibility)
@@ -192,6 +199,43 @@ const populateFormFieldsFromURL = async () => {
}
};
+/**
+ * Return the latest version key from versionPaths (by semver).
+ */
+const getLatestVersionKey = () => {
+ const keys = Object.keys(versionPaths);
+ if (keys.length === 0) return null;
+ keys.sort((a, b) => {
+ const pa = a.split('.').map(Number);
+ const pb = b.split('.').map(Number);
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
+ const na = pa[i] || 0;
+ const nb = pb[i] || 0;
+ if (na !== nb) return nb - na; // descending: latest first
+ }
+ return 0;
+ });
+ return keys[0];
+};
+
+/**
+ * Fetch all version changelogs and return merged package list (union) so dropdown shows every package.
+ */
+const fetchMergedChangelogPackages = async () => {
+ const paths = Object.values(versionPaths);
+ if (paths.length === 0) return {};
+ const results = await Promise.all(paths.map((p) => fetch(p).then((r) => r.json()).catch(() => ({}))));
+ const merged = {};
+ results.forEach((changelog) => {
+ if (changelog && typeof changelog === 'object') {
+ Object.keys(changelog).forEach((pkg) => {
+ if (!merged[pkg]) merged[pkg] = changelog[pkg];
+ });
+ }
+ });
+ return merged;
+};
+
const populateVersions = async () => {
try {
const response = await fetch('logs/main.json');
@@ -779,10 +823,6 @@ const displayComparison = (versionA, versionB, comparisonData) => {
} else {
console.warn('Copy link button not found in DOM');
}
- if (comparisonHelper) {
- comparisonHelper.classList.remove('hide');
- }
-
// Scroll to results smoothly
setTimeout(() => {
comparisonResults.scrollIntoView({behavior: 'smooth', block: 'start'});
@@ -859,11 +899,9 @@ const handleComparisonURLParams = async () => {
* @param {string} versionA - Base version (optional)
* @param {string} versionB - Target version (optional)
*/
-const switchToComparisonMode = (versionA = null, versionB = null) => {
- // Update mode
+const switchToComparisonMode = async (versionA = null, versionB = null) => {
comparisonMode = true;
- // Update button states
if (comparisonViewBtn && singleViewBtn) {
comparisonViewBtn.classList.add('active', 'btn-primary');
comparisonViewBtn.classList.remove('btn-default');
@@ -871,21 +909,35 @@ const switchToComparisonMode = (versionA = null, versionB = null) => {
singleViewBtn.classList.add('btn-default');
}
- // Update form visibility (centralized view state)
updateUIVisibility('comparison');
- // Hide package-level comparison section in version comparison mode
if (packageLevelSection) packageLevelSection.classList.add('hide');
- // Populate version dropdowns
if (versionSelectDropdown && versionSelectDropdown.innerHTML) {
const options = versionSelectDropdown.innerHTML;
if (versionASelect) versionASelect.innerHTML = options;
if (versionBSelect) versionBSelect.innerHTML = options;
}
- // Set selected versions if provided
+ try {
+ const changelog = await fetchMergedChangelogPackages();
+ populateComparisonPackagesFromChangelog(changelog);
+ } catch (e) {
+ console.error('Error loading packages for comparison:', e);
+ populateComparisonPackagesFromChangelog({});
+ }
+
if (versionA && versionASelect) versionASelect.value = versionA;
if (versionB && versionBSelect) versionBSelect.value = versionB;
+
+ if (!versionA && !versionB) {
+ resetComparisonSelections();
+ if (compareButton) compareButton.disabled = true;
+ } else {
+ versionASelect.disabled = false;
+ versionBSelect.disabled = false;
+ if (clearVersionABtn) clearVersionABtn.disabled = false;
+ if (clearVersionBBtn) clearVersionBBtn.disabled = false;
+ }
};
/* ============================================
@@ -961,9 +1013,7 @@ const compareAndRenderPackageVersions = (packageName, versionASpecific, versionB
comparisonData.versionB
);
- // Show copy link button and helper
if (copyComparisonLinkBtn) copyComparisonLinkBtn.classList.remove('hide');
- if (comparisonHelper) comparisonHelper.classList.remove('hide');
// Scroll to results
setTimeout(() => {
@@ -980,6 +1030,28 @@ const compareAndRenderPackageVersions = (packageName, versionASpecific, versionB
}
}
};
+/**
+ * Populate comparison package dropdown from a changelog.
+ * Always includes @webex/widgets and @webex/cc-widgets first, then separator, then rest from changelog alphabetically.
+ */
+const populateComparisonPackagesFromChangelog = (changelog) => {
+ if (!comparisonPackageSelect) return;
+ const specialPackagesAlways = ['@webex/widgets', '@webex/cc-widgets'];
+ const allPackages = Object.keys(changelog || {});
+ const otherPackages = allPackages.filter((pkg) => !specialPackagesAlways.includes(pkg)).sort();
+ const sortedPackages = ['separator', ...specialPackagesAlways, 'separator', ...otherPackages];
+
+ let optionsHtml = '';
+ sortedPackages.forEach((packageName) => {
+ if (packageName === 'separator') {
+ optionsHtml += ``;
+ return;
+ }
+ optionsHtml += ``;
+ });
+ comparisonPackageSelect.innerHTML = optionsHtml;
+};
+
/**
* Populate the package dropdown with union of packages from both versions
* @param {Object} changelogA - Changelog for base version
@@ -996,7 +1068,7 @@ const populateUnionPackages = (changelogA, changelogB) => {
return;
}
- let optionsHtml = '';
+ let optionsHtml = '';
allPackages.forEach((pkg) => {
optionsHtml += ``;
});
@@ -1024,11 +1096,13 @@ const populatePrereleaseVersions = (packageName, changelog, selectId, stableVers
return;
}
- // Check if package exists in this changelog (it might not for union packages)
+ // If package not in this changelog, show the selected stable version as the only option (so user can still compare)
if (!changelog[packageName]) {
- if (versionSelect) {
- versionSelect.innerHTML = '';
- versionSelect.disabled = true;
+ if (versionSelect && stableVersion) {
+ let optionsHtml = '';
+ optionsHtml += ``;
+ versionSelect.innerHTML = optionsHtml;
+ versionSelect.disabled = false;
}
return;
}
@@ -1130,13 +1204,22 @@ const populateComparisonVersions = () => {
};
/**
- * Reset comparison form selections
+ * Reset comparison form selections and disable version/clear controls until package is selected
*/
const resetComparisonSelections = () => {
if (comparisonPackageSelect) comparisonPackageSelect.value = '';
if (versionAPrereleaseSelect) versionAPrereleaseSelect.value = '';
if (versionBPrereleaseSelect) versionBPrereleaseSelect.value = '';
- if (comparisonPackageRow) comparisonPackageRow.style.display = 'none';
+ if (versionASelect) {
+ versionASelect.value = '';
+ versionASelect.disabled = true;
+ }
+ if (versionBSelect) {
+ versionBSelect.value = '';
+ versionBSelect.disabled = true;
+ }
+ if (clearVersionABtn) clearVersionABtn.disabled = true;
+ if (clearVersionBBtn) clearVersionBBtn.disabled = true;
if (prereleaseRow) prereleaseRow.style.display = 'none';
};
@@ -1144,8 +1227,14 @@ const resetComparisonSelections = () => {
* Clear all comparison form inputs and state
*/
const clearComparisonForm = () => {
- if (versionASelect) versionASelect.value = '';
- if (versionBSelect) versionBSelect.value = '';
+ if (versionASelect) {
+ versionASelect.value = '';
+ versionASelect.disabled = true;
+ }
+ if (versionBSelect) {
+ versionBSelect.value = '';
+ versionBSelect.disabled = true;
+ }
resetComparisonSelections();
if (comparisonResults) comparisonResults.classList.add('hide');
@@ -1153,7 +1242,7 @@ const clearComparisonForm = () => {
if (copyComparisonLinkBtn) copyComparisonLinkBtn.classList.add('hide');
if (comparisonHelper) comparisonHelper.classList.add('hide');
- if (compareButton) compareButton.disabled = false;
+ if (compareButton) compareButton.disabled = true;
};
/**
@@ -1177,27 +1266,26 @@ const clearComparisonURLParams = () => {
};
/**
- * Check and update comparison button state based on form selections
+ * Check and update comparison button state based on form selections.
+ * Compare enables only when: package + base version + target version + both pre-release selections.
*/
const updateCompareButtonState = () => {
if (!compareButton) return;
const selectedPackage = comparisonPackageSelect ? comparisonPackageSelect.value : null;
+ const baseVersion = versionASelect ? versionASelect.value : null;
+ const targetVersion = versionBSelect ? versionBSelect.value : null;
const versionASpecific = versionAPrereleaseSelect ? versionAPrereleaseSelect.value : null;
const versionBSpecific = versionBPrereleaseSelect ? versionBPrereleaseSelect.value : null;
const prereleaseRowVisible = prereleaseRow && prereleaseRow.style.display !== 'none';
- if (selectedPackage) {
- // Package selected - require at least one pre-release version
- if (!prereleaseRowVisible || (!versionASpecific && !versionBSpecific)) {
- compareButton.disabled = true;
- } else {
- compareButton.disabled = false;
- }
- } else {
- // No package selected - enable for full version comparison
- compareButton.disabled = false;
- }
+ const hasAll =
+ selectedPackage &&
+ baseVersion &&
+ targetVersion &&
+ (!prereleaseRowVisible || (versionASpecific && versionBSpecific));
+
+ compareButton.disabled = !hasAll;
};
/**
@@ -1213,65 +1301,112 @@ const updatePrereleaseLabels = () => {
};
/**
- * Handle stable version changes - fetch changelogs and populate packages
+ * Handle stable version (base/target) change - fetch changelogs and populate pre-release dropdowns when package selected
*/
const handleStableVersionChange = async () => {
- console.log('🟢 handleStableVersionChange FIRED');
const stableA = versionASelect.value;
const stableB = versionBSelect.value;
+ const selectedPackage = comparisonPackageSelect ? comparisonPackageSelect.value : '';
- resetComparisonSelections();
- updateCompareButtonState();
+ if (versionAPrereleaseSelect) {
+ versionAPrereleaseSelect.value = '';
+ versionAPrereleaseSelect.disabled = true;
+ }
+ if (versionBPrereleaseSelect) {
+ versionBPrereleaseSelect.value = '';
+ versionBPrereleaseSelect.disabled = true;
+ }
- if (stableA && stableB) {
- try {
- const [changelogA, changelogB] = await Promise.all([
- fetch(versionPaths[stableA]).then((res) => res.json()),
- fetch(versionPaths[stableB]).then((res) => res.json()),
- ]);
-
- comparisonState.update(changelogA, changelogB, stableA, stableB);
- populateUnionPackages(changelogA, changelogB);
- updateCompareButtonState();
- } catch (error) {
- console.error('Error loading changelogs:', error);
- alert('Error loading version data. Please try again.');
+ try {
+ if (stableA) {
+ const changelogA = await fetch(versionPaths[stableA]).then((r) => r.json());
+ comparisonState.cachedChangelogA = changelogA;
+ comparisonState.currentStableA = stableA;
+ if (selectedPackage) {
+ populatePrereleaseVersions(
+ selectedPackage,
+ changelogA,
+ 'version-a-prerelease-select',
+ stableA
+ );
+ } else if (versionAPrereleaseSelect) {
+ versionAPrereleaseSelect.innerHTML = '';
+ }
+ } else if (versionAPrereleaseSelect) {
+ versionAPrereleaseSelect.innerHTML = '';
+ }
+ if (stableB) {
+ const changelogB = await fetch(versionPaths[stableB]).then((r) => r.json());
+ comparisonState.cachedChangelogB = changelogB;
+ comparisonState.currentStableB = stableB;
+ if (selectedPackage) {
+ populatePrereleaseVersions(
+ selectedPackage,
+ changelogB,
+ 'version-b-prerelease-select',
+ stableB
+ );
+ } else if (versionBPrereleaseSelect) {
+ versionBPrereleaseSelect.innerHTML = '';
+ }
+ } else if (versionBPrereleaseSelect) {
+ versionBPrereleaseSelect.innerHTML = '';
}
+ if (prereleaseRow) updatePrereleaseLabels();
+
+ // After both base and target are selected, disable version dropdowns so user picks pre-release only
+ if (stableA && stableB && selectedPackage) {
+ versionASelect.disabled = true;
+ versionBSelect.disabled = true;
+ }
+ } catch (error) {
+ console.error('Error loading changelogs:', error);
+ alert('Error loading version data. Please try again.');
}
+ updateCompareButtonState();
};
/**
- * Handle package selection - populate pre-release versions
+ * Handle package selection - enable version dropdowns and clear buttons, show pre-release row
*/
const handlePackageChange = () => {
- console.log('🟢 handlePackageChange FIRED');
- const selectedPackage = comparisonPackageSelect.value;
+ const selectedPackage = comparisonPackageSelect ? comparisonPackageSelect.value : '';
- if (versionAPrereleaseSelect) versionAPrereleaseSelect.value = '';
- if (versionBPrereleaseSelect) versionBPrereleaseSelect.value = '';
+ if (!selectedPackage) {
+ resetComparisonSelections();
+ if (compareButton) compareButton.disabled = true;
+ return;
+ }
+
+ versionASelect.disabled = false;
+ versionBSelect.disabled = false;
+ if (clearVersionABtn) clearVersionABtn.disabled = false;
+ if (clearVersionBBtn) clearVersionBBtn.disabled = false;
+ if (prereleaseRow) prereleaseRow.style.display = 'flex';
- if (selectedPackage && comparisonState.cachedChangelogA && comparisonState.cachedChangelogB) {
+ if (versionASelect.value && comparisonState.cachedChangelogA) {
populatePrereleaseVersions(
selectedPackage,
comparisonState.cachedChangelogA,
'version-a-prerelease-select',
comparisonState.currentStableA
);
+ } else if (versionAPrereleaseSelect) {
+ versionAPrereleaseSelect.innerHTML = '';
+ versionAPrereleaseSelect.disabled = true;
+ }
+ if (versionBSelect.value && comparisonState.cachedChangelogB) {
populatePrereleaseVersions(
selectedPackage,
comparisonState.cachedChangelogB,
'version-b-prerelease-select',
comparisonState.currentStableB
);
-
- if (prereleaseRow) {
- prereleaseRow.style.display = 'flex';
- updatePrereleaseLabels();
- }
- } else {
- if (prereleaseRow) prereleaseRow.style.display = 'none';
+ } else if (versionBPrereleaseSelect) {
+ versionBPrereleaseSelect.innerHTML = '';
+ versionBPrereleaseSelect.disabled = true;
}
-
+ if (prereleaseRow) updatePrereleaseLabels();
updateCompareButtonState();
};
@@ -1297,41 +1432,49 @@ const switchToSingleViewMode = () => {
/**
* Switch to comparison view mode
*/
-const switchToComparisonViewMode = () => {
- console.log('🔵 Switching to COMPARISON VIEW mode');
+const switchToComparisonViewMode = async () => {
comparisonMode = true;
- // Update button styles
comparisonViewBtn.classList.add('active', 'btn-primary');
comparisonViewBtn.classList.remove('btn-default');
singleViewBtn.classList.remove('active', 'btn-primary');
singleViewBtn.classList.add('btn-default');
- // Toggle visibility (centralized view state)
updateUIVisibility('comparison');
populateComparisonVersions();
+ try {
+ const changelog = await fetchMergedChangelogPackages();
+ populateComparisonPackagesFromChangelog(changelog);
+ } catch (e) {
+ console.error('Error loading packages for comparison:', e);
+ populateComparisonPackagesFromChangelog({});
+ }
+ resetComparisonSelections();
+ if (compareButton) compareButton.disabled = true;
};
/**
- * Validate comparison form inputs
+ * Validate comparison form inputs (package and both versions required)
*/
const validateComparisonInputs = (stableA, stableB, selectedPackage, versionASpecific, versionBSpecific) => {
+ if (!selectedPackage) {
+ alert('Please select a package');
+ return false;
+ }
if (!stableA || !stableB) {
- alert('Please select both stable versions');
+ alert('Please select both base and target stable versions');
return false;
}
-
- if (selectedPackage && !versionASpecific && !versionBSpecific) {
- alert('Please select at least one pre-release version, or leave package empty for full version comparison');
+ if (!versionASpecific || !versionBSpecific) {
+ alert('Please select pre-release (or stable) for both base and target');
return false;
}
-
return true;
};
/**
- * Handle comparison form submission
+ * Handle comparison form submission (package-level only)
*/
const handleComparisonSubmit = (event) => {
event.preventDefault();
@@ -1346,25 +1489,16 @@ const handleComparisonSubmit = (event) => {
return;
}
- if (selectedPackage && (versionASpecific || versionBSpecific)) {
- // Package-level comparison
- const finalVersionA = versionASpecific || stableA;
- const finalVersionB = versionBSpecific || stableB;
- console.log('Comparing:', finalVersionA, 'vs', finalVersionB);
-
- compareAndRenderPackageVersions(
- selectedPackage,
- finalVersionA,
- finalVersionB,
- comparisonState.cachedChangelogA,
- comparisonState.cachedChangelogB
- );
- } else {
- // Full version comparison
- performVersionComparison(stableA, stableB);
- }
+ const finalVersionA = versionASpecific || stableA;
+ const finalVersionB = versionBSpecific || stableB;
- if (compareButton) compareButton.disabled = false;
+ compareAndRenderPackageVersions(
+ selectedPackage,
+ finalVersionA,
+ finalVersionB,
+ comparisonState.cachedChangelogA,
+ comparisonState.cachedChangelogB
+ );
};
/**
@@ -1405,6 +1539,34 @@ const setupComparisonEventListeners = () => {
if (comparisonForm) comparisonForm.addEventListener('submit', handleComparisonSubmit);
if (clearComparisonButton) clearComparisonButton.addEventListener('click', handleClearClick);
if (copyComparisonLinkBtn) copyComparisonLinkBtn.addEventListener('click', copyComparisonLink);
+ if (clearVersionABtn) {
+ clearVersionABtn.addEventListener('click', () => {
+ if (versionASelect) {
+ versionASelect.value = '';
+ versionASelect.disabled = false;
+ if (versionAPrereleaseSelect) {
+ versionAPrereleaseSelect.innerHTML = '';
+ versionAPrereleaseSelect.value = '';
+ versionAPrereleaseSelect.disabled = true;
+ }
+ updateCompareButtonState();
+ }
+ });
+ }
+ if (clearVersionBBtn) {
+ clearVersionBBtn.addEventListener('click', () => {
+ if (versionBSelect) {
+ versionBSelect.value = '';
+ versionBSelect.disabled = false;
+ if (versionBPrereleaseSelect) {
+ versionBPrereleaseSelect.innerHTML = '';
+ versionBPrereleaseSelect.value = '';
+ versionBPrereleaseSelect.disabled = true;
+ }
+ updateCompareButtonState();
+ }
+ });
+ }
comparisonListenersInitialized = true;
console.log('comparison listeners are initialized sucessfully......');
@@ -1414,7 +1576,7 @@ const setupComparisonEventListeners = () => {
* Handle enhanced comparison URL parameters on page load
*/
const loadEnhancedComparisonFromURL = async (enhancedParams) => {
- switchToComparisonMode();
+ await switchToComparisonMode();
await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1445,7 +1607,7 @@ const loadEnhancedComparisonFromURL = async (enhancedParams) => {
* Handle standard comparison URL parameters on page load
*/
const loadStandardComparisonFromURL = async (urlParams) => {
- switchToComparisonMode(urlParams.versionA, urlParams.versionB);
+ await switchToComparisonMode(urlParams.versionA, urlParams.versionB);
await new Promise((resolve) => setTimeout(resolve, 300));
diff --git a/docs/changelog/assets/js/comparison-view.js b/docs/changelog/assets/js/comparison-view.js
index 7352606aa..52bb4e4de 100644
--- a/docs/changelog/assets/js/comparison-view.js
+++ b/docs/changelog/assets/js/comparison-view.js
@@ -24,13 +24,11 @@ const extractPackagesFromVersion = (changelog, specificVersions = null) => {
for (const packageName of Object.keys(changelog)) {
const packageVersions = changelog[packageName];
- console.log('packageVersions', packageVersions);
// Safety check: ensure packageVersions is an object
if (!packageVersions || typeof packageVersions !== 'object') continue;
const versionKeys = Object.keys(packageVersions);
- console.log('versionKeys', versionKeys);
if (versionKeys.length === 0) continue;
@@ -370,6 +368,22 @@ const generatePackageComparisonData = (packageName, versionASpecific, versionBSp
...stats,
};
};
+
+/**
+ * Get sorted widget-related package names from a changelog (for comparison package dropdown).
+ * Puts @webex/widgets and @webex/cc-widgets first, then remaining packages alphabetically.
+ * @param {Object} changelog - Changelog data (package name -> versions)
+ * @returns {string[]} Sorted array of package names
+ */
+const getWidgetPackagesFromChangelog = (changelog) => {
+ if (!changelog || typeof changelog !== 'object') return [];
+ const specialPackages = ['@webex/widgets', '@webex/cc-widgets'];
+ const allPackages = Object.keys(changelog);
+ const existingSpecial = specialPackages.filter((p) => allPackages.includes(p));
+ const other = allPackages.filter((p) => !specialPackages.includes(p)).sort();
+ return [...existingSpecial, ...other];
+};
+
//Export All the functions
export {
comparisonState,
@@ -384,4 +398,5 @@ export {
comparePackages,
fetchAndCompareVersions,
generatePackageComparisonData,
+ getWidgetPackagesFromChangelog,
};
diff --git a/docs/changelog/index.html b/docs/changelog/index.html
index 18a7eb548..c924475e7 100644
--- a/docs/changelog/index.html
+++ b/docs/changelog/index.html
@@ -1,100 +1,88 @@
-
-
-
-
- Webex Widgets
-
+
+
+
+
-
-
-
+ Webex Widgets
+
-
-
+
+
+
-
-