Files
ACORE/templates/pages/dashboard_widgets/quick_access.html
T
lokses 24331df462 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>
2026-09-21 19:02:48 +03:00

92 lines
8.3 KiB
HTML

{% load common_tags %}
{% load i18n %}
<div class="dashboard-widget" data-widget="quick_access" 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;">{% trans "Быстрый доступ" %}</h3>
<p style="font-size: 0.8125rem; color: var(--color-muted-foreground); margin-top: 0.125rem;">{% trans "Полезные ссылки и инструменты" %}</p>
</div>
<div style="padding: 1.25rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr)); gap: 0.5rem;">
{% if request.user|can_section:'email' %}
<a href="/email/" hx-get="/email/" hx-target="#main-content" hx-push-url="/email/" 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(205 80% 55% / 0.12); color: hsl(205 80% 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">
<rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/>
</svg>
</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:'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">
<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/>
<path d="M14 2v4a2 2 0 0 0 2 2h4"/>
</svg>
</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">
<rect width="8" height="4" x="8" y="2" rx="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/>
<path d="m9 14 2 2 4-4"/>
</svg>
</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">
<rect width="18" height="18" x="3" y="4" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/>
</svg>
</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;">
<div style="width: 2.5rem; height: 2.5rem; border-radius: 0.625rem; background: hsl(205 80% 55% / 0.12); color: hsl(205 80% 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">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
</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:'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">
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>
</svg>
</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;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 18v-6a9 9 0 0 1 18 0v6"/>
<path d="M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z"/>
</svg>
</div>
<span style="font-size: 0.6875rem; color: var(--color-foreground); text-align: center; line-height: 1.3;">{% trans "Поддержка IT" %}</span>
</a>
</div>
</div>