synops/maskinrommet/src/templates/magasin/article.html
vegard 63630eb55a Fullfører oppgave 14.16: Presentasjonselementer som noder
Publisert tittel, ingress, OG-bilde og undertittel er nå egne noder
koblet til artikler via title/subtitle/summary/og_image-edges.
Rendering bruker presentasjonselementer med fallback til artikkelfelt.

Backend:
- Ny query: GET /query/presentation_elements?article_id=...
- render_article_to_cas henter presentasjonselementer via edges
- fetch_article + fetch_index_articles bruker pres.elementer
- Batch-henting for forsideartikler (én SQL-spørring)
- ArticleData utvides med subtitle + og_image
- Alle fire temaer viser subtitle og OG-bilde
- SEO og_image-tag fylles fra presentasjonselement

Frontend:
- PresentationEditor.svelte: opprett/rediger tittel, undertittel,
  ingress, OG-bilde med variantvelger (editorial/ai/social/rss)
- Integrert i PublishDialog via <details>-seksjon
- API-klient: fetchPresentationElements(), deleteNode()

Grunnlag for A/B-testing (oppgave 14.17): edge-metadata støtter
ab_status/impressions/clicks/ctr, best_of() prioriterer winner > testing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:55:23 +00:00

75 lines
2.5 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ article.title }} — {{ collection_title }}{% endblock %}
{% block seo %}
<meta name="description" content="{{ seo.description }}">
<link rel="canonical" href="{{ seo.canonical_url }}">
<meta property="og:type" content="article">
<meta property="og:title" content="{{ seo.og_title }}">
<meta property="og:description" content="{{ seo.description }}">
<meta property="og:url" content="{{ seo.canonical_url }}">
<meta property="og:site_name" content="{{ collection_title }}">
{% if seo.og_image %}<meta property="og:image" content="{{ seo.og_image }}">{% endif %}
<meta property="article:published_time" content="{{ article.published_at }}">
<link rel="alternate" type="application/atom+xml" title="{{ collection_title }} — RSS" href="{{ base_url }}/feed.xml">
<script type="application/ld+json">{{ seo.json_ld | safe }}</script>
{% endblock %}
{% block extra_css %}
.mag-article {
max-width: var(--layout-max-width);
margin: 0 auto;
padding: 0 1rem;
}
.mag-article__header {
text-align: center;
padding: 3rem 0 2rem;
max-width: 720px;
margin: 0 auto;
}
.mag-article__title {
font-family: var(--font-heading);
font-size: 3rem;
line-height: 1.1;
color: var(--color-primary);
margin-bottom: 0.75rem;
}
.mag-article__meta {
color: var(--color-muted);
font-size: 0.9rem;
}
.mag-article__content {
max-width: 680px;
margin: 0 auto;
font-size: 1.1rem;
line-height: 1.8;
padding-bottom: 3rem;
}
.mag-article__content p { margin-bottom: 1.25em; }
.mag-article__back {
display: inline-block;
margin-top: 2rem;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.mag-article__title { font-size: 2rem; }
.mag-article__header { padding: 2rem 0 1.5rem; }
}
{% endblock %}
{% block content %}
<article class="mag-article">
{% if article.og_image %}<img src="/cas/{{ article.og_image }}" alt="{{ article.title }}" style="width:100%;max-height:500px;object-fit:cover;margin-bottom:0;">{% endif %}
<header class="mag-article__header">
<h1 class="mag-article__title">{{ article.title }}</h1>
{% if article.subtitle %}<p style="font-size:1.25rem;color:var(--color-muted);margin-top:0.5rem;font-family:var(--font-heading);">{{ article.subtitle }}</p>{% endif %}
<div class="mag-article__meta">Publisert {{ article.published_at_short }}</div>
</header>
<div class="mag-article__content">
{{ article.content | safe }}
<a class="mag-article__back" href="{{ base_url }}">&larr; Tilbake</a>
</div>
</article>
{% endblock %}