[BS5] remove ui theme selector - add darkmode toggler

This commit is contained in:
FreddleSpl0it 2022-06-23 16:34:58 +02:00
parent 560df58bb4
commit 052959f435
38 changed files with 233 additions and 286379 deletions

View File

@ -83,16 +83,12 @@ foreach ($RSPAMD_MAPS['regex'] as $rspamd_regex_desc => $rspamd_regex_map) {
];
}
$themes = array_diff(scandir('/web/css/themes'), array('..', '.'));
$themes = array_filter((str_replace("-bootstrap.css", "", $themes)));
$template = 'admin.twig';
$template_data = [
'tfa_data' => $tfa_data,
'tfa_id' => @$_SESSION['tfa_id'],
'fido2_cid' => @$_SESSION['fido2_cid'],
'fido2_data' => $fido2_data,
'themes' => $themes,
'gal' => @$_SESSION['gal'],
'license_guid' => license('guid'),
'api' => [

View File

@ -63,6 +63,10 @@
.navbar-nav {
margin: 0;
}
.navbar-nav .nav-item {
display: flex;
padding: 0 10px !important;
}
.navbar-nav .nav-link {
height: 44px;
display: flex;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -597,7 +597,7 @@ progress {
color: #999;
}
.blockquote-footer::before {
content: "— ";
content: "— ";
}
.img-fluid {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,181 @@
body {
background-color: #414141;
color: #ccc;
}
.card {
border: 1px solid #1c1c1c;
background-color: #3a3a3a;
}
legend {
color: #f5f5f5;
}
.card-header {
color: #bbb;
background-color: #2c2c2c;
border-color: transparent;
}
.btn-secondary, .paginate_button .page-link, .btn-light {
color: #fff;
background-color: #7a7a7a !important;
border-color: #5c5c5c !important;
}
.btn-secondary:focus, .btn-secondary:hover, .btn-group.open .dropdown-toggle.btn-secondary {
background-color: #7a7a7a;
border-color: #5c5c5c !important;
color: #fff;
}
.modal-content {
background-color: #383838;
}
.modal-header {
border-bottom: 1px solid #161616;
}
.modal-title {
color: white;
}
.modal .btn-close {
filter: invert(1) grayscale(100%) brightness(200%);
}
.navbar.bg-light {
background-color: #222222 !important;
border-color: #181818;
}
.nav-link {
color: #ccc !important;
}
.nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link {
background: none;
}
.nav-tabs .nav-link:not(.disabled):hover, .nav-tabs .nav-link:not(.disabled):focus, .nav-tabs .nav-link.active {
border-bottom-color: #414141;
}
.table, .table-striped>tbody>tr:nth-of-type(odd)>*, tbody tr {
color: #ccc !important;
}
.dropdown-menu {
background-color: #585858;
border: 1px solid #333;
}
.dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover {
color: #fafafa;
}
.bootstrap-select>.dropdown-toggle.bs-placeholder, .bootstrap-select>.dropdown-toggle.bs-placeholder:active, .bootstrap-select>.dropdown-toggle.bs-placeholder:focus, .bootstrap-select>.dropdown-toggle.bs-placeholder:hover {
color: #fff;
}
tbody tr {
color: #555;
}
.navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, .navbar-default .navbar-nav>.open>a:hover {
color: #ccc;
}
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus, .navbar-default .navbar-nav>.active>a:hover {
color: #ccc;
}
.list-group-item {
background-color: #333;
border: 1px solid #555;
}
.table-striped>tbody>tr:nth-of-type(odd) {
background-color: #333;
}
tbody tr {
color: #ccc;
}
.label.label-last-login {
color: #ccc !important;
background-color: #555 !important;
}
.progress {
background-color: #555;
}
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
color: #ccc;
}
div.numberedtextarea-number {
color: #999;
}
.well {
border: 1px solid #555;
background-color: #333;
}
pre {
color: #ccc;
background-color: #333;
border: 1px solid #555;
}
input.form-control, textarea.form-control {
color: #e2e2e2 !important;
background-color: #555;
border: 1px solid #999;
}
input.form-control:focus, textarea.form-control {
background-color: #555 !important;
}
input.form-control:disabled, textarea.form-disabled {
color: #a8a8a8 !important;
background-color: #1a1a1a !important;
}
.input-group-addon {
color: #ccc;
background-color: #555;
border: 1px solid #999;
}
.input-group-text {
color: #ccc;
background-color: #242424;
}
.tag-add {
color: #ccc;
}
.tag-add:hover {
color: #d1d1d1;
}
/* Update 2022-02-09 */
/* Rspamd Settings */
a.list-group-item, button.list-group-item {
color: #fafafa;
background-color: #28b62c;
border-color: #23a127;
}
a.list-group-item:focus, a.list-group-item:hover, button.list-group-item:focus, button.list-group-item:hover {
margin-top: 1px;
border-bottom-width: 3px;
background-color: #28b62c;
border-color: #23a127;
color: white;
}
.list-group-item {
color: #ccc;
}
.dropdown-item {
color: #ccc;
}
.dropdown-item:hover {
color: #616161 !important;
}
.dropdown-item.active:hover {
color: #fff !important;
background-color: #31b1e4;
}
.form-select {
color: #e2e2e2!important;
background-color: #555!important;
border: 1px solid #999;
}
.responsive-tabs .card-header .btn {
color: #c7c7c7;
}
.responsive-tabs .card-header .btn:hover {
color: #fff;
}
.navbar-toggler {
color: #fff !important;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -117,20 +117,6 @@ function customize($_action, $_item, $_data = null) {
$ui_announcement_type = (in_array($_data['ui_announcement_type'], array('info', 'warning', 'danger'))) ? $_data['ui_announcement_type'] : false;
$ui_announcement_active = (!empty($_data['ui_announcement_active']) ? 1 : 0);
// check theme
$theme = strtolower($_data['ui_theme']);
$themes = array_diff(scandir('/web/css/themes'), array('..', '.'));
$themes = array_filter((str_replace("-bootstrap.css", "", $themes)));
if (!in_array($theme, $themes)){
// err, theme not found
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => "Theme not found"
);
return false;
}
try {
$redis->set('TITLE_NAME', htmlspecialchars($title_name));
$redis->set('MAIN_NAME', htmlspecialchars($main_name));
@ -140,7 +126,6 @@ function customize($_action, $_item, $_data = null) {
$redis->set('UI_ANNOUNCEMENT_TEXT', $ui_announcement_text);
$redis->set('UI_ANNOUNCEMENT_TYPE', $ui_announcement_type);
$redis->set('UI_ANNOUNCEMENT_ACTIVE', $ui_announcement_active);
$redis->set('UI_THEME', $theme);
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
@ -244,19 +229,6 @@ function customize($_action, $_item, $_data = null) {
return false;
}
break;
case 'ui_theme':
try {
return $redis->get('UI_THEME');
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_item, $_data),
'msg' => array('redis_error', $e)
);
return false;
}
break;
case 'main_logo_specs':
try {
$image = new Imagick();

View File

@ -252,7 +252,8 @@ $css_minifier = new CSSminifierExtended();
$css_dir = array_diff(scandir('/web/css/build'), array('..', '.'));
// get customized ui data
$UI_TEXTS = customize('get', 'ui_texts');
$UI_THEME = customize('get', 'ui_theme');
// minify bootstrap theme
if (file_exists('/web/css/themes/'.$UI_THEME.'-bootstrap.css'))
$css_minifier->add('/web/css/themes/'.$UI_THEME.'-bootstrap.css');

View File

@ -104,6 +104,11 @@ $AVAILABLE_LANGUAGES = array(
'zh' => '中文 (Chinese)'
);
// default theme is lumen
// additional themes can be found here: https://bootswatch.com/
// copy them to data/web/css/themes/{THEME-NAME}-bootstrap.css
$UI_THEME = "lumen";
// Show DKIM private keys - false by default
$SHOW_DKIM_PRIV_KEYS = false;

View File

@ -320,6 +320,28 @@ $(document).ready(function() {
$(tagValuesElem).val(JSON.stringify(value_tags));
$(tagInputElem).val('');
}
// Dark Mode Loader
// check if darkmode is preferred by OS
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
toggleDarkMode();
// check if darkmode is set by localStorage
if (JSON.parse(localStorage.getItem("darkmode")) === true)
toggleDarkMode();
// register dark mode toggle event listener
$('#dark-mode-toggle').click(toggleDarkMode);
// dark mode toggle funtion
function toggleDarkMode(){
if($('#dark-mode-theme').length){
$('#dark-mode-theme').remove();
$('#dark-mode-toggle').prop('checked', false);
localStorage.setItem('darkmode', 'false');
}else{
$('head').append('<link id="dark-mode-theme" rel="stylesheet" type="text/css" href="/css/themes/mailcow-darkmode.css">');
$('#dark-mode-toggle').prop('checked', true);
localStorage.setItem('darkmode', 'true');
}
}
});

View File

@ -1,3 +1,5 @@
$(document).ready(function() {
var darkmode = localStorage.getItem("darkmode");
localStorage.clear();
localStorage.setItem("darkmode", darkmode);
});

View File

@ -338,7 +338,6 @@
"ui_header_announcement_type_info": "Info",
"ui_header_announcement_type_warning": "Important",
"ui_texts": "UI labels and texts",
"ui_theme": "Design",
"unban_pending": "unban pending",
"unchanged_if_empty": "If unchanged leave blank",
"upload": "Upload",

View File

@ -67,14 +67,6 @@
<legend data-bs-target="#ui_texts" style="padding-top:20px" unselectable="on">{{ lang.admin.ui_texts }}</legend><hr />
<div id="ui_texts">
<form class="form" data-id="uitexts" role="form" method="post">
<div class="mb-4 d-flex flex-column">
<label for="uitests_theme">{{ lang.admin.ui_theme }}:</label>
<select class="full-width-select" data-live-search="true" id="uitests_theme" name="ui_theme" required>
{% for theme in themes %}
<option>{{ theme }}</option>
{% endfor %}
</select>
</div>
<div class="mb-2">
<label for="uitests_title_name">{{ lang.admin.title_name }}:</label>
<input type="text" class="form-control" id="uitests_title_name" name="title_name" placeholder="mailcow UI" value="{{ ui_texts.title_name|raw }}">

View File

@ -19,10 +19,16 @@
<div class="container-fluid">
<a class="navbar-brand" href="/"><img alt="mailcow-logo" src="{{ logo|default('/img/cow_mailcow.svg') }}"></a>
<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>
<i class="bi bi-list fs-3"></i>
</button>
<div id="navbar" class="navbar-collapse collapse">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<div class="nav-link form-check form-switch my-auto d-flex align-items-center">
<label class="form-check-label"><i class="bi bi-moon-fill"></i></label>
<input class="form-check-input ms-2" type="checkbox" id="dark-mode-toggle">
</div>
</li>
{% if mailcow_locale %}
<li class="nav-item dropdown{% if available_languages|length == 1 %}lang-link-disabled{% endif %}">
<a href="#" class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-expanded="false"><span class="flag-icon flag-icon-{{ mailcow_locale }}"></span></a>
@ -78,9 +84,9 @@
</li>
{% endif %}
{% if not dual_login and mailcow_cc_username %}
<li class="logged-in-as" class="nav-item"><a href="#" onclick="logout.submit()" class="nav-link"><b class="username-lia">{{ mailcow_cc_username }}</b> <i class="bi bi-power ms-2"></i></a></li>
<li class="logged-in-as nav-item"><a href="#" onclick="logout.submit()" class="nav-link"><b class="username-lia">{{ mailcow_cc_username }}</b> <i class="bi bi-power ms-2"></i></a></li>
{% elseif dual_login %}
<li class="logged-in-as" class="nav-item"><a href="#" onclick="logout.submit()" class="nav-link"><b class="username-lia">{{ mailcow_cc_username }} <span class="text-info">({{ dual_login.username }})</span> </b><i class="bi bi-power ms-2"></i></a></li>
<li class="logged-in-as nav-item"><a href="#" onclick="logout.submit()" class="nav-link"><b class="username-lia">{{ mailcow_cc_username }} <span class="text-info">({{ dual_login.username }})</span> </b><i class="bi bi-power ms-2"></i></a></li>
{% endif %}
{% if not is_master %}
<li class="text-warning slave-info nav-item">[ slave ]</li>

View File

@ -6,7 +6,13 @@
<div class="row my-4">
<div class="col-12 col-md-7 col-lg-6 col-xl-5 ms-auto me-auto">
<div class="card">
<div class="card-header"><i class="bi bi-person-fill"></i> {{ lang.login.login }}</div>
<div class="card-header d-flex">
<i class="bi bi-person-fill"></i> {{ lang.login.login }}
<div class="ms-auto form-check form-switch my-auto d-flex align-items-center">
<label class="form-check-label"><i class="bi bi-moon-fill"></i></label>
<input class="form-check-input ms-2" type="checkbox" id="dark-mode-toggle">
</div>
</div>
<div class="card-body">
<div class="text-center mailcow-logo mb-4"><img src="{{ logo|default('/img/cow_mailcow.svg') }}" alt="mailcow"></div>
{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active %}