• MattFox

    Correct, look under API Docs -> Components -> maSerialChart
    They have a complete guideline of what attribute tags to use to apply values. You will want the series-x-values where the x is the chart number.
    The Chart update rate is affected by the maPointValues components which you can also read about. The realtime="true" attribute will allow datapoints to update into the chart at the rate they change or are updated.
    If you don't want to average, make sure you set the rollup type to NONE. Alternatively, use the rollup-interval to set the interval duration between datapoints in the chart, note that changing from the live updating rate may mean you;ll need to average.

    posted in Dashboard Designer & Custom AngularJS Pages read more
  • MattFox

    OK!
    As a starting point to work from. I'll work with you so you learn how it all works as you go...
    (All code is placed in the /opt/mango/overrides/web... directories)
    /modules/mangoUI/web/dev/components/settingsModal.js

    define(['angular', 'require'], function(angular, require) {
    'use strict';
    
    /* Date: 1/9/18
    	   Author: Matt "Fox" Fox
    	   Desc: component written to launch a modal dialog with either a built in template or just spit out a list of points to save one by one.
    	*/
    	settingsModalController.$inject = ['$mdDialog','maJsonStore'];
    		function settingsModalController ($mdDialog,maJsonStore)
    		{
    			var ctrl = this;
    			ctrl.mdDialog = $mdDialog;
    			ctrl.parsedOptions=[];
    			
    			ctrl.values={};
    			
    			this.$onInit = function()
    			{
    				if(this.points && !angular.isArray(this.points))
    				{
    					console.log('Error: points field not an array of point objects');
    				}
    				if(this.pointOptions && !angular.isArray(this.pointOptions) )
    				{
    					console.log('Error: points options field not an array');
    				}
    				ctrl.clickOffClose = ctrl.clickOffClose===true?true:false;
    				
    				
    				
    				
    				
    			};
    			
    			this.$onChanges = function(e)
    			{
    				console.log(e);
    				checkPoints();
    			}
    			
    			function checkPoints()
    			{
    				ctrl.parsedOptions=[];
    				if(ctrl.points && angular.isArray(ctrl.points))
    				{
    					if(ctrl.pointOptions && angular.isArray(ctrl.pointOptions) )
    					{
    						var ptName,ptDesc;
    						for(var i=0; i<ctrl.points.length; i++)
    						{
    							ptName=ctrl.points[ i ].name;
    							ptDesc='';
    							if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('name') )
    							{
    								ptName = ctrl.pointOptions[ i ].name;
    							}
    							if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('desc') )
    							{
    								ptDesc = ctrl.pointOptions[ i ].desc;
    							}
    							ctrl.parsedOptions.push( {name:ptName,desc:ptDesc} );
    						}
    					}
    					else
    					{
    						for(var i=0; i<ctrl.points.length; i++)
    						{
    							ptName=ctrl.points[ i ].name;
    							ptDesc='';
    						
    							ctrl.parsedOptions.push( {name:ptName,desc:ptDesc} );
    						}
    					}
    				}
    				else if(ctrl.pointOptions && angular.isArray(ctrl.pointOptions) && !ctrl.points )
    				{	
    					var ptId, ptName, ptDesc;
    					for(var i=0; i<ctrl.pointOptions.length; i++)
    					{
    						if(ctrl.pointOptions[ i ] && !ctrl.pointOptions[ i ].hasOwnProperty('name') )
    						{
    							// ctrl.pointOptions=[];
    							ctrl.parsedOptions=[];
    							return;
    						}
    						ptId=i;
    						ptDesc='';
    						ptName=ctrl.pointOptions[ i ].name;
    						if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('id') )
    						{
    							ptId = ctrl.pointOptions[ i ].id;
    						}
    						if(ctrl.pointOptions[ i ] && ctrl.pointOptions[ i ].hasOwnProperty('desc') )
    						{
    							ptDesc = ctrl.pointOptions[ i ].desc;
    						}						
    						ctrl.parsedOptions.push( {id:ptId,name:ptName,desc:ptDesc} );
    					}
    				}
    			}
    			
    			/* DIALOG CODE */
    			ctrl.showDialogue = function(ev) {
    			   // ctrl.updateModals();
    			   if( ctrl.altTemplateUrl!==undefined  )
    			   {
    				   try
    				   {
    					   
    					ctrl.mdDialog.show({
    					  templateUrl:ctrl.altTemplateUrl, 
    					  parent: angular.element(document.body),
    					  targetEvent: ev,
    					  clickOutsideToClose: ctrl.clickOffClose
    					}).then(
    						function()
    						{
    							console.log('function if closed/hidden manually'); 
    						},
    						function()
    						{
    							console.log('function to fire if closed from clicking outside/cancelled');
    						}
    					);
    				   }catch(e){console.warn(e);}
    			   }
    			   else
    			   {
    				   try{
    					   
    					ctrl.mdDialog.show({
    					  contentElement: '#settingsModal',
    					  parent: angular.element(document.body),
    					  targetEvent: ev,
    					  clickOutsideToClose: ctrl.clickOffClose
    					}).then(
    						function()
    						{
    							console.log('function if closed manually'); 
    						},
    						function()
    						{
    							console.log('function to fire if closed from clicking outside/cancelled');
    						}
    					);
    				   }catch(e){console.warn(e);}
    				}
    			};
    			
    			ctrl.hideDialogue = function() {
    				ctrl.mdDialog.hide();
    			};
    
    			ctrl.cancel = function() {	  
    				ctrl.mdDialog.cancel();
    			};
    			/* DIALOG CODE END*/
    			
    			/* JSON Store Stuff: */
    			ctrl.saveToStore = function(data=null)
    			{
    				
    				var item = maJsonStore.newItem( ctrl.jsonStore.toLowerCase() );
    				item.jsonData = data===null ? ctrl.values : data;
    				item.readPermission= "user";
    				item.editPermission= "user"; //can change this at your leisure or we can break it out into a setting...
    				
    				var r = item.$save();
    				
    				if(r.status)
    				{ 
    				}
    				else
    				{ 
    				}
    			};
    			
    			ctrl.loadFromStore = function()
    			{
    				maJsonStore.get({xid: ctrl.jsonStore.toLowerCase() }).$promise.then(function(item) {
    				ctrl.values = item.jsonData;
    			});
    			/* JSON Store Stuff END: */
    			};
    			
    			/* Virtual Point Save stuff */
    			ctrl.saveToPoint = function()
    			{
    				if(ctrl.savePoint===undefined)
    				{
    					alert('Point to save to not set as attribute!');
    					return;
    				}
    				ctrl.savePoint.setValue( JSON.stringify(ctrl.values) );
    			};	
    			
    			/* Virtual Point Save stuff END */
    	}
    		
    		
    		
    	
    	var settingsModal={
    		bindings:{
    			jsonStore: '<?', 		//Store name to save settings to
    			savePoint: '<?', 		//alternatively, save my JSON to a virtual pt, MUST BE TYPE DATAPOINT...
    			altTemplateUrl:'=?', 	//If we want to use the popup to show something else: use this template...
    			modalTitle:'=?', 		//seemed like a good idea at the time... will only work if altTemplateUrl is empty
    			clickOffClose:'=?', 	//set to true to click outside modal to shut it
    			pointOptions:'<?', 	//Alternate names for points,  (object array) [{id:'',name:'',desc:''}], id used for key name if using json/virtual point save
    			points: '<?',			 //Array of points to set individually
    		},
    		controller: settingsModalController,
    		templateUrl:'/modules/mangoUI/web/dev/views/modalDemo.html'
    	};
    	
    	return settingsModal;
    });
    

    and the template markup to add:
    /modules/mangoUI/web/dev/views/modalDemo.html

     <ma-button  hue="hue-2" palette="primary" label="Open Dialogue" ng-click="$ctrl.showDialogue()" raised="true"></ma-button>
     <div ng-if="!$ctrl.altTemplateUrl" style="visibility: hidden">
        <div class="md-dialog-container" id="settingsModal">
          <md-dialog layout-padding>
    			<md-dialog-actions><md-button ng-if="!$ctrl.clickOffClose" ng-click="$ctrl.cancel()" class="md-primary">x</md-button></md-dialog-actions>
     <div ng-if="!$ctrl.points && !$ctrl.parsedOptions">
    		Custom markup needed!
    		</div>
    		 
           <h1 ng-if="$ctrl.modalTitle!==undefined">{{$ctrl.modalTitle}}</h1> <small ng-if="$ctrl.clickOffClose">Click outside dialogue to close</small>
    		
    		<div ng-if="$ctrl.points">
    		<md-input-container ng-repeat="(index,point) in $ctrl.points" style="display:block;width:100%;">
    	   {{$ctrl.parsedOptions[index].name}}
    			<br/>	
    	   {{$ctrl.parsedOptions[index].desc}}
    			<br/>	
    			
    		<span style="display:inline-block;">Current Value: <ma-point-value style="display:inline-block;" point="point" ></ma-point-value></span>
    		 <ma-set-point-value  point="point" show-button="true"></ma-set-point-value> 
    		</md-input-container>
    		</div>
    		<div ng-if="!$ctrl.points && $ctrl.parsedOptions.length>0">
    			<md-input-container ng-repeat="input in $ctrl.parsedOptions">
    			{{input.name}}<br/>{{input.desc}}
    			<input ng-model="$ctrl.values[ input.id ]"/>
    			</md-input-container>
    		</div>
    		
          </md-dialog>
        </div>
      </div>
    

    More than happy to help you work through this (it will be a bit of a crash course)
    I've not added the buttons on the template for saving using a virtual point or JSON store, but that can be added quite easily.
    Basically you can generate a popup which will populate with inputs that can be named, given an ID and a description if necessary. This can also be used to override point names to more 'user friendly' equivalents for your users if they're filling out items in the dialogue box.

    inside the userModule.js directory (assuming that's the name of the file you've followed from Jared's tutorial) you'll want this structure:

    /userModule.js
    /components/settingsModal.js
    /views/modalDemo.html

    and inside userModule.js you'll want this:

    define(['angular', 'require','./components/settingsModal.js'], function(angular, require,settingsModal) {
        'use strict';
     var userModule = angular.module('userModule', ['maUiApp']);
    try {	
    	userModule.component('settingsModal', settingsModal);
    }
    catch(e){console.log(e);}	
        return userModule;
    });
    

    Markup in the dashboard page builder will be:

    <settings-modal point-options="[{id:'test',name:'input 1',desc:'input test 1'},{id:'test2',name:'input 2',desc:'input test 2'}]" points="vp" click-off-close="true"></settings-modal>
    

    See if you can get the popup showing for you first. I'm using 3.4.1 so I'm not completely sure if this will be affected in your version of mangoUI...

    Fox

    EDIT: sorry I'll be sure to add some more code comments later...
    New Edit: added data to save to store as an optional argument

    posted in Wishlist read more
  • MattFox

    This will be a handy post for those who are running cloud hosted solutions as there isn't a mangoES settings section for custom installs.

    posted in User help read more
  • MattFox

    Fixed, just mixed up the full path of the file with the userModule URL after closer inspection.

    posted in User help read more
  • MattFox

    @psysak If youn mean you have a mango unit publishing data and you want to be able to set back the other way, The only way to do so is to create a publisher going back the other way. That way when you set the datapoint on the mango unit receiving the published data the changes are pushed back to the initial mango unit doing the publishing. This does mean you would have a new datasource to capture and hold the set data.

    posted in User help read more
  • MattFox

    Seeing how amcharts have kindly given the source code on how to do this; you would need to get your required data points. Use a get point values query for the respective data points required. Use a "1 YEARS" AVERAGE/SUM rollup if you have multiple values for a given year depending on what you are calculating.

    Next write an angular component/directive which creates a time-line pie instance, and format the incoming point values with their points into the
    "[ 'year' : [ { 'value' : 'datapointValue1', 'label': 'point 1 name'}, { 'value' : 'datapointValue2, 'label': 'point 2 name'} ]" format.

    The supplied source code on amcharts will enable you to create animate effects etc.
    To get yourself started, I suggest you look at Jared's pie chart directive then build on top of that in a new file, just be sure to change the name from pieChart to timePieChart so you don't cause any problems with the native UI components.

    Hope that helps!

    Fox

    posted in Dashboard Designer & Custom AngularJS Pages read more
  • MattFox

    I can tell you that the ma-gauge-chart tag is an angularJS component so it will not show anything between the tags, and thus not be rendered.
    Units usually show if you have set the unit field on the individual datapoint under /data_sources.shtm.
    Feel free to take screenshots and describe further what you are trying to accomplish.

    Fox

    posted in User help read more
  • MattFox

    correct, you need to user the strictMinMax:true property to force the axes to be a given range

    posted in Dashboard Designer & Custom AngularJS Pages read more
  • MattFox

    OK! Here is what the code would be like:
    You need to have a directory structure like this to make it work with my code:
    Use winscp to connect with SSH to your mango install.
    -/opt/mango/overrides/web/modules/mangoUI/web/userModule
    |->/opt/mango/overrides/web/modules/mangoUI/web/userModule/userModule.js
    |->->/opt/mango/overrides/web/modules/mangoUI/web/userModule/directives/gaugeChart.js

    Once configured, make sure you add userModule.js to the administration->UI Settings page under user module url.
    enter this:

    /modules/mangoUI/web/userModule/userModule.js
    

    in the userModule.js file paste this code:

    define(['angular', 'require','./directives/gaugeChart.js'], function(angular, require,gaugeChart) {
    var userModule = angular.module('userModule', ['maUiApp']);
    try
    {
    userModule.directive('gaugeChart', gaugeChart);
     return userModule;
    }catch(e){console.log(e);}
    });
    

    In the directives file, use the code in the post above.

    Now, to use this in your dashboard, simply do the same as above, except the tag would just be 'gauge-chart'

     <gauge-chart id="44cf2d0c-c777-41e0-b20d-ea11a3f9f0cb" style="position: absolute; width: 200px; height: 200px; left: 145px; top: 8px;" point-xid="DP_866585" start="180" end="260" 
      options="{
    	axes: [ {
        axisThickness: 1,
        axisAlpha: 0.2,
        tickAlpha: 0.2,
        valueInterval: 5,
        bands: [ {
          color: '#cc4748',
          endValue: 191,
          startValue: 180
        }, {
          color: '#fdd400',
          endValue: 202,
          startValue: 191
        }, {
          color: '#84b761',
          endValue: 232,
          innerRadius: '95%',
          startValue: 202
        }, {
          color: '#fdd400',
          endValue: 232,
          startValue: 234
        }, {
          color: '#cc4748',
          endValue: 260,
          startValue: 234
        }],
        bottomText: '[[value]] km/h',
        bottomTextYOffset: 0,
        startValue:180,
        endValue: 260
      } ]
    }
    "></gauge-chart>
    

    posted in Dashboard Designer & Custom AngularJS Pages read more
  • MattFox

    /ui/docs/ng-mango/ma-serial-chart
    

    Read the docs under API Docs -> components -> maSerialChart

    there's an attribute you can set to alter the format:

    time-format
    (optional)
    string	
    The moment.js time format to be used in displaying timestamps on the X axis.
    

    Put your moment.js format in there and that will let you set the format to 'DD mm' etc

    posted in Mango Automation general Discussion read more
  • MattFox

    Thanks for doing this on such short notice Jared

    posted in Dashboard Designer & Custom AngularJS Pages read more
  • MattFox

    @joshua-keeler I've done something which allows you to 'toggle' the visibility of charts within an amchart serial chart with a push buitton. You could also use the same code to fire when each chart initialises...
    With your situation, we can just force hide the required charts on page load, so the data is still there. Saves you having to make a call and pull data then updating the chart. This however, is all from an AngularJS controller.

    Alternatively, with the version of amcharts we have now, you can apply CSS classes to a graph.
    https://www.amcharts.com/kbase/toggling-stock-chart-graphs-via-css/

    Under the api docs for mango: [localhost|yourDomain]/ui/docs/ng-mango/ma-serial-chart
    you will see an attribute called 'series -x-etc'

    NOTE: you will be doing this via the markup view, not the dashboard designer view!

    For each item generated on the chart will be labelled with the class: amcharts-graph-series-x where X is the series number.
    So ensure you populate the serial-chart with individual series items rather than the points and values attributes.
    ie series-1-point="pt1" series-1-values="pt1Values"
    Next you will require a button to click for toggling your graph's visibility.

    	<button onclick="(function(){var el = document.getElementsByClassName('amcharts-graph-series-1');  console.log(el);  for (var i = 0; i < el.length; i++) {    el[ i ].style.display = '';  }})();" aria-label="Show Graph" > Show Graph</button> 
    	<button id="hideAll" onclick="(function(){  var el = document.getElementsByClassName('amcharts-graph-series-1');console.log(el);for (var i = 0; i < el.length; i++) {el[ i ].style.display = 'none';}})();" aria-label="Hide Graph" > Hide Graph</button> 
    
    

    Given the nature of using angularJS, this is bad practise and is supposed to be implemented through a controller. But as you're looking for a fix you can apply on the fly it will enable you to show and hide graphs.
    If you've got more than one set of graphs on the page, You can alter the name of the graph name using the 'graph-options' setting attribute as mentioned in the serial chart information on the mango API page.
    Just set the id value for each serial chart graph you're passing.

    graph-options="[ {id:'graph1'}, { id:'graph2 } ]"
    

    Then update each button you're using to hide by replacing amcharts-graph-series-1 with amcharts-graph-graph1
    It doesn't provide you with the ability to hide on load but unless you're confident with javascript and utilising the userModule extension as mentioned on https://help.infiniteautomation.com/getting-started-with-a-user-module/

    I am unable to help you futher.

    posted in Dashboard Designer & Custom AngularJS Pages read more
  • MattFox

    You can use in the text format settings for the respective points on the data sources page /data_sources.shtm (this applies to the rendered value only)
    0_1536611143189_2e34dbd7-bfcf-42e4-8481-71bf96c8bcc3-image.png
    Alternatively:
    Use
    <ma-get-point-value point-xid="DP_4d6ba9d6-116a-4922-9841-515a22710174" point="point"></ma-get-point-value>
    instead and with the point attribute use: {{parseInt(point.value)}} for only one decimal place use {{ point.value.toFixed(1)}}

    Plenty of resources are available in the vanilla javascript Math class:
    https://devdocs.io/javascript-math/

    Hope that helps

    Fox

    posted in How-To read more
  • MattFox

    @mrlucretius said in Fix Cursor-Point position on ma-serial-chart:

    Is this your favorite Flex reference: https://material.angularjs.org/latest/layout/introduction ??

    No I prefer using CSS and a mix of block, inline-block, and grid...
    However Flex is good for ensuring a fit to page view.

    I've made some tiny amendments like a missing flex parameter for the first row of charts. I've also made the charts fit the full width of the container otherwise everything looks lop sided. Same with your text. Have also left-aligned your text, can always make it right again if needs be,
    If you are able to provide more instruction as to how you want to it to look I can likely be of more assistance.

    <div class="ma-designer-root" id="jhodges">
        <ma-now output="time" update-interval="1 SECONDS"></ma-now>
    
    	<div flex layout="row" layout-xs="column">
            <div flex layout="column" >	
    	
            	<!-- ##################### chart1: meter 1 charts kWh ######################### -->
            
                <div id="title-m1-kWh">St. Clair Walker Middle  - Total kWh Generated</div>
                <ma-serial-chart id="chart-m1-kW" style="width:100%; height: 200px;" balloon="true" legend="true" series-1-point="pt_Meter1.kWh" series-1-values="pt_Meter1.kWh_Values" point-title="JHodges.Meter1.kWh" default-type="line" series-1-title="JHodges.Meter1.kWh" export="true">
                </ma-serial-chart>
            	
        	</div>
            <div flex layout="column">
            	
            	<!-- ##################### chart2: meter 1 charts kW ######################### -->
            
                <div id="title-m1-kW">St. Clair Walker - Realtime kW Generation</div>
                <ma-serial-chart id="chart-m1-kWh" style="width:100%; height: 200px;" balloon="true" legend="true" series-1-point="pt_Meter1.kW" series-1-values="pt_Meter1.kW_Values" point-title="JHodges.Meter1.kW" default-type="line" series-1-title="JHodges.Meter1.kW">
                </ma-serial-chart>
                
        	</div>
    	</div>
                
        <div flex layout="row" layout-xs="column">
            <div flex layout="column">	
    	
            	<!-- ##################### stats1 ######################### -->
                <div id="lb-m1-miles" style="width:100%; height: 25px; text-align: left;">Number of Miles Driven in a Car Annually Offset:</div>
                <ma-point-value id="dp-m1-miles" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_4e6c1706-9429-42da-9852-dcdcc74c72b2" enable-popup="hide"></ma-point-value>
            
                <div id="lb-m1-houses" style="width:100%; height: 25px; text-align: left;">Number of Annual House Energy Use Offset:</div>
                <ma-point-value id="dp-m1-houses" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_4d6ba9d6-116a-4922-9841-515a22710174" enable-popup="hide"></ma-point-value>
            	
                <div id="lb-m1-forest" style="width:100%; height: 25px; text-align: left;">Annual Acres of U.S. Forest Offset:</div>
                <ma-point-value id="dp-m1-forest" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_2dc969dd-e452-4ead-b321-b95d9e726058" enable-popup="hide"></ma-point-value>
            	
                <div id="lb-m1-co2" style="width:100%; height: 25px; text-align: left;">Annual Metric Tons of CO2 Offset:</div>
                <ma-point-value id="dp-m1-co2" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_b6888a31-5473-4af1-bb40-e300767de812" enable-popup="hide"></ma-point-value>
            
            </div>
            <div flex layout="column">
        	
            	<!-- ##################### gauges m1 ######################### -->
            
            	<div flex layout="row">
                    <div layout-xs="column">	
                        <ma-gauge-chart id="gauge-m1-irradiance" style="width: 200px; height: 200px;" point-xid="JHodges_DP_e0f6a6e0-1022-42af-8d0b-a7a87f0189ca" end="1300" start="0" interval="100" band3-color="rgb(0, 163, 0)" band3-end="1300" band2-end="800" band1-color="rgb(255, 0, 0)" band1-end="400"></ma-gauge-chart>  
                    </div>
                    <div layout-xs="column">	
            	        <ma-gauge-chart id="gauge-m1-kW" style="width: 200px; height: 200px;" point-xid="JHodges_DP_4d0640de-59a5-488c-8f90-6924dcf44be5" end="500" start="0" interval="100"></ma-gauge-chart>
            	    </div>
            	</div>
            </div>
        </div>	
        	
        	
    	<div flex layout="row" layout-xs="column">
            <div flex layout="column">	
    	
            	<!-- ##################### chart3: meter 2 chart kW ######################### -->
            
                <div id="title-m2-kWh">Elementary School - Total kWh Generated</div>
                <ma-serial-chart id="chart-m2-kW" style="width:100%; height: 200px;" balloon="true" legend="true" series-1-point="pt_Meter2.kWh" series-1-values="pt_Meter2.kWh_Values" point-title="JHodges.Meter2.kWh" default-type="line" series-1-title="JHodges.Meter2.kWh" export="true">
                </ma-serial-chart>
        	
    	    </div>
            <div flex layout="column">
        	
            	<!-- ##################### chart4: meter 2 chart kW ######################### -->
            
                <div id="title-m2-kW">Elementary School -  Realtime kW Generation</div>
                <ma-serial-chart id="chart-m2-kWh" style="width:100%; height: 200px;" balloon="true" legend="true" series-1-point="pt_Meter2.kW" series-1-values="pt_Meter2.kW_Values" point-title="JHodges.Meter2.kW" default-type="line" series-1-title="JHodges.Meter2.kW">
                </ma-serial-chart>
        	
            </div>
        </div>	
        
        <div flex layout="row" layout-xs="column">
            <div flex layout="column">	
        
                <!-- ##################### stats2 ######################### -->
                
                <div id="lb-m2-miles" style="width:100%; height: 25px; text-align: left;">Number of Miles Driven in a Car Annually Offset:</div>
                <ma-point-value id="dp-m2-miles" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_c1da17c5-d74e-4aac-8abb-206d6c659ca8" enable-popup="hide"></ma-point-value>
            	
                <div id="lb-m2-houses" style="width:100%; height: 25px; text-align: left;">Number of Annual House Energy Use Offset:</div>
                <ma-point-value id="dp-m2-houses" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_5a2e9fc3-f3f7-48b7-8deb-ea2b94acadf5" enable-popup="hide"></ma-point-value>
            	
                <div id="lb-m2-forest" style="width:100%; height: 25px; text-align: left;">Annual Acres of U.S. Forest Offset:</div>
                <ma-point-value id="dp-m2-forest" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_e2f44dbe-151d-43d3-a124-bb335bd1e81e" enable-popup="hide"></ma-point-value>
            	
                <div id="lb-m2-co2" style="width:100%; height: 25px; text-align: left;">Annual Metric Tons of CO2 Offset:</div>
                <ma-point-value id="dp-m2-co2" style="width: 90px; height: 25px; text-align: left;" point-xid="DP_627b4c23-461a-47f8-9d44-437d54b7128c" enable-popup="hide"></ma-point-value>
            
            	
            </div>
            <div flex layout="column">
        	
            	<!-- ##################### gauges m2 ######################### -->
            	 <div flex layout="row">
                    <div layout-xs="column">	
                    <ma-gauge-chart id="gauge-m2-irradiance" style="width: 200px; height: 200px;" point-xid="JHodges_DP_e0f6a6e0-1022-42af-8d0b-a7a87f0189ca" end="1300" start="0" interval="100" band3-color="rgb(0, 163, 0)" band3-end="1300" band2-end="800" band1-color="rgb(255, 0, 0)" band1-end="400"></ma-gauge-chart>
                    </div>
                    <div layout-xs="column">	
        	            <ma-gauge-chart id="gauge-m2-kW" style="width: 200px; height: 200px;" point-xid="JHodges_DP_1ec557de-0f77-4436-bf2c-3d276e4ccabf" end="500" start="0" interval="100"></ma-gauge-chart>
        	        </div>
                </div>   
            </div>
    	</div>
    	
    	    <!-- ##################### meter 1 ma-point-values ######################### -->
        
        <ma-point-values id="pt-m1-kWh" style="width:100%; height: 20px;" to="dateBar.to" from="dateBar.from" rollup-interval="{{dateBar.rollupIntervals + ' ' + dateBar.rollupIntervalPeriod}}" rollup="{{dateBar.rollupType}}" values="pt_Meter1.kWh_Values" point="pt_Meter1.kWh" point-xid="JHodges_DP_ec50e6e5-95bb-40f2-850c-96c7c712baa8">
        </ma-point-values>
            
        <ma-point-values id="pt-m1-kW" style="width:100%; height: 20px;" to="dateBar.to" from="dateBar.from" rollup-interval="{{dateBar.rollupIntervals + ' ' + dateBar.rollupIntervalPeriod}}" rollup="{{dateBar.rollupType}}" values="pt_Meter1.kW_Values" point="pt_Meter1.kW" point-xid="JHodges_DP_4d0640de-59a5-488c-8f90-6924dcf44be5">
        </ma-point-values>
    
        <!-- ##################### meter 2 ma-point-values ######################### -->
        
        <ma-point-values id="pt-m2-kWh" style="width:100%; height: 20px;" to="dateBar.to" from="dateBar.from" rollup-interval="{{dateBar.rollupIntervals + ' ' + dateBar.rollupIntervalPeriod}}" rollup="{{dateBar.rollupType}}" values="pt_Meter2.kWh_Values" point="pt_Meter2.kWh" point-xid="JHodges_DP_c56ff01c-a145-408d-bdfb-65322622c164">
        </ma-point-values>
            
        <ma-point-values id="pt-m2-kW" style="width:100%; height: 20px;" to="dateBar.to" from="dateBar.from" rollup-interval="{{dateBar.rollupIntervals + ' ' + dateBar.rollupIntervalPeriod}}" rollup="{{dateBar.rollupType}}" values="pt_Meter2.kW_Values" point="pt_Meter2.kW" point-xid="JHodges_DP_1ec557de-0f77-4436-bf2c-3d276e4ccabf">
        </ma-point-values>
    
    </div>
    

    Fox

    posted in How-To read more
  • MattFox

    There is a way, but it involves only going as far as hiding the menu item. it doesn't remove the link in it's entirety.
    If that will suffice you will need to make a copy of the ui.main.js from
    /opt/mango/web/modules/mangoUI/web directory into the
    /opt/mango/overrides/web/modules/mangoUI/web What I did to get around it is search for the user menu item and insert into the <md-menu-item> at

    <md-menu-item >\n              <md-button aria-label="{{\'ui.app.userProfile\'|maTr}}" ui-sref="ui.settings.users({username: User.current.username})">\n                <md-icon md-menu-align-target>person</md-icon>\n                <span ma-tr="ui.app.userProfile"></span>\n              </md-button>\n            </md-menu-item>\n 
    

    ng-if="User.current.username==\'admin\'"

    So that only admin can see it.
    Dunno if that answers the question. But sometimes a hack is all you need...
    Would be keen to know Phil's thoughts...

    posted in How-To read more
  • MattFox

    That wholly depends on your preferred context setting. If you want updates with the timestamp, use update for the context, otherwise set to change instead.

    change the dropdown under the meta point script for context to only work on changes as opposed to value updates.

    0_1538946589483_7a30d5ed-c6a2-4b33-abb0-4d89389f6d5f-image.png

    To
    0_1538946615470_c7b58929-268f-4850-9571-0150e6754fa2-image.png

    However to make things easier for yourself and ensure your values are the same and prevent running code as well, you could run a series of if statements to check if

    point.value!==point.lastValue
    

    and simply return the metapoint's current value if the statement is false.

    That's my ten cents worth.

    Fox

    posted in User help read more
  • MattFox

    Far from it, if you have a solution that can benefit someone, show it and give examples. That's what this forum is for. All I am saying is that not everyone is comfortable as soon as you start mentioning filters or components etc.
    Yes what you have done works but sometimes simplicity is key.

    posted in How-To read more
  • MattFox

    You'll likely need to do this:
    <ma-point-query query="'in(tags.username,'+user.current.username+')&sort(deviceName)&limit(200)'" points="userPoints">/<ma-point-query>

    posted in Dashboard Designer & Custom AngularJS Pages read more
  • MattFox

    SSH with preshared keys will enable this - this is assuming the target PC runs linux. Otherwise you'd need an open ssh server running in windows. Next, your target PC would have to have Python installed in order to run the scripts you want to fire.
    Make sure you have a mango user on the target pc. Set up SSH keys with puttygen and save the public key into the destination PC's user .ssh directory.
    Store the commands in a bash script and execute the bash script from mango. it should SSH in, execute the script you need
    on the remote pc then log out.

    I'm breezing over a lot of detail here, as I'm not sure how acquainted you are with these systems. Let me know where things seem a bit confusing.

    posted in User help read more