mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 23:02:42 +01:00
Embed slowvotes have basic interaction
Summary: User can now vote through embed slowvote Test Plan: Voted'n stuff Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin, chad, AnhNhan Maniphest Tasks: T2883 Differential Revision: https://secure.phabricator.com/D5743
This commit is contained in:
parent
67da5d6e4b
commit
1fa307750d
8 changed files with 236 additions and 50 deletions
|
@ -2269,6 +2269,19 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/repository/repository-crossreference.js',
|
'disk' => '/rsrc/js/application/repository/repository-crossreference.js',
|
||||||
),
|
),
|
||||||
|
'javelin-behavior-slowvote-embed' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/1315b118/rsrc/js/application/slowvote/behavior-slowvote-embed.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-util',
|
||||||
|
2 => 'javelin-stratcom',
|
||||||
|
3 => 'javelin-dom',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/application/slowvote/behavior-slowvote-embed.js',
|
||||||
|
),
|
||||||
'javelin-behavior-stripe-payment-form' =>
|
'javelin-behavior-stripe-payment-form' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/c1a12d77/rsrc/js/application/phortune/behavior-stripe-payment-form.js',
|
'uri' => '/res/c1a12d77/rsrc/js/application/phortune/behavior-stripe-payment-form.js',
|
||||||
|
@ -3332,7 +3345,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'phabricator-slowvote-css' =>
|
'phabricator-slowvote-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/357ccc42/rsrc/css/application/slowvote/slowvote.css',
|
'uri' => '/res/d1c2e05a/rsrc/css/application/slowvote/slowvote.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -1388,6 +1388,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php',
|
'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php',
|
||||||
'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php',
|
'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php',
|
||||||
'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php',
|
'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php',
|
||||||
|
'PhabricatorSlowvoteVoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteVoteController.php',
|
||||||
'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php',
|
'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php',
|
||||||
'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php',
|
'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php',
|
||||||
'PhabricatorSortTableExample' => 'applications/uiexample/examples/PhabricatorSortTableExample.php',
|
'PhabricatorSortTableExample' => 'applications/uiexample/examples/PhabricatorSortTableExample.php',
|
||||||
|
@ -3088,6 +3089,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO',
|
'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO',
|
||||||
'PhabricatorSlowvotePoll' => 'PhabricatorSlowvoteDAO',
|
'PhabricatorSlowvotePoll' => 'PhabricatorSlowvoteDAO',
|
||||||
'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
|
'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
|
||||||
|
'PhabricatorSlowvoteVoteController' => 'PhabricatorSlowvoteController',
|
||||||
'PhabricatorSlugTestCase' => 'PhabricatorTestCase',
|
'PhabricatorSlugTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorSortTableExample' => 'PhabricatorUIExample',
|
'PhabricatorSortTableExample' => 'PhabricatorUIExample',
|
||||||
'PhabricatorSourceCodeView' => 'AphrontView',
|
'PhabricatorSourceCodeView' => 'AphrontView',
|
||||||
|
|
|
@ -42,6 +42,7 @@ final class PhabricatorApplicationSlowvote extends PhabricatorApplication {
|
||||||
'/vote/' => array(
|
'/vote/' => array(
|
||||||
'(?:view/(?P<view>\w+)/)?' => 'PhabricatorSlowvoteListController',
|
'(?:view/(?P<view>\w+)/)?' => 'PhabricatorSlowvoteListController',
|
||||||
'create/' => 'PhabricatorSlowvoteCreateController',
|
'create/' => 'PhabricatorSlowvoteCreateController',
|
||||||
|
'(?P<id>[1-9]\d*)/' => 'PhabricatorSlowvoteVoteController',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,48 +44,16 @@ final class PhabricatorSlowvotePollController
|
||||||
$comment_text = $viewer_comment->getCommentText();
|
$comment_text = $viewer_comment->getCommentText();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isAjax()) {
|
||||||
$comment = idx($comments_by_user, $viewer_phid, null);
|
$embed = id(new SlowvoteEmbedView())
|
||||||
if ($comment) {
|
->setPoll($poll)
|
||||||
$comment->delete();
|
->setOptions($options)
|
||||||
}
|
->setViewerChoices($viewer_choices);
|
||||||
|
|
||||||
$comment_text = $request->getStr('comments');
|
return id(new AphrontAjaxResponse())
|
||||||
if (strlen($comment_text)) {
|
->setContent(array(
|
||||||
id(new PhabricatorSlowvoteComment())
|
'pollID' => $poll->getID(),
|
||||||
->setAuthorPHID($viewer_phid)
|
'contentHTML' => $embed->render()));
|
||||||
->setPollID($poll->getID())
|
|
||||||
->setCommentText($comment_text)
|
|
||||||
->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
$votes = $request->getArr('vote');
|
|
||||||
|
|
||||||
switch ($poll->getMethod()) {
|
|
||||||
case PhabricatorSlowvotePoll::METHOD_PLURALITY:
|
|
||||||
// Enforce only one vote.
|
|
||||||
$votes = array_slice($votes, 0, 1);
|
|
||||||
break;
|
|
||||||
case PhabricatorSlowvotePoll::METHOD_APPROVAL:
|
|
||||||
// No filtering.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Exception("Unknown poll method!");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($viewer_choices as $viewer_choice) {
|
|
||||||
$viewer_choice->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($votes as $vote) {
|
|
||||||
id(new PhabricatorSlowvoteChoice())
|
|
||||||
->setAuthorPHID($viewer_phid)
|
|
||||||
->setPollID($poll->getID())
|
|
||||||
->setOptionID($vote)
|
|
||||||
->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI('/V'.$poll->getID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require_celerity_resource('phabricator-slowvote-css');
|
require_celerity_resource('phabricator-slowvote-css');
|
||||||
|
@ -159,6 +127,7 @@ final class PhabricatorSlowvotePollController
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
$form = id(new AphrontFormView())
|
||||||
->setUser($user)
|
->setUser($user)
|
||||||
|
->setAction(sprintf('/vote/%d/', $poll->getID()))
|
||||||
->appendChild(hsprintf(
|
->appendChild(hsprintf(
|
||||||
'<p class="aphront-form-instructions">%s</p>',
|
'<p class="aphront-form-instructions">%s</p>',
|
||||||
$instructions))
|
$instructions))
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group slowvote
|
||||||
|
*/
|
||||||
|
final class PhabricatorSlowvoteVoteController
|
||||||
|
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 PhabricatorSlowvotePoll())->load($this->id);
|
||||||
|
$options = id(new PhabricatorSlowvoteOption())->loadAllWhere(
|
||||||
|
'pollID = %d',
|
||||||
|
$poll->getID());
|
||||||
|
$user_choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
|
||||||
|
'pollID = %d AND authorPHID = %s',
|
||||||
|
$poll->getID(),
|
||||||
|
$user->getPHID());
|
||||||
|
|
||||||
|
$comment_text = $request->getStr('comments');
|
||||||
|
$old_comment = id(new PhabricatorSlowvoteComment())->loadOneWhere(
|
||||||
|
'pollID = %d AND authorPHID = %s',
|
||||||
|
$poll->getID(),
|
||||||
|
$user->getPHID());
|
||||||
|
|
||||||
|
$update_comment = false;
|
||||||
|
if ($old_comment && $comment_text &&
|
||||||
|
$old_comment->getCommentText() !== $comment_text) {
|
||||||
|
|
||||||
|
$update_comment = true;
|
||||||
|
} else if (!$old_comment && $comment_text) {
|
||||||
|
$update_comment = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($update_comment) {
|
||||||
|
if ($old_comment) {
|
||||||
|
$old_comment->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
id(new PhabricatorSlowvoteComment())
|
||||||
|
->setAuthorPHID($user->getPHID())
|
||||||
|
->setPollID($poll->getID())
|
||||||
|
->setCommentText($comment_text)
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$old_votes = mpull($user_choices, null, 'getOptionID');
|
||||||
|
|
||||||
|
if ($request->isAjax()) {
|
||||||
|
$vote = $request->getInt('vote');
|
||||||
|
$votes = array_keys($old_votes);
|
||||||
|
$votes = array_fuse($votes, $votes);
|
||||||
|
|
||||||
|
if ($poll->getMethod() == PhabricatorSlowvotePoll::METHOD_PLURALITY) {
|
||||||
|
if (idx($votes, $vote, false)) {
|
||||||
|
$votes = array();
|
||||||
|
} else {
|
||||||
|
$votes = array($vote);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (idx($votes, $vote, false)) {
|
||||||
|
unset($votes[$vote]);
|
||||||
|
} else {
|
||||||
|
$votes[$vote] = $vote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->updateVotes($user, $poll, $old_votes, $votes);
|
||||||
|
|
||||||
|
$updated_choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
|
||||||
|
'pollID = %d AND authorPHID = %s',
|
||||||
|
$poll->getID(),
|
||||||
|
$user->getPHID());
|
||||||
|
|
||||||
|
$embed = id(new SlowvoteEmbedView())
|
||||||
|
->setPoll($poll)
|
||||||
|
->setOptions($options)
|
||||||
|
->setViewerChoices($updated_choices);
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent(array(
|
||||||
|
'pollID' => $poll->getID(),
|
||||||
|
'contentHTML' => $embed->render()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$request->isFormPost()) {
|
||||||
|
return id(new Aphront404Response());
|
||||||
|
}
|
||||||
|
|
||||||
|
$votes = $request->getArr('vote');
|
||||||
|
$votes = array_fuse($votes, $votes);
|
||||||
|
|
||||||
|
$this->updateVotes($user, $poll, $old_votes, $votes);
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())->setURI('/V'.$poll->getID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateVotes($user, $poll, $old_votes, $votes) {
|
||||||
|
|
||||||
|
if (!empty($votes) && count($votes) > 1 &&
|
||||||
|
$poll->getMethod() == PhabricatorSlowvotePoll::METHOD_PLURALITY) {
|
||||||
|
return id(new Aphront400Response());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($old_votes as $old_vote) {
|
||||||
|
if (!idx($votes, $old_vote->getOptionID(), false)) {
|
||||||
|
$old_vote->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($votes as $vote) {
|
||||||
|
if (idx($old_votes, $vote, false)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
id(new PhabricatorSlowvoteChoice())
|
||||||
|
->setAuthorPHID($user->getPHID())
|
||||||
|
->setPollID($poll->getID())
|
||||||
|
->setOptionID($vote)
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -39,6 +39,11 @@ final class SlowvoteEmbedView extends AphrontView {
|
||||||
}
|
}
|
||||||
|
|
||||||
require_celerity_resource('phabricator-slowvote-css');
|
require_celerity_resource('phabricator-slowvote-css');
|
||||||
|
require_celerity_resource('javelin-behavior-slowvote-embed');
|
||||||
|
|
||||||
|
$config = array(
|
||||||
|
'pollID' => $this->poll->getID());
|
||||||
|
Javelin::initBehavior('slowvote-embed', $config);
|
||||||
|
|
||||||
$user_choices = array();
|
$user_choices = array();
|
||||||
if (!empty($this->viewerChoices)) {
|
if (!empty($this->viewerChoices)) {
|
||||||
|
@ -56,17 +61,30 @@ final class SlowvoteEmbedView extends AphrontView {
|
||||||
|
|
||||||
$selected = '';
|
$selected = '';
|
||||||
|
|
||||||
|
|
||||||
if (idx($user_choices, $option->getID(), false)) {
|
if (idx($user_choices, $option->getID(), false)) {
|
||||||
$classes .= ' phabricator-slowvote-embed-option-selected';
|
$classes .= ' phabricator-slowvote-embed-option-selected';
|
||||||
$selected = '@';
|
$selected = '@';
|
||||||
}
|
}
|
||||||
|
|
||||||
$option_text = phutil_tag(
|
$is_selected = javelin_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => $classes
|
'class' => 'phabricator-slowvote-embed-option-vote',
|
||||||
|
'sigil' => 'slowvote-embed-vote'
|
||||||
),
|
),
|
||||||
$selected.$option->getName());
|
$selected);
|
||||||
|
|
||||||
|
$option_text = javelin_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => $classes,
|
||||||
|
'sigil' => 'slowvote-option',
|
||||||
|
'meta' => array(
|
||||||
|
'optionID' => $option->getID()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array($is_selected, $option->getName()));
|
||||||
|
|
||||||
$options[] = phutil_tag(
|
$options[] = phutil_tag(
|
||||||
'div',
|
'div',
|
||||||
|
@ -95,11 +113,16 @@ final class SlowvoteEmbedView extends AphrontView {
|
||||||
array(),
|
array(),
|
||||||
$options);
|
$options);
|
||||||
|
|
||||||
return phutil_tag(
|
return javelin_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => 'phabricator-slowvote-embed'
|
'class' => 'phabricator-slowvote-embed',
|
||||||
|
'sigil' => 'slowvote-embed',
|
||||||
|
'meta' => array(
|
||||||
|
'pollID' => $this->poll->getID()
|
||||||
|
)
|
||||||
),
|
),
|
||||||
array($header, $body));
|
array($header, $body));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,12 +80,12 @@
|
||||||
background: #F0FFFF;
|
background: #F0FFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phabricator-slowvote-embed-option-selected {
|
.phabricator-slowvote-embed-option-vote {
|
||||||
padding-left: 0px !important;
|
display: inline-block;
|
||||||
|
width: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.phabricator-slowvote-embed-option-text {
|
.phabricator-slowvote-embed-option-text {
|
||||||
border: 1px solid #dbdbdb;
|
border: 1px solid #dbdbdb;
|
||||||
border-left: 0px;
|
border-left: 0px;
|
||||||
padding-left: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-slowvote-embed
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-util
|
||||||
|
* javelin-stratcom
|
||||||
|
* javelin-dom
|
||||||
|
*/
|
||||||
|
JX.behavior('slowvote-embed', function(config) {
|
||||||
|
JX.Stratcom.listen(
|
||||||
|
['click'],
|
||||||
|
'slowvote-option',
|
||||||
|
function(e) {
|
||||||
|
if (!e.isNormalMouseEvent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.kill();
|
||||||
|
|
||||||
|
var pollID = e.getNodeData('slowvote-embed').pollID;
|
||||||
|
var voteURI = '/vote/' + pollID + '/';
|
||||||
|
|
||||||
|
var request = new JX.Request(voteURI, function(r) {
|
||||||
|
var updated_poll = JX.$H(r.contentHTML);
|
||||||
|
var root = JX.$('base-page');
|
||||||
|
|
||||||
|
var polls = JX.DOM.scry(root, 'div', 'slowvote-embed');
|
||||||
|
|
||||||
|
for(var i = 0; i < polls.length; i++) {
|
||||||
|
var data = JX.Stratcom.getData(polls[i]);
|
||||||
|
|
||||||
|
if (data.pollID == pollID) {
|
||||||
|
JX.DOM.replace(polls[i], updated_poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
request.addData({vote: e.getNodeData('slowvote-option').optionID});
|
||||||
|
request.send();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in a new issue