{% extends "base.html" %} {% block title %}Historia zmian - Norda Biznes Partner{% endblock %} {% block extra_css %}
{% endblock %} {% block content %}

# 📋 Historia zmian

Dziennik rozwoju platformy Norda Biznes Partner

### {{ stats.companies }}

Firm w katalogu

### {{ stats.categories }}

Kategorii branżowych

### {{ releases|length }}

Aktualizacji

### 2025

Rok startu

{% for release in releases %}
{{ release.version }}
{% for badge in release.badges %} {{ badge }} {% endfor %}
{{ release.date }}
{% if current_user.is_authenticated and current_user.is_admin %}
{% endif %}
{% if release.new %}

#### Nowości

{% for item in release.new %}
- {{ item|safe }}
{% endfor %}

{% endif %} {% if release.improve %}

#### Ulepszenia

{% for item in release.improve %}
- {{ item|safe }}
{% endfor %}

{% endif %} {% if release.fix %}

#### Naprawione

{% for item in release.fix %}
- {{ item|safe }}
{% endfor %}

{% endif %} {% if release.security %}

#### Bezpieczeństwo

{% for item in release.security %}
- {{ item|safe }}
{% endfor %}

{% endif %} {% if release.beta %}

#### W fazie testów (BETA)

{% for item in release.beta %}
- {{ item|safe }}
{% endfor %}

{% endif %}
{% endfor %}

### Wyślij powiadomienia

Czy na pewno chcesz wysłać powiadomienia?

{% endblock %} {% block extra_js %} // Toast function function showToast(message, type = 'info', duration = 4000) { const container = document.getElementById('toastContainer'); const icons = { success: '✓', error: '✕', warning: '⚠', info: 'ℹ' }; const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.innerHTML = `${icons[type]||'ℹ'}${message}`; container.appendChild(toast); setTimeout(() => { toast.style.animation = 'toastOut 0.3s ease forwards'; setTimeout(() => toast.remove(), 300); }, duration); } // Confirm modal let confirmCallback = null; function showConfirmModal(title, message, info, onConfirm) { document.getElementById('confirmTitle').textContent = title; document.getElementById('confirmMessage').textContent = message; document.getElementById('confirmInfo').textContent = info || ''; document.getElementById('confirmModal').classList.add('active'); confirmCallback = onConfirm; } function closeConfirmModal() { document.getElementById('confirmModal').classList.remove('active'); confirmCallback = null; } document.getElementById('confirmButton').addEventListener('click', function() { if (confirmCallback) { confirmCallback(); } closeConfirmModal(); }); document.getElementById('confirmModal').addEventListener('click', function(e) { if (e.target === this) { closeConfirmModal(); } }); {% if current_user.is_authenticated and current_user.is_admin %} function notifyRelease(version, btn) { showConfirmModal( 'Wyślij powiadomienia', `Czy na pewno chcesz wysłać powiadomienia o wersji ${version}?`, 'Powiadomienie pojawi się przy ikonce dzwoneczka u wszystkich użytkowników.', function() { btn.disabled = true; btn.innerHTML = '⏳ Wysyłanie...'; // Get first 3 highlights from the release card const card = btn.closest('.release-card'); const highlights = []; const items = card.querySelectorAll('.change-category.new .change-list li'); items.forEach((item, i) => { if (i < 3) highlights.push(item.textContent.trim()); }); fetch('/admin/notify-release', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': '{{ csrf_token() }}' }, body: JSON.stringify({ version: version, highlights: highlights }) }) .then(response => response.json()) .then(data => { if (data.success) { btn.innerHTML = '✅ Wysłano'; btn.classList.add('sent'); showToast(data.message, 'success'); } else { btn.innerHTML = '❌ Błąd'; btn.disabled = false; showToast('Błąd: ' + data.error, 'error'); } }) .catch(error => { btn.innerHTML = '❌ Błąd'; btn.disabled = false; showToast('Błąd połączenia', 'error'); }); } ); } {% endif %} {% endblock %}