-
Notifications
You must be signed in to change notification settings - Fork 0
feature: preview links in CMS #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
e82e68e
2c0f7e3
1c907d8
a2391ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
DATOCMS_READONLY_API_TOKEN="<Read-only API token>" | ||
DATOCMS_API_TOKEN="<Full-access API token>" | ||
DATOCMS_PREVIEW_API_TOKEN="<Custom API token for preview>" | ||
HEAD_START_PREVIEW_SECRET="" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { Client } from '@datocms/cli/lib/cma-client-node'; | ||
|
||
export default async function (client: Client) { | ||
console.log('Manage upload filters'); | ||
|
||
console.log('Install plugin "Model Deployment Links"'); | ||
await client.plugins.create({ | ||
id: 'MKba9NT5QBKZaeI4HcERwA', | ||
package_name: 'datocms-plugin-model-deployment-links', | ||
}); | ||
await client.plugins.update('MKba9NT5QBKZaeI4HcERwA', { | ||
parameters: { datoApiToken: process.env.DATOCMS_PREVIEW_API_TOKEN }, | ||
}); | ||
|
||
console.log('Creating new fields/fieldsets'); | ||
|
||
console.log( | ||
'Create JSON field "Preview" (`preview`) in model "\uD83D\uDCD1 Page" (`page`)' | ||
); | ||
await client.fields.create('LjXdkuCdQxCFT4hv8_ayew', { | ||
id: 'XF2LuFVWSrmu7Lle8xlhTg', | ||
label: 'Preview', | ||
field_type: 'json', | ||
api_key: 'preview', | ||
localized: true, | ||
appearance: { | ||
addons: [], | ||
editor: 'MKba9NT5QBKZaeI4HcERwA', | ||
parameters: { urlPattern: '/{ locale }/{ slug }/' }, | ||
}, | ||
}); | ||
|
||
console.log( | ||
'Create JSON field "Preview" (`preview`) in model "\uD83C\uDFE0 Home" (`home_page`)' | ||
); | ||
await client.fields.create('X_tZn3TxQY28ltSyjZUGHQ', { | ||
id: 'YPXZOMoWRdKTHLUkN9ytfw', | ||
label: 'Preview', | ||
field_type: 'json', | ||
api_key: 'preview', | ||
localized: true, | ||
appearance: { | ||
addons: [], | ||
editor: 'MKba9NT5QBKZaeI4HcERwA', | ||
parameters: { urlPattern: '/{ locale }/' }, | ||
}, | ||
}); | ||
|
||
console.log( | ||
'Create JSON field "Preview" (`preview`) in model "\uD83E\uDD37 Not found" (`not_found_page`)' | ||
); | ||
await client.fields.create('d_AvMVoMSqmNbMqx-NdqIw', { | ||
id: 'O_DCfpaDSzq1MX4DaRlMpQ', | ||
label: 'Preview', | ||
field_type: 'json', | ||
api_key: 'preview', | ||
localized: true, | ||
appearance: { | ||
addons: [], | ||
editor: 'MKba9NT5QBKZaeI4HcERwA', | ||
parameters: { urlPattern: '/{ locale }/404' }, | ||
}, | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,6 @@ | ||
--- | ||
import type { SiteLocale } from '@lib/i18n/types'; | ||
import type { | ||
NotFoundPageQuery, | ||
NotFoundPageRecord, | ||
} from '@lib/datocms/types'; | ||
import type { NotFoundPageQuery, NotFoundPageRecord } from '@lib/datocms/types'; | ||
import { datocmsRequest } from '@lib/datocms'; | ||
import { noIndexTag, titleTag } from '@lib/seo'; | ||
import Layout from '@layouts/Default.astro'; | ||
|
@@ -15,14 +12,16 @@ export const prerender = false; | |
|
||
Astro.response.status = 404; | ||
|
||
const { locale } = Astro.params as { locale: SiteLocale }; | ||
const localeFromPath = Astro.params.locale as SiteLocale; | ||
const localeFromQuery = Astro.url.searchParams.get('locale') as SiteLocale; | ||
const locale = localeFromQuery || localeFromPath; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is now needed to have the |
||
const { page } = (await datocmsRequest<NotFoundPageQuery>({ | ||
query, | ||
variables: { locale }, | ||
})) as { page: NotFoundPageRecord }; | ||
--- | ||
|
||
<Layout pageUrls={[]} seoMetaTags={[noIndexTag, titleTag(page.title)]}> | ||
<h1>{page.title} {Astro.params.locale}</h1> | ||
<h1>{page.title}</h1> | ||
<Blocks blocks={page.bodyBlocks as AnyBlock[]} /> | ||
</Layout> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,19 +53,30 @@ type Params = { | |
|
||
const { locale, path } = Astro.params as Params; | ||
const variables = { locale, slug: getPageSlugFromPath(path) }; | ||
const { page } = (await datocmsRequest<PageQuery>({ query, variables })) as { | ||
page: NonNullable<PageQuery['page']>; // Only NonNullable when statically generated. Handle as a 404 when this is a server route! | ||
}; | ||
const breadcrumbs = [...getParentPages(page), page].map((page) => | ||
const { page } = await datocmsRequest<PageQuery>({ query, variables }); | ||
|
||
if (!page) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check ensures this type casting is no longer needed: as {
page: NonNullable<PageQuery['page']>; // Only NonNullable when statically generated. Handle as a 404 when this is a server route!
}; But it makes the |
||
return Astro.rewrite(`/404/?locale=${locale}`); | ||
} | ||
|
||
const canonicalUrl = getPageHref({ locale, record: page }); | ||
if (Astro.url.pathname !== canonicalUrl) { | ||
return Astro.redirect(canonicalUrl); | ||
} | ||
|
||
const breadcrumbs = [...getParentPages(page), page].map((record) => | ||
formatBreadcrumb({ | ||
text: page.title, | ||
href: getPageHref({ locale, record: page }), | ||
text: record.title, | ||
href: getPageHref({ locale, record }), | ||
}) | ||
); | ||
const pageUrls = (page._allSlugLocales || []).map(({ locale }) => ({ | ||
locale: locale as SiteLocale, | ||
pathname: getPageHref({ locale: locale as SiteLocale, record: page }), | ||
})) as PageUrl[]; | ||
|
||
const pageLocales = (page._allSlugLocales?.map(({ locale }) => locale) ?? | ||
[]) as SiteLocale[]; | ||
const pageUrls = pageLocales.map((locale) => ({ | ||
locale, | ||
pathname: getPageHref({ locale, record: page }), | ||
})) satisfies PageUrl[]; | ||
--- | ||
|
||
<Layout | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#import '@lib/routing/PageRoute.fragment.graphql' | ||
|
||
query ReroutePage($locale: SiteLocale!, $slug: String!) { | ||
page(locale: $locale, filter: { slug: { eq: $slug } }) { | ||
...PageRoute | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import type { APIRoute } from 'astro'; | ||
import { datocmsRequest } from '@lib/datocms'; | ||
import type { ReroutePageQuery, SiteLocale } from '@lib/datocms/types'; | ||
import { getPageHref } from '@lib/routing'; | ||
import query from './_page.query.graphql'; | ||
|
||
export const prerender = false; | ||
|
||
const jsonResponse = (data: object, status: number = 200) => { | ||
return new Response(JSON.stringify(data), { | ||
status, | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
}; | ||
|
||
export const GET: APIRoute = async ({ request }) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a generic alternate approach that I used in the nododos-website. But I think the canonical url check in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm. I guess the canonical check works on localhost and preview as the generic page route is then always handled dynamically on the server. However the production environment has prerendered pages and will throw a 404 I suppose. So I guess we do need this reroute API handler. In that case the config of the Preview field of the generic page will need to use that one instead. |
||
const locale = new URL(request.url).searchParams.get('locale') as SiteLocale; | ||
if (!locale) { | ||
return jsonResponse({ error: 'Missing \'locale\' parameter' }, 400); | ||
} | ||
|
||
const slug = new URL(request.url).searchParams.get('slug'); | ||
if (!slug) { | ||
return jsonResponse({ error: 'Missing \'slug\' parameter' }, 400); | ||
} | ||
|
||
const { page } = (await datocmsRequest<ReroutePageQuery>({ query, variables: { slug, locale } })); | ||
if (!page) { | ||
return jsonResponse({ error: 'Page not found' }, 404); | ||
} | ||
|
||
return new Response('',{ | ||
status: 307, | ||
headers: { 'Location': getPageHref({ locale, record: page }) }, | ||
}); | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.