Coder Social home page Coder Social logo

sanity-io / hierarchical-document-list Goto Github PK

View Code? Open in Web Editor NEW
39.0 13.0 7.0 1.11 MB

Plugin for editing hierarchical references in the Sanity studio.

License: MIT License

JavaScript 1.57% TypeScript 98.24% Shell 0.19%
sanity-io hierarchical-data plugin

hierarchical-document-list's Introduction

sanity-plugin-hierarchical-document-list

This is a Sanity Studio v3 plugin.

Plugin for visually organizing documents as hierarchies in the Sanity studio. Applications include:

  • Tables of content - such as a book's sections and chapters
  • Navigational structure & menus - a website mega-menu with multiple levels, for example
  • Taxonomy inheritance - "Carbs is a parent of Legumes which is a parent of Beans"

Screenshot of the plugin

⚠️ Compatibility: This plugin requires Sanity Studio version 3.3.0 or higher.

If you're looking for a way to order documents on a flat list, refer to @sanity/orderable-document-list.

Installation

# From the root of your sanity project
npm i @sanity/hierarchical-document-list

Usage

1. Add the plugin and the default documentType to the sanity.config.ts

// sanity.config.js
import {defineConfig} from 'sanity'
import {hierarchicalDocumentList, hierarchyTree} from '@sanity/hierarchical-document-list'
 
export default defineConfig({
   // ...
   plugins: [hierarchicalDocumentList()],
   schema: {
    types: [
      //...,
      hierarchyTree
    ]
   }

})

2. Add one or more hierarchy documents to your Structure Builder.

πŸ’‘ To learn about custom desk structures, refer to the Structure Builder docs.

// sanity.config.ts
import {defineConfig} from 'sanity'
import {deskTool} from 'sanity/desk'
import {createDeskHierarchy, hierarchicalDocumentList, hierarchyTree} from '@sanity/hierarchical-document-list'

export default defineConfig({
  // ...
  plugins: [
    deskTool({
      // NOTE: I'n V3 you MUST pass S and Context along to createDeskHierarchy as props
      structure: (S, context) =>  S.list()
          .title('Content')
          .items([
            ...S.documentTypeListItems(), // or whatever other structure you have
            createDeskHierarchy({
              //prop drill S and context:
              S,
              context,

              //configure plugin

              title: 'Main table of contents',

              // The hierarchy will be stored in this document ID πŸ‘‡
              documentId: 'main-table-of-contents',

              // Document types editors should be able to include in the hierarchy
              referenceTo: ['site.page', 'site.post', 'docs.article', 'social.youtubeVideo'],

              // ❓ Optional: provide filters and/or parameters for narrowing which documents can be added
              referenceOptions: {
                filter: 'status in $acceptedStatuses',
                filterParams: {
                  acceptedStatuses: ['published', 'approved']
                }
              },

              // ❓ Optional: limit the depth of your hierarachies
              maxDepth: 3,

              // ❓ Optional: subarray of referenceTo, when it should not be possible to create new types from all referenceTo types
              creatableTypes: ['site.page']
            })
          ])
    }),
    hierarchicalDocumentList()
  ],
  schema: {
    types: [
      //...,
      hierarchyTree
    ]
  }
})

How it works

The hierarchical data is stored in a centralized document with the documentId of your choosing. As compared to storing parent/child relationships in each individual document in the hierarchy, this makes it easier to implement different hierarchies for the same content according to the context.

This approach also simplifies querying the full structure - as you'll see in querying data below.

Keep in mind that this specified document is live-edited, meaning it has no draft and every change by editors will directly affect its published version.

Instead of requiring editors to manually add items one-by-one, the plugin will create a GROQ query that matches all documents with a _type in the referenceTo option you specify, that also match the optional referenceOptions.filter. From these documents, editors are able to drag, nest and re-order them at will from the "Add more items" list.

If a document in the tree doesn't match the filters set, it'll keep existing in the data. This can happen if the document has a new, unfitting value, the configuration changed or it was deleted. Although the tree will still be publishable, editors will get a warning and won't be able to drag these faulty entries around.

Querying data

The plugin stores flat arrays which represent your hierarchical data through parent keys. Here's an example of one top-level item with one child:

