diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -38,6 +38,7 @@ 'rsrc/css/application/base/notification-menu.css' => '3c9d8aa1', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '16ca323f', 'rsrc/css/application/base/standard-page-view.css' => '61e68a55', + 'rsrc/css/application/calendar/calendar-icon.css' => '98ce946d', 'rsrc/css/application/chatlog/chatlog.css' => '852140ff', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', 'rsrc/css/application/config/config-options.css' => '7fedf08b', @@ -492,6 +493,7 @@ 'aphront-two-column-view-css' => '16ab3ad2', 'aphront-typeahead-control-css' => '0e403212', 'auth-css' => '44975d4b', + 'calendar-icon-css' => '98ce946d', 'changeset-view-manager' => '58562350', 'conduit-api-css' => '7bc725c4', 'config-options-css' => '7fedf08b', 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 @@ -1499,6 +1499,7 @@ 'PhabricatorCalendarEventCancelController' => 'applications/calendar/controller/PhabricatorCalendarEventCancelController.php', 'PhabricatorCalendarEventCommentController' => 'applications/calendar/controller/PhabricatorCalendarEventCommentController.php', 'PhabricatorCalendarEventEditController' => 'applications/calendar/controller/PhabricatorCalendarEventEditController.php', + 'PhabricatorCalendarEventEditIconController' => 'applications/calendar/controller/PhabricatorCalendarEventEditIconController.php', 'PhabricatorCalendarEventEditor' => 'applications/calendar/editor/PhabricatorCalendarEventEditor.php', 'PhabricatorCalendarEventEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventEmailCommand.php', 'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php', @@ -1517,6 +1518,7 @@ 'PhabricatorCalendarEventViewController' => 'applications/calendar/controller/PhabricatorCalendarEventViewController.php', 'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php', 'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php', + 'PhabricatorCalendarIcon' => 'applications/calendar/icon/PhabricatorCalendarIcon.php', 'PhabricatorCalendarRemarkupRule' => 'applications/calendar/remarkup/PhabricatorCalendarRemarkupRule.php', 'PhabricatorCalendarReplyHandler' => 'applications/calendar/mail/PhabricatorCalendarReplyHandler.php', 'PhabricatorCalendarSchemaSpec' => 'applications/calendar/storage/PhabricatorCalendarSchemaSpec.php', @@ -4860,6 +4862,7 @@ 'PhabricatorCalendarEventCancelController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventCommentController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController', + 'PhabricatorCalendarEventEditIconController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorCalendarEventEmailCommand' => 'MetaMTAEmailTransactionCommand', 'PhabricatorCalendarEventInvitee' => array( @@ -4881,6 +4884,7 @@ 'PhabricatorCalendarEventViewController' => 'PhabricatorCalendarController', 'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO', 'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase', + 'PhabricatorCalendarIcon' => 'Phobject', 'PhabricatorCalendarRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorCalendarReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorCalendarSchemaSpec' => 'PhabricatorConfigSchemaSpec', diff --git a/src/applications/calendar/application/PhabricatorCalendarApplication.php b/src/applications/calendar/application/PhabricatorCalendarApplication.php --- a/src/applications/calendar/application/PhabricatorCalendarApplication.php +++ b/src/applications/calendar/application/PhabricatorCalendarApplication.php @@ -45,6 +45,10 @@ '(?:query/(?P[^/]+)/(?:(?P\d+)/'. '(?P\d+)/)?(?:(?P\d+)/)?)?' => 'PhabricatorCalendarEventListController', + 'icon/(?P[1-9]\d*)/' + => 'PhabricatorCalendarEventEditIconController', + 'icon/' + => 'PhabricatorCalendarEventEditIconController', 'event/' => array( 'create/' => 'PhabricatorCalendarEventEditController', diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventEditIconController.php b/src/applications/calendar/controller/PhabricatorCalendarEventEditIconController.php new file mode 100644 --- /dev/null +++ b/src/applications/calendar/controller/PhabricatorCalendarEventEditIconController.php @@ -0,0 +1,102 @@ +id = idx($data, 'id'); + } + + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getUser(); + + if ($this->id) { + $event = id(new PhabricatorCalendarEventQuery()) + ->setViewer($viewer) + ->withIDs(array($this->id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$event) { + return new Aphront404Response(); + } + $cancel_uri = $this->getApplicationURI('/E'.$event->getID()); + $event_icon = $event->getIcon(); + } else { + $cancel_uri = '/calendar/'; + $event_icon = $request->getStr('value'); + } + + require_celerity_resource('calendar-icon-css'); + Javelin::initBehavior('phabricator-tooltips'); + + $calendar_icons = PhabricatorCalendarIcon::getIconMap(); + + if ($request->isFormPost()) { + $v_icon = $request->getStr('icon'); + + return id(new AphrontAjaxResponse())->setContent( + array( + 'value' => $v_icon, + 'display' => PhabricatorCalendarIcon::renderIconForChooser($v_icon), + )); + } + + $ii = 0; + $buttons = array(); + foreach ($calendar_icons as $icon => $label) { + $view = id(new PHUIIconView()) + ->setIconFont($icon); + + $aural = javelin_tag( + 'span', + array( + 'aural' => true, + ), + pht('Choose "%s" Icon', $label)); + + if ($icon == $event_icon) { + $class_extra = ' selected'; + } else { + $class_extra = null; + } + + $buttons[] = javelin_tag( + 'button', + array( + 'class' => 'icon-button'.$class_extra, + 'name' => 'icon', + 'value' => $icon, + 'type' => 'submit', + 'sigil' => 'has-tooltip', + 'meta' => array( + 'tip' => $label, + ), + ), + array( + $aural, + $view, + )); + if ((++$ii % 4) == 0) { + $buttons[] = phutil_tag('br'); + } + } + + $buttons = phutil_tag( + 'div', + array( + 'class' => 'icon-grid', + ), + $buttons); + + return $this->newDialog() + ->setTitle(pht('Choose Calendar Event Icon')) + ->appendChild($buttons) + ->addCancelButton($cancel_uri); + } +} diff --git a/src/applications/calendar/icon/PhabricatorCalendarIcon.php b/src/applications/calendar/icon/PhabricatorCalendarIcon.php new file mode 100644 --- /dev/null +++ b/src/applications/calendar/icon/PhabricatorCalendarIcon.php @@ -0,0 +1,49 @@ + 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 getLabel($key) { + $map = self::getIconMap(); + return $map[$key]; + } + + public static function getAPIName($key) { + return substr($key, 3); + } + + public static function renderIconForChooser($icon) { + $calendar_icons = self::getIconMap(); + + return phutil_tag( + 'span', + array(), + array( + id(new PHUIIconView())->setIconFont($icon), + ' ', + idx($calendar_icons, $icon, pht('Unknown Icon')), + )); + } + +} diff --git a/webroot/rsrc/css/application/calendar/calendar-icon.css b/webroot/rsrc/css/application/calendar/calendar-icon.css new file mode 100644 --- /dev/null +++ b/webroot/rsrc/css/application/calendar/calendar-icon.css @@ -0,0 +1,28 @@ +/** + * @provides calendar-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}; +}