Properly mark all notifications as read

Previously, clicking the "mark all notifications as read" button would individually mark each of the visible notifications as read. Since we now always show a badge with the number of unread notifications, we need to make sure that all notifications (not just the visible ones) can be marked as read. Otherwise it would be possible to get stuck with an unread badge there.

This commit adds a new API endpoint which marks *all* of a user's notifications as read. The JSON-API spec doesn't cover this kind of thing (updating all instances of a certain resource type), so I'm a bit unsure regarding what the endpoint should actually be. For now I've gone with POST /notifications/read, but I'm open to suggestions.

ref #500
This commit is contained in:
Toby Zerner 2015-09-29 16:41:05 +09:30
parent 6463d912a9
commit e0aa99fabb
6 changed files with 146 additions and 4 deletions

View File

@ -134,10 +134,11 @@ export default class NotificationList extends Component {
app.session.user.pushAttributes({unreadNotificationsCount: 0});
app.cache.notifications.forEach(notification => {
if (!notification.isRead()) {
notification.save({isRead: true});
}
app.cache.notifications.forEach(notification => notification.pushAttributes({isRead: true}));
app.request({
url: app.forum.attribute('apiUrl') + '/notifications/read',
method: 'POST'
});
}
}

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Api\Actions\Notifications;
use Flarum\Core\Notifications\Commands\ReadAllNotifications;
use Illuminate\Contracts\Bus\Dispatcher;
use Flarum\Api\Request;
use Flarum\Api\Actions\DeleteAction;
class ReadAllAction extends DeleteAction
{
/**
* @var Dispatcher
*/
protected $bus;
/**
* @param Dispatcher $bus
*/
public function __construct(Dispatcher $bus)
{
$this->bus = $bus;
}
/**
* Mark all notifications as read.
*
* @param Request $request
* @return void
*/
protected function delete(Request $request)
{
$this->bus->dispatch(
new ReadAllNotifications($request->actor)
);
}
}

View File

@ -178,6 +178,13 @@ class ApiServiceProvider extends ServiceProvider
$this->action('Flarum\Api\Actions\Notifications\IndexAction')
);
// Mark all notifications as read
$routes->post(
'/notifications/read',
'flarum.api.notifications.readAll',
$this->action('Flarum\Api\Actions\Notifications\ReadAllAction')
);
// Mark a single notification as read
$routes->patch(
'/notifications/{id}',

View File

@ -0,0 +1,31 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Core\Notifications\Commands;
use Flarum\Core\Users\User;
class ReadAllNotifications
{
/**
* The user performing the action.
*
* @var User
*/
public $actor;
/**
* @param User $actor The user performing the action.
*/
public function __construct(User $actor)
{
$this->actor = $actor;
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Core\Notifications\Commands;
use Flarum\Core\Notifications\Notification;
use Flarum\Core\Notifications\NotificationRepository;
class ReadAllNotificationsHandler
{
/**
* @var NotificationRepository
*/
protected $notifications;
/**
* @param NotificationRepository $notifications
*/
public function __construct(NotificationRepository $notifications)
{
$this->notifications = $notifications;
}
/**
* @param ReadAllNotifications $command
*
* @return void
*/
public function handle(ReadAllNotifications $command)
{
$actor = $command->actor;
if ($actor->isGuest()) {
throw new PermissionDeniedException;
}
$this->notifications->markAllAsRead($actor);
}
}

View File

@ -42,4 +42,16 @@ class NotificationRepository
->latest('time')
->get();
}
/**
* Mark all of a user's notifications as read.
*
* @param User $user
*
* @return void
*/
public function markAllAsRead(User $user)
{
Notification::where('user_id', $user->id)->update(['is_read' => true]);
}
}