2
0
Эх сурвалжийг харах

[BS5] remember last nav pill fix

FreddleSpl0it 3 жил өмнө
parent
commit
cdd2adbc73

+ 0 - 2
data/web/js/build/012-api.js

@@ -318,7 +318,6 @@ $(document).ready(function() {
 
   // General API delete actions
   $(document).on('click', "[data-action='delete_selected']", function(e) {
-    console.log("delete");
     e.preventDefault();
     var id = $(this).data('id');
     // If clicked element #delete_selected has data-item attribute, it is added to "items"
@@ -337,7 +336,6 @@ $(document).ready(function() {
     if (typeof multi_data[id] == "undefined" || multi_data[id] == "") return;
     data_array = multi_data[id];
     api_url = $(this).data('api-url');
-    console.log("delete modal");
     $(document).on('show.bs.modal', '#ConfirmDeleteModal', function() {
       $("#ItemsToDelete").empty();
       for (var i in data_array) {

+ 27 - 6
data/web/js/build/014-mailcow.js

@@ -61,18 +61,38 @@ $(document).ready(function() {
   // remember last navigation pill
   (function () {
     'use strict';
-    if ($('button[data-bs-toggle="tab"]').length) {
-      $('button[data-bs-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;
         }
-        var id = $(this).parents('[role="tablist"]').attr('id');
+        var id = $(this).attr('id');
         var key = 'lastTag';
         if (id) {
           key += ':' + id;
         }
-        localStorage.setItem(key, $(e.target).attr('data-bs-target').substring(1));
+
+        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).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) {
-          $("[id^=" + lastTab + "]").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

+ 188 - 188
data/web/templates/admin/tab-config-admins.twig

@@ -1,230 +1,230 @@
 <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="ollapse-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 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>
-        <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>
+      {# 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 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 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>
 
-        {# 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>
+      {# 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>
-          <br>
         </div>
+        <br>
+      </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>
+      <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>
         </div>
+      </div>
 
-        <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 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;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 mb-5">
-          <form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
-            <div class="row">
-              <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>
+      <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 mb-5">
+        <form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
+          <div class="row">
+            <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="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="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>
-          </form>
-        </div>
+          </div>
+        </form>
+      </div>
 
-        <legend style="cursor:pointer;" 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>
+      <legend style="cursor:pointer;" 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 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-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 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-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 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">
+                      <label>
+                        <input type="checkbox" name="active" {% if api.ro.active %}checked{% endif %}> {{ lang.admin.activate_api }}
+                      </label>
                     </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="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>
-                  </form>
-                </div>
+                  </div>
+                </form>
               </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="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 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-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 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-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 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">
+                      <label>
+                        <input type="checkbox" name="active" {% if api.rw.active %}checked{% endif %}> {{ lang.admin.activate_api }}
+                      </label>
                     </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="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>
-                  </form>
-                </div>
+                  </div>
+                </form>
               </div>
             </div>
           </div>
         </div>
       </div>
     </div>
+  </div>
 
   <div class="card mb-4">
     <div class="card-header d-flex">

+ 12 - 12
data/web/templates/debug.twig

@@ -7,20 +7,20 @@
     <a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.debug.logs }}</a>
     <ul class="dropdown-menu">
       <li role="presentation"><span class="dropdown-header fs-6">{{ lang.debug.in_memory_logs }}</span></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-postfix-logs" aria-controls="tab-postfix-logs" role="tab" data-bs-toggle="tab">Postfix</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-dovecot-logs" aria-controls="tab-dovecot-logs" role="tab" data-bs-toggle="tab">Dovecot</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-sogo-logs" aria-controls="tab-sogo-logs" role="tab" data-bs-toggle="tab">SOGo</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-netfilter-logs" aria-controls="tab-netfilter-logs" role="tab" data-bs-toggle="tab">Netfilter</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-autodiscover-logs" aria-controls="tab-autodiscover-logs" role="tab" data-bs-toggle="tab">Autodiscover</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-watchdog-logs" aria-controls="tab-watchdog-logs" role="tab" data-bs-toggle="tab">Watchdog</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-acme-logs" aria-controls="tab-acme-logs" role="tab" data-bs-toggle="tab">ACME</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-api-logs" aria-controls="tab-api-logs" role="tab" data-bs-toggle="tab">API</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-api-rl" aria-controls="tab-api-rl" role="tab" data-bs-toggle="tab">Ratelimits</a></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-postfix-logs" aria-selected="false" aria-controls="tab-postfix-logs" role="tab" data-bs-toggle="tab">Postfix</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-dovecot-logs" aria-selected="false" aria-controls="tab-dovecot-logs" role="tab" data-bs-toggle="tab">Dovecot</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-sogo-logs" aria-selected="false" aria-controls="tab-sogo-logs" role="tab" data-bs-toggle="tab">SOGo</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-netfilter-logs" aria-selected="false" aria-controls="tab-netfilter-logs" role="tab" data-bs-toggle="tab">Netfilter</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-autodiscover-logs" aria-selected="false" aria-controls="tab-autodiscover-logs" role="tab" data-bs-toggle="tab">Autodiscover</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-watchdog-logs" aria-selected="false" aria-controls="tab-watchdog-logs" role="tab" data-bs-toggle="tab">Watchdog</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-acme-logs" aria-selected="false" aria-controls="tab-acme-logs" role="tab" data-bs-toggle="tab">ACME</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-api-logs" aria-selected="false" aria-controls="tab-api-logs" role="tab" data-bs-toggle="tab">API</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-api-rl" aria-selected="false" aria-controls="tab-api-rl" role="tab" data-bs-toggle="tab">Ratelimits</button></li>
       <li role="presentation"><span class="dropdown-header fs-6">{{ lang.debug.external_logs }}</span></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-rspamd-history" aria-controls="tab-rspamd-history" role="tab" data-bs-toggle="tab">Rspamd</a></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-rspamd-history" aria-selected="false" aria-controls="tab-rspamd-history" role="tab" data-bs-toggle="tab">Rspamd</button></li>
       <li role="presentation"><span class="dropdown-header fs-6">{{ lang.debug.static_logs }}</span></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-ui" aria-controls="tab-ui" role="tab" data-bs-toggle="tab">Mailcow UI</a></li>
-      <li role="presentation"><a class="dropdown-item" href="#tab-sasl" aria-controls="tab-sasl" role="tab" data-bs-toggle="tab">SASL</a></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-ui" aria-selected="false" aria-controls="tab-ui" role="tab" data-bs-toggle="tab">Mailcow UI</button></li>
+      <li role="presentation"><button class="dropdown-item" data-bs-target="#tab-sasl" aria-selected="false" aria-controls="tab-sasl" role="tab" data-bs-toggle="tab">SASL</button></li>
     </ul>
   </li>
 </ul>