Skip to content

Commit 1c8c081

Browse files
authored
Release v1.0.0 (#20)
* Sorting entities based on attribute values (#13) * Large icons and attribute values / disabling compact view (#17) * Allow to use simple strings as attributes in the config Fixes: * Allow resetting (to default) card-level settings on individual entities (#18) * Margin fixes to align with standard entity rows
1 parent b5f24bd commit 1c8c081

File tree

10 files changed

+272
-114
lines changed

10 files changed

+272
-114
lines changed

README.md

Lines changed: 111 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,66 @@
11
# Github Flexi Card
2-
Home Assistant card displaying data from [Github integration](https://www.home-assistant.io/integrations/github/)
2+
[![GitHub Release][releases-shield]][releases]
3+
[![GitHub All Releases][downloads-total-shield]][releases]
4+
<!--[![hacs_badge][hacs-shield]][hacs]
5+
[![Community Forum][forum-shield]][forum]-->
6+
7+
Home Assistant card displaying data from [Github integration][ha-gh-integration]
38

49
## Overview
510

611
The aim of this card is to show all the data provided by github integration. You can specify what kind of data is shown and where. Entity rows are matching the size of other standard entity rows from other native cards (e.g. height of the row, icon/text margins, font sizes, etc).
712

8-
![image](https://user-images.githubusercontent.com/8268674/95763370-d904b180-0ca6-11eb-9951-56c8200ee025.png)
13+
This code works as both: card and enrity-row
914

10-
This component can be used as entity as well
15+
Note: If you plan to use it only as entity row you can consider using the other simpler/smaller code written by benct: [github-entity-row][github-entity-row]
1116

12-
![image](https://user-images.githubusercontent.com/8268674/96303544-7be46500-0ff2-11eb-9a86-16af9c52f1d0.png)
17+
![image](https://user-images.githubusercontent.com/8268674/97019224-fad42300-1547-11eb-8153-46c401f50455.png)
1318

1419
## Configuration
1520

1621
### Card
1722
| Name | Type | Default | Since | Description |
1823
|:-----|:-----|:-----|:-----|:-----|
19-
| title | String | | v0.1.0 | Card header/title text
20-
| entities | [Entity](#entity)[] \| String | **(required)** | v0.1.0 | Collection of entities to display. You can provide simple list of entity_id strings.
24+
| title | string | | v0.1.0 | Card header/title text
25+
| entities | list([Entity](#entity)) \| string | **(required)** | v0.1.0 | Collection of entities to display. You can provide simple list of entity_id strings.
26+
| sort | list([SortOptions](#sort-options)) | | v1.0.0 | Sort options collection (order matters). Every next sorting option is used fot the next level sorting (if the values of the previous one are same)
2127

2228
[+ Entity Properties](#Entity-Properties) - applied to all entities
2329

2430
### Entity
2531
| Name | Type | Default | Since | Description |
2632
|:-----|:-----|:-----|:-----|:-----|
27-
| entity | String | **(required)** | v0.1.0 | Entity ID e.g. `sensor.my_github_project`
33+
| entity | string | **(required)** | v0.1.0 | Entity ID e.g. `sensor.my_github_project`
2834

2935
[+ Entity Properties](#Entity-Properties)
3036

3137
### Entity Properties
3238
| Name | Type | Default | Since | Description |
3339
|:-----|:-----|:-----|:-----|:-----|
34-
| name | [KString](#keywordstring) | | v0.1.0 | Name override
40+
| name | [KString](#keywordstring) | `friendly_name` | v0.1.0 | Name override
3541
| secondary_info | [KString](#keywordstring) | | v0.1.0 | String to display underneath the entity name
36-
| attributes | [Attribute](#attribute)[] | | v0.1.0 | Attributes to display
37-
| url | [KString](#keywordstring) \| Boolean | | v0.2.0 | Url to open on click/tap. (when `true` is used the target url becomes repo homepage)
38-
| attribute_urls | Boolean | | v0.2.0 | When set to `true` turns on default urls for all the displayed attributes
39-
| icon | String | `"mdi:github"` | v0.2.0 | Override for entity icon
42+
| attributes | list([Attribute](#attribute)) | | v0.1.0 | Attributes to display
43+
| url | [KString](#keywordstring) \| bool | | v0.2.0 | Url to open on click/tap. (when `true` is used the target url becomes repo homepage)
44+
| attribute_urls | bool | | v0.2.0 | When set to `true` turns on default urls for all the displayed attributes
45+
| icon | string | `"mdi:github"` | v0.2.0 | Override for entity icon
46+
| compact_view | bool | `true` | v1.0.0 | When set to `false` big icons (and values) are displayed
4047

4148
### Attribute
4249
| Name | Type | Default | Since | Description |
4350
|:-----|:-----|:-----|:-----|:-----|
44-
| name | String | **(required)** | v0.1.0 | Name of the attribute
45-
| icon | String | | v0.1.0 | Icon override (there are default icons for most of the available attributes)
46-
| url | [KString](#keywordstring) \| Boolean | | v0.2.0 | Url to open on click/tap. (there are default urls for most of the available attributes, so you can just use `true`)
51+
| name | string | **(required)** | v0.1.0 | Name of the attribute
52+
| icon | string | | v0.1.0 | Icon override (there are default icons for most of the available attributes)
53+
| url | [KString](#keywordstring) \| bool | | v0.2.0 | Url to open on click/tap. (there are default urls for most of the available attributes, so you can just use `true`)
4754
| label | [KString](#keywordstring) | | v0.5.0 | Label/text which will be shown instead of the icon
4855

56+
### Sort options
57+
58+
| Name | Type | Default | Since | Description |
59+
|:-----|:-----|:-----|:-----|:-----|
60+
| by | string | **(required)** | v1.0.0 | Name of the attribute
61+
| ascending | bool | `false` | v1.0.0 | Whether to sort ascending or descending
62+
63+
4964
### KeywordString
5065

5166
KeywordString is a string which can contain special keywords. Keywords are the attribute names surrounded by curly brackets. Keywords in the string will be replaced by attribute values.
@@ -84,16 +99,16 @@ entities:
8499
- entity: sensor.hideseek_mod
85100
url: true # default url - repo homepage
86101
attributes:
87-
- name: views
88-
- name: stargazers
89-
- name: forks
102+
- views
103+
- stargazers
104+
- forks
90105
- entity: sensor.urleditorpro
91106
name: 'Url Editor Pro (v{latest_release_tag})'
92107
secondary_info: 'Clones: {clones}'
93108
attributes:
94-
- name: views
95-
- name: stargazers
96-
- name: open_issues
109+
- views
110+
- stargazers
111+
- open_issues
97112
```
98113
99114
### Entity
@@ -114,12 +129,12 @@ entities:
114129
url: true
115130
attribute_urls: true
116131
attributes:
117-
- name: views
118-
- name: stargazers
119-
- name: open_issues
120-
- name: clones
121-
- name: forks
122-
- name: open_pull_requests
132+
- views
133+
- stargazers
134+
- open_issues
135+
- clones
136+
- forks
137+
- open_pull_requests
123138
- sensor.hassio_online
124139
- sensor.last_boot
125140
- sensor.processor_use
@@ -138,12 +153,12 @@ secondary_info: 'Released {latest_release_tag}'
138153
url: true
139154
attribute_urls: true
140155
attributes:
141-
- name: views
142-
- name: stargazers
143-
- name: open_issues
144-
- name: clones
145-
- name: forks
146-
- name: open_pull_requests
156+
- views
157+
- stargazers
158+
- open_issues
159+
- clones
160+
- forks
161+
- open_pull_requests
147162
entities:
148163
- sensor.battery_state_card
149164
- sensor.hideseek_mod
@@ -172,6 +187,53 @@ entities:
172187
- sensor.urleditorpro
173188
```
174189

190+
### Compact view (disabling)
191+
192+
![image](https://user-images.githubusercontent.com/8268674/96794344-eda71f00-13f5-11eb-85f2-f60caad2fa63.png)
193+
194+
```yaml
195+
type: 'custom:github-flexi-card'
196+
title: Big icons
197+
url: true
198+
attribute_urls: true
199+
attributes:
200+
- views
201+
- stargazers
202+
entities:
203+
- sensor.battery_state_card
204+
- entity: sensor.hideseek_mod
205+
compact_view: false
206+
- sensor.urleditorpro
207+
```
208+
209+
### Sorting
210+
211+
![image](https://user-images.githubusercontent.com/8268674/96928429-72ef0a00-14b0-11eb-95dd-4f1c76e217ec.png)
212+
213+
```yaml
214+
type: 'custom:github-flexi-card'
215+
title: Sort by starts and views (asc)
216+
secondary_info: '{latest_release_tag}'
217+
url: true
218+
attribute_urls: true
219+
attributes:
220+
- views_unique
221+
- stargazers
222+
- open_issues
223+
- open_pull_requests
224+
sort:
225+
- by: stargazers
226+
- by: views_unique
227+
ascending: true
228+
entities:
229+
- sensor.battery_state_card
230+
- sensor.hideseek_mod
231+
- sensor.github_flexi_card
232+
- sensor.urleditorpro
233+
- entity: sensor.home_assistant_config
234+
secondary_info: null
235+
```
236+
175237
## How to install?
176238

177239
Install HACS and add this repo as custom repository (lovelace plugins). Click on "Install".
@@ -182,4 +244,19 @@ If you have a YAML mode remember to add resource entry for the js bundle in ui-l
182244
resources:
183245
- url: /hacsfiles/github-flexi-card/github-flexi-card.js
184246
type: module
185-
```
247+
```
248+
249+
## Do you like the card?
250+
251+
Don't "buy me a coffee", just star it on github! It will be enough to let me know that you like it and definitely will give me motivation boost to continue working on it and other cards.
252+
253+
254+
[releases]: https://github.com/maxwroc/github-flexi-card/releases
255+
[releases-shield]: https://img.shields.io/github/release/maxwroc/github-flexi-card.svg?style=popout
256+
[downloads-total-shield]: https://img.shields.io/github/downloads/maxwroc/github-flexi-card/total
257+
[forum]: https://community.home-assistant.io/t/lovelace-battery-state-card/191535
258+
[forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg?style=popout
259+
[hacs-shield]: https://img.shields.io/badge/HACS-Default-orange.svg
260+
[hacs]: https://hacs.xyz/docs/default_repositories
261+
[ha-gh-integration]: https://www.home-assistant.io/integrations/github/
262+
[github-entity-row]: https://github.com/benct/lovelace-github-entity-row

hacs.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "Github Flexi Card",
2+
"name": "Github Flexi Card / Entity Row",
33
"content_in_root": false,
44
"filename": "github-flexi-card.js",
55
"render_readme": true

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "github-flexi-card",
3-
"version": "0.5.0",
3+
"version": "1.0.0",
44
"description": "Home assistant github card",
55
"main": "dist/github-flexi-card.js",
66
"scripts": {

src/custom-elements/card.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,11 @@
33
white-space: nowrap;
44
text-overflow: ellipsis;
55
overflow: hidden;
6+
}
7+
8+
.card-content > div {
9+
margin-bottom: 8px;
10+
}
11+
.card-content > div:last-child {
12+
margin-bottom: 0;
613
}

src/custom-elements/card.ts

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { HomeAssistant } from "../ha-types";
22
import { html, LitElement } from "../lit-element";
3-
import { ICardConfig, IEntityConfig } from "../types";
3+
import { ICardConfig, IEntityConfig, ISortOptions } from "../types";
44
import { GithubEntity } from "./entity";
55
import styles from "./card-styles";
6+
import { getConfigValue, safeGetArray, safeGetConfigObject } from "../utils";
67

78
export class GithubFlexiCard extends LitElement {
89

@@ -12,6 +13,10 @@ export class GithubFlexiCard extends LitElement {
1213

1314
private cardSize = 0;
1415

16+
private sortOptions?: ISortOptions[];
17+
18+
private order: number[] = [];
19+
1520
/**
1621
* CSS for the card
1722
*/
@@ -26,6 +31,7 @@ export class GithubFlexiCard extends LitElement {
2631
return {
2732
cardTitle: { type: String },
2833
entities: { type: Array },
34+
order: { type: Array },
2935
};
3036
}
3137

@@ -34,6 +40,28 @@ export class GithubFlexiCard extends LitElement {
3440
*/
3541
set hass(hass: HomeAssistant) {
3642
this.entities.forEach(entity => entity.hass = hass);
43+
44+
if (this.sortOptions && this.sortOptions.length) {
45+
const attrNames = this.sortOptions.map(s => s.by);
46+
const values = this.entities.map(e => e.getEntityAttributeValues(attrNames));
47+
48+
const applySortType = (a: number, b: number, ascending?: boolean) => ascending ? a - b : b - a;
49+
50+
// default order matches the config
51+
const defaultOrder = this.entities.map((e, i) => i);
52+
const newOrder = defaultOrder.sort(
53+
(a, b) => values[a].reduce(
54+
(prev, curr, i) => prev != 0 ? prev : applySortType(curr, values[b][i], this.sortOptions![i].ascending),
55+
0
56+
)
57+
);
58+
59+
// check if order has changed
60+
if (this.order.some((v, i) => v != newOrder[i])) {
61+
// trigger update
62+
this.order = newOrder;
63+
}
64+
}
3765
}
3866

3967
/**
@@ -54,11 +82,16 @@ export class GithubFlexiCard extends LitElement {
5482
elem.setConfig(entityConf);
5583
this.cardSize++;
5684
return elem;
57-
})
85+
});
5886
}
5987
else {
6088
this.entities.forEach((entity, index) => entity.setConfig(getEntityConfig(cardConfig.entities[index], cardConfig)));
6189
}
90+
91+
this.order = this.entities.map((e, i) => i);
92+
93+
const sortOptions = safeGetArray(cardConfig.sort).map(s => safeGetConfigObject(s, "by"))
94+
this.sortOptions = sortOptions;
6295
}
6396

6497
/**
@@ -79,7 +112,7 @@ export class GithubFlexiCard extends LitElement {
79112
<ha-card>
80113
${this.cardTitle && header(this.cardTitle)}
81114
<div class="card-content">
82-
${this.entities}
115+
${this.order.map(i => html`<div>${this.entities[i]}</div>`)}
83116
</div>
84117
</ha-card>
85118
`;
@@ -102,19 +135,16 @@ const header = (title: string) => html`
102135
*/
103136
const getEntityConfig = (configEntry: IEntityConfig | string, cardConfig: ICardConfig): IEntityConfig => {
104137

105-
const entityConfig = typeof configEntry != "string" ?
106-
// we have to make a copy as the original one is immutable
107-
{ ...configEntry } :
108-
// construct simple config entry
109-
{ entity: configEntry };
138+
const entityConfig = safeGetConfigObject(configEntry, "entity");
110139

111140
// if property is not defined take the card-level one
112-
entityConfig.attributes = entityConfig.attributes || cardConfig.attributes;
113-
entityConfig.attribute_urls = entityConfig.attribute_urls !== undefined ? entityConfig.attribute_urls : cardConfig.attribute_urls;
114-
entityConfig.icon = entityConfig.icon || cardConfig.icon;
115-
entityConfig.name = entityConfig.name || cardConfig.name;
116-
entityConfig.secondary_info = entityConfig.secondary_info || cardConfig.secondary_info;
117-
entityConfig.url = entityConfig.url !== undefined ? entityConfig.url : cardConfig.url;
141+
entityConfig.attributes = getConfigValue(entityConfig.attributes, cardConfig.attributes);
142+
entityConfig.attribute_urls = getConfigValue(entityConfig.attribute_urls, cardConfig.attribute_urls);
143+
entityConfig.icon = getConfigValue(entityConfig.icon, cardConfig.icon);
144+
entityConfig.name = getConfigValue(entityConfig.name, cardConfig.name);
145+
entityConfig.secondary_info = getConfigValue(entityConfig.secondary_info, cardConfig.secondary_info);
146+
entityConfig.url = getConfigValue(entityConfig.url, cardConfig.url);
147+
entityConfig.compact_view = getConfigValue(entityConfig.compact_view, cardConfig.compact_view, true);
118148

119149
return entityConfig;
120150
}

src/custom-elements/entity.css

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
.entity-row {
2323
display: flex;
2424
align-items: center;
25-
margin: 8px 0;
2625
}
2726
.entity-row .name {
2827
flex: 1;
@@ -42,8 +41,11 @@
4241
margin-right: 10px;
4342
}
4443

45-
.state {
44+
.compact-view .state {
4645
--mdc-icon-size: var(--attribute-icon-size);
46+
font-size: var(--paper-font-caption_-_font-size);
47+
}
48+
.state {
4749
display: flex;
4850
margin-left: 7px;
4951
}
@@ -54,7 +56,6 @@
5456
margin-left: 0;
5557
}
5658
.state > div {
57-
font-size: var(--paper-font-caption_-_font-size);
5859
line-height: 24px;
5960
}
6061

0 commit comments

Comments
 (0)