Corp/backend/templates/search/results.html
Игорь Надеин 8363cbd541 feat: Complete CSS to SCSS migration (100%)
- Migrated all 28 CSS components to SCSS architecture
- Deleted 29 source CSS files (kept only compiled app.css & bootstrap-custom.css)
- Created 30 SCSS component modules in scss/components/
- Cleaned 24 templates from duplicate CSS links
- Updated main.scss with new imports (layout-spacing, spacing-utils, rightbar-calendar)
- Filled empty _navbar.scss with content
- Refactored css/ folder: removed obsolete files, updated README.md
- Created comprehensive documentation (migration complete, quick reference, reports)

Migration Statistics:
- Components migrated: 28 (~4,768 lines SCSS)
- CSS files deleted: 29
- Templates cleaned: 24
- app.css size: 95 KB (compiled from SCSS)
- bootstrap-custom.css: 301 KB
- Total: 396 KB

Phase 6 Complete: 100% SCSS architecture achieved ✅
2026-01-15 13:48:11 +03:00

296 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html" %}
{% load static django_bootstrap5 %}
{% block title %}Поиск{% endblock %}
{% block extra_css %}{% endblock %}
{% block content %}
<div class="container">
<div class="row gx-0">
<div class="col-12">
<!-- Шапка страницы -->
{% include "includes/components/page_header.html" with icon="bi-search" title="Поиск" count=total count_label="Найдено:" search_id="globalSearch" search_placeholder="Фильтр по заголовкам" no_create=True has_filters=True filters_target="searchFilters" filters_template="search/_filters.html" %}
{% if total > 0 %}
{# ===== ПУБЛИКАЦИИ ===== #}
{% if counts.post %}
<div class="card mb-3 section" data-sec="post">
<div class="card-header">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-journal-text"></i></div>
<div class="card-meta flex-grow-1"><h6 class="mb-0 text-secondary">Публикации</h6></div>
</div>
<div class="list-results">
{% for item in results %}
{% if item.model_name == 'post' %}
{% with post=item.object %}
<div class="result-row d-flex align-items-start gap-2 py-2 px-2" data-type="post" data-haystack="{{ post.title|default_if_none:'' }}">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-journal-text"></i></div>
<div class="flex-grow-1 position-relative">
<a href="{% url 'feed:post_detail' post.pk %}" class="card-title text-decoration-none stretched-link">{{ post.title }}</a>
<div class="card-subtitle mt-1 text-secondary">{{ post.created_at|date:"d.m.Y H:i" }}</div>
{% if post.body %}<div class="small mt-1 text-body">{{ post.body|truncatewords:35 }}</div>{% endif %}
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{# ===== СОТРУДНИКИ ===== #}
{% if counts.employee %}
<div class="card mb-3 section" data-sec="employee">
<div class="card-header">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-person-badge"></i></div>
<div class="card-meta flex-grow-1"><h6 class="mb-0 text-secondary">Сотрудники</h6></div>
</div>
<div class="list-results">
{% for item in results %}
{% if item.model_name == 'employee' %}
{% with emp=item.object %}
<div class="result-row d-flex align-items-start gap-2 py-2 px-2" data-type="employee" data-haystack="{{ emp.last_name }} {{ emp.first_name }} {{ emp.patronymic|default_if_none:'' }}">
<div class="card-icon" style="width:44px;height:44px;">
{% if emp.avatar %}<img src="{{ emp.avatar.url }}" alt="">{% else %}<i class="bi-person"></i>{% endif %}
</div>
<div class="flex-grow-1 position-relative">
<a href="{% url 'employees:employee_detail' emp.pk %}" class="card-title text-decoration-none stretched-link">
{{ emp.last_name }} {{ emp.first_name }}{% if emp.patronymic %} {{ emp.patronymic }}{% endif %}
</a>
<div class="card-subtitle mt-1 text-secondary">
{% if emp.position %}{{ emp.position.name }} · {% endif %}
{{ emp.email }}{% if emp.phone_number %} · {{ emp.phone_number }}{% endif %}
</div>
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{# ===== ОТДЕЛЫ ===== #}
{% if counts.department %}
<div class="card mb-3 section" data-sec="department">
<div class="card-header">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-diagram-3"></i></div>
<div class="card-meta flex-grow-1"><h6 class="mb-0 text-secondary">Отделы</h6></div>
</div>
<div class="list-results">
{% for item in results %}
{% if item.model_name == 'department' %}
{% with dept=item.object %}
<div class="result-row d-flex align-items-start gap-2 py-2 px-2" data-type="department" data-haystack="{{ dept.name|default_if_none:'' }}">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-diagram-3"></i></div>
<div class="flex-grow-1 position-relative">
<a href="{% url 'employees:department_detail' dept.pk %}" class="card-title text-decoration-none stretched-link">{{ dept.name }}</a>
<div class="card-subtitle mt-1 text-secondary">
{% if dept.head %}Руководитель: {{ dept.head.last_name }} {{ dept.head.first_name }}{% if dept.head.patronymic %} {{ dept.head.patronymic }}{% endif %}{% endif %}
</div>
{% if dept.description %}<div class="small mt-1 text-body">{{ dept.description|truncatewords:35 }}</div>{% endif %}
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{# ===== ЗАЯВЛЕНИЯ ===== #}
{% if counts.request %}
<div class="card mb-3 section" data-sec="request">
<div class="card-header">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-file-earmark-text"></i></div>
<div class="card-meta flex-grow-1"><h6 class="mb-0 text-secondary">Заявления</h6></div>
</div>
<div class="list-results">
{% for item in results %}
{% if item.model_name == 'request' %}
{% with req=item.object %}
<div class="result-row d-flex align-items-start gap-2 py-2 px-2" data-type="request" data-haystack="{% firstof req.title req.get_type_display '' %}">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-file-earmark-text"></i></div>
<div class="flex-grow-1 position-relative">
<div class="card-title">
{% firstof req.title req.get_type_display "Заявление" %}
</div>
<div class="card-subtitle mt-1 text-secondary">
Автор: {{ req.employee }}{% if req.department %} · Отдел: {{ req.department }}{% endif %} · {{ req.created_at|date:"d.m.Y H:i" }}
</div>
{% if req.comment %}<div class="small mt-1 text-body">{{ req.comment|truncatewords:35 }}</div>{% endif %}
</div>
<div class="ms-2 mt-1">
{% if req.status == 'pending' %}<span class="badge bg-secondary-subtle text-secondary-emphasis border border-secondary-subtle">На рассмотрении</span>
{% elif req.status == 'approved' %}<span class="badge bg-success-subtle text-success-emphasis border border-success-subtle">Одобрено</span>
{% elif req.status == 'rejected' %}<span class="badge bg-danger-subtle text-danger-emphasis border border-danger-subtle">Отклонено</span>
{% elif req.status == 'cancelled' %}<span class="badge bg-dark-subtle text-dark-emphasis border border-dark-subtle">Отменено</span>
{% elif req.status == 'draft' %}<span class="badge bg-light text-body border">Черновик</span>
{% endif %}
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{# ===== ЧАТЫ ===== #}
{% if counts.chat %}
<div class="card mb-3 section" data-sec="chat">
<div class="card-header">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-chat-dots"></i></div>
<div class="card-meta flex-grow-1"><h6 class="mb-0 text-secondary">Чаты</h6></div>
</div>
<div class="list-results">
{% for item in results %}
{% if item.model_name == 'chat' %}
{% with chat=item.object %}
{% firstof chat.name chat.department.name chat.pk as chat_label %}
<div class="result-row d-flex align-items-start gap-2 py-2 px-2" data-type="chat" data-haystack="{{ chat_label }}">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-chat-dots"></i></div>
<div class="flex-grow-1 position-relative">
<a href="{% url 'communications:chat_detail' chat.pk %}" class="card-title text-decoration-none stretched-link">
{% if chat.type == 'global' %}
Глобальный чат
{% elif chat.type == 'department' and chat.department %}
Чат отдела: {{ chat.department.name }}
{% elif chat.type == 'private' %}
{% for u in chat.participants.all %}{% if u != request.user %}{% if not forloop.first %}, {% endif %}{{ u.get_full_name|default:u.username }}{% endif %}{% endfor %}
{% else %}
{{ chat_label }}
{% endif %}
</a>
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{# ===== СООБЩЕНИЯ ===== #}
{% if counts.message %}
<div class="card mb-3 section" data-sec="message">
<div class="card-header">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-chat-left-text"></i></div>
<div class="card-meta flex-grow-1"><h6 class="mb-0 text-secondary">Сообщения</h6></div>
</div>
<div class="list-results">
{% for item in results %}
{% if item.model_name == 'message' %}
{% with msg=item.object %}
{% firstof msg.chat.name msg.chat.department.name msg.chat.pk as msg_chat_label %}
<div class="result-row d-flex align-items-start gap-2 py-2 px-2" data-type="message" data-haystack="{{ msg.content|default_if_none:'' }}">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-chat-left-text"></i></div>
<div class="flex-grow-1 position-relative">
<a href="{% url 'communications:chat_detail' msg.chat.pk %}" class="card-title text-decoration-none stretched-link">
{% if msg.author %}{{ msg.author.get_full_name|default:msg.author.username }}: {% endif %}
{{ msg.content|default:"(вложение)"|truncatechars:120 }}
</a>
<div class="card-subtitle mt-1 text-secondary">
{{ msg.created_at|date:"d.m.Y H:i" }} · Чат: {{ msg_chat_label }}
</div>
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{# ===== СОБЫТИЯ ===== #}
{% if counts.event %}
<div class="card mb-3 section" data-sec="event">
<div class="card-header">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-calendar-event"></i></div>
<div class="card-meta flex-grow-1"><h6 class="mb-0 text-secondary">События</h6></div>
</div>
<div class="list-results">
{% for item in results %}
{% if item.model_name == 'event' %}
{% with ev=item.object %}
{% firstof ev.title ev.name "Событие" as ev_title %}
<div class="result-row d-flex align-items-start gap-2 py-2 px-2" data-type="event" data-haystack="{{ ev_title }}">
<div class="card-icon" style="width:44px;height:44px;"><i class="bi-calendar-event"></i></div>
<div class="flex-grow-1 position-relative">
<div class="card-title">{{ ev_title }}</div>
<div class="card-subtitle mt-1 text-secondary">
{% if ev.start %}Начало: {{ ev.start|date:"d.m.Y H:i" }}
{% elif ev.starts_at %}Начало: {{ ev.starts_at|date:"d.m.Y H:i" }}{% endif %}
{% if ev.location %} · {{ ev.location }}{% endif %}
{% if ev.department %} · {% firstof ev.department.name ev.department " " %}{% endif %}
</div>
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{% else %}
<div class="alert alert-info shadow-sm mt-3">Ничего не найдено.</div>
{% endif %}
</div>
</div>
</div>
<script type="module">
import { initSearchFilter } from "{% static 'js/components/searchFilterHandler.js' %}";
// Инициализация поиска по заголовкам
initSearchFilter({
inputId: 'globalSearch',
clearSelector: '.ios-search-clear',
sectionSelector: '.section',
rowSelector: '.result-row'
});
// Фильтрация по типу через селект
const typeFilter = document.getElementById('searchTypeFilter');
const applyBtn = document.getElementById('applySearchFilter');
const resetBtn = document.getElementById('resetSearchFilter');
const sections = document.querySelectorAll('.section');
function applyTypeFilter() {
const selectedType = typeFilter.value;
sections.forEach(section => {
const sectionType = section.dataset.sec;
if (selectedType === 'all' || sectionType === selectedType) {
section.style.display = '';
} else {
section.style.display = 'none';
}
});
}
function resetFilter() {
typeFilter.value = 'all';
applyTypeFilter();
}
if (applyBtn) {
applyBtn.addEventListener('click', applyTypeFilter);
}
if (resetBtn) {
resetBtn.addEventListener('click', resetFilter);
}
// Применение при изменении селекта
if (typeFilter) {
typeFilter.addEventListener('change', applyTypeFilter);
}
</script>
{% endblock %}