diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,14 +7,14 @@ return array( 'names' => array( - 'core.pkg.css' => '3f0f5da2', + 'core.pkg.css' => 'ead20778', 'core.pkg.js' => '8c184823', 'darkconsole.pkg.js' => 'df001cab', 'differential.pkg.css' => '4a93db37', 'differential.pkg.js' => 'd1443567', 'diffusion.pkg.css' => '471bc9eb', 'diffusion.pkg.js' => 'bfc0737b', - 'maniphest.pkg.css' => 'f88a8402', + 'maniphest.pkg.css' => 'f5d89daf', 'maniphest.pkg.js' => 'df4aa49f', 'rsrc/css/aphront/aphront-bars.css' => '231ac33c', 'rsrc/css/aphront/context-bar.css' => '1c3b0529', @@ -95,7 +95,6 @@ 'rsrc/css/application/ponder/vote.css' => '8ed6ed8b', 'rsrc/css/application/profile/profile-view.css' => 'b459416e', 'rsrc/css/application/projects/project-icon.css' => 'c2ecb7f1', - 'rsrc/css/application/projects/project-tag.css' => '095c9404', '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', @@ -142,7 +141,7 @@ 'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => '2f562399', - 'rsrc/css/phui/phui-tag-view.css' => '8ac14ba8', + 'rsrc/css/phui/phui-tag-view.css' => '4f920464', 'rsrc/css/phui/phui-text.css' => '23e9b4b7', 'rsrc/css/phui/phui-timeline-view.css' => 'bbd990d0', 'rsrc/css/phui/phui-workboard-view.css' => '2bf82d00', @@ -731,7 +730,6 @@ 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => '41ed7994', 'phabricator-profile-css' => 'b459416e', - 'phabricator-project-tag-css' => '095c9404', 'phabricator-remarkup-css' => '864d4f5e', 'phabricator-search-results-css' => 'f240504c', 'phabricator-shaped-request' => '7cbe244b', @@ -787,7 +785,7 @@ 'phui-remarkup-preview-css' => '19ad512b', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => '2f562399', - 'phui-tag-view-css' => '8ac14ba8', + 'phui-tag-view-css' => '4f920464', 'phui-text-css' => '23e9b4b7', 'phui-timeline-view-css' => 'bbd990d0', 'phui-workboard-view-css' => '2bf82d00', @@ -2322,7 +2320,6 @@ 'maniphest.pkg.css' => array( 0 => 'maniphest-task-summary-css', - 1 => 'phabricator-project-tag-css', ), 'maniphest.pkg.js' => array( diff --git a/resources/celerity/packages.php b/resources/celerity/packages.php --- a/resources/celerity/packages.php +++ b/resources/celerity/packages.php @@ -174,7 +174,6 @@ ), 'maniphest.pkg.css' => array( 'maniphest-task-summary-css', - 'phabricator-project-tag-css', ), 'maniphest.pkg.js' => array( 'javelin-behavior-maniphest-batch-selector', 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 @@ -937,7 +937,6 @@ 'ManiphestTaskOwner' => 'applications/maniphest/constants/ManiphestTaskOwner.php', 'ManiphestTaskPriority' => 'applications/maniphest/constants/ManiphestTaskPriority.php', 'ManiphestTaskProject' => 'applications/maniphest/storage/ManiphestTaskProject.php', - 'ManiphestTaskProjectsView' => 'applications/maniphest/view/ManiphestTaskProjectsView.php', 'ManiphestTaskQuery' => 'applications/maniphest/query/ManiphestTaskQuery.php', 'ManiphestTaskResultListView' => 'applications/maniphest/view/ManiphestTaskResultListView.php', 'ManiphestTaskSearchEngine' => 'applications/maniphest/query/ManiphestTaskSearchEngine.php', @@ -1027,6 +1026,7 @@ 'PHUIFormLayoutView' => 'view/form/PHUIFormLayoutView.php', 'PHUIFormMultiSubmitControl' => 'view/form/control/PHUIFormMultiSubmitControl.php', 'PHUIFormPageView' => 'view/form/PHUIFormPageView.php', + 'PHUIHandleTagListView' => 'applications/phid/view/PHUIHandleTagListView.php', 'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php', 'PHUIIconExample' => 'applications/uiexample/examples/PHUIIconExample.php', 'PHUIIconView' => 'view/phui/PHUIIconView.php', @@ -3705,7 +3705,6 @@ 'ManiphestTaskOwner' => 'ManiphestConstants', 'ManiphestTaskPriority' => 'ManiphestConstants', 'ManiphestTaskProject' => 'ManiphestDAO', - 'ManiphestTaskProjectsView' => 'ManiphestView', 'ManiphestTaskQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ManiphestTaskResultListView' => 'ManiphestView', 'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine', @@ -3804,6 +3803,7 @@ 'PHUIFormLayoutView' => 'AphrontView', 'PHUIFormMultiSubmitControl' => 'AphrontFormControl', 'PHUIFormPageView' => 'AphrontView', + 'PHUIHandleTagListView' => 'AphrontTagView', 'PHUIHeaderView' => 'AphrontView', 'PHUIIconExample' => 'PhabricatorUIExample', 'PHUIIconView' => 'AphrontTagView', @@ -3829,7 +3829,7 @@ 'PHUIStatusItemView' => 'AphrontTagView', 'PHUIStatusListView' => 'AphrontTagView', 'PHUITagExample' => 'PhabricatorUIExample', - 'PHUITagView' => 'AphrontView', + 'PHUITagView' => 'AphrontTagView', 'PHUITextExample' => 'PhabricatorUIExample', 'PHUITextView' => 'AphrontTagView', 'PHUITimelineEventView' => 'AphrontView', diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php --- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php +++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php @@ -553,12 +553,11 @@ $column_groups = mgroup($columns, 'getProjectPHID'); - $project_rows = array(); + $project_handles = array(); + $project_annotations = array(); foreach ($project_phids as $project_phid) { - $row = array(); - $handle = $this->getHandle($project_phid); - $row[] = $handle->renderLink(); + $project_handles[] = $handle; $columns = idx($column_groups, $project_phid, array()); $column = head(array_intersect_key($columns, $in_column_phids)); @@ -572,12 +571,15 @@ ), $column_name); - $row[] = ' '; - $row[] = $column_link; + $project_annotations[$project_phid] = array( + ' ', + $column_link); } - - $project_rows[] = phutil_tag('div', array(), $row); } + + $project_rows = id(new PHUIHandleTagListView()) + ->setHandles($project_handles) + ->setAnnotations($project_annotations); } else { $project_rows = phutil_tag('em', array(), pht('None')); } diff --git a/src/applications/maniphest/view/ManiphestTaskListView.php b/src/applications/maniphest/view/ManiphestTaskListView.php --- a/src/applications/maniphest/view/ManiphestTaskListView.php +++ b/src/applications/maniphest/view/ManiphestTaskListView.php @@ -35,6 +35,8 @@ public function render() { $handles = $this->handles; + require_celerity_resource('maniphest-task-summary-css'); + $list = new PHUIObjectItemListView(); $list->setFlush(true); @@ -74,13 +76,15 @@ $item->addSigil('maniphest-task'); } - $projects_view = new ManiphestTaskProjectsView(); - $projects_view->setHandles( - array_select_keys( - $handles, - $task->getProjectPHIDs())); + $project_handles = array_select_keys( + $handles, + $task->getProjectPHIDs()); - $item->addAttribute($projects_view); + $item->addAttribute( + id(new PHUIHandleTagListView()) + ->setLimit(4) + ->setNoDataString(pht('No Projects')) + ->setHandles($project_handles)); $item->setMetadata( array( diff --git a/src/applications/maniphest/view/ManiphestTaskProjectsView.php b/src/applications/maniphest/view/ManiphestTaskProjectsView.php deleted file mode 100644 --- a/src/applications/maniphest/view/ManiphestTaskProjectsView.php +++ /dev/null @@ -1,67 +0,0 @@ -handles = $handles; - return $this; - } - - public function render() { - require_celerity_resource('phabricator-project-tag-css'); - $max_visible_tags = 4; - - $show = array_slice($this->handles, 0, $max_visible_tags); - - $tags = array(); - if ($show) { - foreach ($show as $handle) { - $tags[] = phutil_tag( - 'a', - array( - 'href' => $handle->getURI(), - 'class' => 'phabricator-project-tag', - ), - phutil_utf8_shorten($handle->getName(), 24)); - } - } else { - $tags[] = phutil_tag( - 'span', - array( - 'class' => 'phabricator-project-tag phabricator-project-tag-grey', - ), - pht('No Project')); - } - - if (count($this->handles) > $max_visible_tags) { - require_celerity_resource('aphront-tooltip-css'); - Javelin::initBehavior('phabricator-tooltips'); - - $all = array(); - foreach ($this->handles as $handle) { - $all[] = $handle->getName(); - } - - $tags[] = javelin_tag( - 'span', - array( - 'class' => 'phabricator-project-tag', - 'sigil' => 'has-tooltip', - 'meta' => array( - 'tip' => implode(', ', $all), - 'size' => 200, - ), - ), - "\xE2\x80\xA6"); - } - - return $tags; - } - -} diff --git a/src/applications/phid/PhabricatorObjectHandle.php b/src/applications/phid/PhabricatorObjectHandle.php --- a/src/applications/phid/PhabricatorObjectHandle.php +++ b/src/applications/phid/PhabricatorObjectHandle.php @@ -25,6 +25,10 @@ } public function getIcon() { + if ($this->getPolicyFiltered()) { + return 'fa-lock'; + } + if ($this->icon) { return $this->icon; } @@ -45,6 +49,10 @@ } public function getTagColor() { + if ($this->getPolicyFiltered()) { + return 'disabled'; + } + if ($this->tagColor) { return $this->tagColor; } diff --git a/src/applications/phid/view/PHUIHandleTagListView.php b/src/applications/phid/view/PHUIHandleTagListView.php new file mode 100644 --- /dev/null +++ b/src/applications/phid/view/PHUIHandleTagListView.php @@ -0,0 +1,100 @@ +handles = $handles; + return $this; + } + + public function setAnnotations(array $annotations) { + $this->annotations = $annotations; + return $this; + } + + public function setLimit($limit) { + $this->limit = $limit; + return $this; + } + + public function setNoDataString($no_data) { + $this->noDataString = $no_data; + return $this; + } + + protected function getTagName() { + return 'ul'; + } + + protected function getTagAttributes() { + return array( + 'class' => 'phabricator-handle-tag-list', + ); + } + + protected function getTagContent() { + $handles = $this->handles; + + // If the list is empty, we may render a "No Projects" tag. + if (!$handles) { + if (strlen($this->noDataString)) { + $no_data_tag = $this->newPlaceholderTag() + ->setName($this->noDataString); + return $this->newItem($no_data_tag); + } + } + + if ($this->limit) { + $handles = array_slice($handles, 0, $this->limit); + } + + $list = array(); + foreach ($handles as $handle) { + $list[] = $this->newItem( + array( + $handle->renderTag(), + idx($this->annotations, $handle->getPHID(), null), + )); + } + + if ($this->limit) { + if ($this->limit < count($this->handles)) { + $tip_text = implode(', ', mpull($this->handles, 'getName')); + + $more = $this->newPlaceholderTag() + ->setName("\xE2\x80\xA6") + ->addSigil('has-tooltip') + ->setMetadata( + array( + 'tip' => $tip_text, + 'size' => 200, + )); + + $list[] = $this->newItem($more); + } + } + + return $list; + } + + private function newItem($content) { + return phutil_tag( + 'li', + array( + 'class' => 'phabricator-handle-tag-list-item', + ), + $content); + } + + private function newPlaceholderTag() { + return id(new PHUITagView()) + ->setType(PHUITagView::TYPE_OBJECT) + ->setShade(PHUITagView::COLOR_DISABLED); + } + +} diff --git a/src/applications/project/events/PhabricatorProjectUIEventListener.php b/src/applications/project/events/PhabricatorProjectUIEventListener.php --- a/src/applications/project/events/PhabricatorProjectUIEventListener.php +++ b/src/applications/project/events/PhabricatorProjectUIEventListener.php @@ -43,21 +43,8 @@ } if ($handles) { - $list = array(); - foreach ($handles as $handle) { - $list[] = phutil_tag( - 'li', - array( - 'class' => 'phabricator-handle-tag-list-item', - ), - $handle->renderTag()); - } - $list = phutil_tag( - 'ul', - array( - 'class' => 'phabricator-handle-tag-list', - ), - $list); + $list = id(new PHUIHandleTagListView()) + ->setHandles($handles); } else { $list = phutil_tag('em', array(), pht('None')); } diff --git a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php --- a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php +++ b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php @@ -286,7 +286,7 @@ $repository->getProjectPHIDs()); if ($project_handles) { $item->addAttribute( - id(new ManiphestTaskProjectsView()) + id(new PHUIHandleTagListView()) ->setHandles($project_handles)); } diff --git a/src/view/phui/PHUITagView.php b/src/view/phui/PHUITagView.php --- a/src/view/phui/PHUITagView.php +++ b/src/view/phui/PHUITagView.php @@ -1,6 +1,6 @@ id = $id; - return $this; - } - - public function getID() { - return $this->id; - } - public function setType($type) { $this->type = $type; switch ($type) { @@ -100,22 +90,56 @@ return $this; } - public function render() { - if (!$this->type) { - throw new Exception(pht('You must call setType() before render()!')); - } + protected function getTagName() { + return strlen($this->href) ? 'a' : 'span'; + } + protected function getTagAttributes() { require_celerity_resource('phui-tag-view-css'); + $classes = array( 'phui-tag-view', 'phui-tag-type-'.$this->type, ); - $color = null; if ($this->shade) { $classes[] = 'phui-tag-shade'; - $classes[] = 'phui-tag-shade-'.$this->shade;; - } else if ($this->backgroundColor) { + $classes[] = 'phui-tag-shade-'.$this->shade; + } + + + if ($this->icon) { + $classes[] = 'phui-tag-icon-view'; + } + + if ($this->phid) { + Javelin::initBehavior('phabricator-hovercards'); + + $attributes = array( + 'href' => $this->href, + 'sigil' => 'hovercard', + 'meta' => array( + 'hoverPHID' => $this->phid, + ), + 'target' => $this->external ? '_blank' : null, + ); + } else { + $attributes = array( + 'href' => $this->href, + 'target' => $this->external ? '_blank' : null, + ); + } + + return $attributes + array('class' => $classes); + } + + public function getTagContent() { + if (!$this->type) { + throw new Exception(pht('You must call setType() before render()!')); + } + + $color = null; + if (!$this->shade && $this->backgroundColor) { $color = 'phui-tag-color-'.$this->backgroundColor; } @@ -134,7 +158,6 @@ if ($this->icon) { $icon = id(new PHUIIconView()) ->setIconFont($this->icon); - $classes[] = 'phui-tag-icon-view'; } else { $icon = null; } @@ -155,33 +178,7 @@ $content); } - if ($this->phid) { - Javelin::initBehavior('phabricator-hovercards'); - - return javelin_tag( - 'a', - array( - 'id' => $this->id, - 'href' => $this->href, - 'class' => implode(' ', $classes), - 'sigil' => 'hovercard', - 'meta' => array( - 'hoverPHID' => $this->phid, - ), - 'target' => $this->external ? '_blank' : null, - ), - array($icon, $content)); - } else { - return phutil_tag( - $this->href ? 'a' : 'span', - array( - 'id' => $this->id, - 'href' => $this->href, - 'class' => implode(' ', $classes), - 'target' => $this->external ? '_blank' : null, - ), - array($icon, $content)); - } + return array($icon, $content); } public static function getTagTypes() { diff --git a/webroot/rsrc/css/application/projects/project-tag.css b/webroot/rsrc/css/application/projects/project-tag.css deleted file mode 100644 --- a/webroot/rsrc/css/application/projects/project-tag.css +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @provides phabricator-project-tag-css - */ - -.phabricator-project-tag, -.phabricator-project-tag:link, -.phabricator-project-tag:visited { - font-weight: normal; - border: 1px solid #bfcfef; - padding: 1px 4px 2px; - background: #f9f9ff; - color: #667799; - text-decoration: none; - font-size: 11px; - display: inline; - cursor: pointer; - margin-right: 2px; - - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - - white-space: nowrap; -} - -.phabricator-project-tag.phabricator-project-tag-grey { - border: 1px solid #ccc; - background: #f7f7f7; - color: {$lightgreytext}; - cursor: default; -} - -.phabricator-project-tag.phabricator-project-tag-grey:hover { - background: #e7e7e7; -} - -.phabricator-project-tag:last-child { - margin-right: 0px; -} - -.phabricator-project-tag:hover { - background: #dfdfef; -} diff --git a/webroot/rsrc/css/phui/phui-tag-view.css b/webroot/rsrc/css/phui/phui-tag-view.css --- a/webroot/rsrc/css/phui/phui-tag-view.css +++ b/webroot/rsrc/css/phui/phui-tag-view.css @@ -304,3 +304,32 @@ .phabricator-handle-tag-list-item + .phabricator-handle-tag-list-item { margin-top: 4px; } + +.phui-object-item .phui-tag-view .phui-tag-core { + display: inline-block; + font-size: 12px; + line-height: 16px; +} + +.phui-object-item .phui-tag-icon-view .phui-tag-core { + padding-left: 20px; +} + +.phui-object-item .phui-tag-view .phui-icon-view { + font-size: 11px; + top: 3px; + left: 5px; +} + +.phui-object-item .phabricator-handle-tag-list { + display: inline-block; +} + +.phui-object-item .phabricator-handle-tag-list-item { + display: inline-block; +} + +.phui-object-item .phabricator-handle-tag-list-item + + .phabricator-handle-tag-list-item { + margin: 0 0 0 4px; +}