Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

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?