1
0
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:
Ryan Cramer
2017-03-08 11:43:58 -05:00
parent c4ea3c3356
commit bbb8e987c9
8 changed files with 198 additions and 22 deletions

View File

@@ -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");

View File

@@ -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 .= ' &hellip;';
}
if($numChildren) $label .= " <small>$numChildren</small>";
$label .= ' &nbsp; ';
$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;

View File

@@ -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;
}
}

View File

@@ -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;

View 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
}
}
}

View File

@@ -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,
);
}

View File

@@ -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);

File diff suppressed because one or more lines are too long