Skip to content
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

fix: remix example bugfixes #987

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/remix/app/components/preview-banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react';

export function PreviewBanner() {
return (
<p>
You&apos;re in <strong>preview mode</strong> (DRAFT content from Contentful served)
<>
<p>You're in <strong>preview mode</strong> (DRAFT content from Contentful served)</p>
<form action="/api/exit-preview" method="post">
<button type="submit">Exit Preview Mode</button>
</form>
</p>
</>
);
}
54 changes: 18 additions & 36 deletions examples/remix/app/routes/$slug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,9 @@ import {
} from '@contentful/live-preview/react';

import { PreviewBanner } from '../components/preview-banner';
import { contentful } from '../../lib/contentful.server';
import { getEntryBySlug } from '../../lib/contentful.server';
import { isPreviewMode } from '../utils/preview-mode.server';

type QueryResponse = {
postCollection: {
items: Post[];
};
};

type Post = {
title: string;
description: string;
sys: {
id: string;
};
};

type LoaderData = {
post: Post;
preview: boolean;
};
import type { LoaderData } from '../../types';

const getPostQuery = gql`
query Post($slug: String!, $preview: Boolean!) {
Expand All @@ -49,20 +31,15 @@ const getPostQuery = gql`

export const loader: LoaderFunction = async ({ params, request }) => {
const { slug } = params;

const preview = await isPreviewMode(request);

const API_TOKEN = preview
? process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN
: process.env.CONTENTFUL_ACCESS_TOKEN;

const data = (await contentful.request(
getPostQuery,
{ slug, preview },
{ authorization: `Bearer ${API_TOKEN}` }
)) as QueryResponse;

const post = data.postCollection.items[0];
const data = slug && await getEntryBySlug({
spaceId: process.env.CONTENTFUL_SPACE_ID || '',
accessToken: preview ? process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN || '' : process.env.CONTENTFUL_ACCESS_TOKEN || '',
query: getPostQuery,
slug,
preview
});
const post = data && data.postCollection.items[0];

return json({
post,
Expand All @@ -72,14 +49,19 @@ export const loader: LoaderFunction = async ({ params, request }) => {

export default function PostDetailPage() {
const { post, preview } = useLoaderData<LoaderData>();
const inspectorProps = useContentfulInspectorMode({ entryId: post.sys.id });
const inspectorProps = useContentfulInspectorMode({ entryId: post?.sys.id });
const updatedPost = useContentfulLiveUpdates(post);

return (
<>
{preview && <PreviewBanner />}
<h1 {...inspectorProps({ fieldId: 'title' })}>{updatedPost.title || ''}</h1>
<div {...inspectorProps({ fieldId: 'description' })}>{updatedPost.description || ''}</div>

{post && (
<>
<h1 {...inspectorProps({ fieldId: 'title' })}>{updatedPost.title || ''}</h1>
<div {...inspectorProps({ fieldId: 'description' })}>{updatedPost.description || ''}</div>
</>
)}
</>
);
}
24 changes: 8 additions & 16 deletions examples/remix/app/routes/api/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,10 @@ import { gql } from 'graphql-request';
import { json, redirect } from '@remix-run/node';
import type { LoaderFunction } from '@remix-run/node';

import { contentful } from '../../../lib/contentful.server';
import { getEntryBySlug } from '../../../lib/contentful.server';
import { previewModeCookie } from '../../utils/preview-mode.server';
import { parseCookie } from '../../utils/parse-cookie.server';

type QueryResponse = {
postCollection: {
items: {
slug: string;
}[];
};
};

const getPostQuery = gql`
query Post($slug: String!) {
postCollection(where: { slug: $slug }, limit: 1, preview: true) {
Expand All @@ -35,13 +27,13 @@ export const loader: LoaderFunction = async ({ request }) => {
}

// Check if the provided `slug` exists
const data = (await contentful.request(
getPostQuery,
{ slug },
{
authorization: `Bearer ${process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN}`,
}
)) as QueryResponse;
const data = await getEntryBySlug({
spaceId: process.env.CONTENTFUL_SPACE_ID || '',
accessToken: process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN || '',
query: getPostQuery,
slug,
preview: true
});

// If the slug doesn't exist prevent preview from being enabled
if (!data.postCollection.items.length) {
Expand Down
40 changes: 9 additions & 31 deletions examples/remix/app/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,10 @@ import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import { gql } from 'graphql-request';

import { contentful } from '../../lib/contentful.server';
import { getEntries } from '../../lib/contentful.server';
import { isPreviewMode } from '../utils/preview-mode.server';
import { PreviewBanner } from '../components/preview-banner';

type QueryResponse = {
postCollection: {
items: Post[];
};
};

type Post = {
title: string;
description: string;
slug: string;
};

type LoaderData = {
posts: Post[];
preview: boolean;
};
import type { LoaderData, Post } from '../../types';

const getPostQuery = gql`
query Post($preview: Boolean!) {
Expand All @@ -44,18 +28,12 @@ const getPostQuery = gql`

export const loader: LoaderFunction = async ({ request }) => {
const preview = await isPreviewMode(request);

const API_TOKEN = preview
? process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN
: process.env.CONTENTFUL_ACCESS_TOKEN;

const data = (await contentful.request(
getPostQuery,
{ preview },
{
authorization: `Bearer ${API_TOKEN}`,
}
)) as QueryResponse;
const data = await getEntries({
spaceId: process.env.CONTENTFUL_SPACE_ID || '',
accessToken: preview ? process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN || '' : process.env.CONTENTFUL_ACCESS_TOKEN || '',
query: getPostQuery,
preview
})

return json({
posts: data.postCollection.items,
Expand All @@ -69,7 +47,7 @@ export default function Index() {
return (
<>
{preview && <PreviewBanner />}
{posts.map((post) => (
{posts && posts.map((post: Post) => (
<a key={post.title} href={`/${post.slug}`}>
{post.title}
</a>
Expand Down
42 changes: 39 additions & 3 deletions examples/remix/lib/contentful.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
import { GraphQLClient } from 'graphql-request';
import type { QueryResponse, Variables } from '../types'

const SPACE = process.env.CONTENTFUL_SPACE_ID;
const fetchData = async (spaceId: string, accessToken: string, query: string, variables: Variables, preview: boolean) => {
const client = new GraphQLClient(`https://graphql.contentful.com/content/v1/spaces/${spaceId}`);
const data = (await client.request(
query,
variables,
{ authorization: `Bearer ${accessToken}` }
)) as QueryResponse;

const endpoint = `https://graphql.contentful.com/content/v1/spaces/${SPACE}`;
return data;
}

export const contentful = new GraphQLClient(endpoint);
// The `spaceId` and `accessToken` are passed as arguments from a `loader` function
// to these utility functions. This approach avoids browser errors that occur when
// trying to access `process.env` from this file, even though it is not executed in
// the browser. This is likely a Remix bundling issue.
export const getEntryBySlug = async ({
spaceId,
accessToken,
query,
slug,
preview,
}: {
spaceId: string,
accessToken: string,
query: string,
slug: string,
preview: boolean,
}) => fetchData(spaceId, accessToken, query, { slug, preview }, preview);

export const getEntries = async ({
spaceId,
accessToken,
query,
preview,
}: {
spaceId: string,
accessToken: string,
query: string,
preview: boolean,
}) => fetchData(spaceId, accessToken, query, { preview }, preview);
24 changes: 24 additions & 0 deletions examples/remix/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export type Post = {
title: string;
description: string;
slug: string;
sys: {
id: string;
};
};

export type LoaderData = {
post: Post;
posts: Post[];
preview: boolean;
};

export type QueryResponse = {
postCollection: {
items: Post[];
};
};

export type Variables = {
[key: string]: string | boolean;
};
Loading