1
0
mirror of https://github.com/flextype/flextype.git synced 2025-08-24 13:52:56 +02:00

feat(admin-plugin): add icons for settings tabs sections #293

feat(admin-plugin): use dots icon for actions dropdown #292
feat(admin-plugin): add plugins settings page #258
feat(admin-plugin): add plugins information page #258
This commit is contained in:
Awilum
2019-11-14 20:12:08 +03:00
parent 8df7c73fef
commit df2979ef6a
14 changed files with 267 additions and 147 deletions

View File

@@ -74,40 +74,25 @@ class PluginsController extends Controller
}
/**
* Edit plugin
* Plugin information
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function edit(Request $request, Response $response) : Response
public function information(Request $request, Response $response) : Response
{
// Get Plugin ID
$id = $request->getQueryParams()['id'];
// Init plugin configs
$plugin = [];
$plugin_settings = [];
$plugin_manifest = [];
$default_plugin_settings = [];
$site_plugin_settings = [];
$default_plugin_manifest = [];
$site_plugin_manifest = [];
$default_plugin_settings_file = PATH['plugins'] . '/' . $id . '/settings.yaml';
$default_plugin_manifest_file = PATH['plugins'] . '/' . $id . '/plugin.yaml';
$site_plugin_settings_file = PATH['config']['site'] . '/plugins/' . $id . '/settings.yaml';
$site_plugin_manifest_file = PATH['config']['site'] . '/plugins/' . $id . '/plugin.yaml';
if (Filesystem::has($default_plugin_settings_file)) {
$default_plugin_settings_file_content = Filesystem::read($default_plugin_settings_file);
$default_plugin_settings = $this->parser->decode($default_plugin_settings_file_content, 'yaml');
}
if (Filesystem::has($site_plugin_settings_file)) {
$site_plugin_settings_file_content = Filesystem::read($site_plugin_settings_file);
$site_plugin_settings = $this->parser->decode($site_plugin_settings_file_content, 'yaml');
}
if (Filesystem::has($default_plugin_manifest_file)) {
$default_plugin_manifest_file_content = Filesystem::read($default_plugin_manifest_file);
$default_plugin_manifest = $this->parser->decode($default_plugin_manifest_file_content, 'yaml');
@@ -122,17 +107,69 @@ class PluginsController extends Controller
array_replace_recursive($default_plugin_manifest, $site_plugin_manifest)
);
return $this->view->render(
$response,
'plugins/admin/views/templates/extends/plugins/information.html',
[
'menu_item' => 'plugins',
'id' => $id,
'plugin_manifest' => $plugin[$id]['manifest'],
'links' => [
'plugins' => [
'link' => $this->router->pathFor('admin.plugins.index'),
'title' => __('admin_plugins'),
'attributes' => ['class' => 'navbar-item'],
],
'plugins_information' => [
'link' => $this->router->pathFor('admin.plugins.information') . '?id=' . $request->getQueryParams()['id'],
'title' => __('admin_information'),
'attributes' => ['class' => 'navbar-item active'],
],
],
]
);
}
/**
* Plugin settings
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function settings(Request $request, Response $response) : Response
{
// Get Plugin ID
$id = $request->getQueryParams()['id'];
// Init plugin configs
$plugin = [];
$plugin_settings = [];
$default_plugin_settings = [];
$site_plugin_settings = [];
$default_plugin_settings_file = PATH['plugins'] . '/' . $id . '/settings.yaml';
$site_plugin_settings_file = PATH['config']['site'] . '/plugins/' . $id . '/settings.yaml';
if (Filesystem::has($default_plugin_settings_file)) {
$default_plugin_settings_file_content = Filesystem::read($default_plugin_settings_file);
$default_plugin_settings = $this->parser->decode($default_plugin_settings_file_content, 'yaml');
}
if (Filesystem::has($site_plugin_settings_file)) {
$site_plugin_settings_file_content = Filesystem::read($site_plugin_settings_file);
$site_plugin_settings = $this->parser->decode($site_plugin_settings_file_content, 'yaml');
}
$plugin[$id]['settings'] = array_merge(
array_replace_recursive($default_plugin_settings, $site_plugin_settings)
);
return $this->view->render(
$response,
'plugins/admin/views/templates/extends/plugins/edit.html',
'plugins/admin/views/templates/extends/plugins/settings.html',
[
'menu_item' => 'plugins',
'id' => $id,
'plugin_manifest' => $plugin[$id]['manifest'],
'plugin_settings' => $this->parser->encode($plugin[$id]['settings'], 'yaml'),
'links' => [
'plugins' => [
@@ -140,14 +177,14 @@ class PluginsController extends Controller
'title' => __('admin_plugins'),
'attributes' => ['class' => 'navbar-item'],
],
'fieldsets_editor' => [
'link' => $this->router->pathFor('admin.plugins.edit') . '?id=' . $request->getQueryParams()['id'],
'title' => __('admin_plugin'),
'plugins_settings' => [
'link' => $this->router->pathFor('admin.plugins.settings') . '?id=' . $request->getQueryParams()['id'],
'title' => __('admin_settings'),
'attributes' => ['class' => 'navbar-item active'],
],
],
'buttons' => [
'save_entry' => [
'save_plugin_settings' => [
'link' => 'javascript:;',
'title' => __('admin_save'),
'attributes' => ['class' => 'js-save-form-submit float-right btn'],
@@ -158,12 +195,12 @@ class PluginsController extends Controller
}
/**
* Edit plugin process
* Plugin settings process
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function editProcess(Request $request, Response $response) : Response
public function settingsProcess(Request $request, Response $response) : Response
{
$data = $request->getParsedBody();

View File

@@ -183,12 +183,12 @@ a {
background-color: $navbar-table-background-color-hover;
}
> tbody,
> tfoot,
> thead,
> tfoot {
> tbody {
> tr {
> td,
> th {
> th,
> td {
border-color: $border-color;
color: $base-font-color;
}

View File

@@ -492,3 +492,42 @@ textarea.form-control.code-editor {
border: none;
opacity: 0;
}
.dropdown-toggle::after {
padding: 0;
margin: 0;
border: none;
}
.dropdown-toggle {
border: none!important;
background: transparent!important;
}
.dropdown-item {
padding: .25rem 1.1rem;
font-size: 14px;
> i {
width: 24px;
font-size: 14px;
}
}
.nav-pills {
.nav-link {
> i {
width: 24px;
font-size: 14px;
}
}
}
.show > .dropdown-toggle {
border: none!important;
background: transparent!important;
color: inherit!important;
outline: none!important;
box-shadow: none!important;
}

View File

@@ -237,6 +237,7 @@ admin_registry: "Registry"
admin_key: "Key"
admin_value: "Value"
admin_activate: "Activate"
admin_deactivate: "Deactivate"
admin_active_theme: "Active Theme"
admin_get_more_themes: "Get More Themes"
admin_images: "Images"

View File

@@ -43,8 +43,9 @@ $app->group('/' . $admin_route, function () use ($app) : void {
// Plugins Controller
$app->get('/plugins', 'PluginsController:index')->setName('admin.plugins.index');
$app->get('/plugins/edit', 'PluginsController:edit')->setName('admin.plugins.edit');
$app->post('/plugins/edit', 'PluginsController:editProcess')->setName('admin.plugins.editProcess');
$app->get('/plugins/information', 'PluginsController:information')->setName('admin.plugins.information');
$app->get('/plugins/settings', 'PluginsController:settings')->setName('admin.plugins.settings');
$app->post('/plugins/settings', 'PluginsController:settingsProcess')->setName('admin.plugins.settingsProcess');
$app->post('/plugins/update-status', 'PluginsController:pluginStatusProcess')->setName('admin.plugins.update-status');
// FieldsetsController

View File

@@ -194,7 +194,8 @@
</div>
{% endif %}
{% if is_current_path('admin.templates.index') or
{% if is_current_path('admin.themes.index') or
is_current_path('admin.templates.index') or
is_current_path('admin.templates.edit') or
is_current_path('admin.templates.rename') or
is_current_path('admin.templates.add') %}
@@ -217,7 +218,8 @@
{% endif %}
{% if is_current_path('admin.plugins.index') or
is_current_path('admin.plugins.edit') %}
is_current_path('admin.plugins.information') or
is_current_path('admin.plugins.settings') %}
<div class="entry-editor-heading">
/ {{ id }}
</div>

View File

@@ -24,28 +24,29 @@
</td>
<td class="text-right">
<div class="btn-group">
<a class="btn btn-default" href="{{ path_for('admin.fieldsets.edit') }}?id={{ id }}">{{ tr('admin_edit') }}</a>
<button type="button" class="btn btn-default dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="{{ path_for('admin.fieldsets.rename') }}?id={{ id }}">{{ tr('admin_rename') }}</a>
<div class="dropdown-menu dropdown-menu-lg-right">
<a class="dropdown-item" href="{{ path_for('admin.fieldsets.edit') }}?id={{ id }}"><i class="fas fa-edit"></i> {{ tr('admin_edit') }}</a>
<a class="dropdown-item" href="{{ path_for('admin.fieldsets.rename') }}?id={{ id }}"><i class="fas fa-font"></i> {{ tr('admin_rename') }}</a>
<form id="duplicate-fieldset-id-{{ id }}" action="{{ path_for('admin.fieldsets.duplicateProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="fieldset-id" value="{{ id }}">
</form>
<a class="dropdown-item" href="javascript:;"
onclick="event.preventDefault();
document.getElementById('duplicate-fieldset-id-{{ id }}').submit();">{{ tr('admin_duplicate') }}</a>
document.getElementById('duplicate-fieldset-id-{{ id }}').submit();"><i class="fas fa-copy"></i> {{ tr('admin_duplicate') }}</a>
<div class="dropdown-divider"></div>
<form id="delete-fieldset-id-{{ id }}" action="{{ path_for('admin.fieldsets.deleteProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="fieldset-id" value="{{ id }}">
</form>
<a class="dropdown-item" href="javascript:;"
onclick="event.preventDefault();
document.getElementById('delete-fieldset-id-{{ id }}').submit();"><i class="fas fa-trash-alt"></i> {{ tr('admin_delete') }}</a>
</div>
</div>
<form id="duplicate-fieldset-id-{{ id }}" action="{{ path_for('admin.fieldsets.duplicateProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="fieldset-id" value="{{ id }}">
</form>
<form id="delete-fieldset-id-{{ id }}" action="{{ path_for('admin.fieldsets.deleteProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="fieldset-id" value="{{ id }}">
</form>
<a class="btn btn-default" href="javascript:;"
onclick="event.preventDefault();
document.getElementById('delete-fieldset-id-{{ id }}').submit();">{{ tr('admin_delete') }}</a>
</td>
</tr>
{% endfor %}

View File

@@ -1,74 +0,0 @@
{% extends "plugins/admin/views/partials/base.html" %}
{% block content %}
<div class="row mt-3">
<div class="col-md-6">
<h3 class="h3 margin-top-none">{{ tr('admin_information') }}</h3>
<hr>
<table class="table no-margin">
<tbody>
<tr>
<td style="width: 200px;">{{ tr('admin_name') }}:</td>
<td>{{ plugin_manifest.name }}</td>
</tr>
<tr>
<td>{{ tr('admin_version') }}:</td>
<td>{{ plugin_manifest.version }}</td>
</tr>
<tr>
<td>{{ tr('admin_description') }}:</td>
<td>{{ plugin_manifest.description }}</td>
</tr>
<tr>
<td>{{ tr('admin_icon') }}:</td>
<td>{{ plugin_manifest.icon }}</td>
</tr>
<tr>
<td>{{ tr('admin_author_name') }}:</td>
<td>{{ plugin_manifest.author.name }}</td>
</tr>
<tr>
<td>{{ tr('admin_author_email') }}:</td>
<td>{{ plugin_manifest.author.email }}</td>
</tr>
<tr>
<td>{{ tr('admin_author_url') }}:</td>
<td>{{ plugin_manifest.author.url }}</td>
</tr>
<tr>
<td>{{ tr('admin_homepage') }}:</td>
<td>{{ plugin_manifest.homepage }}</td>
</tr>
<tr>
<td>{{ tr('admin_bugs') }}:</td>
<td>{{ plugin_manifest.bugs }}</td>
</tr>
<tr>
<td>{{ tr('admin_license') }}:</td>
<td>{{ plugin_manifest.license }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
<h3 class="h3 margin-top-none">{{ tr('admin_settings') }}</h3>
<hr>
<form method="post" id="form">
{{ csrf() }}
<input type="hidden" id="action" name="action" value="save-form">
<input type="hidden" id="id" name="id" value="{{ id }}">
<div class="row">
<div class="col-12">
<div class="form-group">
<textarea name="data" rows="0" cols="0" class="form-control code-editor js-code">{{ plugin_settings }}</textarea>
</div>
</div>
</div>
</form>
</div>
</div>
<br>
<br>
{% endblock %}

View File

@@ -13,7 +13,33 @@
<i class="fas fa-plug"></i>
{% endif %}
</td>
<td style="padding-left:0px;"><a href="{{ path_for('admin.plugins.edit') }}?id={{ key }}">{{ plugin.name }}</a></td>
<td style="padding-left:0px;"><a href="{{ path_for('admin.plugins.information') }}?id={{ key }}">{{ plugin.name }}</a></td>
<td class="text-right">
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu dropdown-menu-lg-right">
<form id="update-status-{{ key }}" action="{{ path_for('admin.plugins.update-status') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="plugin-key" value="{{ key }}">
<input type="hidden" name="plugin-status" value="{% if plugin.enabled %}false{% else %}true{% endif %}">
</form>
<a class="dropdown-item" href="{{ path_for('admin.plugins.information') }}?id={{ key }}"><i class="fas fa-info-circle"></i> {{ tr('admin_information') }}</a>
<a class="dropdown-item" href="{{ path_for('admin.plugins.settings') }}?id={{ key }}"><i class="fas fa-cog"></i> {{ tr('admin_settings') }}</a>
{% if key == 'admin' or key == 'site' or key == '' %}
<a class="dropdown-item opacity-50" href="javascript:;"><i class="fas fa-toggle-on"></i> {{ tr('admin_deactivate') }}</a>
{% else %}
<a class="dropdown-item"
onclick="event.preventDefault(); document.getElementById('update-status-{{ key }}').submit();"
href="javascript:;">{% if plugin.enabled %}<i class="fas fa-toggle-on"></i> {{ tr('admin_deactivate') }}{% else %}<i class="fas fa-toggle-off"></i> {{ tr('admin_activate') }}{% endif %}</a>
{% endif %}
<!--
</div>
</div>
</td>
<!--
<td class="text-right" style="width: 50px;">
<div class="form-group no-margin">
<span class="switch switch-sm {% if key == 'admin' or key == 'site' or key == '' %}opacity-50{% endif %}">
@@ -32,6 +58,7 @@
</form>
</div>
</td>
-->
</tr>
{% endfor %}
</tbody>

View File

@@ -0,0 +1,48 @@
{% extends "plugins/admin/views/partials/base.html" %}
{% block content %}
<table class="table no-margin">
<tbody>
<tr>
<td>{{ tr('admin_name') }}:</td>
<td>{{ plugin_manifest.name }}</td>
</tr>
<tr>
<td>{{ tr('admin_version') }}:</td>
<td>{{ plugin_manifest.version }}</td>
</tr>
<tr>
<td>{{ tr('admin_description') }}:</td>
<td>{{ plugin_manifest.description }}</td>
</tr>
<tr>
<td>{{ tr('admin_icon') }}:</td>
<td>{{ plugin_manifest.icon }}</td>
</tr>
<tr>
<td>{{ tr('admin_author_name') }}:</td>
<td>{{ plugin_manifest.author.name }}</td>
</tr>
<tr>
<td>{{ tr('admin_author_email') }}:</td>
<td>{{ plugin_manifest.author.email }}</td>
</tr>
<tr>
<td>{{ tr('admin_author_url') }}:</td>
<td>{{ plugin_manifest.author.url }}</td>
</tr>
<tr>
<td>{{ tr('admin_homepage') }}:</td>
<td>{{ plugin_manifest.homepage }}</td>
</tr>
<tr>
<td>{{ tr('admin_bugs') }}:</td>
<td>{{ plugin_manifest.bugs }}</td>
</tr>
<tr>
<td>{{ tr('admin_license') }}:</td>
<td>{{ plugin_manifest.license }}</td>
</tr>
</tbody>
</table>
{% endblock %}

View File

@@ -0,0 +1,16 @@
{% extends "plugins/admin/views/partials/base.html" %}
{% block content %}
<form method="post" id="form">
{{ csrf() }}
<input type="hidden" id="action" name="action" value="save-form">
<input type="hidden" id="id" name="id" value="{{ id }}">
<div class="row">
<div class="col-12">
<div class="form-group">
<textarea name="data" rows="0" cols="0" class="form-control code-editor js-code">{{ plugin_settings }}</textarea>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@@ -14,29 +14,31 @@
</td>
<td class="text-right">
<div class="btn-group">
<a class="btn btn-default" href="{{ path_for('admin.snippets.edit') }}?id={{ id }}">{{ tr('admin_edit') }}</a>
<button type="button" class="btn btn-default dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="{{ path_for('admin.snippets.rename') }}?id={{ id }}">{{ tr('admin_rename') }}</a>
<div class="dropdown-menu dropdown-menu-lg-right">
<a class="dropdown-item" href="{{ path_for('admin.snippets.edit') }}?id={{ id }}"><i class="fas fa-edit"></i> {{ tr('admin_edit') }}</a>
<a class="dropdown-item" href="{{ path_for('admin.snippets.rename') }}?id={{ id }}"><i class="fas fa-font"></i> {{ tr('admin_rename') }}</a>
<form id="duplicate-snippet-id-{{ id }}" action="{{ path_for('admin.snippets.duplicateProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="snippet-id" value="{{ id }}">
</form>
<a class="dropdown-item" href="javascript:;"
onclick="event.preventDefault();
document.getElementById('duplicate-snippet-id-{{ id }}').submit();">{{ tr('admin_duplicate') }}</a>
<a class="dropdown-item js-snippets-info" href="javascript:;" data-toggle="modal" data-target="#snippetsInfoModal" data-name="{{ id }}">{{ tr('admin_embeded_code') }}</a>
document.getElementById('duplicate-snippet-id-{{ id }}').submit();"><i class="fas fa-copy"></i> {{ tr('admin_duplicate') }}</a>
<a class="dropdown-item js-snippets-info" href="javascript:;" data-toggle="modal" data-target="#snippetsInfoModal" data-name="{{ id }}"><i class="fas fa-code"></i> {{ tr('admin_embeded_code') }}</a>
<div class="dropdown-divider"></div>
<form id="delete-snippet-id-{{ id }}" action="{{ path_for('admin.snippets.deleteProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="snippet-id" value="{{ id }}">
</form>
<a class="dropdown-item" href="javascript:;"
onclick="event.preventDefault();
document.getElementById('delete-snippet-id-{{ id }}').submit();"><i class="fas fa-trash-alt"></i> {{ tr('admin_delete') }}</a>
</div>
</div>
<form id="duplicate-snippet-id-{{ id }}" action="{{ path_for('admin.snippets.duplicateProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="snippet-id" value="{{ id }}">
</form>
<form id="delete-snippet-id-{{ id }}" action="{{ path_for('admin.snippets.deleteProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="snippet-id" value="{{ id }}">
</form>
<a class="btn btn-default" href="javascript:;"
onclick="event.preventDefault();
document.getElementById('delete-snippet-id-{{ id }}').submit();">{{ tr('admin_delete') }}</a>
</td>
</tr>
{% endfor %}

View File

@@ -2,6 +2,22 @@
{% block content %}
{% if (themes_list|length > 0) %}
<table class="table no-margin">
<tbody>
{% for key, theme in themes_list %}
<tr>
<td style="width: 50px; padding-right: 10px; text-align:center;">
<i class="fas fa-palette" aria-hidden="true"></i>
</td>
<td style="padding-left:0px;"><a href="{{ path_for('admin.templates.index') }}?theme={{ key }}">{{ theme.name }}</a></td>
<td class="text-right" style="width: 50px;">
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!--
<div class="card-deck">
<div class="col-md-12">
<div class="row">
@@ -42,7 +58,11 @@
</div>
</div>
</div>
-->
{% else %}
<div class="empty-list-message">
<i class="fas fa-list"></i>
<h3>{{ tr('admin_you_have_no_themes') }}</h3>
</div>
{% endif %}
{% endblock %}

View File

@@ -284,10 +284,10 @@
</div>
</div>
<div class="tab-pane fade show" id="pills-slim" role="tabpanel" aria-labelledby="pills-slim-tab">
<div class="tab-pane fade show" id="pills-system" role="tabpanel" aria-labelledby="pills-system-tab">
<div class="row">
<div class="col-md-12">
<h3 class="h3 margin-top-none">{{ tr('admin_slim') }}</h3>
<h3 class="h3 margin-top-none">{{ tr('admin_system') }}</h3>
<hr>
</div>
<div class="col-md-6">
@@ -509,7 +509,7 @@
<a class="nav-link" id="pills-error-tab" data-toggle="pill" href="#pills-error" role="tab" aria-controls="pills-error" aria-selected="true"><i class="fas fa-exclamation-circle"></i> {{ tr('admin_error_404_page') }}</a>
<a class="nav-link" id="pills-twig-tab" data-toggle="pill" href="#pills-twig" role="tab" aria-controls="pills-twig" aria-selected="true"><i class="fas fa-pencil-ruler"></i> {{ tr('admin_twig_templating') }}</a>
<a class="nav-link" id="pills-debugging-tab" data-toggle="pill" href="#pills-debugging" role="tab" aria-controls="pills-debugging" aria-selected="true"><i class="fas fa-tools"></i> {{ tr('admin_debugging') }}</a>
<a class="nav-link" id="pills-slim-tab" data-toggle="pill" href="#pills-slim" role="tab" aria-controls="pills-slim" aria-selected="true"><i class="fas fa-cogs"></i> {{ tr('admin_system') }}</a>
<a class="nav-link" id="pills-system-tab" data-toggle="pill" href="#pills-system" role="tab" aria-controls="pills-sytem" aria-selected="true"><i class="fas fa-cogs"></i> {{ tr('admin_system') }}</a>
<a class="nav-link" id="pills-cache-tab" data-toggle="pill" href="#pills-cache" role="tab" aria-controls="pills-cache" aria-selected="true"><i class="fas fa-clone"></i> {{ tr('admin_cache') }}</a>
<a class="nav-link" id="pills-slug-tab" data-toggle="pill" href="#pills-slug" role="tab" aria-controls="pills-slug" aria-selected="true"><i class="fas fa-link"></i> {{ tr('admin_slug') }}</a>
<a class="nav-link" id="pills-admin-tab" data-toggle="pill" href="#pills-admin" role="tab" aria-controls="pills-admin" aria-selected="true"><i class="fab fa-fort-awesome"></i> {{ tr('admin_admin_panel') }}</a>