203 lines
5.1 KiB
TypeScript
203 lines
5.1 KiB
TypeScript
import {defineArrayMember, defineField, defineType} from 'sanity'
|
|
import {DocumentTextIcon} from '@sanity/icons'
|
|
import {blogAuthors, blogCategories} from './blog-options'
|
|
|
|
export const blogType = defineType({
|
|
name: 'blog',
|
|
title: 'Blog',
|
|
type: 'document',
|
|
icon: DocumentTextIcon,
|
|
|
|
groups: [
|
|
{name: 'main', title: 'Main', default: true},
|
|
{name: 'content', title: 'Content'},
|
|
{name: 'references', title: 'Related'},
|
|
],
|
|
|
|
fieldsets: [{name: 'details', title: 'Details', options: {columns: 2}}],
|
|
|
|
fields: [
|
|
defineField({
|
|
name: 'title',
|
|
title: 'Title',
|
|
type: 'string',
|
|
group: 'main',
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'subtitle',
|
|
title: 'Subtitle',
|
|
type: 'string',
|
|
group: 'main',
|
|
}),
|
|
defineField({
|
|
name: 'featuredImage',
|
|
title: 'Featured Image',
|
|
type: 'image',
|
|
group: 'main',
|
|
options: {hotspot: true},
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'slug',
|
|
title: 'Slug',
|
|
type: 'slug',
|
|
group: 'main',
|
|
fieldset: 'details',
|
|
options: {
|
|
source: 'title',
|
|
maxLength: 200,
|
|
},
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'author',
|
|
title: 'Author',
|
|
type: 'string',
|
|
group: 'main',
|
|
fieldset: 'details',
|
|
options: {
|
|
list: blogAuthors,
|
|
},
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'publishDate',
|
|
title: 'Publish Date',
|
|
type: 'date',
|
|
group: 'main',
|
|
fieldset: 'details',
|
|
description: 'Defaults to today. Override to backdate or schedule a post.',
|
|
initialValue: () => new Date().toISOString().split('T')[0],
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
defineField({
|
|
name: 'category',
|
|
title: 'Category',
|
|
type: 'string',
|
|
group: 'main',
|
|
fieldset: 'details',
|
|
options: {
|
|
list: blogCategories,
|
|
},
|
|
validation: (Rule) => Rule.required(),
|
|
}),
|
|
|
|
defineField({
|
|
name: 'content',
|
|
title: 'Content',
|
|
type: 'array',
|
|
group: 'content',
|
|
of: [
|
|
defineArrayMember({type: 'block'}),
|
|
defineArrayMember({
|
|
type: 'image',
|
|
options: {hotspot: true},
|
|
fields: [
|
|
defineField({
|
|
name: 'alt',
|
|
title: 'Alt text',
|
|
type: 'string',
|
|
description: 'Describe the image for accessibility.',
|
|
}),
|
|
defineField({
|
|
name: 'caption',
|
|
title: 'Caption',
|
|
type: 'string',
|
|
}),
|
|
],
|
|
}),
|
|
defineArrayMember({
|
|
type: 'object',
|
|
name: 'youtube',
|
|
title: 'YouTube Video',
|
|
fields: [
|
|
defineField({
|
|
name: 'url',
|
|
title: 'YouTube URL',
|
|
type: 'url',
|
|
validation: (Rule) =>
|
|
Rule.required()
|
|
.uri({scheme: ['https']})
|
|
.custom((url) => {
|
|
if (typeof url !== 'string') return true
|
|
if (
|
|
url.includes('youtube.com/watch') ||
|
|
url.includes('youtu.be/') ||
|
|
url.includes('youtube.com/embed/')
|
|
) {
|
|
return true
|
|
}
|
|
return 'Must be a valid YouTube URL'
|
|
}),
|
|
}),
|
|
],
|
|
preview: {
|
|
select: {url: 'url'},
|
|
prepare({url}) {
|
|
return {title: 'YouTube Video', subtitle: url}
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
}),
|
|
|
|
defineField({
|
|
name: 'releases',
|
|
title: 'Related Release(s)',
|
|
type: 'array',
|
|
group: 'references',
|
|
of: [defineArrayMember({type: 'reference', to: [{type: 'release'}]})],
|
|
}),
|
|
defineField({
|
|
name: 'artists',
|
|
title: 'Related Artist(s)',
|
|
type: 'array',
|
|
group: 'references',
|
|
of: [defineArrayMember({type: 'reference', to: [{type: 'artist'}]})],
|
|
}),
|
|
defineField({
|
|
name: 'composers',
|
|
title: 'Related Composer(s)',
|
|
type: 'array',
|
|
group: 'references',
|
|
of: [defineArrayMember({type: 'reference', to: [{type: 'composer'}]})],
|
|
}),
|
|
defineField({
|
|
name: 'works',
|
|
title: 'Related Work(s)',
|
|
type: 'array',
|
|
group: 'references',
|
|
of: [defineArrayMember({type: 'reference', to: [{type: 'work'}]})],
|
|
}),
|
|
],
|
|
|
|
orderings: [
|
|
{
|
|
title: 'Publish Date (latest first)',
|
|
name: 'publishDateDesc',
|
|
by: [{field: 'publishDate', direction: 'desc'}],
|
|
},
|
|
{
|
|
title: 'Publish Date (oldest first)',
|
|
name: 'publishDateAsc',
|
|
by: [{field: 'publishDate', direction: 'asc'}],
|
|
},
|
|
],
|
|
|
|
preview: {
|
|
select: {
|
|
title: 'title',
|
|
author: 'author',
|
|
media: 'featuredImage',
|
|
category: 'category',
|
|
},
|
|
prepare({title, author, media, category}) {
|
|
return {
|
|
title: title || '(Untitled post)',
|
|
subtitle: [author, category].filter(Boolean).join(' · '),
|
|
media,
|
|
}
|
|
},
|
|
},
|
|
})
|