From 483d90fac19200e1f6f058daa12a72dd81651d0e Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 16 Feb 2016 06:52:32 -0800 Subject: [PATCH] Allow workboard background colors to be configured Summary: Adds a UI for selecting background colors. You can choose "Use Parent", which is the default, and allows you to set a color that all descendants inherit. You can also choose "None", if a parent has a WHACKY BACKGROUND that you refuse to put up with. Test Plan: {F1114588} {F1114589} Reviewers: chad Reviewed By: chad Differential Revision: https://secure.phabricator.com/D15279 --- resources/celerity/map.php | 4 +- src/__phutil_library_map__.php | 4 + .../PhabricatorProjectApplication.php | 2 + ...ricatorProjectWorkboardBackgroundColor.php | 124 +++++++++++++ ...icatorProjectBoardBackgroundController.php | 168 ++++++++++++++++++ ...habricatorProjectBoardManageController.php | 19 ++ .../PhabricatorProjectBoardViewController.php | 18 +- .../PhabricatorProjectTransactionEditor.php | 13 ++ .../project/storage/PhabricatorProject.php | 25 +++ .../storage/PhabricatorProjectTransaction.php | 8 + .../phui/workboards/phui-workboard-color.css | 6 + 11 files changed, 383 insertions(+), 8 deletions(-) create mode 100644 src/applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php create mode 100644 src/applications/project/controller/PhabricatorProjectBoardBackgroundController.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 086954ce50..856da367e1 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -155,7 +155,7 @@ return array( 'rsrc/css/phui/phui-tag-view.css' => '9d5d4400', 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', 'rsrc/css/phui/phui-two-column-view.css' => 'c75bfc5b', - 'rsrc/css/phui/workboards/phui-workboard-color.css' => '543432b9', + 'rsrc/css/phui/workboards/phui-workboard-color.css' => '2f068cc8', 'rsrc/css/phui/workboards/phui-workboard.css' => 'e6d89647', 'rsrc/css/phui/workboards/phui-workcard.css' => '3646fb96', 'rsrc/css/phui/workboards/phui-workpanel.css' => '92197373', @@ -842,7 +842,7 @@ return array( 'phui-theme-css' => 'ab7b848c', 'phui-timeline-view-css' => '2efceff8', 'phui-two-column-view-css' => 'c75bfc5b', - 'phui-workboard-color-css' => '543432b9', + 'phui-workboard-color-css' => '2f068cc8', 'phui-workboard-view-css' => 'e6d89647', 'phui-workcard-view-css' => '3646fb96', 'phui-workpanel-view-css' => '92197373', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index c9c52a9d8a..538ea56772 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2869,6 +2869,7 @@ phutil_register_library_map(array( 'PhabricatorProjectAddHeraldAction' => 'applications/project/herald/PhabricatorProjectAddHeraldAction.php', 'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php', 'PhabricatorProjectArchiveController' => 'applications/project/controller/PhabricatorProjectArchiveController.php', + 'PhabricatorProjectBoardBackgroundController' => 'applications/project/controller/PhabricatorProjectBoardBackgroundController.php', 'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php', 'PhabricatorProjectBoardDisableController' => 'applications/project/controller/PhabricatorProjectBoardDisableController.php', 'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php', @@ -2970,6 +2971,7 @@ phutil_register_library_map(array( 'PhabricatorProjectViewController' => 'applications/project/controller/PhabricatorProjectViewController.php', 'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php', 'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php', + 'PhabricatorProjectWorkboardBackgroundColor' => 'applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php', 'PhabricatorProjectWorkboardProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', @@ -7298,6 +7300,7 @@ phutil_register_library_map(array( 'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectApplication' => 'PhabricatorApplication', 'PhabricatorProjectArchiveController' => 'PhabricatorProjectController', + 'PhabricatorProjectBoardBackgroundController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardDisableController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController', @@ -7413,6 +7416,7 @@ phutil_register_library_map(array( 'PhabricatorProjectViewController' => 'PhabricatorProjectController', 'PhabricatorProjectWatchController' => 'PhabricatorProjectController', 'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView', + 'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject', 'PhabricatorProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index 86f050d281..41620ad4e4 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -86,6 +86,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { => 'PhabricatorProjectBoardDisableController', 'manage/' => 'PhabricatorProjectBoardManageController', + 'background/' + => 'PhabricatorProjectBoardBackgroundController', ), 'update/(?P[1-9]\d*)/(?P[^/]+)/' => 'PhabricatorProjectUpdateController', diff --git a/src/applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php b/src/applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php new file mode 100644 index 0000000000..a6c0fc9b1b --- /dev/null +++ b/src/applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php @@ -0,0 +1,124 @@ + '', + 'name' => pht('Use Parent Background (Default)'), + 'special' => 'parent', + 'icon' => 'fa-chevron-circle-up', + 'group' => 'basic', + ), + array( + 'key' => 'none', + 'name' => pht('No Background'), + 'special' => 'none', + 'icon' => 'fa-ban', + 'group' => 'basic', + ), + array( + 'key' => 'red', + 'name' => pht('Red'), + ), + array( + 'key' => 'orange', + 'name' => pht('Orange'), + ), + array( + 'key' => 'yellow', + 'name' => pht('Yellow'), + ), + array( + 'key' => 'green', + 'name' => pht('Green'), + ), + array( + 'key' => 'blue', + 'name' => pht('Blue'), + ), + array( + 'key' => 'indigo', + 'name' => pht('Indigo'), + ), + array( + 'key' => 'violet', + 'name' => pht('Violet'), + ), + array( + 'key' => 'sky', + 'name' => pht('Sky'), + ), + array( + 'key' => 'pink', + 'name' => pht('Pink'), + ), + array( + 'key' => 'fire', + 'name' => pht('Fire'), + ), + array( + 'key' => 'grey', + 'name' => pht('Grey'), + ), + array( + 'key' => 'gradient-red', + 'name' => pht('Ripe Peach'), + ), + array( + 'key' => 'gradient-orange', + 'name' => pht('Ripe Orange'), + ), + array( + 'key' => 'gradient-yellow', + 'name' => pht('Ripe Mango'), + ), + array( + 'key' => 'gradient-green', + 'name' => pht('Shallows'), + ), + array( + 'key' => 'gradient-blue', + 'name' => pht('Reef'), + ), + array( + 'key' => 'gradient-bluegrey', + 'name' => pht('Depths'), + ), + array( + 'key' => 'gradient-indigo', + 'name' => pht('This One Is Purple'), + ), + array( + 'key' => 'gradient-violet', + 'name' => pht('Unripe Plum'), + ), + array( + 'key' => 'gradient-sky', + 'name' => pht('Blue Sky'), + ), + array( + 'key' => 'gradient-pink', + 'name' => pht('Intensity'), + ), + array( + 'key' => 'gradient-grey', + 'name' => pht('Into The Expanse'), + ), + ); + + foreach ($options as $key => $option) { + if (empty($option['group'])) { + if (preg_match('/^gradient/', $option['key'])) { + $option['group'] = 'gradient'; + } else { + $option['group'] = 'solid'; + } + } + $options[$key] = $option; + } + + return ipull($options, null, 'key'); + } +} diff --git a/src/applications/project/controller/PhabricatorProjectBoardBackgroundController.php b/src/applications/project/controller/PhabricatorProjectBoardBackgroundController.php new file mode 100644 index 0000000000..3ba1f03a56 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectBoardBackgroundController.php @@ -0,0 +1,168 @@ +getUser(); + $board_id = $request->getURIData('projectID'); + + $board = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withIDs(array($board_id)) + ->needImages(true) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$board) { + return new Aphront404Response(); + } + + if (!$board->getHasWorkboard()) { + return new Aphront404Response(); + } + + $this->setProject($board); + $id = $board->getID(); + + $manage_uri = $this->getApplicationURI("board/{$id}/manage/"); + + if ($request->isFormPost()) { + $background_key = $request->getStr('backgroundKey'); + + $xactions = array(); + + $xactions[] = id(new PhabricatorProjectTransaction()) + ->setTransactionType(PhabricatorProjectTransaction::TYPE_BACKGROUND) + ->setNewValue($background_key); + + id(new PhabricatorProjectTransactionEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->applyTransactions($board, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($manage_uri); + } + + $nav = $this->getProfileMenu(); + + $crumbs = id($this->buildApplicationCrumbs()) + ->addTextCrumb(pht('Workboard'), "/project/board/{$board_id}/") + ->addTextCrumb(pht('Manage'), $manage_uri) + ->addTextCrumb(pht('Background Color')); + + $form = id(new AphrontFormView()) + ->setUser($viewer); + + $group_info = array( + 'basic' => array( + 'label' => pht('Basics'), + ), + 'solid' => array( + 'label' => pht('Solid Colors'), + ), + 'gradient' => array( + 'label' => pht('Gradients'), + ), + ); + + $groups = array(); + $options = PhabricatorProjectWorkboardBackgroundColor::getOptions(); + $option_groups = igroup($options, 'group'); + + require_celerity_resource('people-profile-css'); + require_celerity_resource('phui-workboard-color-css'); + Javelin::initBehavior('phabricator-tooltips', array()); + + foreach ($group_info as $group_key => $spec) { + $buttons = array(); + + $available_options = idx($option_groups, $group_key, array()); + foreach ($available_options as $option) { + $buttons[] = $this->renderOptionButton($option); + } + + $form->appendControl( + id(new AphrontFormMarkupControl()) + ->setLabel($spec['label']) + ->setValue($buttons)); + } + + // NOTE: Each button is its own form, so we can't wrap them in a normal + // form. + $layout_view = $form->buildLayoutView(); + + $form_box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Edit Background Color')) + ->appendChild($layout_view); + + return $this->newPage() + ->setTitle( + array( + pht('Edit Background Color'), + $board->getDisplayName(), + )) + ->setCrumbs($crumbs) + ->setNavigation($nav) + ->appendChild($form_box); + } + + private function renderOptionButton(array $option) { + $viewer = $this->getViewer(); + + $icon = idx($option, 'icon'); + if ($icon) { + $preview_class = null; + $preview_content = id(new PHUIIconView()) + ->setIcon($icon, 'lightbluetext'); + } else { + $preview_class = 'phui-workboard-'.$option['key']; + $preview_content = null; + } + + $preview = phutil_tag( + 'div', + array( + 'class' => 'phui-workboard-color-preview '.$preview_class, + ), + $preview_content); + + $button = javelin_tag( + 'button', + array( + 'class' => 'grey profile-image-button', + 'sigil' => 'has-tooltip', + 'meta' => array( + 'tip' => $option['name'], + 'size' => 300, + ), + ), + $preview); + + $input = phutil_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => 'backgroundKey', + 'value' => $option['key'], + )); + + return phabricator_form( + $viewer, + array( + 'class' => 'profile-image-form', + 'method' => 'POST', + ), + array( + $button, + $input, + )); + } + +} diff --git a/src/applications/project/controller/PhabricatorProjectBoardManageController.php b/src/applications/project/controller/PhabricatorProjectBoardManageController.php index b21ea0cf46..db4dfe31be 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardManageController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardManageController.php @@ -96,6 +96,16 @@ final class PhabricatorProjectBoardManageController ->setDisabled(!$can_edit) ->setWorkflow(true)); + $background_uri = $this->getApplicationURI("board/{$id}/background/"); + + $actions->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-paint-brush') + ->setName(pht('Change Background Color')) + ->setHref($background_uri) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + $disable_uri = $this->getApplicationURI("board/{$id}/disable/"); $actions->addAction( @@ -117,6 +127,15 @@ final class PhabricatorProjectBoardManageController ->setUser($viewer) ->setObject($board); + $background = $board->getDisplayWorkboardBackgroundColor(); + if ($background !== null) { + $map = PhabricatorProjectWorkboardBackgroundColor::getOptions(); + $map = ipull($map, 'name'); + + $name = idx($map, $background, $background); + $properties->addProperty(pht('Background Color'), $name); + } + return $properties; } diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index 8bb58779dc..9bc024c123 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -431,12 +431,7 @@ final class PhabricatorProjectBoardViewController $crumbs->addAction($manage_menu); $crumbs->addAction($fullscreen); - // TODO: Wire to Workboard Preferences - // require_celerity_resource('phui-workboard-color-css'); - // ->addClass('phui-workboard-color') - // ->addClass('phui-workboard-bluegrey') - - return $this->newPage() + $page = $this->newPage() ->setTitle( array( $project->getDisplayName(), @@ -454,6 +449,17 @@ final class PhabricatorProjectBoardViewController array( $board_box, )); + + $background = $project->getDisplayWorkboardBackgroundColor(); + if ($background !== null) { + require_celerity_resource('phui-workboard-color-css'); + $background_color_class = "phui-workboard-{$background}"; + + $page->addClass('phui-workboard-color'); + $nav->addClass($background_color_class); + } + + return $page; } private function readRequestState() { diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php index b1aab1e417..aa8c0852ab 100644 --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -42,6 +42,7 @@ final class PhabricatorProjectTransactionEditor $types[] = PhabricatorProjectTransaction::TYPE_HASWORKBOARD; $types[] = PhabricatorProjectTransaction::TYPE_DEFAULT_SORT; $types[] = PhabricatorProjectTransaction::TYPE_DEFAULT_FILTER; + $types[] = PhabricatorProjectTransaction::TYPE_BACKGROUND; return $types; } @@ -77,6 +78,8 @@ final class PhabricatorProjectTransactionEditor return $object->getDefaultWorkboardSort(); case PhabricatorProjectTransaction::TYPE_DEFAULT_FILTER: return $object->getDefaultWorkboardFilter(); + case PhabricatorProjectTransaction::TYPE_BACKGROUND: + return $object->getWorkboardBackgroundColor(); } return parent::getCustomTransactionOldValue($object, $xaction); @@ -100,6 +103,12 @@ final class PhabricatorProjectTransactionEditor return $xaction->getNewValue(); case PhabricatorProjectTransaction::TYPE_HASWORKBOARD: return (int)$xaction->getNewValue(); + case PhabricatorProjectTransaction::TYPE_BACKGROUND: + $value = $xaction->getNewValue(); + if (!strlen($value)) { + return null; + } + return $value; case PhabricatorProjectTransaction::TYPE_SLUGS: return $this->normalizeSlugs($xaction->getNewValue()); } @@ -153,6 +162,9 @@ final class PhabricatorProjectTransactionEditor case PhabricatorProjectTransaction::TYPE_DEFAULT_FILTER: $object->setDefaultWorkboardFilter($xaction->getNewValue()); return; + case PhabricatorProjectTransaction::TYPE_BACKGROUND: + $object->setWorkboardBackgroundColor($xaction->getNewValue()); + return; } return parent::applyCustomInternalTransaction($object, $xaction); @@ -198,6 +210,7 @@ final class PhabricatorProjectTransactionEditor case PhabricatorProjectTransaction::TYPE_HASWORKBOARD: case PhabricatorProjectTransaction::TYPE_DEFAULT_SORT: case PhabricatorProjectTransaction::TYPE_DEFAULT_FILTER: + case PhabricatorProjectTransaction::TYPE_BACKGROUND: return; } diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 861fac646b..81a5c09dc9 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -579,6 +579,31 @@ final class PhabricatorProject extends PhabricatorProjectDAO return $this->setProperty('workboard.filter.default', $filter); } + public function getWorkboardBackgroundColor() { + return $this->getProperty('workboard.background'); + } + + public function setWorkboardBackgroundColor($color) { + return $this->setProperty('workboard.background', $color); + } + + public function getDisplayWorkboardBackgroundColor() { + $color = $this->getWorkboardBackgroundColor(); + + if ($color === null) { + $parent = $this->getParentProject(); + if ($parent) { + return $parent->getDisplayWorkboardBackgroundColor(); + } + } + + if ($color === 'none') { + $color = null; + } + + return $color; + } + /* -( PhabricatorCustomFieldInterface )------------------------------------ */ diff --git a/src/applications/project/storage/PhabricatorProjectTransaction.php b/src/applications/project/storage/PhabricatorProjectTransaction.php index e812952630..ef5d39b4e8 100644 --- a/src/applications/project/storage/PhabricatorProjectTransaction.php +++ b/src/applications/project/storage/PhabricatorProjectTransaction.php @@ -15,6 +15,7 @@ final class PhabricatorProjectTransaction const TYPE_HASWORKBOARD = 'project:hasworkboard'; const TYPE_DEFAULT_SORT = 'project:sort'; const TYPE_DEFAULT_FILTER = 'project:filter'; + const TYPE_BACKGROUND = 'project:background'; // NOTE: This is deprecated, members are just a normal edge now. const TYPE_MEMBERS = 'project:members'; @@ -73,6 +74,7 @@ final class PhabricatorProjectTransaction case self::TYPE_HASWORKBOARD: case self::TYPE_DEFAULT_SORT: case self::TYPE_DEFAULT_FILTER: + case self::TYPE_BACKGROUND: return true; } @@ -84,6 +86,7 @@ final class PhabricatorProjectTransaction case self::TYPE_HASWORKBOARD: case self::TYPE_DEFAULT_SORT: case self::TYPE_DEFAULT_FILTER: + case self::TYPE_BACKGROUND: return true; } @@ -291,6 +294,11 @@ final class PhabricatorProjectTransaction return pht( '%s changed the default filter for the project workboard.', $author_handle); + + case self::TYPE_BACKGROUND: + return pht( + '%s changed the background color of the project workboard.', + $author_handle); } return parent::getTitle(); diff --git a/webroot/rsrc/css/phui/workboards/phui-workboard-color.css b/webroot/rsrc/css/phui/workboards/phui-workboard-color.css index 280f79782c..8d5584d903 100644 --- a/webroot/rsrc/css/phui/workboards/phui-workboard-color.css +++ b/webroot/rsrc/css/phui/workboards/phui-workboard-color.css @@ -30,6 +30,12 @@ background-color: rgba(255,255,255,.6); } +.phui-workboard-color-preview { + width: 50px; + height: 50px; + font-size: 34px; +} + /* Gradients */ .phui-workboard-gradient-red {