From a84a590dadee59c03f7e6bf99460141a5acb5a29 Mon Sep 17 00:00:00 2001 From: idaho <664101+idaho@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:16:14 +0100 Subject: [PATCH 1/3] add option to define a picture for each pattern instead of an icon --- src/cards/trash-card/elements/icon.ts | 4 +- src/cards/trash-card/elements/picture.ts | 43 +++++++++++++++++++ src/cards/trash-card/formSchemas.ts | 8 ++++ src/cards/trash-card/items/BaseItemElement.ts | 43 +++++++++++++++++++ src/cards/trash-card/items/card.ts | 29 +++++-------- src/cards/trash-card/items/chip.ts | 26 ++++------- src/cards/trash-card/items/icon.ts | 33 ++++++-------- src/cards/trash-card/trash-card-config.ts | 2 + src/utils/calendarItem.ts | 1 + src/utils/eventsToItems.ts | 3 +- src/utils/getPicture.ts | 8 ++++ src/utils/itemSettings.ts | 1 + 12 files changed, 139 insertions(+), 62 deletions(-) create mode 100644 src/cards/trash-card/elements/picture.ts create mode 100644 src/cards/trash-card/items/BaseItemElement.ts create mode 100644 src/utils/getPicture.ts diff --git a/src/cards/trash-card/elements/icon.ts b/src/cards/trash-card/elements/icon.ts index 2a29946..5a194d4 100644 --- a/src/cards/trash-card/elements/icon.ts +++ b/src/cards/trash-card/elements/icon.ts @@ -7,7 +7,7 @@ import type { CardStyleConfig } from '../trash-card-config'; import type { CalendarItem } from '../../../utils/calendarItem'; @customElement(`${TRASH_CARD_NAME}-element-icon`) -class ItemCard extends LitElement { +class Icon extends LitElement { @state() private readonly item?: CalendarItem; @state() private readonly hass?: HomeAssistant; @@ -41,5 +41,5 @@ class ItemCard extends LitElement { } export { - ItemCard + Icon }; diff --git a/src/cards/trash-card/elements/picture.ts b/src/cards/trash-card/elements/picture.ts new file mode 100644 index 0000000..9259967 --- /dev/null +++ b/src/cards/trash-card/elements/picture.ts @@ -0,0 +1,43 @@ +import { LitElement, css, html, nothing } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; + +import type { HomeAssistant } from '../../../utils/ha'; +import type { CardStyleConfig } from '../trash-card-config'; +import type { CalendarItem } from '../../../utils/calendarItem'; + +@customElement(`${TRASH_CARD_NAME}-element-picture`) +class Picture extends LitElement { + @state() private readonly item?: CalendarItem; + + @state() private readonly hass?: HomeAssistant; + + @state() private readonly config?: CardStyleConfig; + + @state() private readonly pictureUrl?: string; + + public render () { + if (!this.pictureUrl) { + return nothing; + } + + return html``; + } + + public static get styles () { + return [ + css` + img { + height: var(--mdc-icon-size); + width: var(--mdc-icon-size); + object-fit: contain; + } + ` + ]; + } +} + +export { + Picture +}; diff --git a/src/cards/trash-card/formSchemas.ts b/src/cards/trash-card/formSchemas.ts index 51c5995..4893cb7 100644 --- a/src/cards/trash-card/formSchemas.ts +++ b/src/cards/trash-card/formSchemas.ts @@ -35,6 +35,14 @@ const getPatternSchema = (customLocalize: ReturnType selector: { text: {} } + }, + { + label: customLocalize(`editor.card.trash.pattern.fields.picture_url`), + name: 'picture', + selector: { + text: {} + }, + context: { icon_entity: 'entity' } } ]; diff --git a/src/cards/trash-card/items/BaseItemElement.ts b/src/cards/trash-card/items/BaseItemElement.ts new file mode 100644 index 0000000..f6f0a56 --- /dev/null +++ b/src/cards/trash-card/items/BaseItemElement.ts @@ -0,0 +1,43 @@ +/* eslint-disable unicorn/filename-case */ +import { LitElement, html } from 'lit'; +import { getPicture } from '../../../utils/getPicture'; +import { state } from 'lit/decorators.js'; + +import type { CardStyleConfig } from '../trash-card-config'; +import type { CalendarItem } from '../../../utils/calendarItem'; +import type { HomeAssistant } from '../../../utils/ha'; + +// eslint-disable-next-line @typescript-eslint/ban-types +class BaseItemElement extends LitElement { + @state() protected readonly item?: CalendarItem & T; + + @state() protected readonly hass?: HomeAssistant; + + @state() protected readonly config?: CardStyleConfig; + + protected getPictureUrl () { + return getPicture(this.item!.picture, this.hass!); + } + + protected renderPicture (pictureUrl: string) { + return html` + `; + } + + protected renderIcon () { + return html` + `; + } +} + +export { + BaseItemElement +}; diff --git a/src/cards/trash-card/items/card.ts b/src/cards/trash-card/items/card.ts index b75e975..f540fb5 100644 --- a/src/cards/trash-card/items/card.ts +++ b/src/cards/trash-card/items/card.ts @@ -1,26 +1,17 @@ import { computeRTL } from 'lovelace-mushroom/src/ha'; -import { LitElement, css, html, nothing } from 'lit'; +import { css, html, nothing } from 'lit'; import { styleMap } from 'lit/directives/style-map.js'; import { getDateString } from '../../../utils/getDateString'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement } from 'lit/decorators.js'; import { TRASH_CARD_NAME } from '../const'; import { defaultHaCardStyle } from '../../../utils/defaultHaCardStyle'; import { getColoredStyle } from '../../../utils/getColoredStyle'; +import { BaseItemElement } from './BaseItemElement'; import '../elements/icon'; -import type { CardStyleConfig } from '../trash-card-config'; -import type { CalendarItem } from '../../../utils/calendarItem'; -import type { HomeAssistant } from '../../../utils/ha'; - @customElement(`${TRASH_CARD_NAME}-item-card`) -class ItemCard extends LitElement { - @state() private readonly item?: CalendarItem; - - @state() private readonly hass?: HomeAssistant; - - @state() private readonly config?: CardStyleConfig; - +class ItemCard extends BaseItemElement { public render () { if (!this.hass || !this.item || !this.config) { return nothing; @@ -41,16 +32,15 @@ class ItemCard extends LitElement { const secondary = getDateString(item, hide_time_range ?? false, day_style, this.hass); + const pictureUrl = this.getPictureUrl(); + return html` - +
+ ${pictureUrl ? this.renderPicture(pictureUrl) : this.renderIcon()} +
- + ${pictureUrl ? this.renderPicture(pictureUrl) : this.renderIcon()} ${content ? html`${content}` : nothing} `; } @@ -57,6 +46,7 @@ class ItemChip extends LitElement { return [ css` mushroom-chip { + --mdc-icon-size: var(--trash-card-icon-size, 16px); --chip-background: var(--trash-card-background, var(--ha-card-background, var(--card-background-color, #fff) diff --git a/src/cards/trash-card/items/icon.ts b/src/cards/trash-card/items/icon.ts index 4273b95..a36819d 100644 --- a/src/cards/trash-card/items/icon.ts +++ b/src/cards/trash-card/items/icon.ts @@ -1,29 +1,21 @@ import { computeRTL } from 'lovelace-mushroom/src/ha'; -import { LitElement, css, html, nothing } from 'lit'; +import { css, html, nothing } from 'lit'; import { styleMap } from 'lit/directives/style-map.js'; import { classMap } from 'lit/directives/class-map.js'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement } from 'lit/decorators.js'; import { TRASH_CARD_NAME } from '../const'; import { defaultHaCardStyle } from '../../../utils/defaultHaCardStyle'; import { getColoredStyle } from '../../../utils/getColoredStyle'; import { daysTill } from '../../../utils/daysTill'; +import { BaseItemElement } from './BaseItemElement'; import '../elements/icon'; - -import type { CardStyleConfig } from '../trash-card-config'; -import type { CalendarItem } from '../../../utils/calendarItem'; -import type { HomeAssistant } from '../../../utils/ha'; +import '../elements/picture'; @customElement(`${TRASH_CARD_NAME}-icon-card`) -class IconCard extends LitElement { - @state() private readonly item?: CalendarItem & { +class IconCard extends BaseItemElement<{ nextEvent: boolean; - }; - - @state() private readonly hass?: HomeAssistant; - - @state() private readonly config?: CardStyleConfig; - + }> { public render () { if (!this.hass || !this.item || !this.config) { return nothing; @@ -37,7 +29,7 @@ class IconCard extends LitElement { const style = { ...getColoredStyle([ 'icon', 'background' ], item), // eslint-disable-next-line @typescript-eslint/naming-convention - '--trash-card-icon-size': `${this.config.icon_size}px` + '--trash-card-icon-size': `${this.config.icon_size ?? 40}px` }; const cssClass = { @@ -47,16 +39,15 @@ class IconCard extends LitElement { const daysLeft = daysTill(item); + const pictureUrl = this.getPictureUrl(); + return html` - +
+ ${pictureUrl ? this.renderPicture(pictureUrl) : this.renderIcon()} +
${daysLeft} diff --git a/src/cards/trash-card/trash-card-config.ts b/src/cards/trash-card/trash-card-config.ts index a7b3b66..277badc 100644 --- a/src/cards/trash-card/trash-card-config.ts +++ b/src/cards/trash-card/trash-card-config.ts @@ -38,6 +38,7 @@ type EntityWithOutIcon = Omit; card_style?: typeof CARDSTYLES[number]; color_mode?: typeof COLORMODES[number]; refresh_rate?: number; + icon_size?: number; debug?: boolean; }; @@ -71,6 +72,7 @@ const entityCardConfigStruct = assign( icon: optional(string()), label: optional(string()), pattern: optional(string()), + picture: optional(string()), type: string() }) )) diff --git a/src/utils/calendarItem.ts b/src/utils/calendarItem.ts index e47b30e..d711191 100644 --- a/src/utils/calendarItem.ts +++ b/src/utils/calendarItem.ts @@ -5,6 +5,7 @@ interface CalendarItem extends CalendarEvent { color?: string; icon?: string; type: `custom-${number}` | 'organic' | 'paper' | 'recycle' | 'waste' | 'others'; + picture?: string; } export type { diff --git a/src/utils/eventsToItems.ts b/src/utils/eventsToItems.ts index 3401c54..850a36f 100644 --- a/src/utils/eventsToItems.ts +++ b/src/utils/eventsToItems.ts @@ -21,9 +21,8 @@ const getLabel = (event: CalendarEvent, settings: ItemSettings, useSummary: bool const getData = (event: CalendarEvent, pattern: Pattern & { idx: number }, useSummary: boolean): CalendarItem => ({ ...event, + ...pattern, label: getLabel(event, pattern, useSummary), - icon: pattern.icon!, - color: pattern.color!, type: pattern.type === 'custom' ? `custom-${pattern.idx}` : pattern.type }); diff --git a/src/utils/getPicture.ts b/src/utils/getPicture.ts new file mode 100644 index 0000000..90d1e8b --- /dev/null +++ b/src/utils/getPicture.ts @@ -0,0 +1,8 @@ +import type { HomeAssistant } from './ha'; + +const getPicture = (url: string | undefined, hass: HomeAssistant): string | undefined => + url ? `${hass.hassUrl(url)}` : undefined; + +export { + getPicture +}; diff --git a/src/utils/itemSettings.ts b/src/utils/itemSettings.ts index 66ce5f6..959afe7 100644 --- a/src/utils/itemSettings.ts +++ b/src/utils/itemSettings.ts @@ -4,6 +4,7 @@ interface ItemSettings { pattern?: string; icon?: string; type: 'custom' | 'organic' | 'paper' | 'recycle' | 'waste' | 'others'; + picutre?: string; } export type { From de9606bf7d17e892e9b417834d68b1e232526bc3 Mon Sep 17 00:00:00 2001 From: idaho <664101+idaho@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:21:40 +0100 Subject: [PATCH 2/3] add german translation --- src/cards/trash-card/formSchemas.ts | 1 + src/translations/de.json | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cards/trash-card/formSchemas.ts b/src/cards/trash-card/formSchemas.ts index 4893cb7..3d8784b 100644 --- a/src/cards/trash-card/formSchemas.ts +++ b/src/cards/trash-card/formSchemas.ts @@ -38,6 +38,7 @@ const getPatternSchema = (customLocalize: ReturnType }, { label: customLocalize(`editor.card.trash.pattern.fields.picture_url`), + helper: customLocalize(`editor.card.trash.pattern.fields.picture_url_description`), name: 'picture', selector: { text: {} diff --git a/src/translations/de.json b/src/translations/de.json index a74bd10..f38fda1 100644 --- a/src/translations/de.json +++ b/src/translations/de.json @@ -77,7 +77,9 @@ "label": "Bezeichnung", "color": "Farbe", "icon": "Symbol", - "pattern": "erkennen an Muster" + "pattern": "erkennen an Muster", + "picture_url": "Bild URL", + "picture_url_description": "Wenn eine Bild URL angegeben wird, wird das entsprechende Bild anstelle das Icon angezeigt. Lege ein Bild in dem `/config/www` Ordner ab und verwende `/local/[BILDNAME.ENDNUNG]`." } } } From ccaaf5e26b3aac2685fa4588f8e7753552333048 Mon Sep 17 00:00:00 2001 From: idaho <664101+idaho@users.noreply.github.com> Date: Wed, 28 Feb 2024 15:03:33 +0100 Subject: [PATCH 3/3] add translations --- src/translations/de.json | 2 +- src/translations/en.json | 4 +++- src/translations/fr.json | 4 +++- src/translations/hu.json | 4 +++- src/translations/it.json | 4 +++- src/translations/pl.json | 4 +++- src/translations/sk.json | 4 +++- 7 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/translations/de.json b/src/translations/de.json index f38fda1..5cfd765 100644 --- a/src/translations/de.json +++ b/src/translations/de.json @@ -79,7 +79,7 @@ "icon": "Symbol", "pattern": "erkennen an Muster", "picture_url": "Bild URL", - "picture_url_description": "Wenn eine Bild URL angegeben wird, wird das entsprechende Bild anstelle das Icon angezeigt. Lege ein Bild in dem `/config/www` Ordner ab und verwende `/local/[BILDNAME.ENDNUNG]`." + "picture_url_description": "Wenn eine Bild URL angegeben wird, wird das entsprechende Bild anstelle das Icon angezeigt. Lege ein Bild in dem `/config/www` Ordner ab und verwende `/local/[Dateiname]`." } } } diff --git a/src/translations/en.json b/src/translations/en.json index be33dd2..51d1c30 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -77,7 +77,9 @@ "label": "Label", "color": "Color", "icon": "Icon", - "pattern": "Detection pattern" + "pattern": "Detection pattern", + "picture_url": "Picture URL", + "picture_url_description": "If a picture URL is specified, the corresponding picture is displayed instead of the icon. Place an image in the `/config/www` folder and use `/local/[filename]`." } } } diff --git a/src/translations/fr.json b/src/translations/fr.json index 16c363b..10336af 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -77,7 +77,9 @@ "label": "Étiquette", "color": "Couleur", "icon": "Icône", - "pattern": "Modèle de détection" + "pattern": "Modèle de détection", + "picture_url" : "URL de l'image", + "picture_url_description" : "Si une URL d'image est indiquée, l'image correspondante sera affichée au lieu de l'icône. Placez une image dans le dossier `/config/www` et utilisez `/local/[nom de fichier]`" } } } diff --git a/src/translations/hu.json b/src/translations/hu.json index af50dd4..a5b973a 100644 --- a/src/translations/hu.json +++ b/src/translations/hu.json @@ -77,7 +77,9 @@ "label": "Cimke", "color": "Szín", "icon": "Ikon", - "pattern": "Felismerési minta" + "pattern": "Felismerési minta", + "picture_url": "Kép URL címe", + "picture_url_description": "Ha egy kép URL címe van megadva, akkor az ikon helyett a megfelelő kép jelenik meg. Helyezzen el egy képet a `/config/www` mappában, és használja a `/local/[fájlnév]`" } } } diff --git a/src/translations/it.json b/src/translations/it.json index 8b58be1..e2685dd 100644 --- a/src/translations/it.json +++ b/src/translations/it.json @@ -77,7 +77,9 @@ "label": "Etichetta", "color": "Colore", "icon": "Icona", - "pattern": "Pattern identificazione" + "pattern": "Pattern identificazione", + "picture_url": "URL immagine", + "picture_url_description": "Se viene specificato un URL dell'immagine, al posto dell'icona viene visualizzata l'immagine corrispondente. Posizionare un'immagine nella cartella `/config/www` e utilizzare `/local/[filename]`." } } } diff --git a/src/translations/pl.json b/src/translations/pl.json index 5622fd7..cef07b2 100644 --- a/src/translations/pl.json +++ b/src/translations/pl.json @@ -77,7 +77,9 @@ "label": "Oznaczenie", "color": "Kolor", "icon": "Ikona", - "pattern": "Szablon wzorca" + "pattern": "Szablon wzorca", + "picture_url": "Adres URL obrazka", + "picture_url_description": "Jeśli podano adres URL obrazu, odpowiedni obraz jest wyświetlany zamiast ikony. Umieść obrazek w folderze `/config/www` i użyj `/local/[nazwa_pliku]`." } } } diff --git a/src/translations/sk.json b/src/translations/sk.json index 1fe6e8a..d79111a 100644 --- a/src/translations/sk.json +++ b/src/translations/sk.json @@ -77,7 +77,9 @@ "label": "štítok", "color": "Farba", "icon": "Ikona", - "pattern": "Vzor detekcie" + "pattern": "Vzor detekcie", + "picture_url": "URL obrázku", + "picture_url_description": "Ak je zadaná adresa URL obrázka, namiesto ikony sa zobrazí príslušný obrázok. Umiestnite obrázok do priečinka `/config/www` a použite `/local/[meno súboru]`." } } }