Browse Source

Fix device registration toggle: CSS and SQLAlchemy bugs

- Fix toggle-switch-large CSS: add parent selector to prevent style
  override, center the toggle dot vertically using transform
- Fix SQLAlchemy JSON mutation: reassign whole dict instead of mutating
  to ensure changes are detected and persisted

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
root 2 weeks ago
parent
commit
259e4b69c9

+ 6 - 4
backend/app/api/v1/superadmin/settings.py

@@ -67,8 +67,8 @@ async def get_auto_registration_status(
         time_left = max(0, int(3600 - time_since.total_seconds()))  # 1 hour = 3600 seconds
         time_left = max(0, int(3600 - time_since.total_seconds()))  # 1 hour = 3600 seconds
 
 
         if time_since > timedelta(hours=1):
         if time_since > timedelta(hours=1):
-            # Auto-disable
-            setting.value["enabled"] = False
+            # Auto-disable - must reassign whole dict for SQLAlchemy
+            setting.value = {**setting.value, "enabled": False}
             await db.commit()
             await db.commit()
             enabled = False
             enabled = False
             time_left = 0
             time_left = 0
@@ -106,10 +106,12 @@ async def toggle_auto_registration(
         )
         )
         db.add(setting)
         db.add(setting)
     else:
     else:
-        setting.value["enabled"] = data.enabled
+        # Must reassign the whole dict for SQLAlchemy to detect the change
+        new_value = {**setting.value, "enabled": data.enabled}
         if not data.enabled:
         if not data.enabled:
             # Reset last_device_at when disabling
             # Reset last_device_at when disabling
-            setting.value["last_device_at"] = None
+            new_value["last_device_at"] = None
+        setting.value = new_value
 
 
     await db.commit()
     await db.commit()
 
 

+ 6 - 5
frontend/src/views/superadmin/DevicesView.vue

@@ -1141,7 +1141,7 @@ onBeforeUnmount(() => {
   color: #276749;
   color: #276749;
 }
 }
 
 
-/* Large Toggle Switch */
+/* Large Toggle Switch (for registration banner) */
 .toggle-switch-large {
 .toggle-switch-large {
   position: relative;
   position: relative;
   display: inline-block;
   display: inline-block;
@@ -1153,7 +1153,7 @@ onBeforeUnmount(() => {
   width: 0;
   width: 0;
   height: 0;
   height: 0;
 }
 }
-.toggle-slider {
+.toggle-switch-large .toggle-slider {
   position: absolute;
   position: absolute;
   cursor: pointer;
   cursor: pointer;
   top: 0;
   top: 0;
@@ -1165,13 +1165,14 @@ onBeforeUnmount(() => {
   border-radius: 44px;
   border-radius: 44px;
   border: 2px solid #a0aec0;
   border: 2px solid #a0aec0;
 }
 }
-.toggle-slider:before {
+.toggle-switch-large .toggle-slider:before {
   position: absolute;
   position: absolute;
   content: '';
   content: '';
   height: 36px;
   height: 36px;
   width: 36px;
   width: 36px;
   left: 2px;
   left: 2px;
-  bottom: 2px;
+  top: 50%;
+  transform: translateY(-50%);
   background-color: white;
   background-color: white;
   transition: 0.4s;
   transition: 0.4s;
   border-radius: 50%;
   border-radius: 50%;
@@ -1182,7 +1183,7 @@ onBeforeUnmount(() => {
   border-color: #38a169;
   border-color: #38a169;
 }
 }
 .toggle-switch-large input:checked + .toggle-slider:before {
 .toggle-switch-large input:checked + .toggle-slider:before {
-  transform: translateX(36px);
+  transform: translateY(-50%) translateX(36px);
 }
 }
 .toggle-switch-large input:disabled + .toggle-slider {
 .toggle-switch-large input:disabled + .toggle-slider {
   opacity: 0.6;
   opacity: 0.6;