Skip to content

Commit

Permalink
migrate back to single entities property
Browse files Browse the repository at this point in the history
  • Loading branch information
NecroKote committed Jan 22, 2025
1 parent be1df86 commit 9bec91b
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 44 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ The format is based on [Keep a Changelog][keep-a-changelog]

## [Unreleased]
## What's Changed

* Card now supports setting multiple `entities` in the card configuration. This allows you to show multiple departure boards in one card.
* Previous configurations are still supported, but will be migrated automatically as soon as you open the card editor and save the configuration.
* Editor bundle name changed to `hasl-departure-card-editor.js` to help with manual installation.

## [3.2.0] (2025-01-17)
Expand Down
10 changes: 4 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ Card fully supports configuration through the UI
### Options
| Name | Type | Required? | Description |
|----------------------|------------------|-----------|-------------------------------------------------------------------------------------------------------------|
| entity | entity | required | The entity_id of the 'Departure' sensor. |
| entities | entity[] | required | The array of entity_id of the 'Departure' sensors. If set, takes precedence over `entity` |
| entities | entity[] | required | The array of entity_id's of the 'Departure' sensors. |
| title | string | optional | If set, this will be rendered as the card name. |
| show_entity_name | bool | optional | Render a friendly name of a selected `entity`. Disabled when `entities` are set |
| show_entity_name | bool | optional | Render a friendly name of a selected `entity`. Disabled when `entities` are set to more than 1 entity |
| show_header | bool | optional | Render headers in each section such as "Line", "Destination" and "Departure". |
| show_icon | bool | optional | Render transport icon for each line. |
| show_departures | bool | optional | Render departures section. |
Expand All @@ -51,12 +50,11 @@ Card fully supports configuration through the UI
| hide_departed | bool | optional | If set, will hide already departured vehicles. |
| show_departed_offset | bool | optional | If set, will show some departed vehicles, which departed less than the offset minutes ago. |
| show_time_always | bool | optional | Always present time in HH:MM form. If not set, time will be presented as "in X minutes" or "X minutes ago". |
| show_updated | bool | optional | Render the 'last updated' text. Disabled when `entities` are set |
| show_updated | bool | optional | Render the 'last updated' text. Disabled when `entities` are set to more than 1 entity |
| language | string | optional | The texts will be rendered in this language. Can be one of `sv-SE`, `en-EN`, `fr-FR`. |
| click_action | string or object | optional | Action when tapping the card. See section `click_action` below. |

Only one of `entity` and `entities` is required to function. If both are specified, `entities` takes precedence and `entity` is ignored.
Setting `entities` will render departures from all the sensors as one list, that is sorted by `expected` time.
Setting `entities` to more than one entity will render departures from all of the sensors as one list sorted by `expected` time but will disable `show_entity_name` and `show_updated` options.

#### `click_action`

Expand Down
7 changes: 3 additions & 4 deletions src/DepartureCard/DepartureCard.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export type ClickAction = 'info' | EntityInfoAction | ServiceCallAction

