mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2025-02-09 13:46:58 +02:00
Merge branch 'pr/FreddleSpl0it/4527' into feature/bootstrap5
This commit is contained in:
commit
5629d47cb6
@ -83,6 +83,8 @@ 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 = [
|
||||
@ -90,6 +92,7 @@ $template_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' => [
|
||||
@ -112,6 +115,7 @@ $template_data = [
|
||||
'password_complexity' => password_complexity('get'),
|
||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||
'lang_admin' => json_encode($lang['admin']),
|
||||
'lang_datatables' => json_encode($lang['datatables']),
|
||||
];
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
|
11
data/web/css/build/001-bootstrap.min.css
vendored
11
data/web/css/build/001-bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
2
data/web/css/build/002-breakpoint.min.css
vendored
2
data/web/css/build/002-breakpoint.min.css
vendored
@ -1 +1 @@
|
||||
@media (max-width:1050px){.navbar-header{float:none}.navbar-left,.navbar-nav,.navbar-right{float:none!important}.navbar-toggle{display:block}.navbar-collapse{border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-collapse.collapse{display:none!important}.navbar-nav{margin-top:7.5px}.navbar-nav>li{float:none}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px}.collapse.in{display:block!important}.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}}
|
||||
@media (max-width:1050px){.navbar-header{float:none}.navbar-left,.navbar-nav,.navbar-right{float:none!important}.navbar-toggle{display:block}.navbar-collapse{border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-nav{margin-top:7.5px}.navbar-nav>li{float:none}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px}.collapse.in{display:block!important}.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}}
|
487
data/web/css/build/003-bootstrap-select.css
Normal file
487
data/web/css/build/003-bootstrap-select.css
Normal file
@ -0,0 +1,487 @@
|
||||
/*!
|
||||
* Bootstrap-select v1.14.0-beta2 (https://developer.snapappointments.com/bootstrap-select)
|
||||
*
|
||||
* Copyright 2012-2021 SnapAppointments, LLC
|
||||
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
@-webkit-keyframes bs-notify-fadeOut {
|
||||
0% {
|
||||
opacity: 0.9;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-o-keyframes bs-notify-fadeOut {
|
||||
0% {
|
||||
opacity: 0.9;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes bs-notify-fadeOut {
|
||||
0% {
|
||||
opacity: 0.9;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
select.bs-select-hidden,
|
||||
.bootstrap-select > select.bs-select-hidden,
|
||||
select.selectpicker {
|
||||
display: none !important;
|
||||
}
|
||||
.bootstrap-select {
|
||||
width: 220px \0;
|
||||
/*IE9 and below*/
|
||||
vertical-align: middle;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
display: -webkit-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: justify;
|
||||
-webkit-justify-content: space-between;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle:after {
|
||||
margin-top: -1px;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder:active {
|
||||
color: #999;
|
||||
}
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active,
|
||||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.bootstrap-select > select {
|
||||
position: absolute !important;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
display: block !important;
|
||||
width: 0.5px !important;
|
||||
height: 100% !important;
|
||||
padding: 0 !important;
|
||||
opacity: 0 !important;
|
||||
border: none;
|
||||
z-index: 0 !important;
|
||||
}
|
||||
.bootstrap-select > select.mobile-device {
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
z-index: 2 !important;
|
||||
}
|
||||
.has-error .bootstrap-select .dropdown-toggle,
|
||||
.error .bootstrap-select .dropdown-toggle,
|
||||
.bootstrap-select.is-invalid .dropdown-toggle,
|
||||
.was-validated .bootstrap-select select:invalid + .dropdown-toggle {
|
||||
border-color: #b94a48;
|
||||
}
|
||||
.bootstrap-select.is-valid .dropdown-toggle,
|
||||
.was-validated .bootstrap-select select:valid + .dropdown-toggle {
|
||||
border-color: #28a745;
|
||||
}
|
||||
.bootstrap-select.fit-width {
|
||||
width: auto !important;
|
||||
}
|
||||
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
|
||||
width: 220px;
|
||||
}
|
||||
.bootstrap-select > select.mobile-device:focus + .dropdown-toggle,
|
||||
.bootstrap-select .dropdown-toggle:focus {
|
||||
outline: thin dotted #333333 !important;
|
||||
outline: 5px auto -webkit-focus-ring-color !important;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
.bootstrap-select.form-control {
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
height: auto;
|
||||
}
|
||||
:not(.input-group) > .bootstrap-select.form-control:not([class*="col-"]) {
|
||||
width: 100%;
|
||||
}
|
||||
.bootstrap-select.form-control.input-group-btn {
|
||||
float: none;
|
||||
z-index: auto;
|
||||
}
|
||||
.form-inline .bootstrap-select,
|
||||
.form-inline .bootstrap-select.form-control:not([class*="col-"]) {
|
||||
width: auto;
|
||||
}
|
||||
.bootstrap-select:not(.input-group-btn),
|
||||
.bootstrap-select[class*="col-"] {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
margin-left: 0;
|
||||
}
|
||||
.bootstrap-select.dropdown-menu-right,
|
||||
.bootstrap-select[class*="col-"].dropdown-menu-right,
|
||||
.row .bootstrap-select[class*="col-"].dropdown-menu-right {
|
||||
float: right;
|
||||
}
|
||||
.form-inline .bootstrap-select,
|
||||
.form-horizontal .bootstrap-select,
|
||||
.form-group .bootstrap-select {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.form-group-lg .bootstrap-select.form-control,
|
||||
.form-group-sm .bootstrap-select.form-control {
|
||||
padding: 0;
|
||||
}
|
||||
.form-group-lg .bootstrap-select.form-control .dropdown-toggle,
|
||||
.form-group-sm .bootstrap-select.form-control .dropdown-toggle {
|
||||
height: 100%;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bootstrap-select.form-control-sm .dropdown-toggle,
|
||||
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bootstrap-select.form-control-sm .dropdown-toggle {
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
.form-inline .bootstrap-select .form-control {
|
||||
width: 100%;
|
||||
}
|
||||
.bootstrap-select.disabled,
|
||||
.bootstrap-select > .disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.bootstrap-select.disabled:focus,
|
||||
.bootstrap-select > .disabled:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
.bootstrap-select.bs-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.bootstrap-select.bs-container .dropdown-menu {
|
||||
z-index: 1060;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .filter-option {
|
||||
position: static;
|
||||
top: 0;
|
||||
left: 0;
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 1 auto;
|
||||
-ms-flex: 0 1 auto;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
.bs3.bootstrap-select .dropdown-toggle .filter-option {
|
||||
padding-right: inherit;
|
||||
}
|
||||
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option {
|
||||
position: absolute;
|
||||
padding-top: inherit;
|
||||
padding-bottom: inherit;
|
||||
padding-left: inherit;
|
||||
float: none;
|
||||
}
|
||||
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner {
|
||||
padding-right: inherit;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .filter-option-inner-inner {
|
||||
overflow: hidden;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .filter-expand {
|
||||
width: 0 !important;
|
||||
float: left;
|
||||
opacity: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .caret {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 12px;
|
||||
margin-top: -2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .bs-select-clear-selected {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-right: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.bs3.bootstrap-select .dropdown-toggle .bs-select-clear-selected {
|
||||
padding-right: inherit;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle .bs-select-clear-selected span {
|
||||
position: relative;
|
||||
top: -webkit-calc(((-1em / 1.5) + 1ex) / 2);
|
||||
top: calc(((-1em / 1.5) + 1ex) / 2);
|
||||
pointer-events: none;
|
||||
}
|
||||
.bs3.bootstrap-select .dropdown-toggle .bs-select-clear-selected span {
|
||||
top: auto;
|
||||
}
|
||||
.bootstrap-select .dropdown-toggle.bs-placeholder .bs-select-clear-selected {
|
||||
display: none;
|
||||
}
|
||||
.input-group .bootstrap-select.form-control .dropdown-toggle {
|
||||
border-radius: inherit;
|
||||
}
|
||||
.bootstrap-select[class*="col-"] .dropdown-toggle {
|
||||
width: 100%;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu {
|
||||
min-width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu > .inner:focus {
|
||||
outline: none !important;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu.inner {
|
||||
position: static;
|
||||
float: none;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li {
|
||||
position: relative;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li.active small {
|
||||
color: rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li.disabled a {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a.opt {
|
||||
position: relative;
|
||||
padding-left: 2.25em;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a span.check-mark {
|
||||
display: none;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li a span.text {
|
||||
display: inline-block;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu li small {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu .notify {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
width: 96%;
|
||||
margin: 0 2%;
|
||||
min-height: 26px;
|
||||
padding: 3px 5px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #e3e3e3;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||
pointer-events: none;
|
||||
opacity: 0.9;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bootstrap-select .dropdown-menu .notify.fadeOut {
|
||||
-webkit-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||
-o-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||
animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||
}
|
||||
.bootstrap-select .no-results {
|
||||
padding: 3px;
|
||||
background: #f5f5f5;
|
||||
margin: 0 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .filter-option {
|
||||
position: static;
|
||||
display: inline;
|
||||
padding: 0;
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,
|
||||
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner {
|
||||
display: inline;
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before {
|
||||
content: '\00a0';
|
||||
}
|
||||
.bootstrap-select.fit-width .dropdown-toggle .caret {
|
||||
position: static;
|
||||
top: auto;
|
||||
margin-top: -1px;
|
||||
}
|
||||
.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
right: 15px;
|
||||
top: 5px;
|
||||
}
|
||||
.bootstrap-select.show-tick .dropdown-menu li a span.text {
|
||||
margin-right: 34px;
|
||||
}
|
||||
.bootstrap-select .bs-ok-default:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0.5em;
|
||||
height: 1em;
|
||||
border-style: solid;
|
||||
border-width: 0 0.26em 0.26em 0;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle,
|
||||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle {
|
||||
z-index: 1061;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before {
|
||||
content: '';
|
||||
border-left: 7px solid transparent;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid rgba(204, 204, 204, 0.2);
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 9px;
|
||||
display: none;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after {
|
||||
content: '';
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid white;
|
||||
position: absolute;
|
||||
bottom: -4px;
|
||||
left: 10px;
|
||||
display: none;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before {
|
||||
bottom: auto;
|
||||
top: -4px;
|
||||
border-top: 7px solid rgba(204, 204, 204, 0.2);
|
||||
border-bottom: 0;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after {
|
||||
bottom: auto;
|
||||
top: -4px;
|
||||
border-top: 6px solid white;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before {
|
||||
right: 12px;
|
||||
left: auto;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after {
|
||||
right: 13px;
|
||||
left: auto;
|
||||
}
|
||||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before,
|
||||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before,
|
||||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after,
|
||||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after {
|
||||
display: block;
|
||||
}
|
||||
.bs-searchbox,
|
||||
.bs-actionsbox,
|
||||
.bs-donebutton {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
.bs-actionsbox {
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bs-actionsbox .btn-group {
|
||||
display: block;
|
||||
}
|
||||
.bs-actionsbox .btn-group button {
|
||||
width: 50%;
|
||||
}
|
||||
.bs-donebutton {
|
||||
float: left;
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bs-donebutton .btn-group {
|
||||
display: block;
|
||||
}
|
||||
.bs-donebutton .btn-group button {
|
||||
width: 100%;
|
||||
}
|
||||
.bs-searchbox + .bs-actionsbox {
|
||||
padding: 0 8px 4px;
|
||||
}
|
||||
.bs-searchbox .form-control {
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
float: none;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-select.css.map */
|
File diff suppressed because one or more lines are too long
323
data/web/css/build/006-footable.bootstrap.min.css
vendored
323
data/web/css/build/006-footable.bootstrap.min.css
vendored
@ -1,323 +0,0 @@
|
||||
table.footable-details,
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
table.footable,
|
||||
table.footable-details {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.footable-hide-fouc {
|
||||
display: none;
|
||||
}
|
||||
table > tbody > tr > td > span.footable-toggle {
|
||||
margin-right: 8px;
|
||||
opacity: 0.3;
|
||||
}
|
||||
table > tbody > tr > td > span.footable-toggle.last-column {
|
||||
margin-left: 8px;
|
||||
float: right;
|
||||
}
|
||||
table.table-condensed > tbody > tr > td > span.footable-toggle {
|
||||
margin-right: 5px;
|
||||
}
|
||||
table.footable-details > tbody > tr > th:nth-child(1) {
|
||||
min-width: 40px;
|
||||
width: 120px;
|
||||
}
|
||||
table.footable-details > tbody > tr > td:nth-child(2) {
|
||||
word-break: break-all;
|
||||
}
|
||||
table.footable-details > tbody > tr:first-child > td,
|
||||
table.footable-details > tbody > tr:first-child > th,
|
||||
table.footable-details > tfoot > tr:first-child > td,
|
||||
table.footable-details > tfoot > tr:first-child > th,
|
||||
table.footable-details > thead > tr:first-child > td,
|
||||
table.footable-details > thead > tr:first-child > th {
|
||||
border-top-width: 0;
|
||||
}
|
||||
table.footable-details.table-bordered > tbody > tr:first-child > td,
|
||||
table.footable-details.table-bordered > tbody > tr:first-child > th,
|
||||
table.footable-details.table-bordered > tfoot > tr:first-child > td,
|
||||
table.footable-details.table-bordered > tfoot > tr:first-child > th,
|
||||
table.footable-details.table-bordered > thead > tr:first-child > td,
|
||||
table.footable-details.table-bordered > thead > tr:first-child > th {
|
||||
border-top-width: 1px;
|
||||
}
|
||||
div.footable-loader {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
height: 300px;
|
||||
position: relative;
|
||||
}
|
||||
div.footable-loader > span.fooicon {
|
||||
display: inline-block;
|
||||
opacity: 0.3;
|
||||
font-size: 30px;
|
||||
line-height: 32px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-top: -16px;
|
||||
margin-left: -16px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-animation: fooicon-spin-r 2s infinite linear;
|
||||
animation: fooicon-spin-r 2s infinite linear;
|
||||
}
|
||||
table.footable > tbody > tr.footable-empty > td {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
}
|
||||
table.footable > tbody > tr > td,
|
||||
table.footable > tbody > tr > th {
|
||||
display: none;
|
||||
}
|
||||
table.footable > tbody > tr.footable-detail-row > td,
|
||||
table.footable > tbody > tr.footable-detail-row > th,
|
||||
table.footable > tbody > tr.footable-empty > td,
|
||||
table.footable > tbody > tr.footable-empty > th {
|
||||
display: table-cell;
|
||||
}
|
||||
@-webkit-keyframes fooicon-spin-r {
|
||||
0% {
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@keyframes fooicon-spin-r {
|
||||
0% {
|
||||
-webkit-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
.fooicon {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
display: inline-block;
|
||||
font-family: "bootstrap-icons" !important;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
.fooicon {
|
||||
top: 2px;
|
||||
}
|
||||
}
|
||||
.fooicon:after,
|
||||
.fooicon:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.fooicon-loader:before {
|
||||
content: "\f130";
|
||||
}
|
||||
.fooicon-plus:before {
|
||||
content: "\f4fc";
|
||||
}
|
||||
.fooicon-minus:before {
|
||||
content: "\f2e8";
|
||||
}
|
||||
.fooicon-search:before {
|
||||
content: "\f52a";
|
||||
}
|
||||
.fooicon-remove:before {
|
||||
content: "\f62a";
|
||||
}
|
||||
.fooicon-sort:before {
|
||||
content: "\f3c6";
|
||||
}
|
||||
.fooicon-sort-asc:before {
|
||||
content: "\f575";
|
||||
}
|
||||
.fooicon-sort-desc:before {
|
||||
content: "\f57b";
|
||||
}
|
||||
.fooicon-pencil:before {
|
||||
content: "\f4c9";
|
||||
}
|
||||
.fooicon-trash:before {
|
||||
content: "\f62a";
|
||||
}
|
||||
.fooicon-eye-close:before {
|
||||
content: "\f33f";
|
||||
}
|
||||
.fooicon-flash:before {
|
||||
content: "\f46e";
|
||||
}
|
||||
.fooicon-cog:before {
|
||||
content: "\f3e2";
|
||||
}
|
||||
.fooicon-stats:before {
|
||||
content: "\f359";
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th {
|
||||
border-bottom-width: 1px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.footable-filtering-external.footable-filtering-right,
|
||||
table.footable.footable-filtering-right > thead > tr.footable-filtering > th,
|
||||
table.footable > thead > tr.footable-filtering > th {
|
||||
text-align: right;
|
||||
}
|
||||
.footable-filtering-external.footable-filtering-left,
|
||||
table.footable.footable-filtering-left > thead > tr.footable-filtering > th {
|
||||
text-align: left;
|
||||
}
|
||||
.footable-filtering-external.footable-filtering-center,
|
||||
.footable-paging-external.footable-paging-center,
|
||||
table.footable-paging-center > tfoot > tr.footable-paging > td,
|
||||
table.footable.footable-filtering-center > thead > tr.footable-filtering > th,
|
||||
table.footable > tfoot > tr.footable-paging > td {
|
||||
text-align: center;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group + div.form-group {
|
||||
margin-top: 5px;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.input-group {
|
||||
width: 100%;
|
||||
}
|
||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox,
|
||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox {
|
||||
margin: 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox > label,
|
||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox > label {
|
||||
display: block;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox input[type="checkbox"],
|
||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox input[type="checkbox"] {
|
||||
position: absolute;
|
||||
margin-left: -20px;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
table.footable > thead > tr.footable-filtering > th div.input-group {
|
||||
width: auto;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group + div.form-group {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
table.footable > tbody > tr > td.footable-sortable,
|
||||
table.footable > tbody > tr > th.footable-sortable,
|
||||
table.footable > tfoot > tr > td.footable-sortable,
|
||||
table.footable > tfoot > tr > th.footable-sortable,
|
||||
table.footable > thead > tr > td.footable-sortable,
|
||||
table.footable > thead > tr > th.footable-sortable {
|
||||
position: relative;
|
||||
padding-right: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
td.footable-sortable > span.fooicon,
|
||||
th.footable-sortable > span.fooicon {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 50%;
|
||||
margin-top: -7px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in;
|
||||
}
|
||||
td.footable-sortable.footable-asc > span.fooicon,
|
||||
td.footable-sortable.footable-desc > span.fooicon,
|
||||
td.footable-sortable:hover > span.fooicon,
|
||||
th.footable-sortable.footable-asc > span.fooicon,
|
||||
th.footable-sortable.footable-desc > span.fooicon,
|
||||
th.footable-sortable:hover > span.fooicon {
|
||||
opacity: 1;
|
||||
}
|
||||
table.footable-sorting-disabled td.footable-sortable.footable-asc > span.fooicon,
|
||||
table.footable-sorting-disabled td.footable-sortable.footable-desc > span.fooicon,
|
||||
table.footable-sorting-disabled td.footable-sortable:hover > span.fooicon,
|
||||
table.footable-sorting-disabled th.footable-sortable.footable-asc > span.fooicon,
|
||||
table.footable-sorting-disabled th.footable-sortable.footable-desc > span.fooicon,
|
||||
table.footable-sorting-disabled th.footable-sortable:hover > span.fooicon {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
.footable-paging-external ul.pagination,
|
||||
table.footable > tfoot > tr.footable-paging > td > ul.pagination {
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
.footable-paging-external span.label,
|
||||
table.footable > tfoot > tr.footable-paging > td > span.label {
|
||||
display: inline-block;
|
||||
margin: 0 0 10px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
.footable-paging-external.footable-paging-left,
|
||||
table.footable-paging-left > tfoot > tr.footable-paging > td {
|
||||
text-align: left;
|
||||
}
|
||||
.footable-paging-external.footable-paging-right,
|
||||
table.footable-editing-right td.footable-editing,
|
||||
table.footable-editing-right tr.footable-editing,
|
||||
table.footable-paging-right > tfoot > tr.footable-paging > td {
|
||||
text-align: right;
|
||||
}
|
||||
ul.pagination > li.footable-page {
|
||||
display: none;
|
||||
}
|
||||
ul.pagination > li.footable-page.visible {
|
||||
display: inline;
|
||||
}
|
||||
td.footable-editing {
|
||||
width: 90px;
|
||||
max-width: 90px;
|
||||
}
|
||||
table.footable-editing-no-delete td.footable-editing,
|
||||
table.footable-editing-no-edit td.footable-editing,
|
||||
table.footable-editing-no-view td.footable-editing {
|
||||
width: 70px;
|
||||
max-width: 70px;
|
||||
}
|
||||
table.footable-editing-no-delete.footable-editing-no-view td.footable-editing,
|
||||
table.footable-editing-no-edit.footable-editing-no-delete td.footable-editing,
|
||||
table.footable-editing-no-edit.footable-editing-no-view td.footable-editing {
|
||||
width: 50px;
|
||||
max-width: 50px;
|
||||
}
|
||||
table.footable-editing-no-edit.footable-editing-no-delete.footable-editing-no-view td.footable-editing,
|
||||
table.footable-editing-no-edit.footable-editing-no-delete.footable-editing-no-view th.footable-editing {
|
||||
width: 0;
|
||||
max-width: 0;
|
||||
display: none !important;
|
||||
}
|
||||
table.footable-editing-left td.footable-editing,
|
||||
table.footable-editing-left tr.footable-editing {
|
||||
text-align: left;
|
||||
}
|
||||
table.footable-editing button.footable-add,
|
||||
table.footable-editing button.footable-hide,
|
||||
table.footable-editing-show button.footable-show,
|
||||
table.footable-editing.footable-editing-always-show button.footable-hide,
|
||||
table.footable-editing.footable-editing-always-show button.footable-show,
|
||||
table.footable-editing.footable-editing-always-show.footable-editing-no-add tr.footable-editing {
|
||||
display: none;
|
||||
}
|
||||
table.footable-editing.footable-editing-always-show button.footable-add,
|
||||
table.footable-editing.footable-editing-show button.footable-add,
|
||||
table.footable-editing.footable-editing-show button.footable-hide {
|
||||
display: inline-block;
|
||||
}
|
File diff suppressed because one or more lines are too long
693
data/web/css/build/011-datatables.css
Normal file
693
data/web/css/build/011-datatables.css
Normal file
@ -0,0 +1,693 @@
|
||||
/*
|
||||
* This combined file was created by the DataTables downloader builder:
|
||||
* https://datatables.net/download
|
||||
*
|
||||
* To rebuild or modify this file with the latest versions of the included
|
||||
* software please visit:
|
||||
* https://datatables.net/download/#bs5/dt-1.12.0/r-2.3.0/sl-1.4.0
|
||||
*
|
||||
* Included libraries:
|
||||
* DataTables 1.12.0, Responsive 2.3.0, Select 1.4.0
|
||||
*/
|
||||
|
||||
@charset "UTF-8";
|
||||
table.dataTable td.dt-control {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable td.dt-control:before {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin-top: -9px;
|
||||
display: inline-block;
|
||||
color: white;
|
||||
border: 0.15em solid white;
|
||||
border-radius: 1em;
|
||||
box-shadow: 0 0 0.2em #444;
|
||||
box-sizing: content-box;
|
||||
text-align: center;
|
||||
text-indent: 0 !important;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
line-height: 1em;
|
||||
content: "+";
|
||||
background-color: #31b131;
|
||||
}
|
||||
table.dataTable tr.dt-hasChild td.dt-control:before {
|
||||
content: "-";
|
||||
background-color: #d33333;
|
||||
}
|
||||
|
||||
table.dataTable thead > tr > th.sorting, table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting_asc_disabled, table.dataTable thead > tr > th.sorting_desc_disabled,
|
||||
table.dataTable thead > tr > td.sorting,
|
||||
table.dataTable thead > tr > td.sorting_asc,
|
||||
table.dataTable thead > tr > td.sorting_desc,
|
||||
table.dataTable thead > tr > td.sorting_asc_disabled,
|
||||
table.dataTable thead > tr > td.sorting_desc_disabled {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
padding-right: 26px;
|
||||
}
|
||||
table.dataTable thead > tr > th.sorting:before, table.dataTable thead > tr > th.sorting:after, table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_asc:after, table.dataTable thead > tr > th.sorting_desc:before, table.dataTable thead > tr > th.sorting_desc:after, table.dataTable thead > tr > th.sorting_asc_disabled:before, table.dataTable thead > tr > th.sorting_asc_disabled:after, table.dataTable thead > tr > th.sorting_desc_disabled:before, table.dataTable thead > tr > th.sorting_desc_disabled:after,
|
||||
table.dataTable thead > tr > td.sorting:before,
|
||||
table.dataTable thead > tr > td.sorting:after,
|
||||
table.dataTable thead > tr > td.sorting_asc:before,
|
||||
table.dataTable thead > tr > td.sorting_asc:after,
|
||||
table.dataTable thead > tr > td.sorting_desc:before,
|
||||
table.dataTable thead > tr > td.sorting_desc:after,
|
||||
table.dataTable thead > tr > td.sorting_asc_disabled:before,
|
||||
table.dataTable thead > tr > td.sorting_asc_disabled:after,
|
||||
table.dataTable thead > tr > td.sorting_desc_disabled:before,
|
||||
table.dataTable thead > tr > td.sorting_desc_disabled:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
opacity: 0.125;
|
||||
right: 10px;
|
||||
line-height: 9px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
table.dataTable thead > tr > th.sorting:before, table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_desc:before, table.dataTable thead > tr > th.sorting_asc_disabled:before, table.dataTable thead > tr > th.sorting_desc_disabled:before,
|
||||
table.dataTable thead > tr > td.sorting:before,
|
||||
table.dataTable thead > tr > td.sorting_asc:before,
|
||||
table.dataTable thead > tr > td.sorting_desc:before,
|
||||
table.dataTable thead > tr > td.sorting_asc_disabled:before,
|
||||
table.dataTable thead > tr > td.sorting_desc_disabled:before {
|
||||
bottom: 50%;
|
||||
content: "▴";
|
||||
}
|
||||
table.dataTable thead > tr > th.sorting:after, table.dataTable thead > tr > th.sorting_asc:after, table.dataTable thead > tr > th.sorting_desc:after, table.dataTable thead > tr > th.sorting_asc_disabled:after, table.dataTable thead > tr > th.sorting_desc_disabled:after,
|
||||
table.dataTable thead > tr > td.sorting:after,
|
||||
table.dataTable thead > tr > td.sorting_asc:after,
|
||||
table.dataTable thead > tr > td.sorting_desc:after,
|
||||
table.dataTable thead > tr > td.sorting_asc_disabled:after,
|
||||
table.dataTable thead > tr > td.sorting_desc_disabled:after {
|
||||
top: 50%;
|
||||
content: "▾";
|
||||
}
|
||||
table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_desc:after,
|
||||
table.dataTable thead > tr > td.sorting_asc:before,
|
||||
table.dataTable thead > tr > td.sorting_desc:after {
|
||||
opacity: 0.6;
|
||||
}
|
||||
table.dataTable thead > tr > th.sorting_desc_disabled:after, table.dataTable thead > tr > th.sorting_asc_disabled:before,
|
||||
table.dataTable thead > tr > td.sorting_desc_disabled:after,
|
||||
table.dataTable thead > tr > td.sorting_asc_disabled:before {
|
||||
display: none;
|
||||
}
|
||||
table.dataTable thead > tr > th:active,
|
||||
table.dataTable thead > tr > td:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
div.dataTables_scrollBody table.dataTable thead > tr > th:before, div.dataTables_scrollBody table.dataTable thead > tr > th:after,
|
||||
div.dataTables_scrollBody table.dataTable thead > tr > td:before,
|
||||
div.dataTables_scrollBody table.dataTable thead > tr > td:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.dataTables_processing {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
margin-left: -100px;
|
||||
margin-top: -26px;
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
}
|
||||
div.dataTables_processing > div:last-child {
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 15px;
|
||||
margin: 1em auto;
|
||||
}
|
||||
div.dataTables_processing > div:last-child > div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
border-radius: 50%;
|
||||
background: rgba(13, 110, 253, 0.9);
|
||||
animation-timing-function: cubic-bezier(0, 1, 1, 0);
|
||||
}
|
||||
div.dataTables_processing > div:last-child > div:nth-child(1) {
|
||||
left: 8px;
|
||||
animation: datatables-loader-1 0.6s infinite;
|
||||
}
|
||||
div.dataTables_processing > div:last-child > div:nth-child(2) {
|
||||
left: 8px;
|
||||
animation: datatables-loader-2 0.6s infinite;
|
||||
}
|
||||
div.dataTables_processing > div:last-child > div:nth-child(3) {
|
||||
left: 32px;
|
||||
animation: datatables-loader-2 0.6s infinite;
|
||||
}
|
||||
div.dataTables_processing > div:last-child > div:nth-child(4) {
|
||||
left: 56px;
|
||||
animation: datatables-loader-3 0.6s infinite;
|
||||
}
|
||||
|
||||
@keyframes datatables-loader-1 {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes datatables-loader-3 {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
@keyframes datatables-loader-2 {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate(24px, 0);
|
||||
}
|
||||
}
|
||||
table.dataTable.nowrap th, table.dataTable.nowrap td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
table.dataTable th.dt-left,
|
||||
table.dataTable td.dt-left {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable th.dt-center,
|
||||
table.dataTable td.dt-center,
|
||||
table.dataTable td.dataTables_empty {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable th.dt-right,
|
||||
table.dataTable td.dt-right {
|
||||
text-align: right;
|
||||
}
|
||||
table.dataTable th.dt-justify,
|
||||
table.dataTable td.dt-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
table.dataTable th.dt-nowrap,
|
||||
table.dataTable td.dt-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
table.dataTable thead th,
|
||||
table.dataTable thead td,
|
||||
table.dataTable tfoot th,
|
||||
table.dataTable tfoot td {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable thead th.dt-head-left,
|
||||
table.dataTable thead td.dt-head-left,
|
||||
table.dataTable tfoot th.dt-head-left,
|
||||
table.dataTable tfoot td.dt-head-left {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable thead th.dt-head-center,
|
||||
table.dataTable thead td.dt-head-center,
|
||||
table.dataTable tfoot th.dt-head-center,
|
||||
table.dataTable tfoot td.dt-head-center {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable thead th.dt-head-right,
|
||||
table.dataTable thead td.dt-head-right,
|
||||
table.dataTable tfoot th.dt-head-right,
|
||||
table.dataTable tfoot td.dt-head-right {
|
||||
text-align: right;
|
||||
}
|
||||
table.dataTable thead th.dt-head-justify,
|
||||
table.dataTable thead td.dt-head-justify,
|
||||
table.dataTable tfoot th.dt-head-justify,
|
||||
table.dataTable tfoot td.dt-head-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
table.dataTable thead th.dt-head-nowrap,
|
||||
table.dataTable thead td.dt-head-nowrap,
|
||||
table.dataTable tfoot th.dt-head-nowrap,
|
||||
table.dataTable tfoot td.dt-head-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-left,
|
||||
table.dataTable tbody td.dt-body-left {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-center,
|
||||
table.dataTable tbody td.dt-body-center {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-right,
|
||||
table.dataTable tbody td.dt-body-right {
|
||||
text-align: right;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-justify,
|
||||
table.dataTable tbody td.dt-body-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-nowrap,
|
||||
table.dataTable tbody td.dt-body-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/*! Bootstrap 5 integration for DataTables
|
||||
*
|
||||
* ©2020 SpryMedia Ltd, all rights reserved.
|
||||
* License: MIT datatables.net/license/mit
|
||||
*/
|
||||
table.dataTable {
|
||||
clear: both;
|
||||
margin-top: 6px !important;
|
||||
margin-bottom: 6px !important;
|
||||
max-width: none !important;
|
||||
border-collapse: separate !important;
|
||||
border-spacing: 0;
|
||||
}
|
||||
table.dataTable td,
|
||||
table.dataTable th {
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
table.dataTable td.dataTables_empty,
|
||||
table.dataTable th.dataTables_empty {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable.nowrap th,
|
||||
table.dataTable.nowrap td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) > * {
|
||||
box-shadow: none;
|
||||
}
|
||||
table.dataTable > tbody > tr {
|
||||
background-color: transparent;
|
||||
}
|
||||
table.dataTable > tbody > tr.selected > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.9);
|
||||
color: white;
|
||||
}
|
||||
table.dataTable.table-striped > tbody > tr.odd > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
table.dataTable.table-striped > tbody > tr.odd.selected > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
|
||||
}
|
||||
table.dataTable.table-hover > tbody > tr:hover > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
table.dataTable.table-hover > tbody > tr.selected:hover > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_length label {
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_length select {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter {
|
||||
text-align: right;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter label {
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter input {
|
||||
margin-left: 0.5em;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_info {
|
||||
padding-top: 0.85em;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_paginate {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
|
||||
margin: 2px 0;
|
||||
white-space: nowrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
div.dataTables_scrollHead table.dataTable {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
div.dataTables_scrollBody > table {
|
||||
border-top: none;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
div.dataTables_scrollBody > table > thead .sorting:before,
|
||||
div.dataTables_scrollBody > table > thead .sorting_asc:before,
|
||||
div.dataTables_scrollBody > table > thead .sorting_desc:before,
|
||||
div.dataTables_scrollBody > table > thead .sorting:after,
|
||||
div.dataTables_scrollBody > table > thead .sorting_asc:after,
|
||||
div.dataTables_scrollBody > table > thead .sorting_desc:after {
|
||||
display: none;
|
||||
}
|
||||
div.dataTables_scrollBody > table > tbody tr:first-child th,
|
||||
div.dataTables_scrollBody > table > tbody tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
div.dataTables_scrollFoot > .dataTables_scrollFootInner {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
|
||||
margin-top: 0 !important;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
div.dataTables_wrapper div.dataTables_length,
|
||||
div.dataTables_wrapper div.dataTables_filter,
|
||||
div.dataTables_wrapper div.dataTables_info,
|
||||
div.dataTables_wrapper div.dataTables_paginate {
|
||||
text-align: center;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
table.dataTable.table-sm > thead > tr > th:not(.sorting_disabled) {
|
||||
padding-right: 20px;
|
||||
}
|
||||
table.dataTable.table-sm .sorting:before,
|
||||
table.dataTable.table-sm .sorting_asc:before,
|
||||
table.dataTable.table-sm .sorting_desc:before {
|
||||
top: 5px;
|
||||
right: 0.85em;
|
||||
}
|
||||
table.dataTable.table-sm .sorting:after,
|
||||
table.dataTable.table-sm .sorting_asc:after,
|
||||
table.dataTable.table-sm .sorting_desc:after {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
table.table-bordered.dataTable {
|
||||
border-right-width: 0;
|
||||
}
|
||||
table.table-bordered.dataTable thead tr:first-child th,
|
||||
table.table-bordered.dataTable thead tr:first-child td {
|
||||
border-top-width: 1px;
|
||||
}
|
||||
table.table-bordered.dataTable th,
|
||||
table.table-bordered.dataTable td {
|
||||
border-left-width: 0;
|
||||
}
|
||||
table.table-bordered.dataTable th:first-child, table.table-bordered.dataTable th:first-child,
|
||||
table.table-bordered.dataTable td:first-child,
|
||||
table.table-bordered.dataTable td:first-child {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
|
||||
table.table-bordered.dataTable td:last-child,
|
||||
table.table-bordered.dataTable td:last-child {
|
||||
border-right-width: 1px;
|
||||
}
|
||||
table.table-bordered.dataTable th,
|
||||
table.table-bordered.dataTable td {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
div.dataTables_scrollHead table.table-bordered {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
div.table-responsive > div.dataTables_wrapper > div.row {
|
||||
margin: 0;
|
||||
}
|
||||
div.table-responsive > div.dataTables_wrapper > div.row > div[class^=col-]:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
div.table-responsive > div.dataTables_wrapper > div.row > div[class^=col-]:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td.child,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th.child,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty {
|
||||
cursor: default !important;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td.child:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th.child:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty:before {
|
||||
display: none !important;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
|
||||
top: 50%;
|
||||
left: 5px;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin-top: -9px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
color: white;
|
||||
border: 0.15em solid white;
|
||||
border-radius: 1em;
|
||||
box-shadow: 0 0 0.2em #444;
|
||||
box-sizing: content-box;
|
||||
text-align: center;
|
||||
text-indent: 0 !important;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
line-height: 1em;
|
||||
content: "+";
|
||||
background-color: #0d6efd;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td.dtr-control:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th.dtr-control:before {
|
||||
content: "-";
|
||||
background-color: #d33333;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td.dtr-control,
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th.dtr-control {
|
||||
padding-left: 27px;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td.dtr-control:before,
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th.dtr-control:before {
|
||||
left: 4px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
border-radius: 14px;
|
||||
line-height: 14px;
|
||||
text-indent: 3px;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr > td.dtr-control,
|
||||
table.dataTable.dtr-column > tbody > tr > th.dtr-control,
|
||||
table.dataTable.dtr-column > tbody > tr > td.control,
|
||||
table.dataTable.dtr-column > tbody > tr > th.control {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr > td.dtr-control:before,
|
||||
table.dataTable.dtr-column > tbody > tr > th.dtr-control:before,
|
||||
table.dataTable.dtr-column > tbody > tr > td.control:before,
|
||||
table.dataTable.dtr-column > tbody > tr > th.control:before {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 0.8em;
|
||||
width: 0.8em;
|
||||
margin-top: -0.5em;
|
||||
margin-left: -0.5em;
|
||||
display: block;
|
||||
position: absolute;
|
||||
color: white;
|
||||
border: 0.15em solid white;
|
||||
border-radius: 1em;
|
||||
box-shadow: 0 0 0.2em #444;
|
||||
box-sizing: content-box;
|
||||
text-align: center;
|
||||
text-indent: 0 !important;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
line-height: 1em;
|
||||
content: "+";
|
||||
background-color: #0d6efd;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr.parent td.dtr-control:before,
|
||||
table.dataTable.dtr-column > tbody > tr.parent th.dtr-control:before,
|
||||
table.dataTable.dtr-column > tbody > tr.parent td.control:before,
|
||||
table.dataTable.dtr-column > tbody > tr.parent th.control:before {
|
||||
content: "-";
|
||||
background-color: #d33333;
|
||||
}
|
||||
table.dataTable > tbody > tr.child {
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
table.dataTable > tbody > tr.child:hover {
|
||||
background: transparent !important;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul.dtr-details {
|
||||
display: inline-block;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul.dtr-details > li {
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul.dtr-details > li:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul.dtr-details > li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
table.dataTable > tbody > tr.child span.dtr-title {
|
||||
display: inline-block;
|
||||
min-width: 75px;
|
||||
font-weight: bold;
|
||||
}
|
||||
div.dtr-modal {
|
||||
position: fixed;
|
||||
box-sizing: border-box;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
padding: 10em 1em;
|
||||
}
|
||||
div.dtr-modal div.dtr-modal-display {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
overflow: auto;
|
||||
margin: auto;
|
||||
z-index: 102;
|
||||
overflow: auto;
|
||||
background-color: #f5f5f7;
|
||||
border: 1px solid black;
|
||||
border-radius: 0.5em;
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
div.dtr-modal div.dtr-modal-content {
|
||||
position: relative;
|
||||
padding: 1em;
|
||||
}
|
||||
div.dtr-modal div.dtr-modal-close {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: 1px solid #eaeaea;
|
||||
background-color: #f9f9f9;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
z-index: 12;
|
||||
}
|
||||
div.dtr-modal div.dtr-modal-close:hover {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
div.dtr-modal div.dtr-modal-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 101;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
div.dtr-modal div.dtr-modal-display {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
div.dtr-bs-modal table.table tr:first-child td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
table.dataTable.table-bordered th.dtr-control.dtr-hidden + *,
|
||||
table.dataTable.table-bordered td.dtr-control.dtr-hidden + * {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
|
||||
table.dataTable > tbody > tr > .selected {
|
||||
background-color: rgba(13, 110, 253, 0.9);
|
||||
color: white;
|
||||
}
|
||||
table.dataTable tbody td.select-checkbox,
|
||||
table.dataTable tbody th.select-checkbox {
|
||||
position: relative;
|
||||
}
|
||||
table.dataTable tbody td.select-checkbox:before, table.dataTable tbody td.select-checkbox:after,
|
||||
table.dataTable tbody th.select-checkbox:before,
|
||||
table.dataTable tbody th.select-checkbox:after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 1.2em;
|
||||
left: 50%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
table.dataTable tbody td.select-checkbox:before,
|
||||
table.dataTable tbody th.select-checkbox:before {
|
||||
content: " ";
|
||||
margin-top: -5px;
|
||||
margin-left: -6px;
|
||||
border: 1px solid black;
|
||||
border-radius: 3px;
|
||||
}
|
||||
table.dataTable tr.selected td.select-checkbox:before,
|
||||
table.dataTable tr.selected th.select-checkbox:before {
|
||||
border: 1px solid white;
|
||||
}
|
||||
table.dataTable tr.selected td.select-checkbox:after,
|
||||
table.dataTable tr.selected th.select-checkbox:after {
|
||||
content: "✓";
|
||||
font-size: 20px;
|
||||
margin-top: -19px;
|
||||
margin-left: -6px;
|
||||
text-align: center;
|
||||
text-shadow: 1px 1px #B0BED9, -1px -1px #B0BED9, 1px -1px #B0BED9, -1px 1px #B0BED9;
|
||||
}
|
||||
table.dataTable.compact tbody td.select-checkbox:before,
|
||||
table.dataTable.compact tbody th.select-checkbox:before {
|
||||
margin-top: -12px;
|
||||
}
|
||||
table.dataTable.compact tr.selected td.select-checkbox:after,
|
||||
table.dataTable.compact tr.selected th.select-checkbox:after {
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper span.select-info,
|
||||
div.dataTables_wrapper span.select-item {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
div.dataTables_wrapper span.select-info,
|
||||
div.dataTables_wrapper span.select-item {
|
||||
margin-left: 0;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
table.dataTable.table-sm tbody td.select-checkbox::before {
|
||||
margin-top: -9px;
|
||||
}
|
||||
|
||||
|
1
data/web/css/build/012-Chart.min.css
vendored
1
data/web/css/build/012-Chart.min.css
vendored
@ -1 +0,0 @@
|
||||
@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}
|
@ -1,7 +1,7 @@
|
||||
@font-face {
|
||||
font-family: "bootstrap-icons";
|
||||
src: url("/fonts/bootstrap-icons.woff2?45695e8b569b2b0178db2713ca47065c") format("woff2"),
|
||||
url("/fonts/bootstrap-icons.woff?45695e8b569b2b0178db2713ca47065c") format("woff");
|
||||
src: url("/fonts/bootstrap-icons.woff2?524846017b983fc8ded9325d94ed40f3") format("woff2"),
|
||||
url("/fonts/bootstrap-icons.woff?524846017b983fc8ded9325d94ed40f3") format("woff");
|
||||
}
|
||||
|
||||
.bi::before,
|
||||
@ -19,6 +19,7 @@ url("/fonts/bootstrap-icons.woff?45695e8b569b2b0178db2713ca47065c") format("woff
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.bi-123::before { content: "\f67f"; }
|
||||
.bi-alarm-fill::before { content: "\f101"; }
|
||||
.bi-alarm::before { content: "\f102"; }
|
||||
.bi-align-bottom::before { content: "\f103"; }
|
||||
@ -1425,3 +1426,279 @@ url("/fonts/bootstrap-icons.woff?45695e8b569b2b0178db2713ca47065c") format("woff
|
||||
.bi-webcam-fill::before { content: "\f67c"; }
|
||||
.bi-webcam::before { content: "\f67d"; }
|
||||
.bi-yin-yang::before { content: "\f67e"; }
|
||||
.bi-bandaid-fill::before { content: "\f680"; }
|
||||
.bi-bandaid::before { content: "\f681"; }
|
||||
.bi-bluetooth::before { content: "\f682"; }
|
||||
.bi-body-text::before { content: "\f683"; }
|
||||
.bi-boombox::before { content: "\f684"; }
|
||||
.bi-boxes::before { content: "\f685"; }
|
||||
.bi-dpad-fill::before { content: "\f686"; }
|
||||
.bi-dpad::before { content: "\f687"; }
|
||||
.bi-ear-fill::before { content: "\f688"; }
|
||||
.bi-ear::before { content: "\f689"; }
|
||||
.bi-envelope-check-1::before { content: "\f68a"; }
|
||||
.bi-envelope-check-fill::before { content: "\f68b"; }
|
||||
.bi-envelope-check::before { content: "\f68c"; }
|
||||
.bi-envelope-dash-1::before { content: "\f68d"; }
|
||||
.bi-envelope-dash-fill::before { content: "\f68e"; }
|
||||
.bi-envelope-dash::before { content: "\f68f"; }
|
||||
.bi-envelope-exclamation-1::before { content: "\f690"; }
|
||||
.bi-envelope-exclamation-fill::before { content: "\f691"; }
|
||||
.bi-envelope-exclamation::before { content: "\f692"; }
|
||||
.bi-envelope-plus-fill::before { content: "\f693"; }
|
||||
.bi-envelope-plus::before { content: "\f694"; }
|
||||
.bi-envelope-slash-1::before { content: "\f695"; }
|
||||
.bi-envelope-slash-fill::before { content: "\f696"; }
|
||||
.bi-envelope-slash::before { content: "\f697"; }
|
||||
.bi-envelope-x-1::before { content: "\f698"; }
|
||||
.bi-envelope-x-fill::before { content: "\f699"; }
|
||||
.bi-envelope-x::before { content: "\f69a"; }
|
||||
.bi-explicit-fill::before { content: "\f69b"; }
|
||||
.bi-explicit::before { content: "\f69c"; }
|
||||
.bi-git::before { content: "\f69d"; }
|
||||
.bi-infinity::before { content: "\f69e"; }
|
||||
.bi-list-columns-reverse::before { content: "\f69f"; }
|
||||
.bi-list-columns::before { content: "\f6a0"; }
|
||||
.bi-meta::before { content: "\f6a1"; }
|
||||
.bi-mortorboard-fill::before { content: "\f6a2"; }
|
||||
.bi-mortorboard::before { content: "\f6a3"; }
|
||||
.bi-nintendo-switch::before { content: "\f6a4"; }
|
||||
.bi-pc-display-horizontal::before { content: "\f6a5"; }
|
||||
.bi-pc-display::before { content: "\f6a6"; }
|
||||
.bi-pc-horizontal::before { content: "\f6a7"; }
|
||||
.bi-pc::before { content: "\f6a8"; }
|
||||
.bi-playstation::before { content: "\f6a9"; }
|
||||
.bi-plus-slash-minus::before { content: "\f6aa"; }
|
||||
.bi-projector-fill::before { content: "\f6ab"; }
|
||||
.bi-projector::before { content: "\f6ac"; }
|
||||
.bi-qr-code-scan::before { content: "\f6ad"; }
|
||||
.bi-qr-code::before { content: "\f6ae"; }
|
||||
.bi-quora::before { content: "\f6af"; }
|
||||
.bi-quote::before { content: "\f6b0"; }
|
||||
.bi-robot::before { content: "\f6b1"; }
|
||||
.bi-send-check-fill::before { content: "\f6b2"; }
|
||||
.bi-send-check::before { content: "\f6b3"; }
|
||||
.bi-send-dash-fill::before { content: "\f6b4"; }
|
||||
.bi-send-dash::before { content: "\f6b5"; }
|
||||
.bi-send-exclamation-1::before { content: "\f6b6"; }
|
||||
.bi-send-exclamation-fill::before { content: "\f6b7"; }
|
||||
.bi-send-exclamation::before { content: "\f6b8"; }
|
||||
.bi-send-fill::before { content: "\f6b9"; }
|
||||
.bi-send-plus-fill::before { content: "\f6ba"; }
|
||||
.bi-send-plus::before { content: "\f6bb"; }
|
||||
.bi-send-slash-fill::before { content: "\f6bc"; }
|
||||
.bi-send-slash::before { content: "\f6bd"; }
|
||||
.bi-send-x-fill::before { content: "\f6be"; }
|
||||
.bi-send-x::before { content: "\f6bf"; }
|
||||
.bi-send::before { content: "\f6c0"; }
|
||||
.bi-steam::before { content: "\f6c1"; }
|
||||
.bi-terminal-dash-1::before { content: "\f6c2"; }
|
||||
.bi-terminal-dash::before { content: "\f6c3"; }
|
||||
.bi-terminal-plus::before { content: "\f6c4"; }
|
||||
.bi-terminal-split::before { content: "\f6c5"; }
|
||||
.bi-ticket-detailed-fill::before { content: "\f6c6"; }
|
||||
.bi-ticket-detailed::before { content: "\f6c7"; }
|
||||
.bi-ticket-fill::before { content: "\f6c8"; }
|
||||
.bi-ticket-perforated-fill::before { content: "\f6c9"; }
|
||||
.bi-ticket-perforated::before { content: "\f6ca"; }
|
||||
.bi-ticket::before { content: "\f6cb"; }
|
||||
.bi-tiktok::before { content: "\f6cc"; }
|
||||
.bi-window-dash::before { content: "\f6cd"; }
|
||||
.bi-window-desktop::before { content: "\f6ce"; }
|
||||
.bi-window-fullscreen::before { content: "\f6cf"; }
|
||||
.bi-window-plus::before { content: "\f6d0"; }
|
||||
.bi-window-split::before { content: "\f6d1"; }
|
||||
.bi-window-stack::before { content: "\f6d2"; }
|
||||
.bi-window-x::before { content: "\f6d3"; }
|
||||
.bi-xbox::before { content: "\f6d4"; }
|
||||
.bi-ethernet::before { content: "\f6d5"; }
|
||||
.bi-hdmi-fill::before { content: "\f6d6"; }
|
||||
.bi-hdmi::before { content: "\f6d7"; }
|
||||
.bi-usb-c-fill::before { content: "\f6d8"; }
|
||||
.bi-usb-c::before { content: "\f6d9"; }
|
||||
.bi-usb-fill::before { content: "\f6da"; }
|
||||
.bi-usb-plug-fill::before { content: "\f6db"; }
|
||||
.bi-usb-plug::before { content: "\f6dc"; }
|
||||
.bi-usb-symbol::before { content: "\f6dd"; }
|
||||
.bi-usb::before { content: "\f6de"; }
|
||||
.bi-boombox-fill::before { content: "\f6df"; }
|
||||
.bi-displayport-1::before { content: "\f6e0"; }
|
||||
.bi-displayport::before { content: "\f6e1"; }
|
||||
.bi-gpu-card::before { content: "\f6e2"; }
|
||||
.bi-memory::before { content: "\f6e3"; }
|
||||
.bi-modem-fill::before { content: "\f6e4"; }
|
||||
.bi-modem::before { content: "\f6e5"; }
|
||||
.bi-motherboard-fill::before { content: "\f6e6"; }
|
||||
.bi-motherboard::before { content: "\f6e7"; }
|
||||
.bi-optical-audio-fill::before { content: "\f6e8"; }
|
||||
.bi-optical-audio::before { content: "\f6e9"; }
|
||||
.bi-pci-card::before { content: "\f6ea"; }
|
||||
.bi-router-fill::before { content: "\f6eb"; }
|
||||
.bi-router::before { content: "\f6ec"; }
|
||||
.bi-ssd-fill::before { content: "\f6ed"; }
|
||||
.bi-ssd::before { content: "\f6ee"; }
|
||||
.bi-thunderbolt-fill::before { content: "\f6ef"; }
|
||||
.bi-thunderbolt::before { content: "\f6f0"; }
|
||||
.bi-usb-drive-fill::before { content: "\f6f1"; }
|
||||
.bi-usb-drive::before { content: "\f6f2"; }
|
||||
.bi-usb-micro-fill::before { content: "\f6f3"; }
|
||||
.bi-usb-micro::before { content: "\f6f4"; }
|
||||
.bi-usb-mini-fill::before { content: "\f6f5"; }
|
||||
.bi-usb-mini::before { content: "\f6f6"; }
|
||||
.bi-cloud-haze2::before { content: "\f6f7"; }
|
||||
.bi-device-hdd-fill::before { content: "\f6f8"; }
|
||||
.bi-device-hdd::before { content: "\f6f9"; }
|
||||
.bi-device-ssd-fill::before { content: "\f6fa"; }
|
||||
.bi-device-ssd::before { content: "\f6fb"; }
|
||||
.bi-displayport-fill::before { content: "\f6fc"; }
|
||||
.bi-mortarboard-fill::before { content: "\f6fd"; }
|
||||
.bi-mortarboard::before { content: "\f6fe"; }
|
||||
.bi-terminal-x::before { content: "\f6ff"; }
|
||||
.bi-arrow-through-heart-fill::before { content: "\f700"; }
|
||||
.bi-arrow-through-heart::before { content: "\f701"; }
|
||||
.bi-badge-sd-fill::before { content: "\f702"; }
|
||||
.bi-badge-sd::before { content: "\f703"; }
|
||||
.bi-bag-heart-fill::before { content: "\f704"; }
|
||||
.bi-bag-heart::before { content: "\f705"; }
|
||||
.bi-balloon-fill::before { content: "\f706"; }
|
||||
.bi-balloon-heart-fill::before { content: "\f707"; }
|
||||
.bi-balloon-heart::before { content: "\f708"; }
|
||||
.bi-balloon::before { content: "\f709"; }
|
||||
.bi-box2-fill::before { content: "\f70a"; }
|
||||
.bi-box2-heart-fill::before { content: "\f70b"; }
|
||||
.bi-box2-heart::before { content: "\f70c"; }
|
||||
.bi-box2::before { content: "\f70d"; }
|
||||
.bi-braces-asterisk::before { content: "\f70e"; }
|
||||
.bi-calendar-heart-fill::before { content: "\f70f"; }
|
||||
.bi-calendar-heart::before { content: "\f710"; }
|
||||
.bi-calendar2-heart-fill::before { content: "\f711"; }
|
||||
.bi-calendar2-heart::before { content: "\f712"; }
|
||||
.bi-chat-heart-fill::before { content: "\f713"; }
|
||||
.bi-chat-heart::before { content: "\f714"; }
|
||||
.bi-chat-left-heart-fill::before { content: "\f715"; }
|
||||
.bi-chat-left-heart::before { content: "\f716"; }
|
||||
.bi-chat-right-heart-fill::before { content: "\f717"; }
|
||||
.bi-chat-right-heart::before { content: "\f718"; }
|
||||
.bi-chat-square-heart-fill::before { content: "\f719"; }
|
||||
.bi-chat-square-heart::before { content: "\f71a"; }
|
||||
.bi-clipboard-check-fill::before { content: "\f71b"; }
|
||||
.bi-clipboard-data-fill::before { content: "\f71c"; }
|
||||
.bi-clipboard-fill::before { content: "\f71d"; }
|
||||
.bi-clipboard-heart-fill::before { content: "\f71e"; }
|
||||
.bi-clipboard-heart::before { content: "\f71f"; }
|
||||
.bi-clipboard-minus-fill::before { content: "\f720"; }
|
||||
.bi-clipboard-plus-fill::before { content: "\f721"; }
|
||||
.bi-clipboard-pulse::before { content: "\f722"; }
|
||||
.bi-clipboard-x-fill::before { content: "\f723"; }
|
||||
.bi-clipboard2-check-fill::before { content: "\f724"; }
|
||||
.bi-clipboard2-check::before { content: "\f725"; }
|
||||
.bi-clipboard2-data-fill::before { content: "\f726"; }
|
||||
.bi-clipboard2-data::before { content: "\f727"; }
|
||||
.bi-clipboard2-fill::before { content: "\f728"; }
|
||||
.bi-clipboard2-heart-fill::before { content: "\f729"; }
|
||||
.bi-clipboard2-heart::before { content: "\f72a"; }
|
||||
.bi-clipboard2-minus-fill::before { content: "\f72b"; }
|
||||
.bi-clipboard2-minus::before { content: "\f72c"; }
|
||||
.bi-clipboard2-plus-fill::before { content: "\f72d"; }
|
||||
.bi-clipboard2-plus::before { content: "\f72e"; }
|
||||
.bi-clipboard2-pulse-fill::before { content: "\f72f"; }
|
||||
.bi-clipboard2-pulse::before { content: "\f730"; }
|
||||
.bi-clipboard2-x-fill::before { content: "\f731"; }
|
||||
.bi-clipboard2-x::before { content: "\f732"; }
|
||||
.bi-clipboard2::before { content: "\f733"; }
|
||||
.bi-emoji-kiss-fill::before { content: "\f734"; }
|
||||
.bi-emoji-kiss::before { content: "\f735"; }
|
||||
.bi-envelope-heart-fill::before { content: "\f736"; }
|
||||
.bi-envelope-heart::before { content: "\f737"; }
|
||||
.bi-envelope-open-heart-fill::before { content: "\f738"; }
|
||||
.bi-envelope-open-heart::before { content: "\f739"; }
|
||||
.bi-envelope-paper-fill::before { content: "\f73a"; }
|
||||
.bi-envelope-paper-heart-fill::before { content: "\f73b"; }
|
||||
.bi-envelope-paper-heart::before { content: "\f73c"; }
|
||||
.bi-envelope-paper::before { content: "\f73d"; }
|
||||
.bi-filetype-aac::before { content: "\f73e"; }
|
||||
.bi-filetype-ai::before { content: "\f73f"; }
|
||||
.bi-filetype-bmp::before { content: "\f740"; }
|
||||
.bi-filetype-cs::before { content: "\f741"; }
|
||||
.bi-filetype-css::before { content: "\f742"; }
|
||||
.bi-filetype-csv::before { content: "\f743"; }
|
||||
.bi-filetype-doc::before { content: "\f744"; }
|
||||
.bi-filetype-docx::before { content: "\f745"; }
|
||||
.bi-filetype-exe::before { content: "\f746"; }
|
||||
.bi-filetype-gif::before { content: "\f747"; }
|
||||
.bi-filetype-heic::before { content: "\f748"; }
|
||||
.bi-filetype-html::before { content: "\f749"; }
|
||||
.bi-filetype-java::before { content: "\f74a"; }
|
||||
.bi-filetype-jpg::before { content: "\f74b"; }
|
||||
.bi-filetype-js::before { content: "\f74c"; }
|
||||
.bi-filetype-jsx::before { content: "\f74d"; }
|
||||
.bi-filetype-key::before { content: "\f74e"; }
|
||||
.bi-filetype-m4p::before { content: "\f74f"; }
|
||||
.bi-filetype-md::before { content: "\f750"; }
|
||||
.bi-filetype-mdx::before { content: "\f751"; }
|
||||
.bi-filetype-mov::before { content: "\f752"; }
|
||||
.bi-filetype-mp3::before { content: "\f753"; }
|
||||
.bi-filetype-mp4::before { content: "\f754"; }
|
||||
.bi-filetype-otf::before { content: "\f755"; }
|
||||
.bi-filetype-pdf::before { content: "\f756"; }
|
||||
.bi-filetype-php::before { content: "\f757"; }
|
||||
.bi-filetype-png::before { content: "\f758"; }
|
||||
.bi-filetype-ppt-1::before { content: "\f759"; }
|
||||
.bi-filetype-ppt::before { content: "\f75a"; }
|
||||
.bi-filetype-psd::before { content: "\f75b"; }
|
||||
.bi-filetype-py::before { content: "\f75c"; }
|
||||
.bi-filetype-raw::before { content: "\f75d"; }
|
||||
.bi-filetype-rb::before { content: "\f75e"; }
|
||||
.bi-filetype-sass::before { content: "\f75f"; }
|
||||
.bi-filetype-scss::before { content: "\f760"; }
|
||||
.bi-filetype-sh::before { content: "\f761"; }
|
||||
.bi-filetype-svg::before { content: "\f762"; }
|
||||
.bi-filetype-tiff::before { content: "\f763"; }
|
||||
.bi-filetype-tsx::before { content: "\f764"; }
|
||||
.bi-filetype-ttf::before { content: "\f765"; }
|
||||
.bi-filetype-txt::before { content: "\f766"; }
|
||||
.bi-filetype-wav::before { content: "\f767"; }
|
||||
.bi-filetype-woff::before { content: "\f768"; }
|
||||
.bi-filetype-xls-1::before { content: "\f769"; }
|
||||
.bi-filetype-xls::before { content: "\f76a"; }
|
||||
.bi-filetype-xml::before { content: "\f76b"; }
|
||||
.bi-filetype-yml::before { content: "\f76c"; }
|
||||
.bi-heart-arrow::before { content: "\f76d"; }
|
||||
.bi-heart-pulse-fill::before { content: "\f76e"; }
|
||||
.bi-heart-pulse::before { content: "\f76f"; }
|
||||
.bi-heartbreak-fill::before { content: "\f770"; }
|
||||
.bi-heartbreak::before { content: "\f771"; }
|
||||
.bi-hearts::before { content: "\f772"; }
|
||||
.bi-hospital-fill::before { content: "\f773"; }
|
||||
.bi-hospital::before { content: "\f774"; }
|
||||
.bi-house-heart-fill::before { content: "\f775"; }
|
||||
.bi-house-heart::before { content: "\f776"; }
|
||||
.bi-incognito::before { content: "\f777"; }
|
||||
.bi-magnet-fill::before { content: "\f778"; }
|
||||
.bi-magnet::before { content: "\f779"; }
|
||||
.bi-person-heart::before { content: "\f77a"; }
|
||||
.bi-person-hearts::before { content: "\f77b"; }
|
||||
.bi-phone-flip::before { content: "\f77c"; }
|
||||
.bi-plugin::before { content: "\f77d"; }
|
||||
.bi-postage-fill::before { content: "\f77e"; }
|
||||
.bi-postage-heart-fill::before { content: "\f77f"; }
|
||||
.bi-postage-heart::before { content: "\f780"; }
|
||||
.bi-postage::before { content: "\f781"; }
|
||||
.bi-postcard-fill::before { content: "\f782"; }
|
||||
.bi-postcard-heart-fill::before { content: "\f783"; }
|
||||
.bi-postcard-heart::before { content: "\f784"; }
|
||||
.bi-postcard::before { content: "\f785"; }
|
||||
.bi-search-heart-fill::before { content: "\f786"; }
|
||||
.bi-search-heart::before { content: "\f787"; }
|
||||
.bi-sliders2-vertical::before { content: "\f788"; }
|
||||
.bi-sliders2::before { content: "\f789"; }
|
||||
.bi-trash3-fill::before { content: "\f78a"; }
|
||||
.bi-trash3::before { content: "\f78b"; }
|
||||
.bi-valentine::before { content: "\f78c"; }
|
||||
.bi-valentine2::before { content: "\f78d"; }
|
||||
.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; }
|
||||
.bi-wrench-adjustable-circle::before { content: "\f78f"; }
|
||||
.bi-wrench-adjustable::before { content: "\f790"; }
|
||||
.bi-filetype-json::before { content: "\f791"; }
|
||||
.bi-filetype-pptx::before { content: "\f792"; }
|
||||
.bi-filetype-xlsx::before { content: "\f793"; }
|
@ -63,6 +63,12 @@
|
||||
.navbar-nav {
|
||||
margin: 0;
|
||||
}
|
||||
.navbar-nav .nav-link {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 10px;
|
||||
}
|
||||
.navbar-fixed-bottom .navbar-collapse,
|
||||
.navbar-fixed-top .navbar-collapse {
|
||||
max-height: 1000px
|
||||
@ -75,6 +81,12 @@
|
||||
display: inline-block;
|
||||
font-size: inherit;
|
||||
}
|
||||
.btn-group-xs > .btn, .btn-xs {
|
||||
padding: .25rem .4rem;
|
||||
font-size: .875rem;
|
||||
line-height: 1rem;
|
||||
border-radius: .2rem;
|
||||
}
|
||||
.icon-spin {
|
||||
animation-name: spin;
|
||||
animation-duration: 2000ms;
|
||||
@ -106,12 +118,6 @@
|
||||
}
|
||||
}
|
||||
pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;}
|
||||
.footable-sortable {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
/* Fix modal moving content left */
|
||||
body.modal-open {
|
||||
overflow: inherit;
|
||||
@ -166,19 +172,11 @@ legend {
|
||||
top: 0; right: 0; bottom: 0; left: 0;
|
||||
opacity: 0.7;
|
||||
}
|
||||
#top {
|
||||
padding-top: 70px;
|
||||
}
|
||||
.bootstrap-select.btn-group .no-results {
|
||||
display: none;
|
||||
}
|
||||
.dropdown-desc {
|
||||
display: block;
|
||||
padding: 3px 10px;
|
||||
clear: both;
|
||||
font-weight: bold;
|
||||
color: #5a5a5a;
|
||||
white-space: nowrap;
|
||||
.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary {
|
||||
color: rgb(197, 197, 197) !important;
|
||||
}
|
||||
.haveibeenpwned {
|
||||
cursor: pointer;
|
||||
@ -206,7 +204,7 @@ legend {
|
||||
flex-direction: column;
|
||||
}
|
||||
.footer .version {
|
||||
margin-left: auto;
|
||||
margin-left: auto;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.slave-info {
|
||||
@ -225,16 +223,9 @@ legend {
|
||||
.btn-input-missing:active:hover,
|
||||
.btn-input-missing:active:focus {
|
||||
color: #000 !important;
|
||||
background-color: #ff4136;
|
||||
background-color: rgba(255, 65, 54, 0.2);
|
||||
border-color: #ff291c;
|
||||
}
|
||||
table.footable>tbody>tr.footable-empty>td {
|
||||
font-style:italic;
|
||||
font-size: 1rem;
|
||||
}
|
||||
table>tbody>tr>td>span.footable-toggle {
|
||||
opacity: 0.75;
|
||||
}
|
||||
.navbar-nav > li {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
@ -259,6 +250,23 @@ code {
|
||||
.flag-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.dropdown-header {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dataTables_info {
|
||||
margin: 15px 0 !important;
|
||||
padding: 0px !important;
|
||||
}
|
||||
.dataTables_paginate, .dataTables_length, .dataTables_filter {
|
||||
margin: 15px 0 !important;
|
||||
}
|
||||
.dtr-details {
|
||||
width: 100%;
|
||||
}
|
||||
.dtr-title {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
display: flex;
|
||||
@ -296,4 +304,3 @@ code {
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
@ -1,7 +1,3 @@
|
||||
.space20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn-xs-lg>.lang-sm:after {
|
||||
margin-left: 4px;
|
||||
}
|
||||
@ -10,110 +6,67 @@
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.panel-login .apps .btn {
|
||||
.card-login .apps .btn {
|
||||
width: auto;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
margin-top: auto;
|
||||
}
|
||||
.panel-login .apps .btn:hover {
|
||||
.card-login .apps .btn:hover {
|
||||
margin-top: 1px !important;
|
||||
border-bottom-width: 3px;
|
||||
}
|
||||
|
||||
.responsive-tabs .nav-tabs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dataTables_paginate.paging_simple_numbers .pagination {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.responsive-tabs .nav-tabs {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.responsive-tabs .card .card-body.collapse {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.panel-login .apps .btn {
|
||||
.responsive-tabs .tab-pane {
|
||||
display: block !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.card-login .apps .btn {
|
||||
width: 100%;
|
||||
float: none;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.panel-login .apps .btn {
|
||||
.card-login .apps .btn {
|
||||
border-bottom-width: 4px;
|
||||
}
|
||||
|
||||
.media-clearfix::after {
|
||||
clear: both;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.media-clearfix::before {
|
||||
display: table;
|
||||
content: " ";
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.xs-show {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.js-tabcollapse-panel-group .panel{
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.js-tabcollapse-panel-group .panel-body {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.js-tabcollapse-panel-group .js-tabcollapse-panel-body .panel-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.js-tabcollapse-panel-body .panel-heading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.js-tabcollapse-panel-body .well,
|
||||
.panel-body .form-inline.well {
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.js-tabcollapse-panel-heading {
|
||||
display: block;
|
||||
height: 37px;
|
||||
line-height: 37px;
|
||||
text-indent: 15px;
|
||||
}
|
||||
.js-tabcollapse-panel-heading:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.js-tabcollapse-panel-heading {
|
||||
position: relative;
|
||||
}
|
||||
.js-tabcollapse-panel-heading:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
right: 17px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 2px;
|
||||
vertical-align: middle;
|
||||
border-bottom: 4px dashed;
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
}
|
||||
.js-tabcollapse-panel-heading.collapsed:after {
|
||||
border-bottom: none;
|
||||
border-top: 4px dashed;
|
||||
}
|
||||
|
||||
.recent-login-success {
|
||||
font-size: 14px;
|
||||
margin-top: 10px !important;
|
||||
font-size: 14px;
|
||||
margin-top: 10px !important;
|
||||
}
|
||||
.pull-xs-right {
|
||||
float: right !important;
|
||||
}
|
||||
.pull-xs-right .dropdown-menu {
|
||||
right: 0;
|
||||
left: auto;
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
.text-xs-left {
|
||||
text-align: left;
|
||||
@ -125,36 +78,29 @@
|
||||
font-weight: normal;
|
||||
text-align: justify;
|
||||
}
|
||||
.help-block {
|
||||
text-align: justify;
|
||||
}
|
||||
.btn.visible-xs-block {
|
||||
.btn.d-block {
|
||||
width: 100%;
|
||||
float: none;
|
||||
white-space: normal;
|
||||
}
|
||||
.btn-group.footable-actions .btn.btn-xs-half,
|
||||
.btn.visible-xs-block.btn-xs-half {
|
||||
.btn.btn-xs-half,
|
||||
.btn.d-block.btn-xs-half {
|
||||
width: 50%;
|
||||
float: left;
|
||||
}
|
||||
.btn-group.footable-actions .btn.btn-xs-third,
|
||||
.btn.visible-xs-block.btn-xs-third {
|
||||
.btn.btn-xs-third,
|
||||
.btn.d-block.btn-xs-third {
|
||||
width: 33.33%;
|
||||
float: left;
|
||||
}
|
||||
.btn-group.footable-actions .btn.btn-xs-quart,
|
||||
.btn.visible-xs-block.btn-xs-quart {
|
||||
.btn.btn-xs-quart,
|
||||
.btn.d-block.btn-xs-quart {
|
||||
width: 25%;
|
||||
float: left;
|
||||
}
|
||||
.btn.visible-xs-block.btn-sm,
|
||||
.btn.d-block.btn-sm,
|
||||
.btn-xs-lg {
|
||||
padding: 15px 16px 13px;
|
||||
line-height: 15px;
|
||||
padding: .5rem 1rem;
|
||||
line-height: 20px;
|
||||
}
|
||||
.input-xs-lg {
|
||||
height: 47px;
|
||||
height: 47px;
|
||||
padding: 13px 16px;
|
||||
}
|
||||
.btn-group:not(.input-group-btn) {
|
||||
@ -167,27 +113,27 @@
|
||||
.btn-group.nowrap .dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
.panel-login .btn-group {
|
||||
.card-login .btn-group {
|
||||
display: block;
|
||||
}
|
||||
.mass-actions-user .btn-group {
|
||||
float: none;
|
||||
}
|
||||
div[class^='mass-actions'] .dropdown-menu,
|
||||
.panel-xs-lg .dropdown-menu,
|
||||
.card-xs-lg .dropdown-menu,
|
||||
.dropdown-menu.login {
|
||||
width: 100%;
|
||||
}
|
||||
div[class^='mass-actions'] .btn-group .dropdown-menu {
|
||||
top: 50%;
|
||||
top: 50%;
|
||||
}
|
||||
div[class^='mass-actions'] .btn-group .btn-group .dropdown-menu,
|
||||
div.mass-actions-quarantine .btn-group .dropdown-menu,
|
||||
.panel-xs-lg .dropdown-menu {
|
||||
.card-xs-lg .dropdown-menu {
|
||||
top: 100%;
|
||||
}
|
||||
div[class^='mass-actions'] .dropdown-menu>li>a,
|
||||
.panel-xs-lg .dropdown-menu>li>a,
|
||||
.card-xs-lg .dropdown-menu>li>a,
|
||||
.dropdown-menu.login>li>a {
|
||||
padding: 8px 20px;
|
||||
}
|
||||
@ -195,9 +141,6 @@
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.space20 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.top100 {
|
||||
top: 100% !important;
|
||||
}
|
||||
@ -210,34 +153,17 @@
|
||||
.btn-xs-lg>.lang-sm:after {
|
||||
top: 1px;
|
||||
}
|
||||
table.footable>tfoot>tr.footable-paging>td {
|
||||
text-align: left;
|
||||
}
|
||||
.footable-first-visible {
|
||||
min-width: 55px;
|
||||
}
|
||||
table>tbody>tr>td>span.footable-toggle {
|
||||
font-size: 24px;
|
||||
margin-right: 14px !important;
|
||||
}
|
||||
table>tbody>tr>td>span.footable-toggle + input {
|
||||
position: absolute;
|
||||
left: 38px;
|
||||
}
|
||||
.pagination {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
tr.footable-filtering>th>form {
|
||||
width: 270px;
|
||||
}
|
||||
.mass-actions-mailbox {
|
||||
padding: 0;
|
||||
}
|
||||
.panel-xs-lg .panel-heading {
|
||||
.card-xs-lg .card-header {
|
||||
height: 66px;
|
||||
line-height: 47px;
|
||||
}
|
||||
.panel-xs-lg .btn-group .btn {
|
||||
.card-xs-lg .btn-group .btn {
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
@ -250,55 +176,29 @@
|
||||
.bootstrap-select {
|
||||
max-width: 100%;
|
||||
}
|
||||
.img-responsive {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.btn-group.footable-actions {
|
||||
position: absolute;
|
||||
width: 90vw !important;
|
||||
left: 0;
|
||||
height: 36px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
.btn-group.footable-actions .btn {
|
||||
padding: 10px 16px 7px;
|
||||
line-height: 15px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.btn-group.footable-actions:after {
|
||||
content: "";
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text {
|
||||
margin-right: 14px;
|
||||
white-space: normal;
|
||||
}
|
||||
.clearfix {
|
||||
flex-basis: 100%;
|
||||
height: 0;
|
||||
}
|
||||
.btn-group > .btn-group {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
.btn-group .btn {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.btn-group .btn i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.btn-group .btn .caret {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.panel-login .btn-group .btn {
|
||||
.card-login .btn-group .btn {
|
||||
display: block !important;
|
||||
}
|
||||
.panel-login .clearfix {
|
||||
height: auto;
|
||||
|
||||
.dt-sm-head-hidden .dtr-title {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
|
11427
data/web/css/themes/cerulean-bootstrap.css
Normal file
11427
data/web/css/themes/cerulean-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
10997
data/web/css/themes/cosmo-bootstrap.css
Normal file
10997
data/web/css/themes/cosmo-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11411
data/web/css/themes/cyborg-bootstrap.css
Normal file
11411
data/web/css/themes/cyborg-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11348
data/web/css/themes/darkly-bootstrap.css
Normal file
11348
data/web/css/themes/darkly-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11340
data/web/css/themes/flatly-bootstrap.css
Normal file
11340
data/web/css/themes/flatly-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11312
data/web/css/themes/journal-bootstrap.css
Normal file
11312
data/web/css/themes/journal-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11433
data/web/css/themes/litera-bootstrap.css
Normal file
11433
data/web/css/themes/litera-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11560
data/web/css/themes/lumen-bootstrap.css
Normal file
11560
data/web/css/themes/lumen-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11108
data/web/css/themes/lux-bootstrap.css
Normal file
11108
data/web/css/themes/lux-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
12431
data/web/css/themes/materia-bootstrap.css
Normal file
12431
data/web/css/themes/materia-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11386
data/web/css/themes/minty-bootstrap.css
Normal file
11386
data/web/css/themes/minty-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11949
data/web/css/themes/morph-bootstrap.css
Normal file
11949
data/web/css/themes/morph-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11077
data/web/css/themes/pulse-bootstrap.css
Normal file
11077
data/web/css/themes/pulse-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11813
data/web/css/themes/quartz-bootstrap.css
Normal file
11813
data/web/css/themes/quartz-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11093
data/web/css/themes/regent-bootstrap.css
Normal file
11093
data/web/css/themes/regent-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11400
data/web/css/themes/sandstone-bootstrap.css
Normal file
11400
data/web/css/themes/sandstone-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11384
data/web/css/themes/simplex-bootstrap.css
Normal file
11384
data/web/css/themes/simplex-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11628
data/web/css/themes/sketchy-bootstrap.css
Normal file
11628
data/web/css/themes/sketchy-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11569
data/web/css/themes/slate-bootstrap.css
Normal file
11569
data/web/css/themes/slate-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11345
data/web/css/themes/solar-bootstrap.css
Normal file
11345
data/web/css/themes/solar-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11465
data/web/css/themes/spacelab-bootstrap.css
Normal file
11465
data/web/css/themes/spacelab-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11405
data/web/css/themes/superhero-bootstrap.css
Normal file
11405
data/web/css/themes/superhero-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11274
data/web/css/themes/united-bootstrap.css
Normal file
11274
data/web/css/themes/united-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11746
data/web/css/themes/vapor-bootstrap.css
Normal file
11746
data/web/css/themes/vapor-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11533
data/web/css/themes/yeti-bootstrap.css
Normal file
11533
data/web/css/themes/yeti-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
11458
data/web/css/themes/zephyr-bootstrap.css
Normal file
11458
data/web/css/themes/zephyr-bootstrap.css
Normal file
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,7 @@ $template_data = [
|
||||
'clamd_status' => $clamd_status,
|
||||
'containers' => $containers,
|
||||
'lang_admin' => json_encode($lang['admin']),
|
||||
'lang_datatables' => json_encode($lang['datatables']),
|
||||
];
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
|
@ -189,5 +189,6 @@ $js_minifier->add('/web/js/site/pwgen.js');
|
||||
$template_data['result'] = $result;
|
||||
$template_data['return_to'] = $_SESSION['return_to'];
|
||||
$template_data['lang_user'] = json_encode($lang['user']);
|
||||
$template_data['lang_datatables'] = json_encode($lang['datatables']);
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
|
Binary file not shown.
Binary file not shown.
@ -116,6 +116,21 @@ function customize($_action, $_item, $_data = null) {
|
||||
$ui_announcement_text = $_data['ui_announcement_text'];
|
||||
$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));
|
||||
@ -125,6 +140,7 @@ 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(
|
||||
@ -228,6 +244,19 @@ 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();
|
||||
|
@ -39,7 +39,6 @@ $globalVariables = [
|
||||
'dual_login' => @$_SESSION['dual-login'],
|
||||
'ui_texts' => $UI_TEXTS,
|
||||
'css_path' => '/cache/'.basename($CSSPath),
|
||||
'theme' => strtolower(trim($DEFAULT_THEME)),
|
||||
'logo' => customize('get', 'main_logo'),
|
||||
'available_languages' => $AVAILABLE_LANGUAGES,
|
||||
'lang' => $lang,
|
||||
|
@ -44,21 +44,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/CSSminifierExtended.php';
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/array_merge_real.php';
|
||||
|
||||
// Minify JS
|
||||
use MatthiasMullie\Minify;
|
||||
$js_minifier = new JSminifierExtended();
|
||||
$js_dir = array_diff(scandir('/web/js/build'), array('..', '.'));
|
||||
foreach ($js_dir as $js_file) {
|
||||
$js_minifier->add('/web/js/build/' . $js_file);
|
||||
}
|
||||
|
||||
// Minify CSS
|
||||
$css_minifier = new CSSminifierExtended();
|
||||
$css_dir = array_diff(scandir('/web/css/build'), array('..', '.'));
|
||||
foreach ($css_dir as $css_file) {
|
||||
$css_minifier->add('/web/css/build/' . $css_file);
|
||||
}
|
||||
|
||||
// U2F API + T/HOTP API
|
||||
// u2f - deprecated, should be removed
|
||||
$u2f = new u2flib_server\U2F('https://' . $_SERVER['HTTP_HOST']);
|
||||
@ -221,6 +206,7 @@ if(file_exists($langFile)) {
|
||||
$lang = array_merge_real($lang, json_decode(file_get_contents($langFile), true));
|
||||
}
|
||||
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.acl.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.admin.inc.php';
|
||||
@ -255,4 +241,28 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
// }
|
||||
acl('to_session');
|
||||
}
|
||||
|
||||
// init frontend
|
||||
// Minify JS
|
||||
use MatthiasMullie\Minify;
|
||||
$js_minifier = new JSminifierExtended();
|
||||
$js_dir = array_diff(scandir('/web/js/build'), array('..', '.'));
|
||||
// Minify CSS
|
||||
$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');
|
||||
else
|
||||
$css_minifier->add('/web/css/themes/lumen-bootstrap.css');
|
||||
// minify css build files
|
||||
foreach ($css_dir as $css_file) {
|
||||
$css_minifier->add('/web/css/build/' . $css_file);
|
||||
}
|
||||
// minify js build files
|
||||
foreach ($js_dir as $js_file) {
|
||||
$js_minifier->add('/web/js/build/' . $js_file);
|
||||
}
|
||||
|
@ -104,13 +104,6 @@ $AVAILABLE_LANGUAGES = array(
|
||||
'zh' => '中文 (Chinese)'
|
||||
);
|
||||
|
||||
// Change theme (default: lumen)
|
||||
// Needs to be one of those: cerulean, cosmo, cyborg, darkly, flatly, journal, lumen, paper, readable, sandstone,
|
||||
// simplex, slate, spacelab, superhero, united, yeti
|
||||
// See https://bootswatch.com/
|
||||
// WARNING: Only lumen is loaded locally. Enabling any other theme, will download external sources.
|
||||
$DEFAULT_THEME = 'lumen';
|
||||
|
||||
// Show DKIM private keys - false by default
|
||||
$SHOW_DKIM_PRIV_KEYS = false;
|
||||
|
||||
|
2
data/web/js/build/000-jquery-3.6.0.min.js
vendored
Normal file
2
data/web/js/build/000-jquery-3.6.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
data/web/js/build/000-jquery.min.js
vendored
4
data/web/js/build/000-jquery.min.js
vendored
File diff suppressed because one or more lines are too long
7
data/web/js/build/001-bootstrap.bundle.min.js
vendored
Normal file
7
data/web/js/build/001-bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
data/web/js/build/001-bootstrap.min.js
vendored
7
data/web/js/build/001-bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
3583
data/web/js/build/004-bootstrap-select.js
Normal file
3583
data/web/js/build/004-bootstrap-select.js
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
2
data/web/js/build/006-notifications.min.js
vendored
2
data/web/js/build/006-notifications.min.js
vendored
File diff suppressed because one or more lines are too long
7
data/web/js/build/008-Chart.min.js
vendored
7
data/web/js/build/008-Chart.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
13269
data/web/js/build/008-chart.js
Normal file
13269
data/web/js/build/008-chart.js
Normal file
File diff suppressed because it is too large
Load Diff
7
data/web/js/build/008-chartjs-plugin-datalabels.js
Normal file
7
data/web/js/build/008-chartjs-plugin-datalabels.js
Normal file
File diff suppressed because one or more lines are too long
18694
data/web/js/build/011-datatables.js
Normal file
18694
data/web/js/build/011-datatables.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,778 +0,0 @@
|
||||
//Copyright 2014-2015 Google Inc. All rights reserved.
|
||||
|
||||
//Use of this source code is governed by a BSD-style
|
||||
//license that can be found in the LICENSE file or at
|
||||
//https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
// ref: https://github.com/google/u2f-ref-code/blob/master/u2f-gae-demo/war/js/u2f-api.js
|
||||
|
||||
/**
|
||||
* @fileoverview The U2F api.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Modification:
|
||||
* Wrap implementation so that we can exit if window.u2f is already supplied by the browser (see below).
|
||||
*/
|
||||
(function (root) {
|
||||
/**
|
||||
* Modification:
|
||||
* Only continue load this library if window.u2f is not already supplied by the browser.
|
||||
*/
|
||||
var browserImplementsU2f = !!((typeof root.u2f !== 'undefined') && root.u2f.register);
|
||||
|
||||
if (browserImplementsU2f) {
|
||||
root.u2f.isSupported = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Namespace for the U2F api.
|
||||
* @type {Object}
|
||||
*/
|
||||
var u2f = root.u2f || {};
|
||||
|
||||
/**
|
||||
* Modification:
|
||||
* Check if browser supports U2F API before this wrapper was added.
|
||||
*/
|
||||
u2f.isSupported = !!(((typeof u2f !== 'undefined') && u2f.register) || ((typeof chrome !== 'undefined') && chrome.runtime));
|
||||
|
||||
/**
|
||||
* FIDO U2F Javascript API Version
|
||||
* @number
|
||||
*/
|
||||
var js_api_version;
|
||||
|
||||
/**
|
||||
* The U2F extension id
|
||||
* @const {string}
|
||||
*/
|
||||
// The Chrome packaged app extension ID.
|
||||
// Uncomment this if you want to deploy a server instance that uses
|
||||
// the package Chrome app and does not require installing the U2F Chrome extension.
|
||||
u2f.EXTENSION_ID = 'kmendfapggjehodndflmmgagdbamhnfd';
|
||||
// The U2F Chrome extension ID.
|
||||
// Uncomment this if you want to deploy a server instance that uses
|
||||
// the U2F Chrome extension to authenticate.
|
||||
// u2f.EXTENSION_ID = 'pfboblefjcgdjicmnffhdgionmgcdmne';
|
||||
|
||||
|
||||
/**
|
||||
* Message types for messsages to/from the extension
|
||||
* @const
|
||||
* @enum {string}
|
||||
*/
|
||||
u2f.MessageTypes = {
|
||||
'U2F_REGISTER_REQUEST': 'u2f_register_request',
|
||||
'U2F_REGISTER_RESPONSE': 'u2f_register_response',
|
||||
'U2F_SIGN_REQUEST': 'u2f_sign_request',
|
||||
'U2F_SIGN_RESPONSE': 'u2f_sign_response',
|
||||
'U2F_GET_API_VERSION_REQUEST': 'u2f_get_api_version_request',
|
||||
'U2F_GET_API_VERSION_RESPONSE': 'u2f_get_api_version_response'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Response status codes
|
||||
* @const
|
||||
* @enum {number}
|
||||
*/
|
||||
u2f.ErrorCodes = {
|
||||
'OK': 0,
|
||||
'OTHER_ERROR': 1,
|
||||
'BAD_REQUEST': 2,
|
||||
'CONFIGURATION_UNSUPPORTED': 3,
|
||||
'DEVICE_INELIGIBLE': 4,
|
||||
'TIMEOUT': 5
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A message for registration requests
|
||||
* @typedef {{
|
||||
* type: u2f.MessageTypes,
|
||||
* appId: ?string,
|
||||
* timeoutSeconds: ?number,
|
||||
* requestId: ?number
|
||||
* }}
|
||||
*/
|
||||
u2f.U2fRequest;
|
||||
|
||||
|
||||
/**
|
||||
* A message for registration responses
|
||||
* @typedef {{
|
||||
* type: u2f.MessageTypes,
|
||||
* responseData: (u2f.Error | u2f.RegisterResponse | u2f.SignResponse),
|
||||
* requestId: ?number
|
||||
* }}
|
||||
*/
|
||||
u2f.U2fResponse;
|
||||
|
||||
|
||||
/**
|
||||
* An error object for responses
|
||||
* @typedef {{
|
||||
* errorCode: u2f.ErrorCodes,
|
||||
* errorMessage: ?string
|
||||
* }}
|
||||
*/
|
||||
u2f.Error;
|
||||
|
||||
/**
|
||||
* Data object for a single sign request.
|
||||
* @typedef {enum {BLUETOOTH_RADIO, BLUETOOTH_LOW_ENERGY, USB, NFC}}
|
||||
*/
|
||||
u2f.Transport;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a single sign request.
|
||||
* @typedef {Array<u2f.Transport>}
|
||||
*/
|
||||
u2f.Transports;
|
||||
|
||||
/**
|
||||
* Data object for a single sign request.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* challenge: string,
|
||||
* keyHandle: string,
|
||||
* appId: string
|
||||
* }}
|
||||
*/
|
||||
u2f.SignRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a sign response.
|
||||
* @typedef {{
|
||||
* keyHandle: string,
|
||||
* signatureData: string,
|
||||
* clientData: string
|
||||
* }}
|
||||
*/
|
||||
u2f.SignResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a registration request.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* challenge: string
|
||||
* }}
|
||||
*/
|
||||
u2f.RegisterRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a registration response.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* keyHandle: string,
|
||||
* transports: Transports,
|
||||
* appId: string
|
||||
* }}
|
||||
*/
|
||||
u2f.RegisterResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a registered key.
|
||||
* @typedef {{
|
||||
* version: string,
|
||||
* keyHandle: string,
|
||||
* transports: ?Transports,
|
||||
* appId: ?string
|
||||
* }}
|
||||
*/
|
||||
u2f.RegisteredKey;
|
||||
|
||||
|
||||
/**
|
||||
* Data object for a get API register response.
|
||||
* @typedef {{
|
||||
* js_api_version: number
|
||||
* }}
|
||||
*/
|
||||
u2f.GetJsApiVersionResponse;
|
||||
|
||||
|
||||
//Low level MessagePort API support
|
||||
|
||||
/**
|
||||
* Sets up a MessagePort to the U2F extension using the
|
||||
* available mechanisms.
|
||||
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
|
||||
*/
|
||||
u2f.getMessagePort = function (callback) {
|
||||
if (typeof chrome != 'undefined' && chrome.runtime) {
|
||||
// The actual message here does not matter, but we need to get a reply
|
||||
// for the callback to run. Thus, send an empty signature request
|
||||
// in order to get a failure response.
|
||||
var msg = {
|
||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
||||
signRequests: []
|
||||
};
|
||||
chrome.runtime.sendMessage(u2f.EXTENSION_ID, msg, function () {
|
||||
if (!chrome.runtime.lastError) {
|
||||
// We are on a whitelisted origin and can talk directly
|
||||
// with the extension.
|
||||
u2f.getChromeRuntimePort_(callback);
|
||||
} else {
|
||||
// chrome.runtime was available, but we couldn't message
|
||||
// the extension directly, use iframe
|
||||
u2f.getIframePort_(callback);
|
||||
}
|
||||
});
|
||||
} else if (u2f.isAndroidChrome_()) {
|
||||
u2f.getAuthenticatorPort_(callback);
|
||||
} else if (u2f.isIosChrome_()) {
|
||||
u2f.getIosPort_(callback);
|
||||
} else {
|
||||
// chrome.runtime was not available at all, which is normal
|
||||
// when this origin doesn't have access to any extensions.
|
||||
u2f.getIframePort_(callback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Detect chrome running on android based on the browser's useragent.
|
||||
* @private
|
||||
*/
|
||||
u2f.isAndroidChrome_ = function () {
|
||||
var userAgent = navigator.userAgent;
|
||||
return userAgent.indexOf('Chrome') != -1 &&
|
||||
userAgent.indexOf('Android') != -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Detect chrome running on iOS based on the browser's platform.
|
||||
* @private
|
||||
*/
|
||||
u2f.isIosChrome_ = function () {
|
||||
return ["iPhone", "iPad", "iPod"].indexOf(navigator.platform) > -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Connects directly to the extension via chrome.runtime.connect.
|
||||
* @param {function(u2f.WrappedChromeRuntimePort_)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getChromeRuntimePort_ = function (callback) {
|
||||
var port = chrome.runtime.connect(u2f.EXTENSION_ID,
|
||||
{ 'includeTlsChannelId': true });
|
||||
setTimeout(function () {
|
||||
callback(new u2f.WrappedChromeRuntimePort_(port));
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a 'port' abstraction to the Authenticator app.
|
||||
* @param {function(u2f.WrappedAuthenticatorPort_)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getAuthenticatorPort_ = function (callback) {
|
||||
setTimeout(function () {
|
||||
callback(new u2f.WrappedAuthenticatorPort_());
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a 'port' abstraction to the iOS client app.
|
||||
* @param {function(u2f.WrappedIosPort_)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getIosPort_ = function (callback) {
|
||||
setTimeout(function () {
|
||||
callback(new u2f.WrappedIosPort_());
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* A wrapper for chrome.runtime.Port that is compatible with MessagePort.
|
||||
* @param {Port} port
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedChromeRuntimePort_ = function (port) {
|
||||
this.port_ = port;
|
||||
};
|
||||
|
||||
/**
|
||||
* Format and return a sign request compliant with the JS API version supported by the extension.
|
||||
* @param {Array<u2f.SignRequest>} signRequests
|
||||
* @param {number} timeoutSeconds
|
||||
* @param {number} reqId
|
||||
* @return {Object}
|
||||
*/
|
||||
u2f.formatSignRequest_ =
|
||||
function (appId, challenge, registeredKeys, timeoutSeconds, reqId) {
|
||||
if (js_api_version === undefined || js_api_version < 1.1) {
|
||||
// Adapt request to the 1.0 JS API
|
||||
var signRequests = [];
|
||||
for (var i = 0; i < registeredKeys.length; i++) {
|
||||
signRequests[i] = {
|
||||
version: registeredKeys[i].version,
|
||||
challenge: challenge,
|
||||
keyHandle: registeredKeys[i].keyHandle,
|
||||
appId: appId
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
||||
signRequests: signRequests,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
}
|
||||
// JS 1.1 API
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
||||
appId: appId,
|
||||
challenge: challenge,
|
||||
registeredKeys: registeredKeys,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Format and return a register request compliant with the JS API version supported by the extension..
|
||||
* @param {Array<u2f.SignRequest>} signRequests
|
||||
* @param {Array<u2f.RegisterRequest>} signRequests
|
||||
* @param {number} timeoutSeconds
|
||||
* @param {number} reqId
|
||||
* @return {Object}
|
||||
*/
|
||||
u2f.formatRegisterRequest_ =
|
||||
function (appId, registeredKeys, registerRequests, timeoutSeconds, reqId) {
|
||||
if (js_api_version === undefined || js_api_version < 1.1) {
|
||||
// Adapt request to the 1.0 JS API
|
||||
for (var i = 0; i < registerRequests.length; i++) {
|
||||
registerRequests[i].appId = appId;
|
||||
}
|
||||
var signRequests = [];
|
||||
for (var i = 0; i < registeredKeys.length; i++) {
|
||||
signRequests[i] = {
|
||||
version: registeredKeys[i].version,
|
||||
challenge: registerRequests[0],
|
||||
keyHandle: registeredKeys[i].keyHandle,
|
||||
appId: appId
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
|
||||
signRequests: signRequests,
|
||||
registerRequests: registerRequests,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
}
|
||||
// JS 1.1 API
|
||||
return {
|
||||
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
|
||||
appId: appId,
|
||||
registerRequests: registerRequests,
|
||||
registeredKeys: registeredKeys,
|
||||
timeoutSeconds: timeoutSeconds,
|
||||
requestId: reqId
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Posts a message on the underlying channel.
|
||||
* @param {Object} message
|
||||
*/
|
||||
u2f.WrappedChromeRuntimePort_.prototype.postMessage = function (message) {
|
||||
this.port_.postMessage(message);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Emulates the HTML 5 addEventListener interface. Works only for the
|
||||
* onmessage event, which is hooked up to the chrome.runtime.Port.onMessage.
|
||||
* @param {string} eventName
|
||||
* @param {function({data: Object})} handler
|
||||
*/
|
||||
u2f.WrappedChromeRuntimePort_.prototype.addEventListener =
|
||||
function (eventName, handler) {
|
||||
var name = eventName.toLowerCase();
|
||||
if (name == 'message' || name == 'onmessage') {
|
||||
this.port_.onMessage.addListener(function (message) {
|
||||
// Emulate a minimal MessageEvent object
|
||||
handler({ 'data': message });
|
||||
});
|
||||
} else {
|
||||
console.error('WrappedChromeRuntimePort only supports onMessage');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrap the Authenticator app with a MessagePort interface.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_ = function () {
|
||||
this.requestId_ = -1;
|
||||
this.requestObject_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the Authenticator intent.
|
||||
* @param {Object} message
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.postMessage = function (message) {
|
||||
var intentUrl =
|
||||
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ +
|
||||
';S.request=' + encodeURIComponent(JSON.stringify(message)) +
|
||||
';end';
|
||||
document.location = intentUrl;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells what type of port this is.
|
||||
* @return {String} port type
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.getPortType = function () {
|
||||
return "WrappedAuthenticatorPort_";
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Emulates the HTML 5 addEventListener interface.
|
||||
* @param {string} eventName
|
||||
* @param {function({data: Object})} handler
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.addEventListener = function (eventName, handler) {
|
||||
var name = eventName.toLowerCase();
|
||||
if (name == 'message') {
|
||||
var self = this;
|
||||
/* Register a callback to that executes when
|
||||
* chrome injects the response. */
|
||||
window.addEventListener(
|
||||
'message', self.onRequestUpdate_.bind(self, handler), false);
|
||||
} else {
|
||||
console.error('WrappedAuthenticatorPort only supports message');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback invoked when a response is received from the Authenticator.
|
||||
* @param function({data: Object}) callback
|
||||
* @param {Object} message message Object
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.prototype.onRequestUpdate_ =
|
||||
function (callback, message) {
|
||||
var messageObject = JSON.parse(message.data);
|
||||
var intentUrl = messageObject['intentURL'];
|
||||
|
||||
var errorCode = messageObject['errorCode'];
|
||||
var responseObject = null;
|
||||
if (messageObject.hasOwnProperty('data')) {
|
||||
responseObject = /** @type {Object} */ (
|
||||
JSON.parse(messageObject['data']));
|
||||
}
|
||||
|
||||
callback({ 'data': responseObject });
|
||||
};
|
||||
|
||||
/**
|
||||
* Base URL for intents to Authenticator.
|
||||
* @const
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ =
|
||||
'intent:#Intent;action=com.google.android.apps.authenticator.AUTHENTICATE';
|
||||
|
||||
/**
|
||||
* Wrap the iOS client app with a MessagePort interface.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
u2f.WrappedIosPort_ = function () { };
|
||||
|
||||
/**
|
||||
* Launch the iOS client app request
|
||||
* @param {Object} message
|
||||
*/
|
||||
u2f.WrappedIosPort_.prototype.postMessage = function (message) {
|
||||
var str = JSON.stringify(message);
|
||||
var url = "u2f://auth?" + encodeURI(str);
|
||||
location.replace(url);
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells what type of port this is.
|
||||
* @return {String} port type
|
||||
*/
|
||||
u2f.WrappedIosPort_.prototype.getPortType = function () {
|
||||
return "WrappedIosPort_";
|
||||
};
|
||||
|
||||
/**
|
||||
* Emulates the HTML 5 addEventListener interface.
|
||||
* @param {string} eventName
|
||||
* @param {function({data: Object})} handler
|
||||
*/
|
||||
u2f.WrappedIosPort_.prototype.addEventListener = function (eventName, handler) {
|
||||
var name = eventName.toLowerCase();
|
||||
if (name !== 'message') {
|
||||
console.error('WrappedIosPort only supports message');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets up an embedded trampoline iframe, sourced from the extension.
|
||||
* @param {function(MessagePort)} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getIframePort_ = function (callback) {
|
||||
// Create the iframe
|
||||
var iframeOrigin = 'chrome-extension://' + u2f.EXTENSION_ID;
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.src = iframeOrigin + '/u2f-comms.html';
|
||||
iframe.setAttribute('style', 'display:none');
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
var channel = new MessageChannel();
|
||||
var ready = function (message) {
|
||||
if (message.data == 'ready') {
|
||||
channel.port1.removeEventListener('message', ready);
|
||||
callback(channel.port1);
|
||||
} else {
|
||||
console.error('First event on iframe port was not "ready"');
|
||||
}
|
||||
};
|
||||
channel.port1.addEventListener('message', ready);
|
||||
channel.port1.start();
|
||||
|
||||
iframe.addEventListener('load', function () {
|
||||
// Deliver the port to the iframe and initialize
|
||||
iframe.contentWindow.postMessage('init', iframeOrigin, [channel.port2]);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
//High-level JS API
|
||||
|
||||
/**
|
||||
* Default extension response timeout in seconds.
|
||||
* @const
|
||||
*/
|
||||
u2f.EXTENSION_TIMEOUT_SEC = 30;
|
||||
|
||||
/**
|
||||
* A singleton instance for a MessagePort to the extension.
|
||||
* @type {MessagePort|u2f.WrappedChromeRuntimePort_}
|
||||
* @private
|
||||
*/
|
||||
u2f.port_ = null;
|
||||
|
||||
/**
|
||||
* Callbacks waiting for a port
|
||||
* @type {Array<function((MessagePort|u2f.WrappedChromeRuntimePort_))>}
|
||||
* @private
|
||||
*/
|
||||
u2f.waitingForPort_ = [];
|
||||
|
||||
/**
|
||||
* A counter for requestIds.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
u2f.reqCounter_ = 0;
|
||||
|
||||
/**
|
||||
* A map from requestIds to client callbacks
|
||||
* @type {Object.<number,(function((u2f.Error|u2f.RegisterResponse))
|
||||
* |function((u2f.Error|u2f.SignResponse)))>}
|
||||
* @private
|
||||
*/
|
||||
u2f.callbackMap_ = {};
|
||||
|
||||
/**
|
||||
* Creates or retrieves the MessagePort singleton to use.
|
||||
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
|
||||
* @private
|
||||
*/
|
||||
u2f.getPortSingleton_ = function (callback) {
|
||||
if (u2f.port_) {
|
||||
callback(u2f.port_);
|
||||
} else {
|
||||
if (u2f.waitingForPort_.length == 0) {
|
||||
u2f.getMessagePort(function (port) {
|
||||
u2f.port_ = port;
|
||||
u2f.port_.addEventListener('message',
|
||||
/** @type {function(Event)} */(u2f.responseHandler_));
|
||||
|
||||
// Careful, here be async callbacks. Maybe.
|
||||
while (u2f.waitingForPort_.length)
|
||||
u2f.waitingForPort_.shift()(u2f.port_);
|
||||
});
|
||||
}
|
||||
u2f.waitingForPort_.push(callback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles response messages from the extension.
|
||||
* @param {MessageEvent.<u2f.Response>} message
|
||||
* @private
|
||||
*/
|
||||
u2f.responseHandler_ = function (message) {
|
||||
var response = message.data;
|
||||
var reqId = response['requestId'];
|
||||
if (!reqId || !u2f.callbackMap_[reqId]) {
|
||||
console.error('Unknown or missing requestId in response.');
|
||||
return;
|
||||
}
|
||||
var cb = u2f.callbackMap_[reqId];
|
||||
delete u2f.callbackMap_[reqId];
|
||||
cb(response['responseData']);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches an array of sign requests to available U2F tokens.
|
||||
* If the JS API version supported by the extension is unknown, it first sends a
|
||||
* message to the extension to find out the supported API version and then it sends
|
||||
* the sign request.
|
||||
* @param {string=} appId
|
||||
* @param {string=} challenge
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.SignResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.sign = function (appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
if (js_api_version === undefined) {
|
||||
// Send a message to get the extension to JS API version, then send the actual sign request.
|
||||
u2f.getApiVersion(
|
||||
function (response) {
|
||||
js_api_version = response['js_api_version'] === undefined ? 0 : response['js_api_version'];
|
||||
console.log("Extension JS API Version: ", js_api_version);
|
||||
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
|
||||
});
|
||||
} else {
|
||||
// We know the JS API version. Send the actual sign request in the supported API version.
|
||||
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches an array of sign requests to available U2F tokens.
|
||||
* @param {string=} appId
|
||||
* @param {string=} challenge
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.SignResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.sendSignRequest = function (appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
u2f.getPortSingleton_(function (port) {
|
||||
var reqId = ++u2f.reqCounter_;
|
||||
u2f.callbackMap_[reqId] = callback;
|
||||
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
|
||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
|
||||
var req = u2f.formatSignRequest_(appId, challenge, registeredKeys, timeoutSeconds, reqId);
|
||||
port.postMessage(req);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches register requests to available U2F tokens. An array of sign
|
||||
* requests identifies already registered tokens.
|
||||
* If the JS API version supported by the extension is unknown, it first sends a
|
||||
* message to the extension to find out the supported API version and then it sends
|
||||
* the register request.
|
||||
* @param {string=} appId
|
||||
* @param {Array<u2f.RegisterRequest>} registerRequests
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.register = function (appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
if (js_api_version === undefined) {
|
||||
// Send a message to get the extension to JS API version, then send the actual register request.
|
||||
u2f.getApiVersion(
|
||||
function (response) {
|
||||
js_api_version = response['js_api_version'] === undefined ? 0 : response['js_api_version'];
|
||||
console.log("Extension JS API Version: ", js_api_version);
|
||||
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
|
||||
callback, opt_timeoutSeconds);
|
||||
});
|
||||
} else {
|
||||
// We know the JS API version. Send the actual register request in the supported API version.
|
||||
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
|
||||
callback, opt_timeoutSeconds);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatches register requests to available U2F tokens. An array of sign
|
||||
* requests identifies already registered tokens.
|
||||
* @param {string=} appId
|
||||
* @param {Array<u2f.RegisterRequest>} registerRequests
|
||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
||||
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.sendRegisterRequest = function (appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
|
||||
u2f.getPortSingleton_(function (port) {
|
||||
var reqId = ++u2f.reqCounter_;
|
||||
u2f.callbackMap_[reqId] = callback;
|
||||
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
|
||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
|
||||
var req = u2f.formatRegisterRequest_(
|
||||
appId, registeredKeys, registerRequests, timeoutSeconds, reqId);
|
||||
port.postMessage(req);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches a message to the extension to find out the supported
|
||||
* JS API version.
|
||||
* If the user is on a mobile phone and is thus using Google Authenticator instead
|
||||
* of the Chrome extension, don't send the request and simply return 0.
|
||||
* @param {function((u2f.Error|u2f.GetJsApiVersionResponse))} callback
|
||||
* @param {number=} opt_timeoutSeconds
|
||||
*/
|
||||
u2f.getApiVersion = function (callback, opt_timeoutSeconds) {
|
||||
u2f.getPortSingleton_(function (port) {
|
||||
// If we are using Android Google Authenticator or iOS client app,
|
||||
// do not fire an intent to ask which JS API version to use.
|
||||
if (port.getPortType) {
|
||||
var apiVersion;
|
||||
switch (port.getPortType()) {
|
||||
case 'WrappedIosPort_':
|
||||
case 'WrappedAuthenticatorPort_':
|
||||
apiVersion = 1.1;
|
||||
break;
|
||||
|
||||
default:
|
||||
apiVersion = 0;
|
||||
break;
|
||||
}
|
||||
callback({ 'js_api_version': apiVersion });
|
||||
return;
|
||||
}
|
||||
var reqId = ++u2f.reqCounter_;
|
||||
u2f.callbackMap_[reqId] = callback;
|
||||
var req = {
|
||||
type: u2f.MessageTypes.U2F_GET_API_VERSION_REQUEST,
|
||||
timeoutSeconds: (typeof opt_timeoutSeconds !== 'undefined' ?
|
||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC),
|
||||
requestId: reqId
|
||||
};
|
||||
port.postMessage(req);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Modification:
|
||||
* Assign u2f back to window (root) scope.
|
||||
*/
|
||||
root.u2f = u2f;
|
||||
}(this));
|
@ -355,11 +355,8 @@ $(document).ready(function() {
|
||||
data_array[i] = decodeURIComponent(data_array[i]);
|
||||
$("#ItemsToDelete").append("<li>" + escapeHtml(data_array[i]) + "</li>");
|
||||
}
|
||||
});
|
||||
$('#ConfirmDeleteModal').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
})
|
||||
})
|
||||
$('#ConfirmDeleteModal').modal('show')
|
||||
.one('click', '#IsConfirmed', function(e) {
|
||||
if (is_active($('#IsConfirmed'))) { return false; }
|
||||
$.ajax({
|
||||
|
@ -1,239 +0,0 @@
|
||||
!function ($) {
|
||||
|
||||
"use strict";
|
||||
|
||||
// TABCOLLAPSE CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var TabCollapse = function (el, options) {
|
||||
this.options = options;
|
||||
this.$tabs = $(el);
|
||||
|
||||
this._accordionVisible = false; //content is attached to tabs at first
|
||||
this._initAccordion();
|
||||
this._checkStateOnResize();
|
||||
|
||||
|
||||
// checkState() has gone to setTimeout for making it possible to attach listeners to
|
||||
// shown-accordion.bs.tabcollapse event on page load.
|
||||
// See https://github.com/flatlogic/bootstrap-tabcollapse/issues/23
|
||||
var that = this;
|
||||
setTimeout(function() {
|
||||
that.checkState();
|
||||
}, 0);
|
||||
};
|
||||
|
||||
TabCollapse.DEFAULTS = {
|
||||
accordionClass: 'visible-xs',
|
||||
tabsClass: 'hidden-xs',
|
||||
accordionTemplate: function(heading, groupId, parentId, active) {
|
||||
return '<div class="panel panel-default">' +
|
||||
' <div class="panel-heading">' +
|
||||
' <h4 class="panel-title">' +
|
||||
' </h4>' +
|
||||
' </div>' +
|
||||
' <div id="' + groupId + '" class="panel-collapse collapse ' + (active ? 'in' : '') + '">' +
|
||||
' <div class="panel-body js-tabcollapse-panel-body">' +
|
||||
' </div>' +
|
||||
' </div>' +
|
||||
'</div>'
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
TabCollapse.prototype.checkState = function(){
|
||||
if (this.$tabs.is(':visible') && this._accordionVisible){
|
||||
this.showTabs();
|
||||
this._accordionVisible = false;
|
||||
} else if (this.$accordion.is(':visible') && !this._accordionVisible){
|
||||
this.showAccordion();
|
||||
this._accordionVisible = true;
|
||||
}
|
||||
};
|
||||
|
||||
TabCollapse.prototype.showTabs = function(){
|
||||
var view = this;
|
||||
this.$tabs.trigger($.Event('show-tabs.bs.tabcollapse'));
|
||||
|
||||
var $panelHeadings = this.$accordion.find('.js-tabcollapse-panel-heading').detach();
|
||||
|
||||
$panelHeadings.each(function() {
|
||||
var $panelHeading = $(this),
|
||||
$parentLi = $panelHeading.data('bs.tabcollapse.parentLi');
|
||||
|
||||
var $oldHeading = view._panelHeadingToTabHeading($panelHeading);
|
||||
|
||||
$parentLi.removeClass('active');
|
||||
if ($parentLi.parent().hasClass('dropdown-menu') && !$parentLi.siblings('li').hasClass('active')) {
|
||||
$parentLi.parent().parent().removeClass('active');
|
||||
}
|
||||
|
||||
if (!$oldHeading.hasClass('collapsed')) {
|
||||
$parentLi.addClass('active');
|
||||
$('.tab-pane').removeClass('active');
|
||||
$($panelHeading.attr('href')).addClass('active');
|
||||
if ($parentLi.parent().hasClass('dropdown-menu')) {
|
||||
$parentLi.parent().parent().addClass('active');
|
||||
}
|
||||
} else {
|
||||
$oldHeading.removeClass('collapsed');
|
||||
}
|
||||
|
||||
$parentLi.append($panelHeading);
|
||||
});
|
||||
|
||||
if (!$('li').hasClass('active')) {
|
||||
$('li').first().addClass('active')
|
||||
}
|
||||
|
||||
var $panelBodies = this.$accordion.find('.js-tabcollapse-panel-body');
|
||||
$panelBodies.each(function(){
|
||||
var $panelBody = $(this),
|
||||
$tabPane = $panelBody.data('bs.tabcollapse.tabpane');
|
||||
$tabPane.append($panelBody.contents().detach());
|
||||
});
|
||||
this.$accordion.html('');
|
||||
|
||||
if(this.options.updateLinks) {
|
||||
var $tabContents = this.getTabContentElement();
|
||||
$tabContents.find('[data-toggle-was="tab"], [data-toggle-was="pill"]').each(function() {
|
||||
var $el = $(this);
|
||||
var href = $el.attr('href').replace(/-collapse$/g, '');
|
||||
$el.attr({
|
||||
'data-toggle': $el.attr('data-toggle-was'),
|
||||
'data-toggle-was': '',
|
||||
'data-parent': '',
|
||||
href: href
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.$tabs.trigger($.Event('shown-tabs.bs.tabcollapse'));
|
||||
};
|
||||
|
||||
TabCollapse.prototype.getTabContentElement = function(){
|
||||
var $tabContents = $(this.options.tabContentSelector);
|
||||
if($tabContents.length === 0) {
|
||||
$tabContents = this.$tabs.siblings('.tab-content');
|
||||
}
|
||||
return $tabContents;
|
||||
};
|
||||
|
||||
TabCollapse.prototype.showAccordion = function(){
|
||||
this.$tabs.trigger($.Event('show-accordion.bs.tabcollapse'));
|
||||
|
||||
var $headings = this.$tabs.find('li:not(.dropdown) [data-toggle="tab"], li:not(.dropdown) [data-toggle="pill"]'),
|
||||
view = this;
|
||||
$headings.each(function(){
|
||||
var $heading = $(this),
|
||||
$parentLi = $heading.parent();
|
||||
$heading.data('bs.tabcollapse.parentLi', $parentLi);
|
||||
view.$accordion.append(view._createAccordionGroup(view.$accordion.attr('id'), $heading.detach()));
|
||||
});
|
||||
|
||||
if(this.options.updateLinks) {
|
||||
var parentId = this.$accordion.attr('id');
|
||||
var $selector = this.$accordion.find('.js-tabcollapse-panel-body');
|
||||
$selector.find('[data-toggle="tab"], [data-toggle="pill"]').each(function() {
|
||||
var $el = $(this);
|
||||
var href = $el.attr('href') + '-collapse';
|
||||
$el.attr({
|
||||
'data-toggle-was': $el.attr('data-toggle'),
|
||||
'data-toggle': 'collapse',
|
||||
'data-parent': '#' + parentId,
|
||||
href: href
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.$tabs.trigger($.Event('shown-accordion.bs.tabcollapse'));
|
||||
};
|
||||
|
||||
TabCollapse.prototype._panelHeadingToTabHeading = function($heading) {
|
||||
var href = $heading.attr('href').replace(/-collapse$/g, '');
|
||||
$heading.attr({
|
||||
'data-toggle': 'tab',
|
||||
'href': href,
|
||||
'data-parent': ''
|
||||
});
|
||||
return $heading;
|
||||
};
|
||||
|
||||
TabCollapse.prototype._tabHeadingToPanelHeading = function($heading, groupId, parentId, active) {
|
||||
$heading.addClass('js-tabcollapse-panel-heading ' + (active ? '' : 'collapsed'));
|
||||
$heading.attr({
|
||||
'data-toggle': 'collapse',
|
||||
'data-parent': '#' + parentId,
|
||||
'href': '#' + groupId
|
||||
});
|
||||
return $heading;
|
||||
};
|
||||
|
||||
TabCollapse.prototype._checkStateOnResize = function(){
|
||||
var view = this;
|
||||
$(window).resize(function(){
|
||||
clearTimeout(view._resizeTimeout);
|
||||
view._resizeTimeout = setTimeout(function(){
|
||||
view.checkState();
|
||||
}, 100);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
TabCollapse.prototype._initAccordion = function(){
|
||||
var randomString = function() {
|
||||
var result = "",
|
||||
possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
for( var i=0; i < 5; i++ ) {
|
||||
result += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
var srcId = this.$tabs.attr('id'),
|
||||
accordionId = (srcId ? srcId : randomString()) + '-accordion';
|
||||
|
||||
this.$accordion = $('<div class="panel-group ' + this.options.accordionClass + '" id="' + accordionId +'"></div>');
|
||||
this.$tabs.after(this.$accordion);
|
||||
this.$tabs.addClass(this.options.tabsClass);
|
||||
this.getTabContentElement().addClass(this.options.tabsClass);
|
||||
};
|
||||
|
||||
TabCollapse.prototype._createAccordionGroup = function(parentId, $heading){
|
||||
var tabSelector = $heading.attr('data-target'),
|
||||
active = $heading.data('bs.tabcollapse.parentLi').is('.active');
|
||||
|
||||
if (!tabSelector) {
|
||||
tabSelector = $heading.attr('href');
|
||||
tabSelector = tabSelector && tabSelector.replace(/.*(?=#[^\s]*$)/, ''); //strip for ie7
|
||||
}
|
||||
|
||||
var $tabPane = $(tabSelector),
|
||||
groupId = $tabPane.attr('id') + '-collapse',
|
||||
$panel = $(this.options.accordionTemplate($heading, groupId, parentId, active));
|
||||
$panel.find('.panel-heading > .panel-title').append(this._tabHeadingToPanelHeading($heading, groupId, parentId, active));
|
||||
$panel.find('.panel-body').append($tabPane.contents().detach())
|
||||
.data('bs.tabcollapse.tabpane', $tabPane);
|
||||
|
||||
return $panel;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// TABCOLLAPSE PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
$.fn.tabCollapse = function (option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
var data = $this.data('bs.tabcollapse');
|
||||
var options = $.extend({}, TabCollapse.DEFAULTS, $this.data(), typeof option === 'object' && option);
|
||||
|
||||
if (!data) $this.data('bs.tabcollapse', new TabCollapse(this, options));
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.tabCollapse.Constructor = TabCollapse;
|
||||
|
||||
|
||||
}(window.jQuery);
|
10
data/web/js/build/013-footable.min.js
vendored
10
data/web/js/build/013-footable.min.js
vendored
File diff suppressed because one or more lines are too long
@ -55,14 +55,14 @@ $(document).ready(function() {
|
||||
|
||||
// tooltips
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
$('[data-bs-toggle="tooltip"]').tooltip()
|
||||
});
|
||||
|
||||
// remember last navigation pill
|
||||
(function () {
|
||||
'use strict';
|
||||
if ($('a[data-toggle="tab"]').length) {
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
// remember desktop tabs
|
||||
$('button[data-bs-toggle="tab"]').on('click', function (e) {
|
||||
if ($(this).data('dont-remember') == 1) {
|
||||
return true;
|
||||
}
|
||||
@ -71,8 +71,28 @@ $(document).ready(function() {
|
||||
if (id) {
|
||||
key += ':' + id;
|
||||
}
|
||||
localStorage.setItem(key, $(e.target).attr('href'));
|
||||
|
||||
var tab_id = $(e.target).attr('data-bs-target').substring(1);
|
||||
localStorage.setItem(key, tab_id);
|
||||
});
|
||||
// remember mobile tabs
|
||||
$('button[data-bs-target^="#collapse-tab-"]').on('click', function (e) {
|
||||
// only remember tab if its being opened
|
||||
if ($(this).hasClass('collapsed')) return false;
|
||||
var tab_id = $(this).closest('div[role="tabpanel"]').attr('id');
|
||||
|
||||
if ($(this).data('dont-remember') == 1) {
|
||||
return true;
|
||||
}
|
||||
var id = $(this).parents('[role="tablist"]').attr('id');;
|
||||
var key = 'lastTag';
|
||||
if (id) {
|
||||
key += ':' + id;
|
||||
}
|
||||
|
||||
localStorage.setItem(key, tab_id);
|
||||
});
|
||||
// open last tab
|
||||
$('[role="tablist"]').each(function (idx, elem) {
|
||||
var id = $(elem).attr('id');
|
||||
var key = 'lastTag';
|
||||
@ -81,10 +101,11 @@ $(document).ready(function() {
|
||||
}
|
||||
var lastTab = localStorage.getItem(key);
|
||||
if (lastTab) {
|
||||
$('[href="' + lastTab + '"]').tab('show');
|
||||
$('[data-bs-target="#' + lastTab + '"]').click();
|
||||
var tab = $('[id^="' + lastTab + '"]');
|
||||
$(tab).find('.card-body.collapse').collapse('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
// IE fix to hide scrollbars when table body is empty
|
||||
@ -119,7 +140,7 @@ $(document).ready(function() {
|
||||
shake(password_field);
|
||||
}
|
||||
else {
|
||||
$(hibp_result).attr('class', 'hibp-out label label-info');
|
||||
$(hibp_result).attr('class', 'hibp-out badge fs-5 bg-info');
|
||||
$(hibp_result).text(lang_footer.loading);
|
||||
var password_digest = $.sha1($(password_field).val())
|
||||
var digest_five = password_digest.substring(0, 5).toUpperCase();
|
||||
@ -130,16 +151,16 @@ $(document).ready(function() {
|
||||
type: 'GET',
|
||||
success: function(res) {
|
||||
if (res.search(compl_digest) > -1){
|
||||
$(hibp_result).removeClass('label label-info').addClass('label label-danger');
|
||||
$(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-danger');
|
||||
$(hibp_result).text(lang_footer.hibp_nok)
|
||||
} else {
|
||||
$(hibp_result).removeClass('label label-info').addClass('label label-success');
|
||||
$(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-success');
|
||||
$(hibp_result).text(lang_footer.hibp_ok)
|
||||
}
|
||||
$(hibp_field).removeClass('task-running');
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$(hibp_result).removeClass('label label-info').addClass('label label-warning');
|
||||
$(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-warning');
|
||||
$(hibp_result).text('API error: ' + xhr.responseText)
|
||||
$(hibp_field).removeClass('task-running');
|
||||
}
|
||||
@ -150,8 +171,8 @@ $(document).ready(function() {
|
||||
// Disable disallowed inputs
|
||||
$('[data-acl="0"]').each(function(event){
|
||||
if ($(this).is("a")) {
|
||||
$(this).removeAttr("data-toggle");
|
||||
$(this).removeAttr("data-target");
|
||||
$(this).removeAttr("data-bs-toggle");
|
||||
$(this).removeAttr("data-bs-target");
|
||||
$(this).removeAttr("data-action");
|
||||
$(this).click(function(event) {
|
||||
event.preventDefault();
|
||||
@ -166,8 +187,8 @@ $(document).ready(function() {
|
||||
if ($(this).hasClass('btn-group')) {
|
||||
$(this).find('a').each(function(){
|
||||
$(this).removeClass('dropdown-toggle')
|
||||
.removeAttr('data-toggle')
|
||||
.removeAttr('data-target')
|
||||
.removeAttr('data-bs-toggle')
|
||||
.removeAttr('data-bs-target')
|
||||
.removeAttr('data-action')
|
||||
.removeAttr('id')
|
||||
.attr("disabled", true);
|
||||
@ -182,7 +203,7 @@ $(document).ready(function() {
|
||||
} else if ($(this).hasClass('input-group')) {
|
||||
$(this).find('input').each(function() {
|
||||
$(this).removeClass('dropdown-toggle')
|
||||
.removeAttr('data-toggle')
|
||||
.removeAttr('data-bs-toggle')
|
||||
.attr("disabled", true);
|
||||
$(this).click(function(event) {
|
||||
event.preventDefault();
|
||||
@ -226,7 +247,7 @@ $(document).ready(function() {
|
||||
$('#containerName').text(container);
|
||||
$('#triggerRestartContainer').click(function(){
|
||||
$(this).prop("disabled",true);
|
||||
$(this).html('<i class="bi bi-arrow-repeat icon-spin"></i> ');
|
||||
$(this).html('<div class="spinner-border text-secondary" role="status"><span class="visually-hidden">Loading...</span></div>');
|
||||
$('#statusTriggerRestartContainer').html(lang_footer.restarting_container);
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
@ -253,25 +274,9 @@ $(document).ready(function() {
|
||||
});
|
||||
})
|
||||
|
||||
// responsive tabs
|
||||
$('.responsive-tabs').tabCollapse({
|
||||
tabsClass: 'hidden-xs',
|
||||
accordionClass: 'js-tabcollapse-panel-group visible-xs'
|
||||
});
|
||||
$(document).on("shown.bs.collapse shown.bs.tab", function (e) {
|
||||
var target = $(e.target);
|
||||
if($(window).width() <= 767) {
|
||||
var offset = target.offset().top - 112;
|
||||
$("html, body").stop().animate({
|
||||
scrollTop: offset
|
||||
}, 100);
|
||||
}
|
||||
if(target.hasClass('panel-collapse')){
|
||||
var id = e.target.id.replace(/-collapse$/g, '');
|
||||
if(id){
|
||||
localStorage.setItem('lastTag', '#'+id);
|
||||
}
|
||||
}
|
||||
// Jquery Datatables, enable responsive plugin
|
||||
$.extend($.fn.dataTable.defaults, {
|
||||
responsive: true
|
||||
});
|
||||
|
||||
// tag boxes
|
||||
|
@ -53,237 +53,422 @@ jQuery(function($){
|
||||
$("#show_rspamd_global_filters").click(function() {
|
||||
$.get("inc/ajax/show_rspamd_global_filters.php");
|
||||
$("#confirm_show_rspamd_global_filters").hide();
|
||||
$("#rspamd_global_filters").removeClass("hidden");
|
||||
$("#rspamd_global_filters").removeClass("d-none");
|
||||
});
|
||||
$("#super_delete").click(function() { return confirm(lang.queue_ays); });
|
||||
$(".refresh_table").on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var table_name = $(this).data('table');
|
||||
$('#' + table_name).find("tr.footable-empty").remove();
|
||||
draw_table = $(this).data('draw');
|
||||
eval(draw_table + '()');
|
||||
$('#' + table_name).DataTable().ajax.reload();
|
||||
});
|
||||
function table_admin_ready(ft, name) {
|
||||
heading = ft.$el.parents('.panel').find('.panel-heading')
|
||||
var ft_paging = ft.use(FooTable.Paging)
|
||||
$(heading).children('.table-lines').text(function(){
|
||||
return ft_paging.totalRows;
|
||||
})
|
||||
}
|
||||
function draw_domain_admins() {
|
||||
ft_domainadmins = FooTable.init('#domainadminstable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}},
|
||||
{"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"},
|
||||
{"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/domain-admin/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw domain admin table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#domainadminstable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/domain-admin/all",
|
||||
dataSrc: function(data){
|
||||
return process_table_data(data, 'domainadminstable');
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
||||
"state": {"enabled": true},
|
||||
"filtering": {"enabled": true,"delay": 1200,"position": "left","connectors": false,"placeholder": lang.filter_table},
|
||||
"sorting": {"enabled": true},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: lang.username,
|
||||
data: 'username',
|
||||
},
|
||||
{
|
||||
title: "TFA",
|
||||
data: 'tfa_active',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.admin_domains,
|
||||
data: 'tfa_active',
|
||||
render: function (data, type) {
|
||||
return data;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.active,
|
||||
data: 'active',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
],
|
||||
initComplete: function(settings, json){
|
||||
console.log(settings.aoColumns);
|
||||
}
|
||||
});
|
||||
}
|
||||
function draw_oauth2_clients() {
|
||||
ft_oauth2clientstable = FooTable.init('#oauth2clientstable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"id","type":"text","title":"ID","style":{"width":"50px"}},
|
||||
{"name":"client_id","type":"text","title":lang.oauth2_client_id,"style":{"width":"200px"}},
|
||||
{"name":"client_secret","title":lang.oauth2_client_secret,"breakpoints":"xs sm md","style":{"width":"200px"}},
|
||||
{"name":"redirect_uri","title":lang.oauth2_redirect_uri, "type": "text"},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/oauth2-client/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw oauth2 clients table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#oauth2clientstable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/oauth2-client/all",
|
||||
dataSrc: function(data){
|
||||
return process_table_data(data, 'oauth2clientstable');
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
||||
"sorting": {"enabled": true},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'id',
|
||||
},
|
||||
{
|
||||
title: lang.oauth2_client_id,
|
||||
data: 'client_id'
|
||||
},
|
||||
{
|
||||
title: lang.oauth2_client_secret,
|
||||
data: 'client_secret'
|
||||
},
|
||||
{
|
||||
title: lang.oauth2_redirect_uri,
|
||||
data: 'redirect_uri'
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_admins() {
|
||||
ft_admins = FooTable.init('#adminstable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"sorted": true,"name":"usr","title":lang.username,"style":{"width":"250px"}},
|
||||
{"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/admin/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw admin table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#adminstable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/admin/all",
|
||||
dataSrc: function(data){
|
||||
return process_table_data(data, 'adminstable');
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
||||
"filtering": {"enabled": false},
|
||||
"state": {"enabled": true},
|
||||
"sorting": {"enabled": true},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: lang.username,
|
||||
data: 'username',
|
||||
},
|
||||
{
|
||||
title: "TFA",
|
||||
data: 'tfa_active',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.active,
|
||||
data: 'active',
|
||||
render: function (data, type) {
|
||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||
else return '<i class="bi bi-x-lg"></i>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_fwd_hosts() {
|
||||
ft_forwardinghoststable = FooTable.init('#forwardinghoststable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}},
|
||||
{"name":"source","title":lang.source,"breakpoints":"xs sm"},
|
||||
{"name":"keep_spam","title":lang.spamfilter, "type": "text","style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 'yes'==value?'<i class="bi bi-x-lg"></i>':'no'==value&&'<i class="bi bi-check-lg"></i>';}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/fwdhost/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw forwarding hosts table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#forwardinghoststable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/fwdhost/all",
|
||||
dataSrc: function(data){
|
||||
return process_table_data(data, 'forwardinghoststable');
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
||||
"sorting": {"enabled": true},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: lang.host,
|
||||
data: 'host',
|
||||
},
|
||||
{
|
||||
title: lang.source,
|
||||
data: 'source'
|
||||
},
|
||||
{
|
||||
title: lang.spamfilter,
|
||||
data: 'keep_spam'
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_relayhosts() {
|
||||
ft_relayhoststable = FooTable.init('#relayhoststable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"id","type":"text","title":"ID","style":{"width":"50px"}},
|
||||
{"name":"hostname","type":"text","title":lang.host,"style":{"width":"250px"}},
|
||||
{"name":"username","title":lang.username,"breakpoints":"xs sm"},
|
||||
{"name":"in_use_by","title":lang.in_use_by,"style":{"min-width":"200px","width":"200px"}, "type": "text","breakpoints":"xs sm"},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/relayhost/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw forwarding hosts table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#relayhoststable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/relayhost/all",
|
||||
dataSrc: function(data){
|
||||
return process_table_data(data, 'relayhoststable');
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
||||
"sorting": {"enabled": true},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'id',
|
||||
},
|
||||
{
|
||||
title: lang.host,
|
||||
data: 'hostname'
|
||||
},
|
||||
{
|
||||
title: lang.username,
|
||||
data: 'username'
|
||||
},
|
||||
{
|
||||
title: lang.in_use_by,
|
||||
data: 'in_use_by'
|
||||
},
|
||||
{
|
||||
title: lang.active,
|
||||
data: 'active'
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_transport_maps() {
|
||||
ft_transportstable = FooTable.init('#transportstable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"id","type":"text","title":"ID","style":{"width":"50px"}},
|
||||
{"name":"destination","type":"text","title":lang.destination,"style":{"min-width":"300px","width":"300px"}},
|
||||
{"name":"nexthop","type":"text","title":lang.nexthop,"style":{"min-width":"200px","width":"200px"}},
|
||||
{"name":"username","title":lang.username,"breakpoints":"xs sm"},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/transport/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw transports table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#transportstable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/transport/all",
|
||||
dataSrc: function(data){
|
||||
return process_table_data(data, 'transportstable');
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
||||
"sorting": {"enabled": true},
|
||||
"toggleSelector": "table tbody span.footable-toggle",
|
||||
"on": {
|
||||
"ready.ft.table": function(e, ft){
|
||||
$('.mx-info').tooltip();
|
||||
}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'id',
|
||||
},
|
||||
{
|
||||
title: lang.destination,
|
||||
data: 'destination'
|
||||
},
|
||||
{
|
||||
title: lang.nexthop,
|
||||
data: 'nexthop'
|
||||
},
|
||||
{
|
||||
title: lang.username,
|
||||
data: 'username'
|
||||
},
|
||||
{
|
||||
title: lang.active,
|
||||
data: 'active'
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_queue() {
|
||||
ft_queuetable = FooTable.init('#queuetable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"queue_id","type":"text","title":"QID","style":{"width":"50px"}},
|
||||
{"name":"queue_name","type":"text","title":"Queue","style":{"width":"120px"}},
|
||||
{"name":"arrival_time","sorted": true,"direction": "DESC","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});},"title":lang.arrival_time,"style":{"width":"170px"}},
|
||||
{"name":"message_size","style":{"whiteSpace":"nowrap"},"title":lang.message_size,"formatter": function(value){
|
||||
return humanFileSize(value);
|
||||
}},
|
||||
{"name":"sender","title":lang.sender, "type": "text","breakpoints":"xs sm"},
|
||||
{"name":"recipients","title":lang.recipients, "type": "text","style":{"word-break":"break-all","min-width":"300px"},"breakpoints":"xs sm md"},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/mailq/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw forwarding hosts table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#queuetable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/mailq/all",
|
||||
dataSrc: function(data){
|
||||
return process_table_data(data, 'queuetable');
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
||||
"sorting": {"enabled": true},
|
||||
"toggleSelector": "table tbody span.footable-toggle",
|
||||
"on": {
|
||||
"ready.ft.table": function(e, ft){
|
||||
table_admin_ready(ft, 'queuetable');
|
||||
}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'QID',
|
||||
data: 'queue_id',
|
||||
},
|
||||
{
|
||||
title: 'Queue',
|
||||
data: 'queue_name'
|
||||
},
|
||||
{
|
||||
title: lang.arrival_time,
|
||||
data: 'arrival_time',
|
||||
render: function (data, type){
|
||||
var date = new Date(data ? data * 1000 : 0);
|
||||
return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.message_size,
|
||||
data: 'message_size',
|
||||
render: function (data, type){
|
||||
return humanFileSize(data);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.sender,
|
||||
data: 'sender'
|
||||
},
|
||||
{
|
||||
title: lang.recipients,
|
||||
data: 'recipients'
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
function process_table_data(data, table) {
|
||||
if (table == 'relayhoststable') {
|
||||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="#" data-toggle="modal" data-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="sender-dependent" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
||||
'<a href="/edit/relayhost/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="sender-dependent" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
||||
'<a href="/edit/relayhost/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-rlyhost" data-api-url="delete/relayhost" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
if (item.used_by_mailboxes == '') { item.in_use_by = item.used_by_domains; }
|
||||
@ -294,14 +479,14 @@ jQuery(function($){
|
||||
} else if (table == 'transportstable') {
|
||||
$.each(data, function (i, item) {
|
||||
if (item.is_mx_based) {
|
||||
item.destination = '<i class="bi bi-info-circle-fill text-info mx-info" data-toggle="tooltip" title="' + lang.is_mx_based + '"></i> <code>' + item.destination + '</code>';
|
||||
item.destination = '<i class="bi bi-info-circle-fill text-info mx-info" data-bs-toggle="tooltip" title="' + lang.is_mx_based + '"></i> <code>' + item.destination + '</code>';
|
||||
}
|
||||
if (item.username) {
|
||||
item.username = '<i style="color:#' + intToRGB(hashCode(item.nexthop)) + ';" class="bi bi-square-fill"></i> ' + item.username;
|
||||
}
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="#" data-toggle="modal" data-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="transport-map" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
||||
'<a href="/edit/transport/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="transport-map" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
||||
'<a href="/edit/transport/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-transport" data-api-url="delete/transport" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="transports" name="multi_select" value="' + item.id + '" />';
|
||||
@ -313,21 +498,21 @@ jQuery(function($){
|
||||
return escapeHtml(i);
|
||||
});
|
||||
item.recipients = rcpts.join('<hr style="margin:1px!important">');
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="#" data-toggle="modal" data-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-default">' + lang.queue_show_message + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.queue_show_message + '</a>' +
|
||||
'</div>';
|
||||
});
|
||||
} else if (table == 'forwardinghoststable') {
|
||||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-fwdhost" data-api-url="delete/fwdhost" data-item="' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="fwdhosts" name="multi_select" value="' + item.host + '" />';
|
||||
});
|
||||
} else if (table == 'oauth2clientstable') {
|
||||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="/edit.php?oauth2client=' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?oauth2client=' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-oauth2-client" data-api-url="delete/oauth2-client" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.scope = "profile";
|
||||
@ -339,8 +524,8 @@ jQuery(function($){
|
||||
item.selected_domains = escapeHtml(item.selected_domains);
|
||||
item.selected_domains = item.selected_domains.toString().replace(/,/g, "<br>");
|
||||
item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="/edit/domainadmin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit/domainadmin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-domain-admin" data-api-url="delete/domain-admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-xs-third btn-success"><i class="bi bi-person-fill"></i> Login</a>' +
|
||||
'</div>';
|
||||
@ -353,22 +538,38 @@ jQuery(function($){
|
||||
item.usr = item.username;
|
||||
}
|
||||
item.chkbox = '<input type="checkbox" data-id="admins" name="multi_select" value="' + item.username + '" />';
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="/edit/admin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit/admin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-admin" data-api-url="delete/admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
});
|
||||
}
|
||||
return data
|
||||
};
|
||||
// Initial table drawings
|
||||
draw_domain_admins();
|
||||
draw_admins();
|
||||
draw_fwd_hosts();
|
||||
draw_relayhosts();
|
||||
draw_oauth2_clients();
|
||||
draw_transport_maps();
|
||||
draw_queue();
|
||||
|
||||
// detect element visibility changes
|
||||
function onVisible(element, callback) {
|
||||
$(element).ready(function() {
|
||||
element_object = document.querySelector(element)
|
||||
new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.intersectionRatio > 0) {
|
||||
callback(element_object);
|
||||
observer.disconnect();
|
||||
}
|
||||
});
|
||||
}).observe(element_object);
|
||||
});
|
||||
}
|
||||
// Draw Table if tab is active
|
||||
onVisible("[id^=adminstable]", () => draw_admins());
|
||||
onVisible("[id^=domainadminstable]", () => draw_domain_admins());
|
||||
onVisible("[id^=oauth2clientstable]", () => draw_oauth2_clients());
|
||||
onVisible("[id^=forwardinghoststable]", () => draw_fwd_hosts());
|
||||
onVisible("[id^=relayhoststable]", () => draw_relayhosts());
|
||||
onVisible("[id^=transportstable]", () => draw_transport_maps());
|
||||
onVisible("[id^=queuetable]", () => draw_queue());
|
||||
|
||||
|
||||
$('body').on('click', 'span.footable-toggle', function () {
|
||||
event.stopPropagation();
|
||||
@ -483,11 +684,11 @@ jQuery(function($){
|
||||
if (type == "app_link") {
|
||||
cols = '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required></td>';
|
||||
cols += '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required></td>';
|
||||
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-default" type="button">' + lang.remove_row + '</a></td>';
|
||||
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary" type="button">' + lang.remove_row + '</a></td>';
|
||||
} else if (type == "f2b_regex") {
|
||||
cols = '<td><input style="text-align:center" class="input-sm input-xs-lg form-control" data-id="f2b_regex" type="text" value="+" disabled></td>';
|
||||
cols += '<td><input class="input-sm input-xs-lg form-control regex-input" data-id="f2b_regex" type="text" name="regex" required></td>';
|
||||
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-default" type="button">' + lang.remove_row + '</a></td>';
|
||||
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary" type="button">' + lang.remove_row + '</a></td>';
|
||||
}
|
||||
row.append(cols);
|
||||
table_id.append(row);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -66,22 +66,14 @@ jQuery(function($){
|
||||
return re.test(email);
|
||||
}
|
||||
function draw_wl_policy_domain_table() {
|
||||
ft_wl_policy_mailbox_table = FooTable.init('#wl_policy_domain_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"prefid","style":{"maxWidth":"40px","width":"40px"},"title":"ID","filterable": false,"sortable": false},
|
||||
{"sorted": true,"name":"value","title":lang_user.spamfilter_table_rule},
|
||||
{"name":"object","title":"Scope"}
|
||||
],
|
||||
"empty": lang_user.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
$('#wl_policy_domain_table').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: '/api/v1/get/policy_wl_domain/' + table_for_domain,
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw mailbox policy wl table');
|
||||
},
|
||||
success: function (data) {
|
||||
dataSrc: function(data){
|
||||
$.each(data, function (i, item) {
|
||||
if (!validateEmail(item.object)) {
|
||||
item.chkbox = '<input type="checkbox" data-id="policy_wl_domain" name="multi_select" value="' + item.prefid + '" />';
|
||||
@ -90,35 +82,50 @@ jQuery(function($){
|
||||
item.chkbox = '<input type="checkbox" disabled title="' + lang_user.spamfilter_table_domain_policy + '" />';
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}),
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
}
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'prefid',
|
||||
},
|
||||
{
|
||||
title: lang_user.spamfilter_table_rule,
|
||||
data: 'value'
|
||||
},
|
||||
{
|
||||
title: 'Scope',
|
||||
data: 'object'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_bl_policy_domain_table() {
|
||||
ft_bl_policy_mailbox_table = FooTable.init('#bl_policy_domain_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"prefid","style":{"maxWidth":"40px","width":"40px"},"title":"ID","filterable": false,"sortable": false},
|
||||
{"sorted": true,"name":"value","title":lang_user.spamfilter_table_rule},
|
||||
{"name":"object","title":"Scope"}
|
||||
],
|
||||
"empty": lang_user.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
$('#bl_policy_domain_table').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: '/api/v1/get/policy_bl_domain/' + table_for_domain,
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw mailbox policy bl table');
|
||||
},
|
||||
success: function (data) {
|
||||
dataSrc: function(data){
|
||||
$.each(data, function (i, item) {
|
||||
if (!validateEmail(item.object)) {
|
||||
item.chkbox = '<input type="checkbox" data-id="policy_bl_domain" name="multi_select" value="' + item.prefid + '" />';
|
||||
@ -127,18 +134,58 @@ jQuery(function($){
|
||||
item.chkbox = '<input type="checkbox" disabled tooltip="' + lang_user.spamfilter_table_domain_policy + '" />';
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}),
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
}
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'prefid',
|
||||
},
|
||||
{
|
||||
title: lang_user.spamfilter_table_rule,
|
||||
data: 'value'
|
||||
},
|
||||
{
|
||||
title: 'Scope',
|
||||
data: 'object'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
draw_wl_policy_domain_table();
|
||||
draw_bl_policy_domain_table();
|
||||
|
||||
|
||||
// detect element visibility changes
|
||||
function onVisible(element, callback) {
|
||||
$(element).ready(function() {
|
||||
element_object = document.querySelector(element)
|
||||
new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.intersectionRatio > 0) {
|
||||
callback(element_object);
|
||||
observer.disconnect();
|
||||
}
|
||||
});
|
||||
}).observe(element_object);
|
||||
});
|
||||
}
|
||||
// Draw Table if tab is active
|
||||
onVisible("[id^=wl_policy_domain_table]", () => draw_wl_policy_domain_table());
|
||||
onVisible("[id^=bl_policy_domain_table]", () => draw_bl_policy_domain_table());
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,17 +40,17 @@ jQuery(function($){
|
||||
if (value.score > 0) highlightClass = 'negative'
|
||||
else if (value.score < 0) highlightClass = 'positive'
|
||||
else highlightClass = 'neutral'
|
||||
$('#qid_detail_symbols').append('<span data-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
|
||||
$('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
|
||||
});
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
$('[data-bs-toggle="tooltip"]').tooltip()
|
||||
}
|
||||
if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') {
|
||||
if (data.action === "add header") {
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action label label-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
|
||||
} else if (data.action === "reject") {
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action label label-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
|
||||
} else if (data.action === "rewrite subject") {
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action label label-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
|
||||
}
|
||||
}
|
||||
if (typeof data.recipients !== 'undefined') {
|
||||
|
@ -7,67 +7,20 @@ jQuery(function($){
|
||||
var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};
|
||||
function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
|
||||
function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e<B.length-1);return i.toFixed(1)+" "+B[e]}
|
||||
// Set paging
|
||||
$('[data-page-size]').on('click', function(e){
|
||||
e.preventDefault();
|
||||
var new_size = $(this).data('page-size');
|
||||
var parent_ul = $(this).closest('ul');
|
||||
var table_id = $(parent_ul).data('table-id');
|
||||
FooTable.get('#' + table_id).pageSize(new_size);
|
||||
//$(this).parent().addClass('active').siblings().removeClass('active')
|
||||
heading = $(this).parents('.panel').find('.panel-heading')
|
||||
var n_results = $(heading).children('.table-lines').text().split(' / ')[1];
|
||||
$(heading).children('.table-lines').text(function(){
|
||||
if (new_size > n_results) {
|
||||
new_size = n_results;
|
||||
}
|
||||
return new_size + ' / ' + n_results;
|
||||
})
|
||||
});
|
||||
$(".refresh_table").on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var table_name = $(this).data('table');
|
||||
$('#' + table_name).find("tr.footable-empty").remove();
|
||||
draw_table = $(this).data('draw');
|
||||
eval(draw_table + '()');
|
||||
$('#' + table_name).DataTable().ajax.reload();
|
||||
});
|
||||
function table_quarantine_ready(ft, name) {
|
||||
$('.refresh_table').prop("disabled", false);
|
||||
heading = ft.$el.parents('.panel').find('.panel-heading')
|
||||
var ft_paging = ft.use(FooTable.Paging)
|
||||
$(heading).children('.table-lines').text(function(){
|
||||
var total_rows = ft_paging.totalRows;
|
||||
var size = ft_paging.size;
|
||||
if (size > total_rows) {
|
||||
size = total_rows;
|
||||
}
|
||||
return size + ' / ' + total_rows;
|
||||
})
|
||||
}
|
||||
function draw_quarantine_table() {
|
||||
ft_quarantinetable = FooTable.init('#quarantinetable', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"id","type":"ID","filterable": false,"sorted": true,"direction":"DESC","title":"ID","style":{"width":"50px"}},
|
||||
{"name":"qid","breakpoints":"all","type":"text","title":lang.qid,"style":{"width":"125px"}},
|
||||
{"name":"sender","title":lang.sender},
|
||||
{"name":"subject","title":lang.subj, "type": "text"},
|
||||
{"name":"rspamdaction","title":lang.rspamd_result, "type": "html"},
|
||||
{"name":"rcpt","title":lang.rcpt, "type": "text"},
|
||||
{"name":"virus","title":lang.danger, "type": "text"},
|
||||
{"name":"score","title": lang.spam_score, "type": "text"},
|
||||
{"name":"notified","title":lang.notified, "type": "text"},
|
||||
{"name":"created","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});},"title":lang.received,"style":{"width":"170px"}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right"},"style":{"min-width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/quarantine/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw quarantine table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#quarantinetable').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/quarantine/all",
|
||||
dataSrc: function(data){
|
||||
$.each(data, function (i, item) {
|
||||
if (item.subject === null) {
|
||||
item.subject = '';
|
||||
@ -78,16 +31,16 @@ jQuery(function($){
|
||||
item.score = '-';
|
||||
}
|
||||
if (item.virus_flag > 0) {
|
||||
item.virus = '<span class="label label-danger">' + lang.high_danger + '</span>';
|
||||
item.virus = '<span class="badge fs-5 bg-danger">' + lang.high_danger + '</span>';
|
||||
} else {
|
||||
item.virus = '<span class="label label-default">' + lang.neutral_danger + '</span>';
|
||||
item.virus = '<span class="badge fs-5 bg-secondary">' + lang.neutral_danger + '</span>';
|
||||
}
|
||||
if (item.action === "reject") {
|
||||
item.rspamdaction = '<span class="label label-danger">' + lang.rejected + '</span>';
|
||||
item.rspamdaction = '<span class="badge fs-5 bg-danger">' + lang.rejected + '</span>';
|
||||
} else if (item.action === "add header") {
|
||||
item.rspamdaction = '<span class="label label-warning">' + lang.junk_folder + '</span>';
|
||||
item.rspamdaction = '<span class="badge fs-5 bg-warning">' + lang.junk_folder + '</span>';
|
||||
} else if (item.action === "rewrite subject") {
|
||||
item.rspamdaction = '<span class="label label-warning">' + lang.rewrite_subject + '</span>';
|
||||
item.rspamdaction = '<span class="badge fs-5 bg-warning">' + lang.rewrite_subject + '</span>';
|
||||
}
|
||||
if(item.notified > 0) {
|
||||
item.notified = '✔';
|
||||
@ -95,7 +48,7 @@ jQuery(function($){
|
||||
item.notified = '✖';
|
||||
}
|
||||
if (acl_data.login_as === 1) {
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-info show_qid_info"><i class="bi bi-box-arrow-up-right"></i> ' + lang.show_item + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="del-single-qitem" data-api-url="delete/qitem" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
@ -107,25 +60,76 @@ jQuery(function($){
|
||||
}
|
||||
item.chkbox = '<input type="checkbox" data-id="qitems" name="multi_select" value="' + item.id + '" />';
|
||||
});
|
||||
}
|
||||
}),
|
||||
"empty": lang.empty,
|
||||
"paging": {"enabled": true,"limit": 5,"size": pagination_size},
|
||||
"state": {"enabled": true},
|
||||
"sorting": {"enabled": true},
|
||||
"filtering": {"enabled": true,"position": "left","connectors": false,"placeholder": lang.filter_table},
|
||||
"toggleSelector": "table tbody span.footable-toggle",
|
||||
"on": {
|
||||
"destroy.ft.table": function(e, ft){
|
||||
$('.refresh_table').attr('disabled', 'true');
|
||||
},
|
||||
"ready.ft.table": function(e, ft){
|
||||
table_quarantine_ready(ft, 'quarantinetable');
|
||||
},
|
||||
"after.ft.filtering": function(e, ft){
|
||||
table_quarantine_ready(ft, 'quarantinetable');
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'id',
|
||||
},
|
||||
{
|
||||
title: lang.qid,
|
||||
data: 'qid'
|
||||
},
|
||||
{
|
||||
title: lang.sender,
|
||||
data: 'sender'
|
||||
},
|
||||
{
|
||||
title: lang.subj,
|
||||
data: 'sender'
|
||||
},
|
||||
{
|
||||
title: lang.rspamd_result,
|
||||
data: 'rspamdaction'
|
||||
},
|
||||
{
|
||||
title: lang.rcpt,
|
||||
data: 'rcpt'
|
||||
},
|
||||
{
|
||||
title: lang.danger,
|
||||
data: 'virus'
|
||||
},
|
||||
{
|
||||
title: lang.spam_score,
|
||||
data: 'score'
|
||||
},
|
||||
{
|
||||
title: lang.notified,
|
||||
data: 'notified'
|
||||
},
|
||||
{
|
||||
title: lang.received,
|
||||
data: 'created',
|
||||
render: function (data,type) {
|
||||
var date = new Date(data ? data * 1000 : 0);
|
||||
return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
@ -175,9 +179,9 @@ jQuery(function($){
|
||||
if (value.score > 0) highlightClass = 'negative'
|
||||
else if (value.score < 0) highlightClass = 'positive'
|
||||
else highlightClass = 'neutral'
|
||||
$('#qid_detail_symbols').append('<span data-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
|
||||
$('#qid_detail_symbols').append('<span data-bs-toggle="tooltip" class="rspamd-symbol ' + highlightClass + '" title="' + (value.options ? value.options.join(', ') : '') + '">' + value.name + ' (<span class="score">' + value.score + '</span>)</span>');
|
||||
});
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
$('[data-bs-toggle="tooltip"]').tooltip()
|
||||
}
|
||||
if (typeof data.fuzzy_hashes === 'object' && data.fuzzy_hashes !== null && data.fuzzy_hashes.length !== 0) {
|
||||
$.each(data.fuzzy_hashes, function (index, value) {
|
||||
@ -188,11 +192,11 @@ jQuery(function($){
|
||||
}
|
||||
if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') {
|
||||
if (data.action == "add header") {
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action label label-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
|
||||
} else if (data.action == "reject") {
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action label label-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
|
||||
} else if (data.action == "rewrite subject") {
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action label label-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
|
||||
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
|
||||
}
|
||||
}
|
||||
if (typeof data.recipients !== 'undefined') {
|
||||
|
@ -101,7 +101,7 @@ jQuery(function($){
|
||||
$.each(data.sasl, function (i, item) {
|
||||
var datetime = new Date(item.datetime.replace(/-/g, "/"));
|
||||
var local_datetime = datetime.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
|
||||
var service = '<div class="label label-default">' + item.service.toUpperCase() + '</div>';
|
||||
var service = '<div class="badge fs-5 bg-secondary">' + item.service.toUpperCase() + '</div>';
|
||||
var app_password = item.app_password ? ' <a href="/edit/app-passwd/' + item.app_password + '"><i class="bi bi-app-indicator"></i> ' + escapeHtml(item.app_password_name || "App") + '</a>' : '';
|
||||
var real_rip = item.real_rip.startsWith("Web") ? item.real_rip : '<a href="https://bgp.he.net/ip/' + item.real_rip + '" target="_blank">' + item.real_rip + "</a>";
|
||||
var ip_location = item.location ? ' <span class="flag-icon flag-icon-' + item.location.toLowerCase() + '"></span>' : '';
|
||||
@ -128,26 +128,18 @@ jQuery(function($){
|
||||
}
|
||||
|
||||
function draw_tla_table() {
|
||||
ft_tla_table = FooTable.init('#tla_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"min-width":"60px","width":"60px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"address","title":lang.alias},
|
||||
{"name":"validity","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});},"title":lang.alias_valid_until,"style":{"width":"170px"}},
|
||||
{"sorted": true,"sortValue": function(value){res = new Date(value);return res.getTime();},"direction":"DESC","name":"created","formatter":function date_format(datetime) { var date = new Date(datetime.replace(/-/g, "/")); return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});},"title":lang.created_on,"style":{"width":"170px"}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/time_limited_aliases',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw tla table');
|
||||
},
|
||||
success: function (data) {
|
||||
$('#tla_table').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: "/api/v1/get/time_limited_aliases",
|
||||
dataSrc: function(data){
|
||||
console.log(data);
|
||||
$.each(data, function (i, item) {
|
||||
if (acl_data.spam_alias === 1) {
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-tla" data-api-url="delete/time_limited_alias" data-item="' + encodeURIComponent(item.address) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="tla" name="multi_select" value="' + encodeURIComponent(item.address) + '" />';
|
||||
@ -158,49 +150,59 @@ jQuery(function($){
|
||||
item.action = '<span>-</span>';
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}),
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"state": {"enabled": true},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: lang.alias,
|
||||
data: 'address'
|
||||
},
|
||||
{
|
||||
title: lang.alias_valid_until,
|
||||
data: 'validity',
|
||||
render: function (data, type) {
|
||||
var date = new Date(data ? data * 1000 : 0);
|
||||
return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_sync_job_table() {
|
||||
ft_syncjob_table = FooTable.init('#sync_job_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"min-width":"60px","width":"60px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
|
||||
{"name":"server_w_port","title":"Server","breakpoints":"xs sm md","style":{"word-break":"break-all"}},
|
||||
{"name":"enc1","title":lang.encryption,"breakpoints":"all"},
|
||||
{"name":"user1","title":lang.username},
|
||||
{"name":"exclude","title":lang.excludes,"breakpoints":"all"},
|
||||
{"name":"mins_interval","title":lang.interval + " (min)","breakpoints":"all"},
|
||||
{"name":"last_run","title":lang.last_run,"breakpoints":"xs sm md"},
|
||||
{"name":"exit_status","filterable": false,"title":lang.syncjob_last_run_result},
|
||||
{"name":"log","title":"Log"},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"260px","width":"260px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
$('#sync_job_table').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: '/api/v1/get/syncjobs/' + encodeURIComponent(mailcow_cc_username) + '/no_log',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw sync job table');
|
||||
},
|
||||
success: function (data) {
|
||||
dataSrc: function(data){
|
||||
console.log(data);
|
||||
$.each(data, function (i, item) {
|
||||
item.user1 = escapeHtml(item.user1);
|
||||
item.log = '<a href="#syncjobLogModal" data-toggle="modal" data-syncjob-id="' + item.id + '">' + lang.open_logs + '</a>'
|
||||
item.log = '<a href="#syncjobLogModal" data-bs-toggle="modal" data-syncjob-id="' + item.id + '">' + lang.open_logs + '</a>'
|
||||
if (!item.exclude > 0) {
|
||||
item.exclude = '-';
|
||||
} else {
|
||||
@ -208,8 +210,8 @@ jQuery(function($){
|
||||
}
|
||||
item.server_w_port = escapeHtml(item.user1 + '@' + item.host1 + ':' + item.port1);
|
||||
if (acl_data.syncjobs === 1) {
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="/edit/syncjob/' + item.id + '" class="btn btn-xs btn-xs-half btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit/syncjob/' + item.id + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
|
||||
@ -219,9 +221,9 @@ jQuery(function($){
|
||||
item.chkbox = '<input type="checkbox" disabled />';
|
||||
}
|
||||
if (item.is_running == 1) {
|
||||
item.is_running = '<span id="active-script" class="label label-success">' + lang.running + '</span>';
|
||||
item.is_running = '<span id="active-script" class="badge fs-5 bg-success">' + lang.running + '</span>';
|
||||
} else {
|
||||
item.is_running = '<span id="inactive-script" class="label label-warning">' + lang.waiting + '</span>';
|
||||
item.is_running = '<span id="inactive-script" class="badge fs-5 bg-warning">' + lang.waiting + '</span>';
|
||||
}
|
||||
if (!item.last_run > 0) {
|
||||
item.last_run = lang.waiting;
|
||||
@ -239,39 +241,91 @@ jQuery(function($){
|
||||
}
|
||||
item.exit_status = item.success + ' ' + item.exit_status;
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}),
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"state": {"enabled": true},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'id'
|
||||
},
|
||||
{
|
||||
title: 'Server',
|
||||
data: 'server_w_port'
|
||||
},
|
||||
{
|
||||
title: lang.encryption,
|
||||
data: 'enc1'
|
||||
},
|
||||
{
|
||||
title: lang.username,
|
||||
data: 'user1'
|
||||
},
|
||||
{
|
||||
title: lang.excludes,
|
||||
data: 'exclude'
|
||||
},
|
||||
{
|
||||
title: lang.interval + " (min)",
|
||||
data: 'mins_interval'
|
||||
},
|
||||
{
|
||||
title: lang.last_run,
|
||||
data: 'last_run'
|
||||
},
|
||||
{
|
||||
title: lang.syncjob_last_run_result,
|
||||
data: 'exit_status'
|
||||
},
|
||||
{
|
||||
title: 'Log',
|
||||
data: 'log'
|
||||
},
|
||||
{
|
||||
title: lang.active,
|
||||
data: 'active',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.status,
|
||||
data: 'is_running'
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_app_passwd_table() {
|
||||
ft_apppasswd_table = FooTable.init('#app_passwd_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
|
||||
{"name":"name","title":lang.app_name},
|
||||
{"name":"protocols","title":lang.allowed_protocols},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
$('#app_passwd_table').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: '/api/v1/get/app-passwd/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw app passwd table');
|
||||
},
|
||||
success: function (data) {
|
||||
dataSrc: function(data){
|
||||
console.log(data);
|
||||
$.each(data, function (i, item) {
|
||||
item.name = escapeHtml(item.name)
|
||||
item.protocols = []
|
||||
@ -283,8 +337,8 @@ jQuery(function($){
|
||||
if (item.sieve_access == 1) { item.protocols.push("<code>Sieve</code>"); }
|
||||
item.protocols = item.protocols.join(" ")
|
||||
if (acl_data.app_passwds === 1) {
|
||||
item.action = '<div class="btn-group footable-actions">' +
|
||||
'<a href="/edit/app-passwd/' + item.id + '" class="btn btn-xs btn-xs-half btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit/app-passwd/' + item.id + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-apppasswd" data-api-url="delete/app-passwd" data-item="' + item.id + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="apppasswd" name="multi_select" value="' + item.id + '" />';
|
||||
@ -294,37 +348,63 @@ jQuery(function($){
|
||||
item.chkbox = '<input type="checkbox" disabled />';
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}),
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"state": {"enabled": true},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
},
|
||||
"toggleSelector": "table tbody span.footable-toggle"
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'id'
|
||||
},
|
||||
{
|
||||
title: lang.app_name,
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
title: lang.allowed_protocols,
|
||||
data: 'protocols'
|
||||
},
|
||||
{
|
||||
title: lang.active,
|
||||
data: 'active',
|
||||
render: function (data, type) {
|
||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: lang.action,
|
||||
data: 'action',
|
||||
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_wl_policy_mailbox_table() {
|
||||
ft_wl_policy_mailbox_table = FooTable.init('#wl_policy_mailbox_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"prefid","style":{"maxWidth":"40px","width":"40px"},"title":"ID","filterable": false,"sortable": false},
|
||||
{"sorted": true,"name":"value","title":lang.spamfilter_table_rule},
|
||||
{"name":"object","title":"Scope"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
$('#wl_policy_mailbox_table').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: '/api/v1/get/policy_wl_mailbox',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw mailbox policy wl table');
|
||||
},
|
||||
success: function (data) {
|
||||
dataSrc: function(data){
|
||||
console.log(data);
|
||||
$.each(data, function (i, item) {
|
||||
if (validateEmail(item.object)) {
|
||||
item.chkbox = '<input type="checkbox" data-id="policy_wl_mailbox" name="multi_select" value="' + item.prefid + '" />';
|
||||
@ -336,36 +416,51 @@ jQuery(function($){
|
||||
item.chkbox = '<input type="checkbox" disabled />';
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}),
|
||||
"state": {"enabled": true},
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
}
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'prefid'
|
||||
},
|
||||
{
|
||||
title: lang.spamfilter_table_rule,
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
title:'Scope',
|
||||
data: 'object'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
function draw_bl_policy_mailbox_table() {
|
||||
ft_bl_policy_mailbox_table = FooTable.init('#bl_policy_mailbox_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"prefid","style":{"maxWidth":"40px","width":"40px"},"title":"ID","filterable": false,"sortable": false},
|
||||
{"sorted": true,"name":"value","title":lang.spamfilter_table_rule},
|
||||
{"name":"object","title":"Scope"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
$('#bl_policy_mailbox_table').DataTable({
|
||||
processing: true,
|
||||
serverSide: false,
|
||||
language: lang_datatables,
|
||||
ajax: {
|
||||
type: "GET",
|
||||
url: '/api/v1/get/policy_bl_mailbox',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw mailbox policy bl table');
|
||||
},
|
||||
success: function (data) {
|
||||
dataSrc: function(data){
|
||||
console.log(data);
|
||||
$.each(data, function (i, item) {
|
||||
if (validateEmail(item.object)) {
|
||||
item.chkbox = '<input type="checkbox" data-id="policy_bl_mailbox" name="multi_select" value="' + item.prefid + '" />';
|
||||
@ -377,31 +472,42 @@ jQuery(function($){
|
||||
item.chkbox = '<input type="checkbox" disabled />';
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}),
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"state": {"enabled": true},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
}
|
||||
columns: [
|
||||
{
|
||||
// placeholder, so checkbox will not block child row toggle
|
||||
title: '',
|
||||
data: null,
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
data: 'chkbox',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
defaultContent: ''
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
data: 'prefid'
|
||||
},
|
||||
{
|
||||
title: lang.spamfilter_table_rule,
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
title:'Scope',
|
||||
data: 'object'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
$('body').on('click', 'span.footable-toggle', function () {
|
||||
event.stopPropagation();
|
||||
})
|
||||
|
||||
draw_sync_job_table();
|
||||
draw_app_passwd_table();
|
||||
draw_tla_table();
|
||||
draw_wl_policy_mailbox_table();
|
||||
draw_bl_policy_mailbox_table();
|
||||
last_logins('get');
|
||||
|
||||
// FIDO2 friendly name modal
|
||||
$('#fido2ChangeFn').on('show.bs.modal', function (e) {
|
||||
rename_link = $(e.relatedTarget)
|
||||
@ -433,4 +539,27 @@ jQuery(function($){
|
||||
$('#userFilterModal').on('hidden.bs.modal', function () {
|
||||
$('#user_sieve_filter').text(lang.loading);
|
||||
});
|
||||
|
||||
// detect element visibility changes
|
||||
function onVisible(element, callback) {
|
||||
$(element).ready(function() {
|
||||
element_object = document.querySelector(element)
|
||||
new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if(entry.intersectionRatio > 0) {
|
||||
callback(element_object);
|
||||
observer.disconnect();
|
||||
}
|
||||
});
|
||||
}).observe(element_object);
|
||||
});
|
||||
}
|
||||
|
||||
// Load only if the tab is visible
|
||||
onVisible("[id^=tla_table]", () => draw_tla_table());
|
||||
onVisible("[id^=bl_policy_mailbox_table]", () => draw_bl_policy_mailbox_table());
|
||||
onVisible("[id^=wl_policy_mailbox_table]", () => draw_wl_policy_mailbox_table());
|
||||
onVisible("[id^=sync_job_table]", () => draw_sync_job_table());
|
||||
onVisible("[id^=app_passwd_table]", () => draw_app_passwd_table());
|
||||
last_logins('get');
|
||||
});
|
||||
|
@ -87,7 +87,7 @@
|
||||
"relay_all": "Předávání všech příjemců",
|
||||
"relay_all_info": "<small>Pokud se rozhodnete <b>nepředávat</b> všechny příjemce, musíte přidat prázdnou mailovou schránku pro každého příjemce, který se má předávat.</small>",
|
||||
"relay_domain": "Předávání domény",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> U této domény lze pro konkrétní cíl nastavit transportní mapu. Není-li nastavena, použije se MX záznam.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> U této domény lze pro konkrétní cíl nastavit transportní mapu. Není-li nastavena, použije se MX záznam.",
|
||||
"relay_unknown_only": "Předávat jen neexistující schránky. Doručení do existujících proběhne lokálně.",
|
||||
"relayhost_wrapped_tls_info": "<b>Nepoužívejte</b> prosím porty s aktivním protokolem TLS (většinou port 465).<br>\r\nPoužívejte porty bez TLS a pak pošlete příkaz STARTTLS. Pravidlo k vynucení užití TLS lze vytvořit pomocí mapy TLS pravidel.",
|
||||
"select": "Prosím vyberte...",
|
||||
@ -579,7 +579,7 @@
|
||||
"relay_all": "Předávání všech příjemců",
|
||||
"relay_all_info": "<small>Pokud se rozhodnete <b>nepředávat</b> všechny příjemce, musíte přidat prázdnou mailovou schránku pro každého příjemce, který se má předávat.</small>",
|
||||
"relay_domain": "Předávání domény",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> U této domény lze pro konkrétní cíl nastavit transportní mapu. Není-li nastavena, použije se MX záznam.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> U této domény lze pro konkrétní cíl nastavit transportní mapu. Není-li nastavena, použije se MX záznam.",
|
||||
"relay_unknown_only": "Předávat jen neexistující schránky. Doručení do existujících proběhne lokálně.",
|
||||
"relayhost": "Předávání podle odesílatele",
|
||||
"remove": "Smazat",
|
||||
@ -587,7 +587,7 @@
|
||||
"save": "Uložit změny",
|
||||
"scope": "Rozsah",
|
||||
"sender_acl": "Povolit odesílání jako",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Kontrola odesílatele vypnuta</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Kontrola odesílatele vypnuta</span>",
|
||||
"sender_acl_info": "Má-li uživatel schránky A dovoleno odesílat jako uživatel schránky B, nezobrazuje se adresa odesílatele B v seznamu \"Od\" v SOGo automaticky.<br>\r\n Uživatel schránky A musí nejdříve v SOGo vytvořit pověření, jež umožní uživateli B vybrat svou adresu jako odesílatele. Tento mechanismus neplatí pro aliasy.",
|
||||
"sieve_desc": "Krátký popis",
|
||||
"sieve_type": "Typ filtru",
|
||||
@ -1097,7 +1097,7 @@
|
||||
"running": "Běží",
|
||||
"save": "Uložit změny",
|
||||
"save_changes": "Uložit změny",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Kontrola odesílatele vypnuta</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Kontrola odesílatele vypnuta</span>",
|
||||
"shared_aliases": "Sdílené aliasy",
|
||||
"shared_aliases_desc": "Na sdílené aliasy se neuplatňuje uživatelské nastavení jako filtr spamu nebo pravidla šifrování. Nastavení filtrování spamu může provádět jen správce pro celou doménu.",
|
||||
"show_sieve_filters": "Zobrazit aktivní sieve filtr uživatele",
|
||||
|
@ -83,7 +83,7 @@
|
||||
"relay_all": "Send alle modtagere videre",
|
||||
"relay_all_info": "↪ Hvis du vælger <b> ikke </b> at videresende alle modtagere, skal du tilføje et (\"blind\") postkasse til hver enkelt modtager, der skal videresendes.",
|
||||
"relay_domain": "Send dette domæne videre",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Du kan definere transportkort til en tilpasset destination for dette domæne. Hvis ikke indstillet, foretages der et MX-opslag.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Du kan definere transportkort til en tilpasset destination for dette domæne. Hvis ikke indstillet, foretages der et MX-opslag.",
|
||||
"relay_unknown_only": "Videresend kun ikke-eksisterende postkasser. Eksisterende postkasser leveres lokalt.",
|
||||
"relayhost_wrapped_tls_info": "Vær sød <b>ikke</b> at bruge TLS-indpakkede porte (bruges mest på port 465) .<br>\r\nBrug en ikke-pakket port, og udgiv STARTTLS. En TLS-politik til at håndhæve TLS kan oprettes i \"TLS policy maps\".",
|
||||
"select": "Vælg venligst...",
|
||||
@ -535,7 +535,7 @@
|
||||
"relay_all": "Send alle modtagere videre",
|
||||
"relay_all_info": "↪ Hvis du vælger <b>ikke</b> for at videresende alle modtagere skal du tilføje en (\"blind\") postkasse til hver enkelt modtager, der skal videresendes.",
|
||||
"relay_domain": "Send dette domæne videre",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Du kan definere transportkort til en tilpasset destination for dette domæne. Hvis den ikke er indstillet, foretages der et MX-opslag.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Du kan definere transportkort til en tilpasset destination for dette domæne. Hvis den ikke er indstillet, foretages der et MX-opslag.",
|
||||
"relay_unknown_only": "Videresend kun ikke-eksisterende postkasser. Eksisterende postkasser leveres lokalt.",
|
||||
"relayhost": "Afsenderafhængige transporter",
|
||||
"remove": "Fjerne",
|
||||
@ -543,7 +543,7 @@
|
||||
"save": "Gem ændringer",
|
||||
"scope": "Anvendelsesområde",
|
||||
"sender_acl": "Tillad at sende som",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Afsenderkontrol er deaktiveret</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Afsenderkontrol er deaktiveret</span>",
|
||||
"sender_acl_info": "Hvis postkassebruger A har tilladelse til at sende som postkassebruger B, vises afsenderadressen ikke automatisk som valgbar \"from\" felt i SOGo.<br>\r\n Postkassebruger B skal oprette en delegation i SOGo for at tillade postkassebruger A at vælge deres adresse som afsender. For at delegere en postkasse i SOGo skal du bruge menuen (tre prikker) til højre for dit postkassens navn øverst til venstre, mens du er i postvisningen. Denne adfærd gælder ikke for aliasadresser.",
|
||||
"sieve_desc": "Kort beskrivelse",
|
||||
"sieve_type": "Filtertype",
|
||||
@ -1005,7 +1005,7 @@
|
||||
"running": "Kører",
|
||||
"save": "Gem ændring",
|
||||
"save_changes": "Gem ændringer",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Afsender tjek er slået fra</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Afsender tjek er slået fra</span>",
|
||||
"shared_aliases": "Delte aliasadresser",
|
||||
"shared_aliases_desc": "Delt alias påvirkes ikke af brugerspecifikke indstillinger såsom spamfilter eller krypteringspolitik. Tilselementnde spamfiltre kan kun foretages af en administrator som en politik, der dækker hele domænet.",
|
||||
"show_sieve_filters": "Vis det aktive brugerfilter",
|
||||
|
@ -88,7 +88,7 @@
|
||||
"relay_all": "Alle Empfänger-Adressen relayen",
|
||||
"relay_all_info": "↪ Wenn <b>nicht</b> alle Empfänger-Adressen relayt werden sollen, müssen \"blinde\" Mailboxen für jede Adresse, die relayt werden soll, erstellt werden.",
|
||||
"relay_domain": "Diese Domain relayen",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Transport-Maps können erstellt werden, um individuelle Ziele für eine Relay-Domain zu definieren.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Transport-Maps können erstellt werden, um individuelle Ziele für eine Relay-Domain zu definieren.",
|
||||
"relay_unknown_only": "Nur nicht-lokale Mailboxen relayen. Existente Mailboxen werden weiterhin lokal zugestellt.",
|
||||
"relayhost_wrapped_tls_info": "Bitte <b>keine</b> \"TLS-wrapped Ports\" verwenden (etwa SMTPS via Port 465/tcp).<br>\r\nDer Transport wird stattdessen STARTTLS anfordern, um TLS zu verwenden. TLS kann unter \"TLS Policy Maps\" erzwungen werden.",
|
||||
"select": "Bitte auswählen",
|
||||
@ -465,6 +465,30 @@
|
||||
"value_missing": "Bitte alle Felder ausfüllen",
|
||||
"yotp_verification_failed": "Yubico OTP-Verifizierung fehlgeschlagen: %s"
|
||||
},
|
||||
"datatables": {
|
||||
"decimal": "",
|
||||
"emptyTable": "Keine Daten in der Tabelle vorhanden",
|
||||
"info": "_START_ bis _END_ von _TOTAL_ Einträgen",
|
||||
"infoEmpty": "0 bis 0 von 0 Einträgen",
|
||||
"infoFiltered": "(gefiltert von _MAX_ Einträgen)",
|
||||
"infoPostFix": "",
|
||||
"thousands": ".",
|
||||
"lengthMenu": "_MENU_ Einträge anzeigen",
|
||||
"loadingRecords": "Wird geladen...",
|
||||
"processing": "Bitte warten...",
|
||||
"search": "Suchen",
|
||||
"zeroRecords": "Keine Einträge vorhanden.",
|
||||
"paginate": {
|
||||
"first": "Erste",
|
||||
"previous": "Zurück",
|
||||
"next": "Nächste",
|
||||
"last": "Letzte"
|
||||
},
|
||||
"aria": {
|
||||
"sortAscending": ": aktivieren, um Spalte aufsteigend zu sortieren",
|
||||
"sortDescending": ": aktivieren, um Spalte absteigend zu sortieren"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"chart_this_server": "Chart (dieser Server)",
|
||||
"containers_info": "Container-Information",
|
||||
@ -584,7 +608,7 @@
|
||||
"relay_all": "Alle Empfänger-Adressen relayen",
|
||||
"relay_all_info": "↪ Wenn <b>nicht</b> alle Empfänger-Adressen relayt werden sollen, müssen \"blinde\" Mailboxen für jede Adresse, die relayt werden soll, erstellen werden.",
|
||||
"relay_domain": "Diese Domain relayen",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Transport Maps können erstellt werden, um individuelle Ziele für eine Relay Domain zu definieren.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Transport Maps können erstellt werden, um individuelle Ziele für eine Relay Domain zu definieren.",
|
||||
"relay_unknown_only": "Nur nicht-lokale Mailboxen relayen. Existente Mailboxen werden weiterhin lokal zugestellt.",
|
||||
"relayhost": "Senderabhängige Transport Maps",
|
||||
"remove": "Entfernen",
|
||||
@ -592,7 +616,7 @@
|
||||
"save": "Änderungen speichern",
|
||||
"scope": "Scope",
|
||||
"sender_acl": "Darf Nachrichten versenden als",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Absenderprüfung deaktiviert</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Absenderprüfung deaktiviert</span>",
|
||||
"sender_acl_info": "Wird einem Mailbox-Benutzer A der Versand als Mailbox-Benutzer B gestattet, so erscheint der Absender <b>nicht</b> automatisch in SOGo zur Auswahl.<br>\r\n In SOGo muss zusätzlich eine Delegation eingerichtet werden. Dieses Verhalten trifft nicht auf Alias-Adressen zu.",
|
||||
"sieve_desc": "Kurze Beschreibung",
|
||||
"sieve_type": "Filtertyp",
|
||||
@ -1103,7 +1127,7 @@
|
||||
"running": "Wird ausgeführt",
|
||||
"save": "Änderungen speichern",
|
||||
"save_changes": "Änderungen speichern",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Absenderprüfung deaktiviert</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Absenderprüfung deaktiviert</span>",
|
||||
"shared_aliases": "Geteilte Alias-Adressen",
|
||||
"shared_aliases_desc": "Geteilte Alias-Adressen werden nicht bei benutzerdefinierten Einstellungen, wie die des Spam-Filters oder der Verschlüsselungsrichtlinie, berücksichtigt. Entsprechende Spam-Filter können lediglich von einem Administrator vorgenommen werden.",
|
||||
"show_sieve_filters": "Zeige aktiven Filter des Benutzers",
|
||||
|
@ -88,7 +88,7 @@
|
||||
"relay_all": "Relay all recipients",
|
||||
"relay_all_info": "↪ If you choose <b>not</b> to relay all recipients, you will need to add a (\"blind\") mailbox for every single recipient that should be relayed.",
|
||||
"relay_domain": "Relay this domain",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_unknown_only": "Relay non-existing mailboxes only. Existing mailboxes will be delivered locally.",
|
||||
"relayhost_wrapped_tls_info": "Please do <b>not</b> use TLS-wrapped ports (mostly used on port 465).<br>\r\nUse any non-wrapped port and issue STARTTLS. A TLS policy to enforce TLS can be created in \"TLS policy maps\".",
|
||||
"select": "Please select...",
|
||||
@ -338,6 +338,7 @@
|
||||
"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",
|
||||
@ -465,6 +466,30 @@
|
||||
"value_missing": "Please provide all values",
|
||||
"yotp_verification_failed": "Yubico OTP verification failed: %s"
|
||||
},
|
||||
"datatables": {
|
||||
"decimal": "",
|
||||
"emptyTable": "No data available in table",
|
||||
"info": "Showing _START_ to _END_ of _TOTAL_ entries",
|
||||
"infoEmpty": "Showing 0 to 0 of 0 entries",
|
||||
"infoFiltered": "(filtered from _MAX_ total entries)",
|
||||
"infoPostFix": "",
|
||||
"thousands": ",",
|
||||
"lengthMenu": "Show _MENU_ entries",
|
||||
"loadingRecords": "Loading...",
|
||||
"processing": "",
|
||||
"search": "Search:",
|
||||
"zeroRecords": "No matching records found",
|
||||
"paginate": {
|
||||
"first": "First",
|
||||
"last": "Last",
|
||||
"next": "Next",
|
||||
"previous": "Previous"
|
||||
},
|
||||
"aria": {
|
||||
"sortAscending": ": activate to sort column ascending",
|
||||
"sortDescending": ": activate to sort column descending"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"chart_this_server": "Chart (this server)",
|
||||
"containers_info": "Container information",
|
||||
@ -584,7 +609,7 @@
|
||||
"relay_all": "Relay all recipients",
|
||||
"relay_all_info": "↪ If you choose <b>not</b> to relay all recipients, you will need to add a (\"blind\") mailbox for every single recipient that should be relayed.",
|
||||
"relay_domain": "Relay this domain",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_unknown_only": "Relay non-existing mailboxes only. Existing mailboxes will be delivered locally.",
|
||||
"relayhost": "Sender-dependent transports",
|
||||
"remove": "Remove",
|
||||
@ -592,7 +617,7 @@
|
||||
"save": "Save changes",
|
||||
"scope": "Scope",
|
||||
"sender_acl": "Allow to send as",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_info": "If mailbox user A is allowed to send as mailbox user B, the sender address is not automatically displayed as selectable \"from\" field in SOGo.<br>\r\n Mailbox user B needs to create a delegation in SOGo to allow mailbox user A to select their address as sender. To delegate a mailbox in SOGo, use the menu (three dots) to the right of your mailbox name in the upper left while in mail view. This behaviour does not apply to alias addresses.",
|
||||
"sieve_desc": "Short description",
|
||||
"sieve_type": "Filter type",
|
||||
@ -1111,7 +1136,7 @@
|
||||
"running": "Running",
|
||||
"save": "Save changes",
|
||||
"save_changes": "Save changes",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sender check is disabled</span>",
|
||||
"shared_aliases": "Shared alias addresses",
|
||||
"shared_aliases_desc": "Shared aliases are not affected by user specific settings such as the spam filter or encryption policy. Corresponding spam filters can only be made by an administrator as a domain-wide policy.",
|
||||
"show_sieve_filters": "Show active user sieve filter",
|
||||
|
@ -468,7 +468,7 @@
|
||||
"save": "Tallenna muutokset",
|
||||
"scope": "Laajuus",
|
||||
"sender_acl": "Salli lähettää nimellä",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Lähettäjän tarkistus on poistettu käytöstä</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Lähettäjän tarkistus on poistettu käytöstä</span>",
|
||||
"sender_acl_info": "Jos postilaatikon käyttäjän A sallitaan lähettävän postilaatikon käyttäjäksi B, lähettäjän osoitetta ei näytetä automaattisesti valittavana \"alkaen\" -kentässä SOGossa.<br>\r\nSähkö postilaatikon käyttäjän A on luotava valtuutus SOGoon, jotta sähkö postilaatikon käyttäjä b voi valita osoitteen lähettäjäksi. Tämä käyttäytyminen ei koske alias-osoitteita",
|
||||
"sieve_desc": "Lyhyt kuvaus",
|
||||
"sieve_type": "Suodattimen tyyppi",
|
||||
@ -831,7 +831,7 @@
|
||||
"remove": "Poistaa",
|
||||
"running": "Käynnissä",
|
||||
"save_changes": "Tallenna muutokset",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Lähettäjän tarkistus on poistettu käytöstä</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Lähettäjän tarkistus on poistettu käytöstä</span>",
|
||||
"shared_aliases": "Jaetut aliaksen osoitteet",
|
||||
"shared_aliases_desc": "Käyttäjäkohtaiset asetukset, kuten roska posti suodatin tai salaus käytäntö, eivät vaikuta jaettuihin alias-sähköposti tunnuksiin. Vastaavat roska posti suodattimet voi tehdä vain järjestelmänvalvoja verkkoaluelaajuisiksi käytännöiksi.",
|
||||
"show_sieve_filters": "Näytä aktiivisen käyttäjän sieve suodatin",
|
||||
|
@ -84,7 +84,7 @@
|
||||
"relay_all": "Relayer tous les destinataires",
|
||||
"relay_all_info": "↪ Si vous choissisez <b>de ne pas</b> relayer tous les destinataires, vous devez ajouter une boîte (\"aveugle\") pour chaque destinataire simple qui doit être relayé.",
|
||||
"relay_domain": "Relayer ce domaine",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Vous pouvez définir des cartes de transport vers une destination personnalisée pour ce domaine. sinon, une recherche MX sera effectuée.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Vous pouvez définir des cartes de transport vers une destination personnalisée pour ce domaine. sinon, une recherche MX sera effectuée.",
|
||||
"relay_unknown_only": "Relayer uniquement les boîtes inexistantes. Les boîtes existantes seront livrées localement.",
|
||||
"relayhost_wrapped_tls_info": "Veuillez <b>ne pas</b> utiliser des ports TLS wrappés (généralement utilisés sur le port 465).<br>\r\nUtilisez n'importe quel port non encapsulé et lancez STARTTLS. Une politique TLS pour appliquer TLS peut être créée dans \"Cartes de politique TLS\".",
|
||||
"select": "Veuillez sélectionner...",
|
||||
@ -549,7 +549,7 @@
|
||||
"relay_all": "Relayer tous les destinataires",
|
||||
"relay_all_info": "↪ Si vous <b>ne choissisez pas</b> de relayer tous les destinataires, vous devrez ajouter une boîte (\"aveugle\") pour chaque destinataire qui devrait être relayé.",
|
||||
"relay_domain": "Relayer ce domaine",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Vous pouvez définir des cartes de transport vers une destination personnalisée pour ce domaine. Si elle n’est pas configurée, une recherche MX sera effectuée.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Vous pouvez définir des cartes de transport vers une destination personnalisée pour ce domaine. Si elle n’est pas configurée, une recherche MX sera effectuée.",
|
||||
"relay_unknown_only": "Relais des boîtes non existantes seulement. Les boîtes existantes seront livrées localement..",
|
||||
"relayhost": "Transports dépendant de l’expéditeur",
|
||||
"remove": "Enlever",
|
||||
@ -557,7 +557,7 @@
|
||||
"save": "Enregistrer les modifications",
|
||||
"scope": "Portée",
|
||||
"sender_acl": "Permettre d’envoyer comme",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Le contrôle de l’expéditeur est désactivé</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Le contrôle de l’expéditeur est désactivé</span>",
|
||||
"sender_acl_info": "Si l’utilisateur de la boîte A est autorisé à envoyer en tant qu’utilisateur de la boîte B, l’adresse de l’expéditeur n’est pas automatiquement affichée comme sélectionnable du champ \"from\" dans SOGo.<br>\r\n L’utilisateur B de la boîte doit créer une délégation dans Sogo pour permettre à l’utilisateur A de la boîte de sélectionner son adresse comme expéditeur. Pour déléguer une boîte dans Sogo, utilisez le menu (trois points) à droite du nom de votre boîte dans le coin supérieur gauche dans la vue de courrier. Ce comportement ne s’applique pas aux adresses alias.",
|
||||
"sieve_desc": "Description courte",
|
||||
"sieve_type": "Type de filtre",
|
||||
@ -1024,7 +1024,7 @@
|
||||
"running": "En fonction",
|
||||
"save": "Sauvegarder les changements",
|
||||
"save_changes": "Sauvegarder les changements",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Le contrôle de l’expéditeur est désactivé</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Le contrôle de l’expéditeur est désactivé</span>",
|
||||
"shared_aliases": "Adresses alias partagées",
|
||||
"shared_aliases_desc": "Les alias partagés ne sont pas affectés par les paramètres spécifiques à l’utilisateur tels que le filtre anti-spam ou la politique de chiffrement. Les filtres anti-spam correspondants ne peuvent être effectués que par un administrateur en tant que politique de domaine.",
|
||||
"show_sieve_filters": "Afficher le filtre de tamis actif de l’utilisateur",
|
||||
|
@ -328,7 +328,7 @@
|
||||
"running": "Fut",
|
||||
"save": "Módosítások mentése",
|
||||
"save_changes": "Módosítások mentése",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Küldő ellenőrzése letiltva</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Küldő ellenőrzése letiltva</span>",
|
||||
"shared_aliases": "Megosztott alias címek",
|
||||
"show_sieve_filters": "Aktív felhasználói szűrők megjelenítése",
|
||||
"spam_aliases": "Ideiglenes email alias-ok",
|
||||
|
@ -86,7 +86,7 @@
|
||||
"relay_all": "Trasmettere a tutti i destinatari",
|
||||
"relay_all_info": "↪ Se si sceglie di <b>non</b> inviare a tutti i destinatari, è necessario aggiungere una casella di posta (\"blind\") per ogni singolo destinatario a cui deve essere inoltrato.",
|
||||
"relay_domain": "Trasmetti questo dominio",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Puoi definire mappe di trasporto verso una destinazione a tua scelta per questo dominio. Se non viene impostata, si guarderà il record MX.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Puoi definire mappe di trasporto verso una destinazione a tua scelta per questo dominio. Se non viene impostata, si guarderà il record MX.",
|
||||
"relay_unknown_only": "Inoltra solo caselle di posta inesistenti. I messaggi per gli indirizzi esistenti verranno consegnati localmente.",
|
||||
"relayhost_wrapped_tls_info": "Please do <b>not</b> use TLS-wrapped ports (mostly used on port 465).<br>\r\nUse any non-wrapped port and issue STARTTLS. A TLS policy to enforce TLS can be created in \"TLS policy maps\".",
|
||||
"select": "Si prega di selezionare...",
|
||||
@ -580,7 +580,7 @@
|
||||
"relay_all": "Relay tutti i destinatari",
|
||||
"relay_all_info": "↪ Se si sceglie di <b>non</b> inviare a tutti i destinatari, è necessario aggiungere una casella di posta (\"blind\") per ogni singolo destinatario a cui deve essere inoltrato.",
|
||||
"relay_domain": "Relay dominio",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_unknown_only": "Relay non-existing mailboxes only. Existing mailboxes will be delivered locally.",
|
||||
"relayhost": "Sender-dependent transports",
|
||||
"remove": "Rimuovi",
|
||||
@ -588,7 +588,7 @@
|
||||
"save": "Salva modifiche",
|
||||
"scope": "Scope",
|
||||
"sender_acl": "Consenti di inviare come",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_info": "If mailbox user A is allowed to send as mailbox user B, the sender address is not automatically displayed as selectable \"from\" field in SOGo.<br>\r\n Mailbox user B needs to create a delegation in SOGo to allow mailbox user A to select their address as sender. To delegate a mailbox in SOGo, use the menu (three dots) to the right of your mailbox name in the upper left while in mail view. This behaviour does not apply to alias addresses.",
|
||||
"sieve_desc": "Short description",
|
||||
"sieve_type": "Filter type",
|
||||
@ -1098,7 +1098,7 @@
|
||||
"running": "In esecuzione",
|
||||
"save": "Salva modifiche",
|
||||
"save_changes": "Salva modifiche",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sender check is disabled</span>",
|
||||
"shared_aliases": "Indirizzi alias condivisi",
|
||||
"shared_aliases_desc": "Shared aliases are not affected by user specific settings such as the spam filter or encryption policy. Corresponding spam filters can only be made by an administrator as a domain-wide policy.",
|
||||
"show_sieve_filters": "Show active user sieve filter",
|
||||
|
@ -83,7 +83,7 @@
|
||||
"relay_all": "모든 수신자에게 릴레이",
|
||||
"relay_all_info": "↪ 모든 수신자에게 릴레이를 하지 않으면, 릴레이 받아야 하는 모든 수신자에게 블라인드 메일함을 만들어야 합니다.",
|
||||
"relay_domain": "Relay this domain",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_unknown_only": "Relay non-existing mailboxes only. Existing mailboxes will be delivered locally.",
|
||||
"relayhost_wrapped_tls_info": "Please do <b>not</b> use TLS-wrapped ports (mostly used on port 465).<br>\r\nUse any non-wrapped port and issue STARTTLS. A TLS policy to enforce TLS can be created in \"TLS policy maps\".",
|
||||
"select": "선택하세요...",
|
||||
@ -526,7 +526,7 @@
|
||||
"relay_all": "Relay all recipients",
|
||||
"relay_all_info": "↪ If you choose <b>not</b> to relay all recipients, you will need to add a (\"blind\") mailbox for every single recipient that should be relayed.",
|
||||
"relay_domain": "Relay this domain",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> You can define transport maps for a custom destination for this domain. If not set, a MX lookup will be made.",
|
||||
"relay_unknown_only": "Relay non-existing mailboxes only. Existing mailboxes will be delivered locally.",
|
||||
"relayhost": "Sender-dependent transports",
|
||||
"remove": "Remove",
|
||||
@ -534,7 +534,7 @@
|
||||
"save": "Save changes",
|
||||
"scope": "Scope",
|
||||
"sender_acl": "Allow to send as",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_info": "If mailbox user A is allowed to send as mailbox user B, the sender address is not automatically displayed as selectable \"from\" field in SOGo.<br>\r\n Mailbox user B needs to create a delegation in SOGo to allow mailbox user A to select their address as sender. To delegate a mailbox in SOGo, use the menu (three dots) to the right of your mailbox name in the upper left while in mail view. This behaviour does not apply to alias addresses.",
|
||||
"sieve_desc": "Short description",
|
||||
"sieve_type": "Filter type",
|
||||
@ -955,7 +955,7 @@
|
||||
"running": "실행중",
|
||||
"save": "변경사항 저장",
|
||||
"save_changes": "변경사항 저장",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Sender check is disabled</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sender check is disabled</span>",
|
||||
"shared_aliases": "공동 사용 메일 주소 별칭",
|
||||
"shared_aliases_desc": "공동 사용 메일 별칭은 스팸 필터, 암호화 등 사용자의 설정의 영향을 받지 않습니다. 해당 주소의 스팸 필터는 관리자가 도메인 정책 형식으로 만들어야만 적용됩니다.",
|
||||
"show_sieve_filters": "활성화된 사용자 필터 표시",
|
||||
|
@ -84,7 +84,7 @@
|
||||
"relay_all": "Forward alle ontvangers",
|
||||
"relay_all_info": "↪ Wanneer er wordt gekozen om <b>niet</b> alle ontvangers te forwarden, dient er per ontvanger een lege mailbox aangemaakt te worden.",
|
||||
"relay_domain": "Forward dit domein",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Je kunt transport-maps aanmaken om een aangepaste bestemming in te stellen voor dit domein. Zo niet, zal er een MX-lookup plaatsvinden.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Je kunt transport-maps aanmaken om een aangepaste bestemming in te stellen voor dit domein. Zo niet, zal er een MX-lookup plaatsvinden.",
|
||||
"relay_unknown_only": "Forward uitsluitend niet-bestaande mailboxen. Bestaande mailboxen zullen lokaal afgeleverd worden.",
|
||||
"relayhost_wrapped_tls_info": "Gebruik <b>geen</b> in TLS verpakte poorten (meestal poort 465).<br>Gebruik een reguliere poort en initieer STARTTLS. Beleid om verleuteling te forceren kan worden ingesteld bij \"Globaal versleutelingsbeleid\".",
|
||||
"select": "Selecteer...",
|
||||
@ -544,7 +544,7 @@
|
||||
"relay_all": "Forward alle ontvangers",
|
||||
"relay_all_info": "↪ Wanneer er wordt gekozen om <b>niet</b> alle ontvangers te forwarden, dient er per ontvanger een lege mailbox aangemaakt te worden.",
|
||||
"relay_domain": "Forward dit domein",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Je kunt transport-maps aanmaken om een aangepaste bestemming in te stellen voor dit domein. Zo niet, zal er een MX-lookup plaatsvinden.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Je kunt transport-maps aanmaken om een aangepaste bestemming in te stellen voor dit domein. Zo niet, zal er een MX-lookup plaatsvinden.",
|
||||
"relay_unknown_only": "Forward uitsluitend niet-bestaande mailboxen. Bestaande mailboxen zullen lokaal afgeleverd worden.",
|
||||
"relayhost": "Afzendergebonden transport-maps",
|
||||
"remove": "Verwijder",
|
||||
@ -552,7 +552,7 @@
|
||||
"save": "Wijzigingen opslaan",
|
||||
"scope": "Scope",
|
||||
"sender_acl": "Sta toe om te verzenden als",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Verzendcontrole is uitgeschakeld</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Verzendcontrole is uitgeschakeld</span>",
|
||||
"sender_acl_info": "Wanneer mailboxgebruiker A toegestaan is te verzenden namens mailboxgebruiker B, zal het verzendadres niet automatisch worden weergegeven in het \"van\"-veld in SOGo. Mailboxgebruiker A dient hiervoor een aparte vermelding te maken in SOGo. Om een mailbox te delegeren in SOGo kan het menu (drie punten) aan de rechterkant van de naam van het mailbox linksboven worden gebruikt in de mailweergave. Dit is niet van toepassing op aliasadressen.",
|
||||
"sieve_desc": "Korte beschrijving",
|
||||
"sieve_type": "Filtertype",
|
||||
@ -1015,7 +1015,7 @@
|
||||
"running": "Wordt uitgevoerd",
|
||||
"save": "Sla wijzigingen op",
|
||||
"save_changes": "Wijzigingen opslaan",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Verzendcontrole is uitgeschakeld</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Verzendcontrole is uitgeschakeld</span>",
|
||||
"shared_aliases": "Gedeelde aliasadressen",
|
||||
"shared_aliases_desc": "Een gedeeld aliasadres wordt niet beïnvloed door gebruikersspecifieke instellingen. Een aangepast spamfilter kan eventueel worden ingesteld door een administrator.",
|
||||
"show_sieve_filters": "Toon actieve filters",
|
||||
|
@ -88,7 +88,7 @@
|
||||
"relay_all": "Retransmite toți destinatarii",
|
||||
"relay_all_info": "↪ Dacă alegi să <b>nu</b> retransmiți toți destinatarii, va trebui să adaugi o cutie poștală (\"oarbă\") pentru fiecare destinatar care trebuie retransmis.",
|
||||
"relay_domain": "Retransmite acest domeniu",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Puteți defini hărți de transport pentru o destinație personalizată pentru acest domeniu. Dacă nu este setat, se va face o căutare MX.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Puteți defini hărți de transport pentru o destinație personalizată pentru acest domeniu. Dacă nu este setat, se va face o căutare MX.",
|
||||
"relay_unknown_only": "Releu doar pentru cutiile poștale inexistente. Cutiile poștale existente vor fi livrate local.",
|
||||
"relayhost_wrapped_tls_info": "Vă rugăm să <b>nu</b> utilizați porturi înfășurate TLS (utilizate mai ales pe portul 465).<br>\r\nUtilizați orice port neînfășurat și emiteți STARTTLS. O politică TLS pentru impunerea TLS poate fi creată în \"Hărți ale politicii TLS\".",
|
||||
"select": "Te rog selectează...",
|
||||
@ -583,7 +583,7 @@
|
||||
"relay_all": "Retransmite toți destinatarii",
|
||||
"relay_all_info": "↪ Dacă alegi să <b>nu</b> retransmiți toți destinatarii, va trebui să adaugi o cutie poștală (\"oarbă\") pentru fiecare destinatar care trebuie retransmis.",
|
||||
"relay_domain": "Acest domeniu este releu",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Puteți defini hărți de transport pentru o destinație personalizată pentru acest domeniu. Dacă nu este setat, se va face o căutare MX.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Puteți defini hărți de transport pentru o destinație personalizată pentru acest domeniu. Dacă nu este setat, se va face o căutare MX.",
|
||||
"relay_unknown_only": "Releu doar pentru cutiile poștale inexistente. Cutiile poștale existente vor fi livrate local.",
|
||||
"relayhost": "Transporturi dependente de expeditor",
|
||||
"remove": "Elimină",
|
||||
@ -591,7 +591,7 @@
|
||||
"save": "Salvează modificările",
|
||||
"scope": "Scop",
|
||||
"sender_acl": "Permite trimiterea ca",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Verificarea expeditorului este dezactivată</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Verificarea expeditorului este dezactivată</span>",
|
||||
"sender_acl_info": "Dacă utilizatorului A de căsuță poștală îi este permis să trimită ca utilizatorul B, adresa expeditorului nu este afișată automat ca fiind câmp selectabil \"de la\" în SOGo.<br>\r\n Utilizatorul căsuței poștale B trebuie să creeze o delegație în SOGo pentru a permite utilizatorul cutiei poștale A să selecteze adresa ca expeditor. Pentru a delega o cutie poștală în SOGo, utilizați meniul (trei puncte) din dreapta numelui căsuței poștale în stânga sus, în timp ce vă aflați în vizualizarea e-mailului. Acest comportament nu se aplică adreselor alias.",
|
||||
"sieve_desc": "Descriere scurtă",
|
||||
"sieve_type": "Tip filtru",
|
||||
@ -1107,7 +1107,7 @@
|
||||
"running": "Funcţionare",
|
||||
"save": "Salvează modificările",
|
||||
"save_changes": "Salvează modificările",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Verificarea expeditorului este dezactivată</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Verificarea expeditorului este dezactivată</span>",
|
||||
"shared_aliases": "Adrese alias partajate",
|
||||
"shared_aliases_desc": "Aliasurile partajate nu sunt afectate de setările specifice utilizatorului, cum ar fi filtrul de spam sau politica de criptare. Filtrele de spam corespondente pot fi efectuate numai de către un administrator ca o politică la nivel de domeniu.",
|
||||
"show_sieve_filters": "Afișează filtrul activ al sitei de utilizatori",
|
||||
|
@ -87,7 +87,7 @@
|
||||
"relay_all": "Ретрансляция всех получателей",
|
||||
"relay_all_info": "↪<small>Если вы решите <b>не</b> ретранслировать всех получателей, вам нужно будет добавить (\"слепой\") почтовый адрес для каждого получателя, которого следует ретранслировать.</small>",
|
||||
"relay_domain": "Ретрансляция этого домена",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Инфо</div> Вы можете настроить собственный транспорт для домена. Если такой настройки нет, то доставка будет выполнена на основе MX записей.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Инфо</div> Вы можете настроить собственный транспорт для домена. Если такой настройки нет, то доставка будет выполнена на основе MX записей.",
|
||||
"relay_unknown_only": "Ретрансляция только не существующих почтовых ящиков. Почта к существующим почтовым ящикам будут доставляться локально.",
|
||||
"relayhost_wrapped_tls_info": "Пожалуйста <b>не</b> используйте TLS порты (в основном это 465 порт).<br>\r\nИспользуйте любой <b>не</b> TLS порт который поддерживает STARTTLS. А для защиты от downgrate атак - настройке принудительную политику TLS.",
|
||||
"select": "Пожалуйста, выберите...",
|
||||
@ -583,7 +583,7 @@
|
||||
"relay_all": "Ретрансляция всех получателей",
|
||||
"relay_all_info": "↪<small>Если вы решите <b>не</b> ретранслировать всех получателей, вам нужно будет добавить (\"слепой\") почтовый аккаунт для каждого получателя, которого следует ретранслировать.</small>",
|
||||
"relay_domain": "Ретрансляция этого домена",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Инфо</div> Вы можете настроить собственный транспорт для домена. Если такой настройки нет, то доставка будет выполнена на основе MX записей.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Инфо</div> Вы можете настроить собственный транспорт для домена. Если такой настройки нет, то доставка будет выполнена на основе MX записей.",
|
||||
"relay_unknown_only": "Ретрансляция только не существующих почтовых ящиков. Почта к существующим почтовым ящикам будут доставляться локально.",
|
||||
"relayhost": "Маршрутизация на основе отправителя",
|
||||
"remove": "Удалить",
|
||||
@ -591,7 +591,7 @@
|
||||
"save": "Сохранить изменения",
|
||||
"scope": "Область",
|
||||
"sender_acl": "Разрешить отправлять письма от имени",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Проверка отправителя отключена</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Проверка отправителя отключена</span>",
|
||||
"sender_acl_info": "Учтите, что если пользователю почтового аккаунта A разрешено отправлять от имени пользователя B, то адрес пользователя B не отобразится автоматически в списке \"Отправитель\" при написании писем в SOGo.<br>\r\n Пользователь почтового аккаунта B должен создать делегирование в SOGo, чтобы пользователь почтового аккаунта A мог выбрать его адрес в качестве отправителя. Делегирование находится в меню (троеточие) справа от имени почтового аккаунта в окне почты SOGo. Это поведение не относится к псевдонимам.",
|
||||
"sieve_desc": "Краткое описание",
|
||||
"sieve_type": "Тип фильтра",
|
||||
@ -1101,7 +1101,7 @@
|
||||
"running": "В процессе",
|
||||
"save": "Сохранить изменения",
|
||||
"save_changes": "Сохранить изменения",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Проверка отправителя отключена</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Проверка отправителя отключена</span>",
|
||||
"shared_aliases": "Общие псевдонимы",
|
||||
"shared_aliases_desc": "На общие псевдонимы не влияют пользовательские настройки, такие как фильтр нежелательной почты, или политика шифрования. Соответствующие фильтры нежелательной почты могут быть созданы только администратором в рамках политики домена.",
|
||||
"show_sieve_filters": "Показать включенные фильтры sieve",
|
||||
|
@ -87,7 +87,7 @@
|
||||
"relay_all": "Preposielať všetkým príjemcom",
|
||||
"relay_all_info": "↪ Ak sa rozhodnete <b>nepreposielať ďalej</b> všetkých príjemcov, budete musieť pridať (\"tzv. slepú\") mailovú schránku pre každého príjemcu.",
|
||||
"relay_domain": "Preposielať túto doménu",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Môžete definovať transportné mapy pre vlastné určenie cieľa pre túto doménu. Ak nie sú nastavené, použije sa MX záznam.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Môžete definovať transportné mapy pre vlastné určenie cieľa pre túto doménu. Ak nie sú nastavené, použije sa MX záznam.",
|
||||
"relay_unknown_only": "Preposielať len neexistujúce mailové schránky. Existujúce budú doručené lokálne.",
|
||||
"relayhost_wrapped_tls_info": "Prosím <b>nepoužívajte</b> TLS-wrapped porty (najviac používane na prote 465).<br>\r\nPoužite non-wrapped port a STARTTLS. Vynútené TLS pravidlá môžu byť vytvorené v \"TLS mapách\".",
|
||||
"select": "Prosím vyberte...",
|
||||
@ -582,7 +582,7 @@
|
||||
"relay_all": "Preposielať všetkých prijemcov",
|
||||
"relay_all_info": "↪ Ak sa rozhodnete <b>nepreposielať</b> všetkých príjemcov, budete musieť pridať (\"tzv. slepú\") mailovú schránku pre každého príjemcu.",
|
||||
"relay_domain": "Preposielať túto doménu",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Môžete definovať transportné mapy pre vlastné určenie cieľa pre túto doménu. Ak nie sú nastavené, použije sa MX záznam.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Môžete definovať transportné mapy pre vlastné určenie cieľa pre túto doménu. Ak nie sú nastavené, použije sa MX záznam.",
|
||||
"relay_unknown_only": "Preposielať len neexistujúce mailové schránky. Existujúce budú doručené lokálne.",
|
||||
"relayhost": "Transporty závislé na odosielateľovi",
|
||||
"remove": "Odstrániť",
|
||||
@ -590,7 +590,7 @@
|
||||
"save": "Uložiť zmeny",
|
||||
"scope": "Rozsah",
|
||||
"sender_acl": "Povoliť odosielanie ako",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Kontrola odosielateľa vypnutá</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Kontrola odosielateľa vypnutá</span>",
|
||||
"sender_acl_info": "Ak mailový používateľ A má povolenie poslať ako mailový používateľ B, adresa odosielateľa nieje automaticky viditeľná ako voliteľné \"from\" pole v SOGo.<br>\r\n Mailový používateľ B potrebuje vytvoriť delegáciu v SOGo, aby bol schopný mailový používateľ A vybrať jeho adresu ako odosielateľ. Na delegovanie mailovej adresy v SOGo, použite menu (tri bodky) napravo vášho mailového mena v hornom ľavom rohu, v prehľade správ. Toto neplatí pre alias adresy.",
|
||||
"sieve_desc": "Krátky popis",
|
||||
"sieve_type": "Typ filtru",
|
||||
@ -1105,7 +1105,7 @@
|
||||
"running": "Beží",
|
||||
"save": "Uložiť zmeny",
|
||||
"save_changes": "Uložiť zmeny",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Kontrola odosielateľa je pozastavená</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Kontrola odosielateľa je pozastavená</span>",
|
||||
"shared_aliases": "Zdieľané alias adresy",
|
||||
"shared_aliases_desc": "Zdieľané aliasy nie sú ovplyvnené používateľskými nastaveniami, ako spam filter alebo šifrovacie pravidlá. Zodpovedajúce spam filtre môžu byť vytvorené len administrátorom podľa podmienok domén.",
|
||||
"show_sieve_filters": "Zobraziť sieve filter aktívneho používateľa",
|
||||
|
@ -84,7 +84,7 @@
|
||||
"relay_all": "Vidarebefordra alla mottagaradresser",
|
||||
"relay_all_info": "↪ Om <b>inte</b> alla mottagare ska vidarebefordras måste (\"blinda\") postlådor skapas för varje adress som ska vidarebefordras.",
|
||||
"relay_domain": "Vidarebefordra denna domän",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Transportkartor kan skapas för att definiera enskilda destinationer på en relädomän.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Transportkartor kan skapas för att definiera enskilda destinationer på en relädomän.",
|
||||
"relay_unknown_only": "Vidarebefodra endast om det saknas en lokal postlåda. Existerar det en postlåda kommer det levereras lokalt.",
|
||||
"relayhost_wrapped_tls_info": "Använd <b>inte</b> TLS-bundna portar (exempelvis SMTPS via port 465).<br>\r\nTrafiken kommer istället transporteras med TLS genom att använda STARTTLS. En sådan TLS-policy kan skapas under \"TLS-policyföreskrifter\".",
|
||||
"select": "Välj ...",
|
||||
@ -560,7 +560,7 @@
|
||||
"relay_all": "Vidarebefordra alla mottagare",
|
||||
"relay_all_info": "↪ Om <b>inte</b> alla mottagare ska vidarebefordras måste (\"blinda\") postlådor skapas för varje adress som ska vidarebefordras.",
|
||||
"relay_domain": "Relädomän",
|
||||
"relay_transport_info": "<div class=\"label label-info\">Info</div> Transportkartor kan skapas för att definiera enskilda destinationer på en relädomän.",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Transportkartor kan skapas för att definiera enskilda destinationer på en relädomän.",
|
||||
"relay_unknown_only": "Vidarebefodra endast om det saknas en lokal postlåda. Existerar det en postlåda kommer det levereras lokalt.",
|
||||
"relayhost": "Reläserver",
|
||||
"remove": "Ta bort",
|
||||
@ -568,7 +568,7 @@
|
||||
"save": "Spara ändringar",
|
||||
"scope": "Omfattning",
|
||||
"sender_acl": "Tillåt att skicka som",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Avsändarkontroll är avaktiverad</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Avsändarkontroll är avaktiverad</span>",
|
||||
"sender_acl_info": "Om användaren A tillåts skicka som användaren B visas inte avsändaradressen automatiskt i \"från\" fältet i SOGo.<br>\r\n Användaren B måste skapa en delegation i SOGo för att låta användaren A välja Användaren B's adress som avsändare. För att delegera en postlåda i SOGo, gå till menyn (tre punkter) till höger om ditt namn uppe till vänster i postvyn. Detta gäller inte för aliasadresser.",
|
||||
"sieve_desc": "Kort beskrivning",
|
||||
"sieve_type": "Filtertyp",
|
||||
@ -1038,7 +1038,7 @@
|
||||
"running": "Kör",
|
||||
"save": "Spara ändringarna",
|
||||
"save_changes": "Spara ändringar",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">Kontrollen av avsändaren är inaktiverad</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Kontrollen av avsändaren är inaktiverad</span>",
|
||||
"shared_aliases": "Delade aliasadresses",
|
||||
"shared_aliases_desc": "Delade aliasadresser påverkas inte av användarspecifika inställningar som skräppostfilter eller krypteringspolicy. Motsvarande skräppostfilter kan endast göras av en administratör som en domänövergripande policy.",
|
||||
"show_sieve_filters": "Visa den aktuella användarens sieve-filter",
|
||||
|
@ -83,7 +83,7 @@
|
||||
"relay_all": "中继所有收件人",
|
||||
"relay_all_info": "↪ 如果<b>不</b>选择中继所有收件人,你将需要为每个应该中继的邮件添加一个 (\"盲\") 邮箱。",
|
||||
"relay_domain": "中继这个域名",
|
||||
"relay_transport_info": "<div class=\"label label-info\"></div> 你可以为此域名定义传输规则以自定义发件目标主机,否则遵照MX记录发送邮件。",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\"></div> 你可以为此域名定义传输规则以自定义发件目标主机,否则遵照MX记录发送邮件。",
|
||||
"relay_unknown_only": "只为不存在的邮箱地址中继。已存在的邮箱地址则在本地递送。",
|
||||
"relayhost_wrapped_tls_info": "请 <b>不要</b> 使用\"嵌套TLS\"的端口 (大多为端口465).<br>\r\n使用其他\"非嵌套\"的端口发起STARTTLS. 你可以在\"TLS策略规则\"中添加强制使用TLS的策略。",
|
||||
"select": "请选择...",
|
||||
@ -536,7 +536,7 @@
|
||||
"relay_all": "中继所有收件人",
|
||||
"relay_all_info": "↪ 如果<b>不</b>选择中继所有,你将需要为每个应该中继的邮件添加一个 (\"盲\") 邮箱。",
|
||||
"relay_domain": "中继这个域名",
|
||||
"relay_transport_info": "<div class=\"label label-info\"></div> 你可以为此域名定义传输规则以自定义发件目标主机,否则遵照MX记录发送邮件。",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\"></div> 你可以为此域名定义传输规则以自定义发件目标主机,否则遵照MX记录发送邮件。",
|
||||
"relay_unknown_only": "只为不存在的邮箱地址中继。已存在的邮箱地址则在本地递送。",
|
||||
"relayhost": "中继传输",
|
||||
"remove": "删除",
|
||||
@ -544,7 +544,7 @@
|
||||
"save": "保存更改",
|
||||
"scope": "范围",
|
||||
"sender_acl": "允许发送为",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">发件人检查已关闭</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">发件人检查已关闭</span>",
|
||||
"sender_acl_info": "如果允许邮箱用户A作为邮箱用户B发送邮件,发件人的地址不会在SOGo中\"来自\"区域自动地作为下拉可选项显示。<br>\r\n 邮箱用户B需要添加授权以允许邮箱用户A选择B的地址作为发件人;授权方法为,在SOGo中点击左上方邮箱地址右边的菜单按钮(三个点)并授权。",
|
||||
"sieve_desc": "简短描述",
|
||||
"sieve_type": "过滤器类型",
|
||||
@ -978,7 +978,7 @@
|
||||
"running": "运行中",
|
||||
"save": "保存更改",
|
||||
"save_changes": "保存更改",
|
||||
"sender_acl_disabled": "<span class=\"label label-danger\">发件人检查已关闭</span>",
|
||||
"sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">发件人检查已关闭</span>",
|
||||
"shared_aliases": "共享别名地址",
|
||||
"shared_aliases_desc": "用户设置如垃圾过滤器和加密策略等不会应用到共享别名地址。共享别名地址只能应用域名级别的垃圾过滤器且只能被管理员修改。",
|
||||
"show_sieve_filters": "显示启用的用户sieve过滤器",
|
||||
|
@ -40,6 +40,7 @@ $template_data = [
|
||||
'domains' => $domains,
|
||||
'mailboxes' => $mailboxes,
|
||||
'lang_mailbox' => json_encode($lang['mailbox']),
|
||||
'lang_datatables' => json_encode($lang['datatables']),
|
||||
];
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
|
@ -21,6 +21,7 @@ $template_data = [
|
||||
'role' => $role,
|
||||
'quarantine_settings' => $quarantine_settings,
|
||||
'lang_quarantine' => json_encode($lang['quarantine']),
|
||||
'lang_datatables' => json_encode($lang['datatables']),
|
||||
];
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
|
@ -1,68 +1,71 @@
|
||||
{% extends 'base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<ul class="nav nav-tabs responsive-tabs" role="tablist">
|
||||
<li class="dropdown active">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">{{ lang.admin.access }}<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="active" data-dont-remember="1" role="presentation"><a href="#tab-config-admins" aria-controls="tab-config-admins" role="tab" data-toggle="tab">{{ lang.admin.admins }}</a></li>
|
||||
<!-- <li role="presentation"><a href="#tab-config-ldap-admins" aria-controls="tab-config-ldap-admins" role="tab" data-toggle="tab">{{ lang.admin.admins_ldap }}</a></li> -->
|
||||
<li role="presentation"><a href="#tab-config-oauth2" aria-controls="tab-config-oauth2" role="tab" data-toggle="tab">{{ lang.admin.oauth2_apps }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-rspamd" aria-controls="tab-config-rspamd" role="tab" data-toggle="tab">Rspamd UI</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<div id="admin-content" class="responsive-tabs">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle active" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.access }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item active" data-bs-target="#tab-config-admins" aria-selected="false" aria-controls="tab-config-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins }}</button></li>
|
||||
<!-- <li><button class="dropdown-item" data-bs-target="#tab-config-ldap-admins" aria-controls="tab-config-ldap-admins" role="tab" data-bs-toggle="tab">{{ lang.admin.admins_ldap }}</button></li> -->
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-oauth2" aria-selected="false" aria-controls="tab-config-oauth2" role="tab" data-bs-toggle="tab">{{ lang.admin.oauth2_apps }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-rspamd" aria-selected="false" aria-controls="tab-config-rspamd" role="tab" data-bs-toggle="tab">Rspamd UI</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">{{ lang.admin.configuration }}<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li role="presentation"><a href="#tab-config-dkim" aria-controls="tab-config-dkim" role="tab" data-toggle="tab">{{ lang.admin.dkim_keys }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-fwdhosts" aria-controls="tab-config-fwdhosts" role="tab" data-toggle="tab">{{ lang.admin.forwarding_hosts }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-f2b" aria-controls="tab-config-f2b" role="tab" data-toggle="tab">{{ lang.admin.f2b_parameters }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-quarantine" aria-controls="tab-config-quarantine" role="tab" data-toggle="tab">{{ lang.admin.quarantine }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-quota" aria-controls="tab-config-quota" role="tab" data-toggle="tab">{{ lang.admin.quota_notifications }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-rsettings" aria-controls="tab-config-rsettings" role="tab" data-toggle="tab">{{ lang.admin.rspamd_settings_map }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-password-policy" aria-controls="tab-config-password-policy" role="tab" data-toggle="tab">{{ lang.admin.password_policy }}</a></li>
|
||||
<li role="presentation"><a href="#tab-config-customize" aria-controls="tab-config-customize" role="tab" data-toggle="tab">{{ lang.admin.customize }}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li role="presentation"><a href="#tab-routing" aria-controls="tab-routing" role="tab" data-toggle="tab">{{ lang.admin.routing }}</a></li>
|
||||
<li role="presentation"><a href="#tab-sys-mails" aria-controls="tab-sys-mails" role="tab" data-toggle="tab">{{ lang.admin.sys_mails }}</a></li>
|
||||
<li role="presentation"><a href="#tab-mailq" aria-controls="tab-mailq" role="tab" data-toggle="tab">{{ lang.admin.queue_manager }}</a></li>
|
||||
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">{{ lang.admin.rspamd_global_filters }}
|
||||
<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li role="presentation"><a href="#tab-globalfilter-regex" aria-controls="tab-globalfilter-regex" role="tab" data-toggle="tab">{{ lang.admin.regex_maps }}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.configuration }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-dkim" aria-selected="false" aria-controls="tab-config-dkim" role="tab" data-bs-toggle="tab">{{ lang.admin.dkim_keys }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-fwdhosts" aria-selected="false" aria-controls="tab-config-fwdhosts" role="tab" data-bs-toggle="tab">{{ lang.admin.forwarding_hosts }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-f2b" aria-selected="false" aria-controls="tab-config-f2b" role="tab" data-bs-toggle="tab">{{ lang.admin.f2b_parameters }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-quarantine" aria-selected="false" aria-controls="tab-config-quarantine" role="tab" data-bs-toggle="tab">{{ lang.admin.quarantine }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-quota" aria-selected="false" aria-controls="tab-config-quota" role="tab" data-bs-toggle="tab">{{ lang.admin.quota_notifications }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-rsettings" aria-selected="false" aria-controls="tab-config-rsettings" role="tab" data-bs-toggle="tab">{{ lang.admin.rspamd_settings_map }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-password-policy" aria-selected="false" aria-controls="tab-config-password-policy" role="tab" data-bs-toggle="tab">{{ lang.admin.password_policy }}</button></li>
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-config-customize" aria-selected="false" aria-controls="tab-config-customize" role="tab" data-bs-toggle="tab">{{ lang.admin.customize }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-target="#tab-routing" aria-selected="false" aria-controls="tab-routing" role="tab" data-bs-toggle="tab">{{ lang.admin.routing }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-target="#tab-sys-mails" aria-selected="false" aria-controls="tab-sys-mails" role="tab" data-bs-toggle="tab">{{ lang.admin.sys_mails }}</button></li>
|
||||
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-target="#tab-mailq" aria-selected="false" aria-controls="tab-mailq" role="tab" data-bs-toggle="tab">{{ lang.admin.queue_manager }}</button></li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">{{ lang.admin.rspamd_global_filters }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><button class="dropdown-item" data-bs-target="#tab-globalfilter-regex" aria-selected="false" aria-controls="tab-globalfilter-regex" role="tab" data-bs-toggle="tab">{{ lang.admin.regex_maps }}</button></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="tab-content" style="padding-top:20px">
|
||||
{% include 'admin/tab-config-admins.twig' %}
|
||||
{# {% include 'admin/tab-ldap.twig' %} #}
|
||||
{% include 'admin/tab-config-oauth2.twig' %}
|
||||
{% include 'admin/tab-config-rspamd.twig' %}
|
||||
{% include 'admin/tab-routing.twig' %}
|
||||
{% include 'admin/tab-config-dkim.twig' %}
|
||||
{% include 'admin/tab-config-fwdhosts.twig' %}
|
||||
{% include 'admin/tab-config-f2b.twig' %}
|
||||
{% include 'admin/tab-config-quarantine.twig' %}
|
||||
{% include 'admin/tab-config-quota.twig' %}
|
||||
{% include 'admin/tab-config-rsettings.twig' %}
|
||||
{% include 'admin/tab-config-customize.twig' %}
|
||||
{% include 'admin/tab-config-password-policy.twig' %}
|
||||
{% include 'admin/tab-sys-mails.twig' %}
|
||||
{% include 'admin/tab-mailq.twig' %}
|
||||
{% include 'admin/tab-globalfilter-regex.twig' %}
|
||||
</div>
|
||||
</div> <!-- /col-md-12 -->
|
||||
</div> <!-- /row -->
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="tab-content" style="padding-top:20px">
|
||||
{% include 'admin/tab-config-admins.twig' %}
|
||||
{% include 'admin/tab-ldap.twig' %}
|
||||
{% include 'admin/tab-config-oauth2.twig' %}
|
||||
{% include 'admin/tab-config-rspamd.twig' %}
|
||||
{% include 'admin/tab-routing.twig' %}
|
||||
{% include 'admin/tab-config-dkim.twig' %}
|
||||
{% include 'admin/tab-config-fwdhosts.twig' %}
|
||||
{% include 'admin/tab-config-f2b.twig' %}
|
||||
{% include 'admin/tab-config-quarantine.twig' %}
|
||||
{% include 'admin/tab-config-quota.twig' %}
|
||||
{% include 'admin/tab-config-rsettings.twig' %}
|
||||
{% include 'admin/tab-config-customize.twig' %}
|
||||
{% include 'admin/tab-config-password-policy.twig' %}
|
||||
{% include 'admin/tab-sys-mails.twig' %}
|
||||
{% include 'admin/tab-mailq.twig' %}
|
||||
{% include 'admin/tab-globalfilter-regex.twig' %}
|
||||
</div>
|
||||
</div> <!-- /col-md-12 -->
|
||||
</div> <!-- /row -->
|
||||
|
||||
{% include 'modals/admin.twig' %}
|
||||
|
||||
<script type='text/javascript'>
|
||||
var lang = {{ lang_admin|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var admin_username = '{{ mailcow_cc_username }}';
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = '{{ pagination_size }}';
|
||||
|
@ -1,248 +1,253 @@
|
||||
<div role="tabpanel" class="tab-pane active" id="tab-config-admins">
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading xs-show">{{ lang.admin.admin_details }}</div>
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-condensed" id="adminstable"></table>
|
||||
</div>
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" id="toggle_multi_select_all" data-id="admins" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default dropdown-toggle" data-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }} <span class="caret"></span></a>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"disable_tfa":"1"}' href="#">{{ lang.tfa.disable_tfa }}</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="delete_selected" data-id="admins" data-api-url='delete/admin' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-id="add_admin" data-toggle="modal" data-target="#addAdminModal" href="#"><i class="bi bi-person-plus-fill"></i> {{ lang.admin.add_admin }}</a>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane fade show active" id="tab-config-admins" role="tabpanel" aria-labelledby="tab-config-admins">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-danger text-white d-flex">
|
||||
<button class="btn d-md-none text-white flex-grow-1 text-start" data-bs-target="#collapse-tab-config-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-admins">
|
||||
{{ lang.admin.admin_details }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.admin_details }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-admins" class="card-body collapse show" data-bs-parent="#admin-content">
|
||||
<table id="adminstable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin mb-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="admins" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="admins" data-api-url='edit/admin' data-api-attr='{"disable_tfa":"1"}' href="#">{{ lang.tfa.disable_tfa }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="admins" data-api-url='delete/admin' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" data-id="add_admin" data-bs-toggle="modal" data-bs-target="#addAdminModal" href="#"><i class="bi bi-person-plus-fill"></i> {{ lang.admin.add_admin }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# TFA #}
|
||||
<legend style="margin-top:20px">
|
||||
{{ lang.tfa.tfa }}
|
||||
</legend>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-5 text-right">{{ lang.tfa.tfa }}:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<p id="tfa_pretty">{{ tfa_data.pretty }}</p>
|
||||
{% include 'tfa_keys.twig' %}
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-5 text-right">{{ lang.tfa.set_tfa }}:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<select data-style="btn btn-sm dropdown-toggle bs-placeholder btn-default" data-width="fit" id="selectTFA" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option value="yubi_otp">{{ lang.tfa.yubi_otp }}</option>
|
||||
<option value="webauthn">{{ lang.tfa.webauthn }}</option>
|
||||
<option value="totp">{{ lang.tfa.totp }}</option>
|
||||
<option value="none">{{ lang.tfa.none }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# FIDO2 #}
|
||||
<legend style="margin-top:20px">
|
||||
<i class="bi bi-shield-fill-check"></i>
|
||||
{{ lang.fido2.fido2_auth }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-12 text-right text-xs-left space20">{{ lang.fido2.known_ids }}:</div>
|
||||
<div class="col-sm-9 col-xs-12">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-condensed" id="fido2_keys">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th style="min-width:240px;text-align: right">{{ lang.admin.action }}</th>
|
||||
</tr>
|
||||
{% include 'fido2.twig' %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{# TFA #}
|
||||
<legend style="margin-top:20px">
|
||||
{{ lang.tfa.tfa }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.tfa.tfa }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<p id="tfa_pretty">{{ tfa_data.pretty }}</p>
|
||||
{% include 'tfa_keys.twig' %}
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.tfa.set_tfa }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<select data-style="btn btn-sm dropdown-toggle bs-placeholder btn-secondary" data-width="fit" id="selectTFA" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option value="yubi_otp">{{ lang.tfa.yubi_otp }}</option>
|
||||
<option value="webauthn">{{ lang.tfa.webauthn }}</option>
|
||||
<option value="totp">{{ lang.tfa.totp }}</option>
|
||||
<option value="none">{{ lang.tfa.none }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<div class="btn-group nowrap mass-actions-admin">
|
||||
<button class="btn btn-sm btn-primary visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline" id="register-fido2">{{ lang.fido2.set_fido2 }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-lg btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" id="register-fido2-touchid" style="line-height:1.4;"><i class="bi bi-apple"></i> {{ lang.fido2.set_fido2_touchid }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{# FIDO2 #}
|
||||
<legend style="margin-top:20px">
|
||||
<i class="bi bi-shield-fill-check"></i>
|
||||
{{ lang.fido2.fido2_auth }}</legend><hr />
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-3 col-12 text-sm-end text-start mb-4">{{ lang.fido2.known_ids }}:</div>
|
||||
<div class="col-sm-9 col-12">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-condensed" id="fido2_keys">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th style="min-width:240px;text-align: right">{{ lang.admin.action }}</th>
|
||||
</tr>
|
||||
{% include 'fido2.twig' %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="row" id="status-fido2">
|
||||
<div class="col-sm-3 col-xs-5 text-right">{{ lang.fido2.register_status }}:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
<div id="fido2-alerts">-</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group nowrap mass-actions-admin">
|
||||
<button class="btn btn-sm btn-primary d-block d-sm-inline" id="register-fido2">{{ lang.fido2.set_fido2 }}</button>
|
||||
<button type="button" class="btn btn-sm btn-xs-lg btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" id="register-fido2-touchid"><i class="bi bi-apple"></i> {{ lang.fido2.set_fido2_touchid }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<legend style="cursor:pointer;margin-top:40px" data-target="#license" unselectable="on" data-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.guid_and_license }}
|
||||
</legend>
|
||||
<div id="license" class="collapse">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="guid">{{ lang.admin.guid }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">
|
||||
<i class="bi bi-suit-heart{% if gal.valid == true %}-fill text-danger{% endif %}"></i>
|
||||
</span>
|
||||
<input type="text" id="guid" class="form-control" value="{{ license_guid }}" readonly>
|
||||
</div>
|
||||
<p class="help-block">
|
||||
{{ lang.admin.customer_id }}: {{ gal.c|default('?')|raw }} -
|
||||
{{ lang.admin.service_id }}: {{ gal.s|default('?')|raw }} -
|
||||
{{ lang.admin.sal_level }}: {{ gal.m|default('?')|raw }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<p class="help-block">{{ lang.admin.license_info|raw }}</p>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" name="license_validate_now" type="submit" href="#">{{ lang.admin.validate_license_now }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="row mb-3" id="status-fido2">
|
||||
<div class="col-sm-3 col-5 text-end">{{ lang.fido2.register_status }}:</div>
|
||||
<div class="col-sm-9 col-7">
|
||||
<div id="fido2-alerts">-</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<legend style="cursor:pointer;" data-target="#admin_api" unselectable="on" data-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> API
|
||||
</legend>
|
||||
<div id="admin_api" class="collapse">
|
||||
<legend style="cursor:pointer;margin-top:40px" data-bs-target="#license" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.guid_and_license }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="license" class="collapse">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<p class="help-block">{{ lang.admin.api_info|raw }}</p>
|
||||
<label class="control-label col-sm-3" for="guid">{{ lang.admin.guid }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<i class="bi bi-suit-heart{% if gal.valid == true %}-fill text-danger{% endif %}"></i>
|
||||
</span>
|
||||
<input type="text" id="guid" class="form-control" value="{{ license_guid }}" readonly>
|
||||
</div>
|
||||
<p class="text-muted">
|
||||
{{ lang.admin.customer_id }}: {{ gal.c|default('?')|raw }} -
|
||||
{{ lang.admin.service_id }}: {{ gal.s|default('?')|raw }} -
|
||||
{{ lang.admin.sal_level }}: {{ gal.m|default('?')|raw }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="bi bi-file-earmark-arrow-down"></i> {{ lang.admin.api_read_only }}</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="allow_from_ro">{{ lang.admin.api_allow_from }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_ro" {% if api.ro.skip_ip_check %}disabled{% endif %} required>{{ api.ro.allow_from }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="skip_ip_check" id="skip_ip_check_ro" {% if api.ro.skip_ip_check %}checked{% endif %}> {{ lang.admin.api_skip_ip_check }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3">{{ lang.admin.api_key }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<pre>{{ api.ro.api_key|default('-') }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="active" {% if api.ro.active %}checked{% endif %}> {{ lang.admin.activate_api }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" name="admin_api[ro]" type="submit" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default admin-ays-dialog" name="admin_api_regen_key[ro]" type="submit" href="#" {% if not api.ro.api_key %}disabled{% endif %}>{{ lang.admin.regen_api_key }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<p class="text-muted">{{ lang.admin.license_info|raw }}</p>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" name="license_validate_now" type="submit" href="#">{{ lang.admin.validate_license_now }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="bi bi-file-earmark-diff"></i> {{ lang.admin.api_read_write }}</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="allow_from_rw">{{ lang.admin.api_allow_from }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_rw" {% if api.rw.skip_ip_check %}disabled{% endif %} required>{{ api.rw.allow_from }}</textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<legend style="cursor:pointer;margin-top:20px" data-bs-target="#admin_api" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> API
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="admin_api" class="collapse">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<p class="text-muted">{{ lang.admin.api_info|raw }}</p>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><i class="bi bi-file-earmark-arrow-down"></i> {{ lang.admin.api_read_only }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="allow_from_ro">{{ lang.admin.api_allow_from }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_ro" {% if api.ro.skip_ip_check %}disabled{% endif %} required>{{ api.ro.allow_from }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="skip_ip_check" id="skip_ip_check_ro" {% if api.ro.skip_ip_check %}checked{% endif %}> {{ lang.admin.api_skip_ip_check }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3">{{ lang.admin.api_key }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" value="{{ api.ro.api_key|default('-') }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="active" {% if api.ro.active %}checked{% endif %}> {{ lang.admin.activate_api }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" name="admin_api[ro]" type="submit" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary admin-ays-dialog" name="admin_api_regen_key[ro]" type="submit" href="#" {% if not api.ro.api_key %}disabled{% endif %}>{{ lang.admin.regen_api_key }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="skip_ip_check" id="skip_ip_check_rw" {% if api.rw.skip_ip_check %}checked{% endif %}> {{ lang.admin.api_skip_ip_check }}
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><i class="bi bi-file-earmark-diff"></i> {{ lang.admin.api_read_write }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="allow_from_rw">{{ lang.admin.api_allow_from }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_rw" {% if api.rw.skip_ip_check %}disabled{% endif %} required>{{ api.rw.allow_from }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="skip_ip_check" id="skip_ip_check_rw" {% if api.rw.skip_ip_check %}checked{% endif %}> {{ lang.admin.api_skip_ip_check }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3" for="admin_api_key">{{ lang.admin.api_key }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" value="{{ api.rw.api_key|default('-') }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="active" {% if api.rw.active %}checked{% endif %}> {{ lang.admin.activate_api }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" name="admin_api[rw]" type="submit" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary admin-ays-dialog" name="admin_api_regen_key[rw]" type="submit" {% if not api.rw.api_key %}disabled{% endif %} href="#">{{ lang.admin.regen_api_key }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="admin_api_key">{{ lang.admin.api_key }}:</label>
|
||||
<div class="col-sm-9">
|
||||
<pre>{{ api.rw.api_key|default('-') }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="active" {% if api.rw.active %}checked{% endif %}> {{ lang.admin.activate_api }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" name="admin_api[rw]" type="submit" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default admin-ays-dialog" name="admin_api_regen_key[rw]" type="submit" {% if not api.rw.api_key %}disabled{% endif %} href="#">{{ lang.admin.regen_api_key }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading xs-show">{{ lang.admin.domain_admins }}</div>
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-condensed" id="domainadminstable"></table>
|
||||
</div>
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dadmins" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-dadmins">
|
||||
{{ lang.admin.domain_admins }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.domain_admins }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-dadmins" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<table id="domainadminstable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" id="toggle_multi_select_all" data-id="domain_admins" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default dropdown-toggle" data-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }} <span class="caret"></span></a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="domain_admins" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"disable_tfa":"1"}' href="#">{{ lang.tfa.disable_tfa }}</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="delete_selected" data-id="domain_admins" data-api-url='delete/domain-admin' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"disable_tfa":"1"}' href="#">{{ lang.tfa.disable_tfa }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="domain_admins" data-api-url='delete/domain-admin' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
<a class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-id="add_domain_admin" data-toggle="modal" data-target="#addDomainAdminModal" href="#"><i class="bi bi-person-plus-fill"></i> {{ lang.admin.add_domain_admin }}</a>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" data-id="add_domain_admin" data-bs-toggle="modal" data-bs-target="#addDomainAdminModal" href="#"><i class="bi bi-person-plus-fill"></i> {{ lang.admin.add_domain_admin }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,13 +1,18 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-customize">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.customize }}</div>
|
||||
<div class="panel-body">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_logo }}</legend>
|
||||
<p class="help-block">{{ lang.admin.logo_info }}</p>
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-customize" role="tabpanel" aria-labelledby="tab-config-customize">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-customize" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-customize">
|
||||
{{ lang.admin.customize }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-customize" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<legend><i class="bi bi-file-image"></i> {{ lang.admin.change_logo }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.logo_info }}</p>
|
||||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<input type="file" name="main_logo" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml"><br>
|
||||
<button name="submit_main_logo" type="submit" class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default"><i class="bi bi-upload"></i> {{ lang.admin.upload }}</button>
|
||||
<input class="mb-4" type="file" name="main_logo" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml"><br>
|
||||
<button name="submit_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-upload"></i> {{ lang.admin.upload }}</button>
|
||||
</p>
|
||||
</form>
|
||||
{% if logo %}
|
||||
@ -16,20 +21,20 @@
|
||||
<div class="thumbnail">
|
||||
<img class="img-thumbnail" src="{{ logo }}" alt="mailcow logo">
|
||||
<div class="caption">
|
||||
<span class="label label-info">{{ logo_specs.geometry.width }}x{{ logo_specs.geometry.height }} px</span>
|
||||
<span class="label label-info">{{ logo_specs.mimetype }}</span>
|
||||
<span class="label label-info">{{ logo_specs.fileSize }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.geometry.width }}x{{ logo_specs.geometry.height }} px</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.mimetype }}</span>
|
||||
<span class="badge fs-5 bg-info">{{ logo_specs.fileSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<form class="form-inline" role="form" method="post">
|
||||
<p><button name="reset_main_logo" type="submit" class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default">{{ lang.admin.reset_default }}</button></p>
|
||||
<p><button name="reset_main_logo" type="submit" class="btn btn-sm d-block d-sm-inline btn-secondary">{{ lang.admin.reset_default }}</button></p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<legend>{{ lang.admin.app_links }}</legend>
|
||||
<p class="help-block">{{ lang.admin.merged_vars_hint|raw }}</p>
|
||||
<legend>{{ lang.admin.app_links }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.merged_vars_hint|raw }}</p>
|
||||
<form class="form-inline" data-id="app_links" role="form" method="post">
|
||||
<table class="table table-condensed" style="white-space: nowrap;" id="app_link_table">
|
||||
<tr>
|
||||
@ -42,7 +47,7 @@
|
||||
<tr>
|
||||
<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required value="{{ key }}"></td>
|
||||
<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required value="{{ val }}"></td>
|
||||
<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-default" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
@ -55,39 +60,50 @@
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" type="button" id="add_app_link_row">{{ lang.admin.add_row }}</button>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" type="button" id="add_app_link_row">{{ lang.admin.add_row }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
<legend data-target="#ui_texts" style="padding-top:20px" unselectable="on">{{ lang.admin.ui_texts }}</legend>
|
||||
<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="form-group">
|
||||
<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 }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label for="uitests_main_name">{{ lang.admin.main_name }}:</label>
|
||||
<input type="text" class="form-control" id="uitests_main_name" name="main_name" placeholder="mailcow UI" value="{{ ui_texts.main_name|raw }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label for="uitests_apps_name">{{ lang.admin.apps_name }}:</label>
|
||||
<input type="text" class="form-control" id="uitests_apps_name" name="apps_name" placeholder="{{ lang.header.apps }}" value="{{ ui_texts.apps_name|raw }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="help_text">{{ lang.admin.help_text }}:</label>
|
||||
<textarea class="form-control" id="help_text" name="help_text" rows="7">{{ ui_texts.help_text|raw }}</textarea>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<p class="help-block">{{ lang.admin.ui_header_announcement_help }}</p>
|
||||
<div>
|
||||
<p class="text-muted">{{ lang.admin.ui_header_announcement_help }}</p>
|
||||
<label for="ui_announcement_type">{{ lang.admin.ui_header_announcement }}:</label>
|
||||
<p><select multiple data-width="100%" id="ui_announcement_type" name="ui_announcement_type" class="selectpicker show-tick" data-max-options="1" title="{{ lang.admin.ui_header_announcement_select }}">
|
||||
<option {% if ui_texts.ui_announcement_type == 'info' %}selected{% endif %} value="info">{{ lang.admin.ui_header_announcement_type_info }}</option>
|
||||
<option {% if ui_texts.ui_announcement_type == 'warning' %}selected{% endif %} value="warning">{{ lang.admin.ui_header_announcement_type_warning }}</option>
|
||||
<option {% if ui_texts.ui_announcement_type == 'danger' %}selected{% endif %} value="danger">{{ lang.admin.ui_header_announcement_type_danger }}</option>
|
||||
</select></p>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 col-lg-4 col-xl-3">
|
||||
<p><select multiple data-width="100%" id="ui_announcement_type" name="ui_announcement_type" class="selectpicker show-tick" data-max-options="1" title="{{ lang.admin.ui_header_announcement_select }}">
|
||||
<option {% if ui_texts.ui_announcement_type == 'info' %}selected{% endif %} value="info">{{ lang.admin.ui_header_announcement_type_info }}</option>
|
||||
<option {% if ui_texts.ui_announcement_type == 'warning' %}selected{% endif %} value="warning">{{ lang.admin.ui_header_announcement_type_warning }}</option>
|
||||
<option {% if ui_texts.ui_announcement_type == 'danger' %}selected{% endif %} value="danger">{{ lang.admin.ui_header_announcement_type_danger }}</option>
|
||||
</select></p>
|
||||
</div>
|
||||
</div>
|
||||
<p><textarea class="form-control" id="ui_announcement_text" name="ui_announcement_text" rows="7">{{ ui_texts.ui_announcement_text }}</textarea></p>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
@ -96,11 +112,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="ui_footer">{{ lang.admin.ui_footer }}:</label>
|
||||
<textarea class="form-control" id="ui_footer" name="ui_footer" rows="7">{{ ui_texts.ui_footer }}</textarea>
|
||||
</div>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,65 +1,72 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-dkim">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.dkim_keys }}</div>
|
||||
<div class="panel-body">
|
||||
<div class="btn-group" data-toggle="button" style="margin-bottom: 20px;">
|
||||
<a class="btn btn-sm btn-xs-third visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default active" href="#" data-toggle="collapse" data-target=".dkim_key_valid">{{ lang.admin.dkim_key_valid }}</a>
|
||||
<a class="btn btn-sm btn-xs-third visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default active" href="#" data-toggle="collapse" data-target=".dkim_key_unused">{{ lang.admin.dkim_key_unused }}</a>
|
||||
<a class="btn btn-sm btn-xs-third visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default active" href="#" data-toggle="collapse" data-target=".dkim_key_missing">{{ lang.admin.dkim_key_missing }}</a>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-dkim" role="tabpanel" aria-labelledby="tab-config-dkim">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dkim" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-dkim">
|
||||
{{ lang.admin.dkim_keys }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.dkim_keys }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-dkim" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<div class="btn-group" data-bs-toggle="button" style="margin-bottom: 20px;">
|
||||
<a class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary active" href="#" data-bs-toggle="collapse" data-bs-target=".dkim_key_valid">{{ lang.admin.dkim_key_valid }}</a>
|
||||
<a class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary active" href="#" data-bs-toggle="collapse" data-bs-target=".dkim_key_unused">{{ lang.admin.dkim_key_unused }}</a>
|
||||
<a class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary active" href="#" data-bs-toggle="collapse" data-bs-target=".dkim_key_missing">{{ lang.admin.dkim_key_missing }}</a>
|
||||
</div>
|
||||
{% for domain, domain_data in dkim_domains %}
|
||||
{% if domain_data.dkim %}
|
||||
<div class="row collapse in dkim_key_valid">
|
||||
<div class="row collapse show dkim_key_valid">
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="{{ domain }}"></div>
|
||||
<div class="col-md-3">
|
||||
<p>{{ lang.admin.domain }}: <strong>{{ domain }}</strong>
|
||||
<p class="dkim-label"><span class="label label-success">{{ lang.admin.dkim_key_valid }}</span></p>
|
||||
<p class="dkim-label"><span class="label label-primary">{{ lang.admin.dkim_domains_selector }} '{{ domain_data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="label label-info">{{ domain_data.dkim.length }} bit</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-success">{{ lang.admin.dkim_key_valid }}</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-primary">{{ lang.admin.dkim_domains_selector }} '{{ domain_data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-info">{{ domain_data.dkim.length }} bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<pre>{{ domain_data.dkim.dkim_txt }}</pre>
|
||||
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="{{ domain_data.dkim.privkey }}"><small><i class="bi bi-arrow-return-right"></i> {{ lang.admin.dkim_private_key }}</small></p>
|
||||
<textarea class="form-control" rows="6" readonly>{{ domain_data.dkim.dkim_txt }}</textarea>
|
||||
<small>
|
||||
<i class="bi bi-arrow-return-right"></i>
|
||||
<a href="#" data-bs-toggle="modal" data-bs-target="#showDKIMprivKey" id="dkim_priv" data-priv-key="{{ domain_data.dkim.privkey }}"> {{ lang.admin.dkim_private_key }}</a>
|
||||
</small>
|
||||
</div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row collapse in dkim_key_missing">
|
||||
<div class="col-md-1"><input class="dkim_missing" type="checkbox" data-id="dkim" name="multi_select" value="{{ domain }}" disabled></div>
|
||||
<div class="col-md-3">
|
||||
<p>{{ lang.admin.domain }}: <strong>{{ domain }}</strong><br><span class="label label-danger">{{ lang.admin.dkim_key_missing }}</span></p>
|
||||
<p>{{ lang.admin.domain }}: <strong>{{ domain }}</strong><br><span class="badge fs-6 bg-danger">{{ lang.admin.dkim_key_missing }}</span></p>
|
||||
</div>
|
||||
<div class="col-md-8"><pre>-</pre></div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for alias_domain, alias_domain_data in domain_data.alias_domains %}
|
||||
{% if alias_domain_data.dkim %}
|
||||
<div class="row collapse in dkim_key_valid">
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="{{ alias_domain }}"></div>
|
||||
<div class="col-md-2 col-md-offset-1">
|
||||
<div class="col-md-2 offset-md-1">
|
||||
<p><small>↳ Alias-Domain: <strong>{{ alias_domain }}</strong></small>
|
||||
<p class="dkim-label"><span class="label label-success">{{ lang.admin.dkim_key_valid }}</span></p>
|
||||
<p class="dkim-label"><span class="label label-primary">Selector '{{ alias_domain_data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="label label-info">{{ alias_domain_data.dkim.length }} bit</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-success">{{ lang.admin.dkim_key_valid }}</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-primary">Selector '{{ alias_domain_data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-info">{{ alias_domain_data.dkim.length }} bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<pre>{{ alias_domain_data.dkim.dkim_txt }}</pre>
|
||||
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="{{ alias_domain_data.dkim.privkey }}"><small><i class="bi bi-arrow-return-right"></i> Private key</small></p>
|
||||
<p data-bs-toggle="modal" data-bs-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="{{ alias_domain_data.dkim.privkey }}"><small><i class="bi bi-arrow-return-right"></i> Private key</small></p>
|
||||
</div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="row collapse in dkim_key_missing">
|
||||
<div class="col-md-1"><input class="dkim_missing" type="checkbox" data-id="dkim" name="multi_select" value="{{ alias_domain }}" disabled></div>
|
||||
<div class="col-md-2 col-md-offset-1">
|
||||
<p><small>↳ Alias-Domain: <strong>{{ alias_domain }}</strong><br></small><span class="label label-danger">{{ lang.admin.dkim_key_missing }}</span></p>
|
||||
<div class="col-md-2 offset-md-1">
|
||||
<p><small>↳ Alias-Domain: <strong>{{ alias_domain }}</strong><br></small><span class="badge fs-6 bg-danger">{{ lang.admin.dkim_key_missing }}</span></p>
|
||||
</div>
|
||||
<div class="col-md-8"><pre>-</pre></div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@ -69,82 +76,85 @@
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="{{ blind }}"></div>
|
||||
<div class="col-md-3">
|
||||
<p>{{ lang.admin.domain }}: <strong>{{ blind }}</strong>
|
||||
<p class="dkim-label"><span class="label label-warning">{{ lang.admin.dkim_key_unused }}</span></p>
|
||||
<p class="dkim-label"><span class="label label-primary">Selector '{{ data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="label label-info">{{ data.dkim.length }} bit</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-warning">{{ lang.admin.dkim_key_unused }}</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-primary">Selector '{{ data.dkim.dkim_selector }}'</span></p>
|
||||
<p class="dkim-label"><span class="badge fs-6 bg-info">{{ data.dkim.length }} bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<pre>{{ data.dkim.dkim_txt }}</pre>
|
||||
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="{{ data.dkim.privkey }}"><small><i class="bi bi-arrow-return-right"></i> Private key</small></p>
|
||||
<p data-bs-toggle="modal" data-bs-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="{{ data.dkim.privkey }}"><small><i class="bi bi-arrow-return-right"></i> Private key</small></p>
|
||||
</div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
<hr class="d-block d-md-none">
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" id="toggle_multi_select_all" data-id="dkim" class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button type="button" data-action="delete_selected" name="delete_selected" data-id="dkim" data-api-url="delete/dkim" class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-danger"><i class="bi bi-trash"></i> {{ lang.admin.remove }}</button>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
<button type="button" id="toggle_multi_select_all" data-id="dkim" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</button>
|
||||
<button type="button" data-action="delete_selected" name="delete_selected" data-id="dkim" data-api-url="delete/dkim" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-danger"><i class="bi bi-trash"></i> {{ lang.admin.remove }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<legend style="margin-top:40px">{{ lang.admin.dkim_add_key }}</legend>
|
||||
<legend style="margin-top:40px">{{ lang.admin.dkim_add_key }}</legend><hr />
|
||||
<form class="form" data-id="dkim" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="dkim_add_domains">{{ lang.admin.domain_s }}</label>
|
||||
<input class="form-control input-sm" id="dkim_add_domains" name="domains" placeholder="example.org, example.com" required>
|
||||
<small><i class="bi bi-arrow-return-right"></i> <a href="#" id="dkim_missing_keys">{{ lang.admin.dkim_domains_wo_keys }}</a></small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label for="dkim_selector">{{ lang.admin.dkim_domains_selector }}</label>
|
||||
<input class="form-control input-sm" id="dkim_selector" name="dkim_selector" value="dkim" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select data-style="btn btn-default btn-sm" class="form-control" id="key_size" name="key_size" title="{{ lang.admin.dkim_key_length }}" required>
|
||||
<option data-subtext="bits">1024</option>
|
||||
<option data-subtext="bits">2048</option>
|
||||
</select>
|
||||
<div class="row mb-4">
|
||||
<div class="col-12 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-style="btn btn-secondary btn-sm" class="form-control" id="key_size" name="key_size" title="{{ lang.admin.dkim_key_length }}" required>
|
||||
<option data-subtext="bits">1024</option>
|
||||
<option data-subtext="bits">2048</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</form>
|
||||
|
||||
<legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" unselectable="on" data-toggle="collapse">
|
||||
<legend data-bs-target="#import_dkim" style="margin-top:40px;cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.import_private_key }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="import_dkim" class="collapse">
|
||||
<form class="form" data-id="dkim_import" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label for="dkim_import_domain">{{ lang.admin.domain }}:</label>
|
||||
<input class="form-control input-sm" id="dkim_import_domain" name="domain" placeholder="example.org" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label for="dkim_import_selector">{{ lang.admin.dkim_domains_selector }}:</label>
|
||||
<input class="form-control input-sm" id="dkim_import_selector" name="dkim_selector" value="dkim" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="private_key_file">{{ lang.admin.private_key }}: (RSA PKCS#8)</label>
|
||||
<textarea class="form-control input-sm" rows="10" name="private_key_file" id="private_key_file" required placeholder="-----BEGIN RSA KEY-----"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label>
|
||||
<input type="checkbox" name="overwrite_existing" value="1"> {{ lang.admin.dkim_overwrite_key }}
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" data-action="add_item" data-id="dkim_import" data-api-url='add/dkim_import' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.import }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" data-action="add_item" data-id="dkim_import" data-api-url='add/dkim_import' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.import }}</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<legend data-target="#duplicate_dkim" style="margin-top:40px;cursor:pointer" unselectable="on" data-toggle="collapse">
|
||||
<legend data-bs-target="#duplicate_dkim" style="margin-top:40px;cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.duplicate_dkim }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="duplicate_dkim" class="collapse">
|
||||
<form class="form-horizontal" data-id="dkim_duplicate" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="from_domain">{{ lang.admin.dkim_from }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-style="btn btn-default btn-sm"
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="from_domain">{{ lang.admin.dkim_from }}:</label>
|
||||
<div class="col-sm-10 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-style="btn btn-secondary btn-sm"
|
||||
data-live-search="true"
|
||||
data-id="dkim_duplicate"
|
||||
title="{{ lang.admin.dkim_from_title }}"
|
||||
@ -155,12 +165,12 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="to_domain">{{ lang.admin.dkim_to }}:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="to_domain">{{ lang.admin.dkim_to }}:</label>
|
||||
<div class="col-sm-10 col-md-6 col-lg-4 col-xl-3">
|
||||
<select
|
||||
data-live-search="true"
|
||||
data-style="btn btn-default btn-sm"
|
||||
data-style="btn btn-secondary btn-sm"
|
||||
data-id="dkim_duplicate"
|
||||
title="{{ lang.admin.dkim_to_title }}"
|
||||
name="to_domain" id="to_domain" class="full-width-select form-control" multiple required>
|
||||
@ -170,7 +180,7 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" data-action="add_item" data-id="dkim_duplicate" data-api-url='add/dkim_duplicate' data-api-attr='{}' href="#"><i class="bi bi-clipboard-plus"></i> {{ lang.admin.duplicate }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" data-action="add_item" data-id="dkim_duplicate" data-api-url='add/dkim_duplicate' data-api-attr='{}' href="#"><i class="bi bi-clipboard-plus"></i> {{ lang.admin.duplicate }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,55 +1,60 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-f2b">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.f2b_parameters }}</div>
|
||||
<div class="panel-body">
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-f2b" role="tabpanel" aria-labelledby="tab-config-f2b">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-f2b" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-f2b">
|
||||
{{ lang.admin.f2b_parameters }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.f2b_parameters }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-f2b" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form" data-id="f2b" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="f2b_ban_time">{{ lang.admin.f2b_ban_time }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_ban_time" name="ban_time" value="{{ f2b_data.ban_time }}" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="f2b_max_attempts">{{ lang.admin.f2b_max_attempts }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_max_attempts" name="max_attempts" value="{{ f2b_data.max_attempts }}" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="f2b_retry_window">{{ lang.admin.f2b_retry_window }}:</label>
|
||||
<input type="number" class="form-control" id="f2b_retry_window" name="retry_window" value="{{ f2b_data.retry_window }}" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="f2b_netban_ipv4">{{ lang.admin.f2b_netban_ipv4 }}:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/</span>
|
||||
<span class="input-group-text">/</span>
|
||||
<input type="number" class="form-control" id="f2b_netban_ipv4" name="netban_ipv4" value="{{ f2b_data.netban_ipv4 }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="f2b_netban_ipv6">{{ lang.admin.f2b_netban_ipv6 }}:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/</span>
|
||||
<span class="input-group-text">/</span>
|
||||
<input type="number" class="form-control" id="f2b_netban_ipv6" name="netban_ipv6" value="{{ f2b_data.netban_ipv6 }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<p class="help-block">{{ lang.admin.f2b_list_info|raw }}</p>
|
||||
<div class="form-group">
|
||||
<p class="text-muted">{{ lang.admin.f2b_list_info|raw }}</p>
|
||||
<div class="mb-2">
|
||||
<label for="f2b_whitelist">{{ lang.admin.f2b_whitelist }}:</label>
|
||||
<textarea class="form-control" id="f2b_whitelist" name="whitelist" rows="5">{{ f2b_data.whitelist }}</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<label for="f2b_blacklist">{{ lang.admin.f2b_blacklist }}:</label>
|
||||
<textarea class="form-control" id="f2b_blacklist" name="blacklist" rows="5">{{ f2b_data.blacklist }}</textarea>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<a href="#" role="button" class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" data-toggle="modal" data-container="netfilter-mailcow" data-target="#RestartContainer"><i class="bi bi-arrow-repeat"></i> {{ lang.header.restart_netfilter }}</a>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<a href="#" role="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" data-bs-toggle="modal" data-container="netfilter-mailcow" data-bs-target="#RestartContainer"><i class="bi bi-arrow-repeat"></i> {{ lang.header.restart_netfilter }}</a>
|
||||
</div>
|
||||
</form>
|
||||
<legend data-target="#f2b_regex_filters" style="margin-top:40px;cursor:pointer" unselectable="on" data-toggle="collapse">
|
||||
<legend data-bs-target="#f2b_regex_filters" style="margin-top:40px;cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.f2b_filter }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="f2b_regex_filters" class="collapse">
|
||||
<p class="help-block">{{ lang.admin.f2b_regex_info }}</p>
|
||||
<p class="text-muted">{{ lang.admin.f2b_regex_info }}</p>
|
||||
<form class="form-inline" data-id="f2b_regex" role="form" method="post">
|
||||
<table class="table table-condensed" id="f2b_regex_table">
|
||||
<tr>
|
||||
@ -61,25 +66,25 @@
|
||||
<tr>
|
||||
<td><input disabled class="input-sm input-xs-lg form-control" style="text-align:center" data-id="f2b_regex" type="text" name="app" required value="{{ regex_id }}"></td>
|
||||
<td><input class="input-sm input-xs-lg form-control regex-input" data-id="f2b_regex" type="text" name="regex" required value="{{ regex_val }}"></td>
|
||||
<td><a href="#" role="button" class="btn btn-xs btn-xs-lg btn-default" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
<td><a href="#" role="button" class="btn btn-xs btn-xs-lg btn-secondary" type="button">{{ lang.admin.remove_row }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="edit_selected" data-item="admin" data-id="f2b_regex" data-reload="no" data-api-url='edit/fail2ban' data-api-attr='{"action":"edit-regex"}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default admin-ays-dialog" data-action="edit_selected" data-item="self" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"reset-regex"}' href="#">{{ lang.admin.reset_default }}</button>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" type="button" id="add_f2b_regex_row"><i class="bi bi-plus-lg"></i> {{ lang.admin.add_row }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-success" data-action="edit_selected" data-item="admin" data-id="f2b_regex" data-reload="no" data-api-url='edit/fail2ban' data-api-attr='{"action":"edit-regex"}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary admin-ays-dialog" data-action="edit_selected" data-item="self" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"reset-regex"}' href="#">{{ lang.admin.reset_default }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-secondary" type="button" id="add_f2b_regex_row"><i class="bi bi-plus-lg"></i> {{ lang.admin.add_row }}</button>
|
||||
</div></p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p class="help-block">{{ lang.admin.ban_list_info|raw }}</p>
|
||||
<p class="text-muted">{{ lang.admin.ban_list_info|raw }}</p>
|
||||
{% if not f2b_data.active_bans and not f2b_data.perm_bans %}
|
||||
<i>{{ lang.admin.no_active_bans }}</i>
|
||||
{% endif %}
|
||||
{% for active_ban in f2b_data.active_bans %}
|
||||
<p>
|
||||
<span class="label label-info" style="padding:4px;font-size:85%;">
|
||||
<span class="badge fs-5 bg-info" style="padding:4px;font-size:85%;">
|
||||
<i class="bi bi-funnel-fill"></i>
|
||||
<a href="https://bgp.he.net/ip/{{ active_ban.ip }}" target="_blank" style="color:white">
|
||||
{{ active_ban.network }}
|
||||
@ -98,7 +103,7 @@
|
||||
<hr>
|
||||
{% for perm_ban in f2b_data.perm_bans %}
|
||||
<p>
|
||||
<span class="label label-danger" style="padding: 0.1em 0.4em 0.1em;">
|
||||
<span class="badge fs-5 bg-danger" style="padding: 0.1em 0.4em 0.1em;">
|
||||
<i class="bi bi-funnel-fill"></i>
|
||||
<a href="https://bgp.he.net/ip/{{ perm_ban.ip }}" target="_blank" style="color:white">
|
||||
{{ perm_ban.network }}
|
||||
|
@ -1,38 +1,40 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-fwdhosts">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.forwarding_hosts }}</div>
|
||||
<div class="panel-body">
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-fwdhosts" role="tabpanel" aria-labelledby="tab-config-fwdhosts">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-fwdhosts" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-fwdhosts">
|
||||
{{ lang.admin.forwarding_hosts }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.forwarding_hosts }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-fwdhosts" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p style="margin-bottom:40px">{{ lang.admin.forwarding_hosts_hint }}</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-condensed" id="forwardinghoststable"></table>
|
||||
</div>
|
||||
<table id="forwardinghoststable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" id="toggle_multi_select_all" data-id="fwdhosts" class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default">{{ lang.mailbox.toggle_all }}</button>
|
||||
<a class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default dropdown-toggle" data-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }} <span class="caret"></span></a>
|
||||
<button type="button" id="toggle_multi_select_all" data-id="fwdhosts" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary">{{ lang.mailbox.toggle_all }}</button>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu top100">
|
||||
<li><a data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"0"}' href="#">Enable spam filter</a></li>
|
||||
<li><a data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"1"}' href="#">Disable spam filter</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="delete_selected" data-id="fwdhosts" data-api-url='delete/fwdhost' href="#">{{ lang.admin.remove }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"0"}' href="#">Enable spam filter</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"1"}' href="#">Disable spam filter</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="fwdhosts" data-api-url='delete/fwdhost' href="#">{{ lang.admin.remove }}</a></li>
|
||||
</ul>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
</div>
|
||||
</div>
|
||||
<legend>{{ lang.admin.add_forwarding_host }}</legend>
|
||||
<p class="help-block">{{ lang.admin.forwarding_hosts_add_hint }}</p>
|
||||
<legend>{{ lang.admin.add_forwarding_host }}</legend><hr />
|
||||
<p class="text-muted">{{ lang.admin.forwarding_hosts_add_hint }}</p>
|
||||
<form class="form" data-id="fwdhost" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label for="fwdhost_hostname">{{ lang.admin.host }}</label>
|
||||
<input class="form-control" id="fwdhost_hostname" name="hostname" placeholder="example.org" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-4">
|
||||
<select data-width="200px" class="form-control" id="filter_spam" name="filter_spam" title="{{ lang.user.spamfilter }}" required>
|
||||
<option value="1">{{ lang.admin.active }}</option>
|
||||
<option value="0">{{ lang.admin.inactive }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="add_item" data-id="fwdhost" data-api-url='add/fwdhost' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="add_item" data-id="fwdhost" data-api-url='add/fwdhost' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,24 +1,26 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-oauth2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.oauth2_apps }}</div>
|
||||
<div class="panel-body">
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-oauth2" role="tabpanel" aria-labelledby="tab-config-oauth2">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-oauth2" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-oauth2">
|
||||
{{ lang.admin.oauth2_apps }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-oauth2" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p>{{ lang.admin.oauth2_info|raw }}</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped" id="oauth2clientstable"></table>
|
||||
</div>
|
||||
<table id="oauth2clientstable" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-admin">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" id="toggle_multi_select_all" data-id="oauth2_clients" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default dropdown-toggle" data-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }} <span class="caret"></span></a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="oauth2_clients" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a data-action="delete_selected" data-id="oauth2_clients" data-api-url='delete/oauth2-client' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="edit_selected" data-id="oauth2_clients" data-api-url='edit/oauth2-client' data-api-attr='{"revoke_tokens":"1"}' href="#">{{ lang.admin.oauth2_revoke_tokens }}</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="edit_selected" data-id="oauth2_clients" data-api-url='edit/oauth2-client' data-api-attr='{"renew_secret":"1"}' href="#">{{ lang.admin.oauth2_renew_secret }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="oauth2_clients" data-api-url='delete/oauth2-client' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="oauth2_clients" data-api-url='edit/oauth2-client' data-api-attr='{"revoke_tokens":"1"}' href="#">{{ lang.admin.oauth2_revoke_tokens }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="oauth2_clients" data-api-url='edit/oauth2-client' data-api-attr='{"renew_secret":"1"}' href="#">{{ lang.admin.oauth2_renew_secret }}</a></li>
|
||||
</ul>
|
||||
<div class="clearfix visible-xs"></div>
|
||||
<a class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-id="add_oauth2_client" data-toggle="modal" data-target="#addOAuth2ClientModal" href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.oauth2_add_client }}</a>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" data-id="add_oauth2_client" data-bs-toggle="modal" data-bs-target="#addOAuth2ClientModal" href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.oauth2_add_client }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,20 +1,25 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-password-policy">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.password_policy }}</div>
|
||||
<div class="panel-body">
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-password-policy" role="tabpanel" aria-labelledby="tab-config-password-policy">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-policy" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-password-policy">
|
||||
{{ lang.admin.password_policy }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.password_policy }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-password-policy" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<form class="form-horizontal" data-id="passwordpolicy" role="form" method="post">
|
||||
{% for name, value in password_complexity %}
|
||||
{% if name == 'length' %}
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="length">{{ lang.admin.password_length }}:</label>
|
||||
<div class="row mb-4">
|
||||
<label class="control-label col-sm-3 text-sm-end" for="length">{{ lang.admin.password_length }}:</label>
|
||||
<div class="col-sm-2">
|
||||
<input type="number" class="form-control" min="3" max="64" name="length" id="length" value="{{ value }}" required>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<input type="hidden" name="{{ name }}" value="0">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<label>
|
||||
<input type="checkbox" name="{{ name }}" id="{{ name }}" value="1" {% if value == 1 %}checked{% endif %}> {{ lang.admin['password_policy_'~name] }}
|
||||
</label>
|
||||
@ -22,10 +27,10 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<div class="row mt-4 mb-2">
|
||||
<div class="offset-sm-3 col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-item="passwordpolicy" data-action="edit_selected" data-id="passwordpolicy" data-api-url='edit/passwordpolicy' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="passwordpolicy" data-action="edit_selected" data-id="passwordpolicy" data-api-url='edit/passwordpolicy' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,74 +1,79 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-quarantine">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.quarantine }}</div>
|
||||
<div class="panel-body">
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-quarantine" role="tabpanel" aria-labelledby="tab-config-quarantine">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quarantine" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-quarantine">
|
||||
{{ lang.admin.quarantine }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.quarantine }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-quarantine" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
{% if not q_data.retention_size or not q_data.max_size %}
|
||||
<div class="alert alert-info">{{ lang.quarantine.disabled_by_config }}</div>
|
||||
{% endif %}
|
||||
<form class="form-horizontal" data-id="quarantine" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_retention_size">{{ lang.admin.quarantine_retention_size|raw }}</label>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_retention_size">{{ lang.admin.quarantine_retention_size|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_retention_size" name="retention_size" value="{{ q_data.retention_size }}" placeholder="0" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_max_size">{{ lang.admin.quarantine_max_size|raw }}</label>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_max_size">{{ lang.admin.quarantine_max_size|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_max_size" name="max_size" value="{{ q_data.max_size }}" placeholder="0" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_max_score">{{ lang.admin.quarantine_max_score|raw }}</label>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_max_score">{{ lang.admin.quarantine_max_score|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_max_score" name="max_score" value="{{ q_data.max_score }}" placeholder="9999.0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_max_age">{{ lang.admin.quarantine_max_age|raw }}</label>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_max_age">{{ lang.admin.quarantine_max_age|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" id="quarantine_max_age" name="max_age" value="{{ q_data.max_age }}" min="1" required>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_redirect"><i class="bi bi-box-arrow-right"></i> {{ lang.admin.quarantine_redirect|raw }}</label>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_redirect"><i class="bi bi-box-arrow-right"></i> {{ lang.admin.quarantine_redirect|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" id="quarantine_redirect" name="redirect" value="{{ q_data.redirect }}" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_bcc"><i class="bi bi-files"></i> {{ lang.admin.quarantine_bcc|raw }}</label>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_bcc"><i class="bi bi-files"></i> {{ lang.admin.quarantine_bcc|raw }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" id="quarantine_bcc" name="bcc" value="{{ q_data.bcc }}" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_sender">{{ lang.admin.quarantine_notification_sender }}:</label>
|
||||
<div class="row mb-2">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_sender">{{ lang.admin.quarantine_notification_sender }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="email" class="form-control" id="quarantine_sender" name="sender" value="{{ q_data.sender }}" placeholder="quarantine@localhost">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_subject">{{ lang.admin.quarantine_notification_subject }}:</label>
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_subject">{{ lang.admin.quarantine_notification_subject }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" id="quarantine_subject" name="subject" value="{{ q_data.subject }}" placeholder="Spam Quarantine Notification">
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="quarantine_release_format">{{ lang.admin.quarantine_release_format }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="row mb-2">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_release_format">{{ lang.admin.quarantine_release_format }}:</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-width="100%" id="quarantine_release_format" name="release_format" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option {% if q_data.release_format == 'raw' %}selected{% endif %} value="raw">{{ lang.admin.quarantine_release_format_raw }}</option>
|
||||
<option {% if q_data.release_format == 'attachment' %}selected{% endif %} value="attachment">{{ lang.admin.quarantine_release_format_att }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="exclude_domains">{{ lang.admin.quarantine_exclude_domains }}:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="row mb-4">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="exclude_domains">{{ lang.admin.quarantine_exclude_domains }}:</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-width="100%" name="exclude_domains" class="selectpicker" title="{{ lang.tfa.select }}" multiple>
|
||||
{% for domain in all_domains %}
|
||||
<option {% if domain in q_data.exclude_domains %}selected{% endif %}>{{ domain }}</option>
|
||||
@ -77,13 +82,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<legend data-target="#quarantine_template" style="cursor:pointer" unselectable="on" data-toggle="collapse">
|
||||
<legend data-bs-target="#quarantine_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.quarantine_notification_html|raw }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="quarantine_template" class="collapse" >
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="40" name="html_tmpl">{{ q_data.html_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,18 +1,23 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-quota">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.quota_notifications }}</div>
|
||||
<div class="panel-body">
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-quota" role="tabpanel" aria-labelledby="tab-config-quota">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quota" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-quota">
|
||||
{{ lang.admin.quota_notifications }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.quota_notifications }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-quota" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<p>{{ lang.admin.quota_notifications_info }}</p>
|
||||
<form class="form" role="form" data-id="quota_notification" method="post">
|
||||
<div class="row">
|
||||
<div class="row mb-4">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<label for="quota_notification_sender">{{ lang.admin.quota_notification_sender }}:</label>
|
||||
<input type="email" class="form-control" id="quota_notification_sender" name="sender" value="{{ qn_data.sender }}" placeholder="quota-warning@localhost">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<label for="quota_notification_subject">{{ lang.admin.quota_notification_subject }}:</label>
|
||||
<input type="text" class="form-control" id="quota_notification_subject" name="subject" value="{{ qn_data.subject }}" placeholder="Quota warning">
|
||||
</div>
|
||||
@ -20,20 +25,21 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<legend data-target="#quota_template" style="cursor:pointer" unselectable="on" data-toggle="collapse">
|
||||
<legend data-bs-target="#quota_template" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.quarantine_notification_html|raw }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="quota_template" class="collapse">
|
||||
<!-- <small>{{ lang.admin.quota_notifications_vars }}</small><br><br>-->
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code collapse in" rows="20" name="html_tmpl">{{ qn_data.html_tmpl|raw }}</textarea>
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="html_tmpl">{{ qn_data.html_tmpl|raw }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<br>
|
||||
<a type="button" class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="edit_selected"
|
||||
<a type="button" class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected"
|
||||
data-item="quota_notification"
|
||||
data-id="quota_notification"
|
||||
data-api-url='edit/quota_notification'
|
||||
|
@ -1,10 +1,16 @@
|
||||
<div role="tabpanel" class="tab-pane" id="tab-config-rsettings">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">{{ lang.admin.rspamd_settings_map }}</div>
|
||||
<div class="panel-body">
|
||||
<legend data-target="#active_settings_map" style="cursor:pointer" unselectable="on" data-toggle="collapse">
|
||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-rsettings" role="tabpanel" aria-labelledby="tab-config-rsettings">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex">
|
||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rsettings" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-rsettings">
|
||||
{{ lang.admin.rspamd_settings_map }}
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.admin.rspamd_settings_map }}</span>
|
||||
</div>
|
||||
<div id="collapse-tab-config-rsettings" class="card-body collapse" data-bs-parent="#admin-content">
|
||||
<legend data-bs-target="#active_settings_map" style="cursor:pointer" unselectable="on" data-bs-toggle="collapse">
|
||||
<i style="font-size:10pt;" class="bi bi-plus-square"></i> {{ lang.admin.active_rspamd_settings_map }}
|
||||
</legend>
|
||||
<hr />
|
||||
<div id="active_settings_map" class="collapse" >
|
||||
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="settings_map" readonly>{{ rsettings_map }}</textarea>
|
||||
</div>
|
||||
@ -17,41 +23,41 @@
|
||||
|
||||
{% endif %}
|
||||
{% for rsetting in rsettings %}
|
||||
<a href="#{{ rsetting.details.id }}" class="list-group-item list-group-item-{% if rsetting.details.active %}success{% endif %}" data-dont-remember="1" data-toggle="tab">{{ rsetting.details.desc }} (ID #{{ rsetting.id }})</a>
|
||||
<a href="#{{ rsetting.details.id }}" class="list-group-item list-group-item-{% if rsetting.details.active %}success{% endif %}" data-dont-remember="1" data-bs-toggle="tab">{{ rsetting.details.desc }} (ID #{{ rsetting.id }})</a>
|
||||
{% else %}
|
||||
<span class="list-group-item"><em>{{ lang.admin.rsetting_none }}</em></span>
|
||||
{% endfor %}
|
||||
<a href="#" class="list-group-item list-group-item-default"
|
||||
data-id="add_domain_admin"
|
||||
data-toggle="modal"
|
||||
data-bs-toggle="modal"
|
||||
data-dont-remember="1"
|
||||
data-target="#addRsettingModal"
|
||||
data-toggle="tab">{{ lang.admin.rsetting_add_rule }}</a>
|
||||
data-bs-target="#addRsettingModal"
|
||||
data-bs-toggle="tab">{{ lang.admin.rsetting_add_rule }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="tab-content">
|
||||
{% if not rsettings %}
|
||||
<div id="none" class="tab-pane active">
|
||||
<p class="help-block">{{ lang.admin.rsetting_none }}</p>
|
||||
<p class="text-muted">{{ lang.admin.rsetting_none }}</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div id="none" class="tab-pane active">
|
||||
<p class="help-block">{{ lang.admin.rsetting_no_selection }}</p>
|
||||
<p class="text-muted">{{ lang.admin.rsetting_no_selection }}</p>
|
||||
</div>
|
||||
{% for rsetting in rsettings %}
|
||||
<div id="{{ rsetting.details.id }}" class="tab-pane">
|
||||
<form class="form" data-id="rsettings" role="form" method="post">
|
||||
<input type="hidden" name="active" value="0">
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<label for="rsettings_desc">{{ lang.admin.rsetting_desc }}:</label>
|
||||
<input type="text" class="form-control" id="rsettings_desc" name="desc" value="{{ rsetting.details.desc }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<label for="rsettings_content">{{ lang.admin.rsetting_content }}:</label>
|
||||
<textarea class="form-control" id="rsettings_content" name="content" rows="10">{{ rsetting.details.content }}</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<label>
|
||||
<input type="checkbox" name="active" value="1" {% if rsetting.details.active %}checked{% endif %}> {{ lang.admin.active }}
|
||||
</label>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user