278 files

This commit is contained in:
Home Assistant Version Control committed 2026-09-13 20:38:58 +00:00
1 parent d7a0a08372
commit 1b4f5f68c6
278 files changed
+36892 -7150

No files matched your search

@@ -0,0 +1,125 @@
/*! maintenance_supporter frontend 2.83.0 */
import{a as x,b as $}from"./chunk-WIO3PYFT.js";import{a as h,b as n,d as b,e as y,f as m,g as o,h as _,i as a,j as g,k as v,o as f,p,z as c}from"./chunk-AVD72T2Q.js";import{a as l}from"./chunk-LRS2DZQN.js";var E=80,s=class extends y{constructor(){super(...arguments);this._config={type:""};this._status=null;this._busy=!1;this._error="";this._localMonthly="";this._localYearly="";this._dirty=!1;this._loaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return v(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),g(this,t),t.has("hass")&&this.hass&&!this._loaded&&(this._loaded=!0,this._load())}async _load(){try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/budget_status"});this._status=t,this._localMonthly=t.monthly_budget?String(t.monthly_budget):"",this._localYearly=t.yearly_budget?String(t.yearly_budget):"",this._dirty=!1}catch(t){this._error=c(t,this._lang)}}async _save(){if(this._isAdmin){this._busy=!0,this._error="";try{let t=this._localMonthly.trim()===""?0:parseFloat(this._localMonthly),r=this._localYearly.trim()===""?0:parseFloat(this._localYearly),i={};!isNaN(t)&&t>=0&&(i.budget_monthly=t),!isNaN(r)&&r>=0&&(i.budget_yearly=r),await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/global/update",settings:i}),await this._load()}catch(t){this._error=c(t,this._lang)}finally{this._busy=!1}}}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_budget"),window.dispatchEvent(new CustomEvent("location-changed"))}render(){let t=this._lang,r=this._status;if(!r)return n`<ha-card><div class="loading">${a("loading",t)||"Loading\u2026"}</div></ha-card>`;let i=r.currency_symbol||_,k=r.alert_threshold_pct??E,w=[{label:a("budget_monthly",t)||"Monthly",spent:r.monthly_spent||0,budget:r.monthly_budget||0},{label:a("budget_yearly",t)||"Yearly",spent:r.yearly_spent||0,budget:r.yearly_budget||0}];return n`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">💰</span>
<span>${this._config.title||a("settings_budget",t)||"Budget"}</span>
</div>
<span class="currency">${i}</span>
</div>
${this._error?n`<div class="error">${this._error}</div>`:b}
${w.map(e=>{if(!(e.budget>0))return n`
<div class="track spent-only">
<div class="track-label-row">
<label>${e.label}</label>
<span class="track-numbers ok">${p(e.spent,i,t,0)}</span>
</div>
</div>
`;let d=Math.min(100,Math.max(0,e.spent/e.budget*100)),u=d>=100?"danger":d>=k?"warning":"ok";return n`
<div class="track">
<div class="track-label-row">
<label>${e.label}</label>
<span class="track-numbers ${u}">
${f(e.spent,t,0)} / ${p(e.budget,i,t,0)}
</span>
</div>
<div class="bar"><div class="bar-fill ${u}" style="width:${d}%"></div></div>
</div>
`})}
${this._isAdmin?n`
<div class="inputs-row">
<div class="input-field">
<label>${a("budget_monthly_set",t)||"Set monthly"}</label>
<div class="input-wrap">
<input type="number" min="0" step="1"
.value=${this._localMonthly}
?disabled=${this._busy}
@input=${e=>{this._localMonthly=e.target.value,this._dirty=!0}} />
<span class="input-suffix">${i}</span>
</div>
</div>
<div class="input-field">
<label>${a("budget_yearly_set",t)||"Set yearly"}</label>
<div class="input-wrap">
<input type="number" min="0" step="1"
.value=${this._localYearly}
?disabled=${this._busy}
@input=${e=>{this._localYearly=e.target.value,this._dirty=!0}} />
<span class="input-suffix">${i}</span>
</div>
</div>
</div>
<div class="actions">
<button class="btn ${this._dirty?"primary":"muted"}"
@click=${this._save}
?disabled=${this._busy||!this._dirty}>
<ha-icon icon="${this._dirty?"mdi:content-save":"mdi:check"}"></ha-icon>
${this._dirty?a("save",t)||"Save":a("saved",t)||"Saved"}
</button>
<button class="btn link" @click=${this._onDeepLink}>
${a("budget_advanced",t)||"Currency, alerts\u2026"}
</button>
</div>
`:n`
<button class="btn link" @click=${this._onDeepLink}>
${a("budget_open_panel",t)||"Open in panel"}
</button>
`}
</div>
</ha-card>
`}};s.styles=[$,h`
.currency {
font-size: 14px; font-weight: 600;
color: var(--secondary-text-color);
background: var(--secondary-background-color);
padding: 2px 10px; border-radius: 999px;
}
.track { display: flex; flex-direction: column; gap: 4px; }
.track-label-row {
display: flex; align-items: center; justify-content: space-between;
}
.track-label-row label {
font-size: 12px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.5px;
}
.track-numbers { font-size: 13px; font-weight: 600; }
.track-numbers.ok { color: var(--primary-text-color); }
.track-numbers.warning { color: #ff9800; }
.track-numbers.danger { color: var(--error-color, #f44336); }
.bar {
height: 6px; background: var(--secondary-background-color);
border-radius: 3px; overflow: hidden;
}
.bar-fill { height: 100%; transition: width 0.3s; border-radius: 3px; }
.bar-fill.ok { background: var(--primary-color); }
.bar-fill.warning { background: #ff9800; }
.bar-fill.danger { background: var(--error-color, #f44336); }
.inputs-row {
display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
padding-top: 4px; border-top: 1px solid var(--divider-color);
}
.input-field { display: flex; flex-direction: column; gap: 4px; }
.input-field label {
font-size: 11px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.3px;
}
.input-wrap { position: relative; display: flex; align-items: center; }
.input-wrap input {
flex: 1; padding: 6px 32px 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
.input-suffix {
position: absolute; right: 8px;
color: var(--secondary-text-color); font-size: 13px;
pointer-events: none;
}
.actions { display: flex; gap: 8px; align-items: center; }
`],l([m({attribute:!1})],s.prototype,"hass",2),l([o()],s.prototype,"_config",2),l([o()],s.prototype,"_status",2),l([o()],s.prototype,"_busy",2),l([o()],s.prototype,"_error",2),l([o()],s.prototype,"_localMonthly",2),l([o()],s.prototype,"_localYearly",2),l([o()],s.prototype,"_dirty",2);customElements.get("maintenance-budget-section-card")||customElements.define("maintenance-budget-section-card",s);x({type:"maintenance-budget-section-card",name:"Maintenance Supporter \u2014 Budget",description:"Inline monthly + yearly budget editor",preview:!1});export{s as MaintenanceBudgetSectionCard};
@@ -0,0 +1,125 @@
/*! maintenance_supporter frontend 2.86.0 */
import{a as x,b as $}from"./chunk-4QSUIFST.js";import{B as p,a as h,b as l,d as b,e as y,f as m,g as o,h as g,i as a,j as v,k as _,n as f,q as d}from"./chunk-QP4GVVMP.js";import{a as n}from"./chunk-VMGD53HU.js";var E=80,e=class extends y{constructor(){super(...arguments);this._config={type:""};this._status=null;this._busy=!1;this._error="";this._localMonthly="";this._localYearly="";this._dirty=!1;this._loaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return _(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),v(this,t),t.has("hass")&&this.hass&&!this._loaded&&(this._loaded=!0,this._load())}async _load(){try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/budget_status"});this._status=t,f(t),this._localMonthly=t.monthly_budget?String(t.monthly_budget):"",this._localYearly=t.yearly_budget?String(t.yearly_budget):"",this._dirty=!1}catch(t){this._error=p(t,this._lang)}}async _save(){if(this._isAdmin){this._busy=!0,this._error="";try{let t=this._localMonthly.trim()===""?0:parseFloat(this._localMonthly),r=this._localYearly.trim()===""?0:parseFloat(this._localYearly),i={};!isNaN(t)&&t>=0&&(i.budget_monthly=t),!isNaN(r)&&r>=0&&(i.budget_yearly=r),await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/global/update",settings:i}),await this._load()}catch(t){this._error=p(t,this._lang)}finally{this._busy=!1}}}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_budget"),window.dispatchEvent(new CustomEvent("location-changed"))}render(){let t=this._lang,r=this._status;if(!r)return l`<ha-card><div class="loading">${a("loading",t)}</div></ha-card>`;let i=g(r),k=r.alert_threshold_pct??E,w=[{label:a("budget_monthly",t),spent:r.monthly_spent||0,budget:r.monthly_budget||0},{label:a("budget_yearly",t),spent:r.yearly_spent||0,budget:r.yearly_budget||0}];return l`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">💰</span>
<span>${this._config.title||a("settings_budget",t)}</span>
</div>
<span class="currency">${i}</span>
</div>
${this._error?l`<div class="error">${this._error}</div>`:b}
${w.map(s=>{if(!(s.budget>0))return l`
<div class="track spent-only">
<div class="track-label-row">
<label>${s.label}</label>
<span class="track-numbers ok">${d(s.spent,i,t)}</span>
</div>
</div>
`;let c=Math.min(100,Math.max(0,s.spent/s.budget*100)),u=c>=100?"danger":c>=k?"warning":"ok";return l`
<div class="track">
<div class="track-label-row">
<label>${s.label}</label>
<span class="track-numbers ${u}">
${d(s.spent,void 0,t)} / ${d(s.budget,i,t)}
</span>
</div>
<div class="bar"><div class="bar-fill ${u}" style="width:${c}%"></div></div>
</div>
`})}
${this._isAdmin?l`
<div class="inputs-row">
<div class="input-field">
<label>${a("budget_monthly_set",t)}</label>
<div class="input-wrap">
<input type="number" min="0" step="1"
.value=${this._localMonthly}
?disabled=${this._busy}
@input=${s=>{this._localMonthly=s.target.value,this._dirty=!0}} />
<span class="input-suffix">${i}</span>
</div>
</div>
<div class="input-field">
<label>${a("budget_yearly_set",t)}</label>
<div class="input-wrap">
<input type="number" min="0" step="1"
.value=${this._localYearly}
?disabled=${this._busy}
@input=${s=>{this._localYearly=s.target.value,this._dirty=!0}} />
<span class="input-suffix">${i}</span>
</div>
</div>
</div>
<div class="actions">
<button class="btn ${this._dirty?"primary":"muted"}"
@click=${this._save}
?disabled=${this._busy||!this._dirty}>
<ha-icon icon="${this._dirty?"mdi:content-save":"mdi:check"}"></ha-icon>
${this._dirty?a("save",t):a("saved",t)}
</button>
<button class="btn link" @click=${this._onDeepLink}>
${a("budget_advanced",t)}
</button>
</div>
`:l`
<button class="btn link" @click=${this._onDeepLink}>
${a("budget_open_panel",t)}
</button>
`}
</div>
</ha-card>
`}};e.styles=[$,h`
.currency {
font-size: 14px; font-weight: 600;
color: var(--secondary-text-color);
background: var(--secondary-background-color);
padding: 2px 10px; border-radius: 999px;
}
.track { display: flex; flex-direction: column; gap: 4px; }
.track-label-row {
display: flex; align-items: center; justify-content: space-between;
}
.track-label-row label {
font-size: 12px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.5px;
}
.track-numbers { font-size: 13px; font-weight: 600; }
.track-numbers.ok { color: var(--primary-text-color); }
.track-numbers.warning { color: #ff9800; }
.track-numbers.danger { color: var(--error-color, #f44336); }
.bar {
height: 6px; background: var(--secondary-background-color);
border-radius: 3px; overflow: hidden;
}
.bar-fill { height: 100%; transition: width 0.3s; border-radius: 3px; }
.bar-fill.ok { background: var(--primary-color); }
.bar-fill.warning { background: #ff9800; }
.bar-fill.danger { background: var(--error-color, #f44336); }
.inputs-row {
display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
padding-top: 4px; border-top: 1px solid var(--divider-color);
}
.input-field { display: flex; flex-direction: column; gap: 4px; }
.input-field label {
font-size: 11px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.3px;
}
.input-wrap { position: relative; display: flex; align-items: center; }
.input-wrap input {
flex: 1; padding: 6px 32px 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
.input-suffix {
position: absolute; right: 8px;
color: var(--secondary-text-color); font-size: 13px;
pointer-events: none;
}
.actions { display: flex; gap: 8px; align-items: center; }
`],n([m({attribute:!1})],e.prototype,"hass",2),n([o()],e.prototype,"_config",2),n([o()],e.prototype,"_status",2),n([o()],e.prototype,"_busy",2),n([o()],e.prototype,"_error",2),n([o()],e.prototype,"_localMonthly",2),n([o()],e.prototype,"_localYearly",2),n([o()],e.prototype,"_dirty",2);customElements.get("maintenance-budget-section-card")||customElements.define("maintenance-budget-section-card",e);x({type:"maintenance-budget-section-card",name:"Maintenance Supporter \u2014 Budget",description:"Inline monthly + yearly budget editor",preview:!1});export{e as MaintenanceBudgetSectionCard};
@@ -0,0 +1,60 @@
/*! maintenance_supporter frontend 2.86.0 */
import{a as t}from"./chunk-QP4GVVMP.js";function e(o){let r=window;r.customCards=r.customCards||[],r.customCards.some(a=>a.type===o.type)||r.customCards.push(o)}var d=t`
ha-card { overflow: hidden; }
.card-content {
padding: 16px;
display: flex; flex-direction: column;
gap: 12px;
}
.header {
display: flex; align-items: center; justify-content: space-between;
gap: 12px;
}
.title {
display: flex; align-items: center; gap: 8px;
font-size: 16px; font-weight: 500;
}
.emoji { font-size: 20px; }
/* Button family — primary action / muted-saved-state / link / icon-with-text */
.btn {
padding: 6px 12px; font-size: 13px;
border-radius: 6px; cursor: pointer;
border: 1px solid var(--divider-color);
background: var(--secondary-background-color, transparent);
color: var(--primary-text-color);
font-weight: 500;
display: inline-flex; align-items: center; gap: 4px;
}
.btn:hover { background: var(--state-icon-color, rgba(255,255,255,0.06)); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.btn.primary {
background: var(--primary-color);
color: var(--text-primary-color, white);
border-color: var(--primary-color);
}
.btn.primary[disabled] { opacity: 0.6; }
.btn.muted {
background: transparent;
color: var(--secondary-text-color);
border-style: dashed;
}
.btn.muted[disabled] { opacity: 1; cursor: default; }
.btn.muted ha-icon, .btn.primary ha-icon { --mdc-icon-size: 14px; }
.btn.link {
background: transparent; border: none; padding: 6px 4px;
color: var(--primary-color); margin-left: auto;
}
.btn.link:hover { background: transparent; text-decoration: underline; }
/* Error + loading states */
.error {
padding: 8px; border-radius: 6px;
background: rgba(211, 47, 47, 0.1);
color: var(--error-color, #d32f2f); font-size: 13px;
}
.loading {
padding: 24px; text-align: center;
color: var(--secondary-text-color);
}
`;export{e as a,d as b};
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,88 @@
/*! maintenance_supporter frontend 2.83.0 */
import{a as y,b as s,d as l,e as g,f as o,g as f,i as d,q as m}from"./chunk-AVD72T2Q.js";import{a}from"./chunk-LRS2DZQN.js";function $(n){let t=m("2001-02-03",n).match(/\d+/g)||[],e=v=>t.findIndex(_=>Number(_)===v),h=e(2001),c=e(2),u=e(3);return h===0?"YMD":c>=0&&u>=0&&c<u?"MDY":"DMY"}function p(n,i,t){if(n<1e3||n>9999||i<1||i>12||t<1||t>31)return null;let e=new Date(n,i-1,t);return e.getFullYear()!==n||e.getMonth()!==i-1||e.getDate()!==t?null:`${n}-${String(i).padStart(2,"0")}-${String(t).padStart(2,"0")}`}function b(n,i){let t=n.trim(),e;if(e=t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/))return p(+e[1],+e[2],+e[3]);if(e=t.match(/^(\d{4})$/))return p(+e[1],1,1);if(e=t.match(/^(\d{1,2})[./](\d{4})$/))return p(+e[2],+e[1],1);if(e=t.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/))return p(+e[3],+e[2],+e[1]);if(e=t.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{4})$/)){let h=+e[1],c=+e[2],u=+e[3];return $(i)==="MDY"?p(u,h,c):p(u,c,h)}return null}function x(n,i){if(i)switch(n){case"date":return i.split("T")[0];case"time":return i.length===5?`${i}:00`:i;case"datetime":{let[t,e="00:00:00"]=i.split("T");return`${t} ${e.length===5?`${e}:00`:e}`}}}function k(n,i){if(typeof i!="string"||!i)return"";switch(n){case"date":return i.slice(0,10);case"time":return i.slice(0,5);case"datetime":{let[t,e="00:00:00"]=i.split(" ");return`${t}T${e.length===5?`${e}:00`:e}`}}}var r=class extends g{constructor(){super(...arguments);this.kind="date";this.label="";this.value="";this.clearable=!1;this.disabled=!1;this.required=!1;this.lang="en";this._typing=!1;this._typed="";this._typedInvalid=!1}_startTyping(){this._typed=this.value,this._typedInvalid=!1,this._typing=!0,this.updateComplete.then(()=>this.shadowRoot?.querySelector("input.typed")?.focus())}_commitTyped(){if(!this._typed.trim()){this._typing=!1;return}let t=b(this._typed,this.lang);if(!t){this._typedInvalid=!0;return}this._typing=!1,this._typedInvalid=!1,this._emit(t)}_onTypedKey(t){t.key==="Enter"?(t.preventDefault(),this._commitTyped()):t.key==="Escape"&&(t.preventDefault(),this._typing=!1,this._typedInvalid=!1)}_selector(){switch(this.kind){case"date":return{date:{}};case"time":return{time:{no_second:!0}};case"datetime":return{datetime:{}}}}_onSelectorChange(t){t.stopPropagation(),this._emit(k(this.kind,t.detail?.value))}_clear(){this._emit("")}_emit(t){t!==this.value&&(this.value=t,this.dispatchEvent(new CustomEvent("value-changed",{bubbles:!0,composed:!0,detail:{value:t}})))}render(){return s`
<div class="field">
${this.label?s`<span class="label">${this.label}${this.required?s`<span class="req">*</span>`:l}</span>`:l}
<div class="row">
${this._typing?s`<input class="typed" type="text" inputmode="numeric" autocomplete="off"
.value=${this._typed}
placeholder=${m("1978-03-15",this.lang)}
aria-invalid=${this._typedInvalid?"true":"false"}
@input=${t=>{this._typed=t.target.value,this._typedInvalid=!1}}
@keydown=${this._onTypedKey}
@blur=${this._commitTyped} />`:s`<ha-selector
.hass=${this.hass}
.selector=${this._selector()}
.value=${x(this.kind,this.value)}
.required=${this.required}
.disabled=${this.disabled}
@value-changed=${this._onSelectorChange}
></ha-selector>`}
${this.kind==="date"&&!this.disabled&&!this._typing?s`<button type="button" class="type-toggle" title=${d("date_type_toggle",this.lang)} aria-label=${d("date_type_toggle",this.lang)} @click=${this._startTyping}>
<ha-icon icon="mdi:keyboard-outline"></ha-icon>
</button>`:l}
${this.clearable&&this.value&&!this.disabled&&!this._typing?s`<button type="button" class="clear" title=${d("clear",this.lang)} aria-label=${d("clear",this.lang)} @click=${this._clear}>
<ha-icon icon="mdi:close"></ha-icon>
</button>`:l}
</div>
${this._typedInvalid?s`<span class="helper invalid">${d("date_type_invalid",this.lang)}</span>`:this.helper?s`<span class="helper">${this.helper}</span>`:l}
</div>
`}};r.styles=y`
:host { display: block; }
.field {
display: flex;
flex-direction: column;
gap: 4px;
}
.label {
font-size: 12px;
color: var(--secondary-text-color, #888);
font-weight: 500;
}
.req { color: var(--error-color, #f44336); margin-left: 2px; }
.row {
display: flex;
align-items: center;
gap: 4px;
}
ha-selector {
flex: 1;
min-width: 0;
}
.clear, .type-toggle {
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
border: none;
border-radius: 50%;
background: transparent;
color: var(--secondary-text-color);
cursor: pointer;
--mdc-icon-size: 20px;
}
.clear:hover, .type-toggle:hover { background: rgba(var(--rgb-primary-text-color, 0, 0, 0), 0.08); }
.clear:focus-visible, .type-toggle:focus-visible { outline: 2px solid var(--primary-color); }
.helper {
font-size: 11px;
color: var(--secondary-text-color);
font-style: italic;
}
.helper.invalid { color: var(--error-color, #f44336); font-style: normal; }
input.typed {
flex: 1;
min-width: 0;
height: 40px;
box-sizing: border-box;
padding: 0 12px;
border: 1px solid var(--divider-color, #ccc);
border-radius: 4px;
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
font: inherit;
}
input.typed[aria-invalid="true"] { border-color: var(--error-color, #f44336); }
input.typed:focus { outline: 2px solid var(--primary-color); outline-offset: -1px; }
`,a([o({attribute:!1})],r.prototype,"hass",2),a([o()],r.prototype,"kind",2),a([o()],r.prototype,"label",2),a([o()],r.prototype,"value",2),a([o()],r.prototype,"helper",2),a([o({type:Boolean})],r.prototype,"clearable",2),a([o({type:Boolean})],r.prototype,"disabled",2),a([o({type:Boolean})],r.prototype,"required",2),a([o()],r.prototype,"lang",2),a([f()],r.prototype,"_typing",2),a([f()],r.prototype,"_typed",2),a([f()],r.prototype,"_typedInvalid",2);customElements.get("ms-date-field")||customElements.define("ms-date-field",r);
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.86.0 */
function l(r){if(!r)return[];let n=[],i=r.photo_doc_id;typeof i=="string"&&n.push(i);let o=r.photo_doc_ids;Array.isArray(o)&&n.push(...o);let t=[];for(let e of n){if(typeof e!="string")continue;let s=e.trim();if(!(!s||t.includes(s))&&(t.push(s),t.length>=10))break}return t}function f(){let r=new Uint8Array(4);return(globalThis.crypto??{getRandomValues:n=>n.map(()=>Math.floor(Math.random()*256))}).getRandomValues(r),Array.from(r,n=>n.toString(16).padStart(2,"0")).join("")}function u(r){let n=r?.reading_values;if(!Array.isArray(n))return[];let i=[],o=new Set;for(let t of n){if(!t||typeof t!="object")continue;let e=t;typeof e.id!="string"||!e.id||o.has(e.id)||typeof e.value!="number"||!Number.isFinite(e.value)||(o.add(e.id),i.push({id:e.id,name:typeof e.name=="string"?e.name:e.id,unit:typeof e.unit=="string"?e.unit:null,value:e.value}))}return i}function c(r){return r.filter(n=>n.type==="completed"&&(n.reading_value!=null||u(n).length>0)).sort((n,i)=>n.timestamp.localeCompare(i.timestamp))}function p(r){return c(r??[]).map(n=>({timestamp:n.timestamp,values:u(n)})).filter(n=>n.values.length>0)}function m(r,n,i){let o;for(let t of r){if(i!==void 0){let s=new Date(t.timestamp).getTime();if(!isNaN(s)&&s>=i)break}let e=t.values.find(s=>s.id===n);e&&(o=e)}return o}function _(r,n,i){let o=u(n).find(e=>e.id===i);if(!o)return null;let t=null;for(let e of c(r)){if(e.timestamp>=n.timestamp)break;let s=u(e).find(a=>a.id===i);s&&(t=s.value)}return t==null?null:o.value-t}function R(r){let n=new Set,i=new Set;for(let o of r){let t=(o.name||"").trim().toLowerCase();t&&(n.has(t)?i.add(o.id):n.add(t))}return i}function h(r){let n=[],i=new Set,o=new Set;for(let t of r){let e=(t.name||"").trim();if(!(!e||i.has(t.id)||o.has(e.toLowerCase()))&&(i.add(t.id),o.add(e.toLowerCase()),n.push({id:t.id,name:e,unit:(t.unit||"").trim()||null}),n.length>=20))break}return n}function g(r,n,i,o){let t=i,e=d=>typeof d=="string"?d:null,s=d=>typeof d=="number"?d:null,a=e(t.timestamp)??"";return{entry_id:r,task_id:n,original_timestamp:a,type:e(t.type)||"completed",timestamp:a,notes:e(t.notes),cost:s(t.cost),duration:s(t.duration),completed_by:e(t.completed_by),used_parts:Array.isArray(t.used_parts)?t.used_parts:null,photo_doc_ids:l(t),reading_value:s(t.reading_value),reading_values:u(t),readings:o?.readings??[],task_type:o?.type??null,reading_unit:o?.reading_unit??null}}async function E(r,n,i,o){let e=(await r.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:n})).tasks?.find(a=>a.id===i),s=e?.history?.find(a=>a.timestamp===o);return!e||!s?null:g(n,i,s,e)}export{l as a,f as b,u as c,p as d,m as e,_ as f,R as g,h,g as i,E as j};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.83.0 */
function l(i){if(!i)return[];let n=[],o=i.photo_doc_id;typeof o=="string"&&n.push(o);let r=i.photo_doc_ids;Array.isArray(r)&&n.push(...r);let e=[];for(let t of n){if(typeof t!="string")continue;let a=t.trim();if(!(!a||e.includes(a))&&(e.push(a),e.length>=10))break}return e}function c(){let i=new Uint8Array(4);return(globalThis.crypto??{getRandomValues:n=>n.map(()=>Math.floor(Math.random()*256))}).getRandomValues(i),Array.from(i,n=>n.toString(16).padStart(2,"0")).join("")}function s(i){let n=i?.reading_values;if(!Array.isArray(n))return[];let o=[],r=new Set;for(let e of n){if(!e||typeof e!="object")continue;let t=e;typeof t.id!="string"||!t.id||r.has(t.id)||typeof t.value!="number"||!Number.isFinite(t.value)||(r.add(t.id),o.push({id:t.id,name:typeof t.name=="string"?t.name:t.id,unit:typeof t.unit=="string"?t.unit:null,value:t.value}))}return o}function u(i){return i.filter(n=>n.type==="completed"&&(n.reading_value!=null||s(n).length>0)).sort((n,o)=>n.timestamp.localeCompare(o.timestamp))}function g(i){return u(i??[]).map(n=>({timestamp:n.timestamp,values:s(n)})).filter(n=>n.values.length>0)}function y(i,n,o){let r;for(let e of i){if(o!==void 0){let a=new Date(e.timestamp).getTime();if(!isNaN(a)&&a>=o)break}let t=e.values.find(a=>a.id===n);t&&(r=t)}return r}function p(i,n,o){let r=s(n).find(t=>t.id===o);if(!r)return null;let e=null;for(let t of u(i)){if(t.timestamp>=n.timestamp)break;let a=s(t).find(d=>d.id===o);a&&(e=a.value)}return e==null?null:r.value-e}function m(i){let n=new Set,o=new Set;for(let r of i){let e=(r.name||"").trim().toLowerCase();e&&(n.has(e)?o.add(r.id):n.add(e))}return o}function R(i){let n=[],o=new Set,r=new Set;for(let e of i){let t=(e.name||"").trim();if(!(!t||o.has(e.id)||r.has(t.toLowerCase()))&&(o.add(e.id),r.add(t.toLowerCase()),n.push({id:e.id,name:t,unit:(e.unit||"").trim()||null}),n.length>=20))break}return n}export{l as a,c as b,s as c,g as d,y as e,p as f,m as g,R as h};
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.83.0 */
var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var t=(a,r,c,o)=>{for(var e=o>1?void 0:o?l(r,c):r,i=a.length-1,d;i>=0;i--)(d=a[i])&&(e=(o?d(r,c,e):d(e))||e);return o&&e&&s(r,c,e),e};var m={ok:"var(--success-color, #4caf50)",due_soon:"var(--warning-color, #ff9800)",overdue:"var(--error-color, #f44336)",triggered:"var(--deep-orange-color, #ff5722)",archived:"var(--disabled-color, #9e9e9e)",paused:"var(--info-color, #2196f3)"},v={ok:"mdi:check-circle",due_soon:"mdi:alert-circle",overdue:"mdi:alert-octagon",triggered:"mdi:bell-alert",archived:"mdi:archive-outline",paused:"mdi:pause-circle-outline",completed:"mdi:check-circle",skipped:"mdi:skip-next",missed:"mdi:calendar-remove",reset:"mdi:refresh"};export{t as a,m as b,v as c};
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,88 @@
/*! maintenance_supporter frontend 2.86.0 */
import{a as y,b as s,d as l,e as g,f as o,g as f,i as d,r as m}from"./chunk-QP4GVVMP.js";import{a}from"./chunk-VMGD53HU.js";function $(n){let t=m("2001-02-03",n).match(/\d+/g)||[],e=v=>t.findIndex(_=>Number(_)===v),h=e(2001),c=e(2),u=e(3);return h===0?"YMD":c>=0&&u>=0&&c<u?"MDY":"DMY"}function p(n,i,t){if(n<1e3||n>9999||i<1||i>12||t<1||t>31)return null;let e=new Date(n,i-1,t);return e.getFullYear()!==n||e.getMonth()!==i-1||e.getDate()!==t?null:`${n}-${String(i).padStart(2,"0")}-${String(t).padStart(2,"0")}`}function b(n,i){let t=n.trim(),e;if(e=t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/))return p(+e[1],+e[2],+e[3]);if(e=t.match(/^(\d{4})$/))return p(+e[1],1,1);if(e=t.match(/^(\d{1,2})[./](\d{4})$/))return p(+e[2],+e[1],1);if(e=t.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/))return p(+e[3],+e[2],+e[1]);if(e=t.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{4})$/)){let h=+e[1],c=+e[2],u=+e[3];return $(i)==="MDY"?p(u,h,c):p(u,c,h)}return null}function x(n,i){if(i)switch(n){case"date":return i.split("T")[0];case"time":return i.length===5?`${i}:00`:i;case"datetime":{let[t,e="00:00:00"]=i.split("T");return`${t} ${e.length===5?`${e}:00`:e}`}}}function k(n,i){if(typeof i!="string"||!i)return"";switch(n){case"date":return i.slice(0,10);case"time":return i.slice(0,5);case"datetime":{let[t,e="00:00:00"]=i.split(" ");return`${t}T${e.length===5?`${e}:00`:e}`}}}var r=class extends g{constructor(){super(...arguments);this.kind="date";this.label="";this.value="";this.clearable=!1;this.disabled=!1;this.required=!1;this.lang="en";this._typing=!1;this._typed="";this._typedInvalid=!1}_startTyping(){this._typed=this.value,this._typedInvalid=!1,this._typing=!0,this.updateComplete.then(()=>this.shadowRoot?.querySelector("input.typed")?.focus())}_commitTyped(){if(!this._typed.trim()){this._typing=!1;return}let t=b(this._typed,this.lang);if(!t){this._typedInvalid=!0;return}this._typing=!1,this._typedInvalid=!1,this._emit(t)}_onTypedKey(t){t.key==="Enter"?(t.preventDefault(),this._commitTyped()):t.key==="Escape"&&(t.preventDefault(),this._typing=!1,this._typedInvalid=!1)}_selector(){switch(this.kind){case"date":return{date:{}};case"time":return{time:{no_second:!0}};case"datetime":return{datetime:{}}}}_onSelectorChange(t){t.stopPropagation(),this._emit(k(this.kind,t.detail?.value))}_clear(){this._emit("")}_emit(t){t!==this.value&&(this.value=t,this.dispatchEvent(new CustomEvent("value-changed",{bubbles:!0,composed:!0,detail:{value:t}})))}render(){return s`
<div class="field">
${this.label?s`<span class="label">${this.label}${this.required?s`<span class="req">*</span>`:l}</span>`:l}
<div class="row">
${this._typing?s`<input class="typed" type="text" inputmode="numeric" autocomplete="off"
.value=${this._typed}
placeholder=${m("1978-03-15",this.lang)}
aria-invalid=${this._typedInvalid?"true":"false"}
@input=${t=>{this._typed=t.target.value,this._typedInvalid=!1}}
@keydown=${this._onTypedKey}
@blur=${this._commitTyped} />`:s`<ha-selector
.hass=${this.hass}
.selector=${this._selector()}
.value=${x(this.kind,this.value)}
.required=${this.required}
.disabled=${this.disabled}
@value-changed=${this._onSelectorChange}
></ha-selector>`}
${this.kind==="date"&&!this.disabled&&!this._typing?s`<button type="button" class="type-toggle" title=${d("date_type_toggle",this.lang)} aria-label=${d("date_type_toggle",this.lang)} @click=${this._startTyping}>
<ha-icon icon="mdi:keyboard-outline"></ha-icon>
</button>`:l}
${this.clearable&&this.value&&!this.disabled&&!this._typing?s`<button type="button" class="clear" title=${d("clear",this.lang)} aria-label=${d("clear",this.lang)} @click=${this._clear}>
<ha-icon icon="mdi:close"></ha-icon>
</button>`:l}
</div>
${this._typedInvalid?s`<span class="helper invalid">${d("date_type_invalid",this.lang)}</span>`:this.helper?s`<span class="helper">${this.helper}</span>`:l}
</div>
`}};r.styles=y`
:host { display: block; }
.field {
display: flex;
flex-direction: column;
gap: 4px;
}
.label {
font-size: 12px;
color: var(--secondary-text-color, #888);
font-weight: 500;
}
.req { color: var(--error-color, #f44336); margin-left: 2px; }
.row {
display: flex;
align-items: center;
gap: 4px;
}
ha-selector {
flex: 1;
min-width: 0;
}
.clear, .type-toggle {
flex: none;
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
border: none;
border-radius: 50%;
background: transparent;
color: var(--secondary-text-color);
cursor: pointer;
--mdc-icon-size: 20px;
}
.clear:hover, .type-toggle:hover { background: rgba(var(--rgb-primary-text-color, 0, 0, 0), 0.08); }
.clear:focus-visible, .type-toggle:focus-visible { outline: 2px solid var(--primary-color); }
.helper {
font-size: 11px;
color: var(--secondary-text-color);
font-style: italic;
}
.helper.invalid { color: var(--error-color, #f44336); font-style: normal; }
input.typed {
flex: 1;
min-width: 0;
height: 40px;
box-sizing: border-box;
padding: 0 12px;
border: 1px solid var(--divider-color, #ccc);
border-radius: 4px;
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
font: inherit;
}
input.typed[aria-invalid="true"] { border-color: var(--error-color, #f44336); }
input.typed:focus { outline: 2px solid var(--primary-color); outline-offset: -1px; }
`,a([o({attribute:!1})],r.prototype,"hass",2),a([o()],r.prototype,"kind",2),a([o()],r.prototype,"label",2),a([o()],r.prototype,"value",2),a([o()],r.prototype,"helper",2),a([o({type:Boolean})],r.prototype,"clearable",2),a([o({type:Boolean})],r.prototype,"disabled",2),a([o({type:Boolean})],r.prototype,"required",2),a([o()],r.prototype,"lang",2),a([f()],r.prototype,"_typing",2),a([f()],r.prototype,"_typed",2),a([f()],r.prototype,"_typedInvalid",2);customElements.get("ms-date-field")||customElements.define("ms-date-field",r);
@@ -0,0 +1,2 @@
/*! maintenance_supporter frontend 2.86.0 */
var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var t=(a,r,c,o)=>{for(var e=o>1?void 0:o?l(r,c):r,i=a.length-1,d;i>=0;i--)(d=a[i])&&(e=(o?d(r,c,e):d(e))||e);return o&&e&&s(r,c,e),e};var m={ok:"var(--success-color, #4caf50)",due_soon:"var(--warning-color, #ff9800)",overdue:"var(--error-color, #f44336)",triggered:"var(--deep-orange-color, #ff5722)",archived:"var(--disabled-color, #9e9e9e)",paused:"var(--info-color, #2196f3)"},v={ok:"mdi:check-circle",due_soon:"mdi:alert-circle",overdue:"mdi:alert-octagon",triggered:"mdi:bell-alert",archived:"mdi:archive-outline",paused:"mdi:pause-circle-outline",completed:"mdi:check-circle",skipped:"mdi:skip-next",missed:"mdi:calendar-remove",reset:"mdi:refresh"};export{t as a,m as b,v as c};
@@ -0,0 +1,60 @@
/*! maintenance_supporter frontend 2.83.0 */
import{a as t}from"./chunk-AVD72T2Q.js";function e(o){let r=window;r.customCards=r.customCards||[],r.customCards.some(a=>a.type===o.type)||r.customCards.push(o)}var d=t`
ha-card { overflow: hidden; }
.card-content {
padding: 16px;
display: flex; flex-direction: column;
gap: 12px;
}
.header {
display: flex; align-items: center; justify-content: space-between;
gap: 12px;
}
.title {
display: flex; align-items: center; gap: 8px;
font-size: 16px; font-weight: 500;
}
.emoji { font-size: 20px; }
/* Button family — primary action / muted-saved-state / link / icon-with-text */
.btn {
padding: 6px 12px; font-size: 13px;
border-radius: 6px; cursor: pointer;
border: 1px solid var(--divider-color);
background: var(--secondary-background-color, transparent);
color: var(--primary-text-color);
font-weight: 500;
display: inline-flex; align-items: center; gap: 4px;
}
.btn:hover { background: var(--state-icon-color, rgba(255,255,255,0.06)); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.btn.primary {
background: var(--primary-color);
color: var(--text-primary-color, white);
border-color: var(--primary-color);
}
.btn.primary[disabled] { opacity: 0.6; }
.btn.muted {
background: transparent;
color: var(--secondary-text-color);
border-style: dashed;
}
.btn.muted[disabled] { opacity: 1; cursor: default; }
.btn.muted ha-icon, .btn.primary ha-icon { --mdc-icon-size: 14px; }
.btn.link {
background: transparent; border: none; padding: 6px 4px;
color: var(--primary-color); margin-left: auto;
}
.btn.link:hover { background: transparent; text-decoration: underline; }
/* Error + loading states */
.error {
padding: 8px; border-radius: 6px;
background: rgba(211, 47, 47, 0.1);
color: var(--error-color, #d32f2f); font-size: 13px;
}
.loading {
padding: 24px; text-align: center;
color: var(--secondary-text-color);
}
`;export{e as a,d as b};
@@ -0,0 +1,137 @@
/*! maintenance_supporter frontend 2.86.0 */
import{a as v,b}from"./chunk-4QSUIFST.js";import{B as p,a as u,b as s,d as c,e as h,f as g,g as o,i,k as _,m}from"./chunk-QP4GVVMP.js";import{a}from"./chunk-VMGD53HU.js";var e=class extends h{constructor(){super(...arguments);this._config={type:""};this._groups={};this._loaded=!1;this._busy=!1;this._error="";this._newName="";this._editingId=null;this._editingName="";this._hasInitiallyLoaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return _(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),t.has("hass")&&this.hass&&!this._hasInitiallyLoaded&&(this._hasInitiallyLoaded=!0,this._load(),m(this._lang).then(()=>this.requestUpdate()))}async _load(){try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/groups"});this._groups=t.groups||{},this._loaded=!0}catch(t){this._error=p(t,this._lang)}}async _addGroup(){if(!this._isAdmin)return;let t=this._newName.trim();if(t){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/group/create",name:t}),this._newName="",await this._load()}catch(r){this._error=p(r,this._lang)}finally{this._busy=!1}}}_startEdit(t){this._editingId=t,this._editingName=this._groups[t]?.name||""}async _saveEdit(){if(!this._isAdmin||!this._editingId)return;let t=this._editingName.trim();if(t){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/group/update",group_id:this._editingId,name:t}),this._editingId=null,this._editingName="",await this._load()}catch(r){this._error=p(r,this._lang)}finally{this._busy=!1}}}async _deleteGroup(t,r){if(!this._isAdmin)return;let n=i("group_delete_confirm",this._lang).replace("{name}",r);if(window.confirm(n)){this._busy=!0;try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/group/delete",group_id:t}),await this._load()}catch(d){this._error=p(d,this._lang)}finally{this._busy=!1}}}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_groups"),window.dispatchEvent(new CustomEvent("location-changed"))}_onKeyDown(t,r){t.key==="Enter"?(t.preventDefault(),r()):t.key==="Escape"&&(t.preventDefault(),this._editingId=null,this._editingName="")}render(){let t=this._lang;if(!this._loaded)return s`<ha-card><div class="loading">${i("loading",t)}</div></ha-card>`;let r=Object.keys(this._groups);return s`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">🏷️</span>
<span>${this._config.title||i("groups",t)}</span>
<span class="count">${r.length}</span>
</div>
</div>
${this._error?s`<div class="error">${this._error}</div>`:c}
${r.length===0?s`<div class="empty">${i("groups_empty",t)}</div>`:s`
<div class="group-list">
${r.map(n=>{let d=this._groups[n],y=d.task_refs?.length??0,f=this._editingId===n;return s`
<div class="group-row">
${f?s`
<input class="edit-input" type="text"
.value=${this._editingName}
?disabled=${this._busy}
@input=${l=>{this._editingName=l.target.value}}
@keydown=${l=>this._onKeyDown(l,this._saveEdit.bind(this))} />
<button class="btn small primary"
@click=${this._saveEdit}
?disabled=${this._busy||!this._editingName.trim()}>
${i("save",t)}
</button>
<button class="btn small"
@click=${()=>{this._editingId=null}}>
${i("cancel",t)}
</button>
`:s`
<span class="group-name">${d.name||"Unnamed"}</span>
<span class="task-count">${y}</span>
${this._isAdmin?s`
<button class="icon-btn"
title="${i("edit",t)}"
@click=${()=>this._startEdit(n)}
?disabled=${this._busy}>
<ha-icon icon="mdi:pencil"></ha-icon>
</button>
<button class="icon-btn danger"
title="${i("delete",t)}"
@click=${()=>this._deleteGroup(n,d.name||"Unnamed")}
?disabled=${this._busy}>
<ha-icon icon="mdi:delete"></ha-icon>
</button>
`:c}
`}
</div>
`})}
</div>
`}
${this._isAdmin?s`
<div class="add-row">
<input type="text"
placeholder="${i("group_new_placeholder",t)}"
.value=${this._newName}
?disabled=${this._busy}
@input=${n=>{this._newName=n.target.value}}
@keydown=${n=>this._onKeyDown(n,this._addGroup.bind(this))} />
<button class="btn primary"
@click=${this._addGroup}
?disabled=${this._busy||!this._newName.trim()}>
<ha-icon icon="mdi:plus"></ha-icon>
${i("add",t)}
</button>
</div>
<button class="btn link" @click=${this._onDeepLink}>
${i("groups_manage_tasks",t)}
</button>
`:s`
<button class="btn link" @click=${this._onDeepLink}>
${i("groups_open_panel",t)}
</button>
`}
</div>
</ha-card>
`}};e.styles=[b,u`
.count {
font-size: 12px; color: var(--secondary-text-color);
background: var(--secondary-background-color);
padding: 2px 8px; border-radius: 999px;
}
.empty {
padding: 16px; text-align: center;
color: var(--secondary-text-color); font-style: italic;
}
.group-list { display: flex; flex-direction: column; gap: 4px; }
.group-row {
display: flex; align-items: center; gap: 8px;
padding: 6px 8px; border-radius: 6px;
background: var(--secondary-background-color, rgba(255,255,255,0.03));
}
.group-name { flex: 1; font-size: 14px; }
.task-count {
font-size: 11px; color: var(--secondary-text-color);
background: var(--card-background-color, rgba(0,0,0,0.2));
padding: 1px 8px; border-radius: 999px;
font-weight: 500;
}
.edit-input {
flex: 1; padding: 4px 8px; font-size: 14px;
background: var(--card-background-color, #1c1c1c);
color: var(--primary-text-color);
border: 1px solid var(--primary-color); border-radius: 4px;
font-family: inherit;
}
.icon-btn {
background: transparent; border: none; cursor: pointer;
color: var(--secondary-text-color); padding: 4px;
border-radius: 4px;
}
.icon-btn:hover {
background: var(--state-icon-color, rgba(255,255,255,0.06));
color: var(--primary-text-color);
}
.icon-btn.danger:hover { color: var(--error-color); }
.icon-btn ha-icon { --mdc-icon-size: 18px; }
.add-row {
display: flex; gap: 6px;
padding-top: 8px; border-top: 1px solid var(--divider-color);
}
.add-row input {
flex: 1; padding: 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
/* Card-specific overrides on the shared .btn */
.btn.small { padding: 4px 8px; font-size: 12px; }
.btn ha-icon { --mdc-icon-size: 16px; }
`],a([g({attribute:!1})],e.prototype,"hass",2),a([o()],e.prototype,"_config",2),a([o()],e.prototype,"_groups",2),a([o()],e.prototype,"_loaded",2),a([o()],e.prototype,"_busy",2),a([o()],e.prototype,"_error",2),a([o()],e.prototype,"_newName",2),a([o()],e.prototype,"_editingId",2),a([o()],e.prototype,"_editingName",2);customElements.get("maintenance-groups-section-card")||customElements.define("maintenance-groups-section-card",e);v({type:"maintenance-groups-section-card",name:"Maintenance Supporter \u2014 Groups",description:"Inline group CRUD",preview:!1});export{e as MaintenanceGroupsSectionCard};
@@ -0,0 +1,137 @@
/*! maintenance_supporter frontend 2.83.0 */
import{a as v,b}from"./chunk-WIO3PYFT.js";import{a as u,b as s,d as c,e as h,f as g,g as o,i,k as _,m,z as p}from"./chunk-AVD72T2Q.js";import{a}from"./chunk-LRS2DZQN.js";var e=class extends h{constructor(){super(...arguments);this._config={type:""};this._groups={};this._loaded=!1;this._busy=!1;this._error="";this._newName="";this._editingId=null;this._editingName="";this._hasInitiallyLoaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return _(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),t.has("hass")&&this.hass&&!this._hasInitiallyLoaded&&(this._hasInitiallyLoaded=!0,this._load(),m(this._lang).then(()=>this.requestUpdate()))}async _load(){try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/groups"});this._groups=t.groups||{},this._loaded=!0}catch(t){this._error=p(t,this._lang)}}async _addGroup(){if(!this._isAdmin)return;let t=this._newName.trim();if(t){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/group/create",name:t}),this._newName="",await this._load()}catch(r){this._error=p(r,this._lang)}finally{this._busy=!1}}}_startEdit(t){this._editingId=t,this._editingName=this._groups[t]?.name||""}async _saveEdit(){if(!this._isAdmin||!this._editingId)return;let t=this._editingName.trim();if(t){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/group/update",group_id:this._editingId,name:t}),this._editingId=null,this._editingName="",await this._load()}catch(r){this._error=p(r,this._lang)}finally{this._busy=!1}}}async _deleteGroup(t,r){if(!this._isAdmin)return;let n=(i("group_delete_confirm",this._lang)||'Delete group "{name}"?').replace("{name}",r);if(window.confirm(n)){this._busy=!0;try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/group/delete",group_id:t}),await this._load()}catch(d){this._error=p(d,this._lang)}finally{this._busy=!1}}}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_groups"),window.dispatchEvent(new CustomEvent("location-changed"))}_onKeyDown(t,r){t.key==="Enter"?(t.preventDefault(),r()):t.key==="Escape"&&(t.preventDefault(),this._editingId=null,this._editingName="")}render(){let t=this._lang;if(!this._loaded)return s`<ha-card><div class="loading">${i("loading",t)||"Loading\u2026"}</div></ha-card>`;let r=Object.keys(this._groups);return s`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">🏷️</span>
<span>${this._config.title||i("groups",t)||"Groups"}</span>
<span class="count">${r.length}</span>
</div>
</div>
${this._error?s`<div class="error">${this._error}</div>`:c}
${r.length===0?s`<div class="empty">${i("groups_empty",t)||"No groups yet."}</div>`:s`
<div class="group-list">
${r.map(n=>{let d=this._groups[n],y=d.task_refs?.length??0,f=this._editingId===n;return s`
<div class="group-row">
${f?s`
<input class="edit-input" type="text"
.value=${this._editingName}
?disabled=${this._busy}
@input=${l=>{this._editingName=l.target.value}}
@keydown=${l=>this._onKeyDown(l,this._saveEdit.bind(this))} />
<button class="btn small primary"
@click=${this._saveEdit}
?disabled=${this._busy||!this._editingName.trim()}>
${i("save",t)||"Save"}
</button>
<button class="btn small"
@click=${()=>{this._editingId=null}}>
${i("cancel",t)||"Cancel"}
</button>
`:s`
<span class="group-name">${d.name||"Unnamed"}</span>
<span class="task-count">${y}</span>
${this._isAdmin?s`
<button class="icon-btn"
title="${i("edit",t)||"Edit"}"
@click=${()=>this._startEdit(n)}
?disabled=${this._busy}>
<ha-icon icon="mdi:pencil"></ha-icon>
</button>
<button class="icon-btn danger"
title="${i("delete",t)||"Delete"}"
@click=${()=>this._deleteGroup(n,d.name||"Unnamed")}
?disabled=${this._busy}>
<ha-icon icon="mdi:delete"></ha-icon>
</button>
`:c}
`}
</div>
`})}
</div>
`}
${this._isAdmin?s`
<div class="add-row">
<input type="text"
placeholder="${i("group_new_placeholder",t)||"Add group\u2026"}"
.value=${this._newName}
?disabled=${this._busy}
@input=${n=>{this._newName=n.target.value}}
@keydown=${n=>this._onKeyDown(n,this._addGroup.bind(this))} />
<button class="btn primary"
@click=${this._addGroup}
?disabled=${this._busy||!this._newName.trim()}>
<ha-icon icon="mdi:plus"></ha-icon>
${i("add",t)||"Add"}
</button>
</div>
<button class="btn link" @click=${this._onDeepLink}>
${i("groups_manage_tasks",t)||"Manage task assignments\u2026"}
</button>
`:s`
<button class="btn link" @click=${this._onDeepLink}>
${i("groups_open_panel",t)||"Open in panel"}
</button>
`}
</div>
</ha-card>
`}};e.styles=[b,u`
.count {
font-size: 12px; color: var(--secondary-text-color);
background: var(--secondary-background-color);
padding: 2px 8px; border-radius: 999px;
}
.empty {
padding: 16px; text-align: center;
color: var(--secondary-text-color); font-style: italic;
}
.group-list { display: flex; flex-direction: column; gap: 4px; }
.group-row {
display: flex; align-items: center; gap: 8px;
padding: 6px 8px; border-radius: 6px;
background: var(--secondary-background-color, rgba(255,255,255,0.03));
}
.group-name { flex: 1; font-size: 14px; }
.task-count {
font-size: 11px; color: var(--secondary-text-color);
background: var(--card-background-color, rgba(0,0,0,0.2));
padding: 1px 8px; border-radius: 999px;
font-weight: 500;
}
.edit-input {
flex: 1; padding: 4px 8px; font-size: 14px;
background: var(--card-background-color, #1c1c1c);
color: var(--primary-text-color);
border: 1px solid var(--primary-color); border-radius: 4px;
font-family: inherit;
}
.icon-btn {
background: transparent; border: none; cursor: pointer;
color: var(--secondary-text-color); padding: 4px;
border-radius: 4px;
}
.icon-btn:hover {
background: var(--state-icon-color, rgba(255,255,255,0.06));
color: var(--primary-text-color);
}
.icon-btn.danger:hover { color: var(--error-color); }
.icon-btn ha-icon { --mdc-icon-size: 18px; }
.add-row {
display: flex; gap: 6px;
padding-top: 8px; border-top: 1px solid var(--divider-color);
}
.add-row input {
flex: 1; padding: 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
/* Card-specific overrides on the shared .btn */
.btn.small { padding: 4px 8px; font-size: 12px; }
.btn ha-icon { --mdc-icon-size: 16px; }
`],a([g({attribute:!1})],e.prototype,"hass",2),a([o()],e.prototype,"_config",2),a([o()],e.prototype,"_groups",2),a([o()],e.prototype,"_loaded",2),a([o()],e.prototype,"_busy",2),a([o()],e.prototype,"_error",2),a([o()],e.prototype,"_newName",2),a([o()],e.prototype,"_editingId",2),a([o()],e.prototype,"_editingName",2);customElements.get("maintenance-groups-section-card")||customElements.define("maintenance-groups-section-card",e);v({type:"maintenance-groups-section-card",name:"Maintenance Supporter \u2014 Groups",description:"Inline group CRUD",preview:!1});export{e as MaintenanceGroupsSectionCard};
@@ -0,0 +1,134 @@
/*! maintenance_supporter frontend 2.86.0 */
import{a as g,b as y}from"./chunk-4QSUIFST.js";import"./chunk-UKCMA2RG.js";import{B as o,a as h,b as r,d as c,e as _,f as v,g as n,i as e,j as f,k as m,m as b}from"./chunk-QP4GVVMP.js";import{a as i}from"./chunk-VMGD53HU.js";var s=class extends _{constructor(){super(...arguments);this._config={type:""};this._state=null;this._busy=!1;this._error="";this._localStart="";this._localEnd="";this._localBuffer=7;this._dirty=!1;this._loaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return m(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),f(this,t),t.has("hass")&&this.hass&&!this._loaded&&(this._loaded=!0,this._load(),b(this._lang).then(()=>this.requestUpdate()))}async _load(){try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/state"});this._state=t,this._localStart=t.start||"",this._localEnd=t.end||"",this._localBuffer=t.buffer_days??7,this._dirty=!1}catch(t){this._error=o(t,this._lang)}}async _toggleEnabled(t){this._busy=!0,this._error="";try{let a=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/update",enabled:t});this._state=a}catch(a){this._error=o(a,this._lang)}finally{this._busy=!1}}async _save(){if(this._isAdmin){this._busy=!0,this._error="";try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/update",start:this._localStart||null,end:this._localEnd||null,buffer_days:this._localBuffer});this._state=t,this._dirty=!1}catch(t){this._error=o(t,this._lang)}finally{this._busy=!1}}}async _endNow(){if(this._isAdmin&&window.confirm(e("vacation_end_now_confirm",this._lang))){this._busy=!0;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/end_now"});this._state=t,this._localStart=t.start||"",this._localEnd=t.end||""}catch(t){this._error=o(t,this._lang)}finally{this._busy=!1}}}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_vacation"),window.dispatchEvent(new CustomEvent("location-changed"))}render(){let t=this._lang,a=this._state;if(!a)return r`<ha-card><div class="loading">${e("loading",t)}</div></ha-card>`;let p=a.is_active===!0,d=a.enabled===!0,u=a.exempt_task_ids?.length??0,$=p?e("vacation_status_active",t):d?e("vacation_status_scheduled",t):e("vacation_status_inactive",t),x=p?"active":d?"scheduled":"inactive";return r`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">🏖️</span>
<span>${this._config.title||e("vacation_mode",t)}</span>
</div>
<span class="status-pill ${x}">${$}</span>
</div>
${this._error?r`<div class="error">${this._error}</div>`:c}
${this._isAdmin?r`
<div class="row toggle-row">
<label>${e("enable",t)}</label>
<ha-switch
.checked=${d}
.disabled=${this._busy}
@change=${l=>this._toggleEnabled(l.target.checked)}
></ha-switch>
</div>
<div class="dates-row">
<div class="date-field">
<label>${e("vacation_start",t)}</label>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.value=${this._localStart}
.disabled=${this._busy}
@value-changed=${l=>{this._localStart=l.detail.value,this._dirty=!0}}
></ms-date-field>
</div>
<div class="date-field">
<label>${e("vacation_end",t)}</label>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.value=${this._localEnd}
.disabled=${this._busy}
@value-changed=${l=>{this._localEnd=l.detail.value,this._dirty=!0}}
></ms-date-field>
</div>
<div class="date-field buffer">
<label>${e("vacation_buffer",t)}</label>
<input type="number" min="0" max="14"
.value=${String(this._localBuffer)}
?disabled=${this._busy}
@input=${l=>{this._localBuffer=parseInt(l.target.value,10)||0,this._dirty=!0}} />
</div>
</div>
<div class="actions">
<button class="btn ${this._dirty?"primary":"muted"}"
@click=${this._save}
?disabled=${this._busy||!this._dirty}>
<ha-icon icon="${this._dirty?"mdi:content-save":"mdi:check"}"></ha-icon>
${this._dirty?e("save",t):e("saved",t)}
</button>
${p?r`<button class="btn"
@click=${this._endNow}
?disabled=${this._busy}>
${e("vacation_end_now",t)}
</button>`:c}
${u>0?r`<button class="btn link"
@click=${this._onDeepLink}>
${u} ${e("vacation_exempt_count",t)}…
</button>`:r`<button class="btn link"
@click=${this._onDeepLink}>
${e("vacation_advanced",t)}
</button>`}
</div>
`:r`
<div class="readonly">
${d&&a.start&&a.end?r`<div>${a.start} → ${a.end}</div>`:c}
<button class="btn link" @click=${this._onDeepLink}>
${e("vacation_open_panel",t)}
</button>
</div>
`}
</div>
</ha-card>
`}};s.styles=[y,h`
.status-pill {
font-size: 11px; font-weight: 600;
padding: 3px 8px; border-radius: 999px;
text-transform: uppercase; letter-spacing: 0.5px;
}
.status-pill.active {
background: rgba(76, 175, 80, 0.15);
color: #4caf50;
}
.status-pill.scheduled {
background: rgba(255, 152, 0, 0.15);
color: #ff9800;
}
.status-pill.inactive {
background: rgba(158, 158, 158, 0.15);
color: var(--secondary-text-color);
}
.row.toggle-row {
display: flex; align-items: center; justify-content: space-between;
}
.row.toggle-row label {
font-size: 14px; color: var(--primary-text-color);
}
.dates-row {
display: grid; grid-template-columns: 1fr 1fr 100px; gap: 10px;
}
.date-field.buffer label { white-space: nowrap; }
.date-field { display: flex; flex-direction: column; gap: 4px; }
.date-field label {
font-size: 11px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.3px;
}
.date-field input {
padding: 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
.date-field input:disabled { opacity: 0.5; cursor: not-allowed; }
.actions {
display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
}
.readonly { display: flex; flex-direction: column; gap: 8px; }
`],i([v({attribute:!1})],s.prototype,"hass",2),i([n()],s.prototype,"_config",2),i([n()],s.prototype,"_state",2),i([n()],s.prototype,"_busy",2),i([n()],s.prototype,"_error",2),i([n()],s.prototype,"_localStart",2),i([n()],s.prototype,"_localEnd",2),i([n()],s.prototype,"_localBuffer",2),i([n()],s.prototype,"_dirty",2);customElements.get("maintenance-vacation-section-card")||customElements.define("maintenance-vacation-section-card",s);g({type:"maintenance-vacation-section-card",name:"Maintenance Supporter \u2014 Vacation",description:"Inline vacation mode toggle + dates",preview:!1});export{s as MaintenanceVacationSectionCard};
@@ -0,0 +1,134 @@
/*! maintenance_supporter frontend 2.83.0 */
import{a as g,b as y}from"./chunk-WIO3PYFT.js";import"./chunk-C4KIMTDR.js";import{a as h,b as n,d as c,e as _,f as v,g as r,i as e,j as f,k as m,m as b,z as o}from"./chunk-AVD72T2Q.js";import{a as i}from"./chunk-LRS2DZQN.js";var a=class extends _{constructor(){super(...arguments);this._config={type:""};this._state=null;this._busy=!1;this._error="";this._localStart="";this._localEnd="";this._localBuffer=7;this._dirty=!1;this._loaded=!1}setConfig(t){this._config=t}getCardSize(){return 2}get _lang(){return m(this.hass)}get _isAdmin(){return this.hass?.user?.is_admin??!0}updated(t){super.updated(t),f(this,t),t.has("hass")&&this.hass&&!this._loaded&&(this._loaded=!0,this._load(),b(this._lang).then(()=>this.requestUpdate()))}async _load(){try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/state"});this._state=t,this._localStart=t.start||"",this._localEnd=t.end||"",this._localBuffer=t.buffer_days??7,this._dirty=!1}catch(t){this._error=o(t,this._lang)}}async _toggleEnabled(t){this._busy=!0,this._error="";try{let s=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/update",enabled:t});this._state=s}catch(s){this._error=o(s,this._lang)}finally{this._busy=!1}}async _save(){if(this._isAdmin){this._busy=!0,this._error="";try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/update",start:this._localStart||null,end:this._localEnd||null,buffer_days:this._localBuffer});this._state=t,this._dirty=!1}catch(t){this._error=o(t,this._lang)}finally{this._busy=!1}}}async _endNow(){if(this._isAdmin&&window.confirm(e("vacation_end_now_confirm",this._lang)||"End vacation immediately?")){this._busy=!0;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/vacation/end_now"});this._state=t,this._localStart=t.start||"",this._localEnd=t.end||""}catch(t){this._error=o(t,this._lang)}finally{this._busy=!1}}}_onDeepLink(){history.pushState(null,"","/maintenance-supporter?ms_action=open_vacation"),window.dispatchEvent(new CustomEvent("location-changed"))}render(){let t=this._lang,s=this._state;if(!s)return n`<ha-card><div class="loading">${e("loading",t)||"Loading\u2026"}</div></ha-card>`;let p=s.is_active===!0,d=s.enabled===!0,u=s.exempt_task_ids?.length??0,$=p?e("vacation_status_active",t)||"Active now":d?e("vacation_status_scheduled",t)||"Scheduled":e("vacation_status_inactive",t)||"Inactive",x=p?"active":d?"scheduled":"inactive";return n`
<ha-card>
<div class="card-content">
<div class="header">
<div class="title">
<span class="emoji">🏖️</span>
<span>${this._config.title||e("vacation_mode",t)||"Vacation mode"}</span>
</div>
<span class="status-pill ${x}">${$}</span>
</div>
${this._error?n`<div class="error">${this._error}</div>`:c}
${this._isAdmin?n`
<div class="row toggle-row">
<label>${e("enable",t)||"Enable"}</label>
<ha-switch
.checked=${d}
.disabled=${this._busy}
@change=${l=>this._toggleEnabled(l.target.checked)}
></ha-switch>
</div>
<div class="dates-row">
<div class="date-field">
<label>${e("vacation_start",t)||"Start"}</label>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.value=${this._localStart}
.disabled=${this._busy}
@value-changed=${l=>{this._localStart=l.detail.value,this._dirty=!0}}
></ms-date-field>
</div>
<div class="date-field">
<label>${e("vacation_end",t)||"End"}</label>
<ms-date-field
kind="date"
clearable
.hass=${this.hass}
.lang=${t}
.value=${this._localEnd}
.disabled=${this._busy}
@value-changed=${l=>{this._localEnd=l.detail.value,this._dirty=!0}}
></ms-date-field>
</div>
<div class="date-field buffer">
<label>${e("vacation_buffer",t)||"Buffer days"}</label>
<input type="number" min="0" max="14"
.value=${String(this._localBuffer)}
?disabled=${this._busy}
@input=${l=>{this._localBuffer=parseInt(l.target.value,10)||0,this._dirty=!0}} />
</div>
</div>
<div class="actions">
<button class="btn ${this._dirty?"primary":"muted"}"
@click=${this._save}
?disabled=${this._busy||!this._dirty}>
<ha-icon icon="${this._dirty?"mdi:content-save":"mdi:check"}"></ha-icon>
${this._dirty?e("save",t)||"Save":e("saved",t)||"Saved"}
</button>
${p?n`<button class="btn"
@click=${this._endNow}
?disabled=${this._busy}>
${e("vacation_end_now",t)||"End now"}
</button>`:c}
${u>0?n`<button class="btn link"
@click=${this._onDeepLink}>
${u} ${e("vacation_exempt_count",t)||"exempt"}…
</button>`:n`<button class="btn link"
@click=${this._onDeepLink}>
${e("vacation_advanced",t)||"Advanced\u2026"}
</button>`}
</div>
`:n`
<div class="readonly">
${d&&s.start&&s.end?n`<div>${s.start} → ${s.end}</div>`:c}
<button class="btn link" @click=${this._onDeepLink}>
${e("vacation_open_panel",t)||"Open in panel"}
</button>
</div>
`}
</div>
</ha-card>
`}};a.styles=[y,h`
.status-pill {
font-size: 11px; font-weight: 600;
padding: 3px 8px; border-radius: 999px;
text-transform: uppercase; letter-spacing: 0.5px;
}
.status-pill.active {
background: rgba(76, 175, 80, 0.15);
color: #4caf50;
}
.status-pill.scheduled {
background: rgba(255, 152, 0, 0.15);
color: #ff9800;
}
.status-pill.inactive {
background: rgba(158, 158, 158, 0.15);
color: var(--secondary-text-color);
}
.row.toggle-row {
display: flex; align-items: center; justify-content: space-between;
}
.row.toggle-row label {
font-size: 14px; color: var(--primary-text-color);
}
.dates-row {
display: grid; grid-template-columns: 1fr 1fr 100px; gap: 10px;
}
.date-field.buffer label { white-space: nowrap; }
.date-field { display: flex; flex-direction: column; gap: 4px; }
.date-field label {
font-size: 11px; color: var(--secondary-text-color);
text-transform: uppercase; letter-spacing: 0.3px;
}
.date-field input {
padding: 6px 8px; font-size: 13px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
font-family: inherit;
}
.date-field input:disabled { opacity: 0.5; cursor: not-allowed; }
.actions {
display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
}
.readonly { display: flex; flex-direction: column; gap: 8px; }
`],i([v({attribute:!1})],a.prototype,"hass",2),i([r()],a.prototype,"_config",2),i([r()],a.prototype,"_state",2),i([r()],a.prototype,"_busy",2),i([r()],a.prototype,"_error",2),i([r()],a.prototype,"_localStart",2),i([r()],a.prototype,"_localEnd",2),i([r()],a.prototype,"_localBuffer",2),i([r()],a.prototype,"_dirty",2);customElements.get("maintenance-vacation-section-card")||customElements.define("maintenance-vacation-section-card",a);g({type:"maintenance-vacation-section-card",name:"Maintenance Supporter \u2014 Vacation",description:"Inline vacation mode toggle + dates",preview:!1});export{a as MaintenanceVacationSectionCard};
@@ -1,5 +1,5 @@
/*! maintenance_supporter frontend 2.82.0 */
import{a as T,c as M}from"./chunks/chunk-DNYI2KQV.js";import{c as y}from"./chunks/chunk-GOJ5CE7B.js";var D="maintenance-supporter",H=`ll-strategy-dashboard-${D}`,P="hui-maintenance-supporter-strategy-editor",N="NOT_RUNNING",B=[{status:"overdue",title:"Overdue",icon:y.overdue,path:"overdue"},{status:"triggered",title:"Triggered",icon:y.triggered,path:"triggered"},{status:"due_soon",title:"Due Soon",icon:y.due_soon,path:"due-soon"},{status:"ok",title:"OK",icon:y.ok,path:"ok"}],R=[{title:"Overdue",icon:"mdi:alert-circle",path:"overdue",filter:{filter_due_max_days:-1},matches:n=>n<=-1},{title:"Today",icon:"mdi:calendar-today",path:"today",filter:{filter_due_min_days:0,filter_due_max_days:0},matches:n=>n===0},{title:"This Week",icon:"mdi:calendar-week",path:"this-week",filter:{filter_due_min_days:1,filter_due_max_days:7},matches:n=>n>=1&&n<=7},{title:"This Month",icon:"mdi:calendar-month",path:"this-month",filter:{filter_due_min_days:8,filter_due_max_days:30},matches:n=>n>=8&&n<=30},{title:"Later",icon:"mdi:calendar-clock",path:"later",filter:{filter_due_min_days:31},matches:n=>n>=31}];function p(n){return{type:"grid",cards:[n]}}var $={condition:"view_columns",min:2};function _(n,i,e){let s=i[n];if(s)return`{{ states('${s}') }}`;let t=e[n];return t==null?"\u2014":String(t)}function U(n={},i={}){return{type:"markdown",text_only:!0,content:[`\u{1F534} **${_("overdue",n,i)}** overdue`,`\u26A1 **${_("triggered",n,i)}** triggered`,`\u{1F7E1} **${_("due_soon",n,i)}** due soon`,`\u{1F7E2} **${_("ok",n,i)}** ok`].join(" \xB7 ")}}function W(){return{title:"Maintenance",type:"panel",cards:[{type:"empty-state",icon:"mdi:wrench-clock",icon_color:"primary",content_only:!0,title:"No maintenance objects yet",content:"Open the Maintenance panel to add your first object \u2014 pool pump, HVAC filter, vehicle, anything that needs scheduled care.",buttons:[{icon:"mdi:wrench",text:"Open Maintenance panel",appearance:"filled",variant:"brand",tap_action:{action:"navigate",navigation_path:"/maintenance-supporter"}},{icon:"mdi:plus",text:"Add object",appearance:"outlined",variant:"brand",tap_action:{action:"fire-dom-event",ll_custom:{type:"maintenance-supporter:add-object"}}}]}]}}function Y(n={},i={}){let e=U(n,i);return{title:"Overview",icon:"mdi:wrench-clock",path:"overview",type:"sections",header:{layout:"responsive",card:e},sidebar:{sections:[{type:"grid",cards:[{type:"heading",heading:"Status",heading_style:"title"},e]}],visibility:[$],content_label:"Tasks",sidebar_label:"Status"},sections:[p({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:["overdue","triggered","due_soon"]})]}}function F(n,i){let e=new Map;for(let a of n){let r=a.object.area_id||null;e.has(r)||e.set(r,[]),e.get(r).push(a)}let s=Array.from(e.keys()).filter(a=>a!==null);s.sort((a,r)=>{let d=i[a]?.name||a,c=i[r]?.name||r;return d.localeCompare(c)});let t=[];for(let a of s){let r=e.get(a);if(r.length===0)continue;let d=i[a];t.push({title:d?.name||a,icon:d?.icon||"mdi:floor-plan",path:`area-${a}`,type:"sections",sections:[p({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:r.map(c=>c.object.name)})]})}let o=e.get(null);return o&&o.length>0&&t.push({title:"Unassigned",icon:"mdi:help-circle-outline",path:"unassigned",type:"sections",sections:[p({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:o.map(a=>a.object.name)})]}),t}function K(n){let i=new Set;for(let s of n)for(let t of s.tasks||[])t.status&&i.add(t.status);let e=[];for(let s of B)i.has(s.status)&&e.push({title:s.title,icon:s.icon,path:s.path,type:"sections",sections:[p({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:[s.status]})]});return e}function q(n,i,e){let s=new Map;for(let r of n){let d=r.object.area_id,c=d&&i[d]?.floor_id||null;s.has(c)||s.set(c,[]),s.get(c).push(r)}let t=Array.from(s.keys()).filter(r=>r!==null);t.sort((r,d)=>{let c=e[r],l=e[d],u=c?.level??0,m=l?.level??0;return u!==m?u-m:(c?.name||r).localeCompare(l?.name||d)});let o=[];for(let r of t){let d=s.get(r);if(d.length===0)continue;let c=e[r];o.push({title:c?.name||r,icon:c?.icon||"mdi:home-floor-1",path:`floor-${r}`,type:"sections",sections:[p({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:d.map(l=>l.object.name)})]})}let a=s.get(null);return a&&a.length>0&&o.push({title:"Other",icon:"mdi:help-circle-outline",path:"other",type:"sections",sections:[p({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:a.map(r=>r.object.name)})]}),o}function z(n){return[{title:"Week",icon:"mdi:calendar-week",path:"cal-7",window_days:7},{title:"Fortnight",icon:"mdi:calendar-week-begin",path:"cal-14",window_days:14},{title:"Month",icon:"mdi:calendar-month",path:"cal-30",window_days:30},{title:"Year",icon:"mdi:calendar-clock",path:"cal-365",window_days:365}].map(e=>({title:e.title,icon:e.icon,path:e.path,type:"panel",cards:[{type:"custom:maintenance-supporter-calendar-card",window_days:e.window_days,show_window_chips:!1,show_useLine truncated
/*! maintenance_supporter frontend 2.86.0 */
import{j as T}from"./chunks/chunk-FMRXSKNC.js";import{c as p}from"./chunks/chunk-VMGD53HU.js";var I="maintenance-supporter",H=`ll-strategy-dashboard-${I}`,D="hui-maintenance-supporter-strategy-editor",V="NOT_RUNNING",N=[{status:"overdue",title:"Overdue",icon:p.overdue,path:"overdue"},{status:"triggered",title:"Triggered",icon:p.triggered,path:"triggered"},{status:"due_soon",title:"Due Soon",icon:p.due_soon,path:"due-soon"},{status:"ok",title:"OK",icon:p.ok,path:"ok"}],M=[{title:"Overdue",icon:"mdi:alert-circle",path:"overdue",filter:{filter_due_max_days:-1},matches:n=>n<=-1},{title:"Today",icon:"mdi:calendar-today",path:"today",filter:{filter_due_min_days:0,filter_due_max_days:0},matches:n=>n===0},{title:"This Week",icon:"mdi:calendar-week",path:"this-week",filter:{filter_due_min_days:1,filter_due_max_days:7},matches:n=>n>=1&&n<=7},{title:"This Month",icon:"mdi:calendar-month",path:"this-month",filter:{filter_due_min_days:8,filter_due_max_days:30},matches:n=>n>=8&&n<=30},{title:"Later",icon:"mdi:calendar-clock",path:"later",filter:{filter_due_min_days:31},matches:n=>n>=31}];function u(n){return{type:"grid",cards:[n]}}var B={condition:"view_columns",min:2};function y(n,i,e){let s=i[n];if(s)return`{{ states('${s}') }}`;let t=e[n];return t==null?"\u2014":String(t)}function $(n={},i={}){return{type:"markdown",text_only:!0,content:[`\u{1F534} **${y("overdue",n,i)}** overdue`,`\u26A1 **${y("triggered",n,i)}** triggered`,`\u{1F7E1} **${y("due_soon",n,i)}** due soon`,`\u{1F7E2} **${y("ok",n,i)}** ok`].join(" \xB7 ")}}function U(){return{title:"Maintenance",type:"panel",cards:[{type:"empty-state",icon:"mdi:wrench-clock",icon_color:"primary",content_only:!0,title:"No maintenance objects yet",content:"Open the Maintenance panel to add your first object \u2014 pool pump, HVAC filter, vehicle, anything that needs scheduled care.",buttons:[{icon:"mdi:wrench",text:"Open Maintenance panel",appearance:"filled",variant:"brand",tap_action:{action:"navigate",navigation_path:"/maintenance-supporter"}},{icon:"mdi:plus",text:"Add object",appearance:"outlined",variant:"brand",tap_action:{action:"fire-dom-event",ll_custom:{type:"maintenance-supporter:add-object"}}}]}]}}function W(n={},i={}){let e=$(n,i);return{title:"Overview",icon:"mdi:wrench-clock",path:"overview",type:"sections",header:{layout:"responsive",card:e},sidebar:{sections:[{type:"grid",cards:[{type:"heading",heading:"Status",heading_style:"title"},e]}],visibility:[B],content_label:"Tasks",sidebar_label:"Status"},sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:["overdue","triggered","due_soon"]})]}}function Y(n,i){let e=new Map;for(let a of n){let r=a.object.area_id||null;e.has(r)||e.set(r,[]),e.get(r).push(a)}let s=Array.from(e.keys()).filter(a=>a!==null);s.sort((a,r)=>{let d=i[a]?.name||a,c=i[r]?.name||r;return d.localeCompare(c)});let t=[];for(let a of s){let r=e.get(a);if(r.length===0)continue;let d=i[a];t.push({title:d?.name||a,icon:d?.icon||"mdi:floor-plan",path:`area-${a}`,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:r.map(c=>c.object.name)})]})}let o=e.get(null);return o&&o.length>0&&t.push({title:"Unassigned",icon:"mdi:help-circle-outline",path:"unassigned",type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:o.map(a=>a.object.name)})]}),t}function F(n){let i=new Set;for(let s of n)for(let t of s.tasks||[])t.status&&i.add(t.status);let e=[];for(let s of N)i.has(s.status)&&e.push({title:s.title,icon:s.icon,path:s.path,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_status:[s.status]})]});return e}function K(n,i,e){let s=new Map;for(let r of n){let d=r.object.area_id,c=d&&i[d]?.floor_id||null;s.has(c)||s.set(c,[]),s.get(c).push(r)}let t=Array.from(s.keys()).filter(r=>r!==null);t.sort((r,d)=>{let c=e[r],g=e[d],k=c?.level??0,E=g?.level??0;return k!==E?k-E:(c?.name||r).localeCompare(g?.name||d)});let o=[];for(let r of t){let d=s.get(r);if(d.length===0)continue;let c=e[r];o.push({title:c?.name||r,icon:c?.icon||"mdi:home-floor-1",path:`floor-${r}`,type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:d.map(g=>g.object.name)})]})}let a=s.get(null);return a&&a.length>0&&o.push({title:"Other",icon:"mdi:help-circle-outline",path:"other",type:"sections",sections:[u({type:"custom:maintenance-supporter-card",show_header:!1,filter_objects:a.map(r=>r.object.name)})]}),o}function q(n){return[{title:"Week",icon:"mdi:calendar-week",path:"cal-7",window_days:7},{title:"Fortnight",icon:"mdi:calendar-week-begin",path:"cal-14",window_days:14},{title:"Month",icon:"mdi:calendar-month",path:"cal-30",window_days:30},{title:"Year",icon:"mdi:calendar-clock",path:"cal-365",window_days:365}].map(e=>({title:e.title,icon:e.icon,path:e.path,type:"panel",cards:[{type:"custom:maintenance-supporter-calendar-card",window_days:e.window_days,show_window_chips:!1,show_user_filteLine truncated
<style>
:host, .editor { display: block; padding: 16px 0; }
label { display: block; font-weight: 500; margin-bottom: 8px; }
@@ -22,4 +22,4 @@ import{a as T,c as M}from"./chunks/chunk-DNYI2KQV.js";import{c as y}from"./chunk
The "Overview" view is always first. Empty groups are skipped.
</div>
</div>
`;let t=this.querySelector("#group-by");t?.addEventListener("change",()=>{let o={...this._config,group_by:t.value};this._config=o,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:o},bubbles:!0,composed:!0}))})}},E="maintenance-supporter-section",J=`ll-strategy-section-${E}`,b=class extends HTMLElement{static async generate(i,e){let s={type:"custom:maintenance-supporter-card",show_header:!1};i?.filter_status?.length&&(s.filter_status=i.filter_status),i?.max_items&&(s.max_items=i.max_items),i?.filter_due_min_days!==void 0&&(s.filter_due_min_days=i.filter_due_min_days),i?.filter_due_max_days!==void 0&&(s.filter_due_max_days=i.filter_due_max_days);let t=i?.filter_objects;if(i?.area_id&&!t)try{t=((await e.connection.sendMessagePromise({type:"maintenance_supporter/objects"})).objects||[]).filter(r=>r.object.area_id===i.area_id).map(r=>r.object.name)}catch{}t&&t.length>0&&(s.filter_objects=t);let o=[];return i?.title&&o.push({type:"heading",heading:i.title,heading_style:"title"}),o.push(s),{type:"grid",cards:o}}},G="2.3.6",Z="[maintenance-supporter]";function A(n,i){try{return customElements.get(n)?"skipped":(customElements.define(n,i),"ok")}catch(e){return`ERROR: ${String(e)}`}}var V={editor:A(P,k),section:A(J,b)};console.log(`${Z} strategy bundle v${G} loaded \u2014 registrations:`,V,"\u2014 run maintenanceSupporterDiagnose() in console for full state");window.maintenanceSupporterDiagnose=async()=>{let n=H,i=[];try{let e=document.querySelector("home-assistant");e?.hass&&(i=(await e.hass.connection.sendMessagePromise({type:"lovelace/resources"})).resources||[])}catch(e){i=[{url:`<error: ${String(e)}>`}]}return{version:G,el_registered:!!customElements.get(n),el_class_excerpt:customElements.get(n)?.toString().slice(0,100)||null,customStrategies_dashboard:window.customStrategies?.filter(e=>e.strategyType==="dashboard").map(e=>e.type)||[],scriptTagsInPage:Array.from(document.querySelectorAll("script[type=module]")).map(e=>e.src).filter(e=>/maint|strateg/i.test(e)),lovelaceResources_matching:i.filter(e=>/maint|strateg/i.test(e.url||"")).map(e=>e.url),registrations:V}};var w=class extends HTMLElement{static async generate(i,e){return await import("./chunks/vacation-section-card-2O34KKIU.js"),{type:"grid",cards:[{type:"custom:maintenance-vacation-section-card",title:i?.title}]}}},v=class extends HTMLElement{static async generate(i,e){return await import("./chunks/budget-section-card-XNGOFRAV.js"),{type:"grid",cards:[{type:"custom:maintenance-budget-section-card",title:i?.title}]}}},C=class extends HTMLElement{static async generate(i,e){return await import("./chunks/groups-section-card-X34HJTMC.js"),{type:"grid",cards:[{type:"custom:maintenance-groups-section-card",title:i?.title}]}}},O="ll-strategy-section-maintenance-supporter-vacation",L="ll-strategy-section-maintenance-supporter-budget",x="ll-strategy-section-maintenance-supporter-groups";customElements.get(O)||customElements.define(O,w);customElements.get(L)||customElements.define(L,v);customElements.get(x)||customElements.define(x,C);var re={[E]:b,"maintenance-supporter-vacation":w,"maintenance-supporter-budget":v,"maintenance-supporter-groups":C},h=null;function ee(){return h||(h=import("./chunks/dialog-mount-4OVR4WJA.js").catch(n=>{throw h=null,n})),h}var I="_msSupporterLlCustomBound";function g(n){history.pushState(null,"",n),window.dispatchEvent(new CustomEvent("location-changed"))}function te(){let n=window;n[I]||(n[I]=!0,document.addEventListener("ll-custom",i=>{let e=i.detail;if(!e||typeof e!="object")return;let s=e.ll_custom,t=s&&typeof s=="object"?s:e;if(!t||typeof t.type!="string"||!t.type.startsWith("maintenance-supporter:"))return;let o=t.type.slice(22);if(o==="deep-link"&&typeof t.path=="string"){g(t.path);return}(async()=>{let a;try{a=await ee()}catch{g("/maintenance-supporter");return}if(o==="add-object"){if(a.openCreateObjectDialog())return;g("/maintenance-supporter?ms_action=add_object");return}if(o==="open-task"&&typeof t.entry_id=="string"&&typeof t.task_id=="string"){if(a.openTaskQuickActions(t.entry_id,t.task_id)||a.openEditTaskDialog(t.entry_id,t.task_id))return;g(`/maintenance-supporter?entry_id=${encodeURIComponent(t.entry_id)}&task_id=${encodeURIComponent(t.task_id)}`);return}if(o==="open-object"&&typeof t.entry_id=="string"){if(a.openObjectQuickActions(t.entry_id))return;g(`/maintenance-supporter?entry_id=${encodeURIComponent(t.entry_id)}`);return}if(o==="edit-history"&&typeof t.entry_id=="string"&&typeof t.task_id=="string"&&typeof t.original_timestamp=="string"){let d=document.querySelector("home-assistant")?.hass;if(!d)return;try{let l=(await d.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:t.entry_id})).tasks?.find(m=>m.id===t.task_id),u=l?.history?.find(m=>m.timestamp===t.original_timestamp);if(!u)return;a.openHistoryEditDialog({entry_id:t.entry_id,task_id:t.task_id,original_timestamp:t.original_timestamp,type:u.type||"completed",timestamp:u.timestamp||t.original_timestamp,notes:u.n Line truncated
`;let t=this.querySelector("#group-by");t?.addEventListener("change",()=>{let o={...this._config,group_by:t.value};this._config=o,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:o},bubbles:!0,composed:!0}))})}},S="maintenance-supporter-section",X=`ll-strategy-section-${S}`,_=class extends HTMLElement{static async generate(i,e){let s={type:"custom:maintenance-supporter-card",show_header:!1};i?.filter_status?.length&&(s.filter_status=i.filter_status),i?.max_items&&(s.max_items=i.max_items),i?.filter_due_min_days!==void 0&&(s.filter_due_min_days=i.filter_due_min_days),i?.filter_due_max_days!==void 0&&(s.filter_due_max_days=i.filter_due_max_days);let t=i?.filter_objects;if(i?.area_id&&!t)try{t=((await e.connection.sendMessagePromise({type:"maintenance_supporter/objects"})).objects||[]).filter(r=>r.object.area_id===i.area_id).map(r=>r.object.name)}catch{}t&&t.length>0&&(s.filter_objects=t);let o=[];return i?.title&&o.push({type:"heading",heading:i.title,heading_style:"title"}),o.push(s),{type:"grid",cards:o}}},P="2.3.6",J="[maintenance-supporter]";function j(n,i){try{return customElements.get(n)?"skipped":(customElements.define(n,i),"ok")}catch(e){return`ERROR: ${String(e)}`}}var G={editor:j(D,C),section:j(X,_)};console.log(`${J} strategy bundle v${P} loaded \u2014 registrations:`,G,"\u2014 run maintenanceSupporterDiagnose() in console for full state");window.maintenanceSupporterDiagnose=async()=>{let n=H,i=[];try{let e=document.querySelector("home-assistant");e?.hass&&(i=(await e.hass.connection.sendMessagePromise({type:"lovelace/resources"})).resources||[])}catch(e){i=[{url:`<error: ${String(e)}>`}]}return{version:P,el_registered:!!customElements.get(n),el_class_excerpt:customElements.get(n)?.toString().slice(0,100)||null,customStrategies_dashboard:window.customStrategies?.filter(e=>e.strategyType==="dashboard").map(e=>e.type)||[],scriptTagsInPage:Array.from(document.querySelectorAll("script[type=module]")).map(e=>e.src).filter(e=>/maint|strateg/i.test(e)),lovelaceResources_matching:i.filter(e=>/maint|strateg/i.test(e.url||"")).map(e=>e.url),registrations:G}};var h=class extends HTMLElement{static async generate(i,e){return await import("./chunks/vacation-section-card-SZEIZ5UX.js"),{type:"grid",cards:[{type:"custom:maintenance-vacation-section-card",title:i?.title}]}}},b=class extends HTMLElement{static async generate(i,e){return await import("./chunks/budget-section-card-GWCFNQR3.js"),{type:"grid",cards:[{type:"custom:maintenance-budget-section-card",title:i?.title}]}}},w=class extends HTMLElement{static async generate(i,e){return await import("./chunks/groups-section-card-UECFCP5O.js"),{type:"grid",cards:[{type:"custom:maintenance-groups-section-card",title:i?.title}]}}},A="ll-strategy-section-maintenance-supporter-vacation",O="ll-strategy-section-maintenance-supporter-budget",L="ll-strategy-section-maintenance-supporter-groups";customElements.get(A)||customElements.define(A,h);customElements.get(O)||customElements.define(O,b);customElements.get(L)||customElements.define(L,w);var ie={[S]:_,"maintenance-supporter-vacation":h,"maintenance-supporter-budget":b,"maintenance-supporter-groups":w},f=null;function Z(){return f||(f=import("./chunks/dialog-mount-TBFMCACO.js").catch(n=>{throw f=null,n})),f}var x="_msSupporterLlCustomBound";function l(n){history.pushState(null,"",n),window.dispatchEvent(new CustomEvent("location-changed"))}function ee(){let n=window;n[x]||(n[x]=!0,document.addEventListener("ll-custom",i=>{let e=i.detail;if(!e||typeof e!="object")return;let s=e.ll_custom,t=s&&typeof s=="object"?s:e;if(!t||typeof t.type!="string"||!t.type.startsWith("maintenance-supporter:"))return;let o=t.type.slice(22);if(o==="deep-link"&&typeof t.path=="string"){l(t.path);return}(async()=>{let a;try{a=await Z()}catch{l("/maintenance-supporter");return}if(o==="add-object"){if(a.openCreateObjectDialog())return;l("/maintenance-supporter?ms_action=add_object");return}if(o==="open-task"&&typeof t.entry_id=="string"&&typeof t.task_id=="string"){if(a.openTaskQuickActions(t.entry_id,t.task_id)||a.openEditTaskDialog(t.entry_id,t.task_id))return;l(`/maintenance-supporter?entry_id=${encodeURIComponent(t.entry_id)}&task_id=${encodeURIComponent(t.task_id)}`);return}if(o==="open-object"&&typeof t.entry_id=="string"){if(a.openObjectQuickActions(t.entry_id))return;l(`/maintenance-supporter?entry_id=${encodeURIComponent(t.entry_id)}`);return}if(o==="edit-history"&&typeof t.entry_id=="string"&&typeof t.task_id=="string"&&typeof t.original_timestamp=="string"){let d=document.querySelector("home-assistant")?.hass;if(!d)return;try{let c=await T(d,t.entry_id,t.task_id,t.original_timestamp);if(!c)return;a.openHistoryEditDialog(c)}catch{l("/maintenance-supporter")}}})()}))}ee();var v=window;v.customStrategies=v.customStrategies||[];function m(n){v.customStrategies.some(e=>e.type===n.type&&e.strategyType===n.strategyType)||v.customStrategies.push(n)}m({type:I,strategyType:"dashboard",name:"Maintenance Supporter",descrip Line truncated