FEATURE: make content list in admin nicer

This commit is contained in:
Michal Kváček
2017-04-05 01:40:47 +02:00
parent 2e8f8dca1f
commit 870ca540c4
5 changed files with 403 additions and 400 deletions
+5 -2
View File
@@ -1,13 +1,15 @@
<?php <?php
namespace App\CMS\Widgets\Menu; namespace App\CMS\Widgets\Menu;
use App\CMS\Contracts\Repositories\Content as IContent;
use App\CMS\Contracts\Widgets\PublicWidget; use App\CMS\Contracts\Widgets\PublicWidget;
use App\CMS\Widgets\Contracts\WidgetRenderer; use App\CMS\Contracts\Widgets\WidgetRenderer;
use App\CMS\Widgets\Exceptions\MissingParameterException; use App\CMS\Widgets\Exceptions\MissingParameterException;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Models\Content\Content; use App\Models\Content\Content;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization; use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use App\CMS\Contracts\Repositories\Content as IContent; use Modules\Blog\Article\Handlers\Article;
class Menu implements PublicWidget class Menu implements PublicWidget
{ {
@@ -76,6 +78,7 @@ class Menu implements PublicWidget
$pages = Content::where('language', LaravelLocalization::getCurrentLocale()) $pages = Content::where('language', LaravelLocalization::getCurrentLocale())
->whereIn('id', $ids) ->whereIn('id', $ids)
->whereIn('status', $allowedStatuses) ->whereIn('status', $allowedStatuses)
->where('moduleHandler', '!=', Article::class)
->get(); ->get();
$used = []; $used = [];
foreach ($pages as $page) { foreach ($pages as $page) {
+3 -1
View File
@@ -1,4 +1,5 @@
<?php <?php
namespace App\CMS\Widgets\Menu\Presenters; namespace App\CMS\Widgets\Menu\Presenters;
use App\CMS\Contracts\Repositories\Content as ContentContract; use App\CMS\Contracts\Repositories\Content as ContentContract;
@@ -81,7 +82,8 @@ class Menu implements WidgetRenderer
$content = app(ContentContract::class); $content = app(ContentContract::class);
// get list of all pages // get list of all pages
$pages = $content->getOverview(); $pages = $content->getOverview()
->get();
$widget->settings = new \stdClass(); $widget->settings = new \stdClass();
$widget->settings->links = []; $widget->settings->links = [];
@@ -1,386 +1,377 @@
@import "../imports"; @import "../imports";
/* ******************************************* /* *******************************************
* Item List general styles * Item List general styles
********************************************** */ ********************************************** */
.item-list { .item-list {
list-style: none; list-style: none;
padding: 0; padding: 0;
margin: 0; margin: 0;
margin-bottom: 0; line-height: $item-list-line-height;
line-height: $item-list-line-height;
@include media(lg) { @include media(lg) {
font-size: 1rem; font-size: 1rem;
} }
@include media(md) { @include media(md) {
font-size: 0.95rem; font-size: 0.95rem;
} }
@include media-down(sm) { @include media-down(sm) {
font-size: 1.05rem; font-size: 1.05rem;
} }
display: flex; display: flex;
flex-flow: column nowrap; flex-flow: column nowrap;
&.striped { &.striped {
& > li { & > div {
border-bottom: 1px solid $item-list-color-border; border-bottom: 1px solid $item-list-color-border;
} }
& > li:nth-child(2n + 1) { & > div:nth-child(2n + 1) {
background-color: lighten($color-divider, 12%); background-color: lighten($color-divider, 12%);
@include media-down(sm) { @include media-down(sm) {
background-color: lighten($color-divider, 11%); background-color: lighten($color-divider, 11%);
} }
} }
.item-list-footer { .item-list-footer {
border-bottom: none; border-bottom: none;
} }
} }
} }
/* ******************************************* /* *******************************************
* Item general styles * Item general styles
********************************************** */ ********************************************** */
.item-list { .item-list {
.item { .item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.item-row { .item-row {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
min-width: 100%; min-width: 100%;
&.nowrap { &.nowrap {
flex-wrap: nowrap; flex-wrap: nowrap;
} }
} }
.item-col { .item-col {
align-items: center; align-items: center;
display: flex; display: flex;
padding: $item-list-padding-y $item-list-padding-x $item-list-padding-y 0; padding: $item-list-padding-y $item-list-padding-x $item-list-padding-y 0;
flex-basis: 0; flex-basis: 0;
flex-grow: $item-list-col-grow; flex-grow: $item-list-col-grow;
flex-shrink: $item-list-col-shrink; flex-shrink: $item-list-col-shrink;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
min-width: 0; min-width: 0;
&.fixed { &.fixed {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;
flex-basis: auto; flex-basis: auto;
} }
&.pull-left { &.pull-left {
margin-right: auto; margin-right: auto;
} }
&.pull-right { &.pull-right {
margin-left: auto; margin-left: auto;
} }
& > div { & > div {
width: 100%; width: 100%;
} }
&:last-child { &:last-child {
padding-right: 0; padding-right: 0;
} }
} }
.no-overflow { .no-overflow {
overflow: hidden; overflow: hidden;
} }
.no-wrap { .no-wrap {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
} }
/* ******************************************* /* *******************************************
* Item components * Item components
********************************************** */ ********************************************** */
.item-list { .item-list {
/******************************************** /********************************************
* Header * Header
*********************************************/ *********************************************/
.item-list-header { .item-list-header {
.item-col.item-col-header { .item-col.item-col-header {
span { span {
color: #999; color: #999;
font-size: 0.8rem; font-size: 0.8rem;
font-weight: 700 !important; font-weight: 700 !important;
} }
} }
} }
/******************************************** /********************************************
* Heading * Heading
*********************************************/ *********************************************/
.item-heading { .item-heading {
font-size: 0.9rem; font-size: 0.9rem;
display: none; display: none;
color: #666; color: #666;
font-weight: 700; font-weight: 700;
padding-right: $item-list-padding-x; padding-right: $item-list-padding-x;
@include media-down(sm) { @include media-down(sm) {
display: block; display: block;
} }
@include media(sm) { @include media(sm) {
width: 100%; width: 100%;
} }
@include media(xs) { @include media(xs) {
width: 40%; width: 40%;
} }
} }
/******************************************** /********************************************
* Checkbox * Checkbox
*********************************************/ *********************************************/
.item-col.item-col-check { .item-col.item-col-check {
flex-basis: 20px + $item-list-padding-x; flex-basis: 20px + $item-list-padding-x;
@include media-down(sm) { @include media-down(sm) {
order: -8; order: -8;
} }
} }
.item-check { .item-check {
margin-bottom: 0; margin-bottom: 0;
.checkbox + span { .checkbox + span {
padding-right: 0; padding-right: 0;
&:before { &:before {
width: 20px; width: 20px;
} }
} }
} }
/******************************************** /********************************************
* Image * Image
*********************************************/ *********************************************/
.item-col.item-col-img { .item-col.item-col-img {
display: flex; display: flex;
flex-basis: 60px + $item-list-padding-x; flex-basis: 60px + $item-list-padding-x;
&.xs{ &.xs {
flex-basis: 30px + $item-list-padding-x; flex-basis: 30px + $item-list-padding-x;
} }
&.sm { &.sm {
flex-basis: 40px + $item-list-padding-x; flex-basis: 40px + $item-list-padding-x;
} }
&.lg { &.lg {
flex-basis: 90px + $item-list-padding-x; flex-basis: 90px + $item-list-padding-x;
} }
&.xl { &.xl {
flex-basis: 110px + $item-list-padding-x; flex-basis: 110px + $item-list-padding-x;
} }
a { a {
width: 100%; width: 100%;
// display: flex; // display: flex;
} }
} }
.item-img { .item-img {
flex-grow: 1; flex-grow: 1;
align-self: stretch; align-self: stretch;
background-color: #efefef; background-color: #EFEFEF;
padding-bottom: 100%; padding-bottom: 100%;
width: 100%; width: 100%;
height: 0; height: 0;
@include bg-cover(); @include bg-cover();
} }
/******************************************** /********************************************
* Title * Title
*********************************************/ *********************************************/
.item-col.item-col-title { .item-col.item-col-title {
@include media-down(sm) { @include media-down(sm) {
order: -4; order: -4;
} }
a { a {
display: block; display: block;
} }
} }
.item-title { .item-title {
margin: 0; margin: 0;
font-size: inherit; font-size: inherit;
line-height: inherit; line-height: inherit;
font-weight: 600; font-weight: 600;
} }
/******************************************** /********************************************
* Stats * Stats
*********************************************/ *********************************************/
.item-stats { .item-stats {
height: $item-list-line-height; height: $item-list-line-height;
} }
/******************************************** /********************************************
* Actions * Actions
*********************************************/ *********************************************/
.item-col.item-col-actions-dropdown { .item-col.item-col-actions-dropdown {
flex-basis: 30px + $item-list-padding-x; flex-basis: 30px + $item-list-padding-x;
text-align: center; text-align: center;
padding-left: 0 !important; padding-left: 0 !important;
@include media-down(sm) { @include media-down(sm) {
order: -3; order: -3;
flex-basis: 30px + $item-list-padding-x !important; flex-basis: 30px + $item-list-padding-x !important;
padding-right: $item-list-padding-x; padding-right: $item-list-padding-x;
} }
} }
.item-actions-dropdown { .item-actions-dropdown {
position: relative; position: relative;
font-size: 1.1rem; font-size: 1.1rem;
&.active { &.active {
.item-actions-block { .item-actions-block {
max-width: 120px; max-width: 120px;
} }
.item-actions-toggle-btn { .item-actions-toggle-btn {
color: $color-primary; color: $color-primary;
.active { .active {
display: block; display: block;
} }
.inactive { .inactive {
display: none; display: none;
} }
} }
} }
.item-actions-toggle-btn { .item-actions-toggle-btn {
color: lighten($color-text-light, 10); color: lighten($color-text-light, 10);
font-size: 1.2rem; font-size: 1.2rem;
cursor: pointer; cursor: pointer;
width: 100%; width: 100%;
line-height: 30px; line-height: 30px;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
.active { .active {
display: none; display: none;
} }
} }
.item-actions-block { .item-actions-block {
height: 30px; height: 30px;
max-width: 0px; max-width: 0px;
line-height: 30px; line-height: 30px;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
top: 0; top: 0;
right: 100%; right: 100%;
background-color: $color-divider; background-color: $color-divider;
border-radius: 3px; border-radius: 3px;
transition: all 0.15s ease-in-out; transition: all 0.15s ease-in-out;
&.direction-right { &.direction-right {
right: auto; right: auto;
left: 100%; left: 100%;
} }
.item-actions-list {
padding: 0;
list-style: none;
white-space: nowrap;
padding: 0 5px;
.item-actions-list { li {
padding: 0; display: inline-block;
list-style: none; padding: 0;
white-space: nowrap; }
padding: 0 5px;
li{ a {
display: inline-block; display: block;
padding: 0; padding: 0 5px;
}
a { &.edit {
display: block; color: #38424C;
padding: 0 5px; }
&.edit { &.check {
color: #38424C; color: #40B726;
} }
&.check { &.remove {
color: #40B726; color: #DB0E1E;
} }
}
}
}
&.remove { }
color: #DB0E1E;
}
}
}
}
} /********************************************
* Something else?
/******************************************** *********************************************/
* Something else?
*********************************************/
} }
/* ******************************************* /* *******************************************
* Adjustments * Adjustments
********************************************** */ ********************************************** */
// Item which is located inside card inside item-list // Item which is located inside card inside item-list
.card > .item-list .item > .item-row { .card > .item-list .item > .item-row {
padding: 0 $card-padding-x; padding: 0 $card-padding-x;
@include media(xl) { @include media(xl) {
padding: 0 $card-padding-x-xl; padding: 0 $card-padding-x-xl;
} }
@include media-down(sm) { @include media-down(sm) {
padding: 0 $card-padding-x-sm; padding: 0 $card-padding-x-sm;
} }
} }
@@ -1,5 +1,9 @@
@import "../../../imports"; @import "../../../imports";
.item-list {
}
.items-list-page { .items-list-page {
.title-search-block { .title-search-block {
@@ -313,12 +317,7 @@
text-align: left; text-align: left;
} }
} }
} }
} }
} }
+114 -106
View File
@@ -22,132 +22,140 @@
@endif @endif
@if (count($pages) > 0) @if (count($pages) > 0)
<div class="item-list rows-striped"> <div class="card items">
<div class="row bold p-tb-15"> <div class="card-block">
<div class="col-md-1 hidden-sm-down"></div> <div class="item-list striped rows-striped">
<div class="col-xs-10 col-md-3 col-lg-4">@lang('admin/contents.title')</div> <div class="row bold p-tb-15">
<div class="col-lg-2 col-md-3 hidden-sm-down">@lang('admin/contents.status')</div> <div class="col-md-1 hidden-sm-down"></div>
<div class="col-lg-2 col-md-3 hidden-sm-down">@lang('admin/contents.moduleName')</div> <div class="col-xs-10 col-md-3 col-lg-4">@lang('admin/contents.title')</div>
<div class="col-lg-2 hidden-md-down">@lang('admin/contents.createdAt')</div> <div class="col-lg-2 col-md-3 hidden-sm-down">@lang('admin/contents.status')</div>
<div class="col-xs-2 col-lg-1">@lang('admin/contents.actions')</div> <div class="col-lg-2 col-md-3 hidden-sm-down">@lang('admin/contents.moduleName')</div>
</div> <div class="col-lg-2 hidden-md-down">@lang('admin/contents.createdAt')</div>
@foreach($pages as $page) <div class="col-xs-2 col-lg-1">@lang('admin/contents.actions')</div>
<div class="row p-tb-15">
<div class="col-md-1 hidden-sm-down text-center with-placeholder">
<a href="{{route('content.edit', ['id' => $page->id])}}">
@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>
</div> </div>
<div class="col-xs-10 col-md-3 col-lg-4"> @foreach($pages as $page)
<a href="{{route('content.edit', ['id' => $page->id])}}"> <div class="row p-tb-15">
{{$page->title}} <div class="col-md-1 hidden-sm-down text-center with-placeholder">
</a> <a href="{{route('content.edit', ['id' => $page->id])}}">
@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>
</div>
<div class="col-xs-10 col-md-3 col-lg-4">
<a href="{{route('content.edit', ['id' => $page->id])}}">
{{$page->title}}
</a>
@if($page->isHomepage) <span class="m-l-10 tag tag-primary">@lang('admin/contents.homepage')</span> @endif @if($page->isHomepage) <span
</div> class="m-l-10 tag tag-primary">@lang('admin/contents.homepage')</span> @endif
<div class="col-lg-2 col-md-3 hidden-sm-down"> </div>
<div class="col-lg-2 col-md-3 hidden-sm-down">
<span class="tag @if($page->isPublic()) tag-success <span class="tag @if($page->isPublic()) tag-success
@elseif ($page->isDraft()) tag-danger @elseif ($page->isDraft()) tag-danger
@else tag-warning @endif">{{$statuses[$page->status]}}</span> @else tag-warning @endif">{{$statuses[$page->status]}}</span>
</div> </div>
<div class="col-lg-2 col-md-3 hidden-sm-down"> <div class="col-lg-2 col-md-3 hidden-sm-down">
<a href="{{route('content.overview', ['moduleId' => $page->module_id])}}"> <a href="{{route('content.overview', ['moduleId' => $page->module_id])}}">
{{trans($page->module_name)}} {{trans($page->module_name)}}
</a> </a>
</div> </div>
<div class="col-lg-2 hidden-md-down">@date($page->created_at)</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="col-xs-2 col-lg-1 text-center">
<div class="item-actions-dropdown"> <div class="item-actions-dropdown">
<a class="item-actions-toggle-btn"> <a class="item-actions-toggle-btn">
<span class="inactive"> <span class="inactive">
<i class="fa fa-cog"></i> <i class="fa fa-cog"></i>
</span> </span>
<span class="active"> <span class="active">
<i class="fa fa-chevron-circle-right"></i> <i class="fa fa-chevron-circle-right"></i>
</span> </span>
</a> </a>
<div class="item-actions-block"> <div class="item-actions-block">
<ul class="item-actions-list"> <ul class="item-actions-list">
@if(!$page->isHomepage) @if(!$page->isHomepage)
<li> <li>
<a href="{{route('content.setHomepage', ['id' => $page->id])}}" <a href="{{route('content.setHomepage', ['id' => $page->id])}}"
data-toggle="tooltip" title="@lang('admin/contents.setHomepage')"> data-toggle="tooltip"
<i class="fa fa-home"></i> title="@lang('admin/contents.setHomepage')">
</a> <i class="fa fa-home"></i>
</li> </a>
@endif </li>
@endif
<li> <li>
<a class="edit" href="{{route('content.edit', ['id' => $page->id])}}" <a class="edit" href="{{route('content.edit', ['id' => $page->id])}}"
data-toggle="tooltip" title="@lang('admin/contents.editPlain')"> data-toggle="tooltip" title="@lang('admin/contents.editPlain')">
<i class="fa fa-pencil"></i> <i class="fa fa-pencil"></i>
</a> </a>
</li> </li>
@if($page->isDraft()) @if($page->isDraft())
<li> <li>
<a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'public'])}}" <a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'public'])}}"
class="confirm" data-toggle="tooltip" class="confirm" data-toggle="tooltip"
title="@lang('admin/contents.makePublic')"> title="@lang('admin/contents.makePublic')">
<i class="fa fa-eye"></i> <i class="fa fa-eye"></i>
</a> </a>
</li> </li>
<li> <li>
<a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'protected'])}}" <a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'protected'])}}"
class="confirm" data-toggle="tooltip" class="confirm" data-toggle="tooltip"
title="@lang('admin/contents.makeProtected')"> title="@lang('admin/contents.makeProtected')">
<i class="fa fa-lock"></i> <i class="fa fa-lock"></i>
</a> </a>
</li> </li>
@else @else
<li> <li>
<a href="{{route('page.content', ['url' => $page->url])}}" target="_blank" <a href="{{route('page.content', ['url' => $page->url])}}"
data-toggle="tooltip" title="@lang('admin/contents.viewPage')" target="_blank"
class="button tiny secondary"><i class="fa fa-globe"></i> data-toggle="tooltip" title="@lang('admin/contents.viewPage')"
</a> class="button tiny secondary"><i class="fa fa-globe"></i>
</li> </a>
<li> </li>
<a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'draft'])}}" <li>
class="button tiny warning confirm" data-toggle="tooltip" <a href="{{route('content.changeStatus', ['id' => $page->id, 'status' => 'draft'])}}"
title="@lang('admin/contents.makeDraft')"> class="button tiny warning confirm" data-toggle="tooltip"
<i class="fa fa-eye-slash"></i> title="@lang('admin/contents.makeDraft')">
</a> <i class="fa fa-eye-slash"></i>
</li> </a>
@endif </li>
@endif
<li>
<a href="{{route('content.delete', ['id' => $page->id])}}"
class="button tiny alert remove confirm" data-toggle="tooltip"
title="@lang('admin/contents.deletePage')"><i
class="fa fa-trash-o"></i>
</a>
</li>
</ul>
</div>
</div>
<li>
<a href="{{route('content.delete', ['id' => $page->id])}}"
class="button tiny alert remove confirm" data-toggle="tooltip"
title="@lang('admin/contents.deletePage')"><i
class="fa fa-trash-o"></i>
</a>
</li>
</ul>
</div> </div>
</div> </div>
@endforeach
</div>
</div> </div>
@endforeach </div>
<div class="card-footer">
{!! $pages->render() !!}
</div>
</div> </div>
<div class="row">
{!! $pages->render() !!}
</div>
@else @else
<div class="alert alert-info"> <div class="alert alert-info">