Files
ACORE/templates/pages/ad_import.html
T
lokses 81dee5cba2 Интеграции AD/Mattermost: OU-управление, импорт, шифрование токенов
- ad_connector: страницы управления OU и импорта из AD, поле ad_ou_dn
  в Directory, ADSyncLog; расширение sync-сервиса и клиента
- mattermost_connector: personal access token шифруется (Fernet,
  token_service), бот-сервис, команды создания бота и синхронизации;
  публикация постов в каналы. Тесты (19)
- core: ConnectorConfig, Directory (ad_ou_dn), обновления админки

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 17:32:26 +03:00

126 lines
8.9 KiB
HTML

<div class="page-content" id="ad-import-page">
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:1rem; gap:1rem; flex-wrap:wrap;">
<div>
<h1 style="font-size:1.25rem; font-weight:500; color:var(--color-foreground);">Імпорт співробітників з Active Directory</h1>
<p style="font-size:0.875rem; color:var(--color-muted-foreground); margin-top:0.25rem;">Облікові записи AD, яким ще не відповідає жоден співробітник у системі</p>
</div>
<a href="#" class="btn btn-primary"
hx-get="/ad-import/" hx-target="#main-content" hx-push-url="/ad-import/" hx-indicator="#loader">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/>
</svg>
Оновити
</a>
</div>
{% include "partials/ad_connector_tabs.html" with active="import" %}
{% if imported %}
<div style="background:rgba(22,163,74,0.08); border:1px solid rgba(22,163,74,0.3); border-radius:0.75rem; padding:1rem 1.25rem; margin-bottom:1.5rem; font-size:0.875rem; color:#16a34a;">
Імпортовано: {{ imported|join:", " }}
</div>
{% endif %}
{% if errors %}
<div style="background:color-mix(in srgb, var(--color-destructive) 8%, transparent); border:1px solid color-mix(in srgb, var(--color-destructive) 30%, transparent); border-radius:0.75rem; padding:1rem 1.25rem; margin-bottom:1.5rem; font-size:0.875rem; color:var(--color-destructive);">
{% for err in errors %}<div>{{ err }}</div>{% endfor %}
</div>
{% endif %}
{% if ad_error %}
<div style="background:color-mix(in srgb, var(--color-destructive) 8%, transparent); border:1px solid color-mix(in srgb, var(--color-destructive) 30%, transparent); border-radius:0.75rem; padding:1rem 1.25rem; margin-bottom:1.5rem; display:flex; align-items:center; gap:0.75rem;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--color-destructive)" stroke-width="2" style="flex-shrink:0;">
<circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/>
</svg>
<div style="font-size:0.875rem; color:var(--color-destructive);">{{ ad_error }}</div>
</div>
{% endif %}
<form hx-post="/ad-import/" hx-target="#main-content" hx-indicator="#loader">
{% csrf_token %}
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0 / 0.05); margin-bottom:1.5rem; padding:1.25rem 1.5rem; display:flex; align-items:flex-end; gap:1rem; flex-wrap:wrap;">
<div>
<label style="display:block; font-size:0.8125rem; color:var(--color-muted-foreground); margin-bottom:0.25rem;">Дата прийняття</label>
<input type="date" name="hire_date" value="{{ today }}" class="input" style="max-width:12rem;">
</div>
<div>
<label style="display:block; font-size:0.8125rem; color:var(--color-muted-foreground); margin-bottom:0.25rem;">Локація (офіс)</label>
<select name="user_location" class="input" style="max-width:20rem;">
<option value="">— оберіть —</option>
{% for loc in locations %}
<option value="{{ loc.pk }}">{{ loc.address|default:loc.pk }}</option>
{% endfor %}
</select>
</div>
<div style="font-size:0.8125rem; color:var(--color-muted-foreground);">
Однакові для всього пакету імпорту. Відділ і посаду можна вказати окремо для кожного рядка.
</div>
</div>
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0 / 0.05); margin-bottom:1.5rem;">
<div style="padding:1.25rem 1.5rem; border-bottom:1px solid var(--color-border);">
<h3 style="font-weight:600; color:var(--color-card-foreground); font-size:0.9375rem;">Кандидати на імпорт</h3>
<p style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ candidates_total }} облікових записів AD без співробітника</p>
</div>
<div style="overflow-x:auto;">
<table style="width:100%; border-collapse:collapse; font-size:0.875rem;">
<thead>
<tr style="border-bottom:1px solid var(--color-border);">
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;"></th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Обліковий запис</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Відділ</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Посада</th>
</tr>
</thead>
<tbody>
{% for candidate in candidates %}
<tr style="border-bottom:1px solid var(--color-border);" class="tr-hover">
<td style="padding:0.875rem 1rem; vertical-align:middle;">
<input type="checkbox" name="import_{{ candidate.username }}" value="1">
</td>
<td style="padding:0.875rem 1rem; vertical-align:middle;">
<div style="font-weight:500; color:var(--color-card-foreground);">
{{ candidate.last_name }} {{ candidate.first_name }}
{% if candidate.is_disabled %}
<span style="display:inline-flex; align-items:center; padding:0.125rem 0.5rem; border-radius:9999px; font-size:0.6875rem; font-weight:500; background:var(--color-muted); color:var(--color-muted-foreground); margin-left:0.375rem;">Відключений</span>
{% endif %}
</div>
<div style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ candidate.username }} · {{ candidate.email }}</div>
</td>
<td style="padding:0.875rem 1rem; vertical-align:middle;">
<select name="department_{{ candidate.username }}" class="input" style="font-size:0.8125rem; padding:0.3rem 0.5rem; height:auto; max-width:14rem;">
<option value="">— оберіть —</option>
{% for dep in departments %}
<option value="{{ dep.pk }}">{{ dep.name }}</option>
{% endfor %}
</select>
</td>
<td style="padding:0.875rem 1rem; vertical-align:middle;">
<select name="post_{{ candidate.username }}" class="input" style="font-size:0.8125rem; padding:0.3rem 0.5rem; height:auto; max-width:14rem;">
<option value="">— оберіть —</option>
{% for post in posts %}
<option value="{{ post.pk }}">{{ post.name }}</option>
{% endfor %}
</select>
</td>
</tr>
{% empty %}
<tr>
<td colspan="4" style="padding:2rem; text-align:center; color:var(--color-muted-foreground);">Немає нових облікових записів для імпорту</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include "partials/pagination.html" with page=candidates base_url="/ad-import/" page_param="candidates_page" size_param="candidates_per_page" item_label="кандидатів" %}
</div>
{% if candidates %}
<button type="submit" class="btn btn-primary">Імпортувати відмічені</button>
{% endif %}
</form>
</div>