Replace home directory list with a dashboard
Summary: Rough cut that still needs a lot of polish, but replace the directory list with more of a dashboard type thing: - Show "Unbreak Now", triage-in-your-projects, and other stuff that you're supposed to deal with, then feed. - Move tools a click a way behind nav -- this also lets us put more stuff there and subtools, etc., later. - Remove tabs. - Merge the category/item editing views. - I also added a light blue wash to the side nav, not sure if I like that or not. Test Plan: - Viewed all elements in empty and nonempty states. - Viewed applications, edited items/categories. Reviewers: btrahan, aran Reviewed By: btrahan CC: aran, epriestley, davidreuss Maniphest Tasks: T21, T631 Differential Revision: https://secure.phabricator.com/D1574
This commit is contained in:
@@ -108,7 +108,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'aphront-panel-view-css' =>
|
'aphront-panel-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/58da9c70/rsrc/css/aphront/panel-view.css',
|
'uri' => '/res/f4157618/rsrc/css/aphront/panel-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -126,7 +126,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'aphront-side-nav-view-css' =>
|
'aphront-side-nav-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/42f70a69/rsrc/css/aphront/side-nav-view.css',
|
'uri' => '/res/ba0e18dd/rsrc/css/aphront/side-nav-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1368,7 +1368,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'phabricator-directory-css' =>
|
'phabricator-directory-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/a3d307c5/rsrc/css/application/directory/phabricator-directory.css',
|
'uri' => '/res/61afca2b/rsrc/css/application/directory/phabricator-directory.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1787,28 +1787,7 @@ celerity_register_resource_map(array(
|
|||||||
'uri' => '/res/pkg/540effd7/typeahead.pkg.js',
|
'uri' => '/res/pkg/540effd7/typeahead.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'80580cea' =>
|
'775f5bae' =>
|
||||||
array(
|
|
||||||
'name' => 'differential.pkg.css',
|
|
||||||
'symbols' =>
|
|
||||||
array(
|
|
||||||
0 => 'differential-core-view-css',
|
|
||||||
1 => 'differential-changeset-view-css',
|
|
||||||
2 => 'differential-revision-detail-css',
|
|
||||||
3 => 'differential-revision-history-css',
|
|
||||||
4 => 'differential-table-of-contents-css',
|
|
||||||
5 => 'differential-revision-comment-css',
|
|
||||||
6 => 'differential-revision-add-comment-css',
|
|
||||||
7 => 'differential-revision-comment-list-css',
|
|
||||||
8 => 'phabricator-object-selector-css',
|
|
||||||
9 => 'aphront-headsup-action-list-view-css',
|
|
||||||
10 => 'phabricator-content-source-view-css',
|
|
||||||
11 => 'differential-local-commits-view-css',
|
|
||||||
),
|
|
||||||
'uri' => '/res/pkg/80580cea/differential.pkg.css',
|
|
||||||
'type' => 'css',
|
|
||||||
),
|
|
||||||
'9fd6210b' =>
|
|
||||||
array(
|
array(
|
||||||
'name' => 'core.pkg.css',
|
'name' => 'core.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
@@ -1829,7 +1808,28 @@ celerity_register_resource_map(array(
|
|||||||
13 => 'phabricator-remarkup-css',
|
13 => 'phabricator-remarkup-css',
|
||||||
14 => 'syntax-highlighting-css',
|
14 => 'syntax-highlighting-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/9fd6210b/core.pkg.css',
|
'uri' => '/res/pkg/775f5bae/core.pkg.css',
|
||||||
|
'type' => 'css',
|
||||||
|
),
|
||||||
|
'80580cea' =>
|
||||||
|
array(
|
||||||
|
'name' => 'differential.pkg.css',
|
||||||
|
'symbols' =>
|
||||||
|
array(
|
||||||
|
0 => 'differential-core-view-css',
|
||||||
|
1 => 'differential-changeset-view-css',
|
||||||
|
2 => 'differential-revision-detail-css',
|
||||||
|
3 => 'differential-revision-history-css',
|
||||||
|
4 => 'differential-table-of-contents-css',
|
||||||
|
5 => 'differential-revision-comment-css',
|
||||||
|
6 => 'differential-revision-add-comment-css',
|
||||||
|
7 => 'differential-revision-comment-list-css',
|
||||||
|
8 => 'phabricator-object-selector-css',
|
||||||
|
9 => 'aphront-headsup-action-list-view-css',
|
||||||
|
10 => 'phabricator-content-source-view-css',
|
||||||
|
11 => 'differential-local-commits-view-css',
|
||||||
|
),
|
||||||
|
'uri' => '/res/pkg/80580cea/differential.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'b164acea' =>
|
'b164acea' =>
|
||||||
@@ -1854,16 +1854,16 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'reverse' =>
|
'reverse' =>
|
||||||
array(
|
array(
|
||||||
'aphront-crumbs-view-css' => '9fd6210b',
|
'aphront-crumbs-view-css' => '775f5bae',
|
||||||
'aphront-dialog-view-css' => '9fd6210b',
|
'aphront-dialog-view-css' => '775f5bae',
|
||||||
'aphront-form-view-css' => '9fd6210b',
|
'aphront-form-view-css' => '775f5bae',
|
||||||
'aphront-headsup-action-list-view-css' => '80580cea',
|
'aphront-headsup-action-list-view-css' => '80580cea',
|
||||||
'aphront-list-filter-view-css' => '9fd6210b',
|
'aphront-list-filter-view-css' => '775f5bae',
|
||||||
'aphront-panel-view-css' => '9fd6210b',
|
'aphront-panel-view-css' => '775f5bae',
|
||||||
'aphront-side-nav-view-css' => '9fd6210b',
|
'aphront-side-nav-view-css' => '775f5bae',
|
||||||
'aphront-table-view-css' => '9fd6210b',
|
'aphront-table-view-css' => '775f5bae',
|
||||||
'aphront-tokenizer-control-css' => '9fd6210b',
|
'aphront-tokenizer-control-css' => '775f5bae',
|
||||||
'aphront-typeahead-control-css' => '9fd6210b',
|
'aphront-typeahead-control-css' => '775f5bae',
|
||||||
'differential-changeset-view-css' => '80580cea',
|
'differential-changeset-view-css' => '80580cea',
|
||||||
'differential-core-view-css' => '80580cea',
|
'differential-core-view-css' => '80580cea',
|
||||||
'differential-inline-comment-editor' => '15c4a6dd',
|
'differential-inline-comment-editor' => '15c4a6dd',
|
||||||
@@ -1912,16 +1912,16 @@ celerity_register_resource_map(array(
|
|||||||
'javelin-vector' => 'b164acea',
|
'javelin-vector' => 'b164acea',
|
||||||
'javelin-workflow' => '46547a92',
|
'javelin-workflow' => '46547a92',
|
||||||
'phabricator-content-source-view-css' => '80580cea',
|
'phabricator-content-source-view-css' => '80580cea',
|
||||||
'phabricator-core-buttons-css' => '9fd6210b',
|
'phabricator-core-buttons-css' => '775f5bae',
|
||||||
'phabricator-core-css' => '9fd6210b',
|
'phabricator-core-css' => '775f5bae',
|
||||||
'phabricator-directory-css' => '9fd6210b',
|
'phabricator-directory-css' => '775f5bae',
|
||||||
'phabricator-drag-and-drop-file-upload' => '15c4a6dd',
|
'phabricator-drag-and-drop-file-upload' => '15c4a6dd',
|
||||||
'phabricator-keyboard-shortcut' => '46547a92',
|
'phabricator-keyboard-shortcut' => '46547a92',
|
||||||
'phabricator-keyboard-shortcut-manager' => '46547a92',
|
'phabricator-keyboard-shortcut-manager' => '46547a92',
|
||||||
'phabricator-object-selector-css' => '80580cea',
|
'phabricator-object-selector-css' => '80580cea',
|
||||||
'phabricator-remarkup-css' => '9fd6210b',
|
'phabricator-remarkup-css' => '775f5bae',
|
||||||
'phabricator-shaped-request' => '15c4a6dd',
|
'phabricator-shaped-request' => '15c4a6dd',
|
||||||
'phabricator-standard-page-view' => '9fd6210b',
|
'phabricator-standard-page-view' => '775f5bae',
|
||||||
'syntax-highlighting-css' => '9fd6210b',
|
'syntax-highlighting-css' => '775f5bae',
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -472,13 +472,13 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
|
'PhabricatorDirectoryCategory' => 'applications/directory/storage/category',
|
||||||
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
|
'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete',
|
||||||
'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit',
|
'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit',
|
||||||
'PhabricatorDirectoryCategoryListController' => 'applications/directory/controller/categorylist',
|
'PhabricatorDirectoryCategoryViewController' => 'applications/directory/controller/categoryview',
|
||||||
'PhabricatorDirectoryController' => 'applications/directory/controller/base',
|
'PhabricatorDirectoryController' => 'applications/directory/controller/base',
|
||||||
'PhabricatorDirectoryDAO' => 'applications/directory/storage/base',
|
'PhabricatorDirectoryDAO' => 'applications/directory/storage/base',
|
||||||
|
'PhabricatorDirectoryEditController' => 'applications/directory/controller/edit',
|
||||||
'PhabricatorDirectoryItem' => 'applications/directory/storage/item',
|
'PhabricatorDirectoryItem' => 'applications/directory/storage/item',
|
||||||
'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete',
|
'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete',
|
||||||
'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit',
|
'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit',
|
||||||
'PhabricatorDirectoryItemListController' => 'applications/directory/controller/itemlist',
|
|
||||||
'PhabricatorDirectoryMainController' => 'applications/directory/controller/main',
|
'PhabricatorDirectoryMainController' => 'applications/directory/controller/main',
|
||||||
'PhabricatorDisabledUserController' => 'applications/auth/controller/disabled',
|
'PhabricatorDisabledUserController' => 'applications/auth/controller/disabled',
|
||||||
'PhabricatorDraft' => 'applications/draft/storage/draft',
|
'PhabricatorDraft' => 'applications/draft/storage/draft',
|
||||||
@@ -1204,13 +1204,13 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
|
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
|
||||||
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDirectoryCategoryListController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryCategoryViewController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDirectoryController' => 'PhabricatorController',
|
'PhabricatorDirectoryController' => 'PhabricatorController',
|
||||||
'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO',
|
||||||
|
'PhabricatorDirectoryEditController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO',
|
'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO',
|
||||||
'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController',
|
|
||||||
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
|
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
|
||||||
'PhabricatorDisabledUserController' => 'PhabricatorAuthController',
|
'PhabricatorDisabledUserController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorDraft' => 'PhabricatorDraftDAO',
|
'PhabricatorDraft' => 'PhabricatorDraftDAO',
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ class AphrontDefaultApplicationConfiguration
|
|||||||
'$' => 'PhabricatorDirectoryMainController',
|
'$' => 'PhabricatorDirectoryMainController',
|
||||||
),
|
),
|
||||||
'/directory/' => array(
|
'/directory/' => array(
|
||||||
'item/$'
|
'(?P<id>\d+)/$'
|
||||||
=> 'PhabricatorDirectoryItemListController',
|
=> 'PhabricatorDirectoryCategoryViewController',
|
||||||
|
'edit/$'
|
||||||
|
=> 'PhabricatorDirectoryEditController',
|
||||||
'item/edit/(?:(?P<id>\d+)/)?$'
|
'item/edit/(?:(?P<id>\d+)/)?$'
|
||||||
=> 'PhabricatorDirectoryItemEditController',
|
=> 'PhabricatorDirectoryItemEditController',
|
||||||
'item/delete/(?P<id>\d+)/'
|
'item/delete/(?P<id>\d+)/'
|
||||||
=> 'PhabricatorDirectoryItemDeleteController',
|
=> 'PhabricatorDirectoryItemDeleteController',
|
||||||
'category/$'
|
|
||||||
=> 'PhabricatorDirectoryCategoryListController',
|
|
||||||
'category/edit/(?:(?P<id>\d+)/)?$'
|
'category/edit/(?:(?P<id>\d+)/)?$'
|
||||||
=> 'PhabricatorDirectoryCategoryEditController',
|
=> 'PhabricatorDirectoryCategoryEditController',
|
||||||
'category/delete/(?P<id>\d+)/'
|
'category/delete/(?P<id>\d+)/'
|
||||||
|
|||||||
@@ -369,26 +369,9 @@ class DifferentialRevisionListController extends DifferentialController {
|
|||||||
$views = array();
|
$views = array();
|
||||||
switch ($filter) {
|
switch ($filter) {
|
||||||
case 'active':
|
case 'active':
|
||||||
$active = array();
|
list($active, $waiting) = DifferentialRevisionQuery::splitResponsible(
|
||||||
$waiting = array();
|
$revisions,
|
||||||
|
$user_phid);
|
||||||
// Bucket revisions into $active (revisions you need to do something
|
|
||||||
// about) and $waiting (revisions you're waiting on someone else to do
|
|
||||||
// something about).
|
|
||||||
foreach ($revisions as $revision) {
|
|
||||||
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
|
|
||||||
$needs_review = ($revision->getStatus() == $status_review);
|
|
||||||
$filter_is_author = ($revision->getAuthorPHID() == $user_phid);
|
|
||||||
|
|
||||||
// If exactly one of "needs review" and "the user is the author" is
|
|
||||||
// true, the user needs to act on it. Otherwise, they're waiting on
|
|
||||||
// it.
|
|
||||||
if ($needs_review ^ $filter_is_author) {
|
|
||||||
$active[] = $revision;
|
|
||||||
} else {
|
|
||||||
$waiting[] = $revision;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$view = id(new DifferentialRevisionListView())
|
$view = id(new DifferentialRevisionListView())
|
||||||
->setRevisions($active)
|
->setRevisions($active)
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('arcanist', 'differential/constants/revisionstatus');
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
phutil_require_module('phabricator', 'applications/differential/controller/base');
|
phutil_require_module('phabricator', 'applications/differential/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/differential/query/revision');
|
phutil_require_module('phabricator', 'applications/differential/query/revision');
|
||||||
|
|||||||
@@ -785,5 +785,30 @@ final class DifferentialRevisionQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function splitResponsible(array $revisions, $user_phid) {
|
||||||
|
$active = array();
|
||||||
|
$waiting = array();
|
||||||
|
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
|
||||||
|
|
||||||
|
// Bucket revisions into $active (revisions you need to do something
|
||||||
|
// about) and $waiting (revisions you're waiting on someone else to do
|
||||||
|
// something about).
|
||||||
|
foreach ($revisions as $revision) {
|
||||||
|
$needs_review = ($revision->getStatus() == $status_review);
|
||||||
|
$filter_is_author = ($revision->getAuthorPHID() == $user_phid);
|
||||||
|
|
||||||
|
// If exactly one of "needs review" and "the user is the author" is
|
||||||
|
// true, the user needs to act on it. Otherwise, they're waiting on
|
||||||
|
// it.
|
||||||
|
if ($needs_review ^ $filter_is_author) {
|
||||||
|
$active[] = $revision;
|
||||||
|
} else {
|
||||||
|
$waiting[] = $revision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($active, $waiting);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,28 +26,9 @@ abstract class PhabricatorDirectoryController extends PhabricatorController {
|
|||||||
public function buildStandardPageResponse($view, array $data) {
|
public function buildStandardPageResponse($view, array $data) {
|
||||||
$page = $this->buildStandardPageView();
|
$page = $this->buildStandardPageView();
|
||||||
|
|
||||||
$page->setApplicationName('Directory');
|
|
||||||
$page->setBaseURI('/');
|
$page->setBaseURI('/');
|
||||||
$page->setTitle(idx($data, 'title'));
|
$page->setTitle(idx($data, 'title'));
|
||||||
|
|
||||||
if ($this->getRequest()->getUser()->getIsAdmin()) {
|
|
||||||
$tabs = array(
|
|
||||||
'categories' => array(
|
|
||||||
'href' => '/directory/category/',
|
|
||||||
'name' => 'Categories',
|
|
||||||
),
|
|
||||||
'items' => array(
|
|
||||||
'href' => '/directory/item/',
|
|
||||||
'name' => 'Items',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$tabs = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$page->setTabs(
|
|
||||||
$tabs,
|
|
||||||
idx($data, 'tab'));
|
|
||||||
$page->setGlyph("\xE2\x9A\x92");
|
$page->setGlyph("\xE2\x9A\x92");
|
||||||
$page->appendChild($view);
|
$page->appendChild($view);
|
||||||
|
|
||||||
@@ -55,4 +36,37 @@ abstract class PhabricatorDirectoryController extends PhabricatorController {
|
|||||||
return $response->setContent($page->render());
|
return $response->setContent($page->render());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function buildNav() {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
|
||||||
|
$nav = new AphrontSideNavFilterView();
|
||||||
|
$nav->setBaseURI(new PhutilURI('/'));
|
||||||
|
|
||||||
|
$nav->addLabel('Phabricator');
|
||||||
|
$nav->addFilter('home', 'Tactical Command', '/');
|
||||||
|
$nav->addSpacer();
|
||||||
|
$nav->addLabel('Applications');
|
||||||
|
|
||||||
|
$categories = $this->loadDirectoryCategories();
|
||||||
|
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
$nav->addFilter(
|
||||||
|
'directory/'.$category->getID(),
|
||||||
|
$category->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->getIsAdmin()) {
|
||||||
|
$nav->addSpacer();
|
||||||
|
$nav->addFilter('directory/edit', 'Edit Applications...');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nav;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadDirectoryCategories() {
|
||||||
|
$categories = id(new PhabricatorDirectoryCategory())->loadAll();
|
||||||
|
$categories = msort($categories, 'getSequence');
|
||||||
|
return $categories;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
|
|
||||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/directory/storage/category');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/sidenavfilter');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'parser/uri');
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -35,7 +35,7 @@ class PhabricatorDirectoryCategoryDeleteController
|
|||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
$category->delete();
|
$category->delete();
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI('/directory/category/');
|
->setURI('/directory/edit/');
|
||||||
}
|
}
|
||||||
|
|
||||||
$dialog = new AphrontDialogView();
|
$dialog = new AphrontDialogView();
|
||||||
@@ -43,7 +43,7 @@ class PhabricatorDirectoryCategoryDeleteController
|
|||||||
$dialog->setTitle('Really delete this category?');
|
$dialog->setTitle('Really delete this category?');
|
||||||
$dialog->appendChild("Are you sure you want to delete this category?");
|
$dialog->appendChild("Are you sure you want to delete this category?");
|
||||||
$dialog->addSubmitButton('Delete');
|
$dialog->addSubmitButton('Delete');
|
||||||
$dialog->addCancelButton('/directory/category/');
|
$dialog->addCancelButton('/directory/edit/');
|
||||||
$dialog->setSubmitURI($request->getPath());
|
$dialog->setSubmitURI($request->getPath());
|
||||||
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -52,7 +52,7 @@ class PhabricatorDirectoryCategoryEditController
|
|||||||
if (!$errors) {
|
if (!$errors) {
|
||||||
$category->save();
|
$category->save();
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI('/directory/category/');
|
->setURI('/directory/edit/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ class PhabricatorDirectoryCategoryEditController
|
|||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->setValue('Save')
|
->setValue('Save')
|
||||||
->addCancelButton('/directory/category/'));
|
->addCancelButton('/directory/edit/'));
|
||||||
|
|
||||||
$panel = new AphrontPanelView();
|
$panel = new AphrontPanelView();
|
||||||
if ($category->getID()) {
|
if ($category->getID()) {
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2011 Facebook, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PhabricatorDirectoryCategoryListController
|
|
||||||
extends PhabricatorDirectoryController {
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
$categories = id(new PhabricatorDirectoryCategory())->loadAll();
|
|
||||||
$categories = msort($categories, 'getSequence');
|
|
||||||
|
|
||||||
$rows = array();
|
|
||||||
foreach ($categories as $category) {
|
|
||||||
$rows[] = array(
|
|
||||||
$category->getID(),
|
|
||||||
phutil_render_tag(
|
|
||||||
'a',
|
|
||||||
array(
|
|
||||||
'href' => '/directory/category/edit/'.$category->getID().'/',
|
|
||||||
),
|
|
||||||
phutil_escape_html($category->getName())),
|
|
||||||
javelin_render_tag(
|
|
||||||
'a',
|
|
||||||
array(
|
|
||||||
'href' => '/directory/category/delete/'.$category->getID().'/',
|
|
||||||
'class' => 'button grey small',
|
|
||||||
'sigil' => 'workflow',
|
|
||||||
),
|
|
||||||
'Delete'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$table = new AphrontTableView($rows);
|
|
||||||
$table->setHeaders(
|
|
||||||
array(
|
|
||||||
'ID',
|
|
||||||
'Name',
|
|
||||||
'',
|
|
||||||
));
|
|
||||||
$table->setColumnClasses(
|
|
||||||
array(
|
|
||||||
null,
|
|
||||||
'wide',
|
|
||||||
'action',
|
|
||||||
));
|
|
||||||
|
|
||||||
$panel = new AphrontPanelView();
|
|
||||||
$panel->appendChild($table);
|
|
||||||
$panel->setHeader('Directory Categories');
|
|
||||||
$panel->setCreateButton('New Category', '/directory/category/edit/');
|
|
||||||
|
|
||||||
return $this->buildStandardPageResponse($panel, array(
|
|
||||||
'title' => 'Directory Category List',
|
|
||||||
'tab' => 'categories',
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PhabricatorDirectoryCategoryViewController
|
||||||
|
extends PhabricatorDirectoryController {
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = $data['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldRequireAdmin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$category = id(new PhabricatorDirectoryCategory())->load($this->id);
|
||||||
|
if (!$category) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = id(new PhabricatorDirectoryItem())->loadAllWhere(
|
||||||
|
'categoryID = %d',
|
||||||
|
$category->getID());
|
||||||
|
$items = msort($items, 'getSortKey');
|
||||||
|
|
||||||
|
$nav = $this->buildNav();
|
||||||
|
$nav->selectFilter('directory/'.$this->id, 'directory/'.$this->id);
|
||||||
|
|
||||||
|
require_celerity_resource('phabricator-directory-css');
|
||||||
|
|
||||||
|
$item_markup = array();
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$item_markup[] =
|
||||||
|
'<div class="aphront-directory-item">'.
|
||||||
|
'<h1>'.
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $item->getHref(),
|
||||||
|
),
|
||||||
|
phutil_escape_html($item->getName())).
|
||||||
|
'</h1>'.
|
||||||
|
'<p>'.phutil_escape_html($item->getDescription()).'</p>'.
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$content =
|
||||||
|
'<div class="aphront-directory-list">'.
|
||||||
|
implode("\n", $item_markup).
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
|
||||||
|
$nav->appendChild($content);
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
$nav,
|
||||||
|
array(
|
||||||
|
'title' => 'Directory Category List',
|
||||||
|
'tab' => 'categories',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
phutil_require_module('phabricator', 'applications/directory/controller/base');
|
phutil_require_module('phabricator', 'applications/directory/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/directory/storage/category');
|
phutil_require_module('phabricator', 'applications/directory/storage/category');
|
||||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
phutil_require_module('phabricator', 'applications/directory/storage/item');
|
||||||
phutil_require_module('phabricator', 'view/control/table');
|
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||||
phutil_require_module('phabricator', 'view/layout/panel');
|
|
||||||
|
|
||||||
phutil_require_module('phutil', 'markup');
|
phutil_require_module('phutil', 'markup');
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorDirectoryCategoryListController.php');
|
phutil_require_source('PhabricatorDirectoryCategoryViewController.php');
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,10 +16,71 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PhabricatorDirectoryItemListController
|
final class PhabricatorDirectoryEditController
|
||||||
extends PhabricatorDirectoryController {
|
extends PhabricatorDirectoryController {
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
|
$nav = $this->buildNav();
|
||||||
|
$nav->selectFilter('directory/edit', 'directory/edit');
|
||||||
|
|
||||||
|
$nav->appendChild($this->buildCategoryList());
|
||||||
|
$nav->appendChild($this->buildItemList());
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
$nav,
|
||||||
|
array(
|
||||||
|
'title' => 'Edit Applications',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildCategoryList() {
|
||||||
|
$categories = id(new PhabricatorDirectoryCategory())->loadAll();
|
||||||
|
$categories = msort($categories, 'getSequence');
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
$rows[] = array(
|
||||||
|
$category->getID(),
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/directory/category/edit/'.$category->getID().'/',
|
||||||
|
),
|
||||||
|
phutil_escape_html($category->getName())),
|
||||||
|
javelin_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/directory/category/delete/'.$category->getID().'/',
|
||||||
|
'class' => 'button grey small',
|
||||||
|
'sigil' => 'workflow',
|
||||||
|
),
|
||||||
|
'Delete'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = new AphrontTableView($rows);
|
||||||
|
$table->setHeaders(
|
||||||
|
array(
|
||||||
|
'ID',
|
||||||
|
'Name',
|
||||||
|
'',
|
||||||
|
));
|
||||||
|
$table->setColumnClasses(
|
||||||
|
array(
|
||||||
|
null,
|
||||||
|
'wide',
|
||||||
|
'action',
|
||||||
|
));
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->appendChild($table);
|
||||||
|
$panel->setHeader('Directory Categories');
|
||||||
|
$panel->setCreateButton('New Category', '/directory/category/edit/');
|
||||||
|
|
||||||
|
return $panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildItemList() {
|
||||||
$items = id(new PhabricatorDirectoryItem())->loadAll();
|
$items = id(new PhabricatorDirectoryItem())->loadAll();
|
||||||
$items = msort($items, 'getSortKey');
|
$items = msort($items, 'getSortKey');
|
||||||
|
|
||||||
@@ -70,10 +131,6 @@ class PhabricatorDirectoryItemListController
|
|||||||
$panel->setHeader('Directory Items');
|
$panel->setHeader('Directory Items');
|
||||||
$panel->setCreateButton('New Item', '/directory/item/edit/');
|
$panel->setCreateButton('New Item', '/directory/item/edit/');
|
||||||
|
|
||||||
return $this->buildStandardPageResponse($panel, array(
|
return $panel;
|
||||||
'title' => 'Directory Items',
|
|
||||||
'tab' => 'items',
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -17,4 +17,4 @@ phutil_require_module('phutil', 'markup');
|
|||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorDirectoryItemListController.php');
|
phutil_require_source('PhabricatorDirectoryEditController.php');
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -35,7 +35,7 @@ class PhabricatorDirectoryItemDeleteController
|
|||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
$item->delete();
|
$item->delete();
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI('/directory/item/');
|
->setURI('/directory/edit/');
|
||||||
}
|
}
|
||||||
|
|
||||||
$dialog = new AphrontDialogView();
|
$dialog = new AphrontDialogView();
|
||||||
@@ -43,7 +43,7 @@ class PhabricatorDirectoryItemDeleteController
|
|||||||
$dialog->setTitle('Really delete this item?');
|
$dialog->setTitle('Really delete this item?');
|
||||||
$dialog->appendChild("Are you sure you want to delete this item?");
|
$dialog->appendChild("Are you sure you want to delete this item?");
|
||||||
$dialog->addSubmitButton('Delete');
|
$dialog->addSubmitButton('Delete');
|
||||||
$dialog->addCancelButton('/directory/item/');
|
$dialog->addCancelButton('/directory/edit/');
|
||||||
$dialog->setSubmitURI($request->getPath());
|
$dialog->setSubmitURI($request->getPath());
|
||||||
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class PhabricatorDirectoryItemEditController
|
|||||||
if (!$errors) {
|
if (!$errors) {
|
||||||
$item->save();
|
$item->save();
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI('/directory/item/');
|
->setURI('/directory/edit/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ class PhabricatorDirectoryItemEditController
|
|||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->setValue('Save')
|
->setValue('Save')
|
||||||
->addCancelButton('/directory/item/'));
|
->addCancelButton('/directory/edit/'));
|
||||||
|
|
||||||
$panel = new AphrontPanelView();
|
$panel = new AphrontPanelView();
|
||||||
if ($item->getID()) {
|
if ($item->getID()) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
class PhabricatorDirectoryMainController
|
class PhabricatorDirectoryMainController
|
||||||
extends PhabricatorDirectoryController {
|
extends PhabricatorDirectoryController {
|
||||||
|
|
||||||
|
private $filter;
|
||||||
|
|
||||||
public function shouldRequireAdmin() {
|
public function shouldRequireAdmin() {
|
||||||
// These controllers are admin-only by default, but this one is public,
|
// These controllers are admin-only by default, but this one is public,
|
||||||
// so allow non-admin users to view it.
|
// so allow non-admin users to view it.
|
||||||
@@ -26,61 +28,242 @@ class PhabricatorDirectoryMainController
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
|
||||||
|
$project_query = new PhabricatorProjectQuery();
|
||||||
|
$project_query->setMembers(array($user->getPHID()));
|
||||||
|
$projects = $project_query->execute();
|
||||||
|
|
||||||
$items = id(new PhabricatorDirectoryItem())->loadAll();
|
$unbreak_panel = $this->buildUnbreakNowPanel();
|
||||||
$items = msort($items, 'getSortKey');
|
$triage_panel = $this->buildNeedsTriagePanel($projects);
|
||||||
|
$revision_panel = $this->buildRevisionPanel();
|
||||||
|
$tasks_panel = $this->buildTasksPanel();
|
||||||
|
$feed_view = $this->buildFeedView($projects);
|
||||||
|
|
||||||
$categories = id(new PhabricatorDirectoryCategory())->loadAll();
|
$nav = $this->buildNav();
|
||||||
$categories = msort($categories, 'getSequence');
|
$this->filter = $nav->selectFilter($this->filter, 'home');
|
||||||
|
|
||||||
$category_map = mpull($categories, 'getName', 'getID');
|
$content = array(
|
||||||
$category_map[0] = 'Free Radicals';
|
$unbreak_panel,
|
||||||
$items = mgroup($items, 'getCategoryID');
|
$triage_panel,
|
||||||
|
$revision_panel,
|
||||||
|
$tasks_panel,
|
||||||
|
$feed_view,
|
||||||
|
);
|
||||||
|
|
||||||
require_celerity_resource('phabricator-directory-css');
|
$nav->appendChild($content);
|
||||||
|
|
||||||
$content = array();
|
return $this->buildStandardPageResponse(
|
||||||
foreach ($category_map as $id => $category_name) {
|
$nav,
|
||||||
$category_items = idx($items, $id);
|
array(
|
||||||
if (!$category_items) {
|
'title' => 'Directory',
|
||||||
continue;
|
'tab' => 'directory',
|
||||||
}
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$item_markup = array();
|
private function buildUnbreakNowPanel() {
|
||||||
foreach ($category_items as $item) {
|
$user = $this->getRequest()->getUser();
|
||||||
$item_markup[] =
|
$user_phid = $user->getPHID();
|
||||||
'<div>'.
|
|
||||||
'<h2>'.
|
|
||||||
phutil_render_tag(
|
|
||||||
'a',
|
|
||||||
array(
|
|
||||||
'href' => $item->getHref(),
|
|
||||||
),
|
|
||||||
phutil_escape_html($item->getName())).
|
|
||||||
'</h2>'.
|
|
||||||
'<p>'.phutil_escape_html($item->getDescription()).'</p>'.
|
|
||||||
'</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$content[] =
|
$panel = new AphrontPanelView();
|
||||||
'<div class="aphront-directory-category">'.
|
$panel->setHeader('Unbreak Now!');
|
||||||
'<h1>'.phutil_escape_html($category_name).'</h1>'.
|
$panel->setCaption('Open tasks with "Unbreak Now!" priority.');
|
||||||
'<div class="aphront-directory-group">'.
|
|
||||||
implode("\n", $item_markup).
|
$task_query = new ManiphestTaskQuery();
|
||||||
'</div>'.
|
$task_query->withStatus(ManiphestTaskQuery::STATUS_OPEN);
|
||||||
'</div>';
|
$task_query->withPriority(ManiphestTaskPriority::PRIORITY_UNBREAK_NOW);
|
||||||
|
$task_query->setLimit(10);
|
||||||
|
$task_query->setCalculateRows(true);
|
||||||
|
|
||||||
|
$tasks = $task_query->execute();
|
||||||
|
|
||||||
|
if ($tasks) {
|
||||||
|
$panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/maniphest/view/all/',
|
||||||
|
'class' => 'grey button',
|
||||||
|
),
|
||||||
|
'View All Unbreak Now ('.$task_query->getRowCount().") \xC2\xBB"));
|
||||||
|
|
||||||
|
$panel->appendChild($this->buildTaskListView($tasks));
|
||||||
|
} else {
|
||||||
|
$panel->appendChild(
|
||||||
|
'<p>Nothing appears to be critically broken right now.</p>');
|
||||||
}
|
}
|
||||||
|
|
||||||
$content =
|
return $panel;
|
||||||
'<div class="aphront-directory-list">'.
|
}
|
||||||
implode("\n", $content).
|
|
||||||
'</div>';
|
|
||||||
|
|
||||||
return $this->buildStandardPageResponse($content, array(
|
private function buildNeedsTriagePanel(array $projects) {
|
||||||
'title' => 'Directory',
|
$user = $this->getRequest()->getUser();
|
||||||
'tab' => 'directory',
|
$user_phid = $user->getPHID();
|
||||||
));
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->setHeader('Needs Triage');
|
||||||
|
$panel->setCaption(
|
||||||
|
'Open tasks with "Needs Triage" priority in '.
|
||||||
|
'<a href="/project/">projects you are a member of</a>.');
|
||||||
|
|
||||||
|
$task_query = new ManiphestTaskQuery();
|
||||||
|
$task_query->withStatus(ManiphestTaskQuery::STATUS_OPEN);
|
||||||
|
$task_query->withPriority(ManiphestTaskPriority::PRIORITY_TRIAGE);
|
||||||
|
$task_query->withProjects(mpull($projects, 'getPHID'));
|
||||||
|
$task_query->withAnyProject(true);
|
||||||
|
$task_query->setCalculateRows(true);
|
||||||
|
$task_query->setLimit(10);
|
||||||
|
|
||||||
|
$tasks = $task_query->execute();
|
||||||
|
if ($tasks) {
|
||||||
|
$panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
// TODO: This should filter to just your projects' need-triage
|
||||||
|
// tasks?
|
||||||
|
'href' => '/maniphest/view/alltriage/',
|
||||||
|
'class' => 'grey button',
|
||||||
|
),
|
||||||
|
'View All Triage ('.$task_query->getRowCount().") \xC2\xBB"));
|
||||||
|
$panel->appendChild($this->buildTaskListView($tasks));
|
||||||
|
} else {
|
||||||
|
$panel->appendChild('<p>No tasks in your projects need triage.</p>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildRevisionPanel() {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
$user_phid = $user->getPHID();
|
||||||
|
|
||||||
|
$revision_query = new DifferentialRevisionQuery();
|
||||||
|
$revision_query->withStatus(DifferentialRevisionQuery::STATUS_OPEN);
|
||||||
|
$revision_query->withResponsibleUsers(array($user_phid));
|
||||||
|
$revision_query->needRelationships(true);
|
||||||
|
|
||||||
|
// NOTE: We need to unlimit this query to hit the responsible user
|
||||||
|
// fast-path.
|
||||||
|
$revision_query->setLimit(null);
|
||||||
|
$revisions = $revision_query->execute();
|
||||||
|
|
||||||
|
list($active, $waiting) = DifferentialRevisionQuery::splitResponsible(
|
||||||
|
$revisions,
|
||||||
|
$user_phid);
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->setHeader('Revisions Waiting on You');
|
||||||
|
$panel->setCaption('Revisions waiting for you for review or commit.');
|
||||||
|
|
||||||
|
$panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/differential/',
|
||||||
|
'class' => 'button grey',
|
||||||
|
),
|
||||||
|
"View Active Revisions \xC2\xBB"));
|
||||||
|
|
||||||
|
if ($active) {
|
||||||
|
$revision_view = id(new DifferentialRevisionListView())
|
||||||
|
->setRevisions($active)
|
||||||
|
->setUser($user);
|
||||||
|
$phids = array_merge(
|
||||||
|
array($user_phid),
|
||||||
|
$revision_view->getRequiredHandlePHIDs());
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||||
|
|
||||||
|
$revision_view->setHandles($handles);
|
||||||
|
|
||||||
|
$panel->appendChild($revision_view);
|
||||||
|
} else {
|
||||||
|
$panel->appendChild('<p>No revisions are waiting on you.</p>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildTasksPanel() {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
$user_phid = $user->getPHID();
|
||||||
|
|
||||||
|
$task_query = new ManiphestTaskQuery();
|
||||||
|
$task_query->withStatus(ManiphestTaskQuery::STATUS_OPEN);
|
||||||
|
$task_query->withOwners(array($user_phid));
|
||||||
|
$task_query->setCalculateRows(true);
|
||||||
|
$task_query->setLimit(10);
|
||||||
|
|
||||||
|
$tasks = $task_query->execute();
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->setHeader('Assigned Tasks');
|
||||||
|
$panel->setCaption('Tasks assigned to you.');
|
||||||
|
|
||||||
|
if ($tasks) {
|
||||||
|
$panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/maniphest/',
|
||||||
|
'class' => 'button grey',
|
||||||
|
),
|
||||||
|
"View All Assigned Tasks (".$task_query->getRowCount().") \xC2\xBB"));
|
||||||
|
$panel->appendChild($this->buildTaskListView($tasks));
|
||||||
|
} else {
|
||||||
|
$panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/maniphest/?users='.
|
||||||
|
ManiphestTaskOwner::OWNER_UP_FOR_GRABS,
|
||||||
|
'class' => 'button grey',
|
||||||
|
),
|
||||||
|
"View Unassigned Tasks \xC2\xBB"));
|
||||||
|
$panel->appendChild('<p>You have no assigned tasks.</p>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function buildTaskListView(array $tasks) {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
|
||||||
|
$phids = array_filter(mpull($tasks, 'getOwnerPHID'));
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||||
|
|
||||||
|
$view = new ManiphestTaskListView();
|
||||||
|
$view->setTasks($tasks);
|
||||||
|
$view->setUser($user);
|
||||||
|
$view->setHandles($handles);
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildFeedView(array $projects) {
|
||||||
|
$user = $this->getRequest()->getUser();
|
||||||
|
$user_phid = $user->getPHID();
|
||||||
|
|
||||||
|
$feed_query = new PhabricatorFeedQuery();
|
||||||
|
$feed_query->setFilterPHIDs(
|
||||||
|
array_merge(
|
||||||
|
array($user_phid),
|
||||||
|
mpull($projects, 'getPHID')));
|
||||||
|
$feed = $feed_query->execute();
|
||||||
|
|
||||||
|
$builder = new PhabricatorFeedBuilder($feed);
|
||||||
|
$builder->setUser($user);
|
||||||
|
$feed_view = $builder->buildView();
|
||||||
|
|
||||||
|
|
||||||
|
return
|
||||||
|
'<div style="padding: 1em 1em;">'.
|
||||||
|
'<h1 style="font-size: 18px; '.
|
||||||
|
'border-bottom: 1px solid #aaaaaa; '.
|
||||||
|
'margin: 0 1em;">Feed</h1>'.
|
||||||
|
$feed_view->render().
|
||||||
|
'</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'applications/differential/query/revision');
|
||||||
|
phutil_require_module('phabricator', 'applications/differential/view/revisionlist');
|
||||||
phutil_require_module('phabricator', 'applications/directory/controller/base');
|
phutil_require_module('phabricator', 'applications/directory/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/directory/storage/category');
|
phutil_require_module('phabricator', 'applications/feed/builder/feed');
|
||||||
phutil_require_module('phabricator', 'applications/directory/storage/item');
|
phutil_require_module('phabricator', 'applications/feed/query');
|
||||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
phutil_require_module('phabricator', 'applications/maniphest/constants/owner');
|
||||||
|
phutil_require_module('phabricator', 'applications/maniphest/constants/priority');
|
||||||
|
phutil_require_module('phabricator', 'applications/maniphest/query');
|
||||||
|
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', 'view/layout/panel');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'markup');
|
phutil_require_module('phutil', 'markup');
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,6 +24,7 @@ final class AphrontPanelView extends AphrontView {
|
|||||||
|
|
||||||
private $buttons = array();
|
private $buttons = array();
|
||||||
private $header;
|
private $header;
|
||||||
|
private $caption;
|
||||||
private $width;
|
private $width;
|
||||||
private $classes = array();
|
private $classes = array();
|
||||||
private $id;
|
private $id;
|
||||||
@@ -66,6 +67,11 @@ final class AphrontPanelView extends AphrontView {
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCaption($caption) {
|
||||||
|
$this->caption = $caption;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
if ($this->header !== null) {
|
if ($this->header !== null) {
|
||||||
$header = '<h1>'.$this->header.'</h1>';
|
$header = '<h1>'.$this->header.'</h1>';
|
||||||
@@ -73,6 +79,15 @@ final class AphrontPanelView extends AphrontView {
|
|||||||
$header = null;
|
$header = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->caption !== null) {
|
||||||
|
$caption =
|
||||||
|
'<div class="aphront-panel-view-caption">'.
|
||||||
|
$this->caption.
|
||||||
|
'</div>';
|
||||||
|
} else {
|
||||||
|
$caption = null;
|
||||||
|
}
|
||||||
|
|
||||||
$buttons = null;
|
$buttons = null;
|
||||||
if ($this->buttons) {
|
if ($this->buttons) {
|
||||||
$buttons =
|
$buttons =
|
||||||
@@ -97,7 +112,7 @@ final class AphrontPanelView extends AphrontView {
|
|||||||
'class' => implode(' ', $classes),
|
'class' => implode(' ', $classes),
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
),
|
),
|
||||||
$buttons.$header.$table);
|
$buttons.$header.$caption.$table);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,13 @@
|
|||||||
padding: 2px 0 8px;
|
padding: 2px 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aphront-panel-view-caption {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #666666;
|
||||||
|
margin-top: -0.75em;
|
||||||
|
margin-bottom: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
.aphront-panel-view-buttons {
|
.aphront-panel-view-buttons {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,15 +12,16 @@ td.aphront-side-nav-content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
th.aphront-side-nav-navigation {
|
th.aphront-side-nav-navigation {
|
||||||
border-right: 1px solid #bbbbbb;
|
border-right: 1px solid #99c4d7;
|
||||||
padding-bottom: 8em;
|
padding-bottom: 8em;
|
||||||
|
background: #fbfbff;
|
||||||
}
|
}
|
||||||
|
|
||||||
th.aphront-side-nav-navigation a,
|
th.aphront-side-nav-navigation a,
|
||||||
th.aphront-side-nav-navigation span {
|
th.aphront-side-nav-navigation span {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 0 2px;
|
margin: 0 0 2px;
|
||||||
min-width: 150px;
|
min-width: 165px;
|
||||||
padding: 3px 8px 3px 24px;
|
padding: 3px 8px 3px 24px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -30,11 +31,12 @@ th.aphront-side-nav-navigation span {
|
|||||||
th.aphront-side-nav-navigation span {
|
th.aphront-side-nav-navigation span {
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
th.aphront-side-nav-navigation a:hover {
|
th.aphront-side-nav-navigation a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background: #f3f3f9;
|
background: #e9e9f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
th.aphront-side-nav-navigation hr {
|
th.aphront-side-nav-navigation hr {
|
||||||
@@ -46,5 +48,5 @@ th.aphront-side-nav-navigation hr {
|
|||||||
|
|
||||||
th.aphront-side-nav-navigation a.aphront-side-nav-selected,
|
th.aphront-side-nav-navigation a.aphront-side-nav-selected,
|
||||||
th.aphront-side-nav-navigation a.aphront-side-nav-selected:hover {
|
th.aphront-side-nav-navigation a.aphront-side-nav-selected:hover {
|
||||||
background: #d8dfea;
|
background: #d8d8e6;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,11 @@
|
|||||||
|
|
||||||
|
|
||||||
.aphront-directory-list {
|
.aphront-directory-list {
|
||||||
margin: 1em 3% 8em;
|
margin: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aphront-directory-category h1 {
|
.aphront-directory-list h1 {
|
||||||
border-bottom: 1px solid #cccccc;
|
font-size: 16px;
|
||||||
margin-bottom: .5em;
|
|
||||||
padding-bottom: .1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aphront-directory-list h2 {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -27,12 +21,6 @@
|
|||||||
padding: .05em .5em .5em;
|
padding: .05em .5em .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aphront-directory-category {
|
.aphront-directory-item {
|
||||||
padding: 10px;
|
margin: 1em 0;
|
||||||
width: 300px;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.aphront-directory-group {
|
|
||||||
padding: 0 .5em 3em;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user