From b4e038d2af4940f229296bc6061d7a7ea140b8df Mon Sep 17 00:00:00 2001 From: Chad Little Date: Mon, 10 Aug 2015 14:55:43 -0700 Subject: [PATCH] Add similiar questions sidebar to Ponder Summary: Ref T9099. Testing out a two column layout in Ponder, with the main idea being creating a more browsable, discoverable product. I'd like the side column though to be a little smarter and provide project based searching. Ideally, if I'm reading Resolved Maniphest questions, other Resolved Maniphest questions are likely interesting. Another scenario is if I'm answering questions, in which case browsing more Open questions would also be interesting. Ponder "Main Column" still needs to be redesigned. Test Plan: Browse open questions, resolved questions. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Maniphest Tasks: T9099 Differential Revision: https://secure.phabricator.com/D13849 --- resources/celerity/map.php | 2 + src/__phutil_library_map__.php | 2 + .../ponder/constants/PonderQuestionStatus.php | 10 +++ .../PonderQuestionViewController.php | 66 +++++++++++++++---- src/view/phui/PHUITwoColumnView.php | 48 ++++++++++++++ .../rsrc/css/phui/phui-two-column-view.css | 33 ++++++++++ 6 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 src/view/phui/PHUITwoColumnView.php create mode 100644 webroot/rsrc/css/phui/phui-two-column-view.css diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 10a54b7e8e..5c3fcbbeeb 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -148,6 +148,7 @@ return array( 'rsrc/css/phui/phui-tag-view.css' => '402691cc', 'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-timeline-view.css' => 'f1bccf73', + 'rsrc/css/phui/phui-two-column-view.css' => 'add0a7d1', 'rsrc/css/phui/phui-workboard-view.css' => '6704d68d', 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '1ebb9bf9', @@ -801,6 +802,7 @@ return array( 'phui-text-css' => 'cf019f54', 'phui-theme-css' => '6b451f24', 'phui-timeline-view-css' => 'f1bccf73', + 'phui-two-column-view-css' => 'add0a7d1', 'phui-workboard-view-css' => '6704d68d', 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 633efef26c..9e76723b92 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1406,6 +1406,7 @@ phutil_register_library_map(array( 'PHUITimelineEventView' => 'view/phui/PHUITimelineEventView.php', 'PHUITimelineExample' => 'applications/uiexample/examples/PHUITimelineExample.php', 'PHUITimelineView' => 'view/phui/PHUITimelineView.php', + 'PHUITwoColumnView' => 'view/phui/PHUITwoColumnView.php', 'PHUITypeaheadExample' => 'applications/uiexample/examples/PHUITypeaheadExample.php', 'PHUIWorkboardView' => 'view/phui/PHUIWorkboardView.php', 'PHUIWorkpanelView' => 'view/phui/PHUIWorkpanelView.php', @@ -5183,6 +5184,7 @@ phutil_register_library_map(array( 'PHUITimelineEventView' => 'AphrontView', 'PHUITimelineExample' => 'PhabricatorUIExample', 'PHUITimelineView' => 'AphrontView', + 'PHUITwoColumnView' => 'AphrontTagView', 'PHUITypeaheadExample' => 'PhabricatorUIExample', 'PHUIWorkboardView' => 'AphrontTagView', 'PHUIWorkpanelView' => 'AphrontTagView', diff --git a/src/applications/ponder/constants/PonderQuestionStatus.php b/src/applications/ponder/constants/PonderQuestionStatus.php index 6c612ec4ae..f37a208bcc 100644 --- a/src/applications/ponder/constants/PonderQuestionStatus.php +++ b/src/applications/ponder/constants/PonderQuestionStatus.php @@ -26,6 +26,16 @@ final class PonderQuestionStatus extends PonderConstants { return idx($map, $status, pht('Unknown')); } + public static function getQuestionStatusName($status) { + $map = array( + self::STATUS_OPEN => pht('Open'), + self::STATUS_CLOSED_RESOLVED => pht('Resolved'), + self::STATUS_CLOSED_OBSOLETE => pht('Obsolete'), + self::STATUS_CLOSED_DUPLICATE => pht('Duplicate'), + ); + return idx($map, $status, pht('Unknown')); + } + public static function getQuestionStatusDescription($status) { $map = array( self::STATUS_OPEN => diff --git a/src/applications/ponder/controller/PonderQuestionViewController.php b/src/applications/ponder/controller/PonderQuestionViewController.php index 1fc9c05a0f..10236d775e 100644 --- a/src/applications/ponder/controller/PonderQuestionViewController.php +++ b/src/applications/ponder/controller/PonderQuestionViewController.php @@ -10,6 +10,7 @@ final class PonderQuestionViewController extends PonderController { ->setViewer($viewer) ->withIDs(array($id)) ->needAnswers(true) + ->needProjectPHIDs(true) ->executeOne(); if (!$question) { return new Aphront404Response(); @@ -51,6 +52,7 @@ final class PonderQuestionViewController extends PonderController { $actions = $this->buildActionListView($question); $properties = $this->buildPropertyListView($question, $actions); + $sidebar = $this->buildSidebar($question); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) @@ -59,21 +61,19 @@ final class PonderQuestionViewController extends PonderController { $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); $crumbs->addTextCrumb('Q'.$id, '/Q'.$id); - $ponder_view = phutil_tag( - 'div', - array( - 'class' => 'ponder-question-view', - ), - array( - $crumbs, - $object_box, - $question_xactions, - $answers, - $answer_add_panel, - )); + $ponder_view = id(new PHUITwoColumnView()) + ->setMainColumn(array( + $object_box, + $question_xactions, + $answers, + $answer_add_panel, + )) + ->setSideColumn($sidebar) + ->addClass('ponder-question-view'); return $this->buildApplicationPage( array( + $crumbs, $ponder_view, ), array( @@ -410,4 +410,46 @@ final class PonderQuestionViewController extends PonderController { return array($show, $hide); } + private function buildSidebar(PonderQuestion $question) { + $viewer = $this->getViewer(); + $status = $question->getStatus(); + $id = $question->getID(); + + $questions = id(new PonderQuestionQuery()) + ->setViewer($viewer) + ->withStatuses(array($status)) + ->withEdgeLogicPHIDs( + PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, + PhabricatorQueryConstraint::OPERATOR_OR, + $question->getProjectPHIDs()) + ->setLimit(10) + ->execute(); + + $list = id(new PHUIObjectItemListView()) + ->setUser($viewer) + ->setNoDataString(pht('No similar questions found.')); + + foreach ($questions as $question) { + if ($id == $question->getID()) { + continue; + } + $item = new PHUIObjectItemView(); + $item->setObjectName('Q'.$question->getID()); + $item->setHeader($question->getTitle()); + $item->setHref('/Q'.$question->getID()); + $item->setObject($question); + + $item->addAttribute( + pht('%d Answer(s)', $question->getAnswerCount())); + + $list->addItem($item); + } + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Similar Questions')) + ->setObjectList($list); + + return $box; + } + } diff --git a/src/view/phui/PHUITwoColumnView.php b/src/view/phui/PHUITwoColumnView.php new file mode 100644 index 0000000000..a7af97da52 --- /dev/null +++ b/src/view/phui/PHUITwoColumnView.php @@ -0,0 +1,48 @@ +mainColumn = $main; + return $this; + } + + public function setSideColumn($side) { + $this->sideColumn = $side; + return $this; + } + + protected function getTagAttributes() { + return array( + 'class' => 'phui-two-column-view grouped', + ); + } + + protected function getTagContent() { + require_celerity_resource('phui-two-column-view-css'); + + $main = phutil_tag( + 'div', + array( + 'class' => 'phui-main-column', + ), + $this->mainColumn); + + $side = phutil_tag( + 'div', + array( + 'class' => 'phui-side-column', + ), + $this->sideColumn); + + return phutil_tag_div( + 'phui-two-column-row', + array( + $main, + $side, + )); + } +} diff --git a/webroot/rsrc/css/phui/phui-two-column-view.css b/webroot/rsrc/css/phui/phui-two-column-view.css new file mode 100644 index 0000000000..4701955b49 --- /dev/null +++ b/webroot/rsrc/css/phui/phui-two-column-view.css @@ -0,0 +1,33 @@ +/** + * @provides phui-two-column-view-css + */ + +.phui-two-column-view { + display: table; + width: 100%; +} + +.phui-two-column-row { + display: table-row; +} + +.device-desktop .phui-two-column-view .phui-main-column { + display: table-cell; + vertical-align: top; +} + +.device-desktop .phui-two-column-view .phui-side-column { + width: 320px; + display: table-cell; + vertical-align: top; +} + +.device-desktop .phui-two-column-view + .phui-main-column .phui-object-box:first-child { + margin: 0 16px 0 16px; +} + +.device-desktop .phui-two-column-view + .phui-side-column .phui-object-box:first-child { + margin: 0 16px 16px 0; +}