Merge branch 'feature/ordering-refactor' into develop

# Conflicts:
#	themes/grav/css-compiled/preset.css
#	themes/grav/css-compiled/preset.css.map
This commit is contained in:
Andy Miller
2017-03-22 12:09:15 -06:00
15 changed files with 135 additions and 40 deletions

View File

@@ -2,6 +2,7 @@
## 03/xx/2017 ## 03/xx/2017
1. [](#new) 1. [](#new)
* Completely revamped Page Ordering. Will only reorder with folder-prefix enabled. Can now reorder all siblings.
* Improved `range` form field with touch and counter support [#1016](https://github.com/getgrav/grav-plugin-admin/pull/1016) * Improved `range` form field with touch and counter support [#1016](https://github.com/getgrav/grav-plugin-admin/pull/1016)
1. [](#bugfix) 1. [](#bugfix)
* Cleanup package files via GPM install to make them more windows-friendly [#1361](https://github.com/getgrav/grav/pull/1361) * Cleanup package files via GPM install to make them more windows-friendly [#1361](https://github.com/getgrav/grav/pull/1361)

View File

@@ -246,6 +246,18 @@ form:
title: Notifications title: Notifications
underline: true underline: true
notifications.feed:
type: toggle
label: Feed Notifications
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: Display feed-based notifications
notifications.dashboard: notifications.dashboard:
type: toggle type: toggle
label: Dashboard Notifications label: Dashboard Notifications

View File

@@ -496,9 +496,6 @@ class AdminController extends AdminBaseController
$obj = $obj->move($parent); $obj = $obj->move($parent);
$this->preparePage($obj, false, $obj->language()); $this->preparePage($obj, false, $obj->language());
// Reset slug and route. For now we do not support slug twig variable on save.
$obj->slug($original_slug);
try { try {
$obj->validate(); $obj->validate();
} catch (\Exception $e) { } catch (\Exception $e) {
@@ -514,6 +511,10 @@ class AdminController extends AdminBaseController
$obj->order($original_order + 1); $obj->order($original_order + 1);
} }
if (isset($data['order']) && !empty($data['order'])) {
$reorder = explode(',', $data['order']);
}
// add or remove numeric prefix based on ordering value // add or remove numeric prefix based on ordering value
if (isset($data['ordering'])) { if (isset($data['ordering'])) {
if ($data['ordering'] && !$obj->order()) { if ($data['ordering'] && !$obj->order()) {
@@ -1773,12 +1774,17 @@ class AdminController extends AdminBaseController
{ {
$input = (array)$this->data; $input = (array)$this->data;
if (isset($input['order'])) { // if (isset($input['folder']) && ) {
$order = max(0, // $order = $page->value('order');
((int)isset($input['order']) && $input['order']) ? $input['order'] : $page->value('order')); // $ordering = $order ? sprintf('%02d.', $order) : '';
// $slug = empty($input['folder']) ? $page->value('folder') : (string)$input['folder'];
// $page->folder($ordering . $slug);
// }
if ($input['folder'] != $page->value('folder')) {
$order = $page->value('order');
$ordering = $order ? sprintf('%02d.', $order) : ''; $ordering = $order ? sprintf('%02d.', $order) : '';
$slug = empty($input['folder']) ? $page->value('folder') : (string)$input['folder']; $page->folder($ordering . $input['folder']);
$page->folder($ordering . $slug);
} }
if (isset($input['name']) && !empty($input['name'])) { if (isset($input['name']) && !empty($input['name'])) {

View File

@@ -541,6 +541,7 @@ PLUGIN_ADMIN:
ORDERING_DISABLED_BECAUSE_PARENT_SETTING_ORDER: "Parent setting order, ordering disabled" ORDERING_DISABLED_BECAUSE_PARENT_SETTING_ORDER: "Parent setting order, ordering disabled"
ORDERING_DISABLED_BECAUSE_PAGE_NOT_VISIBLE: "Page is not visible, ordering disabled" ORDERING_DISABLED_BECAUSE_PAGE_NOT_VISIBLE: "Page is not visible, ordering disabled"
ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS: "Ordering via the admin is unsupported because there are more than 200 siblings" ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS: "Ordering via the admin is unsupported because there are more than 200 siblings"
ORDERING_DISABLED_BECAUSE_PAGE_NO_PREFIX: "Page ordering is disabled because <strong>Folder Numeric Prefix</strong> is not enabled"
CANNOT_ADD_MEDIA_FILES_PAGE_NOT_SAVED: "NOTE: You cannot add media files until you save the page. Just click 'Save' on top" CANNOT_ADD_MEDIA_FILES_PAGE_NOT_SAVED: "NOTE: You cannot add media files until you save the page. Just click 'Save' on top"
CANNOT_ADD_FILES_PAGE_NOT_SAVED: "NOTE: Page must be saved before you can upload files to it." CANNOT_ADD_FILES_PAGE_NOT_SAVED: "NOTE: Page must be saved before you can upload files to it."
DROP_FILES_HERE_TO_UPLOAD: "Drop your files here or <strong>click in this area</strong>" DROP_FILES_HERE_TO_UPLOAD: "Drop your files here or <strong>click in this area</strong>"
@@ -656,4 +657,4 @@ PLUGIN_ADMIN:
ZIP_PACKAGE_NOT_FOUND: "ZIP package could not be found" ZIP_PACKAGE_NOT_FOUND: "ZIP package could not be found"
GPM_OFFICIAL_ONLY: "Official GPM Only" GPM_OFFICIAL_ONLY: "Official GPM Only"
GPM_OFFICIAL_ONLY_HELP: "Only allow direct installs from the official GPM repository only." GPM_OFFICIAL_ONLY_HELP: "Only allow direct installs from the official GPM repository only."
NO_CHILD_TYPE: "No child type for this rawroute" NO_CHILD_TYPE: "No child type for this rawroute"

View File

@@ -3,18 +3,42 @@ import Sortable from 'sortablejs';
import PageFilters, { Instance as PageFiltersInstance } from './filter'; import PageFilters, { Instance as PageFiltersInstance } from './filter';
import './page'; import './page';
const pad = (n, s) => (`000${n}`).substr(-s);
// Pages Ordering // Pages Ordering
let Ordering = null; let Ordering = null;
let orderingElement = $('#ordering'); let orderingElement = $('#ordering');
if (orderingElement.length) { if (orderingElement.length) {
Ordering = new Sortable(orderingElement.get(0), { Ordering = new Sortable(orderingElement.get(0), {
filter: '.ignore', filter: '.ignore',
onUpdate: function(event) { onUpdate: function() {
/* Old single page index behavior
let item = $(event.item); let item = $(event.item);
let index = orderingElement.children().index(item) + 1; let index = orderingElement.children().index(item) + 1;
$('[data-order]').val(index); $('[data-order]').val(index);
*/
let indexes = [];
orderingElement.children().each((index, item) => {
item = $(item);
indexes.push(item.data('id'));
item.find('.page-order').text(`${pad(index + 1, 2)}.`);
});
$('[data-order]').val(indexes.join(','));
} }
}); });
$(document).on('input', '[name="data[folder]"]', (event) => {
const target = $(event.currentTarget);
const activeOrder = $('[data-id][data-active-id]');
activeOrder.data('id', target.val());
Ordering.options.onUpdate();
});
} }
export default { export default {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -796,10 +796,8 @@ form {
} }
.form-order-wrapper { .form-order-wrapper {
.note { ul.orderable {
background: inherit;
}
ul#ordering {
li { li {
border: 1px solid $form-border; border: 1px solid $form-border;
background: lighten($content-bg, 2%); background: lighten($content-bg, 2%);
@@ -809,6 +807,15 @@ form {
background: $form-field-bg; background: $form-field-bg;
color: $form-field-text; color: $form-field-text;
} }
&[data-active-id] {
border-color: $form-field-text;
}
}
&.disabled li {
opacity: 0.7;
} }
} }
} }

View File

@@ -434,7 +434,12 @@ textarea.frontmatter {
// Sortables // Sortables
.form-order-wrapper { .form-order-wrapper {
ul#ordering {
.notice {
padding: 5px;
}
ul.orderable {
list-style: none; list-style: none;
margin: 0; margin: 0;
@@ -455,6 +460,10 @@ textarea.frontmatter {
right: 10px; right: 10px;
} }
} }
i {
font-size: 0.8rem;
}
} }
} }
} }

View File

@@ -1,5 +1,6 @@
{% set value = (value is null ? field.default : value) %} {% set value = (value is null ? field.default : value) %}
{% set siblings = data.parent.children.visible %} {% set siblings = data.parent.children %}
{% set canOrder = data.order %}
<div class="form-field grid pure-g"> <div class="form-field grid pure-g">
<div class="form-label block size-1-3 pure-u-1-3"> <div class="form-label block size-1-3 pure-u-1-3">
@@ -14,25 +15,33 @@
</div> </div>
<div class="form-data block size-2-3 pure-u-2-3"> <div class="form-data block size-2-3 pure-u-2-3">
<div class="form-order-wrapper {{ field.size }}"> <div class="form-order-wrapper {{ field.size }}">
{% set canReorder = not data.parent.header.content.items and data.visible %}
<input <input
type="hidden" type="hidden"
data-order data-order
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %} {% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
name="{{ (scope ~ field.name)|fieldName }}" name="{{ (scope ~ field.name)|fieldName }}"
value="{{ canReorder ? value : '' }}" /> value="{{ canReorder ? value : '' }}" />
{% if data.parent.header.content.items %} {% if not canOrder %}
<span class="note">{{ "PLUGIN_ADMIN.ORDERING_DISABLED_BECAUSE_PARENT_SETTING_ORDER"|tu }}</span> <div class="notice">{{ "PLUGIN_ADMIN.ORDERING_DISABLED_BECAUSE_PAGE_NO_PREFIX"|tu|raw }}</div>
{% elseif not data.visible %}
<span class="note">{{ "PLUGIN_ADMIN.ORDERING_DISABLED_BECAUSE_PAGE_NOT_VISIBLE"|tu }}</span>
{% endif %} {% endif %}
{% if siblings|length < 200 %} {% if siblings|length < 200 %}
<ul id="ordering" class="{{ field.classes }}"> {% set sortable_count = 0 %}
{% for page in siblings %} <ul id="ordering" class="orderable {{ field.classes }}">
<li class="{% if page.order == value and canReorder %}drag-handle{% else %}ignore{% endif %}" data-id="{{ page.slug }}">{{ page.title|e }}</li> {% for page in siblings if page.order %}
<li class="drag-handle" data-id="{{ page.slug }}" {{ page.slug == data.slug ? 'data-active-id' : ''}}><span class="page-order">{{ page.order }}</span> {{ page.title|e }} <a href="{{ getPageUrl(page) }}"><i class="fa fa-external-link"></i></a></li>
{% set sortable_count = loop.index %}
{% endfor %} {% endfor %}
</ul> </ul>
{% if sortable_count < siblings|length %}
<label>Unsortable Pages</label>
<ul class="orderable disabled">
{% for page in siblings if not page.order %}
<li {{ page.slug == data.slug ? 'data-active-id' : ''}}>{{ page.title|e }} <a href="{{ getPageUrl(page) }}"><i class="fa fa-external-link"></i></a></li>
{% endfor %}
</ul>
{% endif %}
{% else %} {% else %}
<span class="note">{{ "PLUGIN_ADMIN.ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS"|tu }}</span> <span class="note">{{ "PLUGIN_ADMIN.ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS"|tu }}</span>
{% endif %} {% endif %}

View File

@@ -53,11 +53,11 @@
{% set warn = twig_vars['warn'] %} {% set warn = twig_vars['warn'] %}
{% set uri = twig_vars['uri'] %} {% set uri = twig_vars['uri'] %}
{% if '@self' in page.header.content.items and page.header.content.order.by %} {#{% if '@self' in page.header.content.items and page.header.content.order.by %}#}
{% set pcol = page.children().order(page.header.content.order.by, page.header.content.order.dir) %} {#{% set pcol = page.children().order(page.header.content.order.by, page.header.content.order.dir) %}#}
{% else %} {#{% else %}#}
{% set pcol = page.children() %} {% set pcol = page.children() %}
{% endif %} {#{% endif %}#}
{% for p in pcol %} {% for p in pcol %}
{% set description = (not p.page ? "PLUGIN_ADMIN.FOLDER"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.PAGE"|tu ~ ' &bull; ') ~ {% set description = (not p.page ? "PLUGIN_ADMIN.FOLDER"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.PAGE"|tu ~ ' &bull; ') ~
@@ -65,12 +65,14 @@
(p.routable ? "PLUGIN_ADMIN.ROUTABLE"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.NON_ROUTABLE"|tu ~ ' &bull; ') ~ (p.routable ? "PLUGIN_ADMIN.ROUTABLE"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.NON_ROUTABLE"|tu ~ ' &bull; ') ~
(p.visible ? "PLUGIN_ADMIN.VISIBLE"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.NON_VISIBLE"|tu ~ ' &bull; ') ~ (p.visible ? "PLUGIN_ADMIN.VISIBLE"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.NON_VISIBLE"|tu ~ ' &bull; ') ~
(p.published ? "PLUGIN_ADMIN.PUBLISHED"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.NON_PUBLISHED"|tu ~ ' &bull; ') %} (p.published ? "PLUGIN_ADMIN.PUBLISHED"|tu ~ ' &bull; ' : "PLUGIN_ADMIN.NON_PUBLISHED"|tu ~ ' &bull; ') %}
{% set page_route = p.rawRoute|trim('/') %} {#{% set page_route = p.rawRoute|trim('/') %}#}
{% if p.language and p.language != admin_lang %} {#{% if p.language and p.language != admin_lang %}#}
{% set page_url = base_url_simple ~ '/' ~ p.language ~ '/' ~ admin_route ~ '/pages/' ~ page_route %} {#{% set page_url = base_url_simple ~ '/' ~ p.language ~ '/' ~ admin_route ~ '/pages/' ~ page_route %}#}
{% else %} {#{% else %}#}
{% set page_url = base_url ~ '/pages/' ~ page_route %} {#{% set page_url = base_url ~ '/pages/' ~ page_route %}#}
{% endif %} {#{% endif %}#}
{% set page_url = getPageUrl(p) %}
<li class="page-item" data-nav-id="{{ p.route }}"> <li class="page-item" data-nav-id="{{ p.route }}">
<div class="row"> <div class="row">

View File

@@ -45,6 +45,30 @@ class AdminTwigExtension extends \Twig_Extension
]; ];
} }
public function getFunctions()
{
return [
new \Twig_SimpleFunction('getPageUrl', [$this, 'getPageUrl'], ['needs_context' => true]),
];
}
public function getPageUrl($context, $page)
{
$page_route = trim($page->rawRoute(), '/');
$page_lang = $page->language();
$base_url = $context['base_url'];
$base_url_simple = $context['base_url_simple'];
$admin_lang = Grav::instance()['session']->admin_lang ?: 'en';
if ($page_lang && $page_lang != $admin_lang) {
$page_url = $base_url_simple . '/' . $page_lang . '/' . $context['admin_route'] . '/pages/' . $page_route;
} else {
$page_url = $base_url . '/pages/' . $page_route;
}
return $page_url;
}
public function tuFilter() public function tuFilter()
{ {
$args = func_get_args(); $args = func_get_args();