fix: show employee news once in a collapsed section
This commit is contained in:
1 parent
fd3008dfde
commit
cdf879fdf5
7 files changed
+72
-11
No files matched your search
@@ -281,6 +281,20 @@
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.employee-card__news-toggle {
|
||||
min-height: 44px;
|
||||
align-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.employee-card__news-toggle .employee-section__title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.employee-card__section--news[open] .employee-card__news-toggle {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.employee-card__meta {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
|
||||
@@ -106,8 +106,8 @@
|
||||
{% endif %}
|
||||
|
||||
{% if employee_view.news_links %}
|
||||
<section class="employee-card__section">
|
||||
<h3 class="employee-section__title">В новостях</h3>
|
||||
<details class="employee-card__section employee-card__section--news">
|
||||
<summary class="employee-card__news-toggle"><h3 class="employee-section__title">В новостях</h3></summary>
|
||||
<ul class="employee-card__list">
|
||||
{% for news in employee_view.news_links %}
|
||||
<li class="employee-card__list-item">
|
||||
@@ -121,14 +121,15 @@
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
</details>
|
||||
{% endif %}
|
||||
|
||||
<section class="employee-card__section">
|
||||
<h3 class="employee-section__title">Разделы профиля</h3>
|
||||
{% if employee_view.sections %}
|
||||
{% set profile_sections = employee_view.sections | rejectattr('type', 'equalto', 'news') | list %}
|
||||
{% if profile_sections %}
|
||||
<div class="employee-card__sections">
|
||||
{% for section in employee_view.sections %}
|
||||
{% for section in profile_sections %}
|
||||
<article class="employee-section">
|
||||
<div class="employee-section__header">
|
||||
<h4 class="employee-section__title">{{ section.title }}</h4>
|
||||
|
||||
+3
-3
@@ -1,3 +1,3 @@
|
||||
APP_VERSION = "1.5.0"
|
||||
FRONTEND_VERSION = "1.5.0"
|
||||
BACKEND_VERSION = "1.5.0"
|
||||
APP_VERSION = "1.5.1"
|
||||
FRONTEND_VERSION = "1.5.1"
|
||||
BACKEND_VERSION = "1.5.1"
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "miem-workers"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
description = "MIEM employees parser, admin API, and web admin"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ def test_health_returns_versions():
|
||||
response = TestClient(app).get("/api/health")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["backend_version"] == "1.5.0"
|
||||
assert response.json()["backend_version"] == "1.5.1"
|
||||
|
||||
|
||||
def test_api_employees_and_stats_require_admin_session():
|
||||
|
||||
@@ -230,7 +230,7 @@ def test_public_page_data_minimization_and_safe_links(db_session, export):
|
||||
assert "javascript:" not in fragment.text and "private@example.org" not in fragment.text
|
||||
assert "javascript:" not in response.text and "private@example.org" not in response.text
|
||||
assert "/admin/employees/" not in response.text and "/admin/logout" not in response.text
|
||||
assert "Backend 1.5.0 · Frontend 1.5.0" in response.text
|
||||
assert "Backend 1.5.1 · Frontend 1.5.1" in response.text
|
||||
assert "Вход в систему" in response.text
|
||||
assert client.get("/admin/directory", follow_redirects=False).status_code in (302, 303, 401, 403)
|
||||
assert "Сотрудники не найдены" in client.get("/admin/council?q=missing").text
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from starlette.requests import Request
|
||||
|
||||
from app.models import Employee, EmployeeNewsLink
|
||||
from app.services.admin_data import employee_detail_payload
|
||||
|
||||
|
||||
def test_employee_detail_template_is_human_readable():
|
||||
template = Path("app/templates/employee_detail.html").read_text(encoding="utf-8")
|
||||
@@ -33,3 +41,41 @@ def test_employee_detail_template_is_human_readable():
|
||||
assert "Обновить данные" in template
|
||||
assert 'action="/admin/employees/{{ employee.id }}/refresh"' in template
|
||||
assert "Снапшоты" in template
|
||||
|
||||
|
||||
@pytest.mark.parametrize("news_source", [None, "snapshot", "stored"])
|
||||
@pytest.mark.parametrize("has_other_section", [False, True])
|
||||
def test_employee_news_render_once_in_closed_disclosure(db_session, news_source, has_other_section):
|
||||
sections = [{"title": "Биография", "type": "generic", "paragraphs": ["Текст биографии"]}] if has_other_section else []
|
||||
if news_source:
|
||||
sections.append({"title": "В новостях", "type": "news",
|
||||
"news_links": [{"title": "Новость из профиля", "url": "https://example.test/snapshot"}],
|
||||
"paragraphs": ["Дублирующий текст новостей"]})
|
||||
employee = Employee(profile_key="staff:news", canonical_url="https://example.test/profile",
|
||||
full_name="Тестовый сотрудник", status="active", current_data={"sections": sections})
|
||||
db_session.add(employee)
|
||||
db_session.flush()
|
||||
if news_source == "stored":
|
||||
db_session.add(EmployeeNewsLink(employee_id=employee.id, title="Сохранённая новость",
|
||||
url="https://example.test/stored", summary="Описание новости", source_hash="a" * 64))
|
||||
db_session.flush()
|
||||
template = Environment(loader=FileSystemLoader("app/templates"), autoescape=True).get_template("employee_detail.html")
|
||||
rendered = template.render(employee=employee, employee_view=employee_detail_payload(employee), snapshots=[],
|
||||
request=Request({"type": "http", "scheme": "http", "headers": [],
|
||||
"path": f"/admin/employees/{employee.id}"}))
|
||||
soup = BeautifulSoup(rendered, "html.parser")
|
||||
assert not any(badge.get_text(strip=True) == "news" for badge in soup.select(".employee-section__type"))
|
||||
assert "Дублирующий текст новостей" not in rendered
|
||||
assert ("Текст биографии" in rendered) == has_other_section
|
||||
assert ("Разделы профиля не найдены." in rendered) == (not has_other_section)
|
||||
news = soup.select("details.employee-card__section--news")
|
||||
assert len(news) == (1 if news_source else 0)
|
||||
if news_source:
|
||||
assert not news[0].has_attr("open")
|
||||
assert news[0].summary.h3.get_text(strip=True) == "В новостях"
|
||||
expected_url = f"https://example.test/{'stored' if news_source == 'stored' else 'snapshot'}"
|
||||
assert [link["href"] for link in news[0].select("a")] == [expected_url]
|
||||
assert len(soup.select(f'a[href="{expected_url}"]')) == 1
|
||||
if news_source == "stored":
|
||||
assert "Описание новости" in news[0].get_text()
|
||||
assert "Новость из профиля" not in rendered
|
||||
Reference in new issue
Block a user