update templates and base structure

This commit is contained in:
envoyr
2022-02-18 17:06:23 +01:00
parent 14008d1432
commit 8b2ba97823
16 changed files with 1753 additions and 1819 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +1,50 @@
<div class="d-flex flex-column flex-shrink-0 p-3 text-white bg-dark" style="width: 280px;">
<ul class="nav nav-pills flex-column mb-auto">
<nav id="sidebar" class="sidebar collapse d-md-flex flex-shrink-0 flex-column bg-dark overflow-auto max-h-before-header">
<ul class="nav d-flex flex-fill flex-column py-3">
{% for idx,mitems in nav_entries %}
{% if mitems.label|upper != 'OVERVIEW' %}
{% if mitems.items is not empty %}
<li class="nav-item">
<a class="nav-link text-light {% if mitems.active == 0 %}collapsed{% endif %}" href="#sub{{ idx }}" data-bs-toggle="collapse" data-bs-target="#sub{{ idx }}">
<span class="{{ mitems.icon }}"></span>
{{ mitems.label|upper }}</a>
<div class="collapse {% if mitems.active == 1 %}show{% endif %}" id="sub{{ idx }}" aria-expanded="{% if mitems.active == 1 %}true{% else %}false{% endif %}">
<ul class="flex-column ps-3 nav">
{% for item in mitems.items %}
<li class="nav-item">
<a class="nav-link text-light pb-0 {% if item.active == 1 %}font-weight-bold{% endif %}" href="{{ item.url|raw }}">{{ item.label }}</a>
</li>
{% endfor %}
</ul>
</div>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link text-light {% if mitems.active == 1 %}active{% endif %}" href="{% if mitems.url is not empty %}{{ mitems.url|raw }}{% else %}#{% endif %}" {% if mitems.target is not empty %} target="{{ mitems.target }}" {% endif %}>
{% if mitems.icon is not empty %}
<span class="{{ mitems.icon }}"></span>
{% endif %}
{{ mitems.label|upper }}</a>
</li>
{% endif %}
{% if mitems.items is not empty %}
<li class="nav-item">
<a class="nav-link text-light {% if mitems.active == 0 %}collapsed{% endif %}" href="#sub{{ idx }}" data-bs-toggle="collapse" data-bs-target="#sub{{ idx }}">
{% if mitems.icon is not empty %}
<i class="{{ mitems.icon }}"></i>
{% endif %}
{{ mitems.label }}
</a>
<div class="collapse {% if mitems.active == 1 %}show{% endif %}" id="sub{{ idx }}" aria-expanded="{% if mitems.active == 1 %}true{% else %}false{% endif %}">
<ul class="flex-column ps-3 nav">
{% for item in mitems.items %}
<li class="nav-item">
<a class="nav-link text-light {% if item.active == 1 %}font-weight-bold{% endif %}" href="{{ item.url|raw }}">{{ item.label|raw }}</a>
</li>
{% endfor %}
</ul>
</div>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link text-light {% if mitems.active == 1 %}active{% endif %}" href="{% if mitems.url is not empty %}{{ mitems.url|raw }}{% else %}#{% endif %}" {% if mitems.target is not empty %} target="{{ mitems.target }}" {% endif %}>
{% if mitems.icon is not empty %}
<i class="{{ mitems.icon }}"></i>
{% endif %}
{{ mitems.label|upper }}
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<hr>
<div class="dropdown">
<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 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>
</div>
</nav>

View File

@@ -8,6 +8,24 @@
@extend .shadow-sm;
}
.page-header {
margin-bottom: 2rem;
&:after {
margin-top: .5rem;
display: block;
height: 3px;
width: 100px;
background: $froxlor-blue-dark;
border-radius: 3px;
content: ' ';
}
}
.progress-thin {
height: 3px;
}
.alert-icon {
padding: .5rem;
background: rgba(0, 0, 0, .15);
@@ -16,12 +34,6 @@
margin-right: .75rem;
}
.card .card-body {
p {
@extend .card-text;
}
}
.max-w-420 {
max-width: 420px;
}
@@ -34,6 +46,10 @@
max-width: 991.98px;
}
.max-h-before-header {
max-height: calc(100vh - ($spacer * 3.5));
}
footer {
@extend .text-muted;
}

View File

@@ -0,0 +1,12 @@
.card {
margin-bottom: $spacer * 1.5;
.card-header {
border-bottom: #e5e5e5 solid 1px;
}
.card-body {
p {
@extend .card-text;
}
}
}

View File

@@ -0,0 +1,22 @@
.navbar {
background: darken($navbar-bg, 3);
}
@include media-breakpoint-up(md) {
.navbar {
.navbar-brand {
background: $dark;
width: $sidebar-width;
}
}
}
@include media-breakpoint-down(md) {
.navbar {
background: $dark;
}
.navbar-light .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");
}
}

View File

@@ -0,0 +1,38 @@
.sidebar {
width: $sidebar-width;
@extend .shadow;
&.collapsing {
transition: none;
}
.user-info {
background: darken($dark, 2);
}
>.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 {
background: darken($dark, 2);
a {
opacity: .78;
margin-left: 1.25rem;
}
}
}
}
}

View File

@@ -6,3 +6,6 @@
// Theme
@import "global";
@import "components/navbar";
@import "components/sidebar";
@import "components/card";

View File

@@ -21,7 +21,8 @@ $alert-border-width: 0;
$list-group-item-color-scale: 0;
$list-group-item-bg-scale: 0;
$card-border-width: 0;
// Space
$spacer: 1.25rem;
// Body
$body-bg: $light-bg;
@@ -34,4 +35,12 @@ $border-radius: 0.5rem;
$links: $froxlor-blue-dark;
// Navbar
$navbar-bg: #ffffff;
$navbar-bg: #ffffff;
// Sidebar
$sidebar-width: 280px;
// Card
$card-cap-bg: none;
$card-cap-padding-y: $spacer;
$card-border-width: 0;

View File

@@ -1,29 +1,31 @@
{% macro ditem(lngstr, available, used, assigned = null, formatbytes = false) %}
<div class="col">
<div class="card bg-light h-100 p-2">
<div class="row mb-1">
<div class="col">{{ lng(lngstr) }}</div>
<div class="col-auto">
<small>{% if formatbytes %}{{ used|formatBytes }}{% else %}{{ used }}{% endif %}/{% if available < 0 %}{{ lng('customer.unlimited') }}{% else %}{% if formatbytes %}{{ available|formatBytes }}{% else %}{{ available }}{% endif %}{% endif %}</small>
</div>
</div>
<div class="progress my-auto" style="height: .25rem;">
{% set usageperc = 1 %}
{% if available > 0 %}
{% set usageperc = (used / available) * 100|round %}
{% endif %}
<div class="progress-bar{% if available < 0 %} bg-secondary{% elseif usageperc >= 75 and usageperc < 90 %} bg-warning{% elseif usageperc >= 90 %} bg-danger{% endif %}"
role="progressbar"
style="width: {% if available < 0 %}100{% else %}{{ usageperc }}{% endif %}%;" aria-valuenow="{% if available < 0 %}100{% else %}{{ used }}{% endif %}" aria-valuemin="0" aria-valuemax="{% if available < 0 %}100{% else %}{{ available }}{% endif %}"></div>
</div>
{% if assigned is not empty %}
<div class="progress my-auto" style="height: .25rem;">
<div class="progress-bar bg-info" role="progressbar"
style="width:{% if available > 0 %}{{ (assigned / available) * 100|round }}{% else %}1{% endif %}%;"
aria-valuenow="{{ assigned }}" aria-valuemin="0"
aria-valuemax="{{ available }}"></div>
</div>
{% endif %}
</div>
</div>
<div class="col border-end border-bottom p-3">
<div class="row mb-1">
<div class="col text-truncate">{{ lng(lngstr) }}</div>
<div class="col-auto">
<small>{% if formatbytes %}{{ used|formatBytes }}{% else %}{{ used }}{% endif %}/{% if available < 0 %}{{ lng('customer.unlimited') }}{% else %}{% if formatbytes %}{{ available|formatBytes }}{% else %}{{ available }}{% endif %}{% endif %}</small>
</div>
</div>
<div class="progress progress-thin my-auto">
{% set usageperc = 1 %}
{% if available > 0 %}
{% set usageperc = (used / available) * 100|round %}
{% endif %}
<div
class="progress-bar{% if available < 0 %} bg-secondary{% elseif usageperc >= 75 and usageperc < 90 %} bg-warning{% elseif usageperc >= 90 %} bg-danger{% endif %}"
role="progressbar"
style="width: {% if available < 0 %}100{% else %}{{ usageperc }}{% endif %}%;"
aria-valuenow="{% if available < 0 %}100{% else %}{{ used }}{% endif %}"
aria-valuemin="0"
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"
style="width:{% if available > 0 %}{{ (assigned / available) * 100|round }}{% else %}1{% endif %}%;"
aria-valuenow="{{ assigned }}" aria-valuemin="0"
aria-valuemax="{{ available }}"></div>
</div>
{% endif %}
</div>
{% endmacro %}

View File

@@ -1,6 +1,8 @@
{% extends "Froxlor/userarea.html.twig" %}
{% block content %}
<h2 class="page-header">Dashboard</h2>
{% if get_setting('panel.is_configured') == 0 and userinfo.adminsession == 1 and userinfo.change_serversettings == 1 %}
<div class="alert alert-info position-relative p-5">
<h3>Willkommen bei Froxlor!</h3>
@@ -12,323 +14,103 @@
</div>
{% endif %}
<div class="card">
{% import "Froxlor/user/dashboard-item.html.twig" as dashboard %}
{% if userinfo.adminsession == 1 %}
{# admin-resources #}
<div class="row g-0">
{{ dashboard.ditem('admin.customers', userinfo.customers, overview.number_customers) }}
{{ dashboard.ditem('admin.domains', userinfo.domains, overview.number_domains) }}
{{ dashboard.ditem('customer.diskspace', userinfo.diskspace_bytes, overview.diskspace_bytes_used, overview.diskspace_bytes, true) }}
{{ dashboard.ditem('customer.traffic', userinfo.traffic_bytes, overview.traffic_bytes_used, overview.traffic_bytes, true) }}
{{ dashboard.ditem('customer.subdomains', userinfo.subdomains, overview.subdomains_used, overview.subdomains_assigned) }}
</div>
<div class="row g-0">
{{ dashboard.ditem('customer.mysqls', userinfo.mysqls, overview.mysqls_used, overview.mysqls_assigned) }}
{{ dashboard.ditem('customer.emails', userinfo.emails, overview.emails_used, overview.emails_assigned) }}
{{ dashboard.ditem('customer.accounts', userinfo.email_accounts, overview.email_accounts_used, overview.email_accounts_assigned) }}
{{ dashboard.ditem('customer.forwarders', userinfo.email_forwarders, overview.email_forwarders_used, overview.email_forwarders_assigned) }}
{{ dashboard.ditem('customer.ftps', userinfo.ftps, overview.ftps_used, overview.ftps_assigned) }}
</div>
{% else %}
{# customer-resources #}
<div class="row g-0">
{{ dashboard.ditem('customer.diskspace', userinfo.diskspace_bytes, userinfo.diskspace_bytes_used, null, true) }}
{{ dashboard.ditem('customer.traffic', userinfo.traffic_bytes, userinfo.traffic_bytes_used, null, true) }}
{{ dashboard.ditem('customer.subdomains', userinfo.subdomains, userinfo.subdomains_used) }}
{{ dashboard.ditem('customer.mysqls', userinfo.mysqls, userinfo.mysqls_used) }}
</div>
<div class="row g-0">
{{ dashboard.ditem('customer.emails', userinfo.emails, userinfo.emails_used) }}
{{ dashboard.ditem('customer.accounts', userinfo.email_accounts, userinfo.email_accounts_used) }}
{{ dashboard.ditem('customer.forwarders', userinfo.email_forwarders, userinfo.email_forwarders_used) }}
{{ dashboard.ditem('customer.ftps', userinfo.ftps, userinfo.ftps_used) }}
</div>
{% endif %}
</div>
<div class="row">
<div class="col-12 {% if userinfo.adminsession == 1 %}col-xl-4{% else %}col-xl-8{% endif %} mb-3 mb-xl-0">
<div class="card mb-3">
<div class="col-7">
<div class="card">
<div class="card-header">
<i class="fa-solid fa-chart-line"></i>
{{ lng('panel.usage_statistics') }}
<h5>Applicant Information</h5>
<span class="text-muted">Personal details and application.</span>
</div>
<div class="card-body">
<div class="row row-cols-1 row-cols-md-2{% if userinfo.adminsession == 0 %} row-cols-lg-3 row-cols-xl-4{% endif %} g-4">
{% import "Froxlor/user/dashboard-item.html.twig" as dashboard %}
{% if userinfo.adminsession == 1 %}
{# admin-resources #}
{{ dashboard.ditem('admin.customers', userinfo.customers, overview.number_customers) }}
{{ dashboard.ditem('admin.domains', userinfo.domains, overview.number_domains) }}
{{ dashboard.ditem('customer.diskspace', userinfo.diskspace_bytes, overview.diskspace_bytes_used, overview.diskspace_bytes, true) }}
{{ dashboard.ditem('customer.traffic', userinfo.traffic_bytes, overview.traffic_bytes_used, overview.traffic_bytes, true) }}
{{ dashboard.ditem('customer.subdomains', userinfo.subdomains, overview.subdomains_used, overview.subdomains_assigned) }}
{{ dashboard.ditem('customer.mysqls', userinfo.mysqls, overview.mysqls_used, overview.mysqls_assigned) }}
{{ dashboard.ditem('customer.emails', userinfo.emails, overview.emails_used, overview.emails_assigned) }}
{{ dashboard.ditem('customer.accounts', userinfo.email_accounts, overview.email_accounts_used, overview.email_accounts_assigned) }}
{{ dashboard.ditem('customer.forwarders', userinfo.email_forwarders, overview.email_forwarders_used, overview.email_forwarders_assigned) }}
{{ dashboard.ditem('customer.ftps', userinfo.ftps, overview.ftps_used, overview.ftps_assigned) }}
{% else %}
{# customer-resources #}
{{ dashboard.ditem('customer.diskspace', userinfo.diskspace_bytes, userinfo.diskspace_bytes_used, null, true) }}
{{ dashboard.ditem('customer.traffic', userinfo.traffic_bytes, userinfo.traffic_bytes_used, null, true) }}
{{ dashboard.ditem('customer.subdomains', userinfo.subdomains, userinfo.subdomains_used) }}
{{ dashboard.ditem('customer.mysqls', userinfo.mysqls, userinfo.mysqls_used) }}
{{ dashboard.ditem('customer.emails', userinfo.emails, userinfo.emails_used) }}
{{ dashboard.ditem('customer.accounts', userinfo.email_accounts, userinfo.email_accounts_used) }}
{{ dashboard.ditem('customer.forwarders', userinfo.email_forwarders, userinfo.email_forwarders_used) }}
{{ dashboard.ditem('customer.ftps', userinfo.ftps, userinfo.ftps_used) }}
{% endif %}
</div>
dd
</div>
</div>
{% if userinfo.adminsession == 1 %}
{# froxlor-details #}
<div class="card mb-3">
<div class="card-header">
<i class="fa-solid fa-wrench"></i>
{{ lng('admin.froxlordetails') }}
</div>
<ul class="list-group list-group-flush">
{# froxlor-details #}
<div class="card mb-3">
<div class="card-header">
<i class="fa-solid fa-wrench"></i>
{{ lng('admin.froxlordetails') }}
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('tasks.outstanding_tasks') }}</div>
{% for task in outstanding_tasks %}
<i class="fa-regular fa-clock"></i>
{{ task.desc }}<br>
{% endfor %}
</div>
</li>
{% for cronrun in cron_last_runs %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('tasks.outstanding_tasks') }}</div>
{% for task in outstanding_tasks %}
<i class="fa-regular fa-clock"></i>
{{ task.desc }}<br>
{% endfor %}
</div>
</li>
{% for cronrun in cron_last_runs %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">{{ cronrun.title }}</div>
<span class="badge bg-primary">
<div class="ms-2 me-auto">{{ cronrun.title }}</div>
<span class="badge bg-primary">
{% if cronrun.lastrun > 0 %}
{{ cronrun.lastrun|date('d.m.Y H:i') }}
{% else %}
{{ lng('cronjobs.notyetrun') }}
{% endif %}
</span>
</li>
{% endfor %}
</ul>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{% if userinfo.adminsession == 1 %}
<div
class="col-12 col-xl-4 mb-3 mb-xl-0">
{# system infos #}
<div class="card mb-3">
<div class="card-header">
<i class="fa-solid fa-gears"></i>
{{ lng('admin.systemdetails') }}
<div class="col-5">
<div id="newsfeed" class="card">
<div class="card-header">
<h5>Froxlor Newsfeed</h5>
<span class="text-muted">Personal details and application.</span>
</div>
<div class="list-group list-group-flush" id="newsfeeditems">
<div class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
Loading newsfeed...
</div>
<span>
<i class="fa-solid fa-spinner fa-spin"></i>
</span>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.hostname') }}</div>
{{ sysinfo.hostname }}
</div>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.serversoftware') }}</div>
{{ sysinfo.webserver }}
</div>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.phpversion') }}</div>
<a href="{{ linker({'section':'settings','page':'phpinfo'}) }}">{{ sysinfo.phpversion }}</a>
</div>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.mysqlserverversion') }}</div>
{{ sysinfo.mysqlserverversion }}
</div>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.webserverinterface') }}</div>
{{ sysinfo.phpsapi }}
</div>
</li>
{% if sysinfo.memory is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.memory') }}</div>
<pre>{{ sysinfo.memory }}</pre>
</div>
</li>
{% endif %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.sysload') }}</div>
{{ sysinfo.load }}
</div>
</li>
{% if sysinfo.kernel is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">Kernel</div>
{{ sysinfo.kernel }}
</div>
</li>
{% endif %}
{% if sysinfo.uptime is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">Uptime</div>
{{ sysinfo.uptime }}
</div>
</li>
{% endif %}
</ul>
</div>
</div>
{% endif %}
<div
class="col-12 col-xl-4">
{# newsfeed #}
{% if (userinfo.adminsession == 1 and get_setting('admin.show_news_feed') == 1) or (userinfo.adminsession == 0 and get_setting('customer.show_news_feed') == 1) %}
<div class="card mb-3" id="newsfeed" {% if userinfo.adminsession == 0 %} data-role="customer" {% endif %}>
<div class="card-header">
<i class="fa-solid fa-rss"></i>
News
</div>
<div class="list-group list-group-flush" id="newsfeeditems">
<div class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
Loading newsfeed...
</div>
<span>
<i class="fa-solid fa-spinner fa-spin"></i>
</span>
</div>
</div>
</div>
{% elseif userinfo.adminsession == 1 and get_setting('admin.show_news_feed') == 0 %}
<div class="card bg-warning text-dark mb-3">
<div class="card-header">
<i class="fa-solid fa-rss"></i>
News
</div>
<div class="card-body">
<i class="fa-solid fa-circle-exclamation"></i>
{{ lng('panel.newsfeed_disabled') }}&nbsp;
<a href="{{ linker({'section':'settings','part':'panel'}) }}" title="{{ lng('panel.edit') }}">
<i class="fa-solid fa-pen"></i>
</a>
</div>
</div>
{% endif %}
{% if userinfo.adminsession == 1 %}
{# custom notes #}
{% if userinfo.custom_notes is not empty and userinfo.custom_notes_show == 1 %}
<div class="card bg-info text-dark mb-3">
<div class="card-body">
{{ userinfo.custom_notes|nl2br|raw }}
</div>
</div>
{% endif %}
{# systemdetails #}
{% else %}
{# account info #}
<div class="card mb-3">
<div class="card-header">
<i class="fa-solid fa-user"></i>
{{ lng('index.accountdetails') }}
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('login.username') }}</div>
{{ userinfo.loginname }}
</div>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.email') }}</div>
{{ userinfo.email }}
</div>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.services') }}</div>
{% if userinfo.imap == 1 %}
<span class="badge bg-success">IMAP</span>
{% endif %}
{% if userinfo.pop3 == 1 %}
<span class="badge bg-success">POP3</span>
{% endif %}
{% if userinfo.phpenabled == 1 %}
<span class="badge bg-success">PHP</span>
{% endif %}
{% if userinfo.perlenabled == 1 %}
<span class="badge bg-success">Perl/CGI</span>
{% endif %}
{% if userinfo.api_allowed == 1 %}
<a href="{{ linker({'section':'index','page':'apikeys'}) }}">
<span class="badge bg-success">API</span>
</a>
{% endif %}
</div>
</li>
{% if stdsubdomain is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('admin.stdsubdomain') }}</div>
{{ stdsubdomain }}
</div>
</li>
{% endif %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.domains') }}</div>
{% for domain in domains %}
{{ domain }}<br>
{% endfor %}
</div>
<span class="badge bg-primary rounded-pill">{{ domains|length }}</span>
</li>
</ul>
</div>
{# customer details #}
<div class="card">
<div class="card-header">
<i class="fa-solid fa-id-card"></i>
{{ lng('index.customerdetails') }}
</div>
<ul class="list-group list-group-flush">
{% if userinfo.customernumber is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.customernumber') }}</div>
{{ userinfo.customernumber }}
</div>
</li>
{% endif %}
{% if userinfo.company is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.company') }}</div>
{{ userinfo.company }}
</div>
</li>
{% endif %}
{% if userinfo.name is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.name') }}</div>
{{ userinfo.firstname }}
{{ userinfo.name }}
</div>
</li>
{% endif %}
{% if userinfo.street is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.street') }}</div>
{{ userinfo.street }}
</div>
</li>
{% endif %}
{% if userinfo.city is not empty %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('customer.zipcode') }}/{{ lng('customer.city') }}</div>
{{ userinfo.zipcode }}
{{ userinfo.city }}
</div>
</li>
{% endif %}
{% if userinfo.custom_notes is not empty and userinfo.custom_notes_show == 1 %}
<li class="list-group-item list-group-item-info d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
{{ userinfo.custom_notes|nl2br|raw }}
</div>
</li>
{% endif %}
</ul>
</div>
{% endif %}
</div>
</div>
{% endblock %}

View File

@@ -1,9 +1,9 @@
<a href="{{ link|default('#')|raw }}" class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{ title }}</h5>
<b class="mb-1">{{ title }}</b>
{% if date is not empty %}
<small>{{ date }}</small>
{% endif %}
</div>
<p class="mb-1">{{ content|raw }}</p>
<p class="small mb-1">{{ content|raw }}</p>
</a>

View File

@@ -17,15 +17,20 @@
</div>
{% endif %}
<nav class="navbar navbar-expand py-0">
<nav class="navbar navbar-expand-md navbar-light py-0">
<div class="container-fluid gx-0">
<a class="navbar-brand bg-dark p-3" style="width: 280px" href="{{ linker({'section': 'index'}) }}">
<a class="navbar-brand p-3" href="{{ linker({'section': 'index'}) }}">
<img src="{{ header_logo }}" alt="" width="auto" height="24" class="d-inline-block align-text-top">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTop" aria-controls="navbarTop" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-end px-3" id="navbarTop">
<div class="me-3 me-sm-0">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar" aria-controls="sidebar" aria-expanded="false" aria-label="Toggle sidebar">
<span class="navbar-toggler-icon"></span>
</button>
</div>
<div class="collapse navbar-collapse justify-content-end px-3" id="navbar">
<ul class="navbar-nav align-items-center">
<li class="nav-item text-nowrap d-block me-2">
<a class="btn btn-primary btn-sm d-block" href="{{ linker({'section': 'index'}) }}">
@@ -87,11 +92,13 @@
{% endblock %}
{% block body %}
<div class="d-flex flex-grow-1">
<div class="d-flex flex-grow-1 overflow-hidden">
{{ include('Froxlor/sidebarmenu.html.twig') }}
<main role="main" class="flex-grow-1 p-5">
{% block content %}{% endblock %}
<main role="main" class="d-flex flex-column flex-grow-1 p-5 pb-0 overflow-auto max-h-before-header">
<section class="flex-grow-1">
{% block content %}{% endblock %}
</section>
{{ include('Froxlor/footer.html.twig') }}
</main>