Page MenuHomePhabricator

D9264.id22002.diff
No OneTemporary

D9264.id22002.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -94,6 +94,7 @@
'rsrc/css/application/ponder/post.css' => 'ebab8a70',
'rsrc/css/application/ponder/vote.css' => '8ed6ed8b',
'rsrc/css/application/profile/profile-view.css' => '33e6f703',
+ 'rsrc/css/application/projects/project-icon.css' => 'd80f48b0',
'rsrc/css/application/projects/project-tag.css' => '095c9404',
'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733',
'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5',
@@ -788,6 +789,7 @@
'ponder-feed-view-css' => 'e62615b6',
'ponder-post-css' => 'ebab8a70',
'ponder-vote-css' => '8ed6ed8b',
+ 'project-icon-css' => 'd80f48b0',
'raphael-core' => '51ee6b43',
'raphael-g' => '40dde778',
'raphael-g-line' => '40da039e',
diff --git a/resources/sql/autopatches/20140522.projecticon.sql b/resources/sql/autopatches/20140522.projecticon.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20140522.projecticon.sql
@@ -0,0 +1,5 @@
+ALTER TABLE {$NAMESPACE}_project.project
+ ADD COLUMN icon VARCHAR(32) NOT NULL COLLATE utf8_bin;
+
+UPDATE {$NAMESPACE}_project.project
+ SET icon = "fa-briefcase" WHERE icon = "";
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1949,9 +1949,11 @@
'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php',
'PhabricatorProjectDescriptionField' => 'applications/project/customfield/PhabricatorProjectDescriptionField.php',
'PhabricatorProjectEditDetailsController' => 'applications/project/controller/PhabricatorProjectEditDetailsController.php',
+ 'PhabricatorProjectEditIconController' => 'applications/project/controller/PhabricatorProjectEditIconController.php',
'PhabricatorProjectEditMainController' => 'applications/project/controller/PhabricatorProjectEditMainController.php',
'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php',
'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php',
+ 'PhabricatorProjectIcon' => 'applications/project/icon/PhabricatorProjectIcon.php',
'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php',
'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php',
@@ -4774,9 +4776,11 @@
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
'PhabricatorProjectDescriptionField' => 'PhabricatorProjectStandardCustomField',
'PhabricatorProjectEditDetailsController' => 'PhabricatorProjectController',
+ 'PhabricatorProjectEditIconController' => 'PhabricatorProjectController',
'PhabricatorProjectEditMainController' => 'PhabricatorProjectController',
'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController',
'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase',
+ 'PhabricatorProjectIcon' => 'Phobject',
'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController',
'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController',
diff --git a/src/applications/phid/PhabricatorObjectHandle.php b/src/applications/phid/PhabricatorObjectHandle.php
--- a/src/applications/phid/PhabricatorObjectHandle.php
+++ b/src/applications/phid/PhabricatorObjectHandle.php
@@ -10,6 +10,7 @@
private $fullName;
private $title;
private $imageURI;
+ private $icon;
private $timestamp;
private $status = PhabricatorObjectHandleStatus::STATUS_OPEN;
private $complete;
@@ -17,6 +18,18 @@
private $objectName;
private $policyFiltered;
+ public function setIcon($icon) {
+ $this->icon = $icon;
+ return $this;
+ }
+
+ public function getIcon() {
+ if ($this->icon) {
+ return $this->icon;
+ }
+ return $this->getTypeIcon();
+ }
+
public function getTypeIcon() {
if ($this->getPHIDType()) {
return $this->getPHIDType()->getTypeIcon();
diff --git a/src/applications/project/application/PhabricatorApplicationProject.php b/src/applications/project/application/PhabricatorApplicationProject.php
--- a/src/applications/project/application/PhabricatorApplicationProject.php
+++ b/src/applications/project/application/PhabricatorApplicationProject.php
@@ -50,6 +50,8 @@
=> 'PhabricatorProjectProfileController',
'picture/(?P<id>[1-9]\d*)/' =>
'PhabricatorProjectEditPictureController',
+ 'icon/(?P<id>[1-9]\d*)/' =>
+ 'PhabricatorProjectEditIconController',
'create/' => 'PhabricatorProjectCreateController',
'board/(?P<id>[1-9]\d*)/'.
'(?P<filter>filter/)?'.
diff --git a/src/applications/project/controller/PhabricatorProjectEditIconController.php b/src/applications/project/controller/PhabricatorProjectEditIconController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/controller/PhabricatorProjectEditIconController.php
@@ -0,0 +1,111 @@
+<?php
+
+final class PhabricatorProjectEditIconController
+ extends PhabricatorProjectController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = $data['id'];
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $project = id(new PhabricatorProjectQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$project) {
+ return new Aphront404Response();
+ }
+
+ $view_uri = '/tag/'.$project->getPrimarySlug().'/';
+ $edit_uri = $this->getApplicationURI('edit/'.$project->getID().'/');
+
+ if ($request->isFormPost()) {
+ $v_icon = $request->getStr('icon');
+ $type_icon = PhabricatorProjectTransaction::TYPE_ICON;
+ $xactions = array(id(new PhabricatorProjectTransaction())
+ ->setTransactionType($type_icon)
+ ->setNewValue($v_icon));
+
+ $editor = id(new PhabricatorProjectTransactionEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnMissingFields(true)
+ ->setContinueOnNoEffect(true);
+
+ $editor->applyTransactions($project, $xactions);
+
+ return id(new AphrontReloadResponse())->setURI($edit_uri);
+ }
+
+ require_celerity_resource('project-icon-css');
+ Javelin::initBehavior('phabricator-tooltips');
+
+ $project_icons = PhabricatorProjectIcon::getIconMap();
+ $ii = 0;
+ $buttons = array();
+ foreach ($project_icons as $icon => $label) {
+ $view = id(new PHUIIconView())
+ ->setIconFont($icon.' bluegrey');
+
+ $aural = javelin_tag(
+ 'span',
+ array(
+ 'aural' => true,
+ ),
+ pht('Choose "%s" Icon', $label));
+
+ if ($icon == $project->getIcon()) {
+ $class_extra = ' selected';
+ $tip = $label . pht(' - selected');
+ } else {
+ $class_extra = null;
+ $tip = $label;
+ }
+
+ $buttons[] = javelin_tag(
+ 'button',
+ array(
+ 'class' => 'icon-button'.$class_extra,
+ 'name' => 'icon',
+ 'value' => $icon,
+ 'type' => 'submit',
+ 'sigil' => 'has-tooltip',
+ 'meta' => array(
+ 'tip' => $tip,
+ )
+ ),
+ array(
+ $aural,
+ $view,
+ ));
+ if ((++$ii % 4) == 0) {
+ $buttons[] = phutil_tag('br');
+ }
+ }
+
+ $buttons = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'icon-grid',
+ ),
+ $buttons);
+
+ $dialog = id(new AphrontDialogView())
+ ->setUser($viewer)
+ ->setTitle(pht('Choose Project Icon'))
+ ->appendChild($buttons)
+ ->addCancelButton($edit_uri);
+
+ return id(new AphrontDialogResponse())->setDialog($dialog);
+ }
+}
diff --git a/src/applications/project/controller/PhabricatorProjectEditMainController.php b/src/applications/project/controller/PhabricatorProjectEditMainController.php
--- a/src/applications/project/controller/PhabricatorProjectEditMainController.php
+++ b/src/applications/project/controller/PhabricatorProjectEditMainController.php
@@ -96,6 +96,14 @@
$view->addAction(
id(new PhabricatorActionView())
+ ->setName(pht('Edit Icon'))
+ ->setIcon($project->getIcon())
+ ->setHref($this->getApplicationURI("icon/{$id}/"))
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(true));
+
+ $view->addAction(
+ id(new PhabricatorActionView())
->setName(pht('Edit Picture'))
->setIcon('fa-picture-o')
->setHref($this->getApplicationURI("picture/{$id}/"))
diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
--- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
@@ -15,6 +15,7 @@
$types[] = PhabricatorProjectTransaction::TYPE_SLUGS;
$types[] = PhabricatorProjectTransaction::TYPE_STATUS;
$types[] = PhabricatorProjectTransaction::TYPE_IMAGE;
+ $types[] = PhabricatorProjectTransaction::TYPE_ICON;
return $types;
}
@@ -35,6 +36,8 @@
return $object->getStatus();
case PhabricatorProjectTransaction::TYPE_IMAGE:
return $object->getProfileImagePHID();
+ case PhabricatorProjectTransaction::TYPE_ICON:
+ return $object->getIcon();
}
return parent::getCustomTransactionOldValue($object, $xaction);
@@ -49,6 +52,7 @@
case PhabricatorProjectTransaction::TYPE_SLUGS:
case PhabricatorProjectTransaction::TYPE_STATUS:
case PhabricatorProjectTransaction::TYPE_IMAGE:
+ case PhabricatorProjectTransaction::TYPE_ICON:
return $xaction->getNewValue();
}
@@ -72,6 +76,9 @@
case PhabricatorProjectTransaction::TYPE_IMAGE:
$object->setProfileImagePHID($xaction->getNewValue());
return;
+ case PhabricatorProjectTransaction::TYPE_ICON:
+ $object->setIcon($xaction->getNewValue());
+ return;
case PhabricatorTransactions::TYPE_EDGE:
return;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
@@ -173,6 +180,7 @@
case PhabricatorTransactions::TYPE_JOIN_POLICY:
case PhabricatorProjectTransaction::TYPE_STATUS:
case PhabricatorProjectTransaction::TYPE_IMAGE:
+ case PhabricatorProjectTransaction::TYPE_ICON:
return;
case PhabricatorTransactions::TYPE_EDGE:
$edge_type = $xaction->getMetadataValue('edge:type');
@@ -342,6 +350,7 @@
case PhabricatorProjectTransaction::TYPE_NAME:
case PhabricatorProjectTransaction::TYPE_STATUS:
case PhabricatorProjectTransaction::TYPE_IMAGE:
+ case PhabricatorProjectTransaction::TYPE_ICON:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
diff --git a/src/applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php b/src/applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php
--- a/src/applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php
+++ b/src/applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php
@@ -15,9 +15,7 @@
$user2 = $this->createUser();
$user2->save();
- $proj = $this->createProject();
- $proj->setAuthorPHID($user->getPHID());
- $proj->save();
+ $proj = $this->createProject($user);
$proj = $this->refreshProject($proj, $user, true);
@@ -48,9 +46,7 @@
$user2 = $this->createUser();
$user2->save();
- $proj = $this->createProject();
- $proj->setAuthorPHID($user->getPHID());
- $proj->save();
+ $proj = $this->createProject($user);
// When edit and view policies are set to "user", anyone can edit.
@@ -100,7 +96,6 @@
$user->save();
$proj = $this->createProjectWithNewAuthor();
- $proj->save();
$proj = $this->refreshProject($proj, $user, true);
$this->assertTrue(
@@ -228,9 +223,10 @@
}
}
- private function createProject() {
- $project = new PhabricatorProject();
+ private function createProject(PhabricatorUser $user) {
+ $project = PhabricatorProject::initializeNewProject($user);
$project->setName('Test Project '.mt_rand());
+ $project->save();
return $project;
}
@@ -239,8 +235,7 @@
$author = $this->createUser();
$author->save();
- $project = $this->createProject();
- $project->setAuthorPHID($author->getPHID());
+ $project = $this->createProject($author);
return $project;
}
diff --git a/src/applications/project/icon/PhabricatorProjectIcon.php b/src/applications/project/icon/PhabricatorProjectIcon.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/icon/PhabricatorProjectIcon.php
@@ -0,0 +1,27 @@
+<?php
+
+final class PhabricatorProjectIcon extends Phobject {
+
+ public static function getIconMap() {
+ return
+ array(
+ 'fa-briefcase' => pht('Briefcase'),
+ 'fa-tags' => pht('Tag'),
+ 'fa-folder' => pht('Folder'),
+ 'fa-users' => pht('Team'),
+ 'fa-bug' => pht('Bug'),
+ 'fa-trash-o' => pht('Garbage'),
+ 'fa-calendar' => pht('Deadline'),
+ 'fa-flag-checkered' => pht('Goal'),
+ 'fa-envelope' => pht('Communication'),
+ 'fa-truck' => pht('Release'),
+ 'fa-lock' => pht('Policy'),
+ 'fa-umbrella' => pht('An Umbrella'),
+ );
+ }
+
+ public static function getLabel($key) {
+ $map = self::getIconMap();
+ return $map[$key];
+ }
+}
diff --git a/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php b/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
--- a/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
+++ b/src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
@@ -49,6 +49,7 @@
$handle->setObjectName('#'.$slug);
$handle->setURI("/tag/{$slug}/");
$handle->setImageURI($project->getProfileImageURI());
+ $handle->setIcon($project->getIcon());
if ($project->isArchived()) {
$handle->setStatus(PhabricatorObjectHandleStatus::STATUS_CLOSED);
diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php
--- a/src/applications/project/storage/PhabricatorProject.php
+++ b/src/applications/project/storage/PhabricatorProject.php
@@ -13,6 +13,7 @@
protected $subprojectPHIDs = array();
protected $phrictionSlug;
protected $profileImagePHID;
+ protected $icon;
protected $viewPolicy;
protected $editPolicy;
@@ -26,10 +27,13 @@
private $profileImageFile = self::ATTACHABLE;
private $slugs = self::ATTACHABLE;
+ const DEFAULT_ICON = 'fa-briefcase';
+
public static function initializeNewProject(PhabricatorUser $actor) {
return id(new PhabricatorProject())
->setName('')
->setAuthorPHID($actor->getPHID())
+ ->setIcon(self::DEFAULT_ICON)
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
->setEditPolicy(PhabricatorPolicies::POLICY_USER)
->setJoinPolicy(PhabricatorPolicies::POLICY_USER)
diff --git a/src/applications/project/storage/PhabricatorProjectTransaction.php b/src/applications/project/storage/PhabricatorProjectTransaction.php
--- a/src/applications/project/storage/PhabricatorProjectTransaction.php
+++ b/src/applications/project/storage/PhabricatorProjectTransaction.php
@@ -7,6 +7,7 @@
const TYPE_SLUGS = 'project:slugs';
const TYPE_STATUS = 'project:status';
const TYPE_IMAGE = 'project:image';
+ const TYPE_ICON = 'project:icon';
// NOTE: This is deprecated, members are just a normal edge now.
const TYPE_MEMBERS = 'project:members';
@@ -86,6 +87,12 @@
$this->renderHandleLink($new));
}
+ case PhabricatorProjectTransaction::TYPE_ICON:
+ return pht(
+ '%s set this project\'s icon to %s.',
+ $author_handle,
+ PhabricatorProjectIcon::getLabel($new));
+
case PhabricatorProjectTransaction::TYPE_SLUGS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
diff --git a/src/applications/typeahead/controller/PhabricatorTypeaheadCommonDatasourceController.php b/src/applications/typeahead/controller/PhabricatorTypeaheadCommonDatasourceController.php
--- a/src/applications/typeahead/controller/PhabricatorTypeaheadCommonDatasourceController.php
+++ b/src/applications/typeahead/controller/PhabricatorTypeaheadCommonDatasourceController.php
@@ -288,7 +288,7 @@
->setDisplayType("Project")
->setURI('/project/view/'.$proj->getID().'/')
->setPHID($proj->getPHID())
- ->setIcon('fa-briefcase bluegrey')
+ ->setIcon($proj->getIcon().' bluegrey')
->setClosed($closed);
$proj_result->setImageURI($proj->getProfileImageURI());
diff --git a/src/view/form/control/AphrontFormTokenizerControl.php b/src/view/form/control/AphrontFormTokenizerControl.php
--- a/src/view/form/control/AphrontFormTokenizerControl.php
+++ b/src/view/form/control/AphrontFormTokenizerControl.php
@@ -62,7 +62,7 @@
'id' => $id,
'src' => $this->datasource,
'value' => mpull($values, 'getFullName', 'getPHID'),
- 'icons' => mpull($values, 'getTypeIcon', 'getPHID'),
+ 'icons' => mpull($values, 'getIcon', 'getPHID'),
'limit' => $this->limit,
'username' => $username,
'placeholder' => $this->placeholder,
diff --git a/webroot/rsrc/css/application/projects/project-icon.css b/webroot/rsrc/css/application/projects/project-icon.css
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/css/application/projects/project-icon.css
@@ -0,0 +1,28 @@
+/**
+ * @provides project-icon-css
+ */
+
+button.icon-button {
+ background: #f7f7f7;
+ border: 1px solid {$lightblueborder};
+ position: relative;
+ width: 16px;
+ height: 16px;
+ padding: 12px;
+ margin: 4px;
+ text-shadow: none;
+ box-shadow: none;
+ box-sizing: content-box;
+}
+
+.icon-grid {
+ text-align: center;
+}
+
+.icon-icon + .icon-icon {
+ margin-left: 4px;
+}
+
+button.icon-button.selected {
+ background: {$bluebackground};
+}

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 18, 8:12 AM (3 d, 23 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7704529
Default Alt Text
D9264.id22002.diff (18 KB)

Event Timeline