Problem/Motivation

The current workflow UI is very disjointed. Each link to Create, Update, or Delete a workflow state or transition takes the user off to a new page, which can result them getting lost, or at best a few clicks away from where they started.

Proposed resolution

As proposed in https://marvelapp.com/1124911 the new workflows UI is a unified single area for Creating, Updating, and Deleing workflow states and transitions.

Remaining tasks

User interface changes

Here's some screenshots of the state, transition, and delete modals based on #166:

API changes

Data model changes

CommentFileSizeAuthor
#265 interdiff_263-265.txt681 byteskostyashupenko
#265 2830584-265.patch36.25 KBkostyashupenko
#264 2830584-nr-bot.txt5.15 KBneeds-review-queue-bot
#263 interdiff-263.txt9.15 KBamateescu
#263 2830584-263.patch36.18 KBamateescu
#262 2830584-nr-bot.txt11.62 KBneeds-review-queue-bot
#261 interdiff-261.txt2.49 KBamateescu
#261 2830584-261.patch36.62 KBamateescu
#259 interdiff_258-259.txt3.39 KBpooja saraah
#259 2830584-259.patch33.11 KBpooja saraah
#258 rerolldiff_249-258.txt10.47 KBayush.khare
#258 2830584-258.patch33.13 KBayush.khare
#249 2830584-249.patch36.47 KBmanuel garcia
#245 2830584-245.patch36.46 KBmanuel garcia
#241 2830584-241.patch36.56 KBmanuel garcia
#241 reroll-diff-2830584-238-241.txt2.08 KBmanuel garcia
#238 2830584-238.patch36.62 KBtimmillwood
#238 interdiff-2830584-238.txt2.23 KBtimmillwood
#234 2830584-234.patch36.52 KBjofitz
#234 interdiff-230-234.txt2.08 KBjofitz
#230 2830584-230.patch39.12 KBtimmillwood
#230 interdiff-2830584-230.txt1.54 KBtimmillwood
#228 2830584-228.patch38.5 KBtimmillwood
#228 interdiff-2830584-228.txt9.81 KBtimmillwood
#215 2830584-215.patch36.57 KBmanuel garcia
#210 2830584-210.patch36.65 KBtimmillwood
#210 interdiff-2830584-210.txt3.93 KBtimmillwood
#207 2830584-207.patch36.48 KBtimmillwood
#207 interdiff-2830584-207.txt2.5 KBtimmillwood
#206 2830584-206.patch37.47 KBmanuel garcia
#206 interdiff.txt806 bytesmanuel garcia
#198 2830584-198.patch38.25 KBjofitz
#198 interdiff-197-198.txt1.77 KBjofitz
#197 2830584-197.patch38.22 KBmanuel garcia
#197 interdiff.txt1.65 KBmanuel garcia
#195 2830584-195.patch39.73 KBtimmillwood
#195 interdiff-2830584-195.txt1.66 KBtimmillwood
#193 2830584-193.patch39.68 KBtimmillwood
#193 interdiff-2830584-193.txt19.91 KBtimmillwood
#188 2830584-188.patch40.45 KBsam152
#188 reroll.txt2.93 KBsam152
#185 2830584-185.patch40.26 KBsam152
#182 2830584-181.patch41.41 KBtimmillwood
#182 interdiff-2830584-181.txt3.58 KBtimmillwood
#175 2830584-175.patch41.35 KBmanuel garcia
#175 interdiff.txt8.71 KBmanuel garcia
#169 Screenshot from 2017-08-02 07-58-48.png17.71 KBtimmillwood
#169 Screenshot from 2017-08-02 07-58-33.png33.16 KBtimmillwood
#169 Screenshot from 2017-08-02 07-58-18.png39.31 KBtimmillwood
#166 2830584-166.patch40.56 KBsam152
#166 interdiff_.txt8.43 KBsam152
#162 2830584-162.patch42.76 KBtimmillwood
#162 interdiff-2830584-162.txt9.6 KBtimmillwood
#158 2830584-158.patch42.63 KBsam152
#155 Peek 2017-08-01 08-52.gif4.14 MBmanuel garcia
#151 2830584-151.patch44.67 KBtedbow
#151 interdiff-145-151.txt875 bytestedbow
#145 2830584-145.patch44.56 KBtedbow
#145 interdiff-141-145.txt3.97 KBtedbow
#141 2830584-141.patch44.19 KBtimmillwood
#141 interdiff-2830584-141.txt1.32 KBtimmillwood
#140 2830584-140.patch43.41 KBmanuel garcia
#140 interdiff.txt5.23 KBmanuel garcia
#137 2830584-137.patch43.44 KBtimmillwood
#137 interdiff-2830584-137.txt7.25 KBtimmillwood
#135 2830584-135.patch45.11 KBmanuel garcia
#132 2830584-132.patch44.91 KBmanuel garcia
#132 interdiff.txt4.51 KBmanuel garcia
#131 2830584-131.patch43.45 KBmanuel garcia
#129 2830584-129.patch43.58 KBtimmillwood
#129 interdiff-2830584-129.txt743 bytestimmillwood
#127 2830584-127.patch43.56 KBtimmillwood
#127 interdiff-2830584-127.txt5.03 KBtimmillwood
#125 2830584-125.patch45.45 KBmanuel garcia
#125 interdiff.txt6.77 KBmanuel garcia
#120 2830584-120.patch41.64 KBtimmillwood
#120 interdiff-2830584-120.txt6.24 KBtimmillwood
#118 Screenshot from 2017-07-19 16-26-56.png34.84 KBmanuel garcia
#118 Screenshot from 2017-07-19 16-26-37.png37.64 KBmanuel garcia
#117 2830584-117.patch41.44 KBtedbow
#117 interdiff-2830584-113-117.txt1.83 KBtedbow
#113 2830584-113.patch41.39 KBtedbow
#113 interdiff-2830584-112-113.txt1.22 KBtedbow
#112 2830584-112.patch41.15 KBtedbow
#112 interdiff-2830584-102-112.txt24.14 KBtedbow
#102 2830584-102.patch39.8 KBtimmillwood
#102 interdiff-2830584-102.txt1.46 KBtimmillwood
#96 2830584-96.patch39.57 KBmanuel garcia
#96 interdiff.txt1.98 KBmanuel garcia
#95 2830584-95.patch40.92 KBmanuel garcia
#95 interdiff.txt4.7 KBmanuel garcia
#90 2830584-90.patch41.68 KBmanuel garcia
#90 interdiff.txt2.41 KBmanuel garcia
#89 2830584-89.patch42.08 KBmanuel garcia
#89 interdiff.txt2.26 KBmanuel garcia
#86 2830584-86.patch40.74 KBmanuel garcia
#86 2830584-86-test-only.patch39.23 KBmanuel garcia
#86 interdiff.txt2.49 KBmanuel garcia
#85 2830584-85.patch40.19 KBmanuel garcia
#85 interdiff.txt1.81 KBmanuel garcia
#81 ErrorsOnClickCancel.png56.67 KBtimisoreana
#80 2830584-80.patch38.68 KBmanuel garcia
#80 interdiff.txt3.99 KBmanuel garcia
#77 2830584-76.patch36.66 KBmanuel garcia
#75 2830584-75.patch3.92 KBmanuel garcia
#75 interdiff.txt3.92 KBmanuel garcia
#72 2830584-72.patch35.62 KBmanuel garcia
#72 interdiff.txt1.21 KBmanuel garcia
#68 2830584-68.patch35.6 KBmanuel garcia
#68 interdiff.txt9.24 KBmanuel garcia
#66 2830584-66.patch37.02 KBmanuel garcia
#66 interdiff.txt15.2 KBmanuel garcia
#59 ToField.png3.38 KBtimisoreana
#58 new transitions layout.png139.24 KBjojototh
#54 2830584-54.patch41.01 KBmanuel garcia
#54 interdiff.txt3.89 KBmanuel garcia
#51 2830584-51.patch38.11 KBmanuel garcia
#51 interdiff.txt2.26 KBmanuel garcia
#44 2830584-44.patch37.04 KBmanuel garcia
#43 interdiff.txt5.42 KBmanuel garcia
#43 2830584-43.patch5.42 KBmanuel garcia
#41 2830584-41.patch37.35 KBmanuel garcia
#41 interdiff.txt5.07 KBmanuel garcia
#40 2830584-39.patch36.05 KBmanuel garcia
#40 interdiff.txt1.21 KBmanuel garcia
#38 2830584-38.patch36.05 KBmanuel garcia
#38 interdiff.txt887 bytesmanuel garcia
#35 2830584-35.patch36.04 KBmanuel garcia
#35 interdiff.txt12.17 KBmanuel garcia
#34 2830584-34.patch28.59 KBmanuel garcia
#34 interdiff-30-34.txt18.05 KBmanuel garcia
#34 interdiff.txt15.04 KBmanuel garcia
#31 2830584-31.patch28.73 KBmanuel garcia
#31 interdiff.txt9.98 KBmanuel garcia
#30 2830584-30.patch26.65 KBmanuel garcia
#29 2830584-29.patch26.65 KBmanuel garcia
#29 interdiff.txt7.41 KBmanuel garcia
#26 Peek 2017-05-19 12-49.gif1.23 MBmanuel garcia
#26 2830584-26.patch24.2 KBmanuel garcia
#26 interdiff.txt807 bytesmanuel garcia
#25 2830584-25.patch23.41 KBmanuel garcia
#25 interdiff.txt4.31 KBmanuel garcia
#23 Peek 2017-05-18 16-33.gif4.53 MBmanuel garcia
#23 2830584-23.patch22.5 KBmanuel garcia
#23 interdiff.txt10.64 KBmanuel garcia
#21 transitions-edit-delete.gif1.62 MBmanuel garcia
#21 2830584-21.patch13.01 KBmanuel garcia
#21 interdiff.txt7.01 KBmanuel garcia
#19 transition-edit-modals.gif2 MBmanuel garcia
#19 2830584-19.patch7.97 KBmanuel garcia
#19 interdiff.txt2.52 KBmanuel garcia
#17 2830584-17.patch7.04 KBmanuel garcia
#17 interdiff.txt4.73 KBmanuel garcia
#16 2830584-16.patch3.36 KBvijaycs85
#16 workflow-add-transition.png80.72 KBvijaycs85
#16 workflow-edit-transition.png84.18 KBvijaycs85
#16 workflow-edit-loader.png47.07 KBvijaycs85
#15 add transition.png71.39 KBjojototh
#10 Screen Shot 2017-03-21 at 4.30.41 PM.png71.41 KBtkoleary

Comments

alexpott created an issue. See original summary.

jojototh’s picture

Cross posting from https://www.drupal.org/node/2779647#comment-11821941

Here is a new prototype for workflow:
- keeps the same functionality and technical implementation
- user doesn't leave page before workflow and moderation configuration is done as it all happens on same page instead of 4 different pages - reduces the amount of clicks and pages needed
- simplifies the UX and reduces "up to 25%" of time needed for creating and administering workflows and moderation
- improves the Workflows listing by showing important information such as workflow type, which entity types it affects and states available

Below is a video comparing creating workflow, 1 new state and 1 new transition and configuring moderation for 1 content type in the current and proposed versions.
Video: https://youtu.be/xB-AbupfDxY

Interactive prototype: https://marvelapp.com/1124911

tacituseu’s picture

In my opinion (long term) it would be great if the UI would mirror how the comments work, by which I mean:
1. configure 'Workflow types' under '/admin/structure'
2. add field of type 'Workflow' to the bundle under 'Manage fields' and pick one from step 1
Then allow only one of them to have control over submit button (configurable under 'Edit field settings' on 'Manage fields' tab)

Not sure it's in the scope of this issue, looks more like it's meant to be a minor clean-up of what went in. Opened #2835545: Provide a Workflow FieldType that references a workflow entity and tracks the current state of an entity for this direction.

andypost’s picture

Issue tags: +Needs screenshots
timmillwood’s picture

alexpott’s picture

One of my concerns with the currently proposed prototype is that it will only work nicely on sites with a limited number of entity types and bundles. 20+ content types are not unheard of.

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.

timmillwood’s picture

@alexpott - Are these concerns from a UX or performance point of view? It seems unanimous from the UX site that the selection of entity types and bundles a workflow can be used on needs to move out of the bundle settings. In the latest UX call (https://youtu.be/xWLXFRbs-EM?t=245) Kevin O'Leary expressed concerns about how deep the setting was.

Bojhan’s picture

Without a 'new' form element I am unsure how to resolve @alex his issue. The only suitable pattern we have would be the way we present fields for selection, in the Views UI.

tkoleary’s picture

Issue summary: View changes
StatusFileSize
new71.41 KB

So my comment is not about the entity types bundles thing but more about the general wall of information effect that this UI is presenting. I think it would be great if we could get to a simpler UI that folds together a lot of the tasks that have been pulled apart here into their own discrete feildsets, modals etc.

The one that's been bugging me the most is the transitions UI because I believe it may be the most difficult for people to wrap their heads around. I made this codepen in an effort to work out a UI that would do this without adding too much front-end code. Here's what it looks like:

And here's the link to the codepen prototype: http://codepen.io/tkoleary/pen/EWEXWQ?editors=1100

Setting aside the entity types, this is really all the UI you need to for 80% of tasks. The tabs across the top I envision just loading the next transition into the same space via ajax. The "add transition" button-link could behave the same way, and the "add state" button-link could also load in place or via a modal. The important thing is that it will bring the user right back to this visualization.

The important thing is that I can quickly flip back and forth between the transitions and follow the selected states and the leader lines to see which states are going to where.

I also get a description that tells me what's going to appear in the button, because otherwise I have to—in my head—go "Ok the button always says 'Save and' so My label needs to be 'save and something' but without the 'save and'"

timmillwood’s picture

Status: Active » Needs review

I really like the idea in #10, but do wonder if it'll be unfamiliar to Drupal site builders. The current workflows edit form is very similar to many other admin pages within Drupal. Just my 2 cents.

I actually came here to close this issue in favour of #2843083: Select entity type / bundle in workflow settings which is implementing @jojototh's designs from #2 and nearing completion. Forgot about #10.

This is currently a "must-have" for Workflows to become beta (#2843494: WI: Workflows module roadmap) so looking to action on that.

tkoleary’s picture

@timmillwood

I really like the idea in #10, but do wonder if it'll be unfamiliar to Drupal site builders. The current workflows edit form is very similar to many other admin pages within Drupal. Just my 2 cents.

That is true, but the first question we should be asking is whether it's a simpler and more understandable pattern for *any* user, brand new or experienced with Drupal. We shouldn't willy-nilly introduce new patterns into core, but there are instances when core patterns are insufficient. Given the complexity of the mental model her I think this is one of those instances.

Having said that, this pattern is so new that it does warrant some usability testing.

Bojhan’s picture

Can we centralise the issue that we discuss that UI in? I've seen it in another issue too.

I am very keen on introducing new UI's, we try to fit everything into tables - especially with sequential things like this, its just the best fit. I am very much in agreement with Kevin on this one, a new pattern in this case may be a better fit.

timmillwood’s picture

ok, but does this still need to be a "must have" in #2843494: WI: Workflows module roadmap?

jojototh’s picture

StatusFileSize
new71.39 KB

I think that Kevin's proposal is actually trying to achieve the same thing as I originally proposed for Workflows, but it wasn't yet implemented. See the proposal at: https://marvelapp.com/1124911/screen/17578780

creating transition

vijaycs85’s picture

StatusFileSize
new47.07 KB
new84.18 KB
new80.72 KB
new3.36 KB

Initial patch on proposal in #15

Patch contains:

1. Implemented only for transition edit and add link
2. Updated "to" to selectbox

Yet to do:
1. Apply to other elements. If the implementation is OK.
2. On validation error, going back to page
3. Probably fix alignment issue on loading icon (ref: screenshot)

manuel garcia’s picture

StatusFileSize
new4.73 KB
new7.04 KB

Great stuff @vijaycs85!
Took the liberty to continue where you left off =)

  • We now submit the modal form and close the modal
  • We now update the values on the page for the transitions (I had to simplify how we render these and add some consistency in order to target them on our ajaxresponse).
  • We now display a title like "Edit the Create New Draft transition for the Editorial workflow" for the form.

Still to do (at least):

  • Fix the throbber bug
  • Display the form errors within on the TRANSITIONS details element (on the ajaxCallback())
timmillwood’s picture

Category: Plan » Task

Here's some details on how to get the form errors to display, https://api.drupal.org/api/drupal/core%21core.api.php/group/ajax/8.2.x#s...

manuel garcia’s picture

StatusFileSize
new2.52 KB
new7.97 KB
new2 MB

More progress on this:

  • Form errors now display within the modal
  • Saving successfully now displays the messages just on top of the details for transitions

Still to do:

  • Fix throbber bug
  • On the edit form there is a link to delete the transition - I think we should either change it for a cancel button, or perhaps at least keep the delete confirmation form on the modal, not sure, but as it is it feels weird going to another page.
timmillwood’s picture

The delete link it inherited from EntityForm, I'd be happy to remove it so the only place to delete it a drop button on the workflows page.

manuel garcia’s picture

StatusFileSize
new7.01 KB
new13.01 KB
new1.62 MB

Some more progress...

  • Removed the Delete link from the edit form, placed there instead a Cancel button which closes the dialogue.
  • Made the Delete link display the confirmation form on a modal, and ajaxified it so that the deleted transition is removed from the table, etc.

Still to do:

  • Fix the throbber bug
  • See what to do with the Adding of a new transition. With this patch the form shows on a modal, but it does not submit via ajax. Doing so would mean we'd have to add a new row to the table which is not trivial.

Status: Needs review » Needs work

The last submitted patch, 21: 2830584-21.patch, failed testing.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new10.64 KB
new22.5 KB
new4.53 MB

Couldn't help myself, so I did the same for the workflow states:

In my opinion we should remove the operations links on the transitions table from WorkflowStateEditForm::form(), since it wont work well on a modal context, and we can already edit them below without leaving the same page... thoughts?

Status: Needs review » Needs work

The last submitted patch, 23: 2830584-23.patch, failed testing.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new4.31 KB
new23.41 KB

Fixing the failing test (we removed the delete link from the edit form), and some coding standards violations.

manuel garcia’s picture

StatusFileSize
new807 bytes
new24.2 KB
new1.23 MB

My take on fixing the throbber on these kinds of buttons, not sure if we should do this as a separate issue, if so the interdiff could easily serve as the starting patch.

vijaycs85’s picture

Looks great.

  1. One concern not related to this issue is amount of duplicate code on all 3 entities' add/edit forms. We might need to open a separate ticket to reduce duplicate.
  2. +++ b/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php
    @@ -96,4 +111,46 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +   * Ajax callback to close the modal and remove the deleted state from the
    +   * table.
    

    minor: CS issue: Short description should be < 80 character

  3. +++ b/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php
    @@ -96,4 +111,46 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +   * @return \Drupal\Core\Ajax\AjaxResponse
    

    minor: CS issue: empty line between @param and @return missing

timmillwood’s picture

#27.1 - maybe we need a WorkflowFomBase or similar to inherit shared methods.

manuel garcia’s picture

StatusFileSize
new7.41 KB
new26.65 KB

Thanks for the reviews - fixing CS issues mentioned in #27, reviewed the rest of the patch with that in mind, and adding proper titles to:

  • entity.workflow.add_state_form
  • entity.workflow.edit_state_form
  • entity.workflow.add_transition_form
  • entity.workflow.edit_transition_form

As far as adding a base class for all these forms, do you think it's time to start optimizing this?
Should we have a base form for edit, a base form for adding, etc?

For now I can only see an obvious method that could be reused cancelAjaxCallback(), and perhaps strip out the error handling part of submitAjaxCallback() somehow...

manuel garcia’s picture

StatusFileSize
new26.65 KB

Rerolled, there was a tiny conflict on core/themes/seven/css/components/dropbutton.component.css

manuel garcia’s picture

StatusFileSize
new9.98 KB
new28.73 KB

OK I did a bit of refactoring, introducing WorkflowFormBase. Both WorkflowTransitionEditForm and WorkflowStateEditForm extend it.

Was able to pull out actions(), cancelAjaxCallback() and the error handling part of submitAjaxCallback().

Unfortunately cancelAjaxCallback is stil duplicated on the delete forms, but since those extend ConfirmFormBase, they can't use WorkflowFormBase, which extends EntityForm. So perhaps there is a better approach.

To be honest, I think WorkflowFormBase could be used for editing any entity in a modal in theory...

timmillwood’s picture

Maybe a trait would make more sense.

timmillwood’s picture

I think we should go down the route of adding a trait, and add it to /core/lib/Drupal/Core/Form.

manuel garcia’s picture

StatusFileSize
new15.04 KB
new18.05 KB
new28.59 KB

Thanks @timmillwood for the help on this one, introducing Drupal\Core\Form\ModalFormTrait, instead of Drupal\workflows\Form\WorkflowFormBase.

interdiff.txt is against #31 which introduced the base form, so probably not terribly insightful to look at.
interdiff-30-34.txt is against #30 which is perhaps better to see the effect of introducing the trait itself.

manuel garcia’s picture

StatusFileSize
new12.17 KB
new36.04 KB

Introducing functional javascript tests:

  • core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php - tests for what we introduced on #2843083: Select entity type / bundle in workflow settings.
  • core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php tests what we're trying to do on this issue. Not finished yet.

These led me to discover that we weren't attaching the 'core/drupal.dialog.ajax' library to WorkflowEditForm so doing this as well.

I am blocked on WorkflowEditFormTest::testWorkflowTransitionsForm(), which fails saying that RuntimeException: Unable to complete AJAX request. when trying to save the transition edit form. It has driven me slightly insane: it is identical to the states edit form test, except updating a checkbox field as well as the label. However i have tried the test without updating the transition at all and it still fails. Any pointers would be very welcome!

manuel garcia’s picture

Self review:

+++ b/core/modules/workflows/src/Form/WorkflowTransitionDeleteForm.php
@@ -129,7 +129,7 @@ public function submitAjaxCallback() {
-    $response->addCommand(new HtmlCommand('[data-drupal-selector="edit-transitions-container"] [data-drupal-selector="edit-modal-messages"]', \Drupal::service('renderer')->renderRoot($status_messages)));
+    $response->addCommand(new HtmlCommand('[data-drupal-selector="edit-states-modal-messages"]', \Drupal::service('renderer')->renderRoot($status_messages)));

This should be edit-transitions-modal-messages, but im not testing this yet so my blockade remains.

Status: Needs review » Needs work

The last submitted patch, 35: 2830584-35.patch, failed testing.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new887 bytes
new36.05 KB

Fixing #36 while I'm at it.

The test results at least show why the ajax request doesn't finish, however, that looks to be an unrelated bug to what I'm trying to do?
Error: Syntax error, unrecognized expression: [data-drupal-selector="edit-transitions-publish-to]

Status: Needs review » Needs work

The last submitted patch, 38: 2830584-38.patch, failed testing.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new1.21 KB
new36.05 KB

OK I'm such a retard sometimes haha
Yes its totally related to what I'm doing, and yes, it is totally my fault!
Tests should come back green now, I'll work on expanding the coverage now.

manuel garcia’s picture

StatusFileSize
new5.07 KB
new37.35 KB

Adding tests for deleting a transition, and cleaning up a bit the rest of assertions. With this I think I'm finished with the JavascriptTests =)

Status: Needs review » Needs work

The last submitted patch, 41: 2830584-41.patch, failed testing.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new5.42 KB
new5.42 KB

Failure seems unrelated, fixing coding standards in the mean time...

manuel garcia’s picture

StatusFileSize
new37.04 KB

Oops, wrong patch.

The last submitted patch, 43: 2830584-43.patch, failed testing.

timmillwood’s picture

Issue tags: +Needs usability review

This is looking pretty close and so tempted to RTBC, but one thing is bugging me.

When editing a workflow state (in a modal), clicking the edit or delete link for a transition reloads the page. I think this should close the state modal and open the transition modal.

manuel garcia’s picture

Re #46: If you take the route of editing the transition in a modal from there, then when you save the transition, the user would expect to be back where you started (the state edit modal), and that is going to get very complex if at all possible currently.

This would be doable perhaps if we had nested modals working, which we unfortunately don't (see #2741877: Nested modals don't work: opening a modal from a modal closes the original)

I agree that this part needs some kind of decision on what to do. I proposed this on #23:

In my opinion we should remove the operations links on the transitions table from WorkflowStateEditForm::form(), since it wont work well on a modal context, and we can already edit them below without leaving the same page... thoughts?

gábor hojtsy’s picture

Since the issue clearly went quite forward from *reviewing* the UI, let's update the issue summary/title with clear goals, so we can tell when this is done. As it is now, it is entirely open ended. As a must-have issue for #2843494: WI: Workflows module roadmap, we should have clear goals. If certain things are defined while others need more definition that should be documented too.

timmillwood’s picture

Title: Review the workflow UI » Implement unified workflow UI
Issue summary: View changes
Issue tags: -Needs issue summary update

Updating the title and issue summary to reflect that we are now at the stage of implementing everything suggested in #1.

timmillwood’s picture

@Manuel Garcia - ok, I think removing the edit and delete links for transitions within the state modals sounds good. The mock ups in #1 doesn't have them.

manuel garcia’s picture

StatusFileSize
new2.26 KB
new38.11 KB

Removing the transitions table from the states edit form to reflect what we have on #1.
Also noticed we were adding the attributes twice to the Add a new state link, so removing that from the patch.

timmillwood’s picture

Nice, will RTBC once we have screenshots.

I'll do the screenshots (or animated gif) when I get chance, but anyone is welcome to generate them.

manuel garcia’s picture

Assigned: Unassigned » manuel garcia
Status: Needs review » Needs work

While doing the screenshots i realized that if you generate a form error on the transition / state add forms they take you to their add page (for example admin/config/workflow/workflows/manage/editorial/add_transition)
This totally breaks the flow... so we need to do the submit on the add forms via ajax and display any errors that way.

Working on that

manuel garcia’s picture

Assigned: manuel garcia » Unassigned
Status: Needs work » Needs review
StatusFileSize
new3.89 KB
new41.01 KB

OK now the form submits via ajax, displays the errors if any on the modal, and if there are none, it saves and redirects to the current workflow edit form.

I avoided closing the modal because otherwise when the page reloads it looks funky. Like this you just see the loading icon and then the page reloads.

Bojhan’s picture

Thanks for all the work, this looks really interesting.

From my understanding of this thread at #15, we diverged from the conversation and went with a solution proposed by jojototh using tables as a way to form the states, transitions and applied entities. This is in line with much of core.

I would like to challenge the thinking that this is sufficient for RTBC. The concepts in this screen are complex and the user needs to be guided how to effectively set things up, the fact that very different concepts look homogeneous implies linear sequence and equal importance. While in reality there is an interplay between states and transitions (at least) and this can easily become quite complex.

Can we explore having at least a representation of the states and transitions, like proposed in #10 by tkoleary? I understand making it interactive is a challenge, but the representation will greatly improve the usability.

Bojhan’s picture

Issue tags: -Needs usability review

This would be the review for now, will happily provide more context. From the usability perspective, this is not close to RTBC.

sam152’s picture

Status: Needs review » Needs work

Initial high level code review of #54. Reviewed the code before seeing the suggestions made in #55, but I think that comment and this one is enough for NW.

  1. +++ b/core/lib/Drupal/Core/Form/ModalFormTrait.php
    @@ -0,0 +1,83 @@
    +  /**
    +   * Generates a form's submit and action button elemetns with the #ajax
    +   * functionality set up.
    

    First line should be 80 chars.

  2. +++ b/core/lib/Drupal/Core/Form/ModalFormTrait.php
    @@ -0,0 +1,83 @@
    +        'callback' => [$this, 'modalformsubmithandleerrors'],
    ...
    +        'callback' => [$this, 'modalformclosedialog'],
    

    Why are these methods not camel case?

  3. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php
    @@ -0,0 +1,58 @@
    +    $assert_session = $this->assertSession();
    +    $page = $this->getSession()->getPage();
    

    Is it necasary to cache these? 40 occourances of "$this->assertSession();" in core vs 330 "$this->assertSession()->"

  4. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    @@ -85,7 +89,14 @@ public function form(array $form, FormStateInterface $form_state) {
    +              'width' => 700,
    

    This appears a few times in core. I wonder if some constants for standard modal widths would be useful.

  5. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    @@ -148,16 +181,33 @@ public function form(array $form, FormStateInterface $form_state) {
    +          'aria-label' => $this->t('Edit \'@transition\' transition', ['@transition' => $transition->label()]),
    

    Why not use double quotes to enclose the single quotes.

  6. +++ b/core/modules/workflows/src/Form/WorkflowStateAddForm.php
    @@ -111,12 +115,39 @@ public function save(array $form, FormStateInterface $form_state) {
    +    $response = $this->modalFormSubmitHandleErrors($form, $form_state);
    +    if ($commands = $response->getCommands()) {
    +      return $response;
    +    }
    

    Seems cleaner to check form_state for errors here.

  7. +++ b/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php
    @@ -96,4 +110,24 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +    $response = $this->modalFormCloseDialog();
    +
    +    $data_selector = 'edit-states-' . strtolower(str_replace('_', '-', $this->stateId));
    +
    +    $response->addCommand(new RemoveCommand('[data-drupal-selector="' . $data_selector . '"]'));
    +
    +    $status_messages = ['#type' => 'status_messages'];
    +    $response->addCommand(new HtmlCommand('[data-drupal-selector="edit-states-modal-messages"]', \Drupal::service('renderer')->renderRoot($status_messages)));
    +
    +    return $response;
    

    Can all of this be avoided by sending a RedirectCommand which reloads the page?

  8. +++ b/core/modules/workflows/src/Form/WorkflowStateEditForm.php
    @@ -146,29 +120,41 @@ public function save(array $form, FormStateInterface $form_state) {
    +    $data_selector = 'edit-states-' . strtolower(str_replace('_', '-', $this->stateId));
    

    Maybe something like \Drupal\Component\Utility\Html::cleanCssIdentifier could help us here.

  9. +++ b/core/modules/workflows/src/Form/WorkflowStateEditForm.php
    @@ -146,29 +120,41 @@ public function save(array $form, FormStateInterface $form_state) {
    +    $title = $this->t('Edit the @state state for the @workflow', ['@state' => $workflow->getState($workflow_state)->label(), '@workflow' => $workflow->label()]);
    

    Does this string need work. "Edit the Draft state for the Editorial"?

  10. +++ b/core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
    @@ -147,12 +151,39 @@ public function save(array $form, FormStateInterface $form_state) {
    +    $title = $this->t('Add a new transition to the @workflow', ['@workflow' => $workflow->label()]);
    

    Same here.

  11. +++ b/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
    @@ -149,30 +161,43 @@ public function save(array $form, FormStateInterface $form_state) {
    +    $title = $this->t('Edit the @transition transition for the @workflow', ['@transition' => $workflow->getTransition($workflow_transition)->label(), '@workflow' => $workflow->label()]);
    

    Same here.

jojototh’s picture

StatusFileSize
new139.24 KB

@bojhan thanks for the feedback! I gave it a few thoughts and found some concerns with what tkoleary proposed in #10 that need to be figured out:

  1. you need to select one of multiple options on the “To state” side so it wouldn’t be as simple as in the codepen example
  2. when you go to “add new transition” modal no option would be selected and if there weren’t any checkboxes users might not know what to do, where to click
  3. It also doesn’t communicate that you can select multiple on the “From state” side but only one on the “To state” side

Here is an option, that could benefit from tkoleary's proposal and answer the concerns above

Only local images are allowed.

timisoreana’s picture

StatusFileSize
new3.38 KB
  1. It is not evident that "To" field on "Edit transition" form can't be edited (it's a bit strange, because user can accidentaly save wrong end state and in this case, he should delete the transition and create another). Better to show it like a disabled field.
    To field
  2. Bug. Are shown errors "The transition from ... to ... already exists." after click on Cancel button (and refresh the page). It is expected to not show the error in this case. No matters what user selected, if he didn't save it. video
manuel garcia’s picture

Bug. Are shown errors "The transition from ... to ... already exists." after click on Cancel button (and refresh the page). It is expected to not show the error in this case. No matters what user selected, if he didn't save it. video

Thanks for testing!
Those were probably errors from previous form submissions, but with the latest patch that should not happen since we are already displaying them within the modals. Did you get this with the latest patch (#54) applied?

timisoreana’s picture

Yes, Manuel, it was the latest patch (#54).
These errors, as you said, are shown within the modals, but only when user clicks "Save".
But,
when user clicks "Cancel" and refresh the page he will see these errors (anyway, no need to show errors in this case, no matters on the page or modal).
You are welcome if you have the questions).

manuel garcia’s picture

Thank you @timisoreana for kindly explaining, I will check why this happens when we have a consensus around the UI and I get back to this patch.

timmillwood’s picture

In #2850549: Allow changing of transition 'to' on edit we talk about changing the "to" state of a transition. Therefore here we need to assume the "to" state cannot be changed, then handle in the other issue if and how we allow it to be changed.

timmillwood’s picture

We discussed this issue in the UX call today.

Gabor suggested we move forward with the direction Jozef originally proposed here. Then open a new issue regarding the proposal in #58. Thus we get the initial improvements in, and they don't end up getting derailed and delayed with discussions about the new transitions interface.

gábor hojtsy’s picture

For the record (and anyone can watch the actual recording literally at https://www.youtube.com/watch?v=7afbnHveAJA :D) I said if we agree that using these modals is the best way forward then getting the modals committed as a first step would be best so we can work on refining the *content* of the modals later on. I think introducing the modals and refining the content of the modals in the same issue may result in unfair coupling, hard to review patches, etc. and the modals may not end up in core if we don't end up being able to solve the rest of the technology or argue endlessly about it.

If we don't agree the modals help and there is a more holistic improvement needed not "just" refining the contents of individual pages after they are made modals, then it does not help to commit modals first.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new15.2 KB
new37.02 KB

OK then, worked on stabilizing what we have so far:

Re #57:
1. That line is 72 chars, if I added the next word to it it would go over 80. That said I have reworded that so it makes a bit more sense as to what it does.
2. Fixed
3. Done
4. I chose that width because of that, for example its what's used on the block configuration page. Also works in this case fine.
5. Removed the single quotes, we don't need them and we aren't using them on the sates forms either.
6. Yep you're right, fixed.
7. Yeah I agree, updating all the ui in ajax calbacks is getting very messy. I've reworked all submit ajax callbacks so they first display any errors in the modal if there are any and then reloads the page using a RedirectCommand.
8. No longer necessary since we are reloading the page instead of updating the ui via ajax.
9, 10 & 11. The Editorial workflow is actually called "Editorial workflow". If I add ' workflow' to the string, its going to end up displaying: Edit the Published state for the Editorial workflow workflow. This is an ongoing problem in content_moderation, and we should fix this as a different issue in my opinion, because it probably has an effect on a lot of other different strings.

Re #59.2 - Fixed

So a lot of changes, patch should come back complaining about WorkflowEditFormTest, but I wanted to get this up and see if anything else breaks. Nice that this way the patch is smaller though :)

Status: Needs review » Needs work

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

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new9.24 KB
new35.6 KB

Refactored the tests to actualy just test the js functionality (modals and in-modal form errors), however im getting strange errors locally:
Zumba\GastonJS\Exception\BrowserError: There was an error inside the PhantomJS portion of GastonJS.
Uploading to see if its just me.

I also fixed a bug introduced in #66 which I found by the new tests =)

Status: Needs review » Needs work

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

manuel garcia’s picture

OK so its not just me... anyone seen this before?

tacituseu’s picture

Perhaps #2773791: Clicking elements with children in Javascript tests throws a GastonJS exception ?

Edit:
Failing at
$this->click('#edit-states-container tr:contains(Published) button .dropbutton-arrow');

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new1.21 KB
new35.62 KB

Thanks @tacituseu

OK that selector makes no sense because Published does not have a dropdown button. Duh.
Switching it now to using the Archived state, which does. However the test still fails :S

If I run (with the new selector) jQuery('#edit-states-container tr:contains(Archived) button .dropbutton-arrow').click(); on the js console, and the dropdown shows the delete button properly, so the selector apparently should not the problem now?

I also tried applying the patch on that issue as well, but the tests still fail :S

Other selectors I've tried (both work on the js console):

  • '#edit-states-container tr:contains(Archived) .dropbutton-toggle button'
  • '[data-drupal-selector="edit-states-archived-operations"] .dropbutton-toggle button'

Status: Needs review » Needs work

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

tacituseu’s picture

Might be the reason Drupal\Tests\views_ui\FunctionalJavascript\FilterCriteriaTest::testFilterCriteriaDialog() does it like this:

$page = $this->getSession()->getPage();
$dropbutton = $page->find('css', '.views-ui-display-tab-bucket.filter .dropbutton-toggle button');
$dropbutton->click(); 
manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new3.92 KB
new3.92 KB

Thanks @tacituseu again for helping me out debug this.

It ends up that the selectors weren't the problem. Instead it had these two problems:

  1. There is no Archived state in this test (lol). So I'm using the Draft state instead.
  2. We needed to close the previous modal window in order to continue with the test, taking screenshots is what helped me find this out.

So, in this patch:

  • Fixed the failing tests.
  • Changed the selectors so they are simpler.
  • Added coverage for the cancel buttons closing the modals.

Status: Needs review » Needs work

The last submitted patch, 75: 2830584-75.patch, failed testing. View results

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new36.66 KB

Argh, ignore the patch on #75 its just the interdiff with a different name, sorry bot! So the interdiff on #75 applies to this one.

manuel garcia’s picture

Self review: we should probably merge Drupal\Tests\workflows\FunctionalJavascript|WorkflowEditFormTest into Drupal\Tests\content_moderation\FunctionalJavascript\WorkflowTypeEditFormTest.

manuel garcia’s picture

Re #78: actually as @timmillwood pointed out, one is for workflows and the other is for content_moderation so it's probably fine as it is...

manuel garcia’s picture

StatusFileSize
new3.99 KB
new38.68 KB

Finalized the test that handles the 'This workflow applies to:' section.

It now also checks the UI updates that happen when you change the selection of entities that the workflow applies to, both adding and removing selections. With this I think we are well covered when it comes to JS tests for what's going on on this page.

timisoreana’s picture

StatusFileSize
new56.67 KB

Click on Cancel button doesn't close the modal.
Steps:

  1. Open "Edit transition" modal
  2. Check all initial states (there should be at least 1 already existing transition)
  3. Click Cancel

ER Modal should be closed
AR: Modal is not closed video After click on Cancel
Was applied patch #80

manuel garcia’s picture

Status: Needs review » Needs work

Thanks for testing and the report @timisoreana!

Apparently setting '#limit_validation_errors' => [], on the cancel buttons is causing some issues... its preventing validation which prevents the form errors, but apparently the form is still being submitted, and triggers this as it thinks the user is trying to save the form:

InvalidArgumentException: The 'create_new_draft' transition already allows 'draft' to 'draft' transitions in workflow 'editorial' in Drupal\workflows\Entity\Workflow->setTransitionFromStates() (line 440 of /var/www/drupal8/core/modules/workflows/src/Entity/Workflow.php).

setTransitionFromStates() is only being called from Drupal\workflows\Form\WorkflowTransitionEditForm::copyFormValuesToEntity(), which I'm not sure why its being triggered. The cancel button is just a button, not a submit button... any pointers welcome!

timmillwood’s picture

The entity gets built no matter if the submit is happening or not, so what we need to go is ignore the exception, and depend on form validation, we could do this with a try / catch similar to the patch in #2886567: Adding a workflow state or transition with an integer ID results in unrecoverable fatal errors.

This should do the trick:

diff --git a/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php b/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
index ecc4a8196b..d0b27d4cb1 100644
--- a/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
+++ b/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
@@ -136,15 +136,21 @@ protected function copyFormValuesToEntity(EntityInterface $entity, array $form,
       // Only do something once form validation is complete.
       return;
     }
-    /** @var \Drupal\workflows\WorkflowInterface $entity */
-    $values = $form_state->getValues();
-    $form_state->set('created_transition', FALSE);
-    $entity->setTransitionLabel($values['id'], $values['label']);
-    $entity->setTransitionFromStates($values['id'], array_filter($values['from']));
-    if (isset($values['type_settings'])) {
-      $configuration = $entity->getTypePlugin()->getConfiguration();
-      $configuration['transitions'][$values['id']] = $values['type_settings'][$entity->getTypePlugin()->getPluginId()];
-      $entity->set('type_settings', $configuration);
+    try {
+      /** @var \Drupal\workflows\WorkflowInterface $entity */
+      $values = $form_state->getValues();
+      $form_state->set('created_transition', FALSE);
+      $entity->setTransitionLabel($values['id'], $values['label']);
+      $entity->setTransitionFromStates($values['id'], array_filter($values['from']));
+      if (isset($values['type_settings'])) {
+        $configuration = $entity->getTypePlugin()->getConfiguration();
+        $configuration['transitions'][$values['id']] = $values['type_settings'][$entity->getTypePlugin()
+          ->getPluginId()];
+        $entity->set('type_settings', $configuration);
+      }
+    }
+    catch (\Exception $e) {
+      // Do nothing, if there is an exception we want validation to handle it.
     }
   }
timmillwood’s picture

It looks like the follow up to implement the design from #58 is #2758623: [meta] Redesign workflow configuration page to better visually describe the flow.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new1.81 KB
new40.19 KB

Thanks @timmillwood makes sense, doing so in this patch, which fixes the bug.

manuel garcia’s picture

StatusFileSize
new2.49 KB
new39.23 KB
new40.74 KB

Adding test coverage for what was fixed on #85.

Attached a test-only patch which should fail (doesn't include the interdiff from #85), and a patch with both the fix and the test.

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

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Awesome work on this @Manuel Garcia!

manuel garcia’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new2.26 KB
new42.08 KB

Specifying the type of exception we're catching on WorkflowTransitionEditForm::copyFormValuesToEntity(), and applying the same fix on the transition add form, where we had the same bug.

manuel garcia’s picture

StatusFileSize
new2.41 KB
new41.68 KB

Switching back the transition add form to field to its original radios type (out of scope change)

Adding explanatory comments to the try/catch on copyFormValuesToEntity, and cleaning up an old unnecessary @todo.

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Looks better.

I quite like the try/catch approach to bypassing the exceptions to get the form api validation. We could equally duplicate the validation, but not sure we want to duplicate things.

tstoeckler’s picture

Status: Reviewed & tested by the community » Needs review

Hmm... I'm not excited by the try-catch, as I've mentioned elsewhere in particular because we already decided on the other approach in the other issue. What bothers me even more, though, is that with the patch we have an inconsistency in the validation between e.g. WorkflowStateAddForm::copyFormValuesToEntity() and WorkflowTransitionAddForm::copyFormValuesToEntity(). I really don't think we can commit it like this. I think we should either copy the validation for now and then @timmillwood you can open a follow-up to discuss to change that into a try-catch (for both forms) or we use a try-catch for both foms directly, but then we would need e.g. @Berdir to RTBC as a "tie-breaker" between @timmillwood and me. Kicking back to "needs review" for now.

timmillwood’s picture

The other issue where we're implementing a try/catch is #2886567: Adding a workflow state or transition with an integer ID results in unrecoverable fatal errors. I do like it because I am a firm believer in keeping the code D.R.Y, but we could have some validation method, or just a method that returns the regex to help this, try/catch just seemed like a simple solution.

That being said, I think we do need consistency between the State and Transition forms.

@berdir taking a look sounds like a good idea. ;)

plach’s picture

One minor thing:

+++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
@@ -85,7 +86,14 @@ public function form(array $form, FormStateInterface $form_state) {
+            'class' => ['use-ajax'],
+            'data-dialog-type' => 'modal',
+            'data-dialog-options' => Json::encode([
+              'width' => 700,
+            ]),

@@ -95,12 +103,22 @@ public function form(array $form, FormStateInterface $form_state) {
+              'width' => 700,

@@ -116,7 +134,16 @@ public function form(array $form, FormStateInterface $form_state) {
+          'width' => 700,

@@ -148,16 +175,33 @@ public function form(array $form, FormStateInterface $form_state) {
+            'width' => 700,
...
+            'width' => 700,

@@ -179,7 +225,16 @@ public function form(array $form, FormStateInterface $form_state) {
+          'width' => 700,

Can we store the default dialog attributes in a variable to ensure we have to change them just once, if needed, and no inconsistencies are introduced?

manuel garcia’s picture

StatusFileSize
new4.7 KB
new40.92 KB

Addressing #94

manuel garcia’s picture

StatusFileSize
new1.98 KB
new39.57 KB

I just realized that since we are reloading the page when submitting the modal forms instead of updating the UI on the ajax callbacks, we no longer need to change those parts of the form in order to have markup to target.

Removing those changes in this patch which should make it slightly smaller...

timmillwood’s picture

Patch looks good to me, but we still need to argue about the try/catch Vs. replicating the validation.

plach’s picture

Assigned: Unassigned » berdir

Right, let's try to summon @Berdir then.

manuel garcia’s picture

Opened up #2894499: Rename 'Editorial workflow' to 'Editorial' in order to be able to address #57.9, 10, and 11 properly.
(See my reply to it on #66).

berdir’s picture

Sorry for the delay.

I'm not sure. Neither duplicating the validation nor the try/catch will really help us long term if we want to handle config entity validation like content entities, that is, validate using the validation API/config schema. Which we will need if we want to support REST for them.

But we also have problems there with content entities, for example #2820364: Entity + Field + Property validation constraints are processed in the incorrect order.

I don't really have a preference for try/catch or duplicating the validation. Having a @todo + follow-up seems like a good idea, and if I understand it correctly, if we'd do #2886567: Adding a workflow state or transition with an integer ID results in unrecoverable fatal errors then both forms would use try/catch and would be "consistent"? So I think I'd be ok with the try/catch in both issues and a follow-up to figure out a better solution.

berdir’s picture

Assigned: berdir » Unassigned

As an idea, we could handle things like this by changing the entity validation in entity forms in a way that would only build and validate the entity if there are no form-level validation errors. Then we could have #element_validate and similar things for elements that could break an entity just by setting them. And rest could possibly introduce a pre validate method or something that would allow entities to inspect the raw values before they are set? Or we'd define a special exception interface that rest would be able to handle in a meaningful way.

timmillwood’s picture

StatusFileSize
new1.46 KB
new39.8 KB

- Created follow up #2895310: Building entities in ContentEntityForm::validateForm() can throw exceptions to fix entity validation in regards to forms as @berdir suggested in #101.
- Added @todo to the patch pointing to the follow up.

plach’s picture

Assigned: Unassigned » tstoeckler

Ok, leaving RTBC to @tstoeckler.

xjm’s picture

Title: Implement unified workflow UI » Use modals for creating, updating, and deleting workflows, with a new ModalFormTrait
Issue tags: +Needs issue summary update

The title of this issue terrifies me every time I look at the roadmap, so trying to give it a more descriptive title based on my understanding. :) The summary could use an update with some more detail and screenshots, also.

xjm’s picture

Ideally, the ModalFormTrait would be adde in a separate issue, with its own tests etc., since it is a new API.

tstoeckler’s picture

Assigned: tstoeckler » Unassigned
Status: Needs review » Reviewed & tested by the community

OK, don't want to hold this up any longer. And yes, it's not ideal either way. So let's do this!

tstoeckler’s picture

Oh wait, did #104 want to set this to needs work to update the issue summary? Either way, this is fine by me.

tim.plunkett’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs subsystem maintainer review

Someone pointed me to this issue an hour ago. It adds a new public API to the Form subsystem.
I haven't had a chance to review it yet.

timmillwood’s picture

Just to note, we could do this without the new api or trait, but it seemed to make sense.

xjm’s picture

Per @tim.plunkett and @tedbow, this is adding a trait that's very similar to (but not quite the same as) one added in #2785047: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page, so I do think we should split that trait out into a new dedicated issue so it can be reviewed and used for both. Also since it should have test coverage. (Since the proposed trait is an addition for stable core, we want to get it in sooner than the improvements for the two experimental modules.) Thanks!

tedbow’s picture

I am working on seeing I get 1 trait to working for both issues

tedbow’s picture

Status: Needs work » Needs review
StatusFileSize
new24.14 KB
new41.15 KB

Ok is here is try at using most of the trait here #2785047: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page to work on this issue.

Here is what I did

  1. Copied in the trait from #2785047 but renamed in DialogFormTrait. Modals and the Off-canvas tray are just dialog types.
  2. Change the redirect logic to use destination from the query string. So WorkflowEditForm was changed to pass along the destination.
  3. submitAjaxCallback() is not longer need for each form class
  4. actions() is not longer needed either.

I am just about to update #2785047: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page with the exact same trait.

tedbow’s picture

StatusFileSize
new1.22 KB
new41.39 KB

Realized I didn't override buildForm in WorkflowTransitionAddForm

timmillwood’s picture

It seems like this issue has broken the form actions, as we now have a "delete" showing up on the state edit form when it shouldn't, and it also seems to be linking to the wrong place.

xjm’s picture

Status: Needs review » Needs work

@timmillwood, the patch in general, or @tedbow's work on the trait? Something that needs tests either way I think.

I still really think we should put the trait in a dedicated issue since it's a separate concept in a different (stable) subsystem. But we can validate here first that the modal is working correctly for this usecase before splitting it off.

timmillwood’s picture

@xjm It's @tedbow's patch in #112, previously we were overriding the EntityForm actions method, the #112 patch reverts this.

tedbow’s picture

Status: Needs work » Needs review
StatusFileSize
new1.83 KB
new41.44 KB

Ok this updates the trait to this #2785047-57: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page

It allows passing the CSS selector of the dialog, defaults to modal selector which this module uses.

manuel garcia’s picture

Status: Needs review » Needs work
StatusFileSize
new37.64 KB
new34.84 KB

The modal forms are redirecting to config/workflow/workflows/manage/editorial (its missing the admin/ chunk).

The edit forms are now showing the delete links (we were removing them):

The add forms are also showing delete links (they shouldn't):

timmillwood’s picture

Assigned: Unassigned » timmillwood
timmillwood’s picture

Status: Needs work » Needs review
StatusFileSize
new6.24 KB
new41.64 KB

This patch introduces WorkflowEntityForm which has common methods used by 4 of the workflow forms, such as actions, fixing the delete link issue.
The redirect issue is fixed by an update to \Drupal\Core\Form\DialogFormTrait::submitFormDialog which @tedbow seems to be having issues with when running Drupal in a sub directory. The code is similar to that used in \Drupal\Core\Form\ConfirmFormHelper::buildCancelLink, so should work for all unless we have an issue there too.

tedbow’s picture

Wanted to mention here that @effulgentsia was reviewing #2785047: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page which using this trait and suggested that we might not want to use a trait all. See comment and my reply https://www.drupal.org/node/2785047#comment-12175310

tedbow’s picture

Status: Needs review » Needs work

RE #120

I am still getting a page not found when the I use the State edit form in the modal.

I get redirected to http://www.d8.dev/d8_3_rest/d8_3_rest/admin/config/workflow/workflows/ma...

Notice my sub directory d8_3_rest is in their twice.

I know the test bot runs in a sub directory so I check I and I don't there is JS test that actually saves this form in the modal.

WorkflowEditFormTest just checks the form and that validation errors show.

I think if the test coverage was added this would show the failure.

Will try updating the trait here #2785047: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page because there is test for the redirect on save. See if it indeed fails

tedbow’s picture

+++ b/core/lib/Drupal/Core/Form/DialogFormTrait.php
@@ -0,0 +1,201 @@
+   *   If TRUE the create submit button will be created.q

Weird "q" at the end of line. I probably did this.

sam152’s picture

Manual reviewing the UI, this is looking really cool. One interesting observation (which is probably entirely follow-up or wont-fix territory) is that hitting "Cancel" gets a "close modal" command from the server and then does it's thing, but the actual "X" button at the top right of the modal has a way to dismiss it instantly. I wonder if we can use the same mechanism on both buttons.

While the trait is being discussed, I've reviewed all the non-trait code. There are a few standards violations that the patch introduces, which we can fix in a round of nits once the patch is ready.

  1. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    index 0000000000..dc4e14be13
    --- /dev/null
    
    --- /dev/null
    +++ b/core/modules/workflows/src/Form/WorkflowEntityForm.php
    

    If we aren't intending on use this form as it is and it's designed to be extended, should possibly be called "WorkflowEntityFormBase" or be made abstract. If its primary function is making the other forms that extend it modal-friendly, possibly should indicate that in its name too?

  2. +++ b/core/modules/workflows/src/Form/WorkflowEntityForm.php
    @@ -0,0 +1,34 @@
    +/**
    + * Class WorkflowEntityForm.
    + */
    

    Some better docs here maybe?

  3. +++ b/core/modules/workflows/src/Form/WorkflowEntityForm.php
    @@ -0,0 +1,34 @@
    +class WorkflowEntityForm extends EntityForm {
    +
    +  use DialogFormTrait;
    
    +++ b/core/modules/workflows/src/Form/WorkflowStateAddForm.php
    @@ -2,14 +2,16 @@
    +class WorkflowStateAddForm extends WorkflowEntityForm {
    +
    +  use DialogFormTrait;
    
    +++ b/core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
    @@ -2,15 +2,17 @@
    +class WorkflowTransitionAddForm extends WorkflowEntityForm {
    +
    +  use DialogFormTrait;
    

    If the base uses the trait, do we have to use it again on the classes that extend it?

  4. +++ b/core/modules/workflows/src/Form/WorkflowStateAddForm.php
    @@ -108,15 +110,11 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle($workflow = NULL) {
    +    $title = $this->t('Add a new state to the @workflow', ['@workflow' => $workflow->label()]);
    +    return $title;
    

    Once #2894499: Rename 'Editorial workflow' to 'Editorial' gets in, this will read "Add a new state of the editorial". Just something to be aware of.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new6.77 KB
new45.45 KB

Expanding WorkflowEditFormTest for covering submitting the edit and delete transition&state forms, and verifying that we are still on the same path and the right message is shown.

Status: Needs review » Needs work

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

timmillwood’s picture

Status: Needs work » Needs review
StatusFileSize
new5.03 KB
new43.56 KB

In #2785047: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page it was decided not to use a common trait, so here's a patch moving the trait back to Workflows, but with many of the advances we've seen since the last workflow specific trait.

tim.plunkett’s picture

+++ b/core/modules/workflows/src/Form/DialogFormTrait.php
@@ -120,7 +119,9 @@ public function submitFormDialog(array &$form, FormStateInterface $form_state) {
+      $command = new RedirectCommand($workflow->toUrl('edit-form')->toString());

Per RedirectCommand's constructor, this should have a ->toAbsolute() call before the ->toString()

Removing the tag I added when this was touching \Drupal\Core\Form

timmillwood’s picture

StatusFileSize
new743 bytes
new43.58 KB

Thanks @tim.plunkett!

manuel garcia’s picture

Assigned: timmillwood » manuel garcia
Status: Needs review » Needs work

#2894499: Rename 'Editorial workflow' to 'Editorial' has landed, so we should now do #57 9, 10, and 11

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new43.45 KB

First a reroll, manually fixed conflicts on:

  • core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
  • core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
  • core/modules/workflows/src/Form/WorkflowStateDeleteForm.php
manuel garcia’s picture

Assigned: manuel garcia » Unassigned
StatusFileSize
new4.51 KB
new44.91 KB

And here the changes adjusting the workflow strings due to #2894499: Rename 'Editorial workflow' to 'Editorial'. Fixes #57 9, 10, and 11 - I also searched for "@workflow" in order to find other possible places to fix.

Modified:

  • core/modules/content_moderation/src/Form/WorkflowTypeEditForm.php
  • core/modules/workflows/src/Form/WorkflowStateAddForm.php
  • core/modules/workflows/src/Form/WorkflowStateEditForm.php
  • core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
  • core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
tacituseu’s picture

Title: Use modals for creating, updating, and deleting workflows, with a new ModalFormTrait » Use modals for creating, updating, and deleting workflows, with a new DialogFormTrait
tedbow’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,154 @@
    +   * @param string $dialog_selector
    +   *   The CSS selector for the associated dialog.
    

    Is this necessary anymore? I think I added this change when the trait was in #2896535: Create a helper trait for Forms in ajax dialogs but since this trait is only used inside the workflow module now this will never be used.

    If it is removed you won't have the need for test coverage for different dialog types.

  2. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,154 @@
    +    if (!empty($form['actions']['submit'])) {
    ...
    +    if (!empty($form['actions']['cancel'])) {
    

    Are there case in the workflow module where there will not be a "submit" button? a "cancel" button?

    If not these if statements and $ajax_callback_added could be removed.

  3. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,154 @@
    +          'event' => 'click',
    

    Does the event need to be specified here? Will it work without it?

  4. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,154 @@
    +      $form['#attributes']['id'] = 'dialog-form';
    ...
    +    ]);
    ...
    +      $command = new ReplaceCommand('#dialog-form', $form);
    

    It maybe better to use data-drupal-selector rather id for replaement as we did in #2785047: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page but you want to look at that patch to see how we got around #2897377: $form['#attributes']['data-drupal-selector'] is set to a random value so can't be used for its intended purpose

  5. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,154 @@
    +    return in_array($this->getRequestWrapperFormat(), [
    +      'drupal_ajax',
    +      'drupal_dialog',
    +      'drupal_modal',
    +      'drupal_dialog.off_canvas',
    

    This should only need to check for "drupal_modal" now that is trait only used within Workflow and only used in modals and not other types of dialogs.

    Also I think having "drupal_ajax" could be a problem because this would pick up a ajax callback even if the form was not in dialog.

    We solved by sending the dialogType back on submit. See the interdiff here #2785047-70: In Outside In mode, form validation messages should appear in the off-canvas tray, not the main page.

+++ b/core/modules/workflows/src/Form/DialogFormTrait.php
@@ -0,0 +1,154 @@
+      $command = new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString());

+++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
@@ -82,22 +83,36 @@ public function form(array $form, FormStateInterface $form_state) {
+    $options = ['query' => ['destination' => $this->getEntity()->toUrl('edit-form')->toString()]];

Looks like the WorkflowEditForm still uses the query string destination logic I added in previously but the trait itself is now not using it for a redirect. I think it can be removed from the form.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new45.11 KB

Thanks @tedbow for the review!

First a reroll, manually fixed conflicts on:

  • core/modules/workflows/tests/src/Functional/WorkflowUiTest.php
  • core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
  • core/modules/workflows/src/Form/WorkflowTransitionDeleteForm.php
  • core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
timmillwood’s picture

Assigned: Unassigned » timmillwood

I'm nearly done fixing the issues raised by @tedbow, patch coming soon!

timmillwood’s picture

Assigned: timmillwood » Unassigned
StatusFileSize
new7.25 KB
new43.44 KB

Fixing all items mentioned by @tedbow in #134.

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

Status: Needs review » Needs work

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

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new5.23 KB
new43.41 KB

Updating the patch due to #2849827: Move workflow "settings" setters and getters to WorkflowTypeInterface, and fixing coding style violations found by the bot.
I think however that displaying the form errors on the modal forms no longer works so this should still fail.

timmillwood’s picture

The last submitted patch, 140: 2830584-140.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 141: 2830584-141.patch, failed testing. View results

timmillwood’s picture

Status: Needs work » Needs review

#141 fixes the failes from #140, but the #141 fails looks to be unrelated.

tedbow’s picture

StatusFileSize
new3.97 KB
new44.56 KB

ok I think only #134.3 was the only remain item from my review.
So fixed in this patch. Let me know if we need "click" event specified.

The other changes to this patch are test related.

#141 was NOT failing on DrupalCI but was failing for me locally.
Ajax dialog testing is tricky and we have seen a lot random failures on DrupalCI. but problem is usually works locally but doesn't on DrupalCI which is the opposite of what I am seeing now.
@see #2870146: Even more random fails in \Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest
#2830485: \Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest fails randomly
and #2848177: More \Drupal\Tests\outside_in\FunctionalJavascript\OutsideInBlockFormTest random fails

Most of these revolve around waiting for events to happen

I think this cause of my local fails

$this->assertSession()->assertWaitOnAjaxRequest();
this->assertSession()->addressEquals($path);
$this->assertSession()->pageTextContains('Saved Drafty state.');

assertWaitOnAjaxRequest is tricky with ajax redirect. I think what is happening locally is that that assert passes without the redirect being done.
Then the path 1 passes and the last one fails.

I have changed this to not worry about ajax all and just wait for the "saved" method to appear on the page and then check the path.

manuel garcia’s picture

Thanks @timmillwood & @tedbow!

+++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
@@ -187,9 +182,23 @@ public function testWorkflowTransitionsForm() {
+  protected function assertElementVisibleAfterWait($selector, $locator, $timeout = 10000) {

While I see how this method makes the tests easier to follow, can't help but think that this would also be useful on other situations... let's find a better place for it... perhaps JavascriptTestBase?

tedbow’s picture

@Manuel Garcia should we make a follow up to add assertElementVisibleAfterWait \Drupal\FunctionalJavascriptTests\JSWebAssert where waitForElementVisible lives.

manuel garcia’s picture

@tedbow follow up to move it to JSWebAssert makes sense to me

timmillwood’s picture

Thanks for the patch update @tedbow, looks RTBC ready to me!

tedbow’s picture

Status: Needs review » Needs work

created #2898777: Add assertElementVisibleAfterWait to JSWebAssert

@timmillwood yes looks very close.

tedbow’s picture

Status: Needs work » Needs review
StatusFileSize
new875 bytes
new44.67 KB

Added to @todo to remove assertElementVisibleAfterWait after #2898777: Add assertElementVisibleAfterWait to JSWebAssert

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

I think this is looking good now, thanks @tedbow.

I'm going to RTBC, but think this needs a +1 from @tedbow and / or Manuel as I wrote a lot of the patch.

tedbow’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/workflows/src/Form/DialogFormTrait.php
@@ -0,0 +1,129 @@
+  public function closeDialog(array &$form, FormStateInterface $form_state) {

We no longer need either 1 of these parameters to this function

Otherwise than that +1 on RTBC

tedbow’s picture

Status: Needs work » Reviewed & tested by the community

#153 whoops I was confused with closeDialog() in another version I was working. closeDialog() is an ajax callback so we should leave those parameters.

RTBC!

manuel garcia’s picture

StatusFileSize
new4.14 MB

Had a read through the patch, looks great.
Applied it and had did some manual testing, everything looks awesome +1 to RTBC

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 151: 2830584-151.patch, failed testing. View results

manuel garcia’s picture

Issue tags: +Needs reroll
sam152’s picture

Issue tags: -Needs reroll
StatusFileSize
new42.63 KB

Straight up reroll.

sam152’s picture

Status: Needs work » Needs review
manuel garcia’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @Sam152!
Back to RTBC assuming patch comes back green :)

sam152’s picture

Status: Reviewed & tested by the community » Needs work

Here are some questions and nits I picked up reviewing this. Some of them are borderline style things, but I think a few of them would probably hold up commit if reviewed by a core committer.

  1. diff --git a/core/modules/content_moderation/src/Form/ContentModerationConfigureEntityTypesForm.php b/core/modules/content_moderation/src/Form/ContentModerationConfigureEntityTypesForm.php
    index 3efcafb..03915c3 100644
    --- a/core/modules/content_moderation/src/Form/ContentModerationConfigureEntityTypesForm.php
    +++ b/core/modules/content_moderation/src/Form/ContentModerationConfigureEntityTypesForm.php
    ...
    diff --git a/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php b/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php
    new file mode 100644
    index 0000000..55ffcce
    --- /dev/null
    +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php
    

    Would this be an easier commit if this was in its own issue? It's new tests for a feature that we already have, not introduced in this patch right?

  2. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php
    @@ -0,0 +1,85 @@
    +    $this->assertEqual('Basic block', $selected_block_content->getText());
    ...
    +    $this->assertEqual('none', $selected_block_content->getText());
    

    May as well use "assertEquals" so we're not introducing deprecated method calls.

  3. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,129 @@
    +   * @return \Drupal\Core\Ajax\AjaxResponse
    +   *   An AJAX response that display validation error messages or redirects
    +   *   to a URL
    

    Missing full stop.

  4. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,129 @@
    +    $response = new AjaxResponse();
    +    if ($form_state->hasAnyErrors()) {
    +      $form['status_messages'] = [
    +        '#type' => 'status_messages',
    +        '#weight' => -1000,
    +      ];
    +      $command = new ReplaceCommand('[data-drupal-selector="' . $form['#attributes']['data-drupal-selector'] . '"]', $form);
    +    }
    +    else {
    +      /** @var \Drupal\workflows\WorkflowInterface $workflow */
    +      $workflow = $this->workflow ?: $this->getEntity();
    +      $command = new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString());
    +    }
    +    return $response->addCommand($command);
    

    Why not just call $response->addCommand() twice and return "$response" instead of introducing $command.

  5. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,129 @@
    +   * @return bool|\Drupal\Core\Ajax\AjaxResponse
    +   *   An AJAX response that display validation error messages.
    

    I don't think this ever returns a bool and the method doesn't display validation error messages.

  6. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,129 @@
    +  /**
    +   * @return mixed
    +   */
    

    Can we be a bit more descriptive here?

  7. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    @@ -111,22 +112,33 @@ public function form(array $form, FormStateInterface $form_state) {
    +          'url' => Url::fromRoute('entity.workflow.edit_state_form',
    +            ['workflow' => $workflow->id(), 'workflow_state' => $state->id()]
    +          ),
    

    I think this violates cs.

  8. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    @@ -111,22 +112,33 @@ public function form(array $form, FormStateInterface $form_state) {
    +          'url' => Url::fromRoute('entity.workflow.delete_state_form',
    +            [
    +              'workflow' => $workflow->id(),
    +              'workflow_state' => $state->id(),
    +            ]
    +          ),
    

    I think this violates coding standards, or at the very least isn't accepted practice.

  9. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    @@ -147,7 +159,12 @@ public function form(array $form, FormStateInterface $form_state) {
    +      '#url' => Url::fromRoute('entity.workflow.add_state_form',
    +        ['workflow' => $workflow->id()]
    +      ),
    

    I think this violates coding standards.

  10. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    @@ -178,13 +195,17 @@ public function form(array $form, FormStateInterface $form_state) {
    +        'url' => Url::fromRoute('entity.workflow.edit_transition_form',
    +          ['workflow' => $workflow->id(), 'workflow_transition' => $transition->id()]
    +        ),
    

    Lets be consistent with large array arguments we use in this whole file.

  11. +++ b/core/modules/workflows/src/Form/WorkflowEntityFormBase.php
    @@ -0,0 +1,33 @@
    + * Class WorkflowEntityForm.
    

    Maybe we can describe this better.

  12. +++ b/core/modules/workflows/src/Form/WorkflowStateAddForm.php
    @@ -168,15 +167,11 @@ public function save(array $form, FormStateInterface $form_state) {
    +    $title = $this->t('Add a new state to the @workflow workflow', ['@workflow' => $workflow->label()]);
    +    return $title;
    

    May as well just return here.

  13. +++ b/core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
    @@ -139,9 +138,22 @@ protected function copyFormValuesToEntity(EntityInterface $entity, array $form,
         $values = $form_state->getValues();
         $entity->getTypePlugin()->addTransition($values['id'], $values['label'], array_filter($values['from']), $values['to']);
    +
    +    // Workflow::addTransition uses exceptions for validation, ignore them here
    +    // so that the form validation takes place.
    +    // @todo Remove need for try-catch https://www.drupal.org/node/2895310
    +    try {
    +      /** @var \Drupal\workflows\WorkflowInterface $entity */
    +      $values = $form_state->getValues();
    +      $entity->getTypePlugin()->addTransition($values['id'], $values['label'], array_filter($values['from']), $values['to']);
    +    }
    +    catch (\InvalidArgumentException $e) {
    +      // Do nothing, if there is an exception we want validation to handle it.
    +    }
    

    This could have been an error in the re-roll. Also, is this a general improvement or something specific to the modals? Seems possibly out of scope.

    Edit: yup, I definitely botched the reroll, and the tests failed so this is in-scope.

  14. +++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
    @@ -0,0 +1,207 @@
    +
    +
    

    Extra new line

  15. +++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
    @@ -0,0 +1,207 @@
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $modal = $this->assertSession()->waitForElementVisible('css', '#drupal-modal');
    

    Do we have to do two waits here?

  16. +++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
    @@ -0,0 +1,207 @@
    +
    +
    

    Double newline

timmillwood’s picture

Status: Needs work » Needs review
StatusFileSize
new9.6 KB
new42.76 KB

#161.1 - This patch is not just about adding modals, it's about bringing consistency on the Workflow edit form. These tests are testing that consistency. I don't think there's any harm in adding them here.
#161.2 - Fixed
#161.3 - Fixed
#161.4 - Yeh, that works, done.
#161.5 - I think you're right.
#161.6 - Yes we can.
#161.7 - Updated, just incase.
#161.8 - ok
#161.9 - ok
#161.10 - Went through all uses of fromRoute() to make sure they all use the same syntax.
#161.11 - Tried.
#161.12 - yes
#161.13 - Fixed
#161.14 - Where?
#161.15 - Not sure? @Manuel Garcia or @tedbow?
#161.16 - Where?

manuel garcia’s picture

Thanks both, great stuf!
Re #161.15 I believe we do... the first waits for the ajax request to happen, then the element has to be rendered before the element is visible... we could run into strange failures at times if we don't do this as far as I understand.

tedbow’s picture

re #161.15 yes would recommend leaving the 2 different waits. assertWaitOnAjaxRequest() also checks for animation as well ajax request finishing.

We have run into a lot of random failures trying to figure out when dialog show up in the settings tray module see #145.

I think we want to leave assertWaitOnAjaxRequest() to make sure the ajax request is completed and the dialog is set. Then the next line checks waits for text to occur on the page.
I am pretty sure if you remove assertWaitOnAjaxRequest() it would not cause the test to fail right now but it seems to be the luck of the draw.

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.

sam152’s picture

StatusFileSize
new8.43 KB
new40.56 KB

Reviewed this again, here is a patch which removes the try/catch in the transition forms and has a few other little cs fixes. Here is my 2c on why we shouldn't be adding the try/catch here:

  • It adds them to transition forms and not state forms, seems like an inconsistency.
  • I think it's contentious if it's really the right approach to be using and thus might hold up an otherwise great UI improvement.
  • The scope of this issue is already wide, this will have a much better chance of getting committed if we focus specifically on the modals and not include bugfixes that don't have corresponding testing.

It looks like work is already underway to fix this in #2886567: Adding a workflow state or transition with an integer ID results in unrecoverable fatal errors. Lets just follow-up there with the validation issues.

If we can agree on that, the rest of this looks great and I'm +1 to RTBC.

Status: Needs review » Needs work

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

sam152’s picture

Status: Needs work » Needs review
timmillwood’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs screenshots, -Needs issue summary update
StatusFileSize
new39.31 KB
new33.16 KB
new17.71 KB

Thanks @Sam152, I agree with the +1 to RTBC, so let's to this.

The try/catch was added to fix #81, it looks like this is no longer an issue.

+++ b/core/modules/workflows/src/Form/DialogFormTrait.php
@@ -86,18 +86,20 @@ public function noSubmit(array &$form, FormStateInterface $form_state) {
-      return (new AjaxResponse())->addCommand(new ReplaceCommand('[data-drupal-selector="' . $form['#attributes']['data-drupal-selector'] . '"]', $form));
...
-      return (new AjaxResponse())->addCommand(new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString()));

I thought this approach was fine, it tidies up the method and is also consistent with elsewhere in the trait, but ok either way.

Here's some screenshots of the state, transition, and delete modals based on #166:

sam152’s picture

The command thing was purely style, happy with either, probably shouldn't have changed it.

Either way +1 RTBC and will follow-up with the try/catch in the other issue.

wim leers’s picture

Status: Reviewed & tested by the community » Needs review

Mostly nits, but 2 important questions: one thing that should be @internal and a test that may need to be moved?

  1. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php
    @@ -0,0 +1,85 @@
    +/**
    + * AJAX modal tests for the workflow type edit form.
    + *
    + * @group content_moderation
    + */
    +class WorkflowTypeEditFormTest extends JavascriptTestBase {
    

    This sounds/feels like it belongs in the workflows module, not the content_moderation module?

  2. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php
    @@ -0,0 +1,85 @@
    +    $bundle = BlockContentType::create([
    +      'id' => 'basic',
    +      'label' => 'Basic block',
    +      'revision' => FALSE,
    +    ]);
    +    $bundle->save();
    

    Nit: no need for the intermediate $bundle variable.

    Also: Basic block is an actual custom block type, provided by standard. I'm not a fan of creating test config with identical ids/labels, but that's not exactly the same. I think a random (or silly!) name is better. (Yes, this is partly why I've added so many llamas to core.)

  3. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/WorkflowTypeEditFormTest.php
    @@ -0,0 +1,85 @@
    +    $this->drupalGet('admin/config/workflow/workflows/manage/editorial');
    

    Ahh, the editorial workflow is default content provided by the content_moderation module, this is probably why.

  4. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,131 @@
    +/**
    + * Provides utilities for forms that want to be rendered in dialogs.
    + */
    +trait DialogFormTrait {
    

    Should be marked @internal AFAICT.

  5. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,131 @@
    +   * Close dialog #ajax callback.
    

    Supernit: s/Close/Closes/

  6. +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php
    @@ -147,7 +158,12 @@ public function form(array $form, FormStateInterface $form_state) {
    +      '#url' => Url::fromRoute('entity.workflow.add_state_form', [
    

    Using Url::fromRoute(): 👍

  7. +++ b/core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
    @@ -195,15 +194,11 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle($workflow = NULL) {
    
    +++ b/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
    @@ -204,30 +203,11 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle($workflow = NULL, $workflow_transition) {
    

    Nit: missing typehints?

sam152’s picture

Status: Needs review » Needs work

The form WorkflowTypeEditFormTest is testing used to be called WorkflowTypeEditForm. Since #2896722, it's now called ContentModerationConfigureEntityTypesForm, so it should probably be renamed to ContentModerationConfigureEntityTypesFormTest.

@internal makes a lot of sense for the trait and the rest are all good nits.

wim leers’s picture

#172: that rename would've addressed the questions/concerns in #171.1. Thanks!

manuel garcia’s picture

Assigned: Unassigned » manuel garcia

Thanks all, working now on #171

manuel garcia’s picture

Assigned: manuel garcia » Unassigned
Status: Needs work » Needs review
StatusFileSize
new8.71 KB
new41.35 KB

Re #171
1. Renamed to ContentModerationConfigureEntityTypesFormTest as suggested in #172.
2. I agree. Also, an Epic block is always better than a Basic block.
4. done
5. done
7. Fixed, also on WorkflowStateAddForm, WorkflowTransitionEditForm and WorkflowStateEditForm.

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Looking epic, think we can go back to RTBC!

timmillwood’s picture

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

This is a "should have" for Workflows to be stable, so will need to go in 8.4.x.

wim leers’s picture

  1. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/ContentModerationConfigureEntityTypesFormTest.php
    @@ -32,45 +32,45 @@ public function setUp() {
    +      'id' => 'epic',
    +      'label' => 'Epic block',
    ...
    -    // Open the 'Custom block types' modal and select 'Basic block'.
    +    // Open the 'Custom block types' modal and select 'Epic block'.
    

    👏😀

  2. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/ContentModerationConfigureEntityTypesFormTest.php
    @@ -32,45 +32,45 @@ public function setUp() {
    +    ])->save();
    +
       }
    

    Supernit: unnecessary blank line. Can be fixed on commit.

tim.plunkett’s picture

  1. +++ b/core/modules/workflows/src/Form/WorkflowStateEditForm.php
    @@ -168,7 +169,7 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow = NULL, $workflow_state) {
    
    +++ b/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
    @@ -205,7 +206,7 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow = NULL, $workflow_transition) {
    

    I was reasonably sure this is invalid PHP, but I was wrong. Either way, having an optional parameter followed by a required parameter makes no sense.

  2. +++ b/core/modules/workflows/src/Form/WorkflowStateAddForm.php
    @@ -169,7 +170,7 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow = NULL) {
         return $this->t('Add a new state to the @workflow workflow', ['@workflow' => $workflow->label()]);
    
    +++ b/core/modules/workflows/src/Form/WorkflowStateEditForm.php
    @@ -168,7 +169,7 @@ public function save(array $form, FormStateInterface $form_state) {
         $title = $this->t('Edit the @state state for the @workflow workflow', ['@state' => $workflow->getTypePlugin()->getState($workflow_state)->label(), '@workflow' => $workflow->label()]);
         return $title;
    
    +++ b/core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
    @@ -196,7 +197,7 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow = NULL) {
         $title = $this->t('Add a new transition to the @workflow workflow', ['@workflow' => $workflow->label()]);
         return $title;
    

    This code has no handling for the case if $workflow is NULL. I'd just as soon drop the = NULL than add an if()... Also the $title variable is unneeded.

wim leers’s picture

#179: I agree. I saw this too, but forgot to comment on it.

wim leers’s picture

Status: Reviewed & tested by the community » Needs work

For #179/#180.

timmillwood’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new3.58 KB
new41.41 KB

Thanks @tim.plunkett and @Wim Leers.

wim leers’s picture

RTBC++

sam152’s picture

Component: content_moderation.module » workflows.module

As this primarily affects workflows, updating the component as mentioned in #2755073: WI: Content Moderation module roadmap.

sam152’s picture

StatusFileSize
new40.26 KB

Rerolled.

Status: Reviewed & tested by the community » Needs work

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

Bojhan’s picture

What about just saying "Transition label" and "State label" then you dont need the description.

sam152’s picture

Status: Needs work » Needs review
StatusFileSize
new2.93 KB
new40.45 KB

I botched the reroll.

sam152’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC. Re: #187, that makes a tonne of sense but is out of scope.

I've opened #2902247: Make #title of the "label" fields in the Workflow(Transition|State)(Add|Edit)Form clearer and remove the description. for this.

xjm’s picture

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

I just saw that (a) this was not already committed (I thought it had been) and (b) that @timmillwood moved it back to 8.4.x. After the alpha freeze deadline we only decide after commit whether to backport things, and only until the beta freeze deadline. We don't grant any advance exceptions for things because there's no guarantee they will be committable in time for the release. Reference: https://www.drupal.org/core/d8-allowed-changes#alpha

Setting to 8.5.x so it's clear that this patch contains changes that are only allowed in a minor; otherwise it will be stuck in the patch queue. If another committer reviews this today and finds it ready I could see backporting it today early during the commit freeze.

Bojhan’s picture

@Sam152 Thanks!

larowlan’s picture

Status: Reviewed & tested by the community » Needs review

This looks great, glad to see some big-time use of the dialogs API in core. Will provide a great example for people to reference.
And some awesome test coverage, really thorough.

A couple of observations that are largely nits, but one regression

  1. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/ContentModerationConfigureEntityTypesFormTest.php
    @@ -0,0 +1,84 @@
    +    $user = $this->drupalCreateUser(['administer workflows']);
    +    $this->drupalLogin($user);
    

    nit: no need for the $user variable here

  2. +++ b/core/modules/content_moderation/tests/src/FunctionalJavascript/ContentModerationConfigureEntityTypesFormTest.php
    @@ -0,0 +1,84 @@
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $modal = $this->assertSession()->waitForElementVisible('css', '#drupal-modal');
    ...
    +    $save_button = $this->assertSession()->waitForElementVisible('css', '.ui-dialog button:contains(Save)');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $modal = $this->assertSession()->waitForElementVisible('css', '#drupal-modal');
    ...
    +    $this->assertSession()->waitForElementVisible('css', '[data-drupal-selector="edit-bundles-epic"]')->uncheck();
    ...
    +    $save_button = $this->assertSession()->waitForElementVisible('css', '.ui-dialog button:contains(Save)');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    ...
    +    $selected_block_content = $this->assertSession()->waitForElementVisible('named', ['id', 'selected-block_content']);
    

    we can put $this->assertSession() in a variable here, and save creating N instances.

  3. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,134 @@
    + * Provides utilities for forms that want to be rendered in dialogs.
    

    Suggest 'Provides a utility trait to simplify rendering forms in a dialog'

  4. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,134 @@
    +    if ($this->getRequestWrapperFormat() != 'drupal_modal') {
    

    nit !==

  5. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,134 @@
    +   * This allows modal dialog to using ::submitCallback to validate and submit
    +   * the form via one ajax required.
    

    The english here is slightly off.

  6. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,134 @@
    +      $response->addCommand(new ReplaceCommand('[data-drupal-selector="' . $form['#attributes']['data-drupal-selector'] . '"]', $form));
    

    we can return here and avoid the else. Makes it easier to understand

  7. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,134 @@
    +   *   An AJAX response that display validation error messages.
    

    displays

  8. +++ b/core/modules/workflows/src/Form/WorkflowStateAddForm.php
    @@ -168,15 +168,10 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow) {
    +    return $this->t('Add a new state to the @workflow workflow', ['@workflow' => $workflow->label()]);
    
    +++ b/core/modules/workflows/src/Form/WorkflowStateEditForm.php
    @@ -207,29 +167,11 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow, $workflow_state) {
    +    $title = $this->t('Edit the @state state for the @workflow workflow', ['@state' => $workflow->getTypePlugin()->getState($workflow_state)->label(), '@workflow' => $workflow->label()]);
    +    return $title;
    
    +++ b/core/modules/workflows/src/Form/WorkflowTransitionAddForm.php
    @@ -195,15 +195,11 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow) {
    +    $title = $this->t('Add a new transition to the @workflow workflow', ['@workflow' => $workflow->label()]);
    +    return $title;
    
    +++ b/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
    @@ -204,30 +204,11 @@ public function save(array $form, FormStateInterface $form_state) {
    +  public function getTitle(WorkflowInterface $workflow, $workflow_transition) {
    +    $title = $this->t('Edit the @transition transition for the @workflow workflow', ['@transition' => $workflow->getTypePlugin()->getTransition($workflow_transition)->label(), '@workflow' => $workflow->label()]);
    +    return $title;
    

    I don't think there is any test coverage for these?

  9. +++ b/core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
    @@ -101,7 +101,7 @@ public function form(array $form, FormStateInterface $form_state) {
    -      '#type' => 'radios',
    +      '#type' => 'select',
    

    What is the reason for this change - feels like a regression/reroll issue?

  10. +++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
    @@ -0,0 +1,205 @@
    +    $user = $this->drupalCreateUser(['administer workflows']);
    +    $this->drupalLogin($user);
    

    Same again here, not sure we need the $user variable

  11. +++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
    @@ -0,0 +1,205 @@
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $modal = $this->assertSession()->waitForElementVisible('css', '#drupal-modal');
    ...
    +    $input = $this->assertSession()->elementExists('css', '#drupal-modal .form-item-label input[name="label"]');
    ...
    +    $save_button = $this->assertSession()->waitForElementVisible('css', '.ui-dialog-buttonpane .button--primary');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $this->assertSession()->pageTextContains('Label field is required.');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $input = $this->assertSession()->elementExists('css', '#drupal-modal .form-item-label input[name="label"]');
    ...
    +    $save_button = $this->assertSession()->waitForElementVisible('css', '.ui-dialog-buttonpane .button--primary');
    ...
    +    $this->assertSession()->addressEquals($path);
    ...
    +    $delete_button = $this->assertSession()->waitForElementVisible('css', '[data-drupal-selector="edit-states-draft"] a:contains(Delete)');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $modal = $this->assertSession()->waitForElementVisible('css', '#drupal-modal');
    ...
    +    $delete_button = $this->assertSession()->waitForElementVisible('css', '.ui-dialog-buttonpane .button--primary');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    ...
    +    $delete_button = $this->assertSession()->waitForElementVisible('css', '[data-drupal-selector="edit-states-draft"] a:contains(Delete)');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $modal = $this->assertSession()->waitForElementVisible('css', '#drupal-modal');
    ...
    +    $delete_button = $this->assertSession()->waitForElementVisible('css', '.ui-dialog-buttonpane .button--primary');
    ...
    +    $this->assertSession()->addressEquals($path);
    

    Same story here, we're creating loads of objects we don't need. Let's just do $assert = $this->assertSession() and reuse it

  12. +++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
    @@ -0,0 +1,205 @@
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $modal = $this->assertSession()->waitForElementVisible('css', '#drupal-modal');
    ...
    +    $label_input = $this->assertSession()->elementExists('css', '#drupal-modal .form-item-label input[name="label"]');
    ...
    +    $save_button = $this->assertSession()->waitForElementVisible('css', '.ui-dialog-buttonpane .button--primary');
    ...
    +    $this->assertSession()->assertWaitOnAjaxRequest();
    +    $this->assertSession()->pageTextContains('Label field is required.');
    

    and here too

  13. +++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
    @@ -0,0 +1,205 @@
    +    $label_input->setValue('Publishedlicius');
    

    <3

timmillwood’s picture

StatusFileSize
new19.91 KB
new39.68 KB

Trying to resolve all issues in #192.

Status: Needs review » Needs work

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

timmillwood’s picture

Status: Needs work » Needs review
StatusFileSize
new1.66 KB
new39.73 KB

Fixing tests.

Status: Needs review » Needs work

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

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new1.65 KB
new38.22 KB

This should fix the failing tests =)

jofitz’s picture

StatusFileSize
new1.77 KB
new38.25 KB

Coding standards corrections.

manuel garcia’s picture

Status: Needs review » Reviewed & tested by the community

I think we're ready to go back to RTBC =)

timmillwood’s picture

+1 for RTBC.

xjm’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/themes/seven/css/components/dropbutton.component.css
@@ -203,8 +203,22 @@
   -webkit-transition: none;
   transition: none;
 }
-.dropbutton-single .dropbutton-action a.use-ajax {
-  float: left;
+.dropbutton .dropbutton-action .ajax-progress {
+  position: absolute;
+  z-index: 2;
+  top: 0.2em;
+  right: 0.2em;
+  padding: 0 0 0 0.1em;
+}
+.dropbutton-multiple .dropbutton-action .ajax-progress {
+  right: 2.2em;
+  top: 0.15em;
+  margin-right: 0;
+}
+.dropbutton-multiple .secondary-action .ajax-progress {
+  top: auto;
+  bottom: 0.3em;
+  right: 2em;

Hm, this should probably be going in the module's CSS rather than Seven's? That or it's a separate issue that's straight visual bugfix.

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

@xjm - this is a bug, but a very related one. It fixes the Ajax spinner from falling onto a new line in drop buttons. it doesn't seem worth creating a new issue for this.

xjm’s picture

Status: Reviewed & tested by the community » Needs work

Thanks @timmillwood. Please do create a new issue for that bugfix so that we can direct the frontend framework managers to a 5K CSS patch on an issue with three-or-so comments rather than a 200-comment feature addition that's a lot of Form API. :) (The frontend framework managers have limited availability but the CSS would stop me at least from committing this.) Also, bugfixes can potentially be backported during RC and maybe during a patch release, whereas this feature addition is 8.5.x only.

Edit: References on scoping:
https://www.drupal.org/core/scope#context
https://www.drupal.org/core/scope#release-schedule

tim.plunkett’s picture

Status: Needs work » Needs review
+++ b/core/modules/workflows/src/Form/DialogFormTrait.php
@@ -0,0 +1,133 @@
+    $form['actions']['cancel'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Cancel'),
+      '#weight' => 100,
+      '#submit' => ['::noSubmit'],
+      '#limit_validation_errors' => [],
+      '#ajax' => [
+        'dialogType' => 'modal',
+        'callback' => '::closeDialog',
+      ],
+    ];
...
+  public function noSubmit(array &$form, FormStateInterface $form_state) {
...
+  public function closeDialog(array &$form, FormStateInterface $form_state) {

You shouldn't need this "button" at all. I believe the style guide calls for cancel to be a link, as followed by ConfirmFormBase.

You could make a link, and if you give it the class dialog-cancel, then dialog.ajax.js picks it up automatically. I figured this out when dealing with Layout Builder's dialogs.

tim.plunkett’s picture

Status: Needs review » Needs work

Weird status crosspost...

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new806 bytes
new37.47 KB

Fair enough, created the separate issue to fix the bug with the throbbers, please have a look =):
#2909882: Throbbers showing within dropbuttons jump to next line

Here is the patch now without those changes.

timmillwood’s picture

StatusFileSize
new2.5 KB
new36.48 KB

Here's a patch implementing @tim.plunkett's suggestion in #204. It allows us to remove two classes from the DialogFormTrait too!

Status: Needs review » Needs work

The last submitted patch, 207: 2830584-207.patch, failed testing. View results

tim.plunkett’s picture

+++ b/core/modules/workflows/tests/src/FunctionalJavascript/WorkflowEditFormTest.php
@@ -0,0 +1,208 @@
+    $this->click('.ui-dialog-buttonpane button:contains(Cancel)');
...
+    $this->click('.ui-dialog-buttonpane button:contains(Cancel)');

This is a link now

timmillwood’s picture

Status: Needs work » Needs review
StatusFileSize
new3.93 KB
new36.65 KB

Fixing the broken tests.

manuel garcia’s picture

Status: Needs review » Reviewed & tested by the community

Beautiful @timmillwood thanks!

OK, so #203 and #204 have been addressed... back to RTBC

vijaycs85’s picture

+1 to RTBC. Patch at #210 still applies cleanly.

manuel garcia’s picture

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 210: 2830584-210.patch, failed testing. View results

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new36.57 KB

Rerolling, 3 way merge did the trick.

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC then!

xjm’s picture

So earlier on this issue, we talked about adding the trait to Workflows and not the Form API in order to have more flexibility to backport it without disruption. However, at this point, Workflows is already stable without this UI improvement, and it's just going to go into 8.5.x anyway. Part of my hesitation every time I open this issue in a tab is that I don't think we want to end up with three separate variants of a similar API for this, Settings Tray, and Layout Builder.

So at this point, I'm wondering if it makes sense to do #2896535: Create a helper trait for Forms in ajax dialogs first and build this as well as the Layout Builder's version on top of that, with a followup to refactor Settings Tray to use it also. I'd also prefer to have @tim.plunkett's explicit signoff (he's provided several reviews) since some version of this should end up in the Form API in one way or another.

Leaving at RTBC since this isn't a blocker (and I don't want to push the issue to change direction without confirming the approach with others first).

tim.plunkett’s picture

If there is still desire to do something generic, this would need work.

Additionally, I have some questions on why some parts of this are necessary.

  1. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,101 @@
    +    if ($this->getRequestWrapperFormat() !== 'drupal_modal') {
    +      return;
    +    }
    ...
    +  protected function getRequestWrapperFormat() {
    +    return $this->getRequest()
    +      ->get(MainContentViewSubscriber::WRAPPER_FORMAT);
    +  }
    

    This is similar to LB's code, except instead of drupal_modal we need to check for drupal_dialog.off_canvas.
    No one has come up with a generic way to decide what to check for.

  2. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,101 @@
    +      'dialogType' => 'modal',
    

    I'm not sure why this would need to be specified.

  3. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,101 @@
    +    $form['actions']['cancel'] = [
    +      '#type' => 'link',
    +      '#title' => $this->t('Cancel'),
    ...
    +        'class' => ['button', 'dialog-cancel'],
    

    LB only needs to add the dialog-cancel class to confirmation forms, so this whole array isn't universally needed.

  4. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,101 @@
    +      '#url' => isset($this->workflow) ? $this->workflow->toUrl('edit-form') : $this->getEntity()->toUrl('edit-form'),
    

    Not reusable.

  5. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,101 @@
    +    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
    

    This shouldn't actually be needed? If you trigger the ModalRenderer, it should be handled for you.

  6. +++ b/core/modules/workflows/src/Form/DialogFormTrait.php
    @@ -0,0 +1,101 @@
    +    if ($form_state->hasAnyErrors()) {
    +      $form['status_messages'] = [
    +        '#type' => 'status_messages',
    +        '#weight' => -1000,
    +      ];
    +      $response->addCommand(new ReplaceCommand('[data-drupal-selector="' . $form['#attributes']['data-drupal-selector'] . '"]', $form));
    +    }
    +    else {
    +      /** @var \Drupal\workflows\WorkflowInterface $workflow */
    +      $workflow = $this->workflow ?: $this->getEntity();
    +      $response->addCommand(new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString()));
    +    }
    

    The "if" half of this code is great, and generic. The "else" part is not.

    This is how LB handles this:

        else {
          $response = $this->successfulAjaxSubmit($form, $form_state);
        }
    ...
      abstract protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state);
    

    Then each class using the trait can specify their particular part. Naming TBD.

timmillwood’s picture

@tim.plunkett - the trait used to be much more generic, but it was not needed to be generic anymore, so we removed all of the generic parts. See #134 for example.

effulgentsia’s picture

First of all, I'm sorry this issue is taking so long. Once it lands, I think it'll be a nice UX improvement to Workflows.

Because Workflows is currently stable, prior to me committing the patch, I'd like to review it in more depth to think through whether anything about it feels too temporary and/or special-cased in a way that will make future maintenance on it more difficult due to needing to preserve BC. Some of the points in #218 might be relevant to that, others might not be.

Unfortunately, I won't be able to review it until about 2 weeks from now. I realize the timing of that isn't great, as then we start getting into holidays. If another committer wants to beat me to it, go for it.

larowlan’s picture

Issue tags: +DrupalSouth 2017

Tagging as there is potential for folks to work on this next week at the DS sprint

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs usability review

We need a final sign off here from the UX team, the last review from @Bojhan in #56 was 'this is not close to RBTC' and then some minor comments after that, but no explicit sign-off.

I'll ping @yoroy for a review

hass’s picture

Issue tags: -DrupalSouth 2017

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.

webchick’s picture

Issue tags: -Needs usability review

We reviewed this on the UX team call today.

It seems like this issue has gone in a few different directions, with the advice above being to get the modals in first, then work on other improvements to the form separately (#2758623: [meta] Redesign workflow configuration page to better visually describe the flow). It was the overall form improvements that @Bojhan's previous comments in #56 was referring to, I believe.

So the end result of this issue seems to only be adding a new DialogFormTrait and utilizing it in the Workflows UI to put the add/edit/delete forms in a modal, similar to how the Views UI works. (Although the DialogFormTrait isn't applied to Views as part of this patch? Do we then risk introducing inconsistencies between the two?)

There were no objections from the UX team to utilizing this pattern; it makes sense, especially for short, simple forms like this. We should probably think about expanding it out to other places with short forms like Roles in follow-up patches.

However, as Gábor stated in #44, it's slightly risky to do this, only because we don't ultimately know where #2758623: [meta] Redesign workflow configuration page to better visually describe the flow will end up spec-wise, and we could end up "ping-ponging" users a bit, where 8.4 has forms on separate pages, 8.5 has them in modals, and 8.6 goes back to its own page again. :)

So we would love feedback from the Workflow team if https://www.drupal.org/files/issues/create-new-workflow.png is indeed the direction they want to go in. Because if so, it might not make sense to do this change here, and instead initially introduce the trait to a different set of forms, such as Roles.

manuel garcia’s picture

Thanks a lot UX team for reviewing this!

About the UI conflict on editing transitions due to #2758623: [meta] Redesign workflow configuration page to better visually describe the flow:
When I saw that back in September I stopped working on this, as it became clear we were pushing in different directions. If that is indeed the direction this is going to be going, then I propose that we:

  1. Strip out the modals for Edit transitions from this patch.
  2. Leave the modals for Adding transitions/states on this patch
  3. Leave the modals for Deleting transition/states on this patch
  4. Start working on #2910709: Create vertical tabs for all transition forms and bring these into the main workflow form. and #2910710: Replace the "Transition from" and "Transition to" form controls with a visual interface. instead.

So to summarize, only the edit transition modals would cease to be necessary here. In my opinion adding a new transition would still be useful to do so in a modal instead of a new page, and the same goes for the confirmation form for deleting a transition.

timmillwood’s picture

I think we'll still need the trait even if we end up iterating on the form to fulfill the designs in the screenshot.

My vote would be to commit the current patch, as is, then use the three follow-up issues mentioned in #226 to iterate from there.

timmillwood’s picture

StatusFileSize
new9.81 KB
new38.5 KB

Fixing items from #218 to bring things more into align with LB.

#218.1 - I Just copies the code from LB for now, we can merge when #2896535: Create a helper trait for Forms in ajax dialogs is in.
#218.2 - Removed
#218.3 - Some of these are Entity Forms, so could only fix on Conformation Forms.
#218.4 - I've removed this from the trait and added to the parent forms.
#218.5 - You are correct, removed.
#218.6 - Updated to be the same as LB.

Status: Needs review » Needs work

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

timmillwood’s picture

Status: Needs work » Needs review
StatusFileSize
new1.54 KB
new39.12 KB

Fixing the failing test.

Turns out we do need $form['#id'] = Html::getId($form_state->getBuildInfo()['form_id']); to show errors in the dialog.

Also fixed a coding standards issue.

timmillwood’s picture

Still looking for reviews of this, it'd be a big UX win if we can move all workflow config to dialogs.

alexpott’s picture

#2896535: Create a helper trait for Forms in ajax dialogs has landed - I think the patch can be updated to use it.

timmillwood’s picture

Status: Needs review » Needs work

Awesome

jofitz’s picture

StatusFileSize
new2.08 KB
new36.52 KB

Removed DialogFormTrait and replaced usages with AjaxHelperTrait (from #2896535: Create a helper trait for Forms in ajax dialogs).

jofitz’s picture

Status: Needs work » Needs review
timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @Jo Fitzgerald!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 234: 2830584-234.patch, failed testing. View results

timmillwood’s picture

Status: Needs work » Needs review
StatusFileSize
new2.23 KB
new36.62 KB

Switching from AjaxHelperTrait to AjaxFormHelperTrait.

vijaycs85’s picture

Status: Needs review » Reviewed & tested by the community

Looks good.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 238: 2830584-238.patch, failed testing. View results

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new2.08 KB
new36.56 KB

Rerolled, just a small conflict on core/modules/workflows/src/Form/WorkflowEditForm.php.

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 241: 2830584-241.patch, failed testing. View results

andrewmacpherson’s picture

Issue tags: +Nwdug_may18

Tagging for the Manchester sprint today. @timmillwod mentioned on Slack that this might be an easy re-roll.

manuel garcia’s picture

Status: Needs work » Needs review
StatusFileSize
new36.46 KB

Reroll of #241, manually fixed conflicts on:

  • core/modules/workflows/src/Form/WorkflowEditForm.php
  • core/modules/workflows/src/Form/WorkflowStateEditForm.php
  • core/modules/workflows/src/Form/WorkflowTransitionEditForm.php
andrewmacpherson’s picture

Please don't commit this without accessibility sign-off. There are a couple of must-fix accessibility issues here.

I have tried out the patch in #245, and noticed some unusual behaviour with the dialogs:

  1. Some don't get announced by a screen reader when they open. There's a good chance that a user will not understand how to use this page. It's because focus isn't shifting to the dialog. This MUST be fixed before comitting the patch here.
  2. The escape key should dismiss a dialog, but it isn't working in some cases.
  3. Closing a dialog (using the escape key, the X button, or the cancel button) should return focus to the control that opened the dialog. In the case of the delete-state and delete-transition dialogs, focus shifts to the start of the page. This is annoying, but not a must-fix IMO.

I'm still playing with this, trying to figure out what's wrong, and why focus isn't always moving to the dialog. I think 1 + 2 might be related to #2805219: Some dialogs do not receive focus when opened. I'm not sure if we need to do some extra step per-dialog (in the individual controller classes), or whether this is something that can be fixed for all dialogs generally (in the dialog or ajax JS libs).

--

Next, an accessibility problem with the delete dialogs. When using a keyboard there's a risk of accidental data loss. The problem arises when a keyboard user opens a delete dialog using the enter key. If a user accidentally presses enter twice, they can unintentionally delete config.

The delete dialogs don't have any form elements inside the dialog body, just the buttons in the dialog footer (delete + cancel). When the dialog opens, in the absence of any :tabbable controls in the dialog body, focus shifts to the delete button. I think that comes form the jQuery UI dialog behaviour.

We need to find a way to avoid focus landing on a dangerous delete button when a dialog opens.

Steps to reproduce:

  1. Visit a workflow config page, e.g. admin/config/workflow/workflows/manage/editorial
  2. Press tab until you reach a dropbutton for a state or transition
  3. Focus the dropbutton down-arrow (the focus style isn't very strong, it's like the hover style)
  4. Press enter to open the additional actions dropdown
  5. Press tab to focus the delete link
  6. Now we'll simulate a hand tremor... Press the enter key TWICE in short succession - like a mouse double click, about a quarter of a second apart. You'll see a dialog open, then close, and the workflow state has been deleted. The first keypress opened the dialog, the second operated the delete button in the dialog footer.

This impacts users with motor impairments such as hand tremors. There's a general principle in accessibility, which is to avoid accidental data loss by providing an undo/revert feature, or use an additional confirmation step (i.e. these confirm-delete dialogs). The problem here though, is that there's a danger of accidental activation on the confirm-delete step. This situation isn't an issue when confirm-delete is on a separate page, because the user will have to tab several times to reach the button to confirm deletion. But in the dialogs, where we are focusing the confirm-delete button, an accidental double keypress will lead to data loss.

This can be mitigated by using the "slow keys" feature built into most operating systems, but I think this is a must-fix issue.

--

The problems also affect #2253257: Use a modal for entity delete operation links and #2254935: Use a modal for content entity form delete links confirmation forms. I'll mention it on those issues, too.

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.

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.

manuel garcia’s picture

StatusFileSize
new36.47 KB

Rerolled #245 using three-way merge.

Status: Needs review » Needs work

The last submitted patch, 249: 2830584-249.patch, failed testing. View results

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.

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.

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.

ayush.khare’s picture

StatusFileSize
new33.13 KB
new10.47 KB

Reroll of #249 for 10.1.x

pooja saraah’s picture

StatusFileSize
new33.11 KB
new3.39 KB

Fixed failed commands on #258
Attached patch against Drupal 10.1.x
keeping it in needs work for other failed commands need to be fixed.

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.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new36.62 KB
new2.49 KB

Here's a proper reroll of #249, because #258 was missing some changes to WorkflowEditForm.

Also fixed #241 1. and 2.

Note that the accessibility problem with the delete dialogs is also present on the entity delete operations (from #2253257: Use a modal for entity delete operation links), so I think it should be addressed more generally rather than in this specific patch.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new11.62 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 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.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new36.18 KB
new9.15 KB

A few more fixes.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new5.15 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 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.

kostyashupenko’s picture

Status: Needs work » Needs review
StatusFileSize
new36.25 KB
new681 bytes

Fixed issue reported by bot

Status: Needs review » Needs work

The last submitted patch, 265: 2830584-265.patch, failed testing. View results

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.