diff --git a/apps/trustlab/payload-types.ts b/apps/trustlab/payload-types.ts index c17fa5b4e..b59c1ec34 100644 --- a/apps/trustlab/payload-types.ts +++ b/apps/trustlab/payload-types.ts @@ -5084,6 +5084,14 @@ export interface Organisation { )[] | null; slug: string; + meta?: { + title?: string | null; + description?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: (string | null) | Media; + }; updatedAt: string; createdAt: string; } @@ -9446,6 +9454,13 @@ export interface OrganisationsSelect { }; }; slug?: T; + meta?: + | T + | { + title?: T; + description?: T; + image?: T; + }; updatedAt?: T; createdAt?: T; } diff --git a/apps/trustlab/src/lib/data/common/sitemap.js b/apps/trustlab/src/lib/data/common/sitemap.js index 97afc50ff..7bc7f6318 100644 --- a/apps/trustlab/src/lib/data/common/sitemap.js +++ b/apps/trustlab/src/lib/data/common/sitemap.js @@ -97,12 +97,31 @@ async function getOpportunitiesEntries(api) { return docsToSitemapEntries(docs, "opportunities"); } +async function getOrganisationsEntries(api) { + const { docs } = await api.getCollection("organisations", { + pagination: false, + select: { + pathname: true, + slug: true, + updatedAt: true, + createdAt: true, + link: true, + includeLink: true, + }, + }); + const docsWithAPage = docs.filter( + (doc) => doc?.includeLink && doc.link?.linkType === "internal", + ); + return docsToSitemapEntries(docsWithAPage, "organisations"); +} + async function getSitemapEntries(api) { - const [pages, opportunities] = await Promise.all([ + const [pages, opportunities, organisations] = await Promise.all([ getPagesEntries(api), getOpportunitiesEntries(api), + getOrganisationsEntries(api), ]); - return [...pages, ...opportunities]; + return [...pages, ...opportunities, ...organisations]; } async function buildSitemapXml(api) { diff --git a/apps/trustlab/src/lib/data/pagify/opportunities.js b/apps/trustlab/src/lib/data/pagify/opportunities.js index ee567f382..f11e3f1fc 100644 --- a/apps/trustlab/src/lib/data/pagify/opportunities.js +++ b/apps/trustlab/src/lib/data/pagify/opportunities.js @@ -24,6 +24,8 @@ function pagifyOpportunities(collection) { const doc = docs[0]; const date = formatDate(doc.date); + // opportunities have titles but organisations have name only. + const title = doc.title || doc.name || null; const contentBlocks = doc.blocks || []; // blockify is called after pagefy so *MUST* not call it here const blocks = contentBlocks.filter(Boolean).map((block) => { @@ -37,7 +39,7 @@ function pagifyOpportunities(collection) { } return block; }); - return { ...doc, blocks, date, parent: parentPage }; + return { ...doc, blocks, date, title, parent: parentPage }; }; } diff --git a/apps/trustlab/src/payload/collections/Organisations.js b/apps/trustlab/src/payload/collections/Organisations.js index 613287bd5..8918af14c 100644 --- a/apps/trustlab/src/payload/collections/Organisations.js +++ b/apps/trustlab/src/payload/collections/Organisations.js @@ -1,4 +1,5 @@ import { slug, image, richText, linkGroup } from "@commons-ui/payload/fields"; +import { appendPathnameToCollection } from "@commons-ui/payload/hooks"; import { anyone, hasEditorAccess } from "@/trustlab/payload/access"; import blocks from "@/trustlab/payload/blocks"; @@ -66,6 +67,9 @@ const Organisations = { }, }), ], + hooks: { + afterRead: [appendPathnameToCollection("organisations")], + }, }; export default Organisations; diff --git a/apps/trustlab/src/payload/plugins/index.js b/apps/trustlab/src/payload/plugins/index.js index f01fcafad..cb5d20c9f 100644 --- a/apps/trustlab/src/payload/plugins/index.js +++ b/apps/trustlab/src/payload/plugins/index.js @@ -16,6 +16,15 @@ const s3MaxAttempts = Number(process.env.S3_MAX_ATTEMPTS) || 3; const s3MaxSockets = Number(process.env.S3_MAX_SOCKETS) || 1000; const s3ConnectionTimeout = Number(process.env.S3_CONNECTION_TIMEOUT) || 5000; +function generateURL({ doc }) { + if (!(doc?.pathname || doc?.slug)) { + return ""; + } + // site.url always has a trailing / + const pathname = (doc.pathname || `${doc.slug}`).replace(/^\//, ""); + return `${site.url}${pathname}`; +} + const plugins = [ nestedDocsPlugin({ collections: ["pages", "posts"], @@ -64,7 +73,13 @@ const plugins = [ }), seoPlugin({ // helplines don't have individual pages and we don't resources collection - collections: ["opportunities", "pages", "posts", "reports"], + collections: [ + "organisations", + "opportunities", + "pages", + "posts", + "reports", + ], generateDescription: ({ doc }) => { const data = doc?.description || doc?.excerpt; if (data) { @@ -72,8 +87,9 @@ const plugins = [ } return ""; }, - generateTitle: ({ doc }) => doc?.title ?? "", - generateURL: ({ doc }) => (doc?.slug ? `${site.url}${doc.slug}` : ""), + // Organisations don't have title, just name + generateTitle: ({ doc }) => doc?.title ?? doc?.name ?? "", + generateURL, uploadsCollection: "media", }), ];