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:
2026-06-01 17:44:25 +03:00
parent 7c0c2ea14a
commit b1fde8344e
117 changed files with 3993 additions and 70 deletions
+138 -35
View File
@@ -3,17 +3,17 @@
<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="keywords" content="вендоры МОНТ, вендоры MONT, дистрибьютор МОНТ, корзина продуктов МОНТ, матрица МОНТ, МОНТ Казань, партнёры МОНТ, ИБ вендоры, инфраструктура ПО, MONT vendor map" />
<title>Вендоры MONT — матрица продуктов и категорий дистрибьютора MONT</title>
<meta name="description" content="Корзина продуктов MONT: актуальная матрица вендоров, категорий и продуктовых линеек дистрибьютора MONT. Инфраструктура и информационная безопасность. MONT Казань, Москва." />
<meta name="keywords" content="вендоры MONT, вендоры MONT, дистрибьютор MONT, корзина продуктов MONT, матрица MONT, MONT Казань, партнёры MONT, ИБ вендоры, инфраструктура ПО, MONT vendor map" />
<meta name="robots" content="index, follow" />
<link rel="canonical" href="{{ canonical_url }}" />
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:url" content="{{ canonical_url }}" />
<meta property="og:title" content="Вендоры МОНТ — матрица продуктов и категорий" />
<meta property="og:description" content="Актуальная матрица вендоров и продуктов дистрибьютора МОНТ. Инфраструктура и информационная безопасность." />
<meta property="og:title" content="Вендоры MONT — матрица продуктов и категорий" />
<meta property="og:description" content="Актуальная матрица вендоров и продуктов дистрибьютора MONT. Инфраструктура и информационная безопасность." />
<meta property="og:image" content="{{ canonical_url }}/static/mont_logo.png" />
<meta property="og:locale" content="ru_RU" />
@@ -22,7 +22,7 @@
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "МОНТ",
"name": "MONT",
"alternateName": "MONT",
"description": "Дистрибьютор программного обеспечения. Корзина продуктов: вендоры, категории, продуктовые линейки в сфере инфраструктуры и информационной безопасности.",
"url": "{{ canonical_url }}",
@@ -31,6 +31,7 @@
}
</script>
<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>
@@ -41,21 +42,21 @@
<main class="wrap">
<section class="brand-strip">
<div class="brand-logo">
<img src="/static/mont_logo.png?v=2" alt="MONT logo" />
<a id="logo-link" href="https://4mont.ru"><img src="/static/mont_logo.png?v=3" alt="MONT logo" /></a>
</div>
</section>
<section class="hero">
<div class="hero-layout">
<div>
<h1>Вендоры в корзине МОНТ</h1>
<h1>Вендоры в портфеле MONT</h1>
<p>Актуальная матрица вендоров, продуктов и категорий. Выбирайте вендоров или категории, чтобы видеть релевантные продуктовые линейки в Инфраструктуре и ИБ.</p>
<div class="mode-switch-row">
<div class="mode-switch">
<button id="modeInfra" class="mode-btn active" type="button">Инфраструктура</button>
<button id="modeIb" class="mode-btn" type="button">ИБ</button>
</div>
<a href="https://stend.4mont.ru/" target="_blank" rel="noopener" class="polygon-btn">Инфраструктурный полигон МОНТ</a>
<a id="polygon-link" href="https://stend.4mont.ru/" target="_blank" rel="noopener" class="polygon-btn">Инфраструктурный полигон MONT</a>
</div>
</div>
</div>
@@ -63,39 +64,108 @@
<!-- SSR-контент для поисковых роботов -->
<div style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;" aria-hidden="true">
<h2>Вендоры дистрибьютора МОНТ (MONT)</h2>
<p>Матрица вендоров, продуктов и категорий компании МОНТ — ведущего дистрибьютора программного обеспечения в России. Инфраструктура и информационная безопасность.</p>
<h2>Вендоры дистрибьютора MONT (MONT)</h2>
<p>Матрица вендоров, продуктов и категорий компании MONT — ведущего дистрибьютора программного обеспечения в России. Инфраструктура и информационная безопасность.</p>
<ul>{% for v in ssr_vendors %}<li>{{ v }}</li>{% endfor %}</ul>
<h2>Категории продуктов МОНТ</h2>
<h2>Категории продуктов MONT</h2>
<ul>{% for c in ssr_categories %}<li>{{ c }}</li>{% endfor %}</ul>
</div>
<section class="board">
<article class="card">
<div class="card-header"><h2>Вендоры</h2><span class="count-badge" id="vendorBadge">...</span></div>
<input id="vendorSearch" class="search" placeholder="Поиск вендора..." />
<div id="vendorList" class="chip-grid"></div>
</article>
<div class="page-layout">
<div class="main-col">
<section class="board">
<article class="card">
<div class="card-header"><h2>Вендоры</h2><span class="count-badge" id="vendorBadge">...</span></div>
<input id="vendorSearch" class="search" placeholder="Поиск вендора..." />
<div id="vendorList" class="chip-grid"></div>
</article>
<article class="card">
<div class="card-header"><h2>Категории</h2><span class="count-badge" id="categoryBadge">...</span></div>
<input id="categorySearch" class="search" placeholder="Поиск категории..." />
<div id="categoryList" class="chip-grid"></div>
</article>
</section>
<article class="card">
<div class="card-header"><h2>Категории</h2><span class="count-badge" id="categoryBadge">...</span></div>
<input id="categorySearch" class="search" placeholder="Поиск категории..." />
<div id="categoryList" class="chip-grid"></div>
</article>
</section>
<div class="footer-bar">
<div id="stats">Загрузка...</div>
<button class="action" id="clearBtn">Сбросить фильтры</button>
<div class="footer-bar">
<div id="stats">Загрузка...</div>
<button class="action" id="clearBtn">Сбросить фильтры</button>
</div>
<section class="result">
<div class="result-head">
<h3>Вендоры и продукты (после фильтрации)</h3>
</div>
<div id="activeFilters" class="active-filters"></div>
<div id="resultRows" class="rows"></div>
</section>
</div>
<aside class="news-sidebar">
<div class="news-widget">
<div class="news-widget-head">
<h2>Новости MONT</h2>
<div style="display:flex;gap:6px;align-items:center;">
{% if is_news_editor %}
<a href="/news-admin" class="news-all-link" style="background:linear-gradient(135deg,#1f4ea3,#3978e0);color:#fff;border-color:transparent;">✏️ Редактор</a>
{% endif %}
<a href="/news" class="news-all-link">Все →</a>
</div>
</div>
{% if latest_news %}
<div class="news-list">
{% for n in latest_news %}
<a class="news-card" href="/news/{{ n.slug }}">
<div class="news-card-img-wrap">
{% if n.image %}
<img class="news-card-img" src="/static/{{ n.image }}" alt="{{ n.title }}" />
{% else %}
<span class="news-card-no-img">📰</span>
{% endif %}
</div>
<div class="news-card-body">
<div class="news-card-date">{{ n.created_at[8:10] }}.{{ n.created_at[5:7] }}.{{ n.created_at[:4] }}</div>
<h3 class="news-card-title">{{ n.title }}</h3>
<span class="news-card-btn">Подробнее →</span>
</div>
</a>
{% endfor %}
</div>
{% else %}
<p class="news-empty">Новостей пока нет</p>
{% endif %}
</div>
<div class="news-widget" style="margin-top:14px;">
<div class="news-widget-head">
<h2>Мероприятия MONT</h2>
<a href="/events" class="news-all-link">Все →</a>
</div>
{% if upcoming_events %}
<div class="news-list">
{% for e in upcoming_events %}
<a class="news-card" href="/events/{{ e.slug }}">
<div class="news-card-img-wrap">
{% if e.image %}
<img class="news-card-img" src="/static/{{ e.image }}" alt="{{ e.title }}" />
{% else %}
<span class="news-card-no-img">📅</span>
{% endif %}
</div>
<div class="news-card-body">
<div class="news-card-date">{{ e.event_date[8:10] }}.{{ e.event_date[5:7] }}.{{ e.event_date[:4] }}</div>
<h3 class="news-card-title">{{ e.title }}</h3>
<span class="news-card-btn">Подробнее →</span>
</div>
</a>
{% endfor %}
</div>
{% else %}
<p class="news-empty">Актуальных мероприятий нет</p>
{% endif %}
</div>
</aside>
</div>
<section class="result">
<div class="result-head">
<h3>Вендоры и продукты (после фильтрации)</h3>
</div>
<div id="activeFilters" class="active-filters"></div>
<div id="resultRows" class="rows"></div>
</section>
<div class="credit">
<button type="button" id="btn-contact-ruslan">Made by Galyaviev</button>
</div>
@@ -224,10 +294,43 @@
}
}
document.getElementById('btn-contact-ruslan').addEventListener('click', openModal);
document.getElementById('btn-contact-ruslan').addEventListener('click', () => { window.location.href = 'mailto:ruslan@ipcom.su'; });
overlay.addEventListener('click', e => { if (e.target === overlay) window._closeContact(); });
document.addEventListener('keydown', e => { if (e.key === 'Escape') window._closeContact(); });
})();
</script>
<script>
(function(){
var isMont = location.hostname === 'maps.mont.ru';
var poly = document.getElementById('polygon-link');
if (poly) poly.href = isMont ? 'https://stand.mont.ru/' : 'https://stend.4mont.ru/';
var logo = document.getElementById('logo-link');
if (logo) logo.href = isMont ? 'https://www.mont.ru' : 'https://4mont.ru';
})();
</script>
<div id="cookie-banner" style="display:none;position:fixed;bottom:0;left:0;right:0;z-index:9999;background:#1a3060;color:#fff;padding:1rem 1.5rem;box-shadow:0 -2px 16px rgba(0,0,0,.2);align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;">
<span style="font-size:.9rem;line-height:1.5;">
Мы используем файлы cookie, чтобы сделать работу с сайтом удобнее. Нажмите «Принять», чтобы согласиться с использованием файлов cookie в соответствии с
<a href="https://www.mont.ru/ru-ru/confidential" target="_blank" rel="noopener"
style="color:#7eb3ff;text-decoration:underline;">политикой конфиденциальности</a>.
</span>
<button id="cookie-accept" style="background:linear-gradient(135deg,#3978e0,#5a9ef5);border:none;border-radius:9px;
padding:.55rem 1.4rem;color:#fff;font-weight:700;font-family:Manrope,sans-serif;cursor:pointer;white-space:nowrap;">
Принять
</button>
</div>
<script>
(function(){
if (localStorage.getItem('cookie_accepted')) return;
var b = document.getElementById('cookie-banner');
b.style.display = 'flex';
document.getElementById('cookie-accept').addEventListener('click', function(){
localStorage.setItem('cookie_accepted', '1');
b.style.display = 'none';
});
})();
</script>
</body>
</html>