TileBoard - New dashboard for Homeassistant

@resoai When I press an input_select tile it is currently popping up with a black background and and dark grey text. Makes it hard to read. How can I change the background, and font color of a input_select pop-up? Do I need to change it in styles or can I change an individual tile? What is that element called? Is there a way I can change where the input_select pop-up appears around the tile? For instance, if I am using an input_select for a top tile and I want the pop-up to appear below the tile instead of above it.

Thank you for this project. it is awesome! I am working on my 3rd Tileboard.

You can use the developer tools inspector in your browser to find classes and then apply styles using custom.css.

You just helped me figure so much stuff out. Thank you.

1 Like

I have this problem now too. Did you resolve it? Thanks!

Edit: my state was not updating due to an error in my icons function. In my if statement I accidentally was setting my state equal to 1 rather than comparing to 1 (IE: = instead of ==) .

Is tileboard still expected to be supported with iOS 9.3.5?
I have an old iPad 3rd gen. that i am desperately trying to find useful.

When the iPad tries to access TileBoard there is nothing, just a blue screen.

I have Home Assistant core installed on a debian server, and on the same machine I have a fresh docker of tileboard. My home assistant instance is configured with ssl, so I have changed the two lines in TileBoard’s config.js for https:// and wss://. Also, i’ve set TileBoard to authenticate with HA with long-lived access token to make it as easy and simple as possible for my ipad.

The iPad is so old that barely any apps work and https seems to be a very typical point of failure. Safari works best as a web browser out of the 5 browsers still available for old iPads on the app store.
On my PC, my tileboard instance works perfectly.
Using the firefox docker it does work, but it’s just not stable, scales badly and i just really want to avoid that solution.

I am so lost, does anyone have any idea what to do or what the problem even is?

Okay all. I wanted to get a calendar setup in my Tileboard and there was little to now documentation so I wanted to share my setup…

First, we need a way to get more than one calendar event. For this I used iCal sensor.

Next we need an array of events to parse through so I created a group of iCal sensors and a template sensor in home assistant…

iCal_sensors:
    name: iCal sensors
    entities:
      - sensor.ical_family_calendar_event_0
      - sensor.ical_family_calendar_event_1
      - sensor.ical_family_calendar_event_2
      - sensor.ical_family_calendar_event_3
      - sensor.ical_family_calendar_event_4
      - sensor.ical_family_calendar_event_5
      - sensor.ical_family_calendar_event_6
      - sensor.ical_family_calendar_event_7
      - sensor.ical_family_calendar_event_8
      - sensor.ical_family_calendar_event_9
ical_sensor_array:
        friendly_name: 'iCal sensor array'
        value_template: >-
            {{ '' }}
        attribute_templates:
            start: >-
                {% set start = namespace(value=[]) %}
                {% for entity in states.group.ical_sensors.attributes.entity_id %}
                    {% set start.value = start.value + [state_attr(entity, 'start').strftime('%m-%d-%Y at %I:%m%p')] %} 
                {% endfor %} 
                {{ start.value }}
            end: >-
                {% set end = namespace(value=[]) %}
                {% for entity in states.group.ical_sensors.attributes.entity_id %}
                    {% set end.value = end.value + [state_attr(entity, 'end').strftime('%m-%d-%Y at %I:%m%p')] %} 
                {% endfor %} 
                {{ end.value }}
            all_day: >-
                {% set all_day = namespace(value=[]) %}
                {% for entity in states.group.ical_sensors.attributes.entity_id %}
                    {% set all_day.value = all_day.value + [state_attr(entity, 'all_day')] %} 
                {% endfor %} 
                {{ all_day.value }}
            summary: >-
                {% set sum = namespace(value=[]) %}
                {% for entity in states.group.ical_sensors.attributes.entity_id %}
                    {% set sum.value = sum.value + [state_attr(entity, 'summary').replace('\n', '\n# ')] %} 
                {% endfor %} 
                {{ sum.value }}

Now we can use the data in Tileboard and add it to a custom tile…

