1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-27 15:08:20 +01:00

Revamp Projects with new navigation

Summary:
A refresh of Projects including a new navigations UI.

 - New Navigation UI.
 - Auto switch default page if Workboard has been initialized
 - Move Feed to it's own page
 - Increase 'tasks' on Project Home to 50 over 10
 - Fix various display bugs on Workboards
 - Remove 'crumbs' from Project portal (unneeded).

Test Plan:
- clicked a link for a project with no workboard and saw the profile
- clicked a link for a project with a workboard and saw the workboard
- navigated around the various edit pages, inspecting links and making sure things linked back to the new profile uri

{F266460}

{F266461}

{F266462}

{F266463}

{F266464}

Reviewers: epriestley, btrahan

Reviewed By: epriestley, btrahan

Subscribers: Korvin, epriestley

Differential Revision: https://secure.phabricator.com/D11272
This commit is contained in:
Chad Little 2015-01-12 10:04:01 -08:00
parent 1f6c91a7ba
commit 953f281dc0
26 changed files with 466 additions and 246 deletions

View file

@ -7,7 +7,7 @@
*/ */
return array( return array(
'names' => array( 'names' => array(
'core.pkg.css' => 'b99369cc', 'core.pkg.css' => '60a6d241',
'core.pkg.js' => '61af8961', 'core.pkg.js' => '61af8961',
'darkconsole.pkg.js' => '8ab24e01', 'darkconsole.pkg.js' => '8ab24e01',
'differential.pkg.css' => '8af45893', 'differential.pkg.css' => '8af45893',
@ -23,7 +23,7 @@ return array(
'rsrc/css/aphront/error-view.css' => '3462dbee', 'rsrc/css/aphront/error-view.css' => '3462dbee',
'rsrc/css/aphront/lightbox-attachment.css' => '7acac05d', 'rsrc/css/aphront/lightbox-attachment.css' => '7acac05d',
'rsrc/css/aphront/list-filter-view.css' => '2ae43867', 'rsrc/css/aphront/list-filter-view.css' => '2ae43867',
'rsrc/css/aphront/multi-column.css' => '6d72e772', 'rsrc/css/aphront/multi-column.css' => '41a848c0',
'rsrc/css/aphront/notification.css' => '9c279160', 'rsrc/css/aphront/notification.css' => '9c279160',
'rsrc/css/aphront/pager-view.css' => '2e3539af', 'rsrc/css/aphront/pager-view.css' => '2e3539af',
'rsrc/css/aphront/panel-view.css' => '5846dfa2', 'rsrc/css/aphront/panel-view.css' => '5846dfa2',
@ -94,7 +94,7 @@ return array(
'rsrc/css/application/ponder/feed.css' => 'e62615b6', 'rsrc/css/application/ponder/feed.css' => 'e62615b6',
'rsrc/css/application/ponder/post.css' => 'ebab8a70', 'rsrc/css/application/ponder/post.css' => 'ebab8a70',
'rsrc/css/application/ponder/vote.css' => '8ed6ed8b', 'rsrc/css/application/ponder/vote.css' => '8ed6ed8b',
'rsrc/css/application/profile/profile-view.css' => '28f433ef', 'rsrc/css/application/profile/profile-view.css' => 'fddedfa1',
'rsrc/css/application/projects/project-icon.css' => 'c2ecb7f1', 'rsrc/css/application/projects/project-icon.css' => 'c2ecb7f1',
'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733', 'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733',
'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', 'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5',
@ -115,7 +115,7 @@ return array(
'rsrc/css/layout/phabricator-crumbs-view.css' => 'd5aa87e4', 'rsrc/css/layout/phabricator-crumbs-view.css' => 'd5aa87e4',
'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82',
'rsrc/css/layout/phabricator-hovercard-view.css' => '893f4783', 'rsrc/css/layout/phabricator-hovercard-view.css' => '893f4783',
'rsrc/css/layout/phabricator-side-menu-view.css' => '90eafc85', 'rsrc/css/layout/phabricator-side-menu-view.css' => '7e8c6341',
'rsrc/css/layout/phabricator-source-code-view.css' => '7d346aa4', 'rsrc/css/layout/phabricator-source-code-view.css' => '7d346aa4',
'rsrc/css/phui/calendar/phui-calendar-day.css' => 'de035c8a', 'rsrc/css/phui/calendar/phui-calendar-day.css' => 'de035c8a',
'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1d0ca59', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1d0ca59',
@ -136,7 +136,7 @@ return array(
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
'rsrc/css/phui/phui-list.css' => '53deb25c', 'rsrc/css/phui/phui-list.css' => '53deb25c',
'rsrc/css/phui/phui-object-box.css' => 'dd19785f', 'rsrc/css/phui/phui-object-box.css' => 'dd19785f',
'rsrc/css/phui/phui-object-item-list-view.css' => '5b2ad99d', 'rsrc/css/phui/phui-object-item-list-view.css' => '8279b873',
'rsrc/css/phui/phui-pinboard-view.css' => '3dd4a269', 'rsrc/css/phui/phui-pinboard-view.css' => '3dd4a269',
'rsrc/css/phui/phui-property-list-view.css' => '51480060', 'rsrc/css/phui/phui-property-list-view.css' => '51480060',
'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b', 'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b',
@ -145,7 +145,7 @@ return array(
'rsrc/css/phui/phui-tag-view.css' => '6b74282b', 'rsrc/css/phui/phui-tag-view.css' => '6b74282b',
'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-text.css' => 'cf019f54',
'rsrc/css/phui/phui-timeline-view.css' => '415bf348', 'rsrc/css/phui/phui-timeline-view.css' => '415bf348',
'rsrc/css/phui/phui-workboard-view.css' => '2bf82d00', 'rsrc/css/phui/phui-workboard-view.css' => '8896938c',
'rsrc/css/phui/phui-workpanel-view.css' => 'e495a5cc', 'rsrc/css/phui/phui-workpanel-view.css' => 'e495a5cc',
'rsrc/css/sprite-apps-large.css' => '20ec0cc0', 'rsrc/css/sprite-apps-large.css' => '20ec0cc0',
'rsrc/css/sprite-apps.css' => 'd5baed0f', 'rsrc/css/sprite-apps.css' => 'd5baed0f',
@ -498,7 +498,7 @@ return array(
'aphront-dialog-view-css' => '4dbbe3bb', 'aphront-dialog-view-css' => '4dbbe3bb',
'aphront-error-view-css' => '3462dbee', 'aphront-error-view-css' => '3462dbee',
'aphront-list-filter-view-css' => '2ae43867', 'aphront-list-filter-view-css' => '2ae43867',
'aphront-multi-column-view-css' => '6d72e772', 'aphront-multi-column-view-css' => '41a848c0',
'aphront-pager-view-css' => '2e3539af', 'aphront-pager-view-css' => '2e3539af',
'aphront-panel-view-css' => '5846dfa2', 'aphront-panel-view-css' => '5846dfa2',
'aphront-table-view-css' => 'b22b7216', 'aphront-table-view-css' => 'b22b7216',
@ -728,11 +728,11 @@ return array(
'phabricator-object-selector-css' => '029a133d', 'phabricator-object-selector-css' => '029a133d',
'phabricator-phtize' => 'd254d646', 'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => '72da38cc', 'phabricator-prefab' => '72da38cc',
'phabricator-profile-css' => '28f433ef', 'phabricator-profile-css' => 'fddedfa1',
'phabricator-remarkup-css' => '7604f12e', 'phabricator-remarkup-css' => '7604f12e',
'phabricator-search-results-css' => 'f240504c', 'phabricator-search-results-css' => 'f240504c',
'phabricator-shaped-request' => '7cbe244b', 'phabricator-shaped-request' => '7cbe244b',
'phabricator-side-menu-view-css' => '90eafc85', 'phabricator-side-menu-view-css' => '7e8c6341',
'phabricator-slowvote-css' => '266df6a1', 'phabricator-slowvote-css' => '266df6a1',
'phabricator-source-code-view-css' => '7d346aa4', 'phabricator-source-code-view-css' => '7d346aa4',
'phabricator-standard-page-view' => '2c96cfb5', 'phabricator-standard-page-view' => '2c96cfb5',
@ -780,7 +780,7 @@ return array(
'phui-info-panel-css' => '27ea50a1', 'phui-info-panel-css' => '27ea50a1',
'phui-list-view-css' => '53deb25c', 'phui-list-view-css' => '53deb25c',
'phui-object-box-css' => 'dd19785f', 'phui-object-box-css' => 'dd19785f',
'phui-object-item-list-view-css' => '5b2ad99d', 'phui-object-item-list-view-css' => '8279b873',
'phui-pinboard-view-css' => '3dd4a269', 'phui-pinboard-view-css' => '3dd4a269',
'phui-property-list-view-css' => '51480060', 'phui-property-list-view-css' => '51480060',
'phui-remarkup-preview-css' => '19ad512b', 'phui-remarkup-preview-css' => '19ad512b',
@ -789,7 +789,7 @@ return array(
'phui-tag-view-css' => '6b74282b', 'phui-tag-view-css' => '6b74282b',
'phui-text-css' => 'cf019f54', 'phui-text-css' => 'cf019f54',
'phui-timeline-view-css' => '415bf348', 'phui-timeline-view-css' => '415bf348',
'phui-workboard-view-css' => '2bf82d00', 'phui-workboard-view-css' => '8896938c',
'phui-workpanel-view-css' => 'e495a5cc', 'phui-workpanel-view-css' => 'e495a5cc',
'phuix-action-list-view' => 'b5c256b8', 'phuix-action-list-view' => 'b5c256b8',
'phuix-action-view' => '6e8cefa4', 'phuix-action-view' => '6e8cefa4',

View file

@ -2199,6 +2199,7 @@ phutil_register_library_map(array(
'PhabricatorProjectEditMainController' => 'applications/project/controller/PhabricatorProjectEditMainController.php', 'PhabricatorProjectEditMainController' => 'applications/project/controller/PhabricatorProjectEditMainController.php',
'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php',
'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php', 'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php',
'PhabricatorProjectFeedController' => 'applications/project/controller/PhabricatorProjectFeedController.php',
'PhabricatorProjectIcon' => 'applications/project/icon/PhabricatorProjectIcon.php', 'PhabricatorProjectIcon' => 'applications/project/icon/PhabricatorProjectIcon.php',
'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php',
'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
@ -2225,6 +2226,7 @@ phutil_register_library_map(array(
'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php', 'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php',
'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php', 'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php',
'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php',
'PhabricatorProjectViewController' => 'applications/project/controller/PhabricatorProjectViewController.php',
'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php', 'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php',
'PhabricatorProjectWikiExplainController' => 'applications/project/controller/PhabricatorProjectWikiExplainController.php', 'PhabricatorProjectWikiExplainController' => 'applications/project/controller/PhabricatorProjectWikiExplainController.php',
'PhabricatorProjectsPolicyRule' => 'applications/policy/rule/PhabricatorProjectsPolicyRule.php', 'PhabricatorProjectsPolicyRule' => 'applications/policy/rule/PhabricatorProjectsPolicyRule.php',
@ -5418,6 +5420,7 @@ phutil_register_library_map(array(
'PhabricatorProjectEditMainController' => 'PhabricatorProjectController', 'PhabricatorProjectEditMainController' => 'PhabricatorProjectController',
'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController',
'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase', 'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase',
'PhabricatorProjectFeedController' => 'PhabricatorProjectController',
'PhabricatorProjectIcon' => 'Phobject', 'PhabricatorProjectIcon' => 'Phobject',
'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType',
@ -5445,6 +5448,7 @@ phutil_register_library_map(array(
'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener', 'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener',
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
'PhabricatorProjectViewController' => 'PhabricatorProjectController',
'PhabricatorProjectWatchController' => 'PhabricatorProjectController', 'PhabricatorProjectWatchController' => 'PhabricatorProjectController',
'PhabricatorProjectWikiExplainController' => 'PhabricatorProjectController', 'PhabricatorProjectWikiExplainController' => 'PhabricatorProjectController',
'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule',

View file

@ -52,8 +52,12 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
=> 'PhabricatorProjectMembersEditController', => 'PhabricatorProjectMembersEditController',
'members/(?P<id>[1-9]\d*)/remove/' 'members/(?P<id>[1-9]\d*)/remove/'
=> 'PhabricatorProjectMembersRemoveController', => 'PhabricatorProjectMembersRemoveController',
'view/(?P<id>[1-9]\d*)/' 'profile/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectProfileController', => 'PhabricatorProjectProfileController',
'feed/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectFeedController',
'view/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectViewController',
'picture/(?P<id>[1-9]\d*)/' 'picture/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectEditPictureController', => 'PhabricatorProjectEditPictureController',
'icon/(?P<id>[1-9]\d*)/' 'icon/(?P<id>[1-9]\d*)/'
@ -86,7 +90,7 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
'wiki/' => 'PhabricatorProjectWikiExplainController', 'wiki/' => 'PhabricatorProjectWikiExplainController',
), ),
'/tag/' => array( '/tag/' => array(
'(?P<slug>[^/]+)/' => 'PhabricatorProjectProfileController', '(?P<slug>[^/]+)/' => 'PhabricatorProjectViewController',
'(?P<slug>[^/]+)/board/' => 'PhabricatorProjectBoardViewController', '(?P<slug>[^/]+)/board/' => 'PhabricatorProjectBoardViewController',
), ),
); );

View file

@ -13,12 +13,10 @@ abstract class PhabricatorProjectBoardController
return $this->project; return $this->project;
} }
protected function buildApplicationCrumbs() { public function buildIconNavView(PhabricatorProject $project) {
$project = $this->getProject(); $id = $project->getID();
$crumbs = parent::buildApplicationCrumbs(); $nav = parent::buildIconNavView($project);
$crumbs->addTextCrumb( $nav->selectFilter("board/{$id}/");
$project->getName(), return $nav;
$this->getApplicationURI('view/'.$project->getID().'/'));
return $crumbs;
} }
} }

View file

@ -15,16 +15,9 @@ final class PhabricatorProjectBoardViewController
return true; return true;
} }
public function willProcessRequest(array $data) { public function handleRequest(AphrontRequest $request) {
$this->id = idx($data, 'id');
$this->slug = idx($data, 'slug');
$this->queryKey = idx($data, 'queryKey');
$this->filter = (bool)idx($data, 'filter');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser(); $viewer = $request->getUser();
$id = $request->getURIData('id');
$show_hidden = $request->getBool('hidden'); $show_hidden = $request->getBool('hidden');
$this->showHidden = $show_hidden; $this->showHidden = $show_hidden;
@ -32,10 +25,12 @@ final class PhabricatorProjectBoardViewController
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->needImages(true); ->needImages(true);
if ($this->slug) { $id = $request->getURIData('id');
$project->withSlugs(array($this->slug)); $slug = $request->getURIData('slug');
if ($slug) {
$project->withSlugs(array($slug));
} else { } else {
$project->withIDs(array($this->id)); $project->withIDs(array($id));
} }
$project = $project->executeOne(); $project = $project->executeOne();
if (!$project) { if (!$project) {
@ -111,7 +106,7 @@ final class PhabricatorProjectBoardViewController
$engine->getQueryResultsPageURI($saved->getQueryKey()))); $engine->getQueryResultsPageURI($saved->getQueryKey())));
} }
$query_key = $this->queryKey; $query_key = $request->getURIData('queryKey');
if (!$query_key) { if (!$query_key) {
$query_key = 'open'; $query_key = 'open';
} }
@ -133,7 +128,7 @@ final class PhabricatorProjectBoardViewController
$custom_query = $saved; $custom_query = $saved;
} }
if ($this->filter) { if ($request->getURIData('filter')) {
$filter_form = id(new AphrontFormView()) $filter_form = id(new AphrontFormView())
->setUser($viewer); ->setUser($viewer);
$engine->buildSearchForm($filter_form, $saved); $engine->buildSearchForm($filter_form, $saved);
@ -303,7 +298,7 @@ final class PhabricatorProjectBoardViewController
$header_link = phutil_tag( $header_link = phutil_tag(
'a', 'a',
array( array(
'href' => $this->getApplicationURI('view/'.$project->getID().'/'), 'href' => $this->getApplicationURI('profile/'.$project->getID().'/'),
), ),
$project->getName()); $project->getName());
@ -312,7 +307,7 @@ final class PhabricatorProjectBoardViewController
->setUser($viewer) ->setUser($viewer)
->setNoBackground(true) ->setNoBackground(true)
->setImage($project->getProfileImageURI()) ->setImage($project->getProfileImageURI())
->setImageURL($this->getApplicationURI('view/'.$project->getID().'/')) ->setImageURL($this->getApplicationURI('profile/'.$project->getID().'/'))
->addActionLink($sort_menu) ->addActionLink($sort_menu)
->addActionLink($filter_menu) ->addActionLink($filter_menu)
->addActionLink($manage_menu) ->addActionLink($manage_menu)
@ -322,10 +317,13 @@ final class PhabricatorProjectBoardViewController
->appendChild($board) ->appendChild($board)
->addClass('project-board-wrapper'); ->addClass('project-board-wrapper');
$nav = $this->buildIconNavView($project);
$nav->appendChild($header);
$nav->appendChild($board_box);
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$header, $nav,
$board_box,
), ),
array( array(
'title' => pht('%s Board', $project->getName()), 'title' => pht('%s Board', $project->getName()),

View file

@ -22,6 +22,7 @@ final class PhabricatorProjectColumnDetailController
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
)) ))
->withIDs(array($this->projectID)) ->withIDs(array($this->projectID))
->needImages(true)
->executeOne(); ->executeOne();
if (!$project) { if (!$project) {
@ -47,11 +48,6 @@ final class PhabricatorProjectColumnDetailController
$timeline->setShouldTerminate(true); $timeline->setShouldTerminate(true);
$title = pht('%s', $column->getDisplayName()); $title = pht('%s', $column->getDisplayName());
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Board'),
$this->getApplicationURI('board/'.$project->getID().'/'));
$crumbs->addTextCrumb($title);
$header = $this->buildHeaderView($column); $header = $this->buildHeaderView($column);
$actions = $this->buildActionView($column); $actions = $this->buildActionView($column);
@ -61,11 +57,13 @@ final class PhabricatorProjectColumnDetailController
->setHeader($header) ->setHeader($header)
->addPropertyList($properties); ->addPropertyList($properties);
$nav = $this->buildIconNavView($project);
$nav->appendChild($box);
$nav->appendChild($timeline);
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$crumbs, $nav,
$box,
$timeline,
), ),
array( array(
'title' => $title, 'title' => $title,

View file

@ -23,6 +23,7 @@ final class PhabricatorProjectColumnEditController
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->withIDs(array($this->projectID)) ->withIDs(array($this->projectID))
->needImages(true)
->executeOne(); ->executeOne();
if (!$project) { if (!$project) {
@ -135,11 +136,9 @@ final class PhabricatorProjectColumnEditController
if ($is_new) { if ($is_new) {
$title = pht('Create Column'); $title = pht('Create Column');
$submit = pht('Create Column'); $submit = pht('Create Column');
$crumb_text = pht('Create Column');
} else { } else {
$title = pht('Edit %s', $column->getDisplayName()); $title = pht('Edit %s', $column->getDisplayName());
$submit = pht('Save Column'); $submit = pht('Save Column');
$crumb_text = pht('Edit');
} }
$form->appendChild( $form->appendChild(
@ -147,28 +146,17 @@ final class PhabricatorProjectColumnEditController
->setValue($submit) ->setValue($submit)
->addCancelButton($view_uri)); ->addCancelButton($view_uri));
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
pht('Board'),
$this->getApplicationURI('board/'.$project->getID().'/'));
if (!$is_new) {
$crumbs->addTextCrumb(
$column->getDisplayName(),
$view_uri);
}
$crumbs->addTextCrumb($crumb_text);
$form_box = id(new PHUIObjectBoxView()) $form_box = id(new PHUIObjectBoxView())
->setHeaderText($title) ->setHeaderText($title)
->setValidationException($validation_exception) ->setValidationException($validation_exception)
->setForm($form); ->setForm($form);
$nav = $this->buildIconNavView($project);
$nav->appendChild($form_box);
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$crumbs, $nav,
$form_box,
), ),
array( array(
'title' => $title, 'title' => $title,

View file

@ -2,23 +2,56 @@
abstract class PhabricatorProjectController extends PhabricatorController { abstract class PhabricatorProjectController extends PhabricatorController {
public function buildApplicationMenu() {
return $this->buildSideNavView(true)->getMenu();
}
public function buildSideNavView($for_app = false) { public function buildSideNavView($for_app = false) {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView(); $nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI())); $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$id = null;
if ($for_app) { if ($for_app) {
$user = $this->getRequest()->getUser();
$id = $this->getRequest()->getURIData('id');
if ($id) {
$nav->addFilter("profile/{$id}/", pht('Profile'));
$nav->addFilter("board/{$id}/", pht('Workboard'));
$nav->addFilter("members/{$id}/", pht('Members'));
$nav->addFilter("feed/{$id}/", pht('Feed'));
$nav->addFilter("edit/{$id}/", pht('Edit'));
}
$nav->addFilter('create', pht('Create Project')); $nav->addFilter('create', pht('Create Project'));
} }
id(new PhabricatorProjectSearchEngine()) if (!$id) {
->setViewer($user) id(new PhabricatorProjectSearchEngine())
->addNavigationItems($nav->getMenu()); ->setViewer($user)
->addNavigationItems($nav->getMenu());
}
$nav->selectFilter(null); $nav->selectFilter(null);
return $nav; return $nav;
} }
public function buildIconNavView(PhabricatorProject $project) {
$id = $project->getID();
$picture = $project->getProfileImageURI();
$name = $project->getName();
$nav = new AphrontSideNavFilterView();
$nav->setIconNav(true);
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addIcon("profile/{$id}/", $name, null, $picture);
$nav->addIcon("board/{$id}/", pht('Workboard'), 'fa-columns');
$nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o');
$nav->addIcon("members/{$id}/", pht('Members'), 'fa-group');
$nav->addIcon("edit/{$id}/", pht('Edit'), 'fa-pencil');
return $nav;
}
} }

View file

@ -14,12 +14,14 @@ final class PhabricatorProjectEditDetailsController
$viewer = $request->getUser(); $viewer = $request->getUser();
if ($this->id) { if ($this->id) {
$is_new = false; $id = $request->getURIData('id');
$is_new = false;
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($this->id))
->needSlugs(true) ->needSlugs(true)
->needImages(true)
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
@ -149,7 +151,7 @@ final class PhabricatorProjectEditDetailsController
if ($is_new) { if ($is_new) {
$redirect_uri = $redirect_uri =
$this->getApplicationURI('view/'.$project->getID().'/'); $this->getApplicationURI('profile/'.$project->getID().'/');
} else { } else {
$redirect_uri = $redirect_uri =
$this->getApplicationURI('edit/'.$project->getID().'/'); $this->getApplicationURI('edit/'.$project->getID().'/');
@ -300,22 +302,17 @@ final class PhabricatorProjectEditDetailsController
->setValidationException($validation_exception) ->setValidationException($validation_exception)
->setForm($form); ->setForm($form);
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); if (!$is_new) {
if ($is_new) { $nav = $this->buildIconNavView($project);
$crumbs->addTextCrumb($title); $nav->selectFilter("edit/{$id}/");
$nav->appendChild($form_box);
} else { } else {
$crumbs $nav = array($form_box);
->addTextCrumb($project->getName(),
$this->getApplicationURI('view/'.$project->getID().'/'))
->addTextCrumb(pht('Edit'),
$this->getApplicationURI('edit/'.$project->getID().'/'))
->addTextCrumb(pht('Details'));
} }
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$crumbs, $nav,
$form_box,
), ),
array( array(
'title' => $title, 'title' => $title,

View file

@ -18,6 +18,7 @@ final class PhabricatorProjectEditMainController
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$viewer = $request->getUser(); $viewer = $request->getUser();
$id = $request->getURIData('id');
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
@ -43,12 +44,6 @@ final class PhabricatorProjectEditMainController
$actions = $this->buildActionListView($project); $actions = $this->buildActionListView($project);
$properties = $this->buildPropertyListView($project, $actions); $properties = $this->buildPropertyListView($project, $actions);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(
$project->getName(),
$this->getApplicationURI('view/'.$project->getID().'/'));
$crumbs->addTextCrumb(pht('Edit'));
$object_box = id(new PHUIObjectBoxView()) $object_box = id(new PHUIObjectBoxView())
->setHeader($header) ->setHeader($header)
->addPropertyList($properties); ->addPropertyList($properties);
@ -58,11 +53,16 @@ final class PhabricatorProjectEditMainController
new PhabricatorProjectTransactionQuery()); new PhabricatorProjectTransactionQuery());
$timeline->setShouldTerminate(true); $timeline->setShouldTerminate(true);
$nav = $this->buildIconNavView($project);
$nav->selectFilter("edit/{$id}/");
$nav->appendChild($object_box);
$nav->appendChild($timeline);
$mnav = $this->buildSideNavView();
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$crumbs, $nav,
$object_box,
$timeline,
), ),
array( array(
'title' => $project->getName(), 'title' => $project->getName(),

View file

@ -12,10 +12,12 @@ final class PhabricatorProjectEditPictureController
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$viewer = $request->getUser(); $viewer = $request->getUser();
$id = $request->getURIData('id');
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($this->id))
->needImages(true)
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
@ -27,7 +29,7 @@ final class PhabricatorProjectEditPictureController
} }
$edit_uri = $this->getApplicationURI('edit/'.$project->getID().'/'); $edit_uri = $this->getApplicationURI('edit/'.$project->getID().'/');
$view_uri = $this->getApplicationURI('view/'.$project->getID().'/'); $view_uri = $this->getApplicationURI('profile/'.$project->getID().'/');
$supported_formats = PhabricatorFile::getTransformableImageFormats(); $supported_formats = PhabricatorFile::getTransformableImageFormats();
$e_file = true; $e_file = true;
@ -100,10 +102,6 @@ final class PhabricatorProjectEditPictureController
} }
$title = pht('Edit Project Picture'); $title = pht('Edit Project Picture');
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb($project->getName(), $view_uri);
$crumbs->addTextCrumb(pht('Edit'), $edit_uri);
$crumbs->addTextCrumb(pht('Picture'));
$form = id(new PHUIFormLayoutView()) $form = id(new PHUIFormLayoutView())
->setUser($viewer); ->setUser($viewer);
@ -292,11 +290,14 @@ final class PhabricatorProjectEditPictureController
->setHeaderText(pht('Upload New Picture')) ->setHeaderText(pht('Upload New Picture'))
->setForm($upload_form); ->setForm($upload_form);
$nav = $this->buildIconNavView($project);
$nav->selectFilter("edit/{$id}/");
$nav->appendChild($form_box);
$nav->appendChild($upload_box);
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$crumbs, $nav,
$form_box,
$upload_box,
), ),
array( array(
'title' => $title, 'title' => $title,

View file

@ -0,0 +1,91 @@
<?php
final class PhabricatorProjectFeedController
extends PhabricatorProjectController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
$query = id(new PhabricatorProjectQuery())
->setViewer($user)
->needMembers(true)
->needWatchers(true)
->needImages(true)
->needSlugs(true);
$id = $request->getURIData('id');
$slug = $request->getURIData('slug');
if ($slug) {
$query->withSlugs(array($slug));
} else {
$query->withIDs(array($id));
}
$project = $query->executeOne();
if (!$project) {
return new Aphront404Response();
}
if ($slug && $slug != $project->getPrimarySlug()) {
return id(new AphrontRedirectResponse())
->setURI('/tag/'.$project->getPrimarySlug().'/');
}
require_celerity_resource('phabricator-profile-css');
$query = new PhabricatorFeedQuery();
$query->setFilterPHIDs(
array(
$project->getPHID(),
));
$query->setLimit(50);
$query->setViewer($request->getUser());
$stories = $query->execute();
$feed = $this->renderStories($stories);
$content = phutil_tag_div('phabricator-project-feed', $feed);
$nav = $this->buildIconNavView($project);
$nav->selectFilter("feed/{$id}/");
$nav->appendChild($content);
return $this->buildApplicationPage(
array(
$nav,
),
array(
'title' => $project->getName(),
));
}
private function renderFeedPage(PhabricatorProject $project) {
$query = new PhabricatorFeedQuery();
$query->setFilterPHIDs(array($project->getPHID()));
$query->setViewer($this->getRequest()->getUser());
$query->setLimit(100);
$stories = $query->execute();
if (!$stories) {
return pht('There are no stories about this project.');
}
return $this->renderStories($stories);
}
private function renderStories(array $stories) {
assert_instances_of($stories, 'PhabricatorFeedStory');
$builder = new PhabricatorFeedBuilder($stories);
$builder->setUser($this->getRequest()->getUser());
$builder->setShowHovercards(true);
$view = $builder->buildView();
return phutil_tag_div(
'profile-feed',
$view->render());
}
}

