1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 18:22: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:
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', 'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
'PhabricatorSlowvoteCapabilityDefaultView' => 'applications/slowvote/capability/PhabricatorSlowvoteCapabilityDefaultView.php', 'PhabricatorSlowvoteCapabilityDefaultView' => 'applications/slowvote/capability/PhabricatorSlowvoteCapabilityDefaultView.php',
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php', 'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php',
'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/PhabricatorSlowvoteComment.php', 'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/PhabricatorSlowvoteComment.php',
'PhabricatorSlowvoteCommentController' => 'applications/slowvote/controller/PhabricatorSlowvoteCommentController.php', 'PhabricatorSlowvoteCommentController' => 'applications/slowvote/controller/PhabricatorSlowvoteCommentController.php',
'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php', 'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php',
@ -4968,6 +4969,7 @@ phutil_register_library_map(array(
'PhabricatorSetupIssueView' => 'AphrontView', 'PhabricatorSetupIssueView' => 'AphrontView',
'PhabricatorSlowvoteCapabilityDefaultView' => 'PhabricatorPolicyCapability', 'PhabricatorSlowvoteCapabilityDefaultView' => 'PhabricatorPolicyCapability',
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteCloseController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteCommentController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteCommentController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteController' => 'PhabricatorController', 'PhabricatorSlowvoteController' => 'PhabricatorController',

View file

@ -46,6 +46,7 @@ final class PhabricatorApplicationSlowvote extends PhabricatorApplication {
'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteEditController', 'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteEditController',
'(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteVoteController', '(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteVoteController',
'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteCommentController', '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()) ->setObjectName('V'.$poll->getID())
->setHeader($poll->getQuestion()) ->setHeader($poll->getQuestion())
->setHref('/V'.$poll->getID()) ->setHref('/V'.$poll->getID())
->setDisabled($poll->getIsClosed())
->addIcon('none', $date_created); ->addIcon('none', $date_created);
$description = $poll->getDescription(); $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()) $header = id(new PHUIHeaderView())
->setHeader($poll->getQuestion()) ->setHeader($poll->getQuestion())
->setUser($user) ->setUser($user)
->setStatus($header_icon, '', $header_name)
->setPolicyObject($poll); ->setPolicyObject($poll);
$actions = $this->buildActionView($poll); $actions = $this->buildActionView($poll);
@ -91,6 +95,10 @@ final class PhabricatorSlowvotePollController
$poll, $poll,
PhabricatorPolicyCapability::CAN_EDIT); 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( $view->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())
->setName(pht('Edit Poll')) ->setName(pht('Edit Poll'))
@ -99,6 +107,14 @@ final class PhabricatorSlowvotePollController
->setDisabled(!$can_edit) ->setDisabled(!$can_edit)
->setWorkflow(!$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; return $view;
} }

View file

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

View file

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

View file

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

View file

@ -10,6 +10,7 @@ final class PhabricatorSlowvoteSearchEngine
$this->readUsersFromRequest($request, 'authors')); $this->readUsersFromRequest($request, 'authors'));
$saved->setParameter('voted', $request->getBool('voted')); $saved->setParameter('voted', $request->getBool('voted'));
$saved->setParameter('statuses', $request->getArr('statuses'));
return $saved; return $saved;
} }
@ -22,6 +23,16 @@ final class PhabricatorSlowvoteSearchEngine
$query->withVotesByViewer(true); $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; return $query;
} }
@ -35,6 +46,7 @@ final class PhabricatorSlowvoteSearchEngine
->execute(); ->execute();
$voted = $saved_query->getParameter('voted', false); $voted = $saved_query->getParameter('voted', false);
$statuses = $saved_query->getParameter('statuses', array());
$form $form
->appendChild( ->appendChild(
@ -49,7 +61,20 @@ final class PhabricatorSlowvoteSearchEngine
'voted', 'voted',
1, 1,
pht("Show only polls I've voted in."), 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) { protected function getURI($path) {
@ -58,6 +83,7 @@ final class PhabricatorSlowvoteSearchEngine
public function getBuiltinQueryNames() { public function getBuiltinQueryNames() {
$names = array( $names = array(
'open' => pht('Open Polls'),
'all' => pht('All Polls'), 'all' => pht('All Polls'),
); );
@ -74,6 +100,8 @@ final class PhabricatorSlowvoteSearchEngine
$query->setQueryKey($query_key); $query->setQueryKey($query_key);
switch ($query_key) { switch ($query_key) {
case 'open':
return $query->setParameter('statuses', array('open'));
case 'all': case 'all':
return $query; return $query;
case 'authored': case 'authored':

View file

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

View file

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

View file

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