diff --git a/.sanity-template/manifest.json b/.sanity-template/manifest.json
index 78c72ce..cf77012 100644
--- a/.sanity-template/manifest.json
+++ b/.sanity-template/manifest.json
@@ -1,55 +1,54 @@
{
- "version": 2,
- "title": "HULL – Shopify Starter",
- "description": "Headless Shopify starter powered by Next.js + Sanity.io",
- "previewMedia": {
- "type": "image",
- "src": ".sanity-template/assets/HULL-cover.png",
- "alt": "HULL"
+ "version": 2,
+ "title": "HULL – Shopify Starter",
+ "description": "Headless Shopify starter powered by Next.js + Sanity.io",
+ "previewMedia": {
+ "type": "image",
+ "src": ".sanity-template/assets/HULL-cover.png",
+ "alt": "HULL"
+ },
+ "technologies": [
+ {
+ "id": "nextjs",
+ "name": "Next.js",
+ "url": "https://nextjs.org/"
},
- "technologies": [
+ {
+ "id": "vercel",
+ "name": "Vercel",
+ "url": "https://vercel.com/"
+ },
+ {
+ "id": "shopify",
+ "name": "Shopify",
+ "url": "https://shopify.com/"
+ }
+ ],
+ "deployment": {
+ "provider": "vercel",
+ "studio": {
+ "basePath": "/studio"
+ },
+ "envVars": {
+ "dataset": ["NEXT_PUBLIC_SANITY_PROJECT_DATASET"],
+ "projectId": ["NEXT_PUBLIC_SANITY_PROJECT_ID"]
+ },
+ "tokens": [
{
- "id": "nextjs",
- "name": "Next.js",
- "url": "https://nextjs.org/"
- },
+ "label": "Live Preview",
+ "role": "write",
+ "envVar": "SANITY_API_TOKEN"
+ }
+ ],
+ "corsOrigins": [
{
- "id": "vercel",
- "name": "Vercel",
- "url": "https://vercel.com/"
+ "origin": "https://*.vercel.app",
+ "allowCredentials": true
},
{
- "id": "shopify",
- "name": "Shopify",
- "url": "https://shopify.com/"
+ "origin": "http://localhost:3000",
+ "allowCredentials": true
}
- ],
- "deployment": {
- "provider": "vercel",
- "studio": {
- "basePath": "/studio"
- },
- "envVars": {
- "dataset": ["SANITY_PROJECT_DATASET"],
- "projectId": ["SANITY_PROJECT_ID"]
- },
- "tokens": [
- {
- "label": "Live Preview",
- "role": "write",
- "envVar": "SANITY_API_TOKEN"
- }
- ],
- "corsOrigins": [
- {
- "origin": "https://*.vercel.app",
- "allowCredentials": true
- },
- {
- "origin": "http://localhost:3000",
- "allowCredentials": true
- }
- ]
- }
+ ]
}
-
\ No newline at end of file
+}
diff --git a/README.md b/README.md
index bf14a0d..a9263f1 100644
--- a/README.md
+++ b/README.md
@@ -101,7 +101,7 @@ _Using the Sanity Vercel Deploy plugin, see how easy it is to empower your clien
Quickly [deploy as a Sanity Starter](https://www.sanity.io/create?template=ndimatteo/HULL) on [Vercel](https://vercel.com) with a pre-populated store! Once deployed, simply follow step 2 and 3 below to connect your Shopify store.
-> ⚠️ **Important!**
You should delete the demo products once you connect your own Shopify account. Demo products will not function properly as they are not part of _your Shopify store_. Additionally, any existing products in your Shopify store will not automatically sync into Sanity. To trigger a sync, you must make a change to your existing product(s) in Shopify first.
+> **Warning**
You should delete the demo products once you connect your own Shopify account. Demo products will not function properly as they are not part of _your Shopify store_. Additionally, any existing products in your Shopify store will not automatically sync into Sanity. To trigger a sync, you must make a change to your existing product(s) in Shopify first.
@@ -147,7 +147,7 @@ Clone this repository from your GitHub account with the [Use this template](http
- Product creation - `[live-domain]/api/shopify/product-update`
- Product update - `[live-domain]/api/shopify/product-update`
- Product deletion - `[live-domain]/api/shopify/product-delete`
- > ⚠️ **Note**
You have to use a real, live domain name (not localhost!). Be sure to use your Vercel project URL during development, and then switch to the production domain once live. You may not know your Vercel project URL until you deploy, feel free to enter something temporary, but make sure to update this once deployed!
+ > **Warning**
You have to use a real, live domain name (not localhost!). Be sure to use your Vercel project URL during development, and then switch to the production domain once live. You may not know your Vercel project URL until you deploy, feel free to enter something temporary, but make sure to update this once deployed!
### 4) NextJS
@@ -155,13 +155,13 @@ Clone this repository from your GitHub account with the [Use this template](http
2. Create an `.env.local` file in the project folder, and add the following variables:
```
-SANITY_PROJECT_DATASET=production
-SANITY_PROJECT_ID=XXXXXX
+NEXT_PUBLIC_SANITY_PROJECT_DATASET=production
+NEXT_PUBLIC_SANITY_PROJECT_ID=XXXXXX
SANITY_API_TOKEN=XXXXXX
SANITY_STUDIO_PREVIEW_SECRET=XXXXXX
-SHOPIFY_STORE_ID=XXXXXX
-SHOPIFY_STOREFRONT_API_TOKEN=XXXXXX
+NEXT_PUBLIC_SHOPIFY_STORE_ID=XXXXXX
+NEXT_PUBLIC_SHOPIFY_STOREFRONT_API_TOKEN=XXXXXX
SHOPIFY_ADMIN_API_TOKEN=XXXXXX
SHOPIFY_WEBHOOK_INTEGRITY=XXXXXX
@@ -178,12 +178,12 @@ SENDGRID_API_KEY=XXXXXX
3. Update all the `XXXXXX` values, here's where to find each:
-- `SANITY_PROJECT_ID` - You can grab this after you've initalized Sanity, either from the `studio/sanity.json` file, or from your Sanity Manage dashboard
+- `NEXT_PUBLIC_SANITY_PROJECT_ID` - You can grab this after you've initalized Sanity, either from the `studio/sanity.json` file, or from your Sanity Manage dashboard
- `SANITY_API_TOKEN` - Generate an API token for your Sanity project. Access your project from the Sanity Manage dashboard, and navigate to: "Settings" -> "API" -> "Add New Token" button. Make sure you give `read + write` access!
- `SANITY_STUDIO_PREVIEW_SECRET` - A unique string of your choice. This is used to confirm the authenticity of "preview mode" requests from the Sanity Studio
-- `SHOPIFY_STORE_ID` - This is your Shopify store ID, it's the subdomain behind `.myshopify.com`
+- `NEXT_PUBLIC_SHOPIFY_STORE_ID` - This is your Shopify store ID, it's the subdomain behind `.myshopify.com`
+- `NEXT_PUBLIC_SHOPIFY_STOREFRONT_API_TOKEN` - Copy the Storefront API access token from "Apps" -> "Develop apps" -> [your_custom_app] -> "API credentials".
- `SHOPIFY_ADMIN_API_TOKEN` - Copy the Admin API access token from "Apps" -> "Develop apps" -> [your_custom_app] -> "API credentials". (__Note: you’ll only be able to reveal your Admin API token once.__)
-- `SHOPIFY_STOREFRONT_API_TOKEN` - Copy the Storefront API access token from "Apps" -> "Develop apps" -> [your_custom_app] -> "API credentials".
- `SHOPIFY_WEBHOOK_INTEGRITY` - Copy the Integrity hash from "Settings" -> "Notifications" -> "Webhooks" _(very bottom of page)_
- `KLAVIYO_API_KEY` - Create a Private API Key from your Klaviyo Account "Settings" -> "API Keys"
- `MAILCHIMP_API_KEY` - Create an API key from "Account -> "Extras" -> API Keys
@@ -217,7 +217,7 @@ This will essentially "pass-through" URLs accessed at your Shopify Store to your
`yarn dev` in the `/studio` folder to start the studio locally
- Your Sanity Studio should be running on [http://localhost:3333](http://localhost:3333)
- > ⚠️ **Gotcha!**
If you did not manually set up your project, the `projectId` in `/studio/sanity.json` will still be set to the HULL demo project. Make sure to update this before starting the studio, otherwise you will be denied access when trying to access your studio.
+ > **Warning**
If you did not manually set up your project, the `projectId` in `/studio/sanity.json` will still be set to the HULL demo project. Make sure to update this before starting the studio, otherwise you will be denied access when trying to access your studio.
diff --git a/lib/sanity.js b/lib/sanity.js
index de9e99c..3837236 100644
--- a/lib/sanity.js
+++ b/lib/sanity.js
@@ -2,10 +2,10 @@ import createSanityClient from '@sanity/client'
import sanityImage from '@sanity/image-url'
const options = {
- dataset: process.env.SANITY_PROJECT_DATASET,
- projectId: process.env.SANITY_PROJECT_ID,
+ dataset: process.env.NEXT_PUBLIC_SANITY_PROJECT_DATASET,
+ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
useCdn: process.env.NODE_ENV === 'production',
- apiVersion: '2021-03-25',
+ apiVersion: '2022-08-30',
}
export const sanityClient = createSanityClient(options)
diff --git a/lib/shopify.js b/lib/shopify.js
index 6cbf81a..9012741 100644
--- a/lib/shopify.js
+++ b/lib/shopify.js
@@ -4,7 +4,8 @@ import { isBrowser } from '@lib/helpers'
// First, check that Shopify variables are set
const hasShopify =
- process.env.SHOPIFY_STORE_ID && process.env.SHOPIFY_STOREFRONT_API_TOKEN
+ process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID &&
+ process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_API_TOKEN
// Warn the client if variables are missing
if (!hasShopify && isBrowser) {
@@ -13,8 +14,8 @@ if (!hasShopify && isBrowser) {
// Otherwise, setup the client and export
const options = {
- domain: `${process.env.SHOPIFY_STORE_ID}.myshopify.com`,
- storefrontAccessToken: process.env.SHOPIFY_STOREFRONT_API_TOKEN,
+ domain: `${process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID}.myshopify.com`,
+ storefrontAccessToken: process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_API_TOKEN,
}
export default hasShopify ? Client.buildClient(options) : null
diff --git a/next.config.js b/next.config.js
index b52fdfd..d6e5657 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,9 +1,9 @@
const sanityClient = require('@sanity/client')
const client = sanityClient({
- dataset: process.env.SANITY_PROJECT_DATASET,
- projectId: process.env.SANITY_PROJECT_ID,
+ dataset: process.env.NEXT_PUBLIC_SANITY_PROJECT_DATASET,
+ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
useCdn: process.env.NODE_ENV === 'production',
- apiVersion: '2021-03-25',
+ apiVersion: '2022-08-30',
})
// see breakdown of code bloat
@@ -13,47 +13,19 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
// get redirects from Sanity for Vercel
async function fetchSanityRedirects() {
- const data = await client.fetch(
- `*[_type == "redirect"]{ from, to, isPermanent }`
- )
-
- const redirects = data.map((redirect) => {
- return {
- source: `/${redirect.from}`,
- destination: `/${redirect.to}`,
- permanent: redirect.isPermanent,
+ const redirectData = await client.fetch(`
+ *[_type == "redirect"]{
+ "source": "/" + from,
+ "destination": "/" + to,
+ "permanent": isPermanent
}
- })
+ `)
- return redirects
+ return redirectData
}
module.exports = withBundleAnalyzer({
swcMinify: true,
- env: {
- // Needed for Sanity powered data
- SANITY_PROJECT_DATASET: process.env.SANITY_PROJECT_DATASET,
- SANITY_PROJECT_ID: process.env.SANITY_PROJECT_ID,
- SANITY_API_TOKEN: process.env.SANITY_API_TOKEN,
-
- // Needed for Shopify product syncs
- SHOPIFY_STORE_ID: process.env.SHOPIFY_STORE_ID,
- SHOPIFY_STOREFRONT_API_TOKEN: process.env.SHOPIFY_STOREFRONT_API_TOKEN,
-
- // Needed for Klaviyo forms
- KLAVIYO_API_KEY: process.env.KLAVIYO_API_KEY,
-
- // Needed for Yotpo reviews
- YOTPO_API_KEY: process.env.YOTPO_API_KEY,
- YOTPO_SECRET_KEY: process.env.YOTPO_SECRET_KEY,
-
- // Needed for Mailchimp forms
- MAILCHIMP_API_KEY: process.env.MAILCHIMP_API_KEY,
- MAILCHIMP_SERVER: process.env.MAILCHIMP_SERVER,
-
- // Needed for SendGrid forms
- SENDGRID_API_KEY: process.env.SENDGRID_API_KEY,
- },
async redirects() {
const sanityRedirects = await fetchSanityRedirects()
return sanityRedirects
@@ -71,4 +43,14 @@ module.exports = withBundleAnalyzer({
},
]
},
+ images: {
+ domains: ['i.vimeocdn.com', 'img.youtube.com'],
+ deviceSizes: [
+ 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800,
+ 3000, 3200, 3400,
+ ],
+ imageSizes: [
+ 20, 30, 40, 50, 60, 80, 100, 120, 140, 180, 220, 260, 300, 340, 380, 390,
+ ],
+ },
})
diff --git a/package.json b/package.json
index 23865fe..fcdbd01 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "hull",
- "version": "2.6.0",
+ "version": "2.7.0",
"scripts": {
"dev": "cross-env NODE_ENV=development next dev",
"build": "echo 'Building Sanity to public/studio…' && cd studio && npx sanity build ../public/studio -y && cd .. && next build",
@@ -14,35 +14,35 @@
"license": "MIT",
"dependencies": {
"@mailchimp/mailchimp_marketing": "^3.0.71",
- "@reach/rect": "0.17.0",
+ "@reach/rect": "^0.18.0",
"@sanity/block-content-to-react": "^3.0.0",
"@sanity/client": "^3.0.3",
"@sanity/image-url": "^1.0.1",
"@vimeo/player": "^2.15.3",
- "axios": "0.27.2",
+ "axios": "^1.2.1",
"base64-string": "^1.1.2",
"classnames": "^2.2.6",
"contrast-color": "^1.0.1",
"cross-env": "^7.0.3",
"embla-carousel-react": "^7.0.1",
"focus-trap-react": "^10.0.0",
- "framer-motion": "^7.2.1",
+ "framer-motion": "^8.0.2",
"js-cookie": "^3.0.0",
"jsondiffpatch": "^0.4.1",
"marqy": "^0.0.8",
"next": "^12.0.7",
- "next-themes": "0.2.0",
+ "next-themes": "^0.2.1",
"qs": "^6.10.1",
- "query-string": "^7.0.1",
+ "query-string": "^8.1.0",
"raw-body": "^2.4.1",
"react": "^18.2.0",
"react-cool-inview": "3.0.1",
"react-dom": "^18.2.0",
- "react-hook-form": "7.34.2",
+ "react-hook-form": "^7.41.2",
"react-keyed-flatten-children": "^1.3.0",
"shopify-buy": "^2.13.0",
"sitemap": "^7.0.0",
- "swr": "^1.0.0"
+ "swr": "^2.0.0"
},
"devDependencies": {
"@next/bundle-analyzer": "^12.0.1",
@@ -54,7 +54,7 @@
"autoprefixer": "^10.4.0",
"cssnano": "^5.0.13",
"postcss": "^8.3.11",
- "postcss-import": "^14.0.2",
+ "postcss-import": "^15.1.0",
"tailwindcss": "^3.0.5",
"typescript": "^4.4.4"
},
diff --git a/pages/api/shopify/product-delete.js b/pages/api/shopify/product-delete.js
index f4549b4..0c92ff1 100644
--- a/pages/api/shopify/product-delete.js
+++ b/pages/api/shopify/product-delete.js
@@ -3,10 +3,10 @@ import crypto from 'crypto'
const getRawBody = require('raw-body')
const sanity = sanityClient({
- dataset: process.env.SANITY_PROJECT_DATASET,
- projectId: process.env.SANITY_PROJECT_ID,
+ dataset: process.env.NEXT_PUBLIC_SANITY_PROJECT_DATASET,
+ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
token: process.env.SANITY_API_TOKEN,
- apiVersion: '2021-03-25',
+ apiVersion: '2022-08-30',
useCdn: false,
})
diff --git a/pages/api/shopify/product-images.js b/pages/api/shopify/product-images.js
index 7a2714e..8176db2 100644
--- a/pages/api/shopify/product-images.js
+++ b/pages/api/shopify/product-images.js
@@ -5,10 +5,10 @@ import { queries } from '@data'
import { buildSrc } from '@lib/helpers'
const sanity = sanityClient({
- dataset: process.env.SANITY_PROJECT_DATASET,
- projectId: process.env.SANITY_PROJECT_ID,
+ dataset: process.env.NEXT_PUBLIC_SANITY_PROJECT_DATASET,
+ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
token: process.env.SANITY_API_TOKEN,
- apiVersion: '2021-03-25',
+ apiVersion: '2022-08-30',
useCdn: false,
})
@@ -78,7 +78,7 @@ export default async function handler(req, res) {
// Write our images to Shopify
const shopifyProduct = await axios({
- url: `https://${process.env.SHOPIFY_STORE_ID}.myshopify.com/admin/api/2021-04/products/${productID}.json`,
+ url: `https://${process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID}.myshopify.com/admin/api/2022-10/products/${productID}.json`,
method: 'PUT',
headers: shopifyConfig,
data: {
diff --git a/pages/api/shopify/product-inventory.js b/pages/api/shopify/product-inventory.js
index 868db40..d3844a9 100644
--- a/pages/api/shopify/product-inventory.js
+++ b/pages/api/shopify/product-inventory.js
@@ -6,7 +6,8 @@ export default async function send(req, res) {
} = req
const hasShopify =
- process.env.SHOPIFY_STORE_ID && process.env.SHOPIFY_ADMIN_API_TOKEN
+ process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID &&
+ process.env.SHOPIFY_ADMIN_API_TOKEN
// Bail if no product ID was supplied
if (!id) {
@@ -26,7 +27,7 @@ export default async function send(req, res) {
// Fetch our product from Shopify
const shopifyProduct = await axios({
- url: `https://${process.env.SHOPIFY_STORE_ID}.myshopify.com/admin/api/2021-01/products/${id}.json`,
+ url: `https://${process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID}.myshopify.com/admin/api/2022-10/products/${id}.json`,
method: 'GET',
headers: shopifyConfig,
})
diff --git a/pages/api/shopify/product-update.js b/pages/api/shopify/product-update.js
index 6c278ab..2c9c92e 100644
--- a/pages/api/shopify/product-update.js
+++ b/pages/api/shopify/product-update.js
@@ -6,10 +6,10 @@ const getRawBody = require('raw-body')
const jsondiffpatch = require('jsondiffpatch')
const sanity = sanityClient({
- dataset: process.env.SANITY_PROJECT_DATASET,
- projectId: process.env.SANITY_PROJECT_ID,
+ dataset: process.env.NEXT_PUBLIC_SANITY_PROJECT_DATASET,
+ projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
token: process.env.SANITY_API_TOKEN,
- apiVersion: '2021-03-25',
+ apiVersion: '2022-08-30',
useCdn: false,
})
@@ -73,7 +73,7 @@ export default async function send(req, res) {
body: { status, id, title, handle, options, variants },
} = req
- console.info(`Sync triggered for product: ${title} (id: ${id})`)
+ console.info(`Sync triggered for product: "${title}" (id: ${id})`)
/* ------------------------------ */
/* Construct our product objects
@@ -173,12 +173,13 @@ export default async function send(req, res) {
// Setup our Shopify connection
const shopifyConfig = {
'Content-Type': 'application/json',
+ 'Accept-Encoding': 'gzip,deflate,compress',
'X-Shopify-Access-Token': process.env.SHOPIFY_ADMIN_API_TOKEN,
}
// Fetch the metafields for this product
const shopifyProduct = await axios({
- url: `https://${process.env.SHOPIFY_STORE_ID}.myshopify.com/admin/products/${id}/metafields.json`,
+ url: `https://${process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID}.myshopify.com/admin/api/2022-10/products/${id}/metafields.json`,
method: 'GET',
headers: shopifyConfig,
})
@@ -198,14 +199,14 @@ export default async function send(req, res) {
// update our shopify metafield with the new data before continuing sync with Sanity
axios({
- url: `https://${process.env.SHOPIFY_STORE_ID}.myshopify.com/admin/products/${id}/metafields/${previousSync.id}.json`,
+ url: `https://${process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID}.myshopify.com/admin/api/2022-10/products/${id}/metafields/${previousSync.id}.json`,
method: 'PUT',
headers: shopifyConfig,
data: {
metafield: {
id: previousSync.id,
value: JSON.stringify(productCompare),
- value_type: 'string',
+ type: 'json',
},
},
})
@@ -221,7 +222,7 @@ export default async function send(req, res) {
} else {
console.warn('No previous sync found, Start sync...')
axios({
- url: `https://${process.env.SHOPIFY_STORE_ID}.myshopify.com/admin/products/${id}/metafields.json`,
+ url: `https://${process.env.NEXT_PUBLIC_SHOPIFY_STORE_ID}.myshopify.com/admin/api/2022-10/products/${id}/metafields.json`,
method: 'POST',
headers: shopifyConfig,
data: {
@@ -229,7 +230,7 @@ export default async function send(req, res) {
namespace: 'sanity',
key: 'product_sync',
value: JSON.stringify(productCompare),
- value_type: 'string',
+ type: 'json',
},
},
})
diff --git a/pages/products/[slug].js b/pages/products/[slug].js
index 0b73852..14884b3 100644
--- a/pages/products/[slug].js
+++ b/pages/products/[slug].js
@@ -90,7 +90,7 @@ const Product = ({ data }) => {
// check our product inventory is still correct
const { data: productInventory } = useSWR(
['/api/shopify/product-inventory', page.product.id],
- (url, id) => fetchInventory(url, id),
+ ([url, id]) => fetchInventory(url, id),
{ errorRetryCount: 3 }
)
diff --git a/studio/branding/loader.js b/studio/branding/loader.js
new file mode 100644
index 0000000..a2cffd9
--- /dev/null
+++ b/studio/branding/loader.js
@@ -0,0 +1,65 @@
+import React from 'react'
+import styled from 'styled-components'
+
+const Loader = ({ text = 'Loading...' }) => {
+ return (
+
+
+
+
+
+ {text}
+
+
+ )
+}
+
+const LoadingScreen = styled.div`
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
+ Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ text-align: center;
+ display: flex;
+ width: 100vw;
+ height: 100vh;
+ position: absolute;
+ top: 0;
+ left: 0;
+ background: #000000;
+ color: #f4f4f0;
+`
+
+const LoadingScreenContent = styled.div`
+ margin: auto;
+
+ p {
+ margin-top: 2rem;
+ font-size: 13px;
+ font-weight: 600;
+ }
+`
+
+const LoadingScreenIcon = styled.div`
+ margin: 0 auto;
+ width: 100%;
+ max-width: 6rem;
+
+ svg {
+ display: block;
+ width: 100%;
+ max-width: none;
+ height: auto;
+ fill: currentColor;
+ }
+`
+
+export default Loader
diff --git a/studio/package.json b/studio/package.json
index 8e0e8aa..68b6527 100644
--- a/studio/package.json
+++ b/studio/package.json
@@ -10,24 +10,23 @@
"test": "sanity check"
},
"dependencies": {
- "@sanity/base": "^2.31.0",
- "@sanity/cli": "^2.31.0",
- "@sanity/color-input": "^2.31.0",
+ "@sanity/base": "^2.35.4",
+ "@sanity/cli": "^2.35.3",
+ "@sanity/color-input": "^2.36.0",
"@sanity/components": "^2.14.0",
- "@sanity/core": "^2.31.0",
- "@sanity/dashboard": "^2.31.0",
- "@sanity/default-layout": "^2.31.0",
- "@sanity/default-login": "^2.31.0",
- "@sanity/desk-tool": "^2.31.0",
- "@sanity/vision": "^2.31.0",
+ "@sanity/core": "^2.35.3",
+ "@sanity/dashboard": "^2.36.0",
+ "@sanity/default-layout": "^2.35.4",
+ "@sanity/default-login": "^2.35.4",
+ "@sanity/desk-tool": "^2.35.4",
+ "@sanity/vision": "^2.35.4",
"nanoid": "^4.0.0",
"phosphor-react": "^1.3.1",
"prop-types": "^15.7.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.2.0",
- "sanity-plugin-dashboard-widget-document-list": "^0.0.13",
- "sanity-plugin-media": "^1.4.0",
+ "sanity-plugin-media": "^1.5.1",
"sanity-plugin-note-field": "^1.1.4",
"sanity-plugin-vercel-deploy": "2.1.6",
"styled-components": "^5.3.0"
@@ -37,10 +36,10 @@
"eslint": "^8.22.0",
"eslint-config-sanity": "^6.0.0",
"eslint-config-standard": "^17.0.0",
- "eslint-config-standard-react": "^11.0.1",
+ "eslint-config-standard-react": "^13.0.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
- "eslint-plugin-promise": "6.0.1",
+ "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-standard": "^5.0.0",
"prettier-eslint-cli": "^7.1.0"
diff --git a/studio/parts/resolve-actions.js b/studio/parts/resolve-actions.js
index a9ca1c8..bd5bad5 100644
--- a/studio/parts/resolve-actions.js
+++ b/studio/parts/resolve-actions.js
@@ -6,12 +6,11 @@ import sanityClient from 'part:@sanity/base/client'
import defaultResolve, {
PublishAction,
DiscardChangesAction,
- DeleteAction
+ DeleteAction,
} from 'part:@sanity/base/document-actions'
import { useToast } from '@sanity/ui'
-
-import { Eye, Storefront } from 'phosphor-react'
+import { EyeOpenIcon, BasketIcon, SyncIcon } from '@sanity/icons'
const singletons = [
'generalSettings',
@@ -20,21 +19,21 @@ const singletons = [
'headerSettings',
'footerSettings',
'shopSettings',
- 'seoSettings'
+ 'seoSettings',
]
const editAndDelete = ['product', 'productVariant']
const previews = ['page', 'product', 'collection']
-const PreviewAction = props => {
+const PreviewAction = (props) => {
const slug = props.draft
? props.draft.slug?.current
: props.published?.slug?.current
return {
label: 'Open Preview',
- icon: () => ,
+ icon: EyeOpenIcon,
onHandle: async () => {
const localURL = 'http://localhost:3000'
const remoteURL = await sanityClient.fetch(
@@ -45,25 +44,31 @@ const PreviewAction = props => {
window.location.hostname === 'localhost' ? localURL : remoteURL
window.open(
- `${frontendURL}/api/preview?token=HULL&type=${props.type}&slug=${slug ||
- ''}`
+ `${frontendURL}/api/preview?token=HULL&type=${props.type}&slug=${
+ slug || ''
+ }`
)
- }
+ },
}
}
-const ShopifyAction = props => {
+const ShopifyAction = ({ draft, published }) => {
const [isSyncing, setIsSyncing] = useState(false)
const toast = useToast()
return {
- disabled: !props.published?.productID,
label: isSyncing ? 'Syncing...' : 'Sync images to Shopify',
- icon: () => ,
+ icon: isSyncing ? SyncIcon : BasketIcon,
+ disabled: draft || !published?.productID,
+ title: draft ? 'Must be published first' : null,
onHandle: async () => {
setIsSyncing(true)
+ toast.push({
+ title: 'Beginning Sync...',
+ })
+
const localURL = 'http://localhost:3000'
const remoteURL = await sanityClient.fetch(
'*[_type == "generalSettings"][0].siteURL'
@@ -74,34 +79,35 @@ const ShopifyAction = props => {
axios({
url: `${frontendURL}/api/shopify/product-images`,
method: 'POST',
- data: props.published
+ data: published,
})
- .then(res => res.data)
- .then(res => {
+ .then((res) => res.data)
+ .then((res) => {
setIsSyncing(false)
if (res.error) {
toast.push({
status: 'error',
- description: res.error
+ title: 'Error',
+ description: res.error,
})
} else {
toast.push({
status: 'success',
- description: 'Photos sync’d successfully!'
+ title: 'Photos sync’d to Shopify successfully!',
})
}
})
- .catch(err => {
+ .catch((err) => {
setIsSyncing(false)
- console.log(err)
toast.push({
status: 'error',
- description: 'There was an error.'
+ title: 'Error!',
+ description: 'An unknown error occurred',
})
})
- }
+ },
}
}
@@ -115,7 +121,7 @@ export default function resolveDocumentActions(props) {
return [
PublishAction,
DiscardChangesAction,
- ...(canPreview ? [PreviewAction] : [])
+ ...(canPreview ? [PreviewAction] : []),
]
}
@@ -125,7 +131,7 @@ export default function resolveDocumentActions(props) {
DiscardChangesAction,
DeleteAction,
...(canPreview ? [PreviewAction] : []),
- ...(isProduct ? [ShopifyAction] : [])
+ ...(isProduct ? [ShopifyAction] : []),
]
}
diff --git a/studio/sanity.json b/studio/sanity.json
index aeeed07..ffcc55e 100644
--- a/studio/sanity.json
+++ b/studio/sanity.json
@@ -41,6 +41,10 @@
"implements": "part:@sanity/base/brand-logo",
"path": "./branding/logo.js"
},
+ {
+ "implements": "part:@sanity/base/app-loading-screen",
+ "path": "./branding/loader.js"
+ },
{
"implements": "part:@sanity/base/theme/variables/override-style",
"path": "./branding/skin.css"