diff --git a/js/src/forum/components/PostPoll.js b/js/src/forum/components/PostPoll.js index c312f98e..49583ba7 100644 --- a/js/src/forum/components/PostPoll.js +++ b/js/src/forum/components/PostPoll.js @@ -46,24 +46,29 @@ export default class PostPoll extends Component { return (
-

{poll.question()}

- - {poll.canSeeVoters() && ( - -
diff --git a/js/src/forum/models/Poll.ts b/js/src/forum/models/Poll.ts index 77e9d512..72fa529a 100755 --- a/js/src/forum/models/Poll.ts +++ b/js/src/forum/models/Poll.ts @@ -8,6 +8,10 @@ export default class Poll extends Model { return Model.attribute('question').call(this); } + subtitle() { + return Model.attribute('subtitle').call(this); + } + hasEnded() { return Model.attribute('hasEnded').call(this); } diff --git a/migrations/2024_02_15_000000_modify_polls_add_subtitle.php b/migrations/2024_02_15_000000_modify_polls_add_subtitle.php new file mode 100644 index 00000000..b23399a3 --- /dev/null +++ b/migrations/2024_02_15_000000_modify_polls_add_subtitle.php @@ -0,0 +1,26 @@ + 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'); + }); + }, +]; diff --git a/resources/less/forum.less b/resources/less/forum.less index 5a94cee1..8999ab07 100755 --- a/resources/less/forum.less +++ b/resources/less/forum.less @@ -167,7 +167,7 @@ align-items: baseline; gap: 10px; - &-title { + &-title-container { flex-grow: 1; } @@ -175,6 +175,10 @@ .Button--color-auto("button-primary"); } + &-actions { + + } + .Button { flex-shrink: 1; padding: 6px 10px; diff --git a/resources/locale/en.yml b/resources/locale/en.yml index 5fac60a6..6cbe41cd 100755 --- a/resources/locale/en.yml +++ b/resources/locale/en.yml @@ -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: diff --git a/src/Api/AddPostAttributes.php b/src/Api/AddPostAttributes.php index bb206dfd..3430b9a8 100644 --- a/src/Api/AddPostAttributes.php +++ b/src/Api/AddPostAttributes.php @@ -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); diff --git a/src/Api/Serializers/PollSerializer.php b/src/Api/Serializers/PollSerializer.php index 52a7bcdd..13424e32 100755 --- a/src/Api/Serializers/PollSerializer.php +++ b/src/Api/Serializers/PollSerializer.php @@ -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, diff --git a/src/Commands/CreatePollHandler.php b/src/Commands/CreatePollHandler.php index fe5f19e4..d7d9bfb5 100644 --- a/src/Commands/CreatePollHandler.php +++ b/src/Commands/CreatePollHandler.php @@ -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)); diff --git a/src/Commands/EditPollHandler.php b/src/Commands/EditPollHandler.php index a31da2ce..cb6a424d 100755 --- a/src/Commands/EditPollHandler.php +++ b/src/Commands/EditPollHandler.php @@ -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]; diff --git a/src/Poll.php b/src/Poll.php index c448ac82..ad759dab 100755 --- a/src/Poll.php +++ b/src/Poll.php @@ -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 @@ -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 @@ -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; diff --git a/tests/integration/api/CreatePollTest.php b/tests/integration/api/CreatePollTest.php index edcd1e6a..2975bc5a 100644 --- a/tests/integration/api/CreatePollTest.php +++ b/tests/integration/api/CreatePollTest.php @@ -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( @@ -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); @@ -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); @@ -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); + } }