Browse Source

[BS5] fix minor issues

FreddleSpl0it 3 years ago
parent
commit
560df58bb4

+ 6 - 2
data/web/css/build/013-mailcow.css

@@ -67,7 +67,7 @@
   height: 44px;
   display: flex;
   align-items: center;
-  margin: 0 10px;
+  padding: 0 10px !important;
 }
 .navbar-fixed-bottom .navbar-collapse, 
 .navbar-fixed-top .navbar-collapse {
@@ -267,6 +267,10 @@ code {
 .dtr-title {
   width: 20%;
 }
+table.dataTable>tbody>tr.child ul.dtr-details>li {
+  border-bottom: 1px solid rgba(239, 239, 239, 0.129);
+  padding: 0.5em 0;
+}
 
 .tag-box {
   display: flex;
@@ -291,7 +295,7 @@ code {
 }
 .tag-input {
   margin-left: 10px;
-  border: 0;
+  border: 0 !important;
   flex: 1;
   height: 24px;
   min-width: 150px;

+ 0 - 1
data/web/css/site/admin.css

@@ -25,7 +25,6 @@ body.modal-open {
 }
 .mass-actions-admin {
   user-select: none;
-  padding:10px 0 10px 0;
 }
 .inputMissingAttr {
   border-color: #FF4136;

+ 0 - 1
data/web/css/site/debug.css

@@ -26,7 +26,6 @@
 }
 .mass-actions-debug {
   user-select: none;
-  padding:10px 0 10px 10px;
 }
 .inputMissingAttr {
   border-color: #FF4136;

+ 0 - 1
data/web/css/site/edit.css

@@ -21,7 +21,6 @@
 }
 .mass-actions-user {
   user-select: none;
-  padding:10px 0 10px 0;
 }
 .inputMissingAttr {
   border-color: #FF4136;

+ 0 - 1
data/web/css/site/mailbox.css

@@ -32,7 +32,6 @@
 }
 .mass-actions-mailbox {
   user-select: none;
-  padding:10px 0 10px 10px;
 }
 .inputMissingAttr {
   border-color: #FF4136;

+ 0 - 1
data/web/css/site/quarantine.css

@@ -35,7 +35,6 @@
 
 .mass-actions-quarantine {
   user-select: none;
-  padding: 10px;
 }
 
 .inputMissingAttr {

+ 0 - 1
data/web/css/site/user.css

@@ -21,7 +21,6 @@
 }
 .mass-actions-user {
   user-select: none;
-  padding:10px 0;
 }
 .inputMissingAttr {
   border-color: #FF4136;

+ 1 - 1
data/web/js/build/014-mailcow.js

@@ -303,7 +303,7 @@ $(document).ready(function() {
     if (!Array.isArray(value_tags)) value_tags = [];
     if (value_tags.includes(tag)) return;
 
-    $('<span class="badge badge-primary tag-badge btn-badge"><i class="bi bi-tag-fill"></i> ' + tag + '</span>').insertBefore('.tag-input').click(function(){
+    $('<span class="badge bg-primary tag-badge btn-badge"><i class="bi bi-tag-fill"></i> ' + tag + '</span>').insertBefore('.tag-input').click(function(){
       var del_tag = unescapeHtml($(this).text());
       var del_tags = [];
       try {

+ 38 - 19
data/web/js/site/mailbox.js

@@ -236,17 +236,19 @@ jQuery(function($){
             if (Array.isArray(item.tags)){
               var tags = '';
               for (var i = 0; i < item.tags.length; i++)
-                tags += '<span class="badge badge-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.tags[i]) + '</span>';
+                tags += '<span class="badge bg-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.tags[i]) + '</span>';
               item.tags = tags;
+            } else {
+              item.tags = '';
             }
 
             if (item.backupmx == 1) {
               if (item.relay_unknown_only == 1) {
-                item.domain_name = '<div class="badge fs-5 bg-info">Relay Non-Local</div> ' + item.domain_name;
+                item.domain_name = '<div class="badge fs-6 bg-info">Relay Non-Local</div> ' + item.domain_name;
               } else if (item.relay_all_recipients == 1) {
-                item.domain_name = '<div class="badge fs-5 bg-info">Relay All</div> ' + item.domain_name;
+                item.domain_name = '<div class="badge fs-6 bg-info">Relay All</div> ' + item.domain_name;
               } else {
-                item.domain_name = '<div class="badge fs-5 bg-info">Relay</div> ' + item.domain_name;
+                item.domain_name = '<div class="badge fs-6 bg-info">Relay</div> ' + item.domain_name;
               }
             }
           });
@@ -325,6 +327,17 @@ jQuery(function($){
           title: lang.domain_admins,
           data: 'domain_admins'
         },
+        {
+          title: 'Tags',
+          data: 'tags'
+        },
+        {
+          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>':2==data&&'&#8212;');
+          }
+        },
         {
           title: lang.action,
           data: 'action',
@@ -415,8 +428,10 @@ jQuery(function($){
             if (Array.isArray(item.tags)){
               var tags = '';
               for (var i = 0; i < item.tags.length; i++)
-                tags += '<span class="badge badge-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.tags[i]) + '</span>';
+                tags += '<span class="badge bg-primary tag-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(item.tags[i]) + '</span>';
               item.tags = tags;
+            } else {
+              item.tags = '';
             }
           });
 
@@ -508,6 +523,10 @@ jQuery(function($){
             title: lang.msg_num,
             data: 'messages'
           },
+          {
+            title: 'Tags',
+            data: 'tags'
+          },
           {
             title: lang.active,
             data: 'active',
@@ -535,11 +554,11 @@ jQuery(function($){
         dataSrc: function(json){
           $.each(json, function (i, item) {
             if (item.multiple_bookings == '0') {
-              item.multiple_bookings = '<span id="active-script" class="badge fs-5 bg-success">' + lang.booking_0_short + '</span>';
+              item.multiple_bookings = '<span id="active-script" class="badge fs-6 bg-success">' + lang.booking_0_short + '</span>';
             } else if (item.multiple_bookings == '-1') {
-              item.multiple_bookings = '<span id="active-script" class="badge fs-5 bg-warning">' + lang.booking_lt0_short + '</span>';
+              item.multiple_bookings = '<span id="active-script" class="badge fs-6 bg-warning">' + lang.booking_lt0_short + '</span>';
             } else {
-              item.multiple_bookings = '<span id="active-script" class="badge fs-5 bg-danger">' + lang.booking_custom_short + ' (' + item.multiple_bookings + ')</span>';
+              item.multiple_bookings = '<span id="active-script" class="badge fs-6 bg-danger">' + lang.booking_custom_short + ' (' + item.multiple_bookings + ')</span>';
             }
             item.action = '<div class="btn-group">' +
               '<a href="/edit/resource/' + encodeURIComponent(item.name) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
@@ -627,9 +646,9 @@ jQuery(function($){
             item.local_dest = escapeHtml(item.local_dest);
             item.bcc_dest = escapeHtml(item.bcc_dest);
             if (item.type == 'sender') {
-              item.type = '<span id="active-script" class="badge fs-5 bg-success">' + lang.bcc_sender_map + '</span>';
+              item.type = '<span id="active-script" class="badge fs-6 bg-success">' + lang.bcc_sender_map + '</span>';
             } else {
-              item.type = '<span id="inactive-script" class="badge fs-5 bg-warning">' + lang.bcc_rcpt_map + '</span>';
+              item.type = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.bcc_rcpt_map + '</span>';
             }
           });
 
@@ -877,7 +896,7 @@ jQuery(function($){
               item.private_comment = '-';
             }
             if (item.is_catch_all == 1) {
-              item.address = '<div class="badge fs-5 bg-secondary">' + lang.catch_all + '</div> ' + escapeHtml(item.address);
+              item.address = '<div class="badge fs-6 bg-secondary">' + lang.catch_all + '</div> ' + escapeHtml(item.address);
             }
             else {
               item.address = escapeHtml(item.address);
@@ -886,10 +905,10 @@ jQuery(function($){
               item.goto = '⤷ <i class="bi bi-trash" style="font-size:12px"></i>';
             }
             else if (item.goto == "spam@localhost") {
-              item.goto = '<span class="badge fs-5 bg-danger">' + lang.goto_spam + '</span>';
+              item.goto = '<span class="badge fs-6 bg-danger">' + lang.goto_spam + '</span>';
             }
             else if (item.goto == "ham@localhost") {
-              item.goto = '<span class="badge fs-5 bg-success">' + lang.goto_ham + '</span>';
+              item.goto = '<span class="badge fs-6 bg-success">' + lang.goto_ham + '</span>';
             }
             if (item.in_primary_domain !== "") {
               item.domain = '<i data-domainname="' + item.domain + '" class="bi bi-info-circle-fill alias-domain-info text-info" data-bs-toggle="tooltip" title="' + lang.target_domain + ': ' + item.in_primary_domain + '"></i> ' + item.domain;
@@ -984,7 +1003,7 @@ jQuery(function($){
               '</div>';
             item.chkbox = '<input type="checkbox" data-id="alias-domain" name="multi_select" value="' + encodeURIComponent(item.alias_domain) + '" />';
             if(item.parent_is_backupmx == '1') {
-              item.target_domain = '<span><a href="/edit/domain/' + item.target_domain + '">' + item.target_domain + '</a> <div class="badge fs-5 bg-warning">' + lang.alias_domain_backupmx + '</div></span>';
+              item.target_domain = '<span><a href="/edit/domain/' + item.target_domain + '">' + item.target_domain + '</a> <div class="badge fs-6 bg-warning">' + lang.alias_domain_backupmx + '</div></span>';
             } else {
               item.target_domain = '<span><a href="/edit/domain/' + item.target_domain + '">' + item.target_domain + '</a></span>';
             }
@@ -1073,9 +1092,9 @@ jQuery(function($){
               '</div>';
             item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
             if (item.is_running == 1) {
-              item.is_running = '<span id="active-script" class="badge fs-5 bg-success">' + lang.running + '</span>';
+              item.is_running = '<span id="active-script" class="badge fs-6 bg-success">' + lang.running + '</span>';
             } else {
-              item.is_running = '<span id="inactive-script" class="badge fs-5 bg-warning">' + lang.waiting + '</span>';
+              item.is_running = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.waiting + '</span>';
             }
             if (!item.last_run > 0) {
               item.last_run = lang.waiting;
@@ -1180,12 +1199,12 @@ jQuery(function($){
         dataSrc: function(json){
           $.each(json, function (i, item) {
             if (item.active == 1) {
-              item.active = '<span id="active-script" class="badge fs-5 bg-success">' + lang.active + '</span>';
+              item.active = '<span id="active-script" class="badge fs-6 bg-success">' + lang.active + '</span>';
             } else {
-              item.active = '<span id="inactive-script" class="badge fs-5 bg-warning">' + lang.inactive + '</span>';
+              item.active = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.inactive + '</span>';
             }
             item.script_data = '<pre style="margin:0px">' + escapeHtml(item.script_data) + '</pre>'
-            item.filter_type = '<div class="badge fs-5 bg-secondary">' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '</div>'
+            item.filter_type = '<div class="badge fs-6 bg-secondary">' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '</div>'
             item.action = '<div class="btn-group">' +
               '<a href="/edit/filter/' + 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-filter" data-api-url="delete/filter" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +

+ 3 - 3
data/web/js/site/qhandler.js

@@ -46,11 +46,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 badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
+          $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
         } else if (data.action === "reject") {
-          $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
+          $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
         } else if (data.action === "rewrite subject") {
-          $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
+          $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
         }
       }
       if (typeof data.recipients !== 'undefined') {

+ 8 - 8
data/web/js/site/quarantine.js

@@ -31,16 +31,16 @@ jQuery(function($){
               item.score = '-';
             }
             if (item.virus_flag > 0) {
-              item.virus = '<span class="badge fs-5 bg-danger">' + lang.high_danger + '</span>';
+              item.virus = '<span class="badge fs-6 bg-danger">' + lang.high_danger + '</span>';
             } else {
-              item.virus = '<span class="badge fs-5 bg-secondary">' + lang.neutral_danger + '</span>';
+              item.virus = '<span class="badge fs-6 bg-secondary">' + lang.neutral_danger + '</span>';
             }
             if (item.action === "reject") {
-              item.rspamdaction = '<span class="badge fs-5 bg-danger">' + lang.rejected + '</span>';
+              item.rspamdaction = '<span class="badge fs-6 bg-danger">' + lang.rejected + '</span>';
             } else if (item.action === "add header") {
-              item.rspamdaction = '<span class="badge fs-5 bg-warning">' + lang.junk_folder + '</span>';
+              item.rspamdaction = '<span class="badge fs-6 bg-warning">' + lang.junk_folder + '</span>';
             } else if (item.action === "rewrite subject") {
-              item.rspamdaction = '<span class="badge fs-5 bg-warning">' + lang.rewrite_subject + '</span>';
+              item.rspamdaction = '<span class="badge fs-6 bg-warning">' + lang.rewrite_subject + '</span>';
             }
             if(item.notified > 0) {
               item.notified = '&#10004;';
@@ -192,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 badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
+            $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
           } else if (data.action == "reject") {
-            $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
+            $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
           } else if (data.action == "rewrite subject") {
-            $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-5 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
+            $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
           }
         }
         if (typeof data.recipients !== 'undefined') {

+ 3 - 3
data/web/js/site/user.js

@@ -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="badge fs-5 bg-secondary">' + item.service.toUpperCase() + '</div>';
+              var service = '<div class="badge fs-6 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>' : '';
@@ -221,9 +221,9 @@ jQuery(function($){
               item.chkbox = '<input type="checkbox" disabled />';
             }
             if (item.is_running == 1) {
-              item.is_running = '<span id="active-script" class="badge fs-5 bg-success">' + lang.running + '</span>';
+              item.is_running = '<span id="active-script" class="badge fs-6 bg-success">' + lang.running + '</span>';
             } else {
-              item.is_running = '<span id="inactive-script" class="badge fs-5 bg-warning">' + lang.waiting + '</span>';
+              item.is_running = '<span id="inactive-script" class="badge fs-6 bg-warning">' + lang.waiting + '</span>';
             }
             if (!item.last_run > 0) {
               item.last_run = lang.waiting;

+ 11 - 13
data/web/templates/edit/domain.twig

@@ -23,12 +23,12 @@
           <input type="text" class="form-control" name="description" value="{{ result.description }}">
         </div>
       </div>
-      <div class="form-group">
+      <div class="row">
         <label class="control-label col-sm-2">{{ lang.add.tags }}</label>
         <div class="col-sm-10">
           <div class="form-control tag-box">
             {% for tag in domain_details.tags %}
-              <span data-action='delete_selected' data-item="{{ tag|url_encode }}" data-id="domain_tag_{{ tag }}" data-api-url='delete/domain/tag/{{ domain }}' class="badge badge-primary tag-badge btn-badge">
+              <span data-action='delete_selected' data-item="{{ tag|url_encode }}" data-id="domain_tag_{{ tag }}" data-api-url='delete/domain/tag/{{ domain }}' class="badge bg-primary tag-badge btn-badge">
                 <i class="bi bi-tag-fill"></i> 
                 {{ tag }}
               </span>
@@ -39,7 +39,7 @@
           </div>
         </div>
       </div>
-      <div class="form-group">
+      <div class="row">
         <label class="control-label col-sm-2" for="relayhost">{{ lang.edit.relayhost }}</label>
         <div class="col-sm-10">
           <select data-acl="{{ acl.domain_relayhost }}" data-live-search="true" id="relayhost" name="relayhost" class="form-control">
@@ -141,16 +141,14 @@
   <div id="dratelimit" class="tab-pane fade" role="tabpanel" aria-labelledby="domain-ratelimit">
     <form data-id="domratelimit" class="form-inline well" method="post">
       <div class="row">
-        <label class="control-label">{{ lang.edit.ratelimit }}</label>
-        <input name="rl_value" type="number" value="{{ rl.value }}" autocomplete="off" class="form-control" placeholder="{{ lang.ratelimit.disabled }}">
-      </div>
-      <div class="row">
-        <select name="rl_frame" class="form-control">
-          {% include 'mailbox/rl-frame.twig' %}
-        </select>
-      </div>
-      <div class="row">
-        <button data-acl="{{ acl.ratelimit }}" class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="domratelimit" data-item="{{ domain }}" data-api-url='edit/rl-domain' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
+        <div class="col-12">
+          <label class="control-label">{{ lang.edit.ratelimit }}</label>
+          <input name="rl_value" type="number" value="{{ rl.value }}" autocomplete="off" class="form-control" placeholder="{{ lang.ratelimit.disabled }}">
+          <select name="rl_frame" class="form-control">
+            {% include 'mailbox/rl-frame.twig' %}
+          </select>
+          <button data-acl="{{ acl.ratelimit }}" class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="domratelimit" data-item="{{ domain }}" data-api-url='edit/rl-domain' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>
+        </div>
       </div>
     </form>
   </div>

+ 15 - 15
data/web/templates/edit/mailbox.twig

@@ -22,12 +22,12 @@
           <input type="text" class="form-control" name="name" value="{{ result.name }}">
         </div>
       </div>
-      <div class="form-group">
+      <div class="row">
         <label class="control-label col-sm-2">{{ lang.add.tags }}</label>
         <div class="col-sm-10">
           <div class="form-control tag-box">
             {% for tag in mailbox_details.tags %}
-              <span data-action='delete_selected' data-item="{{ tag }}" data-id="mailbox_tag_{{ tag }}" data-api-url='delete/mailbox/tag/{{ mailbox }}' class="badge badge-primary tag-badge btn-badge">
+              <span data-action='delete_selected' data-item="{{ tag }}" data-id="mailbox_tag_{{ tag }}" data-api-url='delete/mailbox/tag/{{ mailbox }}' class="badge bg-primary tag-badge btn-badge">
                 <i class="bi bi-tag-fill"></i> 
                 {{ tag }}
               </span>
@@ -38,7 +38,7 @@
           </div>
         </div>
       </div>
-      <div class="form-group">
+      <div class="row">
         <label class="control-label col-sm-2" for="quota">{{ lang.edit.quota_mb }}
           <br><span id="quotaBadge" class="badge">max. {{ (result.max_new_quota / 1048576) }} MiB</span>
         </label>
@@ -167,18 +167,18 @@
         <label class="control-label col-sm-2" for="sender_acl">{{ lang.user.tls_policy }}</label>
         <div class="col-sm-10">
           <div class="btn-group" data-acl="{{ acl.tls_policy }}">
-            <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}">
-            data-action="edit_selected"
-            data-item="{{ mailbox }}"
-            data-id="tls_policy"
-            data-api-url='edit/tls_policy'
-            data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
-            <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}">
-            data-action="edit_selected"
-            data-item="{{ mailbox }}"
-            data-id="tls_policy"
-            data-api-url='edit/tls_policy'
-            data-api-attr='{"tls_enforce_out": {% if get_tls_policy.tls_enforce_out == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_out }}</button>
+            <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}"
+              data-action="edit_selected"
+              data-item="{{ mailbox }}"
+              data-id="tls_policy"
+              data-api-url='edit/tls_policy'
+              data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
+            <button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}"
+              data-action="edit_selected"
+              data-item="{{ mailbox }}"
+              data-id="tls_policy"
+              data-api-url='edit/tls_policy'
+              data-api-attr='{"tls_enforce_out": {% if get_tls_policy.tls_enforce_out == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_out }}</button>
           </div>
         </div>
       </div>

+ 11 - 11
data/web/templates/modals/mailbox.twig

@@ -30,8 +30,8 @@
               <input type="text" class="form-control" name="name">
             </div>
           </div>
-          <div class="form-group">
-            <label class="control-label col-sm-2">{{ lang.add.tags }}</label>
+          <div class="row mb-2">
+            <label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.add.tags }}</label>
             <div class="col-sm-10">
               <div class="form-control tag-box">
                 <input type="text" class="tag-input">
@@ -40,8 +40,8 @@
               </div>
             </div>
           </div>
-          <div class="form-group">
-            <label class="control-label col-sm-2" for="addInputQuota">{{ lang.add.quota_mb }}
+          <div class="row mb-2">
+            <label class="control-label col-sm-2 text-sm-end text-sm-end" for="addInputQuota">{{ lang.add.quota_mb }}
               <br /><span id="quotaBadge" class="badge">max. - MiB</span>
             </label>
             <div class="col-sm-10">
@@ -104,8 +104,8 @@
               <input type="text" class="form-control" name="description">
             </div>
           </div>
-          <div class="form-group">
-            <label class="control-label col-sm-2">{{ lang.add.tags }}</label>
+          <div class="row mb-2">
+            <label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.add.tags }}</label>
             <div class="col-sm-10">
               <div class="form-control tag-box">
                 <input type="text" class="tag-input">
@@ -114,8 +114,8 @@
               </div>
             </div>
           </div>
-          <div class="form-group">
-            <label class="control-label col-sm-2" for="aliases">{{ lang.add.max_aliases }}</label>
+          <div class="row mb-2">
+            <label class="control-label col-sm-2 text-sm-end text-sm-end" for="aliases">{{ lang.add.max_aliases }}</label>
             <div class="col-sm-10">
               <input type="number" class="form-control" name="aliases" value="400" required>
             </div>
@@ -208,11 +208,11 @@
           <div class="row mb-4">
             <div class="offset-sm-2 col-sm-10 btn-group">
               {% if not skip_sogo %}
-              <button class="btn btn-xs-lg btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"tags": []}' href="#">{{ lang.add.add_domain_only }}</button>
-              <button class="btn btn-xs-lg btn-xs-half visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-default" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"restart_sogo":"1", "tags": []}' href="#">{{ lang.add.add_domain_restart }}</button>
+              <button class="btn btn-xs-lg btn-xs-half d-block d-sm-inline btn-secondary" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"tags": []}' href="#">{{ lang.add.add_domain_only }}</button>
+              <button class="btn btn-xs-lg btn-xs-half d-block d-sm-inline btn-secondary" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"restart_sogo":"1", "tags": []}' href="#">{{ lang.add.add_domain_restart }}</button>
               <div class="clearfix visible-xs"></div>
               {% else %}
-              <button class="btn btn-xs-lg visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"tags": []}' href="#">{{ lang.add.add }}</button>
+              <button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"tags": []}' href="#">{{ lang.add.add }}</button>
               {% endif %}
             </div>
           </div>

+ 1 - 1
data/web/templates/user/Spamfilter.twig

@@ -12,7 +12,7 @@
         <div class="col-sm-12">
           <form class="form-horizontal" role="form" data-id="spam_score" method="post">
             <div class="row">
-              <div class="col-lg-8 col-sm-12">
+              <div class="col-sm-12">
                 <div id="spam_score" data-provide="slider" data-acl="{{ acl.spam_score }}"></div>
                 <input id="spam_score_value" name="spam_score" type="hidden" value="{{ user_spam_score }}">
                 <ul class="list-group list-group-flush">

+ 4 - 4
data/web/templates/user/tab-user-auth.twig

@@ -1,7 +1,7 @@
 <div role="tabpanel" class="tab-pane active" id="tab-user-auth">
-  <div class="panel panel-default">
-    <div class="panel-heading">{{ lang.user.mailbox_general }}</div>
-    <div class="panel-body">
+  <div class="card">
+    <div class="card-header">{{ lang.user.mailbox_general }}</div>
+    <div class="card-body">
     {% if mailboxdata.attributes.force_pw_update == '1' %}
         <div class="alert alert-danger">{{ lang.user.force_pw_update|raw }}</div>
     {% endif %}
@@ -115,7 +115,7 @@
       </div>
       <hr>
       <div class="row">
-        <div class="col-sm-offset-3 col-sm-9">
+        <div class="offset-sm-3 col-sm-9">
           <p><a target="_blank" href="https://mailcow.github.io/mailcow-dockerized-docs/client/client/#{{ clientconfigstr }}">[{{ lang.user.client_configuration }}]</a></p>
           <p><a href="#userFilterModal" data-bs-toggle="modal">[{{ lang.user.show_sieve_filters }}]</a></p>
           <hr>