This is a perfect approach !
Will get into it tomorrow !
Thanks a lot !
Magical! Thank yo so much, this looks awesome!
I’ll use this on my dashboard, too!
Actually you can simulate a default period…!
In the oh-button config:
fill: =(vars.selectedPeriod || '6h') === loop.period.value
And in the oh-webframe-card config:
src: ='...' + (vars.selectedPeriod || '6h') + '...'
and you can remove the visible parameter as you don’t need it anymore.
Did all of that - when I hardcode the URL in YAML code, it works.
Then I built a widget for it - as long as the url remains hardcoded - no problem.
As soon as I use props for Title, Footer and URL, the URL and footer part doesn’t get updated anymore when the time period is changed:
(I use the footer just to check the logic for the URL string)
URL = footer:
='http://192.168.0.13:3000/d-solo/4OdYJNbMk/energie-pv-haus?orgId=1&refresh=1m&from=now-' + (vars.selectedPeriod || '6h') + '&to=now&panelId=2'
YAML of the widget:
uid: Time series Grafana chart
tags: []
props:
parameters:
- description: Title of the chart
label: Title
name: title
required: false
type: TEXT
- description: Footer of the chart
label: Footer
name: footer
required: false
type: TEXT
- description: URL to show in the frame
label: Source URL
name: URL
required: true
type: TEXT
parameterGroups: []
timestamp: Jan 6, 2021, 11:40:52 AM
component: f7-card-content
slots:
default:
- component: oh-webframe-card
config:
title: =props.title
borders: false
noBorder: false
outline: true
src: =props.URL
footer: =props.footer
- component: f7-segmented
config:
round: true
outline: true
slots:
default:
- component: oh-repeater
config:
fragment: true
for: period
in:
- value: 6h
label: 6 Std
- value: 12h
label: 12 Std
- value: 1d
label: 1 Tag
- value: 7d
label: 7 Tage
- value: 30d
label: 30 Tage
slots:
default:
- component: oh-button
config:
text: =loop.period.label
fill: =(vars.selectedPeriod || '6h') === loop.period.value
round: false
outline: true
action: variable
actionVariable: selectedPeriod
actionVariableValue: =loop.period.value
Any idea why this happens?
That selectedPeriod
is a variable set within the context of the widget so it’s constrained to that conterxt - that’s why it can’t be used in props because it’s outside the context of the parent.
That’s a bit equivalent to doing:
class Widget {
String selectedPeriod;
void renderWidget(String url) {
String src = url;
...
}
void buttonClicked(String value) {
selectedPeriod = value;
}
class Page {
Widget widget = new Widget();
void renderPage() {
widget.renderWidget("http://" + selectedPeriod + "...");
}
This analogy falls short on one thing, is that variables already defined on the parent, if they’re updated in the widget, will be updated for the parent too. I explain with some illustrations how that works here: Widgets: context variables, add oh-input by ghys · Pull Request #356 · openhab/openhab-webui · GitHub
What would likely work is add defineVars
in the page config, that’s the equivalent of declaring a global variable.
Better yet, you can for example decide on a placeholder for your period, like {period}
and in the image use:
src: =props.url.replace('{period}', vars.selectedPeriod || '6h')
then configure your widget with http://192.168.0.13:3000/d-solo/4OdYJNbMk/energie-pv-haus?orgId=1&refresh=1m&from=now-{period}&to=now&panelId=2
Perfect - this works !
Final polishing… I tried to align the style of the buttons to the Web frame card (Main UI default style). Was on F7 website, tried lots of different things… partial success.
Unfortunately, I’m not familiar with styles, etc. at all, but eager to learn on the go…
I’d be grateful, if you could guide me here also… Thank you.
-
Align width of both cards
The segmented button card is a bit wider than the Web frame card.
It is not only the appearance, it is mor that the Web frame card gets a bit queezed in width.
I tried with margin, etc, but failed. -
Outline
I’d wish to have the same outline on the segmented buttons as the Web frame card (which is the Main UI default) = a thin light gray line on dark gray background
-
Background color
The background colors of both cards should ideally be the same - not sure they are. -
Minimize gap between Web frame card and segmented buttons card
Can that be made smaller. -
Font on buttons:
How can I change font size and style (reduce font weight)?
The current YAML:
uid: Time series Grafana chart
tags: []
props:
parameters:
- description: Title of the chart
label: Title
name: title
required: false
type: TEXT
- description: Footer of the chart
label: Footer
name: footer
required: false
type: TEXT
- description: URL to show in the frame
label: Source URL
name: URL
required: true
type: TEXT
parameterGroups: []
timestamp: Jan 6, 2021, 4:48:24 PM
component: f7-card-content
slots:
default:
- component: oh-webframe-card
config:
title: =props.title
borders: false
noBorder: false
outline: true
src: =props.URL.replace('{period}', vars.selectedPeriod || '6h')
footer: =props.footer
- component: f7-segmented
config:
round: false
outline: true
class:
- color-theme-xxxx
- segmented-strong
slots:
default:
- component: oh-repeater
config:
fragment: true
for: period
in:
- value: 6h
label: 6 Std
- value: 12h
label: 12 Std
- value: 1d
label: 1 Tag
- value: 7d
label: 7 Tage
- value: 30d
label: 30 Tage
slots:
default:
- component: oh-button
config:
text: =loop.period.label
fill: =(vars.selectedPeriod || '6h') === loop.period.value
round: false
outline: false
action: variable
actionVariable: selectedPeriod
actionVariableValue: =loop.period.value
How can that be done?
I almost got there…
It is just that the alignment of the widget in the grid is not as it should be - it gets queezed in width when Web frame and buttons reside inside the same “component: f7-card-content”.
How can this be avoided?
uid: Time series Grafana chart
tags: []
props:
parameters:
- description: Title of the chart
label: Title
name: title
required: false
type: TEXT
- description: Footer of the chart
label: Footer
name: footer
required: false
type: TEXT
- description: URL to show in the frame
label: Source URL
name: URL
required: true
type: TEXT
parameterGroups: []
timestamp: Jan 7, 2021, 6:25:42 PM
component: f7-card-content
slots:
default:
- component: oh-webframe-card
config:
title: =props.title
borders: false
noBorder: false
outline: true
src: =props.URL.replace('{period}', vars.selectedPeriod || '6h')
footer: =props.footer
class:
- display-block
- component: f7-segmented
config:
round: false
outline: false
class:
- segmented-strong
- margin-left-half
- margin-right-half
style:
--f7-segmented-strong-padding: 0px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 100
--f7-segmented-strong-bg-color: rgba(255, 255, 255, 0.05)
--f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.07)
slots:
default:
- component: oh-repeater
config:
fragment: true
for: period
in:
- value: 6h
label: 6 Std
- value: 12h
label: 12 Std
- value: 1d
label: 1 Tag
- value: 7d
label: 7 Tage
- value: 30d
label: 30 Tage
slots:
default:
- component: oh-button
config:
text: =loop.period.label
fill: =(vars.selectedPeriod || '6h') === loop.period.value
round: false
outline: false
style:
--f7-button-font-size: 14px
--f7-button-border-width: 1px
--f7-button-text-color: white
--f7-button-border-color: rgba(255,255,255,.15)
--f7-button-border-radius: 5px
action: variable
actionVariable: selectedPeriod
actionVariableValue: =loop.period.value
Maybe by redefining the first variable here: CSS Variables Reference | Framework7 Documentation
style:
--f7-card-content-padding-horizontal: 0
This was the right hint !
I totally forgot to adjust the styles on “component: f7-card-content”.
By applying:
style:
--f7-card-margin-horizontal: 0px
--f7-card-margin-vertical: 3px
--f7-card-content-padding-horizontal: 10px
--f7-card-content-padding-vertical: 10px
… all the elements are nicely aligned to the oh-grid. This also helped to adjust the space between the chart and the buttons.
I tried to further improve to usability/flexibility of the widget -> define time ranges via props.
In a way the same that is done in oh-list-card with command options.
The props part in the widget would look like this:
- description: Comma-separated list of options. Use value=label format to provide a label different than the option.
label: Time range options
name: timerange
required: false
type: TEXT
… but how to feed this back with “=props.timerange” to the following section?
- component: oh-repeater
config:
fragment: true
for: period
in:
- value: 6h
label: 6 Std
- value: 12h
label: 12 Std
- value: 1d
label: 1 Tag
- value: 7d
label: 7 Tage
- value: 30d
label: 30 Tage
The below code doesn’t work.
- component: oh-repeater
config:
fragment: true
for: period
in: =props.timerange
What have I done wrong?
I’m struggeling to get the timeranges via props working - see my first attempt above.
I would like to feed the input list:
6h=6 Std,12h=12 Std,1d=1 Tag,7d=7 Tage,30d=30 Tage
with props definition:
- description: Comma-separated list
label: Time range options
name: timerange
required: false
type: TEXT
to the oh-repeater “in” section (I tried now with split function):
- component: oh-repeater
config:
fragment: true
for: period
in: =props.timerange.split(",")
Result:
Status:
The number of buttons shown below the chart is correct - for the above input list 5 buttons.
The split function seems to work.
Problems:
- No labels are shown on the buttons
- Nothing happens when the buttons are pressed
What did I miss to get this working?
Hey @maxmaximax
You’ve not defined an array position to output in your loop. To itterate over all available array elements, you could add another for-loop
...
- component: oh-repeater
config:
sourceType: range
for: size
fragment: true
slots:
default:
- component: oh-repeater
config:
fragment: true
for: period
in: =[props.timerange.split(",")[loop.size].split("=")[1]]
slots:
default:
...
Nice widget btw.
@RGroll
Glad you like the widget…
Inserted your code, but unfortunately no change at all.
Maybe I misunderstood how to properly insert it?
Here the full YAML as reference:
uid: test grafana props
tags: []
props:
parameters:
- description: Title of the chart
label: Title
name: title
required: false
type: TEXT
- description: Footer of the chart
label: Footer
name: footer
required: false
type: TEXT
- description: URL to show in the frame
label: Source URL
name: URL
required: true
type: TEXT
- description: Comma-separated list of options. Use value=label format to provide a label different than the option.
label: Time range options
name: timerange
required: false
type: TEXT
parameterGroups: []
timestamp: Jan 10, 2021, 6:32:21 PM
component: f7-card-content
config:
style:
--f7-card-margin-horizontal: 0px
--f7-card-margin-vertical: 3px
--f7-card-content-padding-horizontal: 10px
--f7-card-content-padding-vertical: 10px
slots:
default:
- component: oh-webframe-card
config:
title: =props.title
borders: false
noBorder: false
outline: true
src: =props.URL.replace('{period}', vars.selectedPeriod || '6h')
footer: =props.footer
class:
- display-block
- component: f7-segmented
config:
round: false
outline: false
class:
- segmented-strong
style:
--f7-segmented-strong-padding: 0px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 300
--f7-segmented-strong-bg-color: rgba(255, 255, 255, 0.05)
--f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.07)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: size
fragment: true
slots:
default:
- component: oh-repeater
config:
fragment: true
for: period
in: =[props.timerange.split(",")[loop.size].split("=")[1]]
slots:
default:
- component: oh-button
config:
text: =loop.period.label
fill: =(vars.selectedPeriod || '6h') === loop.period.value
round: false
outline: false
style:
--f7-button-font-size: 14px
--f7-button-border-width: 1px
--f7-button-text-color: white
--f7-button-border-color: rgba(255,255,255,.15)
--f7-button-border-radius: 5px
action: variable
actionVariable: selectedPeriod
actionVariableValue: =loop.period.value
At this stage all of my abilities are exhausted… unfortunately…
Hope you can help…
Try this - hope this it what you’d like to achieve
uid: test grafana props
tags: []
props:
parameters:
- description: Title of the chart
label: Title
name: title
required: false
type: TEXT
- description: Footer of the chart
label: Footer
name: footer
required: false
type: TEXT
- description: URL to show in the frame
label: Source URL
name: URL
required: true
type: TEXT
- description: Comma-separated list of options. Use value=label format to provide a label different than the option.
label: Time range options
name: timerange
required: false
type: TEXT
parameterGroups: []
timestamp: Jan 11, 2021, 12:46:27 AM
component: f7-card-content
config:
style:
--f7-card-margin-horizontal: 0px
--f7-card-margin-vertical: 3px
--f7-card-content-padding-horizontal: 10px
--f7-card-content-padding-vertical: 10px
slots:
default:
- component: oh-webframe-card
config:
title: =props.title
borders: false
noBorder: false
outline: true
src: =props.URL.replace('{period}', vars.selectedPeriod || [props.timerange.split(',')[0].split('=')[0]])
footer: =props.footer
class:
- display-block
- component: f7-segmented
config:
round: false
outline: false
class:
- segmented-strong
style:
--f7-segmented-strong-padding: 0px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 300
--f7-segmented-strong-bg-color: rgba(255, 255, 255, 0.05)
--f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.07)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: size
fragment: true
slots:
default:
- component: oh-repeater
config:
fragment: true
for: period
in: =[props.timerange.split(",")[loop.size].split("=")[1]]
slots:
default:
- component: oh-button
config:
text: =loop.period
fill: "=(([props.timerange.split(',')[loop.size].split('=')[0]] == vars.selectedPeriod) || (props.timerange.split(',')[0].split('=')[1] === loop.period) && !vars.selectedPeriod) ? true : false"
round: false
outline: false
action: variable
actionVariable: selectedPeriod
actionVariableValue: =props.timerange.split(",")[loop.size].split("=")[0]
Yes, thanks a lot!
The selected time range used to be highlighted in deeporange as per default color theme. This got lost somehow, even though the style elements have not changed (I hope). Very strange…
Do you think that some part of the new code had changed that?
Is there a way to make the default period = the first timeframe entry?
(instead of hardcoding 6h)
Can this be done?
Updated the above post with the working code (including the highlighting) - I forgot to remove some quotes which made the comparison resulting to false in every case.
Updated this also in the code so it should work without a fixed value now
Oh and before I forget - would be very nice if you could post your widget as an example for others here when you’re ready. I think many users could be interested in a solution like this!
agreed
That looks awesome Marcus!
Just… Yannik, you are a super hero for giving us such a awesome interface and the users are really just getting started mucking around with it, excited to see all the cool stuff to come
When you define a repeater with e.g. for: period
, in the repeated components you’ll have 3 variables defined in the loop
object actually.
-
loop.period
is the current element of the iteration -
loop.period_idx
is the index of the current element in the collection (for instance 0 for the first) -
loop.period_source
is the complete collection you’re iterating over - so the first element isloop.period_source[0]
and the last isloop.period_source[loop.period_source.length - 1]
Thanks for the added explanation!
@RGroll,
Thank you so much for helping out doing the final tweaks. Really appreciated!
Sure I will make a post under the link you posted above when I have a little more time. It should be there in a few days.
As reference, here is the final YAML of the widget in which I re-included the style of oh-button. That part disappeared in your YAML above with the result that the borders of the buttons got lost.
uid: Grafana chart with timeranges
tags: []
props:
parameters:
- description: Title of the chart
label: Title
name: title
required: false
type: TEXT
- description: Footer of the chart
label: Footer
name: footer
required: false
type: TEXT
- description: URL to show in the frame
label: Source URL
name: URL
required: true
type: TEXT
- description: Comma-separated list of options. Use value=label format (e.g. 1d=1 day) to provide a label different than the option. Minimum 1 entry required. The first entry is the default timerange.
label: Time range options
name: timerange
required: true
type: TEXT
parameterGroups: []
timestamp: Jan 11, 2021, 9:28:32 AM
component: f7-card-content
config:
style:
--f7-card-margin-horizontal: 0px
--f7-card-margin-vertical: 3px
--f7-card-content-padding-horizontal: 10px
--f7-card-content-padding-vertical: 10px
slots:
default:
- component: oh-webframe-card
config:
title: =props.title
borders: false
noBorder: false
outline: true
src: =props.URL.replace('{period}', vars.selectedPeriod || [props.timerange.split(',')[0].split('=')[0]])
footer: =props.footer
class:
- display-block
- component: f7-segmented
config:
round: false
outline: false
class:
- segmented-strong
style:
--f7-segmented-strong-padding: 0px
--f7-segmented-strong-between-buttons: 5px
--f7-segmented-strong-button-font-weight: 300
--f7-segmented-strong-bg-color: rgba(255, 255, 255, 0.05)
--f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.07)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: size
fragment: true
slots:
default:
- component: oh-repeater
config:
fragment: true
for: period
in: =[props.timerange.split(",")[loop.size].split("=")[1]]
slots:
default:
- component: oh-button
config:
text: =loop.period
fill: "=(([props.timerange.split(',')[loop.size].split('=')[0]] == vars.selectedPeriod) || (props.timerange.split(',')[0].split('=')[1] === loop.period) && !vars.selectedPeriod) ? true : false"
round: false
outline: false
style:
--f7-button-font-size: 14px
--f7-button-border-width: 1px
--f7-button-text-color: white
--f7-button-border-color: rgba(255,255,255,.15)
--f7-button-border-radius: 5px
action: variable
actionVariable: selectedPeriod
actionVariableValue: =props.timerange.split(",")[loop.size].split("=")[0]
Thanks again to everyone who helped on the way creating this widget !
Hi,
I’m using the code in the post above, but clicking on the buttons does nothing.
Running on OH 3.0 and after upgrading to OH 3.1.0
The URL for Grafana includes the period:
https://grafanaurl/grafana/d/UV-pd2VMz/lounge?orgId=1&refresh=10s&viewPanel=2&fullscreen&kiosk&from=now-{period}&to=now
Not sure what the issue is.
Thanks,
Richie