Răsfoiți Sursa

UI cleanup and slot auto-assign

- Drop "Active code slots" and "Add / overwrite slot" subtitles
- Rename "Set code" button to "Set"
- Switch PIN autocomplete hint to one-time-code to suppress Safari password offer
- set_code slot param now optional; backend picks lowest unused slot from
  cached coordinator data when omitted; frontend slot field shows "auto"
ZiB 4 luni în urmă
părinte
comite
bb15209b60

+ 9 - 9
custom_components/zlock_slots/frontend/zlock-slots-card.js

@@ -109,7 +109,6 @@ class ZLockSlotsCard extends HTMLElement {
         <div class="pending-indicator" id="pending-indicator"><ha-icon icon="mdi:loading"></ha-icon></div>
       <div class="card-content">
         <div class="section">
-          <h3>Active code slots</h3>
           ${slots.length === 0
             ? '<div class="empty-note">No active code slots.</div>'
             : `<table>
@@ -143,7 +142,7 @@ class ZLockSlotsCard extends HTMLElement {
                       <td colspan="3">
                         <div class="pin-edit">
                           <label>New PIN</label>
-                          <input id="pin-input-${s.slot_num}" type="password" minlength="4" maxlength="8" autocomplete="new-password" placeholder="4–8 digits — Enter to save, Esc to cancel" data-slot="${s.slot_num}" data-type="pin" />
+                          <input id="pin-input-${s.slot_num}" type="password" minlength="4" maxlength="8" autocomplete="one-time-code" placeholder="4–8 digits — Enter to save, Esc to cancel" data-slot="${s.slot_num}" data-type="pin" />
                         </div>
                       </td>
                     </tr>
@@ -154,17 +153,16 @@ class ZLockSlotsCard extends HTMLElement {
         </div>
 
         <div class="section">
-          <h3>Add / overwrite slot</h3>
           <div class="form-row-inline">
             <div class="field slot">
               <label>Slot #</label>
-              <input id="add-slot" type="number" min="1" max="999" placeholder="—" />
+              <input id="add-slot" type="number" min="1" max="999" placeholder="auto" />
             </div>
             <div class="field pin">
               <label>PIN</label>
-              <input id="add-code" type="password" minlength="4" maxlength="8" autocomplete="new-password" placeholder="4–8 digits" />
+              <input id="add-code" type="password" minlength="4" maxlength="8" autocomplete="one-time-code" placeholder="4–8 digits" />
             </div>
-            <button class="action" id="add-btn">Set code</button>
+            <button class="action" id="add-btn">Set</button>
           </div>
           <span id="add-status" style="font-size:0.85rem;opacity:0.7"></span>
         </div>
@@ -252,15 +250,17 @@ class ZLockSlotsCard extends HTMLElement {
       const codeInput = root.getElementById("add-code");
       const status = root.getElementById("add-status");
 
-      const slot = parseInt(slotInput.value, 10);
+      const slotVal = slotInput.value ? parseInt(slotInput.value, 10) : undefined;
       const code = codeInput.value.trim();
 
-      if (!slot || slot < 1) { status.textContent = "Enter a valid slot number."; return; }
+      if (slotVal !== undefined && slotVal < 1) { status.textContent = "Slot must be 1 or higher."; return; }
       if (code.length < 4 || code.length > 8) { status.textContent = "PIN must be 4–8 digits."; return; }
 
       status.textContent = "";
       try {
-        await this._callService("set_code", { lock_entity_id: lock, slot, code });
+        const data = { lock_entity_id: lock, code };
+        if (slotVal !== undefined) data.slot = slotVal;
+        await this._callService("set_code", data);
         slotInput.value = "";
         codeInput.value = "";
       } catch (err) {

+ 5 - 2
custom_components/zlock_slots/services.py

@@ -20,7 +20,7 @@ SERVICE_SET_SLOT_ENABLED = "set_slot_enabled"
 
 SET_CODE_SCHEMA = vol.Schema({
   vol.Required("lock_entity_id"): cv.entity_id,
-  vol.Required("slot"): vol.All(int, vol.Range(min=1)),
+  vol.Optional("slot"): vol.All(int, vol.Range(min=1)),
   vol.Required("code"): cv.string,
   vol.Optional("name"): cv.string,
 })
@@ -54,11 +54,14 @@ def _get_coordinator(hass: HomeAssistant, lock_entity_id: str) -> ZLockCoordinat
 def register_services(hass: HomeAssistant) -> None:
   async def handle_set_code(call: ServiceCall) -> None:
     lock_entity_id = call.data["lock_entity_id"]
-    slot = call.data["slot"]
     code = call.data["code"]
     name = call.data.get("name")
 
     coordinator = _get_coordinator(hass, lock_entity_id)
+    slot = call.data.get("slot")
+    if slot is None:
+      used = set(coordinator.data[lock_entity_id].slots.keys())
+      slot = next(i for i in range(1, 1000) if i not in used)
 
     await hass.services.async_call(
       "zwave_js",

+ 2 - 2
custom_components/zlock_slots/services.yaml

@@ -12,8 +12,8 @@ set_code:
           integration: zwave_js
     slot:
       name: Slot number
-      description: Code slot number (1 or higher; slot 0 is reserved).
-      required: true
+      description: Code slot number (1 or higher). If omitted, the lowest unused slot is assigned automatically.
+      required: false
       selector:
         number:
           min: 1