This commit is contained in:
Loïc Guibert
2022-09-30 20:02:02 +01:00
commit 66dafc36c3
2561 changed files with 454489 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
{% set slug = uri.param('slug') %}
{% set changelog = admin.getChangelog(slug) %}
<section id="ajax" class="changelog">
<a href="#" class="remodal-close"></a>
{% if changelog %}
<h1>{{title}} Changelog</h1>
<div class="changelog-overflow">
{% for version, log in changelog %}
<h3 id="{{ version | replace({" ": '-'}) }}">v{{ version }}</h3>
<h4 title="{{ log.date|date('F jS \\a\\t g:ia') }}">{{ log.date|nicetime }}</h4>
{{ log.content|markdown|raw }}
{% endfor %}
</div>
{% endif %}
</section>

View File

@@ -0,0 +1,82 @@
{% extends 'partials/base.html.twig' %}
{% set configurations = admin.configurations(true) %}
{% set config_slug = admin.route %}
{% if not config_slug %}
{% set config_slug = configurations|first %}
{% do admin.redirect('config/' ~ config_slug, 302) %}
{% endif %}
{% set isInfo = (config_slug == 'info') %}
{% set tab_title_string = "PLUGIN_ADMIN." ~ config_slug|upper %}
{% set tab_title = (tab_title_string|t == tab_title_string ? config_slug|capitalize : tab_title_string|t) ?: 'Not Found' %}
{% set title = "PLUGIN_ADMIN.CONFIGURATION"|t ~ ": " ~ tab_title %}
{% if config_slug and not isInfo %}
{% set data = admin.data('config/' ~ config_slug) %}
{% endif %}
{% block stylesheets %}
{% do assets.addCss(theme_url ~ '/css/codemirror/codemirror.css') %}
{{ parent() }}
{% endblock %}
{% block javascripts %}
{{ parent() }}
{% endblock %}
{% block titlebar %}
<div class="button-bar">
<a class="button" href="{{ admin_route('/') }}"><i class="fa fa-reply"></i> {{ "PLUGIN_ADMIN.BACK"|t }}</a>
{% if data.file.filename %}
<button class="button" type="submit" name="task" value="save" form="blueprints"><i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|t }}</button>
{% endif %}
</div>
<h1><i class="fa fa-fw fa-wrench"></i> {{ "PLUGIN_ADMIN.CONFIGURATION"|t }} - {{ tab_title }}</h1>
{% endblock %}
{% block content_top %}
{% if authorize('admin.super') and data.file.filename %}
<div class="alert notice">{{ "PLUGIN_ADMIN.SAVE_LOCATION"|t }}: <b>{{ data.file.filename|replace({(base_path):''}) }}</b></div>
{% endif %}
<div class="form-tabs">
<div class="tabs-nav">
{% for configuration in configurations %}
<a {% if config_slug == configuration %}class="active"{% endif %} href="{{ admin_route('/config/' ~ configuration) }}">
{% set configuration_string = "PLUGIN_ADMIN." ~ configuration|upper %}
<span>{{ (configuration_string|t == configuration_string ? configuration|capitalize : configuration_string|t) }}</span>
</a>
{% endfor %}
</div>
</div>
{% endblock %}
{% block content %}
{% set accessChangelog = authorize(['admin.maintenance', 'admin.super']) %}
{% if config_slug in configurations %}
{% if isInfo %}
<div id="phpinfo">
{% if accessChangelog %}
<div style="margin-left:1.5rem">
<a class="button button-big" href="#" style="text-align: center;" data-remodal-target="changelog" data-remodal-changelog="{{ admin_route('/changelog/type:plugins/slug:' ~ plugin.slug) }}"><i class="fa fa-binoculars"></i> View Grav Changelog</a>
</div>
{% endif %}
{{ admin.phpinfo|raw }}
</div>
{% else %}
<div class="config-wrapper-{{ config_slug }}">
{% include 'partials/blueprints.html.twig' with { blueprints: data.blueprints, data: data } %}
</div>
{% endif %}
{% include 'partials/modal-changes-detected.html.twig' %}
{% if accessChangelog %}
{% include 'partials/modal-changelog.html.twig' %}
{% endif %}
{% else %}
{% do page.modifyHeader('http_response_code', 404) %}
<div class="config-wrapper">
<h2>Not found</h2>
</div>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,73 @@
{% extends 'partials/base.html.twig' %}
{% set title = "PLUGIN_ADMIN.DASHBOARD"|t %}
{% set clear_cache_url = base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache'|e('html_attr') %}
{% block titlebar %}
<div class="button-bar">
{% if authorize(['admin.maintenance', 'admin.super', 'admin.cache']) %}
<div class="button-group">
<button data-clear-cache-type="" data-clear-cache="{{ uri.addNonce(clear_cache_url, 'admin-form', 'admin-nonce') }}" class="button"><i class="fa fa-retweet"></i> {{ "PLUGIN_ADMIN.CLEAR_CACHE"|t }}</button>
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu">
<li><a data-clear-cache-type="all" data-clear-cache="{{ uri.addNonce(clear_cache_url ~'/cleartype' ~ config.system.param_sep ~ 'all', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_ALL_CACHE"|t }}</a></li>
<li><a data-clear-cache-type="assets-only" data-clear-cache="{{ uri.addNonce(clear_cache_url ~'/cleartype' ~ config.system.param_sep ~ 'assets-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_ASSETS_ONLY"|t }}</a></li>
<li><a data-clear-cache-type="images-only" data-clear-cache="{{ uri.addNonce(clear_cache_url ~'/cleartype' ~ config.system.param_sep ~ 'images-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_IMAGES_ONLY"|t }}</a></li>
<li><a data-clear-cache-type="cache-only" data-clear-cache="{{ uri.addNonce(clear_cache_url ~'/cleartype' ~ config.system.param_sep ~ 'cache-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_CACHE_ONLY"|t }}</a></li>
<li><a data-clear-cache-type="tmp-only" data-clear-cache="{{ uri.addNonce(clear_cache_url ~'/cleartype' ~ config.system.param_sep ~ 'tmp-only', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CLEAR_CACHE_TMP_ONLY"|t }}</a></li>
<li><a data-clear-cache-type="purge" data-clear-cache="{{ uri.addNonce(clear_cache_url ~'/cleartype' ~ config.system.param_sep ~ 'purge', 'admin-form', 'admin-nonce') }}" href="#">{{ "PLUGIN_ADMIN.CACHE_PURGE"|t }}</a></li>
</ul>
</div>
{% endif %}
{% if authorize(['admin.maintenance', 'admin.super']) %}
<button data-gpm-checkupdates="" class="button"><i class="fa fa-refresh"></i> {{ "PLUGIN_ADMIN.CHECK_FOR_UPDATES"|t }}</button>
{% endif %}
</div>
<h1><i class="fa fa-fw fa-th"></i> {{ "PLUGIN_ADMIN.DASHBOARD"|t }}</h1>
{% endblock %}
{% block widgets %}
{% if config.plugins.admin.notifications.dashboard %}
<div class="dashboard-notifications-container"></div>
{% endif %}
{# System notifications, cannot be turned off #}
{% include 'partials/dashboard-problems.html.twig' %}
<div id="admin-dashboard">
{% if grav.twig.plugins_hooked_dashboard_widgets_top %}
{% for widget in grav.twig.plugins_hooked_dashboard_widgets_top %}
{% if attribute(config.plugins.admin.widgets_display, widget.template)|string in ['1', 'true'] %}
<div class="dashboard-item-flex">
{% include 'partials/' ~ widget.template ~ '.html.twig' %}
</div>
{% endif %}
{% endfor %}
{% endif %}
</div>
{% endblock %}
{% block content %}
{%- if grav.twig.plugins_hooked_dashboard_widgets_main -%}
{%- for widget in grav.twig.plugins_hooked_dashboard_widgets_main -%}
{% if attribute(config.plugins.admin.widgets_display, widget.template)|string in ['1', 'true'] %}
{% include 'partials/' ~ widget.template ~ '.html.twig' %}
{% endif -%}
{%- endfor -%}
{%- endif -%}
{% endblock %}
{% block content_bottom %}
<div id="admin-dashboard">
{%- if grav.twig.plugins_hooked_dashboard_widgets_bottom -%}
{%- for widget in grav.twig.plugins_hooked_dashboard_widgets_bottom -%}
{% if attribute(config.plugins.admin.widgets_display, widget.template)|string in ['1', 'true'] %}
{% include 'partials/' ~ widget.template ~ '.html.twig' %}
{% endif -%}
{%- endfor -%}
{%- endif -%}
</div>
{% endblock %}

View File

@@ -0,0 +1,5 @@
{% if admin.json_response %}
{{ admin.json_response|json_encode|raw }}
{% else %}
{}
{% endif %}

View File

@@ -0,0 +1,18 @@
{% extends 'partials/base.html.twig' %}
{% block messages %}{% endblock %}
{% block content %}
<div class="admin-block">
<h1>
{{ "PLUGIN_ADMIN.ACCESS_DENIED"|t }}
</h1>
{% include 'partials/messages.html.twig' %}
<p>{{ admin.user.fullname }}, {{ "PLUGIN_ADMIN.ACCOUNT_NOT_ADMIN"|t }}. <a href="{{ uri.addNonce(base_url_relative ~ '/task' ~ config.system.param_sep ~ 'logout', 'logout-form', 'logout-nonce') }}">{{ "PLUGIN_ADMIN.LOGOUT"|t }}</a></p>
</div>
{% endblock %}
{% block navigation %}
{% endblock %}

View File

@@ -0,0 +1,194 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Really Simple HTML Email Template</title>
<style>
/* -------------------------------------
GLOBAL
------------------------------------- */
* {
margin: 0;
padding: 0;
font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
font-size: 100%;
line-height: 1.6;
}
img {
max-width: 100%;
}
body {
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: none;
width: 100%!important;
height: 100%;
}
/* -------------------------------------
ELEMENTS
------------------------------------- */
a {
color: #348eda;
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #348eda;
border: solid #348eda;
border-width: 10px 20px;
line-height: 2;
font-weight: bold;
margin-right: 10px;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 25px;
}
.btn-secondary {
text-decoration: none;
color: #FFF;
background-color: #aaa;
border: solid #aaa;
border-width: 10px 20px;
line-height: 2;
font-weight: bold;
margin-right: 10px;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 25px;
}
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.padding {
padding: 10px 0;
}
/* -------------------------------------
BODY
------------------------------------- */
table.body-wrap {
width: 100%;
padding: 20px;
}
table.body-wrap .container {
border: 1px solid #f0f0f0;
}
/* -------------------------------------
FOOTER
------------------------------------- */
table.footer-wrap {
width: 100%;
clear: both!important;
}
.footer-wrap .container p {
font-size: 12px;
color: #666;
}
table.footer-wrap a {
color: #999;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1, h2, h3 {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
color: #000;
margin: 40px 0 10px;
line-height: 1.2;
font-weight: 200;
}
h1 {
font-size: 36px;
}
h2 {
font-size: 28px;
}
h3 {
font-size: 22px;
}
p, ul, ol {
margin-bottom: 10px;
font-weight: normal;
font-size: 14px;
}
ul li, ol li {
margin-left: 5px;
list-style-position: inside;
}
/* ---------------------------------------------------
RESPONSIVENESS
Nuke it from orbit. It's the only way to be sure.
------------------------------------------------------ */
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block!important;
max-width: 600px!important;
margin: 0 auto!important; /* makes it centered */
clear: both!important;
}
/* Set the padding on the td rather than the div for Outlook compatibility */
.body-wrap .container {
padding: 20px;
}
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
max-width: 600px;
margin: 0 auto;
display: block;
}
/* Let's make sure tables in the content area are 100% wide */
.content table {
width: 100%;
}
</style>
</head>
<body bgcolor="#f6f6f6">
<!-- body -->
<table class="body-wrap" bgcolor="#f6f6f6">
<tr>
<td></td>
<td class="container" bgcolor="#FFFFFF">
<div class="content">
<table>
<tr>
<td>
{{ content|raw }}
</td>
</tr>
</table>
</div>
</td>
<td></td>
</tr>
</table>
<!-- /body -->
<!-- footer -->
<table class="footer-wrap">
<tr>
<td></td>
<td class="container">
<div class="content">
<table>
<tr>
<td align="center">
{{ 'PLUGIN_ADMIN.EMAIL_FOOTER'|t|raw }}
</td>
</tr>
</table>
</div>
</td>
<td></td>
</tr>
</table>
<!-- /footer -->
</body>
</html>

View File

@@ -0,0 +1,20 @@
{% extends 'partials/base.html.twig' %}
{% block titlebar %}
<h1><i class="fa fa-fw fa-exclamation-triangle"></i> {{ "PLUGIN_ADMIN.ERROR"|t }}</h1>
{% endblock %}
{% block content %}
<div class="error-block">
<h1>Error {{ page.header.http_response_code }}</h1>
<div class="padding">
<p>
{{ page.content|raw }}
</p>
</div>
</div>
{% endblock %}
{% block footer_section %}
<br /><br /><br />
{% endblock %}

View File

@@ -0,0 +1 @@
{{ content|json_encode|raw }}

View File

