sanity icon indicating copy to clipboard operation
sanity copied to clipboard

production-preview/resolve-production-url - Accept promise

Open nzhenry opened this issue 4 years ago • 8 comments

Currently this interface only accepts methods which return a string. Could it accept methods which return a promise please?

nzhenry avatar Oct 08 '20 09:10 nzhenry

+1 on this, and generally more parts accepting promises/observables (such as document action resolver, input type resolver etc)

mcky avatar Oct 09 '20 14:10 mcky

I need this as well. In the meantime, I have a workaround for anyone else in the same boat via the document actions API.

// sanity.json
{
  "parts": [
    {
      "implements": "part:@sanity/base/document-actions/resolver",
      "path": "./resolveDocumentActions"
    }
  ]
}

// resolveDocumentActions.js
import React from 'react';
import { EarthGlobeIcon } from '@sanity/icons';
import defaultResolve from 'part:@sanity/base/document-actions';
import asyncGetLink from '...';

const isPreviewable = document => {
  // TODO: implement this function
}

export function OpenPreview({ draft, published }) {
  const document = draft || published;

  if (!document) {
    return null;
  }

  if (!isPreviewable(document)) {
    return null;
  }

  return {
    label: 'Open Preview',
    shortcut: 'cmd+shift+o',
    icon: () => (
      <EarthGlobeIcon
        style={{ width: 25, height: 25, transform: 'translateX(-4px)' }}
      />
    ),
    // `onHandle` is where we can sneak in `async`
    //          👇
    onHandle: async () => {
      const link = await asyncGetLink(document);
      window.open(link);
    },
  };
}

export default function resolveDocumentActions(props) {
  const [firstDefaultAction, ...restOfDefaultActions] = defaultResolve(props);

  return [firstDefaultAction, OpenPreview, ...restOfDefaultActions];
}

image

It's not the typical place for it but this works for me!

ricokahler avatar Mar 27 '21 07:03 ricokahler

I have a hacky solution to this as well:

I have some document paths that include the slugs of parent sections. Since I can't query for these slugs within the function to resolve the preview URL, i "pre-load" them in the scope of the module:

import client from './client';

let sectionsMap = new Map();

const fetchDocuments = async () => {
  const sections = client.fetch(`*[_type == "section"]{ _id, slug }`)
  sections.forEach(section => sectionsMap.set(section._id, section.slug.current));
};

/* Run this once on load */
fetchDocuments();

// path: /sections/:sectionSlug/articles/:articleSlug
const resolveArticleUrl = document => {
  if (!document.section) return null;
  const sectionSlug = sectionsMap.get(document.section._ref);
  if (!sectionSlug) return null;

  return `${BASE_URL}sections/${sectionSlug}/articles/${document.slug}?preview=${document._id}`;
};

good-idea avatar May 13 '21 20:05 good-idea

+1

This feature is really needed, when you have dynamic routing based on parent objects such as. /slug/slug2/slug3, and they are dynamic from parent documents. Allowing resolve-production-url to be async would fix this.

Giving access only to the "document" does not cut it, because slug or slug2 could be inside a reference. Which you would have to fetch async before resolving it to "slug" or "slug2".

peec avatar Jun 04 '21 10:06 peec

+1 ran into this lately

zanedev avatar Jul 29 '21 22:07 zanedev

In the studio we are unaware of the routing that is in the public facing site. So we have an API there to determine the actual url.

EECOLOR avatar Oct 29 '21 13:10 EECOLOR

+1 on this

rshackleton avatar Dec 01 '21 11:12 rshackleton

wow, why is this not a thing yet? are we missing some other obvious way of solving this issue? I really need to be able to build the preview URL via async queries, otherwise it all needs to be hard-coded, which is very inflexible.

ovsw avatar Jul 22 '22 10:07 ovsw

The resolve-production-url API is now async with the release of Sanity Studio v3.

kmelve avatar Jan 11 '23 21:01 kmelve