mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-05 14:19:04 +00:00
@@ -1,125 +1,125 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"fingerprint": "b40916c4f480b150ad894b2e5bea3a62b54827233bab2fc96ed6866eedf04f7c",
|
||||
"fingerprint": "3d6cccf5714d17cd4ec8f516229a0621f28ee00b65b7d84fb542ddc353bc7f5f",
|
||||
"entry": "houseplan-card.js",
|
||||
"initialViewFiles": [
|
||||
"houseplan-assets/houseplan-card-B5mDyjuC.js",
|
||||
"houseplan-assets/houseplan-card-wtxKVHkp.js",
|
||||
"houseplan-card.js"
|
||||
],
|
||||
"initialViewGzipBytes": 277319,
|
||||
"initialViewGzipBytes": 277948,
|
||||
"lazyFiles": [
|
||||
"houseplan-assets/backdrop-pick-DFFLwJ_d.js",
|
||||
"houseplan-assets/de-FazIOsg8.js",
|
||||
"houseplan-assets/editor-CcxmUFV-.js",
|
||||
"houseplan-assets/fr-CFpxbPTS.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-CisKVaG7.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-eqCB-Ax0.js"
|
||||
"houseplan-assets/backdrop-pick-TMl_2iBT.js",
|
||||
"houseplan-assets/de-B775TcPH.js",
|
||||
"houseplan-assets/editor-CIkons5x.js",
|
||||
"houseplan-assets/fr-Cml_YfSz.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-CM78ZHZU.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-BP9ODa6H.js"
|
||||
],
|
||||
"lazyGzipBytes": 191754,
|
||||
"lazyGzipBytes": 192277,
|
||||
"lazyEditorFiles": [
|
||||
"houseplan-assets/backdrop-pick-DFFLwJ_d.js",
|
||||
"houseplan-assets/editor-CcxmUFV-.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-CisKVaG7.js"
|
||||
"houseplan-assets/backdrop-pick-TMl_2iBT.js",
|
||||
"houseplan-assets/editor-CIkons5x.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-CM78ZHZU.js"
|
||||
],
|
||||
"lazyEditorGzipBytes": 139917,
|
||||
"lazyEditorGzipBytes": 140230,
|
||||
"lazyOnboardingFiles": [
|
||||
"houseplan-assets/backdrop-pick-DFFLwJ_d.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-eqCB-Ax0.js"
|
||||
"houseplan-assets/backdrop-pick-TMl_2iBT.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-BP9ODa6H.js"
|
||||
],
|
||||
"lazyOnboardingGzipBytes": 9451,
|
||||
"lazyLocaleFiles": [
|
||||
"houseplan-assets/de-FazIOsg8.js",
|
||||
"houseplan-assets/fr-CFpxbPTS.js"
|
||||
"houseplan-assets/de-B775TcPH.js",
|
||||
"houseplan-assets/fr-Cml_YfSz.js"
|
||||
],
|
||||
"lazyLocaleGzipBytes": 45342,
|
||||
"lazyLocaleGzipBytes": 45551,
|
||||
"files": [
|
||||
{
|
||||
"path": "houseplan-assets/backdrop-pick-DFFLwJ_d.js",
|
||||
"sha256": "f7bdc0ee64684220a751eadda1397edb922b9c785993f5bce1d6b8273c619f21",
|
||||
"path": "houseplan-assets/backdrop-pick-TMl_2iBT.js",
|
||||
"sha256": "2527114d8c2e58532848ac449cb7ea6927b86f5883bad84c649dc740c3872eea",
|
||||
"rawBytes": 6967,
|
||||
"gzipBytes": 2956,
|
||||
"gzipBytes": 2955,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-B5mDyjuC.js"
|
||||
"houseplan-assets/houseplan-card-wtxKVHkp.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/de-FazIOsg8.js",
|
||||
"sha256": "50ca05e9607b7f597cd20b1a1fce1f92fd9bb07a4cb0db4e86c3c921053c9e89",
|
||||
"rawBytes": 75090,
|
||||
"gzipBytes": 22886,
|
||||
"path": "houseplan-assets/de-B775TcPH.js",
|
||||
"sha256": "287e8f70aad3d82cfe292f204e5fe58eef3738631ee3be7078de6fd88c5fde1f",
|
||||
"rawBytes": 75572,
|
||||
"gzipBytes": 22996,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/editor-CcxmUFV-.js",
|
||||
"sha256": "27077f8f6ecd61eea9e8405099b91974f423b8f7a53eef9ae8cf066803c475ef",
|
||||
"path": "houseplan-assets/editor-CIkons5x.js",
|
||||
"sha256": "ecaeb979d94de7e54f08b090355bf757b64a34932cddc9442f023804565ff56c",
|
||||
"rawBytes": 3831,
|
||||
"gzipBytes": 1583,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-B5mDyjuC.js"
|
||||
"houseplan-assets/houseplan-card-wtxKVHkp.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/fr-CFpxbPTS.js",
|
||||
"sha256": "ce2f711435309dac25e14c0024eea6da2c443949728a0fad1b5062851fcc26d6",
|
||||
"rawBytes": 77225,
|
||||
"gzipBytes": 22456,
|
||||
"path": "houseplan-assets/fr-Cml_YfSz.js",
|
||||
"sha256": "eeaa5abe3d199602537bab6f7f40075ceab398a25515685dd5e465d3ea9c9b51",
|
||||
"rawBytes": 77710,
|
||||
"gzipBytes": 22555,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-card-B5mDyjuC.js",
|
||||
"sha256": "d2f3c9df28d6acc99e4c7960c6f3cf1d5b516b42c3b10102429ba263532f569a",
|
||||
"rawBytes": 976343,
|
||||
"gzipBytes": 276523,
|
||||
"path": "houseplan-assets/houseplan-card-wtxKVHkp.js",
|
||||
"sha256": "796b979c90d4791cbdadb991c407dbd7d6768880b5a856cc1b7ec19f1e317c7a",
|
||||
"rawBytes": 979430,
|
||||
"gzipBytes": 277152,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": [
|
||||
"houseplan-assets/de-FazIOsg8.js",
|
||||
"houseplan-assets/editor-CcxmUFV-.js",
|
||||
"houseplan-assets/fr-CFpxbPTS.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-CisKVaG7.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-eqCB-Ax0.js"
|
||||
"houseplan-assets/de-B775TcPH.js",
|
||||
"houseplan-assets/editor-CIkons5x.js",
|
||||
"houseplan-assets/fr-Cml_YfSz.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-CM78ZHZU.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-BP9ODa6H.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-CisKVaG7.js",
|
||||
"sha256": "d99951a97b78d46d05501d0e2e3f5a9cd73a1088a5e9a382d8899903b040bb97",
|
||||
"rawBytes": 524211,
|
||||
"gzipBytes": 135378,
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-CM78ZHZU.js",
|
||||
"sha256": "e439a389b8556a98b6ee0641cbda9a47978b2a10e4279d6663848ec97005771e",
|
||||
"rawBytes": 526486,
|
||||
"gzipBytes": 135692,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-DFFLwJ_d.js",
|
||||
"houseplan-assets/houseplan-card-B5mDyjuC.js"
|
||||
"houseplan-assets/backdrop-pick-TMl_2iBT.js",
|
||||
"houseplan-assets/houseplan-card-wtxKVHkp.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-eqCB-Ax0.js",
|
||||
"sha256": "aba9dab2a60c386b0638636d2ebcc683bd44a56fea5ce594fda9456ee171371d",
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-BP9ODa6H.js",
|
||||
"sha256": "d49d4e5b08de22682d8c548ffa90bd73175fc1d069eca75f98905b9a804cafb0",
|
||||
"rawBytes": 26195,
|
||||
"gzipBytes": 6495,
|
||||
"gzipBytes": 6496,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-DFFLwJ_d.js",
|
||||
"houseplan-assets/houseplan-card-B5mDyjuC.js"
|
||||
"houseplan-assets/backdrop-pick-TMl_2iBT.js",
|
||||
"houseplan-assets/houseplan-card-wtxKVHkp.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-card.js",
|
||||
"sha256": "376b5951ff76686ebc299f63f2a21bf56f331e1027c52eabd487664fc86cd45e",
|
||||
"sha256": "785c3ec627b80c3cda8831faaa08f31c7021ad47b0be372d3326ce5456d7d087",
|
||||
"rawBytes": 1183,
|
||||
"gzipBytes": 796,
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-B5mDyjuC.js"
|
||||
"houseplan-assets/houseplan-card-wtxKVHkp.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5
-5
@@ -1,14 +1,14 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="b40916c4f480b150ad894b2e5bea3a62b54827233bab2fc96ed6866eedf04f7c";import{c as e,l as o,t,c_ as s,A as a,c$ as i,d0 as l,d1 as n,E as r,b as c}from"./houseplan-card-B5mDyjuC.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="3d6cccf5714d17cd4ec8f516229a0621f28ee00b65b7d84fb542ddc353bc7f5f";import{c as e,l as o,t,c$ as s,A as a,d0 as i,d1 as l,d2 as n,E as r,b as c}from"./houseplan-card-wtxKVHkp.js";class f extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,f={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},h=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this._formData}
|
||||
.schema=${e}
|
||||
.computeLabel=${e=>h[e.name]||e.name}
|
||||
.computeLabel=${e=>f[e.name]||e.name}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>`;return c`
|
||||
${d(f.slice(0,3))}
|
||||
${d(h.slice(0,3))}
|
||||
${_?c`<div class="default-floor-error" role="alert"
|
||||
style="color:var(--error-color,#db4437);margin:-4px 0 12px;overflow-wrap:anywhere">
|
||||
${t(s,"editor.default_floor_missing",{id:_})}
|
||||
</div>`:a}
|
||||
${d(f.slice(3))}
|
||||
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}h.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",h);
|
||||
${d(h.slice(3))}
|
||||
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}f.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",f);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+43
-43
File diff suppressed because one or more lines are too long
+153
-126
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="b40916c4f480b150ad894b2e5bea3a62b54827233bab2fc96ed6866eedf04f7c";import{bT as t,bU as s,bV as e,bW as o,aq as a,bX as l,c0 as i,bY as h,bZ as c,b_ as n,b$ as r,A as p,b as _,cS as d,ap as u,ar as g,cT as m}from"./houseplan-card-B5mDyjuC.js";import{i as b,c as $,e as v,r as f,a as y,b as w,s as D,t as S}from"./backdrop-pick-DFFLwJ_d.js";const k=1e3,C=t=>{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},M="b40916c4f480b150ad894b2e5bea3a62b54827233bab2fc96ed6866eedf04f7c";class F{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_openSpaceDialog(p,_){if(!this.host._serverStorage||!this.host._serverCfg)return void this.host._showToast(this.host._t("toast.integration_missing"));if("edit"===p){const i=this.host._serverCfg.spaces.find(t=>t.id===_);if(!i)return;const h=t(i),c=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?s(i.settings.custom_fill):null,n="none"===h.fill?{...c||e,a:0}:c;return void(this.host._spaceDialog={mode:p,spaceId:_,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:h.showBorders,showNames:h.showNames,zeroWallStyle:l(i),displayTouched:!0,hideDecor:h.hideDecor,hideOpenings:h.hideOpenings,roomColor:h.color,roomOpacity:h.opacity,fillMode:"none"===h.fill?"custom":h.fill,customFill:n,glowEnabled:h.glow,bgColor:h.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:a({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:h.tempMin,tempMax:h.tempMax,showLqi:h.showLqi??this.host._config?.show_signal??!0,cardFontScale:h.cardFontScale,labelTemp:h.labelTemp,labelHum:h.labelHum,labelLqi:h.labelLqi,labelLight:h.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:o(Number(i.cell_cm)>0?Number(i.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1})}const d=i(this.host._imperial);this.host._spaceDialog={mode:p,title:"",planUrl:null,planFile:null,...b(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:r,roomOpacity:n,fillMode:"custom",customFill:{...e,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:c,tempMax:h,showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:d,cellCmInput:o(d,this.host._imperial),cellCmTouched:!1,busy:!1}}async _pickPlanFile(t){const s=t.target,e=s.files?.[0];if(!e||!this.host._spaceDialog)return;s.value="";const o=await $(e);if("reject"===o.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===o.kind)return void(this.host._backdropGuard=o.state);const a=await v(e,o.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:a})}_renderBackdropGuard(){return f(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??p}_useServerPlan(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let s=0;s<40;s++){const s=this.host._display(t);if(s){const e=await new Promise(t=>{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:0),e.onerror=()=>t(0),e.src=s}),o=this.host._spaceDialog;return o&&o.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...o,savedAspect:e},e):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){if(confirm(this.host._t("confirm.delete_plan",{name:t})))try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const s=this.host._spaceDialog;s?.saved&&(this.host._spaceDialog={...s,saved:s.saved.filter(s=>s.name!==t)})}catch(t){this.host._showToast(this.host._t("toast.plan_delete_failed",{err:this.host._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return _`<div class="savedplans muted">${this.host._t("space.loading")}</div>`;const s=t.saved||[];if(!s.length)return _`<div class="savedplans muted">${this.host._t("space.no_saved")}</div>`;return _`<div class="savedplans">
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="3d6cccf5714d17cd4ec8f516229a0621f28ee00b65b7d84fb542ddc353bc7f5f";import{bT as t,bU as s,bV as e,bW as o,aq as a,bX as l,c0 as i,bY as h,bZ as c,b_ as n,b$ as r,A as p,b as _,cT as d,ap as u,ar as g,cU as m}from"./houseplan-card-wtxKVHkp.js";import{i as b,c as $,e as v,r as f,a as y,b as w,s as D,t as S}from"./backdrop-pick-TMl_2iBT.js";const k=1e3,C=t=>{if(!t.trim())return null;const s=Number(t.replace(",","."));return Number.isFinite(s)?s:null},M="3d6cccf5714d17cd4ec8f516229a0621f28ee00b65b7d84fb542ddc353bc7f5f";class F{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_openSpaceDialog(p,_){if(!this.host._serverStorage||!this.host._serverCfg)return void this.host._showToast(this.host._t("toast.integration_missing"));if("edit"===p){const i=this.host._serverCfg.spaces.find(t=>t.id===_);if(!i)return;const h=t(i),c=i.settings?.custom_fill&&"object"==typeof i.settings.custom_fill?s(i.settings.custom_fill):null,n="none"===h.fill?{...c||e,a:0}:c;return void(this.host._spaceDialog={mode:p,spaceId:_,title:i.title,planUrl:i.plan_url||null,planFile:null,source:i.plan_url?"file":"draw",showBorders:h.showBorders,showNames:h.showNames,zeroWallStyle:l(i),displayTouched:!0,hideDecor:h.hideDecor,hideOpenings:h.hideOpenings,roomColor:h.color,roomOpacity:h.opacity,fillMode:"none"===h.fill?"custom":h.fill,customFill:n,glowEnabled:h.glow,bgColor:h.bgColor,bgMode:"static"===i.settings?.bg_mode||"daynight"===i.settings?.bg_mode?i.settings.bg_mode:null,northDeg:a({},i.settings),sunRays:"boolean"==typeof i.settings?.sun_rays?i.settings.sun_rays:null,tempMin:h.tempMin,tempMax:h.tempMax,showLqi:h.showLqi??this.host._config?.show_signal??!0,cardFontScale:h.cardFontScale,labelTemp:h.labelTemp,labelHum:h.labelHum,labelLqi:h.labelLqi,labelLight:h.labelLight,cellCm:Number(i.cell_cm)>0?Number(i.cell_cm):5,cellCmInput:o(Number(i.cell_cm)>0?Number(i.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1})}const d=i(this.host._imperial);this.host._spaceDialog={mode:p,title:"",planUrl:null,planFile:null,...b(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:r,roomOpacity:n,fillMode:"custom",customFill:{...e,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:c,tempMax:h,showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:d,cellCmInput:o(d,this.host._imperial),cellCmTouched:!1,busy:!1}}async _pickPlanFile(t){const s=t.target,e=s.files?.[0];if(!e||!this.host._spaceDialog)return;s.value="";const o=await $(e);if("reject"===o.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===o.kind)return void(this.host._backdropGuard=o.state);const a=await v(e,o.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:a})}_renderBackdropGuard(){return f(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??p}_useServerPlan(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let s=0;s<40;s++){const s=this.host._display(t);if(s){const e=await new Promise(t=>{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:0),e.onerror=()=>t(0),e.src=s}),o=this.host._spaceDialog;return o&&o.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...o,savedAspect:e},e):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){if(confirm(this.host._t("confirm.delete_plan",{name:t})))try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const s=this.host._spaceDialog;s?.saved&&(this.host._spaceDialog={...s,saved:s.saved.filter(s=>s.name!==t)})}catch(t){this.host._showToast(this.host._t("toast.plan_delete_failed",{err:this.host._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return _`<div class="savedplans muted">${this.host._t("space.loading")}</div>`;const s=t.saved||[];if(!s.length)return _`<div class="savedplans muted">${this.host._t("space.no_saved")}</div>`;return _`<div class="savedplans">
|
||||
${s.map(s=>{return _`
|
||||
<div class="savedplan ${s.url===t.planUrl?"cur":""}">
|
||||
<img src=${this.host._display(s.url)} alt="" loading="lazy" decoding="async" />
|
||||
@@ -1 +1 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="b40916c4f480b150ad894b2e5bea3a62b54827233bab2fc96ed6866eedf04f7c";try{await import("./houseplan-assets/houseplan-card-B5mDyjuC.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="3d6cccf5714d17cd4ec8f516229a0621f28ee00b65b7d84fb542ddc353bc7f5f";try{await import("./houseplan-assets/houseplan-card-wtxKVHkp.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
|
||||
@@ -510,6 +510,13 @@ def create_export(
|
||||
badge["enabled"] = False
|
||||
badge["source"] = None
|
||||
dropped_marker_links += 1
|
||||
value_source = marker.get("value_source")
|
||||
ref = value_source.get("ref") if isinstance(value_source, dict) \
|
||||
and value_source.get("kind") == "derived_marker_state" else None
|
||||
if isinstance(ref, str) and ref.startswith("marker:") \
|
||||
and ref[len("marker:"):] not in selected_ids:
|
||||
marker.pop("value_source", None)
|
||||
dropped_marker_links += 1
|
||||
config = {
|
||||
"spaces": [_json_copy(space)],
|
||||
"markers": _json_copy(selected_markers),
|
||||
@@ -699,7 +706,7 @@ def _transfer_dropped_marker_links(document: dict[str, Any]) -> int:
|
||||
if not isinstance(transfer, dict):
|
||||
raise ImportFailure("invalid_format", "Transfer metadata must be an object")
|
||||
value = transfer.get("dropped_marker_links", 0)
|
||||
maximum = MAX_MARKERS * (MAX_CONTROLS + 1)
|
||||
maximum = MAX_MARKERS * (MAX_CONTROLS + 2)
|
||||
if isinstance(value, bool) or not isinstance(value, int) or not 0 <= value <= maximum:
|
||||
raise ImportFailure("invalid_format", "Invalid dropped marker link count")
|
||||
return value
|
||||
@@ -803,6 +810,16 @@ def _drop_invalid_import_marker_links(
|
||||
badge["enabled"] = False
|
||||
badge["source"] = None
|
||||
dropped += 1
|
||||
source = marker.get("value_source")
|
||||
if isinstance(source, dict) and source.get("kind") == "derived_marker_state":
|
||||
ref = source.get("ref")
|
||||
target_id = ref[len("marker:"):] \
|
||||
if isinstance(ref, str) and ref.startswith("marker:") else ""
|
||||
target = by_id.get(target_id)
|
||||
if not target_id or target is None or target.get("removed") is True \
|
||||
or target.get("is_light") is not True:
|
||||
marker.pop("value_source", None)
|
||||
dropped += 1
|
||||
return dropped
|
||||
|
||||
|
||||
@@ -1110,6 +1127,20 @@ def _repair_target_space_refs(
|
||||
preserve_related(
|
||||
marker_id, "marker.value_badge", old_target, resolve_marker,
|
||||
)
|
||||
source = marker.get("value_source")
|
||||
if isinstance(source, dict) and source.get("kind") == "derived_marker_state":
|
||||
ref = source.get("ref")
|
||||
old_target = ref[len("marker:"):] \
|
||||
if isinstance(ref, str) and ref.startswith("marker:") else None
|
||||
mapped = replace(
|
||||
marker_id, "marker.value_source", old_target, resolve_marker_link,
|
||||
)
|
||||
if mapped is not None:
|
||||
source["ref"] = "marker:" + mapped
|
||||
else:
|
||||
preserve_related(
|
||||
marker_id, "marker.value_source", old_target, resolve_marker,
|
||||
)
|
||||
|
||||
# Destination wins collisions. Rekey only proven dead plan-owned keys;
|
||||
# opaque HA owners remain literal.
|
||||
@@ -1345,13 +1376,17 @@ def build_space_merge(
|
||||
source = badge.get("source") if isinstance(badge, dict) else None
|
||||
if isinstance(source, dict) and source.get("kind") == "derived_marker_state":
|
||||
dropped_marker_links += 1
|
||||
value_source = marker.get("value_source")
|
||||
if isinstance(value_source, dict) \
|
||||
and value_source.get("kind") == "derived_marker_state":
|
||||
dropped_marker_links += 1
|
||||
marker["binding"] = "virtual"
|
||||
marker["display"] = "static_icon"
|
||||
for field in (
|
||||
"area", "controls", "tap_action", "tap_target", "tap_confirm",
|
||||
"vacuum", "is_light", "use_climate_temp", "glow_color",
|
||||
"glow_radius_cm", "light_entity", "toggle_entity", "hidden", "removed",
|
||||
"value_badge",
|
||||
"value_badge", "value_source",
|
||||
):
|
||||
marker.pop(field, None)
|
||||
output_markers.append(marker)
|
||||
@@ -1395,6 +1430,21 @@ def build_space_merge(
|
||||
badge["enabled"] = False
|
||||
badge["source"] = None
|
||||
dropped_marker_links += 1
|
||||
source = marker.get("value_source")
|
||||
if isinstance(source, dict) and source.get("kind") == "derived_marker_state":
|
||||
ref = source.get("ref")
|
||||
old_target = ref[len("marker:"):] \
|
||||
if isinstance(ref, str) and ref.startswith("marker:") else ""
|
||||
target = None if old_target in virtualized_targets else marker_map.get(old_target)
|
||||
if target:
|
||||
source["ref"] = "marker:" + target
|
||||
_report_remap(
|
||||
reference_report, "incoming", "marker.value_source",
|
||||
str(marker.get("id", "?")), old_target,
|
||||
)
|
||||
else:
|
||||
marker.pop("value_source", None)
|
||||
dropped_marker_links += 1
|
||||
|
||||
output_markers_by_id = {
|
||||
str(marker.get("id")): marker for marker in output_markers
|
||||
|
||||
@@ -805,7 +805,7 @@ def _matching_previous_marker(
|
||||
def validate_marker_value_badges(
|
||||
config: dict, previous: dict | None = None, *, validate_all: bool = False
|
||||
) -> None:
|
||||
"""Validate only new/changed badge data; dormant future/legacy data round-trips."""
|
||||
"""Validate changed badge/face sources; dormant future data round-trips."""
|
||||
markers = config.get("markers") or []
|
||||
by_id = {str(marker.get("id")): marker for marker in markers}
|
||||
old_markers = (previous or {}).get("markers") or []
|
||||
@@ -814,30 +814,14 @@ def validate_marker_value_badges(
|
||||
consumed_old_ids: set[str] = set()
|
||||
known_source_fields = {"kind", "entity_id", "attribute", "ref"}
|
||||
|
||||
for marker_id, marker in by_id.items():
|
||||
old_marker = _matching_previous_marker(
|
||||
marker, marker_id, old_by_id, old_markers, new_ids,
|
||||
consumed_old_ids, validate_all,
|
||||
)
|
||||
badge = marker.get("value_badge")
|
||||
old_badge = None if validate_all else (old_marker or {}).get("value_badge")
|
||||
if not validate_all and badge == old_badge:
|
||||
continue
|
||||
if badge is None:
|
||||
continue
|
||||
if not isinstance(badge, dict):
|
||||
raise MarkerControlError("invalid_value_badge", "Value badge must be an object")
|
||||
if not isinstance(badge.get("enabled"), bool):
|
||||
raise MarkerControlError("invalid_value_badge", "Value badge enabled must be boolean")
|
||||
if badge.get("position") not in VALUE_BADGE_POSITIONS:
|
||||
raise MarkerControlError("invalid_value_badge_position", "Invalid value badge position")
|
||||
source = badge.get("source")
|
||||
if badge["enabled"] and not isinstance(source, dict):
|
||||
raise MarkerControlError("value_badge_source_required", "Enabled value badge needs a source")
|
||||
if source is None:
|
||||
continue
|
||||
def validate_source(source: object, field: str) -> None:
|
||||
prefix = "value_badge" if field == "value_badge" else "value_source"
|
||||
source_error = "invalid_value_badge_source" if field == "value_badge" \
|
||||
else "invalid_value_source"
|
||||
attribute_error = "invalid_value_badge_attribute" if field == "value_badge" \
|
||||
else "invalid_value_source_attribute"
|
||||
if not isinstance(source, dict) or source.get("kind") not in VALUE_BADGE_SOURCE_KINDS:
|
||||
raise MarkerControlError("invalid_value_badge_source", "Invalid value badge source")
|
||||
raise MarkerControlError(source_error, f"Invalid {field} source")
|
||||
kind = source["kind"]
|
||||
allowed_fields = {
|
||||
"entity_state": {"kind", "entity_id"},
|
||||
@@ -846,23 +830,51 @@ def validate_marker_value_badges(
|
||||
"derived_marker_state": {"kind", "ref"},
|
||||
}[kind]
|
||||
if (known_source_fields & set(source)) - allowed_fields:
|
||||
raise MarkerControlError("invalid_value_badge_source", "Inconsistent value badge source")
|
||||
raise MarkerControlError(source_error, f"Inconsistent {field} source")
|
||||
if kind in {"entity_state", "entity_attribute"}:
|
||||
entity_id = source.get("entity_id")
|
||||
if not isinstance(entity_id, str) or not _CONTROL_ENTITY_ID_RE.fullmatch(entity_id):
|
||||
raise MarkerControlError("invalid_value_badge_source", "Invalid value badge entity id")
|
||||
if kind == "entity_attribute":
|
||||
if source.get("attribute") not in VALUE_BADGE_ATTRIBUTES:
|
||||
raise MarkerControlError("invalid_value_badge_attribute", "Invalid value badge attribute")
|
||||
raise MarkerControlError(source_error, f"Invalid {field} entity id")
|
||||
if kind == "entity_attribute" and source.get("attribute") not in VALUE_BADGE_ATTRIBUTES:
|
||||
raise MarkerControlError(attribute_error, f"Invalid {field} attribute")
|
||||
if kind == "derived_marker_state":
|
||||
ref = source.get("ref")
|
||||
if not isinstance(ref, str) or not ref.startswith(MARKER_CONTROL_PREFIX) or not ref[len(MARKER_CONTROL_PREFIX):]:
|
||||
raise MarkerControlError("invalid_value_badge_source", "Invalid marker value badge target")
|
||||
if not isinstance(ref, str) or not ref.startswith(MARKER_CONTROL_PREFIX) \
|
||||
or not ref[len(MARKER_CONTROL_PREFIX):]:
|
||||
raise MarkerControlError(source_error, f"Invalid {field} target")
|
||||
target = by_id.get(ref[len(MARKER_CONTROL_PREFIX):])
|
||||
if target is None or target.get("removed") is True:
|
||||
raise MarkerControlError("value_badge_marker_missing", "Marker value badge target does not exist")
|
||||
raise MarkerControlError(f"{prefix}_marker_missing", f"{field} target does not exist")
|
||||
if target.get("is_light") is not True:
|
||||
raise MarkerControlError("value_badge_marker_not_light", "Marker value badge target is not a forced light")
|
||||
raise MarkerControlError(f"{prefix}_marker_not_light", f"{field} target is not a forced light")
|
||||
|
||||
for marker_id, marker in by_id.items():
|
||||
old_marker = _matching_previous_marker(
|
||||
marker, marker_id, old_by_id, old_markers, new_ids,
|
||||
consumed_old_ids, validate_all,
|
||||
)
|
||||
badge = marker.get("value_badge")
|
||||
old_badge = None if validate_all else (old_marker or {}).get("value_badge")
|
||||
if validate_all or badge != old_badge:
|
||||
if badge is not None:
|
||||
if not isinstance(badge, dict):
|
||||
raise MarkerControlError("invalid_value_badge", "Value badge must be an object")
|
||||
if not isinstance(badge.get("enabled"), bool):
|
||||
raise MarkerControlError("invalid_value_badge", "Value badge enabled must be boolean")
|
||||
if badge.get("position") not in VALUE_BADGE_POSITIONS:
|
||||
raise MarkerControlError("invalid_value_badge_position", "Invalid value badge position")
|
||||
source = badge.get("source")
|
||||
if badge["enabled"] and not isinstance(source, dict):
|
||||
raise MarkerControlError(
|
||||
"value_badge_source_required", "Enabled value badge needs a source"
|
||||
)
|
||||
if source is not None:
|
||||
validate_source(source, "value_badge")
|
||||
|
||||
source = marker.get("value_source")
|
||||
old_source = None if validate_all else (old_marker or {}).get("value_source")
|
||||
if (validate_all or source != old_source) and source is not None:
|
||||
validate_source(source, "value_source")
|
||||
|
||||
|
||||
def validate_marker_light_entities(
|
||||
@@ -1743,6 +1755,12 @@ MARKER_SCHEMA = vol.Schema(
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
),
|
||||
),
|
||||
# Explicit source for display:value. Semantic delta validation shares
|
||||
# the badge source contract while keeping untouched future literals.
|
||||
vol.Optional("value_source"): vol.Any(
|
||||
None,
|
||||
vol.Schema({}, extra=vol.ALLOW_EXTRA),
|
||||
),
|
||||
# climate current_temperature: badge + room-average vote (off unless True)
|
||||
vol.Optional("use_climate_temp"): vol.Any(bool, None),
|
||||
vol.Optional("room_id"): vol.Any(str, None),
|
||||
|
||||
Reference in New Issue
Block a user