Skip to content

Commit f3a2175

Browse files
committed
0.7.3
1 parent e38507c commit f3a2175

File tree

53 files changed

+7476
-2427
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+7476
-2427
lines changed

custom_components/reterminal_dashboard/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
182182
frontend.async_register_built_in_panel(
183183
hass,
184184
component_name="iframe", # Use iframe panel type to load our view
185-
sidebar_title="reTerminal",
185+
sidebar_title="ESPHome Designer",
186186
sidebar_icon="mdi:tablet-dashboard",
187187
frontend_url_path="reterminal-dashboard",
188188
config={"url": "/reterminal-dashboard"},

custom_components/reterminal_dashboard/config_flow.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
@dataclass
4242
class FlowContext:
4343
"""Hold temporary flow context."""
44-
entry_title: str = "reTerminal Dashboard Designer"
44+
entry_title: str = "ESPHome Designer"
4545

4646

4747
async def _get_storage(hass: HomeAssistant) -> DashboardStorage:
@@ -129,7 +129,7 @@ async def async_step_init(self, user_input: dict[str, Any] | None = None):
129129
# Provide a textual summary; options dict not used to drive logic yet.
130130
info_text = (
131131
f"🎨 Dashboard Editor: {dashboard_url}\n\n"
132-
"reTerminal Dashboard Designer is configured.\n\n"
132+
"ESPHome Designer is configured.\n\n"
133133
"Use the following pattern in your ESPHome firmware for the reTerminal E1001:\n"
134134
f" online_image URL: {api_base}" + "/{device_id}/page/{page}/image.png?token={api_token}\n\n"
135135
"Devices and layouts are managed via the dashboard editor and HTTP API."

custom_components/reterminal_dashboard/frontend/editor.html

Lines changed: 246 additions & 12 deletions
Large diffs are not rendered by default.

custom_components/reterminal_dashboard/frontend/feature_registry.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@ class FeatureRegistry {
1515
console.log(`[FeatureRegistry] Registered: ${featureId}`);
1616
}
1717

18+
/**
19+
* Map of legacy/simple names to feature IDs.
20+
*/
21+
static aliases = {
22+
"lvgl_tabview": "lvgl_tabview",
23+
"lvgl_tileview": "lvgl_tileview",
24+
"lvgl_led": "lvgl_led",
25+
"lvgl_spinner": "lvgl_spinner",
26+
"lvgl_buttonmatrix": "lvgl_buttonmatrix",
27+
"lvgl_checkbox": "lvgl_checkbox",
28+
"lvgl_dropdown": "lvgl_dropdown",
29+
"lvgl_keyboard": "lvgl_keyboard",
30+
"lvgl_roller": "lvgl_roller",
31+
"lvgl_spinbox": "lvgl_spinbox",
32+
"lvgl_switch": "lvgl_switch",
33+
"lvgl_textarea": "lvgl_textarea",
34+
"lvgl_obj": "lvgl_obj"
35+
};
36+
1837
/**
1938
* Get a registered feature renderer.
2039
* @param {string} featureId
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
(() => {
2+
// Helper used by the main render function
3+
const drawCalendarPreview = (el, widget, props) => {
4+
// Simple mock rendering for preview
5+
const width = widget.width || 400;
6+
const height = widget.height || 300;
7+
8+
el.style.width = width + "px";
9+
el.style.height = height + "px";
10+
el.style.position = "relative";
11+
el.style.backgroundColor = props.background_color || "white";
12+
el.style.color = props.text_color || "black";
13+
14+
if (props.show_border !== false) {
15+
el.style.border = `${props.border_width || 2}px solid ${props.border_color || "black"}`;
16+
}
17+
18+
// Dynamic Date Data
19+
const now = new Date();
20+
const date = now.getDate();
21+
const dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
22+
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
23+
24+
const dayNameText = dayNames[now.getDay()];
25+
const monthYearText = `${monthNames[now.getMonth()]} ${now.getFullYear()}`;
26+
27+
// Header
28+
const header = document.createElement("div");
29+
header.style.textAlign = "center";
30+
header.style.padding = "10px";
31+
header.style.borderBottom = "1px solid " + (props.text_color || "black");
32+
// Ensure header doesn't grow too large
33+
header.style.flexShrink = "0";
34+
35+
const bigDate = document.createElement("div");
36+
bigDate.style.fontSize = Math.min((props.font_size_date || 100) / 2, 80) + "px";
37+
bigDate.style.fontWeight = "100";
38+
bigDate.style.lineHeight = "1";
39+
bigDate.innerText = date;
40+
header.appendChild(bigDate);
41+
42+
const dayName = document.createElement("div");
43+
dayName.style.fontSize = (props.font_size_day || 24) + "px";
44+
dayName.style.fontWeight = "bold";
45+
dayName.innerText = dayNameText;
46+
header.appendChild(dayName);
47+
48+
const dateLine = document.createElement("div");
49+
dateLine.style.fontSize = (props.font_size_grid || 14) + "px";
50+
dateLine.innerText = monthYearText;
51+
header.appendChild(dateLine);
52+
53+
// Flex layout for the main container to push events to bottom if space permits
54+
el.style.display = "flex";
55+
el.style.flexDirection = "column";
56+
57+
el.appendChild(header);
58+
59+
// Grid Logic
60+
const grid = document.createElement("div");
61+
grid.style.display = "grid";
62+
grid.style.gridTemplateColumns = "repeat(7, 1fr)";
63+
grid.style.padding = "5px";
64+
grid.style.gap = "2px";
65+
grid.style.flexShrink = "0";
66+
67+
const gridFontSize = (props.font_size_grid || 14) + "px";
68+
69+
// Day Headers (Mon-Sun)
70+
["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].forEach(day => {
71+
const d = document.createElement("div");
72+
d.innerText = day;
73+
d.style.textAlign = "center";
74+
d.style.fontWeight = "bold";
75+
d.style.fontSize = gridFontSize;
76+
grid.appendChild(d);
77+
});
78+
79+
// Days of Month
80+
// Calculate correctly:
81+
// 1. First day of current month
82+
const firstDay = new Date(now.getFullYear(), now.getMonth(), 1);
83+
// 2. Days in month
84+
const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0);
85+
const daysInMonth = lastDay.getDate();
86+
87+
// 3. Offset (JS getDay: Sun=0, Mon=1... but we want Mon=0...Sun=6)
88+
let startDay = firstDay.getDay(); // 0=Sun, 1=Mon
89+
if (startDay === 0) startDay = 7; // Make Sunday 7 temporarily
90+
startDay -= 1; // Now 0=Mon, ... 6=Sun
91+
92+
// Empty slots for start offset
93+
for (let i = 0; i < startDay; i++) {
94+
grid.appendChild(document.createElement("div"));
95+
}
96+
97+
// Day numbers
98+
for (let i = 1; i <= daysInMonth; i++) {
99+
const d = document.createElement("div");
100+
d.innerText = i;
101+
d.style.textAlign = "center";
102+
d.style.fontSize = gridFontSize;
103+
104+
if (i === date) {
105+
// Highlight today
106+
d.style.backgroundColor = props.text_color || "black";
107+
d.style.color = props.background_color || "white";
108+
d.style.borderRadius = "50%";
109+
d.style.width = "1.5em";
110+
d.style.height = "1.5em";
111+
d.style.lineHeight = "1.5em";
112+
d.style.margin = "0 auto";
113+
}
114+
grid.appendChild(d);
115+
}
116+
el.appendChild(grid);
117+
118+
// Mock Events
119+
const events = document.createElement("div");
120+
events.style.padding = "10px";
121+
events.style.fontSize = (props.font_size_event || 18) + "px";
122+
events.style.flexGrow = "1"; // Allow events area to fill remaining space
123+
events.style.overflow = "hidden"; // Clip if too small
124+
125+
// Generate a few mock events based on 'today'
126+
events.innerHTML = `
127+
<div style="margin-bottom:4px;"><b>${date}</b> Meeting with Team</div>
128+
<div><b>${Math.min(date + 2, daysInMonth)}</b> Dentist Appointment</div>
129+
`;
130+
el.appendChild(events);
131+
};
132+
133+
const render = (el, widget, tools) => {
134+
const props = widget.props || {};
135+
el.innerHTML = "";
136+
drawCalendarPreview(el, widget, props);
137+
};
138+
139+
// Register with FeatureRegistry
140+
if (window.FeatureRegistry) {
141+
window.FeatureRegistry.register("calendar", { render });
142+
} else {
143+
// Retry in case loaded too early
144+
setTimeout(() => {
145+
if (window.FeatureRegistry) {
146+
window.FeatureRegistry.register("calendar", { render });
147+
}
148+
}, 50);
149+
}
150+
})();

0 commit comments

Comments
 (0)