getgrav / grav-plugin-admin

Grav Admin Plugin
http://getgrav.org
MIT License
355 stars 223 forks source link

Using list controls for page collections #783

Open fredrikekelund opened 7 years ago

fredrikekelund commented 7 years ago

Wasn't sure whether to file this issue here or under plugin-form, so let me know if I should move it.

What I'm trying to do is to set up an admin blueprint that uses a list control to specify a page collection of individual pages. My blueprint looks like this:

title: Collection
'@extends': default

form:
    fields:
        tabs:
            type: tabs

            fields:
                collection:
                    type: tab
                    title: Collection

                    fields:
                        header.content.items:
                            type: list
                            label: Collection
                            btnLabel: Add project
                            style: vertical

                            fields:
                                .@page.self:
                                    type: pages
                                    label: Page

This renders the admin controls correctly, and if I enter the items in a collection manually, the admin panel will render them correctly. However, if I make edits in the admin panel and save, things will trip up on the .@page.self key, and the generated YAML will look something like this:

content:
    items:
        -
            '@page':
                self: /projects/example

How can I prevent @page from becoming an object - ie. how can I make the YAML serializer "escape" the dot in the key name in the admin blueprint?

rhukster commented 7 years ago

I'm not sure it's possible the 'dot' is needed because you have a list. The level you have the .@page.self is purely intended to act as a YAML key that is inserted into the frontmatter. I can't think off hand of a way to do any processing on that.

@mahagr you have any ideas?

fredrikekelund commented 7 years ago

I saw in the antimatter theme that the way it had been solved in one of the blueprints was to supply a textbox that controlled the content field of the page. But that seems like a compromise compared to using a list of page controls - it would be much more understandable for normal users.

rhukster commented 7 years ago

ideally a field could be written that handles this capability, but it's a complex bit of YAML that can be configured a large amount of ways. For the sake of expediency, we just made it a text box and set it a YAML flag:

header.content.items:
              type: textarea
              yaml: true
              label: Items
              default: '@self.children'

The goal is eventually to make this more user-friendly, but it's just not easy to do :)

mahagr commented 7 years ago

It doesn't work like this. To extend the fields you need to use extend@: type inside the field you want to extend. You cannot also extend the page itself as it creates never ending loop. I think you just want to list pages, not to embed page into a page.

In that @rhukster 's code is likely what you'd like to have unless you want to create a field of your own.

fredrikekelund commented 7 years ago

@mahagr I'm not sure I follow, where would I need to use extend@? I totally get if it's difficult to just fix this with regards to how the YAML is interpreted, but I'm guessing this is a pretty common use case, and it would be very natural to use the list and pages fields for it.

mahagr commented 7 years ago

I'm not sure what you're trying to do. Can you explain what you'd like to archive and I try my best to help you.

By my comment I meant that you cannot use fields: .@page.self: in blueprints as first there's no implementation to handle it and second it would end up infinite loop even if it worked.

fredrikekelund commented 7 years ago

What I'm trying to do is to set up admin controls for a page collection that consists of a set of manually selected pages.

I could just use a custom list instead of a page collection, but using a page collection has the advantage of enabling me to reuse the same template for both taxonomy pages and pages with a manually specified collection (since they would look the same, but specify different page collections).

mahagr commented 7 years ago

Now I understand. You are not trying to import fields from another page type to the used one, but you're trying to have select options listing all the available pages, am I right?

In that case you just need to use field that outputs what you want (you may need to create one, not sure if such a field type exists).

fredrikekelund commented 7 years ago

Yup, that's right! Well, the list field does output what I want, and so does the pages field, except it can't handle the .@page.self key. Instead of this (the desired result):

content:
    items:
        -
            '@page.self': /projects/example

I get this (the actual outcome):

content:
    items:
        -
            '@page':
                self: /projects/example

(I attached the blueprint in my initial comment as well)

mahagr commented 7 years ago

Oh, I've been reading this wrong all the time!

Finally I understood what the issue was, its blueprints splitting up the field by dots. The reason for the behaviour is that dot has a special meaning in blueprints.

@rhukster This is a bit issue as there's really no way to get around this issue, at least not that I can think of. We are using dot notation for nested arrays and Grav is using dots for some special field keys as well.

hughbris commented 1 year ago

Any advances on this capability? I am trying to do exactly this now.

If there is a trick, I think it would be good to go another step and create a new blueprint field type for page collections.

I assume this problem can't be solved by something as simple as Grav supporting an escape for the period. That seems obvious and you have probably ruled it out. (edit: nvm, probing further showed me it's not that simple, I think Grav might need to support another delimiter)