Skip to content

Commit c9e58c1

Browse files
committed
feat(basic-starter): upgrade starters to NextDrupal classes
Issue #601
1 parent e9ecd8b commit c9e58c1

File tree

15 files changed

+209
-132
lines changed

15 files changed

+209
-132
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
.pnp.js
77
.yarn/install-state.gz
88

9-
# build/test artifacts
10-
/.turbo
9+
# testing
1110
/coverage
1211

1312
# next.js

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ A next-drupal starter for building your site with Next.js and GraphQL.
66

77
`npx create-next-app -e https://github.com/chapter-three/next-drupal-graphql-starter`
88

9+
## Deploy to Vercel
10+
11+
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fchapter-three%2Fnext-drupal-graphql-starter&env=NEXT_PUBLIC_DRUPAL_BASE_URL,NEXT_IMAGE_DOMAIN,DRUPAL_CLIENT_ID,DRUPAL_CLIENT_SECRET&envDescription=Learn%20more%20about%20environment%20variables&envLink=https%3A%2F%2Fnext-drupal.org%2Fdocs%2Fenvironment-variables&project-name=next-drupal&demo-title=Next.js%20for%20Drupal&demo-description=A%20next-generation%20front-end%20for%20your%20Drupal%20site.&demo-url=https%3A%2F%2Fdemo.next-drupal.org&demo-image=https%3A%2F%2Fnext-drupal.org%2Fimages%2Fdemo-screenshot.jpg)
12+
913
## Documentation
1014

1115
See https://next-drupal.org

components/drupal/Article.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
import Image from "next/image"
22
import { formatDate } from "@/lib/utils"
3-
import type { NodeArticle } from "@/types"
3+
import type { DrupalArticle } from "@/types"
44

55
interface ArticleProps {
6-
node: NodeArticle
6+
node: DrupalArticle
77
}
88

