Skip to content

Commit

Permalink
Add a "jump nav" element to the homepage, for quick tool/object navig…
Browse files Browse the repository at this point in the history
…ation

Summary:
  - Restore quick methods for getting to common features (upload file, create
task, etc.)
  - Provide a flexible cli-like navigation element similar to stuff used at
Facebook (bunny1 / lolbunny).

Test Plan: Used jump nav and nav buttons.

Reviewers: btrahan, fratrik

Reviewed By: btrahan

CC: aran, epriestley

Differential Revision: https://secure.phabricator.com/D1619
  • Loading branch information
epriestley committed Feb 16, 2012
1 parent 29acc84 commit 965a4da
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 15 deletions.
42 changes: 31 additions & 11 deletions src/__celerity_resource_map__.php
Original file line number Diff line number Diff line change
Expand Up @@ -330,17 +330,6 @@
),
'disk' => '/rsrc/js/javelin/lib/behavior.js',
),
0 =>
array(
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-uri',
1 => 'javelin-php-serializer',
),
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
),
'javelin-behavior-aphront-basic-tokenizer' =>
array(
'uri' => '/res/9be30797/rsrc/js/application/core/behavior-tokenizer.js',
Expand Down Expand Up @@ -704,6 +693,17 @@
),
'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
),
'javelin-behavior-phabricator-autofocus' =>
array(
'uri' => '/res/2946bb89/rsrc/js/application/core/behavior-autofocus.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-autofocus.js',
),
'javelin-behavior-phabricator-keyboard-pager' =>
array(
'uri' => '/res/56d64eff/rsrc/js/application/core/behavior-keyboard-pager.js',
Expand Down Expand Up @@ -1413,6 +1413,15 @@
),
'disk' => '/rsrc/css/application/feed/feed.css',
),
'phabricator-jump-nav' =>
array(
'uri' => '/res/69238d2f/rsrc/css/application/directory/phabricator-jump-nav.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/directory/phabricator-jump-nav.css',
),
'phabricator-keyboard-shortcut' =>
array(
'uri' => '/res/beed38cd/rsrc/js/application/core/KeyboardShortcut.js',
Expand Down Expand Up @@ -1520,6 +1529,17 @@
),
'disk' => '/rsrc/js/application/core/ShapedRequest.js',
),
0 =>
array(
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-uri',
1 => 'javelin-php-serializer',
),
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
),
'phabricator-slowvote-css' =>
array(
'uri' => '/res/94d20443/rsrc/css/application/slowvote/slowvote.css',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public function getApplicationName() {

public function getURIMap() {
return $this->getResourceURIMapRules() + array(
'/(?:(?P<filter>feed)/)?$' => 'PhabricatorDirectoryMainController',
'/(?:(?P<filter>(?:feed|jump))/)?$' =>
'PhabricatorDirectoryMainController',
'/directory/' => array(
'(?P<id>\d+)/$'
=> 'PhabricatorDirectoryCategoryViewController',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public function buildNav() {

$nav->addLabel('Phabricator');
$nav->addFilter('home', 'Tactical Command', '/');
$nav->addFilter('jump', 'Jump Nav');
$nav->addFilter('feed', 'Feed');
$nav->addSpacer();
$nav->addLabel('Applications');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,24 @@ public function processRequest() {
$nav = $this->buildNav();
$this->filter = $nav->selectFilter($this->filter, 'home');

$project_query = new PhabricatorProjectQuery();
$project_query->setMembers(array($user->getPHID()));
$projects = $project_query->execute();
switch ($this->filter) {
case 'jump':
break;
case 'home':
case 'feed':
$project_query = new PhabricatorProjectQuery();
$project_query->setMembers(array($user->getPHID()));
$projects = $project_query->execute();
break;
default:
throw new Exception("Unknown filter '{$this->filter}'!");
}

switch ($this->filter) {
case 'feed':
return $this->buildFeedResponse($nav, $projects);
case 'jump':
return $this->buildJumpResponse($nav);
default:
return $this->buildMainResponse($nav, $projects);
}
Expand All @@ -53,6 +64,7 @@ public function processRequest() {
private function buildMainResponse($nav, $projects) {
$unbreak_panel = $this->buildUnbreakNowPanel();
$triage_panel = $this->buildNeedsTriagePanel($projects);
$jump_panel = $this->buildJumpPanel();
$revision_panel = $this->buildRevisionPanel();
$tasks_panel = $this->buildTasksPanel();
$feed_view = $this->buildFeedView($projects, $is_full = false);
Expand All @@ -61,6 +73,7 @@ private function buildMainResponse($nav, $projects) {
$content = array(
$unbreak_panel,
$triage_panel,
$jump_panel,
$revision_panel,
$tasks_panel,
$feed_view,
Expand All @@ -75,6 +88,79 @@ private function buildMainResponse($nav, $projects) {
));
}

private function buildJumpResponse($nav) {
$request = $this->getRequest();

if ($request->isFormPost()) {
$jump = $request->getStr('jump');
$jump = trim($jump);

$help_href = PhabricatorEnv::getDocLink(
'articles/Jump_Nav_User_Guide.html');

$patterns = array(
'/^help/i' => 'uri:'.$help_href,
'/^d$/i' => 'uri:/differential/',
'/^r$/i' => 'uri:/diffusion/',
'/^t$/i' => 'uri:/maniphest/',
'/r([A-Z]+)$/' => 'repository',
'/r([A-Z]+)(\S+)$/' => 'commit',
'/^d(\d+)$/i' => 'revision',
'/^t(\d+)$/i' => 'task',

// TODO: '/^p$/i' => 'uri:/projects/',
// TODO: '/^u$/i' => 'uri:/people/',
// TODO: '/^p\s+(\S+)$/i' => 'project',
// TODO: '/^u\s+(\S+)$/i' => 'user',
// TODO: '/^task:\s+(\S+)/i' => 'create-task',
// TODO: '/^(?:s|symbol)\s+(\S+)/i' => 'find-symbol',
);


foreach ($patterns as $pattern => $effect) {
$matches = null;
if (preg_match($pattern, $jump, $matches)) {
if (!strncmp($effect, 'uri:', 4)) {
return id(new AphrontRedirectResponse())
->setURI(substr($effect, 4));
} else {
switch ($effect) {
case 'repository':
return id(new AphrontRedirectResponse())
->setURI('/diffusion/'.$matches[1].'/');
case 'commit':
return id(new AphrontRedirectResponse())
->setURI('/'.$matches[0]);
case 'revision':
return id(new AphrontRedirectResponse())
->setURI('/D'.$matches[1]);
case 'task':
return id(new AphrontRedirectResponse())
->setURI('/T'.$matches[1]);
default:
throw new Exception("Unknown jump effect '{$effect}'!");
}
}
}
}

$query = new PhabricatorSearchQuery();
$query->setQuery($jump);
$query->save();

return id(new AphrontRedirectResponse())
->setURI('/search/'.$query->getQueryKey().'/');
}


$nav->appendChild($this->buildJumpPanel());
return $this->buildStandardPageResponse(
$nav,
array(
'title' => 'Jump Nav',
));
}

private function buildFeedResponse($nav, $projects) {
$view = $this->buildFeedView($projects, $is_full = true);
$nav->appendChild($view);
Expand Down Expand Up @@ -360,4 +446,76 @@ private function buildFeedView(array $projects, $is_full) {
'</div>';
}

private function buildJumpPanel() {
$request = $this->getRequest();
$user = $request->getUser();

$uniq_id = celerity_generate_unique_node_id();

Javelin::initBehavior(
'phabricator-autofocus',
array(
'id' => $uniq_id,
));

require_celerity_resource('phabricator-jump-nav');

$doc_href = PhabricatorEnv::getDocLink('articles/Jump_Nav_User_Guide.html');
$doc_link = phutil_render_tag(
'a',
array(
'href' => $doc_href,
),
'Jump Nav Use Guide');

$jump_input = phutil_render_tag(
'input',
array(
'type' => 'text',
'class' => 'phabricator-jump-nav',
'name' => 'jump',
'id' => $uniq_id,
)).
phutil_render_tag(
'p',
array(
'class' => 'phabricator-jump-nav-caption',
),
'Enter the name of an object like <tt>D123</tt> to quickly jump to '.
'it. See '.$doc_link.' or type <tt>help</tt>.');

$panel = new AphrontPanelView();
$panel->appendChild(
phabricator_render_form(
$user,
array(
'action' => '/jump/',
'method' => 'POST',
),
$jump_input));

$nav_buttons = array(
'/maniphest/task/create/' => 'Create a Task',
'/file/' => 'Upload a File',
'/paste/' => 'Create Paste',
'/w/' => 'Browse Wiki',
'/diffusion/' => 'Browse Code',
);

$panel->appendChild('<div class="phabricator-jump-nav-buttons">');
foreach ($nav_buttons as $uri => $name) {
$panel->appendChild(
phutil_render_tag(
'a',
array(
'href' => $uri,
'class' => 'button grey',
),
phutil_escape_html($name)));
}
$panel->appendChild('</div>');

return $panel;
}

}
6 changes: 6 additions & 0 deletions src/applications/directory/controller/main/__init__.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@



phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/differential/query/revision');
phutil_require_module('phabricator', 'applications/differential/view/revisionlist');
phutil_require_module('phabricator', 'applications/directory/controller/base');
Expand All @@ -17,6 +18,11 @@
phutil_require_module('phabricator', 'applications/maniphest/view/tasklist');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/project/query/project');
phutil_require_module('phabricator', 'applications/search/storage/query');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/layout/minipanel');
phutil_require_module('phabricator', 'view/layout/panel');

Expand Down
21 changes: 21 additions & 0 deletions src/docs/userguide/jump.diviner
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@title Jump Nav User Guide
@group userguide

Command reference for the jump nav.

= Overview =

The jump nav provides a quick way to navigate to tools and objects: just type
a navigational command into the box and press return.

= Supported Commands =

- **help** - Jump to this document.
- **T** - Jump to Maniphest.
- **T123** - Jump to Maniphest Task 123.
- **D** - Jump to Differential.
- **D123** - Jump to Differential Revision 123.
- **r** - Jump to Diffusion.
- **rXYZ** - Jump to Diffusion Repository XYZ.
- **rXYZabcdef** - Jump to Diffusion Commit rXYZabcdef.
- **(default)** - Search for input.
26 changes: 26 additions & 0 deletions webroot/rsrc/css/application/directory/phabricator-jump-nav.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @provides phabricator-jump-nav
*/

.phabricator-jump-nav {
font-size: 18px;
width: 98%;
padding: .25em 1%;
}

.phabricator-jump-nav-caption {
font-size: 11px;
color: #666666;
margin-top: 4px;
}

.phabricator-jump-nav-buttons {
margin-top: 1em;
text-align: center;
}

.phabricator-jump-nav-buttons a.button {
margin-right: .75em;
width: 125px;
text-align: center;
}
8 changes: 8 additions & 0 deletions webroot/rsrc/js/application/core/behavior-autofocus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @provides javelin-behavior-phabricator-autofocus
* @requires javelin-behavior javelin-dom
*/

JX.behavior('phabricator-autofocus', function(config) {
try { JX.$(config.id).focus(); } catch (x) { }
});

0 comments on commit 965a4da

Please sign in to comment.