mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-09 16:32:39 +01:00
Allowing Closing of questions
Summary: Fixes T3579 As a basic overview, this enables the author of a question to open/close a question. Other bits; - Add "Open" filter to the builtin queries - Add "Status" to search form - Refactor ponder constants - Add coloured bars for different question statuses Test Plan: - Open/Close questions - Search for some bits - Use filters Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T3579 Differential Revision: https://secure.phabricator.com/D6590 Conflicts: src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
This commit is contained in:
parent
91c08ca629
commit
70a5ec600d
21 changed files with 222 additions and 24 deletions
5
resources/sql/patches/20130727.ponderquestionstatus.sql
Normal file
5
resources/sql/patches/20130727.ponderquestionstatus.sql
Normal file
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE {$NAMESPACE}_ponder.ponder_question
|
||||
ADD COLUMN `status` INT(10) UNSIGNED NOT NULL AFTER `authorPHID`;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_ponder.ponder_question
|
||||
ADD INDEX `status` (`status`);
|
|
@ -1881,9 +1881,10 @@ phutil_register_library_map(array(
|
|||
'PonderCommentMail' => 'applications/ponder/mail/PonderCommentMail.php',
|
||||
'PonderCommentQuery' => 'applications/ponder/query/PonderCommentQuery.php',
|
||||
'PonderCommentSaveController' => 'applications/ponder/controller/PonderCommentSaveController.php',
|
||||
'PonderConstants' => 'applications/ponder/PonderConstants.php',
|
||||
'PonderConstants' => 'applications/ponder/constants/PonderConstants.php',
|
||||
'PonderController' => 'applications/ponder/controller/PonderController.php',
|
||||
'PonderDAO' => 'applications/ponder/storage/PonderDAO.php',
|
||||
'PonderLiterals' => 'applications/ponder/constants/PonderLiterals.php',
|
||||
'PonderMail' => 'applications/ponder/mail/PonderMail.php',
|
||||
'PonderMentionMail' => 'applications/ponder/mail/PonderMentionMail.php',
|
||||
'PonderPHIDTypeQuestion' => 'applications/ponder/phid/PonderPHIDTypeQuestion.php',
|
||||
|
@ -1897,6 +1898,8 @@ phutil_register_library_map(array(
|
|||
'PonderQuestionPreviewController' => 'applications/ponder/controller/PonderQuestionPreviewController.php',
|
||||
'PonderQuestionQuery' => 'applications/ponder/query/PonderQuestionQuery.php',
|
||||
'PonderQuestionSearchEngine' => 'applications/ponder/query/PonderQuestionSearchEngine.php',
|
||||
'PonderQuestionStatus' => 'applications/ponder/constants/PonderQuestionStatus.php',
|
||||
'PonderQuestionStatusController' => 'applications/ponder/controller/PonderQuestionStatusController.php',
|
||||
'PonderQuestionSummaryView' => 'applications/ponder/view/PonderQuestionSummaryView.php',
|
||||
'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php',
|
||||
'PonderRemarkupRule' => 'applications/ponder/remarkup/PonderRemarkupRule.php',
|
||||
|
@ -1905,6 +1908,7 @@ phutil_register_library_map(array(
|
|||
'PonderUserProfileView' => 'applications/ponder/view/PonderUserProfileView.php',
|
||||
'PonderVotableInterface' => 'applications/ponder/storage/PonderVotableInterface.php',
|
||||
'PonderVotableView' => 'applications/ponder/view/PonderVotableView.php',
|
||||
'PonderVote' => 'applications/ponder/constants/PonderVote.php',
|
||||
'PonderVoteEditor' => 'applications/ponder/editor/PonderVoteEditor.php',
|
||||
'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php',
|
||||
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
|
||||
|
@ -3996,6 +4000,7 @@ phutil_register_library_map(array(
|
|||
'PonderCommentSaveController' => 'PonderController',
|
||||
'PonderController' => 'PhabricatorController',
|
||||
'PonderDAO' => 'PhabricatorLiskDAO',
|
||||
'PonderLiterals' => 'PonderConstants',
|
||||
'PonderMail' => 'PhabricatorMail',
|
||||
'PonderMentionMail' => 'PonderMail',
|
||||
'PonderPHIDTypeQuestion' => 'PhabricatorPHIDType',
|
||||
|
@ -4021,6 +4026,8 @@ phutil_register_library_map(array(
|
|||
'PonderQuestionPreviewController' => 'PonderController',
|
||||
'PonderQuestionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PonderQuestionSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PonderQuestionStatus' => 'PonderConstants',
|
||||
'PonderQuestionStatusController' => 'PonderController',
|
||||
'PonderQuestionSummaryView' => 'AphrontView',
|
||||
'PonderQuestionViewController' => 'PonderController',
|
||||
'PonderRemarkupRule' => 'PhabricatorRemarkupRuleObject',
|
||||
|
@ -4028,6 +4035,7 @@ phutil_register_library_map(array(
|
|||
'PonderSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
|
||||
'PonderUserProfileView' => 'AphrontView',
|
||||
'PonderVotableView' => 'AphrontView',
|
||||
'PonderVote' => 'PonderConstants',
|
||||
'PonderVoteEditor' => 'PhabricatorEditor',
|
||||
'PonderVoteSaveController' => 'PonderController',
|
||||
'ProjectRemarkupRule' => 'PhabricatorRemarkupRuleObject',
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PonderConstants {
|
||||
const UP_VOTE = 1;
|
||||
const NONE_VOTE = 0;
|
||||
const DOWN_VOTE = -1;
|
||||
|
||||
const ANSWERED_LITERAL = "answered";
|
||||
const ASKED_LITERAL = "asked";
|
||||
}
|
|
@ -54,6 +54,8 @@ final class PhabricatorApplicationPonder extends PhabricatorApplication {
|
|||
'answer/preview/' => 'PonderAnswerPreviewController',
|
||||
'question/ask/' => 'PonderQuestionAskController',
|
||||
'question/preview/' => 'PonderQuestionPreviewController',
|
||||
'question/(?P<status>open|close)/(?P<id>[1-9]\d*)/' =>
|
||||
'PonderQuestionStatusController',
|
||||
'comment/add/' => 'PonderCommentSaveController',
|
||||
'(?P<kind>question)/vote/' => 'PonderVoteSaveController',
|
||||
'(?P<kind>answer)/vote/' => 'PonderVoteSaveController'
|
||||
|
|
4
src/applications/ponder/constants/PonderConstants.php
Normal file
4
src/applications/ponder/constants/PonderConstants.php
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class PonderConstants {
|
||||
}
|
10
src/applications/ponder/constants/PonderLiterals.php
Normal file
10
src/applications/ponder/constants/PonderLiterals.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
/**
|
||||
* @group ponder
|
||||
*/
|
||||
final class PonderLiterals extends PonderConstants {
|
||||
|
||||
const LITERAL_ANSWERED = "answered";
|
||||
const LITERAL_ASKED = "asked";
|
||||
|
||||
}
|
34
src/applications/ponder/constants/PonderQuestionStatus.php
Normal file
34
src/applications/ponder/constants/PonderQuestionStatus.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group ponder
|
||||
*/
|
||||
final class PonderQuestionStatus extends PonderConstants {
|
||||
|
||||
const STATUS_OPEN = 0;
|
||||
const STATUS_CLOSED = 1;
|
||||
|
||||
public static function getQuestionStatusMap() {
|
||||
return array(
|
||||
self::STATUS_OPEN => pht('Open'),
|
||||
self::STATUS_CLOSED => pht('Closed'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function getQuestionStatusFullName($status) {
|
||||
$map = array(
|
||||
self::STATUS_OPEN => pht('Open'),
|
||||
self::STATUS_CLOSED => pht('Closed by author'),
|
||||
);
|
||||
return idx($map, $status, '???');
|
||||
}
|
||||
|
||||
public static function getQuestionStatusTagColor($status) {
|
||||
$map = array(
|
||||
self::STATUS_CLOSED => PhabricatorTagView::COLOR_BLACK,
|
||||
);
|
||||
|
||||
return idx($map, $status);
|
||||
}
|
||||
|
||||
}
|
11
src/applications/ponder/constants/PonderVote.php
Normal file
11
src/applications/ponder/constants/PonderVote.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
/**
|
||||
* @group ponder
|
||||
*/
|
||||
final class PonderVote extends PonderConstants {
|
||||
|
||||
const VOTE_UP = 1;
|
||||
const VOTE_NONE = 0;
|
||||
const VOTE_DOWN = -1;
|
||||
|
||||
}
|
|
@ -29,7 +29,7 @@ final class PonderAnswerPreviewController
|
|||
->setPreview(true)
|
||||
->setUser($user)
|
||||
->setHandles($handles)
|
||||
->setAction(PonderConstants::ANSWERED_LITERAL);
|
||||
->setAction(PonderLiterals::LITERAL_ANSWERED);
|
||||
|
||||
return id(new AphrontAjaxResponse())
|
||||
->setContent($view->render());
|
||||
|
|
|
@ -17,6 +17,7 @@ final class PonderQuestionAskController extends PonderController {
|
|||
if ($request->isFormPost()) {
|
||||
$question->setTitle($request->getStr('title'));
|
||||
$question->setContent($request->getStr('content'));
|
||||
$question->setStatus(PonderQuestionStatus::STATUS_OPEN);
|
||||
|
||||
$len = phutil_utf8_strlen($question->getTitle());
|
||||
if ($len < 1) {
|
||||
|
|
|
@ -45,6 +45,9 @@ final class PonderQuestionListController extends PonderController
|
|||
$item->setHeader($question->getTitle());
|
||||
$item->setHref('/Q'.$question->getID());
|
||||
$item->setObject($question);
|
||||
$item->setBarColor(
|
||||
PonderQuestionStatus::getQuestionStatusTagColor(
|
||||
$question->getStatus()));
|
||||
|
||||
$created_date = phabricator_date($question->getDateCreated(), $viewer);
|
||||
$item->addIcon('none', $created_date);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
final class PonderQuestionStatusController
|
||||
extends PonderController {
|
||||
|
||||
private $status;
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->status = idx($data, 'status');
|
||||
$this->id = idx($data, 'id');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$question = id(new PonderQuestion())->load($this->id);
|
||||
if (!$question) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
switch ($this->status) {
|
||||
case 'open':
|
||||
$question->setStatus(PonderQuestionStatus::STATUS_OPEN);
|
||||
break;
|
||||
case 'close':
|
||||
$question->setStatus(PonderQuestionStatus::STATUS_CLOSED);
|
||||
break;
|
||||
default:
|
||||
return new Aphront400Response();
|
||||
}
|
||||
|
||||
$question->save();
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI('/Q'.$question->getID());
|
||||
}
|
||||
|
||||
}
|
|
@ -92,10 +92,34 @@ final class PonderQuestionViewController extends PonderController {
|
|||
|
||||
private function buildActionListView(PonderQuestion $question) {
|
||||
$request = $this->getRequest();
|
||||
return id(new PhabricatorActionListView())
|
||||
->setUser($request->getUser())
|
||||
$user = $request->getUser();
|
||||
|
||||
$action_list = id(new PhabricatorActionListView())
|
||||
->setUser($user)
|
||||
->setObject($question)
|
||||
->setObjectURI($request->getRequestURI());
|
||||
|
||||
if ($user->getPhid() === $question->getAuthorPhid()) {
|
||||
if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) {
|
||||
$name = pht("Close Question");
|
||||
$icon = "delete";
|
||||
$href = "close";
|
||||
} else {
|
||||
$name = pht("Open Question");
|
||||
$icon = "enable";
|
||||
$href = "open";
|
||||
}
|
||||
$action_list->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName($name)
|
||||
->setIcon($icon)
|
||||
->setRenderAsForm(true)
|
||||
->setHref(
|
||||
$this->getApplicationURI(
|
||||
"/question/{$href}/{$this->questionID}/")));
|
||||
}
|
||||
|
||||
return $action_list;
|
||||
}
|
||||
|
||||
private function buildPropertyListView(
|
||||
|
@ -105,6 +129,11 @@ final class PonderQuestionViewController extends PonderController {
|
|||
$view = id(new PhabricatorPropertyListView())
|
||||
->setUser($viewer)
|
||||
->setObject($question);
|
||||
|
||||
$view->addProperty(
|
||||
pht('Status'),
|
||||
PonderQuestionStatus::getQuestionStatusFullName($question->getStatus()));
|
||||
|
||||
$view->addProperty(
|
||||
pht('Author'),
|
||||
$this->getHandle($question->getAuthorPHID())->renderLink());
|
||||
|
|
|
@ -56,7 +56,7 @@ final class PonderVoteEditor extends PhabricatorEditor {
|
|||
$votable->getVotablePHID());
|
||||
|
||||
if (!$curvote) {
|
||||
$curvote = PonderConstants::NONE_VOTE;
|
||||
$curvote = PonderVote::VOTE_NONE;
|
||||
}
|
||||
|
||||
// adjust votable's score by this much
|
||||
|
|
|
@ -12,6 +12,11 @@ final class PonderQuestionQuery
|
|||
private $answererPHIDs;
|
||||
private $order = self::ORDER_CREATED;
|
||||
|
||||
private $status = 'status-any';
|
||||
const STATUS_ANY = 'status-any';
|
||||
const STATUS_OPEN = 'status-open';
|
||||
const STATUS_CLOSED = 'status-closed';
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
|
@ -27,6 +32,11 @@ final class PonderQuestionQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withStatus($status) {
|
||||
$this->status = $status;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withAnswererPHIDs(array $phids) {
|
||||
$this->answererPHIDs = $phids;
|
||||
return $this;
|
||||
|
@ -83,6 +93,27 @@ final class PonderQuestionQuery
|
|||
$this->authorPHIDs);
|
||||
}
|
||||
|
||||
if ($this->status) {
|
||||
switch ($this->status) {
|
||||
case self::STATUS_ANY:
|
||||
break;
|
||||
case self::STATUS_OPEN:
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'q.status = %d',
|
||||
PonderQuestionStatus::STATUS_OPEN);
|
||||
break;
|
||||
case self::STATUS_CLOSED:
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'q.status = %d',
|
||||
PonderQuestionStatus::STATUS_CLOSED);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown status query '{$this->status}'!");
|
||||
}
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
|
|
|
@ -14,6 +14,8 @@ final class PonderQuestionSearchEngine
|
|||
'answererPHIDs',
|
||||
array_values($request->getArr('answerers')));
|
||||
|
||||
$saved->setParameter('status', $request->getStr('status'));
|
||||
|
||||
return $saved;
|
||||
}
|
||||
|
||||
|
@ -30,6 +32,18 @@ final class PonderQuestionSearchEngine
|
|||
$query->withAnswererPHIDs($answerer_phids);
|
||||
}
|
||||
|
||||
$status = $saved->getParameter('status');
|
||||
if ($status != null) {
|
||||
switch ($status) {
|
||||
case 0:
|
||||
$query->withStatus(PonderQuestionQuery::STATUS_OPEN);
|
||||
break;
|
||||
case 1:
|
||||
$query->withStatus(PonderQuestionQuery::STATUS_CLOSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
@ -39,6 +53,8 @@ final class PonderQuestionSearchEngine
|
|||
|
||||
$author_phids = $saved_query->getParameter('authorPHIDs', array());
|
||||
$answerer_phids = $saved_query->getParameter('answererPHIDs', array());
|
||||
$status = $saved_query->getParameter(
|
||||
'status', PonderQuestionStatus::STATUS_OPEN);
|
||||
|
||||
$phids = array_merge($author_phids, $answerer_phids);
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
|
@ -61,7 +77,13 @@ final class PonderQuestionSearchEngine
|
|||
->setDatasource('/typeahead/common/users/')
|
||||
->setName('answerers')
|
||||
->setLabel(pht('Answered By'))
|
||||
->setValue($answerer_tokens));
|
||||
->setValue($answerer_tokens))
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setLabel(pht('Status'))
|
||||
->setName('status')
|
||||
->setValue($status)
|
||||
->setOptions(PonderQuestionStatus::getQuestionStatusMap()));
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
|
@ -70,6 +92,7 @@ final class PonderQuestionSearchEngine
|
|||
|
||||
public function getBuiltinQueryNames() {
|
||||
$names = array(
|
||||
'open' => pht('Open Questions'),
|
||||
'all' => pht('All Questions'),
|
||||
);
|
||||
|
||||
|
@ -89,6 +112,8 @@ final class PonderQuestionSearchEngine
|
|||
switch ($query_key) {
|
||||
case 'all':
|
||||
return $query;
|
||||
case 'open':
|
||||
return $query->setParameter('status', PonderQuestionQuery::STATUS_OPEN);
|
||||
case 'authored':
|
||||
return $query->setParameter(
|
||||
'authorPHIDs',
|
||||
|
|
|
@ -29,7 +29,7 @@ final class PonderAnswer extends PonderDAO
|
|||
public function setUserVote($vote) {
|
||||
$this->vote = $vote['data'];
|
||||
if (!$this->vote) {
|
||||
$this->vote = PonderConstants::NONE_VOTE;
|
||||
$this->vote = PonderVote::VOTE_NONE;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ final class PonderQuestion extends PonderDAO
|
|||
protected $phid;
|
||||
|
||||
protected $authorPHID;
|
||||
protected $status;
|
||||
protected $content;
|
||||
protected $contentSource;
|
||||
|
||||
|
@ -95,7 +96,7 @@ final class PonderQuestion extends PonderDAO
|
|||
public function setUserVote($vote) {
|
||||
$this->vote = $vote['data'];
|
||||
if (!$this->vote) {
|
||||
$this->vote = PonderConstants::NONE_VOTE;
|
||||
$this->vote = PonderVote::VOTE_NONE;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ final class PonderAnswerListView extends AphrontView {
|
|||
$view
|
||||
->setQuestion($question)
|
||||
->setTarget($cur_answer)
|
||||
->setAction(PonderConstants::ANSWERED_LITERAL)
|
||||
->setAction(PonderLiterals::LITERAL_ANSWERED)
|
||||
->setHandles($handles)
|
||||
->setUser($user);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ final class PonderQuestionDetailView extends AphrontView {
|
|||
->setQuestion($question)
|
||||
->setUser($user)
|
||||
->setHandles($handles)
|
||||
->setAction(PonderConstants::ASKED_LITERAL);
|
||||
->setAction(PonderLiterals::LITERAL_ASKED);
|
||||
|
||||
$commentview = new PonderCommentListView();
|
||||
$commentview
|
||||
|
|
|
@ -1471,14 +1471,18 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'type' => 'php',
|
||||
'name' => $this->getPatchPath('20130716.archivememberlessprojects.php'),
|
||||
),
|
||||
'20130723.taskstarttime.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130723.taskstarttime.sql'),
|
||||
),
|
||||
'20130722.pholioreplace.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130722.pholioreplace.sql'),
|
||||
),
|
||||
'20130723.taskstarttime.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130723.taskstarttime.sql'),
|
||||
),
|
||||
'20130727.ponderquestionstatus.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20130727.ponderquestionstatus.sql'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue