mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-11-12 00:06:04 +01:00
Lists now features a new YAML option collapsed: [true|false] (default: false) and a new UI/UX that allows for collapsing / expanding collection items, allowing to better managing long lists of items. It is advised to always put as first field the most significant one, so that when a list is collapsed it can be still easily browsed.
Reworked List UI to better handle drag & drop sort. To sort it is now required to use the left drag handle (fixes #724)
This commit is contained in:
@@ -4,8 +4,10 @@
|
|||||||
1. [](#improved)
|
1. [](#improved)
|
||||||
* Get fresh media list for `Controller::getListMedia()` rather that cache so always latest.
|
* Get fresh media list for `Controller::getListMedia()` rather that cache so always latest.
|
||||||
* Add translation strings for the new system.force_ssl option
|
* Add translation strings for the new system.force_ssl option
|
||||||
|
* Reworked List UI to better handle drag & drop sort. To sort it is now required to use the left drag handle [#724](https://github.com/getgrav/grav-plugin-admin/issues/724)
|
||||||
* Lists now features a new YAML option `controls: [top|bottom|both]` (default: bottom) which will display the "Add Item" button at the Top and/or Bottom position relative to the list. When the Top button is pressed, a new item will be added at the beginning of the list, when the Bottom button is pressed, a new item will be appended to the list.
|
* Lists now features a new YAML option `controls: [top|bottom|both]` (default: bottom) which will display the "Add Item" button at the Top and/or Bottom position relative to the list. When the Top button is pressed, a new item will be added at the beginning of the list, when the Bottom button is pressed, a new item will be appended to the list.
|
||||||
* Lists now features two new YAML options `sortby: [field]` (default: disabled) and `sortby_dir: [asc|desc]` (default: asc) which will display a new Sorting button in the list allowing to automatically reindex the collection based on the given sort field set.
|
* Lists now features two new YAML options `sortby: [field]` (default: disabled) and `sortby_dir: [asc|desc]` (default: asc) which will display a new Sorting button in the list allowing to automatically reindex the collection based on the given sort field set.
|
||||||
|
* Lists now features a new YAML option `collapsed: [true|false]` (default: false) and a new UI/UX that allows for collapsing / expanding collection items, allowing to better managing long lists of items. It is advised to always put as first field the most significant one, so that when a list is collapsed it can be still easily browsed.
|
||||||
1. [](#bugfix)
|
1. [](#bugfix)
|
||||||
* Fixed issue in Admin favicon URL [#704](https://github.com/getgrav/grav-plugin-admin/issues/704)
|
* Fixed issue in Admin favicon URL [#704](https://github.com/getgrav/grav-plugin-admin/issues/704)
|
||||||
* Fixed issue in `selfupgrade` where the package would get downloaded in the wrong destination
|
* Fixed issue in `selfupgrade` where the package would get downloaded in the wrong destination
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ export default class CollectionsField {
|
|||||||
|
|
||||||
list.on('click', '> .collection-actions [data-action="add"]', (event) => this.addItem(event));
|
list.on('click', '> .collection-actions [data-action="add"]', (event) => this.addItem(event));
|
||||||
list.on('click', '> ul > li > .item-actions [data-action="delete"]', (event) => this.removeItem(event));
|
list.on('click', '> ul > li > .item-actions [data-action="delete"]', (event) => this.removeItem(event));
|
||||||
|
list.on('click', '> ul > li > .item-actions [data-action="collapse"]', (event) => this.collapseItem(event));
|
||||||
|
list.on('click', '> ul > li > .item-actions [data-action="expand"]', (event) => this.expandItem(event));
|
||||||
list.on('click', '> .collection-actions [data-action-sort="date"]', (event) => this.sortItems(event));
|
list.on('click', '> .collection-actions [data-action-sort="date"]', (event) => this.sortItems(event));
|
||||||
|
list.on('click', '> .collection-actions [data-action="collapse_all"]', (event) => this.collapseItems(event));
|
||||||
|
list.on('click', '> .collection-actions [data-action="expand_all"]', (event) => this.expandItems(event));
|
||||||
list.on('input', '[data-key-observe]', (event) => this.observeKey(event));
|
list.on('input', '[data-key-observe]', (event) => this.observeKey(event));
|
||||||
|
|
||||||
list.find('[data-collection-holder]').each((index, container) => {
|
list.find('[data-collection-holder]').each((index, container) => {
|
||||||
@@ -26,6 +30,7 @@ export default class CollectionsField {
|
|||||||
|
|
||||||
container.data('collection-sort', new Sortable(container.get(0), {
|
container.data('collection-sort', new Sortable(container.get(0), {
|
||||||
forceFallback: false,
|
forceFallback: false,
|
||||||
|
handle: '.collection-sort',
|
||||||
animation: 150,
|
animation: 150,
|
||||||
filter: '.CodeMirror, .grav-editor-resizer',
|
filter: '.CodeMirror, .grav-editor-resizer',
|
||||||
onUpdate: () => this.reindex(container)
|
onUpdate: () => this.reindex(container)
|
||||||
@@ -74,6 +79,36 @@ export default class CollectionsField {
|
|||||||
if (sortAction.length && items.length <= 1) { sortAction.addClass('hidden'); }
|
if (sortAction.length && items.length <= 1) { sortAction.addClass('hidden'); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collapseItems(event) {
|
||||||
|
let button = $(event.currentTarget);
|
||||||
|
let items = $(button.closest('[data-type="collection"]')).find('> ul > [data-collection-item] > .item-actions [data-action="collapse"]');
|
||||||
|
|
||||||
|
items.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
collapseItem(event) {
|
||||||
|
let button = $(event.currentTarget);
|
||||||
|
let item = button.closest('[data-collection-item]');
|
||||||
|
|
||||||
|
button.attr('data-action', 'expand').removeClass('fa-chevron-circle-down').addClass('fa-chevron-circle-right');
|
||||||
|
item.addClass('collection-collapsed');
|
||||||
|
}
|
||||||
|
|
||||||
|
expandItems(event) {
|
||||||
|
let button = $(event.currentTarget);
|
||||||
|
let items = $(button.closest('[data-type="collection"]')).find('> ul > [data-collection-item] > .item-actions [data-action="expand"]');
|
||||||
|
|
||||||
|
items.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
expandItem(event) {
|
||||||
|
let button = $(event.currentTarget);
|
||||||
|
let item = button.closest('[data-collection-item]');
|
||||||
|
|
||||||
|
button.attr('data-action', 'collapse').removeClass('fa-chevron-circle-right').addClass('fa-chevron-circle-down');
|
||||||
|
item.removeClass('collection-collapsed');
|
||||||
|
}
|
||||||
|
|
||||||
sortItems(event) {
|
sortItems(event) {
|
||||||
let button = $(event.currentTarget);
|
let button = $(event.currentTarget);
|
||||||
let sortby = button.data('action-sort');
|
let sortby = button.data('action-sort');
|
||||||
|
|||||||
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
28
themes/grav/js/admin.min.js
vendored
28
themes/grav/js/admin.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -702,6 +702,11 @@ form {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collection-sort {
|
||||||
|
background: #e9e9e9;
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-fieldset {
|
.form-fieldset {
|
||||||
|
|||||||
@@ -435,7 +435,6 @@ textarea.frontmatter {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
cursor: move;
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: $form-border-radius;
|
border-radius: $form-border-radius;
|
||||||
margin: 3px 0;
|
margin: 3px 0;
|
||||||
@@ -446,10 +445,15 @@ textarea.frontmatter {
|
|||||||
right: 10px;
|
right: 10px;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
|
|
||||||
.fa-trash-o {
|
.fa {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.collection-collapsed {
|
||||||
|
height: 70px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-collection-nosort] > li {
|
&[data-collection-nosort] > li {
|
||||||
@@ -460,6 +464,22 @@ textarea.frontmatter {
|
|||||||
.collection-actions {
|
.collection-actions {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collection-sort {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 32px;
|
||||||
|
bottom: 0;
|
||||||
|
cursor: move;
|
||||||
|
|
||||||
|
.fa {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-label.block {
|
.form-label.block {
|
||||||
|
|||||||
@@ -39,6 +39,10 @@
|
|||||||
<div class="form-list-wrapper {{ field.size }}" data-type="collection">
|
<div class="form-list-wrapper {{ field.size }}" data-type="collection">
|
||||||
{% if fieldControls in ['top', 'both'] %}
|
{% if fieldControls in ['top', 'both'] %}
|
||||||
<div class="collection-actions{{ not value|length ? ' hidden' : '' }}">
|
<div class="collection-actions{{ not value|length ? ' hidden' : '' }}">
|
||||||
|
<button class="button" type="button" data-action="expand_all"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-chevron-circle-down"></i> {{ "PLUGIN_ADMIN.EXPAND_ALL"|e|tu }}</button>
|
||||||
|
<button class="button" type="button" data-action="collapse_all"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-chevron-circle-right"></i> {{ "PLUGIN_ADMIN.COLLAPSE_ALL"|e|tu }}</button>
|
||||||
{% if field.sortby %}
|
{% if field.sortby %}
|
||||||
<button class="button{{ not value|length ? ' hidden' : '' }}" type="button" data-action="sort" data-action-sort="{{ field.sortby }}" data-action-sort-dir="{{ field.sortby_dir|default('asc') }}"
|
<button class="button{{ not value|length ? ' hidden' : '' }}" type="button" data-action="sort" data-action-sort="{{ field.sortby }}" data-action-sort-dir="{{ field.sortby_dir|default('asc') }}"
|
||||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-sort-amount-{{ field.sortby_dir|default('asc') }}"></i> {{ btnSortLabel|e|tu }} '{{ field.sortby }}'</button>
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-sort-amount-{{ field.sortby_dir|default('asc') }}"></i> {{ btnSortLabel|e|tu }} '{{ field.sortby }}'</button>
|
||||||
@@ -54,7 +58,8 @@
|
|||||||
{% if field.fields %}
|
{% if field.fields %}
|
||||||
{% for key, val in value %}
|
{% for key, val in value %}
|
||||||
{% set itemName = name ? name ~ '.' ~ key : key %}
|
{% set itemName = name ? name ~ '.' ~ key : key %}
|
||||||
<li data-collection-item="{{ itemName }}" data-collection-key="{{ key }}">
|
<li data-collection-item="{{ itemName }}" data-collection-key="{{ key }}" class="{{ field.collapsed ? 'collection-collapsed' : '' }}">
|
||||||
|
<div class="collection-sort"><i class="fa fa-fw fa-bars"></i></div>
|
||||||
{% for childName, child in field.fields %}
|
{% for childName, child in field.fields %}
|
||||||
{% if childName starts with '.' %}
|
{% if childName starts with '.' %}
|
||||||
{% set childKey = childName|trim('.') %}
|
{% set childKey = childName|trim('.') %}
|
||||||
@@ -84,7 +89,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="item-actions">
|
<div class="item-actions">
|
||||||
{% if field.sort is not same as(false) %}
|
{% if field.sort is not same as(false) %}
|
||||||
<i class="fa fa-bars"></i>
|
<i class="fa fa-chevron-circle-{{ field.collapsed ? 'right' : 'down' }}" data-action="{{ field.collapsed ? 'expand' : 'collapse' }}"></i>
|
||||||
<br />
|
<br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<i class="fa fa-trash-o" data-action="delete"></i>
|
<i class="fa fa-trash-o" data-action="delete"></i>
|
||||||
@@ -95,6 +100,10 @@
|
|||||||
</ul>
|
</ul>
|
||||||
{% if fieldControls in ['bottom', 'both'] %}
|
{% if fieldControls in ['bottom', 'both'] %}
|
||||||
<div class="collection-actions">
|
<div class="collection-actions">
|
||||||
|
<button class="button" type="button" data-action="expand_all"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-chevron-circle-down"></i> {{ "PLUGIN_ADMIN.EXPAND_ALL"|e|tu }}</button>
|
||||||
|
<button class="button" type="button" data-action="collapse_all"
|
||||||
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-chevron-circle-right"></i> {{ "PLUGIN_ADMIN.COLLAPSE_ALL"|e|tu }}</button>
|
||||||
{% if field.sortby %}
|
{% if field.sortby %}
|
||||||
<button class="button{{ not value|length ? ' hidden' : '' }}" type="button" data-action="sort" data-action-sort="{{ field.sortby }}" data-action-sort-dir="{{ field.sortby_dir|default('asc') }}"
|
<button class="button{{ not value|length ? ' hidden' : '' }}" type="button" data-action="sort" data-action-sort="{{ field.sortby }}" data-action-sort-dir="{{ field.sortby_dir|default('asc') }}"
|
||||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-sort-amount-{{ field.sortby_dir|default('asc') }}"></i> {{ btnSortLabel|e|tu }} '{{ field.sortby }}'</button>
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-sort-amount-{{ field.sortby_dir|default('asc') }}"></i> {{ btnSortLabel|e|tu }} '{{ field.sortby }}'</button>
|
||||||
@@ -107,6 +116,7 @@
|
|||||||
{%- set itemName = name ? name ~ '.*' : '*' -%}
|
{%- set itemName = name ? name ~ '.*' : '*' -%}
|
||||||
<div style="display: none;" data-collection-template="new" data-collection-template-html="{%- filter replace({' ': ' ', '\n': ' '})|e('html_attr') -%}
|
<div style="display: none;" data-collection-template="new" data-collection-template-html="{%- filter replace({' ': ' ', '\n': ' '})|e('html_attr') -%}
|
||||||
<li data-collection-item="{{ itemName }}">
|
<li data-collection-item="{{ itemName }}">
|
||||||
|
<div class="collection-sort"><i class="fa fa-fw fa-bars"></i></div>
|
||||||
{%- if field.fields -%}
|
{%- if field.fields -%}
|
||||||
{%- for childName, child in field.fields -%}
|
{%- for childName, child in field.fields -%}
|
||||||
{%- if childName starts with '.' -%}
|
{%- if childName starts with '.' -%}
|
||||||
@@ -134,7 +144,7 @@
|
|||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
<div class="item-actions">
|
<div class="item-actions">
|
||||||
{% if field.sort is not same as(false) %}
|
{% if field.sort is not same as(false) %}
|
||||||
<i class="fa fa-bars"></i>
|
<i class="fa fa-chevron-circle-down" data-action="collapse"></i>
|
||||||
<br />
|
<br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<i class="fa fa-trash-o" data-action="delete"></i>
|
<i class="fa fa-trash-o" data-action="delete"></i>
|
||||||
|
|||||||
Reference in New Issue
Block a user