Tenant gains source (LOCAL|GTI_GERENCIADOR), external_client_id, external_code, active and synced_at (migration 0024). central/app/client_sync.py fetches from the panel's new GET /internal/fiscal/clients (dedicated bearer token, never MySQL credentials) and upserts Tenant rows, never touching a LOCAL row. /agents/new now offers only active GTI_GERENCIADOR tenants, with a client-side search box; the POST validates the same rule server-side, not just in the dropdown. central/scripts/sync_clients_from_gerenciador.py is the operator-run sync + reconciliation report. GTI_FISCAL_VERSION/AGENT_VERSION bumped to 1.1.2 (release/VERSION single source of truth), incorporating the installation_id persistence fix. Rebuilt the EXE installer trio at 1.1.2 (scripts/build_windows_installer.ps1). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
44 lines
2.4 KiB
HTML
44 lines
2.4 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Nova instalação | GTI Fiscal{% endblock %}
|
|
{% block content %}
|
|
<div class="page-heading"><div><p class="eyebrow">DISTRIBUIÇÃO DO AGENT</p><h1>Nova instalação</h1><p class="muted">Cria uma instalação pendente; o pacote e o vínculo de enrollment só existem depois de gerados aqui.</p></div><div><a href="/agents" class="secondary">Voltar</a></div></div>
|
|
<section class="panel" style="max-width:560px">
|
|
{% if error %}<p class="error" role="alert">{{ error }}</p>{% endif %}
|
|
{% if not releases %}
|
|
<p class="muted">Nenhuma versão do Agent está publicada ainda. Publique uma release primeiro (<code>python central/scripts/publish_agent_release.py</code>) e ela aparecerá aqui.</p>
|
|
{% elif not tenants %}
|
|
<p class="muted">Nenhum cliente ativo encontrado no GTI Gerenciador. Verifique o cadastro por lá, ou rode a sincronização (<code>python central/scripts/sync_clients_from_gerenciador.py</code>).</p>
|
|
{% else %}
|
|
<form method="post" action="/agents/new">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<label>Cliente
|
|
<input type="text" id="filtro-cliente" placeholder="Buscar cliente..." autocomplete="off" oninput="filtrarClientes(this.value)">
|
|
<select name="tenant_id" id="select-cliente" size="8" required>
|
|
{% for tenant in tenants %}<option value="{{ tenant.id }}">{{ tenant.name }}</option>{% endfor %}
|
|
</select>
|
|
</label>
|
|
<label>Nome da instalação
|
|
<input name="display_name" placeholder="ex. Servidor Principal" maxlength="160" required>
|
|
</label>
|
|
<label>Hostname esperado (opcional)
|
|
<input name="expected_hostname" placeholder="ex. SRV-CONSTRUCAO" maxlength="255">
|
|
</label>
|
|
<label>Versão do Agent
|
|
<select name="release_id" required>
|
|
{% for release in releases %}<option value="{{ release.id }}" {% if loop.first %}selected{% endif %}>{{ release.version }} ({{ release.platform }}/{{ release.architecture }})</option>{% endfor %}
|
|
</select>
|
|
</label>
|
|
<p><button type="submit">Criar instalação</button></p>
|
|
</form>
|
|
<script>
|
|
function filtrarClientes(termo) {
|
|
var alvo = termo.trim().toLowerCase();
|
|
document.querySelectorAll("#select-cliente option").forEach(function (opcao) {
|
|
opcao.hidden = alvo.length > 0 && opcao.textContent.toLowerCase().indexOf(alvo) === -1;
|
|
});
|
|
}
|
|
</script>
|
|
{% endif %}
|
|
</section>
|
|
{% endblock %}
|