Skip to content

Commit

Permalink
Convert cms-agilitycms example to TypeScript (#38976)
Browse files Browse the repository at this point in the history
Converted `cms-agilitycms` example to TypeScript to match Contribution docs.

## Documentation / Examples

- [X] Make sure the linting passes by running `pnpm lint`
- [X] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
  • Loading branch information
maxproske committed Jul 27, 2022
1 parent 44b5534 commit e955850
Show file tree
Hide file tree
Showing 41 changed files with 132 additions and 51 deletions.
File renamed without changes.
Expand Up @@ -2,7 +2,7 @@ import Image from '../lib/components/image'
import cn from 'classnames'
import Link from 'next/link'

export default function CoverImage({ title, responsiveImage, slug }) {
export default function CoverImage({ title, responsiveImage, slug = null }) {
const image = (
<Image
data={{
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 6 additions & 0 deletions examples/cms-agilitycms/environment.d.ts
@@ -0,0 +1,6 @@
declare namespace NodeJS {
export interface ProcessEnv {
readonly AGILITY_CMS_GUID: string
readonly AGILITY_CMS_API_FETCH_KEY: string
}
}
Expand Up @@ -23,6 +23,9 @@ export const getClient = (preview = false) =>

// This client is used by nested components to fetch additional data within `getStaticProps`
export class APIClient {
public preview: any
public client: any

constructor({ preview = false }) {
this.preview = preview
this.client = getClient(preview)
Expand Down
@@ -1,13 +1,21 @@
import React, { useCallback, useState } from 'react'
import { useInView } from 'react-intersection-observer'

type State = {
lazyLoad: boolean
isSsr: boolean
isIntersectionObserverAvailable: boolean
inView?: boolean
loaded: boolean
}

const imageAddStrategy = ({
lazyLoad,
isSsr,
isIntersectionObserverAvailable,
inView,
loaded,
}) => {
}: State) => {
if (!lazyLoad) {
return true
}
Expand All @@ -28,7 +36,7 @@ const imageShowStrategy = ({
isSsr,
isIntersectionObserverAvailable,
loaded,
}) => {
}: State) => {
if (!lazyLoad) {
return true
}
Expand All @@ -44,6 +52,34 @@ const imageShowStrategy = ({
return true
}

type ImageData = {
aspectRatio: number
base64?: string
height?: number
width: number
sizes?: string
src?: string
srcSet?: string
webpSrcSet?: string
bgColor?: string
alt?: string
title?: string
}

type ImageProps = {
data: ImageData
className?: string
pictureClassName?: string
fadeInDuration?: number
intersectionTreshold?: number
intersectionThreshold?: number
intersectionMargin?: string
lazyLoad?: boolean
style?: React.CSSProperties
pictureStyle?: React.CSSProperties
explicitWidth?: boolean
}

const Image = function ({
className,
fadeInDuration,
Expand All @@ -55,7 +91,7 @@ const Image = function ({
pictureStyle,
explicitWidth,
data,
}) {
}: ImageProps) {
const [loaded, setLoaded] = useState(false)

const handleLoad = useCallback(() => {
Expand All @@ -74,7 +110,7 @@ const Image = function ({
? false
: !!window.IntersectionObserver

const absolutePositioning = {
const absolutePositioning: React.CSSProperties = {
position: 'absolute',
left: 0,
top: 0,
Expand Down
File renamed without changes.
Expand Up @@ -24,10 +24,10 @@ export const requireComponentDependancyByName = (name) => {
if (!Component) {
// eslint-disable-next-line no-throw-literal
throw `Could not find a component with the name ${name}. Tried searching:
${userComponentsPath}/${kebabCaseName}.js',
${libComponentsPath}/${kebabCaseName}.js',
${userComponentsPath}/${pascalCaseName}.js',
${libComponentsPath}/${pascalCaseName}.js'.`
${userComponentsPath}/${kebabCaseName}.tsx',
${libComponentsPath}/${kebabCaseName}.tsx',
${userComponentsPath}/${pascalCaseName}.tsx',
${libComponentsPath}/${pascalCaseName}.tsx'.`
}

return Component
Expand All @@ -38,13 +38,13 @@ const requireComponent = (name) => {

try {
//check the user path first (must be relative paths)
Component = require(`../components/${name}.js`).default
Component = require(`../components/${name}.tsx`).default
} catch {}

if (!Component)
try {
//fallback to lib path (must be relative paths)
Component = require(`./components/${name}.js`).default
Component = require(`./components/${name}.tsx`).default
} catch {}

return Component
Expand Down
Expand Up @@ -20,6 +20,14 @@ export function normalizePosts(postsFromAgility) {
excerpt: p.fields.excerpt,
date: p.fields.date,
content: p.fields.content,
author: p.fields.author
? {
name: p.fields.author.fields.name,
picture: {
url: `${p.fields.author.fields.picture.url}?w=100&h=100`,
},
}
: null,
ogImage: {
url: `${p.fields.coverImage.url}?w=2000&h=1000&q=70`,
},
Expand All @@ -40,15 +48,6 @@ export function normalizePosts(postsFromAgility) {
},
}

if (p.fields.author) {
normalizedPost.author = {
name: p.fields.author.fields.name,
picture: {
url: `${p.fields.author.fields.picture.url}?w=100&h=100`,
},
}
}

return normalizedPost
})

Expand Down
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions examples/cms-agilitycms/next-env.d.ts
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
26 changes: 15 additions & 11 deletions examples/cms-agilitycms/package.json
Expand Up @@ -6,19 +6,23 @@
"start": "next start"
},
"dependencies": {
"@agility/content-fetch": "^0.8.1",
"classnames": "2.3.1",
"date-fns": "2.28.0",
"isomorphic-unfetch": "3.0.0",
"@agility/content-fetch": "^1.1.5",
"classnames": "^2.3.1",
"date-fns": "^2.29.1",
"isomorphic-unfetch": "^3.1.0",
"next": "latest",
"react": "^17.0.2",
"react-datocms": "1.1.0",
"react-dom": "^17.0.2",
"react-intersection-observer": "^8.26.1"
"react": "^18.2.0",
"react-datocms": "^3.0.15",
"react-dom": "^18.2.0",
"react-intersection-observer": "^9.4.0"
},
"devDependencies": {
"autoprefixer": "10.4.2",
"postcss": "8.4.5",
"tailwindcss": "^3.0.15"
"@types/node": "^18.6.0",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"autoprefixer": "^10.4.7",
"postcss": "^8.4.14",
"tailwindcss": "^3.1.6",
"typescript": "^4.7.4"
}
}
File renamed without changes.
@@ -1,7 +1,5 @@
import '../styles/index.css'

function MyApp({ Component, pageProps }) {
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}

export default MyApp
15 changes: 0 additions & 15 deletions examples/cms-agilitycms/pages/_document.js

This file was deleted.

13 changes: 13 additions & 0 deletions examples/cms-agilitycms/pages/_document.tsx
@@ -0,0 +1,13 @@
import { Html, Head, Main, NextScript } from 'next/document'

export default function MyDocument() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
@@ -1,4 +1,9 @@
export default async function handler(_, res) {
import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
_req: NextApiRequest,
res: NextApiResponse
) {
// Exit the current user from "Preview Mode". This function accepts no args.
res.clearPreviewData()

Expand Down
@@ -1,6 +1,10 @@
import type { NextApiRequest, NextApiResponse } from 'next'
import { validatePreview } from '../../lib/api'

export default async function handler(req, res) {
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
// Check the secret and next parameters
// This secret should only be known to this API route and the CMS

Expand All @@ -19,6 +23,9 @@ export default async function handler(req, res) {
res.setPreviewData({})

// Redirect to the slug
if (!('slug' in validationResp)) {
throw new Error('invariant missing slug in validation response')
}
res.writeHead(307, { Location: validationResp.slug })
res.end()
}
File renamed without changes.
20 changes: 20 additions & 0 deletions examples/cms-agilitycms/tsconfig.json
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "environment.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

0 comments on commit e955850

Please sign in to comment.