Page MenuHomePhabricator

create subtask side menu to allow creation of subtasks of different types to the parent task
Closed, ResolvedPublic

Description

The current maniphest menu for creating sub tasks assumes that the subtask is of the same subtype as the parent. It's possible to create subtasks of a different type by creating them as new tasks and then setting their parent to be the parent that was originally intended - does that make sense?

Event Timeline

cos created this task.Apr 18 2017, 7:59 PM

Allowing users to select a subform from "Create Subtask" isn't technically very difficult, but it starts to potentially make the UI pretty messy and complicated. Some possible implementations are:

Three-Level Submenu

> Edit Related Tasks...
  > Create Subtask...
    + New Plant Task
    + New Animal Task
  + Edit Parent Tasks
  + Edit Subtasks

Some downsides:

  • Requires an extra click in the common case to open the subtask menu.
  • Particularly on mobile, we'd be dedicating a lot of room in the UI to hierarchy, and might need to redesign the element to make better use of space on devices.

Inline Options

> Edit Related Tasks...
  + New Plant Subtask
  + New Animal Subtask
  + Edit Parent Tasks
  + Edit Subtasks

Some downsides:

  • Adds a lot of options to this submenu that probably almost no one ever uses.
  • Currently, no way to generate those strings in a translatable way -- they'd have to look like "Subtask: New Plant Task" or similar, which is awkward even in English. We could extend forms to include more string customization options.

Modal Workflow

  • Keep the menu the same.
  • When you click it, you get a dialog asking you to pick a subtask type.

Some downsides:

  • Workflow becomes heavier.
  • Menu options have the translation problem -- you're choosing a form, not a subtype, so they'll say "New Animal Task". We could extend forms here.

None of these approaches feel particularly great to me, and I'm hesitant to bring any of them upstream until we have a better sense of how other installs are using subtasks.

In the near term, this is perhaps most easily accomplished with a local patch to implement the Inline Options approach, which would look like this:

diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
index 514090dda8..d557afb254 100644
--- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
@@ -300,12 +300,23 @@ final class ManiphestTaskDetailController extends ManiphestController {
       ->setDisabled(!$can_create)
       ->setWorkflow(!$can_create);
 
+    $plant_uri = id(new PhutilURI($edit_uri))
+      ->setPath($this->getApplicationURI('/task/edit/form/123/'));
+
+    $plant_item = id(new PhabricatorActionView())
+      ->setName(pht('New Plant Subtask'))
+      ->setHref($plant_uri)
+      ->setIcon('fa-leaf')
+      ->setDisabled(!$can_create)
+      ->setWorkflow(!$can_create);
+
     $relationship_list = PhabricatorObjectRelationshipList::newForObject(
       $viewer,
       $task);
 
     $submenu_actions = array(
       $subtask_item,
+      $plant_item,
       ManiphestTaskHasParentRelationship::RELATIONSHIPKEY,
       ManiphestTaskHasSubtaskRelationship::RELATIONSHIPKEY,
       ManiphestTaskMergeInRelationship::RELATIONSHIPKEY,

That adds a new menu item which creates a new subtask with a particular form:

You can find the right ID for the form by going to the normal create form for a task of that subtype, then copying the ID out of the URL. Replace 123 in the patch with that ID. You can add more menu items in a similar way if you have several different types of subtasks you want to make available.

cos added a comment.May 4 2017, 2:47 PM

thanks - we'll give this a go. It's not clear how often people will need to use this so I agree with your concern about UI clutter.

Also, it would be great if you can choose an optional "default subtask subtype" where you configure the subtypes. Something like this:

[
  {
    "key": "userstory",
    "name": "User Story"
    "subtask-key": "subtask"
  },
  {
    "key": "subtask",
    "name": "Subtask"
  },
  {
    "key": "bug",
    "name": "Bug"
  },
]

Or just have a subtask-array configurable, going with the inline approach mentioned above:

[
  {
    "key": "epic",
    "name": "Epic",
    "subtasks": {
        "userstory",
        "bug"
    }
  },
  {
    "key": "userstory",
    "name": "User Story"
    "subtasks": {
        "subtask"
    }
  },
  {
    "key": "subtask",
    "name": "Subtask"
  },
  {
    "key": "bug",
    "name": "Bug"
  },
]

When users click "Create Subtask", we now look for a list of possible subtask forms.

  • If we find zero forms, we give the user an error message.
  • If we find one form, we take them directly to that form (similar to the old behavior).
  • If we find two or more forms, we prompt them with a modal dialog to choose between the forms.

Here's an example of what the modal prompt looks like:

Previously, we took the user to the first edit form they have access to for the parent subtype. The new behavior is configurable by specifying children in maniphest.subtypes:

  • By default, we will now ask the user to choose between all available "Create" forms of the parent subtype. This is a behavioral change.
  • If children specifies a list of subtypes, we'll show "Create" forms for those subtypes instead.
  • If children specifies a list of forms, we'll show an exact list of forms in the provided order. When specifying an exact list of forms, they may be arbitrary forms and do not need to be "Create" or "Edit" forms.

If any of these lists only have one form (or the user can only see one form), we'll take the user directly to the specified form.

If any of these lists only have one form (or the user can only see one form), we'll take the user directly to the specified form.

^ Everything about the new behavior seems very sane and I think it's a really good solution! Thanks @epriestley!