export interface DepartureCardConfig extends LovelaceCardConfig {
title?: string
entity: string
entities?: string[]
entity?: string
entities: string[]

show_entity_name?: boolean
show_header?: boolean
Expand All @@ -34,9 +34,8 @@ export interface DepartureCardConfig extends LovelaceCardConfig {
}

export const DEFAULT_CONFIG: Partial<DepartureCardConfig> = {
entity: '',
title: '',
entities: undefined,
entities: [],

show_entity_name: true,
show_header: true,
Expand Down
64 changes: 34 additions & 30 deletions src/DepartureCard/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@ export class HASLDepartureCard extends LitElement implements LovelaceCard {
}

getCardSize() {
const singleEntitityExtras = (this.isManyEntitiesSet()
? () => 0
: () => {
const [_, attrs] = this.getFirstEntity()
if (!attrs) return 0

return (this.config.show_entity_name && attrs.friendly_name) ? 1 : 0
})()

const deps = this.getDepartures();
const entity = this.config?.entity;
const data = this.hass?.states[entity]
const attrs = data.attributes

const size = [
!!this.config.title ? 1 : 0,
((this.config.show_entity_name && attrs.friendly_name)) ? 1 : 0,
singleEntitityExtras,
!!this.config.show_header ? 1 : 0,
deps?.length || 0,
].reduce((sum, entity) => sum += entity ? entity : 0, 0);
Expand All @@ -46,8 +52,8 @@ export class HASLDepartureCard extends LitElement implements LovelaceCard {

getLayoutOptions() {
return {
grid_min_columns: 3,
grid_min_rows: 2,
grid_min_columns: 3,
grid_min_rows: 2,
};
}

Expand Down Expand Up @@ -77,10 +83,8 @@ export class HASLDepartureCard extends LitElement implements LovelaceCard {
this.isManyEntitiesSet()
? () => nothing
: () => {
const entity = this.config?.entity
if (!entity) return nothing;

const data = this.hass?.states[entity]
const [data, __] = this.getFirstEntity()
if (!data) return nothing;

return (this.config?.show_updated && data.last_updated)
? html`
Expand All @@ -104,20 +108,23 @@ export class HASLDepartureCard extends LitElement implements LovelaceCard {
`
}

private isManyEntitiesSet(): boolean {
return this.config?.entities?.length > 0
}
private isManyEntitiesSet = () => this.config?.entities?.length > 1

private getDeparturesFor(entity: string) {
if (entity === undefined) return undefined;
private getFirstEntity(): [HassEntity, DepartureAttributes] | [undefined, undefined] {
const data = this.hass?.states[this.config?.entities?.[0] || this.config?.entity];
const attrs = data?.attributes
if (data && attrs && isDepartureAttrs(attrs)) {
return [data, attrs]
}
return [undefined, undefined]
}

const data = this.hass?.states[entity]
if (data === undefined) return undefined;
if (!isDepartureAttrs(data.attributes)) return undefined;
private getDeparturesFor(attrs: DepartureAttributes | undefined) {
if (!attrs) return []

const now = new Date()

return (data.attributes.departures
return (attrs.departures
// filter direction
?.filter((d) => {
if (this.config?.direction === 0) return true
Expand Down Expand Up @@ -173,22 +180,19 @@ export class HASLDepartureCard extends LitElement implements LovelaceCard {

private getDepartures() {
if (this.isManyEntitiesSet()) {
return this.getDeparturesCombined(this.config?.entities)
} else {
return this.getDeparturesFor(this.config?.entity)
return this.getDeparturesCombined(this.config?.entities || [])
}

const [_, attrs] = this.getFirstEntity()
if (!attrs) return undefined;

return this.getDeparturesFor(attrs)
}

private renderDepartures = () => {
const renderEntityName = () => {
const entity = this.config?.entity
if (entity === undefined) return nothing;

const data = this.hass?.states[this.config?.entity]
if (data === undefined) return nothing;

const attrs = data.attributes
if (!isDepartureAttrs(attrs)) return nothing;
const [_, attrs] = this.getFirstEntity()
if (!attrs) return nothing;

return (this.config.show_entity_name && attrs.friendly_name)
? html`<div class="row name">${attrs.friendly_name}</div`
Expand Down
13 changes: 10 additions & 3 deletions src/DepartureCardEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ export class HASLDepartureCardEditor extends LitElement implements LovelaceCardE
public setConfig(config: DepartureCardConfig): void {
this._config = config
this._schema = this.getSchema(translateTo(getLanguage()))

// Migrate to multiple entities
if (config.entity && !config.entities?.length) {
const { entity, ...rest } = config
this._dispatchConfigChangedEvent({ ...rest, entities: [config.entity] })
}
}

private getSchema = (_ : (key :string) => string) => {
const haveMultipleEntities = this._config?.entities?.length > 0
const haveMultipleEntities = this._config?.entities?.length > 1

return [
{ name: "title", selector: { text: {} } },
Expand All @@ -33,7 +39,6 @@ export class HASLDepartureCardEditor extends LitElement implements LovelaceCardE
icon: "mdi:database",
title: _("editor_entities"),
schema: [
{ name: "entity", disabled: haveMultipleEntities, selector: { entity: { filter: { domain: 'sensor', integration: 'hasl3' }}} },
{ name: "show_entity_name", type: "boolean", disabled: haveMultipleEntities },
{ name: "entities", selector: { entity: { multiple: true, filter: { domain: 'sensor', integration: 'hasl3' }}} },
],
Expand Down Expand Up @@ -76,8 +81,10 @@ export class HASLDepartureCardEditor extends LitElement implements LovelaceCardE

private _valueChanged(ev: CustomEvent): void {
ev.stopPropagation();
const newConfig = ev.detail.value
this._dispatchConfigChangedEvent(ev.detail.value)
}

private _dispatchConfigChangedEvent(newConfig) {
const event = new Event("config-changed", { bubbles: true, composed: true});
event.detail = { config: newConfig };
this.dispatchEvent(event);
Expand Down

0 comments on commit 9bec91b

Please sign in to comment.