mirror of
https://github.com/kossakovsky/n8n-install.git
synced 2026-03-07 14:23:08 +00:00
feat(welcome): add changelog section to dashboard
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,6 +12,7 @@ volumes/
|
||||
docker-compose.override.yml
|
||||
docker-compose.n8n-workers.yml
|
||||
welcome/data.json
|
||||
welcome/changelog.json
|
||||
|
||||
# Custom TLS certificates
|
||||
certs/*
|
||||
|
||||
15
CHANGELOG.md
15
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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -136,6 +136,11 @@
|
||||
warning: (className = '') => `
|
||||
<svg class="${className}" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
||||
</svg>`,
|
||||
|
||||
changelog: (className = '') => `
|
||||
<svg class="${className}" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"/>
|
||||
</svg>`
|
||||
};
|
||||
|
||||
@@ -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 = `
|
||||
<p class="text-gray-500 text-center py-8">Changelog not available</p>
|
||||
`;
|
||||
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();
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(17, 17, 17, 0.8);
|
||||
background: transparent;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
@@ -198,6 +198,23 @@
|
||||
|
||||
<div class="gradient-line my-8" aria-hidden="true"></div>
|
||||
|
||||
<!-- Changelog Section -->
|
||||
<section class="mb-16">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<div class="w-10 h-10 rounded-lg bg-brand/10 border border-brand/20 flex items-center justify-center"
|
||||
data-section-icon="changelog"></div>
|
||||
<h2 class="text-2xl font-semibold text-white">Changelog</h2>
|
||||
</div>
|
||||
<div id="changelog-container"
|
||||
class="bg-surface-100 rounded-xl border border-surface-400 p-6 overflow-y-auto"
|
||||
style="max-height: 444px;">
|
||||
<!-- Changelog content will be injected here by JavaScript -->
|
||||
<div class="animate-pulse h-32"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="gradient-line my-8" aria-hidden="true"></div>
|
||||
|
||||
<!-- Documentation Section -->
|
||||
<section class="mb-16">
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
|
||||
Reference in New Issue
Block a user