diff --git a/.gitignore b/.gitignore index db19cd4..ff35dc7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ volumes/ docker-compose.override.yml docker-compose.n8n-workers.yml welcome/data.json +welcome/changelog.json # Custom TLS certificates certs/* diff --git a/CHANGELOG.md b/CHANGELOG.md index c83e80f..b85fcda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,9 @@ # Changelog -All notable changes to this project are documented in this file. +## [1.2.0] - 2026-01-12 -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] +### Added +- Changelog section on Welcome Page dashboard ## [1.1.0] - 2026-01-11 @@ -219,3 +217,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Langfuse - LLM observability and analytics platform - Initial fork from coleam00/local-ai-packager with enhanced service support + +--- + +All notable changes to this project are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/scripts/generate_welcome_page.sh b/scripts/generate_welcome_page.sh index a14de8d..25b9683 100755 --- a/scripts/generate_welcome_page.sh +++ b/scripts/generate_welcome_page.sh @@ -541,3 +541,30 @@ EOF log_success "Welcome page data generated at: $OUTPUT_FILE" log_info "Access it at: https://${WELCOME_HOSTNAME:-welcome.${USER_DOMAIN_NAME}}" + +# Generate changelog.json with CHANGELOG.md content +CHANGELOG_JSON_FILE="$PROJECT_ROOT/welcome/changelog.json" +CHANGELOG_SOURCE="$PROJECT_ROOT/CHANGELOG.md" + +if [ -f "$CHANGELOG_SOURCE" ]; then + # Read and escape content for JSON (preserve newlines as \n) + # Using awk for cross-platform compatibility (macOS + Linux) + CHANGELOG_CONTENT=$(awk ' + BEGIN { ORS="" } + { + gsub(/\\/, "\\\\") # Escape backslashes first + gsub(/"/, "\\\"") # Escape double quotes + gsub(/\t/, "\\t") # Escape tabs + gsub(/\r/, "") # Remove carriage returns (CRLF → LF) + if (NR > 1) printf "\\n" + printf "%s", $0 + } + ' "$CHANGELOG_SOURCE") + + # Write changelog.json file + printf '{\n "content": "%s"\n}\n' "$CHANGELOG_CONTENT" > "$CHANGELOG_JSON_FILE" + + log_success "Changelog JSON generated at: $CHANGELOG_JSON_FILE" +else + log_warning "CHANGELOG.md not found, skipping changelog.json generation" +fi diff --git a/welcome/app.js b/welcome/app.js index c162bd8..f1c9b40 100644 --- a/welcome/app.js +++ b/welcome/app.js @@ -136,6 +136,11 @@ warning: (className = '') => ` `, + + changelog: (className = '') => ` + ` }; @@ -844,6 +849,7 @@ const servicesContainer = document.getElementById('services-container'); const quickstartContainer = document.getElementById('quickstart-container'); const commandsContainer = document.getElementById('commands-container'); + const changelogContainer = document.getElementById('changelog-container'); const domainInfo = document.getElementById('domain-info'); /** @@ -959,6 +965,26 @@ commandsContainer.appendChild(grid); } + /** + * Render changelog content + */ + function renderChangelog(content) { + if (!changelogContainer) return; + changelogContainer.innerHTML = ''; + + if (!content) { + changelogContainer.innerHTML = ` +
Changelog not available
+ `; + return; + } + + const pre = document.createElement('pre'); + pre.className = 'text-sm text-gray-300 font-mono whitespace-pre-wrap break-words leading-relaxed'; + pre.textContent = content; + changelogContainer.appendChild(pre); + } + /** * Render error state in services container */ @@ -984,14 +1010,26 @@ // Always render commands (static content) renderCommands(); - try { - const response = await fetch('data.json'); + // Fetch both JSON files in parallel for better performance + // Each fetch is handled independently - changelog failure won't affect main data + const [changelogResult, dataResult] = await Promise.allSettled([ + fetch('changelog.json').then(r => r.ok ? r.json() : null), + fetch('data.json').then(r => r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`))) + ]); - if (!response.ok) { - throw new Error(`Failed to load data (${response.status})`); + // Handle changelog (independent - failures don't break the page) + if (changelogResult.status === 'fulfilled' && changelogResult.value?.content) { + renderChangelog(changelogResult.value.content); + } else { + if (changelogResult.status === 'rejected') { + console.error('Error loading changelog:', changelogResult.reason); } + renderChangelog(null); + } - const data = await response.json(); + // Handle main data + if (dataResult.status === 'fulfilled' && dataResult.value) { + const data = dataResult.value; // Update domain info if (domainInfo) { @@ -1009,9 +1047,8 @@ // Render quick start renderQuickStart(data.quick_start); - - } catch (error) { - console.error('Error loading data:', error); + } else { + console.error('Error loading data:', dataResult.reason); // Show error in UI renderServicesError(); diff --git a/welcome/index.html b/welcome/index.html index 3bed81a..125feae 100644 --- a/welcome/index.html +++ b/welcome/index.html @@ -51,7 +51,7 @@ } ::-webkit-scrollbar-track { - background: rgba(17, 17, 17, 0.8); + background: transparent; border-radius: 5px; } @@ -198,6 +198,23 @@ + +