View file

@ -22,7 +22,7 @@ final class PhabricatorProjectListController
return $this->delegateToController($controller); return $this->delegateToController($controller);
} }
protected function buildApplicationMenu() { public function buildApplicationMenu() {
return $this->buildSideNavView(true)->getMenu(); return $this->buildSideNavView(true)->getMenu();
} }

View file

@ -12,15 +12,16 @@ final class PhabricatorProjectMembersEditController
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$id = $request->getURIData('id');
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($user) ->setViewer($user)
->withIDs(array($this->id)) ->withIDs(array($this->id))
->needMembers(true) ->needMembers(true)
->needImages(true)
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->executeOne(); ->executeOne();
if (!$project) { if (!$project) {
@ -73,39 +74,44 @@ final class PhabricatorProjectMembersEditController
); );
} }
$header_name = pht('Edit Members'); $can_edit = PhabricatorPolicyFilter::hasCapability(
$title = pht('Edit Members'); $user,
$project,
PhabricatorPolicyCapability::CAN_EDIT);
$form = new AphrontFormView(); $form_box = null;
$form $title = pht('Add Members');
->setUser($user) if ($can_edit) {
->appendChild( $header_name = pht('Edit Members');
id(new AphrontFormTokenizerControl()) $view_uri = $this->getApplicationURI('profile/'.$project->getID().'/');
->setName('phids')
->setLabel(pht('Add Members')) $form = new AphrontFormView();
->setDatasource(new PhabricatorPeopleDatasource())) $form
->appendChild( ->setUser($user)
id(new AphrontFormSubmitControl()) ->appendChild(
->addCancelButton('/project/view/'.$project->getID().'/') id(new AphrontFormTokenizerControl())
->setValue(pht('Add Members'))); ->setName('phids')
->setLabel(pht('Add Members'))
->setDatasource(new PhabricatorPeopleDatasource()))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($view_uri)
->setValue(pht('Add Members')));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setForm($form);
}
$member_list = $this->renderMemberList($project, $handles); $member_list = $this->renderMemberList($project, $handles);
$form_box = id(new PHUIObjectBoxView()) $nav = $this->buildIconNavView($project);
->setHeaderText($title) $nav->selectFilter("members/{$id}/");
->setForm($form); $nav->appendChild($form_box);
$nav->appendChild($member_list);
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView())
->addTextCrumb(
$project->getName(),
'/project/view/'.$project->getID().'/')
->addTextCrumb(pht('Edit Members'), $this->getApplicationURI());
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$crumbs, $nav,
$form_box,
$member_list,
), ),
array( array(
'title' => $title, 'title' => $title,
@ -119,8 +125,14 @@ final class PhabricatorProjectMembersEditController
$request = $this->getRequest(); $request = $this->getRequest();
$viewer = $request->getUser(); $viewer = $request->getUser();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$project,
PhabricatorPolicyCapability::CAN_EDIT);
$list = id(new PHUIObjectItemListView()) $list = id(new PHUIObjectItemListView())
->setNoDataString(pht('This project does not have any members.')); ->setNoDataString(pht('This project does not have any members.'))
->setStackable(true);
foreach ($handles as $handle) { foreach ($handles as $handle) {
$remove_uri = $this->getApplicationURI( $remove_uri = $this->getApplicationURI(
@ -131,16 +143,22 @@ final class PhabricatorProjectMembersEditController
->setHref($handle->getURI()) ->setHref($handle->getURI())
->setImageURI($handle->getImageURI()); ->setImageURI($handle->getImageURI());
$item->addAction( if ($can_edit) {
id(new PHUIListItemView()) $item->addAction(
->setIcon('fa-times') id(new PHUIListItemView())
->setName(pht('Remove')) ->setIcon('fa-times')
->setHref($remove_uri) ->setName(pht('Remove'))
->setWorkflow(true)); ->setHref($remove_uri)
->setWorkflow(true));
}
$list->addItem($item); $list->addItem($item);
} }
return $list; $box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Members'))
->appendChild($list);
return $box;
} }
} }

