mirror of
https://github.com/processwire/processwire.git
synced 2025-08-13 10:15:28 +02:00
Add support for Pages > Tree navigation: drill down through the page tree within the top navigation dropdowns. This works in AdminThemeDefault and AdminThemeUikit but not in AdminThemeReno (which just shows the first level, per its nav setup).
This commit is contained in:
@@ -29,7 +29,7 @@ if($user->hasPermission('page-edit')) {
|
||||
$searchForm = '';
|
||||
}
|
||||
|
||||
$version = $adminTheme->version . 'j';
|
||||
$version = $adminTheme->version . 'k';
|
||||
|
||||
$config->styles->prepend($config->urls->root . "wire/templates-admin/styles/AdminTheme.css?v=$version");
|
||||
$config->styles->prepend($config->urls->adminTemplates . "styles/" . ($adminTheme->colors ? "main-$adminTheme->colors" : "main-classic") . ".css?v=$version");
|
||||
|
@@ -243,6 +243,15 @@ class ProcessPageList extends Process implements ConfigurableModule {
|
||||
"</div>$script";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate PageListRender classs
|
||||
*
|
||||
* @param Page $page
|
||||
* @param null|int $limit
|
||||
* @param null|int $start
|
||||
* @return ProcessPageListRender
|
||||
*
|
||||
*/
|
||||
protected function getPageListRender(Page $page, $limit = null, $start = null) {
|
||||
|
||||
require_once(dirname(__FILE__) . '/ProcessPageListRender.php');
|
||||
@@ -354,14 +363,105 @@ class ProcessPageList extends Process implements ConfigurableModule {
|
||||
/**
|
||||
* Output JSON list of navigation items for this module's bookmarks
|
||||
*
|
||||
* @param array $options
|
||||
* @return string|array
|
||||
*
|
||||
*/
|
||||
public function ___executeNavJSON(array $options = array()) {
|
||||
|
||||
$config = $this->wire('config');
|
||||
$urls = $this->wire('urls');
|
||||
|
||||
if($this->useBookmarks) {
|
||||
$bookmarks = $this->getPageBookmarks();
|
||||
$options['edit'] = $this->wire('config')->urls->admin . 'page/?id={id}';
|
||||
$options['edit'] = $urls->admin . 'page/?id={id}';
|
||||
$options = $bookmarks->initNavJSON($options);
|
||||
return parent::___executeNavJSON($options);
|
||||
}
|
||||
|
||||
$parentID = (int) $this->wire('input')->get('parent_id');
|
||||
if(!$parentID) $parentID = 1;
|
||||
$parent = $this->wire('pages')->get($parentID);
|
||||
$parentViewable = $parent->viewable(false);
|
||||
$renderer = $this->getPageListRender($parent);
|
||||
$items = $parentViewable ? $renderer->getChildren() : new PageArray();
|
||||
if($parentID === 1 && $parentViewable) $items->prepend($parent);
|
||||
$skipPageIDs = array($config->trashPageID, $config->adminRootPageID);
|
||||
$maxLabelLength = 40;
|
||||
|
||||
$data = array(
|
||||
'url' => $urls->admin . 'page/list/navJSON/',
|
||||
'label' => '',
|
||||
'icon' => 'sitemap',
|
||||
'list' => array(),
|
||||
);
|
||||
|
||||
$data = array_merge($options, $data);
|
||||
|
||||
foreach($items as $page) {
|
||||
|
||||
$id = $page->id;
|
||||
if(in_array($id, $skipPageIDs)) continue;
|
||||
$url = '';
|
||||
|
||||
if($page->editable()) {
|
||||
$url = $page->editUrl();
|
||||
} else if($page->viewable()) {
|
||||
$url = $page->url();
|
||||
} else if(!$page->listable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$numChildren = $id > 1 ? $page->numChildren : 0;
|
||||
$label = $renderer->getPageLabel($page, array('noTags' => true));
|
||||
if($page->isUnpublished()) $label = "<s>$label</s>";
|
||||
if(strlen($label) > $maxLabelLength) {
|
||||
$label = substr($label, 0, $maxLabelLength);
|
||||
$pos = strrpos($label, ' ');
|
||||
if($pos !== false) $label = substr($label, 0, $pos);
|
||||
$label .= ' …';
|
||||
}
|
||||
if($numChildren) $label .= " <small>$numChildren</small>";
|
||||
$label .= ' ';
|
||||
|
||||
$a = array(
|
||||
'url' => $url,
|
||||
'id' => $id,
|
||||
'label' => $label,
|
||||
'icon' => $page->getIcon(),
|
||||
);
|
||||
|
||||
if($page->id > 1 && $page->numChildren) {
|
||||
$a['navJSON'] = $data['url'] . "?parent_id=$page->id";
|
||||
}
|
||||
|
||||
$data['list'][] = $a;
|
||||
}
|
||||
|
||||
if($items->getTotal() > $items->count()) {
|
||||
$data['list'][] = array(
|
||||
'url' => $urls->admin . "page/?open=$parentID",
|
||||
'label' => $this->_('Show All') . ' ' .
|
||||
'<small>' . sprintf($this->_('(%d pages)'), $items->getTotal()) . '</small>',
|
||||
'icon' => 'arrow-circle-right',
|
||||
'className' => 'separator',
|
||||
);
|
||||
}
|
||||
|
||||
if($parent->addable()) {
|
||||
$data['list'][] = array(
|
||||
'url' => $urls->admin . "page/add/?parent_id=$parentID",
|
||||
'label' => __('Add New', '/wire/templates-admin/default.php'),
|
||||
'icon' => 'plus-circle',
|
||||
'className' => 'separator',
|
||||
);
|
||||
}
|
||||
|
||||
if($config->ajax) header("Content-Type: application/json");
|
||||
|
||||
return json_encode($data);
|
||||
}
|
||||
|
||||
public function ___executeOpen() {
|
||||
$id = (int) $this->wire('input')->urlSegment2;
|
||||
$this->wire('input')->get->open = $id;
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* Base class for Page List rendering
|
||||
*
|
||||
* @method array getPageActions(Page $page)
|
||||
* @method string getPageLabel(Page $page)
|
||||
* @method string getPageLabel(Page $page, array $options = array())
|
||||
*
|
||||
*/
|
||||
abstract class ProcessPageListRender extends Wire {
|
||||
@@ -90,13 +90,14 @@ abstract class ProcessPageListRender extends Wire {
|
||||
* Return the Page's label text, whether that originates from the Page's name, headline, title, etc.
|
||||
*
|
||||
* @param Page $page
|
||||
* @param array $options
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___getPageLabel(Page $page) {
|
||||
public function ___getPageLabel(Page $page, array $options = array()) {
|
||||
|
||||
$value = '';
|
||||
$icon = $page->getIcon();
|
||||
$icon = empty($options['noTags']) ? $page->getIcon() : '';
|
||||
|
||||
if(strpos($this->pageLabelField, '!') === 0) {
|
||||
// exclamation forces this one to be used, rather than template-specific one
|
||||
@@ -162,20 +163,22 @@ abstract class ProcessPageListRender extends Wire {
|
||||
|
||||
if(!strlen("$v")) continue;
|
||||
|
||||
$value .=
|
||||
"<span class='label_$field'>" .
|
||||
htmlspecialchars(strip_tags("$v"), ENT_QUOTES, "UTF-8", false) .
|
||||
"</span>";
|
||||
if(empty($options['noTags'])) $value .= "<span class='label_$field'>";
|
||||
$value .= htmlspecialchars(strip_tags("$v"), ENT_QUOTES, "UTF-8", false);
|
||||
if(empty($options['noTags'])) $value .= "</span>";
|
||||
}
|
||||
}
|
||||
|
||||
$icon = $page->getIcon();
|
||||
if($icon) {
|
||||
$icon = $this->wire('sanitizer')->name($icon);
|
||||
$icon = "<i class='icon fa fa-fw fa-$icon'></i>";
|
||||
}
|
||||
|
||||
if(!strlen($value)) $value = $page->get("title|name");
|
||||
if(!strlen($value)) $value = $this->wire('sanitizer')->entities($page->getUnformatted("title|name"));
|
||||
|
||||
if(!empty($options['noTags']) && strpos($value, '<') !== false) {
|
||||
$value = strip_tags($value);
|
||||
}
|
||||
|
||||
return $icon . trim($value);
|
||||
}
|
||||
@@ -195,5 +198,9 @@ abstract class ProcessPageListRender extends Wire {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getChildren() {
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,7 @@ class SystemUpdate14 extends SystemUpdate {
|
||||
$admin = $this->wire('pages')->get($this->wire('config')->adminRootPageID);
|
||||
$info = array(
|
||||
'ProcessPageEdit' => $admin->path . 'page/edit/',
|
||||
'ProcessPageList' => $admin->path . 'page/list/',
|
||||
// 'ProcessPageList' => $admin->path . 'page/list/',
|
||||
);
|
||||
|
||||
$numCompleted = 0;
|
||||
|
30
wire/modules/System/SystemUpdater/SystemUpdate16.php
Normal file
30
wire/modules/System/SystemUpdater/SystemUpdate16.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
/**
|
||||
* Re-enable the Pages > Tree navigation item
|
||||
*
|
||||
*/
|
||||
class SystemUpdate16 extends SystemUpdate {
|
||||
|
||||
public function execute() {
|
||||
$this->wire()->addHookAfter('ProcessWire::ready', $this, 'executeAtReady');
|
||||
return 0; // indicates we will update system version ourselves when ready
|
||||
}
|
||||
|
||||
public function executeAtReady() {
|
||||
|
||||
$admin = $this->wire('pages')->get($this->wire('config')->adminRootPageID);
|
||||
$page = $this->wire('pages')->get($admin->path . 'page/list/');
|
||||
|
||||
if(!$page->id) return;
|
||||
$page->of(false);
|
||||
$page->removeStatus(Page::statusHidden);
|
||||
try {
|
||||
$page->save();
|
||||
$this->updater->saveSystemVersion(16);
|
||||
} catch(\Exception $e) {
|
||||
// will try next time
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ class SystemUpdater extends WireData implements Module, ConfigurableModule {
|
||||
* This version number is important, as this updater keeps the systemVersion up with this version
|
||||
*
|
||||
*/
|
||||
'version' => 15,
|
||||
'version' => 16,
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -279,6 +279,11 @@ var ProcessWireAdmin = {
|
||||
$.getJSON(url, function(data) {
|
||||
$itemsIcon.removeClass('fa-spinner fa-spin').addClass('fa-angle-right');
|
||||
|
||||
if(!data.list) {
|
||||
console.log(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// now add new event to monitor menu positions
|
||||
if(!dropdownPositionsMonitored && data.list.length > 10) {
|
||||
dropdownPositionsMonitored = true;
|
||||
@@ -298,22 +303,56 @@ var ProcessWireAdmin = {
|
||||
);
|
||||
$ul.append($li);
|
||||
}
|
||||
|
||||
var numSubnavJSON = 0;
|
||||
|
||||
// populate the retrieved items
|
||||
$.each(data.list, function(n) {
|
||||
|
||||
var icon = '';
|
||||
if(this.icon) icon = "<i class='ui-priority-secondary fa fa-fw fa-" + this.icon + "'></i>";
|
||||
var url = '';
|
||||
|
||||
if(this.icon) {
|
||||
icon = "<i class='ui-priority-secondary fa fa-fw fa-" + this.icon + "'></i>";
|
||||
}
|
||||
|
||||
if(this.url == 'navJSON') {
|
||||
// click triggers another navJSON load
|
||||
} else {
|
||||
var url = this.url.indexOf('/') === 0 ? this.url : data.url + this.url;
|
||||
var $li = $("<li class='ui-menu-item'><a href='" + url + "'>" + icon + this.label + "</a></li>");
|
||||
}
|
||||
|
||||
var $li = $("<li class='ui-menu-item'></li>");
|
||||
var $a = $("<a href='" + url + "'>" + icon + this.label + "</a>");
|
||||
var $ulSub = null;
|
||||
|
||||
if(this.navJSON) {
|
||||
$a.attr('data-json', this.navJSON).addClass('pw-has-items pw-has-ajax-items');
|
||||
$ulSub = $("<ul></ul>").addClass('subnavJSON');
|
||||
var $icon = $("<i class='pw-has-items-icon fa fa-angle-right ui-priority-secondary'></i>");
|
||||
$a.prepend($icon);
|
||||
$li.prepend($a).append($ulSub);
|
||||
numSubnavJSON++;
|
||||
} else {
|
||||
$li.prepend($a);
|
||||
}
|
||||
|
||||
if(typeof this.className != "undefined" && this.className && this.className.length) {
|
||||
$li.addClass(this.className);
|
||||
}
|
||||
|
||||
$ul.append($li);
|
||||
});
|
||||
|
||||
|
||||
$ul.addClass('navJSON').addClass('length' + parseInt(data.list.length)).hide();
|
||||
if($ul.children().length) $ul.css('opacity', 1.0).fadeIn('fast');
|
||||
|
||||
if(numSubnavJSON) {
|
||||
var numParents = $ul.parents('ul').length;
|
||||
$ul.find('ul.subnavJSON').css('z-index', 200 + numParents);
|
||||
$ul.menu({});
|
||||
}
|
||||
|
||||
// trigger the first call
|
||||
hoverDropdownAjaxItem($a);
|
||||
|
||||
|
2
wire/templates-admin/scripts/main.min.js
vendored
2
wire/templates-admin/scripts/main.min.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user