diff --git a/matrix.db b/matrix.db index e5e5217..93ff5b0 100644 Binary files a/matrix.db and b/matrix.db differ diff --git a/static/js/index.js b/static/js/index.js index 8c277cf..aeb778d 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -296,7 +296,8 @@ ? `${v.name}` : `${v.name.slice(0,2).toUpperCase()}`; let linksHtml = ''; - if (v.mont_page) linksHtml += `MONT ↗`; + if (v.slug) linksHtml += `Подробнее →`; + if (v.mont_page) linksHtml += `MONT ↗`; if (v.website) linksHtml += `Сайт ↗`; bar.innerHTML = ` @@ -313,7 +314,17 @@ const card = document.createElement("article"); card.className = "row-card"; const title = document.createElement("strong"); - title.textContent = row.vendor.name; + if (row.vendor.slug) { + const a = document.createElement("a"); + a.href = `/vendor/${row.vendor.slug}`; + a.textContent = row.vendor.name; + a.style.cssText = "color:inherit;text-decoration:none;"; + a.addEventListener("mouseenter", () => a.style.textDecoration = "underline"); + a.addEventListener("mouseleave", () => a.style.textDecoration = "none"); + title.appendChild(a); + } else { + title.textContent = row.vendor.name; + } card.appendChild(title); const tags = document.createElement("div"); tags.className = "tags"; diff --git a/templates/vendor.html b/templates/vendor.html new file mode 100644 index 0000000..6436c9e --- /dev/null +++ b/templates/vendor.html @@ -0,0 +1,194 @@ + + + + + + {{ vendor.name }} — вендор МОНТ | матрица продуктов MONT + + + + + + + + + {% if vendor.logo %}{% endif %} + + + + + + + + + + +
+ ← Все вендоры МОНТ + + + +
+
+ {% if vendor.logo %} + {{ vendor.name }} логотип + {% else %} + {{ vendor.name[:2].upper() }} + {% endif %} +
+
+

{{ vendor.name }}

+ {% if vendor.description %} +

{{ vendor.description }}

+ {% endif %} + +
+
+ + {% if products %} +
+

Продукты {{ vendor.name }} в корзине МОНТ

+
+ {% for p in products %} + {% if p.url %} + {{ p.name }} ↗ + {% else %} + {{ p.name }} + {% endif %} + {% endfor %} +
+
+ {% endif %} + + {% if categories %} +
+

Категории

+ {% for c in categories %} + {{ c }} + {% endfor %} +
+ {% endif %} +
+ + diff --git a/zkart_app/db.py b/zkart_app/db.py index efa9b54..ac759e2 100644 --- a/zkart_app/db.py +++ b/zkart_app/db.py @@ -411,7 +411,7 @@ def fetch_scope_data(scope: str) -> dict: conn = get_db() vendors = [dict(r) for r in conn.execute( f"SELECT id, name, COALESCE(logo,'') as logo, COALESCE(description,'') as description, " - f"COALESCE(website,'') as website, COALESCE(mont_page,'') as mont_page " + f"COALESCE(website,'') as website, COALESCE(mont_page,'') as mont_page, COALESCE(slug,'') as slug " f"FROM {tables['vendors']} ORDER BY lower(name)" )] categories = [dict(r) for r in conn.execute(f"SELECT id, name FROM {tables['categories']} ORDER BY lower(name)")] diff --git a/zkart_app/routes.py b/zkart_app/routes.py index 8b306a0..f5ca6b5 100644 --- a/zkart_app/routes.py +++ b/zkart_app/routes.py @@ -582,15 +582,69 @@ def sitemap_xml(): from flask import Response proto = request.headers.get("X-Forwarded-Proto", "https") base = f"{proto}://{request.host}" + conn = get_db() + slugs = [r[0] for r in conn.execute( + "SELECT slug FROM vendors WHERE slug IS NOT NULL " + "UNION SELECT slug FROM ib_vendors WHERE slug IS NOT NULL" + )] + conn.close() + urls = [f' {base}/weekly1.0'] + for slug in slugs: + urls.append(f' {base}/vendor/{slug}monthly0.7') body = ( '\n' '\n' - f' {base}/weekly1.0\n' - '' + + '\n'.join(urls) + '\n' ) return Response(body, mimetype="application/xml") +@bp.get("/vendor/") +def vendor_page(slug: str): + from flask import abort + conn = get_db() + # Search in both tables, prefer infra + vendor = conn.execute( + "SELECT id, name, COALESCE(logo,'') as logo, COALESCE(description,'') as description, " + "COALESCE(website,'') as website, COALESCE(mont_page,'') as mont_page, 'infra' as scope " + "FROM vendors WHERE slug = ?", (slug,) + ).fetchone() + if not vendor: + vendor = conn.execute( + "SELECT id, name, COALESCE(logo,'') as logo, COALESCE(description,'') as description, " + "COALESCE(website,'') as website, COALESCE(mont_page,'') as mont_page, 'ib' as scope " + "FROM ib_vendors WHERE slug = ?", (slug,) + ).fetchone() + if not vendor: + conn.close() + abort(404) + + vendor = dict(vendor) + tables = scope_tables(vendor['scope']) + + products = [dict(r) for r in conn.execute( + f"SELECT name, COALESCE(url,'') as url FROM {tables['products']} " + f"WHERE vendor_id = ? ORDER BY lower(name)", (vendor['id'],) + )] + categories = [r[0] for r in conn.execute( + f"SELECT c.name FROM {tables['categories']} c " + f"JOIN {tables['vendor_categories']} vc ON vc.category_id = c.id " + f"WHERE vc.vendor_id = ? ORDER BY lower(c.name)", (vendor['id'],) + )] + conn.close() + + proto = request.headers.get("X-Forwarded-Proto", "https") + base_url = f"{proto}://{request.host}" + canonical_url = f"{base_url}/vendor/{slug}" + return render_template("vendor.html", + vendor=vendor, + products=products, + categories=categories, + canonical_url=canonical_url, + base_url=base_url, + ) + + @bp.get("/api/data") def api_data(): scope = (request.args.get("scope") or "infra").strip().lower()