mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 18:22:41 +01:00
Convert user profiles to Profile Panels
Summary: Ref T10054. Primary goal is to be able to remove IconNav from the codebase. I've made these non-editable so users can't customize them yet. We //might// want administrators to customize these globally instead? In any case, we avoid a bunch of product questions by just locking these down for now. Test Plan: {F1061348} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15020
This commit is contained in:
parent
2a6b2dbbfd
commit
da5d01e542
12 changed files with 535 additions and 352 deletions
|
@ -2723,6 +2723,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleCreateController' => 'applications/people/controller/PhabricatorPeopleCreateController.php',
|
||||
'PhabricatorPeopleDatasource' => 'applications/people/typeahead/PhabricatorPeopleDatasource.php',
|
||||
'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php',
|
||||
'PhabricatorPeopleDetailsProfilePanel' => 'applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php',
|
||||
'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php',
|
||||
'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php',
|
||||
'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php',
|
||||
|
@ -2741,7 +2742,9 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleOwnerDatasource.php',
|
||||
'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php',
|
||||
'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php',
|
||||
'PhabricatorPeopleProfilePanelEngine' => 'applications/people/engine/PhabricatorPeopleProfilePanelEngine.php',
|
||||
'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php',
|
||||
'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php',
|
||||
'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php',
|
||||
'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php',
|
||||
'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php',
|
||||
|
@ -7060,11 +7063,12 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleAnyOwnerDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorPeopleApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorPeopleApproveController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleCalendarController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleCalendarController' => 'PhabricatorPeopleProfileController',
|
||||
'PhabricatorPeopleController' => 'PhabricatorController',
|
||||
'PhabricatorPeopleCreateController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleDetailsProfilePanel' => 'PhabricatorProfilePanel',
|
||||
'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType',
|
||||
|
@ -7082,8 +7086,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorPeopleOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleProfileController',
|
||||
'PhabricatorPeopleProfilePanelEngine' => 'PhabricatorProfilePanelEngine',
|
||||
'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController',
|
||||
'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController',
|
||||
'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
|
|
|
@ -63,10 +63,12 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication {
|
|||
'picture/(?P<id>[1-9]\d*)/' =>
|
||||
'PhabricatorPeopleProfilePictureController',
|
||||
),
|
||||
'/p/(?P<username>[\w._-]+)/'
|
||||
=> 'PhabricatorPeopleProfileController',
|
||||
'/p/(?P<username>[\w._-]+)/calendar/'
|
||||
=> 'PhabricatorPeopleCalendarController',
|
||||
'/p/(?P<username>[\w._-]+)/' => array(
|
||||
'' => 'PhabricatorPeopleProfileViewController',
|
||||
'panel/'
|
||||
=> $this->getPanelRouting('PhabricatorPeopleProfilePanelController'),
|
||||
'calendar/' => 'PhabricatorPeopleCalendarController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +1,27 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleCalendarController
|
||||
extends PhabricatorPeopleController {
|
||||
|
||||
private $username;
|
||||
extends PhabricatorPeopleProfileController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$username = $request->getURIData('username');
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->username = idx($data, 'username');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
$user = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($viewer)
|
||||
->withUsernames(array($this->username))
|
||||
->withUsernames(array($username))
|
||||
->needProfileImage(true)
|
||||
->executeOne();
|
||||
|
||||
if (!$user) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
$picture = $user->getProfileImageURI();
|
||||
|
||||
$now = time();
|
||||
|
@ -89,16 +82,16 @@ final class PhabricatorPeopleCalendarController
|
|||
$month_view->addEvent($event);
|
||||
}
|
||||
|
||||
$name = $user->getUsername();
|
||||
$nav = $this->getProfileMenu();
|
||||
$nav->selectFilter('calendar');
|
||||
|
||||
$nav = $this->buildIconNavView($user);
|
||||
$nav->selectFilter("{$name}/calendar/");
|
||||
$nav->appendChild($month_view);
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Calendar'));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => pht('Calendar'),
|
||||
));
|
||||
return $this->newPage()
|
||||
->setTitle(pht('Calendar'))
|
||||
->setNavigation($nav)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($month_view);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,49 +44,4 @@ abstract class PhabricatorPeopleController extends PhabricatorController {
|
|||
return $this->buildSideNavView(true)->getMenu();
|
||||
}
|
||||
|
||||
public function buildIconNavView(PhabricatorUser $user) {
|
||||
$viewer = $this->getViewer();
|
||||
$picture = $user->getProfileImageURI();
|
||||
$name = $user->getUsername();
|
||||
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setIconNav(true);
|
||||
$nav->setBaseURI(new PhutilURI('/p/'));
|
||||
$nav->addIcon("{$name}/", $name, null, $picture);
|
||||
|
||||
$class = 'PhabricatorCalendarApplication';
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$nav->addIcon(
|
||||
"{$name}/calendar/", pht('Calendar'), 'fa-calendar');
|
||||
}
|
||||
|
||||
$class = 'PhabricatorManiphestApplication';
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$phid = $user->getPHID();
|
||||
$view_uri = sprintf(
|
||||
'/maniphest/?statuses=open()&assigned=%s#R',
|
||||
$phid);
|
||||
$nav->addIcon(
|
||||
'maniphest', pht('Open Tasks'), 'fa-anchor', null, $view_uri);
|
||||
}
|
||||
|
||||
$class = 'PhabricatorDifferentialApplication';
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$username = phutil_escape_uri($name);
|
||||
$view_uri = '/differential/?authors='.$username;
|
||||
$nav->addIcon(
|
||||
'differential', pht('Revisions'), 'fa-cog', null, $view_uri);
|
||||
}
|
||||
|
||||
$class = 'PhabricatorAuditApplication';
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$username = phutil_escape_uri($name);
|
||||
$view_uri = '/audit/?authors='.$username;
|
||||
$nav->addIcon(
|
||||
'audit', pht('Commits'), 'fa-code', null, $view_uri);
|
||||
}
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,257 +1,63 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleProfileController
|
||||
abstract class PhabricatorPeopleProfileController
|
||||
extends PhabricatorPeopleController {
|
||||
|
||||
private $username;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
private $user;
|
||||
private $profileMenu;
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->username = idx($data, 'username');
|
||||
public function setUser(PhabricatorUser $user) {
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
|
||||
$user = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($viewer)
|
||||
->withUsernames(array($this->username))
|
||||
->needBadges(true)
|
||||
->needProfileImage(true)
|
||||
->needAvailability(true)
|
||||
->executeOne();
|
||||
if (!$user) {
|
||||
return new Aphront404Response();
|
||||
public function getUser() {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
$profile = $user->loadUserProfile();
|
||||
$username = phutil_escape_uri($user->getUserName());
|
||||
public function buildApplicationMenu() {
|
||||
$menu = $this->newApplicationMenu();
|
||||
|
||||
$picture = $user->getProfileImageURI();
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($user->getFullName())
|
||||
->setSubheader($profile->getTitle())
|
||||
->setImage($picture);
|
||||
|
||||
$actions = id(new PhabricatorActionListView())
|
||||
->setObject($user)
|
||||
->setUser($viewer);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$user,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-pencil')
|
||||
->setName(pht('Edit Profile'))
|
||||
->setHref($this->getApplicationURI('editprofile/'.$user->getID().'/'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-picture-o')
|
||||
->setName(pht('Edit Profile Picture'))
|
||||
->setHref($this->getApplicationURI('picture/'.$user->getID().'/'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$class = 'PhabricatorConpherenceApplication';
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$href = id(new PhutilURI('/conpherence/new/'))
|
||||
->setQueryParam('participant', $user->getPHID());
|
||||
|
||||
$can_send = $viewer->isLoggedIn();
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-comments')
|
||||
->setName(pht('Send Message'))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_send)
|
||||
->setHref($href));
|
||||
$profile_menu = $this->getProfileMenu();
|
||||
if ($profile_menu) {
|
||||
$menu->setProfileMenu($profile_menu);
|
||||
}
|
||||
|
||||
if ($viewer->getIsAdmin()) {
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-wrench')
|
||||
->setName(pht('Edit Settings'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit)
|
||||
->setHref('/settings/'.$user->getID().'/'));
|
||||
|
||||
if ($user->getIsAdmin()) {
|
||||
$empower_icon = 'fa-arrow-circle-o-down';
|
||||
$empower_name = pht('Remove Administrator');
|
||||
} else {
|
||||
$empower_icon = 'fa-arrow-circle-o-up';
|
||||
$empower_name = pht('Make Administrator');
|
||||
return $menu;
|
||||
}
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon($empower_icon)
|
||||
->setName($empower_name)
|
||||
->setDisabled(($user->getPHID() == $viewer->getPHID()))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('empower/'.$user->getID().'/')));
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-tag')
|
||||
->setName(pht('Change Username'))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('rename/'.$user->getID().'/')));
|
||||
|
||||
if ($user->getIsDisabled()) {
|
||||
$disable_icon = 'fa-check-circle-o';
|
||||
$disable_name = pht('Enable User');
|
||||
} else {
|
||||
$disable_icon = 'fa-ban';
|
||||
$disable_name = pht('Disable User');
|
||||
}
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon($disable_icon)
|
||||
->setName($disable_name)
|
||||
->setDisabled(($user->getPHID() == $viewer->getPHID()))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('disable/'.$user->getID().'/')));
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-times')
|
||||
->setName(pht('Delete User'))
|
||||
->setDisabled(($user->getPHID() == $viewer->getPHID()))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('delete/'.$user->getID().'/')));
|
||||
|
||||
$can_welcome = $user->canEstablishWebSessions();
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-envelope')
|
||||
->setName(pht('Send Welcome Email'))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_welcome)
|
||||
->setHref($this->getApplicationURI('welcome/'.$user->getID().'/')));
|
||||
}
|
||||
|
||||
$properties = $this->buildPropertyView($user, $actions);
|
||||
$name = $user->getUsername();
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb($name);
|
||||
|
||||
$object_box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->addPropertyList($properties);
|
||||
|
||||
$feed = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Recent Activity'))
|
||||
->appendChild($this->buildPeopleFeed($user, $viewer));
|
||||
|
||||
$badges = $this->buildBadgesView($user);
|
||||
|
||||
$nav = $this->buildIconNavView($user);
|
||||
$nav->selectFilter("{$name}/");
|
||||
$nav->appendChild($object_box);
|
||||
$nav->appendChild($badges);
|
||||
$nav->appendChild($feed);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => $user->getUsername(),
|
||||
));
|
||||
}
|
||||
|
||||
private function buildPropertyView(
|
||||
PhabricatorUser $user,
|
||||
PhabricatorActionListView $actions) {
|
||||
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
$view = id(new PHUIPropertyListView())
|
||||
->setUser($viewer)
|
||||
->setObject($user)
|
||||
->setActionList($actions);
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$user,
|
||||
PhabricatorCustomField::ROLE_VIEW);
|
||||
$field_list->appendFieldsToPropertyList($user, $viewer, $view);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
private function buildBadgesView(
|
||||
PhabricatorUser $user) {
|
||||
|
||||
protected function getProfileMenu() {
|
||||
if (!$this->profileMenu) {
|
||||
$user = $this->getUser();
|
||||
if ($user) {
|
||||
$viewer = $this->getViewer();
|
||||
$class = 'PhabricatorBadgesApplication';
|
||||
$box = null;
|
||||
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$badge_phids = $user->getBadgePHIDs();
|
||||
if ($badge_phids) {
|
||||
$badges = id(new PhabricatorBadgesQuery())
|
||||
$engine = id(new PhabricatorPeopleProfilePanelEngine())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($badge_phids)
|
||||
->withStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE))
|
||||
->execute();
|
||||
->setProfileObject($user);
|
||||
|
||||
$flex = new PHUIBadgeBoxView();
|
||||
foreach ($badges as $badge) {
|
||||
$item = id(new PHUIBadgeView())
|
||||
->setIcon($badge->getIcon())
|
||||
->setHeader($badge->getName())
|
||||
->setSubhead($badge->getFlavor())
|
||||
->setQuality($badge->getQuality());
|
||||
$flex->addItem($item);
|
||||
}
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Badges'))
|
||||
->appendChild($flex);
|
||||
$this->profileMenu = $engine->buildNavigation();
|
||||
}
|
||||
}
|
||||
return $box;
|
||||
|
||||
return $this->profileMenu;
|
||||
}
|
||||
|
||||
private function buildPeopleFeed(
|
||||
PhabricatorUser $user,
|
||||
$viewer) {
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
$query = new PhabricatorFeedQuery();
|
||||
$query->setFilterPHIDs(
|
||||
array(
|
||||
$user->getPHID(),
|
||||
));
|
||||
$query->setLimit(100);
|
||||
$query->setViewer($viewer);
|
||||
$stories = $query->execute();
|
||||
|
||||
$builder = new PhabricatorFeedBuilder($stories);
|
||||
$builder->setUser($viewer);
|
||||
$builder->setShowHovercards(true);
|
||||
$builder->setNoDataString(pht('To begin on such a grand journey, '.
|
||||
'requires but just a single step.'));
|
||||
$view = $builder->buildView();
|
||||
|
||||
return phutil_tag_div('phabricator-project-feed', $view->render());
|
||||
$user = $this->getUser();
|
||||
if ($user) {
|
||||
$crumbs->addTextCrumb(
|
||||
$user->getUsername(),
|
||||
urisprintf('/p/%s/', $user->getUsername()));
|
||||
}
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +1,15 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleProfileEditController
|
||||
extends PhabricatorPeopleController {
|
||||
extends PhabricatorPeopleProfileController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
$user = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($this->id))
|
||||
->withIDs(array($id))
|
||||
->needProfileImage(true)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
|
@ -31,6 +21,8 @@ final class PhabricatorPeopleProfileEditController
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
$profile_uri = '/p/'.$user->getUsername().'/';
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
|
@ -91,14 +83,12 @@ final class PhabricatorPeopleProfileEditController
|
|||
$form_box->setInfoView($note);
|
||||
}
|
||||
|
||||
$nav = $this->buildIconNavView($user);
|
||||
$nav->selectFilter('/');
|
||||
$nav->appendChild($form_box);
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Edit Profile'));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
array(
|
||||
'title' => $title,
|
||||
));
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($form_box);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,15 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleProfilePictureController
|
||||
extends PhabricatorPeopleController {
|
||||
extends PhabricatorPeopleProfileController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
$user = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($this->id))
|
||||
->withIDs(array($id))
|
||||
->needProfileImage(true)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
|
@ -31,6 +21,8 @@ final class PhabricatorPeopleProfilePictureController
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
$profile_uri = '/p/'.$user->getUsername().'/';
|
||||
|
||||
$supported_formats = PhabricatorFile::getTransformableImageFormats();
|
||||
|
@ -256,15 +248,16 @@ final class PhabricatorPeopleProfilePictureController
|
|||
->setHeaderText(pht('Upload New Picture'))
|
||||
->setForm($upload_form);
|
||||
|
||||
$nav = $this->buildIconNavView($user);
|
||||
$nav->selectFilter('/');
|
||||
$nav->appendChild($form_box);
|
||||
$nav->appendChild($upload_box);
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Edit Profile Picture'));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$nav,
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild(
|
||||
array(
|
||||
'title' => $title,
|
||||
$form_box,
|
||||
$upload_box,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleProfileViewController
|
||||
extends PhabricatorPeopleProfileController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$username = $request->getURIData('username');
|
||||
|
||||
$user = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($viewer)
|
||||
->withUsernames(array($username))
|
||||
->needBadges(true)
|
||||
->needProfileImage(true)
|
||||
->needAvailability(true)
|
||||
->executeOne();
|
||||
if (!$user) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$this->setUser($user);
|
||||
|
||||
$profile = $user->loadUserProfile();
|
||||
$picture = $user->getProfileImageURI();
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($user->getFullName())
|
||||
->setSubheader($profile->getTitle())
|
||||
->setImage($picture);
|
||||
|
||||
$actions = id(new PhabricatorActionListView())
|
||||
->setObject($user)
|
||||
->setUser($viewer);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$user,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-pencil')
|
||||
->setName(pht('Edit Profile'))
|
||||
->setHref($this->getApplicationURI('editprofile/'.$user->getID().'/'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-picture-o')
|
||||
->setName(pht('Edit Profile Picture'))
|
||||
->setHref($this->getApplicationURI('picture/'.$user->getID().'/'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$class = 'PhabricatorConpherenceApplication';
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$href = id(new PhutilURI('/conpherence/new/'))
|
||||
->setQueryParam('participant', $user->getPHID());
|
||||
|
||||
$can_send = $viewer->isLoggedIn();
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-comments')
|
||||
->setName(pht('Send Message'))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_send)
|
||||
->setHref($href));
|
||||
}
|
||||
|
||||
if ($viewer->getIsAdmin()) {
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-wrench')
|
||||
->setName(pht('Edit Settings'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit)
|
||||
->setHref('/settings/'.$user->getID().'/'));
|
||||
|
||||
if ($user->getIsAdmin()) {
|
||||
$empower_icon = 'fa-arrow-circle-o-down';
|
||||
$empower_name = pht('Remove Administrator');
|
||||
} else {
|
||||
$empower_icon = 'fa-arrow-circle-o-up';
|
||||
$empower_name = pht('Make Administrator');
|
||||
}
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon($empower_icon)
|
||||
->setName($empower_name)
|
||||
->setDisabled(($user->getPHID() == $viewer->getPHID()))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('empower/'.$user->getID().'/')));
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-tag')
|
||||
->setName(pht('Change Username'))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('rename/'.$user->getID().'/')));
|
||||
|
||||
if ($user->getIsDisabled()) {
|
||||
$disable_icon = 'fa-check-circle-o';
|
||||
$disable_name = pht('Enable User');
|
||||
} else {
|
||||
$disable_icon = 'fa-ban';
|
||||
$disable_name = pht('Disable User');
|
||||
}
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon($disable_icon)
|
||||
->setName($disable_name)
|
||||
->setDisabled(($user->getPHID() == $viewer->getPHID()))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('disable/'.$user->getID().'/')));
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-times')
|
||||
->setName(pht('Delete User'))
|
||||
->setDisabled(($user->getPHID() == $viewer->getPHID()))
|
||||
->setWorkflow(true)
|
||||
->setHref($this->getApplicationURI('delete/'.$user->getID().'/')));
|
||||
|
||||
$can_welcome = $user->canEstablishWebSessions();
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-envelope')
|
||||
->setName(pht('Send Welcome Email'))
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_welcome)
|
||||
->setHref($this->getApplicationURI('welcome/'.$user->getID().'/')));
|
||||
}
|
||||
|
||||
$properties = $this->buildPropertyView($user, $actions);
|
||||
$name = $user->getUsername();
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb($name);
|
||||
|
||||
$object_box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->addPropertyList($properties);
|
||||
|
||||
$feed = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Recent Activity'))
|
||||
->appendChild($this->buildPeopleFeed($user, $viewer));
|
||||
|
||||
$badges = $this->buildBadgesView($user);
|
||||
|
||||
$nav = $this->getProfileMenu();
|
||||
$nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_PROFILE);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($user->getUsername())
|
||||
->setNavigation($nav)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild(
|
||||
array(
|
||||
$object_box,
|
||||
$badges,
|
||||
$feed,
|
||||
));
|
||||
}
|
||||
|
||||
private function buildPropertyView(
|
||||
PhabricatorUser $user,
|
||||
PhabricatorActionListView $actions) {
|
||||
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
$view = id(new PHUIPropertyListView())
|
||||
->setUser($viewer)
|
||||
->setObject($user)
|
||||
->setActionList($actions);
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$user,
|
||||
PhabricatorCustomField::ROLE_VIEW);
|
||||
$field_list->appendFieldsToPropertyList($user, $viewer, $view);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
private function buildBadgesView(
|
||||
PhabricatorUser $user) {
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
$class = 'PhabricatorBadgesApplication';
|
||||
$box = null;
|
||||
|
||||
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
$badge_phids = $user->getBadgePHIDs();
|
||||
if ($badge_phids) {
|
||||
$badges = id(new PhabricatorBadgesQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($badge_phids)
|
||||
->withStatuses(array(PhabricatorBadgesBadge::STATUS_ACTIVE))
|
||||
->execute();
|
||||
|
||||
$flex = new PHUIBadgeBoxView();
|
||||
foreach ($badges as $badge) {
|
||||
$item = id(new PHUIBadgeView())
|
||||
->setIcon($badge->getIcon())
|
||||
->setHeader($badge->getName())
|
||||
->setSubhead($badge->getFlavor())
|
||||
->setQuality($badge->getQuality());
|
||||
$flex->addItem($item);
|
||||
}
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Badges'))
|
||||
->appendChild($flex);
|
||||
}
|
||||
}
|
||||
return $box;
|
||||
}
|
||||
|
||||
private function buildPeopleFeed(
|
||||
PhabricatorUser $user,
|
||||
$viewer) {
|
||||
|
||||
$query = new PhabricatorFeedQuery();
|
||||
$query->setFilterPHIDs(
|
||||
array(
|
||||
$user->getPHID(),
|
||||
));
|
||||
$query->setLimit(100);
|
||||
$query->setViewer($viewer);
|
||||
$stories = $query->execute();
|
||||
|
||||
$builder = new PhabricatorFeedBuilder($stories);
|
||||
$builder->setUser($viewer);
|
||||
$builder->setShowHovercards(true);
|
||||
$builder->setNoDataString(pht('To begin on such a grand journey, '.
|
||||
'requires but just a single step.'));
|
||||
$view = $builder->buildView();
|
||||
|
||||
return phutil_tag_div('phabricator-project-feed', $view->render());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleProfilePanelEngine
|
||||
extends PhabricatorProfilePanelEngine {
|
||||
|
||||
const PANEL_PROFILE = 'people.profile';
|
||||
|
||||
protected function isPanelEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getPanelURI($path) {
|
||||
$user = $this->getProfileObject();
|
||||
$username = $user->getUsername();
|
||||
$username = phutil_escape_uri($username);
|
||||
return "/p/{$username}/panel/{$path}";
|
||||
}
|
||||
|
||||
protected function getBuiltinProfilePanels($object) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$panels = array();
|
||||
|
||||
$panels[] = $this->newPanel()
|
||||
->setBuiltinKey(self::PANEL_PROFILE)
|
||||
->setPanelKey(PhabricatorPeopleDetailsProfilePanel::PANELKEY);
|
||||
|
||||
// TODO: Convert this into a proper panel type.
|
||||
$have_calendar = PhabricatorApplication::isClassInstalledForViewer(
|
||||
'PhabricatorCalendarApplication',
|
||||
$viewer);
|
||||
if ($have_calendar) {
|
||||
$uri = urisprintf(
|
||||
'/p/%s/calendar/',
|
||||
$object->getUsername());
|
||||
|
||||
$panels[] = $this->newPanel()
|
||||
->setBuiltinKey('calendar')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'calendar')
|
||||
->setPanelProperty('name', pht('Calendar'))
|
||||
->setPanelProperty('uri', $uri);
|
||||
}
|
||||
|
||||
$have_maniphest = PhabricatorApplication::isClassInstalledForViewer(
|
||||
'PhabricatorManiphestApplication',
|
||||
$viewer);
|
||||
if ($have_maniphest) {
|
||||
$uri = urisprintf(
|
||||
'/maniphest/?statuses=open()&assigned=%s#R',
|
||||
$object->getPHID());
|
||||
|
||||
$panels[] = $this->newPanel()
|
||||
->setBuiltinKey('tasks')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'maniphest')
|
||||
->setPanelProperty('name', pht('Open Tasks'))
|
||||
->setPanelProperty('uri', $uri);
|
||||
}
|
||||
|
||||
$have_differential = PhabricatorApplication::isClassInstalledForViewer(
|
||||
'PhabricatorDifferentialApplication',
|
||||
$viewer);
|
||||
if ($have_differential) {
|
||||
$uri = urisprintf(
|
||||
'/differential/?authors=%s#R',
|
||||
$object->getPHID());
|
||||
|
||||
$panels[] = $this->newPanel()
|
||||
->setBuiltinKey('revisions')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'differential')
|
||||
->setPanelProperty('name', pht('Revisions'))
|
||||
->setPanelProperty('uri', $uri);
|
||||
}
|
||||
|
||||
$have_diffusion = PhabricatorApplication::isClassInstalledForViewer(
|
||||
'PhabricatorDiffusionApplication',
|
||||
$viewer);
|
||||
if ($have_diffusion) {
|
||||
$uri = urisprintf(
|
||||
'/audit/?authors=%s#R',
|
||||
$object->getPHID());
|
||||
|
||||
$panels[] = $this->newPanel()
|
||||
->setBuiltinKey('commits')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'diffusion')
|
||||
->setPanelProperty('name', pht('Commits'))
|
||||
->setPanelProperty('uri', $uri);
|
||||
}
|
||||
|
||||
return $panels;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleDetailsProfilePanel
|
||||
extends PhabricatorProfilePanel {
|
||||
|
||||
const PANELKEY = 'people.details';
|
||||
|
||||
public function getPanelTypeName() {
|
||||
return pht('User Details');
|
||||
}
|
||||
|
||||
private function getDefaultName() {
|
||||
return pht('User Details');
|
||||
}
|
||||
|
||||
public function getDisplayName(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
$name = $config->getPanelProperty('name');
|
||||
|
||||
if (strlen($name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return $this->getDefaultName();
|
||||
}
|
||||
|
||||
public function buildEditEngineFields(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setPlaceholder($this->getDefaultName())
|
||||
->setValue($config->getPanelProperty('name')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
|
||||
$user = $config->getProfileObject();
|
||||
|
||||
$picture = $user->getProfileImageURI();
|
||||
$name = $user->getUsername();
|
||||
$href = urisprintf(
|
||||
'/p/%s/',
|
||||
$user->getUsername());
|
||||
|
||||
$item = $this->newItem()
|
||||
->setHref($href)
|
||||
->setName($name)
|
||||
->setProfileImage($picture);
|
||||
|
||||
return array(
|
||||
$item,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,6 +36,10 @@ abstract class PhabricatorProfilePanelEngine extends Phobject {
|
|||
|
||||
abstract protected function getPanelURI($path);
|
||||
|
||||
protected function isPanelEngineConfigurable() {
|
||||
return PhabricatorEnv::getEnvConfig('phabricator.show-prototypes');
|
||||
}
|
||||
|
||||
public function buildResponse() {
|
||||
$controller = $this->getController();
|
||||
|
||||
|
@ -45,6 +49,18 @@ abstract class PhabricatorProfilePanelEngine extends Phobject {
|
|||
$request = $controller->getRequest();
|
||||
|
||||
$panel_action = $request->getURIData('panelAction');
|
||||
|
||||
// If the engine is not configurable, don't respond to any of the editing
|
||||
// or configuration routes.
|
||||
if (!$this->isPanelEngineConfigurable()) {
|
||||
switch ($panel_action) {
|
||||
case 'view':
|
||||
break;
|
||||
default:
|
||||
return new Aphront404Response();
|
||||
}
|
||||
}
|
||||
|
||||
$panel_id = $request->getURIData('panelID');
|
||||
|
||||
$panel_list = $this->loadPanels();
|
||||
|
@ -286,7 +302,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject {
|
|||
}
|
||||
|
||||
private function newConfigureMenuItem() {
|
||||
if (!PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
|
||||
if (!$this->isPanelEngineConfigurable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,21 @@ final class PhabricatorProfilePanelIconSet
|
|||
'icon' => 'fa-comments',
|
||||
'name' => pht('Conpherence'),
|
||||
),
|
||||
array(
|
||||
'key' => 'differential',
|
||||
'icon' => 'fa-cog',
|
||||
'name' => pht('Differential'),
|
||||
),
|
||||
array(
|
||||
'key' => 'diffusion',
|
||||
'icon' => 'fa-code',
|
||||
'name' => pht('Diffusion'),
|
||||
),
|
||||
array(
|
||||
'key' => 'calendar',
|
||||
'icon' => 'fa-calendar',
|
||||
'name' => pht('Calendar'),
|
||||
),
|
||||
array(
|
||||
'key' => 'create',
|
||||
'icon' => 'fa-plus',
|
||||
|
|
Loading…
Reference in a new issue