mirror of
https://github.com/flarum/core.git
synced 2025-07-16 22:31:18 +02:00
Flag improvements/tweaks (#18)
* Option to allow users to flag their own post * Increase size of "Flag Post" modal * Allow optional reason detail for offtopic, inappropriate and spam reasons * For other reasons, detail text is now required * Switch to column type "text" to allow more details in reason
This commit is contained in:
@@ -14,6 +14,12 @@ export default class FlagsSettingsModal extends SettingsModal {
|
|||||||
<div className="Form-group">
|
<div className="Form-group">
|
||||||
<label>{app.translator.trans('flarum-flags.admin.settings.guidelines_url_label')}</label>
|
<label>{app.translator.trans('flarum-flags.admin.settings.guidelines_url_label')}</label>
|
||||||
<input className="FormControl" bidi={this.setting('flarum-flags.guidelines_url')}/>
|
<input className="FormControl" bidi={this.setting('flarum-flags.guidelines_url')}/>
|
||||||
|
</div>,
|
||||||
|
<div className="Form-group">
|
||||||
|
<label className="checkbox">
|
||||||
|
<input type="checkbox" bidi={this.setting('flarum-flags.can_flag_own')}/>
|
||||||
|
{app.translator.trans('flarum-flags.admin.settings.user_can_flag_own_posts')}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ import FlagPostModal from './components/FlagPostModal';
|
|||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
extend(PostControls, 'userControls', function(items, post) {
|
extend(PostControls, 'userControls', function(items, post) {
|
||||||
if (post.isHidden() || post.contentType() !== 'comment' || !post.canFlag() || post.user() === app.session.user) return;
|
if (post.isHidden() || post.contentType() !== 'comment' || !post.canFlag()) return;
|
||||||
|
|
||||||
items.add('flag',
|
items.add('flag',
|
||||||
<Button icon="fas fa-flag" onclick={() => app.modal.show(new FlagPostModal({post}))}>{app.translator.trans('flarum-flags.forum.post_controls.flag_button')}</Button>
|
<Button icon="fas fa-flag" onclick={() => app.modal.show(new FlagPostModal({post}))}>{app.translator.trans('flarum-flags.forum.post_controls.flag_button')}</Button>
|
||||||
|
@@ -4,6 +4,7 @@ import Post from 'flarum/components/Post';
|
|||||||
import Button from 'flarum/components/Button';
|
import Button from 'flarum/components/Button';
|
||||||
import ItemList from 'flarum/utils/ItemList';
|
import ItemList from 'flarum/utils/ItemList';
|
||||||
import PostControls from 'flarum/utils/PostControls';
|
import PostControls from 'flarum/utils/PostControls';
|
||||||
|
import humanTime from 'flarum/utils/humanTime';
|
||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
extend(Post.prototype, 'attrs', function(attrs) {
|
extend(Post.prototype, 'attrs', function(attrs) {
|
||||||
@@ -105,9 +106,10 @@ export default function() {
|
|||||||
const user = flag.user();
|
const user = flag.user();
|
||||||
const reason = flag.reason();
|
const reason = flag.reason();
|
||||||
const detail = flag.reasonDetail();
|
const detail = flag.reasonDetail();
|
||||||
|
const time = humanTime(flag.createdAt());
|
||||||
|
|
||||||
return [
|
return [
|
||||||
app.translator.trans(reason ? 'flarum-flags.forum.post.flagged_by_with_reason_text' : 'flarum-flags.forum.post.flagged_by_text', {user, reason}),
|
app.translator.trans(reason ? 'flarum-flags.forum.post.flagged_by_with_reason_text' : 'flarum-flags.forum.post.flagged_by_text', {time, user, reason}),
|
||||||
detail ? <span className="Post-flagged-detail">{detail}</span> : ''
|
detail ? <span className="Post-flagged-detail">{detail}</span> : ''
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ export default class FlagPostModal extends Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
className() {
|
className() {
|
||||||
return 'FlagPostModal Modal--small';
|
return 'FlagPostModal Modal--medium';
|
||||||
}
|
}
|
||||||
|
|
||||||
title() {
|
title() {
|
||||||
@@ -46,6 +46,9 @@ export default class FlagPostModal extends Modal {
|
|||||||
<input type="radio" name="reason" checked={this.reason() === 'off_topic'} value="off_topic" onclick={m.withAttr('value', this.reason)}/>
|
<input type="radio" name="reason" checked={this.reason() === 'off_topic'} value="off_topic" onclick={m.withAttr('value', this.reason)}/>
|
||||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_label')}</strong>
|
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_label')}</strong>
|
||||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_text')}
|
{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_text')}
|
||||||
|
{this.reason() === 'off_topic' ? (
|
||||||
|
<textarea className="FormControl" placeholder={app.translator.trans('flarum-flags.forum.flag_post.optional_details')} value={this.reasonDetail()} oninput={m.withAttr('value', this.reasonDetail)}></textarea>
|
||||||
|
) : ''}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label className="checkbox">
|
<label className="checkbox">
|
||||||
@@ -54,12 +57,18 @@ export default class FlagPostModal extends Modal {
|
|||||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_inappropriate_text', {
|
{app.translator.trans('flarum-flags.forum.flag_post.reason_inappropriate_text', {
|
||||||
a: guidelinesUrl ? <a href={guidelinesUrl} target="_blank"/> : undefined
|
a: guidelinesUrl ? <a href={guidelinesUrl} target="_blank"/> : undefined
|
||||||
})}
|
})}
|
||||||
|
{this.reason() === 'inappropriate' ? (
|
||||||
|
<textarea className="FormControl" placeholder={app.translator.trans('flarum-flags.forum.flag_post.optional_details')} value={this.reasonDetail()} oninput={m.withAttr('value', this.reasonDetail)}></textarea>
|
||||||
|
) : ''}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label className="checkbox">
|
<label className="checkbox">
|
||||||
<input type="radio" name="reason" checked={this.reason() === 'spam'} value="spam" onclick={m.withAttr('value', this.reason)}/>
|
<input type="radio" name="reason" checked={this.reason() === 'spam'} value="spam" onclick={m.withAttr('value', this.reason)}/>
|
||||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_label')}</strong>
|
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_label')}</strong>
|
||||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_text')}
|
{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_text')}
|
||||||
|
{this.reason() === 'spam' ? (
|
||||||
|
<textarea className="FormControl" placeholder={app.translator.trans('flarum-flags.forum.flag_post.optional_details')} value={this.reasonDetail()} oninput={m.withAttr('value', this.reasonDetail)}></textarea>
|
||||||
|
) : ''}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label className="checkbox">
|
<label className="checkbox">
|
||||||
@@ -98,9 +107,17 @@ export default class FlagPostModal extends Modal {
|
|||||||
user: app.session.user,
|
user: app.session.user,
|
||||||
post: this.props.post
|
post: this.props.post
|
||||||
}
|
}
|
||||||
})
|
}, {errorHandler: this.onerror.bind(this)})
|
||||||
.then(() => this.success = true)
|
.then(() => this.success = true)
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.then(this.loaded.bind(this));
|
.then(this.loaded.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onerror(error) {
|
||||||
|
if (error.status === 422) {
|
||||||
|
error.alert.props.children = app.translator.trans('flarum-flags.forum.flag_post.reason-needed');
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onerror(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* For detailed 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('flags', function (Blueprint $table) {
|
||||||
|
$table->text('reason_detail')->change();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'down' => function (Builder $schema) {
|
||||||
|
$schema->table('flags', function (Blueprint $table) {
|
||||||
|
$table->string(['reason_detail'])->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
];
|
@@ -10,9 +10,13 @@
|
|||||||
namespace Flarum\Flags\Command;
|
namespace Flarum\Flags\Command;
|
||||||
|
|
||||||
use Flarum\Flags\Flag;
|
use Flarum\Flags\Flag;
|
||||||
|
use Flarum\Foundation\ValidationException;
|
||||||
use Flarum\Post\CommentPost;
|
use Flarum\Post\CommentPost;
|
||||||
use Flarum\Post\PostRepository;
|
use Flarum\Post\PostRepository;
|
||||||
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Flarum\User\AssertPermissionTrait;
|
use Flarum\User\AssertPermissionTrait;
|
||||||
|
use Flarum\User\Exception\PermissionDeniedException;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface;
|
||||||
use Tobscure\JsonApi\Exception\InvalidParameterException;
|
use Tobscure\JsonApi\Exception\InvalidParameterException;
|
||||||
|
|
||||||
class CreateFlagHandler
|
class CreateFlagHandler
|
||||||
@@ -25,17 +29,31 @@ class CreateFlagHandler
|
|||||||
protected $posts;
|
protected $posts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param PostRepository $posts
|
* @var TranslatorInterface
|
||||||
*/
|
*/
|
||||||
public function __construct(PostRepository $posts)
|
protected $translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SettingsRepositoryInterface
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PostRepository $posts
|
||||||
|
* @param TranslatorInterface $translator
|
||||||
|
*/
|
||||||
|
public function __construct(PostRepository $posts, TranslatorInterface $translator, SettingsRepositoryInterface $settings)
|
||||||
{
|
{
|
||||||
$this->posts = $posts;
|
$this->posts = $posts;
|
||||||
|
$this->translator = $translator;
|
||||||
|
$this->settings = $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CreateFlag $command
|
* @param CreateFlag $command
|
||||||
* @return Flag
|
* @return Flag
|
||||||
* @throws InvalidParameterException
|
* @throws InvalidParameterException
|
||||||
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function handle(CreateFlag $command)
|
public function handle(CreateFlag $command)
|
||||||
{
|
{
|
||||||
@@ -51,6 +69,16 @@ class CreateFlagHandler
|
|||||||
|
|
||||||
$this->assertCan($actor, 'flag', $post);
|
$this->assertCan($actor, 'flag', $post);
|
||||||
|
|
||||||
|
if ($actor->id === $post->user_id && ! $this->settings->get('flarum-flags.can_flag_own')) {
|
||||||
|
throw new PermissionDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_get($data, 'attributes.reason') === null && array_get($data, 'attributes.reasonDetail') === '') {
|
||||||
|
throw new ValidationException([
|
||||||
|
'message' => $this->translator->trans('flarum-flags.forum.flag_post.reason-needed')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
Flag::unguard();
|
Flag::unguard();
|
||||||
|
|
||||||
$flag = Flag::firstOrNew([
|
$flag = Flag::firstOrNew([
|
||||||
|
@@ -14,6 +14,7 @@ use Flarum\Api\Serializer\CurrentUserSerializer;
|
|||||||
use Flarum\Api\Serializer\ForumSerializer;
|
use Flarum\Api\Serializer\ForumSerializer;
|
||||||
use Flarum\Api\Serializer\PostSerializer;
|
use Flarum\Api\Serializer\PostSerializer;
|
||||||
use Flarum\Flags\Flag;
|
use Flarum\Flags\Flag;
|
||||||
|
use Flarum\Post\CommentPost;
|
||||||
use Flarum\Settings\SettingsRepositoryInterface;
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
@@ -49,7 +50,7 @@ class AddFlagsApiAttributes
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($event->isSerializer(PostSerializer::class)) {
|
if ($event->isSerializer(PostSerializer::class)) {
|
||||||
$event->attributes['canFlag'] = $event->actor->can('flag', $event->model);
|
$event->attributes['canFlag'] = $event->actor->can('flag', $event->model) && $this->checkFlagOwnPostSetting($event->actor, $event->model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,4 +77,19 @@ class AddFlagsApiAttributes
|
|||||||
|
|
||||||
return $query->distinct()->count('flags.post_id');
|
return $query->distinct()->count('flags.post_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $actor
|
||||||
|
* @param CommentPost $post
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function checkFlagOwnPostSetting(User $actor, CommentPost $post): bool
|
||||||
|
{
|
||||||
|
if ($actor->id === $post->user_id) {
|
||||||
|
// If $actor is the post author, check to see if the setting is enabled
|
||||||
|
return (bool) $this->settings->get('flarum-flags.can_flag_own');
|
||||||
|
}
|
||||||
|
// $actor is not the post author
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user