mirror of
				https://github.com/beestat/app.git
				synced 2025-10-31 01:57:01 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			212 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Metrics card.
 | |
|  *
 | |
|  * @param {number} thermostat_id The thermostat_id this card is displaying
 | |
|  * data for.
 | |
|  */
 | |
| beestat.component.card.metrics = function(thermostat_id) {
 | |
|   this.thermostat_id_ = thermostat_id;
 | |
| 
 | |
|   var self = this;
 | |
| 
 | |
|   /*
 | |
|    * Debounce so that multiple setting changes don't re-trigger the same
 | |
|    * event. This fires on the trailing edge so that all changes are accounted
 | |
|    * for when rerendering.
 | |
|    */
 | |
|   var change_function = beestat.debounce(function() {
 | |
|     self.rerender();
 | |
|   }, 10);
 | |
| 
 | |
|   beestat.dispatcher.addEventListener(
 | |
|     [
 | |
|       'cache.data.metrics',
 | |
|       'cache.thermostat'
 | |
|     ],
 | |
|     change_function
 | |
|   );
 | |
| 
 | |
|   beestat.component.card.apply(this, arguments);
 | |
| };
 | |
| beestat.extend(beestat.component.card.metrics, beestat.component.card);
 | |
| 
 | |
| beestat.component.card.metrics.prototype.rerender_on_breakpoint_ = true;
 | |
| 
 | |
| /**
 | |
|  * Decorate
 | |
|  *
 | |
|  * @param {rocket.Elements} parent
 | |
|  */
 | |