Tile:

{
            position: [1, 2],
            type: TYPES.CUSTOM,
            width: 2,
            height: 1,
            title: false,
            id: 'sensor.ical_sensor_array',
            customHtml: '<table class="caltbl" id="caltbl"></table>',
            state: function(item, entity) {
              setInterval(getcal('caltbl', 5, entity), 300000); //every 5 minutes
            },
            action: function(item, entity) {
              return this.$scope.openPopup(calpop, calpop.id);
            },
          },

getcal function:

var getcal = function(eleID, rowCount, entity) {
  var tbl = document.getElementById(eleID);
  tbl.innerHTML = "";
  var currentDate = new Date();
  var tomorrowDate = new Date(currentDate);
  tomorrowDate.setDate(tomorrowDate.getDate() + 1);
  var months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
  var monthIndexToday = currentDate.getMonth();
  var monthIndexTomorrow = tomorrowDate.getMonth();
  var today = months[monthIndexToday] + '-' + currentDate.getDate() + '-' + currentDate.getFullYear();
  var tomorrow = months[monthIndexTomorrow] + '-' + tomorrowDate.getDate() + '-' + tomorrowDate.getFullYear();
  for (var i = 0; i < rowCount; i++) {
    var row = tbl.insertRow(i);
    row.setAttribute('class', 'calrow');
    var imgcell = row.insertCell(0);
    imgcell.setAttribute('class', 'calimg');
    var img = document.createElement('img');
    img.setAttribute('class', 'calimgsrc');
    var tm = row.insertCell(1);
    tm.setAttribute('class', 'caltm');
    var starttxt = entity.attributes.start[i];
    var startarry = starttxt.split(' at ');
    if (startarry[0] == today) {
      starttxt = 'Today at ' + startarry[1];
    } else if (startarry[0] == tomorrow) {
      starttxt = 'Tomorrow at ' + startarry[1];
    } else {}
    tm.innerHTML = '<div class="tmdiv">' + starttxt + '<br>' + '</div>';
    var sum = row.insertCell(2);
    sum.setAttribute('class', 'calsum');
    var sumtxt = entity.attributes.summary[i];
    sum.innerHTML = '<div class="sumdiv">' + sumtxt + '</div>';
    if (sumtxt.startsWith('Name1:')) {
      img.style.backgroundColor = 'green';
    } else if (sumtxt.startsWith('Name2:')) {
      img.style.backgroundColor = 'pink';
    } else if (sumtxt.startsWith('All:')) {
      img.style.backgroundColor = 'orange';
    } else {
      img.style.backgroundColor = 'gray';
    }
    imgcell.appendChild(img);
  }
};

Popup:

let calpop = {
  position: [0, 0],
  type: TYPES.POPUP,
  id: {},
  state: false,
  title: false,
  popup: {
    tileSize: 150,
    items: [{
      position: [0, 0],
      type: TYPES.CUSTOM,
      width: 3,
      height: 2,
      title: false,
      id: 'sensor.ical_sensor_array',
      customHtml: '<table class="caltbl" id="caltblpop"></table>',
      state: function(item, entity) {
        getcal('caltblpop', 10, entity);
      },
    }, ],
  },
};

The result:
image

I’ve learned all of my coding knowledge on my own so if anyone sees something that can be refactored/improved please let me know.

5 Likes

Next is a RSS feed…

For this I use feedparser to get the RSS data parsed into Home Assistant.

Here it is in Tileboard…

{
            position: [0, 0],
            type: TYPES.CUSTOM,
            width: 4,
            height: 3,
            title: 'Local',
            id: 'sensor.local_news',
            customHtml: '<table class="rsstbl" id="rsstbl"></table>',
            state: function(item, entity) {
              var getrss = function(eleID, entity) {
                var tbl = document.getElementById(eleID);
                tbl.innerHTML = "";
                for (var i = 0; i < 5; i++) {
                  var imgsrc = entity.attributes.entries[i].image;
                  var tlsrc = entity.attributes.entries[i].title;
                  var dscsrc = entity.attributes.entries[i].summary;
                  let rsspop = {
                    position: [0, 0],
                    type: TYPES.POPUP,
                    id: {},
                    state: false,
                    title: false,
                    popup: {
                      tileSize: 150,
                      items: [{
                        position: [0, 0],
                        type: TYPES.CUSTOM,
                        width: 6,
                        height: 3,
                        title: false,
                        state: false,
                        id: {},
                        customHtml: '<div class="rsspop"><h3 class="rsstlpop">' + tlsrc + '</h3>' +
                          '<img class="rssimgsrcpop" src="' + imgsrc + '"><p class="rssdscpop">' + dscsrc + '</p></div>',
                      }, ],
                    },
                  }
                  var row = tbl.insertRow(i);
                  row.setAttribute('class', 'rssrow');
                  row.onclick = function(item, entity) {
                    return this.$scope.openPopup(rsspop, rsspop.id);
                  }.bind(this)
                  var img = row.insertCell(0);
                  img.setAttribute('class', 'rssimg');
                  img.innerHTML = '<img class="rssimgsrc" src="' + imgsrc + '">';
                  var tl = row.insertCell(1);
                  tl.setAttribute('class', 'rsstl');
                  var tltxt = tlsrc.replace(/(<([^>]+)>)/ig, "");
                  tl.innerHTML = '<div class="tldiv">' + tltxt + '</div>';
                  var dsc = row.insertCell(2);
                  dsc.setAttribute('class', 'rssdsc');
                  var dsctxt = dscsrc.replace(/(<([^>]+)>)/ig, "");
                  dsc.innerHTML = '<div class="dscdiv">' + dsctxt + '</div>';
                }
              }.bind(this)
              setInterval(getrss('rsstbl', entity), 300000); 
            }
          },

The result:
image

Again I’ve learned all of my coding knowledge on my own so if anyone sees something that can be refactored/improved please let me know.

2 Likes

You can see if it’s a Cross-Origin Request Blocked error like in my case by putting in the configuration.yaml under http:

http:
  cors_allowed_origins:
    - '*'

however I don’t know what kind of security risks come with it.

1 Like

Check out this thread. It has to do with CORS allowed not being applied to history. If you apply the fix it works.

Hi SimplyGardner,

How did you set the “background” color on you left side menu? Is it a setting or have you embedded this into the background image?

Best ergards,
/Tonkin

Any help for this?

Firefox - no longer display menu since yesterday.
Hello,
I’m wondering if anyone else is experiencing Firefox not displaying the page navigation anymore?

It’s possible that something has broken since new version was released yesterday. Can you share your config (can remove all entities and any other private information)?

How can I see which version I have?
And how can I update?

I installed TileBoard manually early 2021.

I replaced my config with the example one and I do not see the menu on this either; https://github.com/resoai/TileBoard/blob/f4c537a56bf28179a4085125d5eb6f2b27fd239d/config.example.js

If you running the TileBoard addon then it updates automatically. If you have manually copied tileboard files then the new version is not the cause of your problems.

Can you show a screenshot showing the issue? Maybe the menu is there but icons are missing? Are you able to click where the icons should be?

I now installed it as a HA addon.
Made a backup of my ‘old’ manually installed TILEBOARD directory.

Where are the HA addon files installed?
Which directory?

Read the addon’s manual for how to configure it. If you mean other files than the configuration files then those are within the addon’s container and not really accessible.

I read the installation/config instructions but cannot figure it out. Where can I put my ‘old’ config.js?
Which directory?

I configured ‘config\TileBoard’ in the addon config tab, and put my old files there but this does not work.

I have installed tileboard manually - so it should not be related to this update. I thought you had meant that Firefox released an update (maybe they did?).

I viewed this on Chrome and the menu appears, when I switch to Firefox it disappears - here’s the html elements shown in Firefox, I can not click or highlight to view anything, it’s just not rendering.