99
export function Article({ node, ...props }: ArticleProps) {
1010
return (
1111
<article {...props}>
1212
<h1 className="mb-4 text-6xl font-black leading-tight">{node.title}</h1>
1313
<div className="mb-4 text-gray-600">
14-
{node.author?.displayName ? (
14+
{node.author?.name ? (
1515
<span>
16-
Posted by{" "}
17-
<span className="font-semibold">{node.author.displayName}</span>
16+
Posted by <span className="font-semibold">{node.author.name}</span>
1817
</span>
1918
) : null}
20-
<span> - {formatDate(node.created)}</span>
19+
<span> - {formatDate(node.created.time)}</span>
2120
</div>
2221
{node.image && (
2322
<figure>

components/drupal/ArticleTeaser.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Image from "next/image"
2-
import Link from "next/link"
2+
import { Link } from "@/components/navigation/Link"
33
import { formatDate } from "@/lib/utils"
4-
import type { NodeArticle } from "@/types"
4+
import type { DrupalArticle } from "@/types"
55

66
interface ArticleTeaserProps {
7-
node: Partial<NodeArticle>
7+
node: Partial<DrupalArticle>
88
}
99

1010
export function ArticleTeaser({ node, ...props }: ArticleTeaserProps) {
@@ -14,13 +14,12 @@ export function ArticleTeaser({ node, ...props }: ArticleTeaserProps) {
1414
<h2 className="mb-4 text-4xl font-bold">{node.title}</h2>
1515
</Link>
1616
<div className="mb-4 text-gray-600">
17-
{node.author?.displayName ? (
17+
{node.author?.name ? (
1818
<span>
19-
Posted by{" "}
20-
<span className="font-semibold">{node.author.displayName}</span>
19+
Posted by <span className="font-semibold">{node.author.name}</span>
2120
</span>
2221
) : null}
23-
{node.created && <span> - {formatDate(node.created)}</span>}
22+
{node.created && <span> - {formatDate(node.created.time)}</span>}
2423
</div>
2524
{node.image && (
2625
<figure className="my-4">

components/drupal/BasicPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import type { NodePage } from "@/types"
1+
import type { DrupalPage } from "@/types"
22

33
interface BasicPageProps {
4-
node: NodePage
4+
node: DrupalPage
55
}
66

77
export function BasicPage({ node, ...props }: BasicPageProps) {

components/layout.tsx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,13 @@
1-
import Link from "next/link"
2-
import { PreviewAlert } from "@/components/PreviewAlert"
1+
import { HeaderNav } from "@/components/navigation/HeaderNav"
2+
import { PreviewAlert } from "@/components/misc/PreviewAlert"
33
import type { ReactNode } from "react"
44

55
export function Layout({ children }: { children: ReactNode }) {
66
return (
77
<>
88
<PreviewAlert />
99
<div className="max-w-screen-md px-6 mx-auto">
10-
<header>
11-
<div className="container flex items-center justify-between py-6 mx-auto">
12-
<Link href="/" className="text-2xl font-semibold no-underline">
13-
Next.js for Drupal
14-
</Link>
15-
<Link
16-
href="https://next-drupal.org/docs"
17-
target="_blank"
18-
rel="external"
19-
className="hover:text-blue-600"
20-
>
21-
Read the docs
22-
</Link>
23-
</div>
24-
</header>
10+
<HeaderNav />
2511
<main className="container py-10 mx-auto">{children}</main>
2612
</div>
2713
</>

components/PreviewAlert.tsx renamed to components/misc/PreviewAlert.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@ export function PreviewAlert() {
1414
return null
1515
}
1616

17+
function buttonHandler() {
18+
void fetch("/api/exit-preview")
19+
setShowPreviewAlert(false)
20+
}
21+
1722
return (
1823
<div className="sticky top-0 left-0 z-50 w-full px-2 py-1 text-center text-white bg-black">
1924
<p className="mb-0">
2025
This page is a preview.{" "}
2126
<button
2227
className="inline-block ml-3 rounded border px-1.5 hover:bg-white hover:text-black active:bg-gray-200 active:text-gray-500"
23-
onClick={() => router.push("/api/exit-preview")}
28+
onClick={buttonHandler}
2429
>
2530
Exit preview mode
2631
</button>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Link } from "@/components/navigation/Link"
2+
3+
export function HeaderNav() {
4+
return (
5+
<header>
6+
<div className="container flex items-center justify-between py-6 mx-auto">
7+
<Link href="/" className="text-2xl font-semibold no-underline">
8+
Next.js for Drupal
9+
</Link>
10+
<Link
11+
href="https://next-drupal.org/docs"
12+
target="_blank"
13+
rel="external"
14+
className="hover:text-blue-600"
15+
>
16+
Read the docs
17+
</Link>
18+
</div>
19+
</header>
20+
)
21+
}

components/navigation/Link.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { forwardRef } from "react"
2+
import NextLink from "next/link"
3+
import type { AnchorHTMLAttributes, ReactNode } from "react"
4+
import type { LinkProps as NextLinkProps } from "next/link"
5+
6+
type LinkProps = NextLinkProps &
7+
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof NextLinkProps> & {
8+
children?: ReactNode
9+
}
10+
11+
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
12+
function LinkWithRef(
13+
{
14+
// Turn next/link prefetching off by default.
15+
// @see https://github.com/vercel/next.js/discussions/24009
16+
prefetch = false,
17+
...rest
18+
},
19+
ref
20+
) {
21+
return <NextLink prefetch={prefetch} {...rest} ref={ref} />
22+
}
23+
)

lib/drupal.ts

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,13 @@
1-
import { DrupalClient } from "next-drupal"
1+
import { NextDrupalGraphQL } from "./next-drupal-graphql"
22

3-
const baseUrl: string = process.env.NEXT_PUBLIC_DRUPAL_BASE_URL || ""
4-
const clientId = process.env.DRUPAL_CLIENT_ID || ""
5-
const clientSecret = process.env.DRUPAL_CLIENT_SECRET || ""
3+
const baseUrl = process.env.NEXT_PUBLIC_DRUPAL_BASE_URL as string
4+
const clientId = process.env.DRUPAL_CLIENT_ID as string
5+
const clientSecret = process.env.DRUPAL_CLIENT_SECRET as string
66

7-
export const drupal = new DrupalClient(baseUrl, {
7+
export const drupal = new NextDrupalGraphQL(baseUrl, {
88
auth: {
99
clientId,
1010
clientSecret,
1111
},
12+
// debug: true,
1213
})
13-
14-
export const graphqlEndpoint = drupal.buildUrl("/graphql")
15-
16-
type QueryPayload = {
17-
query: string
18-
variables?: Record<string, string>
19-
}
20-
21-
type QueryJsonResponse<DataType> = {
22-
data?: DataType
23-
errors?: { message: string }[]
24-
}
25-
26-
// This is a wrapper around drupal.fetch.
27-
// Acts as a query helper.
28-
export async function query<DataType>(payload: QueryPayload) {
29-
const response = await drupal.fetch(graphqlEndpoint.toString(), {
30-
method: "POST",
31-
body: JSON.stringify(payload),
32-
withAuth: true, // Make authenticated requests using OAuth.
33-
headers: {
34-
"Content-Type": "application/json",
35-
Accept: "application/json",
36-
},
37-
})
38-
39-
if (!response?.ok) {
40-
throw new Error(response.statusText)
41-
}
42-
43-
const { data, errors }: QueryJsonResponse<DataType> = await response.json()
44-
45-
if (errors) {
46-
console.log(errors)
47-
throw new Error(errors?.map((e) => e.message).join("\n") ?? "unknown")
48-
}
49-
50-
return data
51-
}

0 commit comments

Comments
 (0)