Problem/Motivation
The Outside In prototype introduced in #2753941: [Experimental] Create Outside In module MVP to provide block configuration in Off-Canvas tray and expand site edit mode allows a user to configure page elements in context. Something very frustating happens when trying to edit the page title.


This is partly an existing usability issue with the page title block (the title and display title make no sense for that block), but it's made much worse with the introduction of a module that lets me click on those words and get a sidebar to do everything but change those words. There are several problems:
- The "Display title" checkbox makes no sense for this block.
- The "Display title" checkbox does not display the thing in the title box for this block.
- The contents of the title box are ignored.
- When I click on this, I don't actually want to configure this block at all. I want to edit the node title!
Proposed resolution
Since the nothing you can do to the page title block will actually have any visible effect it should be not get the "Quick Edit" contextual link provided by this module.
- Add new function _outside_in_is_block_editable() that will be called to determine if a block should exclude from getting the Quick Edit link. This sets the Main Content(which was already excluded) and Page Title block.
- Set an attribute data-outside-in-exclude on blocks should not include a Quick Edit link which will remove the link via Javascript. (It is very complicated to remove contextual links on the server side see @Wim Leers' comment in #12)
Remaining tasks
None
User interface changes
No "Quick Edit" contextual link for the Page Title block.
User doesn't get access of the Off-canvas form for the Page Title block which would have no effect anyways.
API changes
None
Data model changes
None
| Comment | File | Size | Author |
|---|---|---|---|
| #103 | 2782891-outsidein-103.patch | 24.7 KB | tim.plunkett |
| #103 | 2782891-outsidein-103-interdiff.txt | 9.94 KB | tim.plunkett |
| #98 | 2782891-98.patch | 23.79 KB | tedbow |
| #98 | interdiff-97-98.txt | 1.13 KB | tedbow |
| #97 | 2782891-outsidein-97.patch | 24.92 KB | tim.plunkett |
Comments
Comment #2
xjmComment #3
xjmComment #4
tedbowComment #5
tkoleary commentedTaking another look at this in the current state of the module I think I have a simple solution. The user who wants to edit the title should have a contextual lin k from the page title block "edit title".
We have another issue to change the 'quick edit' on the block to 'open settings tray' so that would give us three links in the page title block dropdown:
Configure block will go to the backend form, Open settings tray will show the settings for the block in-place (in this case the block title name which is still confusing...), and edit title should trigger quick edit mode with focus on the title field.
This removes the most annoying WTF of this experience which is that I need to go to the third contextual link down to edit the title of the node. 'Configure block' and 'Open settings tray' are still not crystal clear but at least with the third option the user can do some trial and error and get to where they need to be.
Comment #6
tkoleary commentedComment #7
tedbowI think once #2782915: Standardize the behavior of links when Outside In editing mode is enabled lands(hopefully soon) this problem will be easier with better UX.
With that issue in "Edit Mode" if you click an area that is covered by QuickEdit then you the quick edit toolbar will be invoked.
We could extend this functionality to the Title block if it for a QuickEdit entity. The title in this block has the attribute data-quickedit-field-id if it is for a QuickEdit entity.
Then I think we should remove the Settings Tray functionality altogether for this block. It is a form without any real functionality. It has 2 elements. A checkbox for "Display title" that in all other blocks shows the title of the block. If you click it shows the page title twice. The textfield has even less functionality. It literally has no functionality. It updates the title of the block but because the way the checkbox behaves the textfield changes will never show on the site.
You would still be able to get the advanced block form where you could delete the block or changes its region if needed.
Comment #8
tedbowThought a little more about it and no reason to wait for #2782915: Standardize the behavior of links when Outside In editing mode is enabled
Removing the page title block from the "Edit mode" makes sense regardless. Adding the trigger for QuickEdit could be a follow up issue.
This page remove the page title block from the Setting Tray module functionality.
Comment #9
tedbowSetting needs review.
Also couple question about my patch
I could find a better to flag that the block should not have the contextual link. In hook_contextual_links_view_alter we don't have plugin_id any more. We could check from the block id = "*_page_title" but that seems hacky and nothing would stop someone from using that block id pattern for another block.
Wasn't sure if this belonged in the interface but fits the description "Provides an interface for managing information related to Outside-In."
Comment #10
tkoleary commentedTested in simplytest.me. Passes usability review.
Comment #12
wim leersThis needs some documentation. I needed to re-read this 5 times to figure out what's going on.
The second hunk sets a "fake" bit of contextual link metadata.
The first hunk detects the presence of that, and if so, unsets a particular contextual link.
Nit:
$readonly_blocksprobably makes more sense?Let's make this strict (
in_array(…, …, TRUE)Nit: comment does not match function name.
Nit: s/id/ID/
Incomplete sentence.
The reason this is so surprisingly complex: the Contextual Links API was never designed for conditional contextual links. The Quick Edit module generates contextual links in JS (on the client side), so it can do this conditionally quite easily. This patch opts to do it on the server side. Hence it's fairly convoluted.
The approach in this patch can work. I think it's okay… but I can't help but wonder whether it wouldn't be a whole lot simpler to do this on the client side instead, much like Quick Edit.
Comment #13
tedbow@Wim Leers thanks for the review.
Yes I think you right it is complicated to do the removal on the server side.
This patch just sets an attribute if the link should be removed. Then the actual removal is done via Javascript.
From the review
1. Mostly removed now. I add @see comment to point the .js file and to the the module file. Hopefully clearer what is going on.
2. I like "non_editable" because it directly says what the user is restricted by.
3. fixed
4. fixed
5. fixed
Comment #14
wim leerss/client-side/client side/
Are you sure you want to add a block-specific method to the interface? Outside-In is not restricted to blocks AFAIK?
Related: I'd strongly recommend doing what BigPipe did here too: #2835604: BigPipe provides functionality, not an API: mark all classes & interfaces @internal + #2835758: Remove BigPipeInterface and move all of its docs to the implementation.
Comment #15
tedbowre #14
1. fixed
2. Removed this from the interface and moved to a function in the module file.
On the related note I think that makes sense and will make follow up issues.
Comment #16
tedbowOk adding test for the contextual link for the title block being excluded.
Also attaching a TEST_ONLY patch.
Comment #18
wim leersShouldn't we also test the
system_main_blockblock?Other than that, RTBC.
Comment #19
tedbow@Wim Leers thanks for the review!
Yes we should check the content block also. I also realized that not only should we be checking for the contextual link being excluded we should also make sure that the data-drupal-outsidein attribute is not added which would mark the the block as "editable".
Comment #20
wim leersWell, that's just the fallback behavior in
\Drupal\block\Plugin\DisplayVariant\BlockPageVariant::build(). In that case, it's not even an actual block.So I'm not sure that this patch is correct. I think we should place the block. And we should have a separate test ensuring that you also don't get outside in functionality in case no "main content" block is placed.
Comment #21
tedbowOk now placing both the blocks that should be excluded in the same way.
I am not sure we need this \Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest::testBlocks tests Settings Tray edit mode functionality with explicitly placing the main content block.
Comment #22
tedbowNeeds re-roll because of #2862625: Rename offcanvas to two words in code and comments. and other recent commits
Comment #23
rajeevkRe-rolling patch for test & review after rebase.
Comment #24
tedbow@RajeevK reroll looks great, Thanks!!!
Leaving as needs review because changes in #21(rerolled in #23 still need be reviewed.
Comment #25
wim leersPerhaps add an explicit
@internal?Comment #27
tedbowRe-rolled #23 plus Wims' idea in #25
Comment #28
wim leersComment #30
tedbowNeed a re-roll. No changes.
Comment #32
tedbowOk although the patch in #27 applied cleaning there were 3 problems.
Comment #33
tedbowOk so messed the interdiff on #32.
Here is the correct interdiff between #30 and #32.
You can see it has the 3 changes I described in #32
Comment #34
wim leersThat all made sense. I was confused by the
*.jsvs*.es6.jschanges at first, but they actually make sense :)Comment #35
tedbowJust re-roll after #2882729: In off-canvas block form hide Title input unless it will be displayed and change label to Block Title
Comment #36
tedbowComment #37
tedbowComment #38
webchickThanks for the issue summary updates!
Talked about this some with @tedbow. Both @xjm and I felt a bit ooky about committing a new underscore-prefixed function for this. @tedbow explained that the reason this is wrapped in a function is to avoid inlining the same array twice. Makes sense. Another option which @tedbow thought of was, rather than _outside_in_is_block_editable(), add a method to OutsideInManagerInterface isBlockExcluded() because the phpDoc for the interface says “Provides an interface for managing information related to Outside-In.” which presumably would cover this. Marking needs work for that change.
This also addresses another my concerns which was "if contrib defines a block that wants to opt-out as well for whatever reason, what do they do?" Bearing in mind that we want to avoid making an explicit API, per #2894584: Settings Tray provides functionality, not an API: mark PHP and JS as internal.
Comment #39
xjmEdit: Wrong issue, too many tabs, etc.
Comment #40
tedbowI have created \Drupal\outside_in\OutsideInManagerInterface::isBlockEditable() and _outside_in_is_block_editable()
isBlockEditable is actually the exact same code that was in the earlier patch up till #13 and was reviewed by @Wim Leers
I removed in for the _outside_in_is_block_editable() in #15 because of his comment in #14.2
Now after working with the Settings Tray module more and it almost stable I realize it's Edit only deals with Editing Block forms(plus other config added the form). So these seems like a good place for it.
The dialog tray itself could be used by other modules but Settings Tray Edit mode is always triggered through block contextual links and shows the Off-Canvas form for block plugin.
Comment #41
wim leersI don't understand how this is an explicit API as described in #38.
This is
Why not instead make this something that can be specified in the
@Blockannotation? That'd make for an elegant solution: ifoutside_in_block_alter()would be altering the annotation of every block plugin rather than the two it's currently modifying, and would then skip these two, then there would be nothing special anymore, and no need for an extra API.So instead of:
do this:
EDIT: this would probably even mean that you can remove all the JS changes in this patch.
Comment #42
pk188 commentedI have updated the "outside_in_block_alter" function as mentioned in #41.
@Wim Leers, please update me about initial part of #41. We should remove these changes or you are saying something else?
Comment #44
xjmAll of these changes would need to be removed from the patch for Wim's approach.
This comment doesn't need to be removed.
However, it looks like the test is failing; at first I assumed it was because the patch in #42 is incomplete, but on reading the test I couldn't say for sure that any of the now-dead code was causing the problem.
Comment #45
xjmOn #44, not actually sure on the contextual links changes. Maybe that's what's failing? But the goal of the approach is to remove the need for the API additions.
Comment #46
xjmAh here we go; this is the issue:
seText: The website encountered an unexpected error. Please try again later.Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException: The "system_powered_by_block" plugin did not specify a valid "off_canvas" form class, must implement \Drupal\Core\Plugin\PluginFormInterface in Drupal\Core\Plugin\PluginFormFactory->createInstance() (line 57 of core/lib/Drupal/Core/Plugin/PluginFormFactory.php).@Wim Leers' proposal was sort of pseudocode; maybe there is a small bug in the alter hook?
Comment #47
wim leersIndeed it was.
I'll review this once @tedbow rerolls this.
Comment #48
tedbowAfter some investigation I don't think the approach in #41 will work.
The default off_canvas form handler class is actually set in outside_in_entity_type_build() not outside_in_block_alter()
Settings it in outside_in_entity_type_build() is similar to setting in the annotation of core/modules/block/src/Entity/Block.php
Presumably we could remove it from outside_in_entity_type_build() and only set it per definition in outside_in_block_alter() but then we no longer would have a default off_canvas form handler for Block entity.
So if removed it from outside_in_entity_type_build() but had it only outside_in_block_alter() setting it for all blocks except the 2 we want to exclude then we would have no information on the form Entity type level for the block off_canvas form handler.
So this would affect:
\Drupal\Core\Entity\EntityTypeInterface::getFormClass()
\Drupal\Core\Entity\EntityTypeInterface::getHandlerClasses()
I have tried removing the logic in outside_in_entity_type_build() you get this error(in the logs) when trying to open block quick edit form
From \Drupal\Core\Entity\EntityTypeManager::getFormObject().
Comment #49
tedbowOk. here is patch that adds
$definition['outside_in_exclude'] = TRUE;To the block plugin definitions that should be excluded.
it adds a api.php file to document how to do this on other blocks and a \Drupal\outside_in_test\Plugin\Block\ExcludedTestBlock which tests that this works.
Then every things is driven by this. It does add a new "_foo" function to the .module file but this is just to avoid duplicate logic.
Comment #50
wim leersDon't ever press option+command+W. It caused me to lose hours worth of time spent on a comment I'd been writing here. Hours. And if there's one thing I hate, it's repeating work. I got pretty close to kicking my computer.
#48: yep, I understand it now.
class BlockEntityOffCanvasForm extends BlockForm, so it's an alternative for the default block form.SystemBrandingOffCanvasFormandSystemMenuOffCanvasFormare "plugin forms".BlockFormdisplays the "default" or built-in form of a block plugin.BlockEntityOffCanvasFormdisplays the "off canvas" form if it exists, and only those two exist.#49: My key concern still stands: we're doing work to then later undo it again. It's a step in the right direction though. But I think it can be simpler: rather than adding yet another annotation, allow
forms = { "off_canvas" = FALSE' }.So here's what I propose.
Step 1: stop duplicating (commits 1+2+3)
outside_in_preprocess_block()in HEAD is duplicating the existing logic insystem_block_view_system_main_block_alter(), and it's forgetting about doing the same for the Help block (becausehelp_block_view_help_block_alter()).They both do
unset($build['#contextual_links']);.So, just like #2784853: Determine when Outside In library should be loaded: piggyback on contextual_toolbar() piggybacked on what the Contextual Links module is already doing, I'm proposing to do the same here. Which means relying on the fact that the Contextual Links module adds the
.contextual-regionclass. So rather than depending on the selector[data-drupal-outsidein="editable"](in most of Settings Tray's JS) and.outside-in-editable(in all of Settings Tray's CSS), we rely on that too.Commit 1 fixes the PHP, commit 2 updates the JS selectors, commit 3 updates the CSS selectors.
P.S.: there's no reason for the
.outside-in-editableclass — it should either all use the data- attribute, or the class, we shouldn't be adding both. And in fact, we shouldn't be adding either one.Step 2: conditional contextual links (commit 4)
The reason we're doing all this, is because Settings Tray has a need for conditional contextual links. Rather than reinventing how that is supposed to work (which is what Settings Tray is doing today), it can just rely on the already established mechanisms, either:
*.links.contextual.ymlfile — seecore/modules/quickedit/js/views/ContextualLinkView.es6.jsentity.block.off_canvas_formroute for the contextual link would mean the contextual link would be inaccessible when appropriateSince Settings Tray is already defining a contextual links in
outside_in.links.contextual.yml, I'm going with the server-side approach. Proof that this works can be found in the tests at\Drupal\Tests\contextual\FunctionalJavascript\ContextualLinksTestand
\Drupal\Tests\Core\Menu\ContextualLinkManagerTest::testGetContextualLinksArrayByGroupAccessCheck().Includes test coverage.
Step 3: marking
page_title_blockto not have an 'off_canvas' form (commit 5)This builds upon the cleaned up infrastructure to solve what this issue is actually about very simply/elegantly.
Doesn't need extra test coverage because relies on Contextual Links module infrastructure (see previous step).
Step 4: setting the
.outside-in-editableclass in JS (NOT YET DONE)Right now we're unconditionally setting this class, which means that the Page Title block still is clickable. We need to have Outside In's JS add this class to the closest
.contextual-regionDOM node if theoutside_in.block_configurelink is present.Conclusion
End result:
forms[off_canvas]in a Block plugin annotationI think this is the least confusing API, and also the smallest possible API.
In case it helps, these are my notes to capture the high-level reasoning:
Comment #51
tedbowComment #52
tedbowWhoops submitted before I commented.
@Wim Leers yes I like the idea of throwing a 403 and then the Contextual link not being produced at all.
This all looks very good!
I thought we tried to drive CSS off classes and JS functionality off data attributes.
So a theme could still alter the class names and the JS functionality would still work. Like maybe they already have general
highlighted-areathe would rather use instead but the JS functionality would still work because it all based of data attributes(except Contextual module CSS classes because it is not using data attributes)We already changed to using this method in previous issues.
RE
Couldn't we just do this by not adding the class in the first place by checking if plugin doesn't have an 'off_canvas' form?
Seems much simplier than relying on inspecting the DOM in JS.
Reading https://www.drupal.org/core/d8-bc-policy it seems doing it on the server side and not relying on DOM or CSS classes at all is more future proof.
Uploading a patch for this.
Comment #53
wim leersIn the terse, re-typed version of #50, I failed to mention again that the 403 idea was in fact proposed by @tedbow in a call we had yesterday about this issue :)
Comment #54
wim leersWell,
contextual_preprocess()sets.contextual-region. It's a class that's "functional" and not "aestethic". Themes don't modify this class. So you can choose either a class or a data- attribute. The latter is perhaps the more "modern" approach, but there's no clear standards for this. Whichever you prefer :)But then we're still duplicating other logic. We're doing the same calculations in two places. In one case, to generate the contextual links (= markup), and then in this case to determine whether to set a certain class (= markup).
It's better to derive additional markup from existing markup. Besides, if we'd …………………………
Well, now that you mention that: there's another issue we need to open for Settings Tray: it's doing its JS magic to transform the existing Edit button + toolbar always, even on pages where
Drupal.contextual.collectionis empty, i.e. on pages where there are zero contextual links.Why/where? https://www.drupal.org/core/d8-bc-policy#themes is referring to themes, and CSS for themes. It's not referring to attributes. Besides, #2894584: Settings Tray provides functionality, not an API: mark PHP and JS as internal is explicitly marking everything as internal. The end goal (which this issue helps to achieve) is that there is only one single API:
forms = { "off_canvas" = "FQCN" }on block plugin annotations!Comment #55
tedbowThe interdiff I uploaded for 51 was wrong
Comment #56
wim leersI like how #51/#55 is a pragmatic solution that minimizes change, yet still helps settle on the
forms[off_canvas]annotation as the single source of truth.Improving this further can totally be done in a follow-up. OTOH, it means that we still are duplicating logic. #51/#55 duplicates in
outside_in_preprocess_block()what\Drupal\outside_in\Access\BlockPluginHasOffCanvasFormAccessCheckdoes. And for a not-so-clear reason.Ted mentioned in chat:
But Settings Tray's JS is already waiting for Contextual Links JS. To which Ted responded:
While not yet proven, that is a clear reason. D8's Toolbar definitely suffered from this problem until very recently: #2542050: Toolbar implementation creates super annoying re-rendering..
But if we make the change that #51/#55 makes, it's overriding commit 1 from #50, which means we can also revert commits 2 and 3. So the entire "step 1: stop duplicating" from #50 is then undone. I think that's fine though: this patch then becomes smaller, its scope becomes tighter, and this patch can then add documentation as to why it's being done this way. It's an implementation detail anyway — it can be improved later!So, embracing #51/#55, reverting commits 1+2+3 from #50.D'oh, that doesn't work either, because that means the
system_block_view_system_main_block_alter()+help_block_view_help_block_alter()hooks aren't respected! I forgot about that for a moment. Which means that for example the main content block shows up as a Settings Tray-clickable region :(So… let's not do that. The
.contextual-regionclass that was added to the selectors in commits 2+3 is set on the server side anyway (bycontextual_preprocess()), so that can't cause flicker. The only thing that can cause flicker, is setting.outside-in-editableand[data-drupal-outsidein]in JS, because that'd have to wait on Contextual Links' JS.Which means that all that remains to be done here, is adding documentation to
outside_in_preprocess_block(), to document why it's done here on the server side.Comment #57
wim leersI'm comfortable with this patch being committed. But I can't RTBC this, I did most of the work. I think @tedbow should be the one to RTBC this eventually.
I did spot one mistake in the ES6 vs ES5 JS file.
yarn run watch:jsis kinda brittle sadly:This is how the ES6 vs ES5 files got out of sync.
Comment #58
tedbowThanks for the detailed comment here.
Create the follow up issue #2896356: Move 'settings_tray' forms out of Settings Tray and into respective modules and annotations we now need to update the todo
Should we have @todo and an issue to move this to the PageTitleBlock annotation?
This test function was removed. Should we add it and the corresponding test module back in. We don't have functional test that proves you can exclude block though we are adding that functionality.
If we did add it back we would need to change this to
Or something like that. Otherwise the test should still pass I think
Comment #59
tim.plunkettNow that I look again, there's even more robust fallback code in \Drupal\Core\Plugin\PluginFormFactory::createInstance(). These two different has FormClass checks are different, and that is odd. Not the fault of this code though...
This is an interesting change from HEAD.
\Drupal\Core\Plugin\PluginWithFormsTrait::getFormClass() already provides it's own fallback mechanism, and in HEAD that is relied upon. This changes it so that we explicitly declare the "configure" form as used by "off_canvas" operation.
This isn't bad, but possibly slightly confusing.
That said, the entire concept of multiple plugin forms was added to core to support off_canvas.
Comment #60
wim leers#58:
2. Thanks! Will update.
3. Great point, will do.
4+5: yep, we should, and will do.
#59.2: Yep, I am proposing this change because rather than relying on run-time logic that might change, I think it's clearer to rely on metadata (declarative) instead. Are you +1, or do you have doubts about that?
Comment #61
tim.plunkett+1, but can you open a follow-up to discuss the differences and a way to resolve them? As the only implementation of this, we need to be clear about how others should use multiple forms
Comment #62
wim leers#58: All done. Brought over test coverage & API docs from #49, and adjusted it quite a bit, which makes you still eligible for review/RTBC. Also added test blocks for the other two possible kinds of annotations. Big interdiff because big test coverage expansion.
Comment #64
wim leersFixed nits. Should also cause the patch to pass tests again.
Comment #65
wim leers#61: Done: #2896952: Discuss/resolve/document differences in fallback handling between PluginWithFormsTrait::getFormClass() and outside_in_toolbar_alter(). I hope that is a good title + issue summary.
Comment #66
tedbowNot sure if we should include such extensive description of the module in this patch or add this a follow. I agree it is good idea to include the parts in the this patch that affect the excluding of the blocks.
For instances there are other things besides the visibility conditions that aren't shown.
The tailored experience at least in the 2 forms that are provided by this module is not about "limits the form" but actually adding relevant config to the form.
This 2 lines do the same check. We could add back a service(without an interface this time)
With
Then of course we would want to rename
BlockPluginHasOffCanvasFormAccessChecktoBlockPluginSupportSettingsTrayAccessCheckActually since BlockPluginHasOffCanvasFormAccessCheck is already a service could we just call it in outside_in_preprocess_block directly?
I know it implements AccessInterface but is there any reason we can't add another public function, isSettingsTraySupportedBlockPlugin, that checks access also but with plugin id or BlockPluginInterface instead of a BlockInterface. Especially considering #2266817: Deprecate empty AccessInterface and remove usages
'button_text' here can be set to NULL for each of these. $button_text in
testBlocks()is only used if'new_page_text'is specified.Actually 'label_selector' should also be set to NULL. Neither of these tests case will save the form and check for updates on the page after the form is saved.
(I realize this is actually true for 'block-search' test case but that is out of scope for this issue)
Comment #67
wim leers#66:
Comment #69
tedbowYou do actually have to have a callable "access" method @see \Drupal\Core\Access\CheckProvider::loadCheck
the errors for this test
So I am not sure if we leave "access" the way it was and still add accessBlockPlugin(). that would work
Comment #70
wim leersI implemented #66.3 incorrectly anyway: I forgot to update
outside_in_preprocess_block()!Regarding #69: #2266817: Deprecate empty AccessInterface and remove usages is pretty misleading then, seems that
AccessInterfacedoes have a purpose… :( Done.Comment #71
wim leersI also added this in #70, I realized that since #2894584: Settings Tray provides functionality, not an API: mark PHP and JS as internal has landed, we should mark any new classes
@internaltoo.Comment #73
wim leersRerolling…
Comment #74
wim leersComment #75
tedbowSo just looking at \Drupal\outside_in\Block\BlockEntityOffCanvasForm::getPluginForm I realized that BlockPluginInterface does not implement PluginWithFormsInterface so it is not guaranteed to have hasFormClass().
Should we check for
instanceof PluginWithFormsInterfacelike \Drupal\outside_in\Block\BlockEntityOffCanvasForm::getPluginForm does?The disallow access if it doesn't implement the interface.
Otherwise looks done!
Comment #76
wim leersInteresting point! However … it's literally impossible to implement blocks by implementing the interface, you must extend
\Drupal\Core\Block\BlockBase, which does always implement that interface. But doing what you said prepares us better for a smooth future without unpleasant surprises, so let's do it!Expanded test coverage.
Comment #78
wim leersUgh this rename should never have happened. PHPStorm--
Also fixing coding standards violations that I added in #76.
Comment #79
tedbow@Wim Leers thanks for these last changes. RTBC! 🎉
Comment #81
pk188 commentedAs #78 failed to apply.
I am submitting patch again after updating it.
Comment #82
wim leers@pk188 Thanks!
#78 failed because Settings Tray patches have been committed in the mean time (yay!).
I diffed #78 and #81. The reasons the size is different (31 vs 29 KB):
core/modules/outside_in/tests/modules/outside_in_test/outside_in_test.info.ymlhas already been added in another issue — so this patch no longer needs to add itThe patches are functionally identical. Therefore back to RTBC.
Comment #83
pk188 commentedThanks! @Wim Leers for reviewing the patch.
And yes you are right.
Comment #85
xjmUnfortunately it does not apply again. :) Probably following the CSS reset issue. Although it's odd that the patch has not been retested since?
Comment #86
pk188 commentedAs the patch was not applying.
So, I rerolled it.
Comment #87
wim leersI manually diffed #81 and #86, I can confirm it's a straight rebase, no other changes. So back to RTBC.
Comment #88
xjmLots of files in this patch are missing their trailing newline. I haven't finished reviewing the patch yet, but the newline coding standard rule is already enabled and so this needs to be fixed before commit.
Comment #89
pk188 commentedFixed according to #88.
Comment #90
xjmThanks @pk188! In the future, you can also help by providing an interdiff whenever you make patch updates so that others can easily review your changes to the patch.
Comment #91
xjmPartial review, got about halfway through the patch so far... marking NW so someone could fix these things while I continue to review (or in case I don't get back to it today).
Nit: Every block will show its built-in form.
This phrase is difficult to understand. I think it means:
"Limits the form items displayed in the Settings Tray to only items that affect the content of the rendered block, or..."
For both this item and the one before it, an example would help.
This also doesn't quite make sense to me as written. It doesn't always allow the user to change what is rendered by the block (and it won't always necessarily result in better experience, either). Maybe: "These can be used to provide a better experience, so that the Settings Tray only displays what the user will expect to change when editing the block." Is that accurate?
Perhaps it would be useful to add "in their plugin annotation" here? Otherwise it's not necessarily obvious where a developer should put this code snippet.
Nit: Missing serial comma between "main content" and "help".
"off-canvas forms"in quotes is weird. Maybe: "blocks that do not specify an off-canvas form using the annotations above will automatically...".When does it get added?
This switches it from hardcoding one special-flower block to providing an API. I like that!
"...that would mean..." (if it's contrary to what actually happens).
Also why would it mean that?
For now, until what? Is there a followup issue? If not "For now" is probably not helpful as it just adds more words to read.
This comment seems unnecessary unless there is a followup issue we want to reference
Some notes about how I reviewed it: I used
git diff --color-words="[^[:space:],\.\[\[\']+" --stagedto understand the CSS and JS changes since I don't speak those so well. :P
.outside-in-editablewith the more specific.contextual-region.outside-in-editable[data-drupal-outsidein="editable"]with.contextual-region[data-drupal-outsidein="editable"]Comment #92
xjmOkay finished my code review. Mostly just small documentation issues like above.
I'm wondering whether
off_canvasis the correct name for this. It doesn't have anything directly to do with the offcanvas renderer; it has to do with the Settings Tray module. No?In the examples given, the block's content can be modified modules, or on different forms. So maybe:
Oh, and which logic is duplicated?
I think there's something to do, just that it's not being done here. ;) "If a block plugin already defines its own off_canvas form, use that form instead of specifying one here."
So this comment does not describe what's actually happening (I think maybe it did in an earlier version of the patch before we added the new API). Rather, maybe:
Then the @todo after that makes sense as well.
I was about to ask if we would move this logic into each module once Settings Tray is stable, and indeed based on this comment and #2896356: Move 'settings_tray' forms out of Settings Tray and into respective modules and annotations the answer is "Yes!". :)
However, this comment is formatted incorrectly; it does not begin with a capital letter and does not wrap at 80 chars. After it's wrapped, the second line should also be indented two spaces form the
//similarly to https://www.drupal.org/node/1354#todo."Built-in" confused me here.
We should add the link for the relevant followup issue here. So far #2896356: Move 'settings_tray' forms out of Settings Tray and into respective modules and annotations doesn't seem to include removing the preprocess in its scope; is it that issue or a different one? I also don't see any other issues referenced in
outside_in_preprocess_block(). Is that the same mysterious "implementation that may change in the future"? ;)Also, is this comment even in the right place? Would we be removing the whole access checker? Because right now
access()jus t wraps this.I was going to ask how the test was passing when the class name was misspelled; fortunately, it's misspelled in both places. ;) However, we probably should add the "o" to annotation to avoid future development headaches.
s/Testing/Tests/Nit: I read
&as a bitwise operator on first pass. For the low, low price of two characters, we can use the English word "and". :)Non-nit: Where is the functional coverage? I don't know that as a person reading this comment and might like to if it's worth mentioning to me at all.
Non-nit: From this sentence, it sounds like there are only two blocks that support settings tray and that they are called "class" and "none". I don't know how to parse this paragraph. Are "class" and "none" "blocks"? I don't think they are?
Is @see related to this and so the following would be true?
Okay this answered my question. :)
Excellent inline documentation!
Comment #93
ada hernandez commentedFor #91
1.done
2.done
3.pending
4.done
5.done
6.done
7.done
8.pending
9…
10.pending
11.pending
12.the comment was removed but css and js changes wasn’t done
#92
1.done
2.done
3.pending (11 by #91)
4.done
5.done
6.done
7.done
8.pending
9.done
10.done
11.nit: & done, non-nit 12 is the answer
Comment #94
tedbow#91.3 Added an example for this 1. For the 1 before this limiting the form items actually happens in BlockEntityOffCanvasForm which is not used for the block plugin form but for the block entity form. So I am not sure if the comment actually makes sense here because this is talking about the block plugin form.
8. This happens in outside_in_block_alter() added a @see link
10. Fixed comment.
This would happened because contextual links aren't actually on the page when the page loads so we would have to wait till they are to tell which blocks would need the class. Contextual links html is actually stored in the localstorage of the user's browser. When when new blocks are placed or visible for the first time(when could mean multiple blocks at once) each block must make a ajax call back to get the rendered contextual links html. When the page was already in "Edit Mode" and the page first loads then the existing blocks that had the contextual links html stored on the client side would have the class from this module applied quickly but new blocks would have to make individual ajax calls back and it could not be determined if each block should get the class until the ajax call came back.
So the existing blocks would have "editable" look at first page load but new blocks would get the "editable" look 1 at a time as ajax calls come back.
11. Removing "for now" because I don't actually think this is not the desired logic. This limitation of how Contextual links work.
12. I don't CSS and JS should change see 11
#92.1 changed the comment to say " by Settings Tray in the off-canvas dialog"
3. Removing this comment about duplicated logic. Earlier in the patch we were duplicating the logic inside BlockPluginHasOffCanvasFormAccessCheck(or what is was previously named) but now since we are actually getting the service itself we are not duplicating the logic.
7. Just changed comment to use "Settings Tray" instead of "Outside In"
8. The access checker is used in the route "entity.block.off_canvas_form" so it will not be removed.
I am removing the @todo comment about removing the code because I don't think it needs to be. @see my comment above about #91.11
Comment #95
tedbowchatted with @xjm she pointed there were out of scope change regarding the css selector
.contextual-regionRemoved
Comment #96
tedbowJust to clear for any further reviewers
I have checked @Adita's review and all the changes look unless I noted a change in #94
So together with #93 to #95 we I think have covered @xjm reviews in #91 and #92
Comment #97
tim.plunkettCan this change be removed, similar to the removal of the CSS changes?
Rewriting this test class to not need the empty implementations.
Comment #98
tedbow#97.1 Look like in #95 I removed these changes from
outside_in.jsbut notoutside_in.es6.jsversion. That was a mistake. Removing. This should effect tests because in #95 they were already removed fromoutside_in.jswhich is what is actually loaded.#97.2 look good.
Comment #99
tim.plunkettLooks great, thanks!
Comment #100
xjmJust a bunch of nits and coding standards issues. The patch looks great. The refactored test coverage is also an improvement.
Error in the list indentation here.
I can fix this on commitexcept that I found 14 other things.Also, this shouldn't actually be capitalized because it's not a complete sentence. Ditto the second bullet.
s/their/its/
I guess it's "annotation" singular.
Nit: missing period.
Nit: Capitalize the 'm' and add a period.
This line is not wrapped. Also "Used by n some cases" sounds like some kind of bargain cereal.
@see should always go at the end of the docblock. We already have this one down at the end so we can just delete these two lines. Edit: Realized I didn't highlight enough context, but it's the one that's not at the end of the docblock. :P
I almost said "Let's use the dedicated method for the access manager service" but that's
access_managerrather thanaccess_check. Note to self: read the default implementations for both services.Missing period again.
Nit: Both these comments wrap way too early.
This line is 81 chars so we will need to wrap the last word.
The logic here is a little weird and inverted, kind of a double negative. I'd have said
if $plugin_id === 'outside_in_test_false'with that condition first and then let theelsebe all other cases. Also easier to extend that way if we add other kinds of test blocks in the future. This is a total nitpick though.Nit: missing final period.
Over 80 chars and needs to be wrapped.
Also, that test method is on a totally different class, so we should refer to it with the FQCN.
Comment #101
xjmAlso is there a followup for the selector specificity change we removed? I don't see it in the comments or sidebar.
Comment #102
xjmThese also wrap too soon.
Comment #103
tim.plunkett#100
1) Done
2) Done
3) Done
4) Done
5) Done
6) Done
7) Done
8) Done
9) Skipped (not actionable?)
10) Done
11) Done
12) Done
13) Done
14) Done
15) Done
#101
Skipped
#102
Done
Comment #104
tim.plunkettAs all of those changes were to docs nits, I think I can safely RTBC this.
Comment #105
xjmThe followup is: #2903198: Use more specific CSS when attaching Settings Tray links to contextual links.
Comment #106
xjmComment #109
xjmSo looking at #100.9. In generally using the generic
\Drupal::service()method is something we want to avoid; it's more of a convenience wrapper for upgrade paths from D7. I couldn't find any other places in core that were loading an access checker service directly this way except in one test:But, I couldn't find a good example of this being done in a different way either, especially in procedural code. (Quick Edit injects its access checker in its MetadataGenerator). And there are a few examples of loading the block plugin manager this way (although mostly to only clear the block plugin definition cache). TLDR I still don't have any actionable feedback on that point. If someone can think of a cleaner way to do what we're doing with this preprocess, feel free to file an issue, but it doesn't make sense to sidetrack this since there might not be a "better way" anyway.
I noticed a few other issues in the process of testing this.
This took me some trial-and-error to figure out so it made me wonder if we should communicate that somewhere. I did confirm that Settings Tray does declare dependencies on all three corresponding modules.
I'll try to get to filing followup issues for those three things. So, anyway, un-sidetracking!
I manually tested and confirmed that this patch does what it's supposed to: the page title, help, and main system blocks do not have any Settings Trays interactions (no styling, no hover behavior, and no clickability). I was a little worried before I tested the patch that the lack of interaction around the title would be confusing, but it's not at all. If I didn't know it was a separate block because D8 skillz, it wouldn't even occur to me to try to interact with the page title.
Per @webchick's suggestion, I tested the Help block on a frontend page with the submission guidelines for a content type for a user that did not have access to the admin theme, pages, etc. and so saw the article form as a frontend page rather than a backend one. Turns out this also fixes an additional bug in HEAD where the help block incorrectly had Settings Tray styling (although not the clickability).
Committed and pushed to 8.5.x! I also backported it to 8.4.x despite the API additions since Settings Tray is still in alpha. Thanks everyone for working through the many iterations of this patch and for cleaning up the slough of small issues.
Comment #110
xjmTagging for the Settings Tray section of the release notes since this both resolves a UX issue and adds a useful new API.
Comment #111
wim leers#92.1 was not actually fixed by #93, even though it claimed it did. Nor in #94, where @tedbow wrote , but I don't see that in the actual patch. We kept using the
off_canvasname. That's fine while this module is in alpha, but we either need to explain why we keep using that name, or we need to change it, before reaching beta.(I share @xjm's concern, but didn't raise it here, because it's out of scope to change here.)
So, opened a new issue for that: #2904134: Settings Tray uses the off-canvas dialog type, but "off_canvas" is not an accurate form plugin name, "settings_tray" is.
#95's reversal ofNope, it doesn't cause a regression, because of our decision to duplicate some of the logic to avoid flicker. +1 for this change then!.contextual-regionCSS changes caused a regression and #98's related reversal in JS makes this a definite regression. See #50.Comment #112
wim leersI missed #2903198: Use more specific CSS when attaching Settings Tray links to contextual links because it wasn't added as a related issue. Fixed that.
Note that per #111, I don't think we need that follow-up at all.
Comment #113
tedbowChanging to new settings_tray.module component. @drpal thanks for script help! :)
Comment #114
xjmFor the followup issues I still didn't file.