Compare commits
2 Commits
4a264c589d
...
447e1bd3ff
| Author | SHA1 | Date | |
|---|---|---|---|
| 447e1bd3ff | |||
| 29c61ffc76 |
@@ -0,0 +1,46 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from wagtail.admin.ui.tables import Column, DateColumn
|
||||
from wagtail.admin.ui.tables.pages import PageStatusColumn, PageTitleColumn
|
||||
from wagtail.admin.viewsets.pages import PageListingViewSet
|
||||
|
||||
from associations.models import AssociationPage
|
||||
from dnscms.admin import ListingRedirectChooseParentView
|
||||
|
||||
|
||||
class AssociationTypeColumn(Column):
|
||||
def get_value(self, instance):
|
||||
return instance.get_association_type_display()
|
||||
|
||||
|
||||
class AssociationChooseParentView(ListingRedirectChooseParentView):
|
||||
listing_url_name = "associations:index"
|
||||
|
||||
|
||||
class AssociationPageListingViewSet(PageListingViewSet):
|
||||
model = AssociationPage
|
||||
choose_parent_view_class = AssociationChooseParentView
|
||||
icon = "group"
|
||||
menu_label = _("Associations")
|
||||
menu_order = 2
|
||||
add_to_admin_menu = True
|
||||
ordering = "title"
|
||||
|
||||
columns = [
|
||||
PageTitleColumn("title", label=_("Title"), sort_key="title", classname="title"),
|
||||
AssociationTypeColumn(
|
||||
"association_type",
|
||||
label=_("Type"),
|
||||
sort_key="association_type",
|
||||
width="15%",
|
||||
),
|
||||
DateColumn(
|
||||
"latest_revision_created_at",
|
||||
label=_("Updated"),
|
||||
sort_key="latest_revision_created_at",
|
||||
width="10%",
|
||||
),
|
||||
PageStatusColumn("status", label=_("Status"), sort_key="live", width="10%"),
|
||||
]
|
||||
|
||||
|
||||
association_page_listing_viewset = AssociationPageListingViewSet("associations")
|
||||
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 6.0.5 on 2026-05-19 19:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('associations', '0025_associationpage_lead'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='associationindex',
|
||||
options={'verbose_name': 'association index', 'verbose_name_plural': 'association indexes'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='associationpage',
|
||||
options={'verbose_name': 'association', 'verbose_name_plural': 'associations'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='associationpage',
|
||||
name='association_type',
|
||||
field=models.CharField(choices=[('forening', 'Association'), ('utvalg', 'Committee')], default='forening', max_length=64),
|
||||
),
|
||||
]
|
||||
@@ -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,
|
||||
@@ -26,8 +27,8 @@ class AssociationIndex(HeadlessMixin, Page):
|
||||
body = CommonStreamField
|
||||
|
||||
content_panels = Page.content_panels + [
|
||||
FieldPanel("lead", heading="Ingress"),
|
||||
FieldPanel("body", heading="Innhold"),
|
||||
FieldPanel("lead", heading=_("Lead")),
|
||||
FieldPanel("body", heading=_("Content")),
|
||||
]
|
||||
|
||||
graphql_fields = [
|
||||
@@ -37,6 +38,10 @@ class AssociationIndex(HeadlessMixin, Page):
|
||||
|
||||
search_fields = Page.search_fields
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("association index")
|
||||
verbose_name_plural = _("association indexes")
|
||||
|
||||
|
||||
class AssociationPage(HeadlessMixin, WPImportedPageMixin, Page):
|
||||
subpage_types = []
|
||||
@@ -44,8 +49,8 @@ class AssociationPage(HeadlessMixin, WPImportedPageMixin, Page):
|
||||
show_in_menus = False
|
||||
|
||||
class AssociationType(models.TextChoices):
|
||||
FORENING = "forening", "Forening"
|
||||
UTVALG = "utvalg", "Utvalg"
|
||||
FORENING = "forening", _("Association")
|
||||
UTVALG = "utvalg", _("Committee")
|
||||
|
||||
excerpt = models.TextField(max_length=512, blank=False)
|
||||
lead = RichTextField(features=["italic", "link"], blank=True)
|
||||
@@ -65,14 +70,14 @@ class AssociationPage(HeadlessMixin, WPImportedPageMixin, Page):
|
||||
content_panels = Page.content_panels + [
|
||||
FieldPanel(
|
||||
"excerpt",
|
||||
heading="Utdrag",
|
||||
help_text="En veldig kort oppsummering av innholdet nedenfor. Brukes i listevisninger.",
|
||||
heading=_("Excerpt"),
|
||||
help_text=_("A very short summary of the content below. Used in listing views."),
|
||||
),
|
||||
FieldPanel("lead", heading="Ingress"),
|
||||
FieldPanel("body", heading="Innhold"),
|
||||
FieldPanel("lead", heading=_("Lead")),
|
||||
FieldPanel("body", heading=_("Content")),
|
||||
FieldPanel("logo"),
|
||||
FieldPanel("association_type", heading="Type"),
|
||||
FieldPanel("website_url", heading="Nettside"),
|
||||
FieldPanel("association_type", heading=_("Type")),
|
||||
FieldPanel("website_url", heading=_("Website")),
|
||||
]
|
||||
|
||||
graphql_fields = [
|
||||
@@ -89,6 +94,10 @@ class AssociationPage(HeadlessMixin, WPImportedPageMixin, Page):
|
||||
index.SearchField("body"),
|
||||
]
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("association")
|
||||
verbose_name_plural = _("associations")
|
||||
|
||||
def import_wordpress_data(self, data):
|
||||
import html
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from wagtail.admin.viewsets.chooser import ChooserViewSet
|
||||
|
||||
|
||||
class AssociationChooserViewSet(ChooserViewSet):
|
||||
model = "associations.AssociationPage"
|
||||
icon = "group"
|
||||
choose_one_text = "Choose an association"
|
||||
choose_another_text = "Choose another association"
|
||||
edit_item_text = "Edit this association"
|
||||
choose_one_text = _("Choose an association")
|
||||
choose_another_text = _("Choose another association")
|
||||
edit_item_text = _("Edit this association")
|
||||
# form_fields = ["name"]
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
from wagtail import hooks
|
||||
|
||||
from .admin import association_page_listing_viewset
|
||||
from .views import association_chooser_viewset
|
||||
|
||||
|
||||
@hooks.register("register_admin_viewset")
|
||||
def register_viewset():
|
||||
return association_chooser_viewset
|
||||
|
||||
|
||||
@hooks.register("register_admin_viewset")
|
||||
def register_association_page_listing_viewset():
|
||||
return association_page_listing_viewset
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.urls import reverse
|
||||
from wagtail.admin.views.pages.choose_parent import ChooseParentView
|
||||
|
||||
|
||||
class ListingRedirectChooseParentView(ChooseParentView):
|
||||
"""ChooseParentView that redirects new pages back to a listing viewset.
|
||||
|
||||
Subclasses set ``listing_url_name`` (e.g. ``"events:index"``).
|
||||
"""
|
||||
|
||||
listing_url_name: str
|
||||
|
||||
def _with_next(self, response):
|
||||
if response.status_code != 302:
|
||||
return response
|
||||
url = response["Location"]
|
||||
sep = "&" if "?" in url else "?"
|
||||
response["Location"] = f"{url}{sep}{urlencode({'next': reverse(self.listing_url_name)})}"
|
||||
return response
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self._with_next(super().get(request, *args, **kwargs))
|
||||
|
||||
def form_valid(self, form):
|
||||
return self._with_next(super().form_valid(form))
|
||||
@@ -1,12 +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 associations.models import AssociationIndex
|
||||
from news.models import NewsIndex
|
||||
|
||||
|
||||
@hooks.register("register_rich_text_features")
|
||||
@@ -14,24 +8,6 @@ def enable_additional_rich_text_features(features):
|
||||
features.default_features.extend(["h5", "h6", "blockquote"])
|
||||
|
||||
|
||||
@hooks.register("register_admin_menu_item")
|
||||
def register_associations_menu_item():
|
||||
page = AssociationIndex.objects.first()
|
||||
associations_url = "#"
|
||||
if page:
|
||||
associations_url = reverse("wagtailadmin_explore", args=(quote(page.pk),))
|
||||
return MenuItem("Foreninger", associations_url, icon_name="group", order=2)
|
||||
|
||||
|
||||
@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):
|
||||
|
||||
+3
-20
@@ -1,15 +1,12 @@
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext, gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
from wagtail.admin.ui.tables import Column, DateColumn
|
||||
from wagtail.admin.ui.tables.pages import PageStatusColumn, PageTitleColumn
|
||||
from wagtail.admin.views.pages.choose_parent import ChooseParentView
|
||||
from wagtail.admin.views.pages.listing import IndexView
|
||||
from wagtail.admin.viewsets.pages import PageListingViewSet
|
||||
|
||||
from dnscms.admin import ListingRedirectChooseParentView
|
||||
from events.models import EventPage
|
||||
|
||||
|
||||
@@ -44,22 +41,8 @@ class EventPageIndexView(IndexView):
|
||||
)
|
||||
|
||||
|
||||
class EventChooseParentView(ChooseParentView):
|
||||
"""Redirect newly-created EventPages back to the events listing."""
|
||||
|
||||
def _with_next(self, response):
|
||||
if response.status_code != 302:
|
||||
return response
|
||||
url = response["Location"]
|
||||
sep = "&" if "?" in url else "?"
|
||||
response["Location"] = f"{url}{sep}{urlencode({'next': reverse('events:index')})}"
|
||||
return response
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self._with_next(super().get(request, *args, **kwargs))
|
||||
|
||||
def form_valid(self, form):
|
||||
return self._with_next(super().form_valid(form))
|
||||
class EventChooseParentView(ListingRedirectChooseParentView):
|
||||
listing_url_name = "events:index"
|
||||
|
||||
|
||||
class EventPageListingViewSet(PageListingViewSet):
|
||||
|
||||
Binary file not shown.
@@ -7,48 +7,114 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: dnscms\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-19 21:17+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"
|
||||
|
||||
#: events/admin.py:23
|
||||
#: associations/admin.py:23
|
||||
msgid "Associations"
|
||||
msgstr "Foreninger"
|
||||
|
||||
#: associations/admin.py:29 events/admin.py:59 news/admin.py:24
|
||||
msgid "Title"
|
||||
msgstr "Tittel"
|
||||
|
||||
#: associations/admin.py:32 associations/models.py:79
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
||||
#: associations/admin.py:38 events/admin.py:64 news/admin.py:27
|
||||
msgid "Updated"
|
||||
msgstr "Oppdatert"
|
||||
|
||||
#: associations/admin.py:42 events/admin.py:68 news/admin.py:31
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
#: 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:77
|
||||
msgid "Content"
|
||||
msgstr "Innhold"
|
||||
|
||||
#: associations/models.py:42
|
||||
msgid "association index"
|
||||
msgstr "foreningsoversikt"
|
||||
|
||||
#: associations/models.py:43
|
||||
msgid "association indexes"
|
||||
msgstr "foreningsoversikter"
|
||||
|
||||
#: associations/models.py:52
|
||||
msgid "Association"
|
||||
msgstr "Forening"
|
||||
|
||||
#: associations/models.py:53
|
||||
msgid "Committee"
|
||||
msgstr "Utvalg"
|
||||
|
||||
#: associations/models.py:73 news/models.py:60
|
||||
msgid "Excerpt"
|
||||
msgstr "Utdrag"
|
||||
|
||||
#: 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."
|
||||
|
||||
#: associations/models.py:80 events/models.py:189
|
||||
msgid "Website"
|
||||
msgstr "Nettsted"
|
||||
|
||||
#: associations/models.py:98
|
||||
msgid "association"
|
||||
msgstr "forening"
|
||||
|
||||
#: associations/models.py:99
|
||||
msgid "associations"
|
||||
msgstr "foreninger"
|
||||
|
||||
#: associations/views.py:8
|
||||
msgid "Choose an association"
|
||||
msgstr "Velg en forening"
|
||||
|
||||
#: associations/views.py:9
|
||||
msgid "Choose another association"
|
||||
msgstr "Velg en annen forening"
|
||||
|
||||
#: associations/views.py:10
|
||||
msgid "Edit this association"
|
||||
msgstr "Rediger denne foreningen"
|
||||
|
||||
#: 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:76
|
||||
msgid "Title"
|
||||
msgstr "Tittel"
|
||||
|
||||
#: events/admin.py:77
|
||||
#: events/admin.py:60
|
||||
msgid "Date"
|
||||
msgstr "Dato"
|
||||
|
||||
#: events/admin.py:78 events/models.py:333
|
||||
#: events/admin.py:61 events/models.py:331
|
||||
msgid "Organizers"
|
||||
msgstr "Arrangører"
|
||||
|
||||
#: events/admin.py:81
|
||||
msgid "Updated"
|
||||
msgstr "Oppdatert"
|
||||
|
||||
#: events/admin.py:85
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
#: events/models.py:73 events/models.py:156
|
||||
msgid "slug"
|
||||
msgstr "permalenke"
|
||||
@@ -69,7 +135,7 @@ msgstr "Ingen"
|
||||
msgid "Default pig for events of this kind."
|
||||
msgstr "Standardgris for arrangementer av denne typen."
|
||||
|
||||
#: events/models.py:98 events/models.py:343
|
||||
#: events/models.py:98 events/models.py:341
|
||||
msgid "Pig"
|
||||
msgstr "Gris"
|
||||
|
||||
@@ -109,10 +175,6 @@ msgstr "Intern arrangør"
|
||||
msgid "External organizer"
|
||||
msgstr "Ekstern arrangør"
|
||||
|
||||
#: events/models.py:189
|
||||
msgid "Website"
|
||||
msgstr "Nettsted"
|
||||
|
||||
#: events/models.py:190
|
||||
msgid "Leave this empty if the organizer exists in the list above."
|
||||
msgstr "La denne stå tom om arrangøren finnes i lista over."
|
||||
@@ -157,33 +219,34 @@ msgstr ""
|
||||
|
||||
#: events/models.py:284
|
||||
msgid "Direct link to ticket purchase, e.g. TicketCo, Billetto or Ticketmaster"
|
||||
msgstr "Lenke direkte til billettkjøp, f.eks. TicketCo, Billetto eller Ticketmaster"
|
||||
msgstr ""
|
||||
"Lenke direkte til billettkjøp, f.eks. TicketCo, Billetto eller Ticketmaster"
|
||||
|
||||
#: events/models.py:289
|
||||
msgid "Direct link to the event on Facebook"
|
||||
msgstr "Lenke direkte til arrangementet på Facebook"
|
||||
|
||||
#: events/models.py:299
|
||||
#: events/models.py:298
|
||||
msgid "Free"
|
||||
msgstr "Gratis"
|
||||
|
||||
#: events/models.py:299
|
||||
#: events/models.py:298
|
||||
msgid "Is this event free for everyone?"
|
||||
msgstr "Er dette arrangementet gratis for alle?"
|
||||
|
||||
#: events/models.py:305
|
||||
#: events/models.py:303
|
||||
msgid "Regular price"
|
||||
msgstr "Ordinær pris"
|
||||
|
||||
#: events/models.py:306
|
||||
#: events/models.py:304
|
||||
msgid "Price for students"
|
||||
msgstr "Pris for studenter"
|
||||
|
||||
#: events/models.py:307
|
||||
#: events/models.py:305
|
||||
msgid "Price for DNS members"
|
||||
msgstr "Pris for medlemmer av DNS"
|
||||
|
||||
#: events/models.py:314
|
||||
#: events/models.py:312
|
||||
msgid ""
|
||||
"Write <strong>0</strong> for free. An empty field hides the price category. "
|
||||
"If possible, write digits only."
|
||||
@@ -191,59 +254,57 @@ msgstr ""
|
||||
"Skriv <strong>0</strong> om gratis. Tomt felt skjuler priskategorien. Om "
|
||||
"mulig, skriv kun tall."
|
||||
|
||||
#: events/models.py:323
|
||||
#: events/models.py:321
|
||||
msgid "Ticket purchase link"
|
||||
msgstr "Billettkjøpslenke"
|
||||
|
||||
#: events/models.py:327
|
||||
#: events/models.py:325
|
||||
msgid "Subtitle"
|
||||
msgstr "Undertittel"
|
||||
|
||||
#: events/models.py:329
|
||||
msgid "Lead"
|
||||
msgstr "Ingress"
|
||||
|
||||
#: events/models.py:336
|
||||
#: events/models.py:334
|
||||
msgid "Who is behind the event?"
|
||||
msgstr "Hvem står bak arrangementet?"
|
||||
|
||||
#: events/models.py:339
|
||||
#: events/models.py:337
|
||||
msgid "Organizer"
|
||||
msgstr "Arrangør"
|
||||
|
||||
#: events/models.py:346
|
||||
#: events/models.py:344
|
||||
msgid "Facebook link"
|
||||
msgstr "Facebook-lenke"
|
||||
|
||||
#: events/models.py:347
|
||||
#: events/models.py:345
|
||||
msgid "Direct link to the event on Facebook."
|
||||
msgstr "Lenke direkte til arrangementet på Facebook."
|
||||
|
||||
#: events/models.py:349
|
||||
#: events/models.py:347
|
||||
msgid "Pricing and tickets"
|
||||
msgstr "Priser og billettkjøp"
|
||||
|
||||
#: events/models.py:351
|
||||
#: events/models.py:349
|
||||
msgid "Date, time and venue"
|
||||
msgstr "Dato, tid og lokale"
|
||||
|
||||
#: events/models.py:355
|
||||
#: events/models.py:353
|
||||
msgid "If the event spans several days, add each day as a separate occurrence."
|
||||
msgstr "Om arrangementet går over flere dager, legg inn hver dag som en egen forekomst."
|
||||
msgstr ""
|
||||
"Om arrangementet går over flere dager, legg inn hver dag som en egen "
|
||||
"forekomst."
|
||||
|
||||
#: events/models.py:359
|
||||
#: events/models.py:356
|
||||
msgid "Occurrence"
|
||||
msgstr "Forekomst"
|
||||
|
||||
#: events/models.py:402
|
||||
#: events/models.py:399
|
||||
msgid "event"
|
||||
msgstr "arrangement"
|
||||
|
||||
#: events/models.py:403
|
||||
#: events/models.py:400
|
||||
msgid "events"
|
||||
msgstr "arrangementer"
|
||||
|
||||
#: events/models.py:563
|
||||
#: events/models.py:560
|
||||
msgid ""
|
||||
"Use this <em>if none of the venues that can be selected on the left</em> "
|
||||
"fit. E.g. <em>Frederikkeplassen</em> or <em>Sirkusteltet</em>."
|
||||
@@ -251,35 +312,35 @@ msgstr ""
|
||||
"Bruk denne <em>om ingen av lokalene som kan velges til venstre</em> passer. "
|
||||
"F.eks. <em>Frederikkeplassen</em> eller <em>Sirkusteltet</em>."
|
||||
|
||||
#: events/models.py:572
|
||||
#: events/models.py:569
|
||||
msgid "Start"
|
||||
msgstr "Start"
|
||||
|
||||
#: events/models.py:573
|
||||
#: events/models.py:570
|
||||
msgid "End"
|
||||
msgstr "Slutt"
|
||||
|
||||
#: events/models.py:578
|
||||
#: events/models.py:575
|
||||
msgid "Venue"
|
||||
msgstr "Lokale"
|
||||
|
||||
#: events/models.py:579
|
||||
#: events/models.py:576
|
||||
msgid "Venue as free text"
|
||||
msgstr "Lokale som fritekst"
|
||||
|
||||
#: events/models.py:596
|
||||
#: events/models.py:593
|
||||
msgid "You can't both pick a venue and write something in this field."
|
||||
msgstr "Du kan ikke både velge et lokale og skrive noe i dette feltet."
|
||||
|
||||
#: events/models.py:601
|
||||
#: events/models.py:598
|
||||
msgid "Venue is required."
|
||||
msgstr "Lokale er påkrevd."
|
||||
|
||||
#: events/models.py:607
|
||||
#: events/models.py:604
|
||||
msgid "occurrence"
|
||||
msgstr "forekomst"
|
||||
|
||||
#: events/models.py:608
|
||||
#: events/models.py:605
|
||||
msgid "occurrences"
|
||||
msgstr "forekomster"
|
||||
|
||||
@@ -306,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"
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,53 @@
|
||||
from associations.admin import AssociationTypeColumn
|
||||
from associations.models import AssociationPage
|
||||
from tests.conftest import AssociationPageFactory
|
||||
|
||||
|
||||
def test_associationpage_persists_via_factory(association_index):
|
||||
page = AssociationPageFactory(
|
||||
parent=association_index,
|
||||
title="EDB-gjengen",
|
||||
excerpt="WOW FLINKE",
|
||||
association_type=AssociationPage.AssociationType.UTVALG,
|
||||
)
|
||||
|
||||
reloaded = AssociationPage.objects.get(pk=page.pk)
|
||||
assert reloaded.title == "EDB-gjengen"
|
||||
assert reloaded.excerpt == "WOW FLINKE"
|
||||
assert reloaded.association_type == "utvalg"
|
||||
|
||||
|
||||
def test_association_type_column_renders_forening_display(association_index):
|
||||
page = AssociationPageFactory(
|
||||
parent=association_index,
|
||||
association_type=AssociationPage.AssociationType.FORENING,
|
||||
)
|
||||
column = AssociationTypeColumn("association_type")
|
||||
|
||||
assert column.get_value(page) == "Forening"
|
||||
|
||||
|
||||
def test_association_type_column_renders_utvalg_display(association_index):
|
||||
page = AssociationPageFactory(
|
||||
parent=association_index,
|
||||
association_type=AssociationPage.AssociationType.UTVALG,
|
||||
)
|
||||
column = AssociationTypeColumn("association_type")
|
||||
|
||||
assert column.get_value(page) == "Utvalg"
|
||||
|
||||
|
||||
def test_graphql_association_index_query(association_index, graphql_post):
|
||||
response, body = graphql_post(
|
||||
"""
|
||||
query {
|
||||
associationIndex {
|
||||
title
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "errors" not in body, body
|
||||
assert body["data"]["associationIndex"]["title"] == association_index.title
|
||||
@@ -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(
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user