-
-
Notifications
You must be signed in to change notification settings - Fork 315
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
Add support for parent and child page restrictions in page_layout definition #1776
Add support for parent and child page restrictions in page_layout definition #1776
Conversation
af1fc18
to
8209294
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few implementation comments, and I would like to suggest to only implement ONE of sub_pages
or parent_pages
. If a page layout can only have certain subpages, then that's all you should ever need, am I right?
required: true, | ||
selected: @page_layouts.length == 1 ? @page_layouts.first : nil, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
page_layouts.first.presence
instead would do the trick
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice catch will fix next round
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I don't think i can change this as i select first only if length == 1 - Not if first is present
8209294
to
1cf16b7
Compare
lib/alchemy/page_layout.rb
Outdated
# | ||
def selectable_layouts(language_id, only_layoutpages = false) | ||
def selectable_layouts(language_id, only_layoutpages = false, page_layout_name = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method selectable_layouts
has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
1cf16b7
to
2494f31
Compare
03bdcef
to
f6bd940
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
I like the overall idea of this feature a lot. But the implementation should be much easier. I do not see a need for child pages being able to define parent layouts. This does not make any sense. Children can not exist without a parent.
So in my thoughts something like
- name: blog
sub_pages:
only: post
and
- name: standard
sub_pages:
except:
- post
- blog
is a great API we would except.
The selectable layouts methods are worth refactoring so that its easier to understand what is going on. In the end it should be easy as:
All defined page layouts for that site - already taken unique ones - not allowed layouts = selectable layouts for the new page
And we need tests of course.
Again, thanks for that feature. I like it.
(excludes && !excludes.include?(layout['name'])) | ||
end | ||
|
||
def layout_available_from_child?(layout) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why we would need that. We are never able to create a parent for an existing child. That's not possible. Can you elaborate what this is for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not about creating a parent for a child. But under which parents the layout will be available. Previously there was a setting hide = true
which made certain layouts hidden from creation. I just deleted this hide
setting from the conditions in my last push as this can be achived with `layout['parent_pages'] = false.
But the reason why I think this feature makes sense to have is the following. Imagine that you have a mature website with some 15 page layouts available. Then you want a new type of blog post layout special_blog_post
that should only be creatable under the blog layout.
With the new feature you simply set parent_pages['only'] = ['blog']
in the special_blog_post
settings.
Without it you would have to revisit all other page_layout and append `child_pages['except'] = [ ... 'special_blog_post']
... Which feels a lot more tedious/error prone. In the end this logic is only executed on admin page creation, and we're already looping through all layouts to check the rest of the conditions - so i dont think it could have any significant impact on performance?
What do you think?
lib/alchemy/page_layout.rb
Outdated
# | ||
def selectable_layouts(language_id, only_layoutpages = false) | ||
def selectable_layouts(language_id, only_layoutpages = false, page_layout_name = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree this method is overly complex and combined with the other methods its worth refactoring. I think this can be implemented much easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I can simplify this. I added more comments to the code to clear up any misunderstanding.
Also - I chose to call it parent_layout_name
instead of parent_page_layout
to make it clear that it is a name (String) and not a layout (Object/hash) from definition we're expecting - As has been done in a bunch of other places there
lib/alchemy/page_layout.rb
Outdated
@language_id = language_id | ||
@page_layout = page_layout_name.present? ? all.detect{ |layout| layout['name'] == page_layout_name } : nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary in here? We not filter the available page layouts with select
reject
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gets the layout of the parent page (Object/hash from definition where we can check for child_page restrictions) from the parent layout name (String).
Then just below we filter with select and all the conditions.
ac9f4d8
to
984a619
Compare
@tvdeyen Thanks for your comments. I updated most of the things you suggested and added tests. Some questions/thoughts:
This seems kind of like what we have? In method
Then below we have the conditions tested for each layout in the select filter. I only added the first two (and removed the old redundant
Which equates to: (?)
So I'm not sure how you want to simplify this. |
# | ||
def selectable_layouts(language_id, only_layoutpages = false) | ||
def selectable_layouts(language_id, only_layoutpages = false, parent_layout_name = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method selectable_layouts
has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
018ff48
to
8e7d2d7
Compare
Could you please extract the "No please choose if only one layout available" feature into a dedicated PR? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at this again today and although I think this is a nice way to structure pages I still think that the page layout code is getting more and more complex. Since I need to maintain this going forward I need more time to get convinced. Maybe refactoring the code into smaller understandable classes and methods would help. But in the current form I tend to not accept this although I like that feature.
@@ -57,9 +57,9 @@ def info | |||
|
|||
def new | |||
@page ||= Page.new(layoutpage: params[:layoutpage] == "true", parent_id: params[:parent_id]) | |||
@page_layouts = PageLayout.layouts_for_select(@current_language.id, @page.layoutpage?) | |||
@page_layouts = PageLayout.layouts_for_select(@current_language.id, @page.layoutpage?, @page.parent &.page_layout) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be?
@page_layouts = PageLayout.layouts_for_select(@current_language.id, @page.layoutpage?, @page.parent &.page_layout) | |
@page_layouts = PageLayout.layouts_for_select(@current_language.id, @page.layoutpage?, @page.parent&.page_layout) |
A test would have could this. Could you please add one?
@@ -55,6 +55,7 @@ def page_hash(page, has_children, level, folded) | |||
public: page.public?, | |||
restricted: page.restricted?, | |||
page_layout: page.page_layout, | |||
child_pages_allowed: page.definition["child_pages"] != false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not like the name of this attribute
allowed_page_types
, or maybe nestable_pages
nestable_child_pages
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now i named it for what it actually is show_create_page_btn
. Which can be true even if there are no pages available, as the button is only hidden if definition['child_pages'] == false
.
Also added tests for controller method calls. I've been using this feature for quite some time already, [space] &.
works just as fine as [no_space].&
- but i still removed the space as you like.
I think the implementation is good now and for me the feature is essential for controlling the page tree structure. It is also just as you requested it to be as explained in this comment #1776 (comment)
I would say it cannot be simplified more. You have to give me more concrete feedback if you still disagree.
@mickenorlen we switched the default branch to |
…inition child_pages lists which pages can be created under given page layout. parent_pages lists under which page layouts given page can be created. Both will determine which page layouts are available for selection. Set by: child/parent_pages: {include/exclude: [layout_name, ...]
5aea006
to
e1fe6ff
Compare
@tvdeyen Force pushed a fresh single squash merge commit into main as rebase was a mess. |
This pull request has not seen any activiy in a long time. |
This pull request has not seen any activiy in a long time. |
Update 8/7
See comment: #1776 (comment)
What is this pull request for?
Add support for restricting parent/child_pages:
Update 17/5
Renamed
sub_pages
tochild_pages
and addedinclude
/exclude
as suggested by @mamhoff.Note
If child_pages = false
it will entirely hide the create child_page button (+) in page_tree. See screenshot 1.if selectable_layouts.length == 1
i added autoselect and removed blank option in create selection. See screenshot 2Changes in the code
page_layout
of the parent_page toPageLayout.selectable_layouts
to be able to check the definitions.allowing_child_pages: page.definition['child_pages'] != false
to thepage_tree_serializer
so i could hide the create (+) button.Screenshots
No (+) button if
child_pages = false
No blank/"Please choose" option when only 1 to choose.
Tests
I wanted to check with you if the overall implementation looks good before fixing the tests. Currently 2 fails saying
undefined method page_layout for nil:NilClass
Checklist