1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-21 04:50:55 +01:00

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
This commit is contained in:
epriestley 2016-01-19 17:02:29 -08:00
parent 6b1b21c999
commit 9f36594100
11 changed files with 234 additions and 153 deletions

View file

@ -2881,9 +2881,9 @@ phutil_register_library_map(array(
'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php', 'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php',
'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php', 'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php',
'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php',
'PhabricatorProjectFeedController' => 'applications/project/controller/PhabricatorProjectFeedController.php',
'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php', 'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php',
'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php', 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php',
'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php',
'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php', 'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.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',
@ -7283,9 +7283,9 @@ phutil_register_library_map(array(
'PhabricatorProjectEditController' => 'PhabricatorProjectController', 'PhabricatorProjectEditController' => 'PhabricatorProjectController',
'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine',
'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController',
'PhabricatorProjectFeedController' => 'PhabricatorProjectController',
'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine',
'PhabricatorProjectHeraldAction' => 'HeraldAction', 'PhabricatorProjectHeraldAction' => 'HeraldAction',
'PhabricatorProjectHistoryController' => 'PhabricatorProjectController',
'PhabricatorProjectIconSet' => 'PhabricatorIconSet', 'PhabricatorProjectIconSet' => 'PhabricatorIconSet',
'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectListView' => 'AphrontView', 'PhabricatorProjectListView' => 'AphrontView',

View file

@ -44,7 +44,7 @@ final class PhabricatorFileComposeController
)); ));
if ($project_phid) { if ($project_phid) {
$edit_uri = '/project/profile/'.$project->getID().'/'; $edit_uri = '/project/history/'.$project->getID().'/';
$xactions = array(); $xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction()) $xactions[] = id(new PhabricatorProjectTransaction())

View file

@ -55,8 +55,6 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
=> 'PhabricatorProjectMembersRemoveController', => 'PhabricatorProjectMembersRemoveController',
'profile/(?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*)/' 'view/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectViewController', => 'PhabricatorProjectViewController',
'picture/(?P<id>[1-9]\d*)/' 'picture/(?P<id>[1-9]\d*)/'

View file

@ -20,7 +20,7 @@ final class PhabricatorProjectArchiveController
return new Aphront404Response(); return new Aphront404Response();
} }
$edit_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); $edit_uri = $this->getApplicationURI('history/'.$project->getID().'/');
if ($request->isFormPost()) { if ($request->isFormPost()) {
if ($project->isArchived()) { if ($project->isArchived()) {

View file

@ -23,8 +23,8 @@ final class PhabricatorProjectEditPictureController
$this->setProject($project); $this->setProject($project);
$edit_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); $edit_uri = $this->getApplicationURI('history/'.$project->getID().'/');
$view_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); $view_uri = $this->getApplicationURI('history/'.$project->getID().'/');
$supported_formats = PhabricatorFile::getTransformableImageFormats(); $supported_formats = PhabricatorFile::getTransformableImageFormats();
$e_file = true; $e_file = true;

View file

@ -1,62 +0,0 @@
<?php
final class PhabricatorProjectFeedController
extends PhabricatorProjectController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->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());
}
}

View file

@ -0,0 +1,133 @@
<?php
final class PhabricatorProjectHistoryController
extends PhabricatorProjectController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$response = $this->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;
}
}

View file