| beestat.component.card.metrics.prototype.decorate_contents_ = function(parent) {
 | |
|   if (beestat.cache.data.metrics === undefined) {
 | |
|     parent.appendChild($.createElement('div').style('height', '100px'));
 | |
|     this.show_loading_('Fetching');
 | |
|   } else {
 | |
|     /**
 | |
|      * An entry for every possible metric is always returned for clarity.
 | |
|      * Remove the children with no data and then the parents with no children.
 | |
|      */
 | |
|     this.filtered_metrics_ = {};
 | |
|     let metric_count = 0;
 | |
|     for (const parent_metric_name in beestat.cache.data.metrics) {
 | |
|       for (const child_metric_name in beestat.cache.data.metrics[parent_metric_name]) {
 | |
|         if (beestat.cache.data.metrics[parent_metric_name][child_metric_name] !== null) {
 | |
|           if (this.filtered_metrics_[parent_metric_name] === undefined) {
 | |
|             this.filtered_metrics_[parent_metric_name] = {};
 | |
|           }
 | |
|           this.filtered_metrics_[parent_metric_name][child_metric_name] = beestat.cache.data.metrics[parent_metric_name][child_metric_name];
 | |
|           metric_count++;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (metric_count === 0) {
 | |
|       this.decorate_empty_(parent);
 | |
|     } else {
 | |
|       let column_count = 1;
 | |
|       if (beestat.width > 1000) {
 | |
|         column_count = 3;
 | |
|       } else if (beestat.width > 800) {
 | |
|         column_count = 2;
 | |
|       }
 | |
|       const column_span = 12 / column_count;
 | |
| 
 | |
|       const columns = [];
 | |
|       const row = $.createElement('div').addClass('row');
 | |
|       parent.appendChild(row);
 | |
| 
 | |
|       for (let i = 0; i < column_count; i++) {
 | |
|         const column = $.createElement('div')
 | |
|           .addClass([
 | |
|             'column',
 | |
|             'column_' + column_span
 | |
|           ]);
 | |
|         row.appendChild(column);
 | |
|         columns.push({
 | |
|           'size': 0,
 | |
|           'element': column
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       const get_smallest_column = function() {
 | |
|         let smallest_column = columns[0];
 | |
|         columns.forEach(function(column) {
 | |
|           if (column.size < smallest_column.size) {
 | |
|             smallest_column = column;
 | |
|           }
 | |
|         });
 | |
| 
 | |
|         return smallest_column;
 | |
|       };
 | |
| 
 | |
|       for (const parent_metric_name in this.filtered_metrics_) {
 | |
|         const group_size = Object.keys(this.filtered_metrics_[parent_metric_name]).length;
 | |
|         const smallest_column = get_smallest_column();
 | |
|         this.decorate_group_(smallest_column.element, parent_metric_name);
 | |
|         smallest_column.size += group_size;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Put a message in there if no data is present.
 | |
|  *
 | |
|  * @param {rocket.Elements} parent Parent
 | |
|  */
 | |
| beestat.component.card.metrics.prototype.decorate_empty_ = function(parent) {
 | |
|   parent.appendChild($.createElement('p').innerText('We couldn\'t generate any metrics for your system. Try broadening your comparison settings and ensuring your system type and thermostat address are properly set.'));
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Decorate a group of metrics.
 | |
|  *
 | |
|  * @param {rocket.Elements} parent Parent
 | |
|  * @param {string} parent_metric_name The name of the group.
 | |
|  */
 | |
| beestat.component.card.metrics.prototype.decorate_group_ = function(parent, parent_metric_name) {
 | |
|   const parent_metric = this.filtered_metrics_[parent_metric_name];
 | |
| 
 | |
|   const title = parent_metric_name
 | |
|     .replace(/_/g, ' ')
 | |
|     .replace(/^(.)|\s+(.)/g, function($1) {
 | |
|       return $1.toUpperCase();
 | |
|     });
 | |
| 
 | |
|   parent.appendChild($.createElement('p').innerText(title));
 | |
| 
 | |
|   const metric_container = $.createElement('div');
 | |
|   parent.appendChild(metric_container);
 | |
| 
 | |
|   for (const child_metric_name in parent_metric) {
 | |
|     const div = $.createElement('div')
 | |
|       .style({
 | |
|         'background': beestat.style.color.bluegray.dark,
 | |
|         'margin-bottom': beestat.style.size.gutter / 4
 | |
|       });
 | |
|     metric_container.appendChild(div);
 | |
|     (new beestat.component.metric[parent_metric_name][child_metric_name](this.thermostat_id_)).render(div);
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Get the title of the card.
 | |
|  *
 | |
|  * @return {string} The title of the card.
 | |
|  */
 | |
| beestat.component.card.metrics.prototype.get_title_ = function() {
 | |
|   return 'Metrics';
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Decorate the menu.
 | |
|  *
 | |
|  * @param {rocket.Elements} parent
 | |
|  */
 | |
| beestat.component.card.metrics.prototype.decorate_top_right_ = function(parent) {
 | |
|   const menu = (new beestat.component.menu()).render(parent);
 | |
| 
 | |
|   menu.add_menu_item(new beestat.component.menu_item()
 | |
|     .set_text('Help')
 | |
|     .set_icon('help_circle')
 | |
|     .set_callback(function() {
 | |
|       window.open('https://doc.beestat.io/ebfdf00f7f34436c980cd6344a767a12');
 | |
|     }));
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Get the subtitle of the card.
 | |
|  *
 | |
|  * @return {string} The subtitle.
 | |
|  */
 | |
| beestat.component.card.metrics.prototype.get_subtitle_ = function() {
 | |
|   const thermostat = beestat.cache.thermostat[this.thermostat_id_];
 | |
| 
 | |
|   // If the profile has not yet been generated.
 | |
|   if (thermostat.profile === null) {
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   const generated_at_m = moment(
 | |
|     thermostat.profile.metadata.generated_at
 | |
|   );
 | |
| 
 | |
|   let duration_text = '';
 | |
| 
 | |
|   // How much data was used to generate this.
 | |
|   const duration_weeks = Math.round(thermostat.profile.metadata.duration / 7);
 | |
|   duration_text += ' from the past ';
 | |
|   if (duration_weeks === 0) {
 | |
|     duration_text += ' few days';
 | |
|   } else if (duration_weeks === 1) {
 | |
|     duration_text += ' week';
 | |
|   } else if (duration_weeks >= 52) {
 | |
|     duration_text += ' year';
 | |
|   } else {
 | |
|     duration_text += duration_weeks + ' weeks';
 | |
|   }
 | |
|   duration_text += ' of data';
 | |
| 
 | |
|   return 'Generated ' + generated_at_m.format('MMM Do @ h a') + duration_text + ' (updated weekly).';
 | |
| };
 |