init
This commit is contained in:
7
user/plugins/flex-objects/admin/pages/flex-objects.md
Normal file
7
user/plugins/flex-objects/admin/pages/flex-objects.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Flex Objects
|
||||
|
||||
access:
|
||||
admin.flex-objects: true
|
||||
admin.super: true
|
||||
---
|
||||
@@ -0,0 +1,30 @@
|
||||
{%- set user = admin.user -%}
|
||||
{%- set route = controller.route -%}
|
||||
{%- set type = directory.config('admin.template') ?? target -%}
|
||||
|
||||
{# Set action from ?preview=1 #}
|
||||
{%- if key and uri.currentUri().queryParam('preview') %}
|
||||
{% set action = 'preview' %}
|
||||
{% endif -%}
|
||||
|
||||
{%- set template -%}
|
||||
{%- if action == 'add' -%}
|
||||
edit
|
||||
{%- elseif action == 'delete' -%}
|
||||
list
|
||||
{%- else -%}
|
||||
{{- action ?: task ?: 'types' -}}
|
||||
{%- endif -%}
|
||||
{%- endset -%}
|
||||
|
||||
{%- set separator = config.system.param_sep -%}
|
||||
{%- set view_config = directory.config('admin.views.' ~ template) ?? directory.config('admin.' ~ template) ?? [] -%}
|
||||
|
||||
{%- include target ? [
|
||||
'flex-objects/types/' ~ type ~ '/' ~ template ~ '.html.twig',
|
||||
'flex-objects/types/default/' ~ template ~ '.html.twig',
|
||||
'flex-objects/layouts/404.html.twig'
|
||||
] : [
|
||||
'flex-objects/types/default/' ~ template ~ '.html.twig',
|
||||
'flex-objects/layouts/404.html.twig'
|
||||
] -%}
|
||||
@@ -0,0 +1 @@
|
||||
{{- admin.json_response|json_encode|raw -}}
|
||||
@@ -0,0 +1 @@
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.LAYOUT_NOT_FOUND'|tu(template, null) }}
|
||||
@@ -0,0 +1,25 @@
|
||||
{% set active_html = 'class="active"' %}
|
||||
{% set is_configure = route.gravParam('') is same as('configure') %}
|
||||
{% set authorize = directory.config('admin.views.configure.authorize') ?? directory.config('admin.configure.authorize') ?? 'admin.super' %}
|
||||
|
||||
{% if allowed %}
|
||||
<div class="form-tabs">
|
||||
<div class="tabs-nav">
|
||||
{% for name,title in {'user-accounts': 'PLUGIN_ADMIN.USERS', 'user-groups': 'PLUGIN_ADMIN.GROUPS'} %}
|
||||
{% set current = flex.directory(name) %}
|
||||
{% if current and current.isAuthorized('list', 'admin', user) %}
|
||||
{% set active = not is_configure and nav_route|starts_with(flex.adminRoute(current)|trim('/') ~ '/') %}
|
||||
<a {{active ? active_html|raw }} href="{{ admin_route(flex.adminRoute(current)) }}">
|
||||
<span>{{ title|tu }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if user.authorize(authorize) or user.authorize('admin.super') %}
|
||||
<a {{is_configure ? active_html|raw }} href="{{ admin_route('/accounts/configure') }}">
|
||||
<span>{{ 'PLUGIN_ADMIN.CONFIGURATION'|tu }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<a id="titlebar-button-add" class="button" href="{{ route.withGravParam('', 'add') }}">
|
||||
<i class="fa fa-plus"></i> {{ 'PLUGIN_ADMIN.ADD'|tu }}
|
||||
</a>
|
||||
@@ -0,0 +1,3 @@
|
||||
<a id="titlebar-button-back" class="button" href="{{ back_url }}">
|
||||
<i class="fa fa-reply"></i> {{ "PLUGIN_ADMIN.BACK"|tu }}
|
||||
</a>
|
||||
@@ -0,0 +1,7 @@
|
||||
{%- set authorize = directory.config('admin.views.configure.authorize') ?? directory.config('admin.configure.authorize') ?? 'admin.super' %}
|
||||
|
||||
{%- if configure_url and user.authorize(authorize) %}
|
||||
<a id="titlebar-button-configure" class="button" href="{{ configure_url }}">
|
||||
<i class="fa fa-cog"></i> {{ 'PLUGIN_ADMIN.CONFIGURATION'|tu }}
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<a id="titlebar-button-delete" href="#delete" data-remodal-target="delete" data-delete-url="{{ uri.addNonce(route.withoutParams().withGravParam('task', 'delete').getUri(), 'admin-form', 'admin-nonce') }}" class="button danger">
|
||||
<i class="fa fa-fw fa-trash-o"></i> {{ 'PLUGIN_ADMIN.DELETE'|tu }}
|
||||
</a>
|
||||
@@ -0,0 +1,3 @@
|
||||
<a id="titlebar-button-export-csv" class="button" href="{{ route.withGravParam('', 'csv') }}">
|
||||
<i class="fa fa-download"></i> {{ 'PLUGIN_FLEX_OBJECTS.CSV'|tu }}
|
||||
</a>
|
||||
@@ -0,0 +1,21 @@
|
||||
{% if export.options %}
|
||||
<div id="titlebar-button-export" class="button-group">
|
||||
<button id="titlebar-button-export" type="button" class="button dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fa fa-download"></i> {{ 'PLUGIN_ADMIN.EXPORT'|tu }} <i class="fa fa-caret-down"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu lang-switcher">
|
||||
{% for type,option in export.options %}
|
||||
<li>
|
||||
<a id="titlebar-button-export" class="button" href="{{ route.withGravParam('', 'export').withQueryParam('type', type) }}">
|
||||
{{ option.title|tu }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<a id="titlebar-button-export" class="button" href="{{ route.withGravParam('', 'export') }}">
|
||||
<i class="fa fa-download"></i> {{ export.title ?? (export.formatter.class ? 'PLUGIN_ADMIN.EXPORT'|tu : 'PLUGIN_FLEX_OBJECTS.CSV'|tu) }}
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,18 @@
|
||||
<div id="titlebar-languages" class="button-group">
|
||||
<button type="button" class="button disabled">
|
||||
<i class="fa fa-flag-o"></i>
|
||||
{{ all_languages[language] ?? language }}
|
||||
</button>
|
||||
{% if admin_languages|length > (language in admin_languages)|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 lang_code in admin_languages %}
|
||||
{% if lang_code != language %}
|
||||
<li><a href="{{ admin_route(route.getRoute(1), lang_code) }}">{{ all_languages[lang_code] ?? lang_code }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,5 @@
|
||||
{% if preview_url %}
|
||||
<a id="titlebar-button-preview-open" href="{{ preview_url }}" class="button" target="_blank">
|
||||
<i class="fa fa-external-link"></i> {{ "PLUGIN_ADMIN.OPEN_NEW_TAB"|tu }}
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<a id="titlebar-button-preview" href="{{ route.withGravParam('', 'preview') }}" class="button">
|
||||
<i class="fa fa-eye"></i> {{ "PLUGIN_ADMIN.PREVIEW"|tu }}
|
||||
</a>
|
||||
@@ -0,0 +1,4 @@
|
||||
{% set task = task ?? 'save' %}
|
||||
<button id="titlebar-button-save" class="button" type="submit" name="task" value="{{ task }}" form="blueprints" data-flex-safe-action>
|
||||
<i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|tu }}
|
||||
</button>
|
||||
@@ -0,0 +1,103 @@
|
||||
{% extends 'partials/base.html.twig' %}
|
||||
{% use 'flex-objects/types/default/titlebar/configure.html.twig' %}
|
||||
|
||||
{% set name = view_config['form'] %}
|
||||
{% set form = form ?? directory.directoryForm(name) %}
|
||||
|
||||
{# Allowed actions #}
|
||||
{% set can_save = can_save ?? user.authorize(view_config['authorize'] ?? 'admin.super') %}
|
||||
|
||||
{# These variables can be overridden from the main template file #}
|
||||
{% set allowed = allowed ?? (directory and form and can_save) %}
|
||||
{% set back_route = back_route ?? ('/' ~ route.getRoute(1)) %}
|
||||
{% set title_icon = title_icon ?? view_config['icon'] ?? 'fa-cog' %}
|
||||
{% set title -%}
|
||||
{%- set title_config = view_config['title'] ?? null -%}
|
||||
{%- if title_config.template -%}
|
||||
{{- include(template_from_string(title_config.template, 'configure title template')) -}}
|
||||
{%- else -%}
|
||||
{{- directory.title|tu }} - {{ 'PLUGIN_ADMIN.CONFIGURATION'|tu -}}
|
||||
{% endif %}
|
||||
{%- endset %}
|
||||
|
||||
{% macro spanToggle(input, length) %}
|
||||
{{ (repeat(' ', (length - input|length) / 2) ~ input ~ repeat(' ', (length - input|length) / 2))|raw }}
|
||||
{% endmacro %}
|
||||
{% import _self as macro %}
|
||||
|
||||
{% block body %}
|
||||
{% set back_url = back_url ?? admin_route(back_route) %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock body %}
|
||||
|
||||
{% block content_top %}
|
||||
{% if allowed and user.authorize('admin.super') %}
|
||||
{% set save_location = directory.getDirectoryConfigUri(name) %}
|
||||
<div class="alert notice">{{ "PLUGIN_ADMIN.SAVE_LOCATION"|tu }}: <b>{{ url(save_location, false, true)|trim('/') }}</b></div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block topbar %}
|
||||
{% if user.authorize('admin.super') %}
|
||||
<form id="admin-mode-toggle">
|
||||
{% set normalText = 'PLUGIN_ADMIN.NORMAL'|tu %}
|
||||
{% set expertText = 'PLUGIN_ADMIN.EXPERT'|tu %}
|
||||
{% set maxLen = max([normalText|length, expertText|length]) %}
|
||||
{% set normalText = macro.spanToggle(normalText, maxLen) %}
|
||||
{% set expertText = macro.spanToggle(expertText, maxLen) %}
|
||||
|
||||
<div class="switch-toggle switch-grav">
|
||||
<input type="radio" value="normal" data-leave-url="{{ route.withGravParam('mode', 'normal').toString(true) }}" 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="{{ route.withGravParam('mode', 'expert').toString(true) }}" 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 %}
|
||||
{% endblock topbar %}
|
||||
|
||||
{% block content %}
|
||||
{{ parent() }}
|
||||
|
||||
{% if allowed %}
|
||||
<div class="clear directory admin-flex-config">
|
||||
<div class="admin-form-wrapper">
|
||||
{# TODO: RAW MODE
|
||||
<div id="admin-topbar">
|
||||
{{ block('topbar') }}
|
||||
</div>
|
||||
#}
|
||||
{% block edit %}
|
||||
{% include 'partials/blueprints.html.twig' with { form: form, data: form.data } %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'partials/modal-changes-detected.html.twig' %}
|
||||
|
||||
{% else %}
|
||||
|
||||
{% do page.modifyHeader('http_response_code', 404) %}
|
||||
<div class="error-block">
|
||||
<h1>{{ 'PLUGIN_ADMIN.ERROR'|tu }} 404</h1>
|
||||
<div class="padding">
|
||||
<p>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.PAGE_NOT_EXIST'|tu }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block bottom %}
|
||||
{{ parent() }}
|
||||
|
||||
{# TODO: RAW MODE
|
||||
<script>
|
||||
$('.admin-flex-config .form-tabs .tabs-nav').css('margin-right', ($('#admin-topbar').width() + 20) + 'px');
|
||||
</script>
|
||||
#}
|
||||
{% endblock bottom %}
|
||||
@@ -0,0 +1,121 @@
|
||||
{% extends 'partials/base.html.twig' %}
|
||||
{% use 'flex-objects/types/default/titlebar/edit.html.twig' %}
|
||||
|
||||
{# Avoid defining form and object twice: object should always come from the form! #}
|
||||
{% if form is not defined %}
|
||||
{% set form = object.form %}
|
||||
{% set object = form.object %}
|
||||
{% endif %}
|
||||
|
||||
{# Allowed actions #}
|
||||
{% set can_list = can_list ?? directory.isAuthorized('list', 'admin', user) %}
|
||||
{% set can_read = can_read ?? (object.exists ? object.isAuthorized('read', 'admin', user) : directory.isAuthorized('create', 'admin', user)) %}
|
||||
{% set can_create = can_create ?? object.isAuthorized('create', 'admin', user) %}
|
||||
{% set can_save = can_save ?? (object.exists ? object.isAuthorized('update', 'admin', user) : directory.isAuthorized('create', 'admin', user)) %}
|
||||
{% set can_delete = can_delete ?? (object.exists and object.isAuthorized('delete', 'admin', user)) %}
|
||||
{% set can_translate = can_translate ?? (admin.multilang and object.hasFlexFeature('flex-translate')) %}
|
||||
{% set can_preview = can_preview ?? (can_read and object.exists and (directory.config('admin.views.preview.enabled') ?? directory.config('admin.preview.enabled', false))) %}
|
||||
|
||||
{# Translations #}
|
||||
{% if can_translate %}
|
||||
{% set translate_include_default = translate_include_default ?? grav.config.get('system.languages.include_default_lang_file_extension', true) %}
|
||||
{% set all_languages = grav.admin.siteLanguages %}
|
||||
{% set admin_languages = admin.languages_enabled %}
|
||||
{% set default_language = grav.language.default %}
|
||||
{% set object_language = object.language %}
|
||||
{% set language = controller.language %}
|
||||
{% set has_translation = object.hasTranslation(language, false) %}
|
||||
|
||||
{#
|
||||
{% if translate_include_default %}
|
||||
{% set all_languages = all_languages|merge({'': 'Default'}) %}
|
||||
{% set admin_languages = admin_languages|merge({'': ''}) %}
|
||||
{% set object_languages = object.languages(true) %}
|
||||
{% else %}
|
||||
#}
|
||||
{% set language = language ?: default_language %}
|
||||
{% set object_language = object_language ?: default_language %}
|
||||
{% set object_languages = object.languages(false) %}
|
||||
{# endif #}
|
||||
{% endif %}
|
||||
|
||||
{# These variables can be overridden from the main template file #}
|
||||
{% set allowed = allowed ?? (directory and (object.exists and (can_read or can_save)) or (action == 'add' and can_read)) %}
|
||||
{% set back_route = back_route ?? ('/' ~ (action != 'edit' and not key ? route.getRoute(1, not can_list ? -1 : null) : route.getRoute(1, not can_list ? -2 : -1))) %}
|
||||
{% set title_icon = title_icon ?? view_config['icon'] ?? directory.config.admin.menu.list.icon ?? 'fa-file-text-o' %}
|
||||
{% set title -%}
|
||||
{%- set title_config = view_config['title'] -%}
|
||||
{%- if title_config.template -%}
|
||||
{{- include(template_from_string(title_config.template, 'edit title template')) -}}
|
||||
{%- else -%}
|
||||
{{- title ?? object.form.getValue('title') ?? object.title ?? key -}}
|
||||
{% endif %}
|
||||
{%- endset %}
|
||||
|
||||
{% block body %}
|
||||
{% set back_url = back_url ?? admin_route(back_route) %}
|
||||
{% set id = key %}
|
||||
{% set blueprint = blueprint ?? form.blueprint %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock body %}
|
||||
|
||||
{% block content_top %}
|
||||
{% if allowed and user.authorize('admin.super') %}
|
||||
{% if directory and object or action == 'add' %}
|
||||
{% set save_location = object.getStorageFolder() ?? directory.getStorageFolder() %}
|
||||
<div class="alert notice">{{ "PLUGIN_ADMIN.SAVE_LOCATION"|tu }}: <b>{{ url(save_location, false, true)|trim('/') }} {{ not object.exists ? '[' ~ 'PLUGIN_FLEX_OBJECTS.NEW'|tu|upper ~ ']' }}</b></div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if object.exists and form.flash.exists %}
|
||||
<div class="alert secondary-accent">
|
||||
<i class="fa fa-lightbulb-o"></i> {{ 'PLUGIN_FLEX_OBJECTS.STATE.EDITING_DRAFT'|tu }} <button class="button button-link" type="submit" name="task" value="reset" form="blueprints">{{ "PLUGIN_ADMIN.RESET"|tu }}</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if allowed %}
|
||||
<div class="clear directory admin-{{ target }}">
|
||||
<div class="admin-form-wrapper">
|
||||
<div id="admin-topbar">
|
||||
{% block topbar %}{% endblock %}
|
||||
</div>
|
||||
{% block edit %}
|
||||
{% include 'partials/blueprints.html.twig' with { form: form, context: object, data: object } %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'partials/modal-changes-detected.html.twig' %}
|
||||
|
||||
{% if can_delete %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/modals/remove.html.twig', 'flex-objects/types/default/modals/remove.html.twig'] with { name: target } %}
|
||||
{% endif %}
|
||||
|
||||
{% elseif (object.exists) %}
|
||||
|
||||
{% do page.modifyHeader('http_response_code', 403) %}
|
||||
<div class="error-block">
|
||||
<h1>{{ 'PLUGIN_ADMIN.ERROR'|tu }} 403</h1>
|
||||
<div class="padding">
|
||||
<p>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.PAGE_FORBIDDEN'|tu }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
|
||||
{% do page.modifyHeader('http_response_code', 404) %}
|
||||
<div class="error-block">
|
||||
<h1>{{ 'PLUGIN_ADMIN.ERROR'|tu }} 404</h1>
|
||||
<div class="padding">
|
||||
<p>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.PAGE_NOT_EXIST'|tu }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,98 @@
|
||||
{% extends 'partials/base.html.twig' %}
|
||||
{% use 'flex-objects/types/default/titlebar/list.html.twig' %}
|
||||
|
||||
{# Allowed actions #}
|
||||
{% set export = directory.config('admin.views.export') ?? directory.config('admin.export') ?? [] %}
|
||||
{% set can_export = can_export ?? (export['enabled'] ?? export|array|count)|bool %}
|
||||
{% set can_create = can_create ?? directory.isAuthorized('create', 'admin', user) %}
|
||||
{% set can_translate = can_translate ?? (admin.multilang and directory.object.hasFlexFeature('flex-translate')) %}
|
||||
|
||||
{% set per_page = per_page ?? grav.uri.currentUri.queryParam('per_page') %}
|
||||
|
||||
{# Translations #}
|
||||
{% if can_translate %}
|
||||
{% set translate_include_default = translate_include_default ?? grav.config.get('system.languages.include_default_lang_file_extension', true) %}
|
||||
{% set all_languages = grav.admin.siteLanguages %}
|
||||
{% set admin_languages = admin.languages_enabled %}
|
||||
{% set default_language = grav.language.default %}
|
||||
{% set language = controller.language %}
|
||||
{#
|
||||
{% if translate_include_default %}
|
||||
{% set all_languages = all_languages|merge({'': 'Default'}) %}
|
||||
{% set admin_languages = admin_languages|merge({'': ''}) %}
|
||||
{% else %}
|
||||
#}
|
||||
{% set language = language ?: default_language %}
|
||||
{# endif #}
|
||||
{% endif %}
|
||||
|
||||
{# These variables can be overridden from the main template file #}
|
||||
{% set allowed = allowed ?? (directory and directory.isAuthorized('list', 'admin', user)) %}
|
||||
{% set back_route = back_route ?? route.getRoute(1, -1) %}
|
||||
|
||||
{% set configure_path = directory.config('admin.router.actions.configure.path') %}
|
||||
{% set configure_route = configure_route ?? (configure_path ? route.withRoute(admin_route(configure_path)|trim('/')) : null) %}
|
||||
{% set configure_route = configure_route ?? route.withGravParam('', 'configure') %}
|
||||
|
||||
{% set title_icon = title_icon ?? view_config['icon'] ?? directory.config.admin.menu.list.icon ?? 'fa-file-text-o' %}
|
||||
{% set title -%}
|
||||
{%- set title_config = view_config['title'] ?? null -%}
|
||||
{%- if title_config.template -%}
|
||||
{{- include(template_from_string(title_config.template, 'configure title template')) -}}
|
||||
{%- else -%}
|
||||
{{- directory.title|tu -}}
|
||||
{% endif %}
|
||||
{%- endset %}
|
||||
|
||||
{% set schema = directory.blueprint.schema %}
|
||||
|
||||
{% do assets.addJs('plugin://flex-objects/js/flex-objects.js', { 'group': 'bottom', 'loading': 'defer' }) %}
|
||||
|
||||
{% block body %}
|
||||
{% set collection = directory ? collection.isAuthorized('list', 'admin', user) %}
|
||||
{% set directory_config = view_config['options'] ?? config.get('plugins.flex-objects.admin_list', { per_page: 15, order: { by: 'updated_timestamp', dir: 'desc' }}) %}
|
||||
{% set per_page = max(1, per_page ?? directory_config.per_page) %}
|
||||
{% set table = directory ? flex.dataTable(collection.flexDirectory(), { collection: collection, limit: per_page, sort: directory_config.order.by ~ '|' ~ directory_config.order.dir }) %}
|
||||
{% set back_url = admin_route(back_route) %}
|
||||
{% set configure_url = (directory.config('admin.views.configure.hidden') ?? directory.config('admin.configure.hidden', false)) is not same as(true) ? configure_route.toString(true) %}
|
||||
|
||||
{% set fields = table.getColumns() %}
|
||||
{% set fields_count = fields ? count(fields) : 0 %}
|
||||
{% set fields_width = 8 %}
|
||||
{% set fields_set = 0 %}
|
||||
{% set title_field = view_config['title'] %}
|
||||
{% for key,options in fields %}
|
||||
{% set fields_width = fields_width + options.width ?: 0 %}
|
||||
{% set fields_set = fields_set + (options.width ? 1 : 0) %}
|
||||
{% if not title_field and options.link == 'edit' %}
|
||||
{% set title_field = key %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock body %}
|
||||
|
||||
{% block content_top %}
|
||||
{% if allowed and user.authorize('admin.super') %}
|
||||
{% set save_location = directory.getStorageFolder() %}
|
||||
<div class="alert notice">{{ "PLUGIN_ADMIN.SAVE_LOCATION"|tu }}: <b>{{ url(save_location, false, true)|trim('/') }}</b></div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if allowed %}
|
||||
{% block content_list %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/list/list.html.twig', 'flex-objects/types/default/list/list.html.twig'] %}
|
||||
{% endblock %}
|
||||
{% else %}
|
||||
{% do page.modifyHeader('http_response_code', 404) %}
|
||||
<div class="error-block">
|
||||
<h1>{{ 'PLUGIN_ADMIN.ERROR'|tu }} 404</h1>
|
||||
<div class="padding">
|
||||
<p>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.PAGE_NOT_EXIST'|tu }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,112 @@
|
||||
{% block directory %}
|
||||
<div id="directory">
|
||||
{% if not fields %}
|
||||
{% block no_list %}
|
||||
<div class="no-entries">
|
||||
<p>{{ 'PLUGIN_FLEX_OBJECTS.ERROR.BLUEPRINT_NO_LIST'|tu( target, null )|raw }}</p>
|
||||
<ul>
|
||||
<li>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.BLUEPRINT_NO_LIST_ADVISE'|tu }}
|
||||
</li>
|
||||
<li>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.BLUEPRINT_NO_LIST_TEMPLATE'|tu( target, null )|raw }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% elseif not collection.count %}
|
||||
{% block no_entries %}
|
||||
<div class="no-entries">
|
||||
{% if directory.isAuthorized('create', 'admin', user) %}
|
||||
{% set createLink = admin_route(flex.adminRoute(collection, {action: 'add'})) %}
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.LIST_EMPTY_ADD'|tu(createLink, null)|raw }}
|
||||
{% else %}
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.LIST_EMPTY'|tu }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% else %}
|
||||
{% block entries %}
|
||||
{% set per_page = per_page ?? directory_config.per_page %}
|
||||
|
||||
{% set tableFields = [] %}
|
||||
{% set searchFields = [] %}
|
||||
{% for key, options in fields %}
|
||||
{% set name = key %}
|
||||
{% set sortField = options.sort.field ?? key %}
|
||||
{% set title = (options.field.label ?? schema.get(options.alias ?? key).label)|tu %}
|
||||
{% set width = options.width ?: ((100-fields_width) / ((fields_count-fields_set) ?: 1))|round(3) %}
|
||||
{% set title_class = options.title_class ?: '' %}
|
||||
{% set data_class = options.data_class ?: '' %}
|
||||
|
||||
{# Vuetable doesn't like field names with `.` in them, so we convert name and sortField to `_` #}
|
||||
{% set tableFields = tableFields|merge([
|
||||
{
|
||||
name: name|replace({'.': '_'}),
|
||||
sortField: sortField,
|
||||
title: title ?? 'N/A',
|
||||
width: width ~ '%',
|
||||
titleClass: title_class,
|
||||
dataClass: data_class
|
||||
}
|
||||
]) %}
|
||||
|
||||
{# FIXME: Search fields should be passed and individually customizable, right now defaulting to all fields selected #}
|
||||
{% set searchFields = searchFields|merge([key|replace({'.': '_'})]) %}
|
||||
{% endfor %}
|
||||
{% set tableFields = tableFields|merge([{ name: '_actions_', title: 'Actions', titleClass: 'right' }]) %}
|
||||
|
||||
|
||||
{% set list = table.jsonSerialize %}
|
||||
|
||||
<div
|
||||
id="flex-objects-list"
|
||||
data-initial-store="{{
|
||||
{
|
||||
data: list,
|
||||
api: grav.uri.currentRoute().withExtension('json').uri()|string,
|
||||
perPage: per_page,
|
||||
fields: tableFields,
|
||||
searchFields: searchFields,
|
||||
sortOrder: [{ field: directory_config.order.by, direction: directory_config.order.dir }],
|
||||
searchPlaceholder: "PLUGIN_ADMIN.RESOURCE_FILTER"|tu,
|
||||
paginationInfo: "PLUGIN_FLEX_OBJECTS.LIST_INFO"|tu,
|
||||
emptyResult: "PLUGIN_FLEX_OBJECTS.EMPTY_RESULT"|tu
|
||||
}|json_encode|e('html_attr')
|
||||
}}">
|
||||
<svg viewBox="0 0 1060 {{ 31 * (min(per_page, list.data|count) + 2) }}">
|
||||
{% for i in 0..((min(per_page, list.data|count) + 3) - 1) %}
|
||||
<rect clip-path="url(#clip-path-{{ i }})" x="0" y="0" width="1060" height="{{ 31 * per_page }}" style="fill: url(#linear-gradient-{{ i }})"></rect>
|
||||
<defs>
|
||||
<clipPath id="clip-path-{{ i }}">
|
||||
<rect x="13" y="{{ 31 * i + 10 }}" rx="6" ry="6" width="{{ 200 * random([0.7, 0.8, 0.9, 1]) }}" height="12"></rect>
|
||||
<rect x="533" y="{{ 31 * i + 10 }}" rx="6" ry="6" width="{{ 63 * random([0.7, 0.8, 0.9, 1]) }}" height="12"></rect>
|
||||
<rect x="653" y="{{ 31 * i + 10 }}" rx="6" ry="6" width="{{ 78 * random([0.7, 0.8, 0.9, 1]) }}" height="12"></rect>
|
||||
<rect x="755" y="{{ 31 * i + 10 }}" rx="6" ry="6" width="{{ 117 * random([0.7, 0.8, 0.9, 1]) }}" height="12"></rect>
|
||||
<rect x="938" y="{{ 31 * i + 10 }}" rx="6" ry="6" width="{{ 83 * random([0.7, 0.8, 0.9, 1]) }}" height="12"></rect>
|
||||
|
||||
<rect x="0" y="{{ 31 * i }}" rx="6" ry="6" width="1060" height=".3"></rect>
|
||||
</clipPath>
|
||||
<linearGradient id="linear-gradient-{{ i }}">
|
||||
<stop offset="-0.60016" stop-color="#d9d9d9" stop-opacity="1">
|
||||
<animate attributeName="offset" values="-3; 1" dur="2s" repeatCount="indefinite"></animate>
|
||||
</stop>
|
||||
<stop offset="0.39984" stop-color="#ecebeb" stop-opacity="1">
|
||||
<animate attributeName="offset" values="-2; 2" dur="2s" repeatCount="indefinite"></animate>
|
||||
</stop>
|
||||
<stop offset="1.39984" stop-color="#d9d9d9" stop-opacity="1">
|
||||
<animate attributeName="offset" values="-1; 3" dur="2s" repeatCount="indefinite"></animate>
|
||||
</stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
{% endfor %}
|
||||
</svg>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block modals %}
|
||||
{% include 'flex-objects/types/default/modals/remove.html.twig' with { name: target } %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,39 @@
|
||||
{% set object_title = title_field ? "'" ~ object[title_field]|join(' ') ~ "'" : 'Item' %}
|
||||
{% set can_read = object.isAuthorized('read', 'admin', user) %}
|
||||
{% set can_update = object.isAuthorized('update', 'admin', user) %}
|
||||
{% set can_delete = object.isAuthorized('delete', 'admin', user) %}
|
||||
|
||||
{% if can_read and object.getRoute() %}
|
||||
{% block action_preview %}
|
||||
<a href="{{ route.withAddedPath(object.getKey()).withoutParams().withQueryParam('preview', 1).getUri() }}" title="{{ "PLUGIN_ADMIN.PREVIEW"|tu }}" class="preview-action">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if can_update %}
|
||||
{% block action_edit %}
|
||||
<a href="{{ route.withAddedPath(object.getKey()).withoutParams().getUri() }}" title="Edit {{ object_title }}" class="edit-action">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
{% endblock %}
|
||||
{% elseif can_read %}
|
||||
{% block action_read %}
|
||||
<a href="{{ route.withAddedPath(object.getKey()).withoutParams().getUri() }}" title="View {{ object_title }}" class="edit-action">
|
||||
<i class="fa fa-search"></i>
|
||||
</a>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if can_delete %}
|
||||
{% block action_delete %}
|
||||
<a href="#delete"
|
||||
class="page-delete delete-action"
|
||||
title="Delete {{ object_title }}"
|
||||
data-remodal-target="delete"
|
||||
data-delete-url="{{ grav.uri.addNonce(route.withAddedPath(object.getKey()).withoutParams().withGravParam('task', 'delete').getUri(), 'admin-form', 'admin-nonce') }}"
|
||||
>
|
||||
<i class="fa fa-close"></i>
|
||||
</a>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,13 @@
|
||||
<div class="remodal" data-remodal-id="delete" data-remodal-options="hashTracking: false">
|
||||
<form>
|
||||
{# FIXME -name|singularize- is not translatable #}
|
||||
<h1>{{ 'PLUGIN_FLEX_OBJECTS.ACTION.DELETE_N'|tu }} {{ name|singularize|capitalize }}</h1>
|
||||
<p class="bigger">
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ACTION.REALLY_DELETE'|tu( name|singularize, null ) }}
|
||||
</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"|tu }}</button>
|
||||
<a class="button disable-after-click" data-delete-action href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,62 @@
|
||||
{% extends 'partials/base.html.twig' %}
|
||||
{% use 'flex-objects/types/default/titlebar/preview.html.twig' %}
|
||||
|
||||
{# Allowed actions #}
|
||||
{% set can_preview = can_preview ?? (object.exists and (view_config['enabled'] ?? false)) %}
|
||||
{% set can_translate = can_translate ?? (admin.multilang and object.hasFlexFeature('flex-translate')) %}
|
||||
|
||||
{# These variables can be overridden from the main template file #}
|
||||
{% set allowed = allowed ?? (directory and (object.exists or action == 'add')) %}
|
||||
{% set back_route = back_route ?? ('/' ~ route.getRoute(1)) %}
|
||||
{% set title_icon = title_icon ?? view_config['icon'] ?? directory.config.admin.menu.list.icon ?? 'fa-file-text-o' %}
|
||||
{% set title -%}
|
||||
{%- set title_config = view_config['title'] -%}
|
||||
{%- if title_config.template -%}
|
||||
{{- include(template_from_string(title_config.template, 'edit title template')) -}}
|
||||
{%- else -%}
|
||||
{{- title ?? object.form.getValue('title') ?? object.title ?? key -}}
|
||||
{% endif %}
|
||||
{%- endset %}
|
||||
{% set preview_url -%}
|
||||
{%- set route_config = view_config['route'] -%}
|
||||
{%- if route_config.template -%}
|
||||
{{- include(template_from_string(route_config.template, 'preview route template')) -}}
|
||||
{%- else -%}
|
||||
{{- preview_url ?? object.getRoute().uri ?: '' -}}
|
||||
{%- endif -%}
|
||||
{% endset -%}
|
||||
|
||||
{% block body %}
|
||||
{% if not can_preview or not preview_url %}
|
||||
{% set allowed = false %}
|
||||
{% endif %}
|
||||
{% set id = key %}
|
||||
{% set blueprint = object.blueprint ?? directory.blueprint %}
|
||||
{% set back_url = back_url ?? admin_route(back_route) %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock body %}
|
||||
|
||||
{% block content_wrapper %}
|
||||
{% if can_preview and allowed and preview_url %}
|
||||
<div class="content-wrapper preview-wrapper">
|
||||
<div class="content-padding" width="100%" height="100%">
|
||||
<iframe width="100%" height="100%" frameborder="0" src="{{ preview_url }}"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock content_wrapper %}
|
||||
|
||||
{% block content %}
|
||||
{% do page.modifyHeader('http_response_code', 404) %}
|
||||
<div class="error-block">
|
||||
<h1>{{ 'PLUGIN_ADMIN.ERROR'|tu }} 404</h1>
|
||||
<div class="padding">
|
||||
<p>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ERROR.PAGE_NOT_EXIST'|tu }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,32 @@
|
||||
{% block titlebar %}
|
||||
{% block titlebar_button_bar %}
|
||||
<div class="button-bar">
|
||||
{# BACK #}
|
||||
{% block back_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/back.html.twig', 'flex-objects/types/default/buttons/back.html.twig'] %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{% block extra_buttons %}{% endblock extra_buttons %}
|
||||
|
||||
{# SAVE #}
|
||||
{% if can_save %}
|
||||
{% block save_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/save.html.twig', 'flex-objects/types/default/buttons/save.html.twig'] with {task: 'configure'} %}
|
||||
{% endblock save_button %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock titlebar_button_bar %}
|
||||
|
||||
{% block titlebar_title %}
|
||||
<h1>
|
||||
{% if allowed %}
|
||||
<i class="fa fa-fw fa-cog"></i>
|
||||
{{ title }}
|
||||
{% else %}
|
||||
<i class="fa fa-fw fa-exclamation-triangle"></i>
|
||||
{{ 'PLUGIN_ADMIN.ERROR'|tu }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% endblock titlebar_title %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% block titlebar %}
|
||||
{% block titlebar_button_bar %}
|
||||
<div class="button-bar">
|
||||
{# BACK #}
|
||||
{% block back_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/back.html.twig', 'flex-objects/types/default/buttons/back.html.twig'] %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{# PREVIEW #}
|
||||
{% if can_preview %}
|
||||
{% block preview_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/preview.html.twig', 'flex-objects/types/default/buttons/preview.html.twig'] %}
|
||||
{% endblock preview_button %}
|
||||
{% endif %}
|
||||
|
||||
{# DELETE #}
|
||||
{% if can_delete %}
|
||||
{% block delete_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/delete.html.twig', 'flex-objects/types/default/buttons/delete.html.twig'] %}
|
||||
{% endblock delete_button %}
|
||||
{% endif %}
|
||||
|
||||
{% block extra_buttons %}{% endblock extra_buttons %}
|
||||
|
||||
{# SAVE #}
|
||||
{% if allowed and can_save %}
|
||||
{% block save_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/save.html.twig', 'flex-objects/types/default/buttons/save.html.twig'] with {task: 'save'} %}
|
||||
{% endblock save_button %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock titlebar_button_bar %}
|
||||
|
||||
{% block titlebar_title %}
|
||||
<h1>
|
||||
{% if allowed %}
|
||||
<i class="fa fa-fw {{ title_icon }}"></i>
|
||||
{{ not object.exists ? '[' ~ 'PLUGIN_FLEX_OBJECTS.NEW'|tu|upper ~ ']' }} {{ title|tu }}
|
||||
{% else %}
|
||||
<i class="fa fa-fw fa-exclamation-triangle"></i>
|
||||
{{ 'PLUGIN_ADMIN.ERROR'|tu }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% endblock titlebar_title %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,48 @@
|
||||
{% block titlebar %}
|
||||
{% block titlebar_button_bar %}
|
||||
<div class="button-bar">
|
||||
{# BACK #}
|
||||
{% block back_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/back.html.twig', 'flex-objects/types/default/buttons/back.html.twig'] %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{# EXPORT #}
|
||||
{% if can_export %}
|
||||
{% block export_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/export.html.twig', 'flex-objects/types/default/buttons/export.html.twig'] with {export: directory.config('admin.views.export') ?? directory.config('admin.export') ?? []} %}
|
||||
{% endblock export_button %}
|
||||
{% endif %}
|
||||
|
||||
{# CREATE #}
|
||||
{% if can_create %}
|
||||
{% block create_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/add.html.twig', 'flex-objects/types/default/buttons/add.html.twig'] %}
|
||||
{% endblock create_button %}
|
||||
{% endif %}
|
||||
|
||||
{# LANGUAGES #}
|
||||
{% if can_translate %}
|
||||
{% block languages_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/languages.html.twig', 'flex-objects/types/default/buttons/languages.html.twig'] %}
|
||||
{% endblock languages_button %}
|
||||
{% endif %}
|
||||
|
||||
{# CONFIGURE #}
|
||||
{% block configure %}
|
||||
{% include 'flex-objects/types/default/buttons/configuration.html.twig' %}
|
||||
{% endblock configure %}
|
||||
</div>
|
||||
{% endblock titlebar_button_bar %}
|
||||
|
||||
{% block titlebar_title %}
|
||||
<h1>
|
||||
{% if allowed %}
|
||||
<i class="fa fa-fw {{ directory ? title_icon : 'fa-exclamation-triangle' }}"></i>
|
||||
{{ directory ? title|tu : 'Error' }}
|
||||
{% else %}
|
||||
<i class="fa fa-fw fa-exclamation-triangle"></i>
|
||||
{{ 'PLUGIN_ADMIN.ERROR'|tu }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% endblock titlebar_title %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% block titlebar %}
|
||||
{% block titlebar_button_bar %}
|
||||
<div class="button-bar">
|
||||
{# BACK #}
|
||||
{% block back_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/back.html.twig', 'flex-objects/types/default/buttons/back.html.twig'] %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{# PREVIEW #}
|
||||
{% if can_preview %}
|
||||
{% block preview_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/preview-open.html.twig', 'flex-objects/types/default/buttons/preview-open.html.twig'] %}
|
||||
{% endblock preview_button %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock titlebar_button_bar %}
|
||||
|
||||
{% block titlebar_title %}
|
||||
<h1>
|
||||
{% if allowed %}
|
||||
<i class="fa fa-fw {{ title_icon }}"></i>
|
||||
{{ "PLUGIN_ADMIN.PREVIEW"|tu }}: {{ not object.exists ? '[' ~ 'PLUGIN_FLEX_OBJECTS.NEW'|tu|upper ~ ']' }} <strong>{{ title }}</strong>
|
||||
{% else %}
|
||||
<i class="fa fa-fw fa-exclamation-triangle"></i>
|
||||
{{ 'PLUGIN_ADMIN.ERROR'|tu }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% endblock titlebar_title %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
{% block titlebar %}
|
||||
{% block titlebar_button_bar %}
|
||||
<div class="button-bar">
|
||||
{# BACK #}
|
||||
{% block back_button %}
|
||||
{% include 'flex-objects/types/default/buttons/back.html.twig' %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{# CONFIGURE #}
|
||||
{% block configure %}
|
||||
{% include 'flex-objects/types/default/buttons/configuration.html.twig' %}
|
||||
{% endblock configure %}
|
||||
</div>
|
||||
{% endblock titlebar_button_bar %}
|
||||
|
||||
{% block titlebar_title %}
|
||||
<h1>
|
||||
<i class="fa fa-fw fa-list"></i>
|
||||
{{ "PLUGIN_FLEX_OBJECTS.TITLE"|tu }}
|
||||
</h1>
|
||||
{% endblock titlebar_title %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% extends 'partials/base.html.twig' %}
|
||||
{% use 'flex-objects/types/default/titlebar/types.html.twig' %}
|
||||
|
||||
{% set flex = grav['flex_objects'] %}
|
||||
|
||||
{# These variables can be overridden from the main template file #}
|
||||
{% set back_route = back_route ?? ('/' ~ route.getRoute(1, -1)) %}
|
||||
{% set configure_route = '/plugins/flex-objects' %}
|
||||
|
||||
{% block body %}
|
||||
{% set back_url = admin_route(back_route) %}
|
||||
{% set configure_url = configure_route ? admin_route(configure_route) : null %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock body %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ 'PLUGIN_FLEX_OBJECTS.TYPES_TITLE'|tu }}</h1>
|
||||
|
||||
<div id="types" class="card-row grid fixed-blocks pure-g">
|
||||
{% for name,directory in flex.directories if directory.enabled and directory.config('admin.hidden', false) is not same as(true) and not directory.config('admin.menu') %}
|
||||
{% try %}
|
||||
{% set collection = directory.collection %}
|
||||
{% if flex.adminRoute(collection) %}
|
||||
<div class="card-item pure-u-1-3">
|
||||
|
||||
<h2><a href="{{ admin_route(flex.adminRoute(collection)) }}">{{ directory.title|tu }}</a> <span class="badge">{{ collection.isAuthorized('list', 'admin', user).count }}</span></h2>
|
||||
<p>
|
||||
{{ directory.description }}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% catch %}
|
||||
<div class="card-item pure-u-1-3">
|
||||
<h2>{{ 'PLUGIN_FLEX_OBJECTS.ERROR.BAD_DIRECTORY'|tu }} '{{ name }}'</h2>
|
||||
<p>
|
||||
{{ e.message }}
|
||||
</p>
|
||||
</div>
|
||||
{% endcatch %}
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,20 @@
|
||||
<div id="titlebar-add" class="button-group">
|
||||
<button type="button" class="button disabled" href="#modal" data-remodal-target="modal">
|
||||
<i class="fa fa-plus"></i> {{ "PLUGIN_ADMIN.ADD"|tu }}
|
||||
</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"|tu }}</a></li>
|
||||
<li><a class="button" href="#modal-folder" data-remodal-target="modal-folder">{{ "PLUGIN_ADMIN.ADD_FOLDER"|tu }}</a></li>
|
||||
{% if admin.modularTypes is not empty %}
|
||||
<li><a class="button" href="#module" data-remodal-target="module">{{ "PLUGIN_ADMIN.ADD_MODULE"|tu }}</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|tu }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<a id="titlebar-button-back" class="button" href="{{ back_url }}" title="{{ "PLUGIN_ADMIN.BACK"|tu }}">
|
||||
<i class="fa fa-reply"></i>
|
||||
</a>
|
||||
@@ -0,0 +1,4 @@
|
||||
{# href="{{ uri.addNonce(route.withoutParams().withGravParam('task', 'copy').getUri(), 'admin-form', 'admin-nonce') }}" #}
|
||||
<a id="titlebar-button-copy" href="#modal-page-copy" data-remodal-target="modal-page-copy" class="button page-copy">
|
||||
<i class="fa fa-copy"></i> {{ "PLUGIN_ADMIN.COPY"|tu }}
|
||||
</a>
|
||||
@@ -0,0 +1,3 @@
|
||||
<a id="titlebar-button-delete" href="#delete" data-remodal-target="delete" data-delete-url="{{ uri.addNonce(route.withoutParams().withGravParam('task', 'delete').getUri(), 'admin-form', 'admin-nonce') }}" class="button danger">
|
||||
<i class="fa fa-fw fa-trash-o"></i> {{ "PLUGIN_ADMIN.DELETE"|tu }}
|
||||
</a>
|
||||
@@ -0,0 +1,6 @@
|
||||
<a id="titlebar-button-move" class="button" href="#" data-remodal-target="move" data-parents="data[route]">
|
||||
<i class="fa fa-arrows"></i> {{ "PLUGIN_ADMIN.MOVE"|tu }}
|
||||
</a>
|
||||
<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>
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if child_url %}
|
||||
<a id="titlebar-button-nav-child" class="button" href="{{ child_url }}" title="{{ title }}">
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="button disabled">
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if next_url %}
|
||||
<a id="titlebar-button-nav-next" class="button" href="{{ next_url }}" title="{{ title }}">
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="button disabled">
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if parent_url %}
|
||||
<a id="titlebar-button-nav-parent" class="button" href="{{ parent_url }}" title="{{ title }}">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="button disabled">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% if prev_url %}
|
||||
<a id="titlebar-button-nav-prev" class="button" href="{{ prev_url }}" title="{{ title }}">
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="button disabled">
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,5 @@
|
||||
{% if object.routable and object.published %}
|
||||
<a id="titlebar-button-preview" href="{{ route.withGravParam('', 'preview') }}" class="button" title="{{ "PLUGIN_ADMIN.PREVIEW"|tu }}">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,23 @@
|
||||
{% set task = task ?? 'save' %}
|
||||
<div id="titlebar-save" class="button-group">
|
||||
<button class="button success" type="submit" name="task" value="{{ task }}" lang="{{ language }}" form="blueprints">
|
||||
<i class="fa fa-check"></i> {{ "PLUGIN_ADMIN.SAVE"|tu }}
|
||||
</button>
|
||||
{% if can_translate %}
|
||||
{% set untranslated = admin_languages|array_diff(object_languages|merge([language])) %}
|
||||
{% if count(untranslated) %}
|
||||
<button id="titlebar-button-save" 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 lang_code in untranslated %}
|
||||
<li>
|
||||
<button class="button success task" type="submit" name="task" value="saveas" lang="{{ lang_code }}" form="blueprints">
|
||||
{{ "PLUGIN_ADMIN.SAVE_AS"|tu }} {{ all_languages[lang_code] ?? lang_code }}
|
||||
</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,236 @@
|
||||
{% extends 'flex-objects/types/default/edit.html.twig' %}
|
||||
|
||||
{# Avoid defining form and object twice: object should always come from the form! #}
|
||||
{% set expert = user.authorize('admin.super') and admin.session.expert != '0' %}
|
||||
{% if expert or form is not defined %}
|
||||
{% set form = object.form(expert ? 'raw' : '') %}
|
||||
{% set object = form.object %}
|
||||
{% endif %}
|
||||
|
||||
{% set title = title ?? form.getValue('header.title') ?? object.title ?? key %}
|
||||
{% set parent = object.parent %}
|
||||
{% set can_read = can_read ?? (object.exists ? object.isAuthorized('read', 'admin', user) : object.isAuthorized('create', 'admin', user))|bool %}
|
||||
{% set can_copy = can_copy ?? (parent.exists and parent.isAuthorized('create', 'admin', user)) %}
|
||||
{% set can_create = can_create ?? (object.exists and object.isAuthorized('create', 'admin', user)) %}
|
||||
{% set can_save = can_save ?? (object.exists ? object.isAuthorized('update', 'admin', user) : object.isAuthorized('create', 'admin', user))|bool %}
|
||||
{% set can_move = can_move ?? can_save and form.blueprint.schema.property('route').type is same as('parents') %}
|
||||
{% set can_translate = can_translate ?? (admin.multilang and object.hasFlexFeature('page-translate') and not object.root()) %}
|
||||
|
||||
{% macro spanToggle(input, length) %}
|
||||
{{ (repeat(' ', (length - input|length) / 2) ~ input ~ repeat(' ', (length - input|length) / 2))|raw }}
|
||||
{% endmacro %}
|
||||
{% import _self as macro %}
|
||||
|
||||
{% block body %}
|
||||
{% set current_route = '/' ~ route.getRoute(1) %}
|
||||
|
||||
{% if not object.root() %}
|
||||
{% set child = object.children.first %}
|
||||
{% set prev = object.prevSibling %}
|
||||
{% set next = object.nextSibling %}
|
||||
|
||||
{% set parent_url = parent and not parent.root ? admin_route(back_route) %}
|
||||
{% set child_url = can_read and child ? admin_route(current_route ~ '/' ~ child.slug) %}
|
||||
{% set prev_url = can_read and prev ? admin_route(back_route ~ '/' ~ prev.slug) %}
|
||||
{% set next_url = can_read and next ? admin_route(back_route ~ '/' ~ next.slug) %}
|
||||
{% endif %}
|
||||
{% set back_url = back_url ?? admin_route(flex.adminRoute(directory.getFlexType())) %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock body %}
|
||||
|
||||
{% block back_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/back.html.twig', 'flex-objects/types/pages/buttons/back.html.twig']
|
||||
with { back_url: back_url } %}
|
||||
{% if not object.root() %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/nav-prev.html.twig', 'flex-objects/types/pages/buttons/nav-prev.html.twig']
|
||||
with { prev_url: prev_url, title: prev.route } %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/nav-parent.html.twig', 'flex-objects/types/pages/buttons/nav-parent.html.twig']
|
||||
with { parent_url: parent_url, title: parent.route } %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/nav-child.html.twig', 'flex-objects/types/pages/buttons/nav-child.html.twig']
|
||||
with { child_url: child_url, title: child.route } %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/nav-next.html.twig', 'flex-objects/types/pages/buttons/nav-next.html.twig']
|
||||
with { next_url: next_url, title: next.route } %}
|
||||
{% endif %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{% block preview_button %}
|
||||
{% if object.exists and not object.root() %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/preview.html.twig', 'flex-objects/types/pages/buttons/preview.html.twig'] %}
|
||||
{% endif %}
|
||||
{% endblock preview_button %}
|
||||
|
||||
{% block delete_button %}
|
||||
{# FIXME: add support for deleting root file only #}
|
||||
{% if not object.root() %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/delete.html.twig', 'flex-objects/types/pages/buttons/delete.html.twig'] %}
|
||||
{% endif %}
|
||||
{% endblock delete_button %}
|
||||
|
||||
{% block extra_buttons %}
|
||||
{% if object.exists and not object.root() %}
|
||||
{% if can_create %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/add.html.twig', 'flex-objects/types/pages/buttons/add.html.twig'] %}
|
||||
{% endif %}
|
||||
{% if can_copy %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/copy.html.twig', 'flex-objects/types/pages/buttons/copy.html.twig'] %}
|
||||
{% endif %}
|
||||
{% if can_move %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/move.html.twig', 'flex-objects/types/pages/buttons/move.html.twig'] %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock extra_buttons %}
|
||||
|
||||
{% block save_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/save.html.twig', 'flex-objects/types/pages/buttons/save.html.twig'] %}
|
||||
{% endblock save_button %}
|
||||
|
||||
{% block content_top %}
|
||||
{% if allowed and user.authorize('admin.super') %}
|
||||
<div class="alert notice">
|
||||
{% set save_location = object.getStorageFolder() ?: directory.getStorageFolder() %}
|
||||
{{ "PLUGIN_ADMIN.SAVE_LOCATION"|tu }}: <b>{{ url(save_location, false, true)|trim('/') }} {{ not object.exists ? '[' ~ 'PLUGIN_FLEX_OBJECTS.NEW'|tu|upper ~ ']' }}</b> (type: <b>{{ (form.getValue('name') ?: 'default') }}</b>)
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if object.exists and form.flash.exists %}
|
||||
<div class="alert secondary-accent">
|
||||
<i class="fa fa-lightbulb-o"></i> {{ 'PLUGIN_FLEX_OBJECTS.STATE.EDITING_DRAFT'|tu }} <button class="button button-link" type="submit" name="task" value="reset" form="blueprints">{{ "PLUGIN_ADMIN.RESET"|tu }}</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not object.exists %}
|
||||
<div class="alert secondary-accent">
|
||||
<i class="fa fa-lightbulb-o"></i> {{ 'PLUGIN_FLEX_OBJECTS.STATE.NOT_CREATED_YET'|tu }}
|
||||
</div>
|
||||
{% elseif can_translate %}
|
||||
{% set is_default = language is same as(default_language) %}
|
||||
{% if is_default and default_language in object_languages %}
|
||||
{% if not translate_include_default and object.property('lang') %}
|
||||
{# Handle default language extension #}
|
||||
<div class="alert secondary-accent">
|
||||
{% set overrideLanguage = all_languages[object_language] ?? object_language %}
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.LANGUAGE.USING_OVERRIDE'|tu(overrideLanguage, null)|raw }}
|
||||
{{ object.hasTranslation('', false) ? 'PLUGIN_FLEX_OBJECTS.LANGUAGE.UNUSED_DEFAULT'|tu|raw }}
|
||||
</div>
|
||||
{% elseif translate_include_default %}
|
||||
{% if not object.property('lang') %}
|
||||
<div class="alert secondary-accent">
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.LANGUAGE.USING_DEFAULT'|tu|raw }}
|
||||
</div>
|
||||
{% elseif object.hasTranslation('', false) %}
|
||||
<div class="alert secondary-accent">
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.LANGUAGE.UNUSED_DEFAULT'|tu|raw }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% elseif not has_translation %}
|
||||
<div class="alert warning">
|
||||
{% set overrideLanguage = all_languages[language] ?? object_language %}
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.LANGUAGE.NOT_TRANSLATED_YET'|tu(overrideLanguage, null)|raw }}
|
||||
{% if language == object_language %}
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.LANGUAGE.NO_FALLBACK_FOUND'|tu|raw }}
|
||||
{% else %}
|
||||
{% set overrideLanguage = all_languages[object_language] ?? object_language %}
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.LANGUAGE.FALLING_BACK'|tu(overrideLanguage, null)|raw }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock content_top %}
|
||||
|
||||
{% block topbar %}
|
||||
{% if can_translate %}
|
||||
<div id="admin-lang-toggle" class="button-group">
|
||||
<button type="button" class="button disabled">
|
||||
<i class="fa fa-flag-o"></i>
|
||||
{{ all_languages[object_language] ?? object_language }}
|
||||
</button>
|
||||
{% if count(object_languages) > (object_language in object_languages)|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 lang_code in object_languages %}
|
||||
{% if lang_code != object_language %}
|
||||
<li>
|
||||
<a href="{{ admin_route(route.getRoute(1), lang_code) }}">{{ all_languages[lang_code] ?? lang_code }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if user.authorize('admin.super') %}
|
||||
<form id="admin-mode-toggle">
|
||||
{% set normalText = 'PLUGIN_ADMIN.NORMAL'|tu %}
|
||||
{% set expertText = 'PLUGIN_ADMIN.EXPERT'|tu %}
|
||||
{% set maxLen = max([normalText|length, expertText|length]) %}
|
||||
{% set normalText = macro.spanToggle(normalText, maxLen) %}
|
||||
{% set expertText = macro.spanToggle(expertText, maxLen) %}
|
||||
|
||||
<div class="switch-toggle switch-grav">
|
||||
<input type="radio" value="normal" data-leave-url="{{ route.withGravParam('mode', 'normal').toString(true) }}" id="normal" name="mode-switch" class="highlight" {% if expert == '0' %} checked="checked"{% endif %}>
|
||||
<label for="normal">{{ normalText }}</label>
|
||||
<input type="radio" value="expert" data-leave-url="{{ route.withGravParam('mode', 'expert').toString(true) }}" id="expert" name="mode-switch" class="highlight" {% if expert == '1' %} checked="checked"{% endif %}>
|
||||
<label for="expert">{{ expertText }}</label>
|
||||
<a></a>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endblock topbar %}
|
||||
|
||||
{% block edit %}
|
||||
{% include 'partials/blueprints.html.twig' with { context: object, data: object, blueprints: form.blueprint } %}
|
||||
{% endblock edit %}
|
||||
|
||||
{% block content %}
|
||||
{{ parent() }}
|
||||
|
||||
{% include 'partials/modal-changes-detected.html.twig' %}
|
||||
|
||||
{% if object.exists %}
|
||||
{% set modal_data = data({
|
||||
route: '/' ~ object.key,
|
||||
name: object.header.child_type ?? object.blueprint.child_type ?? 'default'
|
||||
}) %}
|
||||
|
||||
<div class="remodal" data-remodal-id="modal" data-remodal-options="hashTracking: false, closeOnOutsideClick: false">
|
||||
{% include 'partials/blueprints-new.html.twig' with { form: null, blueprints: admin.blueprints('admin/pages/new'), data: modal_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 { form: null, blueprints: admin.blueprints('admin/pages/new_folder'), data: modal_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 { form: null, blueprints: admin.blueprints('admin/pages/modular_new'), data: modal_data, form_id: 'new-module' } %}
|
||||
</div>
|
||||
|
||||
<div class="remodal" data-remodal-id="modal-page-copy" data-remodal-options="hashTracking: false, closeOnOutsideClick: false">
|
||||
{% include 'partials/blueprints-copy.html.twig' with { blueprints: admin.blueprints('admin/pages/copy'), data: data({ title: object.title ~ ' (Copy)', folder: object.slug ~ '-copy' }), form_id: 'copy' } %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# TODO: regular pages support extra modals from admin config #}
|
||||
|
||||
<div class="remodal parents-container" data-remodal-id="parents" data-remodal-options="hashTracking: false, stack: true">
|
||||
<form>
|
||||
<h1>{{ 'PLUGIN_FLEX_OBJECTS.PARENTS'|tu }}</h1>
|
||||
<div class="grav-loading"><div class="grav-loader">{{ 'PLUGIN_FLEX_OBJECTS.STATE.LOADING'|tu }}</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"|tu }}</a>
|
||||
<a class="button" data-parents-select href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
{% block bottom %}
|
||||
{{ parent() }}
|
||||
<script>
|
||||
$('.admin-pages .form-tabs .tabs-nav').css('margin-right', ($('#admin-topbar').width() + 20) + 'px');
|
||||
</script>
|
||||
{% endblock bottom %}
|
||||
@@ -0,0 +1,29 @@
|
||||
{% extends 'flex-objects/types/default/list.html.twig' %}
|
||||
|
||||
{% set can_create = true %}
|
||||
|
||||
{% block back_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/back.html.twig', 'flex-objects/types/pages/buttons/back.html.twig'] %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{% block create_button %}
|
||||
{% for key, add_modal in config.plugins.admin.add_modals %}
|
||||
{% if add_modal.show_in|default('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|tu }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/add.html.twig', 'flex-objects/types/pages/buttons/add.html.twig'] %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_top %}{% endblock %}
|
||||
|
||||
{% block content_list %}
|
||||
{% set list_layout = grav.uri.param('layout', 'columns') %}
|
||||
{% include [
|
||||
'flex-objects/types/' ~ target ~ '/list/' ~ list_layout ~ '.html.twig',
|
||||
'flex-objects/types/pages/list/' ~ list_layout ~ '.html.twig',
|
||||
'flex-objects/types/' ~ target ~ '/list/list.html.twig',
|
||||
'flex-objects/types/pages/list/list.html.twig'
|
||||
] %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,155 @@
|
||||
{% macro toggle(id, title, filters, name = null) %}
|
||||
{% set name = id|fieldName %}
|
||||
{% set filter = filters[name] ?? null %}
|
||||
{% set value = filter is null ? 0 : (not filter)|int+1 %}
|
||||
{% set classes = ['status-unchecked', 'status-checked', 'status-indeterminate'] %}
|
||||
|
||||
<span class="checkboxes indeterminate toggleable {{ classes[value] }}" data-_check-status="{{ value }}">
|
||||
<input type="checkbox" id="{{ id }}" name="{{ name }}" indeterminate="{{ value == 2 ? 'true' : 'false' }}" value="{{ filter }}" {% if value == 1 %}checked{% endif %}>
|
||||
<label for="{{ id }}">{{ title }}</label>
|
||||
</span>
|
||||
{% endmacro %}
|
||||
|
||||
{% import _self as macros %}
|
||||
|
||||
{% block directory %}
|
||||
{% set filters = grav.request.getCookieParams()['grav-admin-flexpages']|base64_decode|json_decode(true)['filters'] %}
|
||||
{% set hidePanel = filters|length == 0 or (filters|length == 1 and filters['filters[search]']) %}
|
||||
<div id="pages-content-wrapper">
|
||||
<div id="pages-filters">
|
||||
<form>
|
||||
<div class="filters-bar">
|
||||
<input type="text"
|
||||
placeholder="{{ 'PLUGIN_FLEX_OBJECTS.ACTION.SEARCH_PLACEHOLDER'|tu }}"
|
||||
name="filters[search]"
|
||||
value="{{ filters['filters[search]'] }}" />
|
||||
<a href="#" class="adv-options button-border {{ hidePanel ? 'close' : 'open' }}">
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ACTION.ADVANCED_OPTIONS'|tu }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="filters-advanced {{ hidePanel ? 'hide' }}">
|
||||
<fieldset>
|
||||
<legend>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.FILTER.PAGE_ATTRIBUTES'|tu }}
|
||||
</legend>
|
||||
{{ macros.toggle('filters.routable', 'Routable', filters) }}
|
||||
{{ macros.toggle('filters.module', 'Module', filters) }}
|
||||
{{ macros.toggle('filters.visible', 'Visible', filters) }}
|
||||
{{ macros.toggle('filters.published', 'Published', filters) }}
|
||||
{{ macros.toggle('filters.translated', 'Translated', filters) }}
|
||||
{{ macros.toggle('filters.folder', 'Empty Folder', filters) }}
|
||||
</fieldset>
|
||||
|
||||
{% set selected = filters['filters[page_type]']|split(',') %}
|
||||
{% set page_types = admin.types(null) %} {# directory.config('filters.ignore_page_types') #}
|
||||
<fieldset>
|
||||
<legend>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.FILTER.PAGE_TYPES'|tu }}
|
||||
</legend>
|
||||
{% for name,title in page_types %}
|
||||
<span class="checkboxes toggleable">
|
||||
<input type="checkbox" id="filters.type.{{ name }}" name="filters[page_type][]" value="{{ name }}" {% if name in selected %}checked{% endif %}>
|
||||
<label for="filters.type.{{ name }}">{{ title }}</label>
|
||||
</span>
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
|
||||
{% set module_types = admin.modularTypes(null) %} {# directory.config('filters.ignore_module_types') #}
|
||||
{% if module_types %}
|
||||
<fieldset>
|
||||
<legend>
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.FILTER.MODULAR_TYPES'|tu }}
|
||||
</legend>
|
||||
{% for name,title in module_types %}
|
||||
<span class="checkboxes toggleable">
|
||||
<input type="checkbox" id="filters.type.{{ name }}" name="filters[page_type][]" value="{{ name }}" {% if name in selected %}checked{% endif %}>
|
||||
<label for="filters.type.{{ name }}">{{ title }}</label>
|
||||
</span>
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
|
||||
<a href="#" class="apply-filters button-border" data-filters="apply">
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ACTION.APPLY_FILTERS'|tu }}
|
||||
</a>
|
||||
<a href="#" class="reset-defaults button-border" data-filters="reset">
|
||||
{{ 'PLUGIN_FLEX_OBJECTS.ACTION.RESET_FILTERS'|tu }}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="grav-loading">
|
||||
<div class="grav-loader">{{ 'PLUGIN_FLEX_OBJECTS.STATE.LOADING'|tu }}</div>
|
||||
</div>
|
||||
<div id="pages-columns" style="margin-top: -1rem;"
|
||||
data-lang-url="{{ grav.uri.getCurrentRoute.withoutParams.withExtension('').withLanguage('%LANG%').toString(true) }}"></div>
|
||||
|
||||
</div>
|
||||
|
||||
{# Modals #}
|
||||
<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-module' } %}
|
||||
</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: obj_data,
|
||||
form_id: 'add-modal'
|
||||
}|merge(add_modal.with|defined({})) %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="remodal" data-remodal-id="modal-page-copy" data-remodal-options="hashTracking: false">
|
||||
{% include 'partials/blueprints-copy.html.twig' with { blueprints: admin.blueprints('admin/pages/copy'), data: obj_data, form_id: 'copy' } %}
|
||||
</div>
|
||||
|
||||
<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">{{ 'PLUGIN_FLEX_OBJECTS.STATE.LOADING'|tu }}</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"|tu }}</a>
|
||||
<a class="button" data-parents-select href="#">
|
||||
<i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="remodal" data-remodal-id="delete" data-remodal-options="hashTracking: false">
|
||||
<form>
|
||||
<h1>{{ "PLUGIN_ADMIN.MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_TITLE"|tu }}</h1>
|
||||
<p class="bigger">
|
||||
{% if context %}
|
||||
<strong>{{ "PLUGIN_ADMIN.PAGE"|tu }}: {{ context.title }}</strong>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p class="bigger">
|
||||
{{ "PLUGIN_ADMIN.MODAL_DELETE_PAGE_CONFIRMATION_REQUIRED_DESC"|tu }}
|
||||
</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"|tu }}</button>
|
||||
<a class="button disable-after-click" data-delete-action href="#"><i
|
||||
class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,41 @@
|
||||
{% extends 'flex-objects/types/default/list/list.html.twig' %}
|
||||
|
||||
{% block modals %}
|
||||
<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, closeOnOutsideClick: 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">
|
||||
{% include 'partials/blueprints-new.html.twig' with { blueprints: admin.blueprints('admin/pages/modular_new'), data: obj_data, form_id: 'new-module' } %}
|
||||
</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: obj_data,
|
||||
form_id: 'add-modal'
|
||||
}|merge(add_modal.with|defined({})) %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="remodal" data-remodal-id="modal-page-copy" data-remodal-options="hashTracking: false">
|
||||
{% include 'partials/blueprints-copy.html.twig' with { blueprints: admin.blueprints('admin/pages/copy'), data: obj_data, form_id: 'copy' } %}
|
||||
</div>
|
||||
|
||||
<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">{{ 'PLUGIN_FLEX_OBJECTS.STATE.LOADING'|tu }}</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"|tu }}</a>
|
||||
<a class="button" data-parents-select href="#"><i class="fa fa-fw fa-check"></i> {{ "PLUGIN_ADMIN.CONTINUE"|tu }}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,16 @@
|
||||
{% extends 'flex-objects/types/default/preview.html.twig' %}
|
||||
|
||||
{% set can_translate = can_translate ?? (admin.multilang and object.hasFlexFeature('page-translate')) %}
|
||||
|
||||
{% block back_button %}
|
||||
{% include ['flex-objects/types/' ~ target ~ '/buttons/back.html.twig', 'flex-objects/types/pages/buttons/back.html.twig']
|
||||
with { back_url: back_url } %}
|
||||
{% endblock back_button %}
|
||||
|
||||
{% block body %}
|
||||
{% set parent = object.parent %}
|
||||
|
||||
{% set preview_url = preview_url ?: (object.home ? '/' : '') %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock body %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends 'flex-objects/types/default/configure.html.twig' %}
|
||||
|
||||
{% set back_route = back_route ?? ('/' ~ route.getRoute(1, -1)) %}
|
||||
|
||||
{% block content_top %}
|
||||
{% include 'flex-objects/layouts/accounts/partials/top.html.twig' %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends 'flex-objects/types/default/edit.html.twig' %}
|
||||
|
||||
{% if not directory.isAuthorized('list', 'admin', user) %}
|
||||
{% set back_route = '/' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not object.exists %}
|
||||
{% do object.onPrepareRegistration() %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,7 @@
|
||||
{% extends 'flex-objects/types/default/list.html.twig' %}
|
||||
|
||||
{% block content_top %}
|
||||
{% include 'flex-objects/layouts/accounts/partials/top.html.twig' %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends 'flex-objects/types/default/configure.html.twig' %}
|
||||
|
||||
{% set back_route = back_route ?? ('/' ~ route.getRoute(1, -1)) %}
|
||||
|
||||
{% block content_top %}
|
||||
{% include 'flex-objects/layouts/accounts/partials/top.html.twig' %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,7 @@
|
||||
{% extends 'flex-objects/types/default/list.html.twig' %}
|
||||
|
||||
{% block content_top %}
|
||||
{% include 'flex-objects/layouts/accounts/partials/top.html.twig' %}
|
||||
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,69 @@
|
||||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% macro spanToggle(input, length) %}
|
||||
{% set space = repeat(' ', (length - input|length) / 2) %}
|
||||
{{ (space ~ input ~ space)|raw }}
|
||||
{% endmacro %}
|
||||
|
||||
{% import _self as macro %}
|
||||
|
||||
{% set value = (value is null ? field.default : value) %}
|
||||
|
||||
{% block global_attributes %}
|
||||
{{ parent() }}
|
||||
data-grav-field-name="{{ (scope ~ field.name)|fieldName }}"
|
||||
{% endblock %}
|
||||
|
||||
{% block input %}
|
||||
{% set flex = grav['flex_objects'] %}
|
||||
{% set all = flex.blueprints %}
|
||||
{% if all|count %}
|
||||
{% set legacy = flex.getLegacyBlueprintMap() %}
|
||||
{% for label, directory in all %}
|
||||
{% set url = directory.blueprintFile %}
|
||||
{% set found = url in value %}
|
||||
{% if not found and legacy[url] is defined %}
|
||||
{% set found = legacy[url] in value %}
|
||||
{% endif %}
|
||||
|
||||
<div class="form-data block size-2-3" data-grav-field="toggle" data-grav-disabled="" data-grav-default="null" data-grav-field-name="{{ (scope ~ field.name)|fieldName }}[{{ loop.index0 }}]">
|
||||
<div class="switch-toggle switch-grav switch-2">
|
||||
{% set maxLen = 0 %}
|
||||
{% for text in ['PLUGIN_ADMIN.ENABLED', 'PLUGIN_ADMIN.DISABLED'] %}
|
||||
{% set translation = grav.twig.twig.filters['tu'] is defined ? text|tu : text|t %}
|
||||
{% set maxLen = max(translation|length, maxLen) %}
|
||||
{% endfor %}
|
||||
|
||||
{% set id = "toggle_" ~ field.name ~ '_' ~ label %}
|
||||
|
||||
<input type="radio"
|
||||
value="{{ url }}"
|
||||
id="{{ id ~ '_yes' }}"
|
||||
name="{{ (scope ~ field.name)|fieldName }}[{{ loop.index0 }}]"
|
||||
class="highlight"
|
||||
{% if found %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
/>
|
||||
{% set text = 'PLUGIN_ADMIN.ENABLED' %}
|
||||
{% set translation = (grav.twig.twig.filters['tu'] is defined ? text|tu : text|t)|trim %}
|
||||
<label for="{{ id ~ '_yes' }}">{{ (macro.spanToggle(translation, maxLen)|trim)|raw }}</label>
|
||||
<input type="radio"
|
||||
value=""
|
||||
name="{{ (scope ~ field.name)|fieldName }}[{{ loop.index0 }}]"
|
||||
id="{{ id ~ '_no' }}"
|
||||
{% if not found %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
/>
|
||||
{% set text = 'PLUGIN_ADMIN.DISABLED' %}
|
||||
{% set translation = (grav.twig.twig.filters['tu'] is defined ? text|tu : text|t)|trim %}
|
||||
<label for="{{ id ~ '_no' }}">{{ (macro.spanToggle(translation, maxLen)|trim)|raw }}</label>
|
||||
</div>
|
||||
<span title="{{ directory.description|tu }}">{{ directory.title|tu }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div>{{ 'PLUGIN_FLEX_OBJECTS.ERROR.NO_FLEX_DIRECTORIES'|tu }}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,37 @@
|
||||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% set originalValue = value %}
|
||||
{% set value = (value is null ? field.default : value) %}
|
||||
{% set isNew = key ? false : true %}
|
||||
{% set savedOption = grav.session.post_entries_save|default('create-new') %}
|
||||
|
||||
{% if isNew %}
|
||||
{% set options = {'create-new':'PLUGIN_FLEX_OBJECTS.ACTION.CREATE_NEW', 'edit':'PLUGIN_FLEX_OBJECTS.ACTION.EDIT_ITEM', 'list':'PLUGIN_FLEX_OBJECTS.ACTION.LIST_ITEMS'} %}
|
||||
{% else %}
|
||||
{% set options = {'edit':'PLUGIN_FLEX_OBJECTS.ACTION.EDIT_ITEM', 'list':'PLUGIN_FLEX_OBJECTS.ACTION.LIST_ITEMS'} %}
|
||||
{% endif %}
|
||||
|
||||
{% block input %}
|
||||
{% set savedOption = not isNew and savedOption == 'create-new' ? 'edit' : savedOption %}
|
||||
{% for key, text in options %}
|
||||
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
||||
|
||||
{% if savedOption == key %}
|
||||
{% set value = savedOption %}
|
||||
{% endif %}
|
||||
|
||||
<span class="radio">
|
||||
<input type="radio"
|
||||
value="{{ key|e }}"
|
||||
id="{{ id|e }}"
|
||||
name="{{ (field.name)|fieldName }}"
|
||||
{% if key == value %}checked="checked" {% endif %}
|
||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
||||
/>
|
||||
<label style="display: inline" class="inline" for="{{ id|e }}">{{ text|tu|e }}</label>
|
||||
</span>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user