diff --git a/resources/sql/autopatches/20160124.people.1.icon.sql b/resources/sql/autopatches/20160124.people.1.icon.sql new file mode 100644 index 0000000000..7cd96658d9 --- /dev/null +++ b/resources/sql/autopatches/20160124.people.1.icon.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_user.user_profile + ADD icon VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20160124.people.2.icondefault.sql b/resources/sql/autopatches/20160124.people.2.icondefault.sql new file mode 100644 index 0000000000..bf7dd24886 --- /dev/null +++ b/resources/sql/autopatches/20160124.people.2.icondefault.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_user.user_profile + SET icon = 'person' WHERE icon = ''; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index f6a1c9b720..fc1b152965 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2737,6 +2737,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php', 'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php', 'PhabricatorPeopleHovercardEngineExtension' => 'applications/people/engineextension/PhabricatorPeopleHovercardEngineExtension.php', + 'PhabricatorPeopleIconSet' => 'applications/people/icon/PhabricatorPeopleIconSet.php', 'PhabricatorPeopleInviteController' => 'applications/people/controller/PhabricatorPeopleInviteController.php', 'PhabricatorPeopleInviteListController' => 'applications/people/controller/PhabricatorPeopleInviteListController.php', 'PhabricatorPeopleInviteSendController' => 'applications/people/controller/PhabricatorPeopleInviteSendController.php', @@ -3366,6 +3367,7 @@ phutil_register_library_map(array( 'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php', 'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php', 'PhabricatorUserFulltextEngine' => 'applications/people/search/PhabricatorUserFulltextEngine.php', + 'PhabricatorUserIconField' => 'applications/people/customfield/PhabricatorUserIconField.php', 'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php', 'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php', 'PhabricatorUserPHIDResolver' => 'applications/phid/resolver/PhabricatorUserPHIDResolver.php', @@ -7102,6 +7104,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController', 'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', + 'PhabricatorPeopleIconSet' => 'PhabricatorIconSet', 'PhabricatorPeopleInviteController' => 'PhabricatorPeopleController', 'PhabricatorPeopleInviteListController' => 'PhabricatorPeopleInviteController', 'PhabricatorPeopleInviteSendController' => 'PhabricatorPeopleInviteController', @@ -7853,6 +7856,7 @@ phutil_register_library_map(array( 'PhabricatorUserEmail' => 'PhabricatorUserDAO', 'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase', 'PhabricatorUserFulltextEngine' => 'PhabricatorFulltextEngine', + 'PhabricatorUserIconField' => 'PhabricatorUserCustomField', 'PhabricatorUserLog' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', diff --git a/src/applications/people/config/PhabricatorUserConfigOptions.php b/src/applications/people/config/PhabricatorUserConfigOptions.php index afd1d376a0..c5eefeaa9f 100644 --- a/src/applications/people/config/PhabricatorUserConfigOptions.php +++ b/src/applications/people/config/PhabricatorUserConfigOptions.php @@ -24,6 +24,7 @@ final class PhabricatorUserConfigOptions $default = array( id(new PhabricatorUserRealNameField())->getFieldKey() => true, id(new PhabricatorUserTitleField())->getFieldKey() => true, + id(new PhabricatorUserIconField())->getFieldKey() => true, id(new PhabricatorUserSinceField())->getFieldKey() => true, id(new PhabricatorUserRolesField())->getFieldKey() => true, id(new PhabricatorUserStatusField())->getFieldKey() => true, diff --git a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php index a515dda959..57d02b52b0 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php @@ -27,9 +27,14 @@ final class PhabricatorPeopleProfileViewController $profile = $user->loadUserProfile(); $picture = $user->getProfileImageURI(); + $profile_icon = PhabricatorPeopleIconSet::getIconIcon($profile->getIcon()); + $profile_icon = id(new PHUIIconView()) + ->setIconFont($profile_icon.' grey'); + $profile_title = $profile->getDisplayTitle(); + $header = id(new PHUIHeaderView()) ->setHeader($user->getFullName()) - ->setSubheader($profile->getTitle()) + ->setSubheader(array($profile_icon, $profile_title)) ->setImage($picture); $actions = id(new PhabricatorActionListView()) diff --git a/src/applications/people/customfield/PhabricatorUserIconField.php b/src/applications/people/customfield/PhabricatorUserIconField.php new file mode 100644 index 0000000000..a3f43cb7bf --- /dev/null +++ b/src/applications/people/customfield/PhabricatorUserIconField.php @@ -0,0 +1,61 @@ +value = $object->loadUserProfile()->getIcon(); + } + + public function getOldValueForApplicationTransactions() { + return $this->getObject()->loadUserProfile()->getIcon(); + } + + public function getNewValueForApplicationTransactions() { + return $this->value; + } + + public function applyApplicationTransactionInternalEffects( + PhabricatorApplicationTransaction $xaction) { + $this->getObject()->loadUserProfile()->setIcon($xaction->getNewValue()); + } + + public function readValueFromRequest(AphrontRequest $request) { + $this->value = $request->getStr($this->getFieldKey()); + } + + public function renderEditControl(array $handles) { + return id(new PHUIFormIconSetControl()) + ->setName($this->getFieldKey()) + ->setValue($this->value) + ->setLabel($this->getFieldName()) + ->setIconSet(new PhabricatorPeopleIconSet()); + } + +} diff --git a/src/applications/people/customfield/PhabricatorUserTitleField.php b/src/applications/people/customfield/PhabricatorUserTitleField.php index 6e13b93aa7..af6793e76e 100644 --- a/src/applications/people/customfield/PhabricatorUserTitleField.php +++ b/src/applications/people/customfield/PhabricatorUserTitleField.php @@ -54,8 +54,7 @@ final class PhabricatorUserTitleField return id(new AphrontFormTextControl()) ->setName($this->getFieldKey()) ->setValue($this->value) - ->setLabel($this->getFieldName()) - ->setCaption(pht('Serious business title.')); + ->setLabel($this->getFieldName()); } } diff --git a/src/applications/people/icon/PhabricatorPeopleIconSet.php b/src/applications/people/icon/PhabricatorPeopleIconSet.php new file mode 100644 index 0000000000..06b97829ed --- /dev/null +++ b/src/applications/people/icon/PhabricatorPeopleIconSet.php @@ -0,0 +1,120 @@ +setKey($spec['key']) + ->setIcon($spec['icon']) + ->setLabel($spec['name']); + } + + return $icons; + } + + public static function getDefaultIconKey() { + $specifications = self::getIconSpecifications(); + + foreach ($specifications as $spec) { + if (idx($spec, 'default')) { + return $spec['key']; + } + } + + return null; + } + + public static function getIconIcon($key) { + $specifications = self::getIconSpecifications(); + $map = ipull($specifications, 'icon', 'key'); + return idx($map, $key); + } + + public static function getIconName($key) { + $specifications = self::getIconSpecifications(); + $map = ipull($specifications, 'name', 'key'); + return idx($map, $key); + } + + private static function getIconSpecifications() { + return self::getDefaultSpecifications(); + } + + private static function getDefaultSpecifications() { + return array( + array( + 'key' => 'person', + 'icon' => 'fa-user', + 'name' => pht('User'), + 'default' => true, + ), + array( + 'key' => 'engineering', + 'icon' => 'fa-code', + 'name' => pht('Engineering'), + ), + array( + 'key' => 'operations', + 'icon' => 'fa-space-shuttle', + 'name' => pht('Operations'), + ), + array( + 'key' => 'resources', + 'icon' => 'fa-heart', + 'name' => pht('Resources'), + ), + array( + 'key' => 'relationships', + 'icon' => 'fa-glass', + 'name' => pht('Relationships'), + ), + array( + 'key' => 'administration', + 'icon' => 'fa-fax', + 'name' => pht('Administration'), + ), + array( + 'key' => 'security', + 'icon' => 'fa-shield', + 'name' => pht('Security'), + ), + array( + 'key' => 'logistics', + 'icon' => 'fa-truck', + 'name' => pht('Logistics'), + ), + array( + 'key' => 'research', + 'icon' => 'fa-flask', + 'name' => pht('Research'), + ), + array( + 'key' => 'analysis', + 'icon' => 'fa-bar-chart-o', + 'name' => pht('Analysis'), + ), + array( + 'key' => 'executive', + 'icon' => 'fa-angle-double-up', + 'name' => pht('Executive'), + ), + array( + 'key' => 'animal', + 'icon' => 'fa-paw', + 'name' => pht('Animal'), + ), + ); + } + +} diff --git a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php index 0304173f90..ad452d5f02 100644 --- a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php +++ b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php @@ -26,6 +26,7 @@ final class PhabricatorPeopleUserPHIDType extends PhabricatorPHIDType { return id(new PhabricatorPeopleQuery()) ->withPHIDs($phids) + ->needProfile(true) ->needProfileImage(true) ->needAvailability(true); } @@ -46,6 +47,15 @@ final class PhabricatorPeopleUserPHIDType extends PhabricatorPHIDType { if ($user->getIsMailingList()) { $handle->setIcon('fa-envelope-o'); + $handle->setSubtitle(pht('Mailing List')); + } else { + $profile = $user->getUserProfile(); + $icon_key = $profile->getIcon(); + $icon_icon = PhabricatorPeopleIconSet::getIconIcon($icon_key); + $subtitle = $profile->getDisplayTitle(); + + $handle->setIcon($icon_icon); + $handle->setSubtitle($subtitle); } $availability = null; diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php index f1286f0a5a..2932d8c853 100644 --- a/src/applications/people/query/PhabricatorPeopleQuery.php +++ b/src/applications/people/query/PhabricatorPeopleQuery.php @@ -138,15 +138,16 @@ final class PhabricatorPeopleQuery if ($this->needProfile) { $user_list = mpull($users, null, 'getPHID'); $profiles = new PhabricatorUserProfile(); - $profiles = $profiles->loadAllWhere('userPHID IN (%Ls)', + $profiles = $profiles->loadAllWhere( + 'userPHID IN (%Ls)', array_keys($user_list)); $profiles = mpull($profiles, null, 'getUserPHID'); foreach ($user_list as $user_phid => $user) { $profile = idx($profiles, $user_phid); + if (!$profile) { - $profile = new PhabricatorUserProfile(); - $profile->setUserPHID($user_phid); + $profile = PhabricatorUserProfile::initializeNewProfile($user); } $user->attachUserProfile($profile); diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php index 18526ac04f..07c5695945 100644 --- a/src/applications/people/storage/PhabricatorUser.php +++ b/src/applications/people/storage/PhabricatorUser.php @@ -451,8 +451,7 @@ final class PhabricatorUser $this->getPHID()); if (!$this->profile) { - $profile_dao->setUserPHID($this->getPHID()); - $this->profile = $profile_dao; + $this->profile = PhabricatorUserProfile::initializeNewProfile($this); } return $this->profile; diff --git a/src/applications/people/storage/PhabricatorUserProfile.php b/src/applications/people/storage/PhabricatorUserProfile.php index 8ebd4f2af3..edfa24d78e 100644 --- a/src/applications/people/storage/PhabricatorUserProfile.php +++ b/src/applications/people/storage/PhabricatorUserProfile.php @@ -6,6 +6,15 @@ final class PhabricatorUserProfile extends PhabricatorUserDAO { protected $title; protected $blurb; protected $profileImagePHID; + protected $icon; + + public static function initializeNewProfile(PhabricatorUser $user) { + $default_icon = PhabricatorPeopleIconSet::getDefaultIconKey(); + + return id(new self()) + ->setUserPHID($user->getPHID()) + ->setIcon($default_icon); + } protected function getConfiguration() { return array( @@ -13,6 +22,7 @@ final class PhabricatorUserProfile extends PhabricatorUserDAO { 'title' => 'text255', 'blurb' => 'text', 'profileImagePHID' => 'phid?', + 'icon' => 'text32', ), self::CONFIG_KEY_SCHEMA => array( 'userPHID' => array( @@ -23,4 +33,14 @@ final class PhabricatorUserProfile extends PhabricatorUserDAO { ) + parent::getConfiguration(); } + public function getDisplayTitle() { + $title = $this->getTitle(); + if (strlen($title)) { + return $title; + } + + $icon_key = $this->getIcon(); + return PhabricatorPeopleIconSet::getIconName($icon_key); + } + } diff --git a/src/applications/phid/PhabricatorObjectHandle.php b/src/applications/phid/PhabricatorObjectHandle.php index 4eb6178338..e7245e3d02 100644 --- a/src/applications/phid/PhabricatorObjectHandle.php +++ b/src/applications/phid/PhabricatorObjectHandle.php @@ -27,6 +27,7 @@ final class PhabricatorObjectHandle private $complete; private $objectName; private $policyFiltered; + private $subtitle; public function setIcon($icon) { $this->icon = $icon; @@ -44,6 +45,15 @@ final class PhabricatorObjectHandle return $this->getTypeIcon(); } + public function setSubtitle($subtitle) { + $this->subtitle = $subtitle; + return $this; + } + + public function getSubtitle() { + return $this->subtitle; + } + public function setTagColor($color) { static $colors; if (!$colors) { diff --git a/src/applications/project/view/PhabricatorProjectUserListView.php b/src/applications/project/view/PhabricatorProjectUserListView.php index 4a3fe53260..fe1a2c0f82 100644 --- a/src/applications/project/view/PhabricatorProjectUserListView.php +++ b/src/applications/project/view/PhabricatorProjectUserListView.php @@ -79,6 +79,13 @@ abstract class PhabricatorProjectUserListView extends AphrontView { ->setHref($handle->getURI()) ->setImageURI($handle->getImageURI()); + $icon = id(new PHUIIconView()) + ->setIconFont($handle->getIcon().' grey'); + + $subtitle = $handle->getSubtitle(); + + $item->addAttribute(array($icon, ' ', $subtitle)); + if ($can_edit && !$limit) { $remove_uri = $this->getRemoveURI($user_phid);