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

Allow project colors to be relabeled

Summary: Fixes T5819. Adds configuration for setting color labels on projects and changing the default. Options are locked to what we make available.

Test Plan: {F1066823}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T5819

Differential Revision: https://secure.phabricator.com/D15088
This commit is contained in:
epriestley 2016-01-22 04:33:23 -08:00
parent 12a8726783
commit c25de5e02f
7 changed files with 197 additions and 21 deletions

View file

@ -2858,6 +2858,7 @@ phutil_register_library_map(array(
'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php',
'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php',
'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php',
'PhabricatorProjectColorsConfigOptionType' => 'applications/project/config/PhabricatorProjectColorsConfigOptionType.php',
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
'PhabricatorProjectColumnDetailController' => 'applications/project/controller/PhabricatorProjectColumnDetailController.php',
'PhabricatorProjectColumnEditController' => 'applications/project/controller/PhabricatorProjectColumnEditController.php',
@ -2890,6 +2891,7 @@ phutil_register_library_map(array(
'PhabricatorProjectHeraldFieldGroup' => 'applications/project/herald/PhabricatorProjectHeraldFieldGroup.php',
'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php',
'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php',
'PhabricatorProjectIconsConfigOptionType' => 'applications/project/config/PhabricatorProjectIconsConfigOptionType.php',
'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php',
'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
'PhabricatorProjectListView' => 'applications/project/view/PhabricatorProjectListView.php',
@ -2937,7 +2939,6 @@ phutil_register_library_map(array(
'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',
@ -7255,6 +7256,7 @@ phutil_register_library_map(array(
'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController',
'PhabricatorProjectColorsConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'PhabricatorProjectColumn' => array(
'PhabricatorProjectDAO',
'PhabricatorApplicationTransactionInterface',
@ -7298,6 +7300,7 @@ phutil_register_library_map(array(
'PhabricatorProjectHeraldFieldGroup' => 'HeraldFieldGroup',
'PhabricatorProjectHistoryController' => 'PhabricatorProjectController',
'PhabricatorProjectIconSet' => 'PhabricatorIconSet',
'PhabricatorProjectIconsConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectListView' => 'AphrontView',
'PhabricatorProjectLockController' => 'PhabricatorProjectController',
@ -7347,7 +7350,6 @@ phutil_register_library_map(array(
'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorProjectTypeConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener',
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',

View file

@ -0,0 +1,10 @@
<?php
final class PhabricatorProjectColorsConfigOptionType
extends PhabricatorConfigJSONOptionType {
public function validateOption(PhabricatorConfigOption $option, $value) {
PhabricatorProjectIconSet::validateColorConfiguration($value);
}
}

View file

@ -21,7 +21,7 @@ final class PhabricatorProjectConfigOptions
public function getOptions() {
$default_icons = PhabricatorProjectIconSet::getDefaultConfiguration();
$icons_type = 'custom:PhabricatorProjectTypeConfigOptionType';
$icons_type = 'custom:PhabricatorProjectIconsConfigOptionType';
$icons_description = $this->deformat(pht(<<<EOTEXT
Allows you to change and customize the available project icons.
@ -47,6 +47,27 @@ configuration.
EOTEXT
));
$default_colors = PhabricatorProjectIconSet::getDefaultColorMap();
$colors_type = 'custom:PhabricatorProjectColorsConfigOptionType';
$colors_description = $this->deformat(pht(<<<EOTEXT
Allows you to relabel project colors.
The list of available colors can not be expanded, but the existing colors may
be given labels.
Configure a list of color specifications. Each color specification should be a
dictionary, which may contain these keys:
- `key` //Required string.// The internal key identifying the color.
- `name` //Required string.// Human-readable label for the color.
- `default` //Optional bool.// Selects the default color used when creating
new projects. Exactly one color must be selected as the default.
You can look at the default configuration below for an example of a valid
configuration.
EOTEXT
));
$default_fields = array(
'std:project:internal:description' => true,
@ -76,6 +97,9 @@ EOTEXT
$this->newOption('projects.icons', $icons_type, $default_icons)
->setSummary(pht('Adjust project icons.'))
->setDescription($icons_description),
$this->newOption('projects.colors', $colors_type, $default_colors)
->setSummary(pht('Adjust project colors.'))
->setDescription($colors_description),
);
}

View file

@ -1,6 +1,6 @@
<?php
final class PhabricatorProjectTypeConfigOptionType
final class PhabricatorProjectIconsConfigOptionType
extends PhabricatorConfigJSONOptionType {
public function validateOption(PhabricatorConfigOption $option, $value) {

View file

@ -125,16 +125,6 @@ final class PhabricatorProjectIconSet
return $icons;
}
public static function getColorMap() {
$shades = PHUITagView::getShadeMap();
$shades = array_select_keys(
$shades,
array(PhabricatorProject::DEFAULT_COLOR)) + $shades;
unset($shades[PHUITagView::COLOR_DISABLED]);
return $shades;
}
private static function getIconSpecifications() {
return PhabricatorEnv::getEnvConfig('projects.icons');
}
@ -314,4 +304,157 @@ final class PhabricatorProjectIconSet
}
private static function getColorSpecifications() {
return PhabricatorEnv::getEnvConfig('projects.colors');
}
public static function getColorMap() {
$specifications = self::getColorSpecifications();
return ipull($specifications, 'name', 'key');
}
public static function getDefaultColorKey() {
$specifications = self::getColorSpecifications();
foreach ($specifications as $specification) {
if (idx($specification, 'default')) {
return $specification['key'];
}
}
return null;
}
private static function getAvailableColorKeys() {
$list = array();
$specifications = self::getDefaultColorMap();
foreach ($specifications as $specification) {
$list[] = $specification['key'];
}
return $list;
}
public static function getDefaultColorMap() {
return array(
array(
'key' => PHUITagView::COLOR_RED,
'name' => pht('Red'),
),
array(
'key' => PHUITagView::COLOR_ORANGE,
'name' => pht('Orange'),
),
array(
'key' => PHUITagView::COLOR_YELLOW,
'name' => pht('Yellow'),
),
array(
'key' => PHUITagView::COLOR_GREEN,
'name' => pht('Green'),
),
array(
'key' => PHUITagView::COLOR_BLUE,
'name' => pht('Blue'),
'default' => true,
),
array(
'key' => PHUITagView::COLOR_INDIGO,
'name' => pht('Indigo'),
),
array(
'key' => PHUITagView::COLOR_VIOLET,
'name' => pht('Violet'),
),
array(
'key' => PHUITagView::COLOR_PINK,
'name' => pht('Pink'),
),
array(
'key' => PHUITagView::COLOR_GREY,
'name' => pht('Grey'),
),
array(
'key' => PHUITagView::COLOR_CHECKERED,
'name' => pht('Checkered'),
),
);
}
public static function validateColorConfiguration($config) {
if (!is_array($config)) {
throw new Exception(
pht('Configuration must be a list of project color specifications.'));
}
$available_keys = self::getAvailableColorKeys();
$available_keys = array_fuse($available_keys);
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',
'default' => 'optional bool',
));
$key = $value['key'];
if (!isset($available_keys[$key])) {
throw new Exception(
pht(
'Color key "%s" is not a valid color key. The supported color '.
'keys are: %s.',
$key,
implode(', ', $available_keys)));
}
}
$default = null;
$keys = array();
foreach ($config as $idx => $value) {
$key = $value['key'];
if (isset($keys[$key])) {
throw new Exception(
pht(
'Project colors must have unique keys, but two icons share the '.
'same key ("%s").',
$key));
} else {
$keys[$key] = true;
}
if (idx($value, 'default')) {
if ($default === null) {
$default = $value;
} else {
$original_key = $default['key'];
throw new Exception(
pht(
'Two different colors ("%s", "%s") are marked as the default '.
'color. Only one color may be marked as the default.',
$key,
$original_key));
}
}
}
if ($default === null) {
throw new Exception(
pht(
'Project colors must include one color marked as the "%s" color, '.
'but no such color exists.',
'default'));
}
}
}

View file

@ -42,7 +42,7 @@ final class PhabricatorProjectSearchEngine
}
protected function buildQueryFromParameters(array $map) {
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if (strlen($map['name'])) {
@ -155,8 +155,6 @@ protected function buildQueryFromParameters(array $map) {
->setType(PHUITagView::TYPE_SHADE)
->setShade($color)
->setName($name),
' ',
$name,
);
}

View file

@ -44,8 +44,6 @@ final class PhabricatorProject extends PhabricatorProjectDAO
private $slugs = self::ATTACHABLE;
private $parentProject = self::ATTACHABLE;
const DEFAULT_COLOR = 'blue';
const TABLE_DATASOURCE_TOKEN = 'project_datasourcetoken';
const PANEL_PROFILE = 'project.profile';
@ -68,11 +66,12 @@ final class PhabricatorProject extends PhabricatorProjectDAO
ProjectDefaultJoinCapability::CAPABILITY);
$default_icon = PhabricatorProjectIconSet::getDefaultIconKey();
$default_color = PhabricatorProjectIconSet::getDefaultColorKey();
return id(new PhabricatorProject())
->setAuthorPHID($actor->getPHID())
->setIcon($default_icon)
->setColor(self::DEFAULT_COLOR)
->setColor($default_color)
->setViewPolicy($view_policy)
->setEditPolicy($edit_policy)
->setJoinPolicy($join_policy)
@ -511,7 +510,7 @@ final class PhabricatorProject extends PhabricatorProjectDAO
public function getDisplayColor() {
if ($this->isMilestone()) {
return self::DEFAULT_COLOR;
return PhabricatorProjectIconSet::getDefaultColorKey();
}
return $this->getColor();