1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-27 07:50:57 +01:00

Ability to close poll

Summary: Fixes T3566 List of poll actions should include ability to close an open poll or reopen a closed poll.

Test Plan: Poll author should be able to close/reopen poll. Non-author should get policy screen when attempting to close/reopen poll.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: epriestley, Korvin

Maniphest Tasks: T3566

Differential Revision: https://secure.phabricator.com/D8846
This commit is contained in:
lkassianik 2014-04-24 12:00:31 -07:00 committed by epriestley
parent ea66aead59
commit 9a827096a7
13 changed files with 189 additions and 16 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_slowvote.slowvote_poll
ADD COLUMN isClosed BOOL NOT NULL;

View file

@ -2092,6 +2092,7 @@ phutil_register_library_map(array(
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
'PhabricatorSlowvoteCapabilityDefaultView' => 'applications/slowvote/capability/PhabricatorSlowvoteCapabilityDefaultView.php',
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php',
'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/PhabricatorSlowvoteComment.php',
'PhabricatorSlowvoteCommentController' => 'applications/slowvote/controller/PhabricatorSlowvoteCommentController.php',
'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php',
@ -4968,6 +4969,7 @@ phutil_register_library_map(array(
'PhabricatorSetupIssueView' => 'AphrontView',
'PhabricatorSlowvoteCapabilityDefaultView' => 'PhabricatorPolicyCapability',
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteCloseController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteCommentController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteController' => 'PhabricatorController',

View file

@ -46,6 +46,7 @@ final class PhabricatorApplicationSlowvote extends PhabricatorApplication {
'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteEditController',
'(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteVoteController',
'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteCommentController',
'close/(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteCloseController',
),
);
}

View file

@ -0,0 +1,71 @@
<?php
final class PhabricatorSlowvoteCloseController
extends PhabricatorSlowvoteController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$poll = id(new PhabricatorSlowvoteQuery())
->setViewer($user)
->withIDs(array($this->id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$poll) {
return new Aphront404Response();
}
$close_uri = '/V'.$poll->getID();
if ($request->isFormPost()) {
if ($poll->getIsClosed()) {
$new_status = 0;
} else {
$new_status = 1;
}
$xactions = array();
$xactions[] = id(new PhabricatorSlowvoteTransaction())
->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_CLOSE)
->setNewValue($new_status);
id(new PhabricatorSlowvoteEditor())
->setActor($user)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true)
->applyTransactions($poll, $xactions);
return id(new AphrontRedirectResponse())->setURI($close_uri);
}
if ($poll->getIsClosed()) {
$title = pht('Reopen Poll');
$content = pht('Are you sure you want to reopen the poll?');
$submit = pht('Reopen');
} else {
$title = pht('Close Poll');
$content = pht('Are you sure you want to close the poll?');
$submit = pht('Close');
}
return $this->newDialog()
->setTitle($title)
->appendChild($content)
->addSubmitButton($submit)
->addCancelButton($close_uri);
}
}

View file

@ -51,6 +51,7 @@ final class PhabricatorSlowvoteListController
->setObjectName('V'.$poll->getID())
->setHeader($poll->getQuestion())
->setHref('/V'.$poll->getID())
->setDisabled($poll->getIsClosed())
->addIcon('none', $date_created);
$description = $poll->getDescription();

View file

@ -41,9 +41,13 @@ final class PhabricatorSlowvotePollController
));
}
$header_icon = $poll->getIsClosed() ? 'oh-closed' : 'open';
$header_name = $poll->getIsClosed() ? pht('Closed') : pht('Open');
$header = id(new PHUIHeaderView())
->setHeader($poll->getQuestion())
->setUser($user)
->setStatus($header_icon, '', $header_name)
->setPolicyObject($poll);
$actions = $this->buildActionView($poll);
@ -91,6 +95,10 @@ final class PhabricatorSlowvotePollController
$poll,
PhabricatorPolicyCapability::CAN_EDIT);
$is_closed = $poll->getIsClosed();
$close_poll_text = $is_closed ? pht('Reopen Poll') : pht('Close Poll');
$close_poll_icon = $is_closed ? 'enable' : 'disable';
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Poll'))
@ -99,6 +107,14 @@ final class PhabricatorSlowvotePollController
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$view->addAction(
id(new PhabricatorActionView())
->setName($close_poll_text)
->setIcon($close_poll_icon)
->setHref($this->getApplicationURI('close/'.$poll->getID().'/'))
->setDisabled(!$can_edit)
->setWorkflow(true));
return $view;
}

View file

@ -25,6 +25,9 @@ final class PhabricatorSlowvoteVoteController
if (!$poll) {
return new Aphront404Response();
}
if ($poll->getIsClosed()) {
return new Aphront400Response();
}
$options = $poll->getOptions();
$user_choices = $poll->getViewerChoices($user);

View file

@ -13,6 +13,7 @@ final class PhabricatorSlowvoteEditor
$types[] = PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION;
$types[] = PhabricatorSlowvoteTransaction::TYPE_RESPONSES;
$types[] = PhabricatorSlowvoteTransaction::TYPE_SHUFFLE;
$types[] = PhabricatorSlowvoteTransaction::TYPE_CLOSE;
return $types;
}
@ -54,6 +55,8 @@ final class PhabricatorSlowvoteEditor
return $object->getResponseVisibility();
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
return $object->getShuffle();
case PhabricatorSlowvoteTransaction::TYPE_CLOSE:
return $object->getIsClosed();
}
}
@ -66,6 +69,7 @@ final class PhabricatorSlowvoteEditor
case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
case PhabricatorSlowvoteTransaction::TYPE_RESPONSES:
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
case PhabricatorSlowvoteTransaction::TYPE_CLOSE:
return $xaction->getNewValue();
}
}
@ -87,6 +91,9 @@ final class PhabricatorSlowvoteEditor
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
$object->setShuffle($xaction->getNewValue());
break;
case PhabricatorSlowvoteTransaction::TYPE_CLOSE:
$object->setIsClosed((int)$xaction->getNewValue());
break;
}
}

View file

@ -10,6 +10,7 @@ final class PhabricatorSlowvoteQuery
private $phids;
private $authorPHIDs;
private $withVotesByViewer;
private $isClosed;
private $needOptions;
private $needChoices;
@ -35,6 +36,11 @@ final class PhabricatorSlowvoteQuery
return $this;
}
public function withIsClosed($with_closed) {
$this->isClosed = $with_closed;
return $this;
}
public function needOptions($need_options) {
$this->needOptions = $need_options;
return $this;
@ -146,6 +152,13 @@ final class PhabricatorSlowvoteQuery
$this->authorPHIDs);
}
if ($this->isClosed !== null) {
$where[] = qsprintf(
$conn_r,
'p.isClosed = %d',
(int)$this->isClosed);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}

View file

@ -10,6 +10,7 @@ final class PhabricatorSlowvoteSearchEngine
$this->readUsersFromRequest($request, 'authors'));
$saved->setParameter('voted', $request->getBool('voted'));
$saved->setParameter('statuses', $request->getArr('statuses'));
return $saved;
}
@ -22,6 +23,16 @@ final class PhabricatorSlowvoteSearchEngine
$query->withVotesByViewer(true);
}
$statuses = $saved->getParameter('statuses', array());
if (count($statuses) == 1) {
$status = head($statuses);
if ($status == 'open') {
$query->withIsClosed(false);
} else {
$query->withIsClosed(true);
}
}
return $query;
}
@ -35,6 +46,7 @@ final class PhabricatorSlowvoteSearchEngine
->execute();
$voted = $saved_query->getParameter('voted', false);
$statuses = $saved_query->getParameter('statuses', array());
$form
->appendChild(
@ -49,7 +61,20 @@ final class PhabricatorSlowvoteSearchEngine
'voted',
1,
pht("Show only polls I've voted in."),
$voted));
$voted))
->appendChild(
id(new AphrontFormCheckboxControl())
->setLabel(pht('Status'))
->addCheckbox(
'statuses[]',
'open',
pht('Open'),
in_array('open', $statuses))
->addCheckbox(
'statuses[]',
'closed',
pht('Closed'),
in_array('closed', $statuses)));
}
protected function getURI($path) {
@ -58,6 +83,7 @@ final class PhabricatorSlowvoteSearchEngine
public function getBuiltinQueryNames() {
$names = array(
'open' => pht('Open Polls'),
'all' => pht('All Polls'),
);
@ -74,6 +100,8 @@ final class PhabricatorSlowvoteSearchEngine
$query->setQueryKey($query_key);
switch ($query_key) {
case 'open':
return $query->setParameter('statuses', array('open'));
case 'all':
return $query;
case 'authored':

View file

@ -24,6 +24,7 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO
protected $shuffle;
protected $method;
protected $viewPolicy;
protected $isClosed = 0;
private $options = self::ATTACHABLE;
private $choices = self::ATTACHABLE;

View file

@ -7,6 +7,7 @@ final class PhabricatorSlowvoteTransaction
const TYPE_DESCRIPTION = 'vote:description';
const TYPE_RESPONSES = 'vote:responses';
const TYPE_SHUFFLE = 'vote:shuffle';
const TYPE_CLOSE = 'vote:close';
public function getApplicationName() {
return 'slowvote';
@ -28,6 +29,7 @@ final class PhabricatorSlowvoteTransaction
case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
case PhabricatorSlowvoteTransaction::TYPE_RESPONSES:
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
case PhabricatorSlowvoteTransaction::TYPE_CLOSE:
return ($old === null);
}
@ -73,6 +75,18 @@ final class PhabricatorSlowvoteTransaction
'%s made poll responses appear in a fixed order.',
$this->renderHandleLink($author_phid));
}
break;
case PhabricatorSlowvoteTransaction::TYPE_CLOSE:
if ($new) {
return pht(
'%s closed this poll.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s reopened this poll.',
$this->renderHandleLink($author_phid));
}
break;
}
@ -95,6 +109,12 @@ final class PhabricatorSlowvoteTransaction
return 'fa-pencil';
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
return 'fa-refresh';
case PhabricatorSlowvoteTransaction::TYPE_CLOSE:
if ($new) {
return 'fa-ban';
} else {
return 'fa-pencil';
}
}
return parent::getIcon();
@ -110,6 +130,7 @@ final class PhabricatorSlowvoteTransaction
case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
case PhabricatorSlowvoteTransaction::TYPE_RESPONSES:
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
case PhabricatorSlowvoteTransaction::TYPE_CLOSE:
return PhabricatorTransactions::COLOR_BLUE;
}

View file

@ -128,24 +128,28 @@ final class SlowvoteEmbedView extends AphrontView {
),
$quip);
$submit = phutil_tag(
'div',
array(
'class' => 'slowvote-footer',
),
phutil_tag(
if ($poll->getIsClosed()) {
$submit = null;
} else {
$submit = phutil_tag(
'div',
array(
'class' => 'slowvote-footer-content',
'class' => 'slowvote-footer',
),
array(
$hint,
phutil_tag(
'button',
array(
),
pht('Engage in Deliberations')),
)));
phutil_tag(
'div',
array(
'class' => 'slowvote-footer-content',
),
array(
$hint,
phutil_tag(
'button',
array(
),
pht('Engage in Deliberations')),
)));
}
$body = phabricator_form(
$this->getUser(),
@ -251,6 +255,8 @@ final class SlowvoteEmbedView extends AphrontView {
PhabricatorSlowvotePoll::METHOD_APPROVAL => 'checkbox',
);
$closed = $this->getPoll()->getIsClosed();
return phutil_tag(
'input',
array(
@ -258,6 +264,7 @@ final class SlowvoteEmbedView extends AphrontView {
'name' => 'vote[]',
'value' => $option->getID(),
'checked' => ($selected ? 'checked' : null),
'disabled' => ($closed ? 'disabled' : null),
));
}