New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rethinking the States panel in the frontend #14

Closed
balloob opened this Issue Feb 22, 2018 · 18 comments

Comments

Projects
None yet
6 participants
@balloob
Copy link
Member

balloob commented Feb 22, 2018

The current States panel has a major flaw: it tries to do things magically at runtime. It takes all the available states and will organize all the things according to groups, hidden attributes and by domain (for ungrouped entities).

By doing things magically and at runtime, we've opened a can of worms:

  • All entities will be shown on the first tab unless a user defines a default view.
  • With a default view defined, new entities will not be shown anywhere unless explicitly added by the user to a view
  • All configuration for the runtime layout engine ended up in the state machine: views, groups, hidden attributes, custom UI overrides. By adding it to the state machine, you ended up having to pick 1 way for entities to be shown in every view where you wanted them to be.
  • The domain of an entity defines how it will be displayed.
  • Groups can show a toggle for entities. However, this is not always desirable so a config option was added to the group component to control this. This config option is stored in the state machine.

We can do better. Let's stop conflating concerns. Let the frontend be the frontend. The backend be the backend. The backend should provide the minimal information to the frontend: the entity id, name, state and attributes of an entity. No groups, no views.

For the frontend to figure it out, it should get its own configuration. This configuration will be loaded from the frontend component when the page is loaded and will be used to layout the entities.

So let's talk about the building blocks for a frontend configuration:

Views

A view's purpose is the same as today: view a subset of the states in Home Assistant. It would however no longer be "hacked" into the group component. It would only live inside the frontend component. It will not have a state in the state machine.

  • A user will need to have a minimum of 1 view
  • One of the views will need to be marked as "default".
  • Views can be ordered.
  • Views can either show an icon or a name for the tab.

Whenever a new state is added to Home Assistant, the frontend will check if it has seen this entity ID before. If not, it will add it to the default view. This will only happen once for each entity. The user can just choose to remove the entity from the view if he doesn't want to see it.

Cards & Badges

A view will consist of cards and badges, just like today. The biggest difference is that this will no longer be based on the group component. Instead, the user can configure cards to show things and this will be stored inside the frontend config.

The most important card is the entities card. It will, just like today, show a bunch of entities in a card. If a user doesn't like the climate, camera or media player card, they can now decide to add that entity to the entities card and remove the other card for an entity. A user can also pick to show the same entity 3 times if they feel like.

