feature: parish magazine
This commit is contained in:
parent
4c7825ce4e
commit
f85c50757d
9 changed files with 6978 additions and 12 deletions
47
src/collections/Magazine.ts
Normal file
47
src/collections/Magazine.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { CollectionConfig } from 'payload'
|
||||||
|
import { isAdminOrEmployee } from '@/collections/access/admin'
|
||||||
|
|
||||||
|
export const Magazine: CollectionConfig = {
|
||||||
|
slug: 'magazine',
|
||||||
|
labels: {
|
||||||
|
singular: {
|
||||||
|
de: 'Nordlicht Ausgabe'
|
||||||
|
},
|
||||||
|
plural: {
|
||||||
|
de: 'Nordlicht Ausgaben'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'cover',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'media',
|
||||||
|
label: {
|
||||||
|
de: 'Titelblatt'
|
||||||
|
},
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'documents',
|
||||||
|
label: {
|
||||||
|
de: 'PDF-dokument'
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'date',
|
||||||
|
type: 'date',
|
||||||
|
label: {
|
||||||
|
de: 'Datum'
|
||||||
|
},
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
access: {
|
||||||
|
read: () => true,
|
||||||
|
update: isAdminOrEmployee(),
|
||||||
|
delete: isAdminOrEmployee()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -6,9 +6,9 @@ import { Title } from '@/components/Title/Title'
|
||||||
import { NewsletterItem } from '@/compositions/PublicationAndNewsletter/NewsletterItem'
|
import { NewsletterItem } from '@/compositions/PublicationAndNewsletter/NewsletterItem'
|
||||||
import styles from "./styles.module.scss"
|
import styles from "./styles.module.scss"
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import nordlicht from "./nordlicht.png"
|
|
||||||
import envelope from "./envelope.svg"
|
import envelope from "./envelope.svg"
|
||||||
import Sandbox from '@nyariv/sandboxjs'
|
import Sandbox from '@nyariv/sandboxjs'
|
||||||
|
import { fetchLastMagazine } from '@/fetch/magazine'
|
||||||
|
|
||||||
type NewsletterData = {
|
type NewsletterData = {
|
||||||
guid: string,
|
guid: string,
|
||||||
|
|
@ -40,25 +40,33 @@ export const PublicationAndNewsletter = async () => {
|
||||||
console.error("Could not fetch newsletters. Please check PublicationAndNewsletter component")
|
console.error("Could not fetch newsletters. Please check PublicationAndNewsletter component")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const magazine = await fetchLastMagazine();
|
||||||
|
const magazine_url = magazine && typeof magazine.document === "object" ? magazine.document.url || undefined : undefined;
|
||||||
|
const magazine_cover = magazine && typeof magazine.cover === "object" ? magazine.cover : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section backgroundColor={"off-white"}>
|
<Section backgroundColor={"off-white"}>
|
||||||
<Container>
|
<Container>
|
||||||
<Row alignItems={"center"}>
|
<Row alignItems={"center"}>
|
||||||
<Col>
|
<Col>
|
||||||
<a href={"https://storage.googleapis.com/dreikoenige/documents/nordlicht78-web-1.pdf"} target={"_blank"}>
|
{magazine_url && magazine_cover && magazine_cover.url &&
|
||||||
|
<a href={magazine_url} target={'_blank'}>
|
||||||
<Image
|
<Image
|
||||||
className={styles.image}
|
className={styles.image}
|
||||||
src={nordlicht}
|
src={magazine_cover.url}
|
||||||
alt={"Pfarreimagazin Ausgabe 67"}
|
width={magazine_cover.width || 500}
|
||||||
|
height={magazine_cover.height || 600}
|
||||||
|
alt={'Pfarreimagazin Ausgabe'}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</Col>
|
</Col>
|
||||||
<Col>
|
<Col>
|
||||||
<div className={styles.titleContainer}>
|
<div className={styles.titleContainer}>
|
||||||
<Image src={envelope} alt={"Newsletter icon"}/>
|
<Image src={envelope} alt={'Newsletter icon'} />
|
||||||
<Title
|
<Title
|
||||||
title={"Newsletter aus dem Bistum"}
|
title={'Newsletter aus dem Bistum'}
|
||||||
size={"md"}
|
size={'md'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 743 KiB |
27
src/fetch/magazine.ts
Normal file
27
src/fetch/magazine.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { stringify } from 'qs-esm'
|
||||||
|
import { PaginatedDocs } from 'payload'
|
||||||
|
import { Magazine } from '@/payload-types'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously fetches the last magazine entry from the specified API endpoint.
|
||||||
|
*
|
||||||
|
* This function sends a request to the specified API endpoint to fetch the last magazine based on the given sorting criteria.
|
||||||
|
*
|
||||||
|
* @returns {Promise<Magazine | undefined>} A Promise that resolves to the last fetched magazine entry if successful, or undefined if an error occurs.
|
||||||
|
*/
|
||||||
|
export const fetchLastMagazine = async (): Promise<Magazine | undefined> => {
|
||||||
|
|
||||||
|
const stringifiedQuery = stringify(
|
||||||
|
{
|
||||||
|
sort: "-date",
|
||||||
|
limit: 1,
|
||||||
|
},
|
||||||
|
{ addQueryPrefix: true },
|
||||||
|
)
|
||||||
|
|
||||||
|
const response = await fetch(`http://localhost:3000/api/magazine${stringifiedQuery}`)
|
||||||
|
if (!response.ok) return undefined
|
||||||
|
const announcements = await response.json() as PaginatedDocs<Magazine>
|
||||||
|
return announcements.docs[0]
|
||||||
|
|
||||||
|
}
|
||||||
6793
src/migrations/20250827_093559_magazine.json
Normal file
6793
src/migrations/20250827_093559_magazine.json
Normal file
File diff suppressed because it is too large
Load diff
54
src/migrations/20250827_093559_magazine.ts
Normal file
54
src/migrations/20250827_093559_magazine.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||||
|
|
||||||
|
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS "magazine" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"cover_id" uuid NOT NULL,
|
||||||
|
"document_id" uuid NOT NULL,
|
||||||
|
"date" timestamp(3) with time zone NOT NULL,
|
||||||
|
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||||
|
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE "announcement" ALTER COLUMN "date" SET DEFAULT '2025-08-31T09:35:59.090Z';
|
||||||
|
ALTER TABLE "calendar" ALTER COLUMN "date" SET DEFAULT '2025-08-31T09:35:59.222Z';
|
||||||
|
ALTER TABLE "classifieds" ALTER COLUMN "until" SET DEFAULT '2025-09-26T09:35:59.313Z';
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "magazine_id" uuid;
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "magazine" ADD CONSTRAINT "magazine_cover_id_media_id_fk" FOREIGN KEY ("cover_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "magazine" ADD CONSTRAINT "magazine_document_id_documents_id_fk" FOREIGN KEY ("document_id") REFERENCES "public"."documents"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "magazine_cover_idx" ON "magazine" USING btree ("cover_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "magazine_document_idx" ON "magazine" USING btree ("document_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "magazine_updated_at_idx" ON "magazine" USING btree ("updated_at");
|
||||||
|
CREATE INDEX IF NOT EXISTS "magazine_created_at_idx" ON "magazine" USING btree ("created_at");
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_magazine_fk" FOREIGN KEY ("magazine_id") REFERENCES "public"."magazine"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_magazine_id_idx" ON "payload_locked_documents_rels" USING btree ("magazine_id");`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
ALTER TABLE "magazine" DISABLE ROW LEVEL SECURITY;
|
||||||
|
DROP TABLE "magazine" CASCADE;
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_magazine_fk";
|
||||||
|
|
||||||
|
DROP INDEX IF EXISTS "payload_locked_documents_rels_magazine_id_idx";
|
||||||
|
ALTER TABLE "announcement" ALTER COLUMN "date" SET DEFAULT '2025-08-24T14:31:15.010Z';
|
||||||
|
ALTER TABLE "calendar" ALTER COLUMN "date" SET DEFAULT '2025-08-24T14:31:15.092Z';
|
||||||
|
ALTER TABLE "classifieds" ALTER COLUMN "until" SET DEFAULT '2025-09-17T14:31:15.112Z';
|
||||||
|
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "magazine_id";`)
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import * as migration_20250319_101337_donationbox from './20250319_101337_donati
|
||||||
import * as migration_20250322_134918_classifieds from './20250322_134918_classifieds';
|
import * as migration_20250322_134918_classifieds from './20250322_134918_classifieds';
|
||||||
import * as migration_20250608_105124_new_blocks from './20250608_105124_new_blocks';
|
import * as migration_20250608_105124_new_blocks from './20250608_105124_new_blocks';
|
||||||
import * as migration_20250818_143115_menu from './20250818_143115_menu';
|
import * as migration_20250818_143115_menu from './20250818_143115_menu';
|
||||||
|
import * as migration_20250827_093559_magazine from './20250827_093559_magazine';
|
||||||
|
|
||||||
export const migrations = [
|
export const migrations = [
|
||||||
{
|
{
|
||||||
|
|
@ -58,6 +59,11 @@ export const migrations = [
|
||||||
{
|
{
|
||||||
up: migration_20250818_143115_menu.up,
|
up: migration_20250818_143115_menu.up,
|
||||||
down: migration_20250818_143115_menu.down,
|
down: migration_20250818_143115_menu.down,
|
||||||
name: '20250818_143115_menu'
|
name: '20250818_143115_menu',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
up: migration_20250827_093559_magazine.up,
|
||||||
|
down: migration_20250827_093559_magazine.down,
|
||||||
|
name: '20250827_093559_magazine'
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ export interface Config {
|
||||||
contactPerson: ContactPerson;
|
contactPerson: ContactPerson;
|
||||||
locations: Location;
|
locations: Location;
|
||||||
group: Group;
|
group: Group;
|
||||||
|
magazine: Magazine;
|
||||||
documents: Document;
|
documents: Document;
|
||||||
media: Media;
|
media: Media;
|
||||||
users: User;
|
users: User;
|
||||||
|
|
@ -46,6 +47,7 @@ export interface Config {
|
||||||
contactPerson: ContactPersonSelect<false> | ContactPersonSelect<true>;
|
contactPerson: ContactPersonSelect<false> | ContactPersonSelect<true>;
|
||||||
locations: LocationsSelect<false> | LocationsSelect<true>;
|
locations: LocationsSelect<false> | LocationsSelect<true>;
|
||||||
group: GroupSelect<false> | GroupSelect<true>;
|
group: GroupSelect<false> | GroupSelect<true>;
|
||||||
|
magazine: MagazineSelect<false> | MagazineSelect<true>;
|
||||||
documents: DocumentsSelect<false> | DocumentsSelect<true>;
|
documents: DocumentsSelect<false> | DocumentsSelect<true>;
|
||||||
media: MediaSelect<false> | MediaSelect<true>;
|
media: MediaSelect<false> | MediaSelect<true>;
|
||||||
users: UsersSelect<false> | UsersSelect<true>;
|
users: UsersSelect<false> | UsersSelect<true>;
|
||||||
|
|
@ -532,6 +534,18 @@ export interface Classified {
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "magazine".
|
||||||
|
*/
|
||||||
|
export interface Magazine {
|
||||||
|
id: string;
|
||||||
|
cover: string | Media;
|
||||||
|
document: string | Document;
|
||||||
|
date: string;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "users".
|
* via the `definition` "users".
|
||||||
|
|
@ -611,6 +625,10 @@ export interface PayloadLockedDocument {
|
||||||
relationTo: 'group';
|
relationTo: 'group';
|
||||||
value: string | Group;
|
value: string | Group;
|
||||||
} | null)
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'magazine';
|
||||||
|
value: string | Magazine;
|
||||||
|
} | null)
|
||||||
| ({
|
| ({
|
||||||
relationTo: 'documents';
|
relationTo: 'documents';
|
||||||
value: string | Document;
|
value: string | Document;
|
||||||
|
|
@ -961,6 +979,17 @@ export interface GroupSelect<T extends boolean = true> {
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "magazine_select".
|
||||||
|
*/
|
||||||
|
export interface MagazineSelect<T extends boolean = true> {
|
||||||
|
cover?: T;
|
||||||
|
document?: T;
|
||||||
|
date?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "documents_select".
|
* via the `definition` "documents_select".
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import { PopesPrayerIntentions } from '@/collections/PopesPrayerIntentions'
|
||||||
import { LiturgicalCalendar } from '@/collections/LiturgicalCalendar'
|
import { LiturgicalCalendar } from '@/collections/LiturgicalCalendar'
|
||||||
import { Classifieds } from '@/collections/Classifieds'
|
import { Classifieds } from '@/collections/Classifieds'
|
||||||
import { MenuGlobal } from '@/globals/Menu'
|
import { MenuGlobal } from '@/globals/Menu'
|
||||||
|
import { Magazine } from '@/collections/Magazine'
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const dirname = path.dirname(filename)
|
const dirname = path.dirname(filename)
|
||||||
|
|
@ -89,6 +90,7 @@ export default buildConfig({
|
||||||
ContactPerson,
|
ContactPerson,
|
||||||
Locations,
|
Locations,
|
||||||
Groups,
|
Groups,
|
||||||
|
Magazine,
|
||||||
Documents,
|
Documents,
|
||||||
Media,
|
Media,
|
||||||
Users,
|
Users,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue