- config_form usava fields.csrfField() (inexistente no 11.0.4) -> erro fatal - token CSRF agora via csrf_token_value (PHP); URL usa textField - compatível com 11.0.0+ Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
135 lines
6.9 KiB
Twig
135 lines
6.9 KiB
Twig
{% import 'components/form/fields_macros.html.twig' as fields %}
|
|
|
|
<form method="post" action="{{ action_url }}">
|
|
<input type="hidden" name="_glpi_csrf_token" value="{{ csrf_token_value }}">
|
|
<input type="hidden" name="id" value="1">
|
|
|
|
{# --- Conexão --- #}
|
|
<div class="card mb-3">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h4 class="card-title mb-0">
|
|
<i class="ti ti-plug-connected me-1"></i>{{ __('Conexão com o Redmine', 'redmine') }}
|
|
</h4>
|
|
<button type="submit" name="sync" value="1" class="btn btn-sm btn-outline-secondary">
|
|
<i class="ti ti-refresh me-1"></i>{{ __('Sincronizar Metadados', 'redmine') }}
|
|
</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
{{ fields.textField('redmine_url', redmine_url, __('URL do Redmine', 'redmine'), {
|
|
'helper': 'https://redmine.exemplo.com.br'
|
|
}) }}
|
|
{{ fields.passwordField('api_key', '', __('Chave de API (Admin)', 'redmine'), {
|
|
'helper': has_key
|
|
? __('Deixe em branco para manter a chave atual', 'redmine')
|
|
: __('Chave de API de um usuário administrador do Redmine', 'redmine')
|
|
}) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# --- Valores padrão da issue --- #}
|
|
<div class="card mb-3">
|
|
<div class="card-header">
|
|
<h4 class="card-title mb-0"><i class="ti ti-settings me-1"></i>{{ __('Valores padrão da tarefa (issue) Redmine', 'redmine') }}</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
{% if not has_metadata %}
|
|
<div class="alert alert-warning">{{ __('Salve a URL e a chave e clique em "Sincronizar Metadados" para carregar as opções.', 'redmine') }}</div>
|
|
{% endif %}
|
|
<div class="row">
|
|
{{ fields.dropdownArrayField('default_tracker_id', default_tracker_id, tracker_options, __('Tipo (Tracker) padrão', 'redmine'), {'display_emptychoice': true}) }}
|
|
{{ fields.dropdownArrayField('default_priority_id', default_priority_id, priority_options, __('Prioridade padrão', 'redmine'), {'display_emptychoice': true}) }}
|
|
{{ fields.dropdownArrayField('default_activity_id', default_activity_id, activity_options, __('Atividade padrão (lançamento de tempo)', 'redmine'), {'display_emptychoice': true}) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# --- Autores e observadores --- #}
|
|
<div class="card mb-3">
|
|
<div class="card-header">
|
|
<h4 class="card-title mb-0"><i class="ti ti-users me-1"></i>{{ __('Autores e observadores', 'redmine') }}</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-info">
|
|
{{ __('O autor (técnico atribuído) é adicionado automaticamente como membro do projeto Redmine com o papel abaixo, para permitir a impersonation.', 'redmine') }}
|
|
</div>
|
|
<div class="row">
|
|
{{ fields.dropdownArrayField('default_role_id', default_role_id, role_options, __('Papel padrão para membros (auto-membership)', 'redmine'), {'display_emptychoice': true}) }}
|
|
{{ fields.dropdownArrayField('default_watcher_ids', '', redmine_user_options, __('Observadores padrão', 'redmine'), {
|
|
'multiple': true,
|
|
'values': default_watcher_ids
|
|
}) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# --- Mapa de status --- #}
|
|
<div class="card mb-3">
|
|
<div class="card-header">
|
|
<h4 class="card-title mb-0"><i class="ti ti-arrows-exchange me-1"></i>{{ __('Mapa de status: Chamado GLPI → Issue Redmine', 'redmine') }}</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
{% for sid, slabel in glpi_ticket_statuses %}
|
|
{{ fields.dropdownArrayField('status_map[' ~ sid ~ ']', attribute(status_map, sid)|default(''), status_options, slabel, {'display_emptychoice': true}) }}
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-end mb-3">
|
|
<button type="submit" name="update" value="1" class="btn btn-primary">
|
|
<i class="ti ti-device-floppy me-1"></i>{{ _x('button', 'Save') }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
{# --- Mapeamento de usuários (overrides) — fora do form principal --- #}
|
|
<div class="card mb-3">
|
|
<div class="card-header">
|
|
<h4 class="card-title mb-0"><i class="ti ti-user-cog me-1"></i>{{ __('Mapeamento de usuários (GLPI → Redmine)', 'redmine') }}</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-info">
|
|
{{ __('Usuários com o mesmo e-mail nos dois sistemas são associados automaticamente. Use a tabela abaixo apenas para exceções (e-mails diferentes).', 'redmine') }}
|
|
</div>
|
|
|
|
<table class="table table-sm align-middle">
|
|
<thead><tr>
|
|
<th>{{ __('Usuário GLPI', 'redmine') }}</th>
|
|
<th>{{ __('Usuário Redmine', 'redmine') }}</th>
|
|
<th class="text-end">{{ _x('button', 'Delete') }}</th>
|
|
</tr></thead>
|
|
<tbody>
|
|
{% for m in usermap %}
|
|
<tr>
|
|
<td>{{ m.glpi_name }}</td>
|
|
<td>{{ m.redmine_name }}</td>
|
|
<td class="text-end">
|
|
<form method="post" action="{{ action_url }}" class="d-inline">
|
|
<input type="hidden" name="_glpi_csrf_token" value="{{ csrf_token_value }}">
|
|
<input type="hidden" name="del_usermap" value="{{ m.id }}">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger"><i class="ti ti-trash"></i></button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr><td colspan="3" class="text-muted">{{ __('Nenhum override cadastrado.', 'redmine') }}</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
<form method="post" action="{{ action_url }}" class="mt-3">
|
|
<input type="hidden" name="_glpi_csrf_token" value="{{ csrf_token_value }}">
|
|
<input type="hidden" name="add_usermap" value="1">
|
|
<div class="row">
|
|
{{ fields.dropdownField('User', 'override_users_id', 0, __('Usuário GLPI', 'redmine'), {'display_emptychoice': true}) }}
|
|
{{ fields.dropdownArrayField('override_redmine_user_id', '', redmine_user_options, __('Usuário Redmine', 'redmine'), {'display_emptychoice': true}) }}
|
|
</div>
|
|
<div class="text-end">
|
|
<button type="submit" class="btn btn-outline-primary"><i class="ti ti-plus me-1"></i>{{ _x('button', 'Add') }}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|