2012-07-30 19:43:49 +02:00
|
|
|
<?php
|
|
|
|
|
2014-07-23 02:03:09 +02:00
|
|
|
final class PhabricatorDifferentialApplication extends PhabricatorApplication {
|
2012-07-30 19:43:49 +02:00
|
|
|
|
2012-08-02 23:07:21 +02:00
|
|
|
public function getBaseURI() {
|
|
|
|
return '/differential/';
|
|
|
|
}
|
|
|
|
|
2014-07-23 15:52:50 +02:00
|
|
|
public function getName() {
|
|
|
|
return pht('Differential');
|
|
|
|
}
|
|
|
|
|
2012-08-02 23:07:21 +02:00
|
|
|
public function getShortDescription() {
|
2013-01-24 19:46:47 +01:00
|
|
|
return pht('Review Code');
|
2012-08-02 23:07:21 +02:00
|
|
|
}
|
|
|
|
|
2015-01-25 08:41:43 +01:00
|
|
|
public function getFontIcon() {
|
|
|
|
return 'fa-cog';
|
|
|
|
}
|
|
|
|
|
(Redesign) Clean up older "Tile" code
Summary:
This does some backend cleanup of the tile stuff, and some general cleanup of other application things:
- Users who haven't customized preferences get a small, specific set of pinned applications: Differential, Maniphest, Diffusion, Audit, Phriction, Projects (and, for administrators, Auth, Config and People).
- Old tile size methods are replaced with `isPinnnedByDefault()`.
- Shortened some short descriptions.
- `shouldAppearInLaunchView()` replaced by less ambiguous `isLaunchable()`.
- Added a marker for third-party / extension applications.
Test Plan: Faked away my preferences and viewed the home page, saw a smaller set of default pins.
Reviewers: chad
Reviewed By: chad
Subscribers: epriestley
Differential Revision: https://secure.phabricator.com/D9358
2014-06-04 00:47:27 +02:00
|
|
|
public function isPinnedByDefault(PhabricatorUser $viewer) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-01 17:13:12 +02:00
|
|
|
public function getHelpDocumentationArticles(PhabricatorUser $viewer) {
|
|
|
|
return array(
|
|
|
|
array(
|
|
|
|
'name' => pht('Differential User Guide'),
|
|
|
|
'href' => PhabricatorEnv::getDoclink('Differential User Guide'),
|
|
|
|
),
|
|
|
|
);
|
2012-10-10 23:10:24 +02:00
|
|
|
}
|
|
|
|
|
2012-07-30 19:43:49 +02:00
|
|
|
public function getFactObjectsForAnalysis() {
|
|
|
|
return array(
|
|
|
|
new DifferentialRevision(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-01-18 00:04:57 +01:00
|
|
|
public function getTitleGlyph() {
|
|
|
|
return "\xE2\x9A\x99";
|
|
|
|
}
|
|
|
|
|
2013-02-05 22:46:02 +01:00
|
|
|
public function getEventListeners() {
|
|
|
|
return array(
|
2013-10-22 02:00:21 +02:00
|
|
|
new DifferentialActionMenuEventListener(),
|
2013-04-06 02:01:54 +02:00
|
|
|
new DifferentialHovercardEventListener(),
|
Land Revision button for hosted git repos
Summary:
ref T182.
Simple approach of clone, patch, push. While waiting for drydock, implement a hackish mutex
setup for the workspace, which should work ok as long as there's only one committer who is
carefull about theses things.
Less obvious note: This is taking the both author and commiter's 'primary email' for the commit -
which might rub some people wrong.
Test Plan:
With a hosted repo, created some diffs and landed them.
Also clicked button for some error cases, got the right error message.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley
CC: hach-que, Korvin, epriestley, aran
Maniphest Tasks: T182
Differential Revision: https://secure.phabricator.com/D7486
2013-11-05 22:00:12 +01:00
|
|
|
new DifferentialLandingActionMenuEventListener(),
|
2013-02-05 22:46:02 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-05-29 21:17:54 +02:00
|
|
|
public function getOverview() {
|
|
|
|
return pht(<<<EOTEXT
|
|
|
|
Differential is a **code review application** which allows engineers to review,
|
|
|
|
discuss and approve changes to software.
|
|
|
|
EOTEXT
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-08-05 23:03:39 +02:00
|
|
|
public function getRoutes() {
|
|
|
|
return array(
|
2012-10-06 01:06:16 +02:00
|
|
|
'/D(?P<id>[1-9]\d*)' => 'DifferentialRevisionViewController',
|
2012-08-05 23:03:39 +02:00
|
|
|
'/differential/' => array(
|
Use ApplicationSearch in Differential
Summary:
Ref T603. Ref T2625. Fixes T3241. Depends on D5451. Depends on D6346.
@wez, this changes the Differential revision list UI substantially and may generate a lot of bikeshedding / who-moved-my-cheese churn. See T3417 for context, for example. The motivations for this change are:
- The list now works on devices, like phones and tablets. This is a requirement to make the rest of Differential work on devices.
- Although ApplicationSearch intentionally presents a simpler interface initially and some options which were one click away before aren't now, it is much more powerful than the search it replaces and allows users to build, save, share, fork, edit, and customize a much wider range of queries. Users who used the old filters frequently can use Advanced Search -> Save Custom Query to create new versions of them, and of any other query. "Edit Queries.." allows users to remove and reorder queries, including builtin queries. Basically, there are like three things which have gone from "1-click" to "a few clicks", and ten trillion things which have gone from "hard/impossible" to "relatively easy".
The local screenshots look a bit iffy, but I think a lot of this is the fakenesss of my test data. If they still feel iffy in production we can tweak them until they feel good, like we did for Maniphest.
Test Plan:
{F48477}
{F48478}
Reviewers: btrahan, chad, wez
Reviewed By: btrahan
CC: aran, s
Maniphest Tasks: T603, T2625, T3241
Differential Revision: https://secure.phabricator.com/D6347
2013-07-03 15:11:07 +02:00
|
|
|
'(?:query/(?P<queryKey>[^/]+)/)?'
|
|
|
|
=> 'DifferentialRevisionListController',
|
2012-08-05 23:03:39 +02:00
|
|
|
'diff/' => array(
|
2012-10-06 01:06:16 +02:00
|
|
|
'(?P<id>[1-9]\d*)/' => 'DifferentialDiffViewController',
|
2012-08-05 23:03:39 +02:00
|
|
|
'create/' => 'DifferentialDiffCreateController',
|
|
|
|
),
|
|
|
|
'changeset/' => 'DifferentialChangesetViewController',
|
2015-03-23 18:44:33 +01:00
|
|
|
'revision/' => array(
|
|
|
|
'edit/(?:(?P<id>[1-9]\d*)/)?'
|
|
|
|
=> 'DifferentialRevisionEditController',
|
|
|
|
'land/(?:(?P<id>[1-9]\d*))/(?P<strategy>[^/]+)/'
|
|
|
|
=> 'DifferentialRevisionLandController',
|
|
|
|
'closedetails/(?P<phid>[^/]+)/'
|
|
|
|
=> 'DifferentialRevisionCloseDetailsController',
|
|
|
|
'update/(?P<revisionID>[1-9]\d*)/'
|
|
|
|
=> 'DifferentialDiffCreateController',
|
|
|
|
),
|
2012-08-05 23:03:39 +02:00
|
|
|
'comment/' => array(
|
2012-10-06 01:06:16 +02:00
|
|
|
'preview/(?P<id>[1-9]\d*)/' => 'DifferentialCommentPreviewController',
|
2014-02-27 20:06:55 +01:00
|
|
|
'save/(?P<id>[1-9]\d*)/' => 'DifferentialCommentSaveController',
|
2012-08-05 23:03:39 +02:00
|
|
|
'inline/' => array(
|
2012-10-06 01:06:16 +02:00
|
|
|
'preview/(?P<id>[1-9]\d*)/'
|
|
|
|
=> 'DifferentialInlineCommentPreviewController',
|
|
|
|
'edit/(?P<id>[1-9]\d*)/'
|
|
|
|
=> 'DifferentialInlineCommentEditController',
|
2012-08-05 23:03:39 +02:00
|
|
|
),
|
|
|
|
),
|
2013-08-05 19:46:39 +02:00
|
|
|
'preview/' => 'PhabricatorMarkupPreviewController',
|
2012-08-05 23:03:39 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-10-04 00:46:19 +02:00
|
|
|
public function getApplicationOrder() {
|
Add basic support for new navigation menu
Summary:
Add a new left-side application menu. This menu shows which application you're in and provides a quick way to get to other applications.
On desktops, menus are always shown but the app menu can be collapsed to be very small.
On tablets, navigation buttons allow you to choose between the menus and the content.
On phones, navigation buttons allow you to choose between the app menu, the local menu, and the content.
This needs some code and UI cleanup, but has no effect yet so I think it's okay to land as-is, I'll clean it up a bit as I start integrating it. I want to play around with it a bit and see if it's good/useful or horrible anyway.
Test Plan: Will include screenshots.
Reviewers: vrana, btrahan, chad
Reviewed By: btrahan
CC: aran, alanh
Maniphest Tasks: T1569
Differential Revision: https://secure.phabricator.com/D3223
2012-08-11 16:06:12 +02:00
|
|
|
return 0.100;
|
|
|
|
}
|
|
|
|
|
2013-02-26 23:59:31 +01:00
|
|
|
public function getRemarkupRules() {
|
|
|
|
return array(
|
|
|
|
new DifferentialRemarkupRule(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-08-02 23:07:21 +02:00
|
|
|
public function loadStatus(PhabricatorUser $user) {
|
|
|
|
$revisions = id(new DifferentialRevisionQuery())
|
2013-07-01 21:38:27 +02:00
|
|
|
->setViewer($user)
|
2012-08-02 23:07:21 +02:00
|
|
|
->withResponsibleUsers(array($user->getPHID()))
|
|
|
|
->withStatus(DifferentialRevisionQuery::STATUS_OPEN)
|
2013-02-21 12:10:02 +01:00
|
|
|
->needRelationships(true)
|
2014-12-12 21:02:25 +01:00
|
|
|
->setLimit(self::MAX_STATUS_ITEMS)
|
2012-08-02 23:07:21 +02:00
|
|
|
->execute();
|
2012-08-01 02:58:21 +02:00
|
|
|
|
2012-08-02 23:07:21 +02:00
|
|
|
$status = array();
|
2014-12-12 21:02:25 +01:00
|
|
|
if (count($revisions) == self::MAX_STATUS_ITEMS) {
|
|
|
|
$all_count = count($revisions);
|
|
|
|
$all_count_str = self::formatStatusCount(
|
|
|
|
$all_count,
|
|
|
|
'%s Active Reviews',
|
|
|
|
'%d Active Review(s)');
|
|
|
|
$type = PhabricatorApplicationStatusView::TYPE_WARNING;
|
|
|
|
$status[] = id(new PhabricatorApplicationStatusView())
|
|
|
|
->setType($type)
|
|
|
|
->setText($all_count_str)
|
|
|
|
->setCount($all_count);
|
|
|
|
} else {
|
|
|
|
list($blocking, $active, $waiting) =
|
|
|
|
DifferentialRevisionQuery::splitResponsible(
|
|
|
|
$revisions,
|
|
|
|
array($user->getPHID()));
|
|
|
|
|
|
|
|
$blocking = count($blocking);
|
|
|
|
$blocking_str = self::formatStatusCount(
|
|
|
|
$blocking,
|
|
|
|
'%s Reviews Blocking Others',
|
|
|
|
'%d Review(s) Blocking Others');
|
|
|
|
$type = PhabricatorApplicationStatusView::TYPE_NEEDS_ATTENTION;
|
|
|
|
$status[] = id(new PhabricatorApplicationStatusView())
|
|
|
|
->setType($type)
|
|
|
|
->setText($blocking_str)
|
|
|
|
->setCount($blocking);
|
|
|
|
|
|
|
|
$active = count($active);
|
|
|
|
$active_str = self::formatStatusCount(
|
|
|
|
$active,
|
|
|
|
'%s Reviews Need Attention',
|
|
|
|
'%d Review(s) Need Attention');
|
|
|
|
$type = PhabricatorApplicationStatusView::TYPE_WARNING;
|
|
|
|
$status[] = id(new PhabricatorApplicationStatusView())
|
|
|
|
->setType($type)
|
|
|
|
->setText($active_str)
|
|
|
|
->setCount($active);
|
|
|
|
|
|
|
|
$waiting = count($waiting);
|
|
|
|
$waiting_str = self::formatStatusCount(
|
|
|
|
$waiting,
|
|
|
|
'%s Reviews Waiting on Others',
|
|
|
|
'%d Review(s) Waiting on Others');
|
|
|
|
$type = PhabricatorApplicationStatusView::TYPE_INFO;
|
|
|
|
$status[] = id(new PhabricatorApplicationStatusView())
|
|
|
|
->setType($type)
|
|
|
|
->setText($waiting_str)
|
|
|
|
->setCount($waiting);
|
|
|
|
}
|
2012-08-02 23:07:21 +02:00
|
|
|
|
|
|
|
return $status;
|
2012-08-01 02:58:21 +02:00
|
|
|
}
|
|
|
|
|
2015-01-30 19:31:39 +01:00
|
|
|
public function supportsEmailIntegration() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAppEmailBlurb() {
|
|
|
|
return pht(
|
|
|
|
'Send email to these addresses to create revisions. The body of the '.
|
|
|
|
'message and / or one or more attachments should be the output of a '.
|
|
|
|
'"diff" command. %s',
|
|
|
|
phutil_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
2015-04-05 14:29:39 +02:00
|
|
|
'href' => $this->getInboundEmailSupportLink(),
|
|
|
|
),
|
2015-01-30 19:31:39 +01:00
|
|
|
pht('Learn More')));
|
|
|
|
}
|
|
|
|
|
2013-10-09 22:58:00 +02:00
|
|
|
protected function getCustomCapabilities() {
|
|
|
|
return array(
|
2014-07-25 00:20:39 +02:00
|
|
|
DifferentialDefaultViewCapability::CAPABILITY => array(
|
2014-07-23 02:03:09 +02:00
|
|
|
'caption' => pht('Default view policy for newly created revisions.'),
|
2013-10-09 22:58:00 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-04-01 16:36:16 +02:00
|
|
|
public function getMailCommandObjects() {
|
|
|
|
return array(
|
|
|
|
'revision' => array(
|
2015-04-01 17:13:12 +02:00
|
|
|
'name' => pht('Email Commands: Revisions'),
|
2015-04-01 18:23:00 +02:00
|
|
|
'header' => pht('Interacting with Differential Revisions'),
|
2015-04-01 16:36:16 +02:00
|
|
|
'object' => new DifferentialRevision(),
|
2015-04-01 18:23:00 +02:00
|
|
|
'summary' => pht(
|
|
|
|
'This page documents the commands you can use to interact with '.
|
|
|
|
'revisions in Differential.'),
|
2015-04-01 16:36:16 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
Implement a scope selector for the global search
Summary:
See M1433. Fixes T7266. Fixes T4475. Ref T7314.
Future work/notes/etc:
- Write the User Guide (see TODO).
- This might needs some design tweaks -- I think it's functionally almost-equivalent to the mock, but the UI isn't quite the same.
- (Mobile design is a touch off-looking I think?)
- When you use a custom query, the duplicate "magnifying glass" icons are a little weird. Maybe change one or the other.
- Maybe worth adding an "Open Documents in Current Application" option? Planning to wait for feedback on that.
- Need a Quicksand integration to change the current application at some point.
- Searching in "Current Application" from, e.g., the 404 page just searches all documents. Current plan is to just document this behavior, since the icon is a pretty good callout and it seems plausible that this is intuitive enough that users won't have a hard time with it.
Test Plan:
New dropdown:
{F379150}
Device-ish:
{F379151}
Normal search (current application, from maniphest, selects tasks):
{F379153}
Application search from non-application:
{F379154}
Reviewers: btrahan, chad
Reviewed By: chad
Subscribers: johnny-bit, epriestley
Maniphest Tasks: T7266, T7314, T4475
Differential Revision: https://secure.phabricator.com/D12509
2015-04-22 23:31:36 +02:00
|
|
|
public function getApplicationSearchDocumentTypes() {
|
|
|
|
return array(
|
|
|
|
DifferentialRevisionPHIDType::TYPECONST,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-07-30 19:43:49 +02:00
|
|
|
}
|