Implemented page sorting by title, URL and file name in the CMS back-end. Closes #84

This commit is contained in:
Aleksey Bobkov 2017-01-12 20:13:32 -08:00
parent 5415e64cf3
commit 6e54433bc1
7 changed files with 103 additions and 15 deletions

View File

@ -9,3 +9,7 @@ descriptionProperties:
noRecordsMessage: 'cms::lang.page.no_list_records'
deleteConfirmation: 'cms::lang.page.delete_confirm_multiple'
itemType: page
sortingProperties:
url: 'cms::lang.page.url'
title: 'cms::lang.page.title'
fileName: 'cms::lang.page.file_name'

View File

@ -115,7 +115,10 @@ return [
'delete_confirm_multiple' => 'Delete selected pages?',
'delete_confirm_single' => 'Delete this page?',
'no_layout' => '-- no layout --',
'cms_page' => 'CMS page'
'cms_page' => 'CMS page',
'title' => 'Page title',
'url' => 'Page URL',
'file_name' => 'Page file name'
],
'layout' => [
'not_found_name' => "The layout ':name' is not found",
@ -241,7 +244,8 @@ return [
'not_found' => 'Template not found.',
'saved' => 'Template saved.',
'no_list_records' => 'No records found',
'delete_confirm' => 'Delete selected templates?'
'delete_confirm' => 'Delete selected templates?',
'order_by' =>'Order by'
],
'permissions' => [
'name' => 'CMS',

View File

@ -17,6 +17,8 @@ use Backend\Classes\WidgetBase;
*/
class TemplateList extends WidgetBase
{
const SORTING_FILENAME = 'fileName';
use \Backend\Traits\SelectableWidget;
protected $searchTerm = false;
@ -69,6 +71,12 @@ class TemplateList extends WidgetBase
*/
public $ignoreDirectories = [];
/**
* @var boolean Defines sorting properties.
* The sorting feature is disabled if there are no sorting properties defined.
*/
public $sortingProperties = [];
/*
* Public methods
*/
@ -137,6 +145,16 @@ class TemplateList extends WidgetBase
return $this->updateList();
}
public function onApplySorting()
{
$this->setSortingProperty(Input::get('sortProperty'));
$result = $this->updateList();
$result['#'.$this->getId('sorting-options')] = $this->makePartial('sorting-options');
return $result;
}
//
// Methods for the internal use
//
@ -156,9 +174,7 @@ class TemplateList extends WidgetBase
$items = array_map([$this, 'normalizeItem'], $items);
usort($items, function ($a, $b) {
return strcmp($a->fileName, $b->fileName);
});
$this->sortItems($items);
/*
* Apply the search
@ -217,6 +233,10 @@ class TemplateList extends WidgetBase
}
}
// Sort folders by name regardless of the
// selected sorting options.
ksort($foundGroups);
foreach ($foundGroups as $group) {
$result[] = $group;
}
@ -224,6 +244,15 @@ class TemplateList extends WidgetBase
return $result;
}
protected function sortItems(&$items)
{
$sortingProperty = $this->getSortingProperty();
usort($items, function ($a, $b) use ($sortingProperty) {
return strcmp($a->$sortingProperty, $b->$sortingProperty);
});
}
protected function removeIgnoredDirectories($items)
{
if (!$this->ignoreDirectories) {
@ -274,6 +303,10 @@ class TemplateList extends WidgetBase
'descriptions' => $descriptions
];
foreach ($this->sortingProperties as $property=>$name) {
$result[$property] = $item->$property;
}
return (object) $result;
}
@ -385,4 +418,20 @@ class TemplateList extends WidgetBase
$this->groupStatusCache = $statuses;
$this->putSession($this->getThemeSessionKey('groups'), $statuses);
}
protected function getSortingProperty()
{
$property = $this->getSession($this->getThemeSessionKey('sorting_property'), self::SORTING_FILENAME);
if (!array_key_exists($property, $this->sortingProperties)) {
return self::SORTING_FILENAME;
}
return $property;
}
protected function setSortingProperty($property)
{
$this->putSession($this->getThemeSessionKey('sorting_property'), $property);
}
}

View File

@ -0,0 +1,7 @@
<?php foreach ($this->sortingProperties as $propertyName=>$propertyTitle): ?>
<li role="presentation" <?php if ($this->getSortingProperty() == $propertyName): ?>class="active"<?php endif ?>>
<a role="menuitem" tabindex="-1" href="javascript:;" data-stripe-load-indicator data-request="<?= $this->getEventHandler('onApplySorting') ?>" data-request-data="sortProperty: '<?= e($propertyName) ?>'">
<?= e(trans($propertyTitle)) ?>
</a>
</li>
<?php endforeach ?>

View File

@ -4,16 +4,35 @@
<!-- Control Panel -->
<div class="toolbar-item" data-calculate-width>
<div class="btn-group">
<button type="button" class="btn btn-default oc-icon-plus last"
data-control="create-template"
><?= e(trans('cms::lang.sidebar.add')) ?></button>
<button type="button" class="btn btn-default empty oc-icon-trash-o hide"
id="<?= $this->getId('delete-button') ?>"
data-control="delete-template"
data-confirmation="<?= e(trans($this->deleteConfirmation)) ?>"
data-trigger-action="show"
data-trigger="<?= '#'.$this->getId('template-list') ?> input[type=checkbox]"
data-trigger-condition="checked"></button>
<button type="button" class="btn btn-default oc-icon-plus <?= !$this->sortingProperties ? 'last' : null ?>"
data-control="create-template"
><?= e(trans('cms::lang.sidebar.add')) ?></button>
<?php if ($this->sortingProperties): ?>
<div class="dropdown">
<button type="button" class="btn btn-default empty oc-icon-sort-alpha-desc"
data-toggle="dropdown"
></button>
<ul
class="dropdown-menu offset-left"
role="menu"
data-dropdown-title="<?= e(trans('cms::lang.template.order_by')) ?>"
id="<?= $this->getId('sorting-options') ?>"
>
<?= $this->makePartial('sorting-options') ?>
</ul>
</div>
<?php endif?>
<button type="button" class="btn btn-default empty oc-icon-trash-o hide"
id="<?= $this->getId('delete-button') ?>"
data-control="delete-template"
data-confirmation="<?= e(trans($this->deleteConfirmation)) ?>"
data-trigger-action="show"
data-trigger="<?= '#'.$this->getId('template-list') ?> input[type=checkbox]"
data-trigger-condition="checked"></button>
</div>
</div>

View File

@ -122,6 +122,10 @@
&.dropdown-title { display: none; }
&.divider { margin: 0; }
&.active > a {
font-weight: bold;
}
}
}
}

View File

@ -1360,6 +1360,7 @@ button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-ap
.dropdown-menu .dropdown-container > ul li.first-item a:active:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-bottom:8px solid #3498db}
.dropdown-menu .dropdown-container > ul li.dropdown-title{display:none}
.dropdown-menu .dropdown-container > ul li.divider{margin:0}
.dropdown-menu .dropdown-container > ul li.active > a{font-weight:bold}
.dropdown-menu.pull-right .dropdown-container > ul:after{left:auto;right:15px}
.dropdown-menu.pull-right .dropdown-container > ul:before{left:auto;right:14px}
.dropdown-menu.pull-right .dropdown-container > ul li.first-item a:hover:after,.dropdown-menu.pull-right .dropdown-container > ul li.first-item a:focus:after{left:auto;right:15px}