Skip to content

Commit

Permalink
feat: add templates and lots of refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
denysdovhan committed Apr 20, 2022
1 parent 8c9ca6c commit 6f8bb45
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 57 deletions.
61 changes: 54 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ stats:
- attribute: motor_speed
unit: RPM
subtitle: Motor Speed
- value_template: >-
{{ (states('sensor.purifier_filter_life') | float(0) / 3600) | round(1) }}
unit: hours
subtitle: Filter Life
shortcuts:
- name: Silent
icon: 'mdi:weather-night'
Expand Down Expand Up @@ -126,12 +130,13 @@ Here is what every option means:

You can use any attribute of purifier or even any entity by `entity_id` to display by stats section:

| Name | Type | Default | Description |
| ----------- | :------: | -------- | ---------------------------------------------------- |
| `entity_id` | `string` | Optional | An entity_id with state, i.e. `sensor.purifier_aqi`. |
| `attribute` | `string` | Optional | Attribute name of the stat, i.e. `filter_left`. |
| `unit` | `string` | Optional | Unit of measure, i.e. `hours`. |
| `subtitle` | `string` | Optional | Friendly name of the stat, i.e. `Filter`. |
| Name | Type | Default | Description |
| ---------------- | :------: | -------- | ---------------------------------------------------- |
| `entity_id` | `string` | Optional | An entity_id with state, i.e. `sensor.purifier_aqi`. |
| `attribute` | `string` | Optional | Attribute name of the stat, i.e. `filter_left`. |
| `value_template` | `string` | Optional | Jinja2 template returning a value. |
| `unit` | `string` | Optional | Unit of measure, i.e. `hours`. |
| `subtitle` | `string` | Optional | Friendly name of the stat, i.e. `Filter`. |

### `shortcuts` object

Expand All @@ -152,6 +157,48 @@ The card will automatically try to figure out which one of shortcuts is currentl
2. `entity`'s `percentage` attribute is equal to `shortcut`'s `percentage`.
3. `entity`'s `preset_mode` attribute is equal to `shortcut`'s `preset_mode`.

## Theming

This card can be styled by changing the values of these CSS properties (globally or per-card via [`card-mod`][card-mod]):

| Variable | Default value | Description |
| --------------------------- | ---------------------------------------------------------------- | ------------------------------------ |
| `--pc-background` | `var(--ha-card-background, var(--card-background-color, white))` | Background of the card |
| `--pc-primary-text-color` | `var(--primary-text-color)` | Vacuum name, stats values, etc |
| `--pc-secondary-text-color` | `var(--secondary-text-color)` | Status, stats units and titles, etc |
| `--pc-icon-color` | `var(--secondary-text-color)` | Colors of icons |
| `--pc-slider-path-color` | `var(--round-slider-path-color)` | Color of the slider path |
| `--pc-slider-bar-color` | `var(--round-slider-bar-color)` | Color of the slider bar |
| `--pc-toolbar-background` | `var(--vc-background)` | Background of the toolbar |
| `--pc-toolbar-text-color` | `var(--secondary-text-color)` | Color of the toolbar texts |
| `--pc-toolbar-icon-color` | `var(--secondary-text-color)` | Color of the toolbar icons |
| `--pc-divider-color` | `var(--entities-divider-color, var(--divider-color))` | Color of dividers |
| `--pc-spacing` | `10px` | Paddings and margins inside the card |

### Styling via theme

