feat: news/events pages, pagination, cookie banner, MONT→MONT rename, logo update, admin improvements, API endpoints, dynamic links by domain
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Новости MONT</title>
|
||||
<meta name="description" content="Последние новости дистрибьютора MONT — вендоры, продукты, партнёрские программы." />
|
||||
<meta name="robots" content="index, follow" />
|
||||
<link rel="canonical" href="{{ base_url }}/news" />
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg" />
|
||||
<link rel="icon" type="image/png" href="/static/favicon.png" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root { --brand: #1f4ea3; --brand2: #3978e0; --bg: #eef4ff; }
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-family: Manrope, sans-serif; background: var(--bg); color: #15203b; min-height: 100vh; }
|
||||
.wrap { width: min(900px, calc(100% - 32px)); margin: 0 auto; padding: 28px 0 60px; }
|
||||
.back-btn {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
font-size: 13px; font-weight: 700; color: var(--brand);
|
||||
text-decoration: none; margin-bottom: 24px;
|
||||
padding: 8px 16px; border-radius: 999px;
|
||||
background: #fff; border: 1px solid #c8d8f7; transition: .15s;
|
||||
}
|
||||
.back-btn:hover { background: #eef4ff; transform: translateX(-2px); }
|
||||
h1 { font-size: 28px; font-weight: 800; color: #1a3e79; margin: 0 0 24px; }
|
||||
|
||||
.top3 { margin-bottom: 32px; }
|
||||
.top3-label {
|
||||
font-size: 11px; font-weight: 800; letter-spacing: 1.2px;
|
||||
text-transform: uppercase; color: #7a9bc0; margin-bottom: 14px;
|
||||
}
|
||||
.top3-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
.top3-card {
|
||||
background: #fff; border-radius: 16px;
|
||||
border: 1px solid #dae6ff;
|
||||
box-shadow: 0 6px 20px rgba(16,43,95,.08);
|
||||
overflow: hidden; text-decoration: none; color: inherit;
|
||||
transition: .18s ease; display: flex; flex-direction: column;
|
||||
}
|
||||
.top3-card:hover { transform: translateY(-3px); box-shadow: 0 12px 32px rgba(16,43,95,.14); }
|
||||
.top3-card img { width: 100%; height: 160px; object-fit: cover; display: block; }
|
||||
.top3-card .no-img { width: 100%; height: 100px; background: linear-gradient(135deg, #e8f0ff, #d0e2ff); display: flex; align-items: center; justify-content: center; }
|
||||
.top3-card .no-img-icon { font-size: 32px; opacity: .4; }
|
||||
.top3-card-body { padding: 14px 16px 18px; flex: 1; display: flex; flex-direction: column; }
|
||||
.top3-card-date { font-size: 11px; color: #9ab0d0; font-weight: 600; margin-bottom: 6px; }
|
||||
.top3-card-title { font-size: 14px; font-weight: 800; color: #1a3e79; line-height: 1.4; flex: 1; margin: 0 0 12px; }
|
||||
.top3-card-excerpt { font-size: 12px; color: #5a7090; line-height: 1.55; margin: 0 0 12px; flex: 1;
|
||||
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
.read-more { font-size: 12px; font-weight: 700; color: var(--brand2); }
|
||||
|
||||
.divider { border: none; border-top: 2px solid #e0eaff; margin: 0 0 24px; }
|
||||
.rest-label {
|
||||
font-size: 11px; font-weight: 800; letter-spacing: 1.2px;
|
||||
text-transform: uppercase; color: #7a9bc0; margin-bottom: 16px;
|
||||
}
|
||||
.news-row {
|
||||
background: #fff; border-radius: 14px; border: 1px solid #dae6ff;
|
||||
display: flex; gap: 0; overflow: hidden; margin-bottom: 12px;
|
||||
text-decoration: none; color: inherit;
|
||||
transition: .18s ease; box-shadow: 0 4px 14px rgba(16,43,95,.06);
|
||||
}
|
||||
.news-row:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(16,43,95,.12); }
|
||||
.news-row img { width: 120px; height: 90px; object-fit: cover; flex-shrink: 0; }
|
||||
.news-row .no-img-row { width: 80px; flex-shrink: 0; background: linear-gradient(135deg, #e8f0ff, #d0e2ff); }
|
||||
.news-row-body { padding: 12px 16px; display: flex; flex-direction: column; justify-content: center; }
|
||||
.news-row-date { font-size: 11px; color: #9ab0d0; font-weight: 600; margin-bottom: 4px; }
|
||||
.news-row-title { font-size: 14px; font-weight: 800; color: #1a3e79; line-height: 1.35; margin: 0 0 6px; }
|
||||
.news-row-excerpt { font-size: 12px; color: #5a7090; line-height: 1.5; margin: 0;
|
||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
|
||||
.empty { text-align: center; padding: 60px 0; color: #9ab0d0; font-size: 15px; }
|
||||
|
||||
.pagination { display: flex; justify-content: center; align-items: center; gap: 6px; margin-top: 28px; flex-wrap: wrap; }
|
||||
.pagination a, .pagination span {
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
width: 36px; height: 36px; border-radius: 10px;
|
||||
font-size: 13px; font-weight: 700; text-decoration: none;
|
||||
border: 1px solid #c8d8f7; background: #fff; color: #1f4ea3; transition: .15s;
|
||||
}
|
||||
.pagination a:hover { background: #eef4ff; }
|
||||
.pagination span.current { background: linear-gradient(135deg,#1f4ea3,#3978e0); color: #fff; border-color: transparent; }
|
||||
.pagination span.dots { background: none; border-color: transparent; color: #9ab0d0; }
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.top3-grid { grid-template-columns: 1fr; }
|
||||
.news-row img { width: 90px; height: 70px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<a href="/" class="back-btn">← На главную</a>
|
||||
<h1>Новости MONT</h1>
|
||||
|
||||
{% if articles %}
|
||||
|
||||
{% if page == 1 %}
|
||||
{% set top3 = articles[:3] %}
|
||||
{% set rest = articles[3:] %}
|
||||
<div class="top3">
|
||||
<div class="top3-label">Последние новости</div>
|
||||
<div class="top3-grid">
|
||||
{% for a in top3 %}
|
||||
<a class="top3-card" href="/news/{{ a.slug }}">
|
||||
{% if a.image %}
|
||||
<img src="/static/{{ a.image }}" alt="{{ a.title }}" />
|
||||
{% else %}
|
||||
<div class="no-img"><span class="no-img-icon">📰</span></div>
|
||||
{% endif %}
|
||||
<div class="top3-card-body">
|
||||
<div class="top3-card-date">{{ a.created_at[8:10] }}.{{ a.created_at[5:7] }}.{{ a.created_at[:4] }}</div>
|
||||
<h2 class="top3-card-title">{{ a.title }}</h2>
|
||||
<p class="top3-card-excerpt">{{ a.body | striptags | truncate(180, true, '...') }}</p>
|
||||
<span class="read-more">Читать →</span>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% if rest %}
|
||||
<hr class="divider" />
|
||||
<div class="rest-label">Ещё новости</div>
|
||||
{% for a in rest %}
|
||||
<a class="news-row" href="/news/{{ a.slug }}">
|
||||
{% if a.image %}
|
||||
<img src="/static/{{ a.image }}" alt="{{ a.title }}" />
|
||||
{% else %}
|
||||
<div class="no-img-row"></div>
|
||||
{% endif %}
|
||||
<div class="news-row-body">
|
||||
<div class="news-row-date">{{ a.created_at[8:10] }}.{{ a.created_at[5:7] }}.{{ a.created_at[:4] }}</div>
|
||||
<div class="news-row-title">{{ a.title }}</div>
|
||||
<p class="news-row-excerpt">{{ a.body | striptags | truncate(160, true, '...') }}</p>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<hr class="divider" />
|
||||
<div class="rest-label">Новости — страница {{ page }}</div>
|
||||
{% for a in articles %}
|
||||
<a class="news-row" href="/news/{{ a.slug }}">
|
||||
{% if a.image %}
|
||||
<img src="/static/{{ a.image }}" alt="{{ a.title }}" />
|
||||
{% else %}
|
||||
<div class="no-img-row"></div>
|
||||
{% endif %}
|
||||
<div class="news-row-body">
|
||||
<div class="news-row-date">{{ a.created_at[8:10] }}.{{ a.created_at[5:7] }}.{{ a.created_at[:4] }}</div>
|
||||
<div class="news-row-title">{{ a.title }}</div>
|
||||
<p class="news-row-excerpt">{{ a.body | striptags | truncate(160, true, '...') }}</p>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<div class="empty">Новостей пока нет</div>
|
||||
{% endif %}
|
||||
|
||||
{% if total_pages > 1 %}
|
||||
<div class="pagination">
|
||||
{% if page > 1 %}
|
||||
<a href="?page={{ page - 1 }}">‹</a>
|
||||
{% endif %}
|
||||
{% for p in range(1, total_pages + 1) %}
|
||||
{% if p == page %}
|
||||
<span class="current">{{ p }}</span>
|
||||
{% elif p == 1 or p == total_pages or (p >= page - 2 and p <= page + 2) %}
|
||||
<a href="?page={{ p }}">{{ p }}</a>
|
||||
{% elif p == page - 3 or p == page + 3 %}
|
||||
<span class="dots">…</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if page < total_pages %}
|
||||
<a href="?page={{ page + 1 }}">›</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user