Files
GTI_GERENCIADOR_FISCAL/central/templates/dashboard.html
T

54 lines
5.9 KiB
HTML

{% extends "base.html" %}
{% block title %}Resumo | GTI Fiscal{% endblock %}
{% block content %}
<div class="page-heading">
<div><p class="eyebrow">OPERAÇÃO CENTRAL</p><h1>Qual cliente precisa de atenção?</h1><p class="muted">Somente instalações ativas. Histórico permanece disponível nas listagens.</p></div>
<span class="live-dot">Atualizado pelo snapshot</span>
</div>
<section class="cards" aria-label="Saúde dos servidores">
{% for key,label,health in [("agents_total","Servidores",none),("online","Online","ONLINE"),("degraded","Atenção","DEGRADED"),("offline","Offline","OFFLINE"),("failed","Falhou","FAILED"),("unknown","Não informado","UNKNOWN")] %}
<a class="metric metric-link" href="/agents?scope=active{% if health %}&amp;health={{ health }}{% endif %}" aria-label="{{ label }}: {{ summary[key] }}. Ver servidores{% if health %} filtrados{% endif %}">
<span>{{ label }}</span><strong>{{ summary[key] }}</strong><small>Ver servidores <span aria-hidden="true">→</span></small>
</a>
{% endfor %}
</section>
<section class="split overview-split">
<article class="panel">
<div class="panel-title"><h2>Cobertura dos produtos</h2><a href="/agents?scope=active">Ver servidores</a></div>
<div class="coverage">
{% for key,label,url in [("total_products","Produtos avaliados","/agents?scope=active"),("fiscally_complete","Completos","/agents?scope=active&amp;sort=worst_coverage"),("safe_blocked","Bloqueados com segurança","/blockers?scope=active&amp;status=OPEN"),("failed_products","Falhas técnicas","/agents?scope=active&amp;health=FAILED"),("unclassified_products","Não classificados","/agents?scope=active&amp;sort=worst_coverage")] %}
<a class="coverage-item" href="{{ url|safe }}" aria-label="{{ label }}: {{ summary[key] }}. Abrir listagem"><strong>{{ summary[key] }}</strong><span>{{ label }}</span></a>
{% endfor %}
</div>
{% if summary.coverage_invariant_pass %}<p class="coverage-status">Cobertura reconciliada: total = completos + bloqueados + falhas + não classificados.</p>{% else %}<p class="coverage-status error">Inconsistência de cobertura: {{ summary.coverage_overcount_products }} acima do total; {{ summary.coverage_invalid_snapshots }} snapshot(s) com contagens negativas.</p>{% endif %}
<div class="registry-summary"><a href="/blockers?scope=active&amp;status=OPEN">Produtos com blockers abertos: <strong>{{ summary.safe_blocked_products }}</strong></a><span>Blockers abertos: <strong>{{ summary.open_blockers }}</strong></span></div>
</article>
<article class="panel">
<div class="panel-title"><h2>Breakdown dos blockers</h2><a href="/blockers?scope=active&amp;status=OPEN">Ver blockers</a></div>
{% for key in ["CFOP","ST","ICMS","CSOSN","NCM","OTHER"] %}
{% if summary.open_blocker_breakdown[key] > 0 %}<a class="bar-row bar-link" href="/blockers?scope=active&amp;status=OPEN&amp;field={{ key }}" aria-label="{{ key }}: {{ summary.open_blocker_breakdown[key] }} blockers abertos"><span>{{ key }}</span><b>{{ summary.open_blocker_breakdown[key] }}</b><span aria-hidden="true">→</span></a>
{% else %}<div class="bar-row muted"><span>{{ key }}</span><b>0</b></div>{% endif %}
{% endfor %}
</article>
</section>
<section class="panel attention">
<div class="panel-title"><div><p class="eyebrow">FILA DE AÇÃO</p><h2>Atenção necessária</h2></div><a href="/blockers?scope=active&amp;status=OPEN">Ver blockers</a></div>
{% for item in summary.attention_items %}
<a class="list-row attention-row" href="{{ item.link }}"><span><b>{{ item.client or "Cliente não identificado" }}</b><small>{{ item.hostname or item.display_name or "Servidor sem nome" }} · {{ item.problem }}</small>{% if item.group_count %}<small>{{ item.products_affected }} produtos afetados · {{ item.group_count }} blockers abertos · Ver blockers →</small>{% endif %}</span><em class="badge {{ 'priority-' ~ item.priority|lower if item.priority else item.technical_health|lower }}">{{ item.age }}</em></a>
{% else %}<p class="empty-state">Nenhum item requer atenção imediata.</p>{% endfor %}
</section>
<section class="split jobs-overview">
<article class="panel">
<div class="panel-title"><h2>Jobs com falha</h2><a href="/jobs?scope=active&amp;status=FAILED">Ver jobs</a></div>
{% if summary.failed_jobs %}<p class="metric-inline"><strong>{{ summary.failed_jobs }}</strong> jobs aguardam investigação.</p>
<ul class="failed-jobs" aria-label="Falhas recentes (máximo 10)">
{% for job in summary.recent_failed_jobs %}<li class="failed-job"><div class="failed-job-main"><b>{{ job.client or "Cliente não identificado" }}</b><small>{{ job.display_name or "Instalação" }} · {{ job.hostname or "Servidor não informado" }}</small><span class="failed-job-kind">{{ job.kind_label }}</span><small class="error-text job-error-summary" title="{{ job.error or '' }}">{{ job.error or "Sem detalhe de erro" }}</small></div><div class="failed-job-side"><span title="{{ job.finished_at }}">{{ job.finished_age }}</span><small>{{ job.finished_display }}</small><a href="/jobs?scope=active&amp;status=FAILED&amp;job_id={{ job.job_id }}">Ver detalhes</a></div></li>{% endfor %}
</ul>{% else %}<p class="empty-state">Nenhum job com falha.</p>{% endif %}
</article>
<article class="panel">
<div class="panel-title"><h2>Agents desatualizados</h2><a href="/agents?scope=active&amp;version=outdated">Ver servidores</a></div>
{% for item in summary.outdated_agents[:5] %}<a class="list-row" href="/agents/{{ item.agent_id }}"><span><b>{{ item.client or "Cliente não identificado" }}</b><small>{{ item.display_name or "Instalação" }} · {{ item.hostname or "Servidor não informado" }}</small><small>{{ item.agent_version or "Versão não informada" }} → atualização disponível</small></span><em class="badge warning">Desatualizado</em></a>{% else %}<p class="empty-state">Nenhum Agent desatualizado.</p>{% endfor %}
</article>
</section>
{% endblock %}