feat: improve SEO dashboard with problem tags and better UX
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
- Add "Problemy" column showing actionable issues per company (Slabe SEO, Wolna strona, Niska dostepnosc, Brak standardow) - Add tooltips to column headers explaining each metric - Sort by worst scores first (companies needing help on top) - Unaudited companies always at bottom regardless of sort - Replace "medium" stat card with total companies count - Remove API button from header (admin doesn't need raw JSON) - Add problem/warn/ok/na tag styling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d8ee8fe7e4
commit
bc7b206741
@ -342,6 +342,53 @@
|
||||
.legend-dot.medium { background: #fef3c7; border: 1px solid #92400e; }
|
||||
.legend-dot.poor { background: #fee2e2; border: 1px solid #991b1b; }
|
||||
|
||||
/* Problem tags */
|
||||
.problems-cell {
|
||||
max-width: 160px;
|
||||
}
|
||||
|
||||
.problem-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
background: #fee2e2;
|
||||
color: #991b1b;
|
||||
margin: 1px 2px;
|
||||
}
|
||||
|
||||
.warn-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
}
|
||||
|
||||
.ok-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
.na-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
background: var(--border);
|
||||
color: var(--text-secondary);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 1200px) {
|
||||
.seo-table {
|
||||
@ -552,36 +599,31 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<a href="{{ url_for('api.api_seo_audit') }}" class="btn btn-outline btn-sm" target="_blank">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
|
||||
</svg>
|
||||
API
|
||||
</a>
|
||||
{% if current_user.can_access_admin_panel() %}
|
||||
<button class="btn btn-primary btn-sm" onclick="runBatchAudit()" id="batchAuditBtn">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
||||
</svg>
|
||||
Uruchom audyt
|
||||
Uruchom audyt wszystkich
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Summary Stats -->
|
||||
{% set total_companies = stats.good_count + stats.medium_count + stats.poor_count + stats.not_audited_count %}
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<span class="stat-number green">{{ stats.good_count }}</span>
|
||||
<span class="stat-label">Wynik 90-100</span>
|
||||
<span class="stat-number">{{ total_companies }}</span>
|
||||
<span class="stat-label">Firm ogolnie</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-number yellow">{{ stats.medium_count }}</span>
|
||||
<span class="stat-label">Wynik 50-89</span>
|
||||
<span class="stat-number green">{{ stats.good_count }}</span>
|
||||
<span class="stat-label">Dobre SEO (90+)</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-number red">{{ stats.poor_count }}</span>
|
||||
<span class="stat-label">Wynik 0-49</span>
|
||||
<span class="stat-label">Slabe SEO (ponizej 50)</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-number gray">{{ stats.not_audited_count }}</span>
|
||||
@ -589,7 +631,7 @@
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-number">{{ stats.avg_score|default('-', true) }}{% if stats.avg_score %}<small>/100</small>{% endif %}</span>
|
||||
<span class="stat-label">Sredni wynik SEO</span>
|
||||
<span class="stat-label">Sredni wynik</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -664,20 +706,21 @@
|
||||
<th data-sort="category" class="hide-mobile">
|
||||
Kategoria <span class="sort-icon"></span>
|
||||
</th>
|
||||
<th data-sort="overall" class="sorted sorted-desc">
|
||||
Wynik SEO <span class="sort-icon"></span>
|
||||
<th data-sort="overall" class="sorted sorted-asc" title="Ogolna ocena SEO strony: meta tagi, struktura, indeksowalnosc">
|
||||
SEO <span class="sort-icon"></span>
|
||||
</th>
|
||||
<th data-sort="performance" class="hide-mobile">
|
||||
<th data-sort="performance" class="hide-mobile" title="Performance — szybkosc ladowania strony, czas do interakcji">
|
||||
Performance <span class="sort-icon"></span>
|
||||
</th>
|
||||
<th data-sort="accessibility" class="hide-mobile">
|
||||
Dostepnosc <span class="sort-icon"></span>
|
||||
<th data-sort="accessibility" class="hide-mobile" title="Accessibility — dostepnosc dla osob z niepelnosprawnosciami (kontrast, opisy, nawigacja klawiatura)">
|
||||
Accessibility <span class="sort-icon"></span>
|
||||
</th>
|
||||
<th data-sort="best_practices" class="hide-mobile">
|
||||
<th data-sort="best_practices" class="hide-mobile" title="Best Practices — bezpieczenstwo (HTTPS), nowoczesne standardy, brak bledow w konsoli">
|
||||
Best Practices <span class="sort-icon"></span>
|
||||
</th>
|
||||
<th>Problemy</th>
|
||||
<th data-sort="date">
|
||||
Ostatni audyt <span class="sort-icon"></span>
|
||||
Audyt <span class="sort-icon"></span>
|
||||
</th>
|
||||
<th>Akcje</th>
|
||||
</tr>
|
||||
@ -740,6 +783,36 @@
|
||||
<span class="score-badge score-na">-</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="problems-cell">
|
||||
{% if company.seo_score is not none %}
|
||||
{% set problems = [] %}
|
||||
{% if company.seo_score is not none and company.seo_score < 50 %}
|
||||
{% set _ = problems.append('Slabe SEO') %}
|
||||
{% endif %}
|
||||
{% if company.performance_score is not none and company.performance_score < 50 %}
|
||||
{% set _ = problems.append('Wolna strona') %}
|
||||
{% endif %}
|
||||
{% if company.accessibility_score is not none and company.accessibility_score < 50 %}
|
||||
{% set _ = problems.append('Niska dostepnosc') %}
|
||||
{% endif %}
|
||||
{% if company.best_practices_score is not none and company.best_practices_score < 50 %}
|
||||
{% set _ = problems.append('Brak standardow') %}
|
||||
{% endif %}
|
||||
{% if problems %}
|
||||
{% for p in problems %}
|
||||
<span class="problem-tag">{{ p }}</span>
|
||||
{% endfor %}
|
||||
{% elif company.seo_score >= 90 and (company.performance_score is none or company.performance_score >= 90) %}
|
||||
<span class="ok-tag">Wszystko OK</span>
|
||||
{% else %}
|
||||
<span class="warn-tag">Do poprawy</span>
|
||||
{% endif %}
|
||||
{% elif not company.website %}
|
||||
<span class="na-tag">Brak strony WWW</span>
|
||||
{% else %}
|
||||
<span class="na-tag">Brak danych</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="date-cell">
|
||||
{% if company.seo_audited_at %}
|
||||
{% set days_ago = (now - company.seo_audited_at).days %}
|
||||
@ -869,7 +942,7 @@ document.getElementById('infoModal')?.addEventListener('click', (e) => {
|
||||
});
|
||||
|
||||
// Sorting state
|
||||
let currentSort = { column: 'overall', direction: 'desc' };
|
||||
let currentSort = { column: 'overall', direction: 'asc' };
|
||||
|
||||
// Sort table
|
||||
function sortTable(column) {
|
||||
@ -893,7 +966,7 @@ function sortTable(column) {
|
||||
}
|
||||
});
|
||||
|
||||
// Sort rows
|
||||
// Sort rows (unaudited companies always at the bottom)
|
||||
rows.sort((a, b) => {
|
||||
let aVal, bVal;
|
||||
|
||||
@ -907,8 +980,12 @@ function sortTable(column) {
|
||||
aVal = new Date(a.dataset.date).getTime();
|
||||
bVal = new Date(b.dataset.date).getTime();
|
||||
} else {
|
||||
aVal = parseFloat(a.dataset[column]) || -1;
|
||||
bVal = parseFloat(b.dataset[column]) || -1;
|
||||
aVal = parseFloat(a.dataset[column]);
|
||||
bVal = parseFloat(b.dataset[column]);
|
||||
// Push unaudited (-1) to the bottom regardless of sort direction
|
||||
if (aVal < 0 && bVal >= 0) return 1;
|
||||
if (bVal < 0 && aVal >= 0) return -1;
|
||||
if (aVal < 0 && bVal < 0) return 0;
|
||||
}
|
||||
|
||||
if (aVal < bVal) return currentSort.direction === 'asc' ? -1 : 1;
|
||||
@ -925,6 +1002,9 @@ document.querySelectorAll('.seo-table th[data-sort]').forEach(th => {
|
||||
th.addEventListener('click', () => sortTable(th.dataset.sort));
|
||||
});
|
||||
|
||||
// Initial sort — worst scores first
|
||||
sortTable('overall');
|
||||
|
||||
// Filtering
|
||||
function applyFilters() {
|
||||
const category = document.getElementById('filterCategory').value;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user