- ajax/template_test.php: action=preview (render com sampleContext) e
action=dryrun (cria+apaga objeto de teste no Redmine, traduz erros 422
em dicas acionáveis; issue temporária para log_time/update_status)
- RedmineApi::rawRequest (código+corpo crus) e TemplateEngine::sampleContext
- UI: botão "Testar" + painel por card (preview sempre; teste real opt-in
com seletor de projeto alvo), via fetch com X-Glpi-Csrf-Token
- validado E2E por HTTP: preview, dry-run cria/deleta (204), render inválido
capturado, tradução de 422; sem resíduo de teste no Redmine
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Feedback de UX: o admin precisa saber O QUE o Redmine espera, não só os
valores. Cada card do editor ganha a tabela colapsável "Campos que o
Redmine espera" (campos padrão da operação + custom fields do ambiente,
com obrigatoriedade e valores possíveis) — clicar num campo adiciona a
linha com o caminho pronto. A paleta vira explicitamente o "DE" (variáveis
do GLPI) e ganha chamado.tecnico e tarefa.autor (texto; autoria real segue
automática via impersonation). Sync passa a cachear custom_fields de todos
os tipos (issue/time_entry/project).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- seção "Templates de Payload (avançado)" no formconfig: card por operação,
editor linha-a-linha (flatten/unflatten em JS puro) com toggle Ver JSON,
Gerar template (seed + CFs descobertos), ativar/desativar
- paleta de variáveis clicável (copia tag) + referência do Redmine do ambiente
(trackers/status/prioridades/atividades/custom fields com valores)
- buildFormContext (form.*) e wiring do create_project nos dois controllers,
com fallback 1.x em erro de render
- validado: render da UI (4 cards + paleta + JS) e E2E create_project via
template no Redmine dev (tipos nativos, identifier minúsculo, parent, trackers)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- docs/DESIGN-2.0.md: decisões fechadas (tags PT, editor linha-a-linha,
escopo global, dry-run com preview) e arquitetura Motor x Template
- PluginRedmineTemplateengine: render mustache-like ({{ var | filtro }}),
regra de tipos (tag inteira = tipo nativo), lookup indexado
(map.status[chamado.status]), filtros (truncar, sem_html, minusculo,
identificador, padrao), prune de nulls, seeds 1.x-equivalentes e
descoberta de custom fields obrigatórios
- tabela glpi_plugin_redmine_templates (operation único, is_active)
- wiring com precedência de template + fallback no render em
create_issue, log_time e update_status
- validado: 12/12 unit + E2E (template ativo cria issue/tempo; template
quebrado cai no motor 1.x sem perder lançamento)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>