@@ -21,47 +21,53 @@ import { StatisticValue } from "../recorder-types";
2121import { Config , HassEntity , YValue } from "../types" ;
2222
2323class ConfigParser {
24- private partiallyParsedConfig ?: any ;
24+ private yaml ?: any ;
2525 private errors ?: Error [ ] ;
26- private inputConfig ?: any ;
26+ private yaml_with_defaults ?: any ;
2727 private hass ?: HomeAssistant ;
2828 cache = new Cache ( ) ;
2929 private busy = false ;
3030 private fnParam ! : FnParam ;
3131
32- async update ( input : {
33- raw_config : any ;
32+ async update ( input : { yaml : any ; hass : HomeAssistant } ) {
33+ if ( this . busy ) throw new Error ( "ParseConfig was updated while busy" ) ;
34+ this . busy = true ;
35+ try {
36+ return this . _update ( input ) ;
37+ } finally {
38+ this . busy = false ;
39+ }
40+ }
41+ private async _update ( input : {
42+ yaml : any ;
3443 hass : HomeAssistant ;
35- cssVars : HATheme ;
3644 } ) : Promise < { errors : Error [ ] ; parsed : Config } > {
37- if ( this . busy ) throw new Error ( "ParseConfig was updated while busy" ) ;
38- this . partiallyParsedConfig = { } ;
45+ this . yaml = { } ;
3946 this . errors = [ ] ;
4047
41- this . busy = true ;
42- try {
43- this . hass = input . hass ;
44- const old_uirevision = this . partiallyParsedConfig ?. layout ?. uirevision ;
45- let config = JSON . parse ( JSON . stringify ( input . raw_config ) ) ;
48+ this . hass = input . hass ;
49+ const old_uirevision = this . yaml ?. layout ?. uirevision ;
50+ this . yaml_with_defaults = JSON . parse ( JSON . stringify ( input . yaml ) ) ;
4651
47- // 1st pass: add defaults
48- config = merge (
52+ // 1st pass: add defaults
53+ this . yaml_with_defaults = merge (
54+ { } ,
55+ this . yaml_with_defaults ,
56+ defaultYamlRequired ,
57+ this . yaml_with_defaults . raw_plotly_config ? { } : defaultYamlOptional ,
58+ this . yaml_with_defaults
59+ ) ;
60+ for ( let i = 1 ; i < 31 ; i ++ ) {
61+ const yaxis = "yaxis" + ( i == 1 ? "" : i ) ;
62+ this . yaml_with_defaults . layout [ yaxis ] = merge (
4963 { } ,
50- config ,
51- defaultYamlRequired ,
52- config . raw_plotly_config ? { } : defaultYamlOptional ,
53- config
64+ this . yaml_with_defaults . layout [ yaxis ] ,
65+ this . yaml_with_defaults . defaults ?. yaxes ,
66+ this . yaml_with_defaults . layout [ yaxis ]
5467 ) ;
55- for ( let i = 1 ; i < 31 ; i ++ ) {
56- const yaxis = "yaxis" + ( i == 1 ? "" : i ) ;
57- config . layout [ yaxis ] = merge (
58- { } ,
59- config . layout [ yaxis ] ,
60- config . defaults ?. yaxes ,
61- config . layout [ yaxis ]
62- ) ;
63- }
64- config . entities = config . entities . map ( ( entity ) => {
68+ }
69+ this . yaml_with_defaults . entities = this . yaml_with_defaults . entities . map (
70+ ( entity ) => {
6571 if ( typeof entity === "string" ) entity = { entity } ;
6672 entity . entity ??= "" ;
6773 const [ oldAPI_entity , oldAPI_attribute ] = entity . entity . split ( "::" ) ;
@@ -73,72 +79,67 @@ class ConfigParser {
7379 { } ,
7480 entity ,
7581 defaultEntityRequired ,
76- config . raw_plotly_config ? { } : defaultEntityOptional ,
77- config . defaults ?. entity ,
82+ this . yaml_with_defaults . raw_plotly_config
83+ ? { }
84+ : defaultEntityOptional ,
85+ this . yaml_with_defaults . defaults ?. entity ,
7886 entity
7987 ) ;
8088 return entity ;
81- } ) ;
89+ }
90+ ) ;
8291
83- // 2nd pass: evaluate functions
84- this . fnParam = {
85- vars : { } ,
86- path : "" ,
87- hass : input . hass ,
88- getFromConfig : ( ) => "" ,
89- } ;
90- this . inputConfig = config ;
91- for ( const [ key , value ] of Object . entries ( config ) ) {
92- try {
93- await this . evalNode ( {
94- parent : this . partiallyParsedConfig ,
95- path : key ,
96- key : key ,
97- value,
98- } ) ;
99- } catch ( e ) {
100- console . warn ( `Plotly Graph Card: Error parsing [${ key } ]` , e ) ;
101- this . errors ?. push ( e as Error ) ;
102- }
92+ // 2nd pass: evaluate functions
93+ this . fnParam = {
94+ vars : { } ,
95+ path : "" ,
96+ hass : input . hass ,
97+ getFromConfig : ( ) => "" ,
98+ } ;
99+ for ( const [ key , value ] of Object . entries ( this . yaml_with_defaults ) ) {
100+ try {
101+ await this . evalNode ( {
102+ parent : this . yaml ,
103+ path : key ,
104+ key : key ,
105+ value,
106+ } ) ;
107+ } catch ( e ) {
108+ console . warn ( `Plotly Graph Card: Error parsing [${ key } ]` , e ) ;
109+ this . errors ?. push ( e as Error ) ;
103110 }
111+ }
104112
105- // 3rd pass: decorate
106- /**
107- * These cannot be done via defaults because they are functions and
108- * functions would be overwritten if the user sets a configuration on a parent
109- * */
110- const isBrowsing = ! ! input . raw_config . visible_range ;
111- const yAxisTitles = Object . fromEntries (
112- this . partiallyParsedConfig . entities . map (
113- ( { unit_of_measurement, yaxis } ) => [
114- "yaxis" + yaxis ?. slice ( 1 ) ,
115- { title : unit_of_measurement } ,
116- ]
117- )
118- ) ;
119- merge (
120- this . partiallyParsedConfig . layout ,
121- this . partiallyParsedConfig . raw_plotly_config ? { } : defaultLayout ,
122- this . partiallyParsedConfig . ha_theme
123- ? getThemedLayout ( input . cssVars )
124- : { } ,
125- this . partiallyParsedConfig . raw_plotly_config
126- ? { }
127- : {
128- xaxis : {
129- range : this . partiallyParsedConfig . visible_range ,
130- } ,
131- //changing the uirevision triggers a reset to the axes
132- uirevision : isBrowsing ? old_uirevision : Math . random ( ) ,
113+ // 3rd pass: decorate
114+ /**
115+ * These cannot be done via defaults because they are functions and
116+ * functions would be overwritten if the user sets a configuration on a parent
117+ * */
118+ const isBrowsing = ! ! input . yaml . visible_range ;
119+ const yAxisTitles = Object . fromEntries (
120+ this . yaml . entities . map ( ( { unit_of_measurement, yaxis } ) => [
121+ "yaxis" + yaxis ?. slice ( 1 ) ,
122+ { title : unit_of_measurement } ,
123+ ] )
124+ ) ;
125+ merge (
126+ this . yaml . layout ,
127+ this . yaml . raw_plotly_config ? { } : defaultLayout ,
128+ this . yaml . ha_theme ? getThemedLayout ( this . yaml . css_vars ) : { } ,
129+ this . yaml . raw_plotly_config
130+ ? { }
131+ : {
132+ xaxis : {
133+ range : this . yaml . visible_range ,
133134 } ,
134- this . partiallyParsedConfig . raw_plotly_config ? { } : yAxisTitles ,
135- this . partiallyParsedConfig . layout
136- ) ;
135+ //changing the uirevision triggers a reset to the axes
136+ uirevision : isBrowsing ? old_uirevision : Math . random ( ) ,
137+ } ,
138+ this . yaml . raw_plotly_config ? { } : yAxisTitles ,
139+ this . yaml . layout
140+ ) ;
137141
138- return { errors : this . errors , parsed : this . partiallyParsedConfig } ;
139- } finally {
140- this . busy = false ;
141- }
142+ return { errors : this . errors , parsed : this . yaml } ;
142143 }
143144 private async evalNode ( {
144145 parent,
@@ -277,7 +278,7 @@ class ConfigParser {
277278 + new Date ( ) - ms + global_offset ,
278279 + new Date ( ) + global_offset ,
279280 ] as [ number , number ] ;
280- this . partiallyParsedConfig . visible_range = visible_range ;
281+ this . yaml . visible_range = visible_range ;
281282 }
282283 this . observed_range [ 0 ] = Math . min ( this . observed_range [ 0 ] , visible_range [ 0 ] ) ;
283284 this . observed_range [ 1 ] = Math . max ( this . observed_range [ 1 ] , visible_range [ 1 ] ) ;
@@ -340,10 +341,9 @@ class ConfigParser {
340341 . slice ( 0 , - 1 )
341342 . concat ( path . slice ( 1 ) . split ( "." ) )
342343 . join ( "." ) ;
343- if ( has ( this . partiallyParsedConfig , path ) )
344- return get ( this . partiallyParsedConfig , path ) ;
344+ if ( has ( this . yaml , path ) ) return get ( this . yaml , path ) ;
345345
346- let value = this . inputConfig ;
346+ let value = this . yaml_with_defaults ;
347347 for ( const key of path . split ( "." ) ) {
348348 if ( value === undefined ) return undefined ;
349349 value = value [ key ] ;
0 commit comments