@@ -0,0 +1,14 @@
{% embed 'partials/login.html.twig' with {title:'Grav Forgot Password'} %}
{% block form %}
{% embed 'forms/default/fields.html.twig' with {name: null, fields: form.fields} %}
{% block inner_markup_field_open %}<div>{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
<div class="form-actions primary-accent">
<button type="submit" class="button primary" name="task" value="forgot"><i class="fa fa-paper-plane"></i> {{ "PLUGIN_ADMIN.LOGIN_BTN_SEND_INSTRUCTIONS"|t }}</button>
</div>
{% endblock %}
{% endembed %}

View File

@@ -0,0 +1,130 @@
{% if not field.validate.ignore %}
{% if not blueprints or (blueprints.schema.type(field.type)['input@'] ?? true) is same as(true) %}
{% set default = field.default %}
{% set toggleable = field.toggleable ?? false %}
{% if toggleable %}
{% set originalValue = originalValue ?? value %}
{% set toggleableChecked = originalValue is not null %}
{% endif %}
{% set has_value = value is not null %}
{% if not has_value %}
{% set value = default %}
{% endif %}
{% if (field.yaml or field.validate.type == 'yaml') and value is iterable %}
{% set value = value|toYaml %}
{% endif %}
{% else %}
{% set toggleable = false %}
{% endif %}
{% set vertical = field.style == 'vertical' %}
{% set field_name = (scope ~ field.name)|fieldName %}
{% set show_label = field.label is not same as(false) and field.display_label is not same as(false) %}
{# DEPRECATED: Needed by old form fields; remove when backwards compatibility breaks are allowed #}
{% set isDisabledToggleable = toggleable and not toggleableChecked %}
{% block field %}
<div class="form-field grid{% if vertical %} vertical{% endif %}{% if toggleable %} form-field-toggleable{% endif %} {{ field.outerclasses }} {{ field.field_classes }}">
{% block contents %}
{% if show_label %}
<div class="form-label{% if not vertical %} block size-1-3{% endif %}">
{% if toggleable %}
<span class="checkboxes toggleable" data-grav-field="toggleable" data-grav-field-name="{{ field_name }}">
<input type="checkbox"
id="toggleable_{{ field.name }}"
{% if toggleableChecked %}value="1"{% endif %}
name="toggleable_{{ field_name }}"
{% if toggleableChecked %}checked="checked"{% endif %}
>
<label for="toggleable_{{ field.name }}"></label>
</span>
{% endif %}
<label{{ (toggleable ? ' class="toggleable" for="toggleable_' ~ field.name ~ '"')|raw }}>
{% block label %}
{% if field.help %}
{% if field.markdown %}
<span class="hint--bottom" data-hint="{{ field.help|t|markdown(false) }}">{{ field.label|t|markdown(false)|raw }}</span>
{% else %}
<span class="hint--bottom" data-hint="{{ field.help|t }}">{{ field.label|t|raw }} <i class="hint-icon fa fa-question-circle" aria-hidden="true"></i></span>
{% endif %}
{% else %}
{% if field.markdown %}
{{ field.label|t|markdown(false)|raw }}
{% else %}
{{ field.label|t|raw }}
{% endif %}
{% endif %}
{{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
{% endblock %}
</label>
{% if field.sublabel %}
<div class="form-sublabel">
{% if field.markdown %}
{{ field.sublabel|t|markdown(false)|raw }}
{% else %}
{{ field.sublabel|t|raw }}
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
<div class="form-data{% if not vertical %} block size-2-3{% endif %}"
{% block global_attributes %}
data-grav-field="{{ field.type }}"
data-grav-disabled="{{ toggleableChecked }}"
data-grav-default="{{ field.default|json_encode|e('html_attr') }}"
{% endblock %}
>
{% block group %}
{% block input %}
<div class="form-input-wrapper {{ field.size }} {{ field.wrapper_classes }}">
{% block prepend %}{% endblock prepend %}
{% set input_value = value is iterable ? value|join(',') : value|string %}
<input
{# required attribute structures #}
name="{{ field_name }}"
value="{{ input_value }}"
{% if field.key %}
data-key-observe="{{ (scope ~ field_name)|fieldName }}"
{% endif %}
{# input attribute structures #}
{% block input_attributes %}
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
{% if field.id is defined %}id="{{ field.id }}" {% endif %}
{% if field.style is defined %}style="{{ field.style }}" {% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder|t }}"{% endif %}
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.autocomplete is defined %}autocomplete="{{ field.autocomplete }}"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% if field.validate.pattern %}pattern="{{ field.validate.pattern }}"{% endif %}
{% if field.validate.message %}title="{{ field.validate.message|t }}"
{% elseif field.title is defined %}title="{{ field.title|t }}" {% endif %}
{% endblock %}
/>
{% block append %}{% endblock append %}
</div>
{% endblock %}
{% endblock %}
{% if field.description %}
<div class="form-extra-wrapper {{ field.wrapper_classes }}">
<span class="form-description">
{% if field.markdown %}
{{ field.description|t|markdown(false)|raw }}
{% else %}
{{ field.description|t|raw }}
{% endif %}
</span>
</div>
{% endif %}
</div>
{% endblock %}
</div>
{% endblock %}
{% endif %}

View File

@@ -0,0 +1,134 @@
{% extends "forms/field.html.twig" %}
{% block input %}
{% set permissions = grav.permissions %}
{% set classes = { '': 'status-unchecked', 1: 'status-checked', 0: 'status-indeterminate' } %}
{% set states = { '': 0, 1: 1, 0: 2 } %}
{% if field.data_type == 'access' %}
{% set groupsList = [] %}
{% for action in permissions %}
{% if (action.visible ?? true) %}
{% set groupsList = groupsList|merge([{ label: action.label|t, value: action.name }]) %}
{% endif %}
{% endfor %}
{% set optionsList = [] %}
{% for action in permissions.instances %}
{% if (action.visible ?? true) %}
{% set label = (action.params.letter ? action.parent.label|t ~ ' > ') ~ action.label|t %}
{% set optionsList = optionsList|merge([{ text: label ~ ' (' ~ action.name ~ ')', value: action.name, optgroup: action.scope }]) %}
{% endif %}
{% endfor %}
{% elseif field.data_type == 'permissions' %}
{% set groups = grav.flex.directory('user-groups') %}
{% set groupsList = [] %}
{% set crudp = {
create: { letter: 'C', title: 'Create', value: '' },
read: { letter: 'R', title: 'Read', value: '' },
update: { letter: 'U', title: 'Update', value: '' },
delete: { letter: 'D', title: 'Delete', value: '' }
} %}
{% if object.hasFlexFeature('page') %}
{% set optionsList = [{text: 'Page Authors (Special)', value: 'authors'}, {text: 'Default ACL (Special)', value: 'defaults'}] %}
{% else %}
{% set optionsList = [] %}
{% endif %}
{% for group in groups.index %}
{% set optionsList = optionsList|merge([{ text: group.readableName ?? group.groupname, value: group.groupname }]) %}
{% endfor %}
{% endif %}
<template data-id="acl_picker-{{ field.name }}">
<div class="permissions-item" data-field-type="{{ field.data_type }}">
<a href="#" class="remove-item"><i class="fa fa-trash"></i></a>
<select data-grav-selectize="{{ { options: optionsList, optgroups: groupsList }|json_encode }}"></select>
{% if field.data_type == 'access' %}
<div class="switch-toggle switch-grav medium switch-3">
<input type="radio" value="1" id="{{ field.name ~ '_' }}" name="{{ (scope ~ field.name)|fieldName ~ '[]' }}" class="label1" checked>
<label for="{{ field.name ~ '_' }}">{{ 'PLUGIN_ADMIN.ALLOWED'|t }}</label>
<input type="radio" value="0" id="{{ field.name ~ '_' }}" name="{{ (scope ~ field.name)|fieldName ~ '[]' }}" class="label0">
<label for="{{ field.name ~ '_' }}">{{ 'PLUGIN_ADMIN.DENIED'|t }}</label>
</div>
{% elseif field.data_type == 'permissions' %}
{% set data_field_name = (scope ~ '_json.' ~ field.name)|fieldName %}
<div class="crudp-container" data-field-name="{{ data_field_name ~ '[]' }}">
{% for key, button in crudp %}
<div>
<span class="checkboxes indeterminate toggleable status-unchecked hint--top"
data-_check-status="0"
data-hint="{{ button.title }}">
<input type="checkbox"
id="{{ field.name ~ '_' ~ key ~ '_' }}"
data-crudp-key="{{ key }}"
{# name="{{ (scope ~ field.name)|fieldName ~ '[][' ~ key ~ ']' }}"#}
indeterminte="false" value="">
<label for="{{ field.name ~ '_' ~ key ~ '_' }}">{{ button.letter }}</label>
</span>
</div>
{% endfor %}
<input type="hidden" name="{{ data_field_name ~ '[][' ~ key ~ ']' }}">
</div>
{% endif %}
<button class="button add-item"><i class="fa fa-plus"></i></button>
</div>
</template>
<div class="permissions-container" data-acl_picker_id="{{ field.name }}" data-acl_picker="{{ { options: optionsList, optgroups: groupsList }|json_encode }}">
<div class="permissions-item empty-list {{ value|length ? 'hidden' }}">
<a href="#" class="button add-item"><i class="fa fa-plus"></i></a>
</div>
{% for key, access in value %}
<div class="permissions-item" data-field-type="{{ field.data_type }}">
<a href="#" class="remove-item"><i class="fa fa-trash"></i></a>
<select data-grav-selectize="{{ { options: optionsList, optgroups: groupsList }|json_encode }}">
<option value="{{ key }}" selected>{{ key }}</option>
</select>
{% if field.data_type == 'access' %}
<div class="switch-toggle switch-grav medium switch-3">
{% set rnd = random(100) %}
<input type="radio" value="1" id="{{ field.name ~ '_' ~ rnd }}" name="{{ (scope ~ field.name)|fieldName ~ '[' ~ key ~ ']' }}" class="label1" {{ access ? 'checked' }}>
<label for="{{ field.name ~ '_' ~ rnd }}">{{ 'PLUGIN_ADMIN.ALLOWED'|t }}</label>
{% set rnd = random(100) %}
<input type="radio" value="0" id="{{ field.name ~ '_' ~ rnd }}" name="{{ (scope ~ field.name)|fieldName ~ '[' ~ key ~ ']' }}" class="label0" {{ not access ? 'checked' }}>
<label for="{{ field.name ~ '_' ~ rnd }}">{{ 'PLUGIN_ADMIN.DENIED'|t }}</label>
</div>
{% elseif field.data_type == 'permissions' %}
{% set data_field_name = (scope ~ '_json.' ~ field.name)|fieldName %}
<div class="crudp-container" data-field-name="{{ data_field_name ~ '[]' }}">
{% for crudp_key, button in crudp %}
<div>
{% set crudp_value = value[key][crudp_key] %}
<span class="checkboxes indeterminate toggleable {{ classes[crudp_value] }} hint--top"
data-_check-status="{{ states[crudp_value] }}"
data-hint="{{ button.title }}">
<input type="checkbox"
id="{{ field.name ~ '_' ~ crudp_key ~ '_' }}"
data-crudp-key="{{ crudp_key }}"
{#name="{{ (scope ~ field.name)|fieldName ~ '[' ~ key ~ '][' ~ crudp_key ~ ']' }}"#}
indeterminate="false" value="{{ crudp_value }}">
<label for="{{ field.name ~ '_' ~ crudp_key ~ '_' }}">{{ button.letter }}</label>
</span>
</div>
{% endfor %}
<input type="hidden" name="{{ data_field_name ~ '[' ~ key ~ ']' }}" value="{{ value[key]|default([])|json_encode }}">
</div>
{% endif %}
<button class="button add-item"><i class="fa fa-plus"></i></button>
</div>
{% endfor %}
</div>
{% endblock %}

View File

@@ -0,0 +1,96 @@
{% extends "forms/field.html.twig" %}
{% macro renderer(key, text, field, scope) %}
{% if text is not iterable %}
<div class="form-row{% if field.value_only %} array-field-value_only{% endif %}"
data-grav-array-type="row">
<span data-grav-array-action="sort" class="fa fa-bars"></span>
{% if field.value_only != true %}
{% if key == '0' and text == '' %}
{% set key = '' %}
{% endif %}
<input
data-grav-array-type="key"
type="text" value="{{ key }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
placeholder="{{ field.placeholder_key|t }}" />
{% endif %}
{% if field.value_type == 'textarea' %}
<textarea
data-grav-array-type="value"
name="{{ ((scope ~ field.name)|fieldName) ~ '[' ~ key ~ ']' }}"
placeholder="{{ field.placeholder_value|t }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}>{{ text }}</textarea>
{% else %}
<input
data-grav-array-type="value"
type="text"
name="{{ ((scope ~ field.name)|fieldName) ~ '[' ~ key ~ ']' }}"
placeholder="{{ field.placeholder_value|t }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
value={% if text == 'true' %}true{% elseif text == 'false' %}false{% else %}"{{ text|join(', ') }}"{% endif %} />
{% endif %}
<span data-grav-array-action="rem" class="fa fa-minus"></span>
<span data-grav-array-action="add" class="fa fa-plus"></span>
</div>
{% endif %}
{% endmacro %}
{% import _self as array_field %}
{% block global_attributes %}
data-grav-array-name="{{ (scope ~ field.name)|fieldName }}"
data-grav-array-keyname="{{ field.placeholder_key|t }}"
data-grav-array-valuename="{{ field.placeholder_value|t }}"
data-grav-array-textarea="{{ field.value_type == 'textarea' }}"
{{ parent() }}
{% endblock %}
{% block input %}
<div class="{{ field.size }}" data-grav-array-type="container"{% if field.value_only %} data-grav-array-mode="value_only"{% endif %}{{ value|length <= 1 ? ' class="one-child"' : '' }}>
{% if value|length %}
{% for key, text in value -%}
{% if text is not iterable %}
{{ array_field.renderer(key, text, field, scope) }}
{% else %}
{# Backward compatibility for nested arrays (metas) which are not supported anymore #}
{% for subkey, subtext in text -%}
{{ array_field.renderer(key ~ '[' ~ subkey ~ ']', subtext, field, scope) }}
{% endfor %}
{% endif %}
{% endfor %}
{%- else -%}
{# Empty value, mock the entry field#}
<div class="form-row" data-grav-array-type="row">
<span data-grav-array-action="sort" class="fa fa-bars"></span>
{% if field.value_only != true %}
<input
data-grav-array-type="key"
type="text"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
placeholder="{{ field.placeholder_key|t }}" />
{% endif %}
{% if field.value_type == 'textarea' %}
<textarea
data-grav-array-type="value"
name="{{ (scope ~ field.name)|fieldName }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
placeholder="{{ field.placeholder_value|t }}"></textarea>
{% else %}
<input
data-grav-array-type="value"
type="text"
name="{{ (scope ~ field.name)|fieldName }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
placeholder="{{ field.placeholder_value|t }}" />
{% endif %}
<span data-grav-array-action="rem" class="fa fa-minus"></span>
<span data-grav-array-action="add" class="fa fa-plus"></span>
</div>
{%- endif %}
</div>
{% endblock %}

View File

@@ -0,0 +1,32 @@
{% set delete_url = uri.addNonce(base_url_relative ~ "/backup.json/backup:%BACKUP_FILE/task" ~ config.system.param_sep ~ 'backupDelete', 'admin-form', 'admin-nonce') %}
<table class="backups-history noflex">
<thead>
<tr>
<th>#</th>
<th>{{ "PLUGIN_ADMIN.BACKUP_DATE"|t }}</th>
<th>{{ "PLUGIN_ADMIN.NAME"|t }}</th>
<th class="right pad">{{ "PLUGIN_ADMIN.SIZE"|t }}</th>
<th class="right pad">{{ "PLUGIN_ADMIN.ACTION"|t }}</th>
</tr>
</thead>
<tbody>
{% for backup in backups|default([]) %}
{% set encoded_name = backup.filename|base64_encode|url_encode %}
{% set backup_delete = delete_url|replace({'%BACKUP_FILE': encoded_name}) %}
<tr>
<td>{{ loop.index }}</td>
<td> <i class="fa fa-clock-o"></i> {{ backup.date|date }}</td>
<td>{{ backup.title }}</td>
<td class="right pad">{{ backup.size|nicefilesize }}</td>
<td class="right pad nowrap" >
<a class="button button-small hint--bottom" href="{{ grav.backups.getBackupDownloadUrl(backup.filename, admin.base) }}" data-hint="Download"><i class="fa fa-download"></i></a>
<span class="button button-small danger hint--bottom" data-hint="Delete" data-backup data-ajax="{{ backup_delete }}"><i class="fa fa-close"></i></span>
</td>
</tr>
{% else %}
<tr>
<td colspan="5" class="error" style="text-align: center;">{{ "PLUGIN_ADMIN.BACKUPS_NOT_GENERATED"|t }}</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -0,0 +1,12 @@
{% extends "forms/field.html.twig" %}
{% block field %}
<input
data-grav-field="hidden"
data-grav-disabled="false"
type="hidden"
class="input"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
name="{{ (scope ~ field.name)|fieldName }}"
value="{{ blueprints.name }}" />
{% endblock %}

View File

@@ -0,0 +1,10 @@
{% extends "forms/fields/editor/editor.html.twig" %}
{% set theme = config.plugins.admin.whitelabel.codemirror_theme ?? 'paper.css' %}
{% set font = config.plugins.admin.whitelabel.codemirror_md_font ?? 'sans' %}
{% set codemirrorOptions = {'spellcheck': 'true', 'inputStyle': 'contenteditable', 'mode': 'gfm', 'theme': theme, 'font': font, 'ignore': []}|merge(field.codemirror|default({})) %}
{# backward compatibility #}
{% if field.showPreview %}
{% set codemirrorOptions = codemirrorOptions|merge({'ignore': []}) %}
{% endif %}
{# end backward compatibility #}

View File

@@ -0,0 +1,38 @@
{% extends "forms/field.html.twig" %}
{% set pattern = '^#([a-fA-F0-9]{6})|(rgba\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*((0.[0-9]+)|(1.00)|1.0|1)\\s*\\))$' %}
{% block input %}
<div class="form-list-wrapper {{ field.size }}" data-type="collection">
<div class="g-colorpicker">
{% set input_value = value is iterable ? value|join(',') : value|string %}
<input
data-grav-colorpicker="{{ {update: '.g-colorpicker-preview-wrap .g-colorpicker-preview'}|json_encode|e('html_attr') }}"
{# required attribute structures #}
name="{{ (scope ~ field.name)|fieldName }}"
value="{{ input_value }}"
type="text"
{# input attribute structures #}
{% block input_attributes %}
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
{% if field.id is defined %}id="{{ field.id }}" {% endif %}
{% if field.style is defined %}style="{{ field.style }}" {% endif %}
{% if field.disabled %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.autocomplete in ['on', 'off'] %}autocomplete="{{ field.autocomplete }}"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
pattern="{{ field.validate.pattern|default(pattern)|raw }}"
{% if field.validate.message %}title="{{ field.validate.message|t }}"
{% elseif field.title is defined %}title="{{ field.title|t }}" {% endif %}
{% endblock %}
/>
<div class="g-colorpicker-preview-wrap">
<div class="g-colorpicker-preview" style="background-color: {{ value }}"></div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,40 @@
{% set originalValue = originalValue is defined ? originalValue : value %}
{% set value = (value is null ? field.default : value) %}
{% set classes = field.classes %}
{% block field %}
{% block contents %}
{% block group %}
{% block input %}
<div class="colorbar-element-container g-colorpicker">
<div class="colorbar-element light-border" style="background-color: {{value}}">
<div class="colorbar-title">{{ field.help|t }}</div>
<input
data-grav-colorpicker="{{ {update: '.colorbar-element', offset: {x: -2, y: 20}} |json_encode|e('html_attr') }}"
{# required attribute structures #}
name="{{ (scope ~ field.name)|fieldName }}"
value="{{ value }}"
autocomplete="off"
{# input attribute structures #}
{% block input_attributes %}
{% if classes %}class="{{ classes }}" {% endif %}
{% if field.id is defined %}id="{{ field.id }}" {% endif %}
{% if field.style is defined %}style="{{ field.style }}" {% endif %}
{% if field.disabled %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% if field.validate.pattern %}pattern="{{ field.validate.pattern }}"{% endif %}
{% if field.validate.message %}title="{{ field.validate.message|t }}"
{% elseif field.title is defined %}title="{{ field.title|t }}" {% endif %}
{% endblock %}
/>
</div>
</div>
{% endblock %}
{% endblock %}
{% endblock %}
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends "forms/field.html.twig" %}
{% block input %}
<div class="colorbar current-scheme">
{% include 'forms/default/fields.html.twig' with {name: field.name, fields: field.fields} %}
</div>
{% endblock %}

View File

@@ -0,0 +1,8 @@
{% extends "forms/field.html.twig" %}
{% block field %}
{% embed 'forms/default/fields.html.twig' with {name: name, fields: field.fields} %}
{% block outer_markup_field_open %}<div class="form-column block pure-u-1-{{ cols }}">{% endblock %}
{% block outer_markup_field_close %}</div>{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -0,0 +1,8 @@
{% extends "forms/field.html.twig" %}
{% block field %}
<div class="form-columns grid pure-g">
{% set cols = field.fields|length %}
{% include 'forms/default/fields.html.twig' with {name: field.name|parent_field, fields: field.fields, fallback_field: 'column', cols: cols} %}
</div>
{% endblock %}

View File

@@ -0,0 +1,7 @@
{% extends "forms/field.html.twig" %}
{% block input %}
{% set input_value = value is iterable ? value|join(',') : value|string %}
<input type="hidden" class="input" name="{{ (scope ~ field.name)|fieldName }}" value="{{ input_value }}" />
<div class="cron-selector"></div>
{% endblock %}

View File

@@ -0,0 +1,71 @@
{% set jobs = grav.scheduler.getAllJobs() %}
{% set job_states = grav.scheduler.getJobStates().content() %}
<table class="cron-status noflex">
<thead>
<tr>
<th style="flex:3;">Job ID</th>
<th style="flex:3;">Run</th>
<th>Status</th>
<th class="right pad">State</th>
</tr>
</thead>
<tbody>
{% for job in jobs %}
{% set job_status = attribute(data.status,job.id) %}
{% set job_enabled = job_status is defined and job_status != 'enabled' ? 0 : 1 %}
{% set job_id = job.id %}
{% set job_id_md5 = job_id|md5 %}
{% set job_state = attribute(job_states, job_id) %}
{% set job_at = job.getAt|default('* * * * *') %}
{% set job_backlink = job.backlink %}
<tr>
<td style="flex:3;overflow:hidden;">
{% if job_backlink %}
<a href="{{ admin_route(job_backlink) }}"><kbd>{{ job.id }}</kbd></a>
{% else %}
<kbd>{{ job.id }}</kbd>
{% endif %}
</td>
<td style="flex:3;" class="cron-at">
{% if job_enabled %}
<span class="hint--bottom" data-hint="next run: {{ cron(job_at).getNextRunDate()|date(config.date_format.default) }}">{{ job_at|nicecron }}</span>
{% else %}
{{ job_at|nicecron }}
{% endif %}
</td>
<td>
{% if job_state.state == 'failure' %}
{% set run_type = 'error' %}
{% set run_hint = job_state.error %}
{% set run_text = "<i class=\"fa fa-warning\"></i> Failure" %}
{% else %}
{% set run_type = 'info' %}
{% if job_state.state is not defined %}
{% set run_hint = "not run yet" %}
{% set run_text = "<i class=\"fa fa-check\"></i> Ready" %}
{% else %}
{% set run_hint = "last run: " ~ attribute(job_state,'last-run')|date(config.date_format.default) %}
{% set run_text = "<i class=\"fa fa-check\"></i> Success" %}
{% endif %}
{% endif %}
<span class="hint--bottom" data-hint="{{ run_hint }}">
<span class="badge {{ run_type }}">{{ run_text|raw }}</span>
</span>
</td>
<td class="right pad">
<div class="form-data" data-grav-field="toggle" data-grav-disabled="" data-grav-default="null" data-grav-field-name="data[status][{{ job_id }}]">
<div class="switch-toggle switch-grav switch-2 ">
<input type="radio" value="enabled" id="toggle_status.{{ job_id_md5 }}1" name="data[status][{{ job_id }}]" class="highlight" {% if job_enabled %}checked="checked"{% endif %}>
<label for="toggle_status.{{ job_id_md5 }}1">Enabled</label>
<input type="radio" value="disabled" id="toggle_status.{{ job_id_md5 }}0" name="data[status][{{ job_id }}]" class="" {% if not job_enabled %}checked="checked"{% endif %}>
<label for="toggle_status.{{ job_id_md5 }}0">Disabled</label>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -0,0 +1,24 @@
{% extends "forms/field.html.twig" %}
{% block global_attributes %}
data-grav-selectize="{{ (field.selectize is defined ? field.selectize : {})|json_encode()|e('html_attr') }}"
data-grav-field="select"
{{ parent() }}
{% endblock %}
{% block input %}
<div class="form-select-wrapper {{ field.size }}">
<select class="{{ field.classes }}" name="{{ (scope ~ field.name)|fieldName ~ (field.multiple ? '[]' : '') }}"
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
{% if field.form %}form="{{ field.form }}"{% endif %}
>
{% for key, text in field.options %}
<option {% if key == value or text in value %}selected="selected"{% endif %} value="{{ field.multiple ? text : key }}">{{ key is empty ? text : "now"|date(key) }}</option>
{% endfor %}
</select>
</div>
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends "forms/field.html.twig" %}
{% set value = (value is null ? field.default : value) %}
{% set default_php_dateformat = admin.guessDateFormat(value) %}
{% set php_dateformat = field.format ?: (form ? form.object.dateformat : admin.page.dateformat) ?: config.system.pages.dateformat.default ?: default_php_dateformat %}
{% set js_dateformat = admin.dateformatToMomentJS(php_dateformat) %}
{% set value = (value is null ? value : value|date(php_dateformat)) %}
{% block input %}
<div class="form-input-wrapper datetime-picker-wrapper {{ field.size }}">
{% set input_value = value is iterable ? value|join(',') : value|string %}
<input
name="{{ (scope ~ field.name)|fieldName }}"
value="{{ input_value }}"
{% block input_attributes %}
type="text"
data-grav-datetime="{{ {'format': js_dateformat} | json_encode | e('html_attr') }}"
{% if field.validate.min %}min="{{ (field.validate.min is null ? field.validate.min : field.validate.min|date(php_dateformat)) }}"{% endif %}
{% if field.validate.max %}max="{{ (field.validate.max is null ? field.validate.max : field.validate.max|date(php_dateformat)) }}"{% endif %}
{{ parent() }}
{% endblock %}
/>
<span class="field-icons">
<i class="fa fa-fw fa-calendar"></i>
</span>
</div>
{% endblock %}

View File

@@ -0,0 +1,62 @@
{% extends "forms/field.html.twig" %}
{% set whitelabel = config.plugins.admin.whitelabel %}
{% set theme = whitelabel.codemirror_theme ?? 'paper.css' %}
{% set fontsize = whitelabel.codemirror_fontsize ?? 'lg' %}
{% set value = value ?? field.default|t %}
{% if not codemirrorOptions %}
{% set codemirrorOptions = {'mode': 'gfm', 'theme': theme, 'ignore': ['code', 'preview'], 'font': 'mono'}|merge(field.codemirror|default({})) %}
{% endif %}
{% if codemirrorOptions.theme %}
{% do assets.addCss(theme_url ~ '/css/codemirror/themes/' ~ codemirrorOptions.theme ~ '.css') %}
{% endif %}
{% block field %}
{% block label %}
{% if field.label %}
{% if field.help %}
{% set hint = 'data-hint="' ~ field.help|t|raw ~ '"' %}
{% endif %}
<div class="form-label form-field hint--bottom" {{ hint|raw }}>
{{ field.label|t|raw }}
{{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
</div>
{% endif %}
{% endblock %}
<div class="form-field {{ field.classes|default('') }}">
<div class="form-data grav-editor">
<div class="grav-editor-content is-active fontsize-{{ codemirrorOptions.font_size|default(fontsize) }} fontfamily-{{ codemirrorOptions.font }}">
{% set input_value = value is iterable ? value|join("\n") : value|string %}
<textarea
data-grav-editor="{{ {'codemirror': codemirrorOptions} | json_encode|e('html_attr') }}"
data-grav-editor-mode="editor"
name="{{ (scope ~ field.name)|fieldName }}"
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
{% if field.id is defined %}id="{{ field.id }}" {% endif %}
{% if field.style is defined %}style="{{ field.style }}" {% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder|t }}"{% endif %}
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% if 'preview' not in codemirrorOptions.ignore %}data-grav-urlpreview="{{ base_url }}/media/{{ admin.route|trim('/') }}.json"{% endif %}
>{{ input_value }}</textarea>
</div>
{% if field.resizer is not defined or field.resizer not in ['off', 'false', 0] %}<div class="grav-editor-resizer"></div>{% endif %}
{% if field.description %}
<div class="form-extra-wrapper {{ field.size }} {{ field.wrapper_classes }}">
<span class="form-description">
{% if field.markdown %}
{{ field.description|t|markdown(false)|raw }}
{% else %}
{{ field.description|t|raw }}
{% endif %}
</span>
</div>
{% endif %}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,23 @@
{% extends "forms/field.html.twig" %}
{% block field %}
{% set parent = parent_name|parent_field %}
{% set plain_name = (field.plain_name ?? field.name)|string %}
{% set name = parent ~ '.' ~ plain_name %}
{% if field.field %}
{% set fields = prepare_form_fields({(name): field.field}) %}
{% else %}
{% set fields = prepare_form_fields(field.fields, name) %}
{% endif %}
{% embed 'forms/default/fields.html.twig' with {name: name, fields: fields} %}
{% set initial_state = plain_name is not same as (parent_value|string) ? 'display: none;' %}
{% block outer_markup_field_open %}
<div id="{{ parent_name ~ '__' ~ plain_name }}" class="form-element" style="{{ initial_state }}">
{% endblock %}
{% block outer_markup_field_close %}
</div>
{% endblock %}
{% endembed %}
{% endblock %}

View File

@@ -0,0 +1,20 @@
{% extends "forms/fields/select/select.html.twig" %}
{% set field = field|merge({ autocomplete: 'off' }) %}
{% if grav.admin is not defined %}
{# load some frontend CSS/JS #}
{% endif %}
{% block global_attributes %}
data-grav-elements="{{ field.name }}"
{{ parent() }}
{% endblock %}
{% block field %}
{{ parent() }}
{% set parent_name = field.name %}
{% set parent_value = value %}
{% if fields|length %}
{% include 'forms/default/fields.html.twig' with {name: parent_name, fields: field.fields} %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,81 @@
{% extends "forms/field.html.twig" %}
{% block field %}
<div class="form-fieldset{% if vertical %} vertical{% endif %}{% if field.classes is defined %} {{ field.classes }}{% endif %}">
{% block contents %}
<input type="checkbox" class="hidden" id="fieldset_collapsible_{{ field.name }}"{% if not field.collapsible or not field.collapsed %} checked="checked"{% endif %} />
<div class="form-label form-fieldset--label">
<h2>
<label{% if field.collapsible %} for="fieldset_collapsible_{{ field.name }}" class="form-fieldset--cursor"{% endif %}>
{% if field.help %}
<span class="hint--bottom" data-hint="{{ field.help|t }}">
{% endif %}
{% block label %}
{% if field.icon %}
<i class="fa fa-fw fa-{{ field.icon }}"></i>
{% endif %}
{{ field.title|t }}
{{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
{% if field.info %}
<span class="form-fieldset--info">{{ field.info|t }}</span>
{% endif %}
{% endblock %}
{% if field.help %}
</span>
{% endif %}
{# Actions panel #}
<span class="actions">
{% block actions %}
{% if field.collapsible %}
<span class="form-fieldset--collapsible">
<i class="fa fa-chevron-down open"></i>
<i class="fa fa-chevron-up close"></i>
</span>
{% endif %}
{% endblock %}
</span>
</label>
</h2>
</div>
<div class="form-data"
{#{% block global_attributes %}
data-grav-field="{{ field.type }}"
data-grav-disabled="{{ originalValue is null ? 'true' : 'false' }}"
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
{% endblock %}#}
>
{% block group %}
{% if field.text %}
{{ field.markdown ? field.text|t|markdown : ('<p>' ~ field.text|t ~ '</p>')|raw }}
{% endif %}
{% if field.fields %}
{% for child_name, child in field.fields %}
{% set child = prepare_form_field(child, child_name, field.name, {key: key}) %}
{% if child %}
{% set default_layout = 'text' %}
{% if child.type == 'key' or child.key == true %}
{# Special handling for the key field #}
{% set default_layout = 'key' %}
{% set child_value = key %}
{% elseif child.name == 'value' %}
{# Special handling for the value field #}
{% set child = child|merge({ name: field.name }) %}
{% set child_value = value %}
{% else %}
{% set child_value = form ? form.value(child.name) : data.value(child.name) %}
{% endif %}
{% set field_templates = include_form_field(child.type, field_layout, default_layout) %}
{% include field_templates with { field: child, value: child_value, originalValue: null } %}
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}
</div>
{% endblock %}
</div>
{% endblock %}

View File

@@ -0,0 +1,118 @@
{% extends "forms/field.html.twig" %}
{% macro bytesToSize(bytes) -%}
{% spaceless %}
{% set kilobyte = 1024 %}
{% set megabyte = kilobyte * 1024 %}
{% set gigabyte = megabyte * 1024 %}
{% set terabyte = gigabyte * 1024 %}
{% if bytes < kilobyte %}
{{ bytes ~ ' B' }}
{% elseif bytes < megabyte %}
{{ (bytes / kilobyte)|number_format(2, '.') ~ ' KB' }}
{% elseif bytes < gigabyte %}
{{ (bytes / megabyte)|number_format(2, '.') ~ ' MB' }}
{% elseif bytes < terabyte %}
{{ (bytes / gigabyte)|number_format(2, '.') ~ ' GB' }}
{% else %}
{{ (bytes / terabyte)|number_format(2, '.') ~ ' TB' }}
{% endif %}
{% endspaceless %}
{%- endmacro %}
{% macro preview(path, value, global) %}
{% if value %}
{% set uri = global.grav.uri %}
{% set files = global.files %}
{% set config = global.grav.config %}
{% set route = global.context.route() %}
{% set type = global.blueprint_type ? global.blueprint_type : global.admin.location ? global.admin.location : 'config' %}
{% set blueprint_name = global.blueprints.getFilename %}
{% set real_path = path %}
{% if type == 'pages' %}
{% set blueprint_name = type ~ '/' ~ blueprint_name %}
{% set real_path = (value.thumb ?? global.context.media[path].relativePath ?? global.form.getPagePathFromToken(path) ?? global.admin.getPagePathFromToken(path))|ltrim('/') %}
{% endif %}
{% set blueprint = blueprint_name|base64_encode %}
{% set remove = global.file_task_remove ? global.file_url_remove : uri.addNonce(
global.file_url_remove ~
'/media.json' ~
'/task' ~ config.system.param_sep ~ 'removeFileFromBlueprint' ~
'/proute' ~ config.system.param_sep ~ (route|base64_encode) ~
'/blueprint' ~ config.system.param_sep ~ blueprint ~
'/type' ~ config.system.param_sep ~ type ~
'/field' ~ config.system.param_sep ~ files.name ~
'/path' ~ config.system.param_sep ~ (value.path|base64_encode), 'admin-form', 'admin-nonce') %}
{% set file = value|merge({remove: remove, path: value.thumb_url ?? (uri.rootUrl == '/' ? '/' : uri.rootUrl ~ '/' ~ real_path) }) %}
<div class="hidden" data-file="{{ file|json_encode|e('html_attr') }}"></div>
{% endif %}
{% endmacro %}
{% import _self as macro %}
{% set defaults = config.plugins.form %}
{% set files = defaults.files|merge(field|default([])) %}
{% set limit = not field.multiple ? 1 : files.limit %}
{% block input %}
{% set page_can_upload = exists or (type == 'page' and not exists and not (field.destination starts with '@self' or field.destination starts with 'self@')) %}
{% if form or (type is not defined or page_can_upload) %}
{% block prepend %}{% endblock %}
{% set settings = {name: field.name, paramName: (scope ~ field.name)|fieldName ~ (files.multiple ? '[]' : ''), limit: limit, filesize: form_max_filesize, accept: files.accept, resolution: files.resolution, resizeWidth: files.resizeWidth, resizeHeight: files.resizeHeight, resizeQuality: files.resizeQuality } %}
{% set dropzoneSettings = field.dropzone %}
{% if form.getMediaTaskRoute() %}
{% set file_url_add = base_url_relative ~ form.getMediaTaskRoute({}, 'json') %}
{% set file_task_add = {task: 'media.upload', name: field.name, '__form-name__': form.name, '__unique_form_id__': form.uniqueid} %}
{% set file_url_remove = base_url_relative ~ form.getMediaTaskRoute({}, 'json') %}
{% set file_task_remove = {task: 'media.delete', name: field.name, '__form-name__': form.name, '__unique_form_id__': form.uniqueid} %}
{% else %}
{% set file_url_remove = file_url_remove ?: base_url_relative %}
{% endif %}
<div class="{{ form_field_wrapper_classes ?: 'form-input-wrapper' }} {{ field.classes }} dropzone files-upload {% if field.fancy is not same as(false) %}form-input-file{% endif %} {{ field.size }}"
data-grav-file-settings="{{ settings|json_encode|e('html_attr') }}"
data-dropzone-options="{{ dropzoneSettings|json_encode|e('html_attr') }}"
{% if file_task_add and file_task_remove %}
data-file-post-add="{{ file_task_add|json_encode|e('html_attr') }}"
data-file-post-remove="{{ file_task_remove|json_encode|e('html_attr') }}"
data-file-url-add="{{ file_url_add }}"
data-file-url-remove="{{ file_url_remove }}"
{% else %}
{% if file_url_add %}data-file-url-add="{{ file_url_add }}"{% endif %}
{% if file_url_remove %}data-file-url-remove="{{ file_url_remove }}"{% endif %}
{% endif %}
>
{% block file_extras %}{% endblock %}
<input
{# required attribute structures #}
{% block input_attributes %}
type="file"
{% if files.multiple %}multiple="multiple"{% endif %}
{% if files.accept %}accept="{{ files.accept|join(',') }}"{% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
{% if field.random_name %}random="true"{% endif %}
{% if required %}required="required"{% endif %}
{{ parent() }}
{% endblock %}
/>
{% for path, file in value %}
{{ macro.preview(path, file, _context) }}
{% endfor %}
{% include 'forms/fields/hidden/hidden.html.twig' with {field: {name: '_json.' ~ field.name}, value: (value ?? [])|json_encode} %}
</div>
{% else %}
<span class="note">{{ "PLUGIN_ADMIN.CANNOT_ADD_FILES_PAGE_NOT_SAVED"|t|raw }}</span>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% embed "forms/fields/select/select.html.twig" %}
{% block input %}
{% set input_value = value is iterable ? value|join(',') : value|string %}
{% if not field.options and value %}
{% if value is iterable %}
{% set options = {} %}
{% for val in value %}
{% set options = options|merge({(val): val}) %}
{% endfor %}
{% else %}
{% set options = {(value): value} %}
{% endif %}
{% set field = field|merge({options: options}) %}
{% endif %}
{{ parent() }}
{% endblock %}
{% block global_attributes %}
data-grav-filepicker
data-name="{{ field.name }}"
{% if field.preview_images %}data-preview-images{% endif %}
{% if field.on_demand %}data-ondemand{% endif %}
data-value="{{ input_value }}"
{{ parent() }}
{% endblock %}
{% endembed %}

View File

@@ -0,0 +1,8 @@
{% extends "forms/fields/text/text.html.twig" %}
{% set field = field|merge({'wrapper_classes': 'form-input-addon-wrapper'}) %}
{% block append %}
<div class="form-input-addon form-input-append hint--top" data-hint="{{ 'PLUGIN_ADMIN.AUTOREGENERATE_FOLDER_SLUG'|t }}" data-regenerate='[name="{{ (scope ~ field.name)|fieldName }}"]'>
<i class="fa fa-refresh"></i>
</div>
{% endblock %}

View File

@@ -0,0 +1,10 @@
{# Deprecated field. Alias to editor/editor.html.twig #}
{% extends "forms/fields/editor/editor.html.twig" %}
{% set codemirrorOptions = {'mode': 'yaml', 'indentUnit': 4, ignore: ['code'], 'autofocus': true, 'indentWithTabs': false, 'lineNumbers': true, 'gutters': ["CodeMirror-lint-markers"]}|merge(field.codemirror|default({})) %}
{# backward compatibility #}
{% if field.showPreview %}
{% set codemirrorOptions = codemirrorOptions|merge({'ignore': []}) %}
{% endif %}
{# end backward compatibility #}

View File

@@ -0,0 +1,44 @@
{% extends "forms/field.html.twig" %}
{% block global_attributes %}
data-grav-iconpicker
data-name="{{field.name}}"
data-value="{{value}}"
{{ parent() }}
{% endblock %}
{% block input %}
<div class="form-list-wrapper {{ field.size }}" data-type="collection">
<div class="icon-picker" data-pickerid="fa" data-iconsets='{"fa":"FontAwesome Icons"}'>
{% set input_value = value is iterable ? value|join(',') : value|string %}
<input
{# required attribute structures #}
name="{{ (scope ~ field.name)|fieldName }}"
data-format="{{ field.format == 'short' ? 'short' : 'long' }}"
value="{{ input_value }}"
type="text"
{# input attribute structures #}
{% block input_attributes %}
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
{% if field.id is defined %}id="{{ field.id }}" {% endif %}
{% if field.style is defined %}style="{{ field.style }}" {% endif %}
{% if field.disabled %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.autocomplete in ['on', 'off'] %}autocomplete="{{ field.autocomplete }}"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% endblock %}
/>
</div>
<div class="fa-set icon-set">
<ul>
{% for icon in fa_icons %}
<li data-code="{{icon.unicode}}" data-class="fa fa-{{icon.id}}" class="fa fa-{{icon.id}}"></li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,188 @@
{% extends "forms/field.html.twig" %}
{% set value = (value is null ? field.default : value) %}
{% set name = field.name %}
{% set btnLabel = field.btnLabel is defined ? field.btnLabel : "PLUGIN_ADMIN.ADD_ITEM" %}
{% set btnSortLabel = field.btnSortLabel is defined ? field.btnSortLabel : "PLUGIN_ADMIN.SORT_BY" %}
{% set fieldControls = field.controls|default('bottom') %}
{% block contents %}
<div class="form-label{% if not vertical %} block size-1-3 pure-u-1-3{% endif %}">
{% if field.toggleable %}
<span class="checkboxes toggleable" data-grav-field="toggleable" data-grav-field-name="{{ (scope ~ field.name)|fieldName }}">
<input type="checkbox"
id="toggleable_{{ field.name }}"
{% if toggleableChecked %}value="1"{% endif %}
name="toggleable_{{ (scope ~ field.name)|fieldName }}"
{% if toggleableChecked %}checked="checked"{% endif %}
>
<label for="toggleable_{{ field.name }}"></label>
</span>
{% endif %}
<label{{ (field.toggleable ? ' class="toggleable" for="toggleable_' ~ field.name ~ '"')|raw }}>
{% if field.help %}
<span class="hint--bottom" data-hint="{{ field.help|t }}">{{ field.label|t }}</span>
{% else %}
{{ field.label|t }}
{% endif %}
{{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
</label>
</div>
<div class="form-data{% if not vertical %} block size-2-3 pure-u-2-3{% endif %}"
{% block global_attributes %}
data-grav-field="{{ field.type }}"
data-grav-disabled="{{ toggleableChecked }}"
data-grav-default="{{ field.default|json_encode|e('html_attr') }}"
{% endblock %}
>
<div class="form-list-wrapper {{ field.size }}" data-type="collection"
{% if field.selectunique %}
data-select-unique="{{ field.selectunique|json_encode|e('html_attr') }}"
data-max="{{ field.selectunique|length }}"
{% endif %}
{% if field.min is defined %}data-min="{{ field.min }}"{% endif %}
{% if field.max is defined and not field.selectunique %}data-max="{{ field.max }}"{% endif %}
>
{% if fieldControls in ['top', 'both'] %}
<div class="collection-actions">
{% if collapsible %}
<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"|t }}</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"|t }}</button>
{% endif %}
{% 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') }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-sort-amount-{{ field.sortby_dir|default('asc') }}"></i> {{ btnSortLabel|t }} '{{ field.sortby }}'</button>
{% endif %}
<button class="button" type="button" data-action="add"
data-action-add="{{ field.placement is same as('position') ? 'top' : field.placement|default('bottom') }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
><i class="fa fa-plus"></i> {{ btnLabel|t }}</button>
</div>
{% endif %}
<ul {% if field.classes is defined %}class="{{ field.classes }}"{% endif %} data-collection-holder="{{ name }}"
{% if field.sort is same as(false) %}
data-collection-nosort
{% endif %}>
{% if field.fields %}
{% set collapsible = field.fields|length > 1 and (field.collapsible is not defined or field.collapsible) %}
{% for key, val in value %}
{% set item_name = name ? name ~ '.' ~ key : key %}
<li data-collection-item="{{ item_name }}"
data-collection-key="{{ key }}"
class="{{ collapsible and field.collapsed ? 'collection-collapsed' : '' }}"
{% if field.min_height %}style="min-height:{{ field.min_height }};"{% endif %}>
<div class="collection-sort"><i class="fa fa-fw fa-bars"></i></div>
{%- for child_name, child in field.fields -%}
{% set child = prepare_form_field(child, child_name, item_name) %}
{% if child %}
{% set child = child|merge({ '_list_index': item_name }) %}
{% set default_layout = 'text' %}
{% if child.type == 'key' or (child.key == true and child.type != 'list') %}
{# Special handling for the key field #}
{% set default_layout = 'key' %}
{% set child_value = key %}
{% elseif child.name == 'value' %}
{# Special handling for the value field #}
{% set child = child|merge({ name: item_name }) %}
{% set child_value = val %}
{% else %}
{% set child_value = form ? form.value(child.name) : data.value(child.name) %}
{# Look for a default value for that field #}
{% if child_value is null and val[child_name|trim('.', 'left')] is defined %}
{% set child_value = val[child_name|trim('.', 'left')] %}
{% endif %}
{% endif %}
{% set field_templates = include_form_field(child.type, field_layout, default_layout) %}
{% set template_data = { field: child, value: child_value, originalValue: null } %}
{% if default_layout != 'key' %}
{% if child.type == 'fieldset' %}
{% set template_data = template_data|merge({val: child_value}) %}
{% endif %}
{% endif %}
{%- include field_templates with template_data -%}
{% endif %}
{% endfor %}
<div class="item-actions">
{% if collapsible %}
<i class="fa fa-chevron-circle-{{ field.collapsed ? 'right' : 'down' }}" data-action="{{ field.collapsed ? 'expand' : 'collapse' }}"></i>
<br />
{% endif %}
<i class="fa fa-trash-o" data-action="confirm"></i>
<div class="list-confirm-deletion button danger hidden" data-action="delete">
<i class="fa fa-fw text-primary fa-check"></i>
<span>{{ 'PLUGIN_ADMIN.DELETE'|t }}</span>
</div>
</div>
</li>
{% endfor %}
{% endif %}
</ul>
{% if fieldControls in ['bottom', 'both'] %}
<div class="collection-actions">
{% if collapsible %}
<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"|t }}</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"|t }}</button>
{% endif %}
{% 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') }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}><i class="fa fa-sort-amount-{{ field.sortby_dir|default('asc') }}"></i> {{ btnSortLabel|t }} '{{ field.sortby }}'</button>
{% endif %}
<button class="button" type="button" data-action="add"
data-action-add="{{ field.placement is same as('position') ? 'bottom' : field.placement|default('bottom') }}"
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
><i class="fa fa-plus"></i> {{ btnLabel|t }}</button>
</div>
{% endif %}
{% set template %}
{%- set item_name = name ? name ~ '.*' : '*' -%}
<li data-collection-item="{{ item_name }}">
{% if field.sort is not same as(false) %}
<div class="collection-sort"><i class="fa fa-fw fa-bars"></i></div>
{% endif %}
{%- if field.fields -%}
{%- for child_name, child in field.fields -%}
{% set child = prepare_form_field(child, child_name, item_name) %}
{% if child %}
{% set child = child|merge({ '_list_index': item_name }) %}
{% set default_layout = 'text' %}
{% if child.type == 'key' or child.key == true %}
{# Special handling for the key field #}
{% set default_layout = 'key' %}
{% elseif child.name == 'value' %}
{# Special handling for the value field #}
{% set child = child|merge({ name: item_name }) %}
{% endif %}
{% set field_templates = include_form_field(child.type, field_layout, default_layout) %}
{% include field_templates with { field: child, value: null } %}
{% endif %}
{%- endfor %}
<div class="item-actions">
{% if collapsible %}
<i class="fa fa-chevron-circle-down" data-action="collapse"></i>
<br />
{% endif %}
<i class="fa fa-trash-o" data-action="confirm"></i>
<div class="list-confirm-deletion button danger hidden" data-action="delete">
<i class="fa fa-fw text-primary fa-check"></i>
<span>{{ 'PLUGIN_ADMIN.DELETE'|t }}</span>
</div>
</div>
{%- endif -%}
</li>
{% endset %}
<div style="display: none;" data-collection-template="new"
data-collection-template-html="{{ template|regex_replace('/([ \r\n]+)/', ' ')|e('html_attr') }}"></div>
<div style="display: none;" data-collection-config="{{ name }}"></div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1 @@
{% extends "forms/fields/codemirror/codemirror.html.twig" %}

View File

@@ -0,0 +1,17 @@
{% extends "forms/fields/text/text.html.twig" %}
{% set unique_identifier = random_string() %}
{% block global_attributes %}
{{ parent() }}
data-mediapicker-modal-trigger
data-grav-mediapicker-unique-identifier="{{ unique_identifier }}"
{% endblock %}
{% block contents %}
{{ parent() }}
<div class="remodal remodal-mediapicker" data-remodal-mediapicker data-remodal-unique-identifier="{{ unique_identifier }}" data-remodal-options="hashTracking: false">
{% include 'partials/media-list-wrapper.html.twig' with { is_modal: true } %}
</div>
{% endblock %}

View File

@@ -0,0 +1,121 @@
{% extends "forms/field.html.twig" %}
{% macro renderer(key, content, field, scope, level, parent_key, up_level) %}
{% import _self as self %}
{% macro field(value, key, level, globalvars, disable_name, hidden) %}
{% set name = 'data[' ~ globalvars.field.name|replace({'.': ']['}) ~ ']' ~ key %}
<div class="form-row array-field-value_only js__multilevel-field {{ level == 0 ? 'top' : '' }}"
data-grav-array-type="row" {% if (hidden|default(false) == true) %}style="display: none"{% endif %}>
{% set marginDir = not language_codes.rtl(grav.user.language) ? 'margin-left' : 'margin-right' %}
<input
type="text"
{% if (disable_name != true) %}name="{{ name }}"{% endif %}
data-attr-name="{{ name }}"
placeholder="{{ field.placeholder_value|t }}"
style="{{ marginDir }}: {{ level * 50 }}px"
value="{{ value }}" />
<span class="fa fa-minus js__remove-item"></span>
<span class="fa fa-plus js__add-sibling hidden" data-level="{{level}}"></span>
<span class="fa fa-plus-circle js__add-children hidden" data-level="{{level}}"></span>
</div>
{% endmacro %}
{% if level == 0 %}
{{ self.field(key, '', level, _context, true, (is_numeric(key) ? true : false)) }}
{% if content is not iterable %}
{% set level2 = level + 1 %}
<div class="children-wrapper">
<div class="element-wrapper">
{{ self.field(content, '[' ~ key ~ ']', level2, _context) }}
</div>
</div>
{% endif %}
{% endif %}
{% if up_level %}
{% set level = level + 1 %}
{% endif %}
<div class="children-wrapper">
{% set unique_child = (is_array(content) and content.length > 1) ? true : false %}
{% for inner_key, inner_content in content -%}
<div class="element-wrapper">
{% if not is_numeric(inner_key) %}
{% if (content|length > 1) %}
{{ self.field(inner_key, parent_key, level, _context, true) }}
{% else %}
{{ self.field(inner_key, parent_key, level, _context) }}
{% endif %}
{% set level2 = level + 1 %}
{% set up_level = true %}
{% else %}
{% set up_level = false %}
{% set level2 = level %}
{% endif %}
{% if inner_content is not iterable %}
{% if not is_numeric(inner_key) %}
<div class="children-wrapper">
<div class="element-wrapper">
{% endif %}
{% set last_key = (is_numeric(inner_key)) ? '' : inner_key %}
{{ self.field(inner_content, parent_key ~ '[' ~ inner_key ~ ']', level2, _context) }}
{% if not is_numeric(inner_key) %}
</div>
</div>
{% endif %}
{% else %}
{% set inner_parent_key = parent_key ~ '[' ~ inner_key ~ ']' %}
{{ self.renderer(inner_key, inner_content, field, scope, level, inner_parent_key, up_level) }}
{% endif %}
</div>
{% endfor %}
</div>
{% endmacro %}
{% import _self as macro %}
{% block global_attributes %}
data-grav-array-name="{{ (scope ~ field.name)|fieldName }}"
data-grav-array-keyname="{{ field.placeholder_key|t }}"
data-grav-array-valuename="{{ field.placeholder_value|t }}"
{{ parent() }}
{% endblock %}
{% block input %}
<div data-id="{{random_string()}}" data-grav-multilevel-field data-grav-array-type="container" data-grav-array-mode="value_only"{{ value|length <= 1 ? ' class="one-child"' : '' }}>
{% if value|length %}
{% for key, content in value -%}
<div class="element-wrapper">
{{ macro.renderer(key, content, field, scope, 0, '[' ~ key ~ ']', true) }}
</div>
{% endfor %}
{%- else -%}
{# Empty value, mock the entry field#}
<div class="element-wrapper">
<div class="form-row array-field-value_only js__multilevel-field"
data-grav-array-type="row">
<input
type="text"
name="{{ (scope ~ field.name)|fieldName }}"
placeholder="Enter value"
value="" />
<span class="fa fa-minus js__remove-item"></span>
<span class="fa fa-plus js__add-sibling hidden" data-level="0" ></span>
<span class="fa fa-plus-circle js__add-children hidden" data-level="0"></span>
</div>
</div>
{%- endif %}
</div>
{% endblock %}

View File

@@ -0,0 +1,68 @@
{% extends "forms/field.html.twig" %}
{% set value = (value is null ? field.default : value) %}
{% if form %}
{% set siblings = form.object.parent.children.collection %}
{% set canOrder = form.object.order %}
{% if not form.object.exists %}
{% do siblings.add(form.object) %}
{% endif %}
{% else %}
{% do admin.enablePages() %}
{% set siblings = context.parent.children %}
{% set canOrder = context.order %}
{% endif %}
{% set vertical = field.style == 'vertical' %}
{% block field %}
<div class="form-field grid pure-g{% if vertical %} vertical{% endif %}">
<div class="form-label{% if not vertical %} block size-1-3 pure-u-1-3{% endif %}">
<label>
{% if field.help %}
<span class="tooltip" data-asTooltip-position="w" title="{{ field.help|t }}">{{ field.label|t }}</span>
{% else %}
{{ field.label|t }}
{% endif %}
{{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
</label>
</div>
<div class="form-data{% if not vertical %} block size-2-3 pure-u-2-3{% endif %}">
<div class="form-order-wrapper {{ field.size }}">
<input
type="hidden"
data-order
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
name="{{ (scope ~ field.name)|fieldName }}"
value="" />
{% if not canOrder %}
<div class="notice">{{ "PLUGIN_ADMIN.ORDERING_DISABLED_BECAUSE_PAGE_NO_PREFIX"|t|raw }}</div>
{% endif %}
{% if siblings|length < 200 %}
{% set sortable_count = 0 %}
<ul id="ordering" class="orderable {{ field.classes }}">
{% 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|int }}.</span> {{ page.title ?: 'NEW' }} <a href="{{ getPageUrl(page) }}"><i class="fa fa-external-link"></i></a></li>
{% set sortable_count = loop.index %}
{% endif %}
{% endfor %}
</ul>
{% if sortable_count < siblings|length %}
<label>{{ "PLUGIN_ADMIN.UNSORTABLE_PAGES"|t }}</label>
<ul class="orderable disabled">
{% for page in siblings %}
{% if not page.order %}
<li {{ page.slug == data.slug ? 'data-active-id' : ''}}>{{ page.title ?: 'NEW' }} <a href="{{ getPageUrl(page) }}"><i class="fa fa-external-link"></i></a></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% else %}
<div class="notice">{{ "PLUGIN_ADMIN.ORDERING_DISABLED_BECAUSE_TOO_MANY_SIBLINGS"|t }}</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,65 @@
{% extends "forms/field.html.twig" %}
{% set value = (value is null ? field.default : value) %}
{% block field %}
{% if context.folderExists %}
{% set pagemedia = config.get('plugins.admin.pagemedia') %}
{% set pagemedia_settings = {
resolution: {
min: {
width: pagemedia.res_min_width ?: null,
height: pagemedia.res_min_height ?: null
},
max: {
width: pagemedia.res_max_width ?: null,
height: pagemedia.res_max_height ?: null
}
},
resizeWidth: pagemedia.resize_width ?: null,
resizeHeight: pagemedia.resize_height ?: null,
resizeQuality: pagemedia.resize_quality ?: 0.8
} %}
{% set media_url = form.getMediaTaskRoute() ?: '/media/' ~ admin.route|trim('/') ~ '.json' %}
{% set media_local = form.getMediaRoute() ?: base_url_relative_frontend|rtrim('/') ~ '/' ~ admin.route|trim('/') %}
{% set media_path = url(context.relativePagePath) %}
{% set media_uri = context.mediaUri() %}
{% set dropzone_settings = { maxFilesize: form_max_filesize }|merge(pagemedia_settings) %}
{% set pageMediaStore = get_cookie('grav-admin-pagemedia')|default('{"width":200,"collapsed":false}')|json_decode %}
<div class="pagemedia-field form-field grid vertical {% if field.classes is defined %}{{ field.classes }}{% endif %}">
<div class="form-label">
<label class="media-collapser">
<i class="fa fa-fw small fa-chevron-{{ pageMediaStore.collapsed ? 'right' : 'down' }}"></i>
{{ field.label|t }} <span data-pagemedia-count>({{ admin.page.media|length }})</span>
</label>
<div class="{{ pageMediaStore.collapsed ? 'hidden' : '' }}">
<input type="range" min="70" step="10" max="200" value="{{ pageMediaStore.width }}" class="media-resizer">
</div>
</div>
<div class="form-data form-uploads-wrapper" style="{{ pageMediaStore.collapsed ? 'display: none;' : '' }}">
<div id="grav-dropzone"
class="dropzone"
data-media-url="{{ (base_url ~ media_url)|e('html_attr') }}"
data-media-local="{{ media_local|e('html_attr') }}"
data-media-path="{{ media_path|e('html_attr') }}"
data-media-uri="{{ media_uri|e('html_attr') }}"
data-dropzone-options="{{ dropzone_settings|json_encode|e('html_attr') }}"
data-dropzone-field="{{ (scope ~ field.name)|fieldName }}"></div>
{% if admin.session.expert == '0' or not user.authorize('admin.super') %}
<input type="hidden" name="{{ (scope ~ field.name)|fieldName }}" value="{{ value }}" />
{% endif %}
</div>
</div>
{% else %}
<div class="form-tab">
<div class="form-field">
<div class="form-label">
{{ "PLUGIN_ADMIN.CANNOT_ADD_MEDIA_FILES_PAGE_NOT_SAVED"|t }}
</div>
</div>
</div>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1 @@
{% extends "forms/fields/filepicker/filepicker.html.twig" %}

View File

@@ -0,0 +1,52 @@
{% extends "forms/field.html.twig" %}
{% macro page_options(globals, pages_list) %}
{% set field = globals.field %}
{% set value = globals.value %}
{% if field.options and depth == 0 %}
{% for key, value in field.options %}
<option value="{{ key|e('html_attr') }}">{{ value|t }}</option>
{% endfor %}
{% endif %}
{% for page_route, option in pages_list %}
<option {% if page_route == value or (field.multiple and page_route in value) %}selected="selected"{% endif %} value="{{ page_route }}">{{ option|raw }}</option>
{% endfor %}
{% endmacro %}
{% import _self as macro %}
{% block global_attributes %}
data-grav-selectize="{{ (field.selectize is defined ? field.selectize : {})|json_encode|e('html_attr') }}"
data-grav-field="select"
data-grav-disabled="{{ originalValue is null ? 'true' : 'false' }}"
data-grav-default="{{ field.default|json_encode|e('html_attr') }}"
{% endblock %}
{% block input %}
{% do admin.enablePages %}
{% set start_page = field.start_route ? pages.find(field.start_route) : null %}
{% set show_all = field.show_all is same as(false) ? false : true %}
{% set show_fullpath = field.show_fullpath is same as(true) ? true : false %}
{% set show_slug = field.show_slug is same as(true) ? true : false %}
{% set show_modular = field.show_modular is same as(true) ? true : false %}
{% set limit_levels = field.limit_levels ?: false %}
{% set page_list = grav.pages.getList(start_page, 0, true, show_all, show_fullpath, show_slug, show_modular, limit_levels) %}
<div class="form-select-wrapper {{ field.size }}">
<select class="{{ field.classes }}" name="{{ (scope ~ field.name)|fieldName ~ (field.multiple ? '[]' : '') }}"
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
>
{% if field.show_root %}
<option value="/">/ (root)</option>
{% endif %}
{{ macro.page_options(_context, page_list) }}
</select>
</div>
{% endblock %}

View File

@@ -0,0 +1,58 @@
{% extends "forms/field.html.twig" %}
{% block input %}
{#
{% set defaults = {
show_root: true,
show_all: show_all_val,
show_modular: show_modular_val,
show_slug: show_slug_val,
show_fullpath: show_fullpath_val,
default: last_page_route,
limit_levels: limit_levels_val
} %}
{% set field = field|merge(defaults) %}
#}
{% set name = (scope ~ field.name)|fieldName %}
{% if form %}
{% set parent = form.object.parent.title %}
{% elseif grav['flex_objects'].hasDirectory('pages') %}
{% set directory = grav['flex_objects'].getDirectory('pages') %}
{% set parent = value ? directory.getObject(value|trim('/')).title : '<root>' %}
{% else %}
{% do admin.enablePages() %}
{% set parent = page.find(value).title %}
{% endif %}
<div class="parents-wrapper">
<div class="form-input-wrapper" data-parents="{{ name }}" data-remodal-target="parents">
<div class="parent-title" data-parents-field-name="{{ name }}">{{ parent }}</div>
<span><i class="fa fa-folder-o"></i> <span data-parents-field-label="{{ name }}">{{ value|default('/') }}</span></span>
</div>
<input type="hidden" class="input" name="{{ name }}" data-field-name="{{ field.name }}" value="{{ value|join(', ') }}" />
</div>
{#{% set last_page_route = admin.page.getLastPageRoute %}
{% set show_slug_val = true %}
{% set show_fullpath_val = false %}
{% set show_all_val = true %}
{% set show_parents = config.get('plugins.admin.pages.show_parents') %}
{% if show_parents == 'folder' %}
{% set show_slug_val = false %}
{% elseif show_parents == 'fullpath' %}
{% set show_fullpath_val = true %}
{% endif %}
{% set limit_levels_val = config.get('plugins.admin.pages.parents_levels') %}
{% set show_modular_val = config.get('plugins.admin.pages.show_modular', true) %}
{% if show_modular_val == false %}
{% set show_all_val = false %}
{% endif %}
{% set defaults = {show_root:true, show_all:show_all_val, show_modular:show_modular_val, show_slug:show_slug_val, show_fullpath:show_fullpath_val, default:last_page_route, limit_levels:limit_levels_val} %}
{% set field = field|merge(defaults) %}
{{ parent() }}#}
{% endblock %}

View File

@@ -0,0 +1,161 @@
{% extends "forms/field.html.twig" %}
{% macro spanToggle(input, length) %}
{% set space = repeat('&nbsp;&nbsp;', (length - input|length) / 2) %}
{{ (space ~ input ~ space)|raw }}
{% endmacro %}
{% macro section(section, context, depth) %}
{% import _self as macro %}
{% set section_label = (section.label ?? section.name)|t %}
{# Sub sections can have top-level toggle.. needs to #}
{% if depth > 0 %}
{% set section_value = context.access.get(section.name)|string %}
{% set params = {
context: context,
action_label: section_label,
action_value: section_value,
action_name: section.name,
action_class: 'parent-section'
}
%}
{{ macro.action_row(params) }}
{% endif %}
<fieldset>
{% if depth == 0 %}
<legend>{{ section_label }}</legend>
{% endif %}
{% for action in section %}
{% if action.visible %}
{% if action.count %}
{{ macro.section(action, context, depth + 1) }}
{% else %}
{{ macro.action(action, context) }}
{% endif %}
{% endif %}
{% endfor %}
</fieldset>
{% endmacro %}
{% macro action(action, context) %}
{% import _self as macro %}
{% set action_label = action.label ?? action.name %}
{% set action_value = context.access.get(action.name)|string %}
{% set params = {
context: context,
action_label: action_label,
action_value: action_value,
action_name: action.name,
action_parent: action.getParent().name
}
%}
{{ macro.action_row(params) }}
{% endmacro %}
{% macro action_row(data) %}
{% import _self as macro %}
{% set context = data.context %}
{% set field = context.field %}
<div class="permission-container {{ data.action_class }}">
<div class="permission-name">
<span>{{ data.action_label|t }}</span>
{% if context.auth_badges %}
{% set auth = context.object.authorize(data.action_name, 'test') ?? context.super %}
{% if context.super and auth %}
<span class="badge badge-super"><i class="icon-super"></i></span>
{% elseif auth %}
<span class="badge badge-access"><i class="fa fa-check"></i></span>
{% else %}
<span class="badge badge-denied"><i class="fa fa-ban"></i></span>
{% endif %}
{% endif %}
</div>
<div class="switch-toggle switch-grav medium switch-3">
{% for key, text in context.options %}
{% set parent_id = data.action_parent ? "toggle_" ~ field.name ~ "." ~ data.action_parent %}
{% set id = "toggle_" ~ field.name ~ "." ~ data.action_name ~ key %}
{% set translation = text|t|trim %}
<input type="radio"
value="{{ key }}"
id="{{ id }}"
{% if parent_id %}
data-parent-id="{{ parent_id }}"
{% endif %}
name="{{ (context.scope ~ field.name)|fieldName }}[{{ data.action_name }}]"
class="label{{ key }}"
{% if key|fieldName == '' ~ data.action_value|fieldName %}
checked="checked"
{% endif %}
{% if field.validate.required in ['yes', 'on', 'true', 1, true] %}required="required"{% endif %}
/>
<label for="{{ id }}">{{ macro.spanToggle(translation, context.maxLen)|trim|raw }}</label>
{% endfor %}
<a></a>
</div>
</div>
{% endmacro %}
{% import _self as macro %}
{% block global_attributes %}
data-grav-disabled="{{ originalValue is null ? 'true' : 'false' }}"
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
{% endblock %}
{% block input %}
{% set options = { '1': 'PLUGIN_ADMIN.ALLOWED', '0': 'PLUGIN_ADMIN.DENIED', '': 'PLUGIN_ADMIN.NOT_SET' } %}
{% set maxLen = 0 %}
{% for text in options %}
{% set maxLen = max(text|t|trim|length, maxLen) %}
{% endfor %}
{% set permissions = grav.permissions %}
{% set access = permissions.access(value) %}
{% if object and field.check_authorize %}
{% set auth_badges = true %}
{% set super = object.authorize('admin.super', 'test') %}
{% endif %}
<div class="permissions-container">
{% for section in permissions %}
{% if section.count %}
{{ macro.section(section, _context, 0) }}
{% endif %}
{% endfor %}
{# Look for missing actions #}
{% set unknown %}
{% for key,val in access.getAllActions() %}
{% if not permissions.getAction(key) %}
{{ macro.action({name: key}, _context) }}
{% endif %}
{% endfor %}
{% endset %}
{% if unknown|trim %}
<fieldset>
<legend>Unknown Permissions</legend>
{{ unknown|raw }}
</fieldset>
{% endif %}
</div>
{% endblock %}

View File

@@ -0,0 +1,28 @@
{% extends "forms/field.html.twig" %}
{% block input_attributes %}
type="range"
class="rangefield {% if field.classes is defined %}{{ field.classes }} {% endif %}"
{% if field.validate.min %}min="{{ field.validate.min }}"{% endif %}
{% if field.validate.max %}max="{{ field.validate.max }}"{% endif %}
{% if field.validate.step %}step="{{ field.validate.step }}"{% endif %}
{{ parent() }}
{% endblock %}
{% block append %}
<input
type="number"
class="rangefield {% if field.classes is defined %}{{ field.classes }} {% endif %}"
{% if field.validate.min %}min="{{ field.validate.min }}"{% endif %}
{% if field.validate.max %}max="{{ field.validate.max }}"{% endif %}
{% if field.validate.step %}step="{{ field.validate.step }}"{% endif %}
{% if value is defined %}
value="{{ value }}"
{% elseif field.default is defined %}
value="{{ field.default }}"
{% else %}
value="0"
{% endif %}
/>
<span class="range-append">{{ field.append }}</span>
{% endblock append %}

View File

@@ -0,0 +1,24 @@
{% extends "forms/field.html.twig" %}
{% block field %}
{% if field.security is empty or authorize(array(field.security)) %}
{% if field.title or field.underline %}
<h1 class="{{ field.classes }} {{ field.underline ?: 'no_underline' }}">{{ field.title|t }}</h1>
{% endif %}
{% if field.text %}
<p>{{ field.text|t|markdown|raw }}</p>
{% endif %}
{% embed 'forms/default/fields.html.twig' with {name: field.name, fields: field.fields} %}
{% block outer_markup_field_open %}
<div class="form-section {{ field.field_classes }} {{ field.outer_classes }}">
{% endblock %}
{% block outer_markup_field_close %}
</div>
{% endblock %}
{% endembed %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,19 @@
{% extends "forms/field.html.twig" %}
{% block global_attributes %}
{% if field.selectize is defined %}
{% set fieldSelectize = {create: field.selectize.create ?? true}|merge(field.selectize ?? {}) %}
{% if field.merge_items %}
{% set fieldSelectize = fieldSelectize|merge({'items':value}) %}
{% endif %}
{% else %}
{% set fieldSelectize = {'create': true} %}
{% endif %}
data-grav-selectize="{{ fieldSelectize|json_encode()|e('html_attr') }}"
{{ parent() }}
{% endblock %}
{% block input_attributes %}
type="text"
{{ parent() }}
{% endblock %}

View File

@@ -0,0 +1,43 @@
{% extends "forms/field.html.twig" %}
{% block global_attributes %}
data-grav-selectize="{{ (field.selectize is defined ? field.selectize : {})|json_encode()|e('html_attr') }}"
data-grav-field="select"
{{ parent() }}
{% endblock %}
{% block input %}
<div class="form-input-wrapper {{ field.size }}">
{% set input_value = value is iterable ? value|join(',') : value|string %}
<select
value="{{ input_value }}"
name="{{ (scope ~ field.name)|fieldName }}"
data-select-observe
{% block input_attributes %}
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
{% if field.id is defined %}id="{{ field.id }}" {% endif %}
{% if field.style is defined %}style="{{ field.style }}" {% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
{% if field.placeholder %}placeholder="{{ field.placeholder }}"{% endif %}
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
{% if field.autocomplete in ['on', 'off'] %}autocomplete="{{ field.autocomplete }}"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% if field.validate.pattern %}pattern="{{ field.validate.pattern }}"{% endif %}
{% if field.validate.message %}title="{{ field.validate.message|t }}"
{% elseif field.title is defined %}title="{{ field.title|t }}" {% endif %}
{% endblock %}
>
{% if field.placeholder %}<option value="" disabled selected>{{ field.placeholder|t|raw }}</option>{% endif %}
{% if value is defined %}
<option selected="selected" value="{{ value }}">{{ value }}</option>
{% endif %}
</select>
{% if field.default %}
<div><p class="notice warning">It is advised not to use a <strong>default</strong> option with the selectunique field. Currently default value set to `{{ field.default }}`</p></div>
{% endif %}
</div>
{% endblock %}

View File

@@ -0,0 +1,39 @@
{% extends "forms/field.html.twig" %}
{% block field %}
{% set object = form.object %}
{% set taxonomies = taxonomies ?? field.taxonomies ?? admin.data('config/site').taxonomies ?? [] %}
{% set parentname = field.name %}
{% set options = field.options %}
{% set default = field.default %}
{% for name in taxonomies %}
{% set field_name = parentname ~ '.' ~ name %}
{% set value = form ? form.value(field_name) : data.value(field_name) %}
{% set value = (value ?? default[name] ?? [])|array %}
{% if object %}
{% set can_translate = can_translate ?? (admin.multilang and object.hasFlexFeature('flex-translate')) %}
{% set index = object.getFlexDirectory().getIndex() %}
{% set translated = can_translate ? index.withTranslated(admin.language) : index %}
{% set sub_taxonomies = translated.getDistinctValues(field_name) %}
{% else %}
{% set sub_taxonomies = (attribute(grav.taxonomy.taxonomy, name) ?? [])|keys %}
{% endif %}
{% set list = (options[name] ?? [])|merge(sub_taxonomies)|merge(value)|array_unique %}
{% set field = {
type: 'select',
classes: 'fancy create',
label: name|capitalize,
name: field_name,
multiple: true,
options: list,
style: field.style,
selectize: {
create: true
}
} %}
{% include 'forms/fields/select/select.html.twig' %}
{% endfor %}
{% endblock %}

View File

@@ -0,0 +1,106 @@
{% extends "forms/field.html.twig" %}
{% block input %}
<div class="jquery-horizontal-scroll-wrap">
<div class="jquery-horizontal-scroll">
<div class="holder" style="white-space: nowrap;">
{% for id,preset in whitelabel_presets %}
<style>
.pid-{{ id }} .admin-preview {
background: {{ preset.colors['page-bg'] }};
}
.pid-{{ id }} .ap-sidebar {
background: {{ preset.colors['nav-bg'] }};
}
.pid-{{ id }} .ap-logo {
background: {{ preset.colors['logo-bg'] }};
}
.pid-{{ id }} .ap-logo::after {
background: {{ preset.colors['logo-link'] }};
}
.pid-{{ id }} .ap-text, .pid-{{ id }} .ap-text::before, .pid-{{ id }} .ap-text::after {
background: {{ preset.colors['nav-link'] }};
}
.pid-{{ id }} .ap-active {
background: {{ preset.colors['nav-selected-bg'] }};
border-left-color: {{ preset.colors['button-bg'] }};
}
.pid-{{ id }} .ap-active::after {
background: {{ preset.colors['nav-selected-link'] }};
}
.pid-{{ id }} .ap-toolbar {
background: {{ preset.colors['toolbar-bg'] }};
}
.pid-{{ id }} .ap-toolbar::after {
background: {{ preset.colors['toolbar-text'] }};
}
.pid-{{ id }} .ap-button {
background: {{ preset.colors['button-bg'] }};
}
.pid-{{ id }} .ap-content {
background: {{ preset.colors['content-bg'] }};
}
.pid-{{ id }} .ap-title {
background: {{ preset.colors['content-header'] }};
}
.pid-{{ id }} .ap-content .ap-text {
background: {{ preset.colors['content-link'] }};
}
.pid-{{ id }} .ap-content .ap-text::before, .pid-{{ id }} .ap-content .ap-text::after {
background: {{ preset.colors['content-text'] }};
}
.pid-{{ id }} .ap-update {
background: {{ preset.colors['update-bg'] }};
}
.pid-{{ id }} .ap-update::after {
background: {{ preset.colors['update-text'] }};
}
.pid-{{ id }} .ap-notice {
background: {{ preset.colors['notice-bg'] }};
}
.pid-{{ id }} .ap-notice::after {
background: {{ preset.colors['notice-text'] }};
}
.pid-{{ id }} .ap-critical {
background: {{ preset.colors['critical-bg'] }};
}
.pid-{{ id }} .ap-critical::after {
background: {{ preset.colors['critical-text'] }};
}
</style>
<div class="pid-{{ id }} admin-preview-wrapper" data-preset-values="{{ preset|json_encode|e('html_attr') }}">
<div class="admin-preview form-border">
<div class="ap-overlay"><b><i class="fa fa-upload"></i> {{ "PLUGIN_ADMIN.LOAD_PRESET"|t }}</b></div>
<div class="ap-sidebar">
<div class="ap-logo"></div>
<div class="ap-nav">
<span class="ap-text"></span>
<span class="ap-active"></span>
<span class="ap-text"></span>
</div>
</div>
<div class="ap-toolbar">
<span class="ap-button"></span>
</div>
<div class="ap-page">
<div class="ap-content">
<span class="ap-update"></span>
<span class="ap-title"></span>
<span class="ap-text"></span>
<span class="ap-notice"></span>
<span class="ap-text"></span>
<span class="ap-critical"></span>
<span class="ap-text"></span>
</div>
</div>
</div>
<div class="admin-preview-title">
{{ preset.name }}
</div>
<input type="hidden" value="{{ preset|json_encode }}" />
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,31 @@
{% extends "forms/field.html.twig" %}
{% set options = {} %}
{% for slug, package in admin.themes %}
{% set option = {(slug): package.toArray().name} %}
{% set options = options|merge(option) %}
{% endfor %}
{% block global_attributes %}
data-grav-selectize="{{ (field.selectize is defined ? field.selectize : {})|json_encode()|e('html_attr') }}"
data-grav-field="select"
data-grav-disabled="{{ originalValue is null ? 'true' : 'false' }}"
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
{% endblock %}
{% block input %}
<div class="form-select-wrapper {{ field.size }}">
<select class="{{ field.classes }}" name="{{ (scope ~ field.name)|fieldName ~ (field.multiple ? '[]' : '') }}"
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}>
{% for key, text in options %}
<option {% if key == value or text in value %}selected="selected"{% endif %} value="{{ field.multiple ? text : key }}">{{ text }}</option>
{% endfor %}
</select>
</div>
{% endblock %}

View File

@@ -0,0 +1,19 @@
{% extends "forms/field.html.twig" %}
{% block field %}
<div class="form-field grid user-details">
<div class="form-label block size-1-3">
{% include 'partials/userinfo-avatar.html.twig' %}
</div>
<div class="form-data block size-2-3">
<h2>{{ data.fullname }}</h2>
<h5>
<a href="mailto:{{ data.email }}">{{ data.email }}</a>
{% if data.title %}
- {{ data.title }}
{% endif %}
</h5>
{% include 'partials/userinfo-avatar-credit.html.twig' %}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,61 @@
{#{% extends "forms/field.html.twig" %}#}
{% import _self as macro %}
{% macro spanToggle(input, length) %}
{% set space = repeat('&nbsp;&nbsp;', (length - input|length) / 2) %}
{{ (space ~ input ~ space)|raw }}
{% endmacro %}
{% macro outputWidget(widget) %}
{% endmacro %}
{% set widgets = grav.twig.plugins_hooked_dashboard_widgets_top|array|merge(grav.twig.plugins_hooked_dashboard_widgets_main|array)|merge(grav.twig.plugins_hooked_dashboard_widgets_bottom|array) %}
{% set widgets_display = grav.config.plugins.admin.widgets_display %}
{% for widget in widgets %}
{% set widget_name = widget.name|default(widget.template|titleize) %}
{% set widget_id = widget.template %}
{% set widget_value = widgets_display[widget_id]|string in ['1', 'true'] ? 'true' : 'false' %}
{% set name = 'data['~field.name~']['~widget_id~']' %}
<div class="block block-toggle">
<div class="form-field grid">
<div class="form-label block size-1-3">
<label>
<span>{{ widget_name }} Widget</span>
</label>
</div>
<div class="form-data block size-2-3" data-grav-field="toggle" data-grav-default="1">
<div class="switch-toggle switch-grav medium switch-2">
{% set options = { true: 'PLUGIN_ADMIN.ENABLED', false: 'PLUGIN_ADMIN.DISABLED' } %}
{% set maxLen = 0 %}
{% for value, text in options %}
{% set translation = text|t %}
{% set maxLen = max(translation|length, maxLen) %}
{% endfor %}
{% for key, text in options %}
{% set id = "toggle_" ~ field.name ~ "." ~ widget_id ~ '.' ~ key %}
{% set translation = text|t|trim %}
<input type="radio"
value="{{ key }}"
id="{{ id }}"
name="{{ name }}"
class="{{ 'true' == '' ~ key ? 'highlight' : '' }}"
{% if key|string == widget_value|string %}
checked="checked"
{% endif %}
/>
<label for="{{ id }}">{{ (macro.spanToggle(translation, maxLen)|trim)|raw }}</label>
{% endfor %}
</div>
</div>
</div>
</div>
{% endfor %}

View File

@@ -0,0 +1,6 @@
{% set xss_header = (form ? form.value('header') : data.value('header'))|array %}
{% set xss_content = form ? form.value('content') : data.value('content') %}
{% set xss_status = xss({header: xss_header, content: xss_content}) %}
{% if xss_status is not empty %}
<div class="notice alert">{{ "PLUGIN_ADMIN.XSS_ISSUE"|t(xss_status)|raw }}</div>
{% endif %}

View File

@@ -0,0 +1,13 @@
{% extends 'partials/base.html.twig' %}
{% block messages %}{% endblock %}
{% block content %}
<div class="admin-block">
<h1>
{{ "PLUGIN_ADMIN.INSTALLER"|t }}
</h1>
{% include 'partials/messages.html.twig' %}
</div>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% set user = grav.user %}
{% if user.username and user.authenticated %}
{% if not user.authorized and user.twofa_enabled %}
{% include 'partials/login-twofa.html.twig' %}
{% else %}
{% include 'partials/login-logout.html.twig' %}
{% endif %}
{% else %}
{% include 'partials/login-form.html.twig' %}
{% endif %}

View File

@@ -0,0 +1,19 @@
{% set index = uri.param('index') %}
{% for file in admin.files(true, index) %}
{% set the_file = file.file %}
{% if the_file.exists and the_file.display() is not empty %}
<div class="card-item">
<div class="admin-media-details">
<a href="{% if is_modal %}#{% else %}{{ admin_route('/media-manager/' ~ the_file.filepath|base64_encode) }}{% endif %}" class="js__media-element" data-file-url="{{ file.page_route ~ '/' ~ file.title }}">
{% set thumbnail = the_file.display(the_file.extension == 'svg' ? 'source' : 'thumbnail') %}
{% if thumbnail %}
<img src="{{thumbnail.cropZoom(250, 250).url}}" />
<h4 class="admin-media-title">{{ file.title }}</h4>
{% endif %}
</a>
</div>
</div>
{% endif %}
{% endfor %}

View File

@@ -0,0 +1,469 @@
{% extends 'partials/base.html.twig' %}
{% macro spanToggle(input, length) %}
{{ (repeat('&nbsp;&nbsp;', (length - input|length) / 2) ~ input ~ repeat('&nbsp;&nbsp;', (length - input|length) / 2))|raw }}
{% endmacro %}
{% macro loop(page, depth, twig_vars) %}
{% import _self as self %}
{% set config = twig_vars['config'] %}
{% set separator = config.system.param_sep %}
{% set display_field = config.plugins.admin.pages_list_display_field %} {# DEPRECATED #}
{% set base_url_relative_frontend = twig_vars['base_url_relative_frontend'] %}
{% set admin = twig_vars['admin'] %}
{% set warn = twig_vars['warn'] %}
{% set uri = twig_vars['uri'] %}
{% if page.header.admin.children_display_order == 'collection' and page.header.content.order.by %}
{% if page.header.content.order.custom %}
{% set pcol = page.children().order(page.header.content.order.by, page.header.content.order.dir|default('asc'), page.header.content.order.custom) %}
{% else %}
{% set pcol = page.children().order(page.header.content.order.by, page.header.content.order.dir|default('asc')) %}
{% endif %}
{% else %}
{% set pcol = page.children() %}
{% endif %}
{% for p in pcol %}
{% set description = (not p.page ? "PLUGIN_ADMIN.FOLDER"|t ~ ' &bull; ' : "PLUGIN_ADMIN.PAGE"|t ~ ' &bull; ') ~
(p.isModule ? "PLUGIN_ADMIN.MODULE"|t ~ ' &bull; ' : '') ~
(p.routable ? "PLUGIN_ADMIN.ROUTABLE"|t ~ ' &bull; ' : "PLUGIN_ADMIN.NON_ROUTABLE"|t ~ ' &bull; ') ~
(p.visible ? "PLUGIN_ADMIN.VISIBLE"|t ~ ' &bull; ' : "PLUGIN_ADMIN.NON_VISIBLE"|t ~ ' &bull; ') ~
(p.published ? "PLUGIN_ADMIN.PUBLISHED"|t ~ ' &bull; ' : "PLUGIN_ADMIN.NON_PUBLISHED"|t ~ ' &bull; ') %}
{% set page_url = getPageUrl(p) %}
<li class="page-item" data-nav-id="{{ p.route }}">
<div class="row page-item__row">
<span class="page-item__toggle" {{ p.children(0).count > 0 ? 'data-toggle="children"' : ''}}>
<i class="page-icon fa fa-fw fa-circle-o {{ p.children(0).count > 0 ? 'children-closed' : ''}} {{ p.isModule ? 'modular' : (not p.routable ? 'not-routable' : (not p.visible ? 'not-visible' : (not p.page ? 'folder' : ''))) }}"></i>
</span>
<div class="page-item__content">
<div class="page-item__content-name">
<span data-hint="{{ description|trim(' &bull; ')|raw }}" class="hint--top page-item__content-hint">
{% set page_label = attribute(p.header, display_field)|defined(attribute(p, display_field))|defined(p.title)|default(p.slug|titleize) %}
<a href="{{ page_url }}" class="page-edit">{{ page_label }}</a>
</span>
{% if p.language %}
<span class="badge lang {% if p.language == admin.language %}info{% endif %}">{{p.language}}</span>
{% endif %}
{% if p.home %}
<span class="page-home"><i class="fa fa-home"></i></span>
{% endif %}
</div>
<p class="page-route">{{ p.header.routes.default ?: p.route }} <span class="spacer"><i class="fa fa-long-arrow-right"></i></span> {{ p.template() }}</p>
</div>
<span class="page-item__tools">
{% if config.plugins.admin.frontend_preview_target != 'inline' %}
{% set preview_target = config.plugins.admin.frontend_preview_target %}
{% set preview_route = (base_url_relative_frontend|rtrim('/') ~ (p.home ? '' : p.route)) ?: '/' %}
{% set preview_link = p.routable ? '<a class="page-view" target="' ~ preview_target ~ '" href="' ~ preview_route ~ '" title="' ~ "PLUGIN_ADMIN.PREVIEW"|t ~ '"> <i class="fa fa-fw fa-eye"></i></a>' : '' %}
{% else %}
{% set preview_route = admin_route('/preview' ~ (p.home ? '' : p.route)) %}
{% set preview_link = p.routable ? '<a class="page-view" href="' ~ preview_route ~ '" title="' ~ "PLUGIN_ADMIN.PREVIEW"|t ~ '"> <i class="fa fa-fw fa-eye"></i></a>' : '' %}
{% endif %}
{{ preview_link|raw }}
{% if warn %}
<a href="#delete" data-remodal-target="delete" data-delete-url="{{ uri.addNonce(page_url ~ '/task' ~ separator ~ 'delete', 'admin-form', 'admin-nonce') }}" class="page-delete" ><i class="fa fa-trash-o"></i></a>
{% else %}
<a href="{{ uri.addNonce(page_url ~ '/task' ~ separator ~ 'delete', 'admin-form', 'admin-nonce') }}" class="page-delete" ><i class="fa fa-trash-o"></i></a>
{% endif %}
</span>
</div>
{% if p.children().count > 0 %}
<ul class="depth-{{ depth + 1 }}" style="display:none;">
{{ self.loop(p, depth + 1, twig_vars) }}
</ul>
{% endif %}
</li>
{% endfor %}
{% endmacro %}
{% import _self as macro %}
{% if admin.route %}
{% set context = admin.page(true) %}
{#
{% if admin.language != admin.session.admin_lang %}
{% do admin.setMessage('Session language does not match') %}
{% endif %}
#}
{% elseif grav.language.enabled and admin.language != admin.session.admin_lang %}
{# Redirect to last set language #}
{% do admin.redirect(admin.adminRoute('/pages', admin.session.admin_lang)) %}
{% endif %}
{% if uri.param('new') %}
{% set mode = 'new' %}
{% elseif context %}
{% set mode = 'edit' %}
{% if context.exists %}
{% set page_url = admin_route('/pages' ~ (context.header.routes.default ?: context.rawRoute)) %}
{% set exists = true %}
{% set title = (context.exists ? "PLUGIN_ADMIN.EDIT"|t : "PLUGIN_ADMIN.CREATE"|t ) ~ " " ~ (context.header.title ?: context.title) %}
{% else %}
{% set title = "PLUGIN_ADMIN.ADD_PAGE"|t %}
{% endif %}
{% else %}
{% set mode = 'list' %}
{% set title = "PLUGIN_ADMIN.PAGES"|t %}
{% endif %}
{% set modular = context.isModule ? 'modular_' : '' %}
{% set warn = config.plugins.admin.warnings.delete_page %}
{% set secure_delete = config.plugins.admin.warnings.secure_delete %}
{% set page_lang = context.language %}
{% set type = 'page' %}
{% block stylesheets %}
{% if mode == 'edit' %}
{% do assets.addCss(theme_url~'/css/codemirror/codemirror.css') %}
{% endif %}
{{ parent() }}
{% endblock %}
{% block javascripts %}
{{ parent() }}
{% endblock %}
{% if config.plugins.admin.frontend_preview_target != 'inline' %}
{% set preview_route = (base_url_relative_frontend|rtrim('/') ~ (context.home ? '' : context.route)) ?: '/' %}
{% set preview_target = config.plugins.admin.frontend_preview_target %}
{% set preview_link = context.routable ? '<a class="button" target="' ~ preview_target ~ '" href="' ~ preview_route ~ '" title="' ~ "PLUGIN_ADMIN.PREVIEW"|t ~ '"> <i class="fa fa-fw fa-eye" style="font-size:18px;margin-right:0;"></i></a>' : '' %}
{% else %}
{% set preview_route = admin_route('/preview' ~ (context.home ? '' : context.route)) %}
{% set preview_link = context.routable ? '<a class="button" href="' ~ preview_route ~ '" title="' ~ "PLUGIN_ADMIN.PREVIEW"|t ~ '"> <i class="fa fa-fw fa-eye" style="font-size:18px;margin-right:0;"></i></a>' : '' %}
{% endif %}
{% block titlebar %}
<div class="button-bar">
{% if mode == 'list' %}
<a class="button" href="{{ admin_route('/') }}"><i class="fa fa-reply"></i> {{ "PLUGIN_ADMIN.BACK"|t }}</a>
{% for key, add_modal in config.plugins.admin.add_modals %}
{% if add_modal.show_in|defined('bar') == 'bar' %}
<a class="button {{ add_modal.link_classes }}" href="#modal-add_modal-{{ key }}" data-remodal-target="modal-add_modal-{{ key }}"><i class="fa fa-plus"></i> {{ add_modal.label|t }}</a>
{% endif %}
{% endfor %}
<div class="button-group">
<button type="button" class="button disabled" href="#modal" data-remodal-target="modal">
<i class="fa fa-plus"></i> {{ "PLUGIN_ADMIN.ADD"|t }}
</button>
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu">
<li><a class="button" href="#modal" data-remodal-target="modal">{{ "PLUGIN_ADMIN.ADD_PAGE"|t }}</a></li>
<li><a class="button" href="#modal-folder" data-remodal-target="modal-folder">{{ "PLUGIN_ADMIN.ADD_FOLDER"|t }}</a></li>
{% if admin.modularTypes is not empty %}
<li><a class="button" href="#module" data-remodal-target="module">{{ "PLUGIN_ADMIN.ADD_MODULE"|t }}</a></li>
{% endif %}
{% for key, add_modal in config.plugins.admin.add_modals %}
{% if add_modal.show_in|defined('bar') == 'dropdown' %}
<li><a class="button {{ add_modal.link_classes }}" href="#modal-add_modal-{{ key }}" data-remodal-target="modal-add_modal-{{ key }}">{{ add_modal.label|t }}</a></li>
{% endif %}
{% endfor %}
</ul>
</div>
{% if admin.multilang %}
<div class="button-group">
<button type="button" class="button disabled">
<i class="fa fa-flag-o"></i>
{% set langName = admin.siteLanguages[admin.language] %}
{{ langName[:1]|upper ~ langName[1:] }}
</button>
{% if admin.languages_enabled|length > 1 %}
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu language-switcher">
{% for langCode in admin.languages_enabled %}
{% set langName = admin.siteLanguages[langCode] %}
{% if langCode != admin.language %}
<li><a href="{{ uri.addNonce(base_url_relative ~ theme.slug ~ '/pages/task' ~ config.system.param_sep ~ 'switchlanguage/lang' ~ config.system.param_sep ~ langCode, 'admin-form', 'admin-nonce') }}">{{ langName[:1]|upper ~ langName[1:] }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
{% elseif mode == 'edit' %}
{{ preview_link|raw }}
<a class="button" href="{{ admin_route('/pages') }}" title="{{ "PLUGIN_ADMIN.BACK"|t }}"><i class="fa fa-reply"></i></a>
{% if exists %}
{% set siblings = context.parent().children() %}
{% if not siblings.isFirst(context.path) %}
{% set sib = siblings.nextSibling(context.path) %}
{% set sib_url = admin_route('/pages' ~ (sib.header.routes.default ?: sib.rawRoute)) %}
<a class="button hidden-mobile" href="{{ sib_url }}" title="{{ "PLUGIN_ADMIN.PREVIOUS"|t }}"><i class="fa fa-chevron-left"></i></a>
{% endif %}
{% if not siblings.isLast(context.path) %}
{% set sib = siblings.prevSibling(context.path) %}
{% set sib_url = admin_route('/pages' ~ (sib.header.routes.default ?: sib.rawRoute)) %}
<a class="button hidden-mobile" href="{{ sib_url }}" title="{{ "PLUGIN_ADMIN.NEXT"|t }}"><i class="fa fa-chevron-right"></i></a>
{% endif %}
{% if warn %}
<a class="button" href="#delete" data-remodal-target="delete" data-delete-url="{{ uri.addNonce(page_url ~ '/task' ~ config.system.param_sep ~ 'delete', 'admin-form', 'admin-nonce') }}"><i class="fa fa-trash-o"></i> {{ "PLUGIN_ADMIN.DELETE"|t }}</a>
{% else %}
<a class="button disable-after-click" href="{{ uri.addNonce(uri.route(true) ~ '/task' ~ config.system.param_sep ~ 'delete', 'admin-form', 'admin-nonce') }}" class="page-delete" ><i class="fa fa-trash-o"></i></a>
{% endif %}
<div class="button-group">
<button type="button" class="button disabled" href="#modal" data-remodal-target="modal">
<i class="fa fa-plus"></i> {{ "PLUGIN_ADMIN.ADD"|t }}
</button>
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu">
<li><a class="button" href="#modal" data-remodal-target="modal">{{ "PLUGIN_ADMIN.ADD_PAGE"|t }}</a></li>
<li><a class="button" href="#modal-folder" data-remodal-target="modal-folder">{{ "PLUGIN_ADMIN.ADD_FOLDER"|t }}</a></li>
{% if admin.modularTypes is not empty %}
<li><a class="button" href="#module" data-remodal-target="module">{{ "PLUGIN_ADMIN.ADD_MODULE"|t }}</a></li>
{% endif %}
</ul>
</div>
<a class="button disable-after-click" href="{{ uri.addNonce(page_url ~ '/task' ~ config.system.param_sep ~ 'copy', 'admin-form', 'admin-nonce') }}" class="page-copy" ><i class="fa fa-copy"></i> {{ "PLUGIN_ADMIN.COPY"|t }}</a>
<a class="button" href="#" data-remodal-target="move" data-parents="data[route]"><i class="fa fa-arrows"></i> {{ "PLUGIN_ADMIN.MOVE"|t }}</a>
{% if config.plugins['admin-pro'].enabled %}
<a class="button" href="#" data-remodal-target="revisions"><i class="fa fa-history"></i> {{ "PLUGIN_ADMIN_PRO.REVISIONS"|t }}</a>
{% endif %}
{% endif %}
<div class="button-group">
<button class="button success" name="task" value="save" form="blueprints" type="submit"><i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|t }}</button>
{% if exists and admin.multilang %}
{% set untranslated = context.untranslatedLanguages(true) %}
{% if untranslated %}
<button type="button" class="button success dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu lang-switcher">
{% for langCode in untranslated %}
{% set langName = admin.siteLanguages[langCode] %}
{% if langCode != page_lang %}
<li><button class="button success task" name="task" value="saveas" lang="{{langCode}}" form="blueprints" type="submit">{{ "PLUGIN_ADMIN.SAVE_AS"|t }} {{ langName[:1]|upper ~ langName[1:] }}</button></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endif %}
</div>
{% endif %}
</div>
{% if mode == 'new' %}
<h1><i class="fa fa-fw fa-file-text-o"></i> {{ "PLUGIN_ADMIN.ADD_PAGE"|t }}</h1>
{% elseif mode == 'edit' %}
<h1><i class="fa fa-fw fa-file-text-o"></i>
{{ context.title }}
</h1>
{% else %}
<h1><i class="fa fa-fw fa-file-text-o"></i> {{ "PLUGIN_ADMIN.MANAGE_PAGES"|t }}</h1>
{% endif %}
{% endblock %}
{% block content %}
<div class="clear admin-pages">
{% if mode == 'new' %}
{% include 'partials/blueprints-new.html.twig' with { blueprints: admin.blueprints('pages/page'), data: context } %}
{% elseif mode == 'edit' %}
<div class="admin-form-wrapper">
<div id="admin-topbar">
{% if admin.multilang %}
{% set translated = context.translatedLanguages(false) %}
<div id="admin-lang-toggle" class="button-group">
<button type="button" class="button disabled">
{% if exists %}
{{ page_lang ?? "PLUGIN_ADMIN.DEFAULT"|t }}
{% else %}
{{ admin.language }}
{% endif %}
</button>
{% if exists and translated|length > 1 - (exists and not page_lang)|int %}
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu language-switcher">
{% for language, route in translated %}
{% if language != page_lang ?? grav.language.default %}
<li><button class="task" name="task" value="switchlanguage" lang="{{language}}" redirect="{{context.rawRoute|trim('/')}}" form="blueprints">{{ language }}</button></li>
{% endif %}
{% endfor %}
{% if translated|length > 1 %}
<li><button class="task" name="task" value="switchlanguage" lang="{{ grav.language.default }}" redirect="{{context.rawRoute|trim('/')}}" form="blueprints">Default</button></li>
{% endif %}
</ul>
{% endif %}
</div>
{% endif %}
{% if context.blueprints.fields and user.authorize('admin.super') %}
{% set normalText = "PLUGIN_ADMIN.NORMAL"|t %}
{% set expertText = "PLUGIN_ADMIN.EXPERT"|t %}
{% set maxLen = max([normalText|length, expertText|length]) %}
{% set normalText = macro.spanToggle(normalText, maxLen) %}
{% set expertText = macro.spanToggle(expertText, maxLen) %}
<form id="admin-mode-toggle">
<div class="switch-toggle switch-grav">
<input type="radio" value="normal" data-leave-url="{{ admin_route('/pages/' ~ admin.route|trim('/') ~ '/mode' ~ config.system.param_sep ~ 'normal') }}" id="normal" name="mode-switch" class="highlight" {% if admin.session.expert == '0' %} checked="checked"{% endif %}>
<label for="normal">{{ normalText|raw }}</label>
<input type="radio" value="expert" data-leave-url="{{ admin_route('/pages/' ~ admin.route|trim('/') ~ '/mode' ~ config.system.param_sep ~ 'expert') }}" id="expert" name="mode-switch" class="highlight" {% if admin.session.expert == '1' %} checked="checked"{% endif %}>
<label for="expert">{{ expertText|raw }}</label>
<a></a>
</div>
</form>
{% endif %}
</div>
{# Set current form data back into page content #}
{% if current_form_data %}
{% do context.header(current_form_data.header) %}
{% do context.content(current_form_data.content) %}
{% endif %}
{% if (context.blueprints.fields and admin.session.expert == '0') or not user.authorize('admin.super') %}
{% include 'partials/blueprints.html.twig' with { blueprints: context.blueprints, data: context } %}
{% else %}
{% include 'partials/blueprints-raw.html.twig' with { blueprints: admin.blueprints('admin/pages/'~modular~'raw'), data: context } %}
{% endif %}
</div>
{% else %}
<form id="page-filtering">
<div class="page-filters">
<input type="text" data-filter-labels="{{ [{'id': 'mode', 'name': 'PLUGIN_ADMIN.PAGE_MODES'|t}, {'id': 'type', 'name': 'PLUGIN_ADMIN.PAGE_TYPES'|t}, {'id': 'access', 'name': 'PLUGIN_ADMIN.ACCESS_LEVELS'|t}] |json_encode|e('html_attr')}}" data-filter-types="{{ admin.types|merge(admin.modularTypes)|json_encode|e('html_attr') }}" data-filter-access-levels="{{ admin.accessLevels|json_encode|e('html_attr') }}" placeholder="{{ "PLUGIN_ADMIN.ADD_FILTERS"|t }}" class="page-filter" name="page-filter" />
</div>
<div class="page-search">
<input type="text" placeholder="{{ "PLUGIN_ADMIN.SEARCH_PAGES"|t }}" name="page-search" />
</div>
<div class="page-shortcuts">
<span class="button button-x-small" data-page-toggleall="expand"><i class="fa fa-fw fa-plus-circle"></i> {{ "PLUGIN_ADMIN.EXPAND_ALL"|t }}</span>
<span class="button button-x-small" data-page-toggleall="collapse"><i class="fa fa-fw fa-minus-circle"></i> {{ "PLUGIN_ADMIN.COLLAPSE_ALL"|t }}</span>
</div>
</form>
<div class="pages-list">
<ul class="depth-0">
{{ macro.loop(pages, 0, _context) }}
</ul>
{% include 'partials/page-legend.html.twig' %}
</div>
{% endif %}
</div>
{% if context %}
{% set obj_data = clone(context) %}
{% if mode == 'edit' %}
{% do obj_data.folder('') %}
{% endif %}
{% endif %}
{% if mode == 'list' or mode == 'edit' %}
<div class="remodal" data-remodal-id="modal" data-remodal-options="hashTracking: false, closeOnOutsideClick: false">
{% include 'partials/blueprints-new.html.twig' with { blueprints: admin.blueprints('admin/pages/new'), data: obj_data, form_id:'new-page' } %}
</div>
<div class="remodal" data-remodal-id="modal-folder" data-remodal-options="hashTracking: false">
{% include 'partials/blueprints-new-folder.html.twig' with { blueprints: admin.blueprints('admin/pages/new_folder'), data: obj_data, form_id:'new-folder' } %}
</div>
<div class="remodal" data-remodal-id="module" data-remodal-options="hashTracking: false, closeOnOutsideClick: false">
{% include 'partials/blueprints-new.html.twig' with { blueprints: admin.blueprints('admin/pages/modular_new'), data: obj_data, form_id:'new-modular' } %}
</div>
{% for key, add_modal in config.plugins.admin.add_modals %}
<div class="remodal {{ add_modal.modal_classes|defined('') }}" data-remodal-id="modal-add_modal-{{ key }}" data-remodal-options="hashTracking: false, closeOnOutsideClick: false">
{% include add_modal.template|defined('partials/blueprints-new.html.twig') with { blueprints: admin.blueprints(add_modal.blueprint), data: context, form_id:'add-modal' }|merge(add_modal.with|defined({})) %}
</div>
{% endfor %}
{% endif %}
<div class="remodal parents-container" data-remodal-id="parents" data-remodal-options="hashTracking: false, stack: true">
<form>
<h1>Parents</h1>
<div class="grav-loading"><div class="grav-loader">Loading...</div></div>
<div class="parents-content"></div>
<div class="button-bar">
<a class="button secondary remodal-cancel" data-remodal-action="cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</a>
<a class="button" data-parents-select href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
</div>
</form>
</div>
{% if mode == 'edit' %}
<div class="remodal parents-container" data-remodal-id="move" data-remodal-options="hashTracking: false">
{% include 'partials/page-move.html.twig' with { blueprints: admin.blueprints('admin/pages/move'), data: context } %}
</div>
<div class="remodal" data-remodal-id="revisions" data-remodal-options="hashTracking: false">
{% include ['partials/page-revisions.html.twig', 'empty.html.twig'] ignore missing with { data: context } %}
</div>
{% endif %}
{% include 'partials/modal-changes-detected.html.twig' %}
<div class="remodal" data-remodal-id="delete" data-remodal-optF#ions="hashTracking: false">
<form>
<h1>{{ "PLUGIN_ADMIN.MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE"|t }}</h1>
<p class="bigger">
{% if context %}
<strong>{{ "PLUGIN_ADMIN.PAGE"|t }}: {{ context.title }}</strong>
{% endif %}
</p>
<p class="bigger">
{{ "PLUGIN_ADMIN.MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_DESC"|t }}
</p>
{% if secure_delete %}
<p class="form-secure-delete">
<input id="secure-delete-field" autofocus type="text" placeholder="{{ "PLUGIN_ADMIN.SECURE_DELETE_DESC"|t }}" />
</p>
{% endif %}
<br>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
{% if secure_delete %}
<button id="secure-delete-btn" disabled="true" class="button danger disable-after-click" data-delete-action><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONFIRM"|t }}</button>
{% else %}
<a class="button danger disable-after-click" data-delete-action href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
{% endif %}
</div>
</form>
</div>
{% include 'partials/admin-pro-pages-addons.html.twig' ignore missing %}
{% endblock %}
{% block bottom %}
{{ parent() }}
<script>
$('.admin-pages .form-tabs .tabs-nav').css('margin-right', ($('#admin-topbar').width() + 20) + 'px');
{% if secure_delete %}
$('#secure-delete-field').keyup(function () {
var inputValue = $(this).val();
if (inputValue == 'DELETE') {
$('#secure-delete-btn').attr('disabled', false);
}else{
$('#secure-delete-btn').attr('disabled', true);
}
});
$(document).on('closing', '.remodal', function () {
$('#secure-delete-field').val('');
});
{% endif %}
</script>
{% endblock %}

View File

@@ -0,0 +1,21 @@
<div class="button-group">
{% set profiles = grav.backups.getBackupProfiles() %}
{% set backup_url = uri.addNonce(base_url_relative ~ "/backup.json/id" ~ config.system.param_sep ~ "%BACKUP_ID/task" ~ config.system.param_sep ~ "backup", 'admin-form', 'admin-nonce') %}
<button class="button" data-backup data-ajax="{{ backup_url|replace({'%BACKUP_ID':'0'}) }}">
<i class="fa fa-life-ring"></i> {{ "PLUGIN_ADMIN.BACKUP_NOW"|t }}
</button>
<button type="button" class="button dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu">
{% for id, profile in profiles %}
<li>
<a data-backup data-ajax="{{ backup_url|replace({'%BACKUP_ID':id}) }}" class="button">{{ profile.name }}</a>
</li>
{% endfor %}
<li>
<a href="{{ admin_route('/tools/backups') }}" class="button">Backups Manager</a>
</li>
</ul>
</div>

View File

@@ -0,0 +1,156 @@
{% if uri.extension() == 'json' %}{% include 'default.json.twig' %}{% else %}
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="utf-8" />
<title>{% if title %}{{ title|striptags|raw }} | {% else %}{% if header.title %}{{ header.title }} | {% endif %}{% endif %}{{ site.title }}</title>
{% if header.description %}
<meta name="description" content="{{ header.description }}">
{% else %}
<meta name="description" content="{{ site.description }}">
{% endif %}
{% if header.robots %}
<meta name="robots" content="{{ header.robots }}">
{% else %}
<meta name="robots" content="noindex, nofollow">
{% endif %}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="{{ base_url_simple }}{{ theme_url }}/images/favicon.png">
{% block stylesheets %}
{% include 'partials/stylesheets.html.twig' %}
{% endblock %}
{% include 'partials/javascript-config.html.twig' %}
{% block javascripts %}
{% include 'partials/javascripts.html.twig' %}
{% endblock %}
{% endblock %}
{% block assets deferred %}
{{ assets.css()|raw }}
{{ assets.js()|raw }}
{% endblock %}
<noscript>
<style>
.simplebar-content-wrapper {
overflow: auto;
}
</style>
</noscript>
</head>
{% block body %}
{% set sidebarStatus = get_cookie('grav-admin-sidebar') %}
{% set sidebarStatus = (sidebarStatus is not null and sidebarStatus == 'false') or config.plugins.admin.sidebar.size == 'small' ? 'sidebar-closed' : '' %}
<body class="ga-theme-17x {{ sidebarStatus }} {{ config.plugins.admin.body_classes }} {{ body_classes }}">
{% if not authorize(['admin.login']) %}
{% include 'partials/messages.html.twig' %}
{% else %}
{% block page %}
<div class="remodal-bg">
{% block navigation %}
{% include 'partials/nav.html.twig' %}
{% endblock %}
<main id="admin-main" >
{% include 'partials/nav-toggle.html.twig' %}
<div id="titlebar" class="titlebar">
{% block titlebar %}{% endblock %}
</div>
{% block content_wrapper %}
<div data-simplebar class="content-wrapper">
<div class="{% if config.plugins.admin.content_padding %}content-padding{% endif %}">
{% block messages %}
{% include 'partials/messages.html.twig' %}
{% endblock %}
{% block widgets %}{% endblock %}
<div class="default-box-shadow">
{% block content_top %}{% endblock %}
<div class="admin-block">
{%- block content %}{% endblock -%}
</div>
{% if config.plugins.admin.show_github_msg %}
<div class="notice alert"><i class="fa fa-github"></i> <a href="https://github.com/getgrav/grav-plugin-admin/issues" target="_blank" rel="noopener noreferrer">{{ 'PLUGIN_ADMIN.ADMIN_REPORT_ISSUE'|t }}</a></div>
{% endif %}
{% block content_bottom %}{% endblock %}
</div>
{% block footer %}
<footer id="footer">
{% include 'partials/footer.html.twig' %}
</footer>
{% endblock %}
</div>
</div>
{% endblock %}
{% block modals %}
<div class="remodal" data-remodal-id="generic" data-remodal-options="hashTracking: false">
<form>
<h1>{{ "PLUGIN_ADMIN.ERROR"|t }}</h1>
<div class="error-content"></div>
<div class="button-bar">
<a class="button remodal-cancel" data-remodal-action="cancel" href="#">{{ "PLUGIN_ADMIN.CLOSE"|t }}</a>
</div>
</form>
</div>
<div class="remodal" data-remodal-id="metadata" data-remodal-options="hashTracking: false">
<form>
<h1><span>{{ "PLUGIN_ADMIN.METADATA"|t }} for</span> <strong></strong></h1>
<div class="metadata-preview">
<div class="meta-preview"></div>
<div class="meta-content"></div>
</div>
<div class="button-bar">
<a class="button remodal-cancel" data-remodal-action="cancel" href="#">{{ "PLUGIN_ADMIN.CLOSE"|t }}</a>
</div>
</form>
</div>
<div class="remodal" data-remodal-id="delete-media" data-remodal-options="hashTracking: false">
<form>
<h1>{{ "PLUGIN_ADMIN.MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE"|t }}</h1>
<p class="bigger">
{{ "PLUGIN_ADMIN.MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_DESC"|t }}
</p>
<br>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<button data-remodal-action="confirm" class="button remodal-confirm disable-after-click"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</button>
</div>
</form>
</div>
<div class="remodal" data-remodal-id="update-grav" data-remodal-options="hashTracking: false">
<form>
<h1>{{ "PLUGIN_ADMIN.MODAL_DELETE_FILE_CONFIRMATION_REQUIRED_TITLE"|t }}</h1>
<p class="bigger">
{{ "PLUGIN_ADMIN.MODAL_UPDATE_GRAV_CONFIRMATION_REQUIRED_DESC"|t }}
</p>
<br>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<button data-remodal-action="confirm" class="button remodal-confirm disable-after-click"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</button>
</div>
</form>
</div>
{% endblock %}
</main>
<div id='overlay'></div>
</div>
{% endblock page %}
{% endif %}
{% block bottom %}
{{ assets.js('bottom')|raw }}
{% endblock %}
</body>
{% endblock body %}
</html>
{% endif %}

View File

@@ -0,0 +1 @@
{% extends 'partials/base-root.html.twig' %}

View File

@@ -0,0 +1,19 @@
{% set form_id = form_id ? form_id : 'blueprints' %}
{% set scope = scope ?: 'data.' %}
{% set field_layout = 'admin' %}
<form {% if form_action %}action="{{ form_action }}"{% endif %} id="{{ form_id }}" method="post" data-grav-form="{{ form_id }}" {% if form.novalidate %}novalidate{% endif %} data-grav-keepalive="true">
{% embed 'forms/default/fields.html.twig' with {name: null, fields: blueprints.fields} %}
{% block inner_markup_field_open %}<div class="block block-{{ field.type }}">{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
<input type="hidden" name="task" value="copy" />
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<button class="button success" {#data-flex-safe-action#}><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</button>
</div>
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
</form>

View File

@@ -0,0 +1,18 @@
{% set form_id = form_id ? form_id : 'blueprints' %}
{% set scope = scope ?: 'data.' %}
{% set field_layout = 'admin' %}
<form {% if form_action %}action="{{ form_action }}"{% endif %} id="{{ form_id }}" method="post" data-grav-form="{{ form_id }}" data-grav-keepalive="true">
{% embed 'forms/default/fields.html.twig' with {name: null, fields: blueprints.fields} %}
{% block inner_markup_field_open %}<div class="block block-{{ field.type }}">{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
<input type="hidden" name="task" value="saveNewFolder" />
<div class="button-bar">
<button class="button primary">{{ "PLUGIN_ADMIN.SAVE"|t }}</button>
</div>
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
</form>

View File

@@ -0,0 +1,19 @@
{% set form_id = form_id ? form_id : 'blueprints' %}
{% set scope = scope ?: 'data.' %}
{% set field_layout = 'admin' %}
<form {% if form_action %}action="{{ form_action }}"{% endif %} id="{{ form_id }}" method="post" data-grav-form="{{ form_id }}" {% if form.novalidate %}novalidate{% endif %} data-grav-keepalive="true">
{% embed 'forms/default/fields.html.twig' with {name: null, fields: blueprints.fields} %}
{% block inner_markup_field_open %}<div class="block block-{{ field.type }}">{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
<input type="hidden" name="task" value="continue" />
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<button class="button success"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</button>
</div>
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
</form>

View File

@@ -0,0 +1,22 @@
{% set form_id = form_id ? form_id : 'blueprints' %}
{% set scope = scope ?: 'data.' %}
{% set field_layout = 'admin' %}
{% if admin.findFormFields('file', blueprints.fields) %}
{% set multipart = ' enctype="multipart/form-data"' %}
{% endif %}
<form {% if form_action %}action="{{ form_action }}"{% endif %} id="{{ form_id }}" method="post" data-grav-form="{{ form_id }}" data-grav-keepalive="true"{{ multipart|raw }}>
{% embed 'forms/default/fields.html.twig' with {name: null, fields: blueprints.fields} %}
{% block inner_markup_field_open %}<div class="block block-{{ field.type }}">{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
{% if form %}
{% include "forms/fields/formname/formname.html.twig" %}
{% include 'forms/fields/uniqueid/uniqueid.html.twig' %}
{{ nonce_field(form.getNonceAction(), form.getNonceName())|raw }}
{% else %}
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
{% endif %}
</form>

View File

@@ -0,0 +1,34 @@
{% set blueprints = blueprints ?? form.blueprint %}
{% set data = data ?? form.data %}
{% set form_id = form_id ?? 'blueprints' %}
{% set scope = scope ?: 'data.' %}
{% set field_layout = 'admin' %}
{% if admin.findFormFields('file', blueprints.fields) %}
{% set multipart = ' enctype="multipart/form-data"' %}
{% endif %}
<form {% if form_action %}action="{{ form_action }}"{% endif %} id="{{ form_id }}" method="post" data-grav-form="{{ form_id }}" {% if form.novalidate %}novalidate{% endif %} data-grav-keepalive="true"{{ multipart|raw }}>
{% embed 'forms/default/fields.html.twig' with {name: null, fields: blueprints.fields} %}
{% block inner_markup_field_open %}<div class="block block-{{ field.type }}">{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
{% if data.extra %}
{% for name, value in data.extra %}
{% if name not in ['_json','task','admin-nonce'] %}
{% set field = {name: '_json.' ~ name} %}
{% set value = value|json_encode %}
{% include 'forms/fields/hidden/hidden.html.twig' %}
{% endif %}
{% endfor %}
{% endif %}
{% if form %}
{% include "forms/fields/formname/formname.html.twig" %}
{% include 'forms/fields/uniqueid/uniqueid.html.twig' %}
{{ nonce_field(form.getNonceAction(), form.getNonceName())|raw }}
{% else %}
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
{% endif %}
</form>

View File

@@ -0,0 +1,14 @@
<div id="news-feed" class="dashboard-item admin-block default-box-shadow">
<h1>
{{ "PLUGIN_ADMIN.NEWS_FEED"|t }}
<span class="right">
<a href="#" class="button button-small" data-refresh="feed"><i class="fa fa-refresh"></i></a>
</span>
</h1>
<div class="widget-content">
<div class="widget-loader"><i class="fa fa-refresh fa-spin"></i></div>
<ul></ul>
</div>
</div>

View File

@@ -0,0 +1,33 @@
{% if authorize(['admin.maintenance', 'admin.super']) %}
{% set backup = admin.lastBackup() %}
<div id="updates" class="dashboard-item dashboard-left">
<div class="secondary-accent default-box-shadow">
<h1>{{ "PLUGIN_ADMIN.MAINTENANCE"|t }}</h1>
<div class="admin-update-charts">
<div class="updates-chart" data-chart-name="updates" data-chart-type="pie" data-chart-data="{{ {'series': [100, 0]}|json_encode|e('html_attr') }}">
<div class="chart-wrapper">
<div class="ct-chart chart-loader"><i class="fa fa-refresh fa-spin"></i></div>
<span class="numeric hidden"><span>-</span><em>{{ "PLUGIN_ADMIN.UPDATED"|t|lower }}</em></span>
</div>
<p class="js__updates-available-description">&nbsp;</p>
</div>
<div class="backups-chart" data-chart-name="backups" data-chart-type="pie" data-chart-data="{{ {'series': [backup.chart_fill, backup.chart_empty]}|json_encode|e('html_attr') }}">
<div class="chart-wrapper">
<div class="ct-chart chart-loader"><i class="fa fa-refresh fa-spin"></i></div>
<span class="numeric hidden">{{ backup.days|raw }}<em>{{ "PLUGIN_ADMIN.DAYS"|t|lower }}</em></span>
</div>
<p class="hidden">{{ "PLUGIN_ADMIN.LAST_BACKUP"|t }}</p>
</div>
</div>
<div class="flush-bottom button-bar">
<a class="button hidden" href="#" data-update-packages data-remodal-target="update-packages" data-plugin-action="start-packages-update"><i class="fa fa-cloud-download"></i> {{ "PLUGIN_ADMIN.UPDATE"|t }}</a>
{% include 'partials/backups-button.html.twig' %}
</div>
</div>
</div>
{% include 'partials/modal-update-packages.html.twig' with { type: 'plugin' } %}
{% endif %}

View File

@@ -0,0 +1,13 @@
<div id="notifications" class="dashboard-item admin-block default-box-shadow">
<h1>
{{ "PLUGIN_ADMIN.NOTIFICATIONS"|t }}
<span class="right">
<a href="#" class="button button-small" data-refresh="notifications"><i class="fa fa-refresh"></i></a>
</span>
</h1>
<div class="widget-content">
<div class="widget-loader"><i class="fa fa-refresh fa-spin"></i></div>
<ul></ul>
</div>
</div>

View File

@@ -0,0 +1,18 @@
{% if authorize(['admin.pages.list', 'admin.pages', 'admin.super']) %}
<div id="latest">
<div class="button-bar">
<a class="button" href="{{ admin_route('/pages') }}"><i class="fa fa-fw fa-file-text-o"></i>{{ "PLUGIN_ADMIN.MANAGE_PAGES"|t }}</a>
</div>
<h1>{{ "PLUGIN_ADMIN.LATEST_PAGE_UPDATES"|t }}</h1>
<table>
{% for latest in admin.latestPages if admin.latestPages %}
{% set route = latest.rawRoute %}
<tr>
<td class="triple page-title">
<a href="{{ admin_route('/pages/' ~ route|trim('/')) }}"><i class="fa fa-fw fa-file-text-o"></i> {{ latest.title }}</a></td>
<td class="triple page-route">{{ route }}</td><td>{{ latest.modified|adminNicetime }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endif %}

View File

@@ -0,0 +1,11 @@
{% if authorize(['admin.plugins', 'admin.super']) and grav['flex_objects'] is null %}
<div id="dependency-missing" class="dashboard-item-flex">
<div class="alert warning">
<h1>Admin plugin dependency is missing</h1>
<p>Admin now requires the Flex Objects plugin for managing <em>User Accounts</em> and <em>Flex Pages</em>. For more information, please <a href="https://learn.getgrav.org/17/admin-panel/faq#flex-objects">check the documentation</a>.</p>
<p><a href="{{ admin_route('/plugins/flex-objects') }}" class="button"><i class="fa fa-download"></i> Install and enable Flex Objects plugin</a></p>
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,24 @@
{% if authorize(['admin.statistics', 'admin.super']) %}
<div id="popularity" class="dashboard-item dashboard-right" data-chart-name="popularity" data-chart-type="bar" data-chart-data="{{ {'series': [popularity.getDailyChartData['data']], 'labels': popularity.getDailyChartData['labels']}|json_encode|e('html_attr') }}">
<div class="primary-accent default-box-shadow">
<h1>{{ "PLUGIN_ADMIN.VIEWS_STATISTICS"|t }}</h1>
<div class="admin-statistics-chart">
<div class="ct-chart chart-loader"><i class="fa fa-refresh fa-spin"></i></div>
<div class="flush-bottom button-bar stats-bar">
<span class="stat">
<b>{{ popularity.getDailyTotal }}</b>
<i>{{ "PLUGIN_ADMIN.TODAY"|t }}</i>
</span>
<span class="stat">
<b>{{ popularity.getWeeklyTotal }}</b>
<i>{{ "PLUGIN_ADMIN.WEEK"|t }}</i>
</span>
<span class="stat">
<b>{{ popularity.getMonthlyTotal }}</b>
<i>{{ "PLUGIN_ADMIN.MONTH"|t }}</i>
</span>
</div>
</div>
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,3 @@
{% for entry in feed %}
<li><span class="date">{{ entry.nicetime }}</span> <a href="{{ entry.url }}" target="_blank" title="{{ entry.title|striptags|e('html_attr') }}">{{ entry.title }}</a>
{% endfor %}

View File

@@ -0,0 +1,5 @@
{% if custom_admin_footer %}
{{ custom_admin_footer|raw }}
{% else %}
<a href="https://getgrav.org" target="_blank" rel="noopener noreferrer">Grav</a> v<span class="grav-version">{{ constant('GRAV_VERSION') }}</span> - Admin v{{ admin_version }} - {{ "PLUGIN_ADMIN.WAS_MADE_WITH"|t|lower }} <i class="fa fa-heart-o pulse"></i> {{ "PLUGIN_ADMIN.BY"|t|lower }} <a href="https://trilby.media" target="_blank" rel="noopener noreferrer">Trilby Media</a>.
{% endif %}

View File

@@ -0,0 +1,11 @@
<nav id="nav">
<ul>
{% for page in pages %}
{% if page.visible %}
<li>
<a href="{{ page.url }}">{{ page.menu }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</nav>

View File

@@ -0,0 +1,43 @@
{% if user.authorized and authorize(['admin.login', 'admin.super']) %}
{% set notifications = (config.plugins.admin.widgets['dashboard-notifications'] or config.plugins.admin.notifications.dashboard or config.plugins.admin.notifications.plugins or config.plugins.admin.notifications.themes) ? 1 : 0 %}
{% switch template_route %}
{% case 'dashboard' %}
{% set notifications_filters = "['feed', 'dashboard', 'top']" %}
{% case 'plugins' %}
{% set notifications_filters = "['plugins', 'top']" %}
{% case 'themes' %}
{% set notifications_filters = "['themes', 'top']" %}
{% default %}
{% set notifications_filters = "['top']" %}
{% endswitch %}
<script type="text/javascript">
window.GravAdmin = window.GravAdmin || {};
window.GravAdmin.config = {
current_url: '{{ uri.getCurrentRoute().withLanguage(grav.language.active).withExtension('').withoutParams().toString(true) }}',
base_url_relative: '{{ base_url_relative }}',
base_url_simple: '{{ base_url_simple }}',
route: '{{ admin.route|trim('/') }}',
param_sep: '{{ config.system.param_sep }}',
{% if authorize(['admin.maintenance', 'admin.super']) %}
enable_auto_updates_check: '{{ config.plugins.admin.enable_auto_updates_check }}',
{% endif %}
admin_timeout: '{{ config.plugins.admin.session.timeout ?: 1800 }}',
admin_nonce: '{{ admin.getNonce }}',
language: '{{ grav.user.language|default('en') }}',
pro_enabled: '{{ config.plugins["admin-pro"].enabled }}',
notifications: {
enabled: {{ notifications }},
filters: {{ notifications_filters|raw }}
},
local_notifications: '{{ config.system.local_notifications|default(false) }}',
site: {
delimiter: '{{ config.site.summary.delimiter|default('===') }}'
}
};
window.GravAdmin.uri_params = {};
{% for param, value in grav.uri.params(null, true) %}
window.GravAdmin.uri_params[{{ param|json_encode|raw }}] = "{{value|replace({'\\': '/'})}}";
{% endfor %}
</script>
{% endif %}

View File

@@ -0,0 +1,11 @@
{% do assets.add('jquery',101) %}
{% if authorize(['admin.login', 'admin.super']) %}
{% do assets.addJs(theme_url~'/js/vendor.min.js', { 'loading':'defer' }) %}
{% do assets.addJs(theme_url~'/js/admin.min.js' , { 'loading':'defer' }) %}
{% if browser.getBrowser == 'msie' or browser.getBrowser == 'edge' %}
{% do assets.addJs(theme_url~'/js/form-attr.polyfill.js') %}
{% endif %}
{% include 'partials/javascripts-extra.html.twig' ignore missing %}
{% endif %}

View File

@@ -0,0 +1,13 @@
<form class="sort-actions" data-grav-selectize="true">
<select>
<option value="name" selected>{{ "PLUGIN_ADMIN.NAME"|t }}</option>
<option value="author">{{ "PLUGIN_ADMIN.AUTHOR"|t }}</option>
<option value="official">GravTeam</option>
<option value="premium">Premium</option>
<option value="release-date">{{ "PLUGIN_ADMIN.RELEASE_DATE"|t }}</option>
{% if list_view == 'plugins' and not installing %}<option value="enabled">{{ "PLUGIN_ADMIN.ENABLED"|t }}</option>{% endif %}
{% if not installing %}<option value="updatable">{{ "PLUGIN_ADMIN.UPDATES_AVAILABLE"|t }}</option>{% endif %}
{% if config.system.gpm.releases == 'testing' %}<option value="testing">{{ "PLUGIN_ADMIN.TESTING"|t }}</option>{% endif %}
</select>
<div class="sort-icon"><i class="fa fa-fw fa-sort-amount-asc"></i></div>
</form>

View File

@@ -0,0 +1,25 @@
{% embed 'partials/login.html.twig' with {title: 'Grav Admin Login'} %}
{% block integration %}
{# NEW WAY OF INCLUDING 3RD PARTY LOGIN OPTIONS #}
{% for template in grav.login.getProviderLoginTemplates %}
{% include template %}
{% endfor %}
{% endblock %}
{% block form %}
{% embed 'forms/default/fields.html.twig' with {name: null, fields: form.fields} %}
{% block inner_markup_field_open %}<div>{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
<div class="form-actions primary-accent">
<a class="button secondary" href="{{ admin_route('/forgot') }}"><i class="fa fa-exclamation-circle"></i> {{ 'PLUGIN_ADMIN.LOGIN_BTN_FORGOT'|t }}</a>
<button type="submit" class="button primary" name="task" value="login"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGIN_BTN'|t }}</button>
</div>
{% endblock %}
{% endembed %}

View File

@@ -0,0 +1,14 @@
{% if config.plugins.admin.logo_text %}
<h1 class="text-logo">
{{ config.plugins.admin.logo_text }}
</h1>
{% else %}
<h1 class="{{ custom_login_logo ? 'custom-logo' : 'default-logo' }}">
{{ title }}
{% if custom_login_logo %}
<img src="{{ url(custom_login_logo) }}" title="Login" />
{% else %}
{% include('@admin-images/logo.svg') %}
{% endif %}
</h1>
{% endif %}

View File

@@ -0,0 +1,15 @@
{% embed 'partials/login.html.twig' with {title:'Grav Admin Logout'} %}
{% block integration %}
{% endblock %}
{% block form %}
<div class="form-actions primary-accent">
<a class="button secondary" onclick="window.history.back()"><i class="fa fa-reply"></i> {{ 'PLUGIN_ADMIN.BACK'|t }}</a>
<button type="submit" class="button primary" name="task" value="logout"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_ADMIN.LOGOUT'|t }}</button>
</div>
{% endblock %}
{% endembed %}

View File

@@ -0,0 +1,20 @@
{% embed 'partials/login.html.twig' with {title:'Grav 2-Factor Authentication', redirect: admin.session.redirect} %}
{% block integration %}
{% endblock %}
{% block form %}
{% embed 'forms/default/fields.html.twig' with {name: null, fields: form.fields} %}
{% block inner_markup_field_open %}<div>{% endblock %}
{% block inner_markup_field_close %}</div>{% endblock %}
{% endembed %}
<div class="{{ form_button_outer_classes ?: 'form-actions primary-accent' }}">
<div class="form-actions primary-accent">
<button type="submit" class="button primary" name="task" value="twofa"><i class="fa fa-sign-in"></i> {{ 'PLUGIN_LOGIN.BTN_LOGIN'|t }}</button>
</div>
</div>
{% endblock %}
{% endembed %}

View File

@@ -0,0 +1,33 @@
{% extends 'partials/base.html.twig' %}
{% set scope = form.scope %}
{% set field_layout = 'admin' %}
{% block messages %}{% endblock %}
{% block body %}
<body id="admin-login-wrapper">
<section id="admin-login" class="login-box-shadow {{ classes }}">
{% include 'partials/login-logo.html.twig' %}
{% include 'partials/messages.html.twig' %}
{% block instructions %}{% endblock %}
{% block integration %}{% endblock %}
<form method="post" action="">
<div class="padding">
{% block form %}{% endblock %}
{{ nonce_field(form.getNonceAction(), form.getNonceName())|raw }}
</div>
</form>
<script>
$(document).ready( function() {
$('#messages').delay(5000).animate({ height: 'toggle', opacity: 'toggle' }, 'slow');
});
</script>
</section>
</body>
{% endblock %}

View File

@@ -0,0 +1,20 @@
{% if config.plugins.admin.logo_text %}
<h3>
<a href="{{ admin_route('/') }}">
{{ config.plugins.admin.logo_text }}
</a>
<a class="front-end hint--left" data-hint="{{ "PLUGIN_ADMIN.VIEW_SITE_TIP"|t }}" target="_blank" href="{{ base_url_relative_frontend }}"> <i class="fa fa-external-link"></i></a>
</h3>
{% else %}
<div class="admin-logo {{ custom_admin_logo ? 'custom-logo' : 'default-logo' }}">
<a href="{{ admin_route('/') }}">
{% if custom_admin_logo %}
<img src="{{ url(custom_admin_logo) }}" title="{{ site.title }}" />
{% else %}
{% include('@admin-images/grav-small.svg') %}
{% include('@admin-images/grav-regular.svg') %}
{% endif %}
</a>
<a class="front-end hint--left" data-hint="{{ "PLUGIN_ADMIN.VIEW_SITE_TIP"|t }}" target="_blank" href="{{ base_url_relative_frontend }}"> <i class="fa fa-external-link"></i></a>
</div>
{% endif %}

View File

@@ -0,0 +1,32 @@
<div class="grid media-container {% if is_modal %}in-modal{% endif %}">
{% set default_site_lang = grav.config.system.languages|first|first %}
{% if not route %}
{% include 'partials/media-list-wrapper__sidebar.html.twig' %}
{% endif %}
{% if is_modal %}
<div class="thumbs-list-container block size-3-4">
{% include 'partials/media-list-wrapper__list__filters.html.twig' %}
<h5 class="media-list-title"><span class="page-indicator">All Pages</span> <a class="hidden js__reset-pages-filter" href="#"><i class="fa fa-fw fa-times"></i></a></h5>
<div class="mediapicker-scroll">
{% include 'partials/media-list-wrapper__list.html.twig' with { is_modal: is_modal } %}
</div>
<input name="thumb-size" class="media-range" type="range" min="50" max="250" value="100" />
</div>
{% else %}
<div class="thumbs-list-container block {% if not route %}size-2-3{% endif %} ">
{% if not route %}
{% include 'partials/media-list-wrapper__list__filters.html.twig' %}
<h5 class="media-list-title"><span class="page-indicator">All Pages</span> <a class="hidden js__reset-pages-filter" href="#"><i class="fa fa-fw fa-times"></i></a></h5>
{% include 'partials/media-list-wrapper__list.html.twig' with { is_modal: is_modal } %}
{% else %}
{% include 'partials/media-list-wrapper__details.html.twig' %}
{% endif %}
</div>
{% endif %}
</div>

View File

@@ -0,0 +1,23 @@
<div id="admin-media" class="files js__files card-row grid fixed-blocks pure-g">
{% if not is_modal %}
{% include 'partials/media-list-wrapper__list__dropzone.html.twig' ignore missing %}
{% endif %}
{% if admin.files is empty %}
<div class="empty-state">
{% if (uri.param('type') or uri.param('date')) %}
<h2>Filtering by {{ uri.param('type') }} {{ uri.param('date') }}</h2>
{% endif %}
<h2>No media files found</h2>
<p>You need to add media to a page in order to display it here.</p>
</div>
{% else %}
{% include 'media-list-content.html.twig' with { is_modal: is_modal } %} {# not a partial as used by AJAX #}
{% endif %}
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
</div>
{% include 'partials/spinning-wheel.html.twig' %}

View File

@@ -0,0 +1,28 @@
<div>
<div class="filter-wrapper filter-type">
<select class="filter js__filter" data-name="type" data-grav-selectize>
<option value="*" {% if not grav.uri.param('type') %}selected{% endif %}>All Files</option>
<option value="images" {% if grav.uri.param('type') == 'images' %}selected{% endif %}>Images</option>
<option value="videos"{% if grav.uri.param('type') == 'videos' %}selected{% endif %}>Videos</option>
<option value="audios"{% if grav.uri.param('type') == 'audios' %}selected{% endif %}>Audio</option>
<option value="files"{% if grav.uri.param('type') == 'files' %}selected{% endif %}>Files</option>
</select>
</div>
<div class="filter-wrapper filter-date">
<select class="filter js__filter" data-name="date" data-grav-selectize>
<option value="*">All Dates</option>
{% set theDate = date() %}
{% for year, months in admin.filesDates %}
<optgroup label="{{year}}">
{% for month, number in months %}
<option value="{{year}}-{{month}}" {% if grav.uri.param('date') == year~'-'~month %}selected{% endif %}>
{{theDate.setDate(theDate.format('Y'), month, theDate.format('d'))|date('M')}}
({{number}})</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
</div>
</div>

View File

@@ -0,0 +1,36 @@
{% macro loop(page, depth, twig_vars) %}
{% import _self as self %}
{% for p in page.children() %}
<li class="page-item" data-nav-id="{{ p.route }}">
<div class="row">
<span {{ p.children(0).count > 0 ? 'data-toggle="children"' : ''}} class="hint--bottom">
<i class="page-icon fa fa-fw fa-circle-o {{ p.children(0).count > 0 ? 'children-closed' : ''}} {{ p.isModule ? 'modular' : (not p.routable ? 'not-routable' : (not p.visible ? 'not-visible' : (not p.page ? 'folder' : ''))) }}"></i>
</span>
<span data-hint="{{ p.header.routes.default ?: p.route }}" class="hint--bottom">
<a data-page="{{ p.route }}" class="js__page-link page-link" href="#">{{ p.title }}</a>
</span>
<span class="page-home">{{ p.home ? '<i class="fa fa-home"></i>' }}</span>
</div>
{% if p.children().count > 0 %}
<ul class="depth-{{ depth + 1 }}" style="display:none;">
{{ self.loop(p, depth + 1, twig_vars) }}
</ul>
{% endif %}
</li>
{% endfor %}
{% endmacro %}
{% import _self as macro %}
<div class="pages-list-container clear block size-1-4">
<h5>{{ "PLUGIN_ADMIN.PAGES"|t }}</h5>
<div class="mediapicker-scroll">
<ul class="pages-list depth-0">
{{ macro.loop(pages, 0, _context) }}
</ul>
</div>
</div>

View File

@@ -0,0 +1,14 @@
{% set admin_messages = admin.messages|merge(admin.getTempMessages()) %}
{% set form_message = form.message %}
<div id="messages" class="top-notifications-container{{ admin_messages|length or form_message ? ' default-box-shadow' : '' }}">
<div class="single-notification info alert hidden" data-gpm-grav></div>
{%- for message in admin_messages -%}
<div class="{{ message.scope }} alert">{{ message.message|raw }}</div>
{%- endfor -%}
{%- if form_message -%}
<div class="error alert">{{ form_message|raw }}</div>
{%- endif -%}
{%- for message in plugin_messages -%}
<div class="{{ message.scope }} alert">{{ message.message|raw }}</div>
{%- endfor -%}
</div>

View File

@@ -0,0 +1,89 @@
<div class="remodal"
data-packages-modal
data-remodal-id="add-package"
data-remodal-options="hashTracking: false">
<form>
<div class="add-package-installing">
<h1>{{ "PLUGIN_ADMIN.INSTALLING"|t }}</h1>
<div class="loading">
<p>
{{ "PLUGIN_ADMIN.LOADING"|t }}
<span class="fa fa-spin fa-spinner"></span>
</p>
</div>
<div class="install-dependencies-package-container hidden">
<p><strong>{{ "PLUGIN_ADMIN.DEPENDENCIES_NOT_MET_MESSAGE"|t }}</strong></p>
<div class="type-install hidden">
<p>{{ "PLUGIN_ADMIN.PACKAGES_NOT_INSTALLED"|t }}:</p>
<ul></ul>
</div>
<div class="type-update hidden">
<p>{{ "PLUGIN_ADMIN.PACKAGES_NEED_UPDATE"|t }}:</p>
<ul></ul>
</div>
<div class="type-ignore hidden">
<p>{{ "PLUGIN_ADMIN.PACKAGES_SUGGESTED_UPDATE"|t }}:</p>
<ul></ul>
</div>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<a data-{{ type }}-action="install-dependencies-and-package" class="button"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
</div>
</div>
<div class="install-package-container hidden">
<p>
{{ "PLUGIN_ADMIN.READY_TO_INSTALL_PACKAGES"|t }}
</p>
<ul class="packages-names-list"></ul>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<a data-{{ type }}-action="install-package" class="button"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
</div>
</div>
<div class="install-package-error hidden">
<p>
{{ "PLUGIN_ADMIN.ERROR_INSTALLING_PACKAGES"|t }}
</p>
<ul class="packages-names-list"></ul>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CLOSE"|t }}</button>
</div>
</div>
<div class="installing-dependencies hidden">
<p>
{{ "PLUGIN_ADMIN.INSTALLING_DEPENDENCIES"|t }}
<span class="fa fa-spin fa-spinner"></span>
</p>
</div>
<div class="installing-package hidden">
<p>
{{ "PLUGIN_ADMIN.INSTALLING_PACKAGES"|t }}
<span class="fa fa-spin fa-spinner"></span>
</p>
<ul class="packages-names-list"></ul>
</div>
<div class="installation-complete hidden">
<p>
{{ "PLUGIN_ADMIN.PACKAGES_SUCCESSFULLY_INSTALLED"|t }}
</p>
<ul class="packages-names-list"></ul>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1 @@
<div class="remodal" data-remodal-id="changelog" data-remodal-options="hashTracking: false"></div>

View File

@@ -0,0 +1,13 @@
<div class="remodal" data-remodal-id="changes">
<form>
<h1>{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_TITLE"|t }}</h1>
<p class="bigger">
{{ "PLUGIN_ADMIN.MODAL_CHANGED_DETECTED_DESC"|t }}
</p>
<br>
<div class="button-bar">
<a class="button secondary" data-leave-action="cancel" href="#"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</a>
<a class="button" data-leave-action="continue" href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
</div>
</form>
</div>

View File

@@ -0,0 +1,38 @@
<div class="remodal"
data-remodal-id="reinstall-package"
data-remodal-options="hashTracking: false">
<form>
<div class="reinstall-package-confirm">
<h1>{{ "PLUGIN_ADMIN.REINSTALL_THE"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}</h1>
<p class="bigger">
{{ "PLUGIN_ADMIN.CONFIRM_REINSTALL"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}
</p>
<p class="bigger hidden warning-reinstall-not-latest-release">
{{ "PLUGIN_ADMIN.WARNING_REINSTALL_NOT_LATEST_RELEASE"|t }}
</p>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<button data-{{ type }}-action="reinstall-package"
data-package-slug="{{ package.slug }}"
data-package-type="{{ package.package_type }}"
data-package-name="{{ package.name }}"
data-package-current-version="{{ package.version }}"
class="button"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</button>
<div class="spinning-wheel hidden">
{{ "PLUGIN_ADMIN.INSTALLING"|t }}.. <i class="fa fa-spinner fa-spin"></i>
</div>
</div>
</div>
<div class="reinstall-package-done hidden">
<h1>{{ "PLUGIN_ADMIN.REINSTALLED_SUCCESSFULLY"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}</h1>
</div>
<div class="reinstall-package-error hidden">
<h1>{{ "PLUGIN_ADMIN.ERROR_REINSTALLING_THE"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}</h1>
</div>
</form>
</div>

View File

@@ -0,0 +1,44 @@
<div class="remodal"
data-remodal-id="remove-package"
data-remodal-options="hashTracking: false">
<form>
<div class="remove-package-confirm">
<h1>{{ "PLUGIN_ADMIN.REMOVE_THE"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}</h1>
<p class="bigger">
{{ "PLUGIN_ADMIN.CONFIRM_REMOVAL"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}
</p>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<button data-{{ type }}-action="remove-package" data-packages-slugs="{{ package.slug }}" class="button"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</button>
</div>
</div>
<div class="remove-package-dependencies hidden">
<h1>{{ "PLUGIN_ADMIN.REMOVED_SUCCESSFULLY"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}</h1>
<p>
{{ "PLUGIN_ADMIN.ADDITIONAL_DEPENDENCIES_CAN_BE_REMOVED"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}
</p>
<div>
<ul class="package-dependencies-container"></ul>
</div>
<div class="button-bar">
<a href="{{ admin_route('/' ~ type ~ 's') }}" class="button secondary"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CLOSE"|t }}</a>
</div>
</div>
<div class="remove-package-done hidden">
<h1>{{ "PLUGIN_ADMIN.REMOVED_SUCCESSFULLY"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}</h1>
<div class="button-bar">
<a href="{{ admin_route('/' ~ type ~ 's') }}" class="button secondary"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CLOSE"|t }}</a>
</div>
</div>
<div class="remove-package-error hidden">
<h1>{{ "PLUGIN_ADMIN.ERROR_REMOVING_THE"|t(("PLUGIN_ADMIN." ~ type|upper)|t) }}</h1>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,16 @@
<div class="remodal theme-switcher" data-remodal-id="theme-switch-warn" data-remodal-options="hashTracking: false">
<form>
<h1>{{ "PLUGIN_ADMIN.SWITCHING_TO"|t }} <strong>{theme_name}</strong></h1>
<p class="bigger">
{{ "PLUGIN_ADMIN.SWITCHING_TO_DESCRIPTION"|t }}
</p>
<p class="bigger">
{{ "PLUGIN_ADMIN.SWITCHING_TO_CONFIRMATION"|t }} <strong>{theme_name}</strong>?
</p>
<br>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<a class="button continue" href="#"><i class="fa fa-fw fa-check"></i>{{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
</div>
</form>
</div>

View File

@@ -0,0 +1,89 @@
<div class="remodal"
data-packages-modal
data-remodal-id="update-packages"
data-remodal-options="hashTracking: false">
<form>
<div class="add-package-installing">
<h1>{{ "PLUGIN_ADMIN.UPDATING"|t }}</h1>
<div class="loading">
<p>
{{ "PLUGIN_ADMIN.LOADING"|t }}
<span class="fa fa-spin fa-spinner"></span>
</p>
</div>
<div class="install-dependencies-package-container hidden">
<p><strong>{{ "PLUGIN_ADMIN.DEPENDENCIES_NOT_MET_MESSAGE"|t }}</strong></p>
<div class="type-install hidden">
<p>{{ "PLUGIN_ADMIN.PACKAGES_NOT_INSTALLED"|t }}:</p>
<ul></ul>
</div>
<div class="type-update hidden">
<p>{{ "PLUGIN_ADMIN.PACKAGES_NEED_UPDATE"|t }}:</p>
<ul></ul>
</div>
<div class="type-ignore hidden">
<p>{{ "PLUGIN_ADMIN.PACKAGES_SUGGESTED_UPDATE"|t }}:</p>
<ul></ul>
</div>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<a data-{{ type }}-action="install-dependencies-and-package" class="button"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
</div>
</div>
<div class="install-package-container hidden">
<p>
{{ "PLUGIN_ADMIN.READY_TO_UPDATE_PACKAGES"|t }}
</p>
<ul class="packages-names-list"></ul>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CANCEL"|t }}</button>
<a data-{{ type }}-action="install-package" class="button"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|t }}</a>
</div>
</div>
<div class="install-package-error hidden">
<p>
{{ "PLUGIN_ADMIN.ERROR_UPDATING_PACKAGES"|t }}
</p>
<ul class="packages-names-list"></ul>
<div class="button-bar">
<button data-remodal-action="cancel" class="button secondary remodal-cancel"><i class="fa fa-fw fa-close"></i> {{ "PLUGIN_ADMIN.CLOSE"|t }}</button>
</div>
</div>
<div class="installing-dependencies hidden">
<p>
{{ "PLUGIN_ADMIN.INSTALLING_DEPENDENCIES"|t }}
<span class="fa fa-spin fa-spinner"></span>
</p>
</div>
<div class="installing-package hidden">
<p>
{{ "PLUGIN_ADMIN.UPDATING_PACKAGES"|t }}
<span class="fa fa-spin fa-spinner"></span>
</p>
<ul class="packages-names-list"></ul>
</div>
<div class="installation-complete hidden">
<p>
{{ "PLUGIN_ADMIN.PACKAGES_SUCCESSFULLY_UPDATED"|t }}
</p>
<ul class="packages-names-list"></ul>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,47 @@
{% set clear_cache_url = base_url_relative ~ '/cache.json/task' ~ config.system.param_sep ~ 'clearCache'|e('html_attr') %}
<ul id="admin-nav-quick-tray">
{% if authorize(['admin.maintenance', 'admin.super', 'admin.cache']) %}
<li class="hint--bottom" data-hint="{{ "PLUGIN_ADMIN.CLEAR_CACHE"|t }}">
<a data-clear-cache-type="" data-clear-cache="{{ uri.addNonce(clear_cache_url, 'admin-form', 'admin-nonce') }}">
<i class="fa fa-retweet"></i>
</a>
</li>
{% endif %}
{% if authorize(['admin.super']) and config.plugins.admin.whitelabel.quicktray_recompile %}
<li class="hint--bottom" data-hint="{{ "PLUGIN_ADMIN.QUICKTRAY_RECOMPILE_HELP"|t }}">
<a data-recompile-scss href="#">
<i class="fa fa-paint-brush"></i>
</a>
</li>
{% endif %}
{% if grav.twig.plugins_quick_tray %}
{% for label, item in grav.twig.plugins_quick_tray %}
{% if authorize((item.authorize is defined and item.authorize is iterable) ? item.authorize : [item.authorize ?: ('admin.' ~ (item.location ?: item.route)), 'admin.super']) %}
{% set data_tags = '' %}
{% if (item.data) %}
{% for key, value in item.data %}
{% set data_tags = data_tags ~ ' data-' ~ key ~ '="' ~ value ~ '"' %}
{% endfor %}
{% endif %}
<li class="{{ item.class }} hint--bottom" data-hint="{{ item.hint }}" {{ data_tags|raw }}>
{% if item.route %}
<a href="{{ url(item.route) }}" {% if item.target %}target="{{ item.target }}"{% endif %}>
<i class="fa fa-fw {{ item.icon }}"></i>
</a>
{% else %}
<i class="fa fa-fw {{ item.icon }}"></i>
{% endif %}
</li>
{% endif %}
{% endfor %}
{% else %}
{% if authorize(['admin.maintenance', 'admin.super']) %}
<li class="hint--bottom" data-hint="Add the 'quick-tray-links' plugin for more...">
<a href="{{ admin_route('/plugins/install') }}">
<i class="fa fa-plus"></i>
</a>
</li>
{% endif %}
{% endif %}
</ul>

View File

@@ -0,0 +1,3 @@
<button class="lines-button x" type="button" role="button" aria-label="Toggle Navigation" data-sidebar-mobile-toggle>
<span class="lines"></span>
</button>

View File

@@ -0,0 +1,2 @@
{% set user_avatar = admin.user.getAvatarUrl() %}
<img src="{{ user_avatar ~ '?s=80' }}" />

Some files were not shown because too many files have changed in this diff Show More