mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 08:42:41 +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:
parent
ea66aead59
commit
9a827096a7
13 changed files with 189 additions and 16 deletions
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_slowvote.slowvote_poll
|
||||
ADD COLUMN isClosed BOOL NOT NULL;
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue