Notifications: Extracted watch options, updated UI further
This commit is contained in:
parent
730f539029
commit
6100b99828
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BookStack\Users;
|
||||||
|
|
||||||
|
class UserWatchOptions
|
||||||
|
{
|
||||||
|
protected static array $levelByOption = [
|
||||||
|
'default' => -1,
|
||||||
|
'ignore' => 0,
|
||||||
|
'new' => 1,
|
||||||
|
'updates' => 2,
|
||||||
|
'comments' => 3,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public static function getAvailableOptionNames(): array
|
||||||
|
{
|
||||||
|
return array_keys(static::$levelByOption);
|
||||||
|
}
|
||||||
|
}
|
|
@ -403,4 +403,18 @@ return [
|
||||||
'references' => 'References',
|
'references' => 'References',
|
||||||
'references_none' => 'There are no tracked references to this item.',
|
'references_none' => 'There are no tracked references to this item.',
|
||||||
'references_to_desc' => 'Shown below are all the known pages in the system that link to this item.',
|
'references_to_desc' => 'Shown below are all the known pages in the system that link to this item.',
|
||||||
|
|
||||||
|
// Watch Options
|
||||||
|
'watch' => 'Watch',
|
||||||
|
'watch_title_default' => 'Default Preferences',
|
||||||
|
'watch_desc_default' => 'Revert watching to just your default notification preferences.',
|
||||||
|
'watch_title_ignore' => 'Ignore',
|
||||||
|
'watch_desc_ignore' => 'Ignore all notifications, including those from user-level preferences.',
|
||||||
|
'watch_title_new' => 'New Pages',
|
||||||
|
'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_title_comments' => 'All Page Updates & Comments',
|
||||||
|
'watch_desc_comments' => 'Notify upon all new pages, page changes and new comments.',
|
||||||
|
'watch_change_default' => 'Change default notification preferences',
|
||||||
];
|
];
|
||||||
|
|
|
@ -132,6 +132,7 @@ export class Dropdown extends Component {
|
||||||
|
|
||||||
onSelect(this.toggle, event => {
|
onSelect(this.toggle, event => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
this.show(event);
|
this.show(event);
|
||||||
if (event instanceof KeyboardEvent) {
|
if (event instanceof KeyboardEvent) {
|
||||||
keyboardNavHandler.focusNext();
|
keyboardNavHandler.focusNext();
|
||||||
|
|
|
@ -353,7 +353,7 @@ body.flexbox {
|
||||||
margin-inline-end: $-xl;
|
margin-inline-end: $-xl;
|
||||||
grid-template-columns: 1fr 4fr 1fr;
|
grid-template-columns: 1fr 4fr 1fr;
|
||||||
grid-template-areas: "a b c";
|
grid-template-areas: "a b c";
|
||||||
grid-column-gap: $-xxl;
|
grid-column-gap: $-xl;
|
||||||
.tri-layout-right {
|
.tri-layout-right {
|
||||||
grid-area: c;
|
grid-area: c;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
@ -378,6 +378,14 @@ body.flexbox {
|
||||||
padding-inline-end: $-l;
|
padding-inline-end: $-l;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@include between($xxl, $xxxl) {
|
||||||
|
.tri-layout-container {
|
||||||
|
grid-template-columns: 1fr calc(940px + (2 * $-m)) 1fr;
|
||||||
|
grid-column-gap: $-s;
|
||||||
|
margin-inline-start: $-m;
|
||||||
|
margin-inline-end: $-m;
|
||||||
|
}
|
||||||
|
}
|
||||||
@include between($l, $xxl) {
|
@include between($l, $xxl) {
|
||||||
.tri-layout-left {
|
.tri-layout-left {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
|
|
|
@ -672,7 +672,7 @@ ul.pagination {
|
||||||
@include lightDark(color, #555, #eee);
|
@include lightDark(color, #555, #eee);
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
text-align: start !important;
|
text-align: start !important;
|
||||||
max-height: 500px;
|
max-height: 80vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
&.anchor-left {
|
&.anchor-left {
|
||||||
inset-inline-end: auto;
|
inset-inline-end: auto;
|
||||||
|
@ -683,6 +683,7 @@ ul.pagination {
|
||||||
}
|
}
|
||||||
&.xl-limited {
|
&.xl-limited {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
.text-muted {
|
.text-muted {
|
||||||
color: #999;
|
color: #999;
|
||||||
|
@ -708,6 +709,11 @@ ul.pagination {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
&.break-text {
|
||||||
|
white-space: normal;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
&:hover, &:focus {
|
&:hover, &:focus {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background-color: var(--color-primary-light);
|
background-color: var(--color-primary-light);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
///////////////
|
///////////////
|
||||||
|
|
||||||
// Screen breakpoints
|
// Screen breakpoints
|
||||||
|
$xxxl: 1700px;
|
||||||
$xxl: 1400px;
|
$xxl: 1400px;
|
||||||
$xl: 1100px;
|
$xl: 1100px;
|
||||||
$l: 1000px;
|
$l: 1000px;
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
@section('right')
|
@section('right')
|
||||||
<div class="mb-xl" style="z-index: 1000; opacity: 1;">
|
<div class="mb-xl">
|
||||||
<h5>{{ trans('common.details') }}</h5>
|
<h5>{{ trans('common.details') }}</h5>
|
||||||
<div class="blended-links">
|
<div class="blended-links">
|
||||||
@include('entities.meta', ['entity' => $book])
|
@include('entities.meta', ['entity' => $book])
|
||||||
|
@ -142,6 +142,7 @@
|
||||||
@if(signedInUser())
|
@if(signedInUser())
|
||||||
@include('entities.favourite-action', ['entity' => $book])
|
@include('entities.favourite-action', ['entity' => $book])
|
||||||
@endif
|
@endif
|
||||||
|
@include('entities.watch-action', ['entity' => $book])
|
||||||
@if(userCan('content-export'))
|
@if(userCan('content-export'))
|
||||||
@include('entities.export-menu', ['entity' => $book])
|
@include('entities.export-menu', ['entity' => $book])
|
||||||
@endif
|
@endif
|
||||||
|
|
|
@ -69,11 +69,12 @@
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="dropdown-container">
|
<div component="dropdown"
|
||||||
<div class="entity-meta-item">
|
class="dropdown-container my-xxs">
|
||||||
|
<a refs="dropdown@toggle" href="#" class="entity-meta-item my-none">
|
||||||
@icon('watch')
|
@icon('watch')
|
||||||
<span>Watching with default preferences</span>
|
<span>Watching with default preferences</span>
|
||||||
</div>
|
</a>
|
||||||
@include('entities.watch-controls', ['entity' => $entity])
|
@include('entities.watch-controls', ['entity' => $entity])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<form action="{{ $entity->getUrl('/') }}" method="GET">
|
||||||
|
{{ csrf_field() }}
|
||||||
|
<input type="hidden" name="type" value="{{ get_class($entity) }}">
|
||||||
|
<input type="hidden" name="id" value="{{ $entity->id }}">
|
||||||
|
<button type="submit" data-shortcut="favourite" class="icon-list-item text-link">
|
||||||
|
<span>@icon('watch')</span>
|
||||||
|
<span>{{ trans('entities.watch') }}</span>
|
||||||
|
</button>
|
||||||
|
</form>
|
|
@ -1,71 +1,32 @@
|
||||||
<form action="{{ $entity->getUrl('/') }}" method="GET">
|
<form action="{{ $entity->getUrl('/') }}" method="GET">
|
||||||
{{-- {{ method_field('PUT') }}--}}
|
{{-- {{ method_field('PUT') }}--}}
|
||||||
|
{{ csrf_field() }}
|
||||||
|
<input type="hidden" name="type" value="{{ get_class($entity) }}">
|
||||||
|
<input type="hidden" name="id" value="{{ $entity->id }}">
|
||||||
|
|
||||||
<ul class="dropdown-menu xl-limited anchor-left" style="display: block;">
|
<ul refs="dropdown@menu" class="dropdown-menu xl-limited anchor-left pb-none">
|
||||||
|
@foreach(\BookStack\Users\UserWatchOptions::getAvailableOptionNames() as $option)
|
||||||
<li>
|
<li>
|
||||||
<button name="level" value="default" class="icon-item">
|
<button name="level" value="{{ $option }}" class="icon-item">
|
||||||
<span class="text-pos pt-m">{!! request()->query('level') === 'default' ? icon('check-circle') : '' !!}</span>
|
@if(request()->query('level') === $option)
|
||||||
|
<span class="text-pos pt-m" title="{{ trans('common.status_active') }}">@icon('check-circle')</span>
|
||||||
|
@else
|
||||||
|
<span title="{{ trans('common.status_inactive') }}"></span>
|
||||||
|
@endif
|
||||||
<div class="break-text">
|
<div class="break-text">
|
||||||
<div class="mb-xxs"><strong>Default Preferences</strong></div>
|
<div class="mb-xxs"><strong>{{ trans('entities.watch_title_' . $option) }}</strong></div>
|
||||||
<div class="text-muted text-small">
|
<div class="text-muted text-small">
|
||||||
Revert watching to just your default notification preferences.
|
{{ trans('entities.watch_desc_' . $option) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li><hr class="my-none"></li>
|
<li><hr class="my-none"></li>
|
||||||
|
@endforeach
|
||||||
<li>
|
<li>
|
||||||
<button name="level" value="ignore" class="icon-item">
|
<a href="{{ url('/preferences/notifications') }}"
|
||||||
<span class="text-pos pt-m">{!! request()->query('level') === 'ignore' ? icon('check-circle') : '' !!}</span>
|
target="_blank"
|
||||||
<div class="break-text">
|
class="text-item text-muted text-small break-text">{{ trans('entities.watch_change_default') }}</a>
|
||||||
<div class="mb-xxs"><strong>Ignore</strong></div>
|
|
||||||
<div class="text-muted text-small">
|
|
||||||
Ignore all notifications, including those from user-level preferences.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li><hr class="my-none"></li>
|
|
||||||
<li>
|
|
||||||
<button name="level" value="new" class="icon-item">
|
|
||||||
<span class="text-pos pt-m">{!! request()->query('level') === 'new' ? icon('check-circle') : '' !!}</span>
|
|
||||||
<div class="break-text">
|
|
||||||
<div class="mb-xxs"><strong>New Pages</strong></div>
|
|
||||||
<div class="text-muted text-small">
|
|
||||||
Notify when any new page is created within this item.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li><hr class="my-none"></li>
|
|
||||||
<li>
|
|
||||||
<button name="level" value="updates" class="icon-item">
|
|
||||||
<span class="text-pos pt-m">{!! request()->query('level') === 'updates' ? icon('check-circle') : '' !!}</span>
|
|
||||||
<div class="break-text">
|
|
||||||
<div class="mb-xxs"><strong>All Page Updates</strong></div>
|
|
||||||
<div class="text-muted text-small">
|
|
||||||
Notify upon all new pages and page changes.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li><hr class="my-none"></li>
|
|
||||||
<li>
|
|
||||||
<button name="level" value="comments" class="icon-item">
|
|
||||||
<span class="text-pos pt-m">{!! request()->query('level') === 'comments' ? icon('check-circle') : '' !!}</span>
|
|
||||||
<div class="break-text">
|
|
||||||
<div class="mb-xxs"><strong>All Page Updates & Comments</strong></div>
|
|
||||||
<div class="text-muted text-small">
|
|
||||||
Notify upon all new pages, page changes and new comments.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li><hr class="my-none"></li>
|
|
||||||
<li>
|
|
||||||
<div class="text-small text-muted px-l pb-xxs pt-xs">
|
|
||||||
<a href="{{ url('/preferences/notifications') }}" target="_blank">Change default notification preferences</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</form>
|
</form>
|
Loading…
Reference in New Issue