[
  {
    "_key": "741b9edde2ba",
    "_type": "hierarchy.node",
    "value": {
      "reference": {
        "_ref": "75c47994-e6bb-487a-b8c9-b283f2436031",
        "_type": "reference",
        "_weak": true // This plugin includes weak references by default
      },
      "docType": "docs.article"
    }
    // no `parent`, this item is top-level
  },
  {
    "_key": "f92eaeec96f7",
    "_type": "hierarchy.node",
    "value": {
      "reference": {
        "_ref": "7ad60a02-5d6e-47d8-92e2-6724cc130058",
        "_type": "reference",
        "_weak": true
      },
      "docType": "site.post"
    },
    // The `parent` property points to the _key of the parent node where this one is nested
    "parent": "741b9edde2ba"
  }
]

πŸ“Œ If using GraphQL, refer to Usage with GraphQL.

From the the above, we know how to expand referenced documents in GROQ:

*[_id == "main-table-of-contents"][0]{
  tree[] {
    // Make sure you include each item's _key and parent
    _key,
    parent,

    // "Expand" the reference to the node
    value {
      reference->{
        // Get whatever property you need from your documents
        title,
        slug,
      }
    }
  }
}

The query above will then need to be converted from flat data to a tree. Refer to Using the data.

Using the data

From the flat data queried, you'll need to convert it to a nested tree with flatDataToTree:

import {flatDataToTree} from '@sanity/hierarchical-document-list'

const hierarchyDocument = await client.fetch(`*[_id == "book-v3-review-a"][0]{
  tree[] {
    // Make sure you include each item's _key and parent
    _key,
    parent,
    value {
      reference->{
        title,
        slug,
        content,
      }
    }
  }
}`)
const tree = flatDataToTree(data.tree)

/* Results in a recursively nested structure. Using the example data above:
{
  "_key": "741b9edde2ba",
  "_type": "hierarchy.node",
  "value": {
    "reference": {
      "_ref": "75c47994-e6bb-487a-b8c9-b283f2436031",
      "_type": "reference",
      "_weak": true
    },
    "docType": "docs.article"
  },
  "parent": null,
  "children": [
    {
      "_key": "f92eaeec96f7",
      "_type": "hierarchy.node",
      "value": {
        "reference": {
          "_ref": "7ad60a02-5d6e-47d8-92e2-6724cc130058",
          "_type": "reference",
          "_weak": true
        },
        "docType": "site.post"
      },
      "parent": "741b9edde2ba"
    }
  ]
}
*/

After the transformation above, nodes with nested entries will include a children array. This data structure is recursive.

Usage with GraphQL

By default, this plugin will create and update documents of _type: hierarchy.tree, with a tree field holding the hierarchical data. When deploying a GraphQL Sanity endpoint, however, you'll need an explicit document type in your schema so that you get the proper types for querying.

To add this document type, create a set of schemas with the createHierarchicalSchemas:

// hierarchicalSchemas.js
import {createHierarchicalSchemas} from '@sanity/hierarchical-document-list'

export const hierarchicalOptions = {
  // choose the document type name that suits you best
  documentType: 'myCustomHierarchicalType',

  // key for the tree field in the document - "tree" by default
  fieldKeyInDocument: 'customTreeDataKey',

  // Document types editors should be able to include in the hierarchy
  referenceTo: ['site.page', 'site.post', 'docs.article', 'social.youtubeVideo'],

  // ❓ Optional: provide filters and/or parameters for narrowing which documents can be added
  referenceOptions: {
    filter: 'status in $acceptedStatuses',
    filterParams: {
      acceptedStatuses: ['published', 'approved']
    }
  },

  // ❓ Optional: limit the depth of your hierarachies
  maxDept: 3
}

export default createHierarchicalSchemas(hierarchicalOptions)

And add these schemas to your studio:

import createSchema from 'part:@sanity/base/schema-creator'
import schemaTypes from 'all:part:@sanity/base/schema-type'
import hierarchicalSchemas from './hierarchicalSchemas'

export default createSchema({
  name: 'default',
  types: schemaTypes.concat([
    // ...Other schemas
    ...hierarchicalSchemas // add all items in the array of hierarchical schemas
  ])
})

Then, in your desk structure where you added the hierarchical document(s), include the right documentType and fieldKeyInDocument properties:

createDeskHierarchy({
  // Include whatever values you defined in your schema in the step above
  documentType: 'myCustomHierarchicalType', // the name of your document type
  fieldKeyInDocument: 'customTreeDataKey' // the name of the hierarchical field
  // ...
})

