From 9f36594100af7f708a33596a5b3c8b8aab4d6573 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 19 Jan 2016 17:02:29 -0800 Subject: [PATCH] Put feed on project home, move history to a separate page Summary: Ref T10054. This shuffles some stuff around to move us closer to mocks in M1450 in terms of what information is on which pages. Home now has feed, members, watchers, link to "edit project / project edit history". History now has edit history, edit details, edit picture, archive/unarchive. Test Plan: New home page: {F1064889} New edit/history page: {F1064890} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15060 --- src/__phutil_library_map__.php | 4 +- .../PhabricatorFileComposeController.php | 2 +- .../PhabricatorProjectApplication.php | 2 - .../PhabricatorProjectArchiveController.php | 2 +- ...habricatorProjectEditPictureController.php | 4 +- .../PhabricatorProjectFeedController.php | 62 -------- .../PhabricatorProjectHistoryController.php | 133 ++++++++++++++++++ .../PhabricatorProjectProfileController.php | 124 +++++++--------- .../engine/PhabricatorProjectEditEngine.php | 7 +- .../PhabricatorProjectProfilePanelEngine.php | 9 -- .../view/PhabricatorProjectUserListView.php | 38 ++++- 11 files changed, 234 insertions(+), 153 deletions(-) delete mode 100644 src/applications/project/controller/PhabricatorProjectFeedController.php create mode 100644 src/applications/project/controller/PhabricatorProjectHistoryController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a7e6796ef2..a204da62da 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2881,9 +2881,9 @@ phutil_register_library_map(array( 'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php', 'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', - 'PhabricatorProjectFeedController' => 'applications/project/controller/PhabricatorProjectFeedController.php', 'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php', 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php', + 'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php', 'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php', 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', @@ -7283,9 +7283,9 @@ phutil_register_library_map(array( 'PhabricatorProjectEditController' => 'PhabricatorProjectController', 'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', - 'PhabricatorProjectFeedController' => 'PhabricatorProjectController', 'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorProjectHeraldAction' => 'HeraldAction', + 'PhabricatorProjectHistoryController' => 'PhabricatorProjectController', 'PhabricatorProjectIconSet' => 'PhabricatorIconSet', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListView' => 'AphrontView', diff --git a/src/applications/files/controller/PhabricatorFileComposeController.php b/src/applications/files/controller/PhabricatorFileComposeController.php index 17e605f3a9..404cf44aca 100644 --- a/src/applications/files/controller/PhabricatorFileComposeController.php +++ b/src/applications/files/controller/PhabricatorFileComposeController.php @@ -44,7 +44,7 @@ final class PhabricatorFileComposeController )); if ($project_phid) { - $edit_uri = '/project/profile/'.$project->getID().'/'; + $edit_uri = '/project/history/'.$project->getID().'/'; $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction()) diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index d2990f527a..e1b484ffe2 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -55,8 +55,6 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { => 'PhabricatorProjectMembersRemoveController', 'profile/(?P[1-9]\d*)/' => 'PhabricatorProjectProfileController', - 'feed/(?P[1-9]\d*)/' - => 'PhabricatorProjectFeedController', 'view/(?P[1-9]\d*)/' => 'PhabricatorProjectViewController', 'picture/(?P[1-9]\d*)/' diff --git a/src/applications/project/controller/PhabricatorProjectArchiveController.php b/src/applications/project/controller/PhabricatorProjectArchiveController.php index d6470ca1eb..505af27ef1 100644 --- a/src/applications/project/controller/PhabricatorProjectArchiveController.php +++ b/src/applications/project/controller/PhabricatorProjectArchiveController.php @@ -20,7 +20,7 @@ final class PhabricatorProjectArchiveController return new Aphront404Response(); } - $edit_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); + $edit_uri = $this->getApplicationURI('history/'.$project->getID().'/'); if ($request->isFormPost()) { if ($project->isArchived()) { diff --git a/src/applications/project/controller/PhabricatorProjectEditPictureController.php b/src/applications/project/controller/PhabricatorProjectEditPictureController.php index 41ccb94eb3..b0c013dadc 100644 --- a/src/applications/project/controller/PhabricatorProjectEditPictureController.php +++ b/src/applications/project/controller/PhabricatorProjectEditPictureController.php @@ -23,8 +23,8 @@ final class PhabricatorProjectEditPictureController $this->setProject($project); - $edit_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); - $view_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); + $edit_uri = $this->getApplicationURI('history/'.$project->getID().'/'); + $view_uri = $this->getApplicationURI('history/'.$project->getID().'/'); $supported_formats = PhabricatorFile::getTransformableImageFormats(); $e_file = true; diff --git a/src/applications/project/controller/PhabricatorProjectFeedController.php b/src/applications/project/controller/PhabricatorProjectFeedController.php deleted file mode 100644 index a108384088..0000000000 --- a/src/applications/project/controller/PhabricatorProjectFeedController.php +++ /dev/null @@ -1,62 +0,0 @@ -getUser(); - - $response = $this->loadProject(); - if ($response) { - return $response; - } - - $project = $this->getProject(); - $id = $project->getID(); - - $stories = id(new PhabricatorFeedQuery()) - ->setViewer($viewer) - ->setFilterPHIDs( - array( - $project->getPHID(), - )) - ->setLimit(50) - ->execute(); - - $feed = $this->renderStories($stories); - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Project Activity')) - ->appendChild($feed); - - $nav = $this->getProfileMenu(); - $nav->selectFilter('feed'); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Feed')); - - return $this->newPage() - ->setNavigation($nav) - ->setCrumbs($crumbs) - ->setTitle(array($project->getName(), pht('Feed'))) - ->appendChild($box); - } - - 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()); - } - -} diff --git a/src/applications/project/controller/PhabricatorProjectHistoryController.php b/src/applications/project/controller/PhabricatorProjectHistoryController.php new file mode 100644 index 0000000000..aa58e081f4 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectHistoryController.php @@ -0,0 +1,133 @@ +loadProject(); + if ($response) { + return $response; + } + + $viewer = $request->getUser(); + $project = $this->getProject(); + $id = $project->getID(); + $picture = $project->getProfileImageURI(); + + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Project History')) + ->setUser($viewer) + ->setPolicyObject($project) + ->setImage($picture); + + if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) { + $header->setStatus('fa-check', 'bluegrey', pht('Active')); + } else { + $header->setStatus('fa-ban', 'red', pht('Archived')); + } + + $actions = $this->buildActionListView($project); + $properties = $this->buildPropertyListView($project, $actions); + + $object_box = id(new PHUIObjectBoxView()) + ->setHeader($header) + ->addPropertyList($properties); + + $timeline = $this->buildTransactionTimeline( + $project, + new PhabricatorProjectTransactionQuery()); + $timeline->setShouldTerminate(true); + + $nav = $this->getProfileMenu(); + $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('History')); + + return $this->newPage() + ->setNavigation($nav) + ->setCrumbs($crumbs) + ->setTitle($project->getName()) + ->appendChild( + array( + $object_box, + $timeline, + )); + } + + private function buildActionListView(PhabricatorProject $project) { + $request = $this->getRequest(); + $viewer = $request->getUser(); + + $id = $project->getID(); + + $view = id(new PhabricatorActionListView()) + ->setUser($viewer); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $project, + PhabricatorPolicyCapability::CAN_EDIT); + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Back to Profile')) + ->setIcon('fa-chevron-left') + ->setHref($project->getURI())); + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Details')) + ->setIcon('fa-pencil') + ->setHref($this->getApplicationURI("edit/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Picture')) + ->setIcon('fa-picture-o') + ->setHref($this->getApplicationURI("picture/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + if ($project->isArchived()) { + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Activate Project')) + ->setIcon('fa-check') + ->setHref($this->getApplicationURI("archive/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } else { + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Archive Project')) + ->setIcon('fa-ban') + ->setHref($this->getApplicationURI("archive/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } + + return $view; + } + + private function buildPropertyListView( + PhabricatorProject $project, + PhabricatorActionListView $actions) { + $request = $this->getRequest(); + $viewer = $request->getUser(); + + $view = id(new PHUIPropertyListView()) + ->setUser($viewer) + ->setActionList($actions); + + return $view; + } + + +} diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index 89600e97d7..9bb694d9ba 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -8,13 +8,12 @@ final class PhabricatorProjectProfileController } public function handleRequest(AphrontRequest $request) { - $viewer = $request->getUser(); - $response = $this->loadProject(); if ($response) { return $response; } + $viewer = $request->getUser(); $project = $this->getProject(); $id = $project->getID(); $picture = $project->getProfileImageURI(); @@ -38,14 +37,46 @@ final class PhabricatorProjectProfileController ->setHeader($header) ->addPropertyList($properties); - $timeline = $this->buildTransactionTimeline( - $project, - new PhabricatorProjectTransactionQuery()); - $timeline->setShouldTerminate(true); + $member_list = id(new PhabricatorProjectMemberListView()) + ->setUser($viewer) + ->setProject($project) + ->setLimit(5) + ->setUserPHIDs($project->getMemberPHIDs()); + + $watcher_list = id(new PhabricatorProjectWatcherListView()) + ->setUser($viewer) + ->setProject($project) + ->setLimit(5) + ->setUserPHIDs($project->getWatcherPHIDs()); $nav = $this->getProfileMenu(); $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + + $stories = id(new PhabricatorFeedQuery()) + ->setViewer($viewer) + ->setFilterPHIDs( + array( + $project->getPHID(), + )) + ->setLimit(50) + ->execute(); + + $feed = $this->renderStories($stories); + + $feed = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Recent Activity')) + ->appendChild($feed); + + $columns = id(new AphrontMultiColumnView()) + ->setFluidLayout(true) + ->addColumn($feed) + ->addColumn( + array( + $member_list, + $watcher_list, + )); + $crumbs = $this->buildApplicationCrumbs(); return $this->newPage() @@ -53,8 +84,11 @@ final class PhabricatorProjectProfileController ->setCrumbs($crumbs) ->setTitle($project->getName()) ->setPageObjectPHIDs(array($project->getPHID())) - ->appendChild($object_box) - ->appendChild($timeline); + ->appendChild( + array( + $object_box, + $columns, + )); } private function buildActionListView(PhabricatorProject $project) { @@ -67,44 +101,11 @@ final class PhabricatorProjectProfileController ->setUser($viewer) ->setObject($project); - $can_edit = PhabricatorPolicyFilter::hasCapability( - $viewer, - $project, - PhabricatorPolicyCapability::CAN_EDIT); - $view->addAction( id(new PhabricatorActionView()) - ->setName(pht('Edit Details')) + ->setName(pht('Edit Project')) ->setIcon('fa-pencil') - ->setHref($this->getApplicationURI("edit/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Edit Picture')) - ->setIcon('fa-picture-o') - ->setHref($this->getApplicationURI("picture/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); - - if ($project->isArchived()) { - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Activate Project')) - ->setIcon('fa-check') - ->setHref($this->getApplicationURI("archive/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - } else { - $view->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Archive Project')) - ->setIcon('fa-ban') - ->setHref($this->getApplicationURI("archive/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - } + ->setHref($this->getApplicationURI("history/{$id}/"))); return $view; } @@ -120,33 +121,6 @@ final class PhabricatorProjectProfileController ->setObject($project) ->setActionList($actions); - $hashtags = array(); - foreach ($project->getSlugs() as $slug) { - $hashtags[] = id(new PHUITagView()) - ->setType(PHUITagView::TYPE_OBJECT) - ->setName('#'.$slug->getSlug()); - } - - if ($hashtags) { - $view->addProperty(pht('Hashtags'), phutil_implode_html(' ', $hashtags)); - } - - $view->addProperty( - pht('Members'), - $project->getMemberPHIDs() - ? $viewer - ->renderHandleList($project->getMemberPHIDs()) - ->setAsInline(true) - : phutil_tag('em', array(), pht('None'))); - - $view->addProperty( - pht('Watchers'), - $project->getWatcherPHIDs() - ? $viewer - ->renderHandleList($project->getWatcherPHIDs()) - ->setAsInline(true) - : phutil_tag('em', array(), pht('None'))); - $view->addProperty( pht('Looks Like'), $viewer->renderHandle($project->getPHID())->setAsTag(true)); @@ -159,5 +133,15 @@ final class PhabricatorProjectProfileController return $view; } + 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()); + } } diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php index 389c585fce..42a2000c86 100644 --- a/src/applications/project/engine/PhabricatorProjectEditEngine.php +++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php @@ -78,7 +78,12 @@ final class PhabricatorProjectEditEngine } protected function getObjectViewURI($object) { - return $object->getURI(); + if ($this->getIsCreate()) { + return $object->getURI(); + } else { + $id = $object->getID(); + return "/project/history/{$id}/"; + } } protected function getObjectCreateCancelURI($object) { diff --git a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php index d37caeecf8..f88faa15c4 100644 --- a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php +++ b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php @@ -32,15 +32,6 @@ final class PhabricatorProjectProfilePanelEngine ->setPanelProperty('name', pht('Open Tasks')) ->setPanelProperty('uri', $uri); - // TODO: This is temporary. - $id = $object->getID(); - $panels[] = $this->newPanel() - ->setBuiltinKey('feed') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'feed') - ->setPanelProperty('name', pht('Feed')) - ->setPanelProperty('uri', "/project/feed/{$id}/"); - $panels[] = $this->newPanel() ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); diff --git a/src/applications/project/view/PhabricatorProjectUserListView.php b/src/applications/project/view/PhabricatorProjectUserListView.php index e42b427ed3..f93b9da695 100644 --- a/src/applications/project/view/PhabricatorProjectUserListView.php +++ b/src/applications/project/view/PhabricatorProjectUserListView.php @@ -4,6 +4,7 @@ abstract class PhabricatorProjectUserListView extends AphrontView { private $project; private $userPHIDs; + private $limit; public function setProject(PhabricatorProject $project) { $this->project = $project; @@ -23,6 +24,15 @@ abstract class PhabricatorProjectUserListView extends AphrontView { return $this->userPHIDs; } + public function setLimit($limit) { + $this->limit = $limit; + return $this; + } + + public function getLimit() { + return $this->limit; + } + abstract protected function canEditList(); abstract protected function getNoDataString(); abstract protected function getRemoveURI($phid); @@ -39,7 +49,14 @@ abstract class PhabricatorProjectUserListView extends AphrontView { $list = id(new PHUIObjectItemListView()) ->setNoDataString($no_data); - $user_phids = array_reverse($user_phids); + $limit = $this->getLimit(); + + // If we're showing everything, show oldest to newest. If we're showing + // only a slice, show newest to oldest. + if (!$limit) { + $user_phids = array_reverse($user_phids); + } + $handles = $viewer->loadHandles($user_phids); // Always put the viewer first if they are on the list. @@ -48,7 +65,13 @@ abstract class PhabricatorProjectUserListView extends AphrontView { array_select_keys($user_phids, array($viewer->getPHID())) + $user_phids; - foreach ($user_phids as $user_phid) { + if ($limit) { + $render_phids = array_slice($user_phids, 0, $limit); + } else { + $render_phids = $user_phids; + } + + foreach ($render_phids as $user_phid) { $handle = $handles[$user_phid]; $item = id(new PHUIObjectItemView()) @@ -70,8 +93,17 @@ abstract class PhabricatorProjectUserListView extends AphrontView { $list->addItem($item); } + if ($user_phids) { + $header = pht( + '%s (%s)', + $this->getHeaderText(), + phutil_count($user_phids)); + } else { + $header = $this->getHeaderText(); + } + return id(new PHUIObjectBoxView()) - ->setHeaderText($this->getHeaderText()) + ->setHeaderText($header) ->setObjectList($list); }