diff --git a/dnscms/dnscms/wagtail_hooks.py b/dnscms/dnscms/wagtail_hooks.py index 7ab829d..a71a06c 100644 --- a/dnscms/dnscms/wagtail_hooks.py +++ b/dnscms/dnscms/wagtail_hooks.py @@ -1,11 +1,6 @@ -from django.contrib.admin.utils import quote from django.templatetags.static import static -from django.urls import reverse from django.utils.html import format_html from wagtail import hooks -from wagtail.admin.menu import MenuItem - -from news.models import NewsIndex @hooks.register("register_rich_text_features") @@ -13,15 +8,6 @@ def enable_additional_rich_text_features(features): 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") def make_publish_default_action(menu_items, request, context): for index, item in enumerate(menu_items): diff --git a/dnscms/locale/nb/LC_MESSAGES/django.mo b/dnscms/locale/nb/LC_MESSAGES/django.mo index b2952ed..335f88a 100644 Binary files a/dnscms/locale/nb/LC_MESSAGES/django.mo and b/dnscms/locale/nb/LC_MESSAGES/django.mo differ diff --git a/dnscms/locale/nb/LC_MESSAGES/django.po b/dnscms/locale/nb/LC_MESSAGES/django.po index ad3c85e..173340d 100644 --- a/dnscms/locale/nb/LC_MESSAGES/django.po +++ b/dnscms/locale/nb/LC_MESSAGES/django.po @@ -7,38 +7,39 @@ msgid "" msgstr "" "Project-Id-Version: dnscms\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" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: associations/admin.py:40 +#: associations/admin.py:23 msgid "Associations" msgstr "Foreninger" -#: associations/admin.py:46 events/admin.py:76 +#: associations/admin.py:29 events/admin.py:59 news/admin.py:24 msgid "Title" msgstr "Tittel" -#: associations/admin.py:49 associations/models.py:81 +#: associations/admin.py:32 associations/models.py:79 msgid "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" msgstr "Oppdatert" -#: associations/admin.py:59 events/admin.py:85 +#: associations/admin.py:42 events/admin.py:68 news/admin.py:31 msgid "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" msgstr "Ingress" -#: associations/models.py:31 associations/models.py:79 +#: associations/models.py:31 associations/models.py:77 msgid "Content" msgstr "Innhold" @@ -58,23 +59,24 @@ msgstr "Forening" msgid "Committee" msgstr "Utvalg" -#: associations/models.py:73 +#: associations/models.py:73 news/models.py:60 msgid "Excerpt" msgstr "Utdrag" -#: associations/models.py:75 +#: associations/models.py:74 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" msgstr "Nettsted" -#: associations/models.py:100 +#: associations/models.py:98 msgid "association" msgstr "forening" -#: associations/models.py:101 +#: associations/models.py:99 msgid "associations" msgstr "foreninger" @@ -90,26 +92,26 @@ msgstr "Velg en annen forening" msgid "Edit this association" msgstr "Rediger denne foreningen" -#: events/admin.py:23 +#: events/admin.py:20 msgid "%Y-%m-%d at %H:%M" msgstr "%Y-%m-%d kl %H:%M" -#: events/admin.py:25 +#: events/admin.py:22 #, python-format msgid "%(count)d occurrence" msgid_plural "%(count)d occurrences" msgstr[0] "%(count)d forekomst" msgstr[1] "%(count)d forekomster" -#: events/admin.py:70 +#: events/admin.py:53 msgid "Events" msgstr "Arrangementer" -#: events/admin.py:77 +#: events/admin.py:60 msgid "Date" msgstr "Dato" -#: events/admin.py:78 events/models.py:331 +#: events/admin.py:61 events/models.py:331 msgid "Organizers" msgstr "Arrangører" @@ -365,3 +367,47 @@ msgstr "bilde" #: images/models.py:41 msgid "images" 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" diff --git a/dnscms/news/admin.py b/dnscms/news/admin.py new file mode 100644 index 0000000..d7ef908 --- /dev/null +++ b/dnscms/news/admin.py @@ -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") diff --git a/dnscms/news/migrations/0019_alter_news_options.py b/dnscms/news/migrations/0019_alter_news_options.py new file mode 100644 index 0000000..3726ef1 --- /dev/null +++ b/dnscms/news/migrations/0019_alter_news_options.py @@ -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'), + ), + ] diff --git a/dnscms/news/models.py b/dnscms/news/models.py index bd252f1..d226b87 100644 --- a/dnscms/news/models.py +++ b/dnscms/news/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.utils.translation import gettext_lazy as _ from grapple.helpers import register_singular_query_field from grapple.models import GraphQLImage, GraphQLRichText, GraphQLStreamfield, GraphQLString from wagtail.admin.panels import FieldPanel @@ -19,7 +20,7 @@ class NewsIndex(HeadlessMixin, Page): lead = RichTextField(features=["italic", "link"], blank=True) content_panels = Page.content_panels + [ - FieldPanel("lead", heading="Ingress"), + FieldPanel("lead", heading=_("Lead")), ] graphql_fields = [ @@ -28,6 +29,10 @@ class NewsIndex(HeadlessMixin, Page): search_fields = [] + class Meta: + verbose_name = _("news index") + verbose_name_plural = _("news indexes") + class NewsPage(HeadlessMixin, WPImportedPageMixin, Page): subpage_types = [] @@ -43,23 +48,28 @@ class NewsPage(HeadlessMixin, WPImportedPageMixin, Page): blank=True, on_delete=models.SET_NULL, related_name="+", - help_text=( - "Velg et bilde til bruk i på forsiden og andre visningsflater. " - "Bør være et bilde eller en illustrasjon uten tekst." + 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." ), ) content_panels = Page.content_panels + [ FieldPanel( "excerpt", - heading="Utdrag", - help_text="En veldig kort oppsummering av innholdet i artikkelen. Brukes på forsiden og i artikkeloversikten.", + heading=_("Excerpt"), + 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( "lead", - heading="Ingress", - help_text="Et kortfattet, innledende avsnitt som oppsummerer hovedinnholdet i artikkelen.", + heading=_("Lead"), + help_text=_( + "A brief, introductory paragraph that summarizes the main content of the article." + ), ), FieldPanel("body"), ] @@ -77,6 +87,10 @@ class NewsPage(HeadlessMixin, WPImportedPageMixin, Page): index.SearchField("body"), ] + class Meta: + verbose_name = _("news article") + verbose_name_plural = _("news articles") + def import_wordpress_data(self, data): import html diff --git a/dnscms/news/wagtail_hooks.py b/dnscms/news/wagtail_hooks.py new file mode 100644 index 0000000..c9c7b76 --- /dev/null +++ b/dnscms/news/wagtail_hooks.py @@ -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 diff --git a/dnscms/tests/test_news.py b/dnscms/tests/test_news.py index 1594fd3..4dda665 100644 --- a/dnscms/tests/test_news.py +++ b/dnscms/tests/test_news.py @@ -1,3 +1,4 @@ +from news.admin import NewsPageListingViewSet from news.models import NewsPage from tests.conftest import NewsPageFactory @@ -10,6 +11,11 @@ def test_news_page_persists_via_factory(news_index): 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): response, body = graphql_post( """