Redesign PonderQuestionView

Summary: Full new UI, testing some upcoming treatments for consideration in other View controllers. Small tweaks to allow PHUITwoColumnView to have fixed and fluid width, and let TransactionCommentView go fullWidth.

Test Plan:
Tested a number of Ponder cases, New Question, with and without summary, with and without answers, with and without comments. Mobile, Tablet, and Desktop layouts. Verify Project and Profile UI's still in tact.

{F1120961}

{F1120962}

{F1120963}

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D15315
This commit is contained in:
Chad Little
2016-02-23 07:23:58 -08:00
parent 9baae00fbd
commit e9f4ca6ca3
24 changed files with 425 additions and 646 deletions

View File

@@ -31,6 +31,7 @@ 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,7 +44,32 @@ final class PonderQuestionViewController extends PonderController {
}
$actions = $this->buildActionListView($question);
$properties = $this->buildPropertyListView($question, $actions);
$properties = $this->buildPropertyListView($question);
$details = $this->buildDetailsPropertyView($question);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$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(
@@ -55,11 +81,14 @@ final class PonderQuestionViewController extends PonderController {
$add_comment = id(new PhabricatorApplicationTransactionCommentView())
->setUser($viewer)
->setObjectPHID($question->getPHID())
->setFullWidth(true)
->setShowPreview(false)
->setHeaderText(pht('Question Comment'))
->setAction($this->getApplicationURI("/question/comment/{$id}/"))
->setSubmitButtonName(pht('Comment'));
$add_comment = phutil_tag_div(
'ponder-question-add-comment-view', $add_comment);
$comment_view = phutil_tag(
'div',
array(
@@ -75,38 +104,61 @@ final class PonderQuestionViewController extends PonderController {
->setContentID($content_id)
->setCount(count($xactions));
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties)
->appendChild($footer);
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
$crumbs->addTextCrumb('Q'.$id, '/Q'.$id);
$crumbs->setBorder(true);
$answer_wiki = null;
if ($question->getAnswerWiki()) {
$answer = phutil_tag_div('mlt mlb msr msl', $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())
->setHeaderText(pht('Answer Summary'))
->setColor(PHUIObjectBoxView::COLOR_BLUE)
->appendChild($answer);
->setBackground(PHUIObjectBoxView::BLUE)
->appendChild($wiki_header)
->appendChild($wiki)
->addClass('ponder-answer-wiki');
}
return $this->buildApplicationPage(
require_celerity_resource('ponder-view-css');
$ponder_content = phutil_tag(
'div',
array(
$crumbs,
$object_box,
'class' => 'ponder-question-content',
),
array(
$details,
$footer,
$comment_view,
$answer_wiki,
$answers,
$answer_add_panel,
),
array(
'title' => 'Q'.$question->getID().' '.$question->getTitle(),
'pageObjects' => array_merge(
array($question->getPHID()),
mpull($question->getAnswers(), 'getPHID')),
));
$ponder_view = id(new PHUITwoColumnView())
->setHeader($header)
->setMainColumn($ponder_content)
->setSideColumn($properties)
->addClass('ponder-question-view');
$page_objects = array_merge(
array($question->getPHID()),
mpull($question->getAnswers(), 'getPHID'));
return $this->newPage()
->setTitle('Q'.$question->getID().' '.$question->getTitle())
->setCrumbs($crumbs)
->setPageObjectPHIDs($page_objects)
->appendChild(
array(
$ponder_view,
));
}
private function buildActionListView(PonderQuestion $question) {
@@ -123,14 +175,6 @@ final class PonderQuestionViewController extends PonderController {
->setUser($viewer)
->setObject($question);
$view->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setName(pht('Edit Question'))
->setHref($this->getApplicationURI("/question/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) {
$name = pht('Close Question');
$icon = 'fa-check-square-o';
@@ -157,49 +201,89 @@ final class PonderQuestionViewController extends PonderController {
}
private function buildPropertyListView(
PonderQuestion $question,
PhabricatorActionListView $actions) {
PonderQuestion $question) {
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($question)
->setActionList($actions);
$view->addProperty(
pht('Author'),
$viewer->renderHandle($question->getAuthorPHID()));
$view->addProperty(
pht('Created'),
phabricator_datetime($question->getDateCreated(), $viewer));
->setStacked(true);
$view->invokeWillRenderEvent();
$details = PhabricatorMarkupEngine::renderOneObject(
$question,
$question->getMarkupField(),
$viewer);
if ($details) {
$view->addSectionHeader(
pht('Details'),
PHUIPropertyListView::ICON_SUMMARY);
$view->addTextContent(
array(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
$details),
));
if (!$view->hasAnyProperties()) {
return null;
}
$view = id(new PHUIObjectBoxView())
->appendChild($view)
->setBackground(PHUIObjectBoxView::GREY)
->addClass('ponder-view-properties');
return $view;
}
private function buildDetailsPropertyView(
PonderQuestion $question) {
$viewer = $this->getViewer();
$question_details = PhabricatorMarkupEngine::renderOneObject(
$question,
$question->getMarkupField(),
$viewer);
if (!$question_details) {
$question_details = phutil_tag(
'em',
array(),
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);
$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;
}
/**
* This is fairly non-standard; building N timelines at once (N = number of
* answers) is tricky business.
@@ -211,32 +295,38 @@ final class PonderQuestionViewController extends PonderController {
$viewer = $this->getViewer();
$answers = $question->getAnswers();
$author_phids = mpull($answers, 'getAuthorPHID');
$handles = $this->loadViewerHandles($author_phids);
$answers_sort = array_reverse(msort($answers, 'getVoteCount'));
if ($answers) {
$author_phids = mpull($answers, 'getAuthorPHID');
$handles = $this->loadViewerHandles($author_phids);
$view = array();
foreach ($answers_sort as $answer) {
$id = $answer->getID();
$handle = $handles[$answer->getAuthorPHID()];
$view = array();
foreach ($answers as $answer) {
$id = $answer->getID();
$handle = $handles[$answer->getAuthorPHID()];
$timeline = $this->buildTransactionTimeline(
$answer,
id(new PonderAnswerTransactionQuery())
->withTransactionTypes(array(PhabricatorTransactions::TYPE_COMMENT)));
$xactions = $timeline->getTransactions();
$timeline = $this->buildTransactionTimeline(
$answer,
id(new PonderAnswerTransactionQuery())
->withTransactionTypes(array(PhabricatorTransactions::TYPE_COMMENT)));
$xactions = $timeline->getTransactions();
$view[] = id(new PonderAnswerView())
->setUser($viewer)
->setAnswer($answer)
->setTransactions($xactions)
->setTimeline($timeline)
->setHandle($handle);
$view[] = id(new PonderAnswerView())
->setUser($viewer)
->setAnswer($answer)
->setTransactions($xactions)
->setTimeline($timeline)
->setHandle($handle);
}
$header = id(new PHUIHeaderView())
->setHeader('Answers');
return array($header, $view);
}
return $view;
return null;
}
}