dnscms: improve news app

This commit is contained in:
2026-05-19 22:00:11 +02:00
parent 29c61ffc76
commit 447e1bd3ff
8 changed files with 164 additions and 41 deletions
-14
View File
@@ -1,11 +1,6 @@
from django.contrib.admin.utils import quote
from django.templatetags.static import static from django.templatetags.static import static
from django.urls import reverse
from django.utils.html import format_html from django.utils.html import format_html
from wagtail import hooks from wagtail import hooks
from wagtail.admin.menu import MenuItem
from news.models import NewsIndex
@hooks.register("register_rich_text_features") @hooks.register("register_rich_text_features")
@@ -13,15 +8,6 @@ def enable_additional_rich_text_features(features):
features.default_features.extend(["h5", "h6", "blockquote"]) features.default_features.extend(["h5", "h6", "blockquote"])
@hooks.register("register_admin_menu_item")
def register_news_menu_item():
page = NewsIndex.objects.first()
news_url = "#"
if page:
news_url = reverse("wagtailadmin_explore", args=(quote(page.pk),))
return MenuItem("Nyheter", news_url, icon_name="info-circle", order=3)
@hooks.register("construct_page_action_menu") @hooks.register("construct_page_action_menu")
def make_publish_default_action(menu_items, request, context): def make_publish_default_action(menu_items, request, context):
for index, item in enumerate(menu_items): for index, item in enumerate(menu_items):
Binary file not shown.
+65 -19
View File
@@ -7,38 +7,39 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dnscms\n" "Project-Id-Version: dnscms\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-19 21:36+0200\n" "POT-Creation-Date: 2026-05-19 21:55+0200\n"
"Language: nb\n" "Language: nb\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: associations/admin.py:40 #: associations/admin.py:23
msgid "Associations" msgid "Associations"
msgstr "Foreninger" msgstr "Foreninger"
#: associations/admin.py:46 events/admin.py:76 #: associations/admin.py:29 events/admin.py:59 news/admin.py:24
msgid "Title" msgid "Title"
msgstr "Tittel" msgstr "Tittel"
#: associations/admin.py:49 associations/models.py:81 #: associations/admin.py:32 associations/models.py:79
msgid "Type" msgid "Type"
msgstr "Type" msgstr "Type"
#: associations/admin.py:55 events/admin.py:81 #: associations/admin.py:38 events/admin.py:64 news/admin.py:27
msgid "Updated" msgid "Updated"
msgstr "Oppdatert" msgstr "Oppdatert"
#: associations/admin.py:59 events/admin.py:85 #: associations/admin.py:42 events/admin.py:68 news/admin.py:31
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Status"
#: associations/models.py:30 associations/models.py:78 events/models.py:327 #: associations/models.py:30 associations/models.py:76 events/models.py:327
#: news/models.py:23 news/models.py:69
msgid "Lead" msgid "Lead"
msgstr "Ingress" msgstr "Ingress"
#: associations/models.py:31 associations/models.py:79 #: associations/models.py:31 associations/models.py:77
msgid "Content" msgid "Content"
msgstr "Innhold" msgstr "Innhold"
@@ -58,23 +59,24 @@ msgstr "Forening"
msgid "Committee" msgid "Committee"
msgstr "Utvalg" msgstr "Utvalg"
#: associations/models.py:73 #: associations/models.py:73 news/models.py:60
msgid "Excerpt" msgid "Excerpt"
msgstr "Utdrag" msgstr "Utdrag"
#: associations/models.py:75 #: associations/models.py:74
msgid "A very short summary of the content below. Used in listing views." msgid "A very short summary of the content below. Used in listing views."
msgstr "En veldig kort oppsummering av innholdet nedenfor. Brukes i listevisninger." msgstr ""
"En veldig kort oppsummering av innholdet nedenfor. Brukes i listevisninger."
#: associations/models.py:82 events/models.py:189 #: associations/models.py:80 events/models.py:189
msgid "Website" msgid "Website"
msgstr "Nettsted" msgstr "Nettsted"
#: associations/models.py:100 #: associations/models.py:98
msgid "association" msgid "association"
msgstr "forening" msgstr "forening"
#: associations/models.py:101 #: associations/models.py:99
msgid "associations" msgid "associations"
msgstr "foreninger" msgstr "foreninger"
@@ -90,26 +92,26 @@ msgstr "Velg en annen forening"
msgid "Edit this association" msgid "Edit this association"
msgstr "Rediger denne foreningen" msgstr "Rediger denne foreningen"
#: events/admin.py:23 #: events/admin.py:20
msgid "%Y-%m-%d at %H:%M" msgid "%Y-%m-%d at %H:%M"
msgstr "%Y-%m-%d kl %H:%M" msgstr "%Y-%m-%d kl %H:%M"
#: events/admin.py:25 #: events/admin.py:22
#, python-format #, python-format
msgid "%(count)d occurrence" msgid "%(count)d occurrence"
msgid_plural "%(count)d occurrences" msgid_plural "%(count)d occurrences"
msgstr[0] "%(count)d forekomst" msgstr[0] "%(count)d forekomst"
msgstr[1] "%(count)d forekomster" msgstr[1] "%(count)d forekomster"
#: events/admin.py:70 #: events/admin.py:53
msgid "Events" msgid "Events"
msgstr "Arrangementer" msgstr "Arrangementer"
#: events/admin.py:77 #: events/admin.py:60
msgid "Date" msgid "Date"
msgstr "Dato" msgstr "Dato"
#: events/admin.py:78 events/models.py:331 #: events/admin.py:61 events/models.py:331
msgid "Organizers" msgid "Organizers"
msgstr "Arrangører" msgstr "Arrangører"
@@ -365,3 +367,47 @@ msgstr "bilde"
#: images/models.py:41 #: images/models.py:41
msgid "images" msgid "images"
msgstr "bilder" msgstr "bilder"
#: news/admin.py:18
msgid "News"
msgstr "Nyheter"
#: news/models.py:33
msgid "news index"
msgstr "nyhetsoversikt"
#: news/models.py:34
msgid "news indexes"
msgstr "nyhetsoversikter"
#: news/models.py:52
msgid ""
"Choose an image for use on the front page and other surfaces. Should be a "
"photo or an illustration without too much text."
msgstr ""
"Velg et bilde til bruk på forsiden og andre visningsflater. Bør være et "
"bilde eller en illustrasjon uten for mye tekst."
#: news/models.py:62
msgid ""
"A very short summary of the article's content. Used on the front page and in "
"the article listing."
msgstr ""
"En veldig kort oppsummering av innholdet i artikkelen. Brukes på forsiden "
"og i artikkeloversikten."
#: news/models.py:71
msgid ""
"A brief, introductory paragraph that summarizes the main content of the "
"article."
msgstr ""
"Et kortfattet, innledende avsnitt som oppsummerer hovedinnholdet i "
"artikkelen."
#: news/models.py:92
msgid "news article"
msgstr "nyhetsartikkel"
#: news/models.py:93
msgid "news articles"
msgstr "nyhetsartikler"
+35
View File
@@ -0,0 +1,35 @@
from django.utils.translation import gettext_lazy as _
from wagtail.admin.ui.tables import DateColumn
from wagtail.admin.ui.tables.pages import PageStatusColumn, PageTitleColumn
from wagtail.admin.viewsets.pages import PageListingViewSet
from dnscms.admin import ListingRedirectChooseParentView
from news.models import NewsPage
class NewsChooseParentView(ListingRedirectChooseParentView):
listing_url_name = "news:index"
class NewsPageListingViewSet(PageListingViewSet):
model = NewsPage
choose_parent_view_class = NewsChooseParentView
icon = "info-circle"
menu_label = _("News")
menu_order = 3
add_to_admin_menu = True
ordering = "-latest_revision_created_at"
columns = [
PageTitleColumn("title", label=_("Title"), sort_key="title", classname="title"),
DateColumn(
"latest_revision_created_at",
label=_("Updated"),
sort_key="latest_revision_created_at",
width="10%",
),
PageStatusColumn("status", label=_("Status"), sort_key="live", width="10%"),
]
news_page_listing_viewset = NewsPageListingViewSet("news")
@@ -0,0 +1,28 @@
# Generated by Django 6.0.5 on 2026-05-19 19:55
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('images', '0005_customimage_description'),
('news', '0018_newspage_wp_block_json_newspage_wp_link_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='newsindex',
options={'verbose_name': 'news index', 'verbose_name_plural': 'news indexes'},
),
migrations.AlterModelOptions(
name='newspage',
options={'verbose_name': 'news article', 'verbose_name_plural': 'news articles'},
),
migrations.AlterField(
model_name='newspage',
name='featured_image',
field=models.ForeignKey(blank=True, help_text='Choose an image for use on the front page and other surfaces. Should be a photo or an illustration without too much text.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.customimage'),
),
]
+22 -8
View File
@@ -1,4 +1,5 @@
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from grapple.helpers import register_singular_query_field from grapple.helpers import register_singular_query_field
from grapple.models import GraphQLImage, GraphQLRichText, GraphQLStreamfield, GraphQLString from grapple.models import GraphQLImage, GraphQLRichText, GraphQLStreamfield, GraphQLString
from wagtail.admin.panels import FieldPanel from wagtail.admin.panels import FieldPanel
@@ -19,7 +20,7 @@ class NewsIndex(HeadlessMixin, Page):
lead = RichTextField(features=["italic", "link"], blank=True) lead = RichTextField(features=["italic", "link"], blank=True)
content_panels = Page.content_panels + [ content_panels = Page.content_panels + [
FieldPanel("lead", heading="Ingress"), FieldPanel("lead", heading=_("Lead")),
] ]
graphql_fields = [ graphql_fields = [
@@ -28,6 +29,10 @@ class NewsIndex(HeadlessMixin, Page):
search_fields = [] search_fields = []
class Meta:
verbose_name = _("news index")
verbose_name_plural = _("news indexes")
class NewsPage(HeadlessMixin, WPImportedPageMixin, Page): class NewsPage(HeadlessMixin, WPImportedPageMixin, Page):
subpage_types = [] subpage_types = []
@@ -43,23 +48,28 @@ class NewsPage(HeadlessMixin, WPImportedPageMixin, Page):
blank=True, blank=True,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
related_name="+", related_name="+",
help_text=( help_text=_(
"Velg et bilde til bruk i på forsiden og andre visningsflater. " "Choose an image for use on the front page and other surfaces. "
"Bør være et bilde eller en illustrasjon uten tekst." "Should be a photo or an illustration without too much text."
), ),
) )
content_panels = Page.content_panels + [ content_panels = Page.content_panels + [
FieldPanel( FieldPanel(
"excerpt", "excerpt",
heading="Utdrag", heading=_("Excerpt"),
help_text="En veldig kort oppsummering av innholdet i artikkelen. Brukes på forsiden og i artikkeloversikten.", help_text=_(
"A very short summary of the article's content. "
"Used on the front page and in the article listing."
),
), ),
FieldPanel("featured_image"), FieldPanel("featured_image"),
FieldPanel( FieldPanel(
"lead", "lead",
heading="Ingress", heading=_("Lead"),
help_text="Et kortfattet, innledende avsnitt som oppsummerer hovedinnholdet i artikkelen.", help_text=_(
"A brief, introductory paragraph that summarizes the main content of the article."
),
), ),
FieldPanel("body"), FieldPanel("body"),
] ]
@@ -77,6 +87,10 @@ class NewsPage(HeadlessMixin, WPImportedPageMixin, Page):
index.SearchField("body"), index.SearchField("body"),
] ]
class Meta:
verbose_name = _("news article")
verbose_name_plural = _("news articles")
def import_wordpress_data(self, data): def import_wordpress_data(self, data):
import html import html
+8
View File
@@ -0,0 +1,8 @@
from wagtail import hooks
from .admin import news_page_listing_viewset
@hooks.register("register_admin_viewset")
def register_news_page_listing_viewset():
return news_page_listing_viewset
+6
View File
@@ -1,3 +1,4 @@
from news.admin import NewsPageListingViewSet
from news.models import NewsPage from news.models import NewsPage
from tests.conftest import NewsPageFactory from tests.conftest import NewsPageFactory
@@ -10,6 +11,11 @@ def test_news_page_persists_via_factory(news_index):
assert reloaded.excerpt == "Short summary" assert reloaded.excerpt == "Short summary"
def test_news_listing_viewset_wired_to_newspage():
assert NewsPageListingViewSet.model is NewsPage
assert NewsPageListingViewSet.add_to_admin_menu is True
def test_graphql_news_index_query(news_index, graphql_post): def test_graphql_news_index_query(news_index, graphql_post):
response, body = graphql_post( response, body = graphql_post(
""" """