Ken Eucker
Software Engineer and Bicycling Enthusiast
Set slug on publish document action
This schema is for an older version of Sanity Studio (v2), which is deprecated.
Learn how to migrate to the new Studio v3 →{
"parts": [
{
"implements": "part:@sanity/base/document-actions/resolver",
"path": "./schemas/documentActions.js"
}
]
}
// schemas/documentActions.js
import defaultResolve, {
PublishAction,
} from 'part:@sanity/base/document-actions';
import SetSlugAndPublishAction from "./actions/setSlugAndPublishAction.js"
/// Publish Actions
export default function useDocumentActions(props) {
/// Leave the code below commented out to run this action for all documents
/// Uncomment the code below to restrict this action to specific documents only
// if (["tag"].indexOf(props.type) !== -1) {
return defaultResolve(props).map((Action) =>
Action === PublishAction ? SetSlugAndPublishAction : Action
);
// }
// return defaultResolve(props)
}
// schemas/actions/setSlugAndPublishAction.js
import {useState, useEffect} from 'react'
import {useDocumentOperation} from '@sanity/react-hooks'
import sanityClient from '@sanity/client'
const sanityClientConfig = {
projectId: process.env.SANITY_STUDIO_API_PROJECT_ID,
dataset: process.env.SANITY_STUDIO_API_DATASET,
token: process.env.SANITY_STUDIO_API_TOKEN,
useCdn: true,
}
export default function SetSlugAndPublishAction(props) {
const {patch, publish} = useDocumentOperation(props.id, props.type)
const [isPublishing, setIsPublishing] = useState(false)
useEffect(() => {
// if the isPublishing state was set to true and the draft has changed
// to become `null` the document has been published
if (isPublishing && !props.draft) {
setIsPublishing(false)
}
}, [props.draft])
return {
disabled: publish.disabled,
label: isPublishing ? 'Publishing…' : 'Publish',
onHandle: async () => {
// This will update the button text
setIsPublishing(true)
/// Get the sanity client for fetching referenced field values
const client = sanityClient(sanityClientConfig)
/// Set the initial slug value to the name field
let slug = props.draft.name
/// Set the slug based on the document type
switch (props.type) {
case 'tag':
/// The type of the reference field to get the value from
const referenceNameType = 'category'
/// Query for the referenced "category" and return the "name" field of that referenced document
const query = `*[_type == "${referenceNameType}" && _id == $nameRef][0] {name}`
/// Start with the "category: reference id in the draft
let referenceName = props.draft.category._ref
/// Fetch the category referenced in this document
await client.fetch(query, {nameRef: referenceName}).then(category => {
/// Set the referenceName to the category.name field
referenceName = !!category ? category.name : referenceName
})
/// For the "tag" type document, set the slug to [category.name]-[type]-[number]
slug = `${referenceName}-${props.type}-${props.draft.number}`
/// Set name field for the "tag" type document to be the same value as the slug
patch.execute([{set: { name: slug.toLowerCase() }}])
break;
default:
/// Doing nothing? Consider deleting this switch statement to simplify your code.
break;
}
/// Set the slug field of this document
patch.execute([{set: { slug: { _type: 'slug', current: slug.toLowerCase() }}}])
// Perform the publish
publish.execute()
// Signal that the action is completed
props.onComplete()
}
}
}
What this code does, in order of operations, is the following:
This code makes the following assumptions about your code, which you can modify to meet your schema's needs, using simple field names for the sake of education:
number
, category
, and slug
.name
field within it, of type
string, and presumably a slug
field.slug
and name
field.My use case for this code was to meet the following needs:
Your mileage may vary.
This code example could have been simplified by setting the slug in the same way for all document types. In conjunction with that simplification, the commented-out code in the documentActions.js file could be an easier way to separate the logic between different document types and the way that the slug field is set upon publish, or to only include this publish action with a single document type.
Software Engineer and Bicycling Enthusiast