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

feature: new chooser field type and admin UI widget #675

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

davidferguson
Copy link
Contributor

Issue(s) Resolved

no open issues

Related Issues / Links

Description of Changes

  • Wrote at least one-line docstrings (for any new functions)
  • Added unit test(s) covering the changes (if testable)
  • Included a screenshot or animation (if affecting the UI, see Licecap)
  • Link to corresponding documentation pull request for getlektor.com

The flow widget is great, however it has the limitation that if many blocks are used (on some pages I have 100+) the page is very long, and where more complex custom widgets are used (gui markdown and others), trying to render this many on the page causes the browser to crash. Even with the rather excellent new feature of being able to collapse the blocks, it is rather unwieldy when that many blocks are added.

I've therefore come up with a new type of widget which I'm calling chooser. This is very similar to flow (and indeed is compatible in most ways), however has the following differences.

  • Rather than being able to add flow blocks of different types, chooser is limited to only one type of flow block.
  • Rather than displaying all the blocks in a list, only one is displayed, alongside a selection list, allowing you to choose which block is being edited.
  • The selection list obviously requires some way of identifying the blocks, and due to this, a key_field must be specified in the chooser configuration, which specifies the field that is displayed in the list.

Hopefully this makes sense, and if not maybe the example below helps to illustrate it.

I've not yet written any documentation for this on getlektor.com but I can do that shortly if this PR gets accepted.

I have however added tests for the new chooser type. There weren't any tests for flow that I could see, so I added some for that too.


Example

Suppose you have the following flow block, used for adding references/citations to an article. Each reference has a number, and the reference text.

[block]
name = Reference
button_label = Reference

[fields.number]
label = Number
type = integer
width = 1/4

[fields.reference]
label = Reference
type = bbcodeinline

In the model file for the page, the usage is very similar to flow, except only one flow_block is specified, and a key_field needs to be specified too:

[fields.references]
label = References
type = chooser
flow_block = reference
key_field = number

On the admin UI page, this is displayed as the following widget, where the selection box on the left is showing the value of the key_field for each block, and upon choosing one, it can be edited using the fields to the right:

chooser-widget

The usage in templates is exactly the same as flow (and indeed uses the FlowType and FlowDescriptor classes).

@nixjdm
Copy link
Member

nixjdm commented Jul 31, 2019

This is pretty interesting. I'll try play with it over the weekend to get a better feel for it, and then I'll let you know what I think. Thanks for the creative contribution! :)

Having displayId in props.value allows it to persist when/if the widget is
unmounted and remounted, and given the same value. This is important for use
in nested choosers, or in flow, as that happens often.
Take the new flowblock type from this.props.type.flowblock_order, rather than
this.props.type.flowblocks, as flowblocks contains all the in-use blocks,
while flowblock_order is the flowblocks in use for that widget.
@davidferguson
Copy link
Contributor Author

Added a few fixes, and moved the utility functions that are common to both flow and chooser to a separate file flowformat.jsx.

It would probably be worth looking at merging #670 alongside this, as the chooser widget uses the optimisations from that.

chooser widget can now take a select_width option, that specifies the width of
the <select> box of the chooser type
@davidferguson
Copy link
Contributor Author

(Hopefully) the last commit for this - adds an option to specify the width of the <select> element: select_width, which takes the same width values that the standard width option for all widgets take.

@nixjdm
Copy link
Member

nixjdm commented Aug 4, 2019

Here's my general reaction:

It doesn't seem like the keys actually need to be unique right now (more on that below). I can save it just fine - and it doesn't seem to break anything. There also doesn't seem to be a way that field is really being used as a key. The order of the "chooser blocks" is determined the same way it is for flow blocks. As is, this is a much more condensed view of flow blocks, but AFAICT it doesn't really add a new feature.

It could though. Calling the key_field a "key", and calling this type chooser both really make me want to be able to grab a specific block by the key name. Right now, you can loop through the blocks just as a normal flow block with something like {% for blk in this.references.blocks %}. What would be really cool is if you could also do {% set blk = this.references.blocks_map["key"] %}. You can't do that with flow blocks. I.e. build a view of these blocks as a dictionary where the keys are the values of the key_fields.

If the key uniqueness is enforced and we have that alternate view, I think that's a great new builtin type.

Without the uniqueness, the alternate view can't be made, and this is just another way of presenting flow blocks in the UI (unless I'm missing something). It's basically a presentation where it's only possible to look at one flow block at a time. Offering that is a good idea too. You're right that it can be a pain having many flow blocks on a page. I can easily imagine wanting a similarly condensed UI but not want to deal with making keys.


More specifics:

Uniqueness:

If I make a "chooser block" with a key of 1, and make another with a key of 1, the UI complains and says Key Field must be unique, but that is not actually enforced. It just disables adding another block (the plus button is grayed out) while that block is selected - which doesn't really preventing me from adding another block either - I just have to select a different block first and then the plus button is usable again.

Nullability:

The key_field is also nullable right now - which should change. You can create and save blocks with no value for the key_field.

Key types:

I like that key_fields don't have to be ints. If we can query for them directly, using strings can make a lot of sense. There should probably be a whitelist of types allowed to be keys though, because a lot of types don't make sense. Maybe the whitelist should be: integer, string, float, date, datetime, url, sort_key. Multi-line types don't make sense, neither do special types like checkboxes, booleans, or flow blocks. Using sort_key might be related to key generation (my next comment).

Auto-generating keys:

If keys are integers / sort_keys, than I can also see wanting them to be directly tied to the order of the blocks, and auto-generated. For instance, if I make 5 blocks, it would be cool it I didn't have to manually number them, and if I reordered them, the numbers would still be sequential, but the keys would be mapped to different blocks. It would always be 1 through 5, in order. If this option were used, I'd also want the key_field grayed out and uneditable. If keys could auto-generate like that, I'm not really sure I'd ever use normal flowblocks again. This work isn't necessary for a first PR, but I'd love it.

The sort_key docs already make room for special uses like this, so that might be an easy way of signalling to Lektor that we want auto-generated keys or not; integers could be manual (as you have it now), and sort_keys could have this automatic behavior.

UI improvements:

The UI box that lists the keys is fine for now, but it could be improved. For instance, it's height matches the space required for the fields in the block. If there's only one or two one-line fields, that's not a lot of height. That makes it a bit cumbersome to sift through a long list of keys.

Similarly, being able to search through or filter blocks would also be really nice. That can also be a later improvement.

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.

None yet

2 participants