Other examples of cards: (all already exist today)

  • Group card: show the entities of a group as an entities card
  • Camera
  • Media Player
  • Climate
  • Plant
  • Weather
  • Persistent Notification (I probably will kill this and make notifications it's own section in frontend)

This will also allow us to make custom UI cards first class citizens and have their config be stored as part of the config for the view.

Pretty much all problems that users are facing today are solved by doing the auto layouting of entities when they are added to the default view instead of at runtime. At runtime we will just render the stored config for the view.

Conclusion

The biggest difference is that this setup will allow the user to take control of what is shown on each view without any surprises. It knows what is happening on each view ahead of time and can add new entities to a view of choice.

By still adding new entities to the default view, we will still have a great experience for users that are new to Home Assistant and don't want to dig into configuring views just yet.

It also allows us to relieve the state machine of configuration and will make custom UI first class citizens of our ecosystem.

@c727

This comment has been minimized.

Copy link

c727 commented Feb 22, 2018

  1. So the backend groups are unnecessary with this?
  2. Has this a concept for frontend only (custom) UI's like floorplan or weblinks?
  3. Should all frontend related attributes, like friendly name and icon moved to this?
  4. We have some input_xxx components with min/max for numbers or we have supportedFeatures so we still need to send some static 'attributes' to the frontend. Maybe this is also the time for home-assistant/home-assistant#10732
@balloob

This comment has been minimized.

Copy link
Member Author

balloob commented Feb 22, 2018

Backend groups will not be used anymore.

Thinks like friendly names are still used in entities for things like Alexa or Google Home. That's not a frontend only concern. I would also keep icons and entity picture s backwards compatibility

@OttoWinter

This comment has been minimized.

Copy link

OttoWinter commented Feb 22, 2018

💯for this. I have one tiny detail question though: How would cross-domain groups be done if "Backend groups will not be used anymore"? I mean by expanding #13 to all domains, we'd solve the issue of groups inside one domain. But what if we want to control switches, covers, ... (inter-domain) at the same time? I think we'd still need to have at least some way of doing that, maybe not through the group: domain, but through something else.

@armills

This comment has been minimized.

Copy link
Member

armills commented Feb 22, 2018

Does it makes sense to keep backend groups around, but strip out the frontend concerns? They're pretty widely used in automations.

@balloob

This comment has been minimized.

Copy link
Member Author

balloob commented Feb 22, 2018

Backend groups will still be around, just no longer necessary for the frontend to show groups. Once decoupled from the frontend, we can better judge their future.

@balloob balloob referenced this issue Mar 2, 2018

Closed

Add hide_on_home group option #11592

1 of 4 tasks complete
@mf-social

This comment has been minimized.

Copy link

mf-social commented Mar 3, 2018

Late to the party, but could this be as easy* as

Groups = backend (group of device trackers, group of lights, group of lights and switches in a room), for the purpose of having a 'state' for x number of devices.

Card = frontend card, containing devices or backend groups as listed.

View = frontend view (tab) as it is now, containing cards as listed, and entities (as badges/whatever).

(*) (from an end user perspective, not a dev perspective, I know there's nothing easy about coding all this!)

@NovapaX

This comment has been minimized.

Copy link

NovapaX commented Apr 7, 2018

Can't we migrate the frontend component to a config_entry? And use that as an API to set, save and get configuration. (we could then also leverage migrations if ever implemented/needed as we would not want breaking changes on UI configuration.)
But we could of course also make a seperate API endpoint for frontend configuration.
My main requirement would be that this all should be very easy to get and set in the frontend. Setting this all in yaml would be a PITA.

As noted above groups should be groups for state/backend purposes (can be viewed/used in frontend of course, but are not the way to group items for display purposes)

A very simple schema with some basic attributes could be:

  • entities (customization): icon | icon_color | show_history | show_last_update | custom_ui
  • cards: title | type(could be custom_ui) | entities
  • badges: type | title | entities(sortable list)
  • views: title | icon | badges(sortable list) | cards(sortable list)
  • default_view: references view
  • show_new_entities_on_view: references view

Of course a single entity could act as a card too (like the media-player)
We could add other configuration too, for example the history_graph_card could have additional settings like what type of chart, the size of the chart.
When defining the schema technically, we should make sure it is extendable. So a sortable list would be able to have additional attributes for each list-item. (so we can eventually show/hide/customize stuff based on location in UI and not only based on the entity customization)

@NovapaX

This comment has been minimized.

Copy link

NovapaX commented Apr 7, 2018

another approach could be to not customize entities, but define additional state-cards...
Of course each entity would always have a default state-card. But you can define extra state-cards (custom_ui) for that same entity to show it in a different way.
We could provide our own simple customizable state-card (change icon, color, control type, show one additional attribute) that could act as a basic example for other custom_ui.

@balloob

This comment has been minimized.

Copy link
Member Author

balloob commented Apr 7, 2018

I wouldn't want to use a config entry but instead use a standalone YAML/JSON file. That will allow easier sharing and also means we don't have to start adding a UI before being able to launch this.

For configuration I was thinking of something like this:

# which view to add newly discovered entities to
new_entities_view: living_room

# views that can be defined
views:
 - title: Living Room  # Title of the view, shown as tab name unless icon set
   id: living_room
   # Number of columns in the view. Right now use "auto" but we might allow changing this
   # Can be set to "auto", a number or maybe also "auto(2, 4)" to specify range of min/max ?
   column_count: auto
   cards:
    - type: entities
      # Used in future UI but can also be used as caption for card etc
      name: Kitchen
      config:
        entities:
          - light.kitchen_left
          - light.kitchen_right
          - switch.coffee_maker
    - type: "custom:crazy-camera"  # the name after "custom:" part will be used as web component
      name: Camera backyard
      # to be passed to the card
      config:
        rotate: 180
        refresh: 5
@NovapaX

This comment has been minimized.

Copy link

NovapaX commented Apr 7, 2018

That makes sense. Although I would prefer to (be able to) define cards separately and reference them by id in the view. That makes it easier to manually edit ordering, moving it to another view or showing the same card on multiple views. Same with state-cards/entities.
I do realize that will turn into a relational database rather than a single config object.

@balloob

This comment has been minimized.

Copy link
Member Author

balloob commented Apr 8, 2018

Although I can see the use cases, I also think that it will make it just more complicated for beginners to get started and understand the system. I think that if we allow people to duplicate cards and then move cards to other views, we can cover most of those use cases.

@NovapaX

This comment has been minimized.

Copy link

NovapaX commented Apr 8, 2018

Hmm... both approaches are not mutually exclusive. So we could of course do the 'in-place' config first, and later add the ability to reference a card (elsewhere configured) by id.

I envision some sort of 'UI library' with our default UI 'building blocks', but also custom UI the user added and/or defined. Then it's a matter of adding (drag and drop?) those building blocks into a view.
You could also just store some Card/custom ui for later use.

@NovapaX

This comment has been minimized.

Copy link

NovapaX commented Apr 8, 2018

I just realize I’m getting a bit ahead of ourselves and we should just start building something really basic (but extendable) and see how it goes.

I’m not very familiar with doing big rafactoring/architectural stuff like this, so bear with me ;-) I’m just trying to get things going (and learning from it in the process)

For the backend we need a new ‘frontend’ component that:

  • exposes its config to the frontend.
  • migrates the current group-based views to a new config schema. (This can be removed later)
  • and of course provide some sensible default config (where needed)
  • and (later) takes config changes set in the frontend and save it.

This can be developed completely seperate from everything.

For the frontend it’s a bit harder. We could keep things backward compatible (fallback to groups based views) and do all this on the master branch. But if fear a lot of contidional code and the ‘old way’ holding back progress.
As this is a pretty big change for the frontend maybe we should just create project and a seperate branch to develop this on.

@NovapaX

This comment has been minimized.

Copy link

NovapaX commented Apr 8, 2018

Maybe the migration logic from group-based views to a seperate frontend config should be done in the frontend too.
The logic to determine the views based on the groups is already in place there.

@balloob

This comment has been minimized.

Copy link
Member Author

balloob commented Apr 8, 2018

So we already have a frontend component, so that's easy 😉

We can make it opt-in, have a new key under frontend config that includes a new file.

Frontend will check if config enabled, if so use that, otherwise fall back to old render logic.

The only thing we need to change is that we need some code to use our config instead of our current auto sorting algorithm

@NovapaX

This comment has been minimized.

Copy link

NovapaX commented Apr 8, 2018

There should be a config object (under ‘hass’ object?) that has the view config.
Our group-based view algorithm should be used to initialize that object (with the new scheme) if no other config is present.
That way we can start changing the frontend to use that object/schema without any need to change the backend. And that way it’ll be opt-in and fully backwards compatible. (The only thing is that new features won’t be added to our groups based view/sorting algo)

@balloob

This comment has been minimized.

Copy link
Member Author

balloob commented Apr 8, 2018

You are correct if you are talking about the hass object in the frontend 👍

@balloob

This comment has been minimized.

Copy link
Member Author

balloob commented Apr 8, 2018

We can have it live under the config object in hass. I am planning on making the websocket API extensible, so we can send it over the websocket connection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment