@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+197 -21
+4 -2
src/__phutil_library_map__.php
··· 2858 2858 'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php', 2859 2859 'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php', 2860 2860 'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php', 2861 + 'PhabricatorProjectColorsConfigOptionType' => 'applications/project/config/PhabricatorProjectColorsConfigOptionType.php', 2861 2862 'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php', 2862 2863 'PhabricatorProjectColumnDetailController' => 'applications/project/controller/PhabricatorProjectColumnDetailController.php', 2863 2864 'PhabricatorProjectColumnEditController' => 'applications/project/controller/PhabricatorProjectColumnEditController.php', ··· 2890 2891 'PhabricatorProjectHeraldFieldGroup' => 'applications/project/herald/PhabricatorProjectHeraldFieldGroup.php', 2891 2892 'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php', 2892 2893 'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php', 2894 + 'PhabricatorProjectIconsConfigOptionType' => 'applications/project/config/PhabricatorProjectIconsConfigOptionType.php', 2893 2895 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', 2894 2896 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', 2895 2897 'PhabricatorProjectListView' => 'applications/project/view/PhabricatorProjectListView.php', ··· 2937 2939 'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php', 2938 2940 'PhabricatorProjectTransactionEditor' => 'applications/project/editor/PhabricatorProjectTransactionEditor.php', 2939 2941 'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php', 2940 - 'PhabricatorProjectTypeConfigOptionType' => 'applications/project/config/PhabricatorProjectTypeConfigOptionType.php', 2941 2942 'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php', 2942 2943 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 2943 2944 'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php', ··· 7255 7256 'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController', 7256 7257 'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController', 7257 7258 'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController', 7259 + 'PhabricatorProjectColorsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 7258 7260 'PhabricatorProjectColumn' => array( 7259 7261 'PhabricatorProjectDAO', 7260 7262 'PhabricatorApplicationTransactionInterface', ··· 7298 7300 'PhabricatorProjectHeraldFieldGroup' => 'HeraldFieldGroup', 7299 7301 'PhabricatorProjectHistoryController' => 'PhabricatorProjectController', 7300 7302 'PhabricatorProjectIconSet' => 'PhabricatorIconSet', 7303 + 'PhabricatorProjectIconsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 7301 7304 'PhabricatorProjectListController' => 'PhabricatorProjectController', 7302 7305 'PhabricatorProjectListView' => 'AphrontView', 7303 7306 'PhabricatorProjectLockController' => 'PhabricatorProjectController', ··· 7347 7350 'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction', 7348 7351 'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 7349 7352 'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 7350 - 'PhabricatorProjectTypeConfigOptionType' => 'PhabricatorConfigJSONOptionType', 7351 7353 'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener', 7352 7354 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 7353 7355 'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
+10
src/applications/project/config/PhabricatorProjectColorsConfigOptionType.php
··· 1 + <?php 2 + 3 + final class PhabricatorProjectColorsConfigOptionType 4 + extends PhabricatorConfigJSONOptionType { 5 + 6 + public function validateOption(PhabricatorConfigOption $option, $value) { 7 + PhabricatorProjectIconSet::validateColorConfiguration($value); 8 + } 9 + 10 + }
+25 -1
src/applications/project/config/PhabricatorProjectConfigOptions.php
··· 21 21 22 22 public function getOptions() { 23 23 $default_icons = PhabricatorProjectIconSet::getDefaultConfiguration(); 24 - $icons_type = 'custom:PhabricatorProjectTypeConfigOptionType'; 24 + $icons_type = 'custom:PhabricatorProjectIconsConfigOptionType'; 25 25 26 26 $icons_description = $this->deformat(pht(<<<EOTEXT 27 27 Allows you to change and customize the available project icons. ··· 47 47 EOTEXT 48 48 )); 49 49 50 + $default_colors = PhabricatorProjectIconSet::getDefaultColorMap(); 51 + $colors_type = 'custom:PhabricatorProjectColorsConfigOptionType'; 52 + 53 + $colors_description = $this->deformat(pht(<<<EOTEXT 54 + Allows you to relabel project colors. 55 + 56 + The list of available colors can not be expanded, but the existing colors may 57 + be given labels. 58 + 59 + Configure a list of color specifications. Each color specification should be a 60 + dictionary, which may contain these keys: 61 + 62 + - `key` //Required string.// The internal key identifying the color. 63 + - `name` //Required string.// Human-readable label for the color. 64 + - `default` //Optional bool.// Selects the default color used when creating 65 + new projects. Exactly one color must be selected as the default. 66 + 67 + You can look at the default configuration below for an example of a valid 68 + configuration. 69 + EOTEXT 70 + )); 50 71 51 72 $default_fields = array( 52 73 'std:project:internal:description' => true, ··· 76 97 $this->newOption('projects.icons', $icons_type, $default_icons) 77 98 ->setSummary(pht('Adjust project icons.')) 78 99 ->setDescription($icons_description), 100 + $this->newOption('projects.colors', $colors_type, $default_colors) 101 + ->setSummary(pht('Adjust project colors.')) 102 + ->setDescription($colors_description), 79 103 ); 80 104 } 81 105
+1 -1
src/applications/project/config/PhabricatorProjectTypeConfigOptionType.php src/applications/project/config/PhabricatorProjectIconsConfigOptionType.php
··· 1 1 <?php 2 2 3 - final class PhabricatorProjectTypeConfigOptionType 3 + final class PhabricatorProjectIconsConfigOptionType 4 4 extends PhabricatorConfigJSONOptionType { 5 5 6 6 public function validateOption(PhabricatorConfigOption $option, $value) {
+153 -10
src/applications/project/icon/PhabricatorProjectIconSet.php
··· 125 125 return $icons; 126 126 } 127 127 128 - public static function getColorMap() { 129 - $shades = PHUITagView::getShadeMap(); 130 - $shades = array_select_keys( 131 - $shades, 132 - array(PhabricatorProject::DEFAULT_COLOR)) + $shades; 133 - unset($shades[PHUITagView::COLOR_DISABLED]); 134 - 135 - return $shades; 136 - } 137 - 138 128 private static function getIconSpecifications() { 139 129 return PhabricatorEnv::getEnvConfig('projects.icons'); 140 130 } ··· 310 300 'Project icons must include one icon marked with special attribute '. 311 301 '"%s", but no such icon exists.', 312 302 self::SPECIAL_MILESTONE)); 303 + } 304 + 305 + } 306 + 307 + private static function getColorSpecifications() { 308 + return PhabricatorEnv::getEnvConfig('projects.colors'); 309 + } 310 + 311 + public static function getColorMap() { 312 + $specifications = self::getColorSpecifications(); 313 + return ipull($specifications, 'name', 'key'); 314 + } 315 + 316 + public static function getDefaultColorKey() { 317 + $specifications = self::getColorSpecifications(); 318 + 319 + foreach ($specifications as $specification) { 320 + if (idx($specification, 'default')) { 321 + return $specification['key']; 322 + } 323 + } 324 + 325 + return null; 326 + } 327 + 328 + private static function getAvailableColorKeys() { 329 + $list = array(); 330 + 331 + $specifications = self::getDefaultColorMap(); 332 + foreach ($specifications as $specification) { 333 + $list[] = $specification['key']; 334 + } 335 + 336 + return $list; 337 + } 338 + 339 + public static function getDefaultColorMap() { 340 + return array( 341 + array( 342 + 'key' => PHUITagView::COLOR_RED, 343 + 'name' => pht('Red'), 344 + ), 345 + array( 346 + 'key' => PHUITagView::COLOR_ORANGE, 347 + 'name' => pht('Orange'), 348 + ), 349 + array( 350 + 'key' => PHUITagView::COLOR_YELLOW, 351 + 'name' => pht('Yellow'), 352 + ), 353 + array( 354 + 'key' => PHUITagView::COLOR_GREEN, 355 + 'name' => pht('Green'), 356 + ), 357 + array( 358 + 'key' => PHUITagView::COLOR_BLUE, 359 + 'name' => pht('Blue'), 360 + 'default' => true, 361 + ), 362 + array( 363 + 'key' => PHUITagView::COLOR_INDIGO, 364 + 'name' => pht('Indigo'), 365 + ), 366 + array( 367 + 'key' => PHUITagView::COLOR_VIOLET, 368 + 'name' => pht('Violet'), 369 + ), 370 + array( 371 + 'key' => PHUITagView::COLOR_PINK, 372 + 'name' => pht('Pink'), 373 + ), 374 + array( 375 + 'key' => PHUITagView::COLOR_GREY, 376 + 'name' => pht('Grey'), 377 + ), 378 + array( 379 + 'key' => PHUITagView::COLOR_CHECKERED, 380 + 'name' => pht('Checkered'), 381 + ), 382 + ); 383 + } 384 + 385 + public static function validateColorConfiguration($config) { 386 + if (!is_array($config)) { 387 + throw new Exception( 388 + pht('Configuration must be a list of project color specifications.')); 389 + } 390 + 391 + $available_keys = self::getAvailableColorKeys(); 392 + $available_keys = array_fuse($available_keys); 393 + 394 + foreach ($config as $idx => $value) { 395 + if (!is_array($value)) { 396 + throw new Exception( 397 + pht( 398 + 'Value for index "%s" should be a dictionary.', 399 + $idx)); 400 + } 401 + 402 + PhutilTypeSpec::checkMap( 403 + $value, 404 + array( 405 + 'key' => 'string', 406 + 'name' => 'string', 407 + 'default' => 'optional bool', 408 + )); 409 + 410 + $key = $value['key']; 411 + if (!isset($available_keys[$key])) { 412 + throw new Exception( 413 + pht( 414 + 'Color key "%s" is not a valid color key. The supported color '. 415 + 'keys are: %s.', 416 + $key, 417 + implode(', ', $available_keys))); 418 + } 419 + } 420 + 421 + $default = null; 422 + $keys = array(); 423 + foreach ($config as $idx => $value) { 424 + $key = $value['key']; 425 + if (isset($keys[$key])) { 426 + throw new Exception( 427 + pht( 428 + 'Project colors must have unique keys, but two icons share the '. 429 + 'same key ("%s").', 430 + $key)); 431 + } else { 432 + $keys[$key] = true; 433 + } 434 + 435 + if (idx($value, 'default')) { 436 + if ($default === null) { 437 + $default = $value; 438 + } else { 439 + $original_key = $default['key']; 440 + throw new Exception( 441 + pht( 442 + 'Two different colors ("%s", "%s") are marked as the default '. 443 + 'color. Only one color may be marked as the default.', 444 + $key, 445 + $original_key)); 446 + } 447 + } 448 + } 449 + 450 + if ($default === null) { 451 + throw new Exception( 452 + pht( 453 + 'Project colors must include one color marked as the "%s" color, '. 454 + 'but no such color exists.', 455 + 'default')); 313 456 } 314 457 315 458 }
+1 -3
src/applications/project/query/PhabricatorProjectSearchEngine.php
··· 42 42 } 43 43 44 44 45 - protected function buildQueryFromParameters(array $map) { 45 + protected function buildQueryFromParameters(array $map) { 46 46 $query = $this->newQuery(); 47 47 48 48 if (strlen($map['name'])) { ··· 155 155 ->setType(PHUITagView::TYPE_SHADE) 156 156 ->setShade($color) 157 157 ->setName($name), 158 - ' ', 159 - $name, 160 158 ); 161 159 } 162 160
+3 -4
src/applications/project/storage/PhabricatorProject.php
··· 44 44 private $slugs = self::ATTACHABLE; 45 45 private $parentProject = self::ATTACHABLE; 46 46 47 - const DEFAULT_COLOR = 'blue'; 48 - 49 47 const TABLE_DATASOURCE_TOKEN = 'project_datasourcetoken'; 50 48 51 49 const PANEL_PROFILE = 'project.profile'; ··· 68 66 ProjectDefaultJoinCapability::CAPABILITY); 69 67 70 68 $default_icon = PhabricatorProjectIconSet::getDefaultIconKey(); 69 + $default_color = PhabricatorProjectIconSet::getDefaultColorKey(); 71 70 72 71 return id(new PhabricatorProject()) 73 72 ->setAuthorPHID($actor->getPHID()) 74 73 ->setIcon($default_icon) 75 - ->setColor(self::DEFAULT_COLOR) 74 + ->setColor($default_color) 76 75 ->setViewPolicy($view_policy) 77 76 ->setEditPolicy($edit_policy) 78 77 ->setJoinPolicy($join_policy) ··· 511 510 512 511 public function getDisplayColor() { 513 512 if ($this->isMilestone()) { 514 - return self::DEFAULT_COLOR; 513 + return PhabricatorProjectIconSet::getDefaultColorKey(); 515 514 } 516 515 517 516 return $this->getColor();