mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-11-06 13:25:46 +01:00
Merge branch 'release/1.8.2'
This commit is contained in:
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,3 +1,19 @@
|
|||||||
|
# v1.8.2
|
||||||
|
## 05/24/2018
|
||||||
|
|
||||||
|
1. [](#new)
|
||||||
|
* Added custom object support for filepicker field
|
||||||
|
* Don't allow saving of a user with no local account file
|
||||||
|
* Controls for `list` field were not in sync between top and bottom
|
||||||
|
1. [](#improved)
|
||||||
|
* More subtle `fieldset` styling
|
||||||
|
1. [](#bugfix)
|
||||||
|
* Check if `$object->blueprints()` exists in `onAdminAfterSave`
|
||||||
|
* When creating first user, check `admin.login` not `site.login`
|
||||||
|
* Fix admin login redirects for multisite setups
|
||||||
|
* Fixed issue with filepicker field where images wouldn't properly merge with the current value if in a page header
|
||||||
|
* Fixed media delete for streams
|
||||||
|
|
||||||
# v1.8.1
|
# v1.8.1
|
||||||
## 05/15/2018
|
## 05/15/2018
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ class AdminPlugin extends Plugin
|
|||||||
unset($this->grav['user']);
|
unset($this->grav['user']);
|
||||||
$this->grav['user'] = $user;
|
$this->grav['user'] = $user;
|
||||||
$user->authenticated = true;
|
$user->authenticated = true;
|
||||||
$user->authorized = $user->authorize('site.login');
|
$user->authorized = $user->authorize('admin.login');
|
||||||
|
|
||||||
$messages = $this->grav['messages'];
|
$messages = $this->grav['messages'];
|
||||||
$messages->add($this->grav['language']->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN'), 'info');
|
$messages->add($this->grav['language']->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN'), 'info');
|
||||||
@@ -456,7 +456,9 @@ class AdminPlugin extends Plugin
|
|||||||
$twig->twig_vars['location'] = $this->template;
|
$twig->twig_vars['location'] = $this->template;
|
||||||
$twig->twig_vars['base_url_relative_frontend'] = $twig->twig_vars['base_url_relative'] ?: '/';
|
$twig->twig_vars['base_url_relative_frontend'] = $twig->twig_vars['base_url_relative'] ?: '/';
|
||||||
$twig->twig_vars['admin_route'] = trim($this->admin_route, '/');
|
$twig->twig_vars['admin_route'] = trim($this->admin_route, '/');
|
||||||
|
$twig->twig_vars['current_route'] = '/' . $twig->twig_vars['admin_route'] . '/' . $this->template . '/' . $this->route;
|
||||||
$twig->twig_vars['base_url_relative'] = $twig->twig_vars['base_url_simple'] . '/' . $twig->twig_vars['admin_route'];
|
$twig->twig_vars['base_url_relative'] = $twig->twig_vars['base_url_simple'] . '/' . $twig->twig_vars['admin_route'];
|
||||||
|
$twig->twig_vars['current_url'] = rtrim($twig->twig_vars['base_url_relative'] . '/' . $this->template . '/' . $this->route, '/');
|
||||||
$theme_url = '/' . ltrim($this->grav['locator']->findResource('plugin://admin/themes/' . $this->theme,
|
$theme_url = '/' . ltrim($this->grav['locator']->findResource('plugin://admin/themes/' . $this->theme,
|
||||||
false), '/');
|
false), '/');
|
||||||
$twig->twig_vars['theme_url'] = $theme_url;
|
$twig->twig_vars['theme_url'] = $theme_url;
|
||||||
@@ -762,7 +764,8 @@ class AdminPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
// Special case to redirect after changing the admin route to avoid 'breaking'
|
// Special case to redirect after changing the admin route to avoid 'breaking'
|
||||||
$obj = $event['object'];
|
$obj = $event['object'];
|
||||||
if (null !== $obj) {
|
|
||||||
|
if (null !== $obj && method_exists($obj, 'blueprints')) {
|
||||||
$blueprint = $obj->blueprints()->getFilename();
|
$blueprint = $obj->blueprints()->getFilename();
|
||||||
|
|
||||||
if ($blueprint === 'admin/blueprints' && isset($obj->route) && $this->admin_route !== $obj->route) {
|
if ($blueprint === 'admin/blueprints' && isset($obj->route) && $this->admin_route !== $obj->route) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: Admin Panel
|
name: Admin Panel
|
||||||
version: 1.8.1
|
version: 1.8.2
|
||||||
description: Adds an advanced administration panel to manage your site
|
description: Adds an advanced administration panel to manage your site
|
||||||
icon: empire
|
icon: empire
|
||||||
author:
|
author:
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ class Admin
|
|||||||
|
|
||||||
$userKey = isset($credentials['username']) ? (string)$credentials['username'] : '';
|
$userKey = isset($credentials['username']) ? (string)$credentials['username'] : '';
|
||||||
$ipKey = Uri::ip();
|
$ipKey = Uri::ip();
|
||||||
$redirect = isset($post['redirect']) ? $post['redirect'] : $this->uri->route();
|
$redirect = $this->base . $this->route;
|
||||||
|
|
||||||
// Check if the current IP has been used in failed login attempts.
|
// Check if the current IP has been used in failed login attempts.
|
||||||
$attempts = count($rateLimiter->getAttempts($ipKey, 'ip'));
|
$attempts = count($rateLimiter->getAttempts($ipKey, 'ip'));
|
||||||
@@ -392,11 +392,9 @@ class Admin
|
|||||||
if ($user->authorized) {
|
if ($user->authorized) {
|
||||||
$event->defMessage('PLUGIN_ADMIN.LOGIN_LOGGED_IN', 'info');
|
$event->defMessage('PLUGIN_ADMIN.LOGIN_LOGGED_IN', 'info');
|
||||||
|
|
||||||
$event->defRedirect($redirect);
|
$event->defRedirect(isset($post['redirect']) ? $post['redirect'] : $redirect);
|
||||||
} else {
|
} else {
|
||||||
$this->session->redirect = $redirect;
|
$this->session->redirect = $redirect;
|
||||||
|
|
||||||
$event->defRedirect($this->uri->route());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ($user->authorized) {
|
if ($user->authorized) {
|
||||||
@@ -406,7 +404,7 @@ class Admin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$event->defRedirect($this->uri->route());
|
$event->defRedirect($redirect);
|
||||||
|
|
||||||
$message = $event->getMessage();
|
$message = $event->getMessage();
|
||||||
if ($message) {
|
if ($message) {
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
namespace Grav\Plugin\Admin;
|
namespace Grav\Plugin\Admin;
|
||||||
|
|
||||||
use Grav\Common\Config\Config;
|
use Grav\Common\Config\Config;
|
||||||
|
use Grav\Common\Data\Data;
|
||||||
use Grav\Common\Filesystem\Folder;
|
use Grav\Common\Filesystem\Folder;
|
||||||
use Grav\Common\Grav;
|
use Grav\Common\Grav;
|
||||||
|
use Grav\Common\Media\Interfaces\MediaInterface;
|
||||||
use Grav\Common\Page\Media;
|
use Grav\Common\Page\Media;
|
||||||
use Grav\Common\Utils;
|
use Grav\Common\Utils;
|
||||||
use Grav\Common\Plugin;
|
use Grav\Common\Plugin;
|
||||||
@@ -259,7 +261,7 @@ class AdminBaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle errors and breaks without proceeding further
|
// Handle errors and breaks without proceeding further
|
||||||
if ($upload->file->error != UPLOAD_ERR_OK) {
|
if ($upload->file->error !== UPLOAD_ERR_OK) {
|
||||||
$this->admin->json_response = [
|
$this->admin->json_response = [
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD', null),
|
'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD', null),
|
||||||
@@ -717,9 +719,9 @@ class AdminBaseController
|
|||||||
} else {
|
} else {
|
||||||
$new_data = $files;
|
$new_data = $files;
|
||||||
}
|
}
|
||||||
if (isset($data['header'][$init_key])) {
|
if ($obj->header()->{$init_key}) {
|
||||||
$obj->modifyHeader($init_key,
|
$obj->modifyHeader($init_key,
|
||||||
array_replace_recursive([], $data['header'][$init_key], $new_data));
|
array_replace_recursive([], $obj->header()->{$init_key}, $new_data));
|
||||||
} else {
|
} else {
|
||||||
$obj->modifyHeader($init_key, $new_data);
|
$obj->modifyHeader($init_key, $new_data);
|
||||||
}
|
}
|
||||||
@@ -743,8 +745,17 @@ class AdminBaseController
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->view === 'pages' ? $this->admin->page(true) : $this->prepareData([]);
|
$data = $this->view === 'pages' ? $this->admin->page(true) : $this->prepareData([]);
|
||||||
$settings = $data->blueprints()->schema()->getProperty($this->post['name']);
|
|
||||||
|
if (null === $data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($data instanceof Data) {
|
||||||
|
$settings = $data->blueprints()->schema()->getProperty($this->post['name']);
|
||||||
|
} elseif (method_exists($data, 'getBlueprint')) {
|
||||||
|
$settings = $data->getBlueprint()->schema()->getProperty($this->post['name']);
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($settings['folder'])) {
|
if (isset($settings['folder'])) {
|
||||||
$folder = $settings['folder'];
|
$folder = $settings['folder'];
|
||||||
@@ -754,19 +765,24 @@ class AdminBaseController
|
|||||||
|
|
||||||
// Do not use self@ outside of pages
|
// Do not use self@ outside of pages
|
||||||
if ($this->view !== 'pages' && in_array($folder, ['@self', 'self@', '@self@'])) {
|
if ($this->view !== 'pages' && in_array($folder, ['@self', 'self@', '@self@'])) {
|
||||||
$this->admin->json_response = [
|
if (!$data instanceof MediaInterface) {
|
||||||
'status' => 'error',
|
$this->admin->json_response = [
|
||||||
'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_PREVENT_SELF', null), $folder)
|
'status' => 'error',
|
||||||
];
|
'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_PREVENT_SELF', null), $folder)
|
||||||
|
];
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$media = $data->getMedia();
|
||||||
|
} else {
|
||||||
|
// Set destination
|
||||||
|
$folder = Folder::getRelativePath(rtrim($folder, '/'));
|
||||||
|
$folder = $this->admin->getPagePathFromToken($folder);
|
||||||
|
|
||||||
|
$media = new Media($folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set destination
|
|
||||||
$folder = Folder::getRelativePath(rtrim($folder, '/'));
|
|
||||||
$folder = $this->admin->getPagePathFromToken($folder);
|
|
||||||
|
|
||||||
$media = new Media($folder);
|
|
||||||
$available_files = [];
|
$available_files = [];
|
||||||
$metadata = [];
|
$metadata = [];
|
||||||
$thumbs = [];
|
$thumbs = [];
|
||||||
|
|||||||
@@ -613,12 +613,14 @@ class AdminController extends AdminBaseController
|
|||||||
|
|
||||||
// Special handler for user data.
|
// Special handler for user data.
|
||||||
if ($this->view === 'user') {
|
if ($this->view === 'user') {
|
||||||
|
if (!$this->grav['user']->exists()) {
|
||||||
|
$this->admin->setMessage($this->admin->translate('PLUGIN_ADMIN.NO_USER_EXISTS'),'error');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!$this->admin->authorize(['admin.super', 'admin.users'])) {
|
if (!$this->admin->authorize(['admin.super', 'admin.users'])) {
|
||||||
//not admin.super or admin.users
|
// no user file or not admin.super or admin.users
|
||||||
if ($this->prepareData($data)->username !== $this->grav['user']->username) {
|
if ($this->prepareData($data)->username !== $this->grav['user']->username) {
|
||||||
$this->admin->setMessage($this->admin->translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') . ' save.',
|
$this->admin->setMessage($this->admin->translate('PLUGIN_ADMIN.INSUFFICIENT_PERMISSIONS_FOR_TASK') . ' save.','error');
|
||||||
'error');
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1687,9 +1689,16 @@ class AdminController extends AdminBaseController
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var UniformResourceLocator $locator */
|
||||||
|
$locator = $this->grav['locator'];
|
||||||
|
$path = $media->path();
|
||||||
|
if ($locator->isStream($path)) {
|
||||||
|
$path = $locator->findResource($path, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Upload it
|
// Upload it
|
||||||
if (!move_uploaded_file($_FILES['file']['tmp_name'],
|
if (!move_uploaded_file($_FILES['file']['tmp_name'],
|
||||||
sprintf('%s/%s', $media->path(), $_FILES['file']['name']))
|
sprintf('%s/%s', $path, $_FILES['file']['name']))
|
||||||
) {
|
) {
|
||||||
$this->admin->json_response = [
|
$this->admin->json_response = [
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
@@ -1759,7 +1768,13 @@ class AdminController extends AdminBaseController
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var UniformResourceLocator $locator */
|
||||||
|
$locator = $this->grav['locator'];
|
||||||
|
|
||||||
$targetPath = $media->path() . '/' . $filename;
|
$targetPath = $media->path() . '/' . $filename;
|
||||||
|
if ($locator->isStream($targetPath)) {
|
||||||
|
$targetPath = $locator->findResource($targetPath, true, true);
|
||||||
|
}
|
||||||
$fileParts = pathinfo($filename);
|
$fileParts = pathinfo($filename);
|
||||||
|
|
||||||
$found = false;
|
$found = false;
|
||||||
|
|||||||
@@ -441,6 +441,7 @@ PLUGIN_ADMIN:
|
|||||||
PAGE_FILE: "Page Template"
|
PAGE_FILE: "Page Template"
|
||||||
PAGE_FILE_HELP: "Page template file name, and by default the display template for this page"
|
PAGE_FILE_HELP: "Page template file name, and by default the display template for this page"
|
||||||
NO_USER_ACCOUNTS: "No user accounts found, please create one first..."
|
NO_USER_ACCOUNTS: "No user accounts found, please create one first..."
|
||||||
|
NO_USER_EXISTS: "No local user exists for this account, cannot save..."
|
||||||
REDIRECT_TRAILING_SLASH: "Redirect trailing slash"
|
REDIRECT_TRAILING_SLASH: "Redirect trailing slash"
|
||||||
REDIRECT_TRAILING_SLASH_HELP: "Perform a 301 redirect rather than transparently handling trailing slash URIs."
|
REDIRECT_TRAILING_SLASH_HELP: "Perform a 301 redirect rather than transparently handling trailing slash URIs."
|
||||||
DEFAULT_DATE_FORMAT: "Page date format"
|
DEFAULT_DATE_FORMAT: "Page date format"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { config } from 'grav-config';
|
import { config, uri_params } from 'grav-config';
|
||||||
import request from '../../utils/request';
|
import request from '../../utils/request';
|
||||||
|
|
||||||
const insertTextAt = (string, index, text) => [string.slice(0, index), text, string.slice(index)].join('');
|
const insertTextAt = (string, index, text) => [string.slice(0, index), text, string.slice(index)].join('');
|
||||||
@@ -45,10 +45,11 @@ export default class FilePickerField {
|
|||||||
let parent = field.closest('[data-grav-filepicker]');
|
let parent = field.closest('[data-grav-filepicker]');
|
||||||
let name = parent.data('name');
|
let name = parent.data('name');
|
||||||
let value = parent.data('value');
|
let value = parent.data('value');
|
||||||
|
let params = JSON.stringify(uri_params || '{}');
|
||||||
|
|
||||||
request(url, {
|
request(url, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
body: { name }
|
body: { name, params }
|
||||||
}, (response) => {
|
}, (response) => {
|
||||||
if (typeof response.files === 'undefined') {
|
if (typeof response.files === 'undefined') {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ export default class FilesField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getURI() {
|
getURI() {
|
||||||
console.log(this.container.data('mediaUri'));
|
|
||||||
return this.container.data('mediaUri') || '';
|
return this.container.data('mediaUri') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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
@@ -909,16 +909,16 @@ form {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-fieldset {
|
.form-fieldset {
|
||||||
background-color: #f7f7f7;
|
background-color: darken($content-bg, 1%);
|
||||||
border: 2px solid #e1e1e1;
|
border: 1px solid $form-border;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-fieldset--label {
|
.form-fieldset--label {
|
||||||
background-color: #f3f3f3;
|
background-color: darken($content-bg, 4%);
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
.form-fieldset input:checked + & {
|
.form-fieldset input:checked + & {
|
||||||
background-color: #eee;
|
background-color: darken($content-bg, 6%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#admin-main {
|
#admin-main {
|
||||||
|
|||||||
@@ -604,7 +604,7 @@ textarea.frontmatter {
|
|||||||
letter-spacing: normal;
|
letter-spacing: normal;
|
||||||
}
|
}
|
||||||
.form-fieldset {
|
.form-fieldset {
|
||||||
margin: 1rem 2rem;
|
margin: 1rem 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-fieldset--label {
|
.form-fieldset--label {
|
||||||
|
|||||||
@@ -45,16 +45,18 @@
|
|||||||
{% if field.max is defined and not field.selectunique %}data-max="{{ field.max }}"{% endif %}
|
{% if field.max is defined and not field.selectunique %}data-max="{{ field.max }}"{% endif %}
|
||||||
>
|
>
|
||||||
{% if fieldControls in ['top', 'both'] %}
|
{% if fieldControls in ['top', 'both'] %}
|
||||||
<div class="collection-actions{{ not value|length ? ' hidden' : '' }}">
|
<div class="collection-actions">
|
||||||
<button class="button" type="button" data-action="expand_all"
|
{% if collapsible %}
|
||||||
{% 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="expand_all"
|
||||||
<button class="button" type="button" data-action="collapse_all"
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-chevron-circle-down"></i> {{ "PLUGIN_ADMIN.EXPAND_ALL"|e|tu }}</button>
|
||||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-chevron-circle-right"></i> {{ "PLUGIN_ADMIN.COLLAPSE_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>
|
||||||
|
{% endif %}
|
||||||
{% 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>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="button" type="button" data-action="add" data-action-add="top"
|
<button class="button" type="button" data-action="add" data-action-add="bottom"
|
||||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-plus"></i> {{ btnLabel|e|tu }}</button>
|
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-plus"></i> {{ btnLabel|e|tu }}</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{% if authorize(['admin.pages', 'admin.super']) %}
|
{% if authorize(['admin.pages', 'admin.super']) %}
|
||||||
<div id="latest">
|
<div id="latest">
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<a class="button" href="{{ uri.route(true) }}/pages"><i class="fa fa-fw fa-file-text-o"></i>{{ "PLUGIN_ADMIN.MANAGE_PAGES"|tu }}</a>
|
<a class="button" href="{{ base_url_relative }}/pages"><i class="fa fa-fw fa-file-text-o"></i>{{ "PLUGIN_ADMIN.MANAGE_PAGES"|tu }}</a>
|
||||||
</div>
|
</div>
|
||||||
<h1>{{ "PLUGIN_ADMIN.LATEST_PAGE_UPDATES"|tu }}</h1>
|
<h1>{{ "PLUGIN_ADMIN.LATEST_PAGE_UPDATES"|tu }}</h1>
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
{% block integration %}{% endblock %}
|
{% block integration %}{% endblock %}
|
||||||
|
|
||||||
{% set redirect = redirect ?: uri.route(false) %}
|
{% set redirect = redirect ?: '/' ~ admin_route ~ '/' ~ admin.route %}
|
||||||
|
|
||||||
<form method="post" action="{{ base_url_relative }}">
|
<form method="post" action="{{ base_url_relative }}">
|
||||||
<div class="padding">
|
<div class="padding">
|
||||||
|
|||||||
Reference in New Issue
Block a user