Page Manager is implementing CTools' Wizard API in order to improve the user experience when making a set of changes on a page. While the patch at #2550879: Use CTools Wizard API to add/edit Pages (and move plugin UI using PluginWizardInterface) gets polished and committed, this issue will work on the Panel variant so it supports the wizard API.
@yanniboi and @eclipsegc did the first step with this commit in a GitHub repository, which I am attaching here.
| Comment | File | Size | Author |
|---|---|---|---|
| #48 | 2697587-interdiff.txt | 2.46 KB | eclipsegc |
| #48 | 2697587-48.patch | 84.69 KB | eclipsegc |
| #45 | Page_information___Site-Install.png | 119 KB | japerry |
| #42 | 2697587-interdiff.txt | 899 bytes | eclipsegc |
| #42 | 2697587-42.patch | 82.97 KB | eclipsegc |
Comments
Comment #2
juampynr commentedMy first round of testing went fine. I could create a page with a Panels variant, select a layout and add an Entity:node block to one of its regions. Then I saved and tested the page and it worked. There were no errors nor warnings logged. I have a few questions and things to look at though:
[ ] We should update PanelsTest.php so it tests the new interface.
[ ] Currently we can add entity displays, but I cannot find the ability to add a field display into a region like you can do in Drupal 7. Most probably this is out of scope of this issue, but I would like to know if there is already a solution to this that I am not aware of.
[ ] I could not change the layout once the page was created: it simply does not change when you click on "Content". If I am not mistaken, there was a mid-step after changing the layout of an existing page in which you could relocate blocks in the new layout. Again, this may be out of scope of this issue but I would like to hear from the others.
I will start by updating tests.
Comment #3
juampynr commentedHere I am updating the tests so they work with the Wizard API. I am getting a very weird error when setting the layout at the Variant Settings form. Still debugging it. Here is the error:
Comment #4
juampynr commentedNo luck with that bug. Besides, I have found another one. I have updated the test so it replicates both of them. Here is how to reproduce them:
Bug A: error when updating Layout Settings via AJAX
1. Enable layout_plugin_example.
2. Create a page with a Panel variant. Choose the "Test layout (with settings)" layout.
3. Edit the page: click on the General section of the variant.
4. Select the Layout field to "1 column layout". See how the Layout settings fieldset changes via AJAX.
5. Select the Layout field back to "Test layout (with settings)".
Expected: Layout settings form shows up again.
Actual: nothing happens in the ui, but the following error is logged:
Bug B: error when changing a layout setting
1. Follow steps 1 to 3 from Bug A.
2. Set the Blah field with a different value. Then click Save.
Expected: the setting is saved along with the variant and page.
Actual: the following error shows up:
Comment #6
juampynr commentedHere I fix Bug B. The tests are not reporting useful feedback because they are using page_manager-8.x-1.0-alpha23 instead of 8.x-1.X.
Comment #8
yanniboi commentedSo I think what we need to do is be able to trigger a wizard when the layout is changed because we need to be able to reassign blocks to new regions.
I will have a look at this.
Comment #9
juampynr commentedHere I am fixing a bug when serializing data that contains contexts.
Comment #11
yanniboi commentedOk, so I have been working on this, and my patch is in no way complete (in fact there is probably loads wrong, but I'm sharing my work in progress), but I have run into a few difficulties that I need help with.
I am attaching a few screenshots to help.
When in the page edit wizard, looking at the layout set of the panels variant, I have removed settings from this step and added a button to trigger a 'change layout' wizard.
This currently has 2 steps, 'settings' and 'regions'.
Issues:
I also need to merge @Juampy's patch into mine because we started at slightly separate steps...
Comment #12
marthinal commentedHi! This is my first contact with panels for D8.
1) I'm learning how Wizard API works and I think that we could have 2 different forms for the layout. The first one to add a new variant and a second one to edit the variant.
So in this case we can handle separately...
Does it make sense?
The attached patch is an example.
2) We could use a new wizard form for the edit form but I have no idea about how to add this wizard form inside a wizard form...
Comment #13
marthinal commentedOops Adding the forms here...
Comment #14
marthinal commentedOk! Let's try again:
1) I'm creating a Base Form that could be extended by the Edit and Add Forms. So, these forms are different and I'm overriding the buildForm() from the Edit to add a new custom button (Change Layout).
2) I don't know if this is the best way... but for the moment using "user.private_tempstore" to store the values when loading the form to change the layout.
3) Creating a new route to obtain the substep.
4) Detecting if the current path is a substep and then adding this form to the operation when loading the wizard. We can add different steps/forms.
To be honest I have no idea if this is the correct way but for the moment it works. Needs test and probably refactor but for the moment needs review :-)
Comment #15
eclipsegc commentedApologies to marthinal, my patch is based on an older version of the patch so we need to make sure this code can all be merged. I'm just posting this out there for the masses for the time being.
Main fix here is to remove PageManager specific code in the submit handler of the Layout step. For future reference (because there's likely more of this code that hasn't bit me yet) the objective is to update the cached_values['plugin'] object with new configuration. PM (and Panelizer or others) will extract the values they store from that object.
No interdiff since I'm totally doing a runby-patching. I think this was based on 11, and I'll get an interdiff together after I'm back from vacation.
Eclipse
Comment #17
dobe commentedComments about #14.
// This is totally personal opinion and likely has no weight.
I am not sure having sub_steps is the right way to go. We should be able to do the same thing using the single step routing.
#15 seems like its on the right path but I am getting an error:
PHP Fatal error: Call to a member function getTempstoreId() on a non-object in /modules/contrib/panels/src/Form/LayoutPluginSelector.phpget('wizard') is returning null.
Comment #18
eclipsegc commentedre: 17
Did you upgrade to the newest CTools alpha and/or checkout the newest code from git? I'm not having the same problem and would love steps to reproduce.
Eclipse
Comment #19
eclipsegc commentednvm, found it.
Comment #20
eclipsegc commentedThings worth noting:
TODOS:
Use HEAD of both ctools and page_manager for best results on this.
Eclipse
Comment #21
juampynr commentedShall we document this method?
Why there is LayoutChangeRegions and LayoutChangeSettings?
Again?
Comment #22
eclipsegc commentedThis patch does not address 21 at all but is a set of minor changes to help support panelizer & mini-panels style approaches as well as removing the change layout wizard class and route.
Eclipse
Comment #24
eclipsegc commentedUpdated the getBuilder() method to include a fallback to 'standard'.
Comment #26
eclipsegc commentedUpdated \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant::buildConfigurationForm to always display the builder form elements. This nullified the need for the form alter I added.
Eclipse
Comment #28
hkirsman commentedNice, #26 fixed my Page Manager (dev) content section. It just didn't exist and I could not add any blocks.
https://www.drupal.org/node/2731877
Comment #29
eclipsegc commentedRemoved non-essential layout related methods from the PanelsDisplayVariant class.
Moved variant title to the content page so that it happens AFTER contexts are created.
Comment #30
phenaproximaThis oughta fix the tests.
EDIT: ...locally, that is. They pass against the latest HEAD of Page Manager.
Comment #32
dsnopekNew in #30:
This is removing the test code that verifies that we can change the settings on layouts with settings! We should really keep this in some form rather than remove it...
Comment #33
phenaproxima@dsnopek: Ordinarily I would agree, but at the moment the wizard workflow does not support configuring the layout settings, which is why that code breaks the tests, and why I removed it. I could certainly comment it out rather than outright delete it, though...
@EclipseGc, confirm?
Comment #34
dsnopekSo, this patch removes the ability to configure layout settings? Then that needs to get fixed! The failing tests are a pretty good reminder for us. :-)
If not, this'll render any layouts with settings unusable, and we've supported layouts with settings for a long, long time and people are using it. The Display Suite layouts (which will appear in Panels) have layout settings, and will render invalid HTML (since they allow selecting the tags used, ie. div, article, section, etc) if they can't save their settings. I believe some of the contrib modules that just add layouts also use settings. This really great video tutorial creates a layout with settings. So, we gotta support this.
Comment #35
phenaproximaThe plugin type needs to be documented here.
Missing a sorely needed doc comment.
This is causing PHP notices (offset 1 not found), which leads me to believe that the machine name should be sanity checked before being split out.
Is this supposed to be empty? Also, missing doc comment.
Missing doc comments.
Needs a doc comment.
Missing descriptions.
Missing doc comment.
It doesn't look like $options is ever used in this method except for this.
The result of $this->t() is what should get the string cast; $form_state->getValue('op') will return a string natively, I think.
Alternatively, why not compare op in $form_state to $form['update_layout']['#value'], so that it doesn't need to be repeated twice?
The final argument can be shortened to
$form_state->getValue('layout_settings') ?: []for brevity.Wrong class name.
Why aren't these using $this->variantPlugin?
Needs a description.
This oughta be injected.
This should also be injected.
This needs a doc comment!
Needs a description in the doc comment.
Needs a doc comment.
It makes sense here to simply set $this->pattern to a plugin instance, if $pattern is a string -- that way, if the string is invalid, the pattern manager will throw a PluginNotFoundException and make things nice and clear if a garbage $pattern was passed in.
Needs a doc comment.
Also needs a doc comment.
Ideally, the context mapper should be injected.
Doc comment needed.
Doc comment.
Ditto for the rest of these methods.
All the methods of this interface are missing descriptions of what they do. Kind of a big problem for an interface :)
Comment #36
eclipsegc commentedOk, this patch fleshes out the layout settings/region remapping significantly and makes them actually work. Need to get the test coverage for that back and operational.
Interesting points:
Pretty much all layout plugins extend from LayoutBase which implements ConfigurablePluginInterface and PluginFormInterface. This makes it really hard to tell which layouts are actually configurable, so you will actually find some reflection in the determination of what steps we provide. This is the only way to reliably allow layout settings to be available as their own step. I think we can probably bikeshed whether it should be its own step, but it was the most effective way of supporting custom layout regions which are configurable imo.
The region remapping works and even has some validation, but for some reason when the page loads for the first time, regions which DO map to an existing region (by exact name match) don't appear there. I was unable to figure out why.
Overall, this should be nailing down the functionality we want/need and now we just need to make sure we like the format. I'm not yet convinced that I do. Remapping, in particular should perhaps happen in a dedicated modal or something and the wizard steps don't autoforward through the layout process on change, which feels like a bug (though it's intention in PM edit scenarios so we need to figure out what we want).
I'm pretty happy with how this is coming along, all the discrete parts are present, now lets test them and get them organized properly.
Eclipse
Comment #37
phenaproximaWhat happens if the new layout has a region called 'unassigned'? (Unlikely, but possible). Maybe this should be something like __unassigned__ or similar, to decrease the possibility of a collision.
Why are we doing substr() here? I'm guessing there's a damn good reason, but it needs a comment to explain.
This is repeated a few times in this method. Can it be split off into a private utility method?
It seems to me that rather than check if the method is not in LayoutBase, we should be checking to see if it's in the plugin class. Unless I'm missing something, that seems like the more certain way to be sure that the plugin is actively implementing buildConfigurationForm().
Comment #38
phenaproximaTook care of the minor low-hanging problems in the patch.
Comment #39
eclipsegc commentedOk, updated the route requirements to allow each wizard that uses these steps to inject its own access criteria.
Eclipse
Comment #40
eclipsegc commentedThis patch addresses comments in 37 and 35. It's not been manually tested but any failures here should be minor oversights which I will fix next.
37.1: Yep ok. It's unlikely to be a problem, but now it's REALLY unlikely.
37.2: Yeah that could use a comment.
37.3: I'm currently preventing this step from showing up unless the layout is actually implementing or extending from a class which overrode the PluginFormInterface::buildConfigurationForm() method. This prevents LayoutBase::buildConfigurationForm() from giving us a false positive for this layout being configurable and providing a form. However, unfortunately, "configurability" and providing a form element are actually two completely separate things with separate interfaces. Yes this logic is identical, and I can probably abstract it into a protected method. I have taken a stab at doing that, but the better thing to do is to fix our abstract layout base class so that it doesn't needlessly implement these methods. To that end, I've filed an issue: #2749375: LayoutBase incorrectly implements PluginFormInterface and ConfigurablePluginInterface
37.4: I disagree. One could certainly imagine a group of subclasses whose parent provides a relevant method for this behavior. What we know for certain is that LayoutBase does not, and any class directly using that method is not providing a form. This is why we should really get the house in order on this topic (i.e. the issue I filed for 37.3) because then we'd know for certain. Right now I'm just taking the best guess that I'm most comfortable with.
35.1: Yup, done
35.2: Yup, done
35.3: You already took care of this. (Yay phenaproxima)
35.4: You already took care of this too. (Yay phenaproxima)
35.5: And this (Yay phenaproxima)
35.6: This too (Yay phenaproxima)
35.7: yup (Yay phenaproxima)
35.8: yup (Yay phenaproxima)
35.9: yup (Yay phenaproxima) (And I fixed a deprecated function call we had right there too).
35.10: Yeah, should have done the comparison to the form element for sure, let's see how this works out. Not sure why I'm casting that to a string and them comparing it to an object... but hey it worked (yay D8).
35.11: yup (Yay phenaproxima)
35.12: yup (Yay phenaproxima)
35.13: So I had to read this a few times before I decided I agree with you. In isolation I'd rather use the getter or as we discussed in chat assign a variable based on the result of the getter, but since this method is also assigning the value of the property, I have fewer issues using the property directly. so again phenaproxima++.
35.14: yup (Yay phenaproxima)
35.15: yup (Yay phenaproxima)
35.16: yup (Yay phenaproxima)
35.17: yup (Yay phenaproxima)
35.18: Done
35.19: Done
35.20: Seems sensible however, our other get/set methods that I copied here don't do that and we should probably update all of those methods at the same time. I say we do this in a follow up.
35.21: Done
35.22: Done
35.23: Done
35.24: Done
35.25: Done
35.26: Done
35.27: Done
Comment #41
eclipsegc commentedOk, I added some missing docs, various clarifications and class docs. Fixed tests and a little bit of code that was preventing those from working.
Eclipse
Comment #42
eclipsegc commentedRestoring layout settings test coverage. I think we're at "needs review". Tests should pass against a local checkout that includes head of CTools and head of PageManager.
Eclipse
Comment #44
hkirsman commentedI can say that the last patch still fixes Page Manager :) . Without it I can't add any blocks to Panel pages.
Comment #45
japerrySo I did a UI review of this patch. In general, getting there! I think many of the UI bugs I found are not actually related to the wizard, but just in case I'll post them here.. and if there are better issues already made for these or if we need to make them, then thats pretty straightforward as well.
1) Tests are sorta working. I managed to get through all of them before getting an error at the very end "Call to a member function getUsername() on a non-object in docroot/core/modules/simpletest/src/WebTestBase.php" but I think this might be environment related.
2) Adding a variant. The label in D8 is confusing, and probably should be hidden by default. If someone wants to change it later, they can. Also did we resolve the conflicting namespaces? Multiple variants should be able to be called 'Panels'

3) The builder step for configuring a variant is a bit confusing for regular builders. It also doesn't show IPE for some reason.

4) Editor vs Standard vs IPE show the content pane. When using the standard button and flipping to editor, it erases the page title.

5) Block dialog box is now abnormally large. Not sure if thats a bug in ctools block or something wizards introduced?

6) Placing blocks with IPE can fail due missing contexts


We've had this issue before, but I thought we fixed it in the IPE. However, just selecting the 'authored by' pane should not have thrown this error.
Some of these issues are blockers to the next release of panels, but might not be a blocker per-se to getting the wizards patch in. The sooner it is in, the sooner we can start resolving the issues it may or may not have caused ;)
Comment #46
dsnopekThanks for the reviewing, @japerry!
Just wanted to add my 2 cents on this last point...
Now that Panels is -beta, I really think we should resolve any regressions before merging this patch. It's also a lot easier to find regressions in a single patch, rather than if we end up spreading this across several commits.
For this reason, I think we should aggressively punt anything that isn't a regression or new functionality in this patch to follow-up issues. :-)
Comment #47
japerryHaha words, they don't come easy ;) But yup, I'm right there with ya.
I want to aim for no new regressions from the wizards patch, but make sure we split what is a regression caused by wizards (either in compatibility, other modules being broken, etc), and regressions that wizard api highlights. The latter of these should be punted to their own issue(s).
Comment #48
eclipsegc commentedOk, I'm sorry it took so long to respond to this, somehow I missed the review. My bad.
1.) Tests are reliably working for me and I have no current failures.
2.) Jakob and I went through this all together. I've pushed new code to PageManager (since this variant adding this is a feature of PM not panels nor its integration with PM) that fixes this whole label thing for variants. They are no longer required, they will be set to the administrative label of the selected variant if submitted empty and they are not disabled once they have a value, so they can be updated later. The default variant will be the alphabetically "lowest" variant, which is http status code. This is a change from D7, but I'm not sure how we'd determine which should be the default. I mean Panels... sure, but maybe this is a topic for core?
3.) Editor should likely be removed. It does nothing of note and is kinda confusing. IPE wasn't showing up because of it's requirement for panels storage on the PanelsDisplayVariant. The interdiff shows my fix for this.
4.) Jakob and I decided to ignore this since Editor should go away.
5.) Could not reproduce.
6.) Looks like an IPE bug to me unrelated to the wizard work. Since we're not touching anything on the front end, I would expect this to be a problem in HEAD. I did investigate this a bit and found nothing to debunk my basic assumptions here.
The short of this is that I think I've squared away the issues that were problems in this patch as well as an issue in PM. Anything else?
Eclipse
Comment #50
japerryTests did pass, and after review with Kris in #48 I think we're good.
Committed.
Comment #51
eclipsegc commentedFollowup issues: #2757331: Do we need EditorDisplayBuilder ? #2759463: Panels IPE Loses Route Parameter Contexts