mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Add theme-choosing UI to config panel (#363)
* Add theme-choosing UI to config panel * Add Backend-selected option * Use Object.assign to change hass * Fix #368 - support theme-color update.
This commit is contained in:
parent
1ea7137c78
commit
ebc0c776e2
@ -8,6 +8,7 @@
|
||||
<!-- <link rel="import" href="./group/ha-config-section-group.html"> -->
|
||||
<link rel="import" href="./hassbian/ha-config-section-hassbian.html">
|
||||
<link rel="import" href="./z-wave/ha-config-section-zwave.html">
|
||||
<link rel="import" href="themes/ha-config-section-themes.html">
|
||||
|
||||
<dom-module id="ha-panel-config">
|
||||
<template>
|
||||
@ -53,6 +54,14 @@
|
||||
hass='[[hass]]'
|
||||
></ha-config-section-core>
|
||||
|
||||
<template is='dom-if' if='[[computeIsThemesLoaded(hass)]]'>
|
||||
<div class='border'></div>
|
||||
<ha-config-section-themes
|
||||
is-wide='[[isWide]]'
|
||||
hass='[[hass]]'
|
||||
></ha-config-section-themes>
|
||||
</template>
|
||||
|
||||
<template is='dom-if' if='[[computeIsHassbianLoaded(hass)]]'>
|
||||
<div class='border'></div>
|
||||
<ha-config-section-hassbian
|
||||
@ -120,5 +129,10 @@ Polymer({
|
||||
computeIsZwaveLoaded: function (hass) {
|
||||
return window.hassUtil.isComponentLoaded(hass, 'config.zwave');
|
||||
},
|
||||
|
||||
computeIsThemesLoaded: function (hass) {
|
||||
return hass.themes && hass.themes.themes &&
|
||||
Object.keys(hass.themes.themes).length;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
85
panels/config/themes/ha-config-section-themes.html
Normal file
85
panels/config/themes/ha-config-section-themes.html
Normal file
@ -0,0 +1,85 @@
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
|
||||
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
|
||||
<link rel='import' href='../../../bower_components/paper-listbox/paper-listbox.html'>
|
||||
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
|
||||
|
||||
<link rel="import" href="../ha-config-section.html">
|
||||
|
||||
<dom-module id="ha-config-section-themes">
|
||||
<template>
|
||||
<ha-config-section is-wide='[[isWide]]'>
|
||||
<span slot='header'>Set a theme</span>
|
||||
<span slot='introduction'>
|
||||
Choose 'default' to use whatever theme the backend chooses or pick a theme for this device.
|
||||
</span>
|
||||
|
||||
<paper-card>
|
||||
<div class='card-content'>
|
||||
<paper-dropdown-menu label='Theme' vertical-align='bottom'>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected='{{selectedTheme}}'
|
||||
>
|
||||
<template is='dom-repeat' items='[[themes]]' as='theme'>
|
||||
<paper-item>[[theme]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'ha-config-section-themes',
|
||||
|
||||
properties: {
|
||||
hass: {
|
||||
type: Object,
|
||||
},
|
||||
|
||||
isWide: {
|
||||
type: Boolean,
|
||||
},
|
||||
|
||||
themes: {
|
||||
type: Array,
|
||||
computed: 'computeThemes(hass)',
|
||||
},
|
||||
|
||||
selectedTheme: {
|
||||
type: Number,
|
||||
},
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
if (this.hass.selectedTheme && this.themes.indexOf(this.hass.selectedTheme) > 0) {
|
||||
this.selectedTheme = this.themes.indexOf(this.hass.selectedTheme);
|
||||
} else if (!this.hass.selectedTheme) {
|
||||
this.selectedTheme = 0;
|
||||
}
|
||||
},
|
||||
|
||||
observers: [
|
||||
'selectionChanged(hass, selectedTheme)',
|
||||
],
|
||||
|
||||
computeThemes: function (hass) {
|
||||
if (!hass) return [];
|
||||
return ['Backend-selected', 'default'].concat(Object.keys(hass.themes.themes).sort());
|
||||
},
|
||||
|
||||
selectionChanged: function (hass, selection) {
|
||||
if (selection > 0 && selection < this.themes.length) {
|
||||
if (hass.selectedTheme !== this.themes[selection]) {
|
||||
this.fire('settheme', this.themes[selection]);
|
||||
}
|
||||
} else if (selection === 0 && hass.selectedTheme !== '') {
|
||||
this.fire('settheme', '');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
@ -85,6 +85,10 @@ Polymer({
|
||||
},
|
||||
},
|
||||
|
||||
listeners: {
|
||||
settheme: 'setTheme',
|
||||
},
|
||||
|
||||
computeShowMain: function (hass, iconsLoaded) {
|
||||
return hass && hass.states && hass.config && iconsLoaded;
|
||||
},
|
||||
@ -158,13 +162,13 @@ Polymer({
|
||||
}, this.$.storage.getStoredState());
|
||||
|
||||
var reconnected = () => {
|
||||
this.hass = Object.assign({}, this.hass, { connected: true });
|
||||
this._updateHass({ connected: true });
|
||||
};
|
||||
|
||||
conn.addEventListener('ready', reconnected);
|
||||
|
||||
var disconnected = () => {
|
||||
this.hass = Object.assign({}, this.hass, { connected: false });
|
||||
this._updateHass({ connected: false });
|
||||
};
|
||||
|
||||
conn.addEventListener('disconnected', disconnected);
|
||||
@ -172,7 +176,7 @@ Polymer({
|
||||
var unsubEntities;
|
||||
|
||||
window.HAWS.subscribeEntities(conn, (states) => {
|
||||
this.hass = Object.assign({}, this.hass, { states: states });
|
||||
this._updateHass({ states: states });
|
||||
}).then(function (unsub) {
|
||||
unsubEntities = unsub;
|
||||
});
|
||||
@ -180,7 +184,7 @@ Polymer({
|
||||
var unsubConfig;
|
||||
|
||||
window.HAWS.subscribeConfig(conn, (config) => {
|
||||
this.hass = Object.assign({}, this.hass, { config: config });
|
||||
this._updateHass({ config: config });
|
||||
}).then(function (unsub) {
|
||||
unsubConfig = unsub;
|
||||
});
|
||||
@ -188,12 +192,12 @@ Polymer({
|
||||
var unsubThemes;
|
||||
|
||||
this.hass.callApi('get', 'themes').then((themes) => {
|
||||
this.hass.themes = themes;
|
||||
window.hassUtil.applyThemesOnElement(this, themes);
|
||||
this._updateHass({ themes: themes });
|
||||
window.hassUtil.applyThemesOnElement(this, themes, this.hass.selectedTheme, true);
|
||||
});
|
||||
conn.subscribeEvents((event) => {
|
||||
this.hass.themes = event.data;
|
||||
window.hassUtil.applyThemesOnElement(this, event.data);
|
||||
this._updateHass({ themes: event.data });
|
||||
window.hassUtil.applyThemesOnElement(this, event.data, this.hass.selectedTheme, true);
|
||||
}, 'themes_updated').then(function (unsub) {
|
||||
unsubThemes = unsub;
|
||||
});
|
||||
@ -220,16 +224,12 @@ Polymer({
|
||||
handleMoreInfo: function (ev) {
|
||||
ev.stopPropagation();
|
||||
|
||||
this.hass = Object.assign(
|
||||
{}, this.hass,
|
||||
{ moreInfoEntityId: ev.detail.entityId });
|
||||
this._updateHass({ moreInfoEntityId: ev.detail.entityId });
|
||||
},
|
||||
|
||||
handleDockSidebar: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this.hass = Object.assign(
|
||||
{}, this.hass,
|
||||
{ dockedSidebar: ev.detail.dock });
|
||||
this._updateHass({ dockedSidebar: ev.detail.dock });
|
||||
this.$.storage.storeState();
|
||||
},
|
||||
|
||||
@ -253,5 +253,15 @@ Polymer({
|
||||
ready: function () {
|
||||
this.loadIcons();
|
||||
},
|
||||
|
||||
setTheme: function (event) {
|
||||
this._updateHass({ selectedTheme: event.detail });
|
||||
window.hassUtil.applyThemesOnElement(this, this.hass.themes, this.hass.selectedTheme, true);
|
||||
this.$.storage.storeState();
|
||||
},
|
||||
|
||||
_updateHass: function (obj) {
|
||||
this.hass = Object.assign({}, this.hass, obj);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -2,6 +2,7 @@
|
||||
(function () {
|
||||
var STORED_STATE = [
|
||||
'dockedSidebar',
|
||||
'selectedTheme',
|
||||
];
|
||||
|
||||
Polymer({
|
||||
|
@ -492,25 +492,34 @@ window.hassUtil.computeLocationName = function (hass) {
|
||||
return hass && hass.config.core.location_name;
|
||||
};
|
||||
|
||||
window.hassUtil.applyThemesOnElement = function (element, themes, localTheme) {
|
||||
window.hassUtil.applyThemesOnElement = function (element, themes, localTheme, updateMeta) {
|
||||
if (!element._themes) {
|
||||
element._themes = {};
|
||||
}
|
||||
var themeName = themes.default_theme;
|
||||
let themeName = themes.default_theme;
|
||||
if (localTheme === 'default' || (localTheme && themes.themes[localTheme])) {
|
||||
themeName = localTheme;
|
||||
}
|
||||
if (themeName === 'default') {
|
||||
element.updateStyles(element._themes);
|
||||
return;
|
||||
const styles = Object.assign({}, element._themes);
|
||||
if (themeName !== 'default') {
|
||||
var theme = themes.themes[themeName];
|
||||
Object.keys(theme).forEach((key) => {
|
||||
var prefixedKey = '--' + key;
|
||||
element._themes[prefixedKey] = '';
|
||||
styles[prefixedKey] = theme[key];
|
||||
});
|
||||
}
|
||||
var theme = themes.themes[themeName];
|
||||
var styles = Object.assign({}, element._themes);
|
||||
Object.keys(theme).forEach(function (key) {
|
||||
var prefixedKey = '--' + key;
|
||||
element._themes[prefixedKey] = '';
|
||||
styles[prefixedKey] = theme[key];
|
||||
});
|
||||
element.updateStyles(styles);
|
||||
|
||||
if (!updateMeta) return;
|
||||
|
||||
const meta = document.querySelector('meta[name=theme-color]');
|
||||
if (meta) {
|
||||
if (!meta.hasAttribute('default-content')) {
|
||||
meta.setAttribute('default-content', meta.getAttribute('content'));
|
||||
}
|
||||
const themeColor = styles['--primary-color'] || meta.getAttribute('default-content');
|
||||
meta.setAttribute('content', themeColor);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user