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 @@
<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' }}" />

View File

@@ -0,0 +1,21 @@
<div id="offline-status">
<span><i class="fa fa-fw fa-plane"></i> You are offline</span>
</div>
{% set flex = grav['flex_objects'] ?? null %}
{% set user = admin.user %}
{% if flex and user.hasFlexFeature('user') %}
{% set route = flex.adminRoute(user) %}
{% else %}
{% set route = '/user/' ~ user.username %}
{% endif %}
<div id="admin-user-details">
<a href="{{ admin_route(route) }}">
{% include 'partials/nav-user-avatar.html.twig' %}
<div class="admin-user-names">
<h4>{{ user.fullname }} {% if user.twofa_enabled and config.plugins.admin.twofa_enabled %}<span class="badge">2FA</span>{% endif %}</h4>
<h5>{{ user.title }}</h5>
</div>
</a>
</div>

View File

@@ -0,0 +1,47 @@
{% set nav_hover = config.plugins.admin.sidebar.activate == 'hover' %}
{% if authorize(['admin.login', 'admin.super']) %}
<nav id="admin-sidebar" data-quickopen="{{ config.plugins.admin.sidebar.activate == 'hover' ? 'true' : 'false' }}" data-quickopen-delay="{{ config.plugins.admin.sidebar.hover_delay }}">
<div id="admin-logo" class="{{ nav_hover ? 'nav-hover' }}">
{% if not nav_hover %}
<div id="open-handle" data-sidebar-toggle><i class="fa fa-angle-right"></i></div>
{% endif %}
{% include 'partials/logo.html.twig' %}
</div>
{% include 'partials/nav-user-details.html.twig' %}
{% include 'partials/nav-quick-tray.html.twig' %}
<div data-simplebar class="admin-menu-wrapper">
<ul id="admin-menu">
{% for label, item in grav.twig.plugins_hooked_nav %}
{% set route = (item.route ?? item.location)|trim('/') %}
{% set location = (item.location ?? item.route)|trim('/') ~ '/' %}
{% set auth_rule = item.authorize is iterable ? item.authorize : [item.authorize ?: 'admin.' ~ route, 'admin.super'] %}
{% if authorize(auth_rule) %}
<li class="{{ nav_route|starts_with(location) ? 'selected' : '' }}">
<a href="{{ admin_route(route) }}">
<i class="fa fa-fw {{ item.icon }}"></i>
<em>{{ label|t }}</em>
{% set badge = item.badge ?? null %}
{% if badge %}
<span class="badges {% if badge.updates %}with-updates{% endif %}">
{% if badge.updates is defined %}<span class="badge updates">{{ badge.updates ?: '' }}</span>{% endif %}
<span class="badge count">{{ badge.count }}</span>
</span>
{% endif %}
</a>
</li>
{% endif %}
{% endfor %}
{% include 'partials/nav-pro.html.twig' ignore missing %}
<li>
<a href="{{ uri.addNonce(base_url_relative ~ '/task' ~ config.system.param_sep ~ 'logout', 'logout-form', 'logout-nonce') }}"><i class="fa fa-fw fa-sign-out"></i><em>{{ "PLUGIN_ADMIN.LOGOUT"|t }}</em></a>
</li>
</ul>
</div>
</nav>
{% endif %}

View File

@@ -0,0 +1,6 @@
{% for entry_id, entry in notifications %}
<div class="alert {{ entry.type }} position-dashboard">
<a href="#" data-notification-action="hide-notification" data-notification-id="{{ entry.id }}" class="close hide-notification"><i class="fa fa-close"></i></a>
{{ entry.message|raw }}
</div>
{% endfor %}

View File

@@ -0,0 +1,3 @@
{% for entry in notifications %}
<li class="single-notification {{ entry.type }}-notification"><span class="badge alert {{ entry.type }}">{{ entry.type|capitalize }}</span><a target="_blank" href="{{ entry.link }}" title="{{ entry.message|striptags|e('html_attr') }}">{{ entry.message|raw }}</a></li>
{% endfor %}

View File

@@ -0,0 +1,6 @@
{% for entry_id, entry in notifications %}
<div class="alert {{ entry.type }} position-plugins">
<a href="#" data-notification-action="hide-notification" data-notification-id="{{ entry.id }}" class="close hide-notification"><i class="fa fa-close"></i></a>
{{ entry.message|raw }}
</div>
{% endfor %}

View File

@@ -0,0 +1,6 @@
{% for entry_id, entry in notifications %}
<div class="alert {{ entry.type }} position-themes">
<a href="#" data-notification-action="hide-notification" data-notification-id="{{ entry.id }}" class="close hide-notification"><i class="fa fa-close"></i></a>
{{ entry.message|raw }}
</div>
{% endfor %}

View File

@@ -0,0 +1,6 @@
{% for entry_id, entry in notifications %}
<div class="alert {{ entry.type }} position-top">
<a href="#" data-notification-action="hide-notification" data-notification-id="{{ entry.id }}" class="close hide-notification"><i class="fa fa-close"></i></a>
{{ entry.message|raw }}
</div>
{% endfor %}

View File

@@ -0,0 +1,11 @@
<ul class="grav-menu">
{% for page in pages.children %}
<li class="{{ (admin.route and page.route == context.route) ? 'Selected' : '' }} {{ page.children.count > 0 ? 'hasChildren' : '' }}">
<a href="{{ admin_route('/pages/' ~ page.route|trim('/')) }}"><em class="status {{ page.visible ? 'visible' : '' }}"></em>{{ page.menu }}</a>
{% if page.children.count > 0 %}
{% include 'partials/page-children.html.twig' with {pages: page} %}
{% endif %}
</li>
{% endfor %}
</ul>

View File

@@ -0,0 +1,11 @@
{% set legend = {'VISIBLE':'', 'NON_ROUTABLE':'not-routable', 'NON_VISIBLE':'not-visible', 'MODULE':'module'} %}
<div id="pages-legend">
<strong>{{ 'PLUGIN_ADMIN.LEGEND'|t }}:</strong>
<ul>
{% for key, class in legend %}
<li><i class="page-icon fa fa-fw fa-circle-o {{ class }}"></i> {{ ('PLUGIN_ADMIN.'~key)|t }}</li>
{% endfor %}
</ul>
</div>

View File

@@ -0,0 +1,21 @@
{% set form_id = form_id ? form_id : 'page-move' %}
{% set scope = scope ?: 'data.' %}
{% set field_layout = 'admin' %}
<form id="{{ form_id }}" method="post" data-grav-form="{{ form_id }}" data-page-move>
<h1>Move</h1>
<div class="grav-loading"><div class="grav-loader">Loading...</div></div>
<div class="parents-content"></div>
{% 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 %}
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
<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 primary" name="task" value="save" form="blueprints">{{ "PLUGIN_ADMIN.CONTINUE"|t }}</button>
</div>
</form>

View File

@@ -0,0 +1,74 @@
<table>
{% if plugin.author %}
<tr>
<td>{{ "PLUGIN_ADMIN.AUTHOR"|t }}:</td>
<td class="double">
{% if plugin.author.url %}
<a href="{{ plugin.author.url }}" target="_blank" rel="noopener noreferrer">{{ plugin.author.name }}</a>
{% else %}
{{ plugin.author.name }}
{% endif %}
{% if plugin.author.email %}
- <a href="mailto:{{ plugin.author.email }}">{{ plugin.author.email }}</a>
{% endif %}
</td>
</tr>
{% endif %}
{% if plugin.homepage %}
<tr>
<td>{{ "PLUGIN_ADMIN.HOMEPAGE"|t }}:</td>
<td class="double"><a href="{{ plugin.homepage }}" target="_blank" rel="noopener noreferrer">{{ plugin.homepage }}</a></td>
</tr>
{% endif %}
{% if plugin.demo %}
<tr>
<td>{{ "PLUGIN_ADMIN.DEMO"|t }}:</td>
<td class="double"><a href="{{ plugin.demo }}" target="_blank" rel="noopener noreferrer">{{ plugin.demo }}</a></td>
</tr>
{% endif %}
{% if plugin.bugs %}
<tr>
<td>{{ "PLUGIN_ADMIN.BUG_TRACKER"|t }}:</td>
<td class="double"><a href="{{ plugin.bugs }}" target="_blank" rel="noopener noreferrer">{{ plugin.bugs }}</a></td>
</tr>
{% endif %}
{% if plugin.keywords %}
<tr>
<td>{{ "PLUGIN_ADMIN.KEYWORDS"|t }}:</td>
<td class="double">{{ plugin.keywords|join(', ') }}</td>
</tr>
{% endif %}
{% if plugin.license %}
<tr>
<td>{{ "PLUGIN_ADMIN.LICENSE"|t }}:</td>
{% if plugin.license|starts_with('http') %}
<td class="double"><a href="{{ plugin.license }}" target="_blank">{{ plugin.license }}</a></td>
{% else %}
<td class="double">{{ plugin.license }}</td>
{% endif %}
</tr>
{% endif %}
{% if plugin.description %}
<tr>
<td>{{ "PLUGIN_ADMIN.DESCRIPTION"|t }}:</td>
<td class="double">{{ plugin.description_html|raw }}</td>
</tr>
{% endif %}
{% if plugin.readme or plugin.homepage %}
{% set readme_link = plugin.readme ?: plugin.docs|default(plugin.homepage ~ '/blob/master/README.md') %}
<tr>
<td>{{ plugin.readme ? "PLUGIN_ADMIN.README"|t : "PLUGIN_ADMIN.DOCS"|t }}:</td>
<td class="double"><a href="{{ readme_link }}" target="_blank" rel="noopener noreferrer">{{ readme_link }}</a></td>
</tr>
{% endif %}
{% if admin.gpm.findPackage(plugin.slug, true).changelog %}
<tr>
<td>{{ "PLUGIN_ADMIN.CHANGELOG"|t }}:</td>
<td class="double"><a class="button button-small" href="#" data-remodal-target="changelog" data-remodal-changelog="{{ admin_route('/changelog/slug:' ~ plugin.slug) }}"><i class="fa fa-binoculars"></i> View Changelog</a></td>
</tr>
{% endif %}
</table>

View File

@@ -0,0 +1,76 @@
{% set gpm = admin.gpm() %}
{% set installed = gpm.isPluginInstalled(admin.route) %}
{% set isTestingRelease = gpm.isTestingRelease(plugin.slug) %}
{% set gumroad_loaded = false %}
<div class="grav-update plugin" data-gpm-plugin="{{ admin.route }}">
</div>
<h1>
{{ plugin.name }}
{% if admin.isTeamGrav(plugin) %}
<small><span class="info-reverse"><i class="fa fa-check-circle" title="{{ "PLUGIN_ADMIN.GRAV_OFFICIAL_PLUGIN"|t }}"></i></span></small>
{% endif %}
{% if admin.isPremiumProduct(plugin) %}
<small><span class="badge warning premium"><i class="fa fa-star-o"></i> {{ "PLUGIN_ADMIN.PREMIUM_PRODUCT"|t }}</span></small>
{% endif %}
{% if plugin.symlink %}
<small class="hint--bottom" data-hint="{{ "PLUGIN_ADMIN.PLUGIN_SYMBOLICALLY_LINKED"|t }}">
<i class="fa fa-fw fa-link"></i>
</small>
{% endif %}
<small>{{ plugin.version ? 'v' ~ plugin.version }}</small>
{% if isTestingRelease %}<span class="gpm-testing">test release</span>{% endif %}
</h1>
<div class="gpm-item-info">
<i class="gpm-item-icon fa fa-fw fa-{{ plugin.icon }}"></i>
{% include 'partials/plugin-data.html.twig' with { plugin: plugin } %}
</div>
{% if (installed) %}
{% set data = admin.data('plugins/' ~ admin.route) %}
{% if data.get('enabled') %}
{% include 'partials/blueprints.html.twig' with { data: data, blueprints: data.blueprints } %}
{% else %}
<form>
<div class="form-field grid">
<div class="form-label block size-1-3">
<label>{{ "PLUGIN_ADMIN.PLUGINS_MUST_BE_ENABLED"|t }}</label>
</div>
<div class="form-data block size-2-3">
<a class="button" href="{{ uri.addNonce(base_url_relative ~ '/plugins/' ~ plugin.slug ~ '/task' ~ config.system.param_sep ~ 'enable', 'admin-form', 'admin-nonce') ~ '/redirect:true' }}">
<i class="fa fa-power-off" aria-hidden="true"></i> {{ "PLUGIN_ADMIN.ENABLE"|t }} <strong>{{ plugin.name }}</strong>
</a>
</div>
</div>
</form>
{% endif %}
{% if (plugin.form.fields.enabled.type != 'hidden' and plugin.form.fields.tabs.fields.login.fields.enabled.type != 'hidden') %}
<div class="button-bar danger">
<span class="danger-zone"></span>
{% if not plugin.symlink %}
<a class="button button-reinstall-package hidden" href="#" data-remodal-target="reinstall-package"><i class="fa fa-fw fa-repeat"></i> {{ "PLUGIN_ADMIN.REINSTALL_PLUGIN"|t }}</a>
{% endif %}
<a class="button" href="#" data-remodal-target="remove-package"><i class="fa fa-fw fa-warning"></i> {{ "PLUGIN_ADMIN.REMOVE_PLUGIN"|t }}</a>
</div>
{% endif %}
{% else %}
<div class="button-bar success">
{% if (plugin.premium and not admin.license(plugin.slug)) %}
{% if not gumroad_loaded %}
{% set gumroad_loaded = true %}
<script src="//gumroad.com/js/gumroad.js"></script>
{% endif %}
<a class="gumroad-button button" href="https://gum.co/{{ plugin.premium.permalink }}" target="_blank" data-gumroad-single-product="true"><i class="fa fa-shopping-cart"></i> {{ plugin.premium.button|default('Purchase') }}</a>
{% else %}
<a class="button" href="#" data-remodal-target="add-package" data-packages-slugs="{{ plugin.slug }}" data-plugin-action="start-package-installation"><i class="fa fa-plus"></i> {{ "PLUGIN_ADMIN.INSTALL_PLUGIN"|t }}</a>
{% endif %}
</div>
{% endif %}
{% include 'partials/modal-changes-detected.html.twig' %}
{% include 'partials/modal-add-package.html.twig' with { type: 'plugin' } %}
{% include 'partials/modal-update-packages.html.twig' with { type: 'plugin' } %}
{% include 'partials/modal-remove-package.html.twig' with { type: 'plugin', package: plugin } %}
{% include 'partials/modal-reinstall-package.html.twig' with { type: 'plugin', package: plugin } %}
{% include 'partials/modal-changelog.html.twig' with { package: plugin} %}

View File

@@ -0,0 +1,76 @@
{% set gumroad_loaded = false %}
<div class="grav-update plugins"></div>
{% if installing %}
{% include 'partials/release-toggle.html.twig' %}
{% endif %}
{% include 'partials/list-sort.html.twig' with { list_view: 'plugins' } %}
<h1>
{{ installing ? "PLUGIN_ADMIN.AVAILABLE_PLUGINS"|t : "PLUGIN_ADMIN.INSTALLED_PLUGINS"|t }}
</h1>
<form>
<div class="gpm-search">
<input type="text" placeholder="{{ "PLUGIN_ADMIN.RESOURCE_FILTER"|t }}" data-gpm-filter>
</div>
</form>
<table>
{% for slug, plugin in admin.plugins(not installing).toArray|ksort %}
{% set data = admin.data('plugins/' ~ slug) %}
{% set isTestingRelease = admin.gpm.isTestingRelease(slug) %}
{% set isPremium = admin.isPremiumProduct(plugin) %}
{% set releaseDate = plugin.date ?: admin.gpm.findPackage(slug, true).date %}
<tr data-gpm-plugin="{{ slug|url_encode }}" data-gpm-name="{{ plugin.name }}" data-gpm-release-date="{{ releaseDate }}" data-gpm-author="{{ plugin.author.name }}" data-gpm-official="{{ admin.isTeamGrav(plugin) ? '1' : '2' }}" data-gpm-updatable="{{ admin.gpm.isUpdatable(slug) ? '1' : '2' }}" data-gpm-enabled="{{ data.get('enabled') ? '1' : '2' }}" data-gpm-testing="{{ isTestingRelease ? '1' : '2' }}" data-gpm-premium="{{ isPremium ? '1' : '2' }}">
<td class="gpm-name quadruple">
<i class="fa fa-fw fa-{{ plugin.icon }}"></i>
<a href="{{ admin_route('/plugins/' ~ slug|url_encode) }}">{{ plugin.name }}</a>
{% if admin.isTeamGrav(plugin) %}
<small><span class="info-reverse"><i class="fa fa-check-circle" title="{{ "PLUGIN_ADMIN.GRAV_OFFICIAL_PLUGIN"|t }}"></i></span></small>
{% endif %}
{% if isPremium %}
{% if not gumroad_loaded %}
{% set gumroad_loaded = true %}
<script src="//gumroad.com/js/gumroad.js"></script>
{% endif %}
<small><span class="badge warning premium"><i class="fa fa-star-o"></i> {{ "PLUGIN_ADMIN.PREMIUM_PRODUCT"|t }}</span></small>
{% endif %}
{% if plugin.symlink %}
<span class="hint--bottom" data-hint="{{ "PLUGIN_ADMIN.PLUGIN_SYMBOLICALLY_LINKED"|t }}">
<i class="fa fa-fw fa-link"></i>
</span>
{% endif %}
<span class="gpm-version">v{{ plugin.version }}</span>
{% if isTestingRelease %}<span class="gpm-testing">test release</span>{% endif %}
</td>
<td class="gpm-actions">
{% if (not installing and (plugin.form.fields.enabled.type != 'hidden' and plugin.form.fields.tabs.fields.options.fields.enabled.type != 'hidden')) %}
<a class="{{ data.get('enabled') ? 'enabled' : 'disabled' }}" href="{{ uri.addNonce(base_url_relative ~ '/plugins/' ~ slug ~ '/task' ~ config.system.param_sep ~ (data.get('enabled') ? 'disable' : 'enable'), 'admin-form', 'admin-nonce') }}">
<i class="fa fa-fw fa-toggle-{{ data.get('enabled') ? 'on' : 'off' }}"></i>
</a>
{% elseif (installing) %}
{% if (plugin.premium and not admin.license(plugin.slug)) %}
{% if not gumroad_loaded %}
{% set gumroad_loaded = true %}
<script src="//gumroad.com/js/gumroad.js"></script>
{% endif %}
<a class="gumroad-button button" href="https://gum.co/{{ plugin.premium.permalink }}" target="_blank" data-gumroad-single-product="true"><i class="fa fa-shopping-cart"></i> {{ plugin.premium.button|default('Purchase') }}</a>
{% else %}
<a class="button" href="#" data-remodal-target="add-package" data-packages-slugs="{{ plugin.slug }}" data-plugin-action="start-package-installation"><i class="fa fa-plus"></i> {{ "PLUGIN_ADMIN.INSTALL"|t }}</a>
{% endif %}
{% endif %}
<span class="gpm-details-expand"><i class="fa fa-chevron-down"></i></span>
</td>
<td class="gpm-details">
<div class="table-wrapper">
{% include 'partials/plugin-data.html.twig' with { plugin: plugin } %}
</div>
</td>
</tr>
{% else %}
<tr><td>{{ "PLUGIN_ADMIN.OFFLINE_WARNING"|t }}</td></tr>
{% endfor %}
</table>
{% include 'partials/modal-add-package.html.twig' with { type: 'plugin' } %}
{% include 'partials/modal-update-packages.html.twig' with { type: 'plugin' } %}
{% include 'partials/modal-changelog.html.twig' with { package: plugin} %}

View File

@@ -0,0 +1,24 @@
{% extends 'partials/base.html.twig' %}
{% set scope = form.scope %}
{% set field_layout = 'admin' %}
{% block body %}
<body id="admin-login-wrapper">
<section id="admin-login" class="default-glow-shadow {{ classes }}">
{% include 'partials/login-logo.html.twig' %}
{% include 'partials/messages.html.twig' %}
{% block instructions %}{% endblock %}
<form method="post" action="">
<div class="padding">
{% block form %}{% endblock %}
{% include "forms/fields/formname/formname.html.twig" %}
{% include 'forms/fields/uniqueid/uniqueid.html.twig' %}
{{ nonce_field(form.getNonceAction() ?? 'form', form.getNonceName() ?? 'form-nonce')|raw }}
</div>
</form>
</section>
</body>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% if authorize(['admin.super']) %}
<form id="gpm-release-toggle">
<div class="switch-toggle switch-grav" data-url="{{ base_url }}/ajax.json/task:gpmRelease">
<input type="radio" value="stable" id="stable" name="channel-switch" class="highlight" {% if config.system.gpm.releases == 'stable' %} checked="checked"{% endif %}>
<label for="stable">{{ "PLUGIN_ADMIN.STABLE"|t }}</label>
<input type="radio" value="testing" id="testing" name="channel-switch" class="highlight" {% if config.system.gpm.releases == 'testing' %} checked="checked"{% endif %}>
<label for="testing">{{ "PLUGIN_ADMIN.TESTING"|t }}</label>
<a></a>
</div>
</form>
{% endif %}

View File

@@ -0,0 +1,3 @@
<div class="spinning-wheel" style="display: none">
{{ "PLUGIN_ADMIN.LOADING"|t }} <i class="fa fa-spinner fa-spin"></i>
</div>

View File

@@ -0,0 +1,16 @@
{% do assets.addCss(theme_url~'/css-compiled/nucleus.css', {priority: 20}) %}
{% do assets.addCss(theme_url~'/css-compiled/template.css', {priority: 20}) %}
{% do assets.addCss('asset://admin-preset.css', {priority: 5}) %}
{% do assets.addCss(theme_url~'/css-compiled/simple-fonts.css') %}
{% do assets.addCss(theme_url~'/css/fork-awesome.min.css') %}
{% do assets.addCss(theme_url~'/css/chartist.min.css') %}
{% do assets.addCss(theme_url~'/css/selectize.min.css') %}
{% do assets.addCss(theme_url~'/css/hint.base.min.css') %}
{% do assets.addCss(theme_url~'/css/iconpicker.css') %}
{% if browser.getBrowser == 'msie' and browser.getVersion >= 8 and browser.getVersion <= 9 %}
{% do assets.addCss(theme_url~'/css/nucleus-ie9.css') %}
{% do assets.addCss(theme_url~'/css/pure-0.5.0/grids-min.css') %}
{% endif %}
{% if language_codes.rtl(grav.user.language) %}
{% do assets.addCss(theme_url~'/css/rtl.css') %}
{% endif %}

View File

@@ -0,0 +1,13 @@
{% set theme = admin.themes[admin.route] %}
{% set blueprints = theme.blueprints() %}
<h1>
{{ blueprints.get('name') }}
<small>{{ blueprints.get('version') ? 'v' ~ blueprints.get('version') }}</small>
</h1>
{% include 'partials/messages.html.twig' %}
<p>{{ blueprints.get('description') }}</p>
{% include 'partials/blueprints.html.twig' with { data: theme } %}

View File

@@ -0,0 +1,161 @@
{% set gpm = admin.gpm() %}
{% set installed = gpm.isThemeInstalled(admin.route) %}
{% set isTestingRelease = gpm.isTestingRelease(theme.slug) %}
{% set gumroad_loaded = false %}
{% set state = 'inactive' %}
{% if (config.get('system.pages.theme') == theme.slug) %}{% set state = 'active' %}{% endif %}
<div class="grav-update theme" data-gpm-theme="{{ admin.route }}">
</div>
<h1>
{{ theme.name }}
{% if admin.isTeamGrav(theme) %}
<small><span class="info-reverse"><i class="fa fa-check-circle" title="{{ "PLUGIN_ADMIN.GRAV_OFFICIAL_THEME"|t }}"></i></span></small>
{% endif %}
{% if admin.isPremiumProduct(theme) %}
<small><span class="badge warning premium"><i class="fa fa-star-o"></i> {{ "PLUGIN_ADMIN.PREMIUM_PRODUCT"|t }}</span></small>
{% endif %}
{% if theme.symlink %}
<small class="hint--bottom" data-hint="{{ "PLUGIN_ADMIN.THEME_SYMBOLICALLY_LINKED"|t }}">
<i class="fa fa-fw fa-link"></i>
</small>
{% endif %}
<small>{{ theme.version ? 'v' ~ theme.version }}</small>
{% if isTestingRelease %}<span class="gpm-testing">test release</span>{% endif %}
</h1>
<div class="gpm-item-info">
<i class="gpm-item-icon fa fa-fw fa-{{ theme.icon }}"></i>
<table>
{% if theme.version %}
<tr>
<td>{{ "PLUGIN_ADMIN.VERSION"|t }}:</td>
<td class="double">{{ theme.version }}</td>
</tr>
{% endif %}
{% if theme.author %}
<tr>
<td>{{ "PLUGIN_ADMIN.AUTHOR"|t }}:</td>
<td class="double">
{% if theme.author.url %}
<a href="{{ theme.author.url }}" target="_blank" rel="noopener noreferrer">{{ theme.author.name }}</a>
{% else %}
{{ theme.author.name }}
{% endif %}
{% if theme.author.email %}
- <a href="mailto:{{ theme.author.email }}">{{ theme.author.email }}</a>
{% endif %}
</td>
</tr>
{% endif %}
{% if theme.homepage %}
<tr>
<td>{{ "PLUGIN_ADMIN.HOMEPAGE"|t }}:</td>
<td class="double"><a href="{{ theme.homepage }}" target="_blank" rel="noopener noreferrer">{{ theme.homepage }}</a></td>
</tr>
{% endif %}
{% if theme.demo %}
<tr>
<td>{{ "PLUGIN_ADMIN.DEMO"|t }}:</td>
<td class="double"><a href="{{ theme.demo }}" target="_blank" rel="noopener noreferrer">{{ theme.demo }}</a></td>
</tr>
{% endif %}
{% if theme.bugs %}
<tr>
<td>{{ "PLUGIN_ADMIN.BUG_TRACKER"|t }}:</td>
<td class="double"><a href="{{ theme.bugs }}" target="_blank" rel="noopener noreferrer">{{ theme.bugs }}</a></td>
</tr>
{% endif %}
{% if theme.keywords %}
<tr>
<td>{{ "PLUGIN_ADMIN.KEYWORDS"|t }}:</td>
<td class="double">
{{ theme.keywords|join(', ') }}
</td>
</tr>
{% endif %}
{% if theme.license %}
<tr>
<td>{{ "PLUGIN_ADMIN.LICENSE"|t }}:</td>
{% if theme.license|starts_with('http') %}
<td class="double"><a href="{{ theme.license }}" target="_blank">{{ theme.license }}</a></td>
{% else %}
<td class="double">{{ theme.license }}</td>
{% endif %}
</tr>
{% endif %}
{% if theme.description %}
<tr>
<td>{{ "PLUGIN_ADMIN.DESCRIPTION"|t }}:</td>
<td class="double">{{ theme.description_html|raw }}</td>
</tr>
{% endif %}
{% if theme.readme or theme.homepage %}
{% set readme_link = theme.readme ?: theme.docs|default(theme.homepage ~ '/blob/master/README.md') %}
<tr>
<td>{{ theme.readme ? "PLUGIN_ADMIN.README"|t : "PLUGIN_ADMIN.DOCS"|t }}:</td>
<td class="double"><a href="{{ readme_link }}" target="_blank" rel="noopener noreferrer">{{ readme_link }}</a></td>
</tr>
{% endif %}
{% if admin.gpm.findPackage(theme.slug, true).changelog %}
<tr>
<td>{{ "PLUGIN_ADMIN.CHANGELOG"|t }}:</td>
<td class="double"><a class="button button-small" href="#" data-remodal-target="changelog" data-remodal-changelog="{{ admin_route('/changelog/slug:' ~ theme.slug) }}"><i class="fa fa-binoculars"></i> View Changelog</a></td>
</tr>
{% endif %}
</table>
</div>
{% if installed %}
{% if state == 'active' %}
{% set data = admin.data('themes/' ~ admin.route) %}
{% include 'partials/blueprints.html.twig' with { data: data, blueprints: data.blueprints } %}
{% else %}
<div class="theme" data-gpm-theme="{{ theme.slug }}" data-gpm-name="{{ theme.name }}">
<div style="display:none;" class="gpm-name"><a>{{ theme.name }}</a></div>
<form>
<div class="form-field grid">
<div class="form-label block size-1-3">
<label>{{ "PLUGIN_ADMIN.ACTIVATION_REQUIRED"|t }}</label>
</div>
<div class="form-data block size-2-3">
<a class="button gpm-actions" data-remodal-target="theme-switch-warn" href="{{ uri.addNonce(base_url_relative ~ '/themes/' ~ theme.slug ~ '/task' ~ config.system.param_sep ~ 'activate', 'admin-form', 'admin-nonce') }}">
<i class="fa fa-power-off" aria-hidden="true"></i> {{ "PLUGIN_ADMIN.ACTIVATE"|t }} <strong>{{ theme.name }}</strong>
</a>
</div>
</div>
</form>
</div>
<div class="button-bar danger">
<span class="danger-zone"></span>
{% if not theme.symlink %}
<a class="button button-reinstall-package hidden" href="#" data-remodal-target="reinstall-package"><i class="fa fa-fw fa-repeat"></i> {{ "PLUGIN_ADMIN.REINSTALL_THEME"|t }}</a>
{% endif %}
<a class="button" href="#" data-remodal-target="remove-package"><i class="fa fa-fw fa-warning"></i> {{ "PLUGIN_ADMIN.REMOVE_THEME"|t }}</a>
</div>
{% endif %}
{% else %}
<div class="button-bar success">
{% if (theme.premium and not admin.license(theme.slug)) %}
{% if not gumroad_loaded %}
{% set gumroad_loaded = true %}
<script src="//gumroad.com/js/gumroad.js"></script>
{% endif %}
<a class="gumroad-button button" href="https://gum.co/{{ theme.premium.permalink }}" target="_blank" data-gumroad-single-product="true"><i class="fa fa-shopping-cart"></i> {{ theme.premium.button|default('Purchase') }}</a>
{% else %}
<a class="button" href="#" data-remodal-target="add-package" data-packages-slugs="{{ theme.slug }}" data-theme-action="start-package-installation"><i class="fa fa-plus"></i> {{ "PLUGIN_ADMIN.INSTALL_THEME"|t }}</a>
{% endif %}
</div>
{% endif %}
{% include 'partials/modal-switch-theme.html.twig' with {theme_name: theme.name} %}
{% include 'partials/modal-changes-detected.html.twig' %}
{% include 'partials/modal-add-package.html.twig' with { type: 'theme' } %}
{% include 'partials/modal-update-packages.html.twig' with { type: 'theme' } %}
{% include 'partials/modal-remove-package.html.twig' with { type: 'theme', package: theme } %}
{% include 'partials/modal-reinstall-package.html.twig' with { type: 'theme', package: theme } %}
{% include 'partials/modal-changelog.html.twig' with { package: theme} %}

View File

@@ -0,0 +1,81 @@
{% set gumroad_loaded = false %}
<div class="grav-update themes"></div>
{% if installing %}
{% include 'partials/release-toggle.html.twig' %}
{% endif %}
{% include 'partials/list-sort.html.twig' with { list_view: 'themes' } %}
<h1>
{{ installing ? "PLUGIN_ADMIN.AVAILABLE_THEMES"|t : "PLUGIN_ADMIN.INSTALLED_THEMES"|t }}
</h1>
<form>
<div class="gpm-search">
<input type="text" placeholder="{{ "PLUGIN_ADMIN.RESOURCE_FILTER"|t }}" data-gpm-filter>
</div>
</form>
<div class="themes card-row grid fixed-blocks pure-g">
{% for slug, theme in admin.themes(not installing).toArray|ksort %}
{% set state = 'inactive' %}
{% if (installing) %}{% set state = 'installing' %}{% endif %}
{% if (config.get('system.pages.theme') == slug) %}{% set state = 'active' %}{% endif %}
{% set isTestingRelease = admin.gpm.isTestingRelease(slug) %}
{% set isPremium = admin.isPremiumProduct(theme) %}
{% set releaseDate = theme.date ?: admin.gpm.findPackage(slug, true).date %}
<div class="theme card-item pure-u-1-3 {{ state }}-theme" data-gpm-theme="{{ slug|url_encode }}" data-gpm-name="{{ theme.name }}" data-gpm-release-date="{{ releaseDate }}" data-gpm-author="{{ theme.author.name }}" data-gpm-official="{{ admin.isTeamGrav(theme) ? '1' : '2' }}" data-gpm-updatable="{{ admin.gpm.isUpdatable(slug) ? '1' : '2' }}" data-gpm-enabled="{{ data.get('enabled') ? '1' : '2' }}" data-gpm-testing="{{ isTestingRelease ? '1' : '2' }}" data-gpm-premium="{{ isPremium ? '1' : '2' }}">
<div class="gpm-name">
<i class="fa fa-fw fa-{{ theme.icon }}"></i>
<a href="{{ admin_route('/themes/' ~ slug|url_encode) }}">{{ theme.name }}</a>
{% if admin.isTeamGrav(theme) %}
<small><span class="info-reverse"><i class="fa fa-check-circle" title="{{ "PLUGIN_ADMIN.GRAV_OFFICIAL_THEME"|t }}"></i></span></small>
{% endif %}
{% if isPremium %}
{% if not gumroad_loaded %}
{% set gumroad_loaded = true %}
<script src="//gumroad.com/js/gumroad.js"></script>
{% endif %}
<small><span class="badge warning premium"><i class="fa fa-star-o"></i> {{ "PLUGIN_ADMIN.PREMIUM_PRODUCT"|t }}</span></small>
{% endif %}
{% if theme.symlink %}
<span class="hint--bottom" data-hint="{{ "PLUGIN_ADMIN.THEME_SYMBOLICALLY_LINKED"|t }}">
<i class="fa fa-fw fa-link"></i>
</span>
{% endif %}
<span class="gpm-version">v{{ theme.version }}</span>
{% if isTestingRelease %}<span class="gpm-testing">test release</span>{% endif %}
</div>
<div class="gpm-screenshot">
{% set thumb = installing ? '//getgrav.org/images/' ~ theme.screenshot : theme.thumbnail %}
<a href="{{ admin_route('/themes/' ~ slug|url_encode) }}"><img src="{{ thumb }}" /></a>
</div>
{% if (state == 'installing') %}
<div class="gpm-actions">
{% if (theme.premium and not admin.license(theme.slug)) %}
{% if not gumroad_loaded %}
{% set gumroad_loaded = true %}
<script src="//gumroad.com/js/gumroad.js"></script>
{% endif %}
<a class="gumroad-button button" href="https://gum.co/{{ theme.premium.permalink }}" target="_blank" data-gumroad-single-product="true"><i class="fa fa-shopping-cart"></i> {{ theme.premium.button|default('Purchase') }}</a>
{% else %}
<a class="button" href="#" data-remodal-target="add-package" data-packages-slugs="{{ slug }}" data-theme-action="start-package-installation"><i class="fa fa-plus"></i> {{ "PLUGIN_ADMIN.INSTALL"|t }}</a>
{% endif %}
</div>
{% elseif state == 'active' %}
<div class="gpm-actions">
<i class="fa fa-star"></i> {{ "PLUGIN_ADMIN.ACTIVE_THEME"|t }}
</div>
{% else %}
<a data-remodal-target="theme-switch-warn" href="{{ uri.addNonce(base_url_relative ~ '/themes/' ~ slug ~ '/task' ~ config.system.param_sep ~ 'activate', 'admin-form', 'admin-nonce') }}" class="gpm-actions">
<i class="fa fa-power-off" aria-hidden="true"></i> {{ "PLUGIN_ADMIN.ACTIVATE"|t }}
</a>
{% endif %}
</div>
{% else %}
<tr><td>{{ "PLUGIN_ADMIN.OFFLINE_WARNING"|t }}</td></tr>
{% endfor %}
</div>
{% include 'partials/modal-switch-theme.html.twig' %}
{% include 'partials/modal-add-package.html.twig' with { type: 'theme' } %}
{% include 'partials/modal-update-packages.html.twig' with { type: 'theme' } %}

View File

@@ -0,0 +1,7 @@
<div class="button-bar">
<a class="button" href="{{ base_url }}"><i class="fa fa-reply"></i> {{ "PLUGIN_ADMIN.BACK"|t }}</a>
{% include 'partials/backups-button.html.twig' %}
<button class="button" type="submit" name="task" value="save" form="blueprints"><i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|t }}</button>
</div>
<h1><i class="fa fa-fw fa-briefcase"></i> {{ "PLUGIN_ADMIN.TOOLS"|t }} - {{ "PLUGIN_ADMIN.BACKUPS"|t }}</h1>

View File

@@ -0,0 +1,81 @@
<div class="backups-content">
{% set data = admin.data('config/backups') %}
{% set backups = grav.backups.getAvailableBackups() %}
{% set profiles = grav.backups.getBackupProfiles() %}
{% set purge_config = grav.backups.getPurgeConfig() %}
{% set newest_date = (backups|first).date %}
{% set newest_backup = newest_date ? newest_date|nicetime(false, false) : 'none' %}
{% set oldest_date = (backups|last).date %}
{% set oldest_backup = oldest_date ? oldest_date|nicetime(false, false) : 'none' %}
{% switch purge_config.trigger %}
{% case 'number' %}
{% set count = backups|count %}
{% set max_backups = purge_config.max_backups_count %}
{% if max_backups > 0 %}
{% set percent_used = count == 0 ? 0 : 100 - (count / max_backups * 100) %}
{% else %}
{% set percent_used = 100 %}
{% endif %}
{% set bar_msg = "PLUGIN_ADMIN.BACKUPS_PURGE_NUMBER"|t(count, purge_config.max_backups_count) %}
{% case 'time' %}
{% set last = backups|last %}
{% set days = last == null ? 0 : (date('now')).diff(last.time).days %}
{% set percent_used = days == 0 ? 0 : 100 - (days / purge_config.max_backups_time * 100) %}
{% set bar_msg = "PLUGIN_ADMIN.BACKUPS_PURGE_TIME"|t(purge_config.max_backups_time - days) %}
{% default %}
{% set space_used = grav.backups.getTotalBackupsSize() %}
{% set space_available = purge_config.max_backups_space * 1024 * 1024 * 1024 %}
{% set percent_used = space_used == 0 ? 0 : 100 - (space_used / space_available * 100) %}
{% set bar_msg = "PLUGIN_ADMIN.BACKUPS_PURGE_SPACE"|t(space_used|nicefilesize, space_available|nicefilesize) %}
{% endswitch %}
<div id="admin-dashboard">
<div id="backups-stats" class="dashboard-item">
<div class="primary-accent default-box-shadow">
<h1>{{ "PLUGIN_ADMIN.BACKUPS_STATS"|t }}</h1>
<div class="admin-statistics-chart">
<div class="stats-info">
<div id="backups-usage">
<div class="backups-usage-wrapper">
{% if percent_used >= 100 %}
<div class="usage full"></div>
{% else %}
<div class="usage" style="width:{{ percent_used }}%"></div>
{% endif %}
</div>
<h1>{{ bar_msg }}</h1>
</div>
</div>
<div class="flush-bottom button-bar stats-bar">
<span class="stat">
<b>{{ backups|length }}</b>
<i>{{ "PLUGIN_ADMIN.BACKUPS_COUNT"|t }}</i>
</span>
<span class="stat">
<b>{{ profiles|count }}</b>
<i>{{ "PLUGIN_ADMIN.BACKUPS_PROFILES_COUNT"|t }}</i>
</span>
<span class="stat">
<b>{{ newest_backup }}</b>
<i>{{ "PLUGIN_ADMIN.BACKUPS_NEWEST"|t }}</i>
</span>
<span class="stat">
<b>{{ oldest_backup }}</b>
<i>{{ "PLUGIN_ADMIN.BACKUPS_OLDEST"|t }}</i>
</span>
</div>
</div>
</div>
</div>
</div>
{% include 'partials/blueprints.html.twig' with { blueprints: data.blueprints, data: data } %}
{% include 'partials/modal-changes-detected.html.twig' %}
</div>

View File

@@ -0,0 +1,29 @@
<h1>{{ "PLUGIN_ADMIN.TOOLS_DIRECT_INSTALL_TITLE"|t }}</h1>
<div class="direct-install-content">
<h2>{{ "PLUGIN_ADMIN.TOOLS_DIRECT_INSTALL_UPLOAD_TITLE"|t }}</h2>
<p>{{ "PLUGIN_ADMIN.TOOLS_DIRECT_INSTALL_UPLOAD_DESC"|t|raw }}</p>
<form action="{{ admin_route('/tools/direct-install') }}" method="post" enctype="multipart/form-data">
<input type="file" name="uploaded_file" id="uploaded_file" required accept="application/zip, application/octet-stream">
<input type="submit" value="{{ "PLUGIN_ADMIN.TOOLS_DIRECT_INSTALL_UPLOAD_BUTTON"|t }}" name="submit" class="button">
<input type="hidden" name="task" value="directInstall" />
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
</form>
<h2>{{ "PLUGIN_ADMIN.TOOLS_DIRECT_INSTALL_URL_TITLE"|t }}</h2>
<p>{{ "PLUGIN_ADMIN.TOOLS_DIRECT_INSTALL_URL_DESC"|t|raw }}</p>
<form action="{{ admin_route('/tools/direct-install') }}" method="post">
<input type="text" name="file_path" class="large" required />
<input type="submit" value="{{ "PLUGIN_ADMIN.INSTALL"|t }}" name="submit" class="button">
<input type="hidden" name="task" value="directInstall" />
{{ nonce_field('admin-form', 'admin-nonce')|raw }}
</form>
</div>

View File

@@ -0,0 +1,80 @@
<div class="logs-content">
{% macro render_select(name, options, selected, autokey=false) %}
<div class="forms-select-wrapper">
<select class="form-select" name="{{ name }}" data-grav-selectize>
{% for key,option in options %}
{% if autokey %}
{% set key = key|of_type('int') ? option|lower : key %}
{% endif %}
<option value="{{ key }}" {{ key == selected ? ' selected' : '' }}>{{ option|titleize }}</option>
{% endfor %}
</select>
</div>
{% endmacro %}
{% import _self as macro %}
{% set file = grav.uri.query('log') ?: 'grav.log' %}
{% set verbose = grav.uri.query('verbose') == 'true' ? true : false %}
{% set lines = grav.uri.query('lines') ?: 20 %}
{% set logfile = grav.locator.findResource("log://" ~ file) %}
{% set logs = logfile ? logviewer.objectTail(logfile, lines|int, false) : [] %}
{% set log_files = admin.getLogFiles() %}
{% set title = log_files[file] %}
<div class="logs-output">
<form id="logs-form">
<div class="block block-select">
<div class="form-field">
<div class="form-data">
{% set lines_list = {10:'10 entries', 25:'25 entries', 50:'50 entries', 100:'100 entries', 200:'200 entries', 500:'500 entries'} %}
{{ macro.render_select('log', log_files, file) }}
{{ macro.render_select('verbose', {'false':'Essential Output', 'true':'Verbose Output'}, verbose) }}
{{ macro.render_select('lines', lines_list, lines) }}
</div>
</div>
</div>
</form>
<h1>{{ title }} Output</h1>
<h3>Display the {{ lines }} most recent entries...</h3>
<table class="noflex">
<thead>
<tr>
<th class="date">Date</th>
<th class="level">Level</th>
<th class="message">Message</th>
</tr>
</thead>
<tbody>
{% for log in logs %}
<tr>
<td class="date" title="{{ log.date|date('r') }}">{{ log.date|date }}</td>
<td class="level"><span class="badge {{ log.level|lower }}">{{ log.level }}</span></td>
<td class="message">{{ log.message }}</td>
{% if verbose %}
</tr>
<tr class="trace">
<td colspan="2">&nbsp;</td>
<td>
<div class="overflow">
<ol>
{% for tracerow in log.trace %}
<li><code>{{ tracerow }}</code></li>
{% endfor %}
</ol>
</div>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,15 @@
<div class="reports-content">
{% set reports = admin.generateReports() %}
<div class="report-output">
{% for title, report in reports %}
<h1>{{ title }}</h1>
{{ report|raw }}
{% endfor %}
</div>
{% include 'partials/modal-changes-detected.html.twig' %}
</div>

View File

@@ -0,0 +1,6 @@
<div class="button-bar">
<a class="button" href="{{ base_url }}"><i class="fa fa-reply"></i> {{ "PLUGIN_ADMIN.BACK"|t }}</a>
<button class="button" type="submit" name="task" value="save" form="blueprints"><i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|t }}</button>
</div>
<h1><i class="fa fa-fw fa-briefcase"></i> {{ "PLUGIN_ADMIN.TOOLS"|t }} - {{ "PLUGIN_ADMIN.SCHEDULER"|t }}</h1>

View File

@@ -0,0 +1,36 @@
<div class="scheduler-content">
{% set data = admin.data('config/scheduler') %}
{% set cron_status = grav.scheduler.isCrontabSetup() %}
{% set user = grav.scheduler.whoami() %}
{% if cron_status == 1 %}
<div class="alert notice secondary-accent">
<div id="show-instructions" class="button button-small"><i class="fa fa-clock-o"></i> {{ "PLUGIN_ADMIN.SCHEDULER_INSTALL_INSTRUCTIONS"|t }}</div>
<i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SCHEDULER_INSTALLED_READY"|t }}
</div>
{% elseif cron_status == 2 %}
<div class="alert warning"> {{ "PLUGIN_ADMIN.SCHEDULER_CRON_NA"|t([user])|raw }}</div>
{% else %}
<div class="alert warning"> {{ "PLUGIN_ADMIN.SCHEDULER_NOT_ENABLED"|t([user])|raw }}</div>
{% endif %}
<div class="alert notice"><i class="fa fa-exclamation-circle"></i> {{ "PLUGIN_ADMIN.SCHEDULER_WARNING"|t([user]) }}</div>
<div id="cron-install" class="form-border overlay {{ cron_status == 1 ? 'hide' : ''}}">
<pre><code>{{- grav.scheduler.getCronCommand()|trim -}}</code></pre>
<p>{{ "PLUGIN_ADMIN.SCHEDULER_POST_INSTRUCTIONS"|t([user])|raw }}</p>
</div>
{% include 'partials/blueprints.html.twig' with { blueprints: data.blueprints, data: data } %}
{% include 'partials/modal-changes-detected.html.twig' %}
<script>
$('#show-instructions').click(function() {
$('#cron-install').toggleClass( "hide" );
});
</script>
</div>

View File

@@ -0,0 +1,10 @@
<p class="avatar">
{{ "PLUGIN_ADMIN.AVATAR_BY"|t }}
{% if config.system.accounts.avatar == 'gravatar' %}
<a href="https://gravatar.com" target="_blank" rel="noopener noreferrer">gravatar.com</a>.
{% else %}
<a href="https://multiavatar.com/" target="_blank" rel="noopener noreferrer">Multiavatar</a>.
{% endif %}
{{ "PLUGIN_ADMIN.AVATAR_UPLOAD_OWN"|t }}</p>

View File

@@ -0,0 +1,2 @@
{% set user_avatar = data.getAvatarUrl() %}
<label><img referrerpolicy="no-referrer" src="{{ user_avatar ~ '?s=200' }}" /></label>