@ -8,13 +8,12 @@ final class PhabricatorProjectProfileController
} }
public function handleRequest(AphrontRequest $request) { public function handleRequest(AphrontRequest $request) {
$viewer = $request->getUser();
$response = $this->loadProject(); $response = $this->loadProject();
if ($response) { if ($response) {
return $response; return $response;
} }
$viewer = $request->getUser();
$project = $this->getProject(); $project = $this->getProject();
$id = $project->getID(); $id = $project->getID();
$picture = $project->getProfileImageURI(); $picture = $project->getProfileImageURI();
@ -38,14 +37,46 @@ final class PhabricatorProjectProfileController
->setHeader($header) ->setHeader($header)
->addPropertyList($properties); ->addPropertyList($properties);
$timeline = $this->buildTransactionTimeline( $member_list = id(new PhabricatorProjectMemberListView())
$project, ->setUser($viewer)
new PhabricatorProjectTransactionQuery()); ->setProject($project)
$timeline->setShouldTerminate(true); ->setLimit(5)
->setUserPHIDs($project->getMemberPHIDs());
$watcher_list = id(new PhabricatorProjectWatcherListView())
->setUser($viewer)
->setProject($project)
->setLimit(5)
->setUserPHIDs($project->getWatcherPHIDs());
$nav = $this->getProfileMenu(); $nav = $this->getProfileMenu();
$nav->selectFilter(PhabricatorProject::PANEL_PROFILE); $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(); $crumbs = $this->buildApplicationCrumbs();
return $this->newPage() return $this->newPage()
@ -53,8 +84,11 @@ final class PhabricatorProjectProfileController
->setCrumbs($crumbs) ->setCrumbs($crumbs)
->setTitle($project->getName()) ->setTitle($project->getName())
->setPageObjectPHIDs(array($project->getPHID())) ->setPageObjectPHIDs(array($project->getPHID()))
->appendChild($object_box) ->appendChild(
->appendChild($timeline); array(
$object_box,
$columns,
));
} }
private function buildActionListView(PhabricatorProject $project) { private function buildActionListView(PhabricatorProject $project) {
@ -67,44 +101,11 @@ final class PhabricatorProjectProfileController
->setUser($viewer) ->setUser($viewer)
->setObject($project); ->setObject($project);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$project,
PhabricatorPolicyCapability::CAN_EDIT);
$view->addAction( $view->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setName(pht('Edit Details')) ->setName(pht('Edit Project'))
->setIcon('fa-pencil') ->setIcon('fa-pencil')
->setHref($this->getApplicationURI("edit/{$id}/")) ->setHref($this->getApplicationURI("history/{$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; return $view;
} }
@ -120,33 +121,6 @@ final class PhabricatorProjectProfileController
->setObject($project) ->setObject($project)
->setActionList($actions); ->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( $view->addProperty(
pht('Looks Like'), pht('Looks Like'),
$viewer->renderHandle($project->getPHID())->setAsTag(true)); $viewer->renderHandle($project->getPHID())->setAsTag(true));
@ -159,5 +133,15 @@ final class PhabricatorProjectProfileController
return $view; 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());
}
} }

View file

@ -78,7 +78,12 @@ final class PhabricatorProjectEditEngine
} }
protected function getObjectViewURI($object) { 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) { protected function getObjectCreateCancelURI($object) {

View file

@ -32,15 +32,6 @@ final class PhabricatorProjectProfilePanelEngine
->setPanelProperty('name', pht('Open Tasks')) ->setPanelProperty('name', pht('Open Tasks'))
->setPanelProperty('uri', $uri); ->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() $panels[] = $this->newPanel()
->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS)
->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY);

View file

@ -4,6 +4,7 @@ abstract class PhabricatorProjectUserListView extends AphrontView {
private $project; private $project;
private $userPHIDs; private $userPHIDs;
private $limit;
public function setProject(PhabricatorProject $project) { public function setProject(PhabricatorProject $project) {
$this->project = $project; $this->project = $project;
@ -23,6 +24,15 @@ abstract class PhabricatorProjectUserListView extends AphrontView {
return $this->userPHIDs; 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 canEditList();
abstract protected function getNoDataString(); abstract protected function getNoDataString();
abstract protected function getRemoveURI($phid); abstract protected function getRemoveURI($phid);
@ -39,7 +49,14 @@ abstract class PhabricatorProjectUserListView extends AphrontView {
$list = id(new PHUIObjectItemListView()) $list = id(new PHUIObjectItemListView())
->setNoDataString($no_data); ->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); $handles = $viewer->loadHandles($user_phids);
// Always put the viewer first if they are on the list. // 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())) + array_select_keys($user_phids, array($viewer->getPHID())) +
$user_phids; $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]; $handle = $handles[$user_phid];
$item = id(new PHUIObjectItemView()) $item = id(new PHUIObjectItemView())
@ -70,8 +93,17 @@ abstract class PhabricatorProjectUserListView extends AphrontView {
$list->addItem($item); $list->addItem($item);
} }
if ($user_phids) {
$header = pht(
'%s (%s)',
$this->getHeaderText(),
phutil_count($user_phids));
} else {
$header = $this->getHeaderText();
}
return id(new PHUIObjectBoxView()) return id(new PHUIObjectBoxView())
->setHeaderText($this->getHeaderText()) ->setHeaderText($header)
->setObjectList($list); ->setObjectList($list);
} }