1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-05 19:38:27 +01:00

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

@ -7,7 +7,7 @@
*/
return array(
'names' => array(
'core.pkg.css' => '7935f211',
'core.pkg.css' => 'ecdca229',
'core.pkg.js' => '7d8faf57',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '2de124c9',
@ -92,9 +92,9 @@ 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' => 'b40dc156',
'rsrc/css/application/ponder/ponder-view.css' => 'fdd4629b',
'rsrc/css/application/project/project-card-view.css' => '9418c97d',
'rsrc/css/application/project/project-view.css' => '83bb6654',
'rsrc/css/application/project/project-view.css' => '298b7c5b',
'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',
@ -134,7 +134,7 @@ 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' => '50c5cb6a',
'rsrc/css/phui/phui-header-view.css' => 'a6d7b20d',
'rsrc/css/phui/phui-hovercard.css' => 'de1a2119',
'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad',
'rsrc/css/phui/phui-icon.css' => '3f33ab57',
@ -154,7 +154,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' => '0763177e',
'rsrc/css/phui/phui-two-column-view.css' => 'a317616a',
'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',
@ -818,7 +818,7 @@ return array(
'phui-fontkit-css' => '9cda225e',
'phui-form-css' => 'aac1d51d',
'phui-form-view-css' => '4a1a0f5e',
'phui-header-view-css' => '50c5cb6a',
'phui-header-view-css' => 'a6d7b20d',
'phui-hovercard' => '1bd28176',
'phui-hovercard-view-css' => 'de1a2119',
'phui-icon-set-selector-css' => '1ab67aad',
@ -841,7 +841,7 @@ return array(
'phui-tag-view-css' => '9d5d4400',
'phui-theme-css' => '027ba77e',
'phui-timeline-view-css' => '2efceff8',
'phui-two-column-view-css' => '0763177e',
'phui-two-column-view-css' => 'a317616a',
'phui-workboard-color-css' => 'ac6fe6a7',
'phui-workboard-view-css' => 'e6d89647',
'phui-workcard-view-css' => '3646fb96',
@ -855,9 +855,9 @@ return array(
'policy-css' => '957ea14c',
'policy-edit-css' => '815c66f7',
'policy-transaction-detail-css' => '82100a43',
'ponder-view-css' => 'b40dc156',
'ponder-view-css' => 'fdd4629b',
'project-card-view-css' => '9418c97d',
'project-view-css' => '83bb6654',
'project-view-css' => '298b7c5b',
'releeph-core' => '9b3c5733',
'releeph-preview-branch' => 'b7a6f4a5',
'releeph-request-differential-create-dialog' => '8d8b92cd',

View file

@ -3810,7 +3810,6 @@ phutil_register_library_map(array(
'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php',
'PonderAnswerEditController' => 'applications/ponder/controller/PonderAnswerEditController.php',
'PonderAnswerEditor' => 'applications/ponder/editor/PonderAnswerEditor.php',
'PonderAnswerHasVotingUserEdgeType' => 'applications/ponder/edge/PonderAnswerHasVotingUserEdgeType.php',
'PonderAnswerHistoryController' => 'applications/ponder/controller/PonderAnswerHistoryController.php',
'PonderAnswerMailReceiver' => 'applications/ponder/mail/PonderAnswerMailReceiver.php',
'PonderAnswerPHIDType' => 'applications/ponder/phid/PonderAnswerPHIDType.php',
@ -3828,7 +3827,6 @@ phutil_register_library_map(array(
'PonderDefaultViewCapability' => 'applications/ponder/capability/PonderDefaultViewCapability.php',
'PonderEditor' => 'applications/ponder/editor/PonderEditor.php',
'PonderFooterView' => 'applications/ponder/view/PonderFooterView.php',
'PonderHelpfulSaveController' => 'applications/ponder/controller/PonderHelpfulSaveController.php',
'PonderModerateCapability' => 'applications/ponder/capability/PonderModerateCapability.php',
'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php',
'PonderQuestionCommentController' => 'applications/ponder/controller/PonderQuestionCommentController.php',
@ -3850,10 +3848,6 @@ phutil_register_library_map(array(
'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php',
'PonderRemarkupRule' => 'applications/ponder/remarkup/PonderRemarkupRule.php',
'PonderSchemaSpec' => 'applications/ponder/storage/PonderSchemaSpec.php',
'PonderVotableInterface' => 'applications/ponder/storage/PonderVotableInterface.php',
'PonderVote' => 'applications/ponder/constants/PonderVote.php',
'PonderVoteEditor' => 'applications/ponder/editor/PonderVoteEditor.php',
'PonderVotingUserHasAnswerEdgeType' => 'applications/ponder/edge/PonderVotingUserHasAnswerEdgeType.php',
'ProjectAddProjectsEmailCommand' => 'applications/project/command/ProjectAddProjectsEmailCommand.php',
'ProjectBoardTaskCard' => 'applications/project/view/ProjectBoardTaskCard.php',
'ProjectCanLockProjectsCapability' => 'applications/project/capability/ProjectCanLockProjectsCapability.php',
@ -8479,7 +8473,6 @@ phutil_register_library_map(array(
'PonderDAO',
'PhabricatorApplicationTransactionInterface',
'PhabricatorMarkupInterface',
'PonderVotableInterface',
'PhabricatorPolicyInterface',
'PhabricatorFlaggableInterface',
'PhabricatorSubscribableInterface',
@ -8488,7 +8481,6 @@ phutil_register_library_map(array(
'PonderAnswerCommentController' => 'PonderController',
'PonderAnswerEditController' => 'PonderController',
'PonderAnswerEditor' => 'PonderEditor',
'PonderAnswerHasVotingUserEdgeType' => 'PhabricatorEdgeType',
'PonderAnswerHistoryController' => 'PonderController',
'PonderAnswerMailReceiver' => 'PhabricatorObjectMailReceiver',
'PonderAnswerPHIDType' => 'PhabricatorPHIDType',
@ -8506,7 +8498,6 @@ phutil_register_library_map(array(
'PonderDefaultViewCapability' => 'PhabricatorPolicyCapability',
'PonderEditor' => 'PhabricatorApplicationTransactionEditor',
'PonderFooterView' => 'AphrontTagView',
'PonderHelpfulSaveController' => 'PonderController',
'PonderModerateCapability' => 'PhabricatorPolicyCapability',
'PonderQuestion' => array(
'PonderDAO',
@ -8540,9 +8531,6 @@ phutil_register_library_map(array(
'PonderQuestionViewController' => 'PonderController',
'PonderRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'PonderSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PonderVote' => 'PonderConstants',
'PonderVoteEditor' => 'PhabricatorEditor',
'PonderVotingUserHasAnswerEdgeType' => 'PhabricatorEdgeType',
'ProjectAddProjectsEmailCommand' => 'MetaMTAEmailTransactionCommand',
'ProjectBoardTaskCard' => 'Phobject',
'ProjectCanLockProjectsCapability' => 'PhabricatorPolicyCapability',

View file

@ -60,6 +60,7 @@ final class PhabricatorPeopleProfileViewController
$home = id(new PHUITwoColumnView())
->setHeader($header)
->setFluid(true)
->addClass('project-view-home')
->setMainColumn(
array(

View file

@ -49,8 +49,6 @@ final class PhabricatorPonderApplication extends PhabricatorApplication {
=> 'PonderAnswerCommentController',
'answer/history/(?P<id>\d+)/'
=> 'PonderAnswerHistoryController',
'answer/helpful/(?P<action>add|remove)/(?P<id>[1-9]\d*)/'
=> 'PonderHelpfulSaveController',
'question/edit/(?:(?P<id>\d+)/)?'
=> 'PonderQuestionEditController',
'question/create/'

View file

@ -1,8 +0,0 @@
<?php
final class PonderVote extends PonderConstants {
const VOTE_UP = 1;
const VOTE_NONE = 0;
}

View file

@ -1,60 +0,0 @@
<?php
final class PonderHelpfulSaveController extends PonderController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$action = $request->getURIData('action');
$answer = id(new PonderAnswerQuery())
->setViewer($viewer)
->withIDs(array($id))
->needViewerVotes(true)
->executeOne();
if (!$answer) {
return new Aphront404Response();
}
$edit_uri = '/Q'.$answer->getQuestionID();
switch ($action) {
case 'add':
$newvote = PonderVote::VOTE_UP;
break;
case 'remove':
$newvote = PonderVote::VOTE_NONE;
break;
}
if ($request->isFormPost()) {
$editor = id(new PonderVoteEditor())
->setVotable($answer)
->setActor($viewer)
->setVote($newvote)
->saveVote();
return id(new AphrontRedirectResponse())->setURI($edit_uri);
}
if ($action == 'add') {
$title = pht('Mark Answer as Helpful?');
$body = pht('This answer will be marked as helpful.');
$button = pht('Mark Helpful');
} else {
$title = pht('Remove Helpful From Answer?');
$body = pht('This answer will no longer be marked as helpful.');
$button = pht('Remove Helpful');
}
$dialog = $this->newDialog();
$dialog->setTitle($title);
$dialog->appendChild($body);
$dialog->addCancelButton($edit_uri);
$dialog->addSubmitButton($button);
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}

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,37 +104,60 @@ 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(
));
$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')),
mpull($question->getAnswers(), 'getPHID'));
return $this->newPage()
->setTitle('Q'.$question->getID().' '.$question->getTitle())
->setCrumbs($crumbs)
->setPageObjectPHIDs($page_objects)
->appendChild(
array(
$ponder_view,
));
}
@ -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,47 +201,87 @@ 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(
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 ($details) {
$view->addSectionHeader(
pht('Details'),
PHUIPropertyListView::ICON_SUMMARY);
$view->addTextContent(
array(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
$details),
));
if (!$question_details) {
$question_details = phutil_tag(
'em',
array(),
pht('No further details for this question.'));
}
return $view;
$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;
}
/**
@ -211,12 +295,12 @@ final class PonderQuestionViewController extends PonderController {
$viewer = $this->getViewer();
$answers = $question->getAnswers();
if ($answers) {
$author_phids = mpull($answers, 'getAuthorPHID');
$handles = $this->loadViewerHandles($author_phids);
$answers_sort = array_reverse(msort($answers, 'getVoteCount'));
$view = array();
foreach ($answers_sort as $answer) {
foreach ($answers as $answer) {
$id = $answer->getID();
$handle = $handles[$answer->getAuthorPHID()];
@ -236,7 +320,13 @@ final class PonderQuestionViewController extends PonderController {
}
return $view;
$header = id(new PHUIHeaderView())
->setHeader('Answers');
return array($header, $view);
}
return null;
}
}

View file

@ -1,105 +0,0 @@
<?php
final class PonderAnswerHasVotingUserEdgeType extends PhabricatorEdgeType {
const EDGECONST = 19;
public function shouldWriteInverseTransactions() {
return true;
}
public function getInverseEdgeConstant() {
return PonderVotingUserHasAnswerEdgeType::EDGECONST;
}
public function getTransactionAddString(
$actor,
$add_count,
$add_edges) {
return pht(
'%s added %s voting user(s): %s.',
$actor,
$add_count,
$add_edges);
}
public function getTransactionRemoveString(
$actor,
$rem_count,
$rem_edges) {
return pht(
'%s removed %s voting user(s): %s.',
$actor,
$rem_count,
$rem_edges);
}
public function getTransactionEditString(
$actor,
$total_count,
$add_count,
$add_edges,
$rem_count,
$rem_edges) {
return pht(
'%s edited %s voting user(s), added %s: %s; removed %s: %s.',
$actor,
$total_count,
$add_count,
$add_edges,
$rem_count,
$rem_edges);
}
public function getFeedAddString(
$actor,
$object,
$add_count,
$add_edges) {
return pht(
'%s added %s voting user(s) to %s: %s.',
$actor,
$add_count,
$object,
$add_edges);
}
public function getFeedRemoveString(
$actor,
$object,
$rem_count,
$rem_edges) {
return pht(
'%s removed %s voting user(s) from %s: %s.',
$actor,
$rem_count,
$object,
$rem_edges);
}
public function getFeedEditString(
$actor,
$object,
$total_count,
$add_count,
$add_edges,
$rem_count,
$rem_edges) {
return pht(
'%s edited %s voting user(s) for %s, added %s: %s; removed %s: %s.',
$actor,
$total_count,
$object,
$add_count,
$add_edges,
$rem_count,
$rem_edges);
}
}

View file

@ -1,105 +0,0 @@
<?php
final class PonderVotingUserHasAnswerEdgeType extends PhabricatorEdgeType {
const EDGECONST = 20;
public function shouldWriteInverseTransactions() {
return true;
}
public function getInverseEdgeConstant() {
return PonderAnswerHasVotingUserEdgeType::EDGECONST;
}
public function getTransactionAddString(
$actor,
$add_count,
$add_edges) {
return pht(
'%s added %s answer(s): %s.',
$actor,
$add_count,
$add_edges);
}
public function getTransactionRemoveString(
$actor,
$rem_count,
$rem_edges) {
return pht(
'%s removed %s answer(s): %s.',
$actor,
$rem_count,
$rem_edges);
}
public function getTransactionEditString(
$actor,
$total_count,
$add_count,
$add_edges,
$rem_count,
$rem_edges) {
return pht(
'%s edited %s answer(s), added %s: %s; removed %s: %s.',
$actor,
$total_count,
$add_count,
$add_edges,
$rem_count,
$rem_edges);
}
public function getFeedAddString(
$actor,
$object,
$add_count,
$add_edges) {
return pht(
'%s added %s answer(s) to %s: %s.',
$actor,
$add_count,
$object,
$add_edges);
}
public function getFeedRemoveString(
$actor,
$object,
$rem_count,
$rem_edges) {
return pht(
'%s removed %s answer(s) from %s: %s.',
$actor,
$rem_count,
$object,
$rem_edges);
}
public function getFeedEditString(
$actor,
$object,
$total_count,
$add_count,
$add_edges,
$rem_count,
$rem_edges) {
return pht(
'%s edited %s answer(s) for %s, added %s: %s; removed %s: %s.',
$actor,
$total_count,
$object,
$add_count,
$add_edges,
$rem_count,
$rem_edges);
}
}

View file

@ -1,77 +0,0 @@
<?php
final class PonderVoteEditor extends PhabricatorEditor {
private $answer;
private $votable;
private $anwer;
private $vote;
public function setAnswer($answer) {
$this->answer = $answer;
return $this;
}
public function setVotable($votable) {
$this->votable = $votable;
return $this;
}
public function setVote($vote) {
$this->vote = $vote;
return $this;
}
public function saveVote() {
$actor = $this->requireActor();
if (!$this->votable) {
throw new PhutilInvalidStateException('setVotable');
}
$votable = $this->votable;
$newvote = $this->vote;
// prepare vote add, or update if this user is amending an
// earlier vote
$editor = id(new PhabricatorEdgeEditor())
->addEdge(
$actor->getPHID(),
$votable->getUserVoteEdgeType(),
$votable->getVotablePHID(),
array('data' => $newvote))
->removeEdge(
$actor->getPHID(),
$votable->getUserVoteEdgeType(),
$votable->getVotablePHID());
$conn = $votable->establishConnection('w');
$trans = $conn->openTransaction();
$trans->beginReadLocking();
$votable->reload();
$curvote = (int)PhabricatorEdgeQuery::loadSingleEdgeData(
$actor->getPHID(),
$votable->getUserVoteEdgeType(),
$votable->getVotablePHID());
if (!$curvote) {
$curvote = PonderVote::VOTE_NONE;
}
// Adjust votable's score by this much.
$delta = $newvote - $curvote;
queryfx($conn,
'UPDATE %T as t
SET t.voteCount = t.voteCount + %d
WHERE t.PHID = %s',
$votable->getTableName(),
$delta,
$votable->getVotablePHID());
$editor->save();
$trans->endReadLocking();
$trans->saveTransaction();
}
}

View file

@ -8,9 +8,6 @@ final class PonderAnswerQuery
private $authorPHIDs;
private $questionIDs;
private $needViewerVotes;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
@ -31,11 +28,6 @@ final class PonderAnswerQuery
return $this;
}
public function needViewerVotes($need_viewer_votes) {
$this->needViewerVotes = $need_viewer_votes;
return $this;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
@ -86,25 +78,6 @@ final class PonderAnswerQuery
$answer->attachQuestion($question);
}
if ($this->needViewerVotes) {
$viewer_phid = $this->getViewer()->getPHID();
$etype = PonderAnswerHasVotingUserEdgeType::EDGECONST;
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($answers, 'getPHID'))
->withDestinationPHIDs(array($viewer_phid))
->withEdgeTypes(array($etype))
->needEdgeData(true)
->execute();
foreach ($answers as $answer) {
$user_edge = idx(
$edges[$answer->getPHID()][$etype],
$viewer_phid,
array());
$answer->attachUserVote($viewer_phid, idx($user_edge, 'data', 0));
}
}
return $answers;
}

View file

@ -98,7 +98,6 @@ final class PonderQuestionQuery
$aquery = id(new PonderAnswerQuery())
->setViewer($this->getViewer())
->setOrderVector(array('-id'))
->needViewerVotes(true)
->withQuestionIDs(mpull($questions, 'getID'));
$answers = $aquery->execute();

View file

@ -4,7 +4,6 @@ final class PonderAnswer extends PonderDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorMarkupInterface,
PonderVotableInterface,
PhabricatorPolicyInterface,
PhabricatorFlaggableInterface,
PhabricatorSubscribableInterface,
@ -18,14 +17,10 @@ final class PonderAnswer extends PonderDAO
protected $content;
protected $mailKey;
protected $status;
protected $voteCount;
private $vote;
private $question = self::ATTACHABLE;
private $comments;
private $userVotes = array();
public static function initializeNewAnswer(
PhabricatorUser $actor,
PonderQuestion $question) {
@ -39,7 +34,7 @@ final class PonderAnswer extends PonderDAO
->setContent('')
->attachQuestion($question)
->setAuthorPHID($actor->getPHID())
->setVoteCount(0)
->setVoteCount('0')
->setStatus(PonderAnswerStatus::ANSWER_STATUS_VISIBLE);
}
@ -57,23 +52,6 @@ final class PonderAnswer extends PonderDAO
return '/Q'.$this->getQuestionID().'#A'.$this->getID();
}
public function setUserVote($vote) {
$this->vote = $vote['data'];
if (!$this->vote) {
$this->vote = PonderVote::VOTE_NONE;
}
return $this;
}
public function attachUserVote($user_phid, $vote) {
$this->vote = $vote;
return $this;
}
public function getUserVote() {
return $this->vote;
}
public function setComments($comments) {
$this->comments = $comments;
return $this;
@ -181,15 +159,6 @@ final class PonderAnswer extends PonderDAO
return (bool)$this->getID();
}
// votable interface
public function getUserVoteEdgeType() {
return PonderVotingUserHasAnswerEdgeType::EDGECONST;
}
public function getVotablePHID() {
return $this->getPHID();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -1,8 +0,0 @@
<?php
interface PonderVotableInterface {
public function getUserVoteEdgeType();
public function getVotablePHID();
}

View file

@ -42,42 +42,16 @@ final class PonderAddAnswerView extends AphrontView {
}
$box_style = null;
$own_question = null;
$hide_action_id = celerity_generate_unique_node_id();
$show_action_id = celerity_generate_unique_node_id();
if ($question->getAuthorPHID() == $viewer->getPHID()) {
$box_style = 'display: none;';
$open_link = javelin_tag(
'a',
array(
'sigil' => 'reveal-content',
'class' => 'mml',
'id' => $hide_action_id,
'href' => '#',
'meta' => array(
'showIDs' => array($show_action_id),
'hideIDs' => array($hide_action_id),
),
),
pht('Add an answer.'));
$own_question = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
->setID($hide_action_id)
->appendChild(
pht(
'This is your own question. You are welcome to provide
an answer if you have found a resolution.'))
->appendChild($open_link);
}
$header = id(new PHUIHeaderView())
->setHeader(pht('Add Answer'));
->setHeader(pht('New Answer'))
->addClass('ponder-add-answer-header');
$form = new AphrontFormView();
$form
->setUser($this->user)
->setAction($this->actionURI)
->setWorkflow(true)
->setFullWidth(true)
->addHiddenInput('question_id', $question->getID())
->appendChild(
id(new PhabricatorRemarkupControl())
@ -103,22 +77,14 @@ final class PonderAddAnswerView extends AphrontView {
}
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($form);
->appendChild($form)
->setBackground(PHUIObjectBoxView::GREY)
->addClass('ponder-add-answer-view');
if ($info_panel) {
$box->setInfoView($info_panel);
}
$box = phutil_tag(
'div',
array(
'style' => $box_style,
'class' => 'mlt',
'id' => $show_action_id,
),
$box);
return array($own_question, $box);
return array($header, $box);
}
}

View file

@ -95,7 +95,7 @@ final class PonderAnswerView extends AphrontTagView {
$content = phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup mlt mlb msr msl',
'class' => 'phabricator-remarkup',
),
PhabricatorMarkupEngine::renderOneObject(
$answer,
@ -110,26 +110,14 @@ final class PonderAnswerView extends AphrontTagView {
->setContentID($content_id)
->setCount(count($this->transactions));
$votes = $answer->getVoteCount();
$vote_class = null;
if ($votes > 0) {
$vote_class = 'ponder-footer-action-helpful';
}
$icon = id(new PHUIIconView())
->setIcon('fa-thumbs-up msr');
$helpful = phutil_tag(
'span',
array(
'class' => 'ponder-footer-action '.$vote_class,
),
array($icon, $votes));
$footer->addAction($helpful);
$content = phutil_tag_div(
'ponder-answer-content', array($anchor, $content, $footer));
$answer_view = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($anchor)
->appendChild($content)
->appendChild($footer);
->setBackground(PHUIObjectBoxView::GREY)
->addClass('ponder-answer')
->appendChild($content);
$comment_view = id(new PhabricatorApplicationTransactionCommentView())
->setUser($viewer)
@ -170,28 +158,6 @@ final class PonderAnswerView extends AphrontTagView {
->setUser($viewer)
->setObject($answer);
$user_marked = $answer->getUserVote();
$can_vote = $viewer->isLoggedIn();
if ($user_marked) {
$helpful_uri = "/ponder/answer/helpful/remove/{$id}/";
$helpful_icon = 'fa-times';
$helpful_text = pht('Remove Helpful');
} else {
$helpful_uri = "/ponder/answer/helpful/add/{$id}/";
$helpful_icon = 'fa-thumbs-up';
$helpful_text = pht('Mark as Helpful');
}
$view->addAction(
id(new PhabricatorActionView())
->setIcon($helpful_icon)
->setName($helpful_text)
->setHref($helpful_uri)
->setRenderAsForm(true)
->setDisabled(!$can_vote)
->setWorkflow($can_vote));
$view->addAction(
id(new PhabricatorActionView())
->setIcon('fa-pencil')

View file

@ -36,12 +36,8 @@ final class PonderFooterView extends AphrontTagView {
$content_id = $this->contentID;
if ($this->count == 0) {
$icon = id(new PHUIIconView())
->setIcon('fa-comments msr');
$text = pht('Add a Comment');
} else {
$icon = id(new PHUIIconView())
->setIcon('fa-comments msr');
$text = pht('Show %d Comment(s)', new PhutilNumber($this->count));
}
@ -58,7 +54,7 @@ final class PonderFooterView extends AphrontTagView {
'hideIDs' => array($hide_action_id),
),
),
array($icon, $text));
array($text));
$show_action = javelin_tag(
'a',
@ -73,7 +69,7 @@ final class PonderFooterView extends AphrontTagView {
'hideIDs' => array($content_id, $show_action_id),
),
),
array($icon, pht('Hide Comments')));
array(pht('Hide Comments')));
$actions[] = $hide_action;
$actions[] = $show_action;

View file

@ -87,6 +87,7 @@ final class PhabricatorProjectProfileController
$home = id(new PHUITwoColumnView())
->setHeader($header)
->setFluid(true)
->addClass('project-view-home')
->setMainColumn(
array(

View file

@ -19,6 +19,7 @@ class PhabricatorApplicationTransactionCommentView extends AphrontView {
private $objectPHID;
private $headerText;
private $noPermission;
private $fullWidth;
private $currentVersion;
private $versionedDraft;
@ -102,6 +103,11 @@ class PhabricatorApplicationTransactionCommentView extends AphrontView {
return $this;
}
public function setFullWidth($fw) {
$this->fullWidth = $fw;
return $this;
}
public function setCommentActions(array $comment_actions) {
assert_instances_of($comment_actions, 'PhabricatorEditEngineCommentAction');
$this->commentActions = $comment_actions;
@ -209,6 +215,7 @@ class PhabricatorApplicationTransactionCommentView extends AphrontView {
->setUser($this->getUser())
->addSigil('transaction-append')
->setWorkflow(true)
->setFullWidth($this->fullWidth)
->setMetadata(
array(
'objectPHID' => $this->getObjectPHID(),

View file

@ -5,6 +5,7 @@ final class PHUITwoColumnView extends AphrontTagView {
private $mainColumn;
private $sideColumn;
private $display;
private $fluid;
private $header;
const DISPLAY_LEFT = 'phui-side-column-left';
@ -25,12 +26,17 @@ final class PHUITwoColumnView extends AphrontTagView {
return $this;
}
public function setFluid($fluid) {
$this->fluid = $fluid;
return $this;
}
public function setDisplay($display) {
$this->display = $display;
return $this;
}
public function getDisplay() {
private function getDisplay() {
if ($this->display) {
return $this->display;
} else {
@ -43,6 +49,10 @@ final class PHUITwoColumnView extends AphrontTagView {
$classes[] = 'phui-two-column-view';
$classes[] = $this->getDisplay();
if ($this->fluid) {
$classes[] = 'phui-two-column-fluid';
}
return array(
'class' => implode(' ', $classes),
);
@ -79,6 +89,14 @@ final class PHUITwoColumnView extends AphrontTagView {
$header = phutil_tag_div('phui-two-column-header', $this->header);
}
return array($header, $table);
return phutil_tag(
'div',
array(
'class' => 'phui-two-column-container',
),
array(
$header,
$table,
));
}
}

View file

@ -2,16 +2,112 @@
* @provides ponder-view-css
*/
.ponder-show-comments {
text-align: center;
padding: 8px;
margin: 0 16px;
float: right;
font-weight: bold;
.ponder-question-view {
background: #fff;
border-bottom: 1px solid {$blueborder};
border-left: 1px solid {$lightblueborder};
border-right: 1px solid {$lightblueborder};
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;
border-radius: 0;
}
.device .ponder-question-view .phui-timeline-view,
.device .ponder-question-view .phui-timeline-event-view {
margin: 0;
padding: 0;
}
.ponder-view-properties .phui-property-list-container {
margin: 0;
padding: 0;
}
.ponder-question-view .phui-document-container {
border: none;
}
.ponder-view-properties .phui-property-list-stacked
.phui-property-list-properties .phui-property-list-key {
padding: 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 {
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 {
@ -27,52 +123,102 @@
margin-left: 12px;
}
.ponder-answer-view .phui-header-shell {
padding-bottom: 8px;
.ponder-question-view .ponder-answer-view .phui-header-shell {
padding: 4px 8px 3px 8px;
}
.ponder-answer-view .phui-header-image-href {
display: flex;
}
.ponder-answer-view .phui-header-view .phui-header-header {
font-size: 16px;
font-size: 15px;
}
.ponder-answer-view .phui-header-col1 {
width: 45px;
width: 40px;
}
.ponder-answer-view .ponder-answer-content {
background-color: #fff;
padding: 16px 16px 0 16px;
}
.device-phone .ponder-answer-view .ponder-answer-content {
padding: 12px 12px 0 12px;
}
.ponder-answer-view .phui-header-image {
height: 35px;
width: 35px;
height: 30px;
width: 30px;
border-radius: 3px;
}
.ponder-answer-wiki-header {
font-weight: bold;
border-bottom: 1px solid {$lightblueborder};
color: {$bluetext};
padding-bottom: 8px;
margin-bottom: 16px;
}
.ponder-footer-view {
margin: 0 0 -4px;
text-align: left;
margin-top: 16px;
border-bottom: 1px solid {$thinblueborder};
}
.ponder-answer-view .ponder-footer-view {
margin-top: 24px;
border-top: 1px solid rgba({$alphagrey}, .15);
border-bottom: none;
}
body .phui-main-column .ponder-question-content .ponder-answer-view
.phui-object-box.ponder-answer {
margin: 0;
padding: 0;
}
.ponder-footer-view .ponder-footer-action {
padding: 4px 8px;
padding: 8px 0;
margin-right: 8px;
color: {$anchor};
display: inline-block;
background-color: rgba({$alphablue}, 0.06);
}
.ponder-footer-view .ponder-footer-action.ponder-footer-action-helpful {
background-color: {$lightyellow};
color: {$bluetext};
.ponder-add-answer-header {
margin-top: 64px;
}
.ponder-footer-view .ponder-footer-action.ponder-footer-action-helpful
.phui-icon-view {
color: {$bluetext};
.ponder-add-answer-view {
margin-top: 16px;
}
.ponder-footer-view .ponder-footer-action .phui-icon-view {
color: {$anchor};
.ponder-question-content div.ponder-question-add-comment-view
div.phui-box.phui-object-box {
background: {$lightbluebackground};
margin-right: 0;
margin-left: 32px;
}
.ponder-footer-view a:hover {
text-decoration: none;
background-color: rgba({$alphablue}, 0.10);
.device .ponder-question-content div.ponder-question-add-comment-view
div.phui-box.phui-object-box {
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;
}

View file

@ -85,12 +85,9 @@
padding: 4px 8px 0 8px;
}
.device-desktop .phui-two-column-view.project-view-badges .phui-side-column {
width: 366px;
}
.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 {

View file

@ -98,6 +98,12 @@ body .phui-header-shell.phui-bleed-header
font-size: {$normalfontsize};
}
.phui-header-action-link {
margin-bottom: 4px;
margin-top: 4px;
float: right;
}
.device-phone .phui-header-action-link .phui-button-text {
visibility: hidden;
width: 0;

View file

@ -2,6 +2,27 @@
* @provides phui-two-column-view-css
*/
.phui-two-column-view {
background-color: #fff;
}
.phui-two-column-container {
max-width: 1024px;
margin: 0 auto;
}
.phui-two-column-view .phui-two-column-header .phui-header-shell {
padding-bottom: 32px;
}
.device-phone .phui-two-column-view .phui-two-column-header .phui-header-shell {
padding-bottom: 20px;
}
.phui-two-column-fluid .phui-two-column-container {
max-width: 100%;
}
.phui-two-column-content {
display: table;
width: 100%;