Here is an example of customization via theme. Read more in the [Frontend documentation](https://www.home-assistant.io/integrations/frontend/).

```yaml
my-custom-theme:
pc-background: '#17A8F4'
pc-spacing: 5px
```

### Styling via card-mod

You can use [`card-mod`][card-mod] to customize the card on per-card basis, like this:

```yaml
type: 'custom:purifier-card'
style: |
ha-card {
--pc-background: #17A8F4;
--pc-spacing: 5px;
}
...
```

## Animations

I've added an animation for this card to make it alive:
Expand Down Expand Up @@ -241,7 +288,7 @@ MIT © [Denys Dovhan][denysdovhan]

[home-assistant]: https://www.home-assistant.io/
[hacs]: https://hacs.xyz
[preview-image]: https://user-images.githubusercontent.com/3459374/144429511-23d91a48-e296-4d68-a46c-48f3649bdcda.png
[preview-image]: https://user-images.githubusercontent.com/3459374/164275676-504d92aa-2c61-4451-ae9b-23dad113ce14.png
[latest-release]: https://github.com/denysdovhan/purifier-card/releases/latest
[ha-scripts]: https://www.home-assistant.io/docs/scripts/
[xiaomi-miio-favorite-levels]: https://www.home-assistant.io/integrations/xiaomi_miio/#service-xiaomi_miiofan_set_favorite_level-air-purifiers-only
Expand Down
115 changes: 65 additions & 50 deletions src/purifier-card.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { LitElement, html } from 'lit-element';
import { LitElement, html, nothing } from 'lit';
import { hasConfigOrEntityChanged, fireEvent } from 'custom-card-helpers';
import './purifier-card-editor';
import registerTemplates from 'ha-template';
import localize from './localize';
import styles from './styles';
import styles from './styles.css';
import { version } from '../package.json';
import workingImg from './images/purifier-working.gif';
import standbyImg from './images/purifier-standby.png';
import './purifier-card-editor';

registerTemplates();

console.info(
`%c PURIFIER-CARD %c ${version} `,
Expand Down Expand Up @@ -131,15 +134,15 @@ class PurifierCard extends LitElement {
}
}

handleMore() {
handleMore(entityId = this.entity.entity_id) {
fireEvent(
this,
'hass-more-info',
{
entityId: this.entity.entity_id,
entityId,
},
{
bubbles: true,
bubbles: false,
composed: true,
}
);
Expand Down Expand Up @@ -178,31 +181,33 @@ class PurifierCard extends LitElement {
!preset_modes ||
!(supported_features & SUPPORT_PRESET_MODE)
) {
return html``;
return nothing;
}

const selected = preset_modes.indexOf(preset_mode);

return html`
<ha-button-menu @click="${(e) => e.stopPropagation()}">
<mmp-icon-button slot="trigger">
<ha-icon icon="mdi:fan"></ha-icon>
<span>
${localize(`preset_mode.${preset_mode}`) || preset_mode}
</span>
</mmp-icon-button>
${preset_modes.map(
(item, index) =>
html`<mwc-list-item
?activated=${selected === index}
value=${item}
@click=${(e) => this.handlePresetMode(e)}
>
${localize(`preset_mode.${item}`) || item}
</mwc-list-item>`
)}
</ha-button-menu>
<div class="preset-mode">
<ha-button-menu @click="${(e) => e.stopPropagation()}">
<mmp-icon-button slot="trigger">
<ha-icon icon="mdi:fan"></ha-icon>
<span>
${localize(`preset_mode.${preset_mode}`) || preset_mode}
</span>
</mmp-icon-button>
${preset_modes.map(
(item, index) =>
html`<mwc-list-item
?activated=${selected === index}
value=${item}
@click=${(e) => this.handlePresetMode(e)}
>
${localize(`preset_mode.${item}`) || item}
</mwc-list-item>`
)}
</ha-button-menu>
</div>
`;
}

Expand Down Expand Up @@ -271,7 +276,7 @@ class PurifierCard extends LitElement {
} = this.entity;

if (!this.showName) {
return html``;
return nothing;
}

return html` <div class="friendly-name">${friendly_name}</div> `;
Expand All @@ -282,18 +287,18 @@ class PurifierCard extends LitElement {
const localizedState = localize(`state.${state}`) || state;

if (!this.showState) {
return html``;
return nothing;
}

return html`
<div class="state">
<span class="state-text" alt=${localizedState}>
${localizedState}
</span>
<ha-circular-progress
.active=${this.requestInProgress}
size="small"
></ha-circular-progress>
<mwc-circular-progress
.indeterminate=${this.requestInProgress}
density="-5"
></mwc-circular-progress>
</div>
`;
}
Expand All @@ -303,31 +308,41 @@ class PurifierCard extends LitElement {

const statsList = stats || [];

return statsList.map(({ entity_id, attribute, unit, subtitle }) => {
if (!entity_id && !attribute) {
return html``;
}

const value = entity_id
? this.hass.states[entity_id].state
: this.entity.attributes[attribute];
return statsList.map(
({ entity_id, attribute, value_template, unit, subtitle }) => {
if (!entity_id && !attribute && !value_template) {
return nothing;
}

const state = entity_id
? this.hass.states[entity_id].state
: this.entity.attributes[attribute];

const value = html`
<ha-template
hass=${this.hass}
template=${value_template}
value=${state}
></ha-template>
`;

return html`
<div class="stats-block">
<span class="stats-value">${value}</span>
${unit}
<div class="stats-subtitle">${subtitle}</div>
</div>
`;
});
return html`
<div class="stats-block" @click="${() => this.handleMore(entity_id)}">
<span class="stats-value">${value}</span>
${unit}
<div class="stats-subtitle">${subtitle}</div>
</div>
`;
}
);
}

renderToolbar() {
const { shortcuts = [] } = this.config;
const { state, attributes } = this.entity;

if (!this.showToolbar) {
return html``;
return nothing;
}

const buttons = shortcuts.map(
Expand Down Expand Up @@ -401,7 +416,7 @@ class PurifierCard extends LitElement {
<ha-card>
<div class="preview">
<div class="header">
<div class="preset-mode">
<div class="tips">
${this.renderPresetMode()}
</div>
<ha-icon-button
Expand Down

0 comments on commit 6f8bb45

Please sign in to comment.