🎤 Builder Talk: The Story Behind Lady Gaga’s Digital Experience – Register now

Difference between S.editor() and S.document() and how to disable deletion and unpublishing of certain document types in Sanity.io

8 replies
Last updated: Feb 8, 2022
Maybe a noobie question, but what is the difference between
S.editor()
and
S.document()
I have created a settings document parent type with nested settings menu. But I want to disable the possibility to make it visible as a singular type instead of a document which can be repeated like posts, articles blogs etc. How can I prevent these pages from being deleted, unpublished?
I have a custom "*documentActions*" but it's kinda ugly, wondering if you build the menu with ListItems if there is a property out of the box to disable deletion, unpublish, for these settings pages.

My code.. but wondering if there is a cleaner way
😄?
import userStore from "part:@sanity/base/user";

import defaultResolve, {
  UnpublishAction,
  DuplicateAction,
  DeleteAction,
} from "part:@sanity/base/document-actions";

const documentActions = (props) => {
  return props.type === "navigation" ||
    props.type === "general" ||
    props.type === "featured" ||
    props.type === "promo" ||
    props.type === "cookie" ||
    props.type === "friends"
    ? [
        ...defaultResolve(props).filter(
          (action) =>
            action !== UnpublishAction &&
            action !== DuplicateAction &&
            action !== DeleteAction
        ),
      ]
    : [...defaultResolve(props)];
};

export default documentActions;

Feb 8, 2022, 1:38 PM
Hey
user M
😄 !
I have this now, Will refactor later on. Where should the second code part go?


import defaultResolve, {
  PublishAction,
} from "part:@sanity/base/document-actions";

const singleEdits = [
  "navigation",
  "general",
  "featured",
  "promo",
  "cookie",
  "friends",
];

export default function resolveDocumentActions(props) {
  if (singleEdits.includes(props.type)) {
    return defaultResolve(props).filter((action) => action == PublishAction);
  }

  return [...defaultResolve(props)];
}

Feb 8, 2022, 7:08 PM
Ah sorry, that your new document menu. You can see how to set that up here .
Feb 8, 2022, 7:15 PM
user M
The first part seems to be enough. It’s only possible to Publish action and not create any new document inside the settings and sub settings menu items.
Not sure, but when you apply
$.editor()
instead of
$.document()
it behaves like a single item.
Take a look:


import React from "react";

import S from "@sanity/base/structure-builder";

import { Gear, Cookie, List, Star, Sliders, FlagBanner } from "phosphor-react";

import { icon } from "../lib/helpers";

const { color, weight, size } = icon;

const generalMenu = S.listItem()
  .title("General")
  .icon(() => <Gear color={color} weight={weight} size={size} />)
  .child(
    S.editor()
      .schemaType("general")
      .documentId("generalSettings")
      .title("General Settings")
  );

const navMenu = S.listItem()
  .title("Navigation")
  .icon(() => <List color={color} weight={weight} size={size} />)
  .child(
    S.editor()
      .schemaType("navigation")
      .documentId("navigationSettings")
      .title("Navigation Settings")
  );

const featuredMenu = S.listItem()
  .title("Featured Articles")
  .icon(() => <Star color={color} weight={weight} size={size} />)
  .child(
    S.editor()
      .schemaType("featured")
      .documentId("featuredSettings")
      .title("Featured Articles")
  );

const cookieMenu = S.listItem()
  .title("Cookie Consent")
  .icon(() => <Cookie color={color} weight={weight} size={size} />)
  .child(
    S.editor()
      .schemaType("cookie")
      .documentId("cookieSettings")
      .title("Cookie Consent Settings")
  );

const promoBarMenu = S.listItem()
  .title("Promo Bar")
  .icon(() => <FlagBanner color={color} weight={weight} size={size} />)
  .child(
    S.editor()
      .schemaType("promo")
      .documentId("promoBarSettings")
      .title("Promo Bar Settings")
  );

