feat: enhance color handling in templates and dashboard with hex support
This commit is contained in:
+17
-2
@@ -32,6 +32,17 @@ def get_html_template(content) -> str:
|
||||
return HTML_TEMPLATE.format(content=content)
|
||||
|
||||
|
||||
def _as_hex_color(value: int | str | None) -> str:
|
||||
if isinstance(value, int):
|
||||
return f"#{value:06X}"
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return f"#{parse_color(value):06X}"
|
||||
except ValueError:
|
||||
return "#000000"
|
||||
return "#000000"
|
||||
|
||||
|
||||
def create_app(
|
||||
*,
|
||||
get_state: Callable[[], dict],
|
||||
@@ -77,13 +88,14 @@ def create_app(
|
||||
blocks = []
|
||||
for key, tpl in templates.items():
|
||||
text = (tpl.get("text") or "").replace("'", "'")
|
||||
color = tpl.get("color")
|
||||
color_hex = _as_hex_color(tpl.get("color"))
|
||||
image_url = tpl.get("image_url") or ""
|
||||
blocks.append(
|
||||
"<fieldset style='margin-bottom:16px;'>"
|
||||
f"<legend><strong>{key}</strong></legend>"
|
||||
f"<label>Text<br><textarea name='{key}__text' rows='3' style='width:100%'>{text}</textarea></label><br>"
|
||||
f"<label>Color<br><input name='{key}__color' value='{color}' style='width:200px'></label><br>"
|
||||
f"<label>Color<br><input type='color' name='{key}__color_picker' value='{color_hex}' oninput=\"this.form['{key}__color'].value=this.value\"></label><br>"
|
||||
f"<label>Color value<br><input name='{key}__color' value='{color_hex}' style='width:200px'></label><br>"
|
||||
f"<label>Image URL (optional)<br><input name='{key}__image_url' value='{image_url}' style='width:100%'></label>"
|
||||
"</fieldset>"
|
||||
)
|
||||
@@ -108,6 +120,9 @@ def create_app(
|
||||
for key in current.keys():
|
||||
text = request.form.get(f"{key}__text", "").strip()
|
||||
color_raw = request.form.get(f"{key}__color", "").strip()
|
||||
if not color_raw:
|
||||
color_raw = request.form.get(
|
||||
f"{key}__color_picker", "").strip()
|
||||
image_url = request.form.get(f"{key}__image_url", "").strip()
|
||||
|
||||
if not text:
|
||||
|
||||
+5
-5
@@ -1,24 +1,24 @@
|
||||
{
|
||||
"420": {
|
||||
"color": 3066993,
|
||||
"color": "#2ECC71",
|
||||
"image_url": "https://copyparty.allucanget.biz/img/weed.png",
|
||||
"text": "Blaze it!"
|
||||
},
|
||||
"halftime": {
|
||||
"color": 3066993,
|
||||
"color": "#2ECC71",
|
||||
"image_url": "https://copyparty.allucanget.biz/img/weed.png",
|
||||
"text": "Half-time!"
|
||||
},
|
||||
"reminder": {
|
||||
"color": 15105570,
|
||||
"color": "#E67E22",
|
||||
"text": "This is your 5 minute reminder to 420!"
|
||||
},
|
||||
"reminder_halftime": {
|
||||
"color": 15105570,
|
||||
"color": "#E67E22",
|
||||
"text": "Half-time in 5 minutes!"
|
||||
},
|
||||
"test": {
|
||||
"color": 3447003,
|
||||
"color": "#3498DB",
|
||||
"text": "This is a test notification."
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -49,6 +49,11 @@ def _normalize_templates(raw: dict) -> dict[str, dict]:
|
||||
color = incoming.get("color")
|
||||
if isinstance(color, int):
|
||||
out[key]["color"] = color
|
||||
elif isinstance(color, str):
|
||||
try:
|
||||
out[key]["color"] = parse_color(color)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
image_url = incoming.get("image_url")
|
||||
if isinstance(image_url, str) and image_url.strip():
|
||||
@@ -74,10 +79,16 @@ def load_templates(path: str | Path) -> dict[str, dict]:
|
||||
def save_templates(path: str | Path, templates: dict) -> None:
|
||||
p = Path(path)
|
||||
normalized = _normalize_templates(templates)
|
||||
serialized = deepcopy(normalized)
|
||||
|
||||
for tpl in serialized.values():
|
||||
color = tpl.get("color")
|
||||
if isinstance(color, int):
|
||||
tpl["color"] = f"#{color:06X}"
|
||||
|
||||
p.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = p.with_suffix(p.suffix + ".tmp")
|
||||
tmp.write_text(json.dumps(normalized, indent=2,
|
||||
tmp.write_text(json.dumps(serialized, indent=2,
|
||||
sort_keys=True) + "\n", encoding="utf-8")
|
||||
tmp.replace(p)
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ def test_admin_get_renders_template_form(monkeypatch):
|
||||
assert "Admin: templates" in body
|
||||
assert "name='420__text'" in body
|
||||
assert "name='420__color'" in body
|
||||
assert "name='420__color_picker'" in body
|
||||
assert "type='color'" in body
|
||||
assert "name='420__image_url'" in body
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ def test_save_and_load_templates_roundtrip(tmp_path):
|
||||
}
|
||||
save_templates(path, data)
|
||||
|
||||
raw = path.read_text(encoding="utf-8")
|
||||
assert '"color": "#00007B"' in raw
|
||||
|
||||
loaded = load_templates(path)
|
||||
assert loaded["420"]["text"] == "Custom"
|
||||
assert loaded["420"]["color"] == 123
|
||||
|
||||
Reference in New Issue
Block a user