multiple ui improvements
This commit is contained in:
@@ -59,7 +59,7 @@ class ProgressBar
|
||||
private static function pbData(string $field, array $attributes, int $size_factor = 1024, int $report_max = 90, $infotext = null): array
|
||||
{
|
||||
$percent = 0;
|
||||
$style = 'bg-info';
|
||||
$style = 'bg-primary';
|
||||
$text = PhpHelper::sizeReadable($attributes[$field . '_used'] * $size_factor, null, 'bi') . ' / ' . UI::getLng('panel.unlimited');
|
||||
if ((int)$attributes[$field] >= 0) {
|
||||
if (($attributes[$field] / 100) * $report_max < $attributes[$field . '_used']) {
|
||||
|
||||
@@ -28,7 +28,8 @@ class Listing
|
||||
|
||||
return [
|
||||
'title' => $tabellisting['title'],
|
||||
'icon' => $tabellisting['icon'],
|
||||
'description' => $tabellisting['description'] ?? null,
|
||||
'icon' => $tabellisting['icon'] ?? null,
|
||||
'table' => [
|
||||
'th' => self::generateTableHeadings($tabellisting),
|
||||
'tr' => self::generateTableRows($collection['data']['list'], $tabellisting),
|
||||
|
||||
@@ -84,7 +84,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'admins',
|
||||
'page' => 'admins',
|
||||
|
||||
@@ -25,6 +25,7 @@ use Froxlor\UI\Listing;
|
||||
return [
|
||||
'customer_list' => [
|
||||
'title' => $lng['admin']['customers'],
|
||||
'description' => 'Manage your customers',
|
||||
'icon' => 'fa-solid fa-user',
|
||||
'columns' => [
|
||||
'c.name' => [
|
||||
@@ -91,7 +92,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'customers',
|
||||
'page' => 'customers',
|
||||
|
||||
@@ -101,7 +101,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'domains',
|
||||
'page' => 'domains',
|
||||
|
||||
@@ -44,7 +44,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'templates',
|
||||
'page' => $page,
|
||||
|
||||
@@ -66,7 +66,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'phpsettings',
|
||||
'page' => 'fpmdaemons',
|
||||
|
||||
@@ -98,7 +98,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'ipsandports',
|
||||
'page' => 'ipsandports',
|
||||
|
||||
@@ -50,7 +50,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'templates',
|
||||
'page' => $page,
|
||||
|
||||
@@ -71,7 +71,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'phpsettings',
|
||||
'page' => 'overview',
|
||||
|
||||
@@ -62,7 +62,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'plans',
|
||||
'page' => 'overview',
|
||||
|
||||
@@ -69,7 +69,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'domains',
|
||||
'page' => 'sslcertificates',
|
||||
|
||||
@@ -105,7 +105,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'domains',
|
||||
'page' => 'domains',
|
||||
|
||||
@@ -73,7 +73,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'email',
|
||||
'page' => 'emails',
|
||||
|
||||
@@ -64,7 +64,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'ftp',
|
||||
'page' => 'ftps',
|
||||
|
||||
@@ -76,7 +76,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'extras',
|
||||
'page' => 'htaccess',
|
||||
|
||||
@@ -52,7 +52,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'extras',
|
||||
'page' => 'htpasswds',
|
||||
|
||||
@@ -65,7 +65,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'mysql',
|
||||
'page' => 'mysqls',
|
||||
|
||||
@@ -71,7 +71,7 @@ return [
|
||||
'delete' => [
|
||||
'icon' => 'fa fa-trash',
|
||||
'title' => $lng['panel']['delete'],
|
||||
'class' => 'text-danger',
|
||||
'class' => 'btn-danger',
|
||||
'href' => [
|
||||
'section' => 'index',
|
||||
'page' => 'apikeys',
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -25,16 +25,9 @@
|
||||
{{ theme_js|raw }}
|
||||
{% endif %}
|
||||
{% block custom_js %}{% endblock %}
|
||||
<title>Froxlor
|
||||
{% if page_title %}
|
||||
|
|
||||
{{ page_title }}
|
||||
{% endif %}
|
||||
</title>
|
||||
<title>Froxlor{% if page_title %} | {{ page_title }}{% endif %}</title>
|
||||
</head>
|
||||
<body {% if body_class is defined %}class="{{ body_class }}"{% endif %}>
|
||||
{{ global_errors|raw }}
|
||||
|
||||
<body class="min-vh-100 d-flex flex-column">
|
||||
{% block navigation %}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<footer class="py-5 text-center">
|
||||
<footer class="text-center mb-3">
|
||||
<span>
|
||||
<img src="{{ basehref|default("") }}templates/Froxlor/assets/img/logo_grey.png" alt="Froxlor"/>
|
||||
{% if install_mode is not defined %}
|
||||
|
||||
@@ -3,15 +3,6 @@
|
||||
{% import "Froxlor/form/formfields.html.twig" as formfields %}
|
||||
|
||||
<form action="{{ formaction|default("") }}" method="post" enctype="application/x-www-form-urlencoded" class="form">
|
||||
{% if title is not empty %}
|
||||
<h3 class="page-header">
|
||||
{% if form_data.image is not empty %}
|
||||
<i class="{{ form_data.image }}"></i>
|
||||
{% endif %}
|
||||
{{ title }}
|
||||
</h3>
|
||||
{% endif %}
|
||||
|
||||
{% for section in form_data.sections %}
|
||||
<div class="card mb-3">
|
||||
{% if section.title is not empty %}
|
||||
@@ -22,7 +13,7 @@
|
||||
{{ section.title }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-body">
|
||||
<div class="formfields">
|
||||
{% for id,field in section.fields %}
|
||||
{{ formfields.fieldrow(id, field) }}
|
||||
{% endfor %}
|
||||
@@ -31,8 +22,7 @@
|
||||
{% endfor %}
|
||||
|
||||
<!-- submit buttons -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<div>
|
||||
{% if hiddenid is not empty %}
|
||||
<input type="hidden" name="id" value="{{ hiddenid }}"/>
|
||||
{% endif %}
|
||||
@@ -41,10 +31,9 @@
|
||||
<input type="hidden" name="action" value="{{ action }}"/>
|
||||
<input type="hidden" name="send" value="send"/>
|
||||
|
||||
<div class="col-12 text-center">
|
||||
<button type="reset" class="btn btn-warning">{{ lng('panel.cancel') }}</button>
|
||||
<button type="submit" class="btn btn-success">{{ lng('panel.save') }}</button>
|
||||
</div>
|
||||
<div class="col-12 text-end">
|
||||
<button type="reset" class="btn btn-outline-secondary">{{ lng('panel.cancel') }}</button>
|
||||
<button type="submit" class="btn btn-primary">{{ lng('panel.save') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{% macro fieldrow(id, field, norow = false, nohide = false, em = false) %}
|
||||
{% if field.visible is not defined or (field.visible is defined and field.visible) or nohide == true %}
|
||||
{% if norow == false and field.type != 'hidden' %}
|
||||
<div class="row mb-3 pb-3 border-bottom">
|
||||
<div class="row g-0 formfield d-flex align-items-center">
|
||||
{% if field.label is iterable %}
|
||||
<label for="{{ id }}" class="col-sm-4 col-form-label">
|
||||
<label for="{{ id }}" class="col-sm-4 col-form-label pe-3">
|
||||
{% if em %}
|
||||
<mark>
|
||||
{% endif %}
|
||||
@@ -15,7 +15,7 @@
|
||||
{% endif %}
|
||||
</label>
|
||||
{% else %}
|
||||
<label for="{{ id }}" class="col-sm-4 col-form-label">
|
||||
<label for="{{ id }}" class="col-sm-4 col-form-label pe-3">
|
||||
{% if em %}
|
||||
<mark>
|
||||
{% endif %}
|
||||
@@ -27,7 +27,7 @@
|
||||
{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
<div class="col-sm-8{% if field.type == 'infotext' %} d-flex align-items-center{% endif %}">
|
||||
<div class="col-sm-8">
|
||||
{% endif %}
|
||||
{% if field.type == 'text' or field.type == 'password' or field.type == 'number' or field.type == 'file' or field.type == 'email' or field.type == 'url' or field.type == 'hidden' %}
|
||||
{{ _self.input(id, field) }}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "Froxlor/base.html.twig" %}
|
||||
|
||||
{% set body_class = "min-vh-100 d-flex align-items-center" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container max-w-lg flex align-content-center mt-5">
|
||||
<img src="{{ basehref|default('') }}templates/Froxlor/assets/img/logo.png" class="filter-me" alt="Froxlor Server Management Panel"/>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "Froxlor/base.html.twig" %}
|
||||
|
||||
{% set body_class = "min-vh-100 d-flex align-items-center" %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "Froxlor/base.html.twig" %}
|
||||
|
||||
{% set body_class = "min-vh-100 d-flex align-items-center" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "Froxlor/userarea.html.twig" %}
|
||||
|
||||
{% set body_class = "min-vh-100 d-flex align-items-center" %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'Froxlor/misc/alertbox.html.twig' %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "Froxlor/base.html.twig" %}
|
||||
|
||||
{% set body_class = "min-vh-100 d-flex align-items-center" %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'Froxlor/misc/alertbox.html.twig' %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "Froxlor/base.html.twig" %}
|
||||
|
||||
{% set body_class = "min-vh-100 d-flex align-items-center" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container max-w-lg flex align-content-center mt-5">
|
||||
<img src="templates/Sparkle/assets/img/logo.png" alt="Froxlor Server Management Panel" />
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "Froxlor/base.html.twig" %}
|
||||
|
||||
{% set body_class = "min-vh-100 d-flex align-items-center" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container my-auto">
|
||||
<div class="alert alert-warning fade show" role="alert">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<a class="btn {% if isnewerversion == 0 %}btn-light text-success{% else %}btn-warning{% endif %} btn-sm d-block me-2" {% if isnewerversion == 0 %} href="#" {% else %} href="admin_autoupdate.php?page=overview&s={{ s }}" {% endif %} title="{% if isnewerversion == 0 %}{{ additional_info }}{% else %}{{ message }}{% endif %}">
|
||||
<a class="nav-link {% if isnewerversion == 0 %}text-success{% else %}text-warning{% endif %}" {% if isnewerversion == 0 %} href="#" {% else %} href="admin_autoupdate.php?page=overview&s={{ s }}" {% endif %} title="{% if isnewerversion == 0 %}{{ additional_info }}{% else %}{{ message }}{% endif %}">
|
||||
{% if isnewerversion == 0 %}
|
||||
<i class="fa-solid fa-circle-check me-1"></i>
|
||||
{% else %}
|
||||
<i class="fa-solid fa-circle-exclamation me-1"></i>
|
||||
{% endif %}
|
||||
{{ version }}
|
||||
<span class="d-md-none d-xl-inline">{{ version }}</span>
|
||||
</a>
|
||||
|
||||
@@ -1,52 +1,53 @@
|
||||
{% extends "Froxlor/userarea.html.twig" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-10 order-2 order-md-1">
|
||||
|
||||
<form action="{{ action|default(filename) }}" method="post" enctype="application/x-www-form-urlencoded" class="form">
|
||||
<h3 class="page-header">
|
||||
{% block heading %}
|
||||
<h5>
|
||||
<i class="fa-solid fa-gears"></i>
|
||||
{{ lng('admin.serversettings') }}
|
||||
{% if fields._group is defined %} » {{ fields._group.title }}
|
||||
{% endif %}
|
||||
</h3>
|
||||
</h5>
|
||||
<span class="text-muted">Manage your Froxlor system</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block actions %}
|
||||
<a class="btn btn-outline-primary" href="{{ linker({'section':'settings','page':'overview','part':'all'}) }}">
|
||||
<i class="fa-solid fa-grip me-1"></i>
|
||||
{{ lng('admin.configfiles.overview') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ linker({'section':'settings','page':'importexport'}) }}">
|
||||
<i class="fa-solid fa-file-import me-1"></i>
|
||||
{{ lng('admin.configfiles.importexport') }}
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="{{ action|default(filename) }}" method="post" enctype="application/x-www-form-urlencoded" class="form">
|
||||
{% block settings %}
|
||||
<div class="row row-cols-2 row-cols-md-4 row-cols-xl-6 g-3">
|
||||
<div class="row row-cols-2 row-cols-md-2 row-cols-xl-4 g-3">
|
||||
{% for field in fields %}
|
||||
<div class="col">
|
||||
<div class="card h-100 border {% if field.activated %}border-primary{% else %}border-secondary bg-light{% endif %}">
|
||||
<div class="card-body text-center">
|
||||
<a href="{{ linker({'section':'settings','page':'overview','part':field.part}) }}" class="btn btn-link stretched-link">
|
||||
<i class="{{ field.icon }} fa-4x"></i>
|
||||
<div class="card h-100 position-relative {% if not field.activated %}{% endif %}">
|
||||
<div class="card-body d-flex overflow-hidden align-items-center">
|
||||
<a href="{{ linker({'section':'settings','page':'overview','part':field.part}) }}" class="stretched-link">
|
||||
<i class="{{ field.icon }} fa-2x me-4" style="width: 1em;"></i>
|
||||
</a>
|
||||
<p class="card-text mt-2">{{ field.title }}
|
||||
{% if field.info is defined and field.info is not empty %}<br><small>{{ field.info|raw }}</small>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if field.activated == false %}
|
||||
<small class="text-danger">{{ lng('panel.not_activated') }}</small>
|
||||
<div>
|
||||
{{ field.title }}
|
||||
{% if field.info is defined and field.info is not empty %}
|
||||
{{ field.info|raw }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if not field.activated %}
|
||||
<div class="position-absolute top-0 end-0 p-1">
|
||||
<span class="badge text-muted" style="background: #eee">{{ lng('panel.not_activated') }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="col-12 col-md-2 order-1 order-md-2">
|
||||
|
||||
<a class="btn btn-primary d-block mb-2" href="{{ linker({'section':'settings','page':'overview','part':'all'}) }}">
|
||||
<i class="fa-solid fa-grip me-1"></i>
|
||||
{{ lng('admin.configfiles.overview') }}</a>
|
||||
<a class="btn btn-secondary d-block mb-2" href="{{ linker({'section':'settings','page':'importexport'}) }}">
|
||||
<i class="fa-solid fa-file-import me-1"></i>
|
||||
{{ lng('admin.configfiles.importexport') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -31,20 +31,4 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="d-flex flex-shrink-0 p-3 user-info">
|
||||
<div class="dropdown d-block flex-shrink-0">
|
||||
<a href="#" class="d-flex align-items-center text-white text-decoration-none dropdown-toggle" id="dropdownUser1" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa-solid fa-user me-3"></i>
|
||||
<strong>{{ userinfo.loginname }}</strong>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-dark text-small shadow" aria-labelledby="dropdownUser1">
|
||||
<li><a class="dropdown-item" href="#">New project...</a></li>
|
||||
<li><a class="dropdown-item" href="#">Settings</a></li>
|
||||
<li><a class="dropdown-item" href="#">Profile</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ linker({'section': 'index', 'action': 'logout'}) }}">{{ lng('login.logout') }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -11,7 +11,8 @@ $(document).ready(function () {
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
console.log(request, status, error)
|
||||
$("#updatecheck").html('<div class="alert alert-warning" role="alert">Error checking version</div>');
|
||||
let message = 'Can\'t check version';
|
||||
$("#updatecheck").html('<a class="nav-link disabled text-warning" data-bs-toggle="tooltip" data-bs-placement="left" title="' + message + '"><i class="fa fa-exclamation-triangle"></i> <span class="d-md-none d-xl-inline">' + message + '</span></a>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
@import "~@fortawesome/fontawesome-free/css/all";
|
||||
|
||||
.navbar {
|
||||
background: darken($navbar-bg, 3);
|
||||
}
|
||||
|
||||
.navbar, .card {
|
||||
@extend .shadow-sm;
|
||||
.form-control-plaintext {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
@@ -22,10 +18,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.progress-thin {
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
.alert-icon {
|
||||
padding: .5rem;
|
||||
background: rgba(0, 0, 0, .15);
|
||||
@@ -46,18 +38,23 @@
|
||||
max-width: 991.98px;
|
||||
}
|
||||
|
||||
.max-h-before-header {
|
||||
max-height: calc(100vh - ($spacer * 3.5));
|
||||
}
|
||||
|
||||
.rounded-tl-bl {
|
||||
border-radius: $border-radius 0 $border-radius 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
@extend .text-muted;
|
||||
.progress-thin {
|
||||
height: .5rem;
|
||||
}
|
||||
|
||||
.logcontent {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.formfield {
|
||||
padding: 1rem $spacer;
|
||||
border-bottom: $border-color solid 1px;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
.card {
|
||||
@extend .shadow-sm;
|
||||
margin-bottom: $spacer * 1.5;
|
||||
|
||||
.card-header {
|
||||
border-bottom: #e5e5e5 solid 1px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
p {
|
||||
@extend .card-text;
|
||||
}
|
||||
}
|
||||
|
||||
&.deactivated {
|
||||
@extend .text-muted;
|
||||
background: lighten($light-bg, 3%);
|
||||
|
||||
i {
|
||||
@extend .text-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
templates/Froxlor/src/scss/components/_dropdown.scss
Normal file
12
templates/Froxlor/src/scss/components/_dropdown.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
.dropdown {
|
||||
.dropdown-menu {
|
||||
.dropdown-item {
|
||||
i {
|
||||
width: 1rem;
|
||||
margin-right: 1rem;
|
||||
text-align: center;
|
||||
color: $text-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
templates/Froxlor/src/scss/components/_footer.scss
Normal file
8
templates/Froxlor/src/scss/components/_footer.scss
Normal file
@@ -0,0 +1,8 @@
|
||||
footer {
|
||||
@extend .small;
|
||||
|
||||
a {
|
||||
@extend .text-muted;
|
||||
@extend .text-decoration-none;
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,47 @@
|
||||
background: darken($navbar-bg, 3);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
.navbar {
|
||||
background: $white;
|
||||
|
||||
.navbar-brand {
|
||||
background: $dark;
|
||||
width: $sidebar-width;
|
||||
margin-right: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
.form-control-plaintext {
|
||||
color: $white;
|
||||
}
|
||||
.navbar {
|
||||
background: $dark;
|
||||
|
||||
.navbar-nav {
|
||||
.nav-link {
|
||||
color: $white;
|
||||
|
||||
&:hover {
|
||||
color: rgba(255,255,255,.45);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-light .navbar-toggler-icon {
|
||||
.navbar-light {
|
||||
.navbar-toggler {
|
||||
border-color: transparent;
|
||||
}
|
||||
.navbar-toggler-icon {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
.sidebar {
|
||||
.sidebar, .sub-sidebar {
|
||||
width: $sidebar-width;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
@extend .shadow;
|
||||
width: $sidebar-width;
|
||||
|
||||
&.collapsing {
|
||||
transition: none;
|
||||
@@ -10,29 +14,36 @@
|
||||
background: darken($dark, 2);
|
||||
}
|
||||
|
||||
>.nav {
|
||||
>.nav-item {
|
||||
>.nav-link {
|
||||
> .nav {
|
||||
> .nav-item {
|
||||
> .nav-link {
|
||||
i {
|
||||
margin-right: 1rem;
|
||||
width: 1rem;
|
||||
text-align: center;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
&:not(.collapsed) {
|
||||
background: darken($dark, 4);
|
||||
border-left: $primary solid 3px;
|
||||
padding-left: calc(1rem - 3px);
|
||||
}
|
||||
}
|
||||
>.collapse, >.collapsing {
|
||||
|
||||
> .collapse, > .collapsing {
|
||||
background: darken($dark, 2);
|
||||
|
||||
a {
|
||||
opacity: .78;
|
||||
margin-left: 1.25rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sub-sidebar {
|
||||
@extend .shadow-sm;
|
||||
background: $white;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
// Theme
|
||||
@import "global";
|
||||
@import "components/card";
|
||||
@import "components/dropdown";
|
||||
@import "components/footer";
|
||||
@import "components/form";
|
||||
@import "components/navbar";
|
||||
@import "components/sidebar";
|
||||
@import "components/card";
|
||||
@import "components/form";
|
||||
|
||||
@@ -9,7 +9,6 @@ $froxlor-blue-light: #62c8f4;
|
||||
$froxlor-blue-dark: #1871a2;
|
||||
|
||||
$primary: $froxlor-blue-dark;
|
||||
$secondary: $dark-bg;
|
||||
$info: $froxlor-blue-light;
|
||||
$warning: #FBBF24;
|
||||
$danger: #E11D48;
|
||||
@@ -21,6 +20,10 @@ $alert-border-width: 0;
|
||||
$list-group-item-color-scale: 0;
|
||||
$list-group-item-bg-scale: 0;
|
||||
|
||||
$input-bg: lighten($light-bg, 5%);
|
||||
|
||||
$font-size-root: 16px;
|
||||
|
||||
// Space
|
||||
$spacer: 1.25rem;
|
||||
|
||||
@@ -29,7 +32,7 @@ $body-bg: $light-bg;
|
||||
$body-color: $light-font-color;
|
||||
|
||||
// Borders
|
||||
$border-radius: 0.5rem;
|
||||
// $border-radius: 0.5rem;
|
||||
|
||||
// Links
|
||||
$links: $froxlor-blue-dark;
|
||||
@@ -38,7 +41,7 @@ $links: $froxlor-blue-dark;
|
||||
$navbar-bg: #ffffff;
|
||||
|
||||
// Sidebar
|
||||
$sidebar-width: 280px;
|
||||
$sidebar-width: 256px;
|
||||
|
||||
// Card
|
||||
$card-cap-bg: none;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="progress progress-thin">
|
||||
<div class="progress-bar {{ data.style }}" style="width: {{ data.percent }}%;"></div>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<div class="text-end small">
|
||||
{% if data.infotext is not empty %}
|
||||
<i class="fa-solid fa-circle-info" data-toggle="tooltip" data-placement="right" title="{{ data.infotext|raw }}"></i>
|
||||
{% endif %}
|
||||
@@ -42,6 +42,19 @@
|
||||
{% endapply %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro button(data) %}
|
||||
{% apply spaceless %}
|
||||
<a class="{% if data.class is defined %}btn btn-sm {{ data.class }}{% else %}btn btn-sm btn-outline-secondary{% endif %}" href="{{ data.href }}" {% if data.target is defined %} target="{{ data.target }}" {% endif %}{% if data.title is defined %} title="{{ data.title }}" {% endif %}>
|
||||
{% if data.icon is defined %}
|
||||
<i class="{{ data.icon }}"></i>
|
||||
{% endif %}
|
||||
{% if data.text is defined %}
|
||||
{{ data.text }}
|
||||
{% endif %}
|
||||
</a>
|
||||
{% endapply %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro domainWithSan(data) %}
|
||||
{{ data.domain }}
|
||||
{% if data.san is not empty %}
|
||||
@@ -55,7 +68,7 @@
|
||||
{% macro actions(data) %}
|
||||
{% for action in data %}
|
||||
{% if action.visible is not defined or action.visible is defined and action.visible %}
|
||||
{{ _self.link(action) }}
|
||||
{{ _self.button(action) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -1,52 +1,51 @@
|
||||
{% macro paging(pagination) %}
|
||||
{% if pagination.last_page > 1 %}
|
||||
<div class="card-footer border-top">
|
||||
|
||||
<nav aria-label="Pagination">
|
||||
<ul class="pagination justify-content-center">
|
||||
<ul class="pagination justify-content-center mb-0">
|
||||
{% if pagination.current_page == 1 %}
|
||||
<li class="page-item disabled">
|
||||
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">
|
||||
<i class="fa-solid fa-backward-fast"></i>
|
||||
<i class="fa-solid fa-angles-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item disabled">
|
||||
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">
|
||||
<i class="fa-solid fa-backward"></i>
|
||||
<i class="fa-solid fa-chevron-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% elseif pagination.current_page > 1 %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?s={{ s }}&page={{ page }}&action={{ action }}&pageno=1" tabindex="-1">
|
||||
<i class="fa-solid fa-backward-fast"></i>
|
||||
<i class="fa-solid fa-angles-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?s={{ s }}&page={{ page }}&action={{ action }}&pageno={{ pagination.current_page - 1 }}" tabindex="-1">
|
||||
<i class="fa-solid fa-backward"></i>
|
||||
<i class="fa-solid fa-chevron-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if pagination.current_page < pagination.last_page %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?s={{ s }}&page={{ page }}&action={{ action }}&pageno={{ pagination.current_page + 1 }}" tabindex="-1">
|
||||
<i class="fa-solid fa-forward"></i>
|
||||
<i class="fa-solid fa-chevron-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?s={{ s }}&page={{ page }}&action={{ action }}&pageno={{ pagination.last_page }}" tabindex="-1">
|
||||
<i class="fa-solid fa-forward-fast"></i>
|
||||
<i class="fa-solid fa-angles-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled">
|
||||
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">
|
||||
<i class="fa-solid fa-forward"></i>
|
||||
<i class="fa-solid fa-chevron-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="page-item disabled">
|
||||
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">
|
||||
<i class="fa-solid fa-forward-fast"></i>
|
||||
<i class="fa-solid fa-angles-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
@@ -4,15 +4,6 @@
|
||||
{% import "Froxlor/table/pagination.html.twig" as pagination %}
|
||||
|
||||
<form action="{{ action|default("") }}" method="post" enctype="application/x-www-form-urlencoded" class="form">
|
||||
{% if listing.title is not empty %}
|
||||
<h3 class="page-header">
|
||||
{% if listing.icon is not empty %}
|
||||
<i class="{{ listing.icon }} me-1"></i>
|
||||
{% endif %}
|
||||
{{ listing.title }}
|
||||
</h3>
|
||||
{% endif %}
|
||||
|
||||
{% if listing.table.tr|length == 0 %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h4 class="alert-heading">{{ lng('admin.note') }}</h4>
|
||||
@@ -20,7 +11,7 @@
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card table-responsive">
|
||||
<table class="table table-borderless table-striped table-sm mb-0 px-3">
|
||||
<table class="table table-borderless table-striped align-middle mb-0 px-3">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for key,th in listing.table.th %}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
aria-valuemax="{% if available < 0 %}100{% else %}{{ available }}{% endif %}"></div>
|
||||
</div>
|
||||
{% if assigned is not empty %}
|
||||
<div class="progress progress-thin my-auto">
|
||||
<div class="progress-bar bg-info" role="progressbar"
|
||||
<div class="progress progress-thin mt-2 my-auto">
|
||||
<div class="progress-bar bg-primary" role="progressbar"
|
||||
style="width:{% if available > 0 %}{{ (assigned / available) * 100|round }}{% else %}1{% endif %}%;"
|
||||
aria-valuenow="{{ assigned }}" aria-valuemin="0"
|
||||
aria-valuemax="{{ available }}"></div>
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
{% extends "Froxlor/userarea.html.twig" %}
|
||||
|
||||
{% block heading %}
|
||||
|
||||
{% if formdata.title is not empty %}
|
||||
<div>
|
||||
<h5 class="mb-1">
|
||||
{% if form_data.image is not empty %}
|
||||
<i class="{{ form_data.image }} me-1"></i>
|
||||
{% endif %}
|
||||
{{ formdata.title }}
|
||||
</h5>
|
||||
{% if formdata.description is not empty %}
|
||||
<span class="text-muted">{{ formdata.description }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% import "Froxlor/form/form.html.twig" as form %}
|
||||
|
||||
@@ -1,26 +1,48 @@
|
||||
{% extends "Froxlor/userarea.html.twig" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-12 {% if actions_links is iterable or (entity_info is defined and entity_info is not empty) %}col-md-10 order-2 order-md-1{% endif %}">
|
||||
{% import "Froxlor/table/table.html.twig" as table %}
|
||||
{{ table.table(listing) }}
|
||||
</div>
|
||||
{% block heading %}
|
||||
|
||||
{% if listing.title is not empty %}
|
||||
<h5 class="mb-1">
|
||||
{% if listing.icon is not empty %}
|
||||
<i class="{{ listing.icon }} me-1"></i>
|
||||
{% endif %}
|
||||
{{ listing.title }}
|
||||
</h5>
|
||||
{% if listing.description is not empty %}
|
||||
<span class="text-muted mt-2">{{ listing.description }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block actions %}
|
||||
|
||||
{% if actions_links is iterable or (entity_info is defined and entity_info is not empty) %}
|
||||
<div class="col-12 col-md-2 order-1 order-md-2">
|
||||
<div>
|
||||
{% if actions_links is iterable %}
|
||||
{% for link in actions_links %}
|
||||
<a class="btn {{ link.class|default('btn-success') }} d-block mb-2" href="{{ link.href|raw }}">
|
||||
<i class="{{ link.icon|default('fa-solid fa-plus-circle') }} me-1"></i>
|
||||
{{ link.label }}</a>
|
||||
<a class="btn {{ link.class|default('btn-outline-primary') }}" href="{{ link.href|raw }}">
|
||||
<i class="{{ link.icon|default('fa-solid fa-plus-circle') }}"></i><span class="d-none d-lg-inline ms-lg-1">{{ link.label }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{# TODO: eventually not used anymore because of using a documentation link
|
||||
{% if entity_info is defined and entity_info is not empty %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
{{ entity_info|raw }}
|
||||
</div>
|
||||
{% endif %}
|
||||
#}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% import "Froxlor/table/table.html.twig" as table %}
|
||||
|
||||
{{ table.table(listing) }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<nav class="navbar navbar-expand-md navbar-light py-0">
|
||||
<nav class="navbar navbar-expand-md navbar-light p-0 {% if not block('heading') %}shadow-sm{% endif %}">
|
||||
<div class="container-fluid gx-0">
|
||||
<a class="navbar-brand p-3" href="{{ linker({'section': 'index'}) }}">
|
||||
<a class="navbar-brand" href="{{ linker({'section': 'index'}) }}">
|
||||
<img src="{{ header_logo }}" alt="" width="auto" height="24" class="d-inline-block align-text-top">
|
||||
</a>
|
||||
<div class="me-3 me-sm-0">
|
||||
@@ -30,28 +30,27 @@
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="search" class="position-relative" method="post">
|
||||
<div class="collapse navbar-collapse px-3 px-lg-5" id="navbar">
|
||||
<form id="search" class="d-flex position-relative" method="post">
|
||||
<div class="input-group">
|
||||
<input title="search" type="search" class="form-control-plaintext" placeholder="Search for ..." style="outline: none">
|
||||
</div>
|
||||
<ul id="search-dropdown" class="bg-white border list-group list-group-flush position-absolute" style="display:none; z-index: 50; max-height: 300px; overflow-y: scroll"></ul>
|
||||
<ul id="search-dropdown" class="bg-white border list-group list-group-flush position-absolute" style="top: 2.5rem; display:none; z-index: 50; max-height: 300px; overflow-y: scroll"></ul>
|
||||
</form>
|
||||
<div class="collapse navbar-collapse justify-content-end px-3" id="navbar">
|
||||
<ul class="navbar-nav align-items-center">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
{% if userinfo.adminsession == 1 %}
|
||||
<li class="nav-item text-nowrap d-block" id="updatecheck">
|
||||
</li>
|
||||
<li class="nav-item" id="updatecheck"></li>
|
||||
{% endif %}
|
||||
<li class="nav-item text-nowrap d-block me-2">
|
||||
<a class="btn btn-primary btn-sm d-block" href="{{ linker({'section': 'index'}) }}">
|
||||
<i class="fa fa-dashboard"></i> {{ lng('panel.dashboard') }}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ linker({'section': 'index'}) }}">
|
||||
{{ lng('panel.dashboard') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown me-2">
|
||||
<a class="btn btn-secondary btn-sm d-block dropdown-toggle" href="#" id="navbarOpts" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa fa-gears"></i> {{ lng('panel.options') }}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarOpts" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ userinfo.loginname }}
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="navbarOpts">
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarOpts">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ linker({'section': 'index', 'page': 'change_password'}) }}"><i class="fa-solid fa-lock"></i> {{ lng('login.password') }}</a>
|
||||
</li>
|
||||
@@ -90,8 +89,8 @@
|
||||
Switch back</a>
|
||||
</li>
|
||||
endif -->
|
||||
<li class="nav-item text-nowrap d-block">
|
||||
<a class="btn btn-link" title="{{ lng('login.logout') }}" href="{{ linker({'section': 'index', 'action': 'logout'}) }}">
|
||||
<li class="nav-item">
|
||||
<a class="btn btn-link pe-0" title="{{ lng('login.logout') }}" href="{{ linker({'section': 'index', 'action': 'logout'}) }}">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</a>
|
||||
</li>
|
||||
@@ -102,15 +101,38 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="d-flex flex-grow-1 overflow-hidden">
|
||||
{{ include('Froxlor/sidebarmenu.html.twig') }}
|
||||
<div class="d-flex flex-grow-1">
|
||||
{{ include('Froxlor/sidebar.html.twig') }}
|
||||
|
||||
<main role="main" class="d-flex flex-column flex-grow-1 px-5 pt-4 pb-0 overflow-auto max-h-before-header">
|
||||
<section class="flex-grow-1">
|
||||
<div class="d-flex flex-grow-1 overflow-hidden">
|
||||
{# TODO: eventually planned for settings page ...
|
||||
<div class="sub-sidebar border-end border-top d-none d-sm-block flex-shrink-0 py-3">
|
||||
<span class="px-3 text-muted">Settings</span>
|
||||
<nav class="nav flex-column">
|
||||
<a class="nav-link active" aria-current="page" href="#">Active</a>
|
||||
<a class="nav-link" href="#">Link</a>
|
||||
<a class="nav-link" href="#">Link</a>
|
||||
<a class="nav-link disabled">Disabled</a>
|
||||
</nav>
|
||||
</div>
|
||||
#}
|
||||
|
||||
<main class="d-flex flex-column flex-grow-1 overflow-auto">
|
||||
{% if block('heading') %}
|
||||
<section class="py-3 px-3 px-lg-5 bg-white shadow-sm border-top d-flex justify-content-between align-items-center">
|
||||
<div>{% block heading %}{% endblock %}</div>
|
||||
<div>{% block actions %}{% endblock %}</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<section class="flex-grow-1 p-3 p-lg-5">
|
||||
{% block content %}{% endblock %}
|
||||
</section>
|
||||
|
||||
{{ include('Froxlor/footer.html.twig') }}
|
||||
</main>
|
||||
|
||||
{% block subsidebar %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user