Skip to content

Commit 42a0edd

Browse files
committed
Update icon border progress to 1.7.0 - multi configuration support
1 parent 04caac9 commit 42a0edd

File tree

5 files changed

+130
-13
lines changed

5 files changed

+130
-13
lines changed

modules/icon_border_progress/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
### v1.7.0
4+
5+
<details><summary>See Changes</summary>
6+
7+
- Added ability to define multiple configurations for the same button.
8+
Define separate configuration blocks with conditions, and the configuration matching the condition will be used.
9+
If multiple configurations match, the first one in the list will be used.
10+
</details>
11+
312
### v1.6.0
413

514
<details><summary>See Changes</summary>

modules/icon_border_progress/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,38 @@ icon_border_progress:
242242

243243
</details>
244244

245+
<details>
246+
<summary><strong>Conditional configurations for the same button</strong></summary>
247+
248+
This example shows two different configurations for the same button, based on the battery level of a device.
249+
If multiple configuration conditions match, the first matching configuration in the list will be used.
250+
251+
```yaml
252+
icon_border_progress:
253+
- button: main
254+
source: sensor.robo_vac[battery_level]
255+
condition:
256+
condition: "state",
257+
entity_id: "vacuum.robo_vac",
258+
state: "docked",
259+
color_stops:
260+
- percent: 0
261+
color: "red"
262+
- percent: 100
263+
color: "green"
264+
- button: main
265+
source: sensor.robo_vac[cleaning_progress]
266+
condition:
267+
condition: "state",
268+
entity_id: "vacuum.robo_vac",
269+
state: "cleaning",
270+
color_stops:
271+
- percent: 0
272+
color: "blue"
273+
```
274+
275+
</details>
276+
245277
## Install this module
246278

247279
1. Install [Bubble Card](https://github.com/Clooos/Bubble-Card) in Home Assistant if you haven't already.

modules/icon_border_progress/__tests__/integration.test.js

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe("icon_border_progress - Integration Tests", () => {
9393
{
9494
button: "main",
9595
source: "sensor.progress",
96-
background_color: "#333333",
96+
background_color: "rgb(51, 51, 51)",
9797
condition: [
9898
{
9999
condition: "state",
@@ -126,7 +126,7 @@ describe("icon_border_progress - Integration Tests", () => {
126126
expect(progressStrokeDashArray).toBeTruthy();
127127

128128
// Verify background styling is applied
129-
expect(mainIcon.style.background).toBeTruthy();
129+
expect(mainIcon.style.background).toBe("rgb(51, 51, 51)");
130130

131131
// Setup - Change condition to false
132132
mockHass.states["sensor.enable_progress"] = { state: "off" };
@@ -142,6 +142,67 @@ describe("icon_border_progress - Integration Tests", () => {
142142
expect(mainIcon.style.background).toBe(mainIcon.dataset.originalBackground || "");
143143
});
144144

145+
// https://github.com/lsmarsden/bubble-card-modules/issues/1#issuecomment-3102650787
146+
it("should apply first condition matching when multiple button configs are defined", () => {
147+
// Setup - Real YAML configuration with actual condition
148+
mockThis.config.icon_border_progress = [
149+
{
150+
button: "main",
151+
source: "sensor.progress",
152+
background_color: "rgb(255, 0, 0)",
153+
condition: [
154+
{
155+
condition: "state",
156+
entity_id: "sensor.enable_progress",
157+
state: "off",
158+
},
159+
],
160+
},
161+
{
162+
button: "main",
163+
source: "sensor.progress",
164+
background_color: "rgb(0, 255, 0)",
165+
condition: [
166+
{
167+
condition: "state",
168+
entity_id: "sensor.enable_progress",
169+
state: "on",
170+
},
171+
],
172+
},
173+
{
174+
button: "main",
175+
source: "sensor.progress",
176+
background_color: "rgb(0, 0, 255)",
177+
condition: [
178+
{
179+
condition: "state",
180+
entity_id: "sensor.enable_progress",
181+
state: "on",
182+
},
183+
],
184+
},
185+
];
186+
mockHass.states["sensor.progress"] = { state: "75" };
187+
mockHass.states["sensor.enable_progress"] = { state: "off" };
188+
189+
// exercise - call with state off
190+
icon_border_progress.call(mockThis, mockCard, mockHass);
191+
192+
// verify
193+
const mainIcon = mockCard.querySelector(".bubble-icon-container");
194+
expect(mainIcon.style.background).toBe("rgb(255, 0, 0)");
195+
196+
// set up - change condition to on
197+
mockHass.states["sensor.enable_progress"] = { state: "on" };
198+
199+
// exercise - call with state on
200+
icon_border_progress.call(mockThis, mockCard, mockHass);
201+
202+
// verify first matching condition should apply
203+
expect(mainIcon.style.background).toBe("rgb(0, 255, 0)");
204+
});
205+
145206
it("should handle rapid condition state changes correctly", () => {
146207
// Setup - Configuration with numeric condition
147208
mockThis.config.icon_border_progress = [

modules/icon_border_progress/code.js

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,33 @@ export function icon_border_progress(card, hass) {
8585
applyProgressStyling(buttonElement, adjustedProgress, progressColor, colors, buttonConfig);
8686
}
8787

88-
// Main processing loop
89-
toArray(config).forEach((buttonConfig) => {
90-
const button = buttonConfig.button;
91-
if (!button) return;
88+
// group button configs by button name
89+
function groupByButton(configArray) {
90+
return configArray.reduce((groups, buttonConfig) => {
91+
const button = buttonConfig.button;
92+
if (!button) return groups;
93+
94+
if (!groups.has(button)) {
95+
groups.set(button, []);
96+
}
97+
groups.get(button).push(buttonConfig);
98+
return groups;
99+
}, new Map());
100+
}
92101

102+
// Main processing loop
103+
groupByButton(toArray(config)).forEach((buttonConfigs, button) => {
93104
const selector = getElementSelector(button);
94105
const buttonElement = card.querySelector(selector);
95106
if (!buttonElement) return;
96107

97108
storeOriginalBackground(buttonElement);
98109

99-
if (!checkAllConditions(buttonConfig.condition)) {
110+
// Find the first configuration with matching conditions
111+
const matchingConfig = buttonConfigs.find((config) => checkAllConditions(config.condition));
112+
113+
if (!matchingConfig) {
114+
// No matching conditions found, cleanup styling
100115
cleanupProgressStyling(buttonElement);
101116
const updateIntervalId = buttonElement.dataset.progress_update_interval;
102117
if (updateIntervalId) {
@@ -108,20 +123,20 @@ export function icon_border_progress(card, hass) {
108123

109124
const progressSource = resolveConfig([
110125
{
111-
config: buttonConfig,
126+
config: matchingConfig,
112127
path: "source",
113128
},
114129
{
115-
config: buttonConfig,
130+
config: matchingConfig,
116131
path: "entity",
117132
metadata: { deprecated: true, replacedWith: "source" },
118133
},
119134
]);
120135

121136
manageTimerUpdater(buttonElement, progressSource, () => {
122-
updateProgressDisplay(progressSource, buttonConfig, buttonElement);
137+
updateProgressDisplay(progressSource, matchingConfig, buttonElement);
123138
});
124-
updateProgressDisplay(progressSource, buttonConfig, buttonElement);
125-
applyEffects(buttonElement, buttonConfig.effects || []);
139+
updateProgressDisplay(progressSource, matchingConfig, buttonElement);
140+
applyEffects(buttonElement, matchingConfig.effects || []);
126141
});
127142
}

modules/icon_border_progress/module.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module_info:
22
id: icon_border_progress
33
name: Icon Border Progress
4-
version: 1.6.0
4+
version: 1.7.0
55
creator: lsmarsden
66
link: >-
77
https://github.com/lsmarsden/bubble-card-modules/tree/main/icon_border_progress

0 commit comments

Comments
 (0)