Skip to content

Commit

Permalink
0.2.0 (#2)
Browse files Browse the repository at this point in the history
* Add support for default values, number and boolean

* Fix bug when no variable

* Support for objects

* Update documentation
  • Loading branch information
RomRider authored Jun 8, 2019
1 parent a12ad22 commit 9778a49
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 47 deletions.
52 changes: 37 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This card is for [Lovelace](https://www.home-assistant.io/lovelace) on [Home Ass

We all use multiple times the same block of configuration across our lovelace configuration and we don't want to change the same things in a hundred places across our configuration each time we want to modify something.

`declutterring-card` to the rescue!! This card allows you to reuse multiple times the same configuration in your lovelace configuration to avoid repetition.
`declutterring-card` to the rescue!! This card allows you to reuse multiple times the same configuration in your lovelace configuration to avoid repetition and supports variables and default values.

## Configuration

Expand All @@ -27,29 +27,47 @@ First, you need to define your templates.

The templates are defined in an object at the root of your lovelace configuration. This object needs to be named `decluttering_templates`.

This object needs to contains your templates declaration, each template has a name and can contain variables. A variable needs to be enclosed in double square brackets `[[variable_name]]`. It will later be replaced by a real value when you instanciate a card which uses this template.
This object needs to contains your templates declaration, each template has a name and can contain variables. A variable needs to be enclosed in double square brackets `[[variable_name]]`. It will later be replaced by a real value when you instanciate a card which uses this template. If a variable is alone on it's line, enclose it in single quotes: `'[[variable_name]]'`.

Eg in your `lovelace-ui.yaml`:
You can also define default values for your variables in the `default` object.

```yaml
decluttering_templates:
<template_name>
default: # This is optional
- <variable_name>: <variable_value>
- <variable_name>: <variable_value>
[...]
card: # This is where you put your card config (it can be a card embedding other cards)
type: custom:my-super-card
[...]
```

Example in your `lovelace-ui.yaml`:
```yaml
resources:
- url: /local/decluttering-card.js
type: module

decluttering_templates:
my_first_template: # This is the name of a template
type: custom:button-card
name: '[[name]]'
icon: 'mdi:[[icon]]'
default:
- icon: fire
card:
type: custom:button-card
name: '[[name]]'
icon: 'mdi:[[icon]]'

my_second_template: # This is the name of another template
type: custom:vertical-stack-in-card
cards:
- type: horizontal-stack
cards:
- type: custom:button-card
entity: '[[entity_1]]'
- type: custom:button-card
entity: '[[entity_2]]'
card:
type: custom:vertical-stack-in-card
cards:
- type: horizontal-stack
cards:
- type: custom:button-card
entity: '[[entity_1]]'
- type: custom:button-card
entity: '[[entity_2]]'
```
### Using the card
Expand All @@ -66,7 +84,11 @@ Example which references the previous templates:
template: my_first_template
variables:
- name: Test Button
- icon: fire
- icon: arrow-up
- type: custom:decluttering-card
template: my_first_template
variables: Default Icon Button
- type: custom:decluterring-card
template: my_second_template
Expand Down
17 changes: 11 additions & 6 deletions dist/decluttering-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,25 +183,30 @@ var e = {},
}return null;
},
v = (e, t) => {
if (!e) return t;let n = JSON.stringify(t);return e.forEach(e => {
if (!e && !t.default) return t.card;let n = [];e && (n = e.slice(0)), t.default && (n = n.concat(t.default));let o = JSON.stringify(t.card);return n.forEach(e => {
const t = Object.keys(e)[0],
o = Object.values(e)[0],
r = new RegExp(`\\[\\[${t}\\]\\]`, "gm");n = n.replace(r, o);
}), JSON.parse(n);
n = Object.values(e)[0],
r = new RegExp(`\\[\\[${t}\\]\\]`, "gm");if ("number" == typeof n || "boolean" == typeof n) {
const e = new RegExp(`"\\[\\[${t}\\]\\]"`, "gm");o = o.replace(e, n);
}if ("object" == typeof n) {
const e = new RegExp(`"\\[\\[${t}\\]\\]"`, "gm"),
r = JSON.stringify(n);o = o.replace(e, r);
} else o = o.replace(r, n);
}), JSON.parse(o);
};customElements.define("decluttering-card", class extends HTMLElement {
constructor() {
super(), this.attachShadow({ mode: "open" });
}set hass(e) {
this._card && (this._card.hass = e);
}setConfig(e) {
if (!e.template) throw new Error("Missing template object in your config");const t = g();if (!t.config && !t.config.decluttering_templates) throw new Error("The object decluttering_templates doesn't exist in your main lovelace config.");const n = t.config.decluttering_templates[e.template];if (!n) throw new Error(`The template "${e.template}" doesn't exist in decluttering_templates`);const o = this.shadowRoot;for (; o && o.hasChildNodes();) o.removeChild(o.lastChild);const r = document.createElement("div");r.id = "root", o.appendChild(r);const i = (e, t) => {
if (!e.template) throw new Error("Missing template object in your config");const t = g();if (!t.config && !t.config.decluttering_templates) throw new Error("The object decluttering_templates doesn't exist in your main lovelace config.");const n = t.config.decluttering_templates[e.template];if (!n || !n.card) throw new Error(`The template "${e.template}" doesn't exist in decluttering_templates`);const o = this.shadowRoot;for (; o && o.hasChildNodes();) o.removeChild(o.lastChild);const r = document.createElement("div");r.id = "root", o.appendChild(r);const i = (e, t) => {
const n = document.createElement(e);try {
n.setConfig(t);
} catch (n) {
return console.error(e, n), a(n.message, t);
}return n;
},
a = (e, t) => i("hui-error-card", { type: "error", error: e, config: t });let s = n.type;if (s = s.startsWith("divider") ? "hui-divider-row" : s.startsWith("custom:") ? s.substr("custom:".length) : `hui-${s}-card`, customElements.get(s)) {
a = (e, t) => i("hui-error-card", { type: "error", error: e, config: t });let s = n.card.type;if (s = s.startsWith("divider") ? "hui-divider-row" : s.startsWith("custom:") ? s.substr("custom:".length) : `hui-${s}-card`, customElements.get(s)) {
const t = i(s, v(e.variables, n));r.appendChild(t), this._card = t;
} else {
const e = a(`Custom element doesn't exist: ${s}.`, n);e.style.display = "None";const t = setTimeout(() => {
Expand Down
28 changes: 18 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@
"eslint-plugin-import": "^2.17.2",
"npm": "^6.9.0",
"pre-commit": "^1.2.2",
"prettier": "^1.17.1",
"rollup": "^1.12.2",
"prettier": "^1.18.2",
"rollup": "^1.14.3",
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^4.2.4",
"rollup-plugin-terser": "^4.0.4",
"rollup-plugin-typescript2": "^0.20.1",
"ts-lit-plugin": "^1.0.6",
"typescript": "^3.4.4",
"typescript": "^3.5.1",
"typescript-styled-plugin": "^0.14.0"
},
"dependencies": {
Expand Down
12 changes: 6 additions & 6 deletions src/decluttering-card.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DeclutteringCardConfig } from './types';
import { DeclutteringCardConfig, TemplateConfig } from './types';
import {
HomeAssistant,
getLovelace,
Expand Down Expand Up @@ -28,8 +28,8 @@ class DeclutteringCard extends HTMLElement {
if (!ll.config && !ll.config.decluttering_templates) {
throw new Error('The object decluttering_templates doesn\'t exist in your main lovelace config.');
}
const cardConfig = ll.config.decluttering_templates[config.template]
if (!cardConfig) {
const templateConfig = ll.config.decluttering_templates[config.template] as TemplateConfig;
if (!templateConfig || !templateConfig.card) {
throw new Error(`The template "${config.template}" doesn't exist in decluttering_templates`);
}

Expand Down Expand Up @@ -83,7 +83,7 @@ class DeclutteringCard extends HTMLElement {
}
}

let tag = cardConfig.type;
let tag = templateConfig.card.type;

if (tag.startsWith("divider")) {
tag = `hui-divider-row`;
Expand All @@ -94,14 +94,14 @@ class DeclutteringCard extends HTMLElement {
}

if (customElements.get(tag)) {
const element = _createThing(tag, deepReplace(config.variables, cardConfig));
const element = _createThing(tag, deepReplace(config.variables, templateConfig));
main!.appendChild(element);
this._card = element;
} else {
// If element doesn't exist (yet) create an error
const element = _createError(
`Custom element doesn't exist: ${tag}.`,
cardConfig
templateConfig
);
element.style.display = "None";

Expand Down
31 changes: 24 additions & 7 deletions src/deep-replace.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
import { VariablesConfig } from "./types";
import { VariablesConfig, TemplateConfig } from "./types";

export default (
variables: VariablesConfig[] | undefined,
cardConfig: any,
templateConfig: TemplateConfig,
): any => {
if (!variables) {
return cardConfig;
if (!variables && !templateConfig.default) {
return templateConfig.card;
}
let jsonConfig = JSON.stringify(cardConfig);
variables.forEach(variable => {
let variableArray: VariablesConfig[] = [];
if (variables) {
variableArray = variables.slice(0);
}
if (templateConfig.default) {
variableArray = variableArray.concat(templateConfig.default);
}
let jsonConfig = JSON.stringify(templateConfig.card);
variableArray.forEach(variable => {
const key = Object.keys(variable)[0];
const value = Object.values(variable)[0];
const rxp = new RegExp(`\\[\\[${key}\\]\\]`, "gm");
jsonConfig = jsonConfig.replace(rxp, value);
if (typeof value === 'number' || typeof value === 'boolean') {
const rxp2 = new RegExp(`"\\[\\[${key}\\]\\]"`, "gm");
jsonConfig = jsonConfig.replace(rxp2, (value as unknown as string));
}
if (typeof value === 'object') {
const rxp2 = new RegExp(`"\\[\\[${key}\\]\\]"`, "gm");
const valueString = JSON.stringify(value);
jsonConfig = jsonConfig.replace(rxp2, valueString);
} else {
jsonConfig = jsonConfig.replace(rxp, value);
}
});
return JSON.parse(jsonConfig);
}
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ export interface DeclutteringCardConfig {
export interface VariablesConfig {
[key: string]: any;
}

export interface TemplateConfig {
default: VariablesConfig[];
card: any;
}

0 comments on commit 9778a49

Please sign in to comment.