mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Revised revision list to responsive layout
This commit is contained in:
parent
de807f8538
commit
d4e71e431b
@ -8,6 +8,8 @@ use BookStack\Entities\Repos\PageRepo;
|
|||||||
use BookStack\Entities\Tools\PageContent;
|
use BookStack\Entities\Tools\PageContent;
|
||||||
use BookStack\Exceptions\NotFoundException;
|
use BookStack\Exceptions\NotFoundException;
|
||||||
use BookStack\Facades\Activity;
|
use BookStack\Facades\Activity;
|
||||||
|
use BookStack\Util\SimpleListOptions;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Ssddanbrown\HtmlDiff\Diff;
|
use Ssddanbrown\HtmlDiff\Diff;
|
||||||
|
|
||||||
class PageRevisionController extends Controller
|
class PageRevisionController extends Controller
|
||||||
@ -24,22 +26,29 @@ class PageRevisionController extends Controller
|
|||||||
*
|
*
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
*/
|
*/
|
||||||
public function index(string $bookSlug, string $pageSlug)
|
public function index(Request $request, string $bookSlug, string $pageSlug)
|
||||||
{
|
{
|
||||||
$page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
|
$page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
|
||||||
|
$listOptions = SimpleListOptions::fromRequest($request, 'page_revisions', true)->withSortOptions([
|
||||||
|
'id' => trans('entities.pages_revisions_sort_number')
|
||||||
|
]);
|
||||||
|
|
||||||
$revisions = $page->revisions()->select([
|
$revisions = $page->revisions()->select([
|
||||||
'id', 'page_id', 'name', 'created_at', 'created_by', 'updated_at',
|
'id', 'page_id', 'name', 'created_at', 'created_by', 'updated_at',
|
||||||
'type', 'revision_number', 'summary',
|
'type', 'revision_number', 'summary',
|
||||||
])
|
])
|
||||||
->selectRaw("IF(markdown = '', false, true) as is_markdown")
|
->selectRaw("IF(markdown = '', false, true) as is_markdown")
|
||||||
->with(['page.book', 'createdBy'])
|
->with(['page.book', 'createdBy'])
|
||||||
->get();
|
->reorder('id', $listOptions->getOrder())
|
||||||
|
->reorder('created_at', $listOptions->getOrder())
|
||||||
|
->paginate(50);
|
||||||
|
|
||||||
$this->setPageTitle(trans('entities.pages_revisions_named', ['pageName' => $page->getShortName()]));
|
$this->setPageTitle(trans('entities.pages_revisions_named', ['pageName' => $page->getShortName()]));
|
||||||
|
|
||||||
return view('pages.revisions', [
|
return view('pages.revisions', [
|
||||||
'revisions' => $revisions,
|
'revisions' => $revisions,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
|
'listOptions' => $listOptions,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class UserPreferencesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function changeSort(Request $request, string $id, string $type)
|
public function changeSort(Request $request, string $id, string $type)
|
||||||
{
|
{
|
||||||
$validSortTypes = ['books', 'bookshelves', 'shelf_books', 'users', 'roles', 'webhooks', 'tags'];
|
$validSortTypes = ['books', 'bookshelves', 'shelf_books', 'users', 'roles', 'webhooks', 'tags', 'page_revisions'];
|
||||||
if (!in_array($type, $validSortTypes)) {
|
if (!in_array($type, $validSortTypes)) {
|
||||||
return redirect()->back(500);
|
return redirect()->back(500);
|
||||||
}
|
}
|
||||||
|
@ -28,11 +28,11 @@ class SimpleListOptions
|
|||||||
* Create a new instance from the given request.
|
* Create a new instance from the given request.
|
||||||
* Takes the item type (plural) that's used as a key for storing sort preferences.
|
* Takes the item type (plural) that's used as a key for storing sort preferences.
|
||||||
*/
|
*/
|
||||||
public static function fromRequest(Request $request, string $typeKey): self
|
public static function fromRequest(Request $request, string $typeKey, bool $sortDescDefault = false): self
|
||||||
{
|
{
|
||||||
$search = $request->get('search', '');
|
$search = $request->get('search', '');
|
||||||
$sort = setting()->getForCurrentUser($typeKey . '_sort', '');
|
$sort = setting()->getForCurrentUser($typeKey . '_sort', '');
|
||||||
$order = setting()->getForCurrentUser($typeKey . '_sort_order', 'asc');
|
$order = setting()->getForCurrentUser($typeKey . '_sort_order', $sortDescDefault ? 'desc' : 'asc');
|
||||||
|
|
||||||
return new static($typeKey, $sort, $order, $search);
|
return new static($typeKey, $sort, $order, $search);
|
||||||
}
|
}
|
||||||
|
@ -233,12 +233,14 @@ return [
|
|||||||
'pages_permissions_success' => 'Page permissions updated',
|
'pages_permissions_success' => 'Page permissions updated',
|
||||||
'pages_revision' => 'Revision',
|
'pages_revision' => 'Revision',
|
||||||
'pages_revisions' => 'Page Revisions',
|
'pages_revisions' => 'Page Revisions',
|
||||||
|
'pages_revisions_desc' => 'Listed below are all the past revisions of this page. You can look back upon, compare, and restore old page versions if permissions allow. The full history of the page may not be fully reflected here since, depending on system configuration, old revisions could be auto-deleted.',
|
||||||
'pages_revisions_named' => 'Page Revisions for :pageName',
|
'pages_revisions_named' => 'Page Revisions for :pageName',
|
||||||
'pages_revision_named' => 'Page Revision for :pageName',
|
'pages_revision_named' => 'Page Revision for :pageName',
|
||||||
'pages_revision_restored_from' => 'Restored from #:id; :summary',
|
'pages_revision_restored_from' => 'Restored from #:id; :summary',
|
||||||
'pages_revisions_created_by' => 'Created By',
|
'pages_revisions_created_by' => 'Created By',
|
||||||
'pages_revisions_date' => 'Revision Date',
|
'pages_revisions_date' => 'Revision Date',
|
||||||
'pages_revisions_number' => '#',
|
'pages_revisions_number' => '#',
|
||||||
|
'pages_revisions_sort_number' => 'Revision Number',
|
||||||
'pages_revisions_numbered' => 'Revision #:id',
|
'pages_revisions_numbered' => 'Revision #:id',
|
||||||
'pages_revisions_numbered_changes' => 'Revision #:id Changes',
|
'pages_revisions_numbered_changes' => 'Revision #:id Changes',
|
||||||
'pages_revisions_editor' => 'Editor Type',
|
'pages_revisions_editor' => 'Editor Type',
|
||||||
|
@ -202,6 +202,15 @@ body.flexbox {
|
|||||||
/**
|
/**
|
||||||
* Min width utilities
|
* Min width utilities
|
||||||
*/
|
*/
|
||||||
|
.min-width-xxxxs {
|
||||||
|
min-width: 60px;
|
||||||
|
}
|
||||||
|
.min-width-xxxs {
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
.min-width-xxs {
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
.min-width-xs {
|
.min-width-xs {
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,43 @@
|
|||||||
<tr>
|
<div class="item-list-row flex-container-row items-center wrap">
|
||||||
<td>{{ $revision->revision_number == 0 ? '' : $revision->revision_number }}</td>
|
<div class="flex fit-content min-width-xxxxs px-m py-xs">
|
||||||
<td>
|
<span class="hide-over-l">{{ trans('entities.pages_revisions_number') }}</span>
|
||||||
|
{{ $revision->revision_number == 0 ? '' : $revision->revision_number }}
|
||||||
|
</div>
|
||||||
|
<div class="flex-2 px-m py-xs min-width-s">
|
||||||
{{ $revision->name }}
|
{{ $revision->name }}
|
||||||
<br>
|
<br>
|
||||||
<small class="text-muted">({{ $revision->is_markdown ? 'Markdown' : 'WYSIWYG' }})</small>
|
<small class="text-muted">(<strong class="hide-over-l">{{ trans('entities.pages_revisions_editor') }}: </strong>{{ $revision->is_markdown ? 'Markdown' : 'WYSIWYG' }})</small>
|
||||||
</td>
|
</div>
|
||||||
<td style="line-height: 0;" width="30">
|
<div class="flex-3 px-m py-xs min-width-l">
|
||||||
@if($revision->createdBy)
|
<div class="flex-container-row items-center gap-s">
|
||||||
<img class="avatar" src="{{ $revision->createdBy->getAvatar(30) }}" alt="{{ $revision->createdBy->name }}">
|
@if($revision->createdBy)
|
||||||
@endif
|
<img class="avatar flex-none" height="30" width="30" src="{{ $revision->createdBy->getAvatar(30) }}" alt="{{ $revision->createdBy->name }}">
|
||||||
</td>
|
@endif
|
||||||
<td width="260">
|
<div>
|
||||||
@if($revision->createdBy) {{ $revision->createdBy->name }} @else {{ trans('common.deleted_user') }} @endif
|
@if($revision->createdBy) {{ $revision->createdBy->name }} @else {{ trans('common.deleted_user') }} @endif
|
||||||
<br>
|
<br>
|
||||||
<div class="text-muted">
|
<div class="text-muted">
|
||||||
<small>{{ $revision->created_at->formatLocalized('%e %B %Y %H:%M:%S') }}</small>
|
<small>{{ $revision->created_at->formatLocalized('%e %B %Y %H:%M:%S') }}</small>
|
||||||
<small>({{ $revision->created_at->diffForHumans() }})</small>
|
<small>({{ $revision->created_at->diffForHumans() }})</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
<td>
|
<div class="flex-2 px-m py-xs min-width-m text-small">
|
||||||
{{ $revision->summary }}
|
{{ $revision->summary }}
|
||||||
</td>
|
</div>
|
||||||
<td class="actions text-small text-right">
|
<div class="flex-2 px-m py-xs actions text-small text-l-right min-width-l">
|
||||||
<a href="{{ $revision->getUrl('changes') }}" target="_blank" rel="noopener">{{ trans('entities.pages_revisions_changes') }}</a>
|
<a href="{{ $revision->getUrl('changes') }}" target="_blank" rel="noopener">{{ trans('entities.pages_revisions_changes') }}</a>
|
||||||
<span class="text-muted"> | </span>
|
<span class="text-muted opacity-70"> | </span>
|
||||||
|
|
||||||
|
|
||||||
@if ($index === 0)
|
@if ($current)
|
||||||
<a target="_blank" rel="noopener" href="{{ $revision->page->getUrl() }}"><i>{{ trans('entities.pages_revisions_current') }}</i></a>
|
<a target="_blank" rel="noopener" href="{{ $revision->page->getUrl() }}"><i>{{ trans('entities.pages_revisions_current') }}</i></a>
|
||||||
@else
|
@else
|
||||||
<a href="{{ $revision->getUrl() }}" target="_blank" rel="noopener">{{ trans('entities.pages_revisions_preview') }}</a>
|
<a href="{{ $revision->getUrl() }}" target="_blank" rel="noopener">{{ trans('entities.pages_revisions_preview') }}</a>
|
||||||
|
|
||||||
@if(userCan('page-update', $revision->page))
|
@if(userCan('page-update', $revision->page))
|
||||||
<span class="text-muted"> | </span>
|
<span class="text-muted opacity-70"> | </span>
|
||||||
<div component="dropdown" class="dropdown-container">
|
<div component="dropdown" class="dropdown-container">
|
||||||
<a refs="dropdown@toggle" href="#" aria-haspopup="true" aria-expanded="false">{{ trans('entities.pages_revisions_restore') }}</a>
|
<a refs="dropdown@toggle" href="#" aria-haspopup="true" aria-expanded="false">{{ trans('entities.pages_revisions_restore') }}</a>
|
||||||
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
|
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
|
||||||
@ -52,7 +57,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if(userCan('page-delete', $revision->page))
|
@if(userCan('page-delete', $revision->page))
|
||||||
<span class="text-muted"> | </span>
|
<span class="text-muted opacity-70"> | </span>
|
||||||
<div component="dropdown" class="dropdown-container">
|
<div component="dropdown" class="dropdown-container">
|
||||||
<a refs="dropdown@toggle" href="#" aria-haspopup="true" aria-expanded="false">{{ trans('common.delete') }}</a>
|
<a refs="dropdown@toggle" href="#" aria-haspopup="true" aria-expanded="false">{{ trans('common.delete') }}</a>
|
||||||
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
|
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
|
||||||
@ -71,5 +76,5 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
</div>
|
@ -17,26 +17,36 @@
|
|||||||
|
|
||||||
<main class="card content-wrap">
|
<main class="card content-wrap">
|
||||||
<h1 class="list-heading">{{ trans('entities.pages_revisions') }}</h1>
|
<h1 class="list-heading">{{ trans('entities.pages_revisions') }}</h1>
|
||||||
|
|
||||||
|
<p class="text-muted">{{ trans('entities.pages_revisions_desc') }}</p>
|
||||||
|
|
||||||
|
<div class="flex-container-row my-m items-center justify-space-between wrap gap-x-m gap-y-s">
|
||||||
|
{{ $revisions->links() }}
|
||||||
|
<div>
|
||||||
|
@include('common.sort', $listOptions->getSortControlData())
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if(count($revisions) > 0)
|
@if(count($revisions) > 0)
|
||||||
|
<div class="item-list">
|
||||||
<table class="table">
|
<div class="item-list-row flex-container-row items-center strong hide-under-l">
|
||||||
<tr>
|
<div class="flex fit-content min-width-xxxxs px-m py-xs">{{ trans('entities.pages_revisions_number') }}</div>
|
||||||
<th width="56">{{ trans('entities.pages_revisions_number') }}</th>
|
<div class="flex-2 px-m py-xs">{{ trans('entities.pages_name') }} / {{ trans('entities.pages_revisions_editor') }}</div>
|
||||||
<th>
|
<div class="flex-3 px-m py-xs">{{ trans('entities.pages_revisions_created_by') }} / {{ trans('entities.pages_revisions_date') }}</div>
|
||||||
{{ trans('entities.pages_name') }} / {{ trans('entities.pages_revisions_editor') }}
|
<div class="flex-2 px-m py-xs">{{ trans('entities.pages_revisions_changelog') }}</div>
|
||||||
</th>
|
<div class="flex-2 px-m py-xs text-right">{{ trans('common.actions') }}</div>
|
||||||
<th colspan="2">{{ trans('entities.pages_revisions_created_by') }} / {{ trans('entities.pages_revisions_date') }}</th>
|
</div>
|
||||||
<th>{{ trans('entities.pages_revisions_changelog') }}</th>
|
|
||||||
<th class="text-right">{{ trans('common.actions') }}</th>
|
|
||||||
</tr>
|
|
||||||
@foreach($revisions as $index => $revision)
|
@foreach($revisions as $index => $revision)
|
||||||
@include('pages.parts.revision-table-row', ['revision' => $revision])
|
@include('pages.parts.revisions-index-row', ['revision' => $revision, 'current' => $page->revision_count === $revision->revision_number])
|
||||||
@endforeach
|
@endforeach
|
||||||
</table>
|
</div>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<p>{{ trans('entities.pages_revisions_none') }}</p>
|
<p>{{ trans('entities.pages_revisions_none') }}</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
<div class="my-m">
|
||||||
|
{{ $revisions->links() }}
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user