diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee806b..5852dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,40 @@ All notable changes to HA Daily Counter will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.3.9] - 2025-12-11 + +### ✨ New Feature: Counter Reconfiguration via Options Flow + +This release adds the ability to edit and reconfigure existing counters directly through the Home Assistant UI, without having to delete and recreate them. + +### Added +- ✨ **Edit Counter Option**: New "Edit counter" action in the options flow menu +- 🔄 **Reconfigure Trigger Entity**: Ability to change the entity that triggers the counter +- 🔄 **Reconfigure Trigger State**: Ability to change the state that increments the counter +- 🔄 **Automatic Reload**: Integration automatically reloads when configuration changes are saved +- 📋 **Current Values Display**: Shows current configuration before making changes in the edit flow + +### Changed +- Updated `__init__.py` to register an update listener that reloads the integration when options are modified +- Enhanced `options_flow.py` with new edit steps: `async_step_select_edit`, `async_step_edit_trigger_entity`, and `async_step_edit_trigger_state` +- Updated all translation files (en.json, es.json, strings.json) with new edit-related strings +- Updated version to 1.3.9 in manifest.json + +### Technical Details +- Added `async_reload_entry` function in `__init__.py` to handle config entry reloads +- Registered update listener in `async_setup_entry` to detect option changes and trigger reload +- Modified `HADailyCounterOptionsFlow` class to track editing state with `_selected_edit_index` and `_editing_counter` +- Edit flow preserves counter ID to maintain entity continuity + +### How to Use +1. Go to Settings → Devices & Services +2. Find your HA Daily Counter integration +3. Click "Configure" on any existing counter entry +4. Select "Edit counter" from the action menu +5. Choose which counter you want to edit +6. Update the trigger entity or trigger state +7. The integration will automatically reload with the new configuration + ## [1.3.8] - 2025-12-10 ### 🔧 Critical Bug Fix Release diff --git a/RELEASE_NOTES_v1.3.9.md b/RELEASE_NOTES_v1.3.9.md new file mode 100644 index 0000000..81c023b --- /dev/null +++ b/RELEASE_NOTES_v1.3.9.md @@ -0,0 +1,137 @@ +# Release Notes for v1.3.9 / Notas de Lanzamiento v1.3.9 + +--- + +## 🇬🇧 English Version + +### ✨ New Feature: Counter Reconfiguration via Options Flow + +This release adds the ability to edit and reconfigure existing counters directly through the Home Assistant UI, without having to delete and recreate them. + +#### What's new? +- ✨ **Edit Counter Option**: New "Edit counter" action in the options flow menu +- 🔄 **Reconfigure Trigger Entity**: Change the entity that triggers the counter +- 🔄 **Reconfigure Trigger State**: Change the state that increments the counter +- 🔄 **Automatic Reload**: Integration automatically reloads when configuration changes are saved +- 📋 **Current Values Display**: See current configuration before making changes + +#### Who should use this? +**All users who want to modify their existing counters** without losing their current count values or having to delete and recreate the counter. + +#### How to use the new feature? +1. Go to Settings → Devices & Services +2. Find your HA Daily Counter integration +3. Click "Configure" on any existing counter entry +4. Select "Edit counter" from the action menu +5. Choose which counter you want to edit +6. Update the trigger entity or trigger state +7. The integration will automatically reload with the new configuration + +#### Technical Changes +- Added `async_reload_entry` function in `__init__.py` to handle config entry reloads +- Registered update listener in `async_setup_entry` to detect option changes +- Added `async_step_select_edit`, `async_step_edit_trigger_entity`, and `async_step_edit_trigger_state` methods to `HADailyCounterOptionsFlow` +- Updated translation files (en.json, es.json, strings.json) with new edit-related strings +- Updated version to 1.3.9 in manifest.json + +#### Installation +1. Update via HACS or manually install v1.3.9 +2. Restart Home Assistant +3. Navigate to your integration settings to try the new edit feature + +#### Need help? +If you experience any issues: +1. Check your Home Assistant logs for errors +2. Try reloading the integration from Settings → Devices & Services +3. Report issues at: https://github.com/Geek-MD/HA_Daily_Counter/issues + +--- + +## 🇪🇸 Versión en Español + +### ✨ Nueva Funcionalidad: Reconfiguración de Contadores vía Options Flow + +Este lanzamiento añade la capacidad de editar y reconfigurar contadores existentes directamente a través de la interfaz de Home Assistant, sin necesidad de eliminar y recrear. + +#### ¿Qué hay de nuevo? +- ✨ **Opción de Editar Contador**: Nueva acción "Editar contador" en el menú de flujo de opciones +- 🔄 **Reconfigurar Entidad Disparadora**: Cambia la entidad que dispara el contador +- 🔄 **Reconfigurar Estado Disparador**: Cambia el estado que incrementa el contador +- 🔄 **Recarga Automática**: La integración se recarga automáticamente cuando se guardan los cambios de configuración +- 📋 **Visualización de Valores Actuales**: Ve la configuración actual antes de hacer cambios + +#### ¿Quién debería usar esto? +**Todos los usuarios que quieran modificar sus contadores existentes** sin perder los valores actuales del contador o tener que eliminar y recrear el contador. + +#### ¿Cómo usar la nueva funcionalidad? +1. Ve a Configuración → Dispositivos y Servicios +2. Encuentra tu integración HA Daily Counter +3. Haz clic en "Configurar" en cualquier entrada de contador existente +4. Selecciona "Editar contador" del menú de acciones +5. Elige qué contador quieres editar +6. Actualiza la entidad disparadora o el estado disparador +7. La integración se recargará automáticamente con la nueva configuración + +#### Cambios Técnicos +- Agregada función `async_reload_entry` en `__init__.py` para manejar recargas de entradas de configuración +- Registrado listener de actualización en `async_setup_entry` para detectar cambios de opciones +- Agregados métodos `async_step_select_edit`, `async_step_edit_trigger_entity` y `async_step_edit_trigger_state` a `HADailyCounterOptionsFlow` +- Actualizados archivos de traducción (en.json, es.json, strings.json) con nuevas cadenas relacionadas con edición +- Actualizada versión a 1.3.9 en manifest.json + +#### Instalación +1. Actualiza a través de HACS o instala manualmente la v1.3.9 +2. Reinicia Home Assistant +3. Navega a la configuración de tu integración para probar la nueva función de edición + +#### ¿Necesitas ayuda? +Si experimentas algún problema: +1. Verifica los registros de Home Assistant para errores +2. Intenta recargar la integración desde Configuración → Dispositivos y Servicios +3. Reporta problemas en: https://github.com/Geek-MD/HA_Daily_Counter/issues + +--- + +## 📋 Copy-Paste for GitHub Release / Para copiar en GitHub Release + +### Short Version / Versión Corta + +**✨ New Feature: Counter Reconfiguration via Options Flow** + +This release adds the ability to edit existing counters through the Home Assistant UI without deleting and recreating them. + +**What's New:** +- ✨ Edit counter option in options flow menu +- 🔄 Reconfigure trigger entity and state +- 🔄 Automatic reload when changes are saved +- 📋 Display current values before editing + +**How to Use:** +1. Go to Settings → Devices & Services +2. Click "Configure" on any counter +3. Select "Edit counter" +4. Update trigger entity or state +5. Changes apply automatically after save + +**Installation:** Update via HACS and restart Home Assistant. + +--- + +**✨ Nueva Funcionalidad: Reconfiguración de Contadores vía Options Flow** + +Este lanzamiento añade la capacidad de editar contadores existentes a través de la interfaz de Home Assistant sin eliminarlos y recrearlos. + +**Qué Hay de Nuevo:** +- ✨ Opción de editar contador en el menú de flujo de opciones +- 🔄 Reconfigurar entidad y estado disparador +- 🔄 Recarga automática cuando se guardan los cambios +- 📋 Mostrar valores actuales antes de editar + +**Cómo Usar:** +1. Ve a Configuración → Dispositivos y Servicios +2. Haz clic en "Configurar" en cualquier contador +3. Selecciona "Editar contador" +4. Actualiza entidad o estado disparador +5. Los cambios se aplican automáticamente después de guardar + +**Instalación:** Actualiza vía HACS y reinicia Home Assistant. diff --git a/custom_components/ha_daily_counter/__init__.py b/custom_components/ha_daily_counter/__init__.py index 6decbb2..e9a3d7c 100644 --- a/custom_components/ha_daily_counter/__init__.py +++ b/custom_components/ha_daily_counter/__init__.py @@ -42,6 +42,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: cast(Any, hass.config_entries).async_forward_entry_setups(entry, ["sensor"]) ) + # Register update listener to reload when options change + entry.async_on_unload(entry.add_update_listener(async_reload_entry)) + async def handle_reset_counter(call: ServiceCall) -> None: """Handle the reset_counter service call.""" entity_id = call.data.get("entity_id") @@ -94,3 +97,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Llamada a la versión plural de unload si existe; usar cast para evitar chequeos estáticos. unloaded = await cast(Any, hass.config_entries).async_forward_entry_unloads(entry, ["sensor"]) return all(unloaded) + + +async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Reload config entry when options are updated.""" + await hass.config_entries.async_reload(entry.entry_id) diff --git a/custom_components/ha_daily_counter/manifest.json b/custom_components/ha_daily_counter/manifest.json index bfda8b0..59c0002 100644 --- a/custom_components/ha_daily_counter/manifest.json +++ b/custom_components/ha_daily_counter/manifest.json @@ -8,5 +8,5 @@ "iot_class": "local_push", "issue_tracker": "https://github.com/Geek-MD/HA_Daily_Counter/issues", "requirements": [], - "version": "1.3.8" + "version": "1.3.9" } diff --git a/custom_components/ha_daily_counter/options_flow.py b/custom_components/ha_daily_counter/options_flow.py index ebc14fc..853ba1e 100644 --- a/custom_components/ha_daily_counter/options_flow.py +++ b/custom_components/ha_daily_counter/options_flow.py @@ -22,12 +22,16 @@ def __init__(self, config_entry: ConfigEntry) -> None: self._counters = list(config_entry.options.get("counters", [])) self._new_counter: Dict[str, Any] = {} self._selected_delete_name: Optional[str] = None + self._selected_edit_index: Optional[int] = None + self._editing_counter: Dict[str, Any] = {} async def async_step_init(self, user_input: Optional[Dict[str, Any]] = None) -> config_entries.FlowResult: - """Initial step: add or delete a counter.""" + """Initial step: add, edit, or delete a counter.""" if user_input is not None: if user_input["action"] == "add": return await self.async_step_user() + elif user_input["action"] == "edit": + return await self.async_step_select_edit() elif user_input["action"] == "delete": return await self.async_step_select_delete() @@ -40,6 +44,7 @@ async def async_step_init(self, user_input: Optional[Dict[str, Any]] = None) -> SelectSelectorConfig( options=[ SelectOptionDict(value="add", label="Add counter"), + SelectOptionDict(value="edit", label="Edit counter"), SelectOptionDict(value="delete", label="Delete counter"), SelectOptionDict(value="finish", label="Finish setup") ], @@ -85,25 +90,91 @@ async def async_step_trigger_state(self, user_input: Optional[Dict[str, Any]] = return self.async_show_form( step_id="trigger_state", data_schema={ - "trigger_state": SelectSelector( + "trigger_state": str + }, + ) + + async def async_step_select_edit(self, user_input: Optional[Dict[str, Any]] = None) -> config_entries.FlowResult: + """Step to select a counter to edit.""" + if not self._counters: + return await self.async_step_init() + + if user_input is not None: + selected_name = user_input["edit_target"] + # Find the counter index by name + for idx, counter in enumerate(self._counters): + if counter["name"] == selected_name: + self._selected_edit_index = idx + self._editing_counter = dict(counter) + return await self.async_step_edit_trigger_entity() + # If not found, go back to init + return await self.async_step_init() + + return self.async_show_form( + step_id="select_edit", + data_schema={ + "edit_target": SelectSelector( SelectSelectorConfig( options=[ - SelectOptionDict(value="on", label="on"), - SelectOptionDict(value="off", label="off"), - SelectOptionDict(value="home", label="home"), - SelectOptionDict(value="not_home", label="not_home"), - SelectOptionDict(value="open", label="open"), - SelectOptionDict(value="closed", label="closed"), - SelectOptionDict(value="idle", label="idle"), - SelectOptionDict(value="playing", label="playing") + SelectOptionDict(value=c["name"], label=c["name"]) + for c in self._counters ], - multiple=False, mode=SelectSelectorMode.DROPDOWN ) ) }, ) + async def async_step_edit_trigger_entity(self, user_input: Optional[Dict[str, Any]] = None) -> config_entries.FlowResult: + """Step to edit the trigger entity.""" + if user_input is not None: + self._editing_counter["trigger_entity"] = user_input["trigger_entity"] + return await self.async_step_edit_trigger_state() + + # Get current trigger entity value + current_entity = self._editing_counter.get("trigger_entity", "") + + return self.async_show_form( + step_id="edit_trigger_entity", + data_schema={ + "trigger_entity": EntitySelector( + EntitySelectorConfig() + ) + }, + description_placeholders={ + "current_value": current_entity, + "counter_name": self._editing_counter.get("name", "") + } + ) + + async def async_step_edit_trigger_state(self, user_input: Optional[Dict[str, Any]] = None) -> config_entries.FlowResult: + """Step to edit the trigger state.""" + if user_input is not None: + self._editing_counter["trigger_state"] = user_input["trigger_state"] + # Update the counter in the list + if self._selected_edit_index is not None and 0 <= self._selected_edit_index < len(self._counters): + self._counters[self._selected_edit_index] = self._editing_counter + + # Reset editing state + self._selected_edit_index = None + self._editing_counter = {} + + return await self.async_step_init() + + # Get current trigger state value + current_state = self._editing_counter.get("trigger_state", "") + + return self.async_show_form( + step_id="edit_trigger_state", + data_schema={ + "trigger_state": str + }, + description_placeholders={ + "current_value": current_state, + "counter_name": self._editing_counter.get("name", "") + } + ) + async def async_step_select_delete(self, user_input: Optional[Dict[str, Any]] = None) -> config_entries.FlowResult: """Step to select a counter to delete.""" if not self._counters: diff --git a/custom_components/ha_daily_counter/translations/en.json b/custom_components/ha_daily_counter/translations/en.json index 6c5eaec..d008c58 100644 --- a/custom_components/ha_daily_counter/translations/en.json +++ b/custom_components/ha_daily_counter/translations/en.json @@ -41,11 +41,32 @@ "step": { "init": { "title": "Manage Counters", - "description": "Add or remove counters used by this integration.", + "description": "Add, edit, or remove counters used by this integration.", "data": { "action": "Choose an action" } }, + "select_edit": { + "title": "Edit Counter", + "description": "Select the counter you want to edit.", + "data": { + "edit_target": "Counter" + } + }, + "edit_trigger_entity": { + "title": "Edit Trigger Entity", + "description": "Editing counter: {counter_name}\nCurrent entity: {current_value}\n\nSelect the new trigger entity:", + "data": { + "trigger_entity": "Trigger Entity" + } + }, + "edit_trigger_state": { + "title": "Edit Trigger State", + "description": "Editing counter: {counter_name}\nCurrent state: {current_value}\n\nSelect the new trigger state:", + "data": { + "trigger_state": "Trigger State" + } + }, "select_delete": { "title": "Delete Counter", "description": "Select the counter you want to delete.", diff --git a/custom_components/ha_daily_counter/translations/es.json b/custom_components/ha_daily_counter/translations/es.json index 9ca3655..8ff5bc7 100644 --- a/custom_components/ha_daily_counter/translations/es.json +++ b/custom_components/ha_daily_counter/translations/es.json @@ -41,11 +41,32 @@ "step": { "init": { "title": "Gestionar Contadores", - "description": "Agrega o elimina contadores usados por esta integración.", + "description": "Agrega, edita o elimina contadores usados por esta integración.", "data": { "action": "Elige una acción" } }, + "select_edit": { + "title": "Editar Contador", + "description": "Selecciona el contador que quieres editar.", + "data": { + "edit_target": "Contador" + } + }, + "edit_trigger_entity": { + "title": "Editar Entidad Disparadora", + "description": "Editando contador: {counter_name}\nEntidad actual: {current_value}\n\nSelecciona la nueva entidad disparadora:", + "data": { + "trigger_entity": "Entidad Disparadora" + } + }, + "edit_trigger_state": { + "title": "Editar Estado Disparador", + "description": "Editando contador: {counter_name}\nEstado actual: {current_value}\n\nSelecciona el nuevo estado disparador:", + "data": { + "trigger_state": "Estado Disparador" + } + }, "select_delete": { "title": "Eliminar Contador", "description": "Selecciona el contador que quieres eliminar.", diff --git a/custom_components/ha_daily_counter/translations/strings.json b/custom_components/ha_daily_counter/translations/strings.json index 5dfddb4..5b17838 100644 --- a/custom_components/ha_daily_counter/translations/strings.json +++ b/custom_components/ha_daily_counter/translations/strings.json @@ -41,11 +41,32 @@ "step": { "init": { "title": "Manage Counters", - "description": "Add or remove counters used by this integration.", + "description": "Add, edit, or remove counters used by this integration.", "data": { "action": "Choose an action" } }, + "select_edit": { + "title": "Edit Counter", + "description": "Select the counter you want to edit.", + "data": { + "edit_target": "Counter" + } + }, + "edit_trigger_entity": { + "title": "Edit Trigger Entity", + "description": "Editing counter: {counter_name}\nCurrent entity: {current_value}\n\nSelect the new trigger entity:", + "data": { + "trigger_entity": "Trigger Entity" + } + }, + "edit_trigger_state": { + "title": "Edit Trigger State", + "description": "Editing counter: {counter_name}\nCurrent state: {current_value}\n\nSelect the new trigger state:", + "data": { + "trigger_state": "Trigger State" + } + }, "select_delete": { "title": "Delete Counter", "description": "Select the counter you want to delete.",