From d9fdecd902c3542160e1a21a4cb3833e494baaa0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 14 Aug 2023 13:11:18 +0100 Subject: [PATCH] Notifications: User watch list and differnt page watch options - Adds option filtering and alternative text for page watch options. - Adds "Watched & Ignored Items" list to user notification preferences page to show existing watched items. --- app/Activity/Models/Watch.php | 18 ++++++++-- app/Activity/WatchLevels.php | 34 +++++++++++++++++-- app/Entities/Queries/TopFavourites.php | 2 +- .../Controllers/UserPreferencesController.php | 9 ++++- lang/en/entities.php | 2 ++ lang/en/preferences.php | 2 ++ resources/views/entities/icon-link.blade.php | 7 ++++ .../views/entities/watch-controls.blade.php | 8 +++-- resources/views/settings/audit.blade.php | 8 +---- .../users/preferences/notifications.blade.php | 25 ++++++++++++++ 10 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 resources/views/entities/icon-link.blade.php diff --git a/app/Activity/Models/Watch.php b/app/Activity/Models/Watch.php index 6637c9655..dfb72cc0a 100644 --- a/app/Activity/Models/Watch.php +++ b/app/Activity/Models/Watch.php @@ -2,10 +2,12 @@ namespace BookStack\Activity\Models; +use BookStack\Activity\WatchLevels; use BookStack\Permissions\Models\JointPermission; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphTo; /** * @property int $id @@ -20,14 +22,24 @@ class Watch extends Model { protected $guarded = []; - public function watchable() + public function watchable(): MorphTo { - $this->morphTo(); + return $this->morphTo(); } public function jointPermissions(): HasMany { return $this->hasMany(JointPermission::class, 'entity_id', 'watchable_id') - ->whereColumn('favourites.watchable_type', '=', 'joint_permissions.entity_type'); + ->whereColumn('watches.watchable_type', '=', 'joint_permissions.entity_type'); + } + + public function getLevelName(): string + { + return WatchLevels::levelValueToName($this->level); + } + + public function ignoring(): bool + { + return $this->level === WatchLevels::IGNORE; } } diff --git a/app/Activity/WatchLevels.php b/app/Activity/WatchLevels.php index 2951bc7a8..de3c5e122 100644 --- a/app/Activity/WatchLevels.php +++ b/app/Activity/WatchLevels.php @@ -2,6 +2,10 @@ namespace BookStack\Activity; +use BookStack\Entities\Models\Bookshelf; +use BookStack\Entities\Models\Entity; +use BookStack\Entities\Models\Page; + class WatchLevels { /** @@ -32,6 +36,7 @@ class WatchLevels /** * Get all the possible values as an option_name => value array. + * @returns array */ public static function all(): array { @@ -43,11 +48,36 @@ class WatchLevels return $options; } - public static function levelNameToValue(string $level): int + /** + * Get the watch options suited for the given entity. + * @returns array + */ + public static function allSuitedFor(Entity $entity): array { - return static::all()[$level] ?? -1; + $options = static::all(); + + if ($entity instanceof Page) { + unset($options['new']); + } elseif ($entity instanceof Bookshelf) { + return []; + } + + return $options; } + /** + * Convert the given name to a level value. + * Defaults to default value if the level does not exist. + */ + public static function levelNameToValue(string $level): int + { + return static::all()[$level] ?? static::DEFAULT; + } + + /** + * Convert the given int level value to a level name. + * Defaults to 'default' level name if not existing. + */ public static function levelValueToName(int $level): string { foreach (static::all() as $name => $value) { diff --git a/app/Entities/Queries/TopFavourites.php b/app/Entities/Queries/TopFavourites.php index 3f8d2e62e..cbccf35b0 100644 --- a/app/Entities/Queries/TopFavourites.php +++ b/app/Entities/Queries/TopFavourites.php @@ -10,7 +10,7 @@ class TopFavourites extends EntityQuery public function run(int $count, int $skip = 0) { $user = user(); - if (is_null($user) || $user->isDefault()) { + if ($user->isDefault()) { return collect(); } diff --git a/app/Users/Controllers/UserPreferencesController.php b/app/Users/Controllers/UserPreferencesController.php index faa99629b..999115e7b 100644 --- a/app/Users/Controllers/UserPreferencesController.php +++ b/app/Users/Controllers/UserPreferencesController.php @@ -2,7 +2,9 @@ namespace BookStack\Users\Controllers; +use BookStack\Activity\Models\Watch; use BookStack\Http\Controller; +use BookStack\Permissions\PermissionApplicator; use BookStack\Settings\UserNotificationPreferences; use BookStack\Settings\UserShortcutMap; use BookStack\Users\UserRepo; @@ -49,12 +51,17 @@ class UserPreferencesController extends Controller /** * Show the notification preferences for the current user. */ - public function showNotifications() + public function showNotifications(PermissionApplicator $permissions) { $preferences = (new UserNotificationPreferences(user())); + $query = Watch::query()->where('user_id', '=', user()->id); + $query = $permissions->restrictEntityRelationQuery($query, 'watches', 'watchable_id', 'watchable_type'); + $watches = $query->with('watchable')->paginate(20); + return view('users.preferences.notifications', [ 'preferences' => $preferences, + 'watches' => $watches, ]); } diff --git a/lang/en/entities.php b/lang/en/entities.php index f1e7dcc01..b1b0e5236 100644 --- a/lang/en/entities.php +++ b/lang/en/entities.php @@ -414,8 +414,10 @@ return [ 'watch_desc_new' => 'Notify when any new page is created within this item.', 'watch_title_updates' => 'All Page Updates', 'watch_desc_updates' => 'Notify upon all new pages and page changes.', + 'watch_desc_updates_page' => 'Notify upon all page changes.', 'watch_title_comments' => 'All Page Updates & Comments', 'watch_desc_comments' => 'Notify upon all new pages, page changes and new comments.', + 'watch_desc_comments_page' => 'Notify upon page changes and new comments.', 'watch_change_default' => 'Change default notification preferences', 'watch_detail_ignore' => 'Ignoring notifications', 'watch_detail_new' => 'Watching for new pages', diff --git a/lang/en/preferences.php b/lang/en/preferences.php index 2ade3a0e4..97968f8b1 100644 --- a/lang/en/preferences.php +++ b/lang/en/preferences.php @@ -23,4 +23,6 @@ return [ 'notifications_opt_comment_replies' => 'Notify upon replies to my comments', 'notifications_save' => 'Save Preferences', '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.', ]; diff --git a/resources/views/entities/icon-link.blade.php b/resources/views/entities/icon-link.blade.php new file mode 100644 index 000000000..a3e95fda8 --- /dev/null +++ b/resources/views/entities/icon-link.blade.php @@ -0,0 +1,7 @@ + + @icon($entity->getType()) +
+ {{ $entity->name }} +
+
\ No newline at end of file diff --git a/resources/views/entities/watch-controls.blade.php b/resources/views/entities/watch-controls.blade.php index 4fdda5347..d24e12018 100644 --- a/resources/views/entities/watch-controls.blade.php +++ b/resources/views/entities/watch-controls.blade.php @@ -11,7 +11,7 @@