Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions custom_components/taskmate/coord_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ async def async_apply_setup_wizard(
"avatar": spec.get("avatar") or "mdi:account-circle",
"birthday": normalize_birthday(spec.get("birthday", "")),
"age_group": _age_group(spec.get("age_group")),
"color": spec.get("color") or "",
}
)

Expand Down Expand Up @@ -161,6 +162,7 @@ def resolve(who: str) -> str:
avatar=spec["avatar"],
birthday=spec["birthday"],
age_group=spec["age_group"],
color=spec["color"],
refresh=False,
)
ref_to_id[spec["ref"]] = child.id
Expand Down
2 changes: 2 additions & 0 deletions custom_components/taskmate/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@ async def async_add_child(
presence_entity: str = "",
age_group: str = "",
is_adult: bool = False,
color: str = "",
refresh: bool = True,
) -> Child:
"""Add a new child.
Expand All @@ -1011,6 +1012,7 @@ async def async_add_child(
presence_entity=presence_entity,
age_group=age_group,
is_adult=is_adult,
color=color,
)
self.storage.add_child(child)
await self.storage.async_save()
Expand Down
5 changes: 5 additions & 0 deletions custom_components/taskmate/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ class Child:
# A grown-up's profile (#1061): their own completions never wait for
# approval, and cards leave them out unless a card opts in (show_adults).
is_adult: bool = False
# The child's colour (#1078): "#rrggbb", or "" to fall back to the
# panel's palette by position (every child that predates it).
color: str = ""
id: str = field(default_factory=generate_id)

@classmethod
Expand Down Expand Up @@ -284,6 +287,7 @@ def from_dict(cls, data: dict[str, Any]) -> Child:
birthday=str(data.get("birthday", "") or ""),
age_group=normalize_age_group(data.get("age_group")),
is_adult=bool(data.get("is_adult", False)),
color=str(data.get("color", "") or ""),
availability_entity=data.get("availability_entity", ""),
availability_inverted=data.get("availability_inverted", False),
unavailability_entity=data.get("unavailability_entity", ""),
Expand Down Expand Up @@ -324,6 +328,7 @@ def to_dict(self) -> dict[str, Any]:
"birthday": self.birthday,
"age_group": self.age_group,
"is_adult": self.is_adult,
"color": self.color,
"availability_entity": self.availability_entity,
"availability_inverted": self.availability_inverted,
"unavailability_entity": self.unavailability_entity,
Expand Down
19 changes: 19 additions & 0 deletions custom_components/taskmate/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,20 @@ def _validate_presence_entity(value):
return value


_HEX_COLOR = re.compile(r"#[0-9a-f]{6}")


def validate_child_color(value):
"""voluptuous validator: '' (palette default) or a "#rrggbb" colour (#1078).

Strict hex only — the panel drops it straight into a style attribute.
"""
value = _opt_str(value).lower()
if value and not _HEX_COLOR.fullmatch(value):
raise vol.Invalid("color must be a #rrggbb hex colour")
return value


# ---------------------------------------------------------------------------
# State snapshot
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -496,6 +510,7 @@ async def _ws_get_state(hass, connection, msg, coordinator):
vol.Optional("presence_entity", default=""): _validate_presence_entity,
vol.Optional("age_group", default=""): vol.In(("", *AGE_GROUPS)),
vol.Optional("is_adult", default=False): bool,
vol.Optional("color", default=""): validate_child_color,
}
)
@websocket_api.async_response
Expand All @@ -519,6 +534,7 @@ async def _ws_add_child(hass, connection, msg, coordinator):
presence_entity=msg.get("presence_entity", ""),
age_group=msg.get("age_group", ""),
is_adult=bool(msg.get("is_adult", False)),
color=msg.get("color", ""),
)
connection.send_result(msg["id"], {"id": child.id})

Expand All @@ -541,6 +557,7 @@ async def _ws_add_child(hass, connection, msg, coordinator):
vol.Optional("birthday"): vol.All(str, vol.Length(max=10)),
vol.Optional("age_group"): vol.In(("", *AGE_GROUPS)),
vol.Optional("is_adult"): bool,
vol.Optional("color"): validate_child_color,
}
)
@websocket_api.async_response
Expand Down Expand Up @@ -578,6 +595,8 @@ async def _ws_update_child(hass, connection, msg, coordinator):
existing.age_group = msg["age_group"]
if "is_adult" in msg:
existing.is_adult = bool(msg["is_adult"])
if "color" in msg:
existing.color = msg["color"]
if "is_guest" in msg or "guest_expires_on" in msg:
# Routed through the coordinator so the expiry is validated and an
# archived guest is un-archived when promoted to a family member.
Expand Down
3 changes: 2 additions & 1 deletion custom_components/taskmate/websocket_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from .const import AGE_GROUPS, SCHEDULE_MODES
from .coord_birthdays import normalize_birthday, parse_birthday
from .setup_catalogue import setup_catalogue
from .websocket import WS_SETUP_APPLY, WS_SETUP_CATALOGUE, _admin_only
from .websocket import WS_SETUP_APPLY, WS_SETUP_CATALOGUE, _admin_only, validate_child_color

# Generous ceilings: a wizard run is a handful of children and a few dozen
# chores; these only stop a runaway payload.
Expand All @@ -32,6 +32,7 @@
vol.Optional("avatar", default="mdi:account-circle"): vol.All(str, vol.Length(max=80)),
vol.Optional("birthday", default=""): vol.All(str, vol.Length(max=10)),
vol.Optional("age_group", default=""): _AGE_GROUP,
vol.Optional("color", default=""): validate_child_color,
}

_CHILD_UPDATE_SCHEMA = {
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,9 @@
"panel.child_age_group_hint": "Bestemmer, hvilke pligter opsætningsguiden foreslår. Ændrer ikke andet.",
"panel.child_adult_label": "Voksenprofil",
"panel.child_adult_hint": "Til en forælder eller anden voksen. Pligter, de markerer som udført, tæller med det samme uden godkendelse, og kort viser dem kun, når kortets indstilling \"Vis voksne\" er slået til.",
"panel.child_color_label": "Farve",
"panel.child_color_hint": "Markerer barnets avatar og navn i adminpanelet. Automatisk vælger en ud fra barnets plads på listen.",
"panel.child_color_auto": "Automatisk",
"panel.child_adult_pill": "Voksen",
"wizard.title": "Opsætningsguide",
"wizard.run_btn": "Kør opsætningsguiden",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,9 @@
"panel.child_age_group_hint": "Bestimmt, welche Aufgaben der Einrichtungsassistent vorschlägt. Ändert sonst nichts.",
"panel.child_adult_label": "Erwachsenenprofil",
"panel.child_adult_hint": "Für ein Elternteil oder einen anderen Erwachsenen. Aufgaben, die sie als erledigt markieren, zählen sofort ohne Genehmigung, und Karten zeigen sie nur, wenn die Kartenoption „Erwachsene anzeigen“ aktiviert ist.",
"panel.child_color_label": "Farbe",
"panel.child_color_hint": "Kennzeichnet Avatar und Namen dieses Kindes im Admin-Bereich. „Automatisch“ wählt eine Farbe nach der Position in der Liste.",
"panel.child_color_auto": "Automatisch",
"panel.child_adult_pill": "Erwachsen",
"wizard.title": "Einrichtungsassistent",
"wizard.run_btn": "Einrichtungsassistent starten",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/en-GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,9 @@
"panel.child_age_group_hint": "Decides which chores the setup wizard suggests. Changes nothing else.",
"panel.child_adult_label": "Adult profile",
"panel.child_adult_hint": "For a parent or other grown-up. Chores they mark done count straight away with no approval, and cards leave them out unless the card's \"Show adults\" option is on.",
"panel.child_color_label": "Colour",
"panel.child_color_hint": "Marks this child's avatar and name in the admin panel. Automatic picks one from their place in the list.",
"panel.child_color_auto": "Automatic",
"panel.child_adult_pill": "Adult",
"wizard.title": "Setup wizard",
"wizard.run_btn": "Run setup wizard",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,9 @@
"panel.child_age_group_hint": "Decides which chores the setup wizard suggests. Changes nothing else.",
"panel.child_adult_label": "Adult profile",
"panel.child_adult_hint": "For a parent or other grown-up. Chores they mark done count straight away with no approval, and cards leave them out unless the card's \"Show adults\" option is on.",
"panel.child_color_label": "Colour",
"panel.child_color_hint": "Marks this child's avatar and name in the admin panel. Automatic picks one from their place in the list.",
"panel.child_color_auto": "Automatic",
"panel.child_adult_pill": "Adult",
"wizard.title": "Setup wizard",
"wizard.run_btn": "Run setup wizard",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,9 @@
"panel.child_age_group_hint": "Détermine les tâches suggérées par l'assistant de configuration. Ne change rien d'autre.",
"panel.child_adult_label": "Profil adulte",
"panel.child_adult_hint": "Pour un parent ou un autre adulte. Les tâches qu'il marque comme faites comptent tout de suite, sans validation, et les cartes ne l'affichent que si l'option « Afficher les adultes » de la carte est activée.",
"panel.child_color_label": "Couleur",
"panel.child_color_hint": "Repère l'avatar et le nom de cet enfant dans le panneau d'administration. « Automatique » en choisit une selon sa place dans la liste.",
"panel.child_color_auto": "Automatique",
"panel.child_adult_pill": "Adulte",
"wizard.title": "Assistant de configuration",
"wizard.run_btn": "Lancer l'assistant de configuration",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,9 @@
"panel.child_age_group_hint": "Bestemmer hvilke oppgaver oppsettveiviseren foreslår. Endrer ikke noe annet.",
"panel.child_adult_label": "Voksenprofil",
"panel.child_adult_hint": "For en forelder eller en annen voksen. Oppgaver de markerer som gjort, teller med en gang uten godkjenning, og kort viser dem bare når kortets valg «Vis voksne» er slått på.",
"panel.child_color_label": "Farge",
"panel.child_color_hint": "Markerer barnets avatar og navn i adminpanelet. Automatisk velger en ut fra plassen i lista.",
"panel.child_color_auto": "Automatisk",
"panel.child_adult_pill": "Voksen",
"wizard.title": "Oppsettveiviser",
"wizard.run_btn": "Kjør oppsettveiviseren",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/nn.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,9 @@
"panel.child_age_group_hint": "Avgjer kva oppgåver oppsettsvegvisaren føreslår. Endrar ikkje noko anna.",
"panel.child_adult_label": "Vaksenprofil",
"panel.child_adult_hint": "For ein forelder eller ein annan vaksen. Oppgåver dei markerer som gjort, tel med ein gong utan godkjenning, og kort viser dei berre når kortet sitt val «Vis vaksne» er slått på.",
"panel.child_color_label": "Farge",
"panel.child_color_hint": "Markerer avataren og namnet til barnet i adminpanelet. Automatisk vel ein ut frå plassen i lista.",
"panel.child_color_auto": "Automatisk",
"panel.child_adult_pill": "Vaksen",
"wizard.title": "Oppsettsvegvisar",
"wizard.run_btn": "Køyr oppsettsvegvisaren",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,9 @@
"panel.child_age_group_hint": "Decyduje, jakie obowiązki proponuje kreator. Nie zmienia niczego innego.",
"panel.child_adult_label": "Profil dorosłego",
"panel.child_adult_hint": "Dla rodzica lub innej dorosłej osoby. Obowiązki, które oznaczy jako wykonane, liczą się od razu bez zatwierdzania, a karty pokazują tę osobę tylko wtedy, gdy w karcie włączona jest opcja „Pokaż dorosłych”.",
"panel.child_color_label": "Kolor",
"panel.child_color_hint": "Oznacza awatar i imię dziecka w panelu administracyjnym. „Automatycznie” wybiera kolor według miejsca na liście.",
"panel.child_color_auto": "Automatycznie",
"panel.child_adult_pill": "Dorosły",
"wizard.title": "Kreator konfiguracji",
"wizard.run_btn": "Uruchom kreator konfiguracji",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,9 @@
"panel.child_age_group_hint": "Define quais tarefas o assistente de configuração sugere. Não muda mais nada.",
"panel.child_adult_label": "Perfil de adulto",
"panel.child_adult_hint": "Para um pai, mãe ou outro adulto. As tarefas que ele marcar como feitas contam na hora, sem aprovação, e os cartões só o mostram quando a opção \"Mostrar adultos\" do cartão está ativada.",
"panel.child_color_label": "Cor",
"panel.child_color_hint": "Destaca o avatar e o nome desta criança no painel de administração. \"Automática\" escolhe uma cor pela posição na lista.",
"panel.child_color_auto": "Automática",
"panel.child_adult_pill": "Adulto",
"wizard.title": "Assistente de configuração",
"wizard.run_btn": "Executar assistente de configuração",
Expand Down
3 changes: 3 additions & 0 deletions custom_components/taskmate/www/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,9 @@
"panel.child_age_group_hint": "Decide que tarefas o assistente de configuração sugere. Não altera mais nada.",
"panel.child_adult_label": "Perfil de adulto",
"panel.child_adult_hint": "Para um pai, mãe ou outro adulto. As tarefas que marcar como feitas contam logo, sem aprovação, e os cartões só o mostram quando a opção \"Mostrar adultos\" do cartão está ativa.",
"panel.child_color_label": "Cor",
"panel.child_color_hint": "Assinala o avatar e o nome desta criança no painel de administração. «Automática» escolhe uma cor conforme a posição na lista.",
"panel.child_color_auto": "Automática",
"panel.child_adult_pill": "Adulto",
"wizard.title": "Assistente de configuração",
"wizard.run_btn": "Executar assistente de configuração",
Expand Down
Loading
Loading