From 148a50e48be146b88036032d1cad772d2627da28 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Sat, 12 Mar 2016 13:02:32 -0800 Subject: [PATCH] Convert Differential to new layout Summary: First pass at converting Differential, I likely have some buggy-poos but thought I'd toss this up now in case very bad bugs present. To do: - Need to put status back on Hovercards - "Diff Detail" probably needs a better design Test Plan: Looking at lots of diffs, admittedly I dont have harbormaster, etc, running locally. Checked Diffusion for Table of Content changes on small and large commits. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15463 --- resources/celerity/map.php | 30 +- src/__phutil_library_map__.php | 4 - .../controller/DifferentialController.php | 3 +- .../DifferentialRevisionViewController.php | 412 ++++++++++-------- .../customfield/DifferentialAuthorField.php | 2 +- .../DifferentialHovercardEngineExtension.php | 2 - .../view/DifferentialAddCommentView.php | 2 +- .../view/DifferentialChangesetListView.php | 7 + .../view/DifferentialLocalCommitsView.php | 1 + .../view/DifferentialPrimaryPaneView.php | 23 - .../view/DifferentialRevisionDetailView.php | 121 ----- .../view/DifferentialRevisionListView.php | 7 + .../DifferentialRevisionUpdateHistoryView.php | 2 +- .../controller/DiffusionCommitController.php | 34 +- .../view/HarbormasterUnitSummaryView.php | 19 +- .../view/PHUIDiffTableOfContentsListView.php | 35 +- .../differential/changeset-view.css | 10 +- .../css/application/differential/core.css | 6 +- webroot/rsrc/css/phui/phui-box.css | 4 - webroot/rsrc/css/phui/phui-object-box.css | 10 + .../rsrc/css/phui/phui-two-column-view.css | 4 +- 21 files changed, 361 insertions(+), 377 deletions(-) delete mode 100644 src/applications/differential/view/DifferentialPrimaryPaneView.php delete mode 100644 src/applications/differential/view/DifferentialRevisionDetailView.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index fdc6357f60..d05a7b4903 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,10 +7,10 @@ */ return array( 'names' => array( - 'core.pkg.css' => '9c8e888d', + 'core.pkg.css' => 'c6ad5231', 'core.pkg.js' => '7d8faf57', 'darkconsole.pkg.js' => 'e7393ebb', - 'differential.pkg.css' => '7d0a63a7', + 'differential.pkg.css' => '7ba78475', 'differential.pkg.js' => 'd0cd0df6', 'diffusion.pkg.css' => 'f45955ed', 'diffusion.pkg.js' => '3a9a8bfa', @@ -57,8 +57,8 @@ return array( 'rsrc/css/application/dashboard/dashboard.css' => 'eb458607', 'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', 'rsrc/css/application/differential/add-comment.css' => 'c47f8c40', - 'rsrc/css/application/differential/changeset-view.css' => 'b6b0d1bb', - 'rsrc/css/application/differential/core.css' => '7ac3cabc', + 'rsrc/css/application/differential/changeset-view.css' => '3e3b0b76', + 'rsrc/css/application/differential/core.css' => '5b7b8ff4', 'rsrc/css/application/differential/phui-inline-comment.css' => '5953c28e', 'rsrc/css/application/differential/revision-comment.css' => '14b8565a', 'rsrc/css/application/differential/revision-history.css' => '0e8eb855', @@ -123,7 +123,7 @@ return array( 'rsrc/css/phui/phui-action-panel.css' => '91c7b835', 'rsrc/css/phui/phui-badge.css' => 'f25c3476', 'rsrc/css/phui/phui-big-info-view.css' => 'bd903741', - 'rsrc/css/phui/phui-box.css' => '3830ab21', + 'rsrc/css/phui/phui-box.css' => '06153ae3', 'rsrc/css/phui/phui-button.css' => 'a64a8de6', 'rsrc/css/phui/phui-chart.css' => '6bf6f78e', 'rsrc/css/phui/phui-crumbs-view.css' => '79d536e5', @@ -144,7 +144,7 @@ return array( 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-view.css' => '6d7c3509', 'rsrc/css/phui/phui-list.css' => '9da2aa00', - 'rsrc/css/phui/phui-object-box.css' => '91628842', + 'rsrc/css/phui/phui-object-box.css' => '6b487c57', 'rsrc/css/phui/phui-object-item-list-view.css' => '18b2ce8e', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', @@ -156,7 +156,7 @@ return array( 'rsrc/css/phui/phui-status.css' => '37309046', 'rsrc/css/phui/phui-tag-view.css' => '6bbd83e2', 'rsrc/css/phui/phui-timeline-view.css' => 'a0173eba', - 'rsrc/css/phui/phui-two-column-view.css' => 'e6bf86b6', + 'rsrc/css/phui/phui-two-column-view.css' => '61dd6d38', 'rsrc/css/phui/workboards/phui-workboard-color.css' => 'ac6fe6a7', 'rsrc/css/phui/workboards/phui-workboard.css' => 'e6d89647', 'rsrc/css/phui/workboards/phui-workcard.css' => '3646fb96', @@ -545,8 +545,8 @@ return array( 'conpherence-update-css' => 'faf6be09', 'conpherence-widget-pane-css' => '775eaaba', 'd3' => 'a11a5ff2', - 'differential-changeset-view-css' => 'b6b0d1bb', - 'differential-core-view-css' => '7ac3cabc', + 'differential-changeset-view-css' => '3e3b0b76', + 'differential-core-view-css' => '5b7b8ff4', 'differential-inline-comment-editor' => '64a5550f', 'differential-revision-add-comment-css' => 'c47f8c40', 'differential-revision-comment-css' => '14b8565a', @@ -805,7 +805,7 @@ return array( 'phui-action-panel-css' => '91c7b835', 'phui-badge-view-css' => 'f25c3476', 'phui-big-info-view-css' => 'bd903741', - 'phui-box-css' => '3830ab21', + 'phui-box-css' => '06153ae3', 'phui-button-css' => 'a64a8de6', 'phui-calendar-css' => 'ccabe893', 'phui-calendar-day-css' => 'd1cf6f93', @@ -833,7 +833,7 @@ return array( 'phui-info-view-css' => '6d7c3509', 'phui-inline-comment-view-css' => '5953c28e', 'phui-list-view-css' => '9da2aa00', - 'phui-object-box-css' => '91628842', + 'phui-object-box-css' => '6b487c57', 'phui-object-item-list-view-css' => '18b2ce8e', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', @@ -846,7 +846,7 @@ return array( 'phui-tag-view-css' => '6bbd83e2', 'phui-theme-css' => '027ba77e', 'phui-timeline-view-css' => 'a0173eba', - 'phui-two-column-view-css' => 'e6bf86b6', + 'phui-two-column-view-css' => '61dd6d38', 'phui-workboard-color-css' => 'ac6fe6a7', 'phui-workboard-view-css' => 'e6d89647', 'phui-workcard-view-css' => '3646fb96', @@ -1124,6 +1124,9 @@ return array( 'javelin-util', 'javelin-uri', ), + '3e3b0b76' => array( + 'phui-inline-comment-view-css', + ), '3f5d6dbf' => array( 'javelin-behavior', 'javelin-dom', @@ -1791,9 +1794,6 @@ return array( 'javelin-json', 'phabricator-draggable-list', ), - 'b6b0d1bb' => array( - 'phui-inline-comment-view-css', - ), 'bae58312' => array( 'javelin-install', 'javelin-workboard-card', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index bfad24494a..f253b328b2 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -473,7 +473,6 @@ phutil_register_library_map(array( 'DifferentialParseCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php', 'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php', 'DifferentialPathField' => 'applications/differential/customfield/DifferentialPathField.php', - 'DifferentialPrimaryPaneView' => 'applications/differential/view/DifferentialPrimaryPaneView.php', 'DifferentialProjectReviewersField' => 'applications/differential/customfield/DifferentialProjectReviewersField.php', 'DifferentialProjectsField' => 'applications/differential/customfield/DifferentialProjectsField.php', 'DifferentialQueryConduitAPIMethod' => 'applications/differential/conduit/DifferentialQueryConduitAPIMethod.php', @@ -508,7 +507,6 @@ phutil_register_library_map(array( 'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php', 'DifferentialRevisionDependedOnByRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependedOnByRevisionEdgeType.php', 'DifferentialRevisionDependsOnRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependsOnRevisionEdgeType.php', - 'DifferentialRevisionDetailView' => 'applications/differential/view/DifferentialRevisionDetailView.php', 'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php', 'DifferentialRevisionFulltextEngine' => 'applications/differential/search/DifferentialRevisionFulltextEngine.php', 'DifferentialRevisionHasCommitEdgeType' => 'applications/differential/edge/DifferentialRevisionHasCommitEdgeType.php', @@ -4580,7 +4578,6 @@ phutil_register_library_map(array( 'DifferentialParseCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialParseRenderTestCase' => 'PhabricatorTestCase', 'DifferentialPathField' => 'DifferentialCustomField', - 'DifferentialPrimaryPaneView' => 'AphrontView', 'DifferentialProjectReviewersField' => 'DifferentialCustomField', 'DifferentialProjectsField' => 'DifferentialCoreCustomField', 'DifferentialQueryConduitAPIMethod' => 'DifferentialConduitAPIMethod', @@ -4630,7 +4627,6 @@ phutil_register_library_map(array( 'DifferentialRevisionControlSystem' => 'Phobject', 'DifferentialRevisionDependedOnByRevisionEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionDependsOnRevisionEdgeType' => 'PhabricatorEdgeType', - 'DifferentialRevisionDetailView' => 'AphrontView', 'DifferentialRevisionEditController' => 'DifferentialController', 'DifferentialRevisionFulltextEngine' => 'PhabricatorFulltextEngine', 'DifferentialRevisionHasCommitEdgeType' => 'PhabricatorEdgeType', diff --git a/src/applications/differential/controller/DifferentialController.php b/src/applications/differential/controller/DifferentialController.php index 1aba876c68..43252c07f6 100644 --- a/src/applications/differential/controller/DifferentialController.php +++ b/src/applications/differential/controller/DifferentialController.php @@ -28,7 +28,8 @@ abstract class DifferentialController extends PhabricatorController { $viewer = $this->getViewer(); $toc_view = id(new PHUIDiffTableOfContentsListView()) - ->setUser($viewer); + ->setUser($viewer) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); $have_owners = PhabricatorApplication::isClassInstalledForViewer( 'PhabricatorOwnersApplication', diff --git a/src/applications/differential/controller/DifferentialRevisionViewController.php b/src/applications/differential/controller/DifferentialRevisionViewController.php index cad2932a0c..c59ee04047 100644 --- a/src/applications/differential/controller/DifferentialRevisionViewController.php +++ b/src/applications/differential/controller/DifferentialRevisionViewController.php @@ -40,7 +40,6 @@ final class DifferentialRevisionViewController extends DifferentialController { $revision->attachActiveDiff(last($diffs)); $diff_vs = $request->getInt('vs'); - $target_id = $request->getInt('id'); $target = idx($diffs, $target_id, end($diffs)); @@ -210,14 +209,10 @@ final class DifferentialRevisionViewController extends DifferentialController { $commits_for_links = array(); } - $revision_detail = id(new DifferentialRevisionDetailView()) - ->setUser($viewer) - ->setRevision($revision) - ->setDiff(end($diffs)) - ->setCustomFields($field_list) - ->setURI($request->getRequestURI()); - - $actions = $this->getRevisionActions($revision); + $header = $this->buildHeader($revision); + $subheader = $this->buildSubheaderView($revision); + $details = $this->buildDetails($revision, $field_list); + $curtain = $this->buildCurtain($revision); $whitespace = $request->getStr( 'whitespace', @@ -232,21 +227,16 @@ final class DifferentialRevisionViewController extends DifferentialController { $symbol_indexes = array(); } - $revision_detail->setActions($actions); - $revision_detail->setUser($viewer); - - $revision_detail_box = $revision_detail->render(); - $revision_warnings = $this->buildRevisionWarnings( $revision, $field_list, $warning_handle_map, $handles); + $info_view = null; if ($revision_warnings) { - $revision_warnings = id(new PHUIInfoView()) + $info_view = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setErrors($revision_warnings); - $revision_detail_box->setInfoView($revision_warnings); } $detail_diffs = array_select_keys( @@ -277,39 +267,31 @@ final class DifferentialRevisionViewController extends DifferentialController { $comment_view->setQuoteTargetID('comment-content'); } - $wrap_id = celerity_generate_unique_node_id(); - $comment_view = phutil_tag( - 'div', - array( - 'id' => $wrap_id, - ), - $comment_view); + $changeset_view = id(new DifferentialChangesetListView()) + ->setChangesets($changesets) + ->setVisibleChangesets($visible_changesets) + ->setStandaloneURI('/differential/changeset/') + ->setRawFileURIs( + '/differential/changeset/?view=old', + '/differential/changeset/?view=new') + ->setUser($viewer) + ->setDiff($target) + ->setRenderingReferences($rendering_references) + ->setVsMap($vs_map) + ->setWhitespace($whitespace) + ->setSymbolIndexes($symbol_indexes) + ->setTitle(pht('Diff %s', $target->getID())) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); - $changeset_view = new DifferentialChangesetListView(); - $changeset_view->setChangesets($changesets); - $changeset_view->setVisibleChangesets($visible_changesets); + if ($repository) { + $changeset_view->setRepository($repository); + } if (!$viewer_is_anonymous) { $changeset_view->setInlineCommentControllerURI( '/differential/comment/inline/edit/'.$revision->getID().'/'); } - $changeset_view->setStandaloneURI('/differential/changeset/'); - $changeset_view->setRawFileURIs( - '/differential/changeset/?view=old', - '/differential/changeset/?view=new'); - - $changeset_view->setUser($viewer); - $changeset_view->setDiff($target); - $changeset_view->setRenderingReferences($rendering_references); - $changeset_view->setVsMap($vs_map); - $changeset_view->setWhitespace($whitespace); - if ($repository) { - $changeset_view->setRepository($repository); - } - $changeset_view->setSymbolIndexes($symbol_indexes); - $changeset_view->setTitle(pht('Diff %s', $target->getID())); - $diff_history = id(new DifferentialRevisionUpdateHistoryView()) ->setUser($viewer) ->setDiffs($diffs) @@ -344,71 +326,9 @@ final class DifferentialRevisionViewController extends DifferentialController { $comment_form = null; if (!$viewer_is_anonymous) { - $draft = id(new PhabricatorDraft())->loadOneWhere( - 'authorPHID = %s AND draftKey = %s', - $viewer->getPHID(), - 'differential-comment-'.$revision->getID()); - - $reviewers = array(); - $ccs = array(); - if ($draft) { - $reviewers = idx($draft->getMetadata(), 'reviewers', array()); - $ccs = idx($draft->getMetadata(), 'ccs', array()); - if ($reviewers || $ccs) { - $handles = $this->loadViewerHandles(array_merge($reviewers, $ccs)); - $reviewers = array_select_keys($handles, $reviewers); - $ccs = array_select_keys($handles, $ccs); - } - } - - $comment_form = new DifferentialAddCommentView(); - $comment_form->setRevision($revision); - - $review_warnings = array(); - foreach ($field_list->getFields() as $field) { - $review_warnings[] = $field->getWarningsForDetailView(); - } - $review_warnings = array_mergev($review_warnings); - - if ($review_warnings) { - $review_warnings_panel = id(new PHUIInfoView()) - ->setSeverity(PHUIInfoView::SEVERITY_WARNING) - ->setErrors($review_warnings); - $comment_form->setInfoView($review_warnings_panel); - } - - $comment_form->setActions($this->getRevisionCommentActions($revision)); - $action_uri = $this->getApplicationURI( - 'comment/save/'.$revision->getID().'/'); - - $comment_form->setActionURI($action_uri); - $comment_form->setUser($viewer); - $comment_form->setDraft($draft); - $comment_form->setReviewers(mpull($reviewers, 'getFullName', 'getPHID')); - $comment_form->setCCs(mpull($ccs, 'getFullName', 'getPHID')); - - // TODO: This just makes the "Z" key work. Generalize this and remove - // it at some point. - $comment_form = phutil_tag( - 'div', - array( - 'class' => 'differential-add-comment-panel', - ), - $comment_form); + $comment_form = $this->buildCommentForm($revision, $field_list); } - $pane_id = celerity_generate_unique_node_id(); - Javelin::initBehavior( - 'differential-keyboard-navigation', - array( - 'haunt' => $pane_id, - )); - Javelin::initBehavior('differential-user-select'); - - $page_pane = id(new DifferentialPrimaryPaneView()) - ->setID($pane_id) - ->appendChild($comment_view); - $signatures = DifferentialRequiredSignaturesField::loadForRevision( $revision); $missing_signatures = false; @@ -418,21 +338,17 @@ final class DifferentialRevisionViewController extends DifferentialController { } } + $footer = array(); + $signature_message = null; if ($missing_signatures) { $signature_message = id(new PHUIInfoView()) - ->setErrors( - array( - array( - phutil_tag('strong', array(), pht('Content Hidden:')), - ' ', - pht( - 'The content of this revision is hidden until the author has '. - 'signed all of the required legal agreements.'), - ), - )); - $page_pane->appendChild($signature_message); + ->setTitle(pht('Content Hidden')) + ->appendChild( + pht( + 'The content of this revision is hidden until the author has '. + 'signed all of the required legal agreements.')); } else { - $page_pane->appendChild( + $footer[] = array( $diff_history, $warning, @@ -440,37 +356,28 @@ final class DifferentialRevisionViewController extends DifferentialController { $toc_view, $other_view, $changeset_view, - )); + ); } if ($comment_form) { - $page_pane->appendChild($comment_form); + $footer[] = $comment_form; } else { // TODO: For now, just use this to get "Login to Comment". - $page_pane->appendChild( - id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($viewer) - ->setRequestURI($request->getRequestURI())); + $footer[] = id(new PhabricatorApplicationTransactionCommentView()) + ->setUser($viewer) + ->setRequestURI($request->getRequestURI()); } $object_id = 'D'.$revision->getID(); - $operations_box = $this->buildOperationsBox($revision); - $content = array( - $operations_box, - $revision_detail_box, - $diff_detail_box, - $unit_box, - $page_pane, - ); - $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($object_id, '/'.$object_id); + $crumbs->setBorder(true); $prefs = $viewer->loadPreferences(); - $pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE; + $nav = null; if ($prefs->getPreference($pref_filetree)) { $collapsed = $prefs->getPreference( PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED, @@ -481,15 +388,38 @@ final class DifferentialRevisionViewController extends DifferentialController { ->setBaseURI(new PhutilURI('/D'.$revision->getID())) ->setCollapsed((bool)$collapsed) ->build($changesets); - } else { - $nav = null; } - $page = $this->newPage() + // Haunt Mode + $pane_id = celerity_generate_unique_node_id(); + Javelin::initBehavior( + 'differential-keyboard-navigation', + array( + 'haunt' => $pane_id, + )); + Javelin::initBehavior('differential-user-select'); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setSubheader($subheader) + ->setCurtain($curtain) + ->setID($pane_id) + ->setMainColumn(array( + $operations_box, + $info_view, + $details, + $diff_detail_box, + $unit_box, + $comment_view, + $signature_message, + )) + ->setFooter($footer); + + $page = $this->newPage() ->setTitle($object_id.' '.$revision->getTitle()) ->setCrumbs($crumbs) ->setPageObjectPHIDs(array($revision->getPHID())) - ->appendChild($content); + ->appendChild($view); if ($nav) { $page->setNavigation($nav); @@ -498,59 +428,183 @@ final class DifferentialRevisionViewController extends DifferentialController { return $page; } - private function getRevisionActions(DifferentialRevision $revision) { - $viewer = $this->getRequest()->getUser(); + private function buildHeader(DifferentialRevision $revision) { + $view = id(new PHUIHeaderView()) + ->setHeader($revision->getTitle($revision)) + ->setUser($this->getViewer()) + ->setPolicyObject($revision) + ->setHeaderIcon('fa-cog'); + + $status = $revision->getStatus(); + $status_name = + DifferentialRevisionStatus::renderFullDescription($status); + + $view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name); + + return $view; + } + + private function buildSubheaderView(DifferentialRevision $revision) { + $viewer = $this->getViewer(); + + $author_phid = $revision->getAuthorPHID(); + + $author = $viewer->renderHandle($author_phid)->render(); + $date = phabricator_datetime($revision->getDateCreated(), $viewer); + $author = phutil_tag('strong', array(), $author); + + $handles = $viewer->loadHandles(array($author_phid)); + $image_uri = $handles[$author_phid]->getImageURI(); + $image_href = $handles[$author_phid]->getURI(); + + $content = pht('Authored by %s on %s.', $author, $date); + + return id(new PHUIHeadThingView()) + ->setImage($image_uri) + ->setImageHref($image_href) + ->setContent($content); + } + + private function buildDetails( + DifferentialRevision $revision, + $custom_fields) { + $viewer = $this->getViewer(); + $properties = id(new PHUIPropertyListView()) + ->setUser($viewer); + + if ($custom_fields) { + $custom_fields->appendFieldsToPropertyList( + $revision, + $viewer, + $properties); + } + + $header = id(new PHUIHeaderView()) + ->setHeader(pht('DETAILS')); + + return id(new PHUIObjectBoxView()) + ->setHeader($header) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->appendChild($properties); + } + + private function buildCurtain(DifferentialRevision $revision) { + $viewer = $this->getViewer(); $revision_id = $revision->getID(); $revision_phid = $revision->getPHID(); + $curtain = $this->newCurtainView($revision); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $revision, PhabricatorPolicyCapability::CAN_EDIT); - $actions = array(); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-pencil') + ->setHref("/differential/revision/edit/{$revision_id}/") + ->setName(pht('Edit Revision')) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); - $actions[] = id(new PhabricatorActionView()) - ->setIcon('fa-pencil') - ->setHref("/differential/revision/edit/{$revision_id}/") - ->setName(pht('Edit Revision')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit); - - $actions[] = id(new PhabricatorActionView()) - ->setIcon('fa-upload') - ->setHref("/differential/revision/update/{$revision_id}/") - ->setName(pht('Update Diff')) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-upload') + ->setHref("/differential/revision/update/{$revision_id}/") + ->setName(pht('Update Diff')) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); $this->requireResource('phabricator-object-selector-css'); $this->requireResource('javelin-behavior-phabricator-object-selector'); - $actions[] = id(new PhabricatorActionView()) - ->setIcon('fa-link') - ->setName(pht('Edit Dependencies')) - ->setHref("/search/attach/{$revision_phid}/DREV/dependencies/") - ->setWorkflow(true) - ->setDisabled(!$can_edit); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-link') + ->setName(pht('Edit Dependencies')) + ->setHref("/search/attach/{$revision_phid}/DREV/dependencies/") + ->setWorkflow(true) + ->setDisabled(!$can_edit)); $maniphest = 'PhabricatorManiphestApplication'; if (PhabricatorApplication::isClassInstalled($maniphest)) { - $actions[] = id(new PhabricatorActionView()) - ->setIcon('fa-anchor') - ->setName(pht('Edit Maniphest Tasks')) - ->setHref("/search/attach/{$revision_phid}/TASK/") - ->setWorkflow(true) - ->setDisabled(!$can_edit); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-anchor') + ->setName(pht('Edit Maniphest Tasks')) + ->setHref("/search/attach/{$revision_phid}/TASK/") + ->setWorkflow(true) + ->setDisabled(!$can_edit)); } $request_uri = $this->getRequest()->getRequestURI(); - $actions[] = id(new PhabricatorActionView()) - ->setIcon('fa-download') - ->setName(pht('Download Raw Diff')) - ->setHref($request_uri->alter('download', 'true')); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-download') + ->setName(pht('Download Raw Diff')) + ->setHref($request_uri->alter('download', 'true'))); - return $actions; + return $curtain; + } + + private function buildCommentForm( + DifferentialRevision $revision, + $field_list) { + + $viewer = $this->getViewer(); + + $draft = id(new PhabricatorDraft())->loadOneWhere( + 'authorPHID = %s AND draftKey = %s', + $viewer->getPHID(), + 'differential-comment-'.$revision->getID()); + + $reviewers = array(); + $ccs = array(); + if ($draft) { + $reviewers = idx($draft->getMetadata(), 'reviewers', array()); + $ccs = idx($draft->getMetadata(), 'ccs', array()); + if ($reviewers || $ccs) { + $handles = $this->loadViewerHandles(array_merge($reviewers, $ccs)); + $reviewers = array_select_keys($handles, $reviewers); + $ccs = array_select_keys($handles, $ccs); + } + } + + $comment_form = id(new DifferentialAddCommentView()) + ->setRevision($revision); + + $review_warnings = array(); + foreach ($field_list->getFields() as $field) { + $review_warnings[] = $field->getWarningsForDetailView(); + } + $review_warnings = array_mergev($review_warnings); + + if ($review_warnings) { + $review_warnings_panel = id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) + ->setErrors($review_warnings); + $comment_form->setInfoView($review_warnings_panel); + } + + $action_uri = $this->getApplicationURI( + 'comment/save/'.$revision->getID().'/'); + + $comment_form->setActions($this->getRevisionCommentActions($revision)) + ->setActionURI($action_uri) + ->setUser($viewer) + ->setDraft($draft) + ->setReviewers(mpull($reviewers, 'getFullName', 'getPHID')) + ->setCCs(mpull($ccs, 'getFullName', 'getPHID')); + + // TODO: This just makes the "Z" key work. Generalize this and remove + // it at some point. + $comment_form = phutil_tag( + 'div', + array( + 'class' => 'differential-add-comment-panel', + ), + $comment_form); + return $comment_form; } private function getRevisionCommentActions(DifferentialRevision $revision) { @@ -558,7 +612,7 @@ final class DifferentialRevisionViewController extends DifferentialController { DifferentialAction::ACTION_COMMENT => true, ); - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $viewer_phid = $viewer->getPHID(); $viewer_is_owner = ($viewer_phid == $revision->getAuthorPHID()); $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers()); @@ -814,11 +868,12 @@ final class DifferentialRevisionViewController extends DifferentialController { $viewer = $this->getViewer(); $header = id(new PHUIHeaderView()) - ->setHeader(pht('Recent Similar Open Revisions')); + ->setHeader(pht('Recent Similar Revisions')); $view = id(new DifferentialRevisionListView()) ->setHeader($header) ->setRevisions($revisions) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setUser($viewer); $phids = $view->getRequiredHandlePHIDs(); @@ -845,7 +900,7 @@ final class DifferentialRevisionViewController extends DifferentialController { assert_instances_of($changesets, 'DifferentialChangeset'); assert_instances_of($vs_changesets, 'DifferentialChangeset'); - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); id(new DifferentialHunkQuery()) ->setViewer($viewer) @@ -978,7 +1033,8 @@ final class DifferentialRevisionViewController extends DifferentialController { } $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Diff Detail')) + ->setHeaderText(pht('DIFF DETAIL')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setUser($viewer); $last_tab = null; @@ -1061,7 +1117,8 @@ final class DifferentialRevisionViewController extends DifferentialController { } $box_view = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Active Operations')); + ->setHeaderText(pht('ACTIVE OPERATIONS')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); return id(new DrydockRepositoryOperationStatusView()) ->setUser($viewer) @@ -1078,10 +1135,6 @@ final class DifferentialRevisionViewController extends DifferentialController { return null; } - if (!$diff->getBuildable()) { - return null; - } - $interesting_messages = array(); foreach ($diff->getUnitMessages() as $message) { switch ($message->getResult()) { @@ -1109,6 +1162,7 @@ final class DifferentialRevisionViewController extends DifferentialController { ->setBuildable($diff->getBuildable()) ->setUnitMessages($diff->getUnitMessages()) ->setLimit(5) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setShowViewAll(true); } diff --git a/src/applications/differential/customfield/DifferentialAuthorField.php b/src/applications/differential/customfield/DifferentialAuthorField.php index bac57755ab..fbd74dd2ab 100644 --- a/src/applications/differential/customfield/DifferentialAuthorField.php +++ b/src/applications/differential/customfield/DifferentialAuthorField.php @@ -20,7 +20,7 @@ final class DifferentialAuthorField } public function shouldAppearInPropertyView() { - return true; + return false; } public function renderPropertyViewLabel() { diff --git a/src/applications/differential/engineextension/DifferentialHovercardEngineExtension.php b/src/applications/differential/engineextension/DifferentialHovercardEngineExtension.php index d0bd5917dc..6c178f44e0 100644 --- a/src/applications/differential/engineextension/DifferentialHovercardEngineExtension.php +++ b/src/applications/differential/engineextension/DifferentialHovercardEngineExtension.php @@ -70,8 +70,6 @@ final class DifferentialHovercardEngineExtension $hovercard->addField(pht('Summary'), $summary); } - $tag = DifferentialRevisionDetailView::renderTagForRevision($revision); - $hovercard->addTag($tag); } } diff --git a/src/applications/differential/view/DifferentialAddCommentView.php b/src/applications/differential/view/DifferentialAddCommentView.php index 2d586e7be4..f32c935e12 100644 --- a/src/applications/differential/view/DifferentialAddCommentView.php +++ b/src/applications/differential/view/DifferentialAddCommentView.php @@ -163,7 +163,7 @@ final class DifferentialAddCommentView extends AphrontView { $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $header_text = $is_serious ? pht('Add Comment') - : pht('Leap Into Action'); + : pht('Leap Into Action!'); $header = id(new PHUIHeaderView()) ->setHeader($header_text); diff --git a/src/applications/differential/view/DifferentialChangesetListView.php b/src/applications/differential/view/DifferentialChangesetListView.php index 0cd2923018..4f173bda53 100644 --- a/src/applications/differential/view/DifferentialChangesetListView.php +++ b/src/applications/differential/view/DifferentialChangesetListView.php @@ -8,6 +8,7 @@ final class DifferentialChangesetListView extends AphrontView { private $inlineURI; private $renderURI = '/differential/changeset/'; private $whitespace; + private $background; private $standaloneURI; private $leftRawFileURI; @@ -112,6 +113,11 @@ final class DifferentialChangesetListView extends AphrontView { return $this; } + public function setBackground($background) { + $this->background = $background; + return $this; + } + public function render() { $viewer = $this->getViewer(); @@ -254,6 +260,7 @@ final class DifferentialChangesetListView extends AphrontView { $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->setCollapsed(true) + ->setBackground($this->background) ->appendChild($content); return $object_box; diff --git a/src/applications/differential/view/DifferentialLocalCommitsView.php b/src/applications/differential/view/DifferentialLocalCommitsView.php index ebacabc3f3..639b62fc4b 100644 --- a/src/applications/differential/view/DifferentialLocalCommitsView.php +++ b/src/applications/differential/view/DifferentialLocalCommitsView.php @@ -127,6 +127,7 @@ final class DifferentialLocalCommitsView extends AphrontView { return id(new PHUIObjectBoxView()) ->setHeaderText(pht('Local Commits')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setTable($table); } diff --git a/src/applications/differential/view/DifferentialPrimaryPaneView.php b/src/applications/differential/view/DifferentialPrimaryPaneView.php deleted file mode 100644 index cfa4215fd5..0000000000 --- a/src/applications/differential/view/DifferentialPrimaryPaneView.php +++ /dev/null @@ -1,23 +0,0 @@ -id = $id; - return $this; - } - - public function render() { - - return phutil_tag( - 'div', - array( - 'class' => 'differential-primary-pane', - 'id' => $this->id, - ), - $this->renderChildren()); - } - -} diff --git a/src/applications/differential/view/DifferentialRevisionDetailView.php b/src/applications/differential/view/DifferentialRevisionDetailView.php deleted file mode 100644 index a8436811c2..0000000000 --- a/src/applications/differential/view/DifferentialRevisionDetailView.php +++ /dev/null @@ -1,121 +0,0 @@ -uri = $uri; - return $this; - } - public function getURI() { - return $this->uri; - } - - public function setDiff(DifferentialDiff $diff) { - $this->diff = $diff; - return $this; - } - private function getDiff() { - return $this->diff; - } - - public function setRevision(DifferentialRevision $revision) { - $this->revision = $revision; - return $this; - } - - public function setActions(array $actions) { - $this->actions = $actions; - return $this; - } - private function getActions() { - return $this->actions; - } - - public function setActionList(PhabricatorActionListView $list) { - $this->actionList = $list; - return $this; - } - - public function getActionList() { - return $this->actionList; - } - - public function setCustomFields(PhabricatorCustomFieldList $list) { - $this->customFields = $list; - return $this; - } - - public function render() { - - $this->requireResource('differential-core-view-css'); - - $revision = $this->revision; - $user = $this->getUser(); - - $header = $this->renderHeader($revision); - - $actions = id(new PhabricatorActionListView()) - ->setUser($user) - ->setObject($revision); - foreach ($this->getActions() as $action) { - $actions->addAction($action); - } - - $properties = id(new PHUIPropertyListView()) - ->setUser($user) - ->setObject($revision); - - $properties->setHasKeyboardShortcuts(true); - $properties->setActionList($actions); - $this->setActionList($actions); - - $field_list = $this->customFields; - if ($field_list) { - $field_list->appendFieldsToPropertyList( - $revision, - $user, - $properties); - } - - $object_box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); - - return $object_box; - } - - private function renderHeader(DifferentialRevision $revision) { - $view = id(new PHUIHeaderView()) - ->setHeader($revision->getTitle($revision)) - ->setUser($this->getUser()) - ->setPolicyObject($revision); - - $status = $revision->getStatus(); - $status_name = - DifferentialRevisionStatus::renderFullDescription($status); - - $view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name); - - return $view; - } - - public static function renderTagForRevision( - DifferentialRevision $revision) { - - $status = $revision->getStatus(); - $status_name = - ArcanistDifferentialRevisionStatus::getNameForRevisionStatus($status); - - return id(new PHUITagView()) - ->setType(PHUITagView::TYPE_STATE) - ->setName($status_name); - } - -} diff --git a/src/applications/differential/view/DifferentialRevisionListView.php b/src/applications/differential/view/DifferentialRevisionListView.php index 92394fcb3e..fbafb5a6cc 100644 --- a/src/applications/differential/view/DifferentialRevisionListView.php +++ b/src/applications/differential/view/DifferentialRevisionListView.php @@ -11,6 +11,7 @@ final class DifferentialRevisionListView extends AphrontView { private $header; private $noDataString; private $noBox; + private $background = null; public function setNoDataString($no_data_string) { $this->noDataString = $no_data_string; @@ -38,6 +39,11 @@ final class DifferentialRevisionListView extends AphrontView { return $this; } + public function setBackground($background) { + $this->background = $background; + return $this; + } + public function getRequiredHandlePHIDs() { $phids = array(); foreach ($this->revisions as $revision) { @@ -192,6 +198,7 @@ final class DifferentialRevisionListView extends AphrontView { if ($this->header && !$this->noBox) { $list->setFlush(true); $list = id(new PHUIObjectBoxView()) + ->setBackground($this->background) ->setObjectList($list); if ($this->header instanceof PHUIHeaderView) { diff --git a/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php b/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php index 082344a492..5ce766afb9 100644 --- a/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php +++ b/src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php @@ -305,7 +305,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView { return id(new PHUIObjectBoxView()) ->setHeaderText(pht('Revision Update History')) - ->setFlush(true) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setTable($content); } diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php index 6736b99430..94ca15ac4f 100644 --- a/src/applications/diffusion/controller/DiffusionCommitController.php +++ b/src/applications/diffusion/controller/DiffusionCommitController.php @@ -214,13 +214,11 @@ final class DiffusionCommitController extends DiffusionController { // changes inline even if there are more than the soft limit. $show_all_details = $request->getBool('show_all'); - $change_panel = new PHUIObjectBoxView(); - $header = new PHUIHeaderView(); - $header->setHeader(pht('Changes (%s)', new PhutilNumber($count))); - $change_panel->setID('toc'); + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Changes (%s)', new PhutilNumber($count))); + $warning_view = null; if ($count > self::CHANGES_LIMIT && !$show_all_details) { - $button = id(new PHUIButtonView()) ->setText(pht('Show All Changes')) ->setHref('?show_all=true') @@ -230,11 +228,9 @@ final class DiffusionCommitController extends DiffusionController { $warning_view = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setTitle(pht('Very Large Commit')) + ->addButton($button) ->appendChild( pht('This commit is very large. Load each file individually.')); - - $change_panel->setInfoView($warning_view); - $header->addActionLink($button); } $changesets = DiffusionPathChange::convertToDifferentialChangesets( @@ -244,12 +240,11 @@ final class DiffusionCommitController extends DiffusionController { // TODO: This table and panel shouldn't really be separate, but we need // to clean up the "Load All Files" interaction first. $change_table = $this->buildTableOfContents( - $changesets); + $changesets, + $header, + $warning_view); - $change_panel->setTable($change_table); - $change_panel->setHeader($header); - - $content[] = $change_panel; + $content[] = $change_table; $vcs = $repository->getVersionControlSystem(); switch ($vcs) { @@ -1017,12 +1012,21 @@ final class DiffusionCommitController extends DiffusionController { return $parser->processCorpus($corpus); } - private function buildTableOfContents(array $changesets) { + private function buildTableOfContents( + array $changesets, + $header, + $info_view) { + $drequest = $this->getDiffusionRequest(); $viewer = $this->getViewer(); $toc_view = id(new PHUIDiffTableOfContentsListView()) - ->setUser($viewer); + ->setUser($viewer) + ->setHeader($header); + + if ($info_view) { + $toc_view->setInfoView($info_view); + } // TODO: This is hacky, we just want access to the linkX() methods on // DiffusionView. diff --git a/src/applications/harbormaster/view/HarbormasterUnitSummaryView.php b/src/applications/harbormaster/view/HarbormasterUnitSummaryView.php index 75de4b20df..49efdc3e25 100644 --- a/src/applications/harbormaster/view/HarbormasterUnitSummaryView.php +++ b/src/applications/harbormaster/view/HarbormasterUnitSummaryView.php @@ -7,6 +7,7 @@ final class HarbormasterUnitSummaryView extends AphrontView { private $limit; private $excuse; private $showViewAll; + private $background; public function setBuildable(HarbormasterBuildable $buildable) { $this->buildable = $buildable; @@ -33,6 +34,11 @@ final class HarbormasterUnitSummaryView extends AphrontView { return $this; } + public function setBackground($background) { + $this->background = $background; + return $this; + } + public function render() { $messages = $this->messages; $buildable = $this->buildable; @@ -54,9 +60,14 @@ final class HarbormasterUnitSummaryView extends AphrontView { $tag_icon = 'fa-ban'; } + $tag = id(new PHUITagView()) + ->setType(PHUITagView::TYPE_SHADE) + ->setShade($tag_color) + ->setIcon($tag_icon) + ->setName($tag_text); + $header = id(new PHUIHeaderView()) - ->setHeader(pht('Unit Tests')) - ->setStatus($tag_icon, $tag_color, $tag_text); + ->setHeader(array(pht('Unit Tests'), $tag)); if ($this->showViewAll) { $view_all = id(new PHUIButtonView()) @@ -98,6 +109,10 @@ final class HarbormasterUnitSummaryView extends AphrontView { $box->setTable($table); + if ($this->background) { + $box->setBackground($this->background); + } + return $box; } diff --git a/src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php b/src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php index f032e34017..3330620148 100644 --- a/src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php +++ b/src/infrastructure/diff/view/PHUIDiffTableOfContentsListView.php @@ -4,6 +4,9 @@ final class PHUIDiffTableOfContentsListView extends AphrontView { private $items = array(); private $authorityPackages; + private $header; + private $infoView; + private $background; public function addItem(PHUIDiffTableOfContentsItemView $item) { $this->items[] = $item; @@ -20,6 +23,21 @@ final class PHUIDiffTableOfContentsListView extends AphrontView { return $this->authorityPackages; } + public function setBackground($background) { + $this->background = $background; + return $this; + } + + public function setHeader(PHUIHeaderView $header) { + $this->header = $header; + return $this; + } + + public function setInfoView(PHUIInfoView $infoview) { + $this->infoView = $infoview; + return $this; + } + public function render() { $this->requireResource('differential-core-view-css'); $this->requireResource('differential-table-of-contents-css'); @@ -142,11 +160,24 @@ final class PHUIDiffTableOfContentsListView extends AphrontView { ->setAnchorName('toc') ->setNavigationMarker(true); - return id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Table of Contents')) + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Table of Contents')); + + if ($this->header) { + $header = $this->header; + } + + $box = id(new PHUIObjectBoxView()) + ->setHeader($header) + ->setBackground($this->background) ->setTable($table) ->appendChild($anchor) ->appendChild($buttons); + + if ($this->infoView) { + $box->setInfoView($this->infoView); + } + return $box; } } diff --git a/webroot/rsrc/css/application/differential/changeset-view.css b/webroot/rsrc/css/application/differential/changeset-view.css index 71cfa3170b..85eb5ab437 100644 --- a/webroot/rsrc/css/application/differential/changeset-view.css +++ b/webroot/rsrc/css/application/differential/changeset-view.css @@ -6,7 +6,7 @@ .differential-changeset { position: relative; margin: 0; - padding-top: 32px; + padding-top: 16px; overflow-x: auto; /* Fixes what seems to be a layout bug in Firefox which causes scrollbars, @@ -265,7 +265,7 @@ td.cov-I { .differential-changeset h1 { font-size: {$biggestfontsize}; - padding: 2px 0 12px 12px; + padding: 2px 0 20px 12px; line-height: 20px; color: #000; } @@ -322,7 +322,7 @@ td.cov-I { .differential-changeset-buttons { float: right; - margin-right: 8px; + margin-right: 12px; } .device-phone .differential-changeset-buttons { @@ -362,3 +362,7 @@ tr.differential-inline-hidden { tr.differential-inline-loading { opacity: 0.5; } + +.differential-review-stage { + position: relative; +} diff --git a/webroot/rsrc/css/application/differential/core.css b/webroot/rsrc/css/application/differential/core.css index 7ccd633f3f..2dcc02bb18 100644 --- a/webroot/rsrc/css/application/differential/core.css +++ b/webroot/rsrc/css/application/differential/core.css @@ -3,7 +3,7 @@ */ .differential-primary-pane { - margin-bottom: 32px; + margin-top: -20px; } .differential-panel { @@ -23,3 +23,7 @@ -ms-user-select: none; user-select: none; } + +.differential-content-hidden { + margin: 0 0 24px 0; +} diff --git a/webroot/rsrc/css/phui/phui-box.css b/webroot/rsrc/css/phui/phui-box.css index 1d42cde8fa..d59624ab45 100644 --- a/webroot/rsrc/css/phui/phui-box.css +++ b/webroot/rsrc/css/phui/phui-box.css @@ -66,10 +66,6 @@ padding: 0; } -.phui-box.phui-box-blue-property .phui-header-header { - text-transform: uppercase; -} - .phui-box.phui-box-blue-property .phui-header-header .phui-header-icon { margin-right: 6px; } diff --git a/webroot/rsrc/css/phui/phui-object-box.css b/webroot/rsrc/css/phui/phui-object-box.css index f9f06e2d18..dee0525944 100644 --- a/webroot/rsrc/css/phui/phui-object-box.css +++ b/webroot/rsrc/css/phui/phui-object-box.css @@ -52,6 +52,16 @@ div.phui-object-box.phui-object-box-flush { margin: 8px 8px 0 8px; } +.phui-object-box .phui-header-header .phui-tag-view { + margin-left: 8px; +} + +.phui-object-box .phui-header-header .phui-tag-core { + border-color: transparent; + padding: 1px 6px; + font-size: {$normalfontsize}; +} + /* - Object Box Colors ------------------------------------------------------ */ .phui-box-border.phui-object-box-green { diff --git a/webroot/rsrc/css/phui/phui-two-column-view.css b/webroot/rsrc/css/phui/phui-two-column-view.css index 090fafb63a..a4ee2c4d3f 100644 --- a/webroot/rsrc/css/phui/phui-two-column-view.css +++ b/webroot/rsrc/css/phui/phui-two-column-view.css @@ -182,12 +182,12 @@ /* Info View */ -.phui-two-column-view .phui-two-column-content .phui-info-view { +.phui-two-column-view .phui-two-column-row .phui-info-view { margin: 0 0 20px 0; padding: 16px; } -.phui-two-column-view .phui-two-column-content .phui-object-box +.phui-two-column-view .phui-two-column-row .phui-object-box .phui-info-view { margin: 0; }