View file

@ -3,22 +3,11 @@
final class PhabricatorProjectProfileController final class PhabricatorProjectProfileController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id;
private $slug;
public function shouldAllowPublic() { public function shouldAllowPublic() {
return true; return true;
} }
public function willProcessRequest(array $data) { public function handleRequest(AphrontRequest $request) {
// via /project/view/$id/
$this->id = idx($data, 'id');
// via /tag/$slug/
$this->slug = idx($data, 'slug');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser(); $user = $request->getUser();
$query = id(new PhabricatorProjectQuery()) $query = id(new PhabricatorProjectQuery())
@ -27,55 +16,43 @@ final class PhabricatorProjectProfileController
->needWatchers(true) ->needWatchers(true)
->needImages(true) ->needImages(true)
->needSlugs(true); ->needSlugs(true);
if ($this->slug) { $id = $request->getURIData('id');
$query->withSlugs(array($this->slug)); $slug = $request->getURIData('slug');
if ($slug) {
$query->withSlugs(array($slug));
} else { } else {
$query->withIDs(array($this->id)); $query->withIDs(array($id));
} }
$project = $query->executeOne(); $project = $query->executeOne();
if (!$project) { if (!$project) {
return new Aphront404Response(); return new Aphront404Response();
} }
if ($this->slug && $this->slug != $project->getPrimarySlug()) { if ($slug && $slug != $project->getPrimarySlug()) {
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI('/tag/'.$project->getPrimarySlug().'/'); ->setURI('/tag/'.$project->getPrimarySlug().'/');
} }
$picture = $project->getProfileImageURI(); $picture = $project->getProfileImageURI();
require_celerity_resource('phabricator-profile-css'); require_celerity_resource('phabricator-profile-css');
$tasks = $this->renderTasksPage($project); $tasks = $this->renderTasksPage($project);
$content = phutil_tag_div('phabricator-project-layout', $tasks);
$query = new PhabricatorFeedQuery(); $phid = $project->getPHID();
$query->setFilterPHIDs( $create_uri = '/maniphest/task/create/?projects='.$phid;
array( $icon_new = id(new PHUIIconView())
$project->getPHID(), ->setIconFont('fa-plus');
)); $button_add = id(new PHUIButtonView())
$query->setLimit(50); ->setTag('a')
$query->setViewer($this->getRequest()->getUser()); ->setText(pht('New Task'))
$stories = $query->execute(); ->setHref($create_uri)
$feed = $this->renderStories($stories); ->setIcon($icon_new);
$content = phutil_tag_div(
'phabricator-project-layout',
array($tasks, $feed));
$id = $project->getID();
$icon = id(new PHUIIconView())
->setIconFont('fa-columns');
$board_btn = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Workboard'))
->setHref($this->getApplicationURI("board/{$id}/"))
->setIcon($icon);
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader($project->getName()) ->setHeader($project->getName())
->setUser($user) ->setUser($user)
->setPolicyObject($project) ->setPolicyObject($project)
->setImage($picture) ->setImage($picture)
->addActionLink($board_btn); ->addActionLink($button_add);
if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) { if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) {
$header->setStatus('fa-check', 'bluegrey', pht('Active')); $header->setStatus('fa-check', 'bluegrey', pht('Active'));
@ -86,57 +63,28 @@ final class PhabricatorProjectProfileController
$actions = $this->buildActionListView($project); $actions = $this->buildActionListView($project);
$properties = $this->buildPropertyListView($project, $actions); $properties = $this->buildPropertyListView($project, $actions);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb($project->getName());
$object_box = id(new PHUIObjectBoxView()) $object_box = id(new PHUIObjectBoxView())
->setHeader($header) ->setHeader($header)
->addPropertyList($properties); ->addPropertyList($properties);
$nav = $this->buildIconNavView($project);
$nav->selectFilter("profile/{$id}/");
$nav->appendChild($object_box);
$nav->appendChild($content);
return $this->buildApplicationPage( return $this->buildApplicationPage(
array( array(
$crumbs, $nav,
$object_box,
$content,
), ),
array( array(
'title' => $project->getName(), 'title' => $project->getName(),
)); ));
} }
private function renderFeedPage(PhabricatorProject $project) {
$query = new PhabricatorFeedQuery();
$query->setFilterPHIDs(array($project->getPHID()));
$query->setViewer($this->getRequest()->getUser());
$query->setLimit(100);
$stories = $query->execute();
if (!$stories) {
return pht('There are no stories about this project.');
}
return $this->renderStories($stories);
}
private function renderStories(array $stories) {
assert_instances_of($stories, 'PhabricatorFeedStory');
$builder = new PhabricatorFeedBuilder($stories);
$builder->setUser($this->getRequest()->getUser());
$builder->setShowHovercards(true);
$view = $builder->buildView();
return phutil_tag_div(
'profile-feed',
$view->render());
}
private function renderTasksPage(PhabricatorProject $project) { private function renderTasksPage(PhabricatorProject $project) {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
$limit = 10; $limit = 50;
$query = id(new ManiphestTaskQuery()) $query = id(new ManiphestTaskQuery())
->setViewer($user) ->setViewer($user)
@ -168,24 +116,15 @@ final class PhabricatorProjectProfileController
'/maniphest/?statuses=%s&allProjects=%s#R', '/maniphest/?statuses=%s&allProjects=%s#R',
implode(',', ManiphestTaskStatus::getOpenStatusConstants()), implode(',', ManiphestTaskStatus::getOpenStatusConstants()),
$phid); $phid);
$create_uri = '/maniphest/task/create/?projects='.$phid;
$icon = id(new PHUIIconView()) $icon = id(new PHUIIconView())
->setIconFont('fa-list'); ->setIconFont('fa-search');
$button_view = id(new PHUIButtonView()) $button_view = id(new PHUIButtonView())
->setTag('a') ->setTag('a')
->setText(pht('View All')) ->setText(pht('View Query'))
->setHref($view_uri) ->setHref($view_uri)
->setIcon($icon); ->setIcon($icon);
$icon_new = id(new PHUIIconView())
->setIconFont('fa-plus');
$button_add = id(new PHUIButtonView())
->setTag('a')
->setText(pht('New Task'))
->setHref($create_uri)
->setIcon($icon_new);
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->addActionLink($button_add)
->addActionLink($button_view); ->addActionLink($button_view);
if ($count > $limit) { if ($count > $limit) {
@ -217,20 +156,6 @@ final class PhabricatorProjectProfileController
$project, $project,
PhabricatorPolicyCapability::CAN_EDIT); PhabricatorPolicyCapability::CAN_EDIT);
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Project'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("edit/{$id}/")));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Members'))
->setIcon('fa-users')
->setHref($this->getApplicationURI("members/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$action = null; $action = null;
if (!$project->isUserMember($viewer->getPHID())) { if (!$project->isUserMember($viewer->getPHID())) {
$can_join = PhabricatorPolicyFilter::hasCapability( $can_join = PhabricatorPolicyFilter::hasCapability(

View file

@ -42,7 +42,7 @@ final class PhabricatorProjectUpdateController
return new Aphront404Response(); return new Aphront404Response();
} }
$project_uri = '/project/view/'.$project->getID().'/'; $project_uri = $this->getApplicationURI('profile/'.$project->getID().'/');
if ($process_action) { if ($process_action) {

View file

@ -0,0 +1,56 @@
<?php
final class PhabricatorProjectViewController
extends PhabricatorProjectController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$request = $this->getRequest();
$user = $request->getUser();
$query = id(new PhabricatorProjectQuery())
->setViewer($user)
->needMembers(true)
->needWatchers(true)
->needImages(true)
->needSlugs(true);
$id = $request->getURIData('id');
$slug = $request->getURIData('slug');
if ($slug) {
$query->withSlugs(array($slug));
} else {
$query->withIDs(array($id));
}
$project = $query->executeOne();
if (!$project) {
return new Aphront404Response();
}
$columns = id(new PhabricatorProjectColumnQuery())
->setViewer($user)
->withProjectPHIDs(array($project->getPHID()))
->execute();
if ($columns) {
$controller = 'board';
} else {
$controller = 'profile';
}
switch ($controller) {
case 'board':
$controller_object = new PhabricatorProjectBoardViewController();
break;
case 'profile':
default:
$controller_object = new PhabricatorProjectProfileController();
break;
}
return $this->delegateToController($controller_object);
}
}

View file

@ -25,7 +25,7 @@ final class PhabricatorProjectWatchController
return new Aphront404Response(); return new Aphront404Response();
} }
$project_uri = '/project/view/'.$project->getID().'/'; $project_uri = $this->getApplicationURI('profile/'.$project->getID().'/');
// You must be a member of a project to // You must be a member of a project to
if (!$project->isUserMember($viewer->getPHID())) { if (!$project->isUserMember($viewer->getPHID())) {

View file

@ -219,8 +219,15 @@ final class PhabricatorProjectSearchEngine
foreach ($projects as $key => $project) { foreach ($projects as $key => $project) {
$id = $project->getID(); $id = $project->getID();
$profile_uri = $this->getApplicationURI("profile/{$id}/");
$workboards_uri = $this->getApplicationURI("board/{$id}/"); $workboards_uri = $this->getApplicationURI("board/{$id}/");
$members_uri = $this->getApplicationURI("members/{$id}/"); $members_uri = $this->getApplicationURI("members/{$id}/");
$profile_url = phutil_tag(
'a',
array(
'href' => $profile_uri,
),
pht('Profile'));
$workboards_url = phutil_tag( $workboards_url = phutil_tag(
'a', 'a',
array( array(
@ -252,6 +259,7 @@ final class PhabricatorProjectSearchEngine
->setHref($this->getApplicationURI("view/{$id}/")) ->setHref($this->getApplicationURI("view/{$id}/"))
->setImageURI($project->getProfileImageURI()) ->setImageURI($project->getProfileImageURI())
->addAttribute($tag_list) ->addAttribute($tag_list)
->addAttribute($profile_url)
->addAttribute($workboards_url) ->addAttribute($workboards_url)
->addAttribute($members_url); ->addAttribute($members_url);

View file

@ -27,6 +27,7 @@ final class AphrontSideNavFilterView extends AphrontView {
private $crumbs; private $crumbs;
private $classes = array(); private $classes = array();
private $menuID; private $menuID;
private $iconNav;
public function setMenuID($menu_id) { public function setMenuID($menu_id) {
$this->menuID = $menu_id; $this->menuID = $menu_id;
@ -61,6 +62,11 @@ final class AphrontSideNavFilterView extends AphrontView {
return $this->crumbs; return $this->crumbs;
} }
public function setIconNav($nav) {
$this->iconNav = $nav;
return $this;
}
public function setActive($active) { public function setActive($active) {
$this->active = $active; $this->active = $active;
return $this; return $this;
@ -94,6 +100,22 @@ final class AphrontSideNavFilterView extends AphrontView {
$key, $name, $uri, PHUIListItemView::TYPE_LINK); $key, $name, $uri, PHUIListItemView::TYPE_LINK);
} }
public function addIcon($key, $name, $icon, $image = null) {
$href = clone $this->baseURI;
$href->setPath(rtrim($href->getPath().$key, '/').'/');
$href = (string)$href;
$item = id(new PHUIListItemView())
->setKey($key)
->setRenderNameAsTooltip(true)
->setType(PHUIListItemView::TYPE_ICON_NAV)
->setIcon($icon)
->setHref($href)
->setName($name)
->setProfileImage($image);
return $this->addMenuItem($item);
}
public function addButton($key, $name, $uri = null) { public function addButton($key, $name, $uri = null) {
return $this->addThing( return $this->addThing(
$key, $name, $uri, PHUIListItemView::TYPE_BUTTON); $key, $name, $uri, PHUIListItemView::TYPE_BUTTON);
@ -109,6 +131,7 @@ final class AphrontSideNavFilterView extends AphrontView {
->setName($name) ->setName($name)
->setType($type); ->setType($type);
if (strlen($key)) { if (strlen($key)) {
$item->setKey($key); $item->setKey($key);
} }
@ -192,6 +215,9 @@ final class AphrontSideNavFilterView extends AphrontView {
$nav_classes = array(); $nav_classes = array();
$nav_classes[] = 'phabricator-nav'; $nav_classes[] = 'phabricator-nav';
if ($this->iconNav) {
$nav_classes[] = 'phabricator-icon-nav';
}
$nav_id = null; $nav_id = null;
$drag_id = null; $drag_id = null;

View file

@ -9,6 +9,7 @@ final class PHUIListItemView extends AphrontTagView {
const TYPE_CUSTOM = 'type-custom'; const TYPE_CUSTOM = 'type-custom';
const TYPE_DIVIDER = 'type-divider'; const TYPE_DIVIDER = 'type-divider';
const TYPE_ICON = 'type-icon'; const TYPE_ICON = 'type-icon';
const TYPE_ICON_NAV = 'type-icon-nav';
const STATUS_WARN = 'phui-list-item-warn'; const STATUS_WARN = 'phui-list-item-warn';
const STATUS_FAIL = 'phui-list-item-fail'; const STATUS_FAIL = 'phui-list-item-fail';
@ -26,6 +27,7 @@ final class PHUIListItemView extends AphrontTagView {
private $statusColor; private $statusColor;
private $order; private $order;
private $aural; private $aural;
private $profileImage;
public function setAural($aural) { public function setAural($aural) {
$this->aural = $aural; $this->aural = $aural;
@ -73,6 +75,11 @@ final class PHUIListItemView extends AphrontTagView {
return $this; return $this;
} }
public function setProfileImage($image) {
$this->profileImage = $image;
return $this;
}
public function getIcon() { public function getIcon() {
return $this->icon; return $this->icon;
} }
@ -170,9 +177,11 @@ final class PHUIListItemView extends AphrontTagView {
if ($this->name) { if ($this->name) {
if ($this->getRenderNameAsTooltip()) { if ($this->getRenderNameAsTooltip()) {
Javelin::initBehavior('phabricator-tooltips');
$sigil = 'has-tooltip'; $sigil = 'has-tooltip';
$meta = array( $meta = array(
'tip' => $this->name, 'tip' => $this->name,
'align' => 'E',
); );
} else { } else {
$external = null; $external = null;
@ -224,6 +233,12 @@ final class PHUIListItemView extends AphrontTagView {
->setIconFont($icon_name); ->setIconFont($icon_name);
} }
if ($this->profileImage) {
$icon = id(new PHUIIconView())
->setHeadSize(PHUIIconView::HEAD_SMALL)
->setImage($this->profileImage);
}
if ($this->appIcon) { if ($this->appIcon) {
$icon = id(new PHUIIconView()) $icon = id(new PHUIIconView())
->addClass('phui-list-item-icon') ->addClass('phui-list-item-icon')

View file

@ -159,25 +159,25 @@
display: block; display: block;
width: auto; width: auto;
} }
.device-desktop .aphront-multi-column-column-outer { .device-desktop .dashboard-view .aphront-multi-column-column-outer {
display: block; display: block;
border: none; border: none;
} }
.device-desktop .aphront-multi-column-column.mlr { .device-desktop .dashboard-view .aphront-multi-column-column.mlr {
margin: 0; margin: 0;
} }
.device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up .device-desktop .dashboard-view .aphront-multi-column-fluid
.aphront-multi-column-column-outer.half { .aphront-multi-column-2-up .aphront-multi-column-column-outer.half {
width: auto; width: auto;
margin: 0 0 16px; margin: 0 0 16px;
} }
.device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up .device-desktop .dashboard-view .aphront-multi-column-fluid
.aphront-multi-column-column-outer.thirds { .aphront-multi-column-2-up .aphront-multi-column-column-outer.thirds {
width: auto; width: auto;
margin: 0 0 16px; margin: 0 0 16px;
} }
.device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up .device-desktop .dashboard-view .aphront-multi-column-fluid
.aphront-multi-column-column-outer.third { .aphront-multi-column-2-up .aphront-multi-column-column-outer.third {
width: auto; width: auto;
margin: 0 0 16px; margin: 0 0 16px;
} }

View file

@ -51,3 +51,13 @@
.device-tablet .phabricator-project-layout .profile-feed { .device-tablet .phabricator-project-layout .profile-feed {
padding: 16px; padding: 16px;
} }
.phabricator-project-feed {
padding: 4px 0 12px 12px;
max-width: 640px;
}
.device-phone .phabricator-project-feed {
padding: 0 12px;
width: auto;
}

View file

@ -43,3 +43,44 @@
text-decoration: none; text-decoration: none;
background-color: {$hovergrey}; background-color: {$hovergrey};
} }
.device-desktop .phabricator-icon-nav .phabricator-nav-column-background,
.device-desktop .phabricator-icon-nav .phabricator-nav-local {
width: 40px;
}
.device-desktop .phabricator-icon-nav .phabricator-nav-content {
margin-left: 41px;
}
.phabricator-icon-nav .phabricator-side-menu .phui-list-item-href {
height: 40px;
width: 40px;
padding: 0;
}
.phabricator-icon-nav .phabricator-side-menu .phui-list-item-icon {
font-size: 20px;
width: 40px;
line-height: 40px;
text-align: center;
vertical-align: bottom;
}
.phabricator-icon-nav .phabricator-side-menu .phui-list-item-selected {
border: none;
}
.phabricator-icon-nav .phabricator-side-menu .phui-list-item-selected
.phui-icon-view {
color: {$sky};
}
.phabricator-icon-nav .phui-icon-view.phuihead-small {
height: 24px;
width: 24px;
border: 1px solid #fff;
background-size: 24px;
display: inline-block;
margin: 7px;
}

View file

@ -19,7 +19,7 @@
} }
.phui-object-box .phui-object-item-list-view.phui-object-list-flush { .phui-object-box .phui-object-item-list-view.phui-object-list-flush {
padding: 8px 12px 4px 12px; padding: 8px 8px 4px 8px;
background-color: #E5E8EE; background-color: #E5E8EE;
} }
@ -38,7 +38,7 @@
border-color: {$lightgreyborder}; border-color: {$lightgreyborder};
margin: 5px 0; margin: 5px 0;
overflow: hidden; overflow: hidden;
border-left-width: 6px; border-left-width: 4px;
background: #fff; background: #fff;
margin-bottom: 4px; margin-bottom: 4px;
} }

View file

@ -73,6 +73,15 @@
margin: 0 3px; margin: 0 3px;
} }
.device-desktop .project-board-wrapper .phui-workboard-view-shadow {
left: 53px;
}
.device-desktop .phui-workboard-view .aphront-multi-column-fixed
.aphront-multi-column-inner {
margin-left: 0;
}
.device-tablet .project-board-wrapper { .device-tablet .project-board-wrapper {
margin-left: 8px; margin-left: 8px;
margin-right: 8px; margin-right: 8px;