diff --git a/README.md b/README.md index 86578dc..e8cd42f 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ Filters have the following options, and will match any entity fulfilling **ALL** - `area:` Match entities in given area (e.g. `Kitchen`) - `device:` Match entities belonging to given device (e.g. `Thomas iPhone`) - `attributes:` Map of `attribute: value` pairs to match. +- `last_changed:` Match minutes since last state change (most useful as a comparison, e.g. `last_changed: < 15`) +- `last_updated:` Match minutes since last update Special options: - `options:` Map of options to apply to entity when passed to card. @@ -161,10 +163,10 @@ sort: numeric: ``` -- `method:` **Required** One of `domain`, `entity_id`, `name`, `state` or `attribute` +- `method:` **Required** One of `domain`, `entity_id`, `name`, `state`, `attribute`, `last_changed` or `last_updated` - `reverse:` Set to `true` to reverse the order. Default: `false`. - `ignore_case:` Set to `true` to make the sort case-insensitive. Default: `false`. -- `numeric:` Set to `true` to sort by numeric value. Default: `false`. +- `numeric:` Set to `true` to sort by numeric value. Default: `false` except for `last_changed` and `last_updated` sorting methods. - `attribute:` Attribute to sort by if `method: attribute`. Can be an *object attribute* as above (e.g. `attribute: rgb_color:2`) - `first` and `count` can be used to only display `` entities, starting with the `` (starts with 0). diff --git a/auto-entities.js b/auto-entities.js index 8faa05f..1404fbe 100644 --- a/auto-entities.js +++ b/auto-entities.js @@ -1,2 +1,2 @@ -!function(t){var e={};function i(s){if(e[s])return e[s].exports;var r=e[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)i.d(s,r,function(e){return t[e]}.bind(null,r));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,i){"use strict";i.r(e);const s=customElements.get("home-assistant-main")?Object.getPrototypeOf(customElements.get("home-assistant-main")):Object.getPrototypeOf(customElements.get("hui-view")),r=s.prototype.html;s.prototype.css;function n(){return document.querySelector("home-assistant").hass}const o=n().callWS({type:"config/area_registry/list"}),a=n().callWS({type:"config/device_registry/list"}),c=n().callWS({type:"config/entity_registry/list"});async function u(){return window.cardToolsData=window.cardToolsData||{areas:await o,devices:await a,entities:await c},window.cardToolsData}function l(t){const e=window.cardToolsData;let i=[];if(!t)return i;for(const s of e.devices)s.area_id===t.area_id&&i.push(s);return i}function f(t){const e=window.cardToolsData;let i=[];if(!t)return i;for(const s of e.entities)s.device_id===t.id&&i.push(s.entity_id);return i}function d(t,e){if("string"==typeof e&&"string"==typeof t&&(t.startsWith("/")&&t.endsWith("/")||-1!==t.indexOf("*"))){return t.startsWith("/")||(t=`/^${t=t.replace(/\./g,".").replace(/\*/g,".*")}$/`),new RegExp(t.slice(1,-1)).test(e)}if("string"==typeof t){if(t.startsWith("<="))return parseFloat(e)<=parseFloat(t.substr(2));if(t.startsWith(">="))return parseFloat(e)>=parseFloat(t.substr(2));if(t.startsWith("<"))return parseFloat(e)"))return parseFloat(e)>parseFloat(t.substr(1));if(t.startsWith("!"))return parseFloat(e)!=parseFloat(t.substr(1));if(t.startsWith("="))return parseFloat(e)==parseFloat(t.substr(1))}return t===e}function h(t,e){return function(i){const s="string"==typeof i?t.states[i]:t.states[i.entity];if(!i)return!1;for(const[r,n]of Object.entries(e))switch(r.split(" ")[0]){case"options":case"sort":break;case"domain":if(!d(n,s.entity_id.split(".")[0]))return!1;break;case"entity_id":if(!d(n,s.entity_id))return!1;break;case"state":if(!d(n,s.state))return!1;break;case"name":if(!s.attributes.friendly_name||!d(n,s.attributes.friendly_name))return!1;break;case"group":if(!(n.startsWith("group.")&&t.states[n]&&t.states[n].attributes.entity_id&&t.states[n].attributes.entity_id.includes(s.entity_id)))return!1;break;case"attributes":for(const[t,e]of Object.entries(n)){let i=t.split(" ")[0],r=s.attributes;for(;i&&r;){let t;[t,i]=i.split(":"),r=r[t]}if(void 0===r||e&&!d(e,r))return!1}break;case"not":if(h(t,n)(i))return!1;break;case"device":if(!window.cardToolsData||!window.cardToolsData.devices)return!1;let e=!1;for(const t of window.cardToolsData.devices)d(n,t.name)&&f(t).includes(s.entity_id)&&(e=!0);if(!e)return!1;break;case"area":if(!window.cardToolsData||!window.cardToolsData.areas)return!1;let r=!1;for(const t of window.cardToolsData.areas)d(n,t.name)&&l(t).flatMap(f).includes(s.entity_id)&&(r=!0);if(!r)return!1;break;default:return!1}return!0}}function p(t,e){return"string"==typeof e&&(e={method:e}),function(i,s){const r="string"==typeof i?t.states[i]:t.states[i.entity],n="string"==typeof s?t.states[s]:t.states[s.entity];if(void 0===r||void 0===n)return 0;const[o,a]=e.reverse?[-1,1]:[1,-1];function c(t,i){return e.ignore_case&&t.toLowerCase&&(t=t.toLowerCase()),e.ignore_case&&i.toLowerCase&&(i=i.toLowerCase()),e.numeric&&(isNaN(parseFloat(t))&&isNaN(parseFloat(i))||(t=isNaN(parseFloat(t))?void 0:parseFloat(t),i=isNaN(parseFloat(i))?void 0:parseFloat(i))),void 0===t&&void 0===i?0:void 0===t?o:void 0===i?a:ti?o:0}switch(e.method){case"domain":return c(r.entity_id.split(".")[0],n.entity_id.split(".")[0]);case"entity_id":return c(r.entity_id,n.entity_id);case"friendly_name":case"name":return c(r.attributes.friendly_name||r.entity_id.split(".")[1],n.attributes.friendly_name||n.entity_id.split(".")[1]);case"state":return c(r.state,n.state);case"attribute":let t=r.attributes,i=n.attributes,s=e.attribute;for(;s;){let e;if([e,s]=s.split(":"),t=t[e],i=i[e],void 0===t&&void 0===i)return 0;if(void 0===t)return o;if(void 0===i)return a}return c(t,i);default:return 0}}}function y(t,e,i=null){if((t=new Event(t,{bubbles:!0,cancelable:!1,composed:!0})).detail=e||{},i)i.dispatchEvent(t);else{var s=document.querySelector("home-assistant");(s=(s=(s=(s=(s=(s=(s=(s=(s=(s=(s=s&&s.shadowRoot)&&s.querySelector("home-assistant-main"))&&s.shadowRoot)&&s.querySelector("app-drawer-layout partial-panel-resolver"))&&s.shadowRoot||s)&&s.querySelector("ha-panel-lovelace"))&&s.shadowRoot)&&s.querySelector("hui-root"))&&s.shadowRoot)&&s.querySelector("ha-app-layout #view"))&&s.firstElementChild)&&s.dispatchEvent(t)}}u();const g="custom:";function _(t,e){const i=document.createElement("hui-error-card");return i.setConfig({type:"error",error:t,origConfig:e}),i}function m(t,e){if(!e||"object"!=typeof e||!e.type)return _(`No ${t} type configured`,e);let i=e.type;if(i=i.startsWith(g)?i.substr(g.length):`hui-${i}-${t}`,customElements.get(i))return function(t,e){const i=document.createElement(t);try{i.setConfig(e)}catch(t){return _(t,e)}return i}(i,e);const s=_(`Custom element doesn't exist: ${i}.`,e);s.style.display="None";const r=setTimeout(()=>{s.style.display=""},2e3);return customElements.whenDefined(i).then(()=>{clearTimeout(r),y("ll-rebuild",{},s)}),s}customElements.define("auto-entities",class extends s{static get properties(){return{hass:{}}}setConfig(t){if(!t||!t.card)throw new Error("Invalid configuration");this._config?(this._config=t,this.hass=this.hass):(this._config=t,this.hass=n(),this._getEntities(),this.cardConfig={entities:this.entities,...t.card},this.card=function(t){return m("card",t)}(this.cardConfig)),u().then(()=>this._getEntities())}_getEntities(){let t=[];if(this._config.entities&&(t=t.concat(this._config.entities).map(t=>"string"==typeof t?{entity:t}:t)),!this.hass||!this._config.filter)return t;if(this._config.filter.include){const e=Object.keys(this.hass.states).map(t=>new Object({entity:t}));for(const i of this._config.filter.include){if(void 0!==i.type){t.push(i);continue}let s=e.filter(h(this.hass,i)).map(t=>new Object({...t,...i.options}));void 0!==i.sort&&(s=s.sort(p(this.hass,i.sort))),t=t.concat(s)}}if(this._config.filter.exclude)for(const e of this._config.filter.exclude)t=t.filter(t=>"string"!=typeof t&&void 0===t.entity||!h(this.hass,e)(t));if(this._config.sort&&(t=t.sort(p(this.hass,this._config.sort)),this._config.sort.count)){const e=this._config.sort.first||0;t=t.slice(e,e+this._config.sort.count)}if(this._config.unique){function e(t,i){return typeof t==typeof i&&("object"!=typeof t?t===i:!Object.keys(t).some(t=>!Object.keys(i).includes(t))&&Object.keys(t).every(s=>e(t[s],i[s])))}let i=[];for(const s of t)i.some(t=>e(t,s))||i.push(s);t=i}this.entities=t}set entities(t){(function(t,e){if(t===e)return!0;if(null==t||null==e)return!1;if(t.length!=e.length)return!1;for(var i=0;ithis._getEntities(),0))}createRenderRoot(){return this}render(){return r` - ${this.card}`}getCardSize(){let t=0;return this.card&&this.card.getCardSize&&(t=this.card.getCardSize()),1===t&&this.entities.length&&(t=this.entities.length),0===t&&this._config.filter&&this._config.filter.include&&(t=Object.keys(this._config.filter.include).length),t||1}}),y("ll-rebuild",{})}]); \ No newline at end of file +!function(t){var e={};function i(s){if(e[s])return e[s].exports;var r=e[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)i.d(s,r,function(e){return t[e]}.bind(null,r));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,i){"use strict";i.r(e);const s=customElements.get("home-assistant-main")?Object.getPrototypeOf(customElements.get("home-assistant-main")):Object.getPrototypeOf(customElements.get("hui-view")),r=s.prototype.html;s.prototype.css;function n(){return document.querySelector("home-assistant").hass}const o=n().callWS({type:"config/area_registry/list"}),a=n().callWS({type:"config/device_registry/list"}),c=n().callWS({type:"config/entity_registry/list"});async function u(){return window.cardToolsData=window.cardToolsData||{areas:await o,devices:await a,entities:await c},window.cardToolsData}function l(t){const e=window.cardToolsData;let i=[];if(!t)return i;for(const s of e.devices)s.area_id===t.area_id&&i.push(s);return i}function f(t){const e=window.cardToolsData;let i=[];if(!t)return i;for(const s of e.entities)s.device_id===t.id&&i.push(s.entity_id);return i}function d(t,e){if("string"==typeof e&&"string"==typeof t&&(t.startsWith("/")&&t.endsWith("/")||-1!==t.indexOf("*"))){return t.startsWith("/")||(t=`/^${t=t.replace(/\./g,".").replace(/\*/g,".*")}$/`),new RegExp(t.slice(1,-1)).test(e)}if("string"==typeof t){if(t.startsWith("<="))return parseFloat(e)<=parseFloat(t.substr(2));if(t.startsWith(">="))return parseFloat(e)>=parseFloat(t.substr(2));if(t.startsWith("<"))return parseFloat(e)"))return parseFloat(e)>parseFloat(t.substr(1));if(t.startsWith("!"))return parseFloat(e)!=parseFloat(t.substr(1));if(t.startsWith("="))return parseFloat(e)==parseFloat(t.substr(1))}return t===e}function h(t,e){return function(i){const s="string"==typeof i?t.states[i]:t.states[i.entity];if(!i)return!1;for(const[r,n]of Object.entries(e))switch(r.split(" ")[0]){case"options":case"sort":break;case"domain":if(!d(n,s.entity_id.split(".")[0]))return!1;break;case"entity_id":if(!d(n,s.entity_id))return!1;break;case"state":if(!d(n,s.state))return!1;break;case"name":if(!s.attributes.friendly_name||!d(n,s.attributes.friendly_name))return!1;break;case"group":if(!(n.startsWith("group.")&&t.states[n]&&t.states[n].attributes.entity_id&&t.states[n].attributes.entity_id.includes(s.entity_id)))return!1;break;case"attributes":for(const[t,e]of Object.entries(n)){let i=t.split(" ")[0],r=s.attributes;for(;i&&r;){let t;[t,i]=i.split(":"),r=r[t]}if(void 0===r||e&&!d(e,r))return!1}break;case"not":if(h(t,n)(i))return!1;break;case"device":if(!window.cardToolsData||!window.cardToolsData.devices)return!1;let e=!1;for(const t of window.cardToolsData.devices)d(n,t.name)&&f(t).includes(s.entity_id)&&(e=!0);if(!e)return!1;break;case"area":if(!window.cardToolsData||!window.cardToolsData.areas)return!1;let r=!1;for(const t of window.cardToolsData.areas)d(n,t.name)&&l(t).flatMap(f).includes(s.entity_id)&&(r=!0);if(!r)return!1;break;case"last_changed":if(!d(n,((new Date).getTime()-new Date(s.last_changed).getTime())/6e4))return!1;break;case"last_updated":if(!d(n,((new Date).getTime()-new Date(s.last_updated).getTime())/6e4))return!1;break;default:return!1}return!0}}function p(t,e){return"string"==typeof e&&(e={method:e}),function(i,s){const r="string"==typeof i?t.states[i]:t.states[i.entity],n="string"==typeof s?t.states[s]:t.states[s.entity];if(void 0===r||void 0===n)return 0;const[o,a]=e.reverse?[-1,1]:[1,-1];function c(t,i){return e.ignore_case&&t.toLowerCase&&(t=t.toLowerCase()),e.ignore_case&&i.toLowerCase&&(i=i.toLowerCase()),e.numeric&&(isNaN(parseFloat(t))&&isNaN(parseFloat(i))||(t=isNaN(parseFloat(t))?void 0:parseFloat(t),i=isNaN(parseFloat(i))?void 0:parseFloat(i))),void 0===t&&void 0===i?0:void 0===t?o:void 0===i?a:ti?o:0}switch(e.method){case"domain":return c(r.entity_id.split(".")[0],n.entity_id.split(".")[0]);case"entity_id":return c(r.entity_id,n.entity_id);case"friendly_name":case"name":return c(r.attributes.friendly_name||r.entity_id.split(".")[1],n.attributes.friendly_name||n.entity_id.split(".")[1]);case"state":return c(r.state,n.state);case"attribute":let t=r.attributes,i=n.attributes,s=e.attribute;for(;s;){let e;if([e,s]=s.split(":"),t=t[e],i=i[e],void 0===t&&void 0===i)return 0;if(void 0===t)return o;if(void 0===i)return a}return c(t,i);case"last_changed":case"last_updated":return e.numeric=!0,c(new Date(n.last_changed).getTime(),new Date(r.last_changed).getTime());default:return 0}}}function g(t,e,i=null){if((t=new Event(t,{bubbles:!0,cancelable:!1,composed:!0})).detail=e||{},i)i.dispatchEvent(t);else{var s=document.querySelector("home-assistant");(s=(s=(s=(s=(s=(s=(s=(s=(s=(s=(s=s&&s.shadowRoot)&&s.querySelector("home-assistant-main"))&&s.shadowRoot)&&s.querySelector("app-drawer-layout partial-panel-resolver"))&&s.shadowRoot||s)&&s.querySelector("ha-panel-lovelace"))&&s.shadowRoot)&&s.querySelector("hui-root"))&&s.shadowRoot)&&s.querySelector("ha-app-layout #view"))&&s.firstElementChild)&&s.dispatchEvent(t)}}u();const y="custom:";function _(t,e){const i=document.createElement("hui-error-card");return i.setConfig({type:"error",error:t,origConfig:e}),i}function m(t,e){if(!e||"object"!=typeof e||!e.type)return _(`No ${t} type configured`,e);let i=e.type;if(i=i.startsWith(y)?i.substr(y.length):`hui-${i}-${t}`,customElements.get(i))return function(t,e){const i=document.createElement(t);try{i.setConfig(e)}catch(t){return _(t,e)}return i}(i,e);const s=_(`Custom element doesn't exist: ${i}.`,e);s.style.display="None";const r=setTimeout(()=>{s.style.display=""},2e3);return customElements.whenDefined(i).then(()=>{clearTimeout(r),g("ll-rebuild",{},s)}),s}customElements.define("auto-entities",class extends s{static get properties(){return{hass:{}}}setConfig(t){if(!t||!t.card)throw new Error("Invalid configuration");this._config?(this._config=t,this.hass=this.hass):(this._config=t,this.hass=n(),this._getEntities(),this.cardConfig={entities:this.entities,...t.card},this.card=function(t){return m("card",t)}(this.cardConfig)),u().then(()=>this._getEntities())}_getEntities(){let t=[];if(this._config.entities&&(t=t.concat(this._config.entities).map(t=>"string"==typeof t?{entity:t}:t)),!this.hass||!this._config.filter)return t;if(this._config.filter.include){const e=Object.keys(this.hass.states).map(t=>new Object({entity:t}));for(const i of this._config.filter.include){if(void 0!==i.type){t.push(i);continue}let s=e.filter(h(this.hass,i)).map(t=>new Object({...t,...i.options}));void 0!==i.sort&&(s=s.sort(p(this.hass,i.sort))),t=t.concat(s)}}if(this._config.filter.exclude)for(const e of this._config.filter.exclude)t=t.filter(t=>"string"!=typeof t&&void 0===t.entity||!h(this.hass,e)(t));if(this._config.sort&&(t=t.sort(p(this.hass,this._config.sort)),this._config.sort.count)){const e=this._config.sort.first||0;t=t.slice(e,e+this._config.sort.count)}if(this._config.unique){function e(t,i){return typeof t==typeof i&&("object"!=typeof t?t===i:!Object.keys(t).some(t=>!Object.keys(i).includes(t))&&Object.keys(t).every(s=>e(t[s],i[s])))}let i=[];for(const s of t)i.some(t=>e(t,s))||i.push(s);t=i}this.entities=t}set entities(t){(function(t,e){if(t===e)return!0;if(null==t||null==e)return!1;if(t.length!=e.length)return!1;for(var i=0;ithis._getEntities(),0))}createRenderRoot(){return this}render(){return r` + ${this.card}`}getCardSize(){let t=0;return this.card&&this.card.getCardSize&&(t=this.card.getCardSize()),1===t&&this.entities.length&&(t=this.entities.length),0===t&&this._config.filter&&this._config.filter.include&&(t=Object.keys(this._config.filter.include).length),t||1}}),g("ll-rebuild",{})}]); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6ba115a..0ccc9e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -193,9 +193,9 @@ "dev": true }, "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", "dev": true }, "ajv": { @@ -424,9 +424,9 @@ "dev": true }, "bluebird": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", - "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, "bn.js": { @@ -552,9 +552,9 @@ } }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -627,7 +627,7 @@ "dev": true }, "card-tools": { - "version": "github:thomasloven/lovelace-card-tools#605caa906c46340599614aaf9d4e934aabc19b15", + "version": "github:thomasloven/lovelace-card-tools#8790289006f110d7aefb8cf7ab1bacdad3c620b0", "from": "github:thomasloven/lovelace-card-tools" }, "chalk": { @@ -968,9 +968,9 @@ } }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -1013,9 +1013,9 @@ } }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -1949,9 +1949,9 @@ "dev": true }, "glob": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", - "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -3233,9 +3233,9 @@ "dev": true }, "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, "set-blocking": { @@ -3589,9 +3589,9 @@ "dev": true }, "terser": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.9.tgz", - "integrity": "sha512-NFGMpHjlzmyOtPL+fDw3G7+6Ueh/sz4mkaUYa4lJCxOPTNzd0Uj0aZJOmsDYoSQyfuVoWDMSWTPU3huyOm2zdA==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz", + "integrity": "sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ==", "dev": true, "requires": { "commander": "^2.20.0", @@ -3608,16 +3608,16 @@ } }, "terser-webpack-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", - "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.2.tgz", + "integrity": "sha512-fdEb91kR2l+BVgES77N/NTXWZlpX6vX+pYPjnX5grcDYBF2CMnzJiXX4NNlna4l04lvCW39lZ+O/jSvUhHH/ew==", "dev": true, "requires": { "cacache": "^12.0.2", "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "serialize-javascript": "^2.1.1", "source-map": "^0.6.1", "terser": "^4.1.2", "webpack-sources": "^1.4.0", diff --git a/src/filter.js b/src/filter.js index ff0643c..917a94e 100644 --- a/src/filter.js +++ b/src/filter.js @@ -120,6 +120,25 @@ export function entity_filter(hass, filter) { return false; break; + case 'last_changed': + { + const now = new Date().getTime(); + const changed = new Date(entity.last_changed).getTime(); + if(!match(value, (now-changed)/60000)) + return false; + break; + } + + case 'last_updated': + { + const now = new Date().getTime(); + const updated = new Date(entity.last_updated).getTime(); + + if(!match(value, (now-updated)/60000)) + return false; + break; + } + default: return false; } diff --git a/src/sort.js b/src/sort.js index 06e6e15..64cb564 100644 --- a/src/sort.js +++ b/src/sort.js @@ -65,6 +65,19 @@ export function entity_sorter(hass, method) { if(_b === undefined) return gt; } return compare(_a, _b); + case "last_changed": + method.numeric = true; + // Note A and B are swapped because you'd most likely want to sort by most recently changed first + return compare( + new Date(entityB.last_changed).getTime(), + new Date(entityA.last_changed).getTime() + ); + case "last_updated": + method.numeric=true; + return compare( + new Date(entityB.last_changed).getTime(), + new Date(entityA.last_changed).getTime() + ); default: return 0; }