diff --git a/app/core/src/main/resources/static/js/githubVersion.js b/app/core/src/main/resources/static/js/githubVersion.js index 2aef90d8c..26ad8066b 100644 --- a/app/core/src/main/resources/static/js/githubVersion.js +++ b/app/core/src/main/resources/static/js/githubVersion.js @@ -16,21 +16,89 @@ function compareVersions(version1, version2) { return 0; } -async function getLatestReleaseVersion() { - const url = "https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest"; +function getDownloadUrl() { + // Only show download for non-Docker installations + if (machineType === 'Docker' || machineType === 'Kubernetes') { + return null; + } + + const baseUrl = 'https://files.stirlingpdf.com/'; + + // Determine file based on machine type and security + if (machineType === 'Server-jar') { + return baseUrl + (activeSecurity ? 'Stirling-PDF-with-login.jar' : 'Stirling-PDF.jar'); + } + + // Client installations + if (machineType.startsWith('Client-')) { + const os = machineType.replace('Client-', ''); // win, mac, unix + const type = activeSecurity ? '-server-security' : '-server'; + + if (os === 'unix') { + return baseUrl + os + type + '.jar'; + } else if (os === 'win') { + return baseUrl + os + '-installer.exe'; + } else if (os === 'mac') { + return baseUrl + os + '-installer.dmg'; + } + } + + return null; +} + +async function getUpdateSummary() { + // Map Java License enum to API types + let type = 'community'; + if (licenseType === 'NORMAL') { + type = 'community'; + } else if (licenseType === 'PRO') { + type = 'pro'; + } else if (licenseType === 'ENTERPRISE') { + type = 'enterprise'; + } + const url = `https://supabase.stirling.com/functions/v1/updates?from=${currentVersion}&type=${type}&summary=true`; + console.log("Fetching update summary from:", url); try { const response = await fetch(url); + console.log("Response status:", response.status); if (response.status === 200) { const data = await response.json(); - return data.tag_name ? data.tag_name.substring(1) : ""; + return data; } else { - // If the status is not 200, try to get the version from build.gradle - return await getCurrentVersionFromBypass(); + console.error("Failed to fetch update summary from Supabase:", response.status); + return null; } } catch (error) { - console.error("Failed to fetch latest version from GitHub:", error); - // If an error occurs, try to get the version from build.gradle - return await getCurrentVersionFromBypass(); + console.error("Failed to fetch update summary from Supabase:", error); + return null; + } +} + +async function getFullUpdateInfo() { + // Map Java License enum to API types + let type = 'community'; + if (licenseType === 'NORMAL') { + type = 'community'; + } else if (licenseType === 'PRO') { + type = 'pro'; + } else if (licenseType === 'ENTERPRISE') { + type = 'enterprise'; + } + const url = `https://supabase.stirling.com/functions/v1/updates?from=${currentVersion}&type=${type}&summary=false`; + console.log("Fetching full update info from:", url); + try { + const response = await fetch(url); + console.log("Full update response status:", response.status); + if (response.status === 200) { + const data = await response.json(); + return data; + } else { + console.error("Failed to fetch full update info from Supabase:", response.status); + return null; + } + } catch (error) { + console.error("Failed to fetch full update info from Supabase:", error); + return null; } } @@ -60,6 +128,7 @@ async function checkForUpdate() { var updateLinkLegacy = document.getElementById("update-link-legacy") || null; if (updateBtn !== null) { updateBtn.style.display = "none"; + updateBtn.classList.remove("btn-danger", "btn-warning", "btn-outline-primary"); } if (updateLink !== null) { updateLink.style.display = "none"; @@ -71,19 +140,47 @@ async function checkForUpdate() { } } - const latestVersion = await getLatestReleaseVersion(); - console.log("latestVersion=" + latestVersion); + const updateSummary = await getUpdateSummary(); + if (!updateSummary) { + console.log("No update summary available"); + return; + } + + console.log("updateSummary=", updateSummary); console.log("currentVersion=" + currentVersion); - console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion)); - if (latestVersion && compareVersions(latestVersion, currentVersion) > 0) { + console.log("latestVersion=" + updateSummary.latest_version); + + if (updateSummary.latest_version && compareVersions(updateSummary.latest_version, currentVersion) > 0) { + const priority = updateSummary.max_priority || 'normal'; + if (updateBtn != null) { - document.getElementById("update-btn").style.display = "block"; + // Style button based on priority + if (priority === 'urgent') { + updateBtn.classList.add("btn-danger"); + updateBtn.innerHTML = "🚨 Update Available"; + } else if (priority === 'normal') { + updateBtn.classList.add("btn-warning"); + updateBtn.innerHTML = "Update Available"; + } else { + updateBtn.classList.add("btn-outline-primary"); + updateBtn.innerHTML = "Update Available"; + } + + // Store summary for initial display + updateBtn.setAttribute('data-update-summary', JSON.stringify(updateSummary)); + updateBtn.style.display = "block"; + + // Add click handler for update details modal + updateBtn.onclick = function(e) { + e.preventDefault(); + showUpdateModal(); + }; } if (updateLink !== null) { document.getElementById("update-link").style.display = "flex"; } if (updateLinkLegacy !== null) { - document.getElementById("app-update").innerHTML = updateAvailable.replace("{0}", '' + currentVersion + '').replace("{1}", '' + latestVersion + ''); + document.getElementById("app-update").innerHTML = updateAvailable.replace("{0}", '' + currentVersion + '').replace("{1}", '' + updateSummary.latest_version + ''); if (updateLinkLegacy.classList.contains("visually-hidden")) { updateLinkLegacy.classList.remove("visually-hidden"); } @@ -99,6 +196,160 @@ async function checkForUpdate() { } } +async function showUpdateModal() { + // Close settings modal if open + const settingsModal = bootstrap.Modal.getInstance(document.getElementById('settingsModal')); + if (settingsModal) { + settingsModal.hide(); + } + + // Get summary data from button + const updateBtn = document.getElementById("update-btn"); + const summaryData = JSON.parse(updateBtn.getAttribute('data-update-summary')); + + // Create initial modal with loading state + const initialModalHtml = ` + + `; + + // Remove existing modal if present + const existingModal = document.getElementById('updateModal'); + if (existingModal) { + existingModal.remove(); + } + + // Add modal to body + document.body.insertAdjacentHTML('beforeend', initialModalHtml); + + // Show modal + const modal = new bootstrap.Modal(document.getElementById('updateModal')); + modal.show(); + + // Fetch full update info + const fullUpdateInfo = await getFullUpdateInfo(); + + // Update modal with full information + const modalBody = document.getElementById('updateModalBody'); + if (fullUpdateInfo && fullUpdateInfo.new_versions) { + const detailedVersionsHtml = ` +
+
Available Updates:
+
+ ${fullUpdateInfo.new_versions.map((version, index) => ` +
+

+ +

+
+
+
${version.announcement.title}
+

${version.announcement.message}

+ ${version.compatibility.breaking_changes ? ` + + ` : ''} +
+
+
+ `).join('')} +
+
+ `; + + // Remove loading spinner and add detailed info + const spinner = document.getElementById('loadingSpinner'); + if (spinner) { + spinner.parentElement.remove(); + } + modalBody.insertAdjacentHTML('beforeend', detailedVersionsHtml); + } else { + // Remove loading spinner if failed to load + const spinner = document.getElementById('loadingSpinner'); + if (spinner) { + spinner.parentElement.innerHTML = '

Unable to load detailed version information.

'; + } + } +} + document.addEventListener("DOMContentLoaded", (event) => { checkForUpdate(); }); diff --git a/app/core/src/main/resources/templates/fragments/navbar.html b/app/core/src/main/resources/templates/fragments/navbar.html index e5aea9345..7814bd00e 100644 --- a/app/core/src/main/resources/templates/fragments/navbar.html +++ b/app/core/src/main/resources/templates/fragments/navbar.html @@ -11,6 +11,9 @@