mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-11-02 11:26:04 +01:00
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:
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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'])) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
2
themes/grav/css-compiled/preset.css
vendored
2
themes/grav/css-compiled/preset.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
themes/grav/css-compiled/template.css
vendored
2
themes/grav/css-compiled/template.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
themes/grav/js/admin.min.js
vendored
4
themes/grav/js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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 ~ ' • ' : "PLUGIN_ADMIN.PAGE"|tu ~ ' • ') ~
|
{% set description = (not p.page ? "PLUGIN_ADMIN.FOLDER"|tu ~ ' • ' : "PLUGIN_ADMIN.PAGE"|tu ~ ' • ') ~
|
||||||
@@ -65,12 +65,14 @@
|
|||||||
(p.routable ? "PLUGIN_ADMIN.ROUTABLE"|tu ~ ' • ' : "PLUGIN_ADMIN.NON_ROUTABLE"|tu ~ ' • ') ~
|
(p.routable ? "PLUGIN_ADMIN.ROUTABLE"|tu ~ ' • ' : "PLUGIN_ADMIN.NON_ROUTABLE"|tu ~ ' • ') ~
|
||||||
(p.visible ? "PLUGIN_ADMIN.VISIBLE"|tu ~ ' • ' : "PLUGIN_ADMIN.NON_VISIBLE"|tu ~ ' • ') ~
|
(p.visible ? "PLUGIN_ADMIN.VISIBLE"|tu ~ ' • ' : "PLUGIN_ADMIN.NON_VISIBLE"|tu ~ ' • ') ~
|
||||||
(p.published ? "PLUGIN_ADMIN.PUBLISHED"|tu ~ ' • ' : "PLUGIN_ADMIN.NON_PUBLISHED"|tu ~ ' • ') %}
|
(p.published ? "PLUGIN_ADMIN.PUBLISHED"|tu ~ ' • ' : "PLUGIN_ADMIN.NON_PUBLISHED"|tu ~ ' • ') %}
|
||||||
{% 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">
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user