简体   繁体   中英

Content versioning in Keystone 6

In a previous project in Keystone 4, I was able to work with content versioning. That is, if I were to update a content entity (eg BlogPost), I would have the possibility to toggle between the previous version of the blog post, and the current one.

I can't see any options for this in the documentation for Keystone 6, and I also find it hard to find any resources on this subject online. Does someone have any insight in this? If it's not possible out-of-the-box - do you have any advice on how to accomplish it manually?

Thanks in advance

Content versioning is something the Keystone team has discussed a lot internally but it's quite a complicated area. There are just so many different ways to approach the problem, even when versioning within a single item. If you bring relationships in to it and versioning across multiple items the problem space grows quickly.

If a first party solution did get built it would probably be built "on top of" Keystone – similar to the @keystone-6/auth package – that is, a separate, configurable package that uses the documented Keystone APIs to add functionality. Regardless, as it stands right now, versioning and publishing workflows are something you'll need to design and build out yourself.

My advice would be to first get clear on exactly what you need to version and what you don't. Somethings to consider:

  • Do you need to version the whole item or maybe just a few fields?
  • Do you need a history of changes or is it enough to have a "published" version and an optional "draft" version that's editable?
  • Will you need to "revert" changes, or is an "update only" model sufficient?
  • Do you care about related items? (Eg. say your blog posts are related to a list of Tags , does editing the tags constitute a new "version" of the post or is that "outside" of the versioned part?)
  • What about collaboration; will multiple people be trying to edit a single post/draft at the same time?
  • Can you have multiple draft version or just one?
  • Do you you need to consider previewing changes or (worse) sets of changes?
  • Do you require some kind of integrated approval workflow or can anyone creating content publish/revert it?

Some basic approaches that spring to mind:

Draft/Published Fields

For something relatively simple like aa blog post you maybe able to get away with a draft/published workflow implemented within the item, at the field level. Something like this:

  Post: list({
    fields: {
      slug: text({ validation: { isRequired: true }, isIndexed: 'unique' }),
      publishedTitle: text({ validation: { isRequired: true } }),
      publishedBody: document({ /* ... */ }),
      draftTitle: text({ validation: { isRequired: true } }),
      draftBody: document({ /* ... */ }),
    },
    // access, hooks, etc.
  }),

Your frontend displays only the published... field but you restrict the backend to only allow the draft... fields to be edited (you could even hide the published fields from the Admin UI). A hook or custom mutation can be added to "promote" the draft content to published by copying it between fields. With the right access control, you could even setup the frontend to preview the draft content institchu with a magic URL param or something.

It's pretty basic, but easy to setup and use.

Item Per Version

A more powerful alternative would be to represent versions with separate items and use a field to track which version is the currently published content:

  Post: list({
    fields: {
      slug: text({ validation: { isRequired: true }, isIndexed: true }),
      title: text({ validation: { isRequired: true } }),
      body: document({ /* ... */ }),
      isPublished: checkbox(),
    },
    // access, hooks, etc.
  }),

In this scenario the slug field isn't unique in the list – each post can have multiple items, representing either upcoming drafts or historical versions. When a version of a post is published (by setting isPublished to true), a hook ensures any items with the same slug have the isPublished flag set to false. The front end simply filters by isPublished to get the current version (enforced by access control if needed). This lets you both publish updates and roll back to any previous version. It also solves for relationships to some extent – eg. if you have a related list of Tags , linked many-to-many with Posts , updates to the post's tags are versioned along with the content.

To smooth the workflow out, it would probably be useful to have a custom mutation that duplicated an existing post, allowing you to make changes to existing content with ease. And maybe a custom Admin UI page to help visualising a posts history and managing revert actions, etc.


These are just two examples but there would be dozens of other ways to approach the problem. Just be clear on your requirements then do the simplest thing that works: :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM