Page MenuHomePhabricator

D14918.diff
No OneTemporary

D14918.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -37,7 +37,6 @@
'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601',
'rsrc/css/application/base/phui-theme.css' => '6b451f24',
'rsrc/css/application/base/standard-page-view.css' => '3c99cdf4',
- 'rsrc/css/application/calendar/calendar-icon.css' => 'c69aa59f',
'rsrc/css/application/chatlog/chatlog.css' => 'd295b020',
'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4',
'rsrc/css/application/config/config-options.css' => '0ede4c9b',
@@ -94,7 +93,6 @@
'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43',
'rsrc/css/application/policy/policy.css' => '957ea14c',
'rsrc/css/application/ponder/ponder-view.css' => '7b0df4da',
- 'rsrc/css/application/projects/project-icon.css' => '4e3eaa5a',
'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733',
'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5',
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
@@ -135,6 +133,7 @@
'rsrc/css/phui/phui-form-view.css' => '4a1a0f5e',
'rsrc/css/phui/phui-form.css' => '0b98e572',
'rsrc/css/phui/phui-header-view.css' => '55bb32dd',
+ 'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad',
'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6',
'rsrc/css/phui/phui-image-mask.css' => '5a8b09c8',
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
@@ -465,7 +464,7 @@
'rsrc/js/core/behavior-active-nav.js' => 'e379b58e',
'rsrc/js/core/behavior-audio-source.js' => '59b251eb',
'rsrc/js/core/behavior-autofocus.js' => '7319e029',
- 'rsrc/js/core/behavior-choose-control.js' => '8fee767e',
+ 'rsrc/js/core/behavior-choose-control.js' => '327a00d1',
'rsrc/js/core/behavior-crop.js' => 'fa0f4fc2',
'rsrc/js/core/behavior-dark-console.js' => 'f411b6ae',
'rsrc/js/core/behavior-device.js' => 'a205cf28',
@@ -524,7 +523,6 @@
'aphront-typeahead-control-css' => '0e403212',
'auth-css' => '0877ed6e',
'bulk-job-css' => 'df9c1d4a',
- 'calendar-icon-css' => 'c69aa59f',
'changeset-view-manager' => '58562350',
'conduit-api-css' => '7bc725c4',
'config-options-css' => '0ede4c9b',
@@ -571,7 +569,7 @@
'javelin-behavior-audio-source' => '59b251eb',
'javelin-behavior-audit-preview' => 'd835b03a',
'javelin-behavior-bulk-job-reload' => 'edf8a145',
- 'javelin-behavior-choose-control' => '8fee767e',
+ 'javelin-behavior-choose-control' => '327a00d1',
'javelin-behavior-comment-actions' => 'b65559c0',
'javelin-behavior-config-reorder-fields' => 'b6993408',
'javelin-behavior-conpherence-drag-and-drop-photo' => 'cf86d16a',
@@ -809,6 +807,7 @@
'phui-form-css' => '0b98e572',
'phui-form-view-css' => '4a1a0f5e',
'phui-header-view-css' => '55bb32dd',
+ 'phui-icon-set-selector-css' => '1ab67aad',
'phui-icon-view-css' => 'b0a6b1b6',
'phui-image-mask-css' => '5a8b09c8',
'phui-info-panel-css' => '27ea50a1',
@@ -839,7 +838,6 @@
'policy-edit-css' => '815c66f7',
'policy-transaction-detail-css' => '82100a43',
'ponder-view-css' => '7b0df4da',
- 'project-icon-css' => '4e3eaa5a',
'raphael-core' => '51ee6b43',
'raphael-g' => '40dde778',
'raphael-g-line' => '40da039e',
@@ -1044,6 +1042,12 @@
'2f670a96' => array(
'phui-theme-css',
),
+ '327a00d1' => array(
+ 'javelin-behavior',
+ 'javelin-stratcom',
+ 'javelin-dom',
+ 'javelin-workflow',
+ ),
'331b1611' => array(
'javelin-install',
),
@@ -1522,12 +1526,6 @@
'javelin-install',
'javelin-dom',
),
- '8fee767e' => array(
- 'javelin-behavior',
- 'javelin-stratcom',
- 'javelin-dom',
- 'javelin-workflow',
- ),
'901935ef' => array(
'javelin-behavior',
'javelin-dom',
diff --git a/resources/sql/autopatches/20151231.proj.01.icon.php b/resources/sql/autopatches/20151231.proj.01.icon.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20151231.proj.01.icon.php
@@ -0,0 +1,34 @@
+<?php
+
+$icon_map = array(
+ 'fa-briefcase' => 'project',
+ 'fa-tags' => 'tag',
+ 'fa-lock' => 'policy',
+ 'fa-users' => 'group',
+
+ 'fa-folder' => 'folder',
+ 'fa-calendar' => 'timeline',
+ 'fa-flag-checkered' => 'goal',
+ 'fa-truck' => 'release',
+
+ 'fa-bug' => 'bugs',
+ 'fa-trash-o' => 'cleanup',
+ 'fa-umbrella' => 'umbrella',
+ 'fa-envelope' => 'communication',
+
+ 'fa-building' => 'organization',
+ 'fa-cloud' => 'infrastructure',
+ 'fa-credit-card' => 'account',
+ 'fa-flask' => 'experimental',
+);
+
+$table = new PhabricatorProject();
+$conn_w = $table->establishConnection('w');
+foreach ($icon_map as $old_icon => $new_key) {
+ queryfx(
+ $conn_w,
+ 'UPDATE %T SET icon = %s WHERE icon = %s',
+ $table->getTableName(),
+ $new_key,
+ $old_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
@@ -2902,6 +2902,7 @@
'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php',
'PhabricatorProjectTransactionEditor' => 'applications/project/editor/PhabricatorProjectTransactionEditor.php',
'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php',
+ 'PhabricatorProjectTypeConfigOptionType' => 'applications/project/config/PhabricatorProjectTypeConfigOptionType.php',
'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php',
'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php',
'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php',
@@ -7268,6 +7269,7 @@
'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
+ 'PhabricatorProjectTypeConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener',
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
diff --git a/src/applications/config/custom/PhabricatorConfigOptionType.php b/src/applications/config/custom/PhabricatorConfigOptionType.php
--- a/src/applications/config/custom/PhabricatorConfigOptionType.php
+++ b/src/applications/config/custom/PhabricatorConfigOptionType.php
@@ -24,8 +24,7 @@
$value) {
if (is_array($value)) {
- $json = new PhutilJSON();
- return $json->encodeFormatted($value);
+ return PhabricatorConfigJSON::prettyPrintJSON($value);
} else {
return $value;
}
diff --git a/src/applications/files/controller/PhabricatorFileIconSetSelectController.php b/src/applications/files/controller/PhabricatorFileIconSetSelectController.php
--- a/src/applications/files/controller/PhabricatorFileIconSetSelectController.php
+++ b/src/applications/files/controller/PhabricatorFileIconSetSelectController.php
@@ -26,7 +26,7 @@
}
}
- require_celerity_resource('project-icon-css');
+ require_celerity_resource('phui-icon-set-selector-css');
Javelin::initBehavior('phabricator-tooltips');
$ii = 0;
@@ -37,6 +37,20 @@
$view = id(new PHUIIconView())
->setIconFont($icon->getIcon());
+ $classes = array();
+ $classes[] = 'icon-button';
+
+ $is_selected = ($icon->getKey() == $v_icon);
+
+ if ($is_selected) {
+ $classes[] = 'selected';
+ }
+
+ $is_disabled = $icon->getIsDisabled();
+ if ($is_disabled && !$is_selected) {
+ continue;
+ }
+
$aural = javelin_tag(
'span',
array(
@@ -44,13 +58,6 @@
),
pht('Choose "%s" Icon', $label));
- $classes = array();
- $classes[] = 'icon-button';
-
- if ($icon->getKey() == $v_icon) {
- $classes[] = 'selected';
- }
-
$buttons[] = javelin_tag(
'button',
array(
diff --git a/src/applications/files/iconset/PhabricatorIconSetIcon.php b/src/applications/files/iconset/PhabricatorIconSetIcon.php
--- a/src/applications/files/iconset/PhabricatorIconSetIcon.php
+++ b/src/applications/files/iconset/PhabricatorIconSetIcon.php
@@ -6,6 +6,7 @@
private $key;
private $icon;
private $label;
+ private $isDisabled;
public function setKey($key) {
$this->key = $key;
@@ -28,6 +29,15 @@
return $this->icon;
}
+ public function setIsDisabled($is_disabled) {
+ $this->isDisabled = $is_disabled;
+ return $this;
+ }
+
+ public function getIsDisabled() {
+ return $this->isDisabled;
+ }
+
public function setLabel($label) {
$this->label = $label;
return $this;
diff --git a/src/applications/project/conduit/ProjectConduitAPIMethod.php b/src/applications/project/conduit/ProjectConduitAPIMethod.php
--- a/src/applications/project/conduit/ProjectConduitAPIMethod.php
+++ b/src/applications/project/conduit/ProjectConduitAPIMethod.php
@@ -26,7 +26,7 @@
$project_slugs = $project->getSlugs();
$project_slugs = array_values(mpull($project_slugs, 'getSlug'));
- $project_icon = substr($project->getIcon(), 3);
+ $project_icon = $project->getDisplayIconKey();
$result[$project->getPHID()] = array(
'id' => $project->getID(),
diff --git a/src/applications/project/conduit/ProjectQueryConduitAPIMethod.php b/src/applications/project/conduit/ProjectQueryConduitAPIMethod.php
--- a/src/applications/project/conduit/ProjectQueryConduitAPIMethod.php
+++ b/src/applications/project/conduit/ProjectQueryConduitAPIMethod.php
@@ -76,11 +76,6 @@
$request->getValue('icons');
if ($request->getValue('icons')) {
$icons = array();
- // the internal 'fa-' prefix is a detail hidden from api clients
- // but needs to pre prepended to the values in the icons array:
- foreach ($request->getValue('icons') as $value) {
- $icons[] = 'fa-'.$value;
- }
$query->withIcons($icons);
}
diff --git a/src/applications/project/config/PhabricatorProjectConfigOptions.php b/src/applications/project/config/PhabricatorProjectConfigOptions.php
--- a/src/applications/project/config/PhabricatorProjectConfigOptions.php
+++ b/src/applications/project/config/PhabricatorProjectConfigOptions.php
@@ -20,6 +20,34 @@
}
public function getOptions() {
+ $default_icons = PhabricatorProjectIconSet::getDefaultConfiguration();
+ $icons_type = 'custom:PhabricatorProjectTypeConfigOptionType';
+
+ $icons_description = $this->deformat(pht(<<<EOTEXT
+Allows you to change and customize the available project icons.
+
+You can find a list of available icons in {nav UIExamples > Icons and Images}.
+
+Configure a list of icon specifications. Each icon specification should be
+a dictionary, which may contain these keys:
+
+ - `key` //Required string.// Internal key identifying the icon.
+ - `name` //Required string.// Human-readable icon name.
+ - `icon` //Required string.// Specifies which actual icon image to use.
+ - `default` //Optional bool.// Selects a default icon. Exactly one icon must
+ be selected as the default.
+ - `disabled` //Optional bool.// If true, this icon will no longer be
+ available for selection when creating or editing projects.
+ - `special` //Optional string.// Marks an icon as a special icon:
+ - `milestone` This is the icon for milestones. Exactly one icon must be
+ selected as the milestone icon.
+
+You can look at the default configuration below for an example of a valid
+configuration.
+EOTEXT
+ ));
+
+
$default_fields = array(
'std:project:internal:description' => true,
);
@@ -45,6 +73,9 @@
$this->newOption('projects.fields', $custom_field_type, $default_fields)
->setCustomData(id(new PhabricatorProject())->getCustomFieldBaseClass())
->setDescription(pht('Select and reorder project fields.')),
+ $this->newOption('projects.icons', $icons_type, $default_icons)
+ ->setSummary(pht('Adjust project icons.'))
+ ->setDescription($icons_description),
);
}
diff --git a/src/applications/project/config/PhabricatorProjectTypeConfigOptionType.php b/src/applications/project/config/PhabricatorProjectTypeConfigOptionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/config/PhabricatorProjectTypeConfigOptionType.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorProjectTypeConfigOptionType
+ extends PhabricatorConfigJSONOptionType {
+
+ public function validateOption(PhabricatorConfigOption $option, $value) {
+ PhabricatorProjectIconSet::validateConfiguration($value);
+ }
+
+}
diff --git a/src/applications/project/controller/PhabricatorProjectController.php b/src/applications/project/controller/PhabricatorProjectController.php
--- a/src/applications/project/controller/PhabricatorProjectController.php
+++ b/src/applications/project/controller/PhabricatorProjectController.php
@@ -156,10 +156,10 @@
$subprojects_icon = 'fa-sitemap grey';
}
- if ($project->supportsMilestones()) {
- $milestones_icon = 'fa-map-marker';
- } else {
- $milestones_icon = 'fa-map-marker grey';
+ $key = PhabricatorProjectIconSet::getMilestoneIconKey();
+ $milestones_icon = PhabricatorProjectIconSet::getIconIcon($key);
+ if (!$project->supportsMilestones()) {
+ $milestones_icon = "{$milestones_icon} grey";
}
$nav->addIcon(
diff --git a/src/applications/project/icon/PhabricatorProjectIconSet.php b/src/applications/project/icon/PhabricatorProjectIconSet.php
--- a/src/applications/project/icon/PhabricatorProjectIconSet.php
+++ b/src/applications/project/icon/PhabricatorProjectIconSet.php
@@ -5,38 +5,121 @@
const ICONSETKEY = 'projects';
+ const SPECIAL_MILESTONE = 'milestone';
+
public function getSelectIconTitleText() {
return pht('Choose Project Icon');
}
- protected function newIcons() {
- $map = 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'),
-
- 'fa-cloud' => pht('The Cloud'),
- 'fa-building' => pht('Company'),
- 'fa-credit-card' => pht('Accounting'),
- 'fa-flask' => pht('Experimental'),
+ public static function getDefaultConfiguration() {
+ return array(
+ array(
+ 'key' => 'project',
+ 'icon' => 'fa-briefcase',
+ 'name' => pht('Project'),
+ 'default' => true,
+ ),
+ array(
+ 'key' => 'tag',
+ 'icon' => 'fa-tags',
+ 'name' => pht('Tag'),
+ ),
+ array(
+ 'key' => 'policy',
+ 'icon' => 'fa-lock',
+ 'name' => pht('Policy'),
+ ),
+ array(
+ 'key' => 'group',
+ 'icon' => 'fa-users',
+ 'name' => pht('Group'),
+ ),
+ array(
+ 'key' => 'folder',
+ 'icon' => 'fa-folder',
+ 'name' => pht('Folder'),
+ ),
+ array(
+ 'key' => 'timeline',
+ 'icon' => 'fa-calendar',
+ 'name' => pht('Timeline'),
+ ),
+ array(
+ 'key' => 'goal',
+ 'icon' => 'fa-flag-checkered',
+ 'name' => pht('Goal'),
+ ),
+ array(
+ 'key' => 'release',
+ 'icon' => 'fa-truck',
+ 'name' => pht('Release'),
+ ),
+ array(
+ 'key' => 'bugs',
+ 'icon' => 'fa-bug',
+ 'name' => pht('Bugs'),
+ ),
+ array(
+ 'key' => 'cleanup',
+ 'icon' => 'fa-trash-o',
+ 'name' => pht('Cleanup'),
+ ),
+ array(
+ 'key' => 'umbrella',
+ 'icon' => 'fa-umbrella',
+ 'name' => pht('Umbrella'),
+ ),
+ array(
+ 'key' => 'communication',
+ 'icon' => 'fa-envelope',
+ 'name' => pht('Communication'),
+ ),
+ array(
+ 'key' => 'organization',
+ 'icon' => 'fa-building',
+ 'name' => pht('Organization'),
+ ),
+ array(
+ 'key' => 'infrastructure',
+ 'icon' => 'fa-cloud',
+ 'name' => pht('Infrastructure'),
+ ),
+ array(
+ 'key' => 'account',
+ 'icon' => 'fa-credit-card',
+ 'name' => pht('Account'),
+ ),
+ array(
+ 'key' => 'experimental',
+ 'icon' => 'fa-flask',
+ 'name' => pht('Experimental'),
+ ),
+ array(
+ 'key' => 'milestone',
+ 'icon' => 'fa-map-marker',
+ 'name' => pht('Milestone'),
+ 'special' => self::SPECIAL_MILESTONE,
+ ),
);
+ }
+
+
+ protected function newIcons() {
+ $map = self::getIconSpecifications();
$icons = array();
- foreach ($map as $key => $label) {
+ foreach ($map as $spec) {
+ $special = idx($spec, 'special');
+
+ if ($special === self::SPECIAL_MILESTONE) {
+ continue;
+ }
+
$icons[] = id(new PhabricatorIconSetIcon())
- ->setKey($key)
- ->setLabel($label);
+ ->setKey($spec['key'])
+ ->setIsDisabled(idx($spec, 'disabled'))
+ ->setIcon($spec['icon'])
+ ->setLabel($spec['name']);
}
return $icons;
@@ -52,4 +135,183 @@
return $shades;
}
+ private static function getIconSpecifications() {
+ return PhabricatorEnv::getEnvConfig('projects.icons');
+ }
+
+ public static function getDefaultIconKey() {
+ $icons = self::getIconSpecifications();
+ foreach ($icons as $icon) {
+ if (idx($icon, 'default')) {
+ return $icon['key'];
+ }
+ }
+ return null;
+ }
+
+ public static function getIconIcon($key) {
+ $spec = self::getIconSpec($key);
+ return idx($spec, 'icon', null);
+ }
+
+ public static function getIconName($key) {
+ $spec = self::getIconSpec($key);
+ return idx($spec, 'name', null);
+ }
+
+ private static function getIconSpec($key) {
+ $icons = self::getIconSpecifications();
+ foreach ($icons as $icon) {
+ if (idx($icon, 'key') === $key) {
+ return $icon;
+ }
+ }
+
+ return array();
+ }
+
+ public static function getMilestoneIconKey() {
+ $icons = self::getIconSpecifications();
+ foreach ($icons as $icon) {
+ if (idx($icon, 'special') === self::SPECIAL_MILESTONE) {
+ return idx($icon, 'key');
+ }
+ }
+ return null;
+ }
+
+ public static function validateConfiguration($config) {
+ if (!is_array($config)) {
+ throw new Exception(
+ pht('Configuration must be a list of project icon specifications.'));
+ }
+
+ foreach ($config as $idx => $value) {
+ if (!is_array($value)) {
+ throw new Exception(
+ pht(
+ 'Value for index "%s" should be a dictionary.',
+ $idx));
+ }
+
+ PhutilTypeSpec::checkMap(
+ $value,
+ array(
+ 'key' => 'string',
+ 'name' => 'string',
+ 'icon' => 'string',
+ 'special' => 'optional string',
+ 'disabled' => 'optional bool',
+ 'default' => 'optional bool',
+ ));
+
+ if (!preg_match('/^[a-z]{1,32}\z/', $value['key'])) {
+ throw new Exception(
+ pht(
+ 'Icon key "%s" is not a valid icon key. Icon keys must be 1-32 '.
+ 'characters long and contain only lowercase letters. For example, '.
+ '"%s" and "%s" are reasonable keys.',
+ 'tag',
+ 'group'));
+ }
+
+ $special = idx($value, 'special');
+ $valid = array(
+ self::SPECIAL_MILESTONE => true,
+ );
+
+ if ($special !== null) {
+ if (empty($valid[$special])) {
+ throw new Exception(
+ pht(
+ 'Icon special attribute "%s" is not valid. Recognized special '.
+ 'attributes are: %s.',
+ $special,
+ implode(', ', array_keys($valid))));
+ }
+ }
+ }
+
+ $default = null;
+ $milestone = null;
+ $keys = array();
+ foreach ($config as $idx => $value) {
+ $key = $value['key'];
+ if (isset($keys[$key])) {
+ throw new Exception(
+ pht(
+ 'Project icons must have unique keys, but two icons share the '.
+ 'same key ("%s").',
+ $key));
+ } else {
+ $keys[$key] = true;
+ }
+
+ $is_disabled = idx($value, 'disabled');
+
+ if (idx($value, 'default')) {
+ if ($default === null) {
+ if ($is_disabled) {
+ throw new Exception(
+ pht(
+ 'The project icon marked as the default icon ("%s") must not '.
+ 'be disabled.',
+ $key));
+ }
+ $default = $value;
+ } else {
+ $original_key = $default['key'];
+ throw new Exception(
+ pht(
+ 'Two different icons ("%s", "%s") are marked as the default '.
+ 'icon. Only one icon may be marked as the default.',
+ $key,
+ $original_key));
+ }
+ }
+
+ $special = idx($value, 'special');
+ if ($special === self::SPECIAL_MILESTONE) {
+ if ($milestone === null) {
+ if ($is_disabled) {
+ throw new Exception(
+ pht(
+ 'The project icon ("%s") with special attribute "%s" must '.
+ 'not be disabled',
+ $key,
+ self::SPECIAL_MIILESTONE));
+ }
+ $milestone = $value;
+ } else {
+ $original_key = $milestone['key'];
+ throw new Exception(
+ pht(
+ 'Two different icons ("%s", "%s") are marked with special '.
+ 'attribute "%s". Only one icon may be marked with this '.
+ 'attribute.',
+ $key,
+ $original_key,
+ self::SPECIAL_MILESTONE));
+ }
+ }
+ }
+
+ if ($default === null) {
+ throw new Exception(
+ pht(
+ 'Project icons must include one icon marked as the "%s" icon, '.
+ 'but no such icon exists.',
+ 'default'));
+ }
+
+ if ($milestone === null) {
+ throw new Exception(
+ pht(
+ 'Project icons must include one icon marked with special attribute '.
+ '"%s", but no such icon exists.',
+ self::SPECIAL_MILESTONE));
+ }
+
+ }
+
}
diff --git a/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php b/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php
--- a/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php
+++ b/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php
@@ -51,7 +51,7 @@
}
$handle->setImageURI($project->getProfileImageURI());
- $handle->setIcon($project->getDisplayIcon());
+ $handle->setIcon($project->getDisplayIconIcon());
$handle->setTagColor($project->getDisplayColor());
if ($project->isArchived()) {
diff --git a/src/applications/project/query/PhabricatorProjectSearchEngine.php b/src/applications/project/query/PhabricatorProjectSearchEngine.php
--- a/src/applications/project/query/PhabricatorProjectSearchEngine.php
+++ b/src/applications/project/query/PhabricatorProjectSearchEngine.php
@@ -131,6 +131,10 @@
$set = new PhabricatorProjectIconSet();
foreach ($set->getIcons() as $icon) {
+ if ($icon->getIsDisabled()) {
+ continue;
+ }
+
$options[$icon->getKey()] = array(
id(new PHUIIconView())
->setIconFont($icon->getIcon()),
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
@@ -45,7 +45,6 @@
private $slugs = self::ATTACHABLE;
private $parentProject = self::ATTACHABLE;
- const DEFAULT_ICON = 'fa-briefcase';
const DEFAULT_COLOR = 'blue';
const TABLE_DATASOURCE_TOKEN = 'project_datasourcetoken';
@@ -63,9 +62,11 @@
$join_policy = $app->getPolicy(
ProjectDefaultJoinCapability::CAPABILITY);
+ $default_icon = PhabricatorProjectIconSet::getDefaultIconKey();
+
return id(new PhabricatorProject())
->setAuthorPHID($actor->getPHID())
- ->setIcon(self::DEFAULT_ICON)
+ ->setIcon($default_icon)
->setColor(self::DEFAULT_COLOR)
->setViewPolicy($view_policy)
->setEditPolicy($edit_policy)
@@ -484,12 +485,24 @@
return $number;
}
- public function getDisplayIcon() {
+ public function getDisplayIconKey() {
if ($this->isMilestone()) {
- return 'fa-map-marker';
+ $key = PhabricatorProjectIconSet::getMilestoneIconKey();
+ } else {
+ $key = $this->getIcon();
}
- return $this->getIcon();
+ return $key;
+ }
+
+ public function getDisplayIconIcon() {
+ $key = $this->getDisplayIconKey();
+ return PhabricatorProjectIconSet::getIconIcon($key);
+ }
+
+ public function getDisplayIconName() {
+ $key = $this->getDisplayIconKey();
+ return PhabricatorProjectIconSet::getIconName($key);
}
public function getDisplayColor() {
@@ -608,6 +621,10 @@
->setKey('slug')
->setType('string')
->setDescription(pht('Primary slug/hashtag.')),
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('icon')
+ ->setType('map<string, wild>')
+ ->setDescription(pht('Information about the project icon.')),
);
}
@@ -615,6 +632,11 @@
return array(
'name' => $this->getName(),
'slug' => $this->getPrimarySlug(),
+ 'icon' => array(
+ 'key' => $this->getDisplayIconKey(),
+ 'name' => $this->getDisplayIconName(),
+ 'icon' => $this->getDisplayIconIcon(),
+ ),
);
}
diff --git a/src/applications/project/view/PhabricatorProjectListView.php b/src/applications/project/view/PhabricatorProjectListView.php
--- a/src/applications/project/view/PhabricatorProjectListView.php
+++ b/src/applications/project/view/PhabricatorProjectListView.php
@@ -25,15 +25,24 @@
foreach ($projects as $key => $project) {
$id = $project->getID();
- $tag_list = id(new PHUIHandleTagListView())
- ->setSlim(true)
- ->setHandles(array($handles[$project->getPHID()]));
+ $icon = $project->getDisplayIconIcon();
+ $color = $project->getColor();
+
+ $icon_icon = id(new PHUIIconView())
+ ->setIconFont("{$icon} {$color}");
+
+ $icon_name = $project->getDisplayIconName();
$item = id(new PHUIObjectItemView())
->setHeader($project->getName())
->setHref("/project/view/{$id}/")
->setImageURI($project->getProfileImageURI())
- ->addAttribute($tag_list);
+ ->addAttribute(
+ array(
+ $icon_icon,
+ ' ',
+ $icon_name,
+ ));
if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ARCHIVED) {
$item->addIcon('delete-grey', pht('Archived'));
diff --git a/webroot/rsrc/css/application/calendar/calendar-icon.css b/webroot/rsrc/css/application/calendar/calendar-icon.css
deleted file mode 100644
--- a/webroot/rsrc/css/application/calendar/calendar-icon.css
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * @provides calendar-icon-css
- */
-
-button.icon-button {
- background: {$lightgreybackground};
- 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};
-}
diff --git a/webroot/rsrc/css/application/projects/project-icon.css b/webroot/rsrc/css/phui/phui-icon-set-selector.css
rename from webroot/rsrc/css/application/projects/project-icon.css
rename to webroot/rsrc/css/phui/phui-icon-set-selector.css
--- a/webroot/rsrc/css/application/projects/project-icon.css
+++ b/webroot/rsrc/css/phui/phui-icon-set-selector.css
@@ -1,5 +1,5 @@
/**
- * @provides project-icon-css
+ * @provides phui-icon-set-selector-css
*/
button.icon-button {
@@ -25,4 +25,5 @@
button.icon-button.selected {
background: {$bluebackground};
+ border: 1px solid {$blueborder};
}
diff --git a/webroot/rsrc/js/core/behavior-choose-control.js b/webroot/rsrc/js/core/behavior-choose-control.js
--- a/webroot/rsrc/js/core/behavior-choose-control.js
+++ b/webroot/rsrc/js/core/behavior-choose-control.js
@@ -22,7 +22,7 @@
}
var params = {
- value: input.value
+ icon: input.value
};
new JX.Workflow(data.uri, params)

File Metadata

Mime Type
text/plain
Expires
May 13 2024, 9:35 PM (4 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6277310
Default Alt Text
D14918.diff (28 KB)

Event Timeline