// Ideally, use the same configuration object you defined in your schemas:
import {hierarchicalOptions} from './hierarchicalSchemas'

createDeskHierarchy({
  ...hierarchicalOptions
  // ...
})

πŸ“Œ Note: you can also use the method above to add hierarchies inside the schema of documents and objects, which would be editable outside the desk structure.

We're considering adapting this input to support any type of nest-able data, not only references. Until then, avoid using the generated schemas in nested schemas as, in these contexts, it lacks the necessary affordances for a good editing experience.


License

MIT-licensed. See LICENSE.

License

MIT Β© Sanity

Develop & test

This plugin uses @sanity/plugin-kit with default configuration for build & watch scripts.

See Testing a plugin in Sanity Studio on how to run this plugin with hotreload in the studio.

Release new version

Run "CI & Release" workflow. Make sure to select the main branch and check "Release new version".

Semantic release will only release on configured branches, so it is safe to run release on any branch.

hierarchical-document-list's People

Contributors

hdoro avatar mariuslundgard avatar semantic-release-bot avatar snorrees avatar tine-krueger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hierarchical-document-list's Issues

Multiple referenceTo types breaks things

If I add more than one type to the prop referenceTo, I can only edit the first type when clicking on a DocumentInNode-item. Clicking an item of a different type results in the following error: This document is of type x and cannot be edited as x.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.


Using a curated preset maintained by


Sanity: The Composable Content Cloud

Pending Approval

These branches will be created by Renovate only once you click their checkbox below.

  • chore(deps): update non-major (@commitlint/cli, @commitlint/config-conventional, @sanity/mutator, @sanity/pkg-utils, @sanity/plugin-kit, @sanity/semantic-release-preset, @sanity/util, @types/react, @types/styled-components, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, eslint, eslint-config-sanity, eslint-plugin-prettier, eslint-plugin-react, npm-run-all, prettier, prettier-plugin-packagejson, sanity, typescript)
  • chore(deps): update actions/checkout action to v4
  • chore(deps): update actions/setup-node action to v4
  • chore(deps): update commitlint monorepo to v19 (major) (@commitlint/cli, @commitlint/config-conventional)
  • chore(deps): update dependency @sanity/pkg-utils to v4
  • chore(deps): update dependency @sanity/pkg-utils to v5
  • chore(deps): update dependency @sanity/pkg-utils to v6
  • chore(deps): update dependency @sanity/plugin-kit to v4
  • chore(deps): update dependency styled-components to v6
  • chore(deps): update linters to v7 (major) (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • fix(deps): Update dependency @sanity/ui to v2
  • chore(deps): lock file maintenance
  • πŸ” Create all pending approval PRs at once πŸ”

Detected dependencies

github-actions
.github/workflows/main.yml
  • actions/checkout v3
  • actions/setup-node v3
  • actions/checkout v3
  • actions/setup-node v3
  • actions/checkout v3
  • actions/setup-node v3
npm
package.json
  • @nosferatu500/react-sortable-tree ^4.4.0
  • @sanity/incompatible-plugin ^1.0.4
  • @sanity/mutator ^3.19.3
  • @sanity/ui ^1.9.3
  • @sanity/util ^3.19.3
  • react-dnd 16.0.1
  • react-dnd-html5-backend 16.0.1
  • @commitlint/cli ^18.4.3
  • @commitlint/config-conventional ^18.4.3
  • @sanity/pkg-utils ^3.3.2
  • @sanity/plugin-kit ^3.1.10
  • @sanity/semantic-release-preset ^4.1.6
  • @types/react ^18.2.41
  • @types/styled-components ^5.1.32
  • @typescript-eslint/eslint-plugin ^6.13.1
  • @typescript-eslint/parser ^6.13.1
  • eslint ^8.55.0
  • eslint-config-prettier ^9.1.0
  • eslint-config-sanity ^7.0.1
  • eslint-plugin-prettier ^5.0.1
  • eslint-plugin-react ^7.33.2
  • eslint-plugin-react-hooks ^4.6.0
  • npm-run-all ^4.1.5
  • prettier ^3.1.0
  • prettier-plugin-packagejson ^2.4.7
  • react ^18.2.0
  • react-dom ^18.2.0
  • react-is ^18.2.0
  • rimraf ^5.0.5
  • sanity ^3.20.2
  • styled-components ^5.3.11
  • typescript ^5.3.2
  • react ^18
  • sanity ^3
  • node >=14

  • Check this box to trigger a request for Renovate to run again on this repository

Install and build errors on v2.0.0 (latest) of plugin

Describe the bug

Issues with peer dependencies found on install ([email protected]), and two Vite build errors (DragSource, DropTarget).

To Reproduce

Steps to reproduce the behavior:

  1. For install error: pnpm add @sanity/hierarchical-document-list
  2. For build error (after above):
    Add hierarchicalDocumentList and hierarchyTree per installation instructions.
    Run: pnpm run dev and open browser to http://localhost:3333/

Expected behavior

To install into my Sanity project without errors and run correctly.

Screenshots

Screenshot 2024-03-15 105719
Screenshot 2024-03-15 112625

Which versions of Sanity are you using?

@sanity/cli (global)                3.34.0 (up to date)
@sanity/eslint-config-studio         3.0.1 (up to date)
@sanity/hierarchical-document-list   2.0.0 (up to date)
@sanity/icons                       2.11.2 (up to date)
@sanity/ui                          2.0.10 (up to date)
@sanity/vision                      3.34.0 (up to date)
sanity                              3.34.0 (up to date)

What operating system are you using?

Windows 11

Which versions of Node.js / npm are you running?

Node v21.7.0
pnpm 8.15.4 (via Corepack)

When duplicating content it just adds another instance of the same document

Great plugin! It's been super useful in my latest project.

When clicking the 3 dots and choosing "duplicate" content from the hierarchy tree, an instance of the same document is created, rather than creating a new document. Once duplicated clicking on the document highlights both.

Wondering if this is a bug, or if this is some kind of Sanity config issue.

`flatDataToTree` doesn't work in a NextJS server component

This simple demo

import { client } from "@/sanity/lib/client";
import { groq } from "next-sanity";
import { flatDataToTree } from "@sanity/hierarchical-document-list";

export default async function Page() {
  const pageHierarchy = await client.fetch(groq`*[_id == "page-hierarchy"][0] {
    tree[] {
      // Make sure you include each item's _key and parent
      _key,
      parent,
      value {
        reference->{
          title,
          slug,
          content,
        }
      }
    }
  }`);
  const pageTree = flatDataToTree(pageHierarchy.tree);
  return (
    <div>
      {JSON.stringify(pageTree, null, 2)}
    </div>
  );
}

doesn't work as a NextJS server component. Error message

TypeError: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component

The root cause is in the @nosferatu500/react-sortable-tree => react-dnd@14 dependency, which probably exposes some react-context related functionality.

I fixed it by including this code in my repository:

// /sanity/lib/flatDataToTree.ts
import { SanityReference } from "next-sanity";

export interface StoredTreeItem {
  _key: string;
  _type: string;
  value?: {
    _type: string;
    reference?: SanityReference;
    docType?: string;
  };
  parent?: string | null;
}

interface TreeItemWithChildren extends StoredTreeItem {
  children?: TreeItemWithChildren[];
};

const getTreeFromFlatData = ({
  flatData,
  getKey = (node) => node.id,
  getParentKey = (node) => node.parentId,
  rootKey = '0',
}: {
  flatData: any
  getKey: (node: any) => string
  getParentKey: (node: any) => string
  rootKey: string | null
}) => {
  if (!flatData) {
    return []
  }

  const childrenToParents: Record<string, string[]> = {}
  for (const child of flatData) {
    const parentKey = getParentKey(child)

    if (parentKey in childrenToParents) {
      childrenToParents[parentKey].push(child)
    } else {
      childrenToParents[parentKey] = [child]
    }
  }

  if (!(rootKey! in childrenToParents)) {
    return []
  }

  const trav: (parent: any) => any = parent => {
    const parentKey = getKey(parent)
    if (parentKey in childrenToParents) {
      return {
        ...parent,
        children: childrenToParents[parentKey].map((child) => trav(child)),
      }
    }

    return { ...parent }
  }

  return childrenToParents[rootKey!].map((child) => trav(child))
}

export default function flatDataToTree(data: StoredTreeItem[]): TreeItemWithChildren[] {
  return getTreeFromFlatData({
    flatData: data.map((item) => ({
      ...item,
      parent: item.parent || null,
    })),
    getKey: (item) => item._key,
    getParentKey: (item) => item.parent,
    rootKey: null as any,
  }) as TreeItemWithChildren[];
}

The documentType passed to createDeskHiearchy isn't live editable - while having liveEdit: true in the document

Hello,
I am trying to implement the hierarchical-document-list plugin in a project but despite the document I reference having the liveEdit: true props, I get the following error:

Invalid configuration
The documentType passed to createDeskHiearchy isn't live editable.
To continue using this plugin, add liveEdit: true to your custom schema type or unset documentType in your hierarchy configuration.

Document:

export default {
  name: "mycat",
  type: "document",
  title: "Mycat",
  liveEdit: true,
  fields: [
    {
      name: "name",
      type: "string",
      title: "Name",
    },
    {
      name: "slug",
      type: "slug",
      title: "Slug",
      options: {
        source: "name",
        slugify: (input) =>
          input.toLowerCase().replace(/\s+/g, "-").slice(0, 96),
        maxLength: 96,
      },
    },
  ],
};

Desk:

      createDeskHierarchy({
        title: "Flat categories",
        documentId: "my-cats",
        referenceTo: ["mycat"],
        maxDept: 2,
      }),

Studio: 2.29.5
Plugin: 1.1.0

Two ref errors stopping anything from loading.

Hi there, I am trying to add this to a project of mine and have potentially found a couple of issues.

When clicking the Main table of contents document created by this plugin on the left pane, it starts to show a spinner to load content then fails and only shows Add items from the list below with nothing below.

In the console there are 2 errors, one being Warning: forwardRef render functions accept exactly two parameters: props and ref. Did you forget to use the ref parameter? and the other Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?.

Adding this schema also adds a folder called Hierarchial tree, but clicking into this shows a list of untitled pages and clicking on one returns this:

Unknown field found
Encountered a field that is not defined in the schema.
This field is not defined in the schema, which could mean that the field definition has been removed or that someone else has added it to their own local project and have not deployed their changes yet.

It might be myself missing something here as I am new, and if I am can you point me in the right direction please.

All of my Sanity versions are 2.30 so I have made sure it's compatible.

Hope you can advise.

Thanks,
Jack

Studio v3 support

Hey, this plugin would be pretty handy for a project of mine. Was wondering if you're planning on updating it for v3 any time soon? :)

Annoying double scrollbar on hierarchy document list.

Describe the bug

Annoying double scrollbar on hierarchy document list. May be related to issue #20, which I reported separately as I am unsure if they are related.

To Reproduce

Steps:

  1. Install hierarchical-document-list and add it to your structure following installation steps
  2. Run sanity dev (npm run dev) and in your browser, open the new structure page added to Sanity
  3. See error in browser console.

Expected behavior

To only have one scroll bar to navigate the hierarchy document list.

Screenshots

problem-demo

Which versions of Sanity are you using?

@sanity/cli (global)                3.34.0 (up to date)
@sanity/eslint-config-studio         3.0.1 (up to date)
@sanity/hierarchical-document-list   2.0.0 (up to date)
@sanity/icons                       2.11.2 (up to date)
@sanity/ui                          2.0.10 (up to date)
@sanity/vision                      3.34.0 (up to date)
sanity                              3.34.0 (up to date)

What operating system are you using?

Windows 11

Which versions of Node.js / npm are you running?

Node v21.7.0
NPM 9.1.2

Additional context

Display Resolution 3840 x 2160.
Scale is set to 250% in Windows Display settings (the recommended setting).
Tested on Firefox Developer Edition 124.0b9 (64-bit) and Chrome Version 122.0.6261.129 (Official Build) (64-bit).

Slow component start up

This plugin is exactly what I'm looking for for my project. However I have noticed that with only ~40 documents being arranged in the tree switching to or from that view has a ~5s hang.

I've tested with a smaller node tree and there isn't a hang.

React warning on opening hierarchical-document-list in browser console

Describe the bug

React warning level error on opening hierarchical-document-list in browser console:

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `UserComponentPane`.
div
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Box<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42456:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
UserComponentPaneContent@http://localhost:3333/node_modules/.sanity/vite/deps/index-pIqlMpni-5ND6P5H7.js?v=84435e5d:54:7
div
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Box<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42456:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Flex<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42642:85
BoundaryElementProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43689:33
div
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Box<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42456:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
tt@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31085:32
ThemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41341:53
ThemeColorProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41361:38
Card<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43074:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
LayerProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43868:50
LegacyLayerProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:104977:43
Pane2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:2034:204
UserComponentPane@http://localhost:3333/node_modules/.sanity/vite/deps/index-pIqlMpni-5ND6P5H7.js?v=84435e5d:103:7
Suspense
PaneRouterProvider@http://localhost:3333/node_modules/.sanity/vite/deps/index-Bn6gWj4A-BO5HHXBB.js?v=84435e5d:121:7
StructureToolPane2@http://localhost:3333/node_modules/.sanity/vite/deps/index-Bn6gWj4A-BO5HHXBB.js?v=84435e5d:1108:7
div
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Box<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42456:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
tt@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31085:32
ThemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41341:53
ThemeColorProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41361:38
Card<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43074:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
PaneLayout@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:2497:70
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
PortalProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43965:85
StructureTool2@http://localhost:3333/node_modules/.sanity/vite/deps/index-Bn6gWj4A-BO5HHXBB.js?v=84435e5d:1301:7
StructureToolProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:11407:72
SourceProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:99921:33
ErrorBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43751:5
StructureToolBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/index-Bn6gWj4A-BO5HHXBB.js?v=84435e5d:1408:7
StudioActiveToolLayout@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:102598:26
TasksStudioActiveToolLayout@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:10969:23
Suspense
RouteScope@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:64532:7
div
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Box<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42456:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
tt@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31085:32
ThemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41341:53
ThemeColorProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41361:38
Card<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43074:7
ErrorBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43751:5
StudioErrorBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:102861:52
div
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Box<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42456:7
O2@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31145:6
Flex<@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:42642:85
StudioLayoutComponent@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:102890:34
TasksStudioLayoutInner@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:10976:23
TasksEnabledProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:9642:22
TasksStudioLayout
ConditionalWrapper@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:28772:7
CommentsOnboardingProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:1647:24
AddonDatasetProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:106748:7
CommentsStudioLayout@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-DVB2AI7Q.js?v=84435e5d:5158:51
StudioLayout@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:102885:19
ResourceCacheProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:98358:22
I18nextProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:28749:7
Suspense
LocaleProviderBase@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:81175:71
LocaleProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:81171:95
TelemetryProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:71936:7
StudioTelemetryProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:103991:27
RouterProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:64482:7
WorkspaceRouterProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:104169:51
SourceProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:99921:33
WorkspaceProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:87795:33
WorkspaceLoader@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:104267:40
ErrorBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43751:5
WorkspaceLoaderBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:104275:46
AuthBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:103956:151
UserColorManagerProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:82189:49
LayerProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43868:50
tt@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31085:32
ThemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41341:53
StudioThemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:104020:22
RouterHistoryProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:100939:41
ActiveWorkspaceMatcherContextProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:100950:78
ActiveWorkspaceMatcher@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:101035:90
WorkspacesProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:100933:40
ErrorBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:43751:5
StudioErrorBoundary@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:102861:52
ToastProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:47215:66
tt@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:31085:32
ThemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-KTXG2ZXI.js?v=84435e5d:41341:53
ColorThemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:101078:39
ColorSchemeLocalStorageProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:101092:38
ColorSchemeProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:101085:58
StudioProvider@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:104287:133
Studio@http://localhost:3333/node_modules/.sanity/vite/deps/chunk-VXZWTXXD.js?v=84435e5d:107709:7
[react-dom.development.js:86:29](http://localhost:3333/node_modules/react-dom/cjs/react-dom.development.js)

To Reproduce

Steps to reproduce the behavior:

  1. Install hierarchical-document-list and add it to your structure following installation steps
  2. Run sanity dev (npm run dev) and in your browser, open the new structure page added to Sanity
  3. See error in browser console.

Expected behavior

For Sanity and the plugin to run error free.

Which versions of Sanity are you using?

@sanity/cli (global)                3.34.0 (up to date)
@sanity/eslint-config-studio         3.0.1 (up to date)
@sanity/hierarchical-document-list   2.0.0 (up to date)
@sanity/icons                       2.11.2 (up to date)
@sanity/ui                          2.0.10 (up to date)
@sanity/vision                      3.34.0 (up to date)
sanity                              3.34.0 (up to date)

What operating system are you using?

Windows 11

Which versions of Node.js / npm are you running?

Node v21.7.0
NPM 9.1.2

Dependency free function to convert flat data to tree

Hi everyone,

In my frontend (using Svelte) I needed to convert the flat list of documents into a nested tree, without using react module as stated in the readme:

import {flatDataToTree} from '@sanity/hierarchical-document-list'

So instead of above’s module with several dependencies, here’s the standalone function:

const flatDataToTree = (data) => {

  // assign new ID "root" to parent for docs where parent == null (root level)
  data = data.map(doc => {
    if(doc.parent === null){
      return {
        ...doc, parent: 'root', children: []
      }
    }
    return {
      ...doc, children: []
    }
  });

  // create new root object
  let root = {_key: 'root', parent: null, children: []};
  let docList = { 'root' : root};

  // build tree
  for (var i = 0; i < data.length; i++) {
    docList[data[i]._key] = data[i];
    docList[data[i].parent].children.push(docList[data[i]._key]);
  }

  return root;
}

It needs the _key and parent fields to be present in data from your GROQ query:

  const query = `//groq
    *[_id == "YOUR-TREE-DOCUMENT-ID"][0]{
      tree[] {
        _key,
        parent,
        value {
          reference->{
            title,
            slug,
          }
        }
      }
    }
  `;

@nosferatu500/react-sortable-tree is not compatible with react-dnd@16

Describe the bug

Crashes due to unresolved DragSource import:

 [ERROR] No matching export in "../../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/react-dnd/dist/index.js" for import "DragSource"

    ../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@nosferatu500/react-sortable-tree/esm/index.js:5:9:
      5 β”‚ import { DragSource, DropTarget, DndContext, DndProvider } from 'react-dnd';
      

To Reproduce

dependencies:

"dependencies": {
    "@sanity/client": "^5.4.2",
    "@sanity/code-input": "^4.1.1",
    "@sanity/color-input": "^3.1.0",
    "@sanity/scheduled-publishing": "^1.2.2",
    "@sanity/vision": "3.17.0",
    "cloudinary": "^1.33.0",
    "lodash": "^4.17.21",
    "prop-types": "^15.8.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "sanity": "3.17.0",
    "sanity-plugin-cloudinary": "1.1.1",
    "sanity-plugin-markdown": "4.1.0",
    "styled-components": "^5.3.11",
  },
  "devDependencies": {
    "@sanity/cli": "^3.16.4",
    "@sanity/eslint-config-studio": "^3.0.1",
    "@sanity/types": "^3.16.4",
    "@swc/cli": "^0.1.62",
    "@swc/core": "^1.3.62",
    "@vitejs/plugin-react": "^4.1.0",
    "typescript": "^4.8.4"
  }

Description

@sanity/hierarchical-document-list has @nosferatu500/react-sortable-tree and "react-dnd": "16.0.1" in dependencies, however @nosferatu500/react-sortable-tree expects react-dnd@14 in peerDependencies, which causes a crash due to failed imports from react-dnd

peerDependencies": {
    "react": "^17.0.0 || ^18.0.0",
    "react-dnd": "14.0.4",
    "react-dom": "^17.0.0 || ^18.0.0"
  }

Expected behavior
Plugin is compatible with [email protected] or has react-dnd@14 in dependencies

Full error log

✘ [ERROR] No matching export in "../../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/react-dnd/dist/index.js" for import "DragSource"

    ../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@nosferatu500/react-sortable-tree/esm/index.js:5:9:
      5 β”‚ import { DragSource, DropTarget, DndContext, DndProvider } from 'react-dnd';
        β•΅          ~~~~~~~~~~

✘ [ERROR] No matching export in "../../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/react-dnd/dist/index.js" for import "DropTarget"

    ../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@nosferatu500/react-sortable-tree/esm/index.js:5:21:
      5 β”‚ import { DragSource, DropTarget, DndContext, DndProvider } from 'react-dnd';
        β•΅                      ~~~~~~~~~~

7:19:51 PM [vite] error while updating dependencies:
Error: Build failed with 2 errors:
../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@nosferatu500/react-sortable-tree/esm/index.js:5:9: ERROR: No matching export in "../../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/react-dnd/dist/index.js" for import "DragSource"
../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@nosferatu500/react-sortable-tree/esm/index.js:5:21: ERROR: No matching export in "../../node_modules/.pnpm/[email protected]_@[email protected][email protected]/node_modules/react-dnd/dist/index.js" for import "DropTarget"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.