Notifications: Added new preferences view and access control

- Added general user preferences view and updated link in profile menu
  to suit.
- Made notification permission required for notification preferences
  view, added test to cover.
This commit is contained in:
Dan Brown 2023-08-14 17:29:12 +01:00
parent d9fdecd902
commit 371779205a
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
9 changed files with 123 additions and 29 deletions

View File

@ -17,6 +17,14 @@ class UserPreferencesController extends Controller
) {
}
/**
* Show the overview for user preferences.
*/
public function index()
{
return view('users.preferences.index');
}
/**
* Show the user-specific interface shortcuts.
*/
@ -53,6 +61,8 @@ class UserPreferencesController extends Controller
*/
public function showNotifications(PermissionApplicator $permissions)
{
$this->checkPermission('receive-notifications');
$preferences = (new UserNotificationPreferences(user()));
$query = Watch::query()->where('user_id', '=', user()->id);
@ -70,6 +80,7 @@ class UserPreferencesController extends Controller
*/
public function updateNotifications(Request $request)
{
$this->checkPermission('receive-notifications');
$data = $this->validate($request, [
'preferences' => ['required', 'array'],
'preferences.*' => ['required', 'string'],

View File

@ -42,6 +42,7 @@ return [
'remove' => 'Remove',
'add' => 'Add',
'configure' => 'Configure',
'manage' => 'Manage',
'fullscreen' => 'Fullscreen',
'favourite' => 'Favourite',
'unfavourite' => 'Unfavourite',

View File

@ -5,6 +5,8 @@
*/
return [
'preferences' => 'Preferences',
'shortcuts' => 'Shortcuts',
'shortcuts_interface' => 'Interface Keyboard Shortcuts',
'shortcuts_toggle_desc' => 'Here you can enable or disable keyboard system interface shortcuts, used for navigation and actions.',
@ -15,6 +17,7 @@ return [
'shortcuts_save' => 'Save Shortcuts',
'shortcuts_overlay_desc' => 'Note: When shortcuts are enabled a helper overlay is available via pressing "?" which will highlight the available shortcuts for actions currently visible on the screen.',
'shortcuts_update_success' => 'Shortcut preferences have been updated!',
'shortcuts_overview_desc' => 'Manage keyboard shortcuts you can use to navigate the system user interface.',
'notifications' => 'Notification Preferences',
'notifications_desc' => 'Control the email notifications you receive when certain activity is performed within the system.',
@ -25,4 +28,6 @@ return [
'notifications_update_success' => 'Notification preferences have been updated!',
'notifications_watched' => 'Watched & Ignored Items',
'notifications_watched_desc' => ' Below are the items that have custom watch preferences applied. To update your preferences for these, view the item then find the watch options in the sidebar.',
'profile_overview_desc' => ' Manage your user profile details including preferred language and authentication options.',
];

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><g><circle cx="10" cy="8" r="4"/><path d="M10.67,13.02C10.45,13.01,10.23,13,10,13c-2.42,0-4.68,0.67-6.61,1.82C2.51,15.34,2,16.32,2,17.35V20h9.26 C10.47,18.87,10,17.49,10,16C10,14.93,10.25,13.93,10.67,13.02z"/><path d="M20.75,16c0-0.22-0.03-0.42-0.06-0.63l1.14-1.01l-1-1.73l-1.45,0.49c-0.32-0.27-0.68-0.48-1.08-0.63L18,11h-2l-0.3,1.49 c-0.4,0.15-0.76,0.36-1.08,0.63l-1.45-0.49l-1,1.73l1.14,1.01c-0.03,0.21-0.06,0.41-0.06,0.63s0.03,0.42,0.06,0.63l-1.14,1.01 l1,1.73l1.45-0.49c0.32,0.27,0.68,0.48,1.08,0.63L16,21h2l0.3-1.49c0.4-0.15,0.76-0.36,1.08-0.63l1.45,0.49l1-1.73l-1.14-1.01 C20.72,16.42,20.75,16.22,20.75,16z M17,18c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S18.1,18,17,18z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 752 B

View File

@ -104,9 +104,9 @@
</li>
<li><hr></li>
<li>
<a href="{{ url('/preferences/shortcuts') }}" class="icon-item">
@icon('shortcuts')
<div>{{ trans('preferences.shortcuts') }}</div>
<a href="{{ url('/preferences') }}" class="icon-item">
@icon('user-preferences')
<div>{{ trans('preferences.preferences') }}</div>
</a>
</li>
<li>

View File

@ -0,0 +1,41 @@
@extends('layouts.simple')
@section('body')
<div class="container small my-xl">
<section class="card content-wrap auto-height items-center justify-space-between gap-m flex-container-row">
<div>
<h2 class="list-heading">{{ trans('preferences.shortcuts_interface') }}</h2>
<p class="text-muted">{{ trans('preferences.shortcuts_overview_desc') }}</p>
</div>
<div class="text-right">
<a href="{{ url('/preferences/shortcuts') }}" class="button outline">{{ trans('common.manage') }}</a>
</div>
</section>
@if(userCan('receive-notifications'))
<section class="card content-wrap auto-height items-center justify-space-between gap-m flex-container-row">
<div>
<h2 class="list-heading">{{ trans('preferences.notifications') }}</h2>
<p class="text-muted">{{ trans('preferences.notifications_desc') }}</p>
</div>
<div class="text-right">
<a href="{{ url('/preferences/notifications') }}" class="button outline">{{ trans('common.manage') }}</a>
</div>
</section>
@endif
@if(signedInUser())
<section class="card content-wrap auto-height items-center justify-space-between gap-m flex-container-row">
<div>
<h2 class="list-heading">{{ trans('settings.users_edit_profile') }}</h2>
<p class="text-muted">{{ trans('preferences.profile_overview_desc') }}</p>
</div>
<div class="text-right">
<a href="{{ user()->getEditUrl() }}" class="button outline">{{ trans('common.manage') }}</a>
</div>
</section>
@endif
</div>
@stop

View File

@ -11,33 +11,36 @@
<h1 class="list-heading">{{ trans('preferences.notifications') }}</h1>
<p class="text-small text-muted">{{ trans('preferences.notifications_desc') }}</p>
<div class="toggle-switch-list">
<div>
@include('form.toggle-switch', [
'name' => 'preferences[own-page-changes]',
'value' => $preferences->notifyOnOwnPageChanges(),
'label' => trans('preferences.notifications_opt_own_page_changes'),
])
<div class="flex-container-row wrap justify-space-between pb-m">
<div class="toggle-switch-list min-width-l">
<div>
@include('form.toggle-switch', [
'name' => 'preferences[own-page-changes]',
'value' => $preferences->notifyOnOwnPageChanges(),
'label' => trans('preferences.notifications_opt_own_page_changes'),
])
</div>
<div>
@include('form.toggle-switch', [
'name' => 'preferences[own-page-comments]',
'value' => $preferences->notifyOnOwnPageComments(),
'label' => trans('preferences.notifications_opt_own_page_comments'),
])
</div>
<div>
@include('form.toggle-switch', [
'name' => 'preferences[comment-replies]',
'value' => $preferences->notifyOnCommentReplies(),
'label' => trans('preferences.notifications_opt_comment_replies'),
])
</div>
</div>
<div>
@include('form.toggle-switch', [
'name' => 'preferences[own-page-comments]',
'value' => $preferences->notifyOnOwnPageComments(),
'label' => trans('preferences.notifications_opt_own_page_comments'),
])
</div>
<div>
@include('form.toggle-switch', [
'name' => 'preferences[comment-replies]',
'value' => $preferences->notifyOnCommentReplies(),
'label' => trans('preferences.notifications_opt_comment_replies'),
])
<div class="mt-auto">
<button class="button">{{ trans('preferences.notifications_save') }}</button>
</div>
</div>
<div class="form-group text-right">
<button class="button">{{ trans('preferences.notifications_save') }}</button>
</div>
</form>
</section>

View File

@ -231,7 +231,7 @@ Route::middleware('auth')->group(function () {
Route::delete('/settings/users/{id}', [UserControllers\UserController::class, 'destroy']);
// User Preferences
Route::redirect('/preferences', '/');
Route::get('/preferences', [UserControllers\UserPreferencesController::class, 'index']);
Route::get('/preferences/shortcuts', [UserControllers\UserPreferencesController::class, 'showShortcuts']);
Route::put('/preferences/shortcuts', [UserControllers\UserPreferencesController::class, 'updateShortcuts']);
Route::get('/preferences/notifications', [UserControllers\UserPreferencesController::class, 'showNotifications']);

View File

@ -6,6 +6,22 @@ use Tests\TestCase;
class UserPreferencesTest extends TestCase
{
public function test_index_view()
{
$resp = $this->asEditor()->get('/preferences');
$resp->assertOk();
$resp->assertSee('Interface Keyboard Shortcuts');
$resp->assertSee('Edit Profile');
}
public function test_index_view_accessible_but_without_profile_for_guest_user()
{
$this->setSettings(['app-public' => 'true']);
$resp = $this->get('/preferences');
$resp->assertOk();
$resp->assertSee('Interface Keyboard Shortcuts');
$resp->assertDontSee('Edit Profile');
}
public function test_interface_shortcuts_updating()
{
$this->asEditor();
@ -45,12 +61,28 @@ class UserPreferencesTest extends TestCase
$this->withHtml($this->get('/'))->assertElementExists('body[component="shortcuts"]');
}
public function test_notification_routes_requires_notification_permission()
{
$viewer = $this->users->viewer();
$resp = $this->actingAs($viewer)->get('/preferences/notifications');
$this->assertPermissionError($resp);
$resp = $this->put('/preferences/notifications');
$this->assertPermissionError($resp);
$this->permissions->grantUserRolePermissions($viewer, ['receive-notifications']);
$resp = $this->get('/preferences/notifications');
$resp->assertOk();
$resp->assertSee('Notification Preferences');
}
public function test_notification_preferences_updating()
{
$this->asEditor();
$editor = $this->users->editor();
$this->permissions->grantUserRolePermissions($editor, ['receive-notifications']);
// View preferences with defaults
$resp = $this->get('/preferences/notifications');
$resp = $this->actingAs($editor)->get('/preferences/notifications');
$resp->assertSee('Notification Preferences');
$html = $this->withHtml($resp);