Files
ACORE/templates/pages/ad_ou_manage.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

127 lines
9.0 KiB
HTML

<div class="page-content" id="ad-ou-manage-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;">Управління OU та їх прив'язкою до відділів (Directory.ad_ou_dn)</p>
</div>
<a href="#" class="btn btn-primary"
hx-get="/ad-ou-manage/" hx-target="#main-content" hx-push-url="/ad-ou-manage/" 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="ou" %}
{% if notice %}
<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;">
{{ notice }}
</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 %}
<!-- Создание OU -->
<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;">Нова OU</h3>
</div>
<form hx-post="/ad-ou-manage/" hx-target="#main-content" hx-indicator="#loader"
style="padding:1.25rem 1.5rem; display:flex; align-items:flex-end; gap:0.75rem; flex-wrap:wrap;">
{% csrf_token %}
<input type="hidden" name="action" value="create">
<div>
<label style="display:block; font-size:0.8125rem; color:var(--color-muted-foreground); margin-bottom:0.25rem;">Назва</label>
<input type="text" name="name" required class="input" style="max-width:16rem;">
</div>
<div>
<label style="display:block; font-size:0.8125rem; color:var(--color-muted-foreground); margin-bottom:0.25rem;">Батьківська OU</label>
<select name="parent_dn" class="input" style="max-width:26rem;">
<option value="{{ root_ou }}">{{ root_ou }} (корінь)</option>
{% for ou in ous %}
<option value="{{ ou.dn }}">{{ ou.dn }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary" style="font-size:0.8125rem;">Створити</button>
</form>
</div>
<!-- Список OU -->
<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);">
<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;">OU в домені</h3>
<p style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ ous_page.paginator.count }} організаційних юнітів</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;">OU</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:right; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Дії</th>
</tr>
</thead>
<tbody>
{% for ou in ous_page %}
<tr style="border-bottom:1px solid var(--color-border);" class="tr-hover">
<td style="padding:0.875rem 1rem; vertical-align:middle;">
<div style="font-weight:500; color:var(--color-card-foreground);">{{ ou.name }}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem; max-width:24rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="{{ ou.dn }}">{{ ou.dn }}</div>
</td>
<td style="padding:0.875rem 1rem; vertical-align:middle;">
{% if ou.department %}
<span style="display:inline-flex; align-items:center; padding:0.125rem 0.625rem; border-radius:9999px; font-size:0.75rem; font-weight:500; background:rgba(37,99,235,0.1); color:#2563eb;">{{ ou.department }}</span>
{% else %}
<span style="color:var(--color-muted-foreground); font-size:0.8125rem;">—</span>
{% endif %}
</td>
<td style="padding:0.875rem 1rem; vertical-align:middle;">
<form hx-post="/ad-ou-manage/" hx-target="#main-content" hx-indicator="#loader" style="display:flex; align-items:center; gap:0.5rem; margin:0;">
{% csrf_token %}
<input type="hidden" name="action" value="rename">
<input type="hidden" name="dn" value="{{ ou.dn }}">
<input type="text" name="new_name" value="{{ ou.name }}" class="input" style="font-size:0.8125rem; padding:0.3rem 0.5rem; height:auto; max-width:12rem;">
<button type="submit" class="btn btn-ghost" style="font-size:0.8125rem; padding:0.3rem 0.75rem;">Перейменувати</button>
</form>
</td>
<td style="padding:0.875rem 1rem; vertical-align:middle; text-align:right; white-space:nowrap;">
<form hx-post="/ad-ou-manage/" hx-target="#main-content" hx-indicator="#loader"
hx-confirm="Видалити OU «{{ ou.name }}»? Дія доступна лише для порожніх OU."
style="display:inline; margin:0;">
{% csrf_token %}
<input type="hidden" name="action" value="delete">
<input type="hidden" name="dn" value="{{ ou.dn }}">
<button type="submit" class="btn btn-ghost" style="font-size:0.8125rem; padding:0.3rem 0.75rem; color:var(--color-destructive);">Видалити</button>
</form>
</td>
</tr>
{% empty %}
<tr>
<td colspan="4" style="padding:2rem; text-align:center; color:var(--color-muted-foreground);">OU не знайдено</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include "partials/pagination.html" with page=ous_page base_url="/ad-ou-manage/" page_param="ou_page" size_param="ou_per_page" item_label="OU" %}
</div>
<p style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:1rem;">
Щоб прив'язати OU до відділу, вкажіть її DN у полі «OU в Active Directory» картки відділу (Довідники → Відділи).
При синхронізації співробітник переноситься в OU свого відділу автоматично.
</p>
</div>