export const settingsMenu = S.listItem()
  .title("Settings")
  .child(
    S.list()
      .title("Settings")
      .items([
        generalMenu,
        S.divider(),
        navMenu,
        S.divider(),
        featuredMenu,
        S.divider(),
        cookieMenu,
        S.divider(),
        promoBarMenu,
      ])
  )
  .icon(() => <Sliders color={color} weight={weight} size={size} />);
documentActions.js

I’v included the DiscardChanges
😄 is it good like so?
import defaultResolve, {
  DiscardChangesAction,
  PublishAction,
} from "part:@sanity/base/document-actions";

console.table(defaultResolve);

const singleEdits = [
  "navigation",
  "general",
  "featured",
  "promo",
  "cookie",
  "friends",
];

export default function resolveDocumentActions(props) {
  if (singleEdits.includes(props.type)) {
    return defaultResolve(props).filter(
      (action) => action === PublishAction || action === DiscardChangesAction
    );
  }

  return [...defaultResolve(props)];
}

Feb 8, 2022, 7:30 PM
Yep, that should work! Not sure on the
.editor
and
.document
methods though. I always just use
.document
since it has more documentation in the reference.
Feb 8, 2022, 7:39 PM
user M
Oke 😊, finally works like a charm the only problem now, I need the “*`DiscardChangesAction`*” it’s working for general, promo, cookie. But not for navigation and featured which are both array fields?

import defaultResolve, {
  DiscardChangesAction,
  PublishAction,
} from "part:@sanity/base/document-actions";

const singleSettings = [
  "general",
  "navigation",
  "featured",
  "promo",
  "cookie",
  "friends",
];

const resolveDocumentActions = (props) => {
  if (singleSettings.includes(props.type)) {
    console.log(props);
    return defaultResolve(props).filter(
      (action) => action === PublishAction || action === DiscardChangesAction
    );
  }

  return [...defaultResolve(props)];
};

export default resolveDocumentActions;
Feb 8, 2022, 7:45 PM
I would think that
navigation
and
featured
aren't the actual types that get passed in, so
props.type
is something else. Can you check by `console.log`ging
props.type
?
Feb 8, 2022, 8:15 PM
user M
Figured it out never published anything to make the discard button visible thanks🙌
Feb 8, 2022, 8:20 PM
user M
Figured it out never published anything to make the discard button visible thanks🙌
Feb 8, 2022, 8:20 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?

Related answers

Get more help in the community Slack

TopicCategoriesFeaturedRepliesLast Updated
How to turn PortableText into plain text in Javascript?Dec 7, 2020
Rendering nested block contentJan 18, 2021
Custom Document Views - Is it Even Possible to Use the Structure Builder?Apr 21, 2022
GraphQL query resolving references on a _raw field in GatsbyMay 17, 2022
Error: unable to resolve image URL from source (undefined)Sep 11, 2022
Extracting referenced images from an object array in Sanity.ioMay 17, 2020
How to Disallow Robots on a SubdomainNov 12, 2020
How to preview content inside a reference array in Sanity.ioAug 14, 2020
Adding a ref to the body tag using Helmet in ReactJul 2, 2020
Hi, I need help with Iframe preview, I have a `route` schema with unique `slug` (`/lb/123`) and also I have `page` schema...Dec 21, 2020

Related contributions

Turbo Start Sanity
- Template

The battle-tested Sanity template that powers Roboto Studio's websites

Go to Turbo Start Sanity

Schema UI - Next.js Sanity Starter
- Template

A Next.js starter template with Next.js 15, Tailwind CSS, shadcn/ui, and Sanity CMS with Live Editing. Get production-ready React components with matching Sanity schemas and queries. Build dynamic pages faster while keeping full control over customization.

Serge Ovcharenko
Go to Schema UI - Next.js Sanity Starter

The Swaddle
- Made with Sanity

A new brand identity to represent a more mature company, to signify The Swaddle’s evolution from publisher to production house, combined with an easier to navigate platform that can surface multiple content types - drawing readers through The Swaddle’s content offering.

Nightjar
Go to The Swaddle