@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Chad Little and committed by
epriestley
fe7e288c 8240e0f7

+734 -491
+25 -23
resources/celerity/map.php
··· 7 7 */ 8 8 return array( 9 9 'names' => array( 10 - 'core.pkg.css' => '76a3afdf', 10 + 'core.pkg.css' => 'e50c063a', 11 11 'core.pkg.js' => '7d8faf57', 12 12 'darkconsole.pkg.js' => 'e7393ebb', 13 13 'differential.pkg.css' => '2de124c9', ··· 52 52 'rsrc/css/application/conpherence/update.css' => 'faf6be09', 53 53 'rsrc/css/application/conpherence/widget-pane.css' => '775eaaba', 54 54 'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4', 55 - 'rsrc/css/application/countdown/timer.css' => 'e7544472', 55 + 'rsrc/css/application/countdown/timer.css' => '96696f21', 56 56 'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a', 57 57 'rsrc/css/application/dashboard/dashboard.css' => 'eb458607', 58 58 'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', ··· 79 79 'rsrc/css/application/maniphest/task-summary.css' => '11cc5344', 80 80 'rsrc/css/application/objectselector/object-selector.css' => '85ee8ce6', 81 81 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 82 - 'rsrc/css/application/paste/paste.css' => 'a5157c48', 82 + 'rsrc/css/application/paste/paste.css' => '1898e534', 83 83 'rsrc/css/application/people/people-profile.css' => '2473d929', 84 84 'rsrc/css/application/phame/phame.css' => '737792d6', 85 85 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', ··· 92 92 'rsrc/css/application/policy/policy-edit.css' => '815c66f7', 93 93 'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43', 94 94 'rsrc/css/application/policy/policy.css' => '957ea14c', 95 - 'rsrc/css/application/ponder/ponder-view.css' => '212495e0', 95 + 'rsrc/css/application/ponder/ponder-view.css' => '4e321d68', 96 96 'rsrc/css/application/project/project-card-view.css' => '9418c97d', 97 - 'rsrc/css/application/project/project-view.css' => '298b7c5b', 97 + 'rsrc/css/application/project/project-view.css' => '9ce99f21', 98 98 'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733', 99 99 'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', 100 100 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 101 101 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 102 102 'rsrc/css/application/search/search-results.css' => '7dea472c', 103 - 'rsrc/css/application/slowvote/slowvote.css' => 'da0afb1b', 103 + 'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230', 104 104 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 105 105 'rsrc/css/application/uiexample/example.css' => '528b19de', 106 - 'rsrc/css/core/core.css' => '5b3563c8', 106 + 'rsrc/css/core/core.css' => 'd0801452', 107 107 'rsrc/css/core/remarkup.css' => 'fc228f08', 108 108 'rsrc/css/core/syntax.css' => '9fd11da8', 109 109 'rsrc/css/core/z-index.css' => '5b6fcf3f', ··· 123 123 'rsrc/css/phui/phui-action-panel.css' => '91c7b835', 124 124 'rsrc/css/phui/phui-badge.css' => 'f25c3476', 125 125 'rsrc/css/phui/phui-big-info-view.css' => 'bd903741', 126 - 'rsrc/css/phui/phui-box.css' => 'dd1294d3', 127 - 'rsrc/css/phui/phui-button.css' => 'edf464e9', 126 + 'rsrc/css/phui/phui-box.css' => '348bd872', 127 + 'rsrc/css/phui/phui-button.css' => 'c096e4e9', 128 128 'rsrc/css/phui/phui-chart.css' => '6bf6f78e', 129 129 'rsrc/css/phui/phui-crumbs-view.css' => '79d536e5', 130 130 'rsrc/css/phui/phui-document-pro.css' => '92d5b648', ··· 134 134 'rsrc/css/phui/phui-fontkit.css' => '9cda225e', 135 135 'rsrc/css/phui/phui-form-view.css' => '4a1a0f5e', 136 136 'rsrc/css/phui/phui-form.css' => 'aac1d51d', 137 - 'rsrc/css/phui/phui-header-view.css' => 'a6d7b20d', 137 + 'rsrc/css/phui/phui-head-thing.css' => '11731da0', 138 + 'rsrc/css/phui/phui-header-view.css' => 'b541cc78', 138 139 'rsrc/css/phui/phui-hovercard.css' => 'de1a2119', 139 140 'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad', 140 141 'rsrc/css/phui/phui-icon.css' => '3f33ab57', ··· 142 143 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 143 144 'rsrc/css/phui/phui-info-view.css' => '6d7c3509', 144 145 'rsrc/css/phui/phui-list.css' => '9da2aa00', 145 - 'rsrc/css/phui/phui-object-box.css' => '407eaf5a', 146 + 'rsrc/css/phui/phui-object-box.css' => '91628842', 146 147 'rsrc/css/phui/phui-object-item-list-view.css' => '18b2ce8e', 147 148 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 148 149 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', ··· 154 155 'rsrc/css/phui/phui-status.css' => '888cedb8', 155 156 'rsrc/css/phui/phui-tag-view.css' => '9d5d4400', 156 157 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', 157 - 'rsrc/css/phui/phui-two-column-view.css' => 'a317616a', 158 + 'rsrc/css/phui/phui-two-column-view.css' => '7c5d0741', 158 159 'rsrc/css/phui/workboards/phui-workboard-color.css' => 'ac6fe6a7', 159 160 'rsrc/css/phui/workboards/phui-workboard.css' => 'e6d89647', 160 161 'rsrc/css/phui/workboards/phui-workcard.css' => '3646fb96', ··· 740 741 'multirow-row-manager' => 'b5d57730', 741 742 'owners-path-editor' => 'aa1733d0', 742 743 'owners-path-editor-css' => '2f00933b', 743 - 'paste-css' => 'a5157c48', 744 + 'paste-css' => '1898e534', 744 745 'path-typeahead' => 'f7fc67ec', 745 746 'people-profile-css' => '2473d929', 746 747 'phabricator-action-list-view-css' => 'c5eba19d', ··· 748 749 'phabricator-busy' => '59a7976a', 749 750 'phabricator-chatlog-css' => 'd295b020', 750 751 'phabricator-content-source-view-css' => '4b8b05d4', 751 - 'phabricator-core-css' => '5b3563c8', 752 - 'phabricator-countdown-css' => 'e7544472', 752 + 'phabricator-core-css' => 'd0801452', 753 + 'phabricator-countdown-css' => '96696f21', 753 754 'phabricator-dashboard-css' => 'eb458607', 754 755 'phabricator-drag-and-drop-file-upload' => '81f182b5', 755 756 'phabricator-draggable-list' => '5a13c79f', ··· 772 773 'phabricator-search-results-css' => '7dea472c', 773 774 'phabricator-shaped-request' => '7cbe244b', 774 775 'phabricator-side-menu-view-css' => '3a3d9f41', 775 - 'phabricator-slowvote-css' => 'da0afb1b', 776 + 'phabricator-slowvote-css' => 'a94b7230', 776 777 'phabricator-source-code-view-css' => 'cbeef983', 777 778 'phabricator-standard-page-view' => 'e709f6d0', 778 779 'phabricator-textareautils' => '5813016a', ··· 802 803 'phui-action-panel-css' => '91c7b835', 803 804 'phui-badge-view-css' => 'f25c3476', 804 805 'phui-big-info-view-css' => 'bd903741', 805 - 'phui-box-css' => 'dd1294d3', 806 - 'phui-button-css' => 'edf464e9', 806 + 'phui-box-css' => '348bd872', 807 + 'phui-button-css' => 'c096e4e9', 807 808 'phui-calendar-css' => 'ccabe893', 808 809 'phui-calendar-day-css' => 'd1cf6f93', 809 810 'phui-calendar-list-css' => 'c1c7f338', ··· 818 819 'phui-fontkit-css' => '9cda225e', 819 820 'phui-form-css' => 'aac1d51d', 820 821 'phui-form-view-css' => '4a1a0f5e', 821 - 'phui-header-view-css' => 'a6d7b20d', 822 + 'phui-head-thing-view-css' => '11731da0', 823 + 'phui-header-view-css' => 'b541cc78', 822 824 'phui-hovercard' => '1bd28176', 823 825 'phui-hovercard-view-css' => 'de1a2119', 824 826 'phui-icon-set-selector-css' => '1ab67aad', ··· 828 830 'phui-info-view-css' => '6d7c3509', 829 831 'phui-inline-comment-view-css' => '0fdb3667', 830 832 'phui-list-view-css' => '9da2aa00', 831 - 'phui-object-box-css' => '407eaf5a', 833 + 'phui-object-box-css' => '91628842', 832 834 'phui-object-item-list-view-css' => '18b2ce8e', 833 835 'phui-pager-css' => 'bea33d23', 834 836 'phui-pinboard-view-css' => '2495140e', ··· 841 843 'phui-tag-view-css' => '9d5d4400', 842 844 'phui-theme-css' => '027ba77e', 843 845 'phui-timeline-view-css' => '2efceff8', 844 - 'phui-two-column-view-css' => 'a317616a', 846 + 'phui-two-column-view-css' => '7c5d0741', 845 847 'phui-workboard-color-css' => 'ac6fe6a7', 846 848 'phui-workboard-view-css' => 'e6d89647', 847 849 'phui-workcard-view-css' => '3646fb96', ··· 855 857 'policy-css' => '957ea14c', 856 858 'policy-edit-css' => '815c66f7', 857 859 'policy-transaction-detail-css' => '82100a43', 858 - 'ponder-view-css' => '212495e0', 860 + 'ponder-view-css' => '4e321d68', 859 861 'project-card-view-css' => '9418c97d', 860 - 'project-view-css' => '298b7c5b', 862 + 'project-view-css' => '9ce99f21', 861 863 'releeph-core' => '9b3c5733', 862 864 'releeph-preview-branch' => 'b7a6f4a5', 863 865 'releeph-request-differential-create-dialog' => '8d8b92cd',
+3 -1
src/__phutil_library_map__.php
··· 1524 1524 'PHUIHandleListView' => 'applications/phid/view/PHUIHandleListView.php', 1525 1525 'PHUIHandleTagListView' => 'applications/phid/view/PHUIHandleTagListView.php', 1526 1526 'PHUIHandleView' => 'applications/phid/view/PHUIHandleView.php', 1527 + 'PHUIHeadThingView' => 'view/phui/PHUIHeadThingView.php', 1527 1528 'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php', 1528 1529 'PHUIHovercardUIExample' => 'applications/uiexample/examples/PHUIHovercardUIExample.php', 1529 1530 'PHUIHovercardView' => 'view/phui/PHUIHovercardView.php', ··· 5758 5759 'PHUIHandleListView' => 'AphrontTagView', 5759 5760 'PHUIHandleTagListView' => 'AphrontTagView', 5760 5761 'PHUIHandleView' => 'AphrontView', 5762 + 'PHUIHeadThingView' => 'AphrontTagView', 5761 5763 'PHUIHeaderView' => 'AphrontTagView', 5762 5764 'PHUIHovercardUIExample' => 'PhabricatorUIExample', 5763 5765 'PHUIHovercardView' => 'AphrontTagView', ··· 6380 6382 'PhabricatorCountdownTransaction' => 'PhabricatorApplicationTransaction', 6381 6383 'PhabricatorCountdownTransactionComment' => 'PhabricatorApplicationTransactionComment', 6382 6384 'PhabricatorCountdownTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 6383 - 'PhabricatorCountdownView' => 'AphrontTagView', 6385 + 'PhabricatorCountdownView' => 'AphrontView', 6384 6386 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 6385 6387 'PhabricatorCredentialsUsedByObjectEdgeType' => 'PhabricatorEdgeType', 6386 6388 'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery',
+1 -4
src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php
··· 192 192 'sh-disabledbackground' => '#f3f3f3', 193 193 194 194 // Background color for "most" themes. 195 - 'page.background' => '#f1f1f4', 196 - 197 - // Background color for "dark" themes. 198 - 'page.background.dark' => '#ebecee', 195 + 'page.background' => '#f8f8fb', 199 196 200 197 'menu.profile.text' => 'rgba(255,255,255,.8)', 201 198 'menu.profile.text.selected' => 'rgba(255,255,255,1)',
+42 -32
src/applications/countdown/controller/PhabricatorCountdownViewController.php
··· 21 21 22 22 $countdown_view = id(new PhabricatorCountdownView()) 23 23 ->setUser($viewer) 24 - ->setCountdown($countdown) 25 - ->setHeadless(true); 24 + ->setCountdown($countdown); 26 25 27 26 $id = $countdown->getID(); 28 27 $title = $countdown->getTitle(); 29 28 30 29 $crumbs = $this 31 30 ->buildApplicationCrumbs() 32 - ->addTextCrumb("C{$id}"); 31 + ->addTextCrumb("C{$id}") 32 + ->setBorder(true); 33 33 34 34 $epoch = $countdown->getEpoch(); 35 35 if ($epoch >= PhabricatorTime::getNow()) { ··· 49 49 ->setStatus($icon, $color, $status); 50 50 51 51 $actions = $this->buildActionListView($countdown); 52 - $properties = $this->buildPropertyListView($countdown, $actions); 53 - 54 - $object_box = id(new PHUIObjectBoxView()) 55 - ->setHeader($header) 56 - ->addPropertyList($properties); 52 + $properties = $this->buildPropertyListView($countdown); 53 + $subheader = $this->buildSubheaderView($countdown); 57 54 58 55 $timeline = $this->buildTransactionTimeline( 59 56 $countdown, 60 57 new PhabricatorCountdownTransactionQuery()); 61 - 62 58 $add_comment = $this->buildCommentForm($countdown); 63 59 60 + $content = array( 61 + $countdown_view, 62 + $timeline, 63 + $add_comment, 64 + ); 64 65 66 + $view = id(new PHUITwoColumnView()) 67 + ->setHeader($header) 68 + ->setSubheader($subheader) 69 + ->setMainColumn($content) 70 + ->setPropertyList($properties) 71 + ->setActionList($actions); 65 72 66 73 return $this->newPage() 67 74 ->setTitle($title) ··· 72 79 )) 73 80 ->appendChild( 74 81 array( 75 - $object_box, 76 - $countdown_view, 77 - $timeline, 78 - $add_comment, 82 + $view, 79 83 )); 80 84 } 81 85 ··· 114 118 } 115 119 116 120 private function buildPropertyListView( 117 - PhabricatorCountdown $countdown, 118 - PhabricatorActionListView $actions) { 119 - 121 + PhabricatorCountdown $countdown) { 120 122 $viewer = $this->getViewer(); 121 - 122 123 $view = id(new PHUIPropertyListView()) 123 124 ->setUser($viewer) 124 - ->setObject($countdown) 125 - ->setActionList($actions); 125 + ->setObject($countdown); 126 + $view->invokeWillRenderEvent(); 127 + return $view; 128 + } 126 129 127 - $view->addProperty( 128 - pht('Author'), 129 - $viewer->renderHandle($countdown->getAuthorPHID())); 130 + private function buildSubheaderView( 131 + PhabricatorCountdown $countdown) { 132 + $viewer = $this->getViewer(); 133 + 134 + $author = $viewer->renderHandle($countdown->getAuthorPHID())->render(); 135 + $date = phabricator_datetime($countdown->getDateCreated(), $viewer); 136 + $author = phutil_tag('strong', array(), $author); 137 + 138 + $person = id(new PhabricatorPeopleQuery()) 139 + ->setViewer($viewer) 140 + ->withPHIDs(array($countdown->getAuthorPHID())) 141 + ->needProfileImage(true) 142 + ->executeOne(); 130 143 131 - $view->invokeWillRenderEvent(); 144 + $image_uri = $person->getProfileImageURI(); 145 + $image_href = '/p/'.$person->getUsername(); 132 146 133 - $description = $countdown->getDescription(); 134 - if (strlen($description)) { 135 - $description = new PHUIRemarkupView($viewer, $description); 136 - $view->addSectionHeader( 137 - pht('Description'), 138 - PHUIPropertyListView::ICON_SUMMARY); 139 - $view->addTextContent($description); 140 - } 147 + $content = pht('Authored by %s on %s.', $author, $date); 141 148 142 - return $view; 149 + return id(new PHUIHeadThingView()) 150 + ->setImage($image_uri) 151 + ->setImageHref($image_href) 152 + ->setContent($content); 143 153 } 144 154 145 155 private function buildCommentForm(PhabricatorCountdown $countdown) {
+29 -29
src/applications/countdown/view/PhabricatorCountdownView.php
··· 1 1 <?php 2 2 3 - final class PhabricatorCountdownView extends AphrontTagView { 3 + final class PhabricatorCountdownView extends AphrontView { 4 4 5 5 private $countdown; 6 - private $headless; 7 - 8 - 9 - public function setHeadless($headless) { 10 - $this->headless = $headless; 11 - return $this; 12 - } 13 6 14 7 public function setCountdown(PhabricatorCountdown $countdown) { 15 8 $this->countdown = $countdown; 16 9 return $this; 17 10 } 18 11 19 - 20 - protected function getTagContent() { 12 + public function render() { 21 13 $countdown = $this->countdown; 22 - 23 14 require_celerity_resource('phabricator-countdown-css'); 24 15 25 - $header = null; 26 - if (!$this->headless) { 27 - $header = phutil_tag( 28 - 'div', 16 + $header_text = array( 17 + 'C'.$countdown->getID(), 18 + ' ', 19 + phutil_tag( 20 + 'a', 29 21 array( 30 - 'class' => 'phabricator-timer-header', 22 + 'href' => '/countdown/'.$countdown->getID(), 31 23 ), 32 - array( 33 - 'C'.$countdown->getID(), 34 - ' ', 35 - phutil_tag( 36 - 'a', 37 - array( 38 - 'href' => '/countdown/'.$countdown->getID(), 39 - ), 40 - $countdown->getTitle()), 41 - )); 42 - } 24 + $countdown->getTitle()), 25 + ); 43 26 27 + $header = id(new PHUIHeaderView()) 28 + ->setHeader($header_text); 44 29 45 30 $ths = array( 46 31 phutil_tag('th', array(), pht('Days')), ··· 66 51 ), 67 52 $launch_date); 68 53 54 + $description = $countdown->getDescription(); 55 + if (strlen($description)) { 56 + $description = new PHUIRemarkupView($this->getUser(), $description); 57 + $description = phutil_tag( 58 + 'div', 59 + array( 60 + 'class' => 'countdown-description phabricator-remarkup', 61 + ), 62 + $description); 63 + } 64 + 69 65 $container = celerity_generate_unique_node_id(); 70 66 $content = phutil_tag( 71 67 'div', 72 68 array('class' => 'phabricator-timer', 'id' => $container), 73 69 array( 74 - $header, 70 + $description, 75 71 phutil_tag('table', array('class' => 'phabricator-timer-table'), array( 76 72 phutil_tag('tr', array(), $ths), 77 73 phutil_tag('tr', array(), $dashes), ··· 84 80 'container' => $container, 85 81 )); 86 82 87 - return $content; 83 + return id(new PHUIObjectBoxView()) 84 + ->setHeader($header) 85 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 86 + ->addClass('phabricator-timer-view') 87 + ->appendChild($content); 88 88 } 89 89 90 90 }
+63 -19
src/applications/passphrase/controller/PassphraseCredentialViewController.php
··· 28 28 $title = pht('%s %s', 'K'.$credential->getID(), $credential->getName()); 29 29 $crumbs = $this->buildApplicationCrumbs(); 30 30 $crumbs->addTextCrumb('K'.$credential->getID()); 31 + $crumbs->setBorder(true); 31 32 32 33 $header = $this->buildHeaderView($credential); 33 34 $actions = $this->buildActionView($credential, $type); 34 - $properties = $this->buildPropertyView($credential, $type, $actions); 35 + $properties = $this->buildPropertyView($credential, $type); 36 + $subheader = $this->buildSubheaderView($credential); 37 + $content = $this->buildDetailsView($credential, $type); 35 38 36 - $box = id(new PHUIObjectBoxView()) 39 + $view = id(new PHUITwoColumnView()) 37 40 ->setHeader($header) 38 - ->addPropertyList($properties); 41 + ->setSubheader($subheader) 42 + ->setMainColumn(array($content, $timeline)) 43 + ->setPropertyList($properties) 44 + ->setActionList($actions); 39 45 40 - return $this->buildApplicationPage( 41 - array( 42 - $crumbs, 43 - $box, 44 - $timeline, 45 - ), 46 - array( 47 - 'title' => $title, 46 + return $this->newPage() 47 + ->setTitle($title) 48 + ->setCrumbs($crumbs) 49 + ->appendChild( 50 + array( 51 + $view, 48 52 )); 49 53 } 50 54 ··· 63 67 return $header; 64 68 } 65 69 70 + private function buildSubheaderView( 71 + PassphraseCredential $credential) { 72 + $viewer = $this->getViewer(); 73 + 74 + $author = $viewer->renderHandle($credential->getAuthorPHID())->render(); 75 + $date = phabricator_datetime($credential->getDateCreated(), $viewer); 76 + $author = phutil_tag('strong', array(), $author); 77 + 78 + $person = id(new PhabricatorPeopleQuery()) 79 + ->setViewer($viewer) 80 + ->withPHIDs(array($credential->getAuthorPHID())) 81 + ->needProfileImage(true) 82 + ->executeOne(); 83 + 84 + if (!$person) { 85 + return null; 86 + } 87 + 88 + $image_uri = $person->getProfileImageURI(); 89 + $image_href = '/p/'.$credential->getUsername(); 90 + 91 + $content = pht('Created by %s on %s.', $author, $date); 92 + 93 + return id(new PHUIHeadThingView()) 94 + ->setImage($image_uri) 95 + ->setImageHref($image_href) 96 + ->setContent($content); 97 + } 98 + 66 99 private function buildActionView( 67 100 PassphraseCredential $credential, 68 101 PassphraseCredentialType $type) { ··· 153 186 return $actions; 154 187 } 155 188 156 - private function buildPropertyView( 189 + private function buildDetailsView( 157 190 PassphraseCredential $credential, 158 - PassphraseCredentialType $type, 159 - PhabricatorActionListView $actions) { 191 + PassphraseCredentialType $type) { 160 192 $viewer = $this->getRequest()->getUser(); 161 193 162 194 $properties = id(new PHUIPropertyListView()) 163 - ->setUser($viewer) 164 - ->setObject($credential) 165 - ->setActionList($actions); 195 + ->setUser($viewer); 166 196 167 197 $properties->addProperty( 168 198 pht('Credential Type'), ··· 192 222 $viewer->renderHandleList($used_by_phids)); 193 223 } 194 224 195 - $properties->invokeWillRenderEvent(); 196 - 197 225 $description = $credential->getDescription(); 198 226 if (strlen($description)) { 199 227 $properties->addSectionHeader( ··· 203 231 new PHUIRemarkupView($viewer, $description)); 204 232 } 205 233 234 + return id(new PHUIObjectBoxView()) 235 + ->setHeaderText(pht('PROPERTIES')) 236 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 237 + ->appendChild($properties); 238 + } 239 + 240 + private function buildPropertyView( 241 + PassphraseCredential $credential, 242 + PassphraseCredentialType $type) { 243 + $viewer = $this->getRequest()->getUser(); 244 + 245 + $properties = id(new PHUIPropertyListView()) 246 + ->setUser($viewer) 247 + ->setObject($credential); 248 + 249 + $properties->invokeWillRenderEvent(); 206 250 return $properties; 207 251 } 208 252
+45 -32
src/applications/paste/controller/PhabricatorPasteViewController.php
··· 48 48 49 49 $header = $this->buildHeaderView($paste); 50 50 $actions = $this->buildActionView($viewer, $paste); 51 - $properties = $this->buildPropertyView($paste, $fork_phids, $actions); 52 - 53 - $object_box = id(new PHUIObjectBoxView()) 54 - ->setHeader($header) 55 - ->addPropertyList($properties); 56 - 51 + $properties = $this->buildPropertyView($paste, $fork_phids); 52 + $subheader = $this->buildSubheaderView($paste); 57 53 $source_code = $this->buildSourceCodeView($paste, $this->highlightMap); 58 54 59 55 require_celerity_resource('paste-css'); 60 - $source_code = phutil_tag( 61 - 'div', 62 - array( 63 - 'class' => 'container-of-paste', 64 - ), 65 - $source_code); 66 56 67 57 $monogram = $paste->getMonogram(); 68 58 $crumbs = $this->buildApplicationCrumbs() 69 - ->addTextCrumb($monogram, '/'.$monogram); 59 + ->addTextCrumb($monogram) 60 + ->setBorder(true); 70 61 71 62 $timeline = $this->buildTransactionTimeline( 72 63 $paste, ··· 79 70 $timeline->setQuoteRef($monogram); 80 71 $comment_view->setTransactionTimeline($timeline); 81 72 73 + $paste_view = id(new PHUITwoColumnView()) 74 + ->setHeader($header) 75 + ->setSubheader($subheader) 76 + ->setMainColumn(array( 77 + $source_code, 78 + $timeline, 79 + $comment_view, 80 + )) 81 + ->setPropertyList($properties) 82 + ->setActionList($actions) 83 + ->addClass('ponder-question-view'); 84 + 82 85 return $this->newPage() 83 86 ->setTitle($paste->getFullName()) 84 87 ->setCrumbs($crumbs) ··· 86 89 array( 87 90 $paste->getPHID(), 88 91 )) 89 - ->appendChild( 90 - array( 91 - $object_box, 92 - $source_code, 93 - $timeline, 94 - $comment_view, 95 - )); 92 + ->appendChild($paste_view); 96 93 } 97 94 98 95 private function buildHeaderView(PhabricatorPaste $paste) { ··· 167 164 return $action_list; 168 165 } 169 166 167 + 168 + private function buildSubheaderView( 169 + PhabricatorPaste $paste) { 170 + $viewer = $this->getViewer(); 171 + 172 + $author = $viewer->renderHandle($paste->getAuthorPHID())->render(); 173 + $date = phabricator_datetime($paste->getDateCreated(), $viewer); 174 + $author = phutil_tag('strong', array(), $author); 175 + 176 + $author_info = id(new PhabricatorPeopleQuery()) 177 + ->setViewer($viewer) 178 + ->withPHIDs(array($paste->getAuthorPHID())) 179 + ->needProfileImage(true) 180 + ->executeOne(); 181 + 182 + $image_uri = $author_info->getProfileImageURI(); 183 + $image_href = '/p/'.$author_info->getUsername(); 184 + 185 + $content = pht('Authored by %s on %s.', $author, $date); 186 + 187 + return id(new PHUIHeadThingView()) 188 + ->setImage($image_uri) 189 + ->setImageHref($image_href) 190 + ->setContent($content); 191 + } 192 + 170 193 private function buildPropertyView( 171 194 PhabricatorPaste $paste, 172 - array $child_phids, 173 - PhabricatorActionListView $actions) { 195 + array $child_phids) { 174 196 $viewer = $this->getViewer(); 175 197 176 198 $properties = id(new PHUIPropertyListView()) 177 199 ->setUser($viewer) 178 - ->setObject($paste) 179 - ->setActionList($actions); 180 - 181 - $properties->addProperty( 182 - pht('Author'), 183 - $viewer->renderHandle($paste->getAuthorPHID())); 184 - 185 - $properties->addProperty( 186 - pht('Created'), 187 - phabricator_datetime($paste->getDateCreated(), $viewer)); 200 + ->setObject($paste); 188 201 189 202 if ($paste->getParentPHID()) { 190 203 $properties->addProperty(
+5 -3
src/applications/people/controller/PhabricatorPeopleProfileViewController.php
··· 52 52 $name = $user->getUsername(); 53 53 54 54 $feed = $this->buildPeopleFeed($user, $viewer); 55 - $feed = phutil_tag_div('project-view-feed', $feed); 55 + $feed = id(new PHUIObjectBoxView()) 56 + ->setHeaderText(pht('Recent Activity')) 57 + ->addClass('project-view-feed') 58 + ->appendChild($feed); 56 59 57 60 $projects = $this->buildProjectsView($user); 58 61 $badges = $this->buildBadgesView($user); ··· 106 109 return null; 107 110 } 108 111 109 - $view = id(new PHUIBoxView()) 110 - ->setBorder(true) 112 + $view = id(new PHUIObjectBoxView()) 111 113 ->appendChild($view) 112 114 ->addClass('project-view-properties'); 113 115
+46 -82
src/applications/ponder/controller/PonderQuestionViewController.php
··· 31 31 $header->setHeader($question->getTitle()); 32 32 $header->setUser($viewer); 33 33 $header->setPolicyObject($question); 34 - $header->setProfileHeader(true); 35 34 36 35 if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) { 37 36 $header->setStatus('fa-square-o', 'bluegrey', pht('Open')); ··· 43 42 $header->setStatus($icon, 'dark', $text); 44 43 } 45 44 46 - $actions = $this->buildActionListView($question); 47 45 $properties = $this->buildPropertyListView($question); 46 + $actions = $this->buildActionListView($question); 48 47 $details = $this->buildDetailsPropertyView($question); 49 48 50 49 $can_edit = PhabricatorPolicyFilter::hasCapability( ··· 52 51 $question, 53 52 PhabricatorPolicyCapability::CAN_EDIT); 54 53 55 - $edit_uri = '/question/edit/'.$question->getID().'/'; 56 - $edit_button = id(new PHUIButtonView()) 57 - ->setTag('a') 58 - ->setText(pht('Edit')) 59 - ->setHref($this->getApplicationURI($edit_uri)) 60 - ->setIcon('fa-pencil') 61 - ->setDisabled(!$can_edit) 62 - ->setWorkflow(!$can_edit); 63 - 64 - $action_button = id(new PHUIButtonView()) 65 - ->setTag('a') 66 - ->setText(pht('Actions')) 67 - ->setHref('#') 68 - ->setIcon('fa-bars') 69 - ->setDropdownMenu($actions); 70 - 71 - $header->addActionLink($action_button); 72 - $header->addActionLink($edit_button); 73 - 74 54 $content_id = celerity_generate_unique_node_id(); 75 55 $timeline = $this->buildTransactionTimeline( 76 56 $question, ··· 81 61 $add_comment = id(new PhabricatorApplicationTransactionCommentView()) 82 62 ->setUser($viewer) 83 63 ->setObjectPHID($question->getPHID()) 84 - ->setFullWidth(true) 85 64 ->setShowPreview(false) 86 65 ->setAction($this->getApplicationURI("/question/comment/{$id}/")) 87 66 ->setSubmitButtonName(pht('Comment')); ··· 108 87 $crumbs->addTextCrumb('Q'.$id, '/Q'.$id); 109 88 $crumbs->setBorder(true); 110 89 90 + $subheader = $this->buildSubheaderView($question); 91 + 111 92 $answer_wiki = null; 112 93 if ($question->getAnswerWiki()) { 113 94 $wiki = new PHUIRemarkupView($viewer, $question->getAnswerWiki()); 114 - $wiki_header = phutil_tag( 115 - 'div', 116 - array( 117 - 'class' => 'ponder-answer-wiki-header', 118 - ), 119 - pht('Answer Summary')); 120 - 121 95 $answer_wiki = id(new PHUIObjectBoxView()) 122 - ->setBackground(PHUIObjectBoxView::BLUE) 123 - ->appendChild($wiki_header) 96 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 97 + ->setHeaderText(pht('ANSWER SUMMARY')) 124 98 ->appendChild($wiki) 125 99 ->addClass('ponder-answer-wiki'); 126 100 } ··· 143 117 144 118 $ponder_view = id(new PHUITwoColumnView()) 145 119 ->setHeader($header) 120 + ->setSubheader($subheader) 146 121 ->setMainColumn($ponder_content) 147 - ->setSideColumn($properties) 122 + ->setPropertyList($properties) 123 + ->setActionList($actions) 148 124 ->addClass('ponder-question-view'); 149 125 150 126 $page_objects = array_merge( ··· 182 158 $name = pht('Reopen Question'); 183 159 $icon = 'fa-square-o'; 184 160 } 161 + 162 + $view->addAction( 163 + id(new PhabricatorActionView()) 164 + ->setIcon('fa-pencil') 165 + ->setName(pht('Edit Question')) 166 + ->setHref($this->getApplicationURI("/question/edit/{$id}/")) 167 + ->setDisabled(!$can_edit) 168 + ->setWorkflow(!$can_edit)); 185 169 186 170 $view->addAction( 187 171 id(new PhabricatorActionView()) ··· 206 190 $viewer = $this->getViewer(); 207 191 $view = id(new PHUIPropertyListView()) 208 192 ->setUser($viewer) 209 - ->setObject($question) 210 - ->setStacked(true); 193 + ->setObject($question); 211 194 212 195 $view->invokeWillRenderEvent(); 213 196 214 - if (!$view->hasAnyProperties()) { 215 - return null; 216 - } 217 - 218 - $view = id(new PHUIObjectBoxView()) 219 - ->appendChild($view) 220 - ->setBackground(PHUIObjectBoxView::GREY) 221 - ->addClass('ponder-view-properties'); 222 - 223 197 return $view; 224 198 } 225 199 226 - private function buildDetailsPropertyView( 200 + private function buildSubheaderView( 227 201 PonderQuestion $question) { 228 202 $viewer = $this->getViewer(); 229 203 230 - $question_details = PhabricatorMarkupEngine::renderOneObject( 231 - $question, 232 - $question->getMarkupField(), 233 - $viewer); 234 - 235 - if (!$question_details) { 236 - $question_details = phutil_tag( 237 - 'em', 238 - array(), 239 - pht('No further details for this question.')); 240 - } 241 - 242 204 $asker = $viewer->renderHandle($question->getAuthorPHID())->render(); 243 205 $date = phabricator_datetime($question->getDateCreated(), $viewer); 244 206 $asker = phutil_tag('strong', array(), $asker); ··· 252 214 $image_uri = $author->getProfileImageURI(); 253 215 $image_href = '/p/'.$author->getUsername(); 254 216 255 - $image = phutil_tag( 256 - 'a', 257 - array( 258 - 'class' => 'ponder-details-author-image', 259 - 'style' => 'background-image: url('.$image_uri.');', 260 - 'href' => $image_href, 261 - )); 217 + $content = pht('Asked by %s on %s.', $asker, $date); 262 218 263 - $details_header = phutil_tag( 264 - 'div', 265 - array( 266 - 'class' => 'ponder-details-subtitle', 267 - ), 268 - array( 269 - $image, 270 - pht('Asked by %s on %s.', $asker, $date), 271 - )); 219 + return id(new PHUIHeadThingView()) 220 + ->setImage($image_uri) 221 + ->setImageHref($image_href) 222 + ->setContent($content); 223 + } 272 224 273 - $details = phutil_tag( 274 - 'div', 275 - array( 276 - 'class' => 'ponder-detail-view', 277 - ), 278 - array( 279 - $details_header, 280 - phutil_tag_div('phabricator-remarkup', $question_details), 281 - )); 225 + private function buildDetailsPropertyView( 226 + PonderQuestion $question) { 227 + $viewer = $this->getViewer(); 282 228 229 + $question_details = PhabricatorMarkupEngine::renderOneObject( 230 + $question, 231 + $question->getMarkupField(), 232 + $viewer); 283 233 284 - return $details; 234 + if (!$question_details) { 235 + $question_details = phutil_tag( 236 + 'em', 237 + array(), 238 + pht('No further details for this question.')); 239 + } 240 + 241 + $question_details = phutil_tag_div( 242 + 'phabricator-remarkup ml', $question_details); 243 + 244 + return id(new PHUIObjectBoxView()) 245 + ->setHeaderText(pht('DETAILS')) 246 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 247 + ->setFlush(true) 248 + ->appendChild($question_details); 285 249 } 286 250 287 251 /**
+1 -2
src/applications/ponder/view/PonderAddAnswerView.php
··· 51 51 ->setUser($this->user) 52 52 ->setAction($this->actionURI) 53 53 ->setWorkflow(true) 54 - ->setFullWidth(true) 55 54 ->addHiddenInput('question_id', $question->getID()) 56 55 ->appendChild( 57 56 id(new PhabricatorRemarkupControl()) ··· 78 77 79 78 $box = id(new PHUIObjectBoxView()) 80 79 ->appendChild($form) 81 - ->setBackground(PHUIObjectBoxView::GREY) 80 + ->setHeaderText('Answer') 82 81 ->addClass('ponder-add-answer-view'); 83 82 84 83 if ($info_panel) {
+6 -3
src/applications/project/controller/PhabricatorProjectProfileController.php
··· 82 82 ->execute(); 83 83 84 84 $feed = $this->renderStories($stories); 85 - $feed = phutil_tag_div('project-view-feed', $feed); 85 + $feed = id(new PHUIObjectBoxView()) 86 + ->setHeaderText(pht('Recent Activity')) 87 + ->addClass('project-view-feed') 88 + ->appendChild($feed); 89 + 86 90 require_celerity_resource('project-view-css'); 87 91 88 92 $home = id(new PHUITwoColumnView()) ··· 134 138 return null; 135 139 } 136 140 137 - $view = id(new PHUIBoxView()) 138 - ->setBorder(true) 141 + $view = id(new PHUIObjectBoxView()) 139 142 ->appendChild($view) 140 143 ->addClass('project-view-properties'); 141 144
+42 -23
src/applications/slowvote/controller/PhabricatorSlowvotePollController.php
··· 23 23 } 24 24 25 25 $poll_view = id(new SlowvoteEmbedView()) 26 - ->setHeadless(true) 27 26 ->setUser($viewer) 28 27 ->setPoll($poll); 29 28 ··· 47 46 ->setPolicyObject($poll); 48 47 49 48 $actions = $this->buildActionView($poll); 50 - $properties = $this->buildPropertyView($poll, $actions); 49 + $properties = $this->buildPropertyView($poll); 50 + $subheader = $this->buildSubheaderView($poll); 51 51 52 52 $crumbs = $this->buildApplicationCrumbs(); 53 53 $crumbs->addTextCrumb('V'.$poll->getID()); 54 + $crumbs->setBorder(true); 54 55 55 56 $timeline = $this->buildTransactionTimeline( 56 57 $poll, 57 58 new PhabricatorSlowvoteTransactionQuery()); 58 59 $add_comment = $this->buildCommentForm($poll); 59 60 60 - $object_box = id(new PHUIObjectBoxView()) 61 + $poll_content = array( 62 + $poll_view, 63 + $timeline, 64 + $add_comment, 65 + ); 66 + 67 + $view = id(new PHUITwoColumnView()) 61 68 ->setHeader($header) 62 - ->addPropertyList($properties); 69 + ->setSubheader($subheader) 70 + ->setMainColumn($poll_content) 71 + ->setPropertyList($properties) 72 + ->setActionList($actions); 63 73 64 74 return $this->newPage() 65 75 ->setTitle('V'.$poll->getID().' '.$poll->getQuestion()) ··· 67 77 ->setPageObjectPHIDs(array($poll->getPHID())) 68 78 ->appendChild( 69 79 array( 70 - $object_box, 71 - $poll_view, 72 - $timeline, 73 - $add_comment, 80 + $view, 74 81 )); 75 82 } 76 83 ··· 110 117 } 111 118 112 119 private function buildPropertyView( 113 - PhabricatorSlowvotePoll $poll, 114 - PhabricatorActionListView $actions) { 120 + PhabricatorSlowvotePoll $poll) { 115 121 116 122 $viewer = $this->getRequest()->getUser(); 117 - 118 123 $view = id(new PHUIPropertyListView()) 119 124 ->setUser($viewer) 120 - ->setObject($poll) 121 - ->setActionList($actions); 125 + ->setObject($poll); 126 + $view->invokeWillRenderEvent(); 127 + 128 + return $view; 129 + } 130 + 131 + private function buildSubheaderView( 132 + PhabricatorSlowvotePoll $poll) { 133 + $viewer = $this->getViewer(); 122 134 123 - $view->invokeWillRenderEvent(); 135 + $author = $viewer->renderHandle($poll->getAuthorPHID())->render(); 136 + $date = phabricator_datetime($poll->getDateCreated(), $viewer); 137 + $author = phutil_tag('strong', array(), $author); 124 138 125 - $description = $poll->getDescription(); 126 - if (strlen($description)) { 127 - $description = new PHUIRemarkupView($viewer, $description); 128 - $view->addSectionHeader( 129 - pht('Description'), 130 - PHUIPropertyListView::ICON_SUMMARY); 131 - $view->addTextContent($description); 132 - } 139 + $person = id(new PhabricatorPeopleQuery()) 140 + ->setViewer($viewer) 141 + ->withPHIDs(array($poll->getAuthorPHID())) 142 + ->needProfileImage(true) 143 + ->executeOne(); 133 144 134 - return $view; 145 + $image_uri = $person->getProfileImageURI(); 146 + $image_href = '/p/'.$person->getUsername(); 147 + 148 + $content = pht('Asked by %s on %s.', $author, $date); 149 + 150 + return id(new PHUIHeadThingView()) 151 + ->setImage($image_uri) 152 + ->setImageHref($image_href) 153 + ->setContent($content); 135 154 } 136 155 137 156 private function buildCommentForm(PhabricatorSlowvotePoll $poll) {
+19 -27
src/applications/slowvote/view/SlowvoteEmbedView.php
··· 4 4 5 5 private $poll; 6 6 private $handles; 7 - private $headless; 8 - 9 - public function setHeadless($headless) { 10 - $this->headless = $headless; 11 - return $this; 12 - } 13 7 14 8 public function setPoll(PhabricatorSlowvotePoll $poll) { 15 9 $this->poll = $poll; ··· 68 62 ), 69 63 $poll->getQuestion()); 70 64 71 - if ($this->headless) { 72 - $header = null; 73 - } else { 74 - $header = id(new PHUIHeaderView()) 75 - ->setHeader($link_to_slowvote); 76 - 77 - $description = $poll->getDescription(); 78 - if (strlen($description)) { 79 - $description = new PHUIRemarkupView($this->getUser(), $description); 80 - $description = phutil_tag( 81 - 'div', 82 - array( 83 - 'class' => 'slowvote-description', 84 - ), 85 - $description); 86 - } 65 + $header = id(new PHUIHeaderView()) 66 + ->setHeader($link_to_slowvote); 87 67 88 - $header = array( 89 - $header, 90 - $description, 91 - ); 68 + $description = $poll->getDescription(); 69 + if (strlen($description)) { 70 + $description = new PHUIRemarkupView($this->getUser(), $description); 71 + $description = phutil_tag( 72 + 'div', 73 + array( 74 + 'class' => 'slowvote-description', 75 + ), 76 + $description); 92 77 } 78 + 79 + $header = array( 80 + $header, 81 + $description, 82 + ); 93 83 94 84 $vis = $poll->getResponseVisibility(); 95 85 if ($this->areResultsVisible()) { ··· 163 153 array($body)); 164 154 165 155 return id(new PHUIObjectBoxView()) 156 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 166 157 ->setHeader($header) 167 - ->appendChild($embed); 158 + ->appendChild($embed) 159 + ->addClass('slowvote-poll-view'); 168 160 } 169 161 170 162 private function renderLabel(PhabricatorSlowvoteOption $option, $selected) {
+65
src/view/phui/PHUIHeadThingView.php
··· 1 + <?php 2 + 3 + final class PHUIHeadThingView extends AphrontTagView { 4 + 5 + private $image; 6 + private $imageHref; 7 + private $content; 8 + private $size; 9 + 10 + const SMALL = 'head-thing-small'; 11 + const MEDIUM = 'head-thing-medium'; 12 + 13 + public function setImageHref($href) { 14 + $this->imageHref = $href; 15 + return $this; 16 + } 17 + 18 + public function setImage($image) { 19 + $this->image = $image; 20 + return $this; 21 + } 22 + 23 + public function setContent($content) { 24 + $this->content = $content; 25 + return $this; 26 + } 27 + 28 + public function setSize($size) { 29 + $this->size = $size; 30 + return $this; 31 + } 32 + 33 + protected function getTagAttributes() { 34 + require_celerity_resource('phui-head-thing-view-css'); 35 + 36 + $classes = array(); 37 + $classes[] = 'phui-head-thing-view'; 38 + 39 + if ($this->size) { 40 + $classes[] = $this->size; 41 + } else { 42 + $classes[] = self::SMALL; 43 + } 44 + 45 + return array( 46 + 'class' => $classes, 47 + ); 48 + } 49 + 50 + protected function getTagContent() { 51 + 52 + $image = phutil_tag( 53 + 'a', 54 + array( 55 + 'class' => 'phui-head-thing-image', 56 + 'style' => 'background-image: url('.$this->image.');', 57 + 'href' => $this->imageHref, 58 + )); 59 + 60 + return array($image, $this->content); 61 + 62 + 63 + } 64 + 65 + }
+1
src/view/phui/PHUIObjectBoxView.php
··· 36 36 const COLOR_YELLOW = 'yellow'; 37 37 38 38 const BLUE = 'phui-box-blue'; 39 + const BLUE_PROPERTY = 'phui-box-blue-property'; 39 40 const GREY = 'phui-box-grey'; 40 41 41 42 public function addPropertyList(
+65 -15
src/view/phui/PHUITwoColumnView.php
··· 3 3 final class PHUITwoColumnView extends AphrontTagView { 4 4 5 5 private $mainColumn; 6 - private $sideColumn; 6 + private $sideColumn = null; 7 7 private $display; 8 8 private $fluid; 9 9 private $header; 10 + private $subheader; 11 + private $actionList; 12 + private $propertyList; 10 13 11 14 const DISPLAY_LEFT = 'phui-side-column-left'; 12 15 const DISPLAY_RIGHT = 'phui-side-column-right'; ··· 23 26 24 27 public function setHeader(PHUIHeaderView $header) { 25 28 $this->header = $header; 29 + return $this; 30 + } 31 + 32 + public function setSubheader($subheader) { 33 + $this->subheader = $subheader; 34 + return $this; 35 + } 36 + 37 + public function setActionList(PhabricatorActionListView $list) { 38 + $this->actionList = $list; 39 + return $this; 40 + } 41 + 42 + public function setPropertyList(PHUIPropertyListView $list) { 43 + $this->propertyList = $list; 26 44 return $this; 27 45 } 28 46 ··· 53 71 $classes[] = 'phui-two-column-fluid'; 54 72 } 55 73 74 + if ($this->subheader) { 75 + $classes[] = 'with-subheader'; 76 + } 77 + 56 78 return array( 57 79 'class' => implode(' ', $classes), 58 80 ); ··· 68 90 ), 69 91 $this->mainColumn); 70 92 71 - $side = phutil_tag( 72 - 'div', 73 - array( 74 - 'class' => 'phui-side-column', 75 - ), 76 - $this->sideColumn); 77 - 78 - if ($this->getDisplay() == self::DISPLAY_LEFT) { 79 - $order = array($side, $main); 80 - } else { 81 - $order = array($main, $side); 82 - } 93 + $side = $this->buildSideColumn(); 94 + $order = array($side, $main); 83 95 84 - $inner = phutil_tag_div('phui-two-column-row', $order); 96 + $inner = phutil_tag_div('phui-two-column-row grouped', $order); 85 97 $table = phutil_tag_div('phui-two-column-content', $inner); 86 98 87 99 $header = null; 88 100 if ($this->header) { 89 - $header = phutil_tag_div('phui-two-column-header', $this->header); 101 + if ($this->actionList) { 102 + $this->header->setActionList($this->actionList); 103 + } 104 + $header = phutil_tag_div( 105 + 'phui-two-column-header', $this->header); 106 + } 107 + 108 + $subheader = null; 109 + if ($this->subheader) { 110 + $subheader = phutil_tag_div( 111 + 'phui-two-column-subheader', $this->subheader); 90 112 } 91 113 92 114 return phutil_tag( ··· 96 118 ), 97 119 array( 98 120 $header, 121 + $subheader, 99 122 $table, 123 + )); 124 + } 125 + 126 + private function buildSideColumn() { 127 + $property_list = $this->propertyList; 128 + $action_list = $this->actionList; 129 + 130 + $properties = null; 131 + if ($property_list || $action_list) { 132 + if ($property_list) { 133 + $property_list->setStacked(true); 134 + } 135 + 136 + $properties = id(new PHUIObjectBoxView()) 137 + ->appendChild($action_list) 138 + ->appendChild($property_list) 139 + ->addClass('phui-two-column-properties'); 140 + } 141 + 142 + return phutil_tag( 143 + 'div', 144 + array( 145 + 'class' => 'phui-side-column', 146 + ), 147 + array( 148 + $properties, 149 + $this->sideColumn, 100 150 )); 101 151 } 102 152 }
+9 -20
webroot/rsrc/css/application/countdown/timer.css
··· 4 4 5 5 .phabricator-timer { 6 6 margin: 16px 16px 0 16px; 7 - border: 1px solid {$lightblueborder}; 8 - border-radius: 3px; 9 - background: #ffffff; 10 7 } 11 8 12 9 .device .phabricator-timer { ··· 14 11 margin-right: 8px; 15 12 } 16 13 17 - .phabricator-remarkup .phabricator-timer { 18 - max-width: 360px; 14 + .phabricator-remarkup .phabricator-timer-view { 15 + max-width: 460px; 19 16 margin: 0 0 12px 0; 20 17 } 21 18 19 + .phabricator-timer .countdown-description { 20 + border-bottom: 1px solid {$thinblueborder}; 21 + padding-bottom: 16px; 22 + } 23 + 22 24 .device-phone .phabricator-remarkup .phabricator-timer { 23 25 width: auto; 24 26 } 25 27 26 - .phabricator-timer-header { 27 - font-weight: bold; 28 - padding: 8px; 29 - background: {$bluebackground}; 30 - border-radius: 3px 3px 0 0; 31 - } 32 - 33 - .phabricator-timer-header a { 34 - color: {$darkbluetext}; 35 - font-weight: normal; 36 - } 37 - 38 28 .phabricator-timer-table { 39 29 width: 100%; 40 30 margin: 8px 0 0 0; ··· 60 50 } 61 51 62 52 .phabricator-timer-table td.phabricator-timer-foot { 63 - font-size: {$normalfontsize}; 53 + font-size: {$biggerfontsize}; 64 54 line-height: 16px; 65 55 border-top: 1px solid {$thinblueborder}; 66 56 color: {$bluetext}; 67 - font-weight: normal; 68 - padding: 8px; 57 + padding: 12px 0; 69 58 border-bottom-right-radius: 3px; 70 59 border-bottom-left-radius: 3px; 71 60 text-align: center;
-8
webroot/rsrc/css/application/paste/paste.css
··· 2 2 * @provides paste-css 3 3 */ 4 4 5 - .container-of-paste { 6 - margin: 16px 16px 0 16px; 7 - } 8 - 9 - .device .container-of-paste { 10 - margin: 8px 8px 0 8px; 11 - } 12 - 13 5 .paste-embed { 14 6 background: {$sh-yellowbackground}; 15 7 border: 1px solid {$sh-lightyellowborder};
+7 -90
webroot/rsrc/css/application/ponder/ponder-view.css
··· 2 2 * @provides ponder-view-css 3 3 */ 4 4 5 - .ponder-question-view { 6 - background: #fff; 7 - padding-bottom: 64px; 8 - } 9 - 10 - .device-desktop .ponder-question-view.phui-two-column-view .phui-side-column { 11 - width: 300px; 12 - } 13 - 14 - .ponder-question-view .phui-object-box, 15 - .ponder-question-view .phui-info-view { 16 - margin-left: 0; 17 - margin-right: 0; 18 - } 19 - 20 - .device-phone .ponder-question-view .phui-profile-header.phui-header-shell 21 - .phui-header-header { 22 - font-size: 20px; 23 - } 24 - 25 5 .ponder-question-container { 26 6 border-top: 1px solid {$thinblueborder}; 27 7 } 28 8 29 - .ponder-question-content { 30 - margin: 0 24px; 31 - padding: 24px 0; 32 - border-top: 1px solid rgba({$alphagrey}, .15); 33 - } 34 - 35 - .device-phone .ponder-question-content { 36 - margin: 0 16px; 37 - } 38 - 39 9 .device .ponder-view-properties { 40 10 border-left: none; 41 11 border-right: none; ··· 57 27 border: none; 58 28 } 59 29 60 - .ponder-view-properties .phui-property-list-stacked 61 - .phui-property-list-properties .phui-property-list-key { 62 - padding: 0; 63 - } 64 - 65 - .ponder-view-properties .phui-property-list-stacked 66 - .phui-property-list-properties .phui-property-list-value { 67 - margin-bottom: 16px; 68 - padding: 0; 30 + .phui-two-column-view .phui-main-column .ponder-question-content 31 + .phui-box.ponder-answer-wiki { 32 + margin: 24px 0; 69 33 } 70 34 71 - .phui-box.ponder-answer-wiki { 35 + .ponder-answer-wiki .phabricator-remarkup { 72 36 padding: 16px; 73 - margin: 24px 0; 74 - } 75 - 76 - .ponder-details-subtitle { 77 - height: 24px; 78 - line-height: 24px; 79 - margin-bottom: 12px; 80 - color: {$greytext}; 81 - position: relative; 82 - padding-left: 32px; 83 - } 84 - 85 - .ponder-details-subtitle a { 86 - color: {$darkgreytext}; 87 - } 88 - 89 - .ponder-details-author-image { 90 - height: 24px; 91 - width: 24px; 92 - background-size: 100%; 93 - margin-right: 8px; 94 - border-radius: 3px; 95 - display: inline-block; 96 - position: absolute; 97 - top: 0; 98 - left: 0; 99 - } 100 - 101 - .ponder-detail-view .phabricator-remarkup { 102 - margin-left: 32px; 103 37 } 104 38 105 39 .ponder-question-content .phui-timeline-view { 106 40 padding-right: 0; 107 - } 108 - 109 - .ponder-question-content .phui-timeline-view .phui-timeline-core-content { 110 - background-color: {$lightbluebackground}; 111 41 } 112 42 113 43 .ponder-answer-view { ··· 123 53 margin-left: 12px; 124 54 } 125 55 126 - .ponder-question-view .ponder-answer-view .phui-header-shell { 56 + .ponder-question-view .ponder-answer .phui-header-shell { 127 57 padding: 4px 8px 3px 8px; 128 58 } 129 59 ··· 192 122 193 123 .ponder-add-answer-header { 194 124 margin-top: 64px; 125 + margin-bottom: 20px; 195 126 } 196 127 197 128 .ponder-add-answer-view { ··· 200 131 201 132 .ponder-question-content div.ponder-question-add-comment-view 202 133 div.phui-box.phui-object-box { 203 - background: {$lightbluebackground}; 204 134 margin-right: 0; 205 - margin-left: 32px; 135 + margin-left: 62px; 206 136 } 207 137 208 138 .device .ponder-question-content div.ponder-question-add-comment-view ··· 210 140 margin: 0; 211 141 } 212 142 213 - .ponder-add-answer-view .phui-form-full-width.phui-form-view 214 - label.aphront-form-label, 215 - .ponder-question-add-comment-view .phui-form-full-width.phui-form-view 216 - label.aphront-form-label{ 217 - display: none; 218 - } 219 - 220 - .ponder-add-answer-view.phui-box-grey .phui-header-shell { 221 - border: none; 222 - padding-bottom: 8px; 223 - } 224 - 225 - .ponder-add-answer-view .remarkup-assist-textarea, 226 143 .ponder-question-add-comment-view .remarkup-assist-textarea { 227 144 height: 8em; 228 145 }
+23 -29
webroot/rsrc/css/application/project/project-view.css
··· 2 2 * @provides project-view-css 3 3 */ 4 4 5 - .project-view-home { 6 - padding-bottom: 64px; 7 - background: #fff; 8 - } 9 - 10 5 .project-view-header-tag { 11 6 margin-left: 8px; 12 7 font-size: {$normalfontsize}; ··· 24 19 color: {$bluetext}; 25 20 } 26 21 22 + .device .project-view-home .phui-two-column-row { 23 + display: flex; 24 + flex-direction: column-reverse; 25 + } 26 + 27 27 .project-view-home .phui-box.project-view-properties { 28 - margin: 0 16px 16px 16px; 29 - padding: 4px 12px; 30 - border: 2px solid rgba({$alphagrey},.1); 31 - background-color: #F7F7F9; 28 + margin: 0 0 16px 0; 29 + padding: 0; 30 + border: 1px solid rgba({$alphagrey}, .2); 31 + background-color: #fff; 32 32 } 33 33 34 + .device-desktop .phui-two-column-view .project-view-properties 35 + .phui-property-list-container { 36 + padding: 12px 0; 37 + } 38 + 34 39 .device-phone .phui-box.project-view-properties { 35 40 margin: 0 12px 0 12px; 36 41 } 37 42 38 43 .project-view-properties .phui-property-list-container + 39 44 .phui-property-list-text-content { 40 - border-color: rgba({$alphagrey},.15); 45 + border-color: rgba({$alphagrey},.2); 41 46 } 42 47 43 48 .project-view-properties .phui-property-list-key { 44 49 width: auto; 45 - margin-left: 4px2 50 + margin-left: 4px; 46 51 } 47 52 48 53 .project-view-properties .phui-property-list-section-header { ··· 50 55 padding: 12px 4px 0; 51 56 } 52 57 53 - .project-view-feed .phui-object-box.phui-box-border { 54 - padding: 0 4px 8px 4px; 55 - border: none; 56 - } 57 - 58 - .project-view-feed .phui-object-box .phui-header-shell { 59 - padding: 8px 4px; 60 - } 61 - 62 - .project-view-feed .phui-header-header { 63 - font-size: {$biggerfontsize}; 64 - margin-left: 8px; 65 - } 66 - 67 - .device-desktop .project-view-feed .phui-feed-story, 68 - .device-tablet .project-view-feed .phui-feed-story { 69 - padding-left: 22px; 58 + .project-view-feed.phui-object-box.phui-box-border { 59 + border: 1px solid rgba({$alphagrey}, .2); 70 60 } 71 61 72 62 .project-view-home .phui-box-grey { ··· 81 71 font-size: {$biggerfontsize}; 82 72 } 83 73 74 + .project-view-home .phui-box-grey .phui-header-action-link { 75 + margin-top: 0; 76 + margin-bottom: 0; 77 + } 78 + 84 79 .project-view-home .phui-box-grey .phui-object-item-list-view { 85 80 padding: 4px 8px 0 8px; 86 81 } 87 82 88 83 .project-view-badges .phui-badge-flex-view { 89 84 background-color: #fff; 90 - width: 340px; 91 85 } 92 86 93 87 .project-view-home .phui-box-grey .phui-object-item-attribute .phui-icon-view {
+3 -17
webroot/rsrc/css/application/slowvote/slowvote.css
··· 2 2 * @provides phabricator-slowvote-css 3 3 */ 4 4 5 - .slowvote-embed { 6 - background: #fff; 7 - border-color: {$lightblueborder}; 8 - border-radius: 3px; 9 - } 10 - 11 - .slowvote-header { 12 - font-weight: bold; 13 - line-height: 16px; 14 - border-bottom: 1px solid #bbbbbb; 15 - } 16 - 17 5 .slowvote-description { 18 - color: {$greytext}; 19 - font-size: {$biggerfontsize}; 20 - padding: 12px 4px 4px; 6 + padding: 12px 16px 4px; 21 7 } 22 8 23 9 .slowvote-header-content { ··· 25 11 } 26 12 27 13 .slowvote-body-content { 28 - padding: 8px 4px 0; 14 + padding: 8px 16px; 29 15 } 30 16 31 17 .slowvote-option-label { ··· 121 107 } 122 108 123 109 .slowvote-footer-content { 124 - padding: 8px; 110 + padding: 8px 16px; 125 111 overflow: hidden; 126 112 } 127 113
+31 -1
webroot/rsrc/css/phui/phui-box.css
··· 15 15 .phui-box-grey { 16 16 background-color: #F7F7F9; 17 17 border-radius: 3px; 18 - border-color: rgba({$alphagrey},.1); 18 + border-color: rgba({$alphagrey},.2); 19 19 } 20 20 21 21 .phui-box-blue { ··· 55 55 border: none; 56 56 color: {$greytext}; 57 57 } 58 + 59 + 60 + /* Property Boxes */ 61 + 62 + .phui-box.phui-box-blue-property { 63 + border-radius: 3px; 64 + border-color: {$lightblueborder}; 65 + margin: 0; 66 + padding: 0; 67 + } 68 + 69 + .device .phui-box.phui-box-blue-property { 70 + padding: 0; 71 + } 72 + 73 + .phui-box.phui-object-box.phui-box-blue-property .phui-header-shell { 74 + background-color: #eff3fc; 75 + border-top-right-radius: 3px; 76 + border-top-left-radius: 3px; 77 + padding: 6px 16px; 78 + } 79 + 80 + .device .phui-box.phui-box-blue-property .phui-header-shell { 81 + padding: 6px 12px; 82 + } 83 + 84 + .phui-box.phui-box-blue-property .phui-header-header { 85 + font-size: 13px; 86 + color: {$bluetext}; 87 + }
+4 -3
webroot/rsrc/css/phui/phui-button.css
··· 60 60 a.grey, 61 61 a.grey:visited { 62 62 background-color: #F7F7F9; 63 - border: 1px solid rgba({$alphagrey},.1); 63 + background-image: linear-gradient(to bottom, #ffffff, #f1f0f1); 64 + border: 1px solid rgba({$alphablue},.2); 64 65 color: {$darkgreytext}; 65 66 } 66 67 ··· 106 107 107 108 a.button.grey:hover, 108 109 button.grey:hover { 109 - background-color: rgba({$alphablue}, 0.1); 110 - border-color: rgba({$alphablue}, 0.15); 110 + background-image: linear-gradient(to bottom, #ffffff, #eeebec); 111 + border-color: rgba({$alphablue}, 0.3); 111 112 transition: 0.1s; 112 113 } 113 114
+33
webroot/rsrc/css/phui/phui-head-thing.css
··· 1 + /** 2 + * @provides phui-head-thing-view-css 3 + */ 4 + 5 + .phui-head-thing-view { 6 + height: 24px; 7 + line-height: 22px; 8 + color: {$greytext}; 9 + position: relative; 10 + padding-left: 32px; 11 + } 12 + 13 + .device-phone .phui-head-thing-view { 14 + min-height: 24px; 15 + height: auto; 16 + line-height: inherit; 17 + } 18 + 19 + .phui-head-thing-view a { 20 + color: {$darkgreytext}; 21 + } 22 + 23 + .phui-head-thing-image { 24 + height: 24px; 25 + width: 24px; 26 + background-size: 100%; 27 + margin-right: 8px; 28 + border-radius: 3px; 29 + display: inline-block; 30 + position: absolute; 31 + top: 0; 32 + left: 0; 33 + }
+1 -1
webroot/rsrc/css/phui/phui-header-view.css
··· 185 185 .phui-header-subheader .phui-header-status { 186 186 padding: 3px 9px; 187 187 border-radius: 3px; 188 - background: rgba({$alphablue}, 0.06); 188 + background: rgba({$alphablue}, 0.08); 189 189 margin-right: 8px; 190 190 } 191 191
+4
webroot/rsrc/css/phui/phui-object-box.css
··· 120 120 margin: 0; 121 121 } 122 122 123 + .phui-object-box .phui-box-border.phui-box-blue-property { 124 + border-width: 1px; 125 + } 126 + 123 127 .phui-object-box .phui-object-box .phui-header-shell .phui-header-header { 124 128 font-size: {$normalfontsize}; 125 129 margin: 0;
+161 -27
webroot/rsrc/css/phui/phui-two-column-view.css
··· 2 2 * @provides phui-two-column-view-css 3 3 */ 4 4 5 - .phui-two-column-view { 5 + .phui-two-column-view .phui-two-column-header { 6 6 background-color: #fff; 7 + border-bottom: 1px solid rgba({$alphagrey}, .12); 8 + margin-bottom: 24px; 7 9 } 8 10 9 - .phui-two-column-container { 10 - max-width: 1024px; 11 - margin: 0 auto; 11 + .phui-two-column-view.with-subheader .phui-two-column-header { 12 + margin-bottom: 0; 13 + } 14 + 15 + .phui-two-column-header .phui-header-header { 16 + font-size: 20px; 17 + font-family: 'Aleo', {$fontfamily}; 18 + color: #000; 19 + } 20 + 21 + .device-phone .phui-two-column-header .phui-header-header { 22 + font-size: 18px; 12 23 } 13 24 14 25 .phui-two-column-view .phui-two-column-header .phui-header-shell { 15 - padding-bottom: 32px; 26 + padding: 24px 32px 28px; 27 + border: none; 28 + } 29 + 30 + .phui-two-column-view .phui-two-column-header 31 + .phui-profile-header.phui-header-shell { 32 + padding-bottom: 20px; 16 33 } 17 34 18 - .device-phone .phui-two-column-view .phui-two-column-header .phui-header-shell { 19 - padding-bottom: 20px; 35 + .device .phui-two-column-view .phui-two-column-header .phui-header-shell { 36 + padding: 12px 12px 16px; 20 37 } 21 38 22 - .phui-two-column-fluid .phui-two-column-container { 23 - max-width: 100%; 39 + .phui-two-column-header .phui-header-subheader { 40 + margin-top: 12px; 24 41 } 25 42 26 - .phui-two-column-content { 27 - display: table; 28 - width: 100%; 43 + .phui-two-column-subheader { 44 + padding: 12px 32px; 29 45 } 30 46 31 - .phui-two-column-row { 32 - display: table-row; 47 + .device .phui-two-column-subheader { 48 + padding: 12px 16px; 49 + } 50 + 51 + .device-desktop .phui-two-column-content { 52 + padding: 0 32px; 53 + } 54 + 55 + .device .phui-two-column-content { 56 + padding: 0 12px; 33 57 } 34 58 35 59 .device-desktop .phui-two-column-view .phui-main-column { 36 - display: table-cell; 37 - vertical-align: top; 60 + float: left; 61 + width: calc(100% - 320px); 38 62 } 39 63 40 64 .device-desktop .phui-two-column-view .phui-side-column { 41 - width: 320px; 42 - display: table-cell; 43 - vertical-align: top; 65 + float: right; 66 + width: 300px; 67 + } 68 + 69 + .device .phui-side-column { 70 + margin-bottom: 20px; 71 + } 72 + 73 + .phui-two-column-view .phui-two-column-content 74 + .phui-object-box { 75 + margin: 0 0 20px 0; 76 + } 77 + 78 + /* Timeline */ 79 + 80 + .phui-two-column-view .phui-timeline-view { 81 + padding: 0; 82 + background-position: 78px; 44 83 } 45 84 46 - .device-desktop .phui-two-column-view 47 - .phui-main-column .phui-object-box:first-child { 48 - margin: 0 16px 0 16px; 85 + .phui-two-column-view .phui-main-column .phui-object-box + .phui-timeline-view { 86 + margin-top: -20px; 87 + } 88 + 89 + .device .phui-two-column-view .phui-timeline-view { 90 + background-position: 16px; 91 + padding: 0; 49 92 } 50 93 51 - .device-desktop .phui-two-column-view 52 - .phui-side-column .phui-object-box { 53 - margin: 0 16px 16px 0; 94 + .device-phone .phui-two-column-view .phui-timeline-event-view { 95 + margin: 0; 54 96 } 55 97 56 - .phui-two-column-view pre { 57 - white-space: pre-wrap; 98 + /* Main Column Properties */ 99 + 100 + .device-desktop .phui-main-column .phui-property-list-key { 101 + margin-left: 0; 102 + width: 140px; 103 + } 104 + 105 + .device-desktop .phui-main-column .phui-property-list-value { 106 + margin-left: 8px; 107 + width: auto; 108 + } 109 + 110 + 111 + /* Property / Action List */ 112 + 113 + .phui-two-column-properties .phabricator-action-list-view { 114 + padding-top: 4px; 115 + } 116 + 117 + .device-desktop .phui-two-column-view .phui-property-list-container { 118 + padding: 12px 16px; 119 + } 120 + 121 + .device .phui-two-column-view .phui-property-list-container { 122 + padding: 12px 8px; 123 + } 124 + 125 + .phui-two-column-properties.phui-object-box { 126 + border: 1px solid rgba({$alphablue}, .2); 127 + } 128 + 129 + .phui-two-column-properties .phui-property-list-stacked 130 + .phui-property-list-properties .phui-property-list-key { 131 + margin: 20px 0 8px 0; 132 + padding: 20px 4px 0; 133 + border-top: 1px solid rgba({$alphablue}, .2); 134 + } 135 + 136 + .phui-two-column-properties .phui-property-list-stacked 137 + .phui-property-list-properties .phui-property-list-value { 138 + margin: 0; 139 + padding: 0 4px; 140 + } 141 + 142 + .device-desktop .phui-two-column-properties .phui-property-list-container { 143 + padding: 0 0 20px 0; 144 + } 145 + 146 + .device .phui-two-column-properties .phui-property-list-stacked 147 + .phui-property-list-properties .phui-property-list-key { 148 + margin: 12px 0 4px 0; 149 + padding: 0; 150 + border: none; 151 + } 152 + 153 + .device .phui-two-column-properties .phui-property-list-container { 154 + padding: 0 0 12px 0; 155 + } 156 + 157 + .device .phui-two-column-content .phui-two-column-properties.phui-object-box { 158 + padding: 0 12px; 159 + } 160 + 161 + .phui-two-column-properties .phabricator-action-view-icon { 162 + top: 8px; 163 + left: 8px; 164 + } 165 + 166 + .phabricator-action-view button.phabricator-action-view-item, 167 + .phabricator-action-view-item { 168 + padding: 5px 4px 5px 28px; 169 + } 170 + 171 + .device-desktop .phui-two-column-properties .phabricator-action-view:hover 172 + .phabricator-action-view-item { 173 + text-decoration: none; 174 + background-color: rgba({$alphablue}, .08); 175 + color: {$sky}; 176 + border-radius: 3px; 177 + } 178 + 179 + .device-desktop .phui-two-column-properties .phabricator-action-view:hover 180 + .phabricator-action-view-icon { 181 + color: {$sky}; 182 + } 183 + 184 + .phui-two-column-view .phui-property-list-section-header, 185 + .phui-two-column-view .phui-property-list-text-content { 186 + margin: 0 16px; 187 + } 188 + 189 + .device .phui-two-column-view .phui-property-list-section-header, 190 + .device .phui-two-column-view .phui-property-list-text-content { 191 + margin: 0 8px; 58 192 }