5800f79eec
В /documents/ добавлено дерево департаментов, права view/edit через DocumentAccessGrant и выдача доступа сотрудникам/отделам/группам. Co-authored-by: Cursor <cursoragent@cursor.com>
123 lines
7.2 KiB
HTML
123 lines
7.2 KiB
HTML
{% load i18n %}
|
|
<div class="docs-acl" style="border:1px solid var(--color-border); border-radius:0.5rem; padding:0.75rem; margin-top:0.75rem; background:var(--color-muted);">
|
|
<div style="display:flex; align-items:center; gap:0.5rem; margin-bottom:0.5rem;">
|
|
<div style="font-weight:600; font-size:0.8125rem; flex:1;">
|
|
{% if is_folder %}{% trans "Права на папку" %}{% else %}{% trans "Права на файл" %}{% endif %}
|
|
<span style="font-weight:400; color:var(--color-muted-foreground);">· {{ path|default:"«корінь»" }}</span>
|
|
</div>
|
|
<button type="button" class="nc-file-act" onclick="document.getElementById('docs-acl-panel').innerHTML=''">{% trans "Закрити" %}</button>
|
|
</div>
|
|
|
|
{% if grants %}
|
|
<table style="width:100%; border-collapse:collapse; font-size:0.75rem; margin-bottom:0.75rem; background:var(--color-card); border-radius:0.375rem;">
|
|
<tbody>
|
|
{% for g in grants %}
|
|
<tr style="border-bottom:1px solid var(--color-border);">
|
|
<td style="padding:0.4rem 0.5rem;">
|
|
{% if g.employee %}{{ g.employee.get_full_name|default:g.employee }}
|
|
{% elif g.grant_department %}{% trans "Відділ" %}: {{ g.grant_department.name }}
|
|
{% elif g.group %}{% trans "Група" %}: {{ g.group.name }}{% endif %}
|
|
</td>
|
|
<td style="padding:0.4rem 0.5rem; white-space:nowrap;">
|
|
{% if g.level == 'edit' %}{% trans "редагування" %}{% else %}{% trans "перегляд" %}{% endif %}
|
|
</td>
|
|
<td style="padding:0.4rem 0.5rem; text-align:right;">
|
|
<form method="post" action="/documents/acl/revoke/"
|
|
hx-post="/documents/acl/revoke/" hx-target="#docs-acl-panel" hx-swap="innerHTML"
|
|
style="display:inline;">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="grant_id" value="{{ g.pk }}">
|
|
<input type="hidden" name="section" value="{{ section.key }}">
|
|
<input type="hidden" name="path" value="{{ sub }}">
|
|
{% if section.department_id %}<input type="hidden" name="dept" value="{{ section.department_id }}">{% endif %}
|
|
{% if name %}<input type="hidden" name="name" value="{{ name }}">{% endif %}
|
|
<button type="submit" class="nc-file-act nc-file-act-danger">{% trans "Забрати" %}</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-bottom:0.5rem;">
|
|
{% trans "Явних прав ще немає (діють правила за замовчуванням)." %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<form method="post" action="/documents/acl/grant/"
|
|
hx-post="/documents/acl/grant/" hx-target="#docs-acl-panel" hx-swap="innerHTML"
|
|
class="docs-acl-form" style="display:flex; flex-direction:column; gap:0.65rem;">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="section" value="{{ section.key }}">
|
|
<input type="hidden" name="path" value="{{ sub }}">
|
|
{% if section.department_id %}<input type="hidden" name="dept" value="{{ section.department_id }}">{% endif %}
|
|
{% if name %}<input type="hidden" name="name" value="{{ name }}">{% endif %}
|
|
|
|
<div style="display:flex; flex-wrap:wrap; gap:0.5rem; align-items:center;">
|
|
<span style="font-size:0.75rem; color:var(--color-muted-foreground);">{% trans "Кому" %}:</span>
|
|
<label style="font-size:0.75rem; display:inline-flex; align-items:center; gap:0.25rem; cursor:pointer;">
|
|
<input type="radio" name="subject_type" value="employee" checked
|
|
onchange="docsAclSubjectSwitch(this.form, this.value)"> {% trans "Співробітники" %}
|
|
</label>
|
|
<label style="font-size:0.75rem; display:inline-flex; align-items:center; gap:0.25rem; cursor:pointer;">
|
|
<input type="radio" name="subject_type" value="department"
|
|
onchange="docsAclSubjectSwitch(this.form, this.value)"> {% trans "Відділ" %}
|
|
</label>
|
|
<label style="font-size:0.75rem; display:inline-flex; align-items:center; gap:0.25rem; cursor:pointer;">
|
|
<input type="radio" name="subject_type" value="group"
|
|
onchange="docsAclSubjectSwitch(this.form, this.value)"> {% trans "Група" %}
|
|
</label>
|
|
</div>
|
|
|
|
<div data-acl-subj="employee">
|
|
{% include 'partials/people-picker-field.html' with label="Співробітники" field_name='employee_ids' options=employee_options selected_ids=empty_ids placeholder="+ Додати співробітника…" %}
|
|
</div>
|
|
|
|
<div data-acl-subj="department" style="display:none;">
|
|
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Відділ-отримувач" %}</label>
|
|
<div class="searchable-select" data-placeholder="{% trans 'Пошук відділу…' %}">
|
|
<select name="grant_department_id" hidden>
|
|
<option value="">—</option>
|
|
{% for d in department_options %}
|
|
<option value="{{ d.pk }}">{{ d.label }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div data-acl-subj="group" style="display:none;">
|
|
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Група" %}</label>
|
|
<div class="searchable-select" data-placeholder="{% trans 'Пошук групи…' %}">
|
|
<select name="group_id" hidden>
|
|
<option value="">—</option>
|
|
{% for g in group_options %}
|
|
<option value="{{ g.pk }}">{{ g.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display:flex; flex-wrap:wrap; gap:0.5rem; align-items:flex-end;">
|
|
<label style="font-size:0.75rem;">
|
|
{% trans "Рівень" %}
|
|
<select name="level" class="input" style="display:block; font-size:0.8125rem; margin-top:0.2rem; min-width:9rem;">
|
|
<option value="view">{% trans "Перегляд" %}</option>
|
|
<option value="edit">{% trans "Редагування" %}</option>
|
|
</select>
|
|
</label>
|
|
<button type="submit" class="btn btn-primary" style="font-size:0.8125rem;">{% trans "Видати" %}</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
if (typeof initPeoplePickers === 'function') initPeoplePickers(document.getElementById('docs-acl-panel'));
|
|
if (typeof initSearchableSelects === 'function') initSearchableSelects(document.getElementById('docs-acl-panel'));
|
|
})();
|
|
function docsAclSubjectSwitch(form, value) {
|
|
form.querySelectorAll('[data-acl-subj]').forEach(function (el) {
|
|
el.style.display = el.getAttribute('data-acl-subj') === value ? '' : 'none';
|
|
});
|
|
}
|
|
</script>
|