Problem/Motivation

(original report motivation)

The default action on /admin/content is "Delete selected content". It's really easy to push "Apply" button by mistake, thinking it will apply the filter, because of the button title, and because it's positioned at the bottom of the form, typically where people expect to look for submit buttons. (This actually happened to me today, and I've been using Drupal for 8 years)

screen
Existing content operations in Drupal 8
Existing content operations in Drupal 7

Steps to reproduce

See screenshots.

Proposed resolution

MR to review !4583

Proposal:

  • Store the order of the actions in the Views Bulk Form handler configuration (actually, the View config entity)
  • Provide an upgrade path to set the order config in each Bulk Form field but preserve BC. On existing sites the order should be preserved even the "dangerous" actions are on top. Then site builders might decide to manually change that.
  • For new sites provide a default order that is safe. Specifically, the "Delete" action should be the last in the list avoiding incidents.

A little history>

Initially, adding a weight to action config entities has been tried. However, as is mentioned in #152, this is not the correct approach as an action (read a config entity) may appear on several views and the site builder may need different sort orders on each view. Read the #152 comment for more background.

Remaining tasks

None.

User interface changes

Bulk Form admin form

Before:

Selecting actions on the view-edit form

The checkboxes let you select which actions will be available, but you cannot control the order.

After:

The form element used to select the actions is converted from checkboxes to draggable table. The table allows both, actions selection and action reordering.

Views with Bulk Form

The actions are reordered for new sites on /admin/content, /admin/content/comment, /admin/content/comment/approval, /admin/content/media with the "Delete" action as last option.

Before:

Available bulk actions on /admin/content, with Delete first

After:

Available bulk actions on /admin/content, with Delete last

API changes

None.

Data model changes

New actions_order option for Bulk Form handler.

Release notes snippet

Use drag and drop in Views bulk form field configuration form to define order which will be used to expose the actions in the bulk forms.

CommentFileSizeAuthor
#236 2381293-nr-bot.txt90 bytesneeds-review-queue-bot
#231 2381293-nr-bot.txt10.49 KBneeds-review-queue-bot
#229 2381293-nr-bot.txt90 bytesneeds-review-queue-bot
#206 2381293-nr-bot.txt150 bytesneeds-review-queue-bot
#190 Screen Shot 2022-03-04 at 11.18.25 AM.png209.78 KBbenjifisher
#188 content-after.png17.73 KBDevashish Jangid
#188 content-before.png18.26 KBDevashish Jangid
#188 config-after.PNG31.25 KBDevashish Jangid
#188 config-before.PNG34.17 KBDevashish Jangid
#187 content-action-after.png21.08 KBbenjifisher
#187 content-actions-before.png18.58 KBbenjifisher
#187 selected-actions-before.png68.88 KBbenjifisher
#186 2381293-186.patch30 KBclaudiu.cristea
#186 2381293-186.interdiff.txt1.53 KBclaudiu.cristea
#183 D7-bulk-with-options.jpg23.8 KBidimopoulos
#181 2381293-181.patch30.01 KBclaudiu.cristea
#181 2381293-181.interdiff.txt2.83 KBclaudiu.cristea
#178 2381293-178.patch27.99 KBclaudiu.cristea
#178 2381293-178.interdiff.txt13.71 KBclaudiu.cristea
#177 action-order3.png82.1 KBclaudiu.cristea
#177 2381293-177.patch37.91 KBclaudiu.cristea
#177 2381293-177.interdiff.txt1.88 KBclaudiu.cristea
#175 2381293-174.interdiff.txt709 bytesclaudiu.cristea
#175 2381293-174.patch36.94 KBclaudiu.cristea
#173 action-order2.png100.44 KBclaudiu.cristea
#173 2381293-173.patch37.35 KBclaudiu.cristea
#173 2381293-173.interdiff.txt6.03 KBclaudiu.cristea
#170 2381293-170.patch36.85 KBclaudiu.cristea
#170 2381293-170.interdiff.txt1.37 KBclaudiu.cristea
#169 2381293-168.patch35.48 KBclaudiu.cristea
#169 2381293-168.interdiff.txt2.56 KBclaudiu.cristea
#166 actions-order.png112.24 KBclaudiu.cristea
#165 2381293-165.patch34.86 KBclaudiu.cristea
#165 2381293-165.interdiff.txt10.36 KBclaudiu.cristea
#164 2381293-164.patch27.2 KBclaudiu.cristea
#164 2381293-164.interdiff.txt3.51 KBclaudiu.cristea
#163 interdiff-2381293-162_163.txt673 bytesGauravvvv
#163 2381293-163.patch25.75 KBGauravvvv
#162 2381293-162.interdiff.txt3.94 KBclaudiu.cristea
#162 2381293-162.patch25.79 KBclaudiu.cristea
#161 2381293-161.patch23.98 KBclaudiu.cristea
#161 2381293-161.interdiff.txt6.45 KBclaudiu.cristea
#160 2381293-160.patch17.81 KBclaudiu.cristea
#160 2381293-160.interdiff.txt838 bytesclaudiu.cristea
#157 2381293-157.patch17.84 KBclaudiu.cristea
#157 2381293-157.interdiff.txt888 bytesclaudiu.cristea
#156 2381293-156.patch16.97 KBclaudiu.cristea
#156 2381293-156.interdiff.txt4.87 KBclaudiu.cristea
#153 2381293-153.patch13.79 KBclaudiu.cristea
#134 2381293-134.patch92.17 KBclaudiu.cristea
#130 interdiff_128.txt1.63 KBidimopoulos
#130 2381293_D8_130.patch73.25 KBidimopoulos
#128 interdiff_121.txt941 bytesidimopoulos
#128 2381293_D8_128.patch73.03 KBidimopoulos
#121 interdiff_118.txt2.83 KBidimopoulos
#121 2381293_D8_121.patch73.25 KBidimopoulos
#118 interdiff_117.txt3.21 KBidimopoulos
#118 2381293_D8_118.patch72.05 KBidimopoulos
#117 2381293_D8_117.patch71.64 KBidimopoulos
#117 interdiff_111.txt6.88 KBidimopoulos
#111 2381293-111.patch70.82 KBidimopoulos
#111 interdiff_110.txt2.45 KBidimopoulos
#110 2381293-110.patch69.89 KBidimopoulos
#110 interdiff_107.txt1.53 KBidimopoulos
#107 2381293-107.patch69 KBidimopoulos
#107 interdiff_98.txt44.92 KBidimopoulos
#100 interdiff_95.txt57.25 KBidimopoulos
#98 2381293-98.patch65.32 KBidimopoulos
#98 interdiff_95.txt577.44 KBidimopoulos
#95 2381293-95.patch66.78 KBidimopoulos
#95 interdiff_93.txt903 bytesidimopoulos
#93 2381293-93.patch66.78 KBidimopoulos
#92 2381293-92.patch105.59 KBidimopoulos
#92 interdiff_90.txt2.94 KBidimopoulos
#90 2381293_D8-90.patch65.71 KBidimopoulos
#90 interdiff_89.txt655 bytesidimopoulos
#89 2381293_D8-89.patch65.66 KBidimopoulos
#89 interdiff_88.txt3.35 KBidimopoulos
#88 interdiff_85-88.txt48.39 KBidimopoulos
#88 2381293_D8-88.patch65.5 KBidimopoulos
#85 2381293_D8-85.patch17.11 KBidimopoulos
#85 interdiff_82-85.txt2.76 KBidimopoulos
#82 2381293-82.patch17.04 KBidimopoulos
#77 interdiff-70-73.txt543 bytesbenjifisher
#73 2381293-73.patch17.03 KBvacho
#70 2381293-70.patch17.04 KBgovind.maloo
#67 2381293-67.patch17.05 KBgovind.maloo
#63 2381293-63.patch17.11 KBbenjifisher
#63 interdiff-2381293-60-63.txt1.19 KBbenjifisher
#60 2381293-60.patch15.77 KBbenjifisher
#60 interdiff-2381293-58-60.patch2.2 KBbenjifisher
#58 2381293-58.patch12.77 KBbenjifisher
#58 interdiff-2381293-57-58.txt1.55 KBbenjifisher
#57 2381293-57.patch12.68 KBkbentham
#56 2381293-56.patch13.13 KBkbentham
#54 2381293-54.patch13.11 KBkbentham
#52 2381293-52.patch12.5 KBkbentham
#50 2381293-50.patch12.5 KBkbentham
#45 2381293-45.patch12.54 KBkbentham
#44 2381293-44.patch12.48 KBkbentham
#39 After patch - Delete content.png40.72 KBNikitaJain
#39 Delete content - Before patch.png40.69 KBNikitaJain
#31 views-content-list-bulk-operations.png63.16 KByoroy
#27 2381293-26.png179.65 KBmohit_aghera
#26 interdiff-2381293-24-26.txt680 bytestoniteof
#26 2381293-26.patch12.03 KBtoniteof
#24 interdiff-2381293-22-24.txt1002 bytestoniteof
#24 2381293-24.patch12.02 KBtoniteof
#22 interdiff-2381293-18-22.txt2.57 KBtoniteof
#22 2381293-22.patch11.94 KBtoniteof
#20 patch-2381293-12.jpg21.3 KBtoniteof
#19 patch-2381293-15.jpg22.01 KBtoniteof
#18 interdiff-2381293-15-18.txt3.02 KBtoniteof
#18 2381293-18.patch9.37 KBtoniteof
#15 interdiff-2381293-13-15.txt2.52 KBtoniteof
#15 2381293-15.patch6.35 KBtoniteof
#13 2381293-13.patch7.45 KBtoniteof
#12 interdiff-2381293-9-12.txt2.14 KBtoniteof
#12 2381293-12.patch3.45 KBtoniteof
#9 2381293-9.patch1.31 KBtoniteof
#2 2381293-current-D7.png40.12 KBSutharsan
#2 2381293-current-D8.png40.67 KBSutharsan
default_delete.png94.08 KBgrendzy

Issue fork drupal-2381293

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

grendzy’s picture

Issue summary: View changes
Sutharsan’s picture

Issue summary: View changes
FileSize
40.67 KB
40.12 KB

I produced a few alternatives and put them in the issue summary. Disclaimer: The statements of usage (frequent/infrequent) in the alternatives are assumptions based on my contact with side editors of sites build by both myself and by third parties. Feel free to replace it with facts.

Variation 1: D7-like
Pros: Familiar to D7 users
Cons: Publish is executed without confirmation

Variation 2: Safe default
Pros: 1. Safe default. Content state is not changed; 2. Freedom to choose any order for the remaining actions; 3. All frequently used operations on the top of the list.
Cons: 1. Clicking Apply will with the default result in a (friendly) (error) message; 2. New UX pattern for core

Variation 3: Safe first
Pros: Non-destructive content operation as default option
Cons: 1. Default operation is executed without warning; 2. Less frequently used operations are placed on top.

As a side note, I think the Save option should be removed. But perhaps we should create a follow-up issue for this.

yoroy’s picture

Agree the current situation is not a good default. I don't think we have to come up with really new ideas here. Matching it to what we have in D7 is a good enough fix I'd say.

Sutharsan’s picture

Issue summary: View changes

I investigated the code behind this drop down list.
The items in the select list are bulk operation actions and can be configured in the Content view (admin/structure/views/view/content). Similar select lists are used in the Comment admin and User admin views. The order of user actions list (admin/people) needs some love too.

The items in the list are Action plugins (e.g. Drupal\node\Plugin\Action\DeleteNode). They are sorted by their action plugin ID (e.g. node_delete_action). The action plugin does not have a weight to be sorted by.

I see a few ways to fix it:
- Add a weight to the Action plugin and and sort them by it. This includes a modification of the schema of the Action plugin.
- Let Views add a weight to the action plugins, perhaps first hard coded, later with a sort option in the Views interface.
- Reverse the current sort order. Unpublish will become the first option.

Sutharsan’s picture

An additional solution to explore after discussion with dawehner:
- Add the property 'category' to the Action plugin and sort by category first, by ID next. Block plugin already has a 'category'.

milosetfrs’s picture

Assigned: Unassigned » milosetfrs

assigning to me.

Bojhan’s picture

Assigned: milosetfrs » Unassigned
toniteof’s picture

Assigned: Unassigned » toniteof

I am working on it.

toniteof’s picture

Just few changes are done in order to get safer drop down list (similar as Alternative 2: Safe default).
- None - is added as first item in the list (default) and validation of option value. Reverse the current sort order can be done if it is needed.
Using weight or category gives more flexibility but I don't know what will be affected with changes should be done.

toniteof’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 9: 2381293-9.patch, failed testing.

toniteof’s picture

Status: Needs work » Needs review
FileSize
3.45 KB
2.14 KB

Add some tests.

This looks like:
patch-2381293-12.jpg

toniteof’s picture

Second solution, same as Alternative 3: Safe first.
Added weight to Action, changed schema, added default weight values and overridden function getBulkOptions.

Status: Needs review » Needs work

The last submitted patch, 13: 2381293-13.patch, failed testing.

toniteof’s picture

Code is a bit simpler.
I can't solve fails in tests. When default weight values are set in core\modules\node\config\install\system.action.node_*_action.yml, get these fails. Guess that system.action.* is proper changed.
Some advice?

slashrsm’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 15: 2381293-15.patch, failed testing.

toniteof’s picture

Status: Needs work » Needs review
FileSize
9.37 KB
3.02 KB

Trying to fix patch.

toniteof’s picture

FileSize
22.01 KB

2381293-18.patch looks like:
patch-2381293-15.jpg

toniteof’s picture

FileSize
21.3 KB

Add image for comment #12.

slashrsm’s picture

Status: Needs review » Needs work

Patch looks ok to me... We would need to add update hook which would load all actions, set appropriate weights on them and save them.

toniteof’s picture

Status: Needs work » Needs review
FileSize
11.94 KB
2.57 KB

Thanks @slashrsm

Add hook update and tests.

slashrsm’s picture

Status: Needs review » Needs work
+++ b/core/modules/node/node.install
@@ -218,3 +218,35 @@ function node_update_8003() {
+    // Set appropriate weights only to node actions.
+    if (array_key_exists($action_name, $node_actions_default_weight)) {

Let's set weight for the actions that are not in the list above to some sane default. 0 maybe?

toniteof’s picture

0 is set as the default weight for other actions.

toniteof’s picture

Status: Needs work » Needs review
toniteof’s picture

A little bit better documentation.

mohit_aghera’s picture

FileSize
179.65 KB

Tested issue on simplytest.me. Looks good on frontend.
Attached image Updated dropdown menu

Delete is moved to bottom. Further if we don't want to change the order, it's good to move to RTBC

mohit_aghera’s picture

Status: Needs review » Reviewed & tested by the community
slashrsm’s picture

+1 for RTBC

catch’s picture

Status: Reviewed & tested by the community » Needs review

Does/should the weight show up in the config entity form?

yoroy’s picture

Thanks for working on this @toniteof!

@catch: I think this screenshot means the answer is no?

I don't think they have to be made reorderable(?), a fixed order keeps is better here, just like "Quit" is always the bottom one in desktop apps etc.

swentel’s picture

I also think exposing them would be a bit weird since it would be hard to change them one by one. It probably would be better to use the draggable list builder to order them all at once, but that's maybe for a follow up ?

Bojhan’s picture

Yhea, lets fix the bug - and then do the reodering in refinements?

catch’s picture

Version: 8.0.x-dev » 8.1.x-dev
Status: Needs review » Reviewed & tested by the community

Yep completely agreed we shouldn't show it unless we eventually do a draggable list, and we shouldn't do the draggable list here, just wanted to check :)

Back to RTBC. Due to the update/config schema change this should just go into 8.1.x

alexpott’s picture

So this is changing an interface by adding a method which is a total BC break and we can't do even in 8.1.x. There is an issue to discuss whether entities should have interfaces see #2661926: [policy no-patch] Document that interfaces without an @api tag can have API additions during a minor release.

See for a discuss of this see the most recent comments on #306662: Add redirect option to site-wide contact forms

catch’s picture

Status: Reviewed & tested by the community » Needs review

It doesn't change the interface, only the base class, but it probably should pending those discussions. There's also comments on #2550249: [meta] Document @internal APIs both explicitly in phpdoc and implicitly in d.o documentation.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

NikitaJain’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
40.69 KB
40.72 KB

Tested and verified #26 patch (2381293-26.patch) on dev-8.3.x. Its working fine and "Delete Content" has moved to the bottom.
Screenshots attached.

webchick’s picture

Because of the solution chosen, seems like it'd be good for this to have Framework Manager sign-off.

However, it would be awesome to see this fixed because yuck!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/node/node.install
@@ -218,3 +218,39 @@ function node_update_8003() {
+function node_update_8004() {

This update needs to be in system module because all actions now have weight not just the ones provided by node and the node module is not required.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kbentham’s picture

Version: 8.5.x-dev » 8.4.3
FileSize
12.48 KB

I have rebase the patch from #26 against 8.4.3. I also moved the update hook from the node module to the system module.

kbentham’s picture

Version: 8.4.3 » 8.5.x-dev
FileSize
12.54 KB

I also rebased the patch against 8.5.x.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

manningpete’s picture

Status: Needs work » Needs review

The last submitted patch, 44: 2381293-44.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 45: 2381293-45.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kbentham’s picture

Status: Needs work » Needs review
FileSize
12.5 KB

I have rerolled the patch in #45 against 8.6.x and fixed the syntax errors.

Status: Needs review » Needs work

The last submitted patch, 50: 2381293-50.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kbentham’s picture

Status: Needs work » Needs review
FileSize
12.5 KB

I have fixed the syntax errors thrown by the last patch.

Status: Needs review » Needs work

The last submitted patch, 52: 2381293-52.patch, failed testing. View results

kbentham’s picture

Status: Needs work » Needs review
FileSize
13.11 KB

I have updated the tests for 8.6.

Status: Needs review » Needs work

The last submitted patch, 54: 2381293-54.patch, failed testing. View results

kbentham’s picture

Update the delete action plugin names.

kbentham’s picture

Fix the user_add_role_action test failures and rebase against the newest version of 8.6x.

benjifisher’s picture

Status: Needs work » Needs review
FileSize
1.55 KB
12.77 KB
+++ b/core/modules/node/tests/src/Functional/Views/BulkFormTest.php
@@ -90,6 +90,18 @@ protected function setUp($import_test_views = TRUE) {
     $this->drupalGet('test-node-bulk-form');
     $elements = $this->xpath('//select[@id="edit-action"]//option');
     $this->assertIdentical(count($elements), 8, 'All node operations are found.');
+
+    // Check the node operations order.
+    $order = TRUE;
+    $order &= $elements[0]->getValue() == 'node_make_sticky_action';
+    $order &= $elements[1]->getValue() == 'node_make_unsticky_action';
+    $order &= $elements[2]->getValue() == 'node_promote_action';
+    $order &= $elements[3]->getValue() == 'node_unpromote_action';
+    $order &= $elements[4]->getValue() == 'node_publish_action';
+    $order &= $elements[5]->getValue() == 'node_unpublish_action';
+    $order &= $elements[6]->getValue() == 'node_delete_action';
+    $order &= $elements[7]->getValue() == 'node_save_action';
+    $this->assertTrue($order, 'All node operations are in proper order.');

I think the problem is that &= does not do logical AND. It does bitwise AND, returning an int instead of a bool.

Let's see what the testbot thinks of my version of the patch.

Status: Needs review » Needs work

The last submitted patch, 58: 2381293-58.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

benjifisher’s picture

Assigned: toniteof » Unassigned
Status: Needs work » Needs review
FileSize
2.2 KB
15.77 KB

Here is a minimal patch that (I hope) fixes the failing tests. I did the following:

  1. Restore Drupal\node\Plugin\views\field\NodeBulkForm::getBulkOptions() from the patch in #26.
  2. Add weight: 0 to core/modules/media/config/optional/system.action.*.yml

I am not sure that the new test should be added to the setUp() method in the node module's BulkFormTest. This means the test is executed twice. Why not add it to testBulkForm()?

Do we want to update getBulkOptions() in NodeBulkForm or in the parent class? The update function is in the system module (as requested in Comment #41) and weights are added to all (?) the core actions, but so far we only use those weights in the node module.

Do we want to reorder the actions in the Media bulk-options list as part of this issue, or is that out of scope? (Can we make it in scope by changing the issue title?)

The last submitted patch, 60: interdiff-2381293-58-60.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 60: 2381293-60.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

benjifisher’s picture

Status: Needs work » Needs review
FileSize
1.19 KB
17.11 KB

Oops, I misnamed my interdiff.

The previous patch actually changed the bulk actions form. It turns out that another test assumes that "Delete content" is the default action. This patch takes care of that.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dqd’s picture

  1. I found no general nit picks
  2. Conceptually others may be better reviewers,
  3. ... simplytest.me hangs on applying it @ 8.7.x-dev.

Does it still apply on 8.7.x-dev ?

benjifisher’s picture

Issue summary: View changes
Status: Needs review » Needs work
Issue tags: +Needs reroll, +Novice

@diqidoq:

Thanks for having a look. No, the patch does not apply on 8.7.x, so it needs a re-roll. This is probably a good Novice task, so I will add the appropriate tags.

govind.maloo’s picture

govind.maloo’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 67: 2381293-67.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

govind.maloo’s picture

Status: Needs work » Needs review
FileSize
17.04 KB

Status: Needs review » Needs work

The last submitted patch, 70: 2381293-70.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

benjifisher’s picture

Issue summary: View changes

@govind.maloo:

Thanks for taking this on!

If you follow the link to the (failing) test results, and scroll to the bottom, you will find a link labeled "1 coding standards message". If you click to expand that, it points you to one line that should use the short array syntax. I think fixing that problem is a suitable Novice task.

It looks as though the failing tests were added as part of #2788777: Allow a site-specific profile to be installed from existing config, which explains why the patch in #63 did not cause them to fail. This may be a case where the tests have to be updated. In fact, I think the three tarballs under core/tests/fixtures/config_install/ need to be updated for the config changes in this issue. Feel free to work on that if you are interested, but it is also OK to fix the coding-standard issue and remove the Novice tag.

vacho’s picture

Resolved the novice issue with array syntax.

vacho’s picture

Issue tags: -Needs reroll, -Novice

the patch can apply, so no need to reroll

andypost’s picture

Status: Needs work » Needs review
+++ b/core/modules/node/src/Plugin/views/field/NodeBulkForm.php
@@ -18,4 +18,24 @@ protected function emptySelectedMessage() {
+    uasort($options, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);

better to refactor it as uasort($options, [SortArray::class, 'sortByWeightElement']); and add to use the classname

andypost’s picture

Status: Needs review » Needs work
benjifisher’s picture

Issue summary: View changes
FileSize
543 bytes

The patch for #70 was a tricky reroll. When I applied the patch from #63 and merged with the 8.7.x branch, there was a merge conflict because ActionResourceTestBase.php in the Rest module was more-or-less moved to ActionResourceTestBase.php in the System module. I think the reroll was done properly, adding a weight key to getExpectedNormalizedEntity() in the new location.

Good work, @govind.maloo!

I have attached an interdiff comparing the patches in #70 and #73. The patch in #73 makes exactly the change it says it does. Thanks, @vacho!

I am updating the remaining tasks.

Berdir’s picture

+++ b/core/modules/system/system.install
@@ -2172,3 +2172,39 @@ function system_update_8501() {
+
+    // Set appropriate weights to node actions, otherwise set 0 as default
+    // weight for other actions.
+    if (array_key_exists($action_name, $node_actions_default_weight)) {
+      $data['weight'] = $node_actions_default_weight[$action_name];
+    }

why specific to node? we have e.g. media actions too and there's more in contrib. The names are fairly unified, so instead of having the complete name for node, we could for example do a partial match for "delete" and so on.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

danrod’s picture

Comment #78:

why specific to node? we have e.g. media actions too and there's more in contrib. The names are fairly unified, so instead of having the complete name for node, we could for example do a partial match for "delete" and so on.

Having the same issue with comments as well, the patch #73 works perfect for nodes, but the default action on "/admin/content/comment" is still "Delete comment".

I will try to rewrite this patch to make it work with comments as well.

yoroy’s picture

That would be great @danrod. This has been a long standing usability bug, lets fix it :)

idimopoulos’s picture

Adding a straight re-roll for 8.8.x.

However, I would like to point out also @danrod's suggestion. From what I see, if the overwrite of the method happens on the base class instead of the node override, it should work out of the box.

As for actions from other entity types, from what I can understand, in general, people in this ticket don't want delete to be first, which mostly is the case due to the letter 'D'. Other thing I noticed here is that 'Save' comes even later so we want to have the 'Delete' as the pre-last case and save as last one.

We can have the update hook set every action that contains the 'delete' string to -1, the 'save' string to 0 and all the rest to a default value -2 (since Drupal tends to count from 0 backwards when it comes to weight).
All related actions in Core share these two strings.
Then, for the other cases, e.g. comments and media, separate tickets can be opened so that the specific order is decided and checked in terms of usability.

idimopoulos’s picture

Status: Needs work » Needs review

Setting to NR so that tests run.

Status: Needs review » Needs work

The last submitted patch, 82: 2381293-82.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
2.76 KB
17.11 KB

Adding my approach on this for review. Will fix the tests as well.

andypost’s picture

Interesting idea to move sorting, BC is a question

Status: Needs review » Needs work

The last submitted patch, 85: 2381293_D8-85.patch, failed testing. View results

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
65.5 KB
48.39 KB

@andypost there were no tests up to now ensuring the order of the actions and the system update ensures that the existing actions will receive a default value.

The only case where a problem could happen is in the sorting when the entity does not have the weight set. However, SortArray has a backup for this as the sortByWeightElement calls for sortByKeyInt which starts with

$a_weight = (is_array($a) && isset($a[$key])) ? $a[$key] : 0;
$b_weight = (is_array($b) && isset($b[$key])) ? $b[$key] : 0;
if ($a_weight == $b_weight) {
  return 0;
}

So the order will not change in that case.

What other BC break might occur?

Also, attaching an attempt to fix the tests.

idimopoulos’s picture

FileSize
3.35 KB
65.66 KB

I am moving the update path to the post updates since we are making changes to config entities. Hook updates are meant for changes like altering databse tables.

Also, it was annoying when I was trying to apply the changes to our project. We are still running 8.7 and this is meant for 8.8 and was marked as update 8802. That could cause a issues.

idimopoulos’s picture

FileSize
655 bytes
65.71 KB

I am also adding a condition where I skip cases where the weight is already set. The reason is that if someone comes across this patch before it is merged in core, they will probably find it because they already have the need for weights and possibly different weight than the one offered here.
However, the post update of the system module might run later than that user's update.
This is to ensure that the update will not overwrite any other values.

pfrenssen’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/system/src/Entity/Action.php
    @@ -143,6 +151,15 @@ public function getType() {
    +   * Returns the weight of operation.
    

    This should be:

    Returns the weight of the action

    We also should move this documentation to the ActionConfigEntityInterface and replace this one with {@inheritdoc}.

    An earlier review in this issue rejected the method in the interface as a B/C break, but this was before we nailed down the B/C policy. Adding methods to interfaces is already allowed since Drupal 8.1.x (ref Backwards compatibility policy).

  2. +++ b/core/modules/system/system.post_update.php
    @@ -206,3 +206,48 @@ function system_post_update_add_expand_all_items_key_in_system_menu_block(&$sand
    +  // List of node actions.
    +  $node_actions_default_weight = [
    +    'system.action.node_make_sticky_action' => -7,
    +    'system.action.node_make_unsticky_action' => -6,
    +    'system.action.node_promote_action' => -5,
    +    'system.action.node_unpromote_action' => -4,
    +    'system.action.node_publish_action' => -3,
    +    'system.action.node_unpublish_action' => -2,
    +    'system.action.node_delete_action' => -1,
    +    'system.action.node_save_action' => 0,
    +  ];
    

    Updating the actions of the node module should not happen in the system module but instead in a post update inside the Node module. This will break in sites that do not have the Node module enabled.

    We also need a similar update hook in all other modules that offer a delete action, such as the Comment module, the Media module and the User module.

  3. +++ b/core/modules/system/system.post_update.php
    @@ -206,3 +206,48 @@ function system_post_update_add_expand_all_items_key_in_system_menu_block(&$sand
    +    // Set appropriate weights to node actions, otherwise set 0 as default
    +    // weight for other actions.
    +    if (array_key_exists($action_name, $node_actions_default_weight)) {
    +      $data['weight'] = $node_actions_default_weight[$action_name];
    +    }
    +    elseif (strpos($action_name, 'delete') !== FALSE) {
    +      $data['weight'] = -1;
    +    }
    +    elseif (strpos($action_name, 'save') !== FALSE) {
    +      $data['weight'] = 0;
    +    }
    +    else {
    +      $data['weight'] = -2;
    +    }
    

    This was suggested by @berdir in #2381293-78: Actions reordering on views bulk forms but I don't like this, it relies too much on magic for my taste. Checking if the machine name of an action contains the word 'delete' is not reliable.

    Even in the core actions this doesn't work, for example the action to delete a user account is system.action.user_cancel_user_action - it doesn't contain the word 'delete'.

    We should not try to babysit action defined in contrib and try to autofix them by guessing their functionality by the machine names. Let's just reliably fix the actions that are provided by core in scope of this patch.

    Contrib modules that consider it important to reorder their actions will be able to set their own weights in a post update hook once this gets in.

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
2.94 KB
105.59 KB

1. You are right, done.

2. We are not updating 'node' actions in the system hook. We are hardcoding the names of the node actions and if the name of the loaded action is included in the list, we are setting a different weight.
Since this is the first application, I do not think there is a problem performing this in the system update. However, I will move it to the node and make sure that the update does not conflict with each other and the order doesn't matter.

The only thing I don't get is what do you propose about the rest of the actions. We should update explicitly actions for all other entity types in this ticket or apply a generic default value (-2) and leave it for a follow up?

3. No strong opinion here. Reverted the changes.

Attaching an attempt for the above.

idimopoulos’s picture

FileSize
66.78 KB

Status: Needs review » Needs work

The last submitted patch, 93: 2381293-93.patch, failed testing. View results

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
903 bytes
66.78 KB

Oops, it seems that the $config_factory->loadMultiple is loading Immutable config objects so I cannot use this to load them all.
Anyway, there are only 8 of them so it is not an issue to load them one by one.

claudiu.cristea’s picture

Status: Needs review » Needs work
Issue tags: +Needs upgrade path tests
  1. +++ b/core/modules/node/node.post_update.php
    @@ -34,3 +34,29 @@ function node_post_update_configure_status_field_widget() {
    +  $node_actions_default_weight = [
    +    'system.action.node_make_sticky_action' => -7,
    +    'system.action.node_make_unsticky_action' => -6,
    +    'system.action.node_promote_action' => -5,
    +    'system.action.node_unpromote_action' => -4,
    +    'system.action.node_publish_action' => -3,
    +    'system.action.node_unpublish_action' => -2,
    +    'system.action.node_delete_action' => -1,
    +    'system.action.node_save_action' => 0,
    +  ];
    

    This will change the order of the list for existing sites and I think this should never happen. New sites will get the new order but existing sites behaviour should be preserved. Then the site builders, acknowledging the new weight feature, will be able to make a decision and, if case, will reorder the actions. That being said, what we need as (post)update is to ensure a weight: 0 for existing system.action.* configs.

  2. +++ b/core/modules/jsonapi/tests/src/Functional/ActionTest.php
    @@ -54,6 +54,7 @@ protected function createEntity() {
    +      'weight' => -2,
    
    @@ -97,6 +98,7 @@ protected function getExpectedDocument() {
    +          'weight' => -2,
    
    +++ b/core/modules/node/config/install/system.action.node_unpublish_action.yml
    @@ -7,4 +7,5 @@ id: node_unpublish_action
    +weight: -2
    
    +++ b/core/modules/node/node.post_update.php
    @@ -34,3 +34,29 @@ function node_post_update_configure_status_field_widget() {
    +    $data['weight'] = isset($node_actions_default_weight[$name]) ? $node_actions_default_weight[$name] : -2;
    
    +++ b/core/modules/system/system.post_update.php
    @@ -206,3 +206,27 @@ function system_post_update_add_expand_all_items_key_in_system_menu_block(&$sand
    +    // Since Drupal starts counting weights from 0 backwards, a default -2 would
    +    // allow the delete action to be set to -1 or 0 so that it never appears
    +    // first.
    +    // @see node_post_update_set_default_action_weights
    +    $data['weight'] = -2;
    
    +++ b/core/modules/system/tests/fixtures/update/system.action.goto_2815379.yml
    @@ -8,5 +8,6 @@ id: goto_2815379
    +weight: -2
    
    +++ b/core/modules/system/tests/fixtures/update/system.action.message_2815379.yml
    @@ -8,5 +8,6 @@ id: message_2815379
    +weight: -2
    
    +++ b/core/modules/system/tests/fixtures/update/system.action.send_email_2815379.yml
    @@ -8,6 +8,7 @@ id: send_email_2815379
    +weight: -2
    
    +++ b/core/modules/taxonomy/config/install/system.action.taxonomy_term_publish_action.yml
    @@ -7,4 +7,5 @@ id: taxonomy_term_publish_action
    +weight: -2
    
    +++ b/core/modules/taxonomy/config/install/system.action.taxonomy_term_unpublish_action.yml
    @@ -7,4 +7,5 @@ id: taxonomy_term_unpublish_action
    +weight: -2
    

    Why -2? The weight can be positive, zero or negative. The smaller will get on top. So, I think we need to put all existing configs on 0 except the "delete" ones which will get a positive value. This would cover also existing contrib/custom actions that will not update their config YAML files, because SortArray::sortByWeightElement() considers the lack of weight key as weight === 0. See also the previous comment. And we can move the whole (post_update logic in system module as we iterate over all system.action.* configs and those config entities are defined by system module.

    Also the update path needs tests.

claudiu.cristea’s picture

+++ b/core/modules/node/node.post_update.php
@@ -34,3 +34,29 @@ function node_post_update_configure_status_field_widget() {
+    $action = $config_factory->getEditable($name);
+    $data = $action->getRawData();
+    $data['weight'] = isset($node_actions_default_weight[$name]) ? $node_actions_default_weight[$name] : -2;
+    $action->setData($data);

Also, this is doing the job but it's not quite the right way to update a config value. Using ::set() is the way:

\Drupal::getEditable($name)
  ->set('weight', NEW VALUE)
  ->save();

EDIT: but we have to use the helper for updating config entities https://www.drupal.org/node/2949630

idimopoulos’s picture

Title: "Delete" should not be the default action on /admin/content » Add the 'weight' property to actions to allow sorting
FileSize
577.44 KB
65.32 KB

@claudiu.cristea In general I continued the request in the ticket. The "Delete" should not be the first action. That is why I continued on the philosofy of the patches before mine. Indeed it is kinda breaking the BC and it is not like it is hard for sites to adapt to their will accordingly.
I am providing a patch that switches back to the idea of the default weight being 0. Also, updating the title of the issue so that it matches your remarks.

I am also fixing one more case of an action created with a null weight so that the missing expected weight does not make the tests fail.

Also updated the system post update function to use the new approach for updating config entities.

I am not hidding the earlier patches to keep a space for the rest to raise an argument if needed.

idimopoulos’s picture

Status: Needs work » Needs review

Oops, forgot the status change.

idimopoulos’s picture

FileSize
57.25 KB

Ugh... Please, ignore the interdiff... I rerolled the patch to the latest develop but compared it to the previous branch (as a branch) and the result was weird.

Uploading the actual interdiff.

claudiu.cristea’s picture

The interdiff is weird. Also I see that all actions have now weight 0. Shouldn't an action, such as system.action.node_delete_action have a higher weight so that it sinks to the bottom of the list? New sites will get the new order. Existing sites without config management will work as they do now. Existing sites that are managing config are owning the site config in their sync directory. Exporting the new config is part of an update, so it should be an effect of a decision.

  1. +++ b/core/modules/system/system.post_update.php
    @@ -213,3 +213,17 @@ function system_post_update_clear_menu_cache() {
    +  \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'action', function ($action) {
    +    /** @var \Drupal\system\Entity\Action $action */
    

    We don't need the type hint, we can strict type in the closure signature. And I think we should use the interface.

  2. +++ b/core/modules/system/system.post_update.php
    @@ -213,3 +213,17 @@ function system_post_update_clear_menu_cache() {
    +    if (empty($action->get('weight'))) {
    

    A more accurate check would be to test if is null: $action->get('weight') === NULL.

andypost’s picture

I think it makes sense to add weight to plugin annotation, this way delete action will get default "high" weight

PS: here is example #2994748: Make a way for Help Page Sections to be ordered

claudiu.cristea’s picture

I think it makes sense to add weight to plugin annotation, this way delete action will get default "high" weight

@andypost, I'm not so sure. I think the logic of having the split between plugin and config is clear. The plugin provides the logic while the config is customizing a specific implementation of the plugin. Meaning we may use an action plugin in more than one place but with different customizations (different config entities). The weight, looks to me, more belonging to customization (i.e. config entity), than the plugin business logic. In a view we may want the "Delete..." action on the bottom of the list, on other circumstances we my want it on other position. It provides the same business logic but in different contexts.

pfrenssen’s picture

The way I read the suggestion from @andypost it is that the annotation weight is the _default_ weight, to be set initially when the config is created.

This is in line with some of the other annotation values that are also being stored in the config when it is created: like the ID, label and entity type.

Having the default value in the annotation makes it possible for action plugin developers to provide a default weight without having to ship an install / update hook.

claudiu.cristea’s picture

@pfrenssen @andypost, the plugin annotation providing a "default weight" sounds interesting. That meaning the config can override that value. If a config is created and no weight has been specified, then will default to the plugin default weight. This is my understanding. That being said, I think, on annotation, it should be default_weight, not simply 'weight". Then the post upgrade path will have to set 0 to keep the actual order.

idimopoulos’s picture

Ok, then how do we proceed? do we go with @andypost's suggestion or do we wait for him to answer? Btw, I am also in favor of what @claudiu.cristea initially said. The linked issue is providing the weight property to the HelpSection plugin. Then in the HelpController the weight is being passed to the section output directly, at

      $this_output = [
        '#theme' => 'help_section',
        '#title' => $plugin->getTitle(),
        '#description' => $plugin->getDescription(),
        '#empty' => $this->t('There is currently nothing in this section.'),
        '#links' => [],
        '#weight' => $plugin_definition['weight'],
      ];

As @claudiu.cristea pointed out, the helper section plugin is a plugin that holds the information displayed in the help page and holds explicitly information on the section information.
On the contrary, an Action is a plugin holding information about, well, an action. An action is not sortable or is having any meaning for weight. The weight doesn't really make sense outside the scope of the form because it is the only place where we sort them. It is not like we are going to use the plugin manager to load all actions and we do not want the delete action to be the first one.
What we do display on the form is an Action config entity instead. This config entity is meant to be listed and shown in the UI so it makes sense for it to have a weight in case it needs custom sorting.
I scavenged a bit and found more config entities that do such a thing:

\Drupal\contact\Entity\ContactForm
\Drupal\filter\Entity\FilterFormat
\Drupal\language\Entity\ConfigurableLanguage
\Drupal\taxonomy\Entity\Vocabulary

explicitly declare the weight as a default value in the protected property as

  /**
   * The weight of the category.
   *
   * @var int
   */
  protected $weight = 0;

\Drupal\user\Entity\Role is not using the default protected $weight = 0; way but instead uses a ::preSave method to fill in the default value if left empty and then there is the case of \Drupal\search\Entity\SearchPage which is having it created in the ::postCreate method which however was based on the https://www.drupal.org/node/2004756 which was closed without action in which Berdir points out the direct assignment to the property or the ::preCreate method for setting default values (points out in general, not in comparison for the config entities).

The config entities above, if I am not mistaking, are not based on some plugin but their purpose is pretty clear.

To give you another example, let's say that in the future we create some entity that performs more than one actions in core. That entity would somehow reference more than one actions. In that case, a weight property in the plugin itself would make much more sense since it would matter in the sequence that they are executed. If we set the $weight property to the plugin now, we merely declare that Action plugin now are tied to the UI of Drupal as it carries a property that affects its appearance.

I am not going to refactor the patch any longer until we have a final decision on that. @andypost can we have your thoughts on this as well? Also @claudiu.cristea and @pfrenssen.

idimopoulos’s picture

FileSize
44.92 KB
69 KB

I have discussed this with @claudiu.cristea about if the decision is final and was concluded that we will go with the default plugin. I still have concerns on this but still, here is a candidate patch.

idimopoulos’s picture

Title: Add the 'weight' property to actions to allow sorting » "Delete" should not be the default action on /admin/content

Also, I am restoring the previous title as according to the #101, this is still needed. Also, remarks from #101 are met.

Status: Needs review » Needs work

The last submitted patch, 107: 2381293-107.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
1.53 KB
69.89 KB

Some fixes for the tests.

idimopoulos’s picture

FileSize
2.45 KB
70.82 KB

It turns out that the suggestion from @andypost has caused the bulk actions for media entities to also change order. Since this is the case, I added a test similar to the one added for the nodes.

pfrenssen’s picture

Status: Needs review » Needs work

I really like how this is looking now. Some small remarks:

--- a/core/lib/Drupal/Core/Action/ActionBase.php
+++ b/core/lib/Drupal/Core/Action/ActionBase.php
@@ -14,6 +14,13 @@
  */
 abstract class ActionBase extends PluginBase implements ActionInterface {
 
+  /**
+   * A default weight new actions.
+   *
+   * @var int (optional)
+   */
+  protected $weight = 0;

This sounds a bit strange, how about "The default weight for new actions.".

It should also be @var int to be in line with our coding standards. It is not allowed to add (optional) to a property declaration.

@@ -23,4 +30,14 @@ public function executeMultiple(array $entities) {
     }
   }
 
+  /**
+   * Returns the weight of the action.
+   *
+   * @return int
+   *   The action weight.
+   */
+  public function getWeight() {
+    return $this->weight;
+  }

Since this is public this should be documented on the Drupal\Core\Action\ActionInterface and replaced with {@inheritdoc} here.

I would also change the documentation to be clear that this returns the default weight of the action.

--- a/core/lib/Drupal/Core/Annotation/Action.php
+++ b/core/lib/Drupal/Core/Annotation/Action.php
@@ -63,4 +63,11 @@ class Action extends Plugin {
    */
   public $category;
 
+  /**
+   * The action weight
+   *
+   * @var int
+   */
+  public $weight;

This is missing a period at the end. Let's change it to The default weight the action will have in the UI. to be entirely clear what this is about.

--- a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
+++ b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
@@ -89,6 +89,21 @@ protected function setUp() {
     $this->drupalPlaceBlock('local_actions_block');
   }
 
+  /**
+   * Tests that actions are sorted first by weight and then by name.
+   */
+  public function testBulkFormActionOrder() {
+    $this->drupalGet('admin/content/media');
+    $order = TRUE;
+    $elements = $this->xpath('//select[@id="edit-action"]//option');
+
+    $order = $order && $elements[0]->getValue() == 'media_save_action';
+    $order = $order && $elements[1]->getValue() == 'media_publish_action';
+    $order = $order && $elements[2]->getValue() == 'media_unpublish_action';
+    $order = $order && $elements[3]->getValue() == 'media_delete_action';
+    $this->assertTrue($order, 'All node operations are ordered alphabetically by default due to equal weight apart from the delete action which has a bigger weight.');
+  }

This test is not about node operations but media library operations.

@@ -157,4 +173,14 @@ public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b)
     return parent::sort($a, $b);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage) {
+    parent::preSave($storage);
+    if ($this->weight === NULL) {
+      $this->weight = $this->getPlugin()->getWeight();
+    }
+  }

The weight should be initialized in the constructor, not in the ::preSave() method. Otherwise if we call $action->getWeight() on a newly created, unsaved Action entity we are getting NULL back which is in violation of the interface (which declares that this returns an integer).

--- a/core/modules/system/tests/src/Kernel/Action/ActionTest.php
+++ b/core/modules/system/tests/src/Kernel/Action/ActionTest.php
@@ -98,4 +98,32 @@ public function testDependencies() {
     $this->assertIdentical($expected, $action->calculateDependencies()->getDependencies());
   }
 
+  public function testDefaultWeight() {

This test is missing documentation.

--- a/core/modules/system/tests/src/Kernel/Action/ActionTest.php
+++ b/core/modules/system/tests/src/Kernel/Action/ActionTest.php
@@ -98,4 +98,32 @@ public function testDependencies() {
+    $action = Action::create([
+      'id' => 'user_add_role_action.' . RoleInterface::ANONYMOUS_ID,
+      'type' => 'user',
+      'label' => t('Add the anonymous role to the selected users'),
+      'configuration' => [
+        'rid' => RoleInterface::ANONYMOUS_ID,
+      ],
+      'plugin' => 'user_add_role_action',
+    ]);
+    $this->assertNull($action->getWeight(), 'Weight is not set during creation.');

This test is wrong, it should instead test that the correct weight (as set in the plugin annotation) is returned immediately after creation. The $action->getWeight() method should never return NULL but should always return the correct value.

andypost’s picture

I don't wanna detail it more but what about using priority instead of weight

andypost’s picture

Issue tags: +Needs change record
pfrenssen’s picture

I'm not sure that priority would be better than weight. I think weight is more in line with how we commonly name this in Drupal.

Priority is mostly used to change the order of execution, while weight is used for the order in the UI.

Berdir’s picture

Agreed that we should stick to weight, which we use almost everywhere in Drupal, Symfony uses priority. The main difference is IMHO not about execution order vs order in UI, but that the values are inverted. high order => end of the list, high priority => start of the list.

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
6.88 KB
71.64 KB

@pfrenssen thanks for the review.

It should also be @var int to be in line with our coding standards. It is not allowed to add (optional) to a property declaration.

I removed that. I got it from the \Drupal\filter\Annotation\Filter's weight property actually.

The weight should be initialized in the constructor, not in the ::preSave() method.

In general, the only case where that can help is the upgrade path. Loading actions and having them with NULL weight is easier to check if they need update. However, I think you are right on wanting the weight to be set on the constructor.

I am providing an attempt to fix all remarks.

idimopoulos’s picture

FileSize
72.05 KB
3.21 KB

So, in terms of the __constructor / ::presave remark I had changed it but I am reverting back to the original way for the main reason that the weight is being retrieved by the plugin, but during the \Drupal\system\Entity\Action::create method does not have the plugin_id as a mandatory property.
This causes a crash when you try to create an Action object without the plugin ID passed in from the beginning.
To keep this in the constructor, I see two ways, either handle the case where the plugin is not set yet, which might cause the object to be stored without a weight, or we will include it both in the constructor and the presave which is a redundant piece of code.

The weight should be initialized in the constructor, not in the ::preSave() method. Otherwise if we call $action->getWeight() on a newly created, unsaved Action entity we are getting NULL back which is in violation of the interface (which declares that this returns an integer).

I have updated the docblock to show that it can return NULL if the weight has not been set yet.

The last submitted patch, 117: 2381293_D8_117.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

pfrenssen’s picture

So, in terms of the __constructor / ::presave remark I had changed it but I am reverting back to the original way for the main reason that the weight is being retrieved by the plugin, but during the \Drupal\system\Entity\Action::create method does not have the plugin_id as a mandatory property.
This causes a crash when you try to create an Action object without the plugin ID passed in from the beginning.

I had a look at the cases where this can happen and if there was maybe another way to solve it. One example is that an action entity is created in user_user_role_insert(). This is indeed a use case where the entity is created in a standard way without passing the weight. The developer expectation here is that the weight should get the default value. In this flow it is indeed a good solution to use the ::preSave() to set the value.

I have one final small suggestion:

@@ -80,6 +89,14 @@ class Action extends ConfigEntityBase implements ActionConfigEntityInterface, En
    */
   protected $pluginCollection;
 
+  /**
+   * {inheritdoc}
+   */
+  public function __construct(array $values, $entity_type) {
+    parent::__construct($values, $entity_type);
+  }
+
+

This code block is no longer needed and can be removed.

Also it looks like the upgrade path test still needs to be written.

idimopoulos’s picture

FileSize
73.25 KB
2.83 KB

I fixed a small underscore that I added to test the update manually, cleaned up the code and provided an update test.
Also, thanks for the guidance :D @claudiu.cristea also helped with pinpointing the update test base class :)

andypost’s picture

It looks great, now needs change record

pfrenssen’s picture

Assigned: Unassigned » pfrenssen

Awesome work! Assigning for writing the change record.

pfrenssen’s picture

Assigned: pfrenssen » Unassigned
Issue tags: -Needs change record

Created draft change record: https://www.drupal.org/node/3083509

I reviewed the changes in #121 and they look good. RTBC from me.

pfrenssen’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/system/src/Entity/Action.php
@@ -143,6 +152,23 @@ public function getType() {
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage) {
+    parent::preSave($storage);
+    if ($this->weight === NULL) {
+      $this->weight = $this->getPlugin()->getWeight();
+    }
+  }

+++ b/core/modules/system/tests/src/Kernel/Action/ActionTest.php
+++ b/core/modules/system/tests/src/Kernel/Action/ActionTest.php
@@ -98,4 +98,35 @@ public function testDependencies() {

I think this code is unnecessary. \Drupal\system\Entity\Action implements EntityWithPluginCollectionInterface which means all the plugin values are copied to the config entity automatically. \Drupal\Tests\system\Kernel\Action\ActionTest::testDefaultWeight() passes with this code removed.

claudiu.cristea’s picture

+++ b/core/lib/Drupal/Core/Annotation/Action.php
@@ -63,4 +63,11 @@ class Action extends Plugin {
+  public $weight;

We should init this to 0. Annotations without weight will take this value. I know it's already init in ActionBase but I would do it also here.

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
73.03 KB
941 bytes

Fixed the remarks from #126 and #127.

Status: Needs review » Needs work

The last submitted patch, 128: 2381293_D8_128.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

idimopoulos’s picture

Status: Needs work » Needs review
FileSize
73.25 KB
1.63 KB

It seems that the tests fail.
@alexpott it was actually a false positive. The ::assertEquals does a == comparison and considers 0 equals to NULL.

There is a similar issue that explains this a bit already at https://github.com/sebastianbergmann/phpunit/issues/1717#issuecomment-11...

I tried to find a place where values were copied (or filled) over by the plugin but could not find anything.
I changed the check to ::assertSame which does not safecast anything and does a type comparison as well.
Everything seems to be returning to normal like this.
Bottom line, it seems that the test was wrong but the ::preSave was right.

alexpott’s picture

So I've taken a long look at this patch and I think we need to step back a bit. At the moment weight is being set on the action plugin annotations and then also saved as a root property on the configuration entity. But when it is being saved on the config entity is being saved outside of the plugin configuration. That's not really correct it should be part of the plugin configuration. If it was, then the logic in \Drupal\Core\Config\Entity\ConfigEntityBase::preSave() would ensure that the value on the plugin and configuration are in-sync. This isn't working because weight is not being saved as part of \Drupal\system\Entity\Action::$configuration (which is where plugin config goes).

One really big question is should weight even be configurable? It doesn't have to be - it could be something defined in the annotation and leave it at that.

If we are going to make it configurable then the following things need to be addressed. However I think adding it to the annotation and therefore part of the plugin's abilities could come first and then we could make it part of configuration in a separate patch.

  1. +++ b/core/modules/system/src/ActionConfigEntityInterface.php
    @@ -30,4 +30,11 @@ public function getType();
    +  /**
    +   * Returns the action weight or null if the weight has not been set yet.
    +   *
    +   * @return int|null
    +   */
    +  public function getWeight();
    
    +++ b/core/modules/system/src/Entity/Action.php
    @@ -32,6 +33,7 @@
    + *     "weight",
    
    @@ -73,6 +75,13 @@ class Action extends ConfigEntityBase implements ActionConfigEntityInterface, En
    +  /**
    +   * The action weight.
    +   *
    +   * @var int
    +   */
    +  protected $weight;
    
    @@ -143,6 +152,23 @@ public function getType() {
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function preSave(EntityStorageInterface $storage) {
    +    parent::preSave($storage);
    +    if ($this->weight === NULL) {
    +      $this->weight = $this->getPlugin()->getWeight();
    +    }
    +  }
    +
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function getWeight() {
    +    return $this->weight;
    +  }
    

    This doesn't need to be here.

  2. +++ b/core/modules/system/system.post_update.php
    @@ -213,3 +213,24 @@ function system_post_update_clear_menu_cache() {
    +  // Only update actions that have not a weight value set to avoid overriding
    +  // already fixed values.
    

    I don;t understand why we're doing this. How has a value already been fixed?

  3. +++ b/core/modules/system/system.post_update.php
    @@ -213,3 +213,24 @@ function system_post_update_clear_menu_cache() {
    +  \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'action', function ($action) {
    +    $action->set('weight', 0);
    +    return TRUE;
    +  });
    

    As this is the first time actions have weight we should be getting the weight from the annotation. If we get this right re-saving the config entity will be enough to pull the default config in the plugin system.

  4. +++ b/core/modules/system/tests/fixtures/update/system.action.goto_2815379.yml
    @@ -8,5 +8,6 @@ id: goto_2815379
    +weight: 0
    
    +++ b/core/modules/system/tests/fixtures/update/system.action.message_2815379.yml
    @@ -8,5 +8,6 @@ id: message_2815379
    +weight: 0
    
    +++ b/core/modules/system/tests/fixtures/update/system.action.send_email_2815379.yml
    @@ -8,6 +8,7 @@ id: send_email_2815379
    +weight: 0
    

    These configurations shouldn't need to be changed. They are part of an update test and so should be as it was at the time when the update function was written.

Berdir’s picture

Just some quick inputs:

* A bit confused about the annotation vs plugin configuration explanation from @alexpott, only default config is added to the plugin configuration, and if it's not configuration then why should it be in there?

* Keep in mind that only some action plugins are configurable, most aren't, so we can't rely on adding something to the default configuration and it then just working. The UI currently also only allows to configure/add configurable action plugins, but I think we should change that.

* At the same time, if action plugins are actually configurable, then being able to configure weights as a user definitely makes sense, e.g. with #2797583: Dynamically provide action plugins for every moderation state change, you want the publish action to be shown above the archive action.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

claudiu.cristea’s picture

Reroll for 8.8.x.

Status: Needs review » Needs work

The last submitted patch, 134: 2381293-134.patch, failed testing. View results

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

pfrenssen’s picture

Opened a MR with the patch rebased on 9.4.x.

idimopoulos’s picture

@alexpott about 2. and 3., we are doing both for BC (or at least this is how we thought it).

For 2, this is because, as soon as this is accepted, a user interested in this might create their own update hook in order to set their desired weight. Since the system default weight setup takes place in a post update, any update hook or configuration synchronization before that might already set the values.

For 3, it is even more simple. According to @claudiu.cristea's comment #96, we want to by default not change the current behavior in existing sites. That means that all sites should get an equal weight so that the order is preserved.

Question to all, should I also update the 8.8.x branch? is this going to be committed to 8.8.x too?

Edit: 1 seems to be fixed in 9.4.x and last point does not apply as the actions don't seem to exist anymore in 9.4.x.

idimopoulos’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

Status: Needs review » Needs work

NW, see the MR.

claudiu.cristea’s picture

Regarding #131.2:

I don;t understand why we're doing this. How has a value already been fixed?

@alexpott, well, in theory it doesn't. But, practically, a lot of sites were already using this patch and site builders did set weights on their actions. I think it doesn't cost us to much to add an if (...). However, that needs to be handled inside the action configs update closure, as I proposed in https://git.drupalcode.org/project/drupal/-/merge_requests/1670#note_69909

idimopoulos’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

Status: Needs review » Needs work

There's a misspelled word, see https://www.drupal.org/pift-ci-job/2314338:

/var/www/html/core/modules/views/tests/modules/user_batch_action_test/config/install/system.action.user_batch_action_test_action.yml:10:1 - Unknown word (weigth)

CSpell: failed

idimopoulos’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

Status: Needs review » Needs work

Few more remarks and an architectural observation: Should the plugin provide the default weight as annotation or as an internal property (with setter/getter)?

I'm opting more for annotation as this is a static, non-changing, value and fits well with the annotations scope.

EDIT: If we go with annotation, then it should be renamed as default_weight.

idimopoulos’s picture

People I have an issue and require your intervention.

    // Tests that actions are sorted by weight.
    $elements = $this->xpath('//select[@id="edit-action"]//option');

    $expected_actions = [
      'media_publish_action',
      'media_save_action',
      'media_unpublish_action',
      'media_delete_action',
    ];
    $this->assertSame($expected_actions, array_map(function (NodeElement $element): string {
      return $element->getValue();
    }, $elements));

The above code works fine for PHP8.0 but fails for PHP7.4. That is because we do not sort by label as a secondary sort and the actions (apart from the weight) are simply presented as they come from the database. I don't know if something related to this changed in PHP8.0 because it seems to come like this from the storage. How should we proceed with this?

idimopoulos’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

@idimopoulos, thank you for moving on with this, looks good.

However, I'm not anymore sure about the architectural approach...

  • Having weight on action config entities and default weight on action plugin annotations doesn't make any sense to actions themselves. Weights only have a meaning in a certain context.
  • If you change the context, e.g. create a new view, you will get the same actions order even you want a different order for the 2nd view. This is because the weight is stored in the action, not in the view.
  • I think (and I'm more and more convinced) that the actions order doesn't belong to actions themselves but to the context (views in most of the cases) where they are displayed.
  • As an analogy, let's take the entity displays: The order of the fields is defined in the entity display (which in this case is the context) rather than in the fields themselves. This allows to have different orders in different contexts (displays). If weights were stored in the field configs, we would have a side-wide field ordering. The same goes with text formats and filters: The text format stores the filters ordering. This allows different filters order on different text formats. An there also other examples in Drupal core...

Proposal

  • Store the weight on a per-view basis. Allow the site builder to decide the order from UI.
  • Upgrade path to fix the existing views but provide BC.
claudiu.cristea’s picture

Status: Needs work » Needs review
Issue tags: -Needs upgrade path
FileSize
13.79 KB

Here's a Proof Of Concept (no interdiff as is a fresh approach)

Still needs:

  • Tests
  • Add all actions as dependencies and resolve the view on dependency removal. Test this.

Regarding the UI: Unfortunately Drupal core lacks a tableselect with draggable rows. I went with an approach used also in text formats: A list of checkboxes and, below, the re-rdering draggable table.

claudiu.cristea’s picture

Component: node system » views.module

And seems to belong to Views module now.

Status: Needs review » Needs work

The last submitted patch, 153: 2381293-153.patch, failed testing. View results

claudiu.cristea’s picture

Status: Needs work » Needs review
FileSize
4.87 KB
16.97 KB

Fix tests

claudiu.cristea’s picture

FileSize
888 bytes
17.84 KB

Fix also the JS test

The last submitted patch, 156: 2381293-156.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 157: 2381293-157.patch, failed testing. View results

claudiu.cristea’s picture

Status: Needs work » Needs review
Issue tags: -Usability +Needs usability review
FileSize
838 bytes
17.81 KB

Another try...

claudiu.cristea’s picture

FileSize
6.45 KB
23.98 KB

Fixing the dependency to actions.

Still needs:

  • Tests to cover the actions ordering.
  • Change record update
  • Usability review
  • IS update
claudiu.cristea’s picture

Adding missing dependencies in views.view.*.yml files.

Gauravvvv’s picture

Re-rolled patch #162, Attached interdiff for same.

claudiu.cristea’s picture

claudiu.cristea’s picture

Issue tags: -Needs tests
FileSize
10.36 KB
34.86 KB

Added test coverage.

claudiu.cristea’s picture

Title: "Delete" should not be the default action on /admin/content » Actions reordering on views bulk forms
Category: Task » Feature request
Issue summary: View changes
FileSize
112.24 KB
  • Fixed title
  • Fixed IS
  • Changed to Feature request
claudiu.cristea’s picture

Fix tags.

Status: Needs review » Needs work

The last submitted patch, 165: 2381293-165.patch, failed testing. View results

claudiu.cristea’s picture

Status: Needs work » Needs review
FileSize
2.56 KB
35.48 KB

Fixed DefaultConfigTest test. Still need to figure out how to fix Umami profile failures.

claudiu.cristea’s picture

FileSize
1.37 KB
36.85 KB

Move Media actions in config/install as now they are dependencies for other module config.

claudiu.cristea’s picture

Issue summary: View changes
Issue tags: -Needs change record updates
  • Updated the change record.
  • Improved the IS with UX/UI explanations
benjifisher’s picture

Issue summary: View changes

I am fixing a typo in the issue summary.

I plan to look at this issue in the weekly usability meeting (maybe this week). Thanks, @claudiu.cristea, for the clear issue summary, especially the "User interface changes" section. If you think of any other usability questions that we should consider, then please add them there.

claudiu.cristea’s picture

FileSize
6.03 KB
37.35 KB
100.44 KB

@benjifisher, Thank you. It seems that I was able to overcome the UX issue. I've managed to merge the actions selection with the actions ordering in a single widget. However, it needs some CSS love.

benjifisher’s picture

That is good news!

Does this issue still need usability review? Does it need an accessibility (a11y) review?

Do you plan to work on the CSS yourself or should we try to recruit a front-end developer to help?

claudiu.cristea’s picture

FileSize
36.94 KB
709 bytes

Do you plan to work on the CSS yourself or should we try to recruit a front-end developer to help?

@benjifisher, CSS is not my strongest point. It would be nice if a frontend dev can step in.

Does this issue still need usability review? Does it need an accessibility (a11y) review?

Not sure about usability but yes to accessibility.


Other aspects:

Removing a leftover.

An important question here is: Do we really need the dependencies management here?

Because now, with this patch, when an action gets deleted, the bulk form fields are removed from the view and the view is disabled. This looks very aggressive. Views doesn't seem to handle nice dependency removals. But if we remove the dependency management, on an action removal, the dead action ID will continue to be stored in the View but will not harm in any way, as only existing actions are loaded. Then on the next view save, the dead action IDs are removed.

markconroy’s picture

I think if you add the draggable library as a dependency to you patch, you should get the correct alignment, same as we use when dragging blocks up/down on the Admin > Structure > Blocks page.

claudiu.cristea’s picture

Issue summary: View changes
Issue tags: -Needs usability review
FileSize
1.88 KB
37.91 KB
82.1 KB

Thank you @markconroy for guiding me on the CSS issue. It would be great if you can review, at least, the CSS part. Here are the CSS fixes (I'm updating also the IS). I think UX review is not needed anymore.

claudiu.cristea’s picture

Issue tags: +Needs usability review
FileSize
13.71 KB
27.99 KB

As per #175, I think we should not do dependency management. See #175 for details. I've undone all the work regarding calculating dependencies and "on dependency removal".


I've changed my mind let's keep Needs usability review

The last submitted patch, 177: 2381293-177.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 178: 2381293-178.patch, failed testing. View results

claudiu.cristea’s picture

Status: Needs work » Needs review
FileSize
2.83 KB
30.01 KB

Fix theme library override tests.

markconroy’s picture

Remember, we need to support IE11 for now, so should not use width: min-content.

I'd suggest we use width: 1.5rem or something like that.

idimopoulos’s picture

FileSize
23.8 KB

This will be very disappointing (it was to me) but while discussing with @claudiu.cristea I remembered that in the beginning, we thought it properly. When me, @claudiu.cristea and @pfrenssen started working on this, it was to have weight only as part of the plugin. I guess we lost track later in the QA when it was proposed to be configurable because at that point, we should have thought that in multiple views, we cannot have multiple weights storing the weight in the configuration.. And I have the feeling that we had discussed this in the past but lost track.

Anyway, I think strongly that the latest approach from @claudiu.cristea is the correct approach. I still think that if we want a "Delete" action to not be first by default, we can still add the plugin non-configurable weight, so that actions are initialized in the view but this is not really needed with configurable weight within the view.

Only thing I am thinking of is that in D7 I remember there are modules offering sub-options. I don't know if this patch should care about this. An example is below:
D7-bulk-with-options

Of course, there are solutions for this, facets is doing it already by dynamically adding the settings in another container lower in the page. Maybe something like that could apply for this too.

benjifisher’s picture

I have read some of the recent comments, but not looked at the code. I have two questions.

First, this issue may be suffering from scope creep. Is there a workable solution that makes something other than Delete the default action, without adding per-view configuration?

Second, please confirm my understanding of this, from #175:

Then on the next view save, the dead action IDs are removed.

This is the expected behavior of the patches in #178, #181, correct?

If so, then I agree with that change. We already have similar behavior with other views dependencies.

Details: I recently removed several unused roles from a site. Any views exposed filter has the option to "remember" the selection based on role. If I remember correctly, every filter on every view stores the list of roles, even if the filter is not exposed. I noticed this when I searched the YAML files for the removed roles. I had to edit each view, and edit each filter, then save, in order to get the view to save without the obsolete roles. (Or I could edit the YAML files directly. I am not saying.)

claudiu.cristea’s picture

@benjifisher,

First, this issue may be suffering from scope creep. Is there a workable solution that makes something other than Delete the default action, without adding per-view configuration?

Very early, since #4, the scope was clarified to not only provide a default safe order of the actions but to allow actions reordering. We're within the scope of the issue. Initially, this has been achieved by adding a weight on actions but this is not quite correct. I've explained in #152 why.

This is the expected behavior of the patches in #178, #181, correct?

Yes. Initially, I've implemented calculate dependencies & on dependency removal (see #177 patch), but this creates the following issue: When an action is deleted, the bulk form fields using that action are removed from the view(s) and the view(s) is/are disabled. This is too aggressive. Instead, I prefer to keep the dead references to removed actions in the view. This has no effect as only the existing actions are loaded and exposed. So, dead references are still there but doesn't create any issue. If the field is updated and the view is saved, they are removed from the view storage. Not sure is the same situation as with the roles.

@idimopoulos

Only thing I am thinking of is that in D7 I remember there are modules offering sub-options. I don't know if this patch should care about this.below:

True, but that is the VBO contrib. It's a totally different thing. The Drupal core Bulk Field doesn't expose such sub-forms.

claudiu.cristea’s picture

FileSize
1.53 KB
30 KB

Fixed #182

benjifisher’s picture

I am adding some screenshots to the issue summary.

I think a slight drawback is that the tabledrag (when editing the available actions in the view) takes up so much space. The 8 options available with the Standard profile fill up most of the modal window on a fairly large (desktop) screen.

Despite that, I think this issue is a big help.

Devashish Jangid’s picture

FileSize
34.17 KB
31.25 KB
18.26 KB
17.73 KB

Verified and tested patch #186.
Patch applied successfully and looks good to me.
Sharing screenshot for the reference.
Moving this ticket to RTBC.

sourabhjain’s picture

Status: Needs review » Reviewed & tested by the community
benjifisher’s picture

Status: Reviewed & tested by the community » Needs work
FileSize
209.78 KB

Usability review

We discussed this issue at #3266551: Drupal Usability Meeting 2022-03-04. That issue will have a link to a recording of the meeting.

One participant mentioned that her clients have sometimes clicked the "Apply" button when they meant to click "Filter". So this issue addresses a real problem, not a theoretical one!

I am setting the status to NW because the Views configuration for Claro needs some work, as this screenshot show:

Screenshot showing the views configuration table-drag in the Claro theme

We also thought it would be a good idea to add a do-nothing option at the top of the list as the default. Something like "- Select -" or whatever the usual label is when a selection is required. There was pretty strong consensus on this.

The last idea we had was to change the default order, grouping opposites together. For example, Publish and Unpublish should be next to each other. This should probably be done in a follow-up issue, unless you would like to work on it here.

benjifisher’s picture

Issue tags: -Needs usability review

I forgot to remove the tag for a usability review.

For the record, the participants at the usability meeting were

benjifisher, rkoller, AaronMcHale, andregp, Antoniya, ckrina, guilherme-rabelo, guilherme-rabelo, kimberlly_amaral, victoria-marina, shaal, tmaiochi, worldlinemine

claudiu.cristea’s picture

Many thanks for the review

One participant mentioned that her clients have sometimes clicked the "Apply" button when they meant to click "Filter". So this issue addresses a real problem, not a theoretical one!

(…)

We also thought it would be a good idea to add a do-nothing option at the top of the list as the default. Something like "- Select -" or whatever the usual label is when a selection is required. There was pretty strong consensus on this.

Wouldn’t that be a BC break? Suddenly existing sites will have a new default option when they probably expect there an action. Maybe we can add the no-action text as a new configuration and on empty text we don’t show this empty option. Then we can provide BC for existing sites… But would that be acceptable from a UX perspective? I mean adding more clutter to the config form. If yes, IMHO that is slightly out-of-scope and it would be a good candidate for a follow-up. Any thoughts?

I am setting the status to NW because the Views configuration for Claro needs some work, as this screenshot show

Could anyone with better CSS skills step in? I’m really not the best person.

The last idea we had was to change the default order, grouping opposites together. For example, Publish and Unpublish should be next to each other. This should probably be done in a follow-up issue, unless you would like to work on it here.

I think we should do it here because releasing this change as it is will raise other BC problems in the follow-up


Waiting for a UX guidance on the first problem

benjifisher’s picture

The question about BC is a good one. I think we do not have to preserve compatibility in this case. According to Drupal 8 and 9 backwards compatibility and internal API policy (backend),

The following parts of the code base should always be treated as internal and are not guaranteed to not change between minor versions. For patch versions we will aim to avoid any breaking changes even to @internal code unless required to fix a serious bug:

...

Render arrays (including form arrays)

There is more detail on the companion page Drupal 8 and 9 frontend backwards compatibility (BC) policy:

Render arrays (including form arrays)
While the Render and Form APIs themselves are stable, the exposed data structures used to build and cache pages and forms are not. We will change these structures where necessary to make usability improvements or add features in minor versions. This means alter hook implementations may need to be updated.

(emphasis added).

Given the strong consensus at the usability meeting, I think this issue is one where we are allowed to make a BC break.

benjifisher’s picture

Looking at the screenshots in the issue summary, I see that Drupal 7 grouped opposite actions together, as we suggested in #190. I think that going back to the same order as D7 is a reasonable default.

claudiu.cristea’s picture

Assigned: Unassigned » claudiu.cristea

Assigning to work on #190 & Co.

claudiu.cristea’s picture

claudiu.cristea’s picture

Assigned: claudiu.cristea » Unassigned
Status: Needs work » Needs review

I've implemented UX requirements from #190

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

claudiu.cristea’s picture

Work moved to !2931

saidatom made their first commit to this issue’s fork.

Gauravvvv’s picture

needs-review-queue-bot’s picture

Status: Needs review » Needs work
FileSize
150 bytes

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

Bhanu951 made their first commit to this issue’s fork.

Bhanu951’s picture

Status: Needs work » Needs review

Rebased to latest head and fixed Merge conflict in MR #2931

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative

Tried testing MR 2931

I see the reordering feature in the bulk operation view field.
But reordering and checking different items seems to have no baring.
I checked 2 items but all appear.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

claudiu.cristea’s picture

reordering and checking different items seems to have no baring.

@smustgrave, I don't understand what "no baring" means in this context. Could you, please, explain?

smustgrave’s picture

Meant that I couldn't reorder or remove actions with the change.

But is this needed anymore default option is no longer "delete". If still needed definitely will need an issue summary update.

claudiu.cristea’s picture

Issue summary: View changes
Status: Needs work » Needs review

Re #209, #213

@smustgrave ,

Thank you for looking at this.

Meant that I couldn't reorder or remove actions with the change.

This is not about removing actions. It's only about reordering of actions on a per-view basis. I've tested again manually and everything works as expected. Also, the tests are a proof that is working correctly.

The IS is explaining all these and doesn't need any change. However, I've tweaked a little the Proposed resolution to make it more clear.

Please re-read the scope and test again. For any issue I'm available here or on Slack. Thank you.

smustgrave’s picture

Status: Needs review » Needs work

Can none 11.x branch be hidden or noted in IS which MR should be reviewed.

Assumed 4583 as that's the last one but appears to have a test failure.

Applied the MR though and can confirm I can change the order without issue.

claudiu.cristea changed the visibility of the branch 2381293-delete-should-not to hidden.

claudiu.cristea changed the visibility of the branch 2381293-delete-action-10.0.x to hidden.

claudiu.cristea changed the visibility of the branch 2381293-delete-action-10.1.x to hidden.

claudiu.cristea’s picture

Hide attached files

claudiu.cristea’s picture

Issue summary: View changes

Added MR to be reviewed in IS

claudiu.cristea’s picture

Status: Needs work » Needs review

A new action has been introduced recently, in 79a07a4e, and that made the test fail. This is ready for review.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

That seemed to address the test failure.

Retested the reordering and that functionality still works.

quietone’s picture

Updating credit

quietone’s picture

Issue summary: View changes

I'm triaging RTBC issues. I read the IS, the comments, the MR and change record.

Thanks for keeping the Issue Summary up to date. I have moved the 'MR to review' to the 'proposed resolution' section because it is the proposed resolution. ;-)

Like @benjifisher, I am concerned about scope creep on this issue. The direction set in #4 states, "- Let Views add a weight to the action plugins, perhaps first hard coded, later with a sort option in the Views interface." I read that to mean the changes to the Views interface are to be done later. That is also a suitable separation of tasks here. And bring the patch size down to something manageable for a review.

I spotted one nit in the MR (which I did not review) and the grammar in the change record needs work. However, I am not commenting or tagging for those because the scope issue should be settled first.

I am leaving at RTBC and will ask the committers.

claudiu.cristea’s picture

The direction set in #4 states, "- Let Views add a weight to the action plugins, perhaps first hard coded, later with a sort option in the Views interface." I read that to mean the changes to the Views interface are to be done later. That is also a suitable separation of tasks here

That was more a proposal than setting the issue’s scope. And until #152 a different approach has been considered, which we considered to be functionally wrong, for the reasons expressed in #152. Of course we can separate the UI part in a follow-up but the work is already done here and it benefited from the contributions of UX and fronted devs.

idimopoulos changed the visibility of the branch 2381293-delete-action-10.2.x to hidden.

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
FileSize
90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

claudiu.cristea’s picture

Status: Needs work » Reviewed & tested by the community

Rerolled

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
FileSize
10.49 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

claudiu.cristea’s picture

Status: Needs work » Reviewed & tested by the community

Rerolled

catch’s picture

Status: Reviewed & tested by the community » Needs work

The phpcs job failed.

sourabhjain’s picture

Status: Needs work » Needs review
claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

Setting back as RTBC as it was just very minor change in the PHPCS rules added recently

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
FileSize
90 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

andypost’s picture

Bhanu951’s picture

Rebased to latest head but need to merge commits, a697018f and 78d40bad - Update /multilingual.tar.gz .

@claudiu.cristea by any chance do you remember what those changes are ?

Bhanu951’s picture