Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] New (Multi-)Relation Widget #1928

Closed
wants to merge 4 commits into from

Conversation

leonardodino
Copy link
Contributor

@leonardodino leonardodino commented Dec 1, 2018

Summary

Add a new relation-like widget capable of selecting multiple entries (also support single).

It's based on react-select, as the new select from #1901.

Motivation (TLDR; we need a multi-relation widget)

I'm working on my college campus newspaper website, and using NetlifyCMS to manage it's contents. It's working great! I'm really glad this awesome project is being maintained (:

The journalism students from a dedicated online news course are the ones editing it, It currently uses an extended version of the relation widget for selecting author and the category. It's a bit hacky, especially considering it saves an object (title + slug), although it can only select a single author. The most requested feature was multi-author attribution in the posts.

current relation UI hack current relation data hack
UI hacks, relation widget data model before this PR

I'm saving the title so it's more readable in the CMS UI, although that complicates a lot linking the files in Gatsby, and adds potentially stale data.
The ideal for this case is an array of slugs, but requires that the CMS can resolve slugs back to data to have a nice UI, hence exporting loadEntry action, and persisting only slugs (incompatible with current relation).

How it looks

All of the styling work is directly borrowed from the recent update in the select field by @alexandernanberg (:
It should, probably, be de-duplicated later by exporting it from netlify-cms-ui-default or something like that.

single-relation multi-relation
single relation multiple relation

How it works

It saves the related entry slug, or array of slugs, and pulls it back when displaying it. The autocomplete list still renders from the queryHits, as in the original relation.

Based on my limited knowledge of SSG (mostly Gatsby and harp), and file based CMS (kirby and stacey), linking by the slug, granted it's stable as in NetlifyCMS, is the least painful method of linking entries together.

Caveats

It is incompatible with the current relation, because there's no valueField option.
displayFields is possible but not implemented, as a js constructor or composing seems a better way to configure it, as demonstrated in the motivation image.

Test plan

[WIP] probably will do something based of the select widget as well.

this is WIP

I've opened it here for discussion.

It seems to be working right now, but it lacks tests, and it could be improved in some ways.
Also, it's not compatible with current relation widget, and probably never will.

  • multiple slug relation array (that was implemented first)
  • working single slug relation (was little work on top)
  • naming (SlugRelation is a bad name, need suggestions) will extend current relation
  • add support for custom identifier field (re: Add support for setting custom identifier field  #1543)
  • add backwards compatibility with current relation widget (re: @erquhart)
  • docs update (thanks for reminding @verythorough)
  • tests!
  • better UX (when loading or not searching it shows "no options" text)
  • remove copy-pasted style code from select. (move to netlify-cms-ui-default, probably another PR)
  • export a factory method to create custom UI (maybe another PR)
  • code style (the lint passes, but I'm sure it's not consistent prettier 🎉)



A picture of a cute animal (not mandatory but encouraged)

@verythorough
Copy link
Contributor

Deploy preview for netlify-cms-www ready!

Built with commit c9758d8

https://deploy-preview-1928--netlify-cms-www.netlify.com

@verythorough
Copy link
Contributor

Deploy preview for netlify-cms-www ready!

Built with commit 01fade7

https://deploy-preview-1928--netlify-cms-www.netlify.com

@leonardodino leonardodino changed the title new (multi-)relation widget New (Multi-)Relation Widget Dec 1, 2018
@verythorough
Copy link
Contributor

Deploy preview for cms-demo ready!

Built with commit 01fade7

https://deploy-preview-1928--cms-demo.netlify.com

@alexandernanberg
Copy link
Contributor

Nice work! But I think I would be more in favor of keeping the current behavior of the relation widget and just replace react-autocomplete with react-select tho. I don't really understand why you need to save the slug, in eg Gatsby you can use mapping create the "link" between the posts.

@leonardodino
Copy link
Contributor Author

leonardodino commented Dec 4, 2018

Hey @alexandernanberg, thanks for chiming in. (:

I fully agree and I'm not at all opposed to reimplementing the current relation widget with react-select. It's definitely a good idea for consistency.

But this PR tries to solve a different issue. named: consistent multiple relations. (and a custom UI)


I'm very concerned with UX for the editing interface, as it reduces support requests and anxiety.
Displaying slugs is not at all user-friendly, and if the Option popup can have custom layout, I think it helps directing user. (see above table on UI Hacks, built on top of current relation).

Actually on my case I go a little further and filter the options based on another field on the entry. (that part is not on this PR)

Specifically on my case, there can be multiple authors that go by exactly the same name (it's scoped by semesters, on a same semester they are unique, across all time they aren't). So saving only name doesn't cut for me, and if someone change it's name, the linking is broken. that's why I think saving slug is more robust.

Regarding Gatsby

As far as documentation goes, I don't think I can unwrap, natively, object properties inside an array for mapping. example:

authors: [{title: 'Leonardo Dino', slug: '/authors/2018-2-leonardo-dino'}, ...]

if it's a simple list of strings, I know I can, as stated on the docs.

Regarding NetlifyCMS

Right now, there's no way of fetching data on the relation after saved. That's why, on my case, I save both the slug and title. It was a bit of dev effort, but it's more readable on the user end.

Because of the lack of fetching/"hard linking" it's also not possible to informing via UI of a broken relation (if I delete an author for example). It will result in a broken build or silently missing a relation.


So that's why it's not a proposal of replacing/deprecating relation, it has it's uses on looser content handling, but for a tighter experience I think it's lacking some features (:

@erquhart
Copy link
Contributor

erquhart commented Dec 4, 2018

The custom UI "hack" looks really, really cool.

Relations are inherently tricky with no database. What you're trying to do is an approximation of relational database behavior where records are referenced by a unique ID rather than based on their values, which, as you mentioned, may change.

What you're doing makes sense - a tl;dr version of your requirements seems to be:

  • support slug-as-value in relation fields
  • multi-select in relation fields

Let me know if that's incorrect or lacking.

I do believe that this is compatible with the current relation widget, we'd just add a use_slug boolean flag to the options - if it's true, we use the new behavior. I also expect that valueField and displayFields should work fine. If we can use the relation widget already to look up a related entry based on unique value and retrieve values from it, we should be able to look up a related entry by slug and do the same.

@tomrutgers
Copy link
Contributor

The custom UI "hack" looks really, really cool.

Can I haz? Also in the select widget! 😄

@leonardodino
Copy link
Contributor Author

Will try to get some time this weekend. (:

I really liked @erquhart suggestion: adding an option for using only slugs in the relation and reusing/extending the current widget.

That would also solve the migration from react-autocomplete to react-select. one less lib on the bundle! 🎉


I'd like some feedback on the approach of EntryLoader, on this PR, it's using redux connect outside core, that may be a code smell. I think we should have another package, importable from widget/previews, for this kind's of integrations.
It's easier to test it in isolation in one place, instead of having this kind of tests inside this widget. (I think it can help on #1896, but I'm not sure)


Thanks for the positive feedback on "UI hacks"! (:
I will try to also have an example of how that would work on this new widget.

@verythorough
Copy link
Contributor

This looks awesome! Can you add docs updates to your checklist? 😉

@talves talves changed the title New (Multi-)Relation Widget [WIP] New (Multi-)Relation Widget Jan 13, 2019
@talves
Copy link
Collaborator

talves commented Jan 13, 2019

Added [WIP] in title. Once you are ready @leonardodino just remove it from the title.

@leonardodino
Copy link
Contributor Author

thanks @talves (: it's indeed WIP, but there are a couple of roadblocks: #1013 #1936.
Aiming for a backwards compatible relation widget that also implements this behavior would be nice, but also much work right now.

I'm proposing moving this to the "userland". One of the intentions of the netlify-cms v2 was to be more modular, and this one is a case where i think is well suited to this modularity. I will create a PR to merge 974fc3d in the master, as it's the only requirement for this module to work (:

@erquhart
Copy link
Contributor

erquhart commented Feb 3, 2019

#2010 merged instead, as requested.

@erquhart erquhart closed this Feb 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants