1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-25 21:19:21 +01:00
Commit graph

905 commits

Author SHA1 Message Date
epriestley
c42c5983aa Fix an issue where loading a mangled project graph could fail too abruptly
Summary:
Ref T13484. If you load a subproject S which has a mangled/invalid `parentPath`, the query currently tries to execute an empty edge query and fatals.

Instead, we want to deny-by-default in the policy layer but not fail the query. The subproject should become restricted but not fatal anything related to it.

See T13484 for a future refinement where we could identify "broken / data integrity issue" objects explicilty.

Test Plan:
  - Modified the `projectPath` of some subproject in the database to `QQQQ...`.
  - Loaded that project page.
  - Before patch: fatal after issuing bad edge query.
  - After patch: "functionally correct" policy layer failure, although an explicit "data integrity issue" failure would be better.

Maniphest Tasks: T13484

Differential Revision: https://secure.phabricator.com/D20963
2020-02-03 08:54:04 -08:00
epriestley
6c4500046f Add "Project tags added" and "Project tags removed" fields in Herald
Summary: Ref T13480. These fields don't serve a specific strong use case, but are broadly reasonable capabilities after "state" vs "change" actions were relaxed by T13283.

Test Plan: Wrote rules using the new fields, added and removed projects (and did neither) to fire them / not fire them. Inspected the transcripts to see the project PHIDs making it to the field values.

Maniphest Tasks: T13480

Differential Revision: https://secure.phabricator.com/D20946
2020-01-22 18:20:57 -08:00
epriestley
d58eddcf0a When predicting project membership during edits, predict milestones will have parent membership
Summary:
Depends on D20919. Ref T13462. When editing milestones, we currently predict they will have no members for policy evaluation purposes. This isn't the right rule.

Instead, predict that their membership will be the same as the parent project's membership, and pass this hint to the policy layer.

See T13462 for additional context and discussion.

Test Plan:
  - Set project A's edit policy to "Project Members".
  - Joined project A.
  - Tried to create a milestone of project A.
    - Before: policy exception that the edit policy excludes me.
    - After: clean milestone creation.
  - As a non-member, tried to create a milestone. Received appropriate policy error.

Maniphest Tasks: T13462

Differential Revision: https://secure.phabricator.com/D20920
2019-11-18 23:07:05 -08:00
epriestley
959504a488 When predicting object policies for project milestones, adjust objects so they behave like milestones
Summary:
Ref T13462. Currently, when testing milestone edit policies during creation, the project object does not behave like a milestone:

  - it doesn't have a milestone number yet, so it doesn't try to access the parent project; and
  - the parent project isn't attached yet.

Instead: attach the parent project sooner (which "should" be harmless, although it's possible this has weird side effects); and give the adjusted policy object a dummy milestone number if it doesn't have one yet. This forces it to act like a milestone when emitting policies.

Test Plan:
  - Set "Projects" application default edit policy to "No One".
  - Created a milestone I had permission to create.
    - Before: failed with a policy error, because the project behaved like a non-milestone and returned "No One" as the effective edit policy.
    - After: worked properly, correctly evaluting the parent project edit policy as the effective edit policy.
  - Tried to create a milestone I did not have permission to create (no edit permission on parent project).
    - Got an appropriate edit policy error.

Maniphest Tasks: T13462

Differential Revision: https://secure.phabricator.com/D20919
2019-11-18 23:06:03 -08:00
epriestley
be2b8f4bcb Support querying projects by "Root Projects" in the UI, and "min/max depth" in the API
Summary:
Fixes T13441. Internally, projects can be queried by depth, but this is not exposed in the UI.

Add a "Is root project?" contraint in the UI, and "minDepth" / "maxDepth" constraints to the API.

Test Plan:
  - Used the UI to query root projects, got only root projects back.
  - Used "project.search" in the API to query combinations of root projects and projects at particular depths, got matching results.

Maniphest Tasks: T13441

Differential Revision: https://secure.phabricator.com/D20886
2019-10-31 12:56:33 -07:00
epriestley
9d8cdce8e1 Make the top-level burndown chart in "Maniphest > Reports" show open tasks, not total tasks
Summary:
Ref T13279. See PHI1491. Currently, the top-level "Burnup Rate" chart in Maniphest shows total created tasks above the X-axis, without adjusting for closures.

This is unintended and not very useful. The filtered-by-project charts show the right value (cumulative open tasks, i.e. open minus close). Change the value to aggregate creation events and status change events.

Test Plan: Viewed top-level chart, saw the value no longer monotonically increasing.

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20879
2019-10-29 13:48:43 -07:00
epriestley
38694578e1 Improve project member list behaviors related to disabled users
Summary:
Fixes T13431.

Increase the "panel" version of project member lists to 10 users, hide disabled users, swap the buttons to "tail buttons".

Sort disabled users to the bottom of "full list" versions of member lists.

For UI consistency, render the remove "X" as disabled but visible if users don't have permission to remove members.

Test Plan:
  - Viewed a project with disabled members.
    - Saw only enabled members on the main project page.
    - Saw disabled members sorted to the bottom on the members page.
  - Clicked "View All" to jump from the panel to the members page.
  - As a user who could not edit a project, viewed the members page and saw a disabled "X" with a policy error when clicked.
    - Removed a member as before, as a normal user with permission to remove members.

Maniphest Tasks: T13431

Differential Revision: https://secure.phabricator.com/D20864
2019-10-24 18:41:33 -07:00
epriestley
f497b93e43 Fix a fatal in the "Projects" curtain extension when a project edge connects an object to a non-project
Summary:
Ref T13429. It's currently possible to write "TYPE_EDGE" relationships for the "object has project" edge to PHIDs which may not actually be projects. Today, this fatals.

As a first step, unfatal it. T13429 discusses general improvements and greater context.

Test Plan:
Used "maniphest.edit" to write a "project" edge to a user PHID, viewed the task in the UI. Previously it fataled; now it renders unusually (the object is "tagged" with a user) but faithfully reflects database state.

{F6957606}

Maniphest Tasks: T13429

Differential Revision: https://secure.phabricator.com/D20860
2019-10-17 09:49:01 -07:00
epriestley
5dafabd5b4 Fix deprecated argument order for "implode()"
Summary: Fixes T13428. In modern PHP, "implode()" should take the glue parameter first.

Test Plan:
Used the linter introduced in D20857 to identify affected callsites.

```
$ git grep -i implode | cut -d: -f1 | sort | uniq | xargs arc lint --output summary --never-apply-patches | grep -i glue
```

Maniphest Tasks: T13428

Differential Revision: https://secure.phabricator.com/D20858
2019-10-17 09:11:27 -07:00
epriestley
09d86c2d20 Unprototype "Facts" to clear Maniphest/chart fatals
Summary: Ref T13279. Facts is still fairly rough, but not broken/policy-violating, so it can be unprototyped to fix the issue where Maniphest reports (which are now driven by Facts) don't work if prototypes are disabled.

Test Plan: Viewed Maniphest reports and Project reports with prototypes on/off and Fact installed/uninstalled.

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20822
2019-09-23 13:01:18 -07:00
epriestley
16de9151c7 Give "Burndown" charts a more straightforward definition and move all the event stuff into "Activity" charts
Summary:
Depends on D20818. Ref T13279. The behavior of the "burndown" chart has wandered fairly far afield; make it look more like a burndown.

Move the other thing into an "Activity" chart.

Test Plan: {F6865207}

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20819
2019-09-17 13:30:29 -07:00
epriestley
c06dd4818b Support explicit stacking configuration in stacked area charts
Summary:
Ref T13279. Allow engines to choose how areas in a stacked area chart stack on top of one another.

This could also be accomplished by using multiple stacked area datasets, but datasets would still need to know if they're stacking "up" or "down" so it's probably about the same at the end of the day.

Test Plan: {F6865165}

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20818
2019-09-17 13:26:07 -07:00
epriestley
d4ed5d0428 Make various UX improvements to charts so they're closer to making visual sense
Summary: Ref T13279. Fix some tabular stuff, draw areas better, make the "compose()" API more consistent, unfatal the demo chart, unfatal the project burndown, make the project chart do something roughly physical.

Test Plan: Looked at charts, saw fewer obvious horrors.

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20817
2019-09-17 09:43:21 -07:00
epriestley
769e745a3f In charts, make "min" and "max" into pure functions and formally mark pure functions as pure
Summary:
Depends on D20814. Currently, "min()" and "max()" are still "min(f, n)". This is no longer consistent with the construction of functions a function-generators that are composed at top level.

Turn them into "min(n)" and "max(n)" (i.e., not higher-order functions).

Then, mark all the functions which are pure mathematical functions and not higher-order as "pure". These functions have no function parameters and do not reference external data. For now, this distinction has no immediate implications, but it will simplify the next change (which tracks where data came from when it originated from an external source -- these pure functions never have any source information, since they only apply pure mathematical transformations to data).

Test Plan: Loaded a burnup chart, nothing seemed obviously broken.

Subscribers: yelirekim

Differential Revision: https://secure.phabricator.com/D20815
2019-09-17 09:28:23 -07:00
epriestley
3e60128037 Support "Subtype" in Herald
Summary: See PHI1434. For objects that support subtypes and have subtypes configured, allow Herald rules to act on subtypes.

Test Plan:
  - Configured task and project subtypes, wrote Herald rules, saw "Subtypes" as an option, saw appropriate typeahead values and detail page rendering.
  - Unconfigured project subtypes, saw field vanish from UI for new rules.
  - Wrote a "subtype"-depenent rule that added a comment, interacted with tasks of that subtype and a different subtype. Saw Herald act only on tasks with the correct subtype.

Differential Revision: https://secure.phabricator.com/D20809
2019-09-12 14:34:06 -07:00
epriestley
d890c03ac3 Namespace all column references in ProjectQuery to fix ambiguity with Ferret constraints
Summary:
Fixes T13378. If we join Ferret tables and page, we can end up with an ambiguous `id` column here.

Explicitly refer to "project.x" in all cases that we're interacting with the project table.

Test Plan:
  - Changed page size to 3.
  - Issued a Projects query for "~e", matching more than 3 results.
  - Clicked "Next Page".
    - Before: ambiguous id column fatal.
    - After: next page.

Maniphest Tasks: T13378

Differential Revision: https://secure.phabricator.com/D20714
2019-08-15 12:21:54 -07:00
epriestley
0a3c26998f When the feed query on project profile pages overheats, contain the damage
Summary:
Ref T13349. This is almost the same change as D20678, but for project profiles instead of user profiles.

The general reproduction case is "view a project where you can't see more than 50 of the 500 most recent feed stories".

Test Plan:
  - Forced all queries to overheat.
  - Viewed a project profile page.
  - Before: overheating fatal near top level.
  - After: damage contained to feed panel.

Maniphest Tasks: T13349

Differential Revision: https://secure.phabricator.com/D20704
2019-08-08 21:01:50 -07:00
epriestley
937edcdc58 Fix a warning in BoardLayoutEngine when no objects are being updated
Summary: Fixes T13368. Some workflows (like "Move tasks to...") execute board layout without objects to update. In these cases, we can hit a warning because `objectPHIDs` is not initialized to `array()`.

Test Plan: Went through the "Move tasks to..." workflow on a workboard, no longer saw a warning when trying to iterate over an empty `objectPHIDs` list.

Maniphest Tasks: T13368

Differential Revision: https://secure.phabricator.com/D20701
2019-08-08 10:17:59 -07:00
epriestley
0561043a1f In "Move task to..." workflow, separate visible and hidden columns in the dropdown
Summary:
Ref T13368. Currently, both visible and hidden columns are shown in the "Move tasks to..." dropdown on workflows from workboards.

When the dropdown contains hidden columns, move them to a separate section to make it clear that they're not likely targets.

Test Plan:
  - Used "Move tasks to project..." targeting a board with no hidden columns. Saw a single ungrouped dropdown.
  - Used "Move tasks to project..." targeting a board with hidden columns. Saw a dropdown grouped into "Visible" and "Hidden" columns.

Maniphest Tasks: T13368

Differential Revision: https://secure.phabricator.com/D20700
2019-08-07 09:23:53 -07:00
epriestley
6deac35659 Don't show proxy (subproject/milestone) columns as options in "Move tasks..." workflows from workboards
Summary:
Ref T13368. Proxy columns should not be selectable from this workflow. If you want to move tasks to milestone/subproject X, do "Move tasks to project..." and pick X as the project.

(This could be made to work some day.)

Test Plan: Went through a "Move tasks to project..." workflow targeting a project with subprojects. No longer saw subproject columns presented as dropdown options.

Maniphest Tasks: T13368

Differential Revision: https://secure.phabricator.com/D20699
2019-08-07 09:23:29 -07:00
epriestley
31254c5124 Correct column options presented in "Move tasks to project..." on workboards
Summary: Ref T13368. The column options presented to the user are currently incorrect because the wrong set of columns are drawn from.

Test Plan: On a workboard, used "Move tasks to project..." to target another board, saw that board's columns.

Maniphest Tasks: T13368

Differential Revision: https://secure.phabricator.com/D20698
2019-08-07 09:22:57 -07:00
epriestley
d81d0c3ea0 Fix an issue where editing cards on a workboard with implicit column ordering could reorder cards improperly
Summary:
Depends on D20680. Ref T4900. The "BoardLayoutEngine" operates on PHIDs without knowledge of the underlying objects, but this means it has to be sensitive to PHID input order when falling back to a default layout order.

We use "default layout order" on workboards which are sorted by "Natual" order but which have one or more cards which no user has ever reordered. For example, if you add 10 tasks to a project, then create a board, there's no existing order for those tasks in the "Backlog" column. The layout engine uses the input order to place them in the column, with the expectation that input order is ID/creation order, so new cards will end up on top.

I think this code never really made an explicit effort to guarantee that the LayoutEngine received objects in ID order, and it just sort of happened to by coincidence and good fortune. Some recent change has disrupted this, so the edit operation can end up with the PHIDs arranged in arbitrary order.

Explicitly put them in ID order so we always get an implicit default layout order to fall back to. Also, update to `msortv()`.

Test Plan:
  - Tagged several tasks with project X, a project without a board yet.
  - Created the project X workboard.
  - (Did not drag any tasks around on the project X board!)
  - Viewed the board in "Natural" order.

This creates a view of the board where tasks are ordered by implicit/virtual/input order. The expectation, and "view" behavior of this board, is that this order is "newest on top".

  - Edited one of the cards on the board, changing the title (don't reorder it!)
  - Before: page state synchronized with cards in arbitrary/random/different order.
  - After: page state synchronized with cards in the same order as before ("newest on top").

Reviewers: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20681
2019-07-30 13:17:30 -07:00
epriestley
d02beaf816 Make reloading workboards with "R" respect workboard ordering
Summary:
Depends on D20653. Ref T4900. Pass ordering details to the reload endpoint so it can give the client accurate ordering/header information in the response.

The removed comment mentions this, but here's why this is a difficult mess:

  - In window A, view a board with "Group by: Owner" and no tasks owned by "Alice". Since "Alice" owns no tasks, this means the columns do not have an "Assigned to: Alice" header!
  - In window B, edit task T and assign it to Alice.
  - In window A, press "R".

Window A now not only needs to update to properly reflect the state of task T, it actually needs to draw a new "Assigned to: Alice" header in every column.

Fortunately, the "group by" code anticipates this being a big mess, is fairly careful about handling it, and the client can handle this state change and the actual code change here isn't too involved. This is just causing a lot of not-very-obvious indirect effects in the pipeline to handle these situations that need complex redraws.

Test Plan:
  - After making various normal edits/creates/moves in window A, pressed "R" in window B. Saw ordering reflected correctly after sync.
  - Went through the whole "Group by: Owner" + assign to unrepresented owner flow above. After pressing "R", saw "Assigned to: Alice" appear on the board.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20654
2019-07-17 13:17:00 -07:00
epriestley
8669c3c0d2 When updating a workboard with "R", send the client visible set with version numbers
Summary:
Depends on D20652. Ref T4900. When the user presses "R", send a list of cards currently visible on the client and their version numbers.

On the server:

  - Compare the client verisons to the server versions so we can skip updates for objects which have not changed. (For now, the client version is always "1" and the server version is always "2", so this doesn't do anything meaningful, and every card is always updated.)
  - Compare the client visible set to the server visible set and "remove" any cards which have been removed from the board.

I believe this means that "R" always puts the board into the right state (except for some issues with client orderings not being fully handled yet). It's not tremendously efficient, but we can make versioning better (using the largest object transaction ID) to improve that and loading the page in the first place doesn't take all that long so even sending down the full visible set shouldn't be a huge problem.

Test Plan:
  - In window A, removed a card from a board.
  - In window B, pressed "R" and saw the removal reflected on the client.
  - (Also added cards, edited cards, etc., and didn't catch anything exploding.)

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20653
2019-07-17 13:16:03 -07:00
epriestley
1ee6ecf397 Move "BoardResponseEngine" toward a more comprehensive update model
Summary:
Depends on D20639. Ref T4900. Currently, "BoardResponseEngine" has a `setObjectPHID()` method. This is called after edit operations to mean "we just edited object X, so we know it needs to be updated".

Move toward `setUpdatePHIDs(...)` in all cases, with `setUpdatePHIDs(array(the-object-we-just-edited))` as a special case of that. After this change, callers pass:

  - An optional list of PHIDs they know need to be updated on the client. Today, this is always be a card we just edited (on edit/move flows), or a sort of made-up list of PHIDs for the moment (when you press "R"). In the future, the "R" endpoint will do a better job of figuring out a more realistic update set.
  - An optional list of PHIDs currently visible on the client. This is used to update ordering details and mark cards for removal. This is currently passed by edit/move, but not by pressing "R" (it will be in the future).
  - An optional list of objects. The "R" workflow has to load these anyway, so we can save a couple queries by letting callers pass them. For now, the edit/move flows still rely on the engine to figure out what it needs to load.

This does very little to actually change client behavior, it mostly just paves the way for the next update to the "R" workflow to make it handle add/remove cases properly.

Test Plan:
  - Edited and moved cards on a workboard.
  - Pressed "R" to reload a workboard.

Neither of these operations seem any worse off than they were before. They still don't fully work:

  - When you edit a card and delete the current workboard project from it, it remains visible. This is also the behavior on `master`. This is sort of intentional since we don't necessarily want to make these cards suddenly disappear? Ideally, we would probably have some kind of "tombstone" state where the card can still be edited but can't be dragged, and the next explicit user interaction would clean up old tombstones. This interaction is very rare and I don't think it's particularly important to specialize.
  - When a card is removed from the board, "R" can't currently figure out that it should be removed from the client. This is because the client does not yet pass a "visiblePHIDs" state. It will in an upcoming change.
  - The "R" flow always sends a full set of card updates, and can not yet detect that some cards have not changed.
  - There's a TODO, but some ordering stuff isn't handled yet.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20652
2019-07-17 13:13:15 -07:00
epriestley
db69686927 Make pressing "R" on your keyboard reload the card state on workboards
Summary:
Depends on D20638. Ref T4900. This is an incremental step toward proper workboard updates.

Currently, the client can mostly update its view because we do updates when you edit or move a card, and the client and server know how to send lists of card updates, so a lot of the work is already done.

However, the code assumes we're only updating/redrawing one card at a time. Make the client accept and process multiple card updates.

In future changes, I'll add versioning (so we only update cards that have actually changed), fix the "TODO" around ordering, and move toward actual Aphlict-based real-time updates.

Test Plan:
  - Opened the same workboard in two windows.
  - Edited cards in one window, pressed "R" (capital letter, with no modifier keys) to reload the second window.
  - Saw edits and moves reflected accurately after sync, except for some special cases of header/order interaction (see "TODO").

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20639
2019-07-17 13:11:26 -07:00
epriestley
45f4211541 Fix URI escaping, which should actually be "%s", not "%p"
See <https://discourse.phabricator-community.org/t/projects-workboards-links-issue/2896>.

The documentation on `urisprintf()` isn't very clear here, I'll update it in
a followup. "%p" is for cases like encoding a branch name (which may contain
slashes) as a single path component in a URI.
2019-07-04 11:00:04 -07:00
epriestley
2de8a23adb Remove remnants of clumsy old URI state handling from workboards
Summary:
Depends on D20636. Ref T4900. Previously, some workflows didn't know how to identify the default state for the board, so they needed explicit ("force") parameters.

Everything uses the same state management code now so we can rip out the old stuff.

Test Plan: Changed board filters, selected a custom filter, edited a custom filter.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20637
2019-07-03 10:05:34 -07:00
epriestley
58e2fa0d47 Differentiate between "Move Tasks to Column..." and "Move Tasks to Project..." in the workboard UI
Summary:
Depends on D20635. Ref T4900. Fixes T13316.

Currently, "Move Tasks to Column..." first prompts you to select a project, then prompts you for a column. The first step is prefilled with the current project, so the common case (moving to another column on the same board) requires you to confirm that you aren't doing an off-project move by clicking "Continue", then you can select a column.

This isn't a huge inconvenience and the workflow isn't terribly common, but it's surprising enough that it has come up a few times as a stumbling block. Particularly, we're suggesting to users that they're about to pick a column, then we're asking them to pick a project. The prompt also says "Project: XYZ", not "Project: Keep in current project" or something like that.

Smooth this out by splitting the action into two better-cued flows:

  - "Move Tasks to Project..." is the current flow: pick a project, then pick a column.
    - The project selection no longer defaults to the current project, since we now expect you to usually use this flow to move tasks to a different project.
  - "Move Tasks to Column..." prompts you to select a column on the same board.
    - This just skips step 1 of the workflow.
    - This now defaults to the current column, which isn't a useful selection, but is more clear.

In both cases, the action cue ("Move tasks to X...") now matches what the dialog actually asks you for ("Pick an X").

Test Plan:
  - Moved tasks across projects and columns within the same project.
  - Hit all (I think?) the error cases and got sensible error and recovery behavior.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13316, T4900

Differential Revision: https://secure.phabricator.com/D20636
2019-07-03 10:02:44 -07:00
epriestley
24b466cd62 Move workboard "Move Tasks to Column..." workflow to a separate controller
Summary: Depends on D20634. Ref T4900. Ref T13316. I'm planning to do a bit of additional cleanup here in followups, but this separates the main workflow out of the common controller.

Test Plan:
  - Used "Move Tasks to Column..." to move some tasks on a board.
  - Tried to move an empty column, hit an error.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13316, T4900

Differential Revision: https://secure.phabricator.com/D20635
2019-07-02 15:16:38 -07:00
epriestley
ec352b1b31 Move workboard "Bulk Edit Tasks" workflow to a separate controller
Summary: Depends on D20633. Ref T4900. Separate the "Bulk Edit Tasks..." flow out of the main workboard controller.

Test Plan:
  - Used "Bulk Edit Tasks" on a column with some tasks, got an appropraite edit operation.
  - Used "Bulk Edit Tasks" on an empty column, got an error.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20634
2019-07-02 15:04:38 -07:00
epriestley
9ea7227f0f Move workboard "View as Query" workflow to a separate controller
Summary:
Depends on D20632. Ref T4900. As with other workflows on the board controller, this one is currently in the giant main "do everything" method. Move it to a separate controller.

This makes one material improvement: previously, we built the full board and did layout on all the cards before building the query. However, we do not actually need to do this: we don't need the cards. Instead, just do layout without handing over any card PHIDs. This is slightly faster, particularly on large boards.

Test Plan:
  - Clicked "View as Query" on a board, got a query page for the column.
  - Applied a custom filter, then clicked "View as Query" on a board. Got a query page merging the two filters.
  - Applied a custom filter, then clicked "Veiw as Query" on a board, in a subproject column. Got a query page merging the two filters, respecting the project-ness of the column.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20633
2019-07-02 15:00:36 -07:00
epriestley
577020aea9 Move workboard "filter" workflow to a separate controller
Summary:
Depends on D20629. Ref T4900. Currently, the "Advanced Filter..." workflow on workboards (where you build a custom query) is inline in the main board controller.

This is because the filter flow depends on some of the board view state: we want to start with the current filter applied to the board, and preserve other state after you change the filter.

Now that `ViewState` can handle state management, we can separate this stuff out pretty easily.

Test Plan:
  - Changed filters on a board.
  - Applied a custom filter to a board.
  - Changed the ordering of a board, then applied a custom filter. Verified "Cancel" and "Apply Filter" both preserve the order state.
  - Changed the ordering of a board, then applied a custom filter, intentionally making a mistake in configuring the filter by entering an invalid date. Saw a dialog with an error. After correcting the error, saw state preserved properly.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20632
2019-07-02 14:39:34 -07:00
epriestley
9e096cd274 Give the workboard "default" workflows more modern state handling
Summary:
Depends on D20628. Ref T4900. Currently, the "Save Current Order/Filter As Default" flows on workboards duplicate some state construction, and require parameters to be passed to them explicitly.

Now that state management is separate, they can reuse a bit more code and be made to look more like other similar controllers.

Test Plan:
  - Changed the default order of a workboard.
  - Changed the default filter of a workboard.
  - Changed the order of a board to something non-default, then changed the filter, then saved the new filter as the default. Saw the modified order preserved and the modified filter removed, so I ended up in the right ("most correct") place: on the board, with my custom order in a URI parameter, and no filter URI parameter so I could see my new default filter behavior. This is an edge case that's not terribly important to get right, but we do get it right.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20629
2019-07-02 14:36:15 -07:00
epriestley
9c190d68ed Separate workboard view state (ordering, filtering, hidden columns) from the View controller
Summary:
Depends on D20627. Ref T4900. If a user orders a board by "Sort by Title", then toggles the visibility of hidden columns, we want to keep the board sorted by title. To accomplish this, we pass the board state around to all the workflows here.

Pull the "bag of state properties" code out of the View controller. This class basically:

  - reads state from a request (order, hidden, filter);
  - manages defaults;
  - provides the application with the current settings; and
  - generates URIs with "?order=X&hidden=Y&filter=Z" to preserve state.

This is still a little questionable/transitional since some of the controllers need more cleanup.

Test Plan:
Toggled state, order, filters, clicked around various workflows and saw the filters preserved.

A lot of these workflows are pretty serious edge cases. For example, here's a feature this implements:

  - Changed workboard order to "Title".
  - Selected "Bulk Edit Tasks..." in an empty column and command-clicked it to open the link in a new window.
  - Hovered over "Cancel".
  - Saw the link properly generate with "?order=title", preserving the order.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20628
2019-07-02 14:34:33 -07:00
epriestley
0ae9e2c75d Remove property "id" from Workboard View controller
Summary: Depends on D20626. Ref T4900. On this controller, "id" is a separate property, but serves little purpose and complicates separating state management. Remove it.

Test Plan: Bulk edited a column, managed filters, did show/hide on columns, edited a column.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20627
2019-07-02 05:17:01 -07:00
epriestley
df29b82ad6 Remove unused property "slug" from Workboard View controller
Summary:
Ref T4900. The Workboard view controller currently has a lot of different responsibilities (it's ~1,500 lines long) because it has to manage the board filter/sort state.

I'd like to split it up and make it easier to move some workboard features (like "move all tasks in column...") to other Controllers, so we can have smaller controllers implementing specific workflows.

I think the state handling isn't really all that bad, it just needs to be separated a little better than it currently is.

To start with, remove the unused "slug" property.

Test Plan: Searched for "slug", got no hits. This class is final and the property is private, so this is certainly unused.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

Differential Revision: https://secure.phabricator.com/D20626
2019-07-02 05:16:34 -07:00
epriestley
f91bef64f1 Stack chart functions in a more physical way
Summary:
Ref T13279. See that task for some discussion.

The accumulations of some of the datasets may be negative (e.g., if more tasks are moved out of a project than into it) which can lead to negative area in the stacked chart.

Introduce `min(...)` and `max(...)` to separate a function into points above or below some line, then mangle the areas to pick the negative and positive regions apart so they at least have a plausible physical interpretation and none of the areas are negative.

This is presumably not a final version, I'm just trying to produce a chart that isn't a sequence of overlapping regions with negative areas that is "technically" correct but not really possible to interpret.

Test Plan: {F6439195}

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20506
2019-05-22 05:40:39 -07:00
epriestley
f190c42bcd Store charts earlier and build them out a little later
Summary:
Ref T13279. Currently, we store a fairly low-level description of functions and datasets in a chart. This will create problems with (for example) translating function labels.

If you view a chart someone links you, it should say "El Charto" if you speak Spanish, not "The Chart" if the original viewer speaks English.

To support this, store a slightly higher level version of the chart: the chart engine key, plus configuration parameters. This is very similar to how SearchEngine works.

For example, the burndown chart now stores a list of project PHIDs, instead of a list of `[accumulate [sum [fact task.open <project-phid>]]]` functions.

(This leaves some serialization code with no callsites, but we may eventually have a "CustomChartEngine" which stores raw functions, so I'm leaving it for now.)

As a result, function labels provided by the chart engine are now translatable.

(Note that the actual chart is meaningless since the underlying facts can't be stacked like they're being stacked, as some are negative in some areas of their accumulation.)

Test Plan: {F6439121}

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20504
2019-05-22 05:39:32 -07:00
epriestley
81456db559 Roughly support stacked area charts
Summary:
Ref T13279. This adds support for:

  - Datasets can have types, like "stacked area".
  - Datasets can have multiple functions.
  - Charts can store dataset types and datasets with multiple functions.
  - Adds a "stacked area" dataset.
  - Makes D3 actually draw a stacked area chart.

Lots of rough edges here still, but the result looks slightly more like it's supposed to look.

D3 can do some of this logic itself, like adding up the area stacks on top of one another with `d3.stack()`. I'm doing it in PHP instead because I think it's a bit easier to debug, and it gives us more options for things like caching or "export to CSV" or "export to API" or rendering a data table under the chart or whatever.

Test Plan: {F6427780}

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20498
2019-05-22 05:19:41 -07:00
epriestley
5c1b91ab45 Consolidate burndown logic into a "BurndownChartEngine"
Summary:
Ref T13279. For now, we need to render burndowns from both Maniphest (legacy) and Projects (new prototype).

Consolidate this logic into a "BurndownChartEngine". I plan to expand this to work a bit like a "SearchEngine", and serve as a UI layer on top of the raw chart features.

The old "ChartEngine" is now "ChartRenderingEngine".

Test Plan:
  - Viewed burndowns ("burnups") in Maniphest.
  - Viewed burndowns in Projects.
  - Saw the same chart.

Reviewers: amckinley

Reviewed By: amckinley

Subscribers: yelirekim

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20496
2019-05-22 05:10:42 -07:00
epriestley
0aee3da19e Add a "Reports" menu item to Projects
Summary:
Ref T13279. Since the use cases that have made it upstream are all for relatively complex charts (e.g., requiring aggregation and composition of multiple data series in nontrivial ways) I'm currently looking at an overall approach like this:

  - At least for now, Charts provides a low-level internal-only API for composing charts from raw datasets.
  - This is exposed to users through pre-built `SearchEngine`-like interfaces that provide a small number of more manageable controls (show chart from date X to date Y, show projects A, B, C), but not the full set of composition features (`compose(scale(2), cos())` and such).
  - Eventually, we may put more UI on the raw chart composition stuff and let you build your own fully custom charts by gluing together datasets and functions.
  - Or we may add this stuff in piecemeal to the higher-level UI as tools like "add goal line" or "add trend line" or whatever.

This will let the low-level API mature/evolve a bit before users get hold of it directly, if they ever do. Most requests today are likely satisfiable with a small number of chart engines plus raw API data access, so maybe UI access to flexible charting is far away.

Step toward this by adding a "Reports" section to projects. For now, this just renders a basic burnup for the current project. Followups will add an "Engine" layer above this and make the chart it produces more useful.

Test Plan: {F6426984}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13279

Differential Revision: https://secure.phabricator.com/D20495
2019-05-22 05:08:55 -07:00
epriestley
a1f08de283 When viewing a workboard, only link to parent workboards in crumbs if parents have workboards
Summary:
Depends on D20516. See PHI1247. In D20331, I made the crumbs on workboards point at ancestor workboards.

However, this isn't a great destination if an ancestor doesn't actually have a workboard. In this case, point at the normal profile URI instead.

Test Plan:
  - Viewed a milestone workboard with a parent that had no workboard. Saw a profile link instead of a workboard link (new behavior).
  - Viewed a milestone workboard with a parent that also had a workboard. Saw a workboard link (existing old behavior still works).

Reviewers: amckinley

Reviewed By: amckinley

Differential Revision: https://secure.phabricator.com/D20517
2019-05-15 07:08:54 -07:00
epriestley
ee89c2fad9 Fix a fatal when navigating to a Workboard after removing the Workboard menu item
Summary:
See PHI1247. If you remove the Workboard from a project profile menu, then navigate to the URI, we currently fatal when trying to select the "Workboard" item.

Instead, only try to select the item if some matching item is present.

Test Plan:
  - Disabled the workboard on a project, navigated to `/board/`, got a sensible page with no navigation item selected instead of a fatal.
  - Viewed a normal workboard, saw the correct selection.

Reviewers: amckinley

Reviewed By: amckinley

Differential Revision: https://secure.phabricator.com/D20516
2019-05-14 09:26:02 -07:00
epriestley
cd2215fd4a Don't warn that workboard columns need a name when editing milestone columns
Summary: See <https://discourse.phabricator-community.org/t/columns-must-have-a-name-while-editong-point-limit-on-milestone-column/2650>. This check doesn't make sense for proxy columns, including milestone columns.

Test Plan: Added a point limit to a milestone column.

Reviewers: amckinley

Reviewed By: amckinley

Differential Revision: https://secure.phabricator.com/D20448
2019-04-18 13:13:10 -07:00
epriestley
870b01f2d0 Distinguish between "bad record format" and "bad record value" when validating Trigger rules
Summary:
Depends on D20416. Ref T13269. See D20329.

If you try to save an "Assign to" rule with no assignee, we currently replace the control with an "InvalidRule" control that isn't editable. We'd prefer to give you an empty field back and let you pick a different value.

Differentiate between "bad record format" (i.e., we can't really do anything with this) and "bad record value" (i.e., everything is structurally fine, you just typed the wrong thing). In the latter case, we still build a properly typed rule for the UI, we just refuse to update storage until you fix the problem.

Test Plan:
First, hit the original issue and got a nicer UI with a more consistent control width (note full-width error):

{F6374205}

Then, applied the rest of the patch and got a normal "fix the issue" form state instead of a dead-end:

{F6374211}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13269

Differential Revision: https://secure.phabricator.com/D20417
2019-04-17 12:40:55 -07:00
epriestley
9532bfbb32 Improve trigger editor behavior when switching to/from tokenizers
Summary:
Ref T13269. See D20329. When we switch trigger rule control types, reset the rule value.

Also, pick slightly nicer defaults for status/priority.

Test Plan:
  - Created a "Change Status To: X" rule.
  - Saved it.
  - Edited it.
  - Selected "Assign to" for the existing action's dropdown.
  - Before: tokenizer filled with nonsense.
  - After: tokenizer cleared.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13269

Differential Revision: https://secure.phabricator.com/D20416
2019-04-17 12:24:23 -07:00
Austin McKinley
55d64d0fab Add trigger rule to remove projects from tasks
Summary: Ref T13269. Same as D20379 with the polarity reversed.

Test Plan: Added some triggers, removed some projects, observed expected results.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Maniphest Tasks: T13269

Differential Revision: https://secure.phabricator.com/D20390
2019-04-10 12:27:01 -07:00
Austin McKinley
8b475898ee Add trigger rule for adding projects to a task
Summary: Ref T13269. This is mostly copying code from the similar Herald implementation. Note that the drop effect preview always renders because we don't have the infrastructure to compare lists of edge targets.

Test Plan: Created some triggers, dragged some tasks around, checked that tasks that already had project membership didn't write additional edges.

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Maniphest Tasks: T13269

Differential Revision: https://secure.phabricator.com/D20379
2019-04-10 12:10:08 -07:00
epriestley
fb19310631 Fix some overlooked profile menu construction callsites
Summary: Depends on D20384. Ref T13275. A bunch of this code got converted but I missed some callsites that aren't reached directly from the menu.

Test Plan:
  - Visited each controller, saw actual pages instead of menu construction fatals.
  - Grepped for `getProfileMenu()`.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13275

Differential Revision: https://secure.phabricator.com/D20385
2019-04-09 14:47:44 -07:00