Skip to content

Instantly share code, notes, and snippets.

@ajmalafif
Last active October 16, 2021 09:46
Show Gist options
  • Save ajmalafif/2eebf40e6343dbe5963d279a89987eaf to your computer and use it in GitHub Desktop.
Save ajmalafif/2eebf40e6343dbe5963d279a89987eaf to your computer and use it in GitHub Desktop.

Revisions

  1. ajmalafif revised this gist Oct 16, 2021. 1 changed file with 135 additions and 0 deletions.
    135 changes: 135 additions & 0 deletions review.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,135 @@
    // studio / schemas / documents / review.js
    import {format} from 'date-fns'

    export default {
    name: 'review',
    type: 'document',
    title: 'Reviews',
    fields: [
    {
    name: 'title',
    type: 'string',
    title: 'Title',
    description: 'Titles should be catchy, descriptive, and not too long'
    },
    {
    name: 'slug',
    type: 'slug',
    title: 'Slug',
    description: 'Some frontends will require a slug to be set to be able to show the post',
    options: {
    source: 'title',
    maxLength: 96
    }
    },
    {
    name: 'publishedAt',
    type: 'datetime',
    title: 'Published at',
    description: 'This can be used to schedule post for publishing'
    },
    {
    name: 'mainImage',
    type: 'mainImage',
    title: 'Main image'
    },
    {
    name: 'excerpt',
    type: 'excerptPortableText',
    title: 'Excerpt',
    description:
    'This ends up on summary pages, on Google, when people share your post in social media.'
    },
    {
    name: 'authors',
    title: 'Authors',
    type: 'array',
    of: [
    {
    type: 'authorReference'
    }
    ]
    },
    {
    title: 'Tag',
    name: 'tag',
    type: 'array',
    of: [{type: 'string'}],
    options: {
    layout: 'tags'
    }
    },
    {
    name: 'categories',
    type: 'array',
    title: 'Review Category',
    of: [
    {
    type: 'reference',
    to: [
    {
    title: 'Category',
    type: 'categoryReview'
    }
    ]
    }
    ]
    },
    {
    name: 'reviews',
    type: 'array',
    title: 'Collection of Reviews',
    of: [
    {
    type: 'reviewText'
    }
    ]
    }
    ],
    orderings: [
    {
    name: 'publishingDateAsc',
    title: 'Publishing date new–>old',
    by: [
    {
    field: 'publishedAt',
    direction: 'asc'
    },
    {
    field: 'title',
    direction: 'asc'
    }
    ]
    },
    {
    name: 'publishingDateDesc',
    title: 'Publishing date old->new',
    by: [
    {
    field: 'publishedAt',
    direction: 'desc'
    },
    {
    field: 'title',
    direction: 'asc'
    }
    ]
    }
    ],
    preview: {
    select: {
    title: 'title',
    publishedAt: 'publishedAt',
    slug: 'slug',
    media: 'mainImage'
    },
    prepare({ title = 'No title', publishedAt, slug = {}, media }) {
    const path = `/${slug.current}/`
    return {
    title,
    media,
    subtitle: publishedAt ? path : 'Missing publishing date'
    }
    }
    }
    }
  2. ajmalafif created this gist Oct 16, 2021.
    63 changes: 63 additions & 0 deletions gatsby-node.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    //Hook into the createSchemaCustomization API
    //This hook runs after all our nodes have been created
    exports.createSchemaCustomization = ({ actions, schema }) => {
    //The createTypes action allows us to create custom types
    //and modify existing ones
    const { createTypes } = actions

    // Create our schema customizations
    const typeDefs = [
    // Replace "SanityReview" with your _typename of your post type
    "type SanityReview implements Node { related: [SanityReview] }",
    schema.buildObjectType({
    name: "SanityReview",
    fields: {
    related: {
    type: "[SanityReview]",
    //The resolve field is called when your page query looks for related posts
    //Here we can query our data for posts we deem 'related'
    //Exactly how you do this is up to you
    //I'm querying purely by category
    //But you could pull every single post and do a text match if you really wanted
    //(note that might slow down your build time a bit)
    //You could even query an external API if you needed
    resolve: async (source, args, context, info) => {
    //source is the current (post) object
    //context provides some methods to interact with the data store

    //Map a simple array of category IDs from our source object
    //In my data each category in the array is an object with a _id field
    //We're just flattening that to an array of those _id values
    //E.g. categories = ["1234", "4567", "4534"]
    const categories = source.categories.map((c) => c._id)

    //If this post has no categories, return an empty array
    if (!categories.length) return ["uncategorized"]

    //Query the data store for posts in our target categories
    const post = await context.nodeModel.runQuery({
    query: {
    filter: {
    //We're filtering for categories that are sharedby our source node
    categories: { elemMatch: { _id: { in: categories } } },
    //Dont forget to exclude the current post node!
    _id: { ne: source._id },
    },
    },
    //Change this to match the data type of your post
    //This will vary depending on how you source content
    type: "SanityReview",
    })

    //Gatsby gets unhappy if we return "null" here
    //So check the result and either return an array of post,
    //or an empty array
    return post && post.length ? post : []
    },
    },
    },
    }),
    ]

    createTypes(typeDefs)
    }