From fe7e288cf558051c5405679d8569ce26847482ef Mon Sep 17 00:00:00 2001 From: Chad Little Date: Fri, 26 Feb 2016 14:34:51 -0800 Subject: [PATCH] Solidify PHUITwoColumnView as a page layout Summary: Rolls out a new "Object Page" design with PHUITwoColumnView. This is reasonably polished, but wanted to post it up for you now for feedback before chasing down minor bugs. This implements TwoColumn in the following applications: - Ponder - Paste - Slowvote - Countdown - Projects - Profile - Passphrase This helped track down display issues and inconsistencies and make sure the layout was flexible for different pages. Test Plan: Test each of the applications on mobile, tablet, and desktop breakpoints. {F1135705} {F1135706} {F1135707} {F1135708} {F1135709} {F1135710} {F1135711} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D15366 --- resources/celerity/map.php | 48 ++--- src/__phutil_library_map__.php | 4 +- .../CelerityDefaultPostprocessor.php | 5 +- .../PhabricatorCountdownViewController.php | 80 ++++---- .../view/PhabricatorCountdownView.php | 58 +++--- .../PassphraseCredentialViewController.php | 82 ++++++-- .../PhabricatorPasteViewController.php | 77 ++++--- ...PhabricatorPeopleProfileViewController.php | 8 +- .../PonderQuestionViewController.php | 134 +++++-------- .../ponder/view/PonderAddAnswerView.php | 3 +- .../PhabricatorProjectProfileController.php | 9 +- .../PhabricatorSlowvotePollController.php | 65 +++--- .../slowvote/view/SlowvoteEmbedView.php | 46 ++--- src/view/phui/PHUIHeadThingView.php | 65 ++++++ src/view/phui/PHUIObjectBoxView.php | 1 + src/view/phui/PHUITwoColumnView.php | 80 ++++++-- .../rsrc/css/application/countdown/timer.css | 29 +-- webroot/rsrc/css/application/paste/paste.css | 8 - .../css/application/ponder/ponder-view.css | 97 +-------- .../css/application/project/project-view.css | 54 +++-- .../css/application/slowvote/slowvote.css | 20 +- webroot/rsrc/css/phui/phui-box.css | 32 ++- webroot/rsrc/css/phui/phui-button.css | 7 +- webroot/rsrc/css/phui/phui-head-thing.css | 33 +++ webroot/rsrc/css/phui/phui-header-view.css | 2 +- webroot/rsrc/css/phui/phui-object-box.css | 4 + .../rsrc/css/phui/phui-two-column-view.css | 188 +++++++++++++++--- 27 files changed, 741 insertions(+), 498 deletions(-) create mode 100644 src/view/phui/PHUIHeadThingView.php create mode 100644 webroot/rsrc/css/phui/phui-head-thing.css diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 1a4c791ddb..4df1247742 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '76a3afdf', + 'core.pkg.css' => 'e50c063a', 'core.pkg.js' => '7d8faf57', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -52,7 +52,7 @@ return array( 'rsrc/css/application/conpherence/update.css' => 'faf6be09', 'rsrc/css/application/conpherence/widget-pane.css' => '775eaaba', 'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4', - 'rsrc/css/application/countdown/timer.css' => 'e7544472', + 'rsrc/css/application/countdown/timer.css' => '96696f21', 'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a', 'rsrc/css/application/dashboard/dashboard.css' => 'eb458607', 'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', @@ -79,7 +79,7 @@ return array( 'rsrc/css/application/maniphest/task-summary.css' => '11cc5344', 'rsrc/css/application/objectselector/object-selector.css' => '85ee8ce6', 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', - 'rsrc/css/application/paste/paste.css' => 'a5157c48', + 'rsrc/css/application/paste/paste.css' => '1898e534', 'rsrc/css/application/people/people-profile.css' => '2473d929', 'rsrc/css/application/phame/phame.css' => '737792d6', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', @@ -92,18 +92,18 @@ return array( 'rsrc/css/application/policy/policy-edit.css' => '815c66f7', 'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43', 'rsrc/css/application/policy/policy.css' => '957ea14c', - 'rsrc/css/application/ponder/ponder-view.css' => '212495e0', + 'rsrc/css/application/ponder/ponder-view.css' => '4e321d68', 'rsrc/css/application/project/project-card-view.css' => '9418c97d', - 'rsrc/css/application/project/project-view.css' => '298b7c5b', + 'rsrc/css/application/project/project-view.css' => '9ce99f21', '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', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 'rsrc/css/application/search/search-results.css' => '7dea472c', - 'rsrc/css/application/slowvote/slowvote.css' => 'da0afb1b', + 'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230', 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', - 'rsrc/css/core/core.css' => '5b3563c8', + 'rsrc/css/core/core.css' => 'd0801452', 'rsrc/css/core/remarkup.css' => 'fc228f08', 'rsrc/css/core/syntax.css' => '9fd11da8', 'rsrc/css/core/z-index.css' => '5b6fcf3f', @@ -123,8 +123,8 @@ 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' => 'dd1294d3', - 'rsrc/css/phui/phui-button.css' => 'edf464e9', + 'rsrc/css/phui/phui-box.css' => '348bd872', + 'rsrc/css/phui/phui-button.css' => 'c096e4e9', 'rsrc/css/phui/phui-chart.css' => '6bf6f78e', 'rsrc/css/phui/phui-crumbs-view.css' => '79d536e5', 'rsrc/css/phui/phui-document-pro.css' => '92d5b648', @@ -134,7 +134,8 @@ return array( 'rsrc/css/phui/phui-fontkit.css' => '9cda225e', 'rsrc/css/phui/phui-form-view.css' => '4a1a0f5e', 'rsrc/css/phui/phui-form.css' => 'aac1d51d', - 'rsrc/css/phui/phui-header-view.css' => 'a6d7b20d', + 'rsrc/css/phui/phui-head-thing.css' => '11731da0', + 'rsrc/css/phui/phui-header-view.css' => 'b541cc78', 'rsrc/css/phui/phui-hovercard.css' => 'de1a2119', 'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad', 'rsrc/css/phui/phui-icon.css' => '3f33ab57', @@ -142,7 +143,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' => '407eaf5a', + 'rsrc/css/phui/phui-object-box.css' => '91628842', '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', @@ -154,7 +155,7 @@ return array( 'rsrc/css/phui/phui-status.css' => '888cedb8', 'rsrc/css/phui/phui-tag-view.css' => '9d5d4400', 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', - 'rsrc/css/phui/phui-two-column-view.css' => 'a317616a', + 'rsrc/css/phui/phui-two-column-view.css' => '7c5d0741', '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', @@ -740,7 +741,7 @@ return array( 'multirow-row-manager' => 'b5d57730', 'owners-path-editor' => 'aa1733d0', 'owners-path-editor-css' => '2f00933b', - 'paste-css' => 'a5157c48', + 'paste-css' => '1898e534', 'path-typeahead' => 'f7fc67ec', 'people-profile-css' => '2473d929', 'phabricator-action-list-view-css' => 'c5eba19d', @@ -748,8 +749,8 @@ return array( 'phabricator-busy' => '59a7976a', 'phabricator-chatlog-css' => 'd295b020', 'phabricator-content-source-view-css' => '4b8b05d4', - 'phabricator-core-css' => '5b3563c8', - 'phabricator-countdown-css' => 'e7544472', + 'phabricator-core-css' => 'd0801452', + 'phabricator-countdown-css' => '96696f21', 'phabricator-dashboard-css' => 'eb458607', 'phabricator-drag-and-drop-file-upload' => '81f182b5', 'phabricator-draggable-list' => '5a13c79f', @@ -772,7 +773,7 @@ return array( 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-side-menu-view-css' => '3a3d9f41', - 'phabricator-slowvote-css' => 'da0afb1b', + 'phabricator-slowvote-css' => 'a94b7230', 'phabricator-source-code-view-css' => 'cbeef983', 'phabricator-standard-page-view' => 'e709f6d0', 'phabricator-textareautils' => '5813016a', @@ -802,8 +803,8 @@ return array( 'phui-action-panel-css' => '91c7b835', 'phui-badge-view-css' => 'f25c3476', 'phui-big-info-view-css' => 'bd903741', - 'phui-box-css' => 'dd1294d3', - 'phui-button-css' => 'edf464e9', + 'phui-box-css' => '348bd872', + 'phui-button-css' => 'c096e4e9', 'phui-calendar-css' => 'ccabe893', 'phui-calendar-day-css' => 'd1cf6f93', 'phui-calendar-list-css' => 'c1c7f338', @@ -818,7 +819,8 @@ return array( 'phui-fontkit-css' => '9cda225e', 'phui-form-css' => 'aac1d51d', 'phui-form-view-css' => '4a1a0f5e', - 'phui-header-view-css' => 'a6d7b20d', + 'phui-head-thing-view-css' => '11731da0', + 'phui-header-view-css' => 'b541cc78', 'phui-hovercard' => '1bd28176', 'phui-hovercard-view-css' => 'de1a2119', 'phui-icon-set-selector-css' => '1ab67aad', @@ -828,7 +830,7 @@ return array( 'phui-info-view-css' => '6d7c3509', 'phui-inline-comment-view-css' => '0fdb3667', 'phui-list-view-css' => '9da2aa00', - 'phui-object-box-css' => '407eaf5a', + 'phui-object-box-css' => '91628842', 'phui-object-item-list-view-css' => '18b2ce8e', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', @@ -841,7 +843,7 @@ return array( 'phui-tag-view-css' => '9d5d4400', 'phui-theme-css' => '027ba77e', 'phui-timeline-view-css' => '2efceff8', - 'phui-two-column-view-css' => 'a317616a', + 'phui-two-column-view-css' => '7c5d0741', 'phui-workboard-color-css' => 'ac6fe6a7', 'phui-workboard-view-css' => 'e6d89647', 'phui-workcard-view-css' => '3646fb96', @@ -855,9 +857,9 @@ return array( 'policy-css' => '957ea14c', 'policy-edit-css' => '815c66f7', 'policy-transaction-detail-css' => '82100a43', - 'ponder-view-css' => '212495e0', + 'ponder-view-css' => '4e321d68', 'project-card-view-css' => '9418c97d', - 'project-view-css' => '298b7c5b', + 'project-view-css' => '9ce99f21', 'releeph-core' => '9b3c5733', 'releeph-preview-branch' => 'b7a6f4a5', 'releeph-request-differential-create-dialog' => '8d8b92cd', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a3f54fbf3e..740021f3c5 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1524,6 +1524,7 @@ phutil_register_library_map(array( 'PHUIHandleListView' => 'applications/phid/view/PHUIHandleListView.php', 'PHUIHandleTagListView' => 'applications/phid/view/PHUIHandleTagListView.php', 'PHUIHandleView' => 'applications/phid/view/PHUIHandleView.php', + 'PHUIHeadThingView' => 'view/phui/PHUIHeadThingView.php', 'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php', 'PHUIHovercardUIExample' => 'applications/uiexample/examples/PHUIHovercardUIExample.php', 'PHUIHovercardView' => 'view/phui/PHUIHovercardView.php', @@ -5758,6 +5759,7 @@ phutil_register_library_map(array( 'PHUIHandleListView' => 'AphrontTagView', 'PHUIHandleTagListView' => 'AphrontTagView', 'PHUIHandleView' => 'AphrontView', + 'PHUIHeadThingView' => 'AphrontTagView', 'PHUIHeaderView' => 'AphrontTagView', 'PHUIHovercardUIExample' => 'PhabricatorUIExample', 'PHUIHovercardView' => 'AphrontTagView', @@ -6380,7 +6382,7 @@ phutil_register_library_map(array( 'PhabricatorCountdownTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorCountdownTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorCountdownTransactionQuery' => 'PhabricatorApplicationTransactionQuery', - 'PhabricatorCountdownView' => 'AphrontTagView', + 'PhabricatorCountdownView' => 'AphrontView', 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 'PhabricatorCredentialsUsedByObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery', diff --git a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php index 4fdeaeccb1..13cef002cf 100644 --- a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php +++ b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php @@ -192,10 +192,7 @@ final class CelerityDefaultPostprocessor 'sh-disabledbackground' => '#f3f3f3', // Background color for "most" themes. - 'page.background' => '#f1f1f4', - - // Background color for "dark" themes. - 'page.background.dark' => '#ebecee', + 'page.background' => '#f8f8fb', 'menu.profile.text' => 'rgba(255,255,255,.8)', 'menu.profile.text.selected' => 'rgba(255,255,255,1)', diff --git a/src/applications/countdown/controller/PhabricatorCountdownViewController.php b/src/applications/countdown/controller/PhabricatorCountdownViewController.php index 401e159c5f..423bfe5207 100644 --- a/src/applications/countdown/controller/PhabricatorCountdownViewController.php +++ b/src/applications/countdown/controller/PhabricatorCountdownViewController.php @@ -21,15 +21,15 @@ final class PhabricatorCountdownViewController $countdown_view = id(new PhabricatorCountdownView()) ->setUser($viewer) - ->setCountdown($countdown) - ->setHeadless(true); + ->setCountdown($countdown); $id = $countdown->getID(); $title = $countdown->getTitle(); $crumbs = $this ->buildApplicationCrumbs() - ->addTextCrumb("C{$id}"); + ->addTextCrumb("C{$id}") + ->setBorder(true); $epoch = $countdown->getEpoch(); if ($epoch >= PhabricatorTime::getNow()) { @@ -49,19 +49,26 @@ final class PhabricatorCountdownViewController ->setStatus($icon, $color, $status); $actions = $this->buildActionListView($countdown); - $properties = $this->buildPropertyListView($countdown, $actions); - - $object_box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); + $properties = $this->buildPropertyListView($countdown); + $subheader = $this->buildSubheaderView($countdown); $timeline = $this->buildTransactionTimeline( $countdown, new PhabricatorCountdownTransactionQuery()); - $add_comment = $this->buildCommentForm($countdown); + $content = array( + $countdown_view, + $timeline, + $add_comment, + ); + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setSubheader($subheader) + ->setMainColumn($content) + ->setPropertyList($properties) + ->setActionList($actions); return $this->newPage() ->setTitle($title) @@ -72,10 +79,7 @@ final class PhabricatorCountdownViewController )) ->appendChild( array( - $object_box, - $countdown_view, - $timeline, - $add_comment, + $view, )); } @@ -114,34 +118,40 @@ final class PhabricatorCountdownViewController } private function buildPropertyListView( - PhabricatorCountdown $countdown, - PhabricatorActionListView $actions) { - + PhabricatorCountdown $countdown) { $viewer = $this->getViewer(); - $view = id(new PHUIPropertyListView()) ->setUser($viewer) - ->setObject($countdown) - ->setActionList($actions); - - $view->addProperty( - pht('Author'), - $viewer->renderHandle($countdown->getAuthorPHID())); - - $view->invokeWillRenderEvent(); - - $description = $countdown->getDescription(); - if (strlen($description)) { - $description = new PHUIRemarkupView($viewer, $description); - $view->addSectionHeader( - pht('Description'), - PHUIPropertyListView::ICON_SUMMARY); - $view->addTextContent($description); - } - + ->setObject($countdown); + $view->invokeWillRenderEvent(); return $view; } + private function buildSubheaderView( + PhabricatorCountdown $countdown) { + $viewer = $this->getViewer(); + + $author = $viewer->renderHandle($countdown->getAuthorPHID())->render(); + $date = phabricator_datetime($countdown->getDateCreated(), $viewer); + $author = phutil_tag('strong', array(), $author); + + $person = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withPHIDs(array($countdown->getAuthorPHID())) + ->needProfileImage(true) + ->executeOne(); + + $image_uri = $person->getProfileImageURI(); + $image_href = '/p/'.$person->getUsername(); + + $content = pht('Authored by %s on %s.', $author, $date); + + return id(new PHUIHeadThingView()) + ->setImage($image_uri) + ->setImageHref($image_href) + ->setContent($content); + } + private function buildCommentForm(PhabricatorCountdown $countdown) { $viewer = $this->getViewer(); diff --git a/src/applications/countdown/view/PhabricatorCountdownView.php b/src/applications/countdown/view/PhabricatorCountdownView.php index 2e8f1dedb3..4e975c3626 100644 --- a/src/applications/countdown/view/PhabricatorCountdownView.php +++ b/src/applications/countdown/view/PhabricatorCountdownView.php @@ -1,46 +1,31 @@ headless = $headless; - return $this; - } public function setCountdown(PhabricatorCountdown $countdown) { $this->countdown = $countdown; return $this; } - - protected function getTagContent() { + public function render() { $countdown = $this->countdown; - require_celerity_resource('phabricator-countdown-css'); - $header = null; - if (!$this->headless) { - $header = phutil_tag( - 'div', + $header_text = array( + 'C'.$countdown->getID(), + ' ', + phutil_tag( + 'a', array( - 'class' => 'phabricator-timer-header', + 'href' => '/countdown/'.$countdown->getID(), ), - array( - 'C'.$countdown->getID(), - ' ', - phutil_tag( - 'a', - array( - 'href' => '/countdown/'.$countdown->getID(), - ), - $countdown->getTitle()), - )); - } + $countdown->getTitle()), + ); + $header = id(new PHUIHeaderView()) + ->setHeader($header_text); $ths = array( phutil_tag('th', array(), pht('Days')), @@ -66,12 +51,23 @@ final class PhabricatorCountdownView extends AphrontTagView { ), $launch_date); + $description = $countdown->getDescription(); + if (strlen($description)) { + $description = new PHUIRemarkupView($this->getUser(), $description); + $description = phutil_tag( + 'div', + array( + 'class' => 'countdown-description phabricator-remarkup', + ), + $description); + } + $container = celerity_generate_unique_node_id(); $content = phutil_tag( 'div', array('class' => 'phabricator-timer', 'id' => $container), array( - $header, + $description, phutil_tag('table', array('class' => 'phabricator-timer-table'), array( phutil_tag('tr', array(), $ths), phutil_tag('tr', array(), $dashes), @@ -84,7 +80,11 @@ final class PhabricatorCountdownView extends AphrontTagView { 'container' => $container, )); - return $content; + return id(new PHUIObjectBoxView()) + ->setHeader($header) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->addClass('phabricator-timer-view') + ->appendChild($content); } } diff --git a/src/applications/passphrase/controller/PassphraseCredentialViewController.php b/src/applications/passphrase/controller/PassphraseCredentialViewController.php index c156be81ce..b4ccf0ad9e 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialViewController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialViewController.php @@ -28,23 +28,27 @@ final class PassphraseCredentialViewController extends PassphraseController { $title = pht('%s %s', 'K'.$credential->getID(), $credential->getName()); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb('K'.$credential->getID()); + $crumbs->setBorder(true); $header = $this->buildHeaderView($credential); $actions = $this->buildActionView($credential, $type); - $properties = $this->buildPropertyView($credential, $type, $actions); + $properties = $this->buildPropertyView($credential, $type); + $subheader = $this->buildSubheaderView($credential); + $content = $this->buildDetailsView($credential, $type); - $box = id(new PHUIObjectBoxView()) + $view = id(new PHUITwoColumnView()) ->setHeader($header) - ->addPropertyList($properties); + ->setSubheader($subheader) + ->setMainColumn(array($content, $timeline)) + ->setPropertyList($properties) + ->setActionList($actions); - return $this->buildApplicationPage( - array( - $crumbs, - $box, - $timeline, - ), - array( - 'title' => $title, + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild( + array( + $view, )); } @@ -63,6 +67,35 @@ final class PassphraseCredentialViewController extends PassphraseController { return $header; } + private function buildSubheaderView( + PassphraseCredential $credential) { + $viewer = $this->getViewer(); + + $author = $viewer->renderHandle($credential->getAuthorPHID())->render(); + $date = phabricator_datetime($credential->getDateCreated(), $viewer); + $author = phutil_tag('strong', array(), $author); + + $person = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withPHIDs(array($credential->getAuthorPHID())) + ->needProfileImage(true) + ->executeOne(); + + if (!$person) { + return null; + } + + $image_uri = $person->getProfileImageURI(); + $image_href = '/p/'.$credential->getUsername(); + + $content = pht('Created by %s on %s.', $author, $date); + + return id(new PHUIHeadThingView()) + ->setImage($image_uri) + ->setImageHref($image_href) + ->setContent($content); + } + private function buildActionView( PassphraseCredential $credential, PassphraseCredentialType $type) { @@ -153,16 +186,13 @@ final class PassphraseCredentialViewController extends PassphraseController { return $actions; } - private function buildPropertyView( + private function buildDetailsView( PassphraseCredential $credential, - PassphraseCredentialType $type, - PhabricatorActionListView $actions) { + PassphraseCredentialType $type) { $viewer = $this->getRequest()->getUser(); $properties = id(new PHUIPropertyListView()) - ->setUser($viewer) - ->setObject($credential) - ->setActionList($actions); + ->setUser($viewer); $properties->addProperty( pht('Credential Type'), @@ -192,8 +222,6 @@ final class PassphraseCredentialViewController extends PassphraseController { $viewer->renderHandleList($used_by_phids)); } - $properties->invokeWillRenderEvent(); - $description = $credential->getDescription(); if (strlen($description)) { $properties->addSectionHeader( @@ -203,6 +231,22 @@ final class PassphraseCredentialViewController extends PassphraseController { new PHUIRemarkupView($viewer, $description)); } + return id(new PHUIObjectBoxView()) + ->setHeaderText(pht('PROPERTIES')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->appendChild($properties); + } + + private function buildPropertyView( + PassphraseCredential $credential, + PassphraseCredentialType $type) { + $viewer = $this->getRequest()->getUser(); + + $properties = id(new PHUIPropertyListView()) + ->setUser($viewer) + ->setObject($credential); + + $properties->invokeWillRenderEvent(); return $properties; } diff --git a/src/applications/paste/controller/PhabricatorPasteViewController.php b/src/applications/paste/controller/PhabricatorPasteViewController.php index 530b2245c5..f259cdc6af 100644 --- a/src/applications/paste/controller/PhabricatorPasteViewController.php +++ b/src/applications/paste/controller/PhabricatorPasteViewController.php @@ -48,25 +48,16 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { $header = $this->buildHeaderView($paste); $actions = $this->buildActionView($viewer, $paste); - $properties = $this->buildPropertyView($paste, $fork_phids, $actions); - - $object_box = id(new PHUIObjectBoxView()) - ->setHeader($header) - ->addPropertyList($properties); - + $properties = $this->buildPropertyView($paste, $fork_phids); + $subheader = $this->buildSubheaderView($paste); $source_code = $this->buildSourceCodeView($paste, $this->highlightMap); require_celerity_resource('paste-css'); - $source_code = phutil_tag( - 'div', - array( - 'class' => 'container-of-paste', - ), - $source_code); $monogram = $paste->getMonogram(); $crumbs = $this->buildApplicationCrumbs() - ->addTextCrumb($monogram, '/'.$monogram); + ->addTextCrumb($monogram) + ->setBorder(true); $timeline = $this->buildTransactionTimeline( $paste, @@ -79,6 +70,18 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { $timeline->setQuoteRef($monogram); $comment_view->setTransactionTimeline($timeline); + $paste_view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setSubheader($subheader) + ->setMainColumn(array( + $source_code, + $timeline, + $comment_view, + )) + ->setPropertyList($properties) + ->setActionList($actions) + ->addClass('ponder-question-view'); + return $this->newPage() ->setTitle($paste->getFullName()) ->setCrumbs($crumbs) @@ -86,13 +89,7 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { array( $paste->getPHID(), )) - ->appendChild( - array( - $object_box, - $source_code, - $timeline, - $comment_view, - )); + ->appendChild($paste_view); } private function buildHeaderView(PhabricatorPaste $paste) { @@ -167,24 +164,40 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { return $action_list; } + + private function buildSubheaderView( + PhabricatorPaste $paste) { + $viewer = $this->getViewer(); + + $author = $viewer->renderHandle($paste->getAuthorPHID())->render(); + $date = phabricator_datetime($paste->getDateCreated(), $viewer); + $author = phutil_tag('strong', array(), $author); + + $author_info = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withPHIDs(array($paste->getAuthorPHID())) + ->needProfileImage(true) + ->executeOne(); + + $image_uri = $author_info->getProfileImageURI(); + $image_href = '/p/'.$author_info->getUsername(); + + $content = pht('Authored by %s on %s.', $author, $date); + + return id(new PHUIHeadThingView()) + ->setImage($image_uri) + ->setImageHref($image_href) + ->setContent($content); + } + private function buildPropertyView( PhabricatorPaste $paste, - array $child_phids, - PhabricatorActionListView $actions) { + array $child_phids) { $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer) - ->setObject($paste) - ->setActionList($actions); - - $properties->addProperty( - pht('Author'), - $viewer->renderHandle($paste->getAuthorPHID())); - - $properties->addProperty( - pht('Created'), - phabricator_datetime($paste->getDateCreated(), $viewer)); + ->setObject($paste); if ($paste->getParentPHID()) { $properties->addProperty( diff --git a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php index 698ff983f1..60b02b01f4 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php @@ -52,7 +52,10 @@ final class PhabricatorPeopleProfileViewController $name = $user->getUsername(); $feed = $this->buildPeopleFeed($user, $viewer); - $feed = phutil_tag_div('project-view-feed', $feed); + $feed = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Recent Activity')) + ->addClass('project-view-feed') + ->appendChild($feed); $projects = $this->buildProjectsView($user); $badges = $this->buildBadgesView($user); @@ -106,8 +109,7 @@ final class PhabricatorPeopleProfileViewController return null; } - $view = id(new PHUIBoxView()) - ->setBorder(true) + $view = id(new PHUIObjectBoxView()) ->appendChild($view) ->addClass('project-view-properties'); diff --git a/src/applications/ponder/controller/PonderQuestionViewController.php b/src/applications/ponder/controller/PonderQuestionViewController.php index 1b5b21e464..75a458fdc8 100644 --- a/src/applications/ponder/controller/PonderQuestionViewController.php +++ b/src/applications/ponder/controller/PonderQuestionViewController.php @@ -31,7 +31,6 @@ final class PonderQuestionViewController extends PonderController { $header->setHeader($question->getTitle()); $header->setUser($viewer); $header->setPolicyObject($question); - $header->setProfileHeader(true); if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) { $header->setStatus('fa-square-o', 'bluegrey', pht('Open')); @@ -43,8 +42,8 @@ final class PonderQuestionViewController extends PonderController { $header->setStatus($icon, 'dark', $text); } - $actions = $this->buildActionListView($question); $properties = $this->buildPropertyListView($question); + $actions = $this->buildActionListView($question); $details = $this->buildDetailsPropertyView($question); $can_edit = PhabricatorPolicyFilter::hasCapability( @@ -52,25 +51,6 @@ final class PonderQuestionViewController extends PonderController { $question, PhabricatorPolicyCapability::CAN_EDIT); - $edit_uri = '/question/edit/'.$question->getID().'/'; - $edit_button = id(new PHUIButtonView()) - ->setTag('a') - ->setText(pht('Edit')) - ->setHref($this->getApplicationURI($edit_uri)) - ->setIcon('fa-pencil') - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit); - - $action_button = id(new PHUIButtonView()) - ->setTag('a') - ->setText(pht('Actions')) - ->setHref('#') - ->setIcon('fa-bars') - ->setDropdownMenu($actions); - - $header->addActionLink($action_button); - $header->addActionLink($edit_button); - $content_id = celerity_generate_unique_node_id(); $timeline = $this->buildTransactionTimeline( $question, @@ -81,7 +61,6 @@ final class PonderQuestionViewController extends PonderController { $add_comment = id(new PhabricatorApplicationTransactionCommentView()) ->setUser($viewer) ->setObjectPHID($question->getPHID()) - ->setFullWidth(true) ->setShowPreview(false) ->setAction($this->getApplicationURI("/question/comment/{$id}/")) ->setSubmitButtonName(pht('Comment')); @@ -108,19 +87,14 @@ final class PonderQuestionViewController extends PonderController { $crumbs->addTextCrumb('Q'.$id, '/Q'.$id); $crumbs->setBorder(true); + $subheader = $this->buildSubheaderView($question); + $answer_wiki = null; if ($question->getAnswerWiki()) { $wiki = new PHUIRemarkupView($viewer, $question->getAnswerWiki()); - $wiki_header = phutil_tag( - 'div', - array( - 'class' => 'ponder-answer-wiki-header', - ), - pht('Answer Summary')); - $answer_wiki = id(new PHUIObjectBoxView()) - ->setBackground(PHUIObjectBoxView::BLUE) - ->appendChild($wiki_header) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->setHeaderText(pht('ANSWER SUMMARY')) ->appendChild($wiki) ->addClass('ponder-answer-wiki'); } @@ -143,8 +117,10 @@ final class PonderQuestionViewController extends PonderController { $ponder_view = id(new PHUITwoColumnView()) ->setHeader($header) + ->setSubheader($subheader) ->setMainColumn($ponder_content) - ->setSideColumn($properties) + ->setPropertyList($properties) + ->setActionList($actions) ->addClass('ponder-question-view'); $page_objects = array_merge( @@ -183,6 +159,14 @@ final class PonderQuestionViewController extends PonderController { $icon = 'fa-square-o'; } + $view->addAction( + id(new PhabricatorActionView()) + ->setIcon('fa-pencil') + ->setName(pht('Edit Question')) + ->setHref($this->getApplicationURI("/question/edit/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + $view->addAction( id(new PhabricatorActionView()) ->setName($name) @@ -206,23 +190,38 @@ final class PonderQuestionViewController extends PonderController { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) - ->setObject($question) - ->setStacked(true); + ->setObject($question); $view->invokeWillRenderEvent(); - if (!$view->hasAnyProperties()) { - return null; - } - - $view = id(new PHUIObjectBoxView()) - ->appendChild($view) - ->setBackground(PHUIObjectBoxView::GREY) - ->addClass('ponder-view-properties'); - return $view; } + private function buildSubheaderView( + PonderQuestion $question) { + $viewer = $this->getViewer(); + + $asker = $viewer->renderHandle($question->getAuthorPHID())->render(); + $date = phabricator_datetime($question->getDateCreated(), $viewer); + $asker = phutil_tag('strong', array(), $asker); + + $author = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withPHIDs(array($question->getAuthorPHID())) + ->needProfileImage(true) + ->executeOne(); + + $image_uri = $author->getProfileImageURI(); + $image_href = '/p/'.$author->getUsername(); + + $content = pht('Asked by %s on %s.', $asker, $date); + + return id(new PHUIHeadThingView()) + ->setImage($image_uri) + ->setImageHref($image_href) + ->setContent($content); + } + private function buildDetailsPropertyView( PonderQuestion $question) { $viewer = $this->getViewer(); @@ -239,49 +238,14 @@ final class PonderQuestionViewController extends PonderController { pht('No further details for this question.')); } - $asker = $viewer->renderHandle($question->getAuthorPHID())->render(); - $date = phabricator_datetime($question->getDateCreated(), $viewer); - $asker = phutil_tag('strong', array(), $asker); + $question_details = phutil_tag_div( + 'phabricator-remarkup ml', $question_details); - $author = id(new PhabricatorPeopleQuery()) - ->setViewer($viewer) - ->withPHIDs(array($question->getAuthorPHID())) - ->needProfileImage(true) - ->executeOne(); - - $image_uri = $author->getProfileImageURI(); - $image_href = '/p/'.$author->getUsername(); - - $image = phutil_tag( - 'a', - array( - 'class' => 'ponder-details-author-image', - 'style' => 'background-image: url('.$image_uri.');', - 'href' => $image_href, - )); - - $details_header = phutil_tag( - 'div', - array( - 'class' => 'ponder-details-subtitle', - ), - array( - $image, - pht('Asked by %s on %s.', $asker, $date), - )); - - $details = phutil_tag( - 'div', - array( - 'class' => 'ponder-detail-view', - ), - array( - $details_header, - phutil_tag_div('phabricator-remarkup', $question_details), - )); - - - return $details; + return id(new PHUIObjectBoxView()) + ->setHeaderText(pht('DETAILS')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->setFlush(true) + ->appendChild($question_details); } /** diff --git a/src/applications/ponder/view/PonderAddAnswerView.php b/src/applications/ponder/view/PonderAddAnswerView.php index ad17f68af6..fb52bd17ed 100644 --- a/src/applications/ponder/view/PonderAddAnswerView.php +++ b/src/applications/ponder/view/PonderAddAnswerView.php @@ -51,7 +51,6 @@ final class PonderAddAnswerView extends AphrontView { ->setUser($this->user) ->setAction($this->actionURI) ->setWorkflow(true) - ->setFullWidth(true) ->addHiddenInput('question_id', $question->getID()) ->appendChild( id(new PhabricatorRemarkupControl()) @@ -78,7 +77,7 @@ final class PonderAddAnswerView extends AphrontView { $box = id(new PHUIObjectBoxView()) ->appendChild($form) - ->setBackground(PHUIObjectBoxView::GREY) + ->setHeaderText('Answer') ->addClass('ponder-add-answer-view'); if ($info_panel) { diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index ddbd0ffb5b..f61ebd28d2 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -82,7 +82,11 @@ final class PhabricatorProjectProfileController ->execute(); $feed = $this->renderStories($stories); - $feed = phutil_tag_div('project-view-feed', $feed); + $feed = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Recent Activity')) + ->addClass('project-view-feed') + ->appendChild($feed); + require_celerity_resource('project-view-css'); $home = id(new PHUITwoColumnView()) @@ -134,8 +138,7 @@ final class PhabricatorProjectProfileController return null; } - $view = id(new PHUIBoxView()) - ->setBorder(true) + $view = id(new PHUIObjectBoxView()) ->appendChild($view) ->addClass('project-view-properties'); diff --git a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php index fd05afb057..8603185c73 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php @@ -23,7 +23,6 @@ final class PhabricatorSlowvotePollController } $poll_view = id(new SlowvoteEmbedView()) - ->setHeadless(true) ->setUser($viewer) ->setPoll($poll); @@ -47,19 +46,30 @@ final class PhabricatorSlowvotePollController ->setPolicyObject($poll); $actions = $this->buildActionView($poll); - $properties = $this->buildPropertyView($poll, $actions); + $properties = $this->buildPropertyView($poll); + $subheader = $this->buildSubheaderView($poll); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb('V'.$poll->getID()); + $crumbs->setBorder(true); $timeline = $this->buildTransactionTimeline( $poll, new PhabricatorSlowvoteTransactionQuery()); $add_comment = $this->buildCommentForm($poll); - $object_box = id(new PHUIObjectBoxView()) + $poll_content = array( + $poll_view, + $timeline, + $add_comment, + ); + + $view = id(new PHUITwoColumnView()) ->setHeader($header) - ->addPropertyList($properties); + ->setSubheader($subheader) + ->setMainColumn($poll_content) + ->setPropertyList($properties) + ->setActionList($actions); return $this->newPage() ->setTitle('V'.$poll->getID().' '.$poll->getQuestion()) @@ -67,10 +77,7 @@ final class PhabricatorSlowvotePollController ->setPageObjectPHIDs(array($poll->getPHID())) ->appendChild( array( - $object_box, - $poll_view, - $timeline, - $add_comment, + $view, )); } @@ -110,30 +117,42 @@ final class PhabricatorSlowvotePollController } private function buildPropertyView( - PhabricatorSlowvotePoll $poll, - PhabricatorActionListView $actions) { + PhabricatorSlowvotePoll $poll) { $viewer = $this->getRequest()->getUser(); - $view = id(new PHUIPropertyListView()) ->setUser($viewer) - ->setObject($poll) - ->setActionList($actions); - + ->setObject($poll); $view->invokeWillRenderEvent(); - $description = $poll->getDescription(); - if (strlen($description)) { - $description = new PHUIRemarkupView($viewer, $description); - $view->addSectionHeader( - pht('Description'), - PHUIPropertyListView::ICON_SUMMARY); - $view->addTextContent($description); - } - return $view; } + private function buildSubheaderView( + PhabricatorSlowvotePoll $poll) { + $viewer = $this->getViewer(); + + $author = $viewer->renderHandle($poll->getAuthorPHID())->render(); + $date = phabricator_datetime($poll->getDateCreated(), $viewer); + $author = phutil_tag('strong', array(), $author); + + $person = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withPHIDs(array($poll->getAuthorPHID())) + ->needProfileImage(true) + ->executeOne(); + + $image_uri = $person->getProfileImageURI(); + $image_href = '/p/'.$person->getUsername(); + + $content = pht('Asked by %s on %s.', $author, $date); + + return id(new PHUIHeadThingView()) + ->setImage($image_uri) + ->setImageHref($image_href) + ->setContent($content); + } + private function buildCommentForm(PhabricatorSlowvotePoll $poll) { $viewer = $this->getRequest()->getUser(); diff --git a/src/applications/slowvote/view/SlowvoteEmbedView.php b/src/applications/slowvote/view/SlowvoteEmbedView.php index 3582ea45b3..452cfbe9eb 100644 --- a/src/applications/slowvote/view/SlowvoteEmbedView.php +++ b/src/applications/slowvote/view/SlowvoteEmbedView.php @@ -4,12 +4,6 @@ final class SlowvoteEmbedView extends AphrontView { private $poll; private $handles; - private $headless; - - public function setHeadless($headless) { - $this->headless = $headless; - return $this; - } public function setPoll(PhabricatorSlowvotePoll $poll) { $this->poll = $poll; @@ -68,29 +62,25 @@ final class SlowvoteEmbedView extends AphrontView { ), $poll->getQuestion()); - if ($this->headless) { - $header = null; - } else { - $header = id(new PHUIHeaderView()) - ->setHeader($link_to_slowvote); + $header = id(new PHUIHeaderView()) + ->setHeader($link_to_slowvote); - $description = $poll->getDescription(); - if (strlen($description)) { - $description = new PHUIRemarkupView($this->getUser(), $description); - $description = phutil_tag( - 'div', - array( - 'class' => 'slowvote-description', - ), - $description); - } - - $header = array( - $header, - $description, - ); + $description = $poll->getDescription(); + if (strlen($description)) { + $description = new PHUIRemarkupView($this->getUser(), $description); + $description = phutil_tag( + 'div', + array( + 'class' => 'slowvote-description', + ), + $description); } + $header = array( + $header, + $description, + ); + $vis = $poll->getResponseVisibility(); if ($this->areResultsVisible()) { if ($vis == PhabricatorSlowvotePoll::RESPONSES_OWNER) { @@ -163,8 +153,10 @@ final class SlowvoteEmbedView extends AphrontView { array($body)); return id(new PHUIObjectBoxView()) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setHeader($header) - ->appendChild($embed); + ->appendChild($embed) + ->addClass('slowvote-poll-view'); } private function renderLabel(PhabricatorSlowvoteOption $option, $selected) { diff --git a/src/view/phui/PHUIHeadThingView.php b/src/view/phui/PHUIHeadThingView.php new file mode 100644 index 0000000000..4ff0290578 --- /dev/null +++ b/src/view/phui/PHUIHeadThingView.php @@ -0,0 +1,65 @@ +imageHref = $href; + return $this; + } + + public function setImage($image) { + $this->image = $image; + return $this; + } + + public function setContent($content) { + $this->content = $content; + return $this; + } + + public function setSize($size) { + $this->size = $size; + return $this; + } + + protected function getTagAttributes() { + require_celerity_resource('phui-head-thing-view-css'); + + $classes = array(); + $classes[] = 'phui-head-thing-view'; + + if ($this->size) { + $classes[] = $this->size; + } else { + $classes[] = self::SMALL; + } + + return array( + 'class' => $classes, + ); + } + + protected function getTagContent() { + + $image = phutil_tag( + 'a', + array( + 'class' => 'phui-head-thing-image', + 'style' => 'background-image: url('.$this->image.');', + 'href' => $this->imageHref, + )); + + return array($image, $this->content); + + + } + +} diff --git a/src/view/phui/PHUIObjectBoxView.php b/src/view/phui/PHUIObjectBoxView.php index 5cbb3a58b6..9fa280a843 100644 --- a/src/view/phui/PHUIObjectBoxView.php +++ b/src/view/phui/PHUIObjectBoxView.php @@ -36,6 +36,7 @@ final class PHUIObjectBoxView extends AphrontTagView { const COLOR_YELLOW = 'yellow'; const BLUE = 'phui-box-blue'; + const BLUE_PROPERTY = 'phui-box-blue-property'; const GREY = 'phui-box-grey'; public function addPropertyList( diff --git a/src/view/phui/PHUITwoColumnView.php b/src/view/phui/PHUITwoColumnView.php index 5a47dc925a..62db9c16e7 100644 --- a/src/view/phui/PHUITwoColumnView.php +++ b/src/view/phui/PHUITwoColumnView.php @@ -3,10 +3,13 @@ final class PHUITwoColumnView extends AphrontTagView { private $mainColumn; - private $sideColumn; + private $sideColumn = null; private $display; private $fluid; private $header; + private $subheader; + private $actionList; + private $propertyList; const DISPLAY_LEFT = 'phui-side-column-left'; const DISPLAY_RIGHT = 'phui-side-column-right'; @@ -26,6 +29,21 @@ final class PHUITwoColumnView extends AphrontTagView { return $this; } + public function setSubheader($subheader) { + $this->subheader = $subheader; + return $this; + } + + public function setActionList(PhabricatorActionListView $list) { + $this->actionList = $list; + return $this; + } + + public function setPropertyList(PHUIPropertyListView $list) { + $this->propertyList = $list; + return $this; + } + public function setFluid($fluid) { $this->fluid = $fluid; return $this; @@ -53,6 +71,10 @@ final class PHUITwoColumnView extends AphrontTagView { $classes[] = 'phui-two-column-fluid'; } + if ($this->subheader) { + $classes[] = 'with-subheader'; + } + return array( 'class' => implode(' ', $classes), ); @@ -68,25 +90,25 @@ final class PHUITwoColumnView extends AphrontTagView { ), $this->mainColumn); - $side = phutil_tag( - 'div', - array( - 'class' => 'phui-side-column', - ), - $this->sideColumn); + $side = $this->buildSideColumn(); + $order = array($side, $main); - if ($this->getDisplay() == self::DISPLAY_LEFT) { - $order = array($side, $main); - } else { - $order = array($main, $side); - } - - $inner = phutil_tag_div('phui-two-column-row', $order); + $inner = phutil_tag_div('phui-two-column-row grouped', $order); $table = phutil_tag_div('phui-two-column-content', $inner); $header = null; if ($this->header) { - $header = phutil_tag_div('phui-two-column-header', $this->header); + if ($this->actionList) { + $this->header->setActionList($this->actionList); + } + $header = phutil_tag_div( + 'phui-two-column-header', $this->header); + } + + $subheader = null; + if ($this->subheader) { + $subheader = phutil_tag_div( + 'phui-two-column-subheader', $this->subheader); } return phutil_tag( @@ -96,7 +118,35 @@ final class PHUITwoColumnView extends AphrontTagView { ), array( $header, + $subheader, $table, )); } + + private function buildSideColumn() { + $property_list = $this->propertyList; + $action_list = $this->actionList; + + $properties = null; + if ($property_list || $action_list) { + if ($property_list) { + $property_list->setStacked(true); + } + + $properties = id(new PHUIObjectBoxView()) + ->appendChild($action_list) + ->appendChild($property_list) + ->addClass('phui-two-column-properties'); + } + + return phutil_tag( + 'div', + array( + 'class' => 'phui-side-column', + ), + array( + $properties, + $this->sideColumn, + )); + } } diff --git a/webroot/rsrc/css/application/countdown/timer.css b/webroot/rsrc/css/application/countdown/timer.css index 8b87aa6ed2..bbb2fdd684 100644 --- a/webroot/rsrc/css/application/countdown/timer.css +++ b/webroot/rsrc/css/application/countdown/timer.css @@ -4,9 +4,6 @@ .phabricator-timer { margin: 16px 16px 0 16px; - border: 1px solid {$lightblueborder}; - border-radius: 3px; - background: #ffffff; } .device .phabricator-timer { @@ -14,27 +11,20 @@ margin-right: 8px; } -.phabricator-remarkup .phabricator-timer { - max-width: 360px; +.phabricator-remarkup .phabricator-timer-view { + max-width: 460px; margin: 0 0 12px 0; } +.phabricator-timer .countdown-description { + border-bottom: 1px solid {$thinblueborder}; + padding-bottom: 16px; +} + .device-phone .phabricator-remarkup .phabricator-timer { width: auto; } -.phabricator-timer-header { - font-weight: bold; - padding: 8px; - background: {$bluebackground}; - border-radius: 3px 3px 0 0; -} - -.phabricator-timer-header a { - color: {$darkbluetext}; - font-weight: normal; -} - .phabricator-timer-table { width: 100%; margin: 8px 0 0 0; @@ -60,12 +50,11 @@ } .phabricator-timer-table td.phabricator-timer-foot { - font-size: {$normalfontsize}; + font-size: {$biggerfontsize}; line-height: 16px; border-top: 1px solid {$thinblueborder}; color: {$bluetext}; - font-weight: normal; - padding: 8px; + padding: 12px 0; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; text-align: center; diff --git a/webroot/rsrc/css/application/paste/paste.css b/webroot/rsrc/css/application/paste/paste.css index 78bfec2587..b9b2fe2dd2 100644 --- a/webroot/rsrc/css/application/paste/paste.css +++ b/webroot/rsrc/css/application/paste/paste.css @@ -2,14 +2,6 @@ * @provides paste-css */ -.container-of-paste { - margin: 16px 16px 0 16px; -} - -.device .container-of-paste { - margin: 8px 8px 0 8px; -} - .paste-embed { background: {$sh-yellowbackground}; border: 1px solid {$sh-lightyellowborder}; diff --git a/webroot/rsrc/css/application/ponder/ponder-view.css b/webroot/rsrc/css/application/ponder/ponder-view.css index a5bd01a6b1..8d0556ef87 100644 --- a/webroot/rsrc/css/application/ponder/ponder-view.css +++ b/webroot/rsrc/css/application/ponder/ponder-view.css @@ -2,40 +2,10 @@ * @provides ponder-view-css */ -.ponder-question-view { - background: #fff; - padding-bottom: 64px; -} - -.device-desktop .ponder-question-view.phui-two-column-view .phui-side-column { - width: 300px; -} - -.ponder-question-view .phui-object-box, -.ponder-question-view .phui-info-view { - margin-left: 0; - margin-right: 0; -} - -.device-phone .ponder-question-view .phui-profile-header.phui-header-shell - .phui-header-header { - font-size: 20px; -} - .ponder-question-container { border-top: 1px solid {$thinblueborder}; } -.ponder-question-content { - margin: 0 24px; - padding: 24px 0; - border-top: 1px solid rgba({$alphagrey}, .15); -} - -.device-phone .ponder-question-content { - margin: 0 16px; -} - .device .ponder-view-properties { border-left: none; border-right: none; @@ -57,59 +27,19 @@ border: none; } -.ponder-view-properties .phui-property-list-stacked - .phui-property-list-properties .phui-property-list-key { - padding: 0; +.phui-two-column-view .phui-main-column .ponder-question-content + .phui-box.ponder-answer-wiki { + margin: 24px 0; } -.ponder-view-properties .phui-property-list-stacked - .phui-property-list-properties .phui-property-list-value { - margin-bottom: 16px; - padding: 0; -} - -.phui-box.ponder-answer-wiki { +.ponder-answer-wiki .phabricator-remarkup { padding: 16px; - margin: 24px 0; -} - -.ponder-details-subtitle { - height: 24px; - line-height: 24px; - margin-bottom: 12px; - color: {$greytext}; - position: relative; - padding-left: 32px; -} - -.ponder-details-subtitle a { - color: {$darkgreytext}; -} - -.ponder-details-author-image { - height: 24px; - width: 24px; - background-size: 100%; - margin-right: 8px; - border-radius: 3px; - display: inline-block; - position: absolute; - top: 0; - left: 0; -} - -.ponder-detail-view .phabricator-remarkup { - margin-left: 32px; } .ponder-question-content .phui-timeline-view { padding-right: 0; } -.ponder-question-content .phui-timeline-view .phui-timeline-core-content { - background-color: {$lightbluebackground}; -} - .ponder-answer-view { margin-top: 16px; } @@ -123,7 +53,7 @@ margin-left: 12px; } -.ponder-question-view .ponder-answer-view .phui-header-shell { +.ponder-question-view .ponder-answer .phui-header-shell { padding: 4px 8px 3px 8px; } @@ -192,6 +122,7 @@ body .phui-main-column .ponder-question-content .ponder-answer-view .ponder-add-answer-header { margin-top: 64px; + margin-bottom: 20px; } .ponder-add-answer-view { @@ -200,9 +131,8 @@ body .phui-main-column .ponder-question-content .ponder-answer-view .ponder-question-content div.ponder-question-add-comment-view div.phui-box.phui-object-box { - background: {$lightbluebackground}; margin-right: 0; - margin-left: 32px; + margin-left: 62px; } .device .ponder-question-content div.ponder-question-add-comment-view @@ -210,19 +140,6 @@ body .phui-main-column .ponder-question-content .ponder-answer-view margin: 0; } -.ponder-add-answer-view .phui-form-full-width.phui-form-view - label.aphront-form-label, -.ponder-question-add-comment-view .phui-form-full-width.phui-form-view - label.aphront-form-label{ - display: none; -} - -.ponder-add-answer-view.phui-box-grey .phui-header-shell { - border: none; - padding-bottom: 8px; -} - -.ponder-add-answer-view .remarkup-assist-textarea, .ponder-question-add-comment-view .remarkup-assist-textarea { height: 8em; } diff --git a/webroot/rsrc/css/application/project/project-view.css b/webroot/rsrc/css/application/project/project-view.css index be3e8b67f4..2c0fd7d6d8 100644 --- a/webroot/rsrc/css/application/project/project-view.css +++ b/webroot/rsrc/css/application/project/project-view.css @@ -2,11 +2,6 @@ * @provides project-view-css */ -.project-view-home { - padding-bottom: 64px; - background: #fff; -} - .project-view-header-tag { margin-left: 8px; font-size: {$normalfontsize}; @@ -24,25 +19,35 @@ color: {$bluetext}; } -.project-view-home .phui-box.project-view-properties { - margin: 0 16px 16px 16px; - padding: 4px 12px; - border: 2px solid rgba({$alphagrey},.1); - background-color: #F7F7F9; +.device .project-view-home .phui-two-column-row { + display: flex; + flex-direction: column-reverse; } +.project-view-home .phui-box.project-view-properties { + margin: 0 0 16px 0; + padding: 0; + border: 1px solid rgba({$alphagrey}, .2); + background-color: #fff; +} + +.device-desktop .phui-two-column-view .project-view-properties + .phui-property-list-container { + padding: 12px 0; + } + .device-phone .phui-box.project-view-properties { margin: 0 12px 0 12px; } .project-view-properties .phui-property-list-container + .phui-property-list-text-content { - border-color: rgba({$alphagrey},.15); + border-color: rgba({$alphagrey},.2); } .project-view-properties .phui-property-list-key { width: auto; - margin-left: 4px2 + margin-left: 4px; } .project-view-properties .phui-property-list-section-header { @@ -50,23 +55,8 @@ padding: 12px 4px 0; } -.project-view-feed .phui-object-box.phui-box-border { - padding: 0 4px 8px 4px; - border: none; -} - -.project-view-feed .phui-object-box .phui-header-shell { - padding: 8px 4px; -} - -.project-view-feed .phui-header-header { - font-size: {$biggerfontsize}; - margin-left: 8px; -} - -.device-desktop .project-view-feed .phui-feed-story, -.device-tablet .project-view-feed .phui-feed-story { - padding-left: 22px; +.project-view-feed.phui-object-box.phui-box-border { + border: 1px solid rgba({$alphagrey}, .2); } .project-view-home .phui-box-grey { @@ -81,13 +71,17 @@ font-size: {$biggerfontsize}; } +.project-view-home .phui-box-grey .phui-header-action-link { + margin-top: 0; + margin-bottom: 0; +} + .project-view-home .phui-box-grey .phui-object-item-list-view { padding: 4px 8px 0 8px; } .project-view-badges .phui-badge-flex-view { background-color: #fff; - width: 340px; } .project-view-home .phui-box-grey .phui-object-item-attribute .phui-icon-view { diff --git a/webroot/rsrc/css/application/slowvote/slowvote.css b/webroot/rsrc/css/application/slowvote/slowvote.css index afa45a8032..907ff0c242 100644 --- a/webroot/rsrc/css/application/slowvote/slowvote.css +++ b/webroot/rsrc/css/application/slowvote/slowvote.css @@ -2,22 +2,8 @@ * @provides phabricator-slowvote-css */ -.slowvote-embed { - background: #fff; - border-color: {$lightblueborder}; - border-radius: 3px; -} - -.slowvote-header { - font-weight: bold; - line-height: 16px; - border-bottom: 1px solid #bbbbbb; -} - .slowvote-description { - color: {$greytext}; - font-size: {$biggerfontsize}; - padding: 12px 4px 4px; + padding: 12px 16px 4px; } .slowvote-header-content { @@ -25,7 +11,7 @@ } .slowvote-body-content { - padding: 8px 4px 0; + padding: 8px 16px; } .slowvote-option-label { @@ -121,7 +107,7 @@ } .slowvote-footer-content { - padding: 8px; + padding: 8px 16px; overflow: hidden; } diff --git a/webroot/rsrc/css/phui/phui-box.css b/webroot/rsrc/css/phui/phui-box.css index 1516285cf8..38ca1d7610 100644 --- a/webroot/rsrc/css/phui/phui-box.css +++ b/webroot/rsrc/css/phui/phui-box.css @@ -15,7 +15,7 @@ .phui-box-grey { background-color: #F7F7F9; border-radius: 3px; - border-color: rgba({$alphagrey},.1); + border-color: rgba({$alphagrey},.2); } .phui-box-blue { @@ -55,3 +55,33 @@ border: none; color: {$greytext}; } + + +/* Property Boxes */ + +.phui-box.phui-box-blue-property { + border-radius: 3px; + border-color: {$lightblueborder}; + margin: 0; + padding: 0; +} + +.device .phui-box.phui-box-blue-property { + padding: 0; +} + +.phui-box.phui-object-box.phui-box-blue-property .phui-header-shell { + background-color: #eff3fc; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + padding: 6px 16px; +} + +.device .phui-box.phui-box-blue-property .phui-header-shell { + padding: 6px 12px; +} + +.phui-box.phui-box-blue-property .phui-header-header { + font-size: 13px; + color: {$bluetext}; +} diff --git a/webroot/rsrc/css/phui/phui-button.css b/webroot/rsrc/css/phui/phui-button.css index 0ba3007e5f..837c093872 100644 --- a/webroot/rsrc/css/phui/phui-button.css +++ b/webroot/rsrc/css/phui/phui-button.css @@ -60,7 +60,8 @@ input[type="submit"].grey, a.grey, a.grey:visited { background-color: #F7F7F9; - border: 1px solid rgba({$alphagrey},.1); + background-image: linear-gradient(to bottom, #ffffff, #f1f0f1); + border: 1px solid rgba({$alphablue},.2); color: {$darkgreytext}; } @@ -106,8 +107,8 @@ button:hover { a.button.grey:hover, button.grey:hover { - background-color: rgba({$alphablue}, 0.1); - border-color: rgba({$alphablue}, 0.15); + background-image: linear-gradient(to bottom, #ffffff, #eeebec); + border-color: rgba({$alphablue}, 0.3); transition: 0.1s; } diff --git a/webroot/rsrc/css/phui/phui-head-thing.css b/webroot/rsrc/css/phui/phui-head-thing.css new file mode 100644 index 0000000000..bce67ef387 --- /dev/null +++ b/webroot/rsrc/css/phui/phui-head-thing.css @@ -0,0 +1,33 @@ +/** + * @provides phui-head-thing-view-css + */ + +.phui-head-thing-view { + height: 24px; + line-height: 22px; + color: {$greytext}; + position: relative; + padding-left: 32px; +} + +.device-phone .phui-head-thing-view { + min-height: 24px; + height: auto; + line-height: inherit; +} + +.phui-head-thing-view a { + color: {$darkgreytext}; +} + +.phui-head-thing-image { + height: 24px; + width: 24px; + background-size: 100%; + margin-right: 8px; + border-radius: 3px; + display: inline-block; + position: absolute; + top: 0; + left: 0; +} diff --git a/webroot/rsrc/css/phui/phui-header-view.css b/webroot/rsrc/css/phui/phui-header-view.css index c364059fc5..b743e1de7b 100644 --- a/webroot/rsrc/css/phui/phui-header-view.css +++ b/webroot/rsrc/css/phui/phui-header-view.css @@ -185,7 +185,7 @@ body .phui-header-shell.phui-bleed-header .phui-header-subheader .phui-header-status { padding: 3px 9px; border-radius: 3px; - background: rgba({$alphablue}, 0.06); + background: rgba({$alphablue}, 0.08); margin-right: 8px; } diff --git a/webroot/rsrc/css/phui/phui-object-box.css b/webroot/rsrc/css/phui/phui-object-box.css index d7452c2126..f9f06e2d18 100644 --- a/webroot/rsrc/css/phui/phui-object-box.css +++ b/webroot/rsrc/css/phui/phui-object-box.css @@ -120,6 +120,10 @@ div.phui-object-box.phui-object-box-flush { margin: 0; } +.phui-object-box .phui-box-border.phui-box-blue-property { + border-width: 1px; +} + .phui-object-box .phui-object-box .phui-header-shell .phui-header-header { font-size: {$normalfontsize}; margin: 0; diff --git a/webroot/rsrc/css/phui/phui-two-column-view.css b/webroot/rsrc/css/phui/phui-two-column-view.css index 6e0880a4d9..91e236ec6b 100644 --- a/webroot/rsrc/css/phui/phui-two-column-view.css +++ b/webroot/rsrc/css/phui/phui-two-column-view.css @@ -2,57 +2,191 @@ * @provides phui-two-column-view-css */ -.phui-two-column-view { +.phui-two-column-view .phui-two-column-header { background-color: #fff; + border-bottom: 1px solid rgba({$alphagrey}, .12); + margin-bottom: 24px; } -.phui-two-column-container { - max-width: 1024px; - margin: 0 auto; +.phui-two-column-view.with-subheader .phui-two-column-header { + margin-bottom: 0; +} + +.phui-two-column-header .phui-header-header { + font-size: 20px; + font-family: 'Aleo', {$fontfamily}; + color: #000; +} + +.device-phone .phui-two-column-header .phui-header-header { + font-size: 18px; } .phui-two-column-view .phui-two-column-header .phui-header-shell { - padding-bottom: 32px; + padding: 24px 32px 28px; + border: none; } -.device-phone .phui-two-column-view .phui-two-column-header .phui-header-shell { - padding-bottom: 20px; +.phui-two-column-view .phui-two-column-header + .phui-profile-header.phui-header-shell { + padding-bottom: 20px; } -.phui-two-column-fluid .phui-two-column-container { - max-width: 100%; +.device .phui-two-column-view .phui-two-column-header .phui-header-shell { + padding: 12px 12px 16px; } -.phui-two-column-content { - display: table; - width: 100%; +.phui-two-column-header .phui-header-subheader { + margin-top: 12px; } -.phui-two-column-row { - display: table-row; +.phui-two-column-subheader { + padding: 12px 32px; +} + +.device .phui-two-column-subheader { + padding: 12px 16px; +} + +.device-desktop .phui-two-column-content { + padding: 0 32px; +} + +.device .phui-two-column-content { + padding: 0 12px; } .device-desktop .phui-two-column-view .phui-main-column { - display: table-cell; - vertical-align: top; + float: left; + width: calc(100% - 320px); } .device-desktop .phui-two-column-view .phui-side-column { - width: 320px; - display: table-cell; - vertical-align: top; + float: right; + width: 300px; } -.device-desktop .phui-two-column-view - .phui-main-column .phui-object-box:first-child { - margin: 0 16px 0 16px; +.device .phui-side-column { + margin-bottom: 20px; } -.device-desktop .phui-two-column-view - .phui-side-column .phui-object-box { - margin: 0 16px 16px 0; +.phui-two-column-view .phui-two-column-content + .phui-object-box { + margin: 0 0 20px 0; } -.phui-two-column-view pre { - white-space: pre-wrap; +/* Timeline */ + +.phui-two-column-view .phui-timeline-view { + padding: 0; + background-position: 78px; +} + +.phui-two-column-view .phui-main-column .phui-object-box + .phui-timeline-view { + margin-top: -20px; +} + +.device .phui-two-column-view .phui-timeline-view { + background-position: 16px; + padding: 0; +} + +.device-phone .phui-two-column-view .phui-timeline-event-view { + margin: 0; +} + +/* Main Column Properties */ + +.device-desktop .phui-main-column .phui-property-list-key { + margin-left: 0; + width: 140px; +} + +.device-desktop .phui-main-column .phui-property-list-value { + margin-left: 8px; + width: auto; +} + + +/* Property / Action List */ + +.phui-two-column-properties .phabricator-action-list-view { + padding-top: 4px; +} + +.device-desktop .phui-two-column-view .phui-property-list-container { + padding: 12px 16px; +} + +.device .phui-two-column-view .phui-property-list-container { + padding: 12px 8px; +} + +.phui-two-column-properties.phui-object-box { + border: 1px solid rgba({$alphablue}, .2); +} + +.phui-two-column-properties .phui-property-list-stacked + .phui-property-list-properties .phui-property-list-key { + margin: 20px 0 8px 0; + padding: 20px 4px 0; + border-top: 1px solid rgba({$alphablue}, .2); +} + +.phui-two-column-properties .phui-property-list-stacked + .phui-property-list-properties .phui-property-list-value { + margin: 0; + padding: 0 4px; +} + +.device-desktop .phui-two-column-properties .phui-property-list-container { + padding: 0 0 20px 0; +} + +.device .phui-two-column-properties .phui-property-list-stacked + .phui-property-list-properties .phui-property-list-key { + margin: 12px 0 4px 0; + padding: 0; + border: none; +} + +.device .phui-two-column-properties .phui-property-list-container { + padding: 0 0 12px 0; +} + +.device .phui-two-column-content .phui-two-column-properties.phui-object-box { + padding: 0 12px; +} + +.phui-two-column-properties .phabricator-action-view-icon { + top: 8px; + left: 8px; +} + +.phabricator-action-view button.phabricator-action-view-item, +.phabricator-action-view-item { + padding: 5px 4px 5px 28px; +} + +.device-desktop .phui-two-column-properties .phabricator-action-view:hover + .phabricator-action-view-item { + text-decoration: none; + background-color: rgba({$alphablue}, .08); + color: {$sky}; + border-radius: 3px; +} + +.device-desktop .phui-two-column-properties .phabricator-action-view:hover + .phabricator-action-view-icon { + color: {$sky}; +} + +.phui-two-column-view .phui-property-list-section-header, +.phui-two-column-view .phui-property-list-text-content { + margin: 0 16px; +} + +.device .phui-two-column-view .phui-property-list-section-header, +.device .phui-two-column-view .phui-property-list-text-content { + margin: 0 8px; }