diff --git a/src/applications/differential/controller/DifferentialRevisionListController.php b/src/applications/differential/controller/DifferentialRevisionListController.php index ad1be4bf00..e54143a466 100644 --- a/src/applications/differential/controller/DifferentialRevisionListController.php +++ b/src/applications/differential/controller/DifferentialRevisionListController.php @@ -1,520 +1,495 @@ allowsAnonymousAccess(); } public function willProcessRequest(array $data) { $this->filter = idx($data, 'filter'); $this->username = idx($data, 'username'); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $viewer_is_anonymous = !$user->isLoggedIn(); $params = array_filter( array( 'status' => $request->getStr('status'), 'order' => $request->getStr('order'), )); $params['participants'] = $request->getArr('participants'); $default_filter = ($viewer_is_anonymous ? 'all' : 'active'); $filters = $this->getFilters(); $this->filter = $this->selectFilter( $filters, $this->filter, $default_filter); // Redirect from search to canonical URL. $phid_arr = $request->getArr('view_users'); if ($phid_arr) { $view_users = id(new PhabricatorUser()) ->loadAllWhere('phid IN (%Ls)', $phid_arr); if (count($view_users) == 1) { // This is a single user, so generate a pretty URI. $uri = new PhutilURI( '/differential/filter/'.$this->filter.'/'. phutil_escape_uri(reset($view_users)->getUserName()).'/'); $uri->setQueryParams($params); return id(new AphrontRedirectResponse())->setURI($uri); } } $uri = new PhutilURI('/differential/filter/'.$this->filter.'/'); $uri->setQueryParams($params); $username = ''; if ($this->username) { $view_user = id(new PhabricatorUser()) ->loadOneWhere('userName = %s', $this->username); if (!$view_user) { return new Aphront404Response(); } $username = phutil_escape_uri($this->username).'/'; $uri->setPath('/differential/filter/'.$this->filter.'/'.$username); $params['view_users'] = array($view_user->getPHID()); } else { $phids = $request->getArr('view_users'); if ($phids) { $params['view_users'] = $phids; $uri->setQueryParams($params); } } // Fill in the defaults we'll actually use for calculations if any // parameters are missing. $params += array( 'view_users' => array($user->getPHID()), 'status' => 'all', 'order' => 'modified', ); $side_nav = new AphrontSideNavFilterView(); $side_nav->setBaseURI(id(clone $uri)->setPath('/differential/filter/')); foreach ($filters as $filter) { list($filter_name, $display_name) = $filter; if ($filter_name) { $side_nav->addFilter($filter_name.'/'.$username, $display_name); } else { $side_nav->addLabel($display_name); } } $side_nav->selectFilter($this->filter.'/'.$username, null); $panels = array(); $handles = array(); $controls = $this->getFilterControls($this->filter); if ($this->getFilterRequiresUser($this->filter) && !$params['view_users']) { // In the anonymous case, we still want to let you see some user's // list, but we don't have a default PHID to provide (normally, we use // the viewing user's). Show a warning instead. $warning = new AphrontErrorView(); $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->setTitle(pht('User Required')); $warning->appendChild( pht('This filter requires that a user be specified above.')); $panels[] = $warning; } else { $query = $this->buildQuery($this->filter, $params); $pager = null; if ($this->getFilterAllowsPaging($this->filter)) { $pager = new AphrontPagerView(); $pager->setOffset($request->getInt('page')); $pager->setPageSize(1000); $pager->setURI($uri, 'page'); $query->setOffset($pager->getOffset()); $query->setLimit($pager->getPageSize() + 1); } foreach ($controls as $control) { $this->applyControlToQuery($control, $query, $params); } $revisions = $query->execute(); if ($pager) { $revisions = $pager->sliceResults($revisions); } $views = $this->buildViews( $this->filter, $params['view_users'], $revisions); $view_objects = array(); foreach ($views as $view) { if (empty($view['special'])) { $view_objects[] = $view['view']; } } $phids = mpull($view_objects, 'getRequiredHandlePHIDs'); $phids[] = $params['view_users']; $phids = array_mergev($phids); $handles = $this->loadViewerHandles($phids); foreach ($views as $view) { - if (empty($view['special'])) { - $view['view']->setHandles($handles); - } + $view['view']->setHandles($handles); $panel = new AphrontPanelView(); $panel->setHeader($view['title']); $panel->appendChild($view['view']); if ($pager) { $panel->appendChild($pager); } $panel->setNoBackground(); $panels[] = $panel; } } $filter_form = id(new AphrontFormView()) ->setMethod('GET') ->setNoShading(true) ->setAction('/differential/filter/'.$this->filter.'/') ->setUser($user); foreach ($controls as $control) { $control_view = $this->renderControl($control, $handles, $uri, $params); $filter_form->appendChild($control_view); } $filter_form ->addHiddenInput('status', $params['status']) ->addHiddenInput('order', $params['order']) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Filter Revisions'))); $filter_view = new AphrontListFilterView(); $filter_view->appendChild($filter_form); $side_nav->appendChild($filter_view); foreach ($panels as $panel) { $side_nav->appendChild($panel); } $crumbs = $this->buildApplicationCrumbs(); $name = $side_nav ->getMenu() ->getItem($side_nav->getSelectedFilter()) ->getName(); $crumbs->addCrumb( id(new PhabricatorCrumbView()) ->setName($name) ->setHref($request->getRequestURI())); $side_nav->setCrumbs($crumbs); return $this->buildApplicationPage( $side_nav, array( 'title' => pht('Differential Home'), 'dust' => true, )); } private function getFilters() { return array( array(null, pht('User Revisions')), array('active', pht('Active')), array('revisions', pht('Revisions')), array('reviews', pht('Reviews')), array('subscribed', pht('Subscribed')), array('drafts', pht('Draft Reviews')), array(null, pht('All Revisions')), array('all', pht('All')), ); } private function selectFilter( array $filters, $requested_filter, $default_filter) { // If the user requested a filter, make sure it actually exists. if ($requested_filter) { foreach ($filters as $filter) { if ($filter[0] === $requested_filter) { return $requested_filter; } } } // If not, return the default filter. return $default_filter; } private function getFilterRequiresUser($filter) { static $requires = array( 'active' => true, 'revisions' => true, 'reviews' => true, 'subscribed' => true, 'drafts' => true, 'all' => false, ); if (!isset($requires[$filter])) { throw new Exception("Unknown filter '{$filter}'!"); } return $requires[$filter]; } private function getFilterAllowsPaging($filter) { static $allows = array( 'active' => false, 'revisions' => true, 'reviews' => true, 'subscribed' => true, 'drafts' => true, 'all' => true, ); if (!isset($allows[$filter])) { throw new Exception("Unknown filter '{$filter}'!"); } return $allows[$filter]; } private function getFilterControls($filter) { static $controls = array( 'active' => array('phid'), 'revisions' => array('phid', 'participants', 'status', 'order'), 'reviews' => array('phid', 'participants', 'status', 'order'), 'subscribed' => array('subscriber', 'status', 'order'), 'drafts' => array('phid', 'status', 'order'), 'all' => array('status', 'order'), ); if (!isset($controls[$filter])) { throw new Exception("Unknown filter '{$filter}'!"); } return $controls[$filter]; } private function buildQuery($filter, array $params) { $user_phids = $params['view_users']; $query = new DifferentialRevisionQuery(); $query->needRelationships(true); switch ($filter) { case 'active': $query->withResponsibleUsers($user_phids); $query->withStatus(DifferentialRevisionQuery::STATUS_OPEN); $query->setLimit(null); break; case 'revisions': $query->withAuthors($user_phids); $query->withReviewers($params['participants']); break; case 'reviews': $query->withReviewers($user_phids); $query->withAuthors($params['participants']); break; case 'subscribed': $query->withSubscribers($user_phids); break; case 'drafts': $query->withDraftRepliesByAuthors($user_phids); break; case 'all': break; default: throw new Exception("Unknown filter '{$filter}'!"); } return $query; } private function renderControl( $control, array $handles, PhutilURI $uri, array $params) { assert_instances_of($handles, 'PhabricatorObjectHandle'); switch ($control) { case 'subscriber': case 'phid': $value = mpull( array_select_keys($handles, $params['view_users']), 'getFullName'); if ($control == 'subscriber') { $source = '/typeahead/common/allmailable/'; $label = pht('View Subscribers'); } else { $source = '/typeahead/common/accounts/'; switch ($this->filter) { case 'revisions': $label = pht('Authors'); break; case 'reviews': $label = pht('Reviewers'); break; default: $label = pht('View Users'); break; } } return id(new AphrontFormTokenizerControl()) ->setDatasource($source) ->setLabel($label) ->setName('view_users') ->setValue($value); case 'participants': switch ($this->filter) { case 'revisions': $label = pht('Reviewers'); break; case 'reviews': $label = pht('Authors'); break; } $value = mpull( array_select_keys($handles, $params['participants']), 'getFullName'); return id(new AphrontFormTokenizerControl()) ->setDatasource('/typeahead/common/accounts/') ->setLabel($label) ->setName('participants') ->setValue($value); case 'status': return id(new AphrontFormToggleButtonsControl()) ->setLabel(pht('Status')) ->setValue($params['status']) ->setBaseURI($uri, 'status') ->setButtons( array( 'all' => pht('All'), 'open' => pht('Open'), 'closed' => pht('Closed'), 'abandoned' => pht('Abandoned'), )); case 'order': return id(new AphrontFormToggleButtonsControl()) ->setLabel(pht('Order')) ->setValue($params['order']) ->setBaseURI($uri, 'order') ->setButtons( array( 'modified' => pht('Updated'), 'created' => pht('Created'), )); default: throw new Exception("Unknown control '{$control}'!"); } } private function applyControlToQuery($control, $query, array $params) { switch ($control) { case 'phid': case 'subscriber': case 'participants': // Already applied by query construction. break; case 'status': if ($params['status'] == 'open') { $query->withStatus(DifferentialRevisionQuery::STATUS_OPEN); } else if ($params['status'] == 'closed') { $query->withStatus(DifferentialRevisionQuery::STATUS_CLOSED); } else if ($params['status'] == 'abandoned') { $query->withStatus(DifferentialRevisionQuery::STATUS_ABANDONED); } break; case 'order': if ($params['order'] == 'created') { $query->setOrder(DifferentialRevisionQuery::ORDER_CREATED); } break; default: throw new Exception("Unknown control '{$control}'!"); } } private function buildViews($filter, array $user_phids, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $user = $this->getRequest()->getUser(); $template = id(new DifferentialRevisionListView()) ->setUser($user) ->setFields(DifferentialRevisionListView::getDefaultFields($user)); $views = array(); switch ($filter) { case 'active': list($blocking, $active, $waiting) = DifferentialRevisionQuery::splitResponsible( $revisions, $user_phids); $view = id(clone $template) ->setHighlightAge(true) ->setRevisions($blocking) ->loadAssets(); $views[] = array( 'title' => pht('Blocking Others'), 'view' => $view, ); $view = id(clone $template) ->setHighlightAge(true) ->setRevisions($active) ->loadAssets(); $views[] = array( 'title' => pht('Action Required'), 'view' => $view, ); - // Flags are sort of private, so only show the flag panel if you're - // looking at your own requests. - if (in_array($user->getPHID(), $user_phids)) { - $flags = id(new PhabricatorFlagQuery()) - ->setViewer($user) - ->withOwnerPHIDs(array($user->getPHID())) - ->withTypes(array(PhabricatorPHIDConstants::PHID_TYPE_DREV)) - ->needHandles(true) - ->execute(); - - if ($flags) { - $view = id(new PhabricatorFlagListView()) - ->setFlags($flags) - ->setUser($user); - - $views[] = array( - 'title' => pht('Flagged Revisions'), - 'view' => $view, - 'special' => true, - ); - } - } - $view = id(clone $template) ->setRevisions($waiting) ->loadAssets(); $views[] = array( 'title' => pht('Waiting On Others'), 'view' => $view, ); break; case 'revisions': case 'reviews': case 'subscribed': case 'drafts': case 'all': $titles = array( 'revisions' => pht('Revisions by Author'), 'reviews' => pht('Revisions by Reviewer'), 'subscribed' => pht('Revisions by Subscriber'), 'all' => pht('Revisions'), ); $view = id(clone $template) ->setRevisions($revisions) ->loadAssets(); $views[] = array( 'title' => idx($titles, $filter), 'view' => $view, ); break; default: throw new Exception("Unknown filter '{$filter}'!"); } return $views; } } diff --git a/src/applications/flag/controller/PhabricatorFlagEditController.php b/src/applications/flag/controller/PhabricatorFlagEditController.php index 69968ba678..ff8c356da7 100644 --- a/src/applications/flag/controller/PhabricatorFlagEditController.php +++ b/src/applications/flag/controller/PhabricatorFlagEditController.php @@ -1,90 +1,90 @@ phid = $data['phid']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $phid = $this->phid; $handle = PhabricatorObjectHandleData::loadOneHandle($phid, $user); if (!$handle->isComplete()) { return new Aphront404Response(); } $flag = PhabricatorFlagQuery::loadUserFlag($user, $phid); if (!$flag) { $flag = new PhabricatorFlag(); $flag->setOwnerPHID($user->getPHID()); $flag->setType($handle->getType()); $flag->setObjectPHID($handle->getPHID()); $flag->setReasonPHID($user->getPHID()); } if ($request->isDialogFormPost()) { $flag->setColor($request->getInt('color')); $flag->setNote($request->getStr('note')); $flag->save(); return id(new AphrontReloadResponse())->setURI('/flag/'); } $type_name = $handle->getTypeName(); $dialog = new AphrontDialogView(); $dialog->setUser($user); $dialog->setTitle(pht("Flag %s", $type_name)); require_celerity_resource('phabricator-flag-css'); $form = new AphrontFormLayoutView(); $is_new = !$flag->getID(); if ($is_new) { $form ->appendChild(hsprintf( "

%s


", - pht('You can flag this %s if you want to remember to look ". - "at it later.', + pht('You can flag this %s if you want to remember to look '. + 'at it later.', $type_name))); } $radio = new AphrontFormRadioButtonControl(); foreach (PhabricatorFlagColor::getColorNameMap() as $color => $text) { $class = 'phabricator-flag-radio phabricator-flag-color-'.$color; $radio->addButton($color, $text, '', $class); } $form ->appendChild( $radio ->setName('color') ->setLabel(pht('Flag Color')) ->setValue($flag->getColor())) ->appendChild( id(new AphrontFormTextAreaControl()) ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) ->setName('note') ->setLabel(pht('Note')) ->setValue($flag->getNote())); $dialog->appendChild($form); $dialog->addCancelButton($handle->getURI()); $dialog->addSubmitButton( $is_new ? pht("Flag %s") : pht('Save')); return id(new AphrontDialogResponse())->setDialog($dialog); } } diff --git a/src/applications/flag/controller/PhabricatorFlagListController.php b/src/applications/flag/controller/PhabricatorFlagListController.php index f4ebca574f..9b43507f92 100644 --- a/src/applications/flag/controller/PhabricatorFlagListController.php +++ b/src/applications/flag/controller/PhabricatorFlagListController.php @@ -1,40 +1,74 @@ getRequest(); $user = $request->getUser(); $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI('/flag/view/')); - $nav->addLabel(pht('Flags')); - $nav->addFilter('all', pht('Your Flags')); - $nav->selectFilter('all', 'all'); + + $filter_form = new AphrontFormView(); + $filter_form->setUser($user); + $filter_form->appendChild( + id(new AphrontFormToggleButtonsControl()) + ->setName('o') + ->setLabel(pht('Sort Order')) + ->setBaseURI($request->getRequestURI(), 'o') + ->setValue($request->getStr('o', 'n')) + ->setButtons( + array( + 'n' => pht('Date'), + 'c' => pht('Color'), + 'o' => pht('Object Type'), + 'r' => pht('Reason'), + ))); + + $filter = new AphrontListFilterView(); + $filter->appendChild($filter_form); $query = new PhabricatorFlagQuery(); $query->withOwnerPHIDs(array($user->getPHID())); $query->setViewer($user); $query->needHandles(true); + switch ($request->getStr('o', 'n')) { + case 'n': + $order = PhabricatorFlagQuery::ORDER_ID; + break; + case 'c': + $order = PhabricatorFlagQuery::ORDER_COLOR; + break; + case 'o': + $order = PhabricatorFlagQuery::ORDER_OBJECT; + break; + case 'r': + $order = PhabricatorFlagQuery::ORDER_REASON; + break; + default: + throw new Exception("Unknown order!"); + } + $query->withOrder($order); + $flags = $query->execute(); $view = new PhabricatorFlagListView(); $view->setFlags($flags); $view->setUser($user); - $panel = new AphrontPanelView(); - $panel->setHeader(pht('Flags')); - $panel->appendChild($view); - $panel->setNoBackground(); + $header = new PhabricatorHeaderView(); + $header->setHeader(pht('Flags')); - $nav->appendChild($panel); + $nav->appendChild($header); + $nav->appendChild($filter); + $nav->appendChild($view); - return $this->buildStandardPageResponse( + return $this->buildApplicationPage( $nav, array( 'title' => pht('Flags'), + 'dust' => true, )); } } diff --git a/src/applications/flag/query/PhabricatorFlagQuery.php b/src/applications/flag/query/PhabricatorFlagQuery.php index 8ee7b33753..20fb19e416 100644 --- a/src/applications/flag/query/PhabricatorFlagQuery.php +++ b/src/applications/flag/query/PhabricatorFlagQuery.php @@ -1,161 +1,194 @@ viewer = $viewer; return $this; } public function withOwnerPHIDs(array $owner_phids) { $this->ownerPHIDs = $owner_phids; return $this; } public function withTypes(array $types) { $this->types = $types; return $this; } public function withObjectPHIDs(array $object_phids) { $this->objectPHIDs = $object_phids; return $this; } + public function withOrder($order) { + $this->order = $order; + return $this; + } + public function needHandles($need) { $this->needHandles = $need; return $this; } public function needObjects($need) { $this->needObjects = $need; return $this; } public function setLimit($limit) { $this->limit = $limit; return $this; } public function setOffset($offset) { $this->offset = $offset; return $this; } public static function loadUserFlag(PhabricatorUser $user, $object_phid) { // Specifying the type in the query allows us to use a key. return id(new PhabricatorFlag())->loadOneWhere( 'ownerPHID = %s AND type = %s AND objectPHID = %s', $user->getPHID(), phid_get_type($object_phid), $object_phid); } public function execute() { $table = new PhabricatorFlag(); $conn_r = $table->establishConnection('r'); $where = $this->buildWhereClause($conn_r); $limit = $this->buildLimitClause($conn_r); $order = $this->buildOrderClause($conn_r); $data = queryfx_all( $conn_r, 'SELECT * FROM %T flag %Q %Q %Q', $table->getTableName(), $where, $order, $limit); $flags = $table->loadAllFromArray($data); if ($this->needHandles || $this->needObjects) { $phids = ipull($data, 'objectPHID'); $query = new PhabricatorObjectHandleData($phids); $query->setViewer($this->viewer); if ($this->needHandles) { $handles = $query->loadHandles(); foreach ($flags as $flag) { $handle = idx($handles, $flag->getObjectPHID()); if ($handle) { $flag->attachHandle($handle); } } } if ($this->needObjects) { $objects = $query->loadObjects(); foreach ($flags as $flag) { $object = idx($objects, $flag->getObjectPHID()); if ($object) { $flag->attachObject($object); } } } } return $flags; } private function buildWhereClause($conn_r) { $where = array(); if ($this->ownerPHIDs) { $where[] = qsprintf( $conn_r, 'flag.ownerPHID IN (%Ls)', $this->ownerPHIDs); } if ($this->types) { $where[] = qsprintf( $conn_r, 'flag.type IN (%Ls)', $this->types); } if ($this->objectPHIDs) { $where[] = qsprintf( $conn_r, 'flag.objectPHID IN (%Ls)', $this->objectPHIDs); } if ($where) { return 'WHERE ('.implode(') AND (', $where).')'; } else { return ''; } } private function buildOrderClause($conn_r) { - return 'ORDER BY id DESC'; + return qsprintf($conn_r, + 'ORDER BY %Q', + $this->getOrderColumn($conn_r)); + } + + private function getOrderColumn($conn_r) { + switch ($this->order) { + case self::ORDER_ID: + return 'id DESC'; + break; + case self::ORDER_COLOR: + return 'color DESC'; + break; + case self::ORDER_OBJECT: + return 'type ASC'; + break; + case self::ORDER_REASON: + return 'reasonPHID DESC'; + break; + default: + throw new Exception("Unknown order {$this->order}!"); + break; + } } private function buildLimitClause($conn_r) { if ($this->limit && $this->offset) { return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, $this->limit); } else if ($this->limit) { return qsprintf($conn_r, 'LIMIT %d', $this->limit); } else if ($this->offset) { return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, PHP_INT_MAX); } else { return ''; } } } diff --git a/src/applications/flag/view/PhabricatorFlagListView.php b/src/applications/flag/view/PhabricatorFlagListView.php index 9e43887216..1ee5b2ed48 100644 --- a/src/applications/flag/view/PhabricatorFlagListView.php +++ b/src/applications/flag/view/PhabricatorFlagListView.php @@ -1,84 +1,74 @@ flags = $flags; return $this; } + public function setFlush($flush) { + $this->flush = $flush; + return $this; + } + public function render() { $user = $this->user; require_celerity_resource('phabricator-flag-css'); + $list = new PhabricatorObjectItemListView(); + $list->setCards(true); + $list->setNoDataString(pht('No flags.')); + $list->setFlush($this->flush); + $rows = array(); foreach ($this->flags as $flag) { $class = PhabricatorFlagColor::getCSSClass($flag->getColor()); - $rows[] = array( - phutil_tag( - 'div', - array( - 'class' => 'phabricator-flag-icon '.$class, - ), - ''), - $flag->getHandle()->renderLink(), - $flag->getNote(), - phabricator_datetime($flag->getDateCreated(), $user), - phabricator_form( - $user, - array( - 'method' => 'POST', - 'action' => '/flag/edit/'.$flag->getObjectPHID().'/', - 'sigil' => 'workflow', - ), - phutil_tag( - 'button', - array( - 'class' => 'small grey', - ), - pht('Edit Flag'))), - phabricator_form( - $user, - array( - 'method' => 'POST', - 'action' => '/flag/delete/'.$flag->getID().'/', - 'sigil' => 'workflow', - ), - phutil_tag( - 'button', - array( - 'class' => 'small grey', - ), - pht('Remove Flag'))), - ); + $flag_icon = phutil_tag( + 'div', + array( + 'class' => 'phabricator-flag-icon '.$class, + ), + ''); + + $edit_link = javelin_tag( + 'a', + array( + 'href' => '/flag/edit/'.$flag->getObjectPHID().'/', + 'sigil' => 'workflow', + ), + pht('Edit')); + + $remove_link = javelin_tag( + 'a', + array( + 'href' => '/flag/delete/'.$flag->getID().'/', + 'sigil' => 'workflow', + ), + pht('Remove')); + + $item = new PhabricatorObjectItemView(); + $item->addIcon('edit', $edit_link); + $item->addIcon('delete', $remove_link); + + $item->setHeader(hsprintf('%s %s', + $flag_icon, $flag->getHandle()->renderLink())); + + $item->addAttribute(phabricator_datetime($flag->getDateCreated(), $user)); + + if ($flag->getNote()) { + $item->addAttribute($flag->getNote()); + } + + $list->addItem($item); } - $table = new AphrontTableView($rows); - $table->setHeaders( - array( - '', - pht('Flagged Object'), - pht('Note'), - pht('Flagged On'), - '', - '', - )); - $table->setColumnClasses( - array( - 'narrow', - 'wrap pri', - 'wrap', - 'narrow', - 'narrow action', - 'narrow action', - )); - $table->setNoDataString(pht('No flags.')); - - return $table->render(); + return $list; } } diff --git a/webroot/rsrc/css/application/flag/flag.css b/webroot/rsrc/css/application/flag/flag.css index 5ab0b12ea0..b5a1a8c17b 100644 --- a/webroot/rsrc/css/application/flag/flag.css +++ b/webroot/rsrc/css/application/flag/flag.css @@ -1,50 +1,57 @@ /** * @provides phabricator-flag-css */ .phabricator-flag-icon { padding: 8px; background: transparent 0 0 no-repeat; } +.phabricator-object-item .phabricator-flag-icon { + float: left; + margin: 2px; + margin-right: 8px; + margin-bottom: 0; +} + .phabricator-flag-radio { padding-left: 18px; margin: 1px; background: transparent 0 0 no-repeat; } .phabricator-flag-color-0 { background-image: url(/rsrc/image/icon/fatcow/flag_red.png); } .phabricator-flag-color-1 { background-image: url(/rsrc/image/icon/fatcow/flag_orange.png); } .phabricator-flag-color-2 { background-image: url(/rsrc/image/icon/fatcow/flag_yellow.png); } .phabricator-flag-color-3 { background-image: url(/rsrc/image/icon/fatcow/flag_green.png); } .phabricator-flag-color-4 { background-image: url(/rsrc/image/icon/fatcow/flag_blue.png); } .phabricator-flag-color-5 { background-image: url(/rsrc/image/icon/fatcow/flag_pink.png); } .phabricator-flag-color-6 { background-image: url(/rsrc/image/icon/fatcow/flag_purple.png); } .phabricator-flag-color-7 { background-image: url(/rsrc/image/icon/fatcow/flag_finish.png); } .phabricator-flag-ghost { background-image: url(/rsrc/image/icon/fatcow/flag_ghost.png); }