--- /dev/null
+<?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);
+ }
+}
'references' => 'References',
'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.',
+
+ // 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',
];
onSelect(this.toggle, event => {
event.stopPropagation();
+ event.preventDefault();
this.show(event);
if (event instanceof KeyboardEvent) {
keyboardNavHandler.focusNext();
margin-inline-end: $-xl;
grid-template-columns: 1fr 4fr 1fr;
grid-template-areas: "a b c";
- grid-column-gap: $-xxl;
+ grid-column-gap: $-xl;
.tri-layout-right {
grid-area: c;
min-width: 0;
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) {
.tri-layout-left {
position: sticky;
@include lightDark(color, #555, #eee);
fill: currentColor;
text-align: start !important;
- max-height: 500px;
+ max-height: 80vh;
overflow-y: auto;
&.anchor-left {
inset-inline-end: auto;
}
&.xl-limited {
width: 280px;
+ max-width: 100%;
}
.text-muted {
color: #999;
white-space: nowrap;
line-height: 1.4;
cursor: pointer;
+ &.break-text {
+ white-space: normal;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ }
&:hover, &:focus {
text-decoration: none;
background-color: var(--color-primary-light);
///////////////
// Screen breakpoints
+$xxxl: 1700px;
$xxl: 1400px;
$xl: 1100px;
$l: 1000px;
@stop
@section('right')
- <div class="mb-xl" style="z-index: 1000; opacity: 1;">
+ <div class="mb-xl">
<h5>{{ trans('common.details') }}</h5>
<div class="blended-links">
@include('entities.meta', ['entity' => $book])
@if(signedInUser())
@include('entities.favourite-action', ['entity' => $book])
@endif
+ @include('entities.watch-action', ['entity' => $book])
@if(userCan('content-export'))
@include('entities.export-menu', ['entity' => $book])
@endif
</a>
@endif
- <div class="dropdown-container">
- <div class="entity-meta-item">
+ <div component="dropdown"
+ class="dropdown-container my-xxs">
+ <a refs="dropdown@toggle" href="#" class="entity-meta-item my-none">
@icon('watch')
<span>Watching with default preferences</span>
- </div>
+ </a>
@include('entities.watch-controls', ['entity' => $entity])
</div>
</div>
\ No newline at end of file
--- /dev/null
+<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>
\ No newline at end of file
<form action="{{ $entity->getUrl('/') }}" method="GET">
{{-- {{ 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>
- <button name="level" value="default" class="icon-item">
- <span class="text-pos pt-m">{!! request()->query('level') === 'default' ? icon('check-circle') : '' !!}</span>
+ <button name="level" value="{{ $option }}" class="icon-item">
+ @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="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">
- Revert watching to just your default notification preferences.
+ {{ trans('entities.watch_desc_' . $option) }}
</div>
</div>
</button>
</li>
<li><hr class="my-none"></li>
+ @endforeach
<li>
- <button name="level" value="ignore" class="icon-item">
- <span class="text-pos pt-m">{!! request()->query('level') === 'ignore' ? icon('check-circle') : '' !!}</span>
- <div class="break-text">
- <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>
+ <a href="{{ url('/preferences/notifications') }}"
+ target="_blank"
+ class="text-item text-muted text-small break-text">{{ trans('entities.watch_change_default') }}</a>
</li>
</ul>
</form>
\ No newline at end of file