dashboard: проверка доступности виджетов и плиток быстрого доступа
Виджеты теперь могут требовать доступ к разделу портала (required_section). Недоступный виджет не отдаётся и не предлагается в настройке — даже если остался в сохранённой раскладке или в наборе по умолчанию; save_layout отбрасывает недоступные ключи (защита от подмены). Виджет «Метрики» (общекорпоративная сводка) требует доступа к разделу «Отчёты». Плитки в «Быстром доступе» скрываются по can_section (Документы, Задачи, Календарь, Сотрудники) — как email и справочники ранее; остаются только разделы, доступные пользователю. - core/dashboard.py: required_section, widget_allowed, accessible_keys; фильтрация в resolve/customize/save - quick_access.html: плитки под can_section - tests: 6 тестов доступности (скрытие/показ, отбрасывание, ре-фильтр) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user|can_section:'documents' %}
|
||||
<a href="/documents/" hx-get="/documents/" hx-target="#main-content" hx-push-url="/documents/" hx-indicator="#loader" class="li-hover" style="display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 0.875rem 0.25rem; border-radius: 0.5rem; text-decoration: none; cursor: pointer; transition: background 150ms;">
|
||||
<div style="width: 2.5rem; height: 2.5rem; border-radius: 0.625rem; background: hsl(270 60% 55% / 0.12); color: hsl(270 60% 45%); display: flex; align-items: center; justify-content: center;">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@@ -27,7 +28,9 @@
|
||||
</div>
|
||||
<span style="font-size: 0.6875rem; color: var(--color-foreground); text-align: center; line-height: 1.3;">{% trans "Документы" %}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user|can_section:'tasks' %}
|
||||
<a href="/tasks/" hx-get="/tasks/" hx-target="#main-content" hx-push-url="/tasks/" hx-indicator="#loader" class="li-hover" style="display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 0.875rem 0.25rem; border-radius: 0.5rem; text-decoration: none; cursor: pointer; transition: background 150ms;">
|
||||
<div style="width: 2.5rem; height: 2.5rem; border-radius: 0.625rem; background: hsl(152 55% 45% / 0.12); color: hsl(152 55% 35%); display: flex; align-items: center; justify-content: center;">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@@ -37,7 +40,9 @@
|
||||
</div>
|
||||
<span style="font-size: 0.6875rem; color: var(--color-foreground); text-align: center; line-height: 1.3;">{% trans "Задачи" %}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user|can_section:'calendar' %}
|
||||
<a href="/calendar/" hx-get="/calendar/" hx-target="#main-content" hx-push-url="/calendar/" hx-indicator="#loader" class="li-hover" style="display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 0.875rem 0.25rem; border-radius: 0.5rem; text-decoration: none; cursor: pointer; transition: background 150ms;">
|
||||
<div style="width: 2.5rem; height: 2.5rem; border-radius: 0.625rem; background: hsl(38 92% 50% / 0.12); color: hsl(38 80% 35%); display: flex; align-items: center; justify-content: center;">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@@ -46,6 +51,7 @@
|
||||
</div>
|
||||
<span style="font-size: 0.6875rem; color: var(--color-foreground); text-align: center; line-height: 1.3;">{% trans "Календарь" %}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user|can_section:'databases' %}
|
||||
<a href="/databases/" hx-get="/databases/" hx-target="#main-content" hx-push-url="/databases/" hx-indicator="#loader" class="li-hover" style="display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 0.875rem 0.25rem; border-radius: 0.5rem; text-decoration: none; cursor: pointer; transition: background 150ms;">
|
||||
@@ -58,6 +64,7 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user|can_section:'hr_portal' %}
|
||||
<a href="/hr-portal/" hx-get="/hr-portal/" hx-target="#main-content" hx-push-url="/hr-portal/" hx-indicator="#loader" class="li-hover" style="display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 0.875rem 0.25rem; border-radius: 0.5rem; text-decoration: none; cursor: pointer; transition: background 150ms;">
|
||||
<div style="width: 2.5rem; height: 2.5rem; border-radius: 0.625rem; background: hsl(174 55% 42% / 0.12); color: hsl(174 55% 35%); display: flex; align-items: center; justify-content: center;">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
@@ -68,6 +75,7 @@
|
||||
</div>
|
||||
<span style="font-size: 0.6875rem; color: var(--color-foreground); text-align: center; line-height: 1.3;">{% trans "Сотрудники" %}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<a href="/it-support/" hx-get="/it-support/" hx-target="#main-content" hx-push-url="/it-support/" hx-indicator="#loader" class="li-hover" style="display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 0.875rem 0.25rem; border-radius: 0.5rem; text-decoration: none; cursor: pointer; transition: background 150ms;">
|
||||
<div style="width: 2.5rem; height: 2.5rem; border-radius: 0.625rem; background: hsl(152 55% 45% / 0.12); color: hsl(152 55% 35%); display: flex; align-items: center; justify-content: center;">
|
||||
|
||||
Reference in New Issue
Block a user