Skip to content

Commit

Permalink
Forecast dates and overdue icon config options
Browse files Browse the repository at this point in the history
  • Loading branch information
bmcclure committed Apr 16, 2023
1 parent 6b477ef commit d0461af
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 49 deletions.
84 changes: 43 additions & 41 deletions custom_components/chore_helper/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,57 +58,59 @@ def optional(
return vol.Optional(key, description={"suggested_value": suggested_value})


def general_schema_definition(
handler: SchemaConfigFlowHandler | SchemaOptionsFlowHandler,
) -> Mapping[str, Any]:
"""Create general schema."""
schema = {
required(
const.CONF_FREQUENCY, handler.options, const.DEFAULT_FREQUENCY
): selector.SelectSelector(
selector.SelectSelectorConfig(options=const.FREQUENCY_OPTIONS)
),
optional(
const.CONF_ICON_NORMAL, handler.options, const.DEFAULT_ICON_NORMAL
): selector.IconSelector(),
optional(
const.CONF_ICON_TOMORROW, handler.options, const.DEFAULT_ICON_TOMORROW
): selector.IconSelector(),
optional(
const.CONF_ICON_TODAY, handler.options, const.DEFAULT_ICON_TODAY
): selector.IconSelector(),
optional(
const.CONF_ICON_OVERDUE, handler.options, const.DEFAULT_ICON_OVERDUE
): selector.IconSelector(),
optional(
const.CONF_FORECAST_DATES, handler.options, const.DEFAULT_FORECAST_DATES
): selector.NumberSelector(
selector.NumberSelectorConfig(
min=0,
max=100,
mode=selector.NumberSelectorMode.BOX,
step=1,
)
),
optional(ATTR_HIDDEN, handler.options, False): bool,
optional(const.CONF_MANUAL, handler.options, False): bool,
}

return schema


async def general_config_schema(
handler: SchemaConfigFlowHandler | SchemaOptionsFlowHandler,
) -> vol.Schema:
"""Generate config schema."""
return vol.Schema(
{
optional(CONF_NAME, handler.options): selector.TextSelector(),
required(
const.CONF_FREQUENCY, handler.options, const.DEFAULT_FREQUENCY
): selector.SelectSelector(
selector.SelectSelectorConfig(options=const.FREQUENCY_OPTIONS)
),
optional(
const.CONF_ICON_NORMAL, handler.options, const.DEFAULT_ICON_NORMAL
): selector.IconSelector(),
optional(
const.CONF_ICON_TODAY, handler.options, const.DEFAULT_ICON_TODAY
): selector.IconSelector(),
optional(
const.CONF_ICON_TOMORROW, handler.options, const.DEFAULT_ICON_TOMORROW
): selector.IconSelector(),
optional(ATTR_HIDDEN, handler.options, False): bool,
optional(const.CONF_MANUAL, handler.options, False): bool,
}
)
schema_obj = {required(CONF_NAME, handler.options): selector.TextSelector()}
schema_obj.update(general_schema_definition(handler))
return vol.Schema(schema_obj)


async def general_options_schema(
handler: SchemaConfigFlowHandler | SchemaOptionsFlowHandler,
) -> vol.Schema:
"""Generate options schema."""
return vol.Schema(
{
required(
const.CONF_FREQUENCY, handler.options, const.DEFAULT_FREQUENCY
): selector.SelectSelector(
selector.SelectSelectorConfig(options=const.FREQUENCY_OPTIONS)
),
optional(
const.CONF_ICON_NORMAL, handler.options, const.DEFAULT_ICON_NORMAL
): selector.IconSelector(),
optional(
const.CONF_ICON_TODAY, handler.options, const.DEFAULT_ICON_TODAY
): selector.IconSelector(),
optional(
const.CONF_ICON_TOMORROW, handler.options, const.DEFAULT_ICON_TOMORROW
): selector.IconSelector(),
optional(ATTR_HIDDEN, handler.options, False): bool,
optional(const.CONF_MANUAL, handler.options, False): bool,
}
)
return vol.Schema(general_schema_definition(handler))


async def detail_config_schema(
Expand Down
4 changes: 4 additions & 0 deletions custom_components/chore_helper/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@

CONF_SENSOR = "sensor"
CONF_ENABLED = "enabled"
CONF_FORECAST_DATES = "forecast_dates"
CONF_FREQUENCY = "frequency"
CONF_MANUAL = "manual_update"
CONF_ICON_NORMAL = "icon_normal"
CONF_ICON_TODAY = "icon_today"
CONF_ICON_TOMORROW = "icon_tomorrow"
CONF_ICON_OVERDUE = "icon_overdue"
CONF_OFFSET = "offset"
CONF_DAY_OF_MONTH = "day_of_month"
CONF_FIRST_MONTH = "first_month"
Expand All @@ -54,10 +56,12 @@
DEFAULT_PERIOD = 1
DEFAULT_FIRST_WEEK = 1
DEFAULT_DATE_FORMAT = "%b-%d-%Y"
DEFAULT_FORECAST_DATES = 10

DEFAULT_ICON_NORMAL = "mdi:broom"
DEFAULT_ICON_TODAY = "mdi:bell"
DEFAULT_ICON_TOMORROW = "mdi:bell-outline"
DEFAULT_ICON_OVERDUE = "mdi:bell-alert"
ICON = DEFAULT_ICON_NORMAL

STATE_TODAY = "today"
Expand Down
20 changes: 14 additions & 6 deletions custom_components/chore_helper/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from datetime import date, datetime, time, timedelta
from typing import Any
from collections.abc import Generator
import itertools

from dateutil.relativedelta import relativedelta
from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -71,10 +72,12 @@ class Chore(RestoreEntity):
"_icon_normal",
"_icon_today",
"_icon_tomorrow",
"_icon_overdue",
"_last_month",
"_last_updated",
"_manual",
"_next_due_date",
"_forecast_dates",
"_overdue",
"_overdue_days",
"_frequency",
Expand Down Expand Up @@ -109,9 +112,11 @@ def __init__(self, config_entry: ConfigEntry) -> None:
self._icon_normal = config.get(const.CONF_ICON_NORMAL)
self._icon_today = config.get(const.CONF_ICON_TODAY)
self._icon_tomorrow = config.get(const.CONF_ICON_TOMORROW)
self._icon_overdue = config.get(const.CONF_ICON_OVERDUE)
self._date_format = config.get(
const.CONF_DATE_FORMAT, const.DEFAULT_DATE_FORMAT
)
self._forecast_dates: int = config.get(const.CONF_FORECAST_DATES) or 0
self._due_dates: list[date] = []
self._next_due_date: date | None = None
self._last_updated: datetime | None = None
Expand Down Expand Up @@ -395,7 +400,9 @@ def chore_schedule(self) -> Generator[date, None, None]:
today = helpers.now().date()
start_date: date = self._calculate_start_date()
last_date: date = date(today.year + 1, 12, 31)
while True:
for i in itertools.count():
if i > self._forecast_dates:
break
try:
next_due_date = self._find_candidate_date(start_date)
except (TypeError, ValueError):
Expand Down Expand Up @@ -556,11 +563,12 @@ def update_state(self) -> None:
self._attr_state = self._days
if self._days > 1:
self._attr_icon = self._icon_normal
else:
if self._days == 0:
self._attr_icon = self._icon_today
elif self._days == 1:
self._attr_icon = self._icon_tomorrow
elif self._days < 0:
self._attr_icon = self._icon_overdue
elif self._days == 0:
self._attr_icon = self._icon_today
elif self._days == 1:
self._attr_icon = self._icon_tomorrow
self._overdue = self._days < 0
self._overdue_days = 0 if self._days > -1 else abs(self._days)
else:
Expand Down
8 changes: 6 additions & 2 deletions custom_components/chore_helper/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"manual_update": "Manual update - sensor state updated manually by a service (Blueprint)",
"icon_normal": "Icon (mdi:broom) - optional",
"icon_tomorrow": "Icon due tomorrow (mdi:bell-outline) - optional",
"icon_today": "Icon due today (mdi:bell) - optional"
"icon_today": "Icon due today (mdi:bell) - optional",
"icon_overdue": "Icon overdue (mdi:bell-alert) - optional",
"forecast_dates": "Number of future due dates to forecast"
}
},
"detail": {
Expand Down Expand Up @@ -61,7 +63,9 @@
"manual_update": "Manual update - sensor state updated manually by a service (Blueprint)",
"icon_normal": "Icon (mdi:broom) - optional",
"icon_tomorrow": "Icon due tomorrow (mdi:bell-outline) - optional",
"icon_today": "Icon due today (mdi:bell) - optional"
"icon_today": "Icon due today (mdi:bell) - optional",
"icon_overdue": "Icon overdue (mdi:bell-alert) - optional",
"forecast_dates": "Number of future due dates to forecast"
}
},
"detail": {
Expand Down

0 comments on commit d0461af

Please sign in to comment.