FEATURE: add page ordering
This commit is contained in:
@@ -117,4 +117,24 @@ class EditContent extends Controller
|
||||
->route('content.overview')
|
||||
->with('success', trans('admin/contents.successfullyEdited'));
|
||||
}
|
||||
|
||||
public function order() {
|
||||
$pages = $this->content->getOverview()->get();
|
||||
|
||||
return view('admin.content.order', compact('pages'));
|
||||
}
|
||||
|
||||
public function setOrder(Request $request) {
|
||||
|
||||
$data = $request->get('page');
|
||||
|
||||
foreach ($data as $id => $order) {
|
||||
Content::where('id', $id)->update(['order' => $order]);
|
||||
}
|
||||
|
||||
// something was changed, inform user
|
||||
return redirect()
|
||||
->route('content.overview')
|
||||
->with('success', trans('admin/contents.orderSuccessfullySet'));
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use App\CMS\Helpers\Traits\Nullable;
|
||||
use App\CMS\Observers\Content as ContentObserver;
|
||||
use App\Models\FileManager\File;
|
||||
use App\Models\Module;
|
||||
use App\Models\Templates\Template;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@@ -33,6 +34,7 @@ class Content extends Model
|
||||
'isHomepage',
|
||||
'title',
|
||||
'url',
|
||||
'order',
|
||||
'metaKeywords',
|
||||
'metaDescription',
|
||||
'pageContent',
|
||||
@@ -63,6 +65,10 @@ class Content extends Model
|
||||
return $this->hasMany(ContentHistory::class);
|
||||
}
|
||||
|
||||
public function templateModel() {
|
||||
return $this->belongsTo(Template::class, 'template', 'template_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark relationship with users table
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
@@ -100,7 +106,7 @@ class Content extends Model
|
||||
*/
|
||||
public function subpages()
|
||||
{
|
||||
return $this->hasMany(Content::class, 'parentId');
|
||||
return $this->hasMany(Content::class, 'parentId')->orderBy('order')->orderBy('created_at', 'DESC');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +115,7 @@ class Content extends Model
|
||||
*/
|
||||
public function publishedSubpages()
|
||||
{
|
||||
$query = $this->hasMany(Content::class, 'parentId');
|
||||
$query = $this->subpages();
|
||||
|
||||
if (\Auth::check()) {
|
||||
$query = $query->where('status', '!=', ContentContract::STATUS_DRAFT);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddOrderToContent extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('contents', function (Blueprint $table) {
|
||||
$table->integer('order')
|
||||
->after('viewed')
|
||||
->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('contents', function (Blueprint $table) {
|
||||
$table->dropColumn('order');
|
||||
});
|
||||
}
|
||||
}
|
||||
+6
-74
@@ -340,79 +340,11 @@ img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*.tag {*/
|
||||
/*display: inline-block;*/
|
||||
/*padding: 0.25em 0.4em;*/
|
||||
/*font-size: 75%;*/
|
||||
/*font-weight: bold;*/
|
||||
/*line-height: 1;*/
|
||||
/*color: #FFF;*/
|
||||
/*text-align: center;*/
|
||||
/*white-space: nowrap;*/
|
||||
/*vertical-align: baseline;*/
|
||||
/*border-radius: 0.25rem;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag:empty {*/
|
||||
/*display: none;*/
|
||||
/*}*/
|
||||
|
||||
/*.btn .tag {*/
|
||||
/*position: relative;*/
|
||||
/*top: -1px;*/
|
||||
/*}*/
|
||||
|
||||
/*a.tag:focus, a.tag:hover {*/
|
||||
/*color: #FFF;*/
|
||||
/*text-decoration: none;*/
|
||||
/*cursor: pointer;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-pill {*/
|
||||
/*padding-right: 0.6em;*/
|
||||
/*padding-left: 0.6em;*/
|
||||
/*border-radius: 10rem;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-default {*/
|
||||
/*background-color: #818A91;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-default[href]:focus, .tag-default[href]:hover {*/
|
||||
/*background-color: #687077;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-success {*/
|
||||
/*background-color: #5CB85C;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-success[href]:focus, .tag-success[href]:hover {*/
|
||||
/*background-color: #449D44;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-info {*/
|
||||
/*background-color: #5BC0DE;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-info[href]:focus, .tag-info[href]:hover {*/
|
||||
/*background-color: #31B0D5;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-warning {*/
|
||||
/*background-color: #F0AD4E;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-warning[href]:focus, .tag-warning[href]:hover {*/
|
||||
/*background-color: #EC971F;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-danger {*/
|
||||
/*background-color: #D9534F;*/
|
||||
/*}*/
|
||||
|
||||
/*.tag-danger[href]:focus, .tag-danger[href]:hover {*/
|
||||
/*background-color: #C9302C;*/
|
||||
/*}*/
|
||||
|
||||
.has-subpages:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#orderSetup .subpage td:first-child {
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
|
||||
@@ -386,9 +386,9 @@ $ (document).ready (function () {
|
||||
|
||||
$ ('#confirm-button').attr ('href', href);
|
||||
} else if (tag === 'BUTTON') {
|
||||
var form = $(this).closest('form');
|
||||
var form = $ (this).closest ('form');
|
||||
$ ('#confirm-button').click (function () {
|
||||
form.submit();
|
||||
form.submit ();
|
||||
})
|
||||
}
|
||||
|
||||
@@ -462,3 +462,11 @@ $ ('.checkbox').change (function () {
|
||||
$ ('#checkbox-parent-' + parent).prop ('checked', true);
|
||||
}
|
||||
});
|
||||
|
||||
$ ('.has-subpages').click (function (e) {
|
||||
if (!$ (e.target).is ("div"))
|
||||
return;
|
||||
|
||||
var id = $ (this).data ('id');
|
||||
$ ('.parent-page-' + id).toggleClass ('hidden-xs-up');
|
||||
})
|
||||
@@ -49,6 +49,19 @@
|
||||
********************************************** */
|
||||
|
||||
.item-list {
|
||||
|
||||
.subpage {
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -56,4 +56,6 @@ return [
|
||||
"title" => "Titulek",
|
||||
"uploadTitleImage" => "Nahrát titulní obrázek",
|
||||
"viewPage" => "Zobrazit",
|
||||
'setOrder' => 'Nastavení pořadí stránek',
|
||||
'orderSuccessfullySet' => 'Pořadí stránek úspěšně nastaveno',
|
||||
];
|
||||
|
||||
@@ -27,5 +27,6 @@ return [
|
||||
"widgetAreas" => "Plochy pro widgety",
|
||||
"widgets" => "Widgety",
|
||||
"widgetsOverview" => "Všechny widgety",
|
||||
'permissions' => 'Přístupová práva'
|
||||
'permissions' => 'Přístupová práva',
|
||||
'contentOrder' => 'Pořadí stránek'
|
||||
];
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<tr class="{{$extraClass or ''}}">
|
||||
<td>
|
||||
<label class="label-control" for="order-{{$page->id}}">
|
||||
{{$page->title}}
|
||||
</label>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input class="form-control" id="order-{{$page->id}}" type="text"
|
||||
name="page[{{$page->id}}]"
|
||||
value="{{old('page['.$page->id.']', $page->order)}}" />
|
||||
|
||||
@include('admin.snippets.hasError', ['field' => 'page['.$page->id.']'])
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@@ -0,0 +1,137 @@
|
||||
<div data-id="{{$page->id}}" class="row p-tb-15 parent-page-{{$page->parentId or 'none'}} {{$extraClass or ''}}">
|
||||
<div class="col-md-1 hidden-sm-down text-center with-placeholder">
|
||||
@can('update', $page)
|
||||
<a href="{{route('content.edit', ['page' => $page])}}">
|
||||
@if(!view()->exists(template_name($page->template, false)))
|
||||
<i class="fa fa-2x text-warning fa-warning" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.invalidTemplateSelected')"></i>
|
||||
@else
|
||||
@if(!empty($page->titlePhoto))
|
||||
<div class="thumbnail" style="background-image: url(@thumbnail($page->titlePhoto))"></div>
|
||||
@else
|
||||
<img src="{{asset('resources/assets/admin/img/placeholder.png')}}"
|
||||
class="placeholder"
|
||||
alt="{{$page->title}}" />
|
||||
@endif
|
||||
@endif
|
||||
</a>
|
||||
@else
|
||||
@if(!empty($page->titlePhoto))
|
||||
<img src="@thumbnail($page->titlePhoto)" class="placeholder"
|
||||
alt="{{$page->title}}" />
|
||||
@endif
|
||||
@endcan
|
||||
</div>
|
||||
<div class="col-xs-10 col-md-3 col-lg-4">
|
||||
@can('update', $page)
|
||||
<a href="{{route('content.edit', ['page' => $page])}}">
|
||||
{{$page->title}}
|
||||
</a>
|
||||
@else
|
||||
{{$page->title}}
|
||||
@endcan
|
||||
|
||||
|
||||
@if($page->isHomepage) <span
|
||||
class="m-l-10 tag tag-primary">@lang('admin/contents.homepage')</span> @endif
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 hidden-sm-down">
|
||||
<span class="tag @if($page->isPublic()) tag-success
|
||||
@elseif ($page->isDraft()) tag-danger
|
||||
@else tag-warning @endif">{{$statuses[$page->status]}}</span>
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 hidden-sm-down">
|
||||
<a href="{{route('content.overview', ['module' => $page->module->alias])}}">
|
||||
@lang($page->module->name)
|
||||
</a>
|
||||
<br>
|
||||
<small>({{$page->templateModel->name}})</small>
|
||||
</div>
|
||||
<div class="col-lg-2 hidden-md-down">@date($page->created_at)</div>
|
||||
<div class="col-xs-2 col-lg-1 text-center">
|
||||
<div class="item-actions-dropdown">
|
||||
<a class="item-actions-toggle-btn">
|
||||
<span class="inactive">
|
||||
<i class="fa fa-cog"></i>
|
||||
</span>
|
||||
<span class="active">
|
||||
<i class="fa fa-chevron-circle-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
<div class="item-actions-block">
|
||||
<ul class="item-actions-list">
|
||||
|
||||
@if(!$page->isHomepage)
|
||||
@can('set-homepage', $page)
|
||||
<li>
|
||||
<a href="{{route('content.setHomepage', ['page' => $page])}}"
|
||||
data-toggle="tooltip"
|
||||
title="@lang('admin/contents.setHomepage')">
|
||||
<i class="fa fa-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@endif
|
||||
|
||||
@can('update', $page)
|
||||
<li>
|
||||
<a class="edit" href="{{route('content.edit', ['page' => $page])}}"
|
||||
data-toggle="tooltip" title="@lang('admin/contents.editPlain')">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
@if($page->isDraft())
|
||||
@can('publish', $page)
|
||||
<li>
|
||||
<a href="{{route('content.changeStatus', ['page' => $page, 'status' => 'public'])}}"
|
||||
class="confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.makePublic')">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('protect', $page)
|
||||
<li>
|
||||
<a href="{{route('content.changeStatus', ['page' => $page, 'status' => 'protected'])}}"
|
||||
class="confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.makeProtected')">
|
||||
<i class="fa fa-lock"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@else
|
||||
<li>
|
||||
<a href="{{route('page.content', ['url' => $page->url])}}"
|
||||
target="_blank"
|
||||
data-toggle="tooltip" title="@lang('admin/contents.viewPage')"
|
||||
class="button tiny secondary"><i class="fa fa-globe"></i>
|
||||
</a>
|
||||
</li>
|
||||
@can('draft', $page)
|
||||
<li>
|
||||
<a href="{{route('content.changeStatus', ['page' => $page, 'status' => 'draft'])}}"
|
||||
class="button tiny warning confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.makeDraft')">
|
||||
<i class="fa fa-eye-slash"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@endif
|
||||
|
||||
@can('delete', $page)
|
||||
<li>
|
||||
<a href="{{route('content.delete', ['page' => $page])}}"
|
||||
class="button tiny alert remove confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.deletePage')"><i
|
||||
class="fa fa-trash-o"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,39 @@
|
||||
@extends('admin.layoutWithNavigation')
|
||||
|
||||
@section('pageHeading', trans('admin/contents.setOrder'))
|
||||
|
||||
@section('content')
|
||||
|
||||
@if (count($pages) > 0)
|
||||
<div class="card items" id="orderSetup">
|
||||
<div class="card-block">
|
||||
<form method="POST" enctype="multipart/form-data" class="form-inline"
|
||||
action="{{route('content.setOrder')}}">
|
||||
{!! csrf_field() !!}
|
||||
|
||||
<table>
|
||||
@foreach($pages as $page)
|
||||
@include('admin.content._partials.orderSetupRow')
|
||||
|
||||
@foreach($page->subpages as $subpage)
|
||||
@include('admin.content._partials.orderSetupRow', ['page' => $subpage, 'extraClass' => 'subpage'])
|
||||
@endforeach
|
||||
@endforeach
|
||||
</table>
|
||||
|
||||
|
||||
<button type="submit" class="btn btn-primary">@lang('admin/contents.save')</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@else
|
||||
<div class="alert alert-info">
|
||||
@lang('admin/contents.noPagesAvailable')
|
||||
</div>
|
||||
@endif
|
||||
@endsection
|
||||
@@ -46,142 +46,11 @@
|
||||
<div class="col-xs-2 col-lg-1">@lang('admin/contents.actions')</div>
|
||||
</div>
|
||||
@foreach($pages as $page)
|
||||
<div class="row p-tb-15">
|
||||
<div class="col-md-1 hidden-sm-down text-center with-placeholder">
|
||||
@can('update', $page)
|
||||
<a href="{{route('content.edit', ['page' => $page])}}">
|
||||
@if(!view()->exists(template_name($page->template, false)))
|
||||
<i class="fa fa-2x text-warning fa-warning" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.invalidTemplateSelected')"></i>
|
||||
@else
|
||||
@if(!empty($page->titlePhoto))
|
||||
<img src="@thumbnail($page->titlePhoto)" class="placeholder"
|
||||
alt="{{$page->title}}" />
|
||||
@else
|
||||
<img src="{{asset('resources/assets/admin/img/placeholder.png')}}"
|
||||
class="placeholder"
|
||||
alt="{{$page->title}}" />
|
||||
@endif
|
||||
@endif
|
||||
</a>
|
||||
@else
|
||||
@if(!empty($page->titlePhoto))
|
||||
<img src="@thumbnail($page->titlePhoto)" class="placeholder"
|
||||
alt="{{$page->title}}" />
|
||||
@endif
|
||||
@endcan
|
||||
</div>
|
||||
<div class="col-xs-10 col-md-3 col-lg-4">
|
||||
@can('update', $page)
|
||||
<a href="{{route('content.edit', ['page' => $page])}}">
|
||||
{{$page->title}}
|
||||
</a>
|
||||
@else
|
||||
{{$page->title}}
|
||||
@endcan
|
||||
@include('admin.content._partials.overviewRow', ['extraClass' => $page->subpages->isEmpty() ?: 'has-subpages'])
|
||||
|
||||
|
||||
@if($page->isHomepage) <span
|
||||
class="m-l-10 tag tag-primary">@lang('admin/contents.homepage')</span> @endif
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 hidden-sm-down">
|
||||
<span class="tag @if($page->isPublic()) tag-success
|
||||
@elseif ($page->isDraft()) tag-danger
|
||||
@else tag-warning @endif">{{$statuses[$page->status]}}</span>
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 hidden-sm-down">
|
||||
<a href="{{route('content.overview', ['module' => $page->module->alias])}}">
|
||||
{{trans($page->module_name)}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-2 hidden-md-down">@date($page->created_at)</div>
|
||||
<div class="col-xs-2 col-lg-1 text-center">
|
||||
<div class="item-actions-dropdown">
|
||||
<a class="item-actions-toggle-btn">
|
||||
<span class="inactive">
|
||||
<i class="fa fa-cog"></i>
|
||||
</span>
|
||||
<span class="active">
|
||||
<i class="fa fa-chevron-circle-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
<div class="item-actions-block">
|
||||
<ul class="item-actions-list">
|
||||
|
||||
@if(!$page->isHomepage)
|
||||
@can('set-homepage', $page)
|
||||
<li>
|
||||
<a href="{{route('content.setHomepage', ['page' => $page])}}"
|
||||
data-toggle="tooltip"
|
||||
title="@lang('admin/contents.setHomepage')">
|
||||
<i class="fa fa-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@endif
|
||||
|
||||
@can('update', $page)
|
||||
<li>
|
||||
<a class="edit" href="{{route('content.edit', ['page' => $page])}}"
|
||||
data-toggle="tooltip" title="@lang('admin/contents.editPlain')">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
@if($page->isDraft())
|
||||
@can('publish', $page)
|
||||
<li>
|
||||
<a href="{{route('content.changeStatus', ['page' => $page, 'status' => 'public'])}}"
|
||||
class="confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.makePublic')">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@can('protect', $page)
|
||||
<li>
|
||||
<a href="{{route('content.changeStatus', ['page' => $page, 'status' => 'protected'])}}"
|
||||
class="confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.makeProtected')">
|
||||
<i class="fa fa-lock"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@else
|
||||
<li>
|
||||
<a href="{{route('page.content', ['url' => $page->url])}}"
|
||||
target="_blank"
|
||||
data-toggle="tooltip" title="@lang('admin/contents.viewPage')"
|
||||
class="button tiny secondary"><i class="fa fa-globe"></i>
|
||||
</a>
|
||||
</li>
|
||||
@can('draft', $page)
|
||||
<li>
|
||||
<a href="{{route('content.changeStatus', ['page' => $page, 'status' => 'draft'])}}"
|
||||
class="button tiny warning confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.makeDraft')">
|
||||
<i class="fa fa-eye-slash"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
@endif
|
||||
|
||||
@can('delete', $page)
|
||||
<li>
|
||||
<a href="{{route('content.delete', ['page' => $page])}}"
|
||||
class="button tiny alert remove confirm" data-toggle="tooltip"
|
||||
title="@lang('admin/contents.deletePage')"><i
|
||||
class="fa fa-trash-o"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@foreach($page->subpages as $subpage)
|
||||
@include('admin.content._partials.overviewRow', ['page' => $subpage, 'extraClass' => 'subpage hidden-xs-up'])
|
||||
@endforeach
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,4 +50,7 @@ Route::group(['namespace' => 'Contents'], function () {
|
||||
Route::get('history/diff/{revision}', 'History@getDiff')
|
||||
->name('history.diff')
|
||||
->middleware('can:viewHistory,'.\App\Models\Content\Content::class);
|
||||
|
||||
Route::get('content/order', 'EditContent@order')->name('content.order');
|
||||
Route::post('content/order', 'EditContent@setOrder')->name('content.setOrder');
|
||||
});
|
||||
Reference in New Issue
Block a user