I want to render a table of information (a school timetable) on my dashboard.
The information is all in a single sensor’s attribute. Currently I use a markdown card and jinja to loop over the attribute’s array contents and output the right bits in a table.
I’m finding the Markdown card a bit limiting, or at least I’m finding the documentation a bit limiting. I want to create a table with three columns (time, class name and classroom). It seems the only way is to use an html table. Ok, but now I can’t add any text decoration or colour.
Are there other ways of presenting this data such that I can make it more interesting?
I have some Mushroom cards installed, but I don’t know where to start.
Markdown tables work as well. The primary way of colouring markdown text in HA is using <font color="blue">Your text</font>. Also you can use UIX/card-mod and target the table elements for general theming.
Here’s a markdown card I use for monitoring App system resource use that utilizes both. Inline <font color="xx"> for dynamic colour changes based on the values, and UIX styles for the general stuff.
type: markdown
content: |-
{% set info = integration_entities('Supervisor') | select('has_value') | list %}
{% set info = zip(info | select('search', '_memory_percent'),
info | select('search', '_memory_percent')
| map('states')|map('float', 0.0),
info | select('search', '_cpu_percent')
| map('states')|map('float', 0.0)) %}
| App | Mem. % | CPU % |
|-|-:|-:|
{% for id,mem,cpu in info | sort(attribute='1,2,0', reverse=true) -%}
{% set mem_colour = ('limegreen' if mem is le 25 else 'orange' if mem is lt 35 else 'red')
if id | device_name is eq 'Home Assistant Core' else
'limegreen' if mem is le 20 else 'orange' if mem is lt 25 else 'red' -%}
{% set cpu_colour = 'limegreen' if cpu is le 2.5 else 'orange' if cpu is lt 5 else 'red' -%}
{{ '|'~id | device_name~
'|<font color="'~mem_colour~'">' ~mem~ ' %</font>|'
~'<font color="'~cpu_colour~'">' ~cpu~ ' %</font>|' }}
{% endfor %}
grid_options:
rows: auto
columns: 21
uix:
style:
ha-markdown $: |
table {
font-size: 1.2em;
}
thead th {
text-align: var(--markdown-table-text-align, center);
color: var(--primary-color)
}
td:nth-child(1) {
padding: 0.25em 5em 0.25em 1em !important;
}
td:nth-child(n+2) {
padding: 0 1em !important;
}
Thank you for the hints as to how to achieve this.
I’ve worked out the Markdown table syntax which was helpful.
The font decoration is quite limited as you can only really change colour. There’s no (non card-mod) way to change the background colour of the table cells.
As an aside I’ve managed to create a template macro which saves me a lot of code duplication. I have the same style output required from 6 different inputs, so it’s nice to change it in one place and have it update everywhere.
For anyone else who’s interested, here’s the template macro.
Put the following into a file in home_assistant/custom_templates/timetable_macro.jinja
{% macro format_timetable(lessons) %}
{# accepts a list of lessons, such as given by state_attr(<pronote timetable>,'lessons') and formats the output with markdown. #}
{%- for lesson in lessons -%}
{%- set color = lesson.background_color -%}
{%- if color == "#FFFFFF" -%}
{%- set color = "#000000" -%}
{%- endif -%}
{%- set dec = '<font color="'~color~'">' -%}
{%- set dec_end = "</font>" -%}
{%- if lesson.canceled == True -%}
{%- set dec = '<del>'~dec -%}
{%- set dec_end = '</del>'~dec%}
{%- endif -%}
{%- if loop.first -%}
<div>{{as_timestamp(lesson.start_at) | int | timestamp_custom('%A %-d %b', true)}}</div>
{# table header #}
|Time| Subject | Room |
|-|:-|-:|
{%- endif -%}
{# table contents #}
|{{dec~(as_timestamp(lesson.start_at) | int | timestamp_custom('%Hh%M', true))~'-'~(as_timestamp(lesson.end_at) | int | timestamp_custom('%Hh%M', true))~dec_end}}|{{dec~('<font color="')~color~('">')~(lesson.lesson | capitalize)~('</font>')~dec_end}}|{{dec~lesson.classroom~dec_end}}|
{%- if loop.last -%}
{# end table #}
{% set lessons = "" %}
{% endif %}
{%- endfor -%}
{% endmacro %}
For each element of the lessons array that is passed to the function, the loop will output a row of the table. The for loop uses loop.first to output the table header. This is the important bit for getting the markdown parser to treat this as a table. For each element of the lessons array I set some “dec” and “dec_end” variables to get some text decoration. This is either a color or a color and a strike-through. I couldn’t think of a neater way to do this without making the row generation even bulkier and more difficult to understand.
Then, in your markdown card, add the following line at the start: {%- from 'timetablemacro.jinja' import format_timetable -%}
Now, whenever you want to render the contents of ‘lessons’, just use this (with your own sensor name and attribute, obviously): {{ format_timetable(state_attr('sensor.<your_sensor>','<attribute>')) }}
This is great for what I want it to do and hopefully another “worked” example will help someone else.