@@ -53,36 +53,157 @@ <h3 style="color:#1e88e5;">📝 Generated YAML:</h3>
5353< pre id ="output "> </ pre >
5454< button class ="copy-button " onclick ="copyYAML() "> 📋 Copy to Clipboard</ button >
5555
56- <!-- Generator script will be injected here -->
57- < script src ="matrix-generator.js "> </ script >
56+ < script >
57+ ( function ( ) {
58+ 'use strict' ;
59+ const output = document . getElementById ( "output" ) ;
60+ const entries = document . getElementById ( "entity-entries" ) ;
61+ const urlInput = document . getElementById ( "matrix-url" ) ;
62+
63+ const defaultConfigs = [
64+ { primary : "temperature" , primaryEntity : "weather.nowcast" , secondary : "feels_like" , secondaryEntity : "sensor.feels_like" , tempUnit : "F" } ,
65+ { primary : "lock" , primaryEntity : "lock.front_door_lock" , secondary : "none" , secondaryEntity : "" , tempUnit : "F" } ,
66+ { primary : "co2" , primaryEntity : "sensor.brandon_air_1_co2" , secondary : "voc" , secondaryEntity : "sensor.brandon_air_1_sen55_voc" , tempUnit : "F" } ,
67+ { primary : "ping" , primaryEntity : "sensor.1_1_1_1_round_trip_time_average" , secondary : "alarm" , secondaryEntity : "alarm_control_panel.alarmo" , tempUnit : "F" }
68+ ] ;
69+
70+ for ( let i = 0 ; i < 4 ; i ++ ) {
71+ const def = defaultConfigs [ i ] ;
72+ const fieldset = document . createElement ( "fieldset" ) ;
73+ fieldset . innerHTML = `
74+ <legend>Segment ${ i } </legend>
75+ <label>Primary Data Type:
76+ <input type="text" name="primary" value="${ def . primary } " data-id="${ i } ">
77+ </label>
78+ <label>Primary Entity ID:
79+ <input type="text" name="primaryEntity" value="${ def . primaryEntity } " placeholder="e.g., sensor.living_room_temperature" data-id="${ i } ">
80+ </label>
81+ <label>Secondary Data Type:
82+ <input type="text" name="secondary" value="${ def . secondary } " data-id="${ i } ">
83+ </label>
84+ <label>Secondary Entity ID:
85+ <input type="text" name="secondaryEntity" value="${ def . secondaryEntity } " placeholder="e.g., sensor.feels_like" data-id="${ i } ">
86+ </label>
87+ <label>Temperature Unit:
88+ <select name="tempunit" data-id="${ i } ">
89+ <option value="F"${ def . tempUnit === 'F' ? ' selected' : '' } >Fahrenheit (°F)</option>
90+ <option value="C"${ def . tempUnit === 'C' ? ' selected' : '' } >Celsius (°C)</option>
91+ </select>
92+ </label>
93+ <label>Custom Template:
94+ <textarea name="custom" rows="2" cols="60" data-id="${ i } " placeholder="Enter custom Jinja template (e.g., {{ states('sensor.custom') }} units)"></textarea>
95+ </label>
96+ ` ;
97+ entries . appendChild ( fieldset ) ;
98+ }
99+
100+ function updateYAML ( ) {
101+ const defaultFX = 122 ;
102+ const segments = Array . from ( entries . querySelectorAll ( "fieldset" ) ) . map ( ( fs , i ) => {
103+ const primaryType = fs . querySelector ( 'input[name="primary"]' ) . value ;
104+ const primaryEntity = fs . querySelector ( 'input[name="primaryEntity"]' ) . value . trim ( ) ;
105+ const secondaryType = fs . querySelector ( 'input[name="secondary"]' ) . value ;
106+ const secondaryEntity = fs . querySelector ( 'input[name="secondaryEntity"]' ) . value . trim ( ) ;
107+ const tempUnit = fs . querySelector ( 'select[name="tempunit"]' ) ?. value || "F" ;
108+ const custom = fs . querySelector ( 'textarea[name="custom"]' ) . value . trim ( ) ;
109+
110+ if ( ! primaryEntity && primaryType !== 'custom' ) return null ;
111+
112+ let template = primaryType + ':' + primaryEntity ;
113+ if ( secondaryType !== 'none' && secondaryEntity ) {
114+ template += ' | ' + secondaryType + ':' + secondaryEntity ;
115+ }
116+ if ( custom ) {
117+ template += ' ' + custom ;
118+ }
119+
120+ template = template . replace ( / " / g, '\\"' ) ;
121+ return ` {
122+ "id": ${ i } ,
123+ "fx": ${ defaultFX } ,
124+ "n": "${ template } "
125+ }` ;
126+ } ) . filter ( Boolean ) ;
127+
128+ const yaml = `rest_command:
129+ matrix_all_segments:
130+ url: ${ urlInput . value . trim ( ) } /json/state
131+ content_type: 'application/json'
132+ verify_ssl: false
133+ method: 'post'
134+ timeout: 20
135+ payload: >
136+ {
137+ "seg":[
138+ ${ segments . join ( ",\n" ) }
139+ ]
140+ }` ;
141+
142+ output . textContent = yaml ;
143+ }
144+
145+ entries . querySelectorAll ( "input, select, textarea" ) . forEach ( el => {
146+ el . addEventListener ( "input" , updateYAML ) ;
147+ el . addEventListener ( "change" , updateYAML ) ;
148+ } ) ;
149+ urlInput . addEventListener ( "input" , updateYAML ) ;
150+ urlInput . addEventListener ( "change" , updateYAML ) ;
151+
152+ window . copyYAML = function ( ) {
153+ if ( navigator . clipboard && navigator . clipboard . writeText ) {
154+ navigator . clipboard . writeText ( output . textContent ) . then ( ( ) => {
155+ alert ( "YAML copied to clipboard!" ) ;
156+ } ) . catch ( err => {
157+ console . error ( 'Failed to copy: ' , err ) ;
158+ fallbackCopy ( ) ;
159+ } ) ;
160+ } else {
161+ fallbackCopy ( ) ;
162+ }
163+ } ;
164+
165+ function fallbackCopy ( ) {
166+ const textArea = document . createElement ( "textarea" ) ;
167+ textArea . value = output . textContent ;
168+ document . body . appendChild ( textArea ) ;
169+ textArea . focus ( ) ;
170+ textArea . select ( ) ;
171+ try {
172+ document . execCommand ( 'copy' ) ;
173+ alert ( "YAML copied to clipboard!" ) ;
174+ } catch ( err ) {
175+ alert ( "Copy failed. Please manually select and copy the text." ) ;
176+ }
177+ document . body . removeChild ( textArea ) ;
178+ }
179+
180+ updateYAML ( ) ;
181+ } ) ( ) ;
182+ </ script >
58183
59184< style >
60185 form , fieldset , input , select , textarea , button {
61186 font-family : inherit;
62187 font-size : 1rem ;
63188 }
64-
65189 fieldset {
66190 background : # f9f9f9 ;
67191 border : 1px solid # cce0ff ;
68192 border-radius : 8px ;
69193 padding : 1em ;
70194 margin-bottom : 1em ;
71195 }
72-
73196 legend {
74197 color : # 1e88e5 ;
75198 font-weight : bold;
76199 padding : 0 0.5em ;
77200 }
78-
79201 label {
80202 display : block;
81203 margin : 0.5em 0 0.25em ;
82204 font-weight : 500 ;
83205 color : # 1e88e5 ;
84206 }
85-
86207 input , select , textarea {
87208 width : 100% ;
88209 max-width : 100% ;
@@ -91,7 +212,6 @@ <h3 style="color:#1e88e5;">📝 Generated YAML:</h3>
91212 border-radius : 6px ;
92213 box-sizing : border-box;
93214 }
94-
95215 button {
96216 background-color : # 1e88e5 ;
97217 color : white;
@@ -101,11 +221,9 @@ <h3 style="color:#1e88e5;">📝 Generated YAML:</h3>
101221 cursor : pointer;
102222 margin-top : 1em ;
103223 }
104-
105224 button : hover {
106225 background-color : # 0d6fd3 ;
107226 }
108-
109227 pre {
110228 background : # 1e1e1e ;
111229 color : # dcdcdc ;
@@ -116,12 +234,10 @@ <h3 style="color:#1e88e5;">📝 Generated YAML:</h3>
116234 white-space : pre-wrap;
117235 word-wrap : break-word;
118236 }
119-
120237 .copy-button {
121238 margin-top : 0.5em ;
122239 margin-bottom : 1em ;
123240 }
124241</ style >
125-
126242</ body >
127243</ html >
0 commit comments