mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 15:36:58 +00:00
update to agility/next
This commit is contained in:
parent
17f458b45b
commit
e836a5950f
@ -1,20 +1,20 @@
|
||||
import pageTemplates from "components/agility-pageTemplates"
|
||||
|
||||
const AgilityPage = (props:any) => {
|
||||
const AgilityPage = ({ header, agilityProps, error, revalidate }: {header:any, agilityProps: any, error?: any, revalidate?: any}) => {
|
||||
|
||||
if (!props || !props.pageTemplateName) {
|
||||
if (!agilityProps) {
|
||||
console.error(`Page object or template was not found.`)
|
||||
return null
|
||||
}
|
||||
|
||||
let AgilityPageTemplate = pageTemplates(props.pageTemplateName)
|
||||
let AgilityPageTemplate = pageTemplates(agilityProps.pageTemplateName)
|
||||
if (! AgilityPageTemplate) {
|
||||
console.error(`${props.pageTemplateName} not found.`)
|
||||
console.error(`${agilityProps.pageTemplateName} not found.`)
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<AgilityPageTemplate {...props} />
|
||||
<AgilityPageTemplate {...agilityProps} />
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import moduleComponents from "components/agility-modules"
|
||||
import {getModule} from "components/agility-modules"
|
||||
|
||||
|
||||
function ContentZone({ name, page, dynamicPageItem }) {
|
||||
@ -11,7 +11,7 @@ import moduleComponents from "components/agility-modules"
|
||||
|
||||
const modulesToRender = modules.map(m => {
|
||||
|
||||
const AgilityModule = moduleComponents(m.moduleName)
|
||||
const AgilityModule = getModule(m.moduleName)
|
||||
|
||||
if (AgilityModule) {
|
||||
return <AgilityModule key={m.item.contentID} page={page} dynamicPageItem={dynamicPageItem} {...m.item} />
|
||||
|
@ -2,16 +2,17 @@ import React, { FC } from 'react'
|
||||
|
||||
import { ProductCard } from '@components/product'
|
||||
import { Grid, Marquee, Hero } from '@components/ui'
|
||||
import { ModuleWithInit } from '@agility/nextjs'
|
||||
|
||||
interface Fields {
|
||||
interface ICustomData {
|
||||
bestSelling: any
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields,
|
||||
customData: any
|
||||
interface IModule {
|
||||
}
|
||||
|
||||
const BestsellingProducts:FC<Props> = ({fields, customData}) => {
|
||||
|
||||
const BestsellingProducts: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
|
||||
const bestSelling = customData.bestSelling
|
||||
|
||||
@ -31,5 +32,6 @@ const BestsellingProducts:FC<Props> = ({fields, customData}) => {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default BestsellingProducts
|
||||
|
||||
|
@ -1,16 +1,22 @@
|
||||
import { FC } from "react"
|
||||
import { Grid, Marquee, Hero } from '@components/ui'
|
||||
import { ProductCard } from '@components/product'
|
||||
import { ModuleWithInit } from "@agility/nextjs"
|
||||
|
||||
interface Fields {
|
||||
interface ICustomData {
|
||||
featured: any
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields,
|
||||
customData: any
|
||||
interface IModule {
|
||||
}
|
||||
|
||||
|
||||
const FeaturedProducts: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
|
||||
if (! customData) {
|
||||
return <div>No featured products returned.</div>
|
||||
}
|
||||
|
||||
const FeaturedProducts:FC<Props> = ({fields, customData}) => {
|
||||
const featured:any = customData.featured
|
||||
|
||||
return (
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { FC } from 'react'
|
||||
import { Hero } from '@components/ui'
|
||||
import * as AgilityTypes from "@agility/types"
|
||||
import { Module } from '@agility/nextjs'
|
||||
|
||||
|
||||
interface Fields {
|
||||
@ -9,11 +10,7 @@ interface Fields {
|
||||
cTA?:AgilityTypes.URLField
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields
|
||||
}
|
||||
|
||||
const HeroModule:FC<Props> = ({fields}) => {
|
||||
const HeroModule:Module<Fields> = ({ module: {fields }}) => {
|
||||
|
||||
return (
|
||||
<Hero
|
||||
|
@ -1,20 +1,27 @@
|
||||
import React, { FC } from 'react'
|
||||
import HomeAllProductsGrid from '@components/common/HomeAllProductsGrid'
|
||||
import { ModuleWithInit } from '@agility/nextjs'
|
||||
|
||||
interface Fields {
|
||||
|
||||
|
||||
interface ICustomData {
|
||||
categories: any
|
||||
newestProducts: any
|
||||
brands: any
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields,
|
||||
customData: any
|
||||
interface IModule {
|
||||
}
|
||||
|
||||
const HomeAllProductsGridModule:FC<Props> = ({fields, customData}) => {
|
||||
|
||||
const HomeAllProductsGridModule: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
|
||||
const categories = customData.categories
|
||||
const newestProducts = customData.newestProducts
|
||||
const brands = customData.brands
|
||||
|
||||
if (!categories) return <div>No data</div>
|
||||
|
||||
return (
|
||||
<HomeAllProductsGrid
|
||||
categories={categories}
|
||||
|
@ -2,17 +2,13 @@ import React, { FC } from 'react'
|
||||
|
||||
import { Container, Text } from '@components/ui'
|
||||
import { Bag } from '@components/icons'
|
||||
import { Module } from '@agility/nextjs'
|
||||
|
||||
|
||||
interface Fields {
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields,
|
||||
customData: any
|
||||
}
|
||||
|
||||
const Orders: FC<Props> = ({ fields, customData }) => {
|
||||
const Orders: Module<Fields> = ({ }) => {
|
||||
return (
|
||||
<Container>
|
||||
<Text variant="pageHeading">My Orders</Text>
|
||||
|
@ -3,19 +3,16 @@ import { Hero } from '@components/ui'
|
||||
import * as AgilityTypes from "@agility/types"
|
||||
import { GetProductResult } from '@framework/api/operations/get-product'
|
||||
import { ProductView } from '@components/product'
|
||||
import { Module } from '@agility/nextjs'
|
||||
|
||||
interface Fields {
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields,
|
||||
dynamicPageItem:any
|
||||
}
|
||||
|
||||
const HeroModule:FC<Props> = ({fields, dynamicPageItem}) => {
|
||||
|
||||
const HeroModule:Module<Fields> = ({ dynamicPageItem }) => {
|
||||
const product:any = dynamicPageItem
|
||||
return (
|
||||
<ProductView product={dynamicPageItem} />
|
||||
<ProductView product={product} />
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@ import {
|
||||
getDesignerPath,
|
||||
useSearchMeta,
|
||||
} from '@lib/search'
|
||||
import { ModuleWithInit } from '@agility/nextjs'
|
||||
|
||||
|
||||
const SORT = Object.entries({
|
||||
'latest-desc': 'Latest arrivals',
|
||||
@ -23,15 +25,17 @@ const SORT = Object.entries({
|
||||
'price-desc': 'Price: High to low',
|
||||
})
|
||||
|
||||
interface Fields {
|
||||
|
||||
interface ICustomData {
|
||||
categories: any
|
||||
brands: any
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields,
|
||||
customData: any
|
||||
interface IModule {
|
||||
}
|
||||
|
||||
const ProductSearch: FC<Props> = ({ fields, customData }) => {
|
||||
|
||||
const ProductSearch: ModuleWithInit<IModule, ICustomData> = ({ customData }) => {
|
||||
|
||||
const categories:[any] = customData.categories
|
||||
const brands:[any] = customData.brands
|
||||
@ -39,6 +43,7 @@ const ProductSearch: FC<Props> = ({ fields, customData }) => {
|
||||
const [activeFilter, setActiveFilter] = useState('')
|
||||
const [toggleFilter, setToggleFilter] = useState(false)
|
||||
|
||||
|
||||
const router = useRouter()
|
||||
const { asPath } = router
|
||||
const { q, sort } = router.query
|
||||
@ -447,4 +452,6 @@ const ProductSearch: FC<Props> = ({ fields, customData }) => {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default ProductSearch
|
@ -2,6 +2,7 @@ import React, { FC } from 'react'
|
||||
|
||||
import useCustomer from '@framework/use-customer'
|
||||
import { Container, Text } from '@components/ui'
|
||||
import { Module } from '@agility/nextjs'
|
||||
|
||||
interface Fields {
|
||||
heading: string,
|
||||
@ -10,11 +11,8 @@ interface Fields {
|
||||
notLoggedInMessage: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields
|
||||
}
|
||||
|
||||
const ProfileModule:FC<Props> = ({fields}) => {
|
||||
const ProfileModule:Module<Fields> = ({ module: {fields}}) => {
|
||||
|
||||
const { data } = useCustomer()
|
||||
return (
|
||||
|
@ -1,15 +1,14 @@
|
||||
import React, {FC} from 'react';
|
||||
import { Text, Container } from '@components/ui'
|
||||
import { Module } from '@agility/nextjs';
|
||||
|
||||
interface Fields {
|
||||
textblob:string,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields
|
||||
}
|
||||
const RichTextArea:Module<Fields> = ({ module: {fields} }) => {
|
||||
|
||||
|
||||
const RichTextArea:FC<Props> = ({fields}) => {
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
@ -5,6 +5,7 @@ import useWishlist from '@framework/wishlist/use-wishlist'
|
||||
import { Heart } from '@components/icons'
|
||||
import { Text, Container } from '@components/ui'
|
||||
import { WishlistCard } from '@components/wishlist'
|
||||
import { Module } from '@agility/nextjs'
|
||||
|
||||
|
||||
interface Fields {
|
||||
@ -13,12 +14,7 @@ interface Fields {
|
||||
addItemsMessage?: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
fields: Fields,
|
||||
customData: any
|
||||
}
|
||||
|
||||
const Wishlist: FC<Props> = ({ fields, customData }) => {
|
||||
const Wishlist: Module<Fields> = ({ module: { fields } }) => {
|
||||
const { data, isEmpty } = useWishlist({ includeProducts: true })
|
||||
|
||||
return (
|
||||
|
@ -33,10 +33,8 @@ const allModules = [
|
||||
* Find the component for a module by name.
|
||||
* @param moduleName
|
||||
*/
|
||||
const getModule = (moduleName: string): any | null => {
|
||||
export const getModule = (moduleName: string): any | null => {
|
||||
const obj = allModules.find(m => m.name.toLowerCase() === moduleName.toLowerCase())
|
||||
if (!obj) return null
|
||||
return obj.module
|
||||
}
|
||||
|
||||
export default getModule
|
||||
|
@ -1,11 +1,13 @@
|
||||
import React, { Component } from 'react';
|
||||
import ContentZone from 'components/agility-global/ContentZone'
|
||||
import { ContentZone } from '@agility/nextjs'
|
||||
|
||||
import { getModule } from "components/agility-modules"
|
||||
|
||||
const MainTemplate = (props:any) => {
|
||||
|
||||
return (
|
||||
<div className="one-column-template">
|
||||
<ContentZone name='MainContentZone' {...props} />
|
||||
<ContentZone name='MainContentZone' {...props} getModule={getModule} />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -5,7 +5,7 @@ import rangeMap from '@lib/range-map'
|
||||
|
||||
const nonNullable = (v: any) => v
|
||||
|
||||
const BestsellingProductsInit = async function ({ item, agility, languageCode, channelName, pageInSitemap, dynamicPageItem }: any) {
|
||||
const getCustomInitialProps = async function ({ }):Promise<{bestSelling:any}> {
|
||||
//TODO: pass the locale and preview mode as props...
|
||||
|
||||
|
||||
@ -52,4 +52,4 @@ const BestsellingProductsInit = async function ({ item, agility, languageCode, c
|
||||
|
||||
}
|
||||
|
||||
export default BestsellingProductsInit
|
||||
export default {getCustomInitialProps}
|
@ -7,7 +7,7 @@ import rangeMap from '@lib/range-map'
|
||||
|
||||
const nonNullable = (v: any) => v
|
||||
|
||||
const FeaturedProductsInit = async function ({ item, agility, languageCode, channelName, pageInSitemap, dynamicPageItem }: any) {
|
||||
const getCustomInitialProps = async function ({ item, agility, languageCode, channelName, pageInSitemap, dynamicPageItem }: any) {
|
||||
//TODO: pass the locale and preview mode as props...
|
||||
|
||||
|
||||
@ -31,4 +31,4 @@ const FeaturedProductsInit = async function ({ item, agility, languageCode, chan
|
||||
|
||||
}
|
||||
|
||||
export default FeaturedProductsInit
|
||||
export default { getCustomInitialProps }
|
@ -8,7 +8,7 @@ import rangeMap from '@lib/range-map'
|
||||
|
||||
const nonNullable = (v: any) => v
|
||||
|
||||
const HomeAllProductsGridData = async function ({ item, agility, languageCode, channelName, pageInSitemap, dynamicPageItem }: any) {
|
||||
const getCustomInitialProps = async function ({ item, agility, languageCode, channelName, pageInSitemap, dynamicPageItem }: any) {
|
||||
//TODO: pass the locale and preview mode as props...
|
||||
|
||||
const locale = "en-US"
|
||||
@ -35,4 +35,4 @@ const HomeAllProductsGridData = async function ({ item, agility, languageCode, c
|
||||
|
||||
}
|
||||
|
||||
export default HomeAllProductsGridData
|
||||
export default { getCustomInitialProps }
|
@ -1,7 +1,8 @@
|
||||
import { getConfig } from '@framework/api'
|
||||
import getSiteInfo from '@framework/api/operations/get-site-info'
|
||||
|
||||
const ProductSearchData = async function ({ item, agility, languageCode, channelName, pageInSitemap, dynamicPageItem }: any) {
|
||||
const getCustomInitialProps = async ({ agility, channelName, languageCode }:any) => {
|
||||
|
||||
//TODO: pass the locale and preview mode as props...
|
||||
|
||||
const locale = "en-US"
|
||||
@ -18,4 +19,6 @@ const ProductSearchData = async function ({ item, agility, languageCode, channel
|
||||
|
||||
}
|
||||
|
||||
export default ProductSearchData
|
||||
export default {
|
||||
getCustomInitialProps
|
||||
}
|
||||
|
@ -14,10 +14,8 @@ const allModules:any =[
|
||||
* Find the data method for a module by module reference name.
|
||||
* @param moduleName
|
||||
*/
|
||||
const getInitMethod = (moduleName:string):any => {
|
||||
export const getModuleData = (moduleName:string):any => {
|
||||
const obj = allModules.find((m: { name: string }) => m.name.toLowerCase() === moduleName.toLowerCase())
|
||||
if (!obj) return null
|
||||
return obj.init
|
||||
}
|
||||
|
||||
export default getInitMethod
|
||||
|
@ -1,9 +1,7 @@
|
||||
const bundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
enabled: !!process.env.BUNDLE_ANALYZE,
|
||||
})
|
||||
|
||||
module.exports = bundleAnalyzer({
|
||||
|
||||
module.exports = {
|
||||
webpack5: true,
|
||||
images: {
|
||||
domains: ['cdn11.bigcommerce.com', 'cdn.aglty.io'],
|
||||
},
|
||||
@ -11,6 +9,16 @@ module.exports = bundleAnalyzer({
|
||||
locales: ['en-US', 'es'],
|
||||
defaultLocale: 'en-US',
|
||||
},
|
||||
webpack: (config, { isServer }) => {
|
||||
if (!isServer) {
|
||||
config.node = {
|
||||
net: 'empty',
|
||||
dns: 'empty'
|
||||
};
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
rewrites() {
|
||||
return [
|
||||
{
|
||||
@ -39,4 +47,4 @@ module.exports = bundleAnalyzer({
|
||||
},
|
||||
]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
20581
package-lock.json
generated
Normal file
20581
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@ -2,18 +2,19 @@
|
||||
"name": "nextjs-commerce",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"predev": "node framework/agility/agility.sync.js sync",
|
||||
"predev": "agility-next sync",
|
||||
"dev": "next dev",
|
||||
"prebuild": "node framework/agility/agility.sync.js prebuild",
|
||||
"prebuild": "agility-next prebuild",
|
||||
"build": "next build",
|
||||
"postbuild": "node framework/agility/agility.sync.js postbuild",
|
||||
"export": "next export",
|
||||
"postbuild": "agility-next postbuild",
|
||||
"start": "next start",
|
||||
"cms-pull": "agility-next sync",
|
||||
"cms-clean": "agility-next clean",
|
||||
"analyze": "BUNDLE_ANALYZE=both yarn build",
|
||||
"find:unused": "next-unused",
|
||||
"generate": "graphql-codegen",
|
||||
"generate:definitions": "node framework/bigcommerce/scripts/generate-definitions.js",
|
||||
"cms-pull": "NODE_ENV=development && node framework/agility/agility.sync.js sync",
|
||||
"cms-clear": "node framework/agility/agility.sync.js clear"
|
||||
"generate:definitions": "node framework/bigcommerce/scripts/generate-definitions.js"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
@ -49,7 +50,8 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@agility/content-sync": "^0.1.23",
|
||||
"@agility/content-sync": "^1.0.3",
|
||||
"@agility/nextjs": "^0.1.8",
|
||||
"@reach/portal": "^0.11.2",
|
||||
"@tailwindcss/ui": "^0.6.2",
|
||||
"@vercel/fetch": "^6.1.0",
|
||||
@ -64,12 +66,12 @@
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.random": "^3.2.0",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"next": "^10.0.5-canary.11",
|
||||
"next": "^10.2.3",
|
||||
"next-seo": "^4.11.0",
|
||||
"next-themes": "^0.0.4",
|
||||
"postcss-nesting": "^7.0.1",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-merge-refs": "^1.1.0",
|
||||
"react-ticker": "^1.2.2",
|
||||
"swr": "^0.4.0",
|
||||
|
@ -6,23 +6,23 @@ import type {
|
||||
} from 'next'
|
||||
|
||||
|
||||
|
||||
import { Layout } from '@components/common'
|
||||
import { missingLocaleInPages } from '@lib/usage-warns'
|
||||
|
||||
import { getAgilityPageProps, getAgilityPaths } from "@agility/nextjs/node"
|
||||
import { handlePreview } from "@agility/nextjs"
|
||||
|
||||
import { defaultPageProps } from '@lib/defaults'
|
||||
|
||||
import AgilityPage from "components/agility-global/AgilityPage"
|
||||
|
||||
import { getConfig } from '@framework/api'
|
||||
import getProduct from '@framework/api/operations/get-product'
|
||||
import { getModuleData } from "framework/module-data"
|
||||
|
||||
import { getAgilityPageProps, getAgilityPaths } from "framework/agility/agility.node";
|
||||
import getAllProductPaths from '@framework/api/operations/get-all-product-paths'
|
||||
|
||||
|
||||
export async function getStaticProps({ preview, params, locale }: GetStaticPropsContext<{ slug: string[] }>) {
|
||||
|
||||
export async function getStaticProps({ preview, params, locale, locales, defaultLocale }: GetStaticPropsContext<{ slug: string[] }>) {
|
||||
try {
|
||||
let productCode: string | null = null
|
||||
|
||||
//check if this page is a product...
|
||||
@ -32,10 +32,19 @@ export async function getStaticProps({ preview, params, locale }: GetStaticProps
|
||||
params.slug[1] = "product-details"
|
||||
}
|
||||
|
||||
const page = await getAgilityPageProps({ preview, params, locale });
|
||||
//add any global components (header, footer) that need agility data here
|
||||
const globalComponents = {
|
||||
// "header": GlobalHeader,
|
||||
// "footer": GlobalFooter
|
||||
}
|
||||
|
||||
const agilityProps = await getAgilityPageProps({ preview, params, locale, getModule: getModuleData, defaultLocale, globalComponents });
|
||||
|
||||
|
||||
let rebuildFrequency = 10
|
||||
|
||||
let productDetail:any = null
|
||||
|
||||
if (productCode) {
|
||||
const config = getConfig({ locale })
|
||||
const { product } = await getProduct({
|
||||
@ -45,30 +54,43 @@ export async function getStaticProps({ preview, params, locale }: GetStaticProps
|
||||
})
|
||||
|
||||
if (product !== null) {
|
||||
page.dynamicPageItem = product
|
||||
|
||||
//moderate hack: use the Product as the dynamic page item for product detail pages
|
||||
agilityProps.dynamicPageItem = product
|
||||
rebuildFrequency = 60 * 60 //once per hour for products
|
||||
} else {
|
||||
throw new Error(`Product not found`)
|
||||
}
|
||||
}
|
||||
|
||||
const pages = await getAgilityPaths(preview)
|
||||
|
||||
if (!page) {
|
||||
if (!agilityProps) {
|
||||
// We throw to make sure this fails at build time as this is never expected to happen
|
||||
throw new Error(`Page not found`)
|
||||
}
|
||||
|
||||
return {
|
||||
props: { ...defaultPageProps, pages, page },
|
||||
props: { ...defaultPageProps, agilityProps },
|
||||
revalidate: rebuildFrequency
|
||||
}
|
||||
} catch (err) {
|
||||
var e = new Error();
|
||||
const st = e.stack;
|
||||
|
||||
console.log("Error getting page props", params, err)
|
||||
|
||||
return {
|
||||
props: {
|
||||
error: `Params: ${params}, Error: ${err}, Stack: ${st}`,
|
||||
revalidate: 60000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStaticPaths({ locales }: GetStaticPathsContext) {
|
||||
export async function getStaticPaths({ defaultLocale, locales }: GetStaticPathsContext) {
|
||||
|
||||
//get the paths configured in agility
|
||||
let agilityPaths = await getAgilityPaths(false)
|
||||
let agilityPaths = await getAgilityPaths({ preview: false, defaultLocale, locales })
|
||||
|
||||
//remove product/product-details from the agility paths (special details page...)
|
||||
agilityPaths = agilityPaths.filter(p => p !== "/product/product-details")
|
||||
@ -85,10 +107,10 @@ export async function getStaticPaths({ locales }: GetStaticPathsContext) {
|
||||
}
|
||||
}
|
||||
|
||||
export default function Pages({ page }: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
export default function Pages(props: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
|
||||
return (
|
||||
<AgilityPage {...page} />
|
||||
<AgilityPage {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
|
39
pages/api/bigcommerce/search-products.ts
Normal file
39
pages/api/bigcommerce/search-products.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// import { NextApiRequest, NextApiResponse } from "next"
|
||||
// import getProducts from "../../shopify-api/get-products"
|
||||
|
||||
|
||||
|
||||
// const searchProducts = async (req:NextApiRequest, res:NextApiResponse) => {
|
||||
|
||||
// //cors stuff
|
||||
// res.setHeader('Access-Control-Allow-Credentials', "true")
|
||||
// res.setHeader('Access-Control-Allow-Origin', '*')
|
||||
// res.setHeader('Access-Control-Allow-Methods', 'GET,OPTIONS,PATCH,DELETE,POST,PUT')
|
||||
// res.setHeader(
|
||||
// 'Access-Control-Allow-Headers',
|
||||
// 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
|
||||
// )
|
||||
|
||||
// if (req.method === 'OPTIONS') {
|
||||
// res.status(200).end()
|
||||
// return
|
||||
// }
|
||||
|
||||
// try {
|
||||
// const filter = req.query.filter ?? ""
|
||||
|
||||
// const products = await getProducts({filter})
|
||||
|
||||
// res.statusCode = 200
|
||||
// res.json(products)
|
||||
|
||||
// } catch (e) {
|
||||
|
||||
// res.statusCode = 500
|
||||
// res.json({ message: "An error occurred ", error: e })
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// export default searchProducts
|
188
public/agility-ui-ext/custom-fields.js
Normal file
188
public/agility-ui-ext/custom-fields.js
Normal file
@ -0,0 +1,188 @@
|
||||
//
|
||||
// API Item Picker
|
||||
//
|
||||
|
||||
var baseAPIUrl = "http://localhost:3000"
|
||||
|
||||
var ChooseProductCustomField = function () {
|
||||
/// <summary>The type definition of this Agility Custom Field Type.</summary>
|
||||
var self = this;
|
||||
|
||||
/// <field name="Label" type="String">The display name of the Custom Field Type</field>
|
||||
self.Label = "Choose Product";
|
||||
|
||||
/// <field name="ReferenceName" type="String">The internal reference name of the Custom Field Type. Must not contain any special characters.</field>
|
||||
self.ReferenceName = "ChooseProduct";
|
||||
|
||||
/// <field name="Render" type="Function">This function runs every time the field is rendered</field>
|
||||
self.Render = function (options) {
|
||||
/// <summary>
|
||||
/// The Render handler for this field. Create any elements and bindings that you might need, pull down resources.
|
||||
/// This method will be called everytime to the field value changes.
|
||||
/// </summary>
|
||||
/// <param name="options" type="ContentManager.Global.CustomInputFieldParams">The options used to render this field.</param>
|
||||
|
||||
|
||||
|
||||
//get our base element
|
||||
var $pnl = $(".product-picker-field", options.$elem);
|
||||
|
||||
if ($pnl.size() == 0) {
|
||||
|
||||
var htmlContent = `
|
||||
<style>
|
||||
.prod-img {
|
||||
display:inline-block;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
width: 40px;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.prod-img-small {
|
||||
margin-top: 2px;
|
||||
display:inline-block;
|
||||
height: 20px;
|
||||
border-radius: 5px;
|
||||
width: 20px;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.prod-text {
|
||||
display:inline-block;
|
||||
margin-left: 5px;
|
||||
line-height: 20px;
|
||||
}
|
||||
</style>
|
||||
<input class='product-picker-field' type='hidden' style='width:100%' data-bind='value:selectedValue,select2:select2'>`;
|
||||
//pull down the html template and load it into the element
|
||||
options.$elem.append(htmlContent)
|
||||
|
||||
$pnl = $(".product-picker-field", options.$elem);
|
||||
|
||||
|
||||
//bind our viewmodel to this
|
||||
var viewModel = function () {
|
||||
|
||||
/// <summary>The KO ViewModel that will be binded to your HTML template.</summary>
|
||||
/// <param name="options" type="Object">
|
||||
/// <field name="$elem" type="jQueryElem">The .field-row jQuery Dom Element.</field>
|
||||
/// <field name="contentItem" type="ContentItem Object">The entire Content Item object including Values and their KO Observable properties of all other fields on the form.</field>
|
||||
/// <field name="fieldBinding" type="KO Observable">The value binding of thie Custom Field Type. Get and set this field's value by using this property.</field>
|
||||
/// <field name="fieldSetting" type="Object">Object representing the field's settings such as 'Hidden', 'Label', and 'Description'</field>
|
||||
/// <field name="readonly" type="boolean">Represents if this field should be readonly or not.</field>
|
||||
/// </param>
|
||||
var self = this;
|
||||
|
||||
self.ajaxRequest = null;
|
||||
|
||||
self.selectedValue = options.fieldBinding.extend({ throttle: 500 });
|
||||
|
||||
self.formatResult = function (item) {
|
||||
|
||||
return $(`<div class='prod-img' style="background-image:url('${item.node.featuredImage.transformedSrc}')"/></div><div class='prod-text'>${item.node.title}</div>`);
|
||||
//return item.node.title;
|
||||
};
|
||||
|
||||
|
||||
|
||||
self.formatSelection = function (item) {
|
||||
|
||||
return $(`<div class='prod-img-small' style="background-image:url('${item.node.featuredImage.transformedSrc}')"/></div><div class='prod-text'>${item.node.title}</div>`);
|
||||
|
||||
};
|
||||
self.ajaxRequest = null;
|
||||
|
||||
self.select2 = {
|
||||
label: 'Product',
|
||||
readOnly: false,
|
||||
value: options.fieldBinding,
|
||||
multiple: false,
|
||||
maximumSelectionSize: 1,
|
||||
minimumInputLength: 0,
|
||||
placeholder: 'Find product...',
|
||||
formatResult: self.formatResult,
|
||||
formatSelection: self.formatSelection,
|
||||
templateResult: self.templateResult,
|
||||
|
||||
matcher: function (term, text) {
|
||||
return true;
|
||||
},
|
||||
|
||||
id: function (obj) {
|
||||
//set content of the Agility CMS Content Item
|
||||
|
||||
//options.contentItem.Values.ExternalID(obj.ID)
|
||||
|
||||
//options.contentItem.Values.MyField1(obj.Value1)
|
||||
//options.contentItem.Values.MyField2(obj.Value2)
|
||||
//etc...
|
||||
|
||||
//save the whole thing as JSON
|
||||
return JSON.stringify(obj.node)
|
||||
},
|
||||
|
||||
ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
|
||||
url: `${baseAPIUrl}/api/search-products`,
|
||||
dataType: 'json',
|
||||
type: "get",
|
||||
quietMillis: 250,
|
||||
|
||||
originalValue: ko.unwrap(options.fieldBinding),
|
||||
term: "",
|
||||
data: function (term, page, params) {
|
||||
return {
|
||||
filter: term, // search term
|
||||
};
|
||||
},
|
||||
results: function (data, page) {
|
||||
|
||||
return {
|
||||
results: data
|
||||
};
|
||||
},
|
||||
current: function (data) {
|
||||
|
||||
},
|
||||
cache: true
|
||||
},
|
||||
initSelection: function (element, callback) {
|
||||
//use the hidden "product name" field
|
||||
var json = ko.unwrap(options.fieldBinding);
|
||||
console.log({ json })
|
||||
if (json && json.length > 0) {
|
||||
|
||||
var node = JSON.parse(json)
|
||||
console.log({ node })
|
||||
callback({ node })
|
||||
}
|
||||
|
||||
|
||||
|
||||
// console.log(val)
|
||||
|
||||
// var label = ko.unwrap(options.contentItem.Values.ProductName);
|
||||
|
||||
// if (val && label) {
|
||||
// var data = {
|
||||
// node: {
|
||||
// id: val,
|
||||
// title: label
|
||||
// }
|
||||
// };
|
||||
|
||||
// callback(data);
|
||||
// }
|
||||
},
|
||||
allowClear: false,
|
||||
dropdownCssClass: "bigdrop"
|
||||
};
|
||||
}
|
||||
|
||||
ko.applyBindings(viewModel, $pnl.get(0));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ContentManager.Global.CustomInputFormFields.push(new ChooseProductCustomField());
|
Loading…
x
Reference in New Issue
Block a user