filter on future events when fetching for home page / event index
This commit is contained in:
@ -1,7 +1,9 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Min, Q
|
||||||
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from grapple.helpers import register_query_field
|
from grapple.helpers import register_query_field, register_singular_query_field
|
||||||
from grapple.models import (
|
from grapple.models import (
|
||||||
GraphQLBoolean,
|
GraphQLBoolean,
|
||||||
GraphQLCollection,
|
GraphQLCollection,
|
||||||
@ -25,17 +27,31 @@ from wagtail.admin.panels import (
|
|||||||
)
|
)
|
||||||
from wagtail.fields import StreamField
|
from wagtail.fields import StreamField
|
||||||
from wagtail.images.blocks import ImageChooserBlock
|
from wagtail.images.blocks import ImageChooserBlock
|
||||||
from wagtail.models import Orderable, Page
|
from wagtail.models import Orderable, Page, PageManager, PageQuerySet
|
||||||
from wagtail.snippets.models import register_snippet
|
from wagtail.snippets.models import register_snippet
|
||||||
|
|
||||||
from venues.models import VenuePage
|
from venues.models import VenuePage
|
||||||
|
|
||||||
|
|
||||||
|
@register_singular_query_field("eventIndex")
|
||||||
class EventIndex(Page):
|
class EventIndex(Page):
|
||||||
# there can only be one event index page
|
|
||||||
max_count = 1
|
max_count = 1
|
||||||
subpage_types = ["events.EventPage"]
|
subpage_types = ["events.EventPage"]
|
||||||
|
|
||||||
|
def future_events(self, info, **kwargs):
|
||||||
|
return EventPage.objects.future().order_by("next_occurrence")
|
||||||
|
|
||||||
|
graphql_fields = [
|
||||||
|
GraphQLCollection(
|
||||||
|
GraphQLForeignKey,
|
||||||
|
"future_events",
|
||||||
|
"events.EventPage",
|
||||||
|
required=True,
|
||||||
|
item_required=True,
|
||||||
|
is_queryset=True,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@register_snippet
|
@register_snippet
|
||||||
@register_query_field("eventCategory", "eventCategories")
|
@register_query_field("eventCategory", "eventCategories")
|
||||||
@ -108,23 +124,22 @@ class EventOrganizer(ClusterableModel):
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class EventPageQuerySet(PageQuerySet):
|
||||||
|
def future(self):
|
||||||
|
today = timezone.localtime(timezone.now()).date()
|
||||||
|
next_occurrence = Min("occurrences__start", filter=Q(occurrences__start__gte=today))
|
||||||
|
return self.filter(occurrences__start__gte=today).annotate(next_occurrence=next_occurrence)
|
||||||
|
|
||||||
|
|
||||||
|
EventPageManager = PageManager.from_queryset(EventPageQuerySet)
|
||||||
|
|
||||||
|
|
||||||
class EventPage(Page):
|
class EventPage(Page):
|
||||||
# no children
|
|
||||||
subpage_types = []
|
subpage_types = []
|
||||||
parent_page_types = ["events.EventIndex"]
|
parent_page_types = ["events.EventIndex"]
|
||||||
# should not be able to be shown in menus
|
|
||||||
show_in_menus = False
|
show_in_menus = False
|
||||||
|
|
||||||
# inherited from Page:
|
objects = EventPageManager()
|
||||||
# title = text
|
|
||||||
# slug = text (in promote panel)
|
|
||||||
# content_type = points to this model
|
|
||||||
# live = bool
|
|
||||||
# owner = page creator
|
|
||||||
# first_published_at = datetime
|
|
||||||
# last_published_at = datetime
|
|
||||||
# seo_title: text (in promote panel)
|
|
||||||
# search_description: text (in promote panel)
|
|
||||||
|
|
||||||
featured_image = models.ForeignKey(
|
featured_image = models.ForeignKey(
|
||||||
"images.CustomImage",
|
"images.CustomImage",
|
||||||
@ -167,8 +182,6 @@ class EventPage(Page):
|
|||||||
help_text="Lenke direkte til arrangementet på Facebook",
|
help_text="Lenke direkte til arrangementet på Facebook",
|
||||||
)
|
)
|
||||||
|
|
||||||
# "event_organizers": [390, 322],
|
|
||||||
|
|
||||||
price_regular = models.IntegerField(null=True, blank=True)
|
price_regular = models.IntegerField(null=True, blank=True)
|
||||||
price_student = models.IntegerField(null=True, blank=True)
|
price_student = models.IntegerField(null=True, blank=True)
|
||||||
price_member = models.IntegerField(null=True, blank=True)
|
price_member = models.IntegerField(null=True, blank=True)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { getClient } from "@/app/client";
|
import { getClient } from "@/app/client";
|
||||||
import { EventContainer } from "@/components/events/EventContainer";
|
import { EventContainer } from "@/components/events/EventContainer";
|
||||||
import {
|
import {
|
||||||
allEventsQuery,
|
futureEventsQuery,
|
||||||
EventFragment,
|
EventFragment,
|
||||||
EventCategory,
|
EventCategory,
|
||||||
EventOccurrence,
|
EventOccurrence,
|
||||||
@ -10,8 +10,8 @@ import { PageHeader } from "@/components/general/PageHeader";
|
|||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const { data, error } = await getClient().query(allEventsQuery, {});
|
const { data, error } = await getClient().query(futureEventsQuery, {});
|
||||||
const events = (data?.events ?? []) as EventFragment[];
|
const events = (data?.events?.futureEvents ?? []) as EventFragment[];
|
||||||
const eventCategories = (data?.eventCategories ?? []) as EventCategory[];
|
const eventCategories = (data?.eventCategories ?? []) as EventCategory[];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,9 +19,15 @@ const HomeFragmentDefinition = graphql(`
|
|||||||
export default async function Home() {
|
export default async function Home() {
|
||||||
const homeQuery = graphql(`
|
const homeQuery = graphql(`
|
||||||
query home {
|
query home {
|
||||||
events: pages(contentType: "events.EventPage") {
|
events: eventIndex {
|
||||||
|
... on EventIndex {
|
||||||
|
futureEvents {
|
||||||
|
... on EventPage {
|
||||||
...Event
|
...Event
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
home: page(contentType: "home.HomePage", urlPath: "/home/") {
|
home: page(contentType: "home.HomePage", urlPath: "/home/") {
|
||||||
... on HomePage {
|
... on HomePage {
|
||||||
...Home
|
...Home
|
||||||
@ -30,7 +36,7 @@ export default async function Home() {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
const { data, error } = await getClient().query(homeQuery, {});
|
const { data, error } = await getClient().query(homeQuery, {});
|
||||||
const events = (data?.events ?? []) as EventFragment[];
|
const events = (data?.events?.futureEvents ?? []) as EventFragment[];
|
||||||
const home = (data?.home ?? []) as HomeFragment;
|
const home = (data?.home ?? []) as HomeFragment;
|
||||||
|
|
||||||
const featuredEventIds = home.featuredEvents.map((x) => x.id);
|
const featuredEventIds = home.featuredEvents.map((x) => x.id);
|
||||||
|
@ -28,11 +28,11 @@ const documents = {
|
|||||||
"\n fragment Venue on VenuePage {\n __typename\n id\n slug\n title\n body {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n }\n featuredImage {\n ...Image\n }\n showAsBookable\n floor\n preposition\n capabilityAudio\n capabilityAudioVideo\n capabilityBar\n capabilityLighting\n capacityLegal\n capacityStanding\n capacitySitting\n }\n": types.VenueFragmentDoc,
|
"\n fragment Venue on VenuePage {\n __typename\n id\n slug\n title\n body {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n }\n featuredImage {\n ...Image\n }\n showAsBookable\n floor\n preposition\n capabilityAudio\n capabilityAudioVideo\n capabilityBar\n capabilityLighting\n capacityLegal\n capacityStanding\n capacitySitting\n }\n": types.VenueFragmentDoc,
|
||||||
"\n query allVenues {\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n ...Venue\n }\n }\n }\n ": types.AllVenuesDocument,
|
"\n query allVenues {\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n ...Venue\n }\n }\n }\n ": types.AllVenuesDocument,
|
||||||
"\n fragment Home on HomePage {\n ... on HomePage {\n featuredEvents {\n id\n }\n }\n }\n": types.HomeFragmentDoc,
|
"\n fragment Home on HomePage {\n ... on HomePage {\n featuredEvents {\n id\n }\n }\n }\n": types.HomeFragmentDoc,
|
||||||
"\n query home {\n events: pages(contentType: \"events.EventPage\") {\n ...Event\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n }\n ": types.HomeDocument,
|
"\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n }\n ": types.HomeDocument,
|
||||||
"\n fragment Blocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n ... on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n ... on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n }\n": types.BlocksFragmentDoc,
|
"\n fragment Blocks on StreamFieldInterface {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n ... on ImageWithTextBlock {\n image {\n ...Image\n }\n imageFormat\n text\n }\n ... on ImageSliderBlock {\n images {\n ... on ImageSliderItemBlock {\n image {\n ...Image\n }\n text\n }\n }\n }\n }\n": types.BlocksFragmentDoc,
|
||||||
"\n fragment Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\n }\n": types.ImageFragmentDoc,
|
"\n fragment Image on CustomImage {\n id\n url\n width\n height\n alt\n attribution\n }\n": types.ImageFragmentDoc,
|
||||||
"\n fragment Event on EventPage {\n __typename\n id\n slug\n title\n body {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n }\n featuredImage {\n ...Image\n }\n facebookUrl\n ticketUrl\n priceRegular\n priceMember\n priceStudent\n categories {\n ... on EventCategory {\n name\n slug\n }\n }\n occurrences {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n venue {\n __typename\n id\n slug\n title\n }\n }\n }\n }\n": types.EventFragmentDoc,
|
"\n fragment Event on EventPage {\n __typename\n id\n slug\n title\n body {\n id\n blockType\n field\n ... on RichTextBlock {\n rawValue\n value\n }\n }\n featuredImage {\n ...Image\n }\n facebookUrl\n ticketUrl\n priceRegular\n priceMember\n priceStudent\n categories {\n ... on EventCategory {\n name\n slug\n }\n }\n occurrences {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n venue {\n __typename\n id\n slug\n title\n }\n }\n }\n }\n": types.EventFragmentDoc,
|
||||||
"\n query allEvents {\n events: pages(contentType: \"events.EventPage\") {\n ... on EventPage {\n ...Event\n }\n }\n eventCategories: eventCategories {\n ... on EventCategory {\n name\n slug\n showInFilters\n }\n }\n }\n": types.AllEventsDocument,
|
"\n query futureEvents {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories {\n ... on EventCategory {\n name\n slug\n showInFilters\n }\n }\n }\n": types.FutureEventsDocument,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,7 +112,7 @@ export function graphql(source: "\n fragment Home on HomePage {\n ... on Hom
|
|||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n query home {\n events: pages(contentType: \"events.EventPage\") {\n ...Event\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n }\n "): (typeof documents)["\n query home {\n events: pages(contentType: \"events.EventPage\") {\n ...Event\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n }\n "];
|
export function graphql(source: "\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n }\n "): (typeof documents)["\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n }\n "];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
@ -128,7 +128,7 @@ export function graphql(source: "\n fragment Event on EventPage {\n __typena
|
|||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n query allEvents {\n events: pages(contentType: \"events.EventPage\") {\n ... on EventPage {\n ...Event\n }\n }\n eventCategories: eventCategories {\n ... on EventCategory {\n name\n slug\n showInFilters\n }\n }\n }\n"): (typeof documents)["\n query allEvents {\n events: pages(contentType: \"events.EventPage\") {\n ... on EventPage {\n ...Event\n }\n }\n eventCategories: eventCategories {\n ... on EventCategory {\n name\n slug\n showInFilters\n }\n }\n }\n"];
|
export function graphql(source: "\n query futureEvents {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories {\n ... on EventCategory {\n name\n slug\n showInFilters\n }\n }\n }\n"): (typeof documents)["\n query futureEvents {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories {\n ... on EventCategory {\n name\n slug\n showInFilters\n }\n }\n }\n"];
|
||||||
|
|
||||||
export function graphql(source: string) {
|
export function graphql(source: string) {
|
||||||
return (documents as any)[source] ?? {};
|
return (documents as any)[source] ?? {};
|
||||||
|
File diff suppressed because one or more lines are too long
@ -68,13 +68,17 @@ const EventFragmentDefinition = graphql(`
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
export const allEventsQuery = graphql(`
|
export const futureEventsQuery = graphql(`
|
||||||
query allEvents {
|
query futureEvents {
|
||||||
events: pages(contentType: "events.EventPage") {
|
events: eventIndex {
|
||||||
|
... on EventIndex {
|
||||||
|
futureEvents {
|
||||||
... on EventPage {
|
... on EventPage {
|
||||||
...Event
|
...Event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
eventCategories: eventCategories {
|
eventCategories: eventCategories {
|
||||||
... on EventCategory {
|
... on EventCategory {
|
||||||
name
|
name
|
||||||
|
Reference in New Issue
Block a user