Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/im/global-polls' into sh/form-ui
Browse files Browse the repository at this point in the history
# Conflicts:
#	js/src/forum/components/CreatePollModal.js
#	js/src/forum/components/EditPollModal.js
  • Loading branch information
novacuum committed Feb 19, 2024
2 parents 2b204a7 + ce20ae8 commit 72d4dc0
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 24 deletions.
41 changes: 23 additions & 18 deletions js/src/forum/components/PostPoll.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,29 @@ export default class PostPoll extends Component {
return (
<div className="Post-poll" data-id={poll.id()}>
<div className="PollHeading">
<h3 className="PollHeading-title">{poll.question()}</h3>

{poll.canSeeVoters() && (
<Tooltip text={app.translator.trans('fof-polls.forum.public_poll')}>
<Button className="Button PollHeading-voters" onclick={this.showVoters.bind(this)} icon="fas fa-poll" />
</Tooltip>
)}

{poll.canEdit() && (
<Tooltip text={app.translator.trans('fof-polls.forum.moderation.edit')}>
<Button className="Button PollHeading-edit" onclick={app.modal.show.bind(app.modal, EditPollModal, { poll })} icon="fas fa-pen" />
</Tooltip>
)}
{poll.canDelete() && (
<Tooltip text={app.translator.trans('fof-polls.forum.moderation.delete')}>
<Button className="Button PollHeading-delete" onclick={this.deletePoll.bind(this)} icon="fas fa-trash" />
</Tooltip>
)}
<div className="PollHeading-title-container">
<h3 className="PollHeading-title">{poll.question()}</h3>
{poll.subtitle() && <p className="helpText PollHeading-subtitle">{poll.subtitle()}</p>}
</div>

<div className="PollHeading-actions">
{poll.canSeeVoters() && (
<Tooltip text={app.translator.trans('fof-polls.forum.public_poll')}>
<Button className="Button PollHeading-voters" onclick={this.showVoters.bind(this)} icon="fas fa-poll" />
</Tooltip>
)}

{poll.canEdit() && (
<Tooltip text={app.translator.trans('fof-polls.forum.moderation.edit')}>
<Button className="Button PollHeading-edit" onclick={app.modal.show.bind(app.modal, EditPollModal, { poll })} icon="fas fa-pen" />
</Tooltip>
)}
{poll.canDelete() && (
<Tooltip text={app.translator.trans('fof-polls.forum.moderation.delete')}>
<Button className="Button PollHeading-delete" onclick={this.deletePoll.bind(this)} icon="fas fa-trash" />
</Tooltip>
)}
</div>
</div>

<div>
Expand Down
4 changes: 4 additions & 0 deletions js/src/forum/models/Poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export default class Poll extends Model {
return Model.attribute<string>('question').call(this);
}

subtitle() {
return Model.attribute<string | null>('subtitle').call(this);
}

hasEnded() {
return Model.attribute<boolean>('hasEnded').call(this);
}
Expand Down
26 changes: 26 additions & 0 deletions migrations/2024_02_15_000000_modify_polls_add_subtitle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of fof/polls.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;

return [
'up' => function (Builder $schema) {
$schema->table('polls', function (Blueprint $table) {
$table->text('subtitle')->nullable()->after('question');
});
},
'down' => function (Builder $schema) {
$schema->table('polls', function (Blueprint $table) {
$table->dropColumn('subtitle');
});
},
];
6 changes: 5 additions & 1 deletion resources/less/forum.less
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,18 @@
align-items: baseline;
gap: 10px;

&-title {
&-title-container {
flex-grow: 1;
}

&-voters {
.Button--color-auto("button-primary");
}

&-actions {

}

.Button {
flex-shrink: 1;
padding: 6px 10px;
Expand Down
1 change: 1 addition & 0 deletions resources/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fof-polls:
hide_votes_label: Hide votes until poll ends
allow_change_vote_label: Allow users to change their vote
question_placeholder: Question
subtitle_placeholder: Subtitle/Description (Optional)
submit: Submit

moderation:
Expand Down
5 changes: 4 additions & 1 deletion src/Api/AddPostAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@

namespace FoF\Polls\Api;

use Flarum\Api\Serializer\PostSerializer;
use Flarum\Post\Post;

class AddPostAttributes
{
public function __invoke($serializer, $post, $attributes)
public function __invoke(PostSerializer $serializer, Post $post, array $attributes): array
{
$attributes['canStartPoll'] = $serializer->getActor()->can('startPoll', $post);

Expand Down
1 change: 1 addition & 0 deletions src/Api/Serializers/PollSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ protected function getDefaultAttributes($poll)

$attributes = [
'question' => $poll->question,
'subtitle' => $poll->subtitle,
'hasEnded' => $poll->hasEnded(),
'allowMultipleVotes' => $poll->allow_multiple_votes,
'maxVotes' => $poll->max_votes,
Expand Down
1 change: 1 addition & 0 deletions src/Commands/CreatePollHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public function handle(CreatePoll $command)
Arr::get($attributes, 'maxVotes'),
Arr::get($attributes, 'hideVotes'),
Arr::get($attributes, 'allowChangeVote'),
Arr::get($attributes, 'subtitle')
);

$this->events->dispatch(new SavingPollAttributes($command->actor, $poll, $attributes, $attributes));
Expand Down
4 changes: 4 additions & 0 deletions src/Commands/EditPollHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public function handle(EditPoll $command)
$poll->question = $attributes['question'];
}

if (isset($attributes['subtitle'])) {
$poll->subtitle = empty($attributes['subtitle']) ? null : $attributes['subtitle'];
}

foreach (['publicPoll', 'allowMultipleVotes', 'hideVotes', 'allowChangeVote'] as $key) {
if (isset($attributes[$key])) {
$poll->settings[Str::snake($key)] = (bool) $attributes[$key];
Expand Down
10 changes: 6 additions & 4 deletions src/Poll.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
use Illuminate\Support\Arr;

/**
* @property int $id
* @property string $question
* @property int $id
* @property string $question
* @property string|null $subtitle
* @property-read bool $public_poll
* @property-read bool $allow_multiple_votes
* @property-read int $max_votes
Expand All @@ -30,7 +31,7 @@
* @property int $vote_count
* @property Post $post
* @property User $user
* @property int $post_id
* @property int|null $post_id
* @property int $user_id
* @property \Carbon\Carbon|null $end_date
* @property \Carbon\Carbon $created_at
Expand Down Expand Up @@ -66,11 +67,12 @@ class Poll extends AbstractModel
*
* @return static
*/
public static function build($question, $postId, $actorId, $endDate, $publicPoll, $allowMultipleVotes = false, $maxVotes = 0, $hideVotes = false, $allowChangeVote = true)
public static function build($question, $postId, $actorId, $endDate, $publicPoll, $allowMultipleVotes = false, $maxVotes = 0, $hideVotes = false, $allowChangeVote = true, $subtitle = null)
{
$poll = new static();

$poll->question = $question;
$poll->subtitle = $subtitle;
$poll->post_id = $postId;
$poll->user_id = $actorId;
$poll->end_date = $endDate;
Expand Down
124 changes: 124 additions & 0 deletions tests/integration/api/CreatePollTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public function authorized_user_can_create_poll_in_post(int $userId)
$this->assertNotNull($poll);

$this->assertEquals('What is your favourite colour?', $poll->question);
$this->assertNull($poll->subtitle);

$response = $this->send(
$this->request(
Expand Down Expand Up @@ -258,6 +259,7 @@ public function authorized_user_can_create_post_poll_on_api(int $userId)
$attributes = $data['attributes'];

$this->assertEquals('Add a poll to an existing post', $attributes['question']);
$this->assertNull($attributes['subtitle']);

$pollId = $data['id'];
$this->assertNotNull($pollId);
Expand Down Expand Up @@ -411,6 +413,7 @@ public function authorized_user_can_create_global_poll_on_api(int $userId)
$attributes = $data['attributes'];

$this->assertEquals('Add a global poll', $attributes['question']);
$this->assertNull($attributes['subtitle']);

$pollId = $data['id'];
$this->assertNotNull($pollId);
Expand Down Expand Up @@ -476,4 +479,125 @@ public function unauthorized_user_cannot_create_global_poll_on_api(int $userId)

$this->assertEquals(403, $response->getStatusCode());
}

/**
* @dataProvider authorizedUserProvider
*
* @test
*/
public function authorized_user_can_create_a_poll_with_a_subtitle_via_api(int $userId)
{
$response = $this->send(
$this->request(
'POST',
'/api/fof/polls',
[
'authenticatedAs' => $userId,
'json' => [
'data' => [
'attributes' => [
'question' => 'Add a poll with a subtitle',
'subtitle' => 'This is a subtitle',
'publicPoll' => false,
'hideVotes' => false,
'allowChangeVote' => true,
'allowMultipleVotes' => false,
'maxVotes' => 0,
'endDate' => false,
'options' => [
[
'answer' => 'Yes',
],
[
'answer' => 'No',
],
],
],
],
],
]
)
);

$this->assertEquals(201, $response->getStatusCode());

$json = json_decode($response->getBody()->getContents(), true);

$data = $json['data'];
$attributes = $data['attributes'];

$this->assertEquals('Add a poll with a subtitle', $attributes['question']);
$this->assertEquals('This is a subtitle', $attributes['subtitle']);
}

/**
* @dataProvider authorizedUserProvider
*
* @test
*/
public function authorized_user_can_create_a_poll_with_a_subtitle_via_post(int $userId)
{
$response = $this->send(
$this->request(
'POST',
'/api/posts',
[
'authenticatedAs' => $userId,
'json' => [
'data' => [
'attributes' => [
'content' => 'Here is my poll',
'poll' => [
'question' => 'What is your favourite colour?',
'subtitle' => 'This is a subtitle',
'publicPoll' => false,
'hideVotes' => false,
'allowChangeVote' => true,
'allowMultipleVotes' => false,
'maxVotes' => 0,
'endDate' => false,
'options' => [
[
'answer' => 'Red',
],
[
'answer' => 'Blue',
],
[
'answer' => 'Yellow',
],
],
],
],
'relationships' => [
'discussion' => [
'data' => [
'type' => 'discussions',
'id' => 1,
],
],
],
],
],
]
)
);

$this->assertEquals(201, $response->getStatusCode());

$json = json_decode($response->getBody()->getContents(), true);
$data = $json['data'];

$this->assertArrayHasKey('polls', $data['relationships']);

$pollId = $data['relationships']['polls']['data'][0]['id'];
$this->assertNotNull($pollId);

$poll = Poll::find($pollId);

$this->assertNotNull($poll);

$this->assertEquals('What is your favourite colour?', $poll->question);
$this->assertEquals('This is a subtitle', $poll->subtitle);
}
}

0 comments on commit 72d4dc0

Please sign in to comment.