• ThomasEinasto ThomasEinasto

    Hi @cwangv ,

    From and To objects are actually date objects in Javascript made using MomentJS if I am not mistaken.

    https://momentjs.com/

    Mango uses date-picker which is hooked into the header if page is configured to use date-picker on this page.

    https://material.angular.io/components/datepicker/overview

    By utilizing these previous two ma-date-picker is created.

    ValueOf represents ms of the presented date in epoch.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueOf

    Date picker then creates a date object which can be used in amCharts date axis (typically x axis).

    Example:

    https://www.amcharts.com/demos/date-based-data/

    AmCharts is then used to create a chart for us following amCharts documentation in here:

    https://docs.amcharts.com/3/javascriptcharts/ValueAxis << See all sub-sections on the left to see all the properties of the Chart itself. All can be hooked into ma-serial-chart.

    To solve the confusion IAS staff has created ma-serial-chart compontent which solves all programming and helps user to create charts without going into details what is actually happening.

    Actually a lot of information about the tools is written in API Docs with examples and links to all information.

    posted in How-To read more
  • ThomasEinasto ThomasEinasto

    Hi @benaznbe!

    As @phildunlap suggested, you should take a look at that forum thread on how to create your own customized module.

    You can see that you are limited for 10 series by using mangos own component.

    In mango 3.x you can access user module page in Administration -> UI settings. Scroll down until you find Miscellaneous settings. There you can find User module URL. Click on the paperclip and click + sign on top right corner.

    ref: https://help.infiniteautomation.com/getting-started-with-a-user-module/

    The following is taken from this forum post https://forum.infiniteautomation.com/topic/2862/bar-chart-category-as-x-axis/15 .

    Thank @Jared-Wiltshire for input.

    Create filename usermodule.js. Add following to there.

    define(['angular', 'require', 'amcharts/serial'], function(angular, require, AmCharts) {
    'use strict';
    
    var userModule = angular.module('userModule', ['maUiApp']);
    userModule.component('categoryXAxis', {
        bindings: {
            values: '<?',
        },
        controller: ['$scope', '$element', function($scope, $element) {
            const options = {
              "type": "serial",
              "theme": "light",
              "addClassNames": true,
              "marginRight": 70,
              "dataProvider": [],
              "valueAxes": [{
                "axisAlpha": 0,
                "position": "left",
                "title": "Level"
              }],
              "startDuration": 1,
              "graphs": [{
                "balloonText": "<b>[[category]]: [[value]]</b>",
                "fillColorsField": "color",
                "fillAlphas": 0.9,
                "lineAlpha": 0.2,
                "type": "column",
                "valueField": "level"
              }],
              "chartCursor": {
                "categoryBalloonEnabled": false,
                "cursorAlpha": 0,
                "zoomable": false
              },
              "categoryField": "INVxx",
              "categoryAxis": {
                "gridPosition": "start",
                "labelRotation": 45
              },
                "titles": [{
                 "text": "Production Chart"
             }]
            };
            
            const chart = AmCharts.makeChart($element[0], options);
    
            $scope.$watch('$ctrl.values', () => {
                chart.dataProvider = this.values;
                chart.validateData();
            }, true);
        }]
    });
    
    return userModule;
    
    }); // define
    
    
    userModule.component('categoryXAxis', {
    

    categoryXAxis string is defining the brackets of HTML. You can rename it as you like.

              "categoryField": "INVxx",
    

    Declares the variable name in an values array which describes labels of columns.

                "valueField": "level"
    

    Declares the variable in an values array which describes the value of the point.

    For making it dynamic and live

            $scope.$watch('$ctrl.values', () => {
                chart.dataProvider = this.values;
                chart.validateData();
            }, true);
    

    This looks at values variable change. see ref: https://www.sitepoint.com/mastering-watch-angularjs/

    For more customization see amCharts own documentation which @Jared-Wiltshire and @phildunlap promote all the time on the forums and in Mango. It has all the documentation for them.

    ref: https://www.amcharts.com/demos/simple-column-chart/

    Now press OK on the opened modal and press SAVE on top left corner of the UI Settings page.

    You have now created your own component called categoryXAxis.

    How can you use it on your own page?

    As @phildunlap said you probably do not need to use statistics to get last values of your points.

    <ma-get-point-value> 
    

    already does it for you

    So for your page I eliminated the statistics to make it more shorter. It is below

    <md-whiteframe id="graph2" align="center" style="position: absolute; left: 24px; top: 240px; width: 900px; height: 280px; background-color: rgb(255, 255, 255); border: 1px solid rgb(169, 169, 169); font-size: 20px; font-weight: bolder; color: rgb(1, 1, 1);">Production Chart
            <div style="display:none;" ng-init="myPreset='DAY_SO_FAR'"></div>
                <div ng-init="myInterval='1 minutes'"></div>
                <ma-date-range-picker style="display:none;" update-interval="{{myInterval}}" preset="{{myPreset}}" to="to" from="from"></ma-date-range-picker>
                <div id="14145" style="display:none;width: 500px; height: 35px; position: absolute; left: 800px; top: 700px;" layout="row">
                    <md-input-container flex=""> 
                    <label>From date</label>
                        <ma-date-picker format="DD-MM-YYYY" mode="both" ng-model="from"></ma-date-picker>
                        </md-input-container>
                        <md-input-container flex="">
                        <label>To date</label>
                        <ma-date-picker format="DD-MM-YYYY" mode="both" ng-model="to"></ma-date-picker>
                        </md-input-container>
        </div>
        
        <ma-get-point-value point-xid="INV01.DailyEnergy" point="point1"></ma-get-point-value>
        <ma-get-point-value point-xid="INV02.DailyEnergy" point="point2"></ma-get-point-value>
        <ma-get-point-value point-xid="INV03.DailyEnergy" point="point3"></ma-get-point-value>
        <ma-get-point-value point-xid="INV04.DailyEnergy" point="point4"></ma-get-point-value>
        <ma-get-point-value point-xid="INV05.DailyEnergy" point="point5"></ma-get-point-value>
        <ma-get-point-value point-xid="INV06.DailyEnergy" point="point6"></ma-get-point-value>
        <ma-get-point-value point-xid="INV07.DailyEnergy" point="point7"></ma-get-point-value>
        <ma-get-point-value point-xid="INV08.DailyEnergy" point="point8"></ma-get-point-value>
        <ma-get-point-value point-xid="INV09.DailyEnergy" point="point9"></ma-get-point-value>
        <ma-get-point-value point-xid="INV10.DailyEnergy" point="point10"></ma-get-point-value>
        <ma-get-point-value point-xid="INV11.DailyEnergy" point="point11"></ma-get-point-value>
        <ma-get-point-value point-xid="INV12.DailyEnergy" point="point12"></ma-get-point-value>
        <ma-get-point-value point-xid="INV13.DailyEnergy" point="point13"></ma-get-point-value>
        <ma-get-point-value point-xid="INV14.DailyEnergy" point="point14"></ma-get-point-value>
        <ma-get-point-value point-xid="INV15.DailyEnergy" point="point15"></ma-get-point-value>
        <ma-get-point-value point-xid="INV16.DailyEnergy" point="point16"></ma-get-point-value>
        <ma-get-point-value point-xid="INV17.DailyEnergy" point="point17"></ma-get-point-value>
        <ma-get-point-value point-xid="INV18.DailyEnergy" point="point18"></ma-get-point-value>
       
       <category-x-axis class="amchart"
       values="[{INVxx: point1.name, level: point1.value,color:'blue'}, 
                {INVxx: point2.name, level: point2.value,color:'red'}, 
                {INVxx: point3.name, level: point3.value,color:'green'}, 
                {INVxx: point4.name, level: point4.value,color:'gray'}, 
                {INVxx: point5.name, level: point5.value,color:'brown'}, 
                {INVxx: point6.name, level: point6.value,color:'orange'}, 
                {INVxx: point7.name, level: point7.value,color:'yellow'}, 
                {INVxx: point8.name, level: point8.value,color:'purple'}, 
                {INVxx: point9.name, level: point9.value,color:'blue'}, 
                {INVxx: point10.name, level: point10.value,color:'blue'} , 
                {INVxx: point11.name, level: point11.value,color:'blue'} , 
                {INVxx: point12.name, level: point12.value,color:'blue'} , 
                {INVxx: point13.name, level: point13.value,color:'blue'} , 
                {INVxx: point14.name, level: point14.value,color:'blue'} , 
                {INVxx: point15.name, level: point15.value,color:'blue'} , 
                {INVxx: point16.name, level: point16.value,color:'blue'} , 
                {INVxx: point17.name, level: point17.value,color:'blue'} , 
                {INVxx: point18.name, level: point18.value,color:'blue'}]">
       </category-x-axis>
       
        </md-whiteframe>
    

    ref: https://forum.infiniteautomation.com/topic/3503/how-to-chart-with-data-points-in-the-x-axis-instead-of-time

    I wish you good luck in all.

    Thomas

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

    Old UI topic

    Older users of Mango were using Legacy UI before Angular was introduced in Mango. But Mango legacy pages did not have so much flexibility / easy configuration to create your own system like you want which is probably why IAS took the direction for the Mango 3.x UI.

    Most simply said in Mango 3.x user is in a web-application developed in Angular which uses Mango (and other) API's/ libraries to configure Mango settings. The same way like in the old UI.

    You can go to legacy (old-UI) by going to lets say /data_sources.shtm to see how old Mango looked like. There on top left corner you can also see your overrides logo if I am not mistaken.

    File topic

    And you are correct. The uploaded file should stay in that folder if you update Mango. The file is actually put in $ROOT/filestore/public/ folder which is not modified by updates.

    Have a nice weekend!
    Thomas

    posted in User help read more
  • ThomasEinasto ThomasEinasto

    Dear Mango community,

    I don't know if it is the right forum section for this but it seemed like so.

    Sometimes while doing your Mango projects you might come into a situation where your clients cannot use Chrome or a modern browser due to the limitations of their own internal policy, be it some restrictions on computer usage or whatever.

    For that sometimes it is required to create your own cross-platform application which your client can use to get to their Mango instance. This actually creates your own application and you can distribute the application to your users while commissioning.

    NodeJS and Electron is quite good solution to solve this. Even better solution without having to learn all the steps in NodeJS and Electron is Nativefier.

    https://nodejs.org/en/download/
    https://github.com/jiahaog/nativefier

    Tutorial is on the github page above.

    This lets you create an cross-platform application for any website by just running one command on the NodeJS command line to create your own application easily.

    I am not the developer for this but just searching around the internet I stumbled upon a easy solution without having to learn really anything and thought it would be useful for the community.

    The post is made just to share to the community as there are many users who are not so good in modern web development but might come into these troubles while trying to sell your solution to your customer.

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

    Thanks @Jared-Wiltshire

    App works perfectly with buttons so that Mango is looking like a real app with buttons. Is it possible to inject them behind help button so that it would look better?

    0_1571163280269_1c745c87-661d-4435-a9ae-4d1b6f7a0dd2-image.png

    Anyone who is interested:

    Solved this by first creating preloader.js file in the folder where app will be created with following code. There are several options I guess but this was just one of the easiest to accomplish:

    function sd() {
    	const remote = require('electron').remote;
    	var currentwindow = remote.getCurrentWindow();
    	var logFn = console.log;
    
    console.log = function(arg1) {
    
       if (arg1 == 'close-electron'){
    	   
            let windows = remote.getCurrentWindow();
            windows.close();	
    		
       }else if (arg1 == 'maximize-electron'){
    	   
    	   if(currentwindow.isMaximized()){
    			let windows = remote.getCurrentWindow();
    			windows.unmaximize();
    	   }else{
    			let windows = remote.getCurrentWindow();
    			windows.maximize();
    	   }
    	   
       }else if (arg1 == 'minimize-electron'){
    	   
    	   let windows = remote.getCurrentWindow();
           windows.minimize();
    		
       }else{
    	   
    	   logFn(arg1)
    	   
       }
       
    }
    
    }
    
    sd();
    
    
    
    

    Following code actually rewrites console.log function to a custom function in a global scope within the application.

    Then add usermodule by modifying @Jared-Wiltshire usermodule like this:

    define(['angular', 'require'], function(angular, require) {
        'use strict';
    var electron = false;
    const userModule = angular.module('userModule', ['maUiApp','ngLocale']);
    
                    var userAgent = navigator.userAgent.toLowerCase();
                    console.log(userAgent)
                    if (userAgent == 'electron') {
                        electron = true
                    }else{
                        electron = false;
                    }
    if (electron){
        
        run.$inject = ['$rootScope', 'maTranslate', '$templateCache'];
        function run($rootScope, Translate, $templateCache) {
            const userActionsUrl = 'userActions.html';
            $templateCache.put(userActionsUrl,
                `
                <md-button class="md-icon-button" ng-click="minimize()">
                    <md-icon>more_horiz</md-icon>
                </md-button>
                <md-button class="md-icon-button" ng-click="maximize()">
                    <md-icon>fullscreen</md-icon>
                </md-button>
                <md-button class="md-icon-button" ng-click="close()">
                    <md-icon>close</md-icon>
                </md-button>`);
                
            $rootScope.userActions = userActionsUrl;
            $rootScope.close = () => {
                console.log('close-electron');
            };
            $rootScope.maximize = () => {
                console.log('maximize-electron');
            };
            $rootScope.minimize = () => {
                console.log('minimize-electron');
            };
        }
        
        userModule.run(run);     
        
    }      
            return userModule;
        
        }); // define
    

    This module actually console.logs commands which are analyzed in a function located in preloader.js file and only activates when userAgent is called 'electron' which we will define in a final function below.

    Add also your custom css in mango UI settings to make header draggable.

    .ma-ui-main-toolbar{
        
        -webkit-app-region: drag;
        
    }
    button {
        
        -webkit-app-region: no-drag;
        
    }
    md-input-container{
        -webkit-app-region: no-drag;
    }
    
    .ma-ui-tools > div[ng-include=userActions] {
      order: 1;
    }
    

    Finally, ensure that you are using nativefier version 7.6.10 so that injection actually would work correctly. Check your version with nativefier -v, should output as

    7.6.10
    

    If not then following command will allow you to install correct version from npm.

    npm install -g nativefier@7.6.10
    

    Now create app with following command:

    nativefier -u electron -e 2.0.8 http://url-to-mangoinstance --browserwindow-options "{ \"webPreferences\": { \"nodeIntegration\":true } }" --inject preloader.js --hide-window-frame
    

    -u specifies your useragent which is electron,
    -e specifies electron version (use 2.0.8 so that --inject would be successful.
    your link to the mango instance
    --browserwindows-options JSON string for specifing electron browser options. see https://electronjs.org/docs/api/browser-window#new-browserwindowoptions
    (we are using nodeIntegration to enable electron in front-end)
    --inject The file to inject to the page after DOM has loaded.
    --hide-window-frame Hide windows framing because we will be using mango header which css we have enabled in UI settings.

    You have now created the application for your Mango instance.

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

    Hi @sky_watcher

    I assume your external IP which you provided is your own modem IP (router). And your MangoES is connected into your local network. You should first see port forwarding to make it secure and to make your router forward remote connections to your ES. This is not good practice as you will be providing to everyone your router which is not a server per say.

    See, for more information-> https://portforward.com/

    Secondly you should buy a domain to get an human understandable address. https://www.sky_watcher.net for an example.

    After buying a domain you can assign this domain dns to be linked with your ip address. Then you would have to wait for a few hours after your dns settings have been updated through all dns servers.

    Then if you go to your bought domain name through your browser then the dns server which you are using for your computer will connect you remotely to your assigned IP address.

    More information is in available like this.
    https://www.ntchosting.com/encyclopedia/dns/ip-address/

    Thomas

    posted in Mango General read more
  • ThomasEinasto ThomasEinasto

    As reading through the help :

    When point value changes is the default logging setting. The point value and its time of occurrence is written to the database only if the value of the point actually changes. This setting provides the best compromise of quality of historical information vs storage space efficiency. For Numeric points, a Tolerance, or "deadband", can also be provided; the value will be logged if the absolute value of the difference between the present value and the previous value equals or exceeds the given tolerance.

    I would suggest to use The When point timestamp changes setting which is similar in behaviour to the on value change setting, but the timestamp of the sample is compared instead of the value to save all triggers to Mango database.

    Thomas

    posted in User help read more
  • ThomasEinasto ThomasEinasto

    Hi @Nomathamsanqa-Philiso

    You can create one dashboard page for your customers and then change the datapoint permissions according to your customer points. Log into your Mango instance as an admin. I hope you have created the datasources/datapoints for your clients.

    After logging in click on the users icon. ( 3rd icon from the left ) Then you have opened this: 0_1477064859909_upload-020c9a15-2a69-40db-b771-5e4393ac6227

    On the Edit user dropdown list you have an icon Add User. When clicked you will open up a new user details.

    Edit the Username, password, e-mail etc... Set the home URL as the link to the custom dashboard page. Change the permissions to some keyword which Mango uses to link the datapoints according to the user. e.g "Client1" or "Client2" etc... so that you will remember that the user permissions are linked that specific client. Then save the user.

    After that you have created a new user and then you can go and click on the Data point permissions where you can setup the points which the user can see. There you can filter the points by datasource name / xid etc.

    I have filtered the datasource as "Client1DataSource"

    0_1477065431591_upload-4687c80e-ae00-47c9-b360-a3dadec2bc61

    Then you can bulk apply permissions to the filtered points on the bottom of the page. I have my client setup as their permissions name "gases".

    0_1477065549962_upload-b4b4c786-9d2f-4a89-99fd-dccd86374692

    Then the client who logs into their session with the home url as the custom dashboard link can only see the points which have been assigned to them in their dashboard.

    Hope you understood the quick tutorial where I tried to explain the basics of the permissions. But I strongly suggest you take a look at the links which Will pointed you out in the previous post.

    Thomas,

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

    Hi @MattFox !

    Sorry for replying so late but I went with your suggestion on doing some programming for achieving the results which I need.

    I was pleased to see your requests / posts on the forum which pointed me to right directions while customizing for new directives.

    Mainly where @jared-wiltshire said in future defining of usermodule required scripts/functions help:

    https://github.com/infiniteautomation/ma-dashboards/blob/3.3.x/UI/web/ngMango/directives/PointValueController.js

    Which helped my a lot for customizing Mangos own directives in the future as for 3.3.x all the directives and components are in AMD/Require style which usermodules use.

    If someone have not noticed then this should be number one place to go to see how @Jared-Wiltshire has done the directives. https://github.com/infiniteautomation/ma-dashboards/blob/3.3.x/UI/web/ngMango/

    I'll put out the customized directive and component if someone wants to use prezooming, start-end date of the zoom for further data analysis.

    https://pastebin.com/8h4MV8B1

    I changed the dateformats from original as ngMango own directive uses other services etc.

    Function pointValueToString was taken from https://github.com/infiniteautomation/ma-dashboards/blob/3.3.x/UI/web/ngMango/services/Util.js

    Added bindings:

    End - takes timestamp of zoom end
    hours - takes a number of hours and then uses moment for subtracting the hours from end zoom.
    selected - Object output binding

    • selected.start >> zoomed chart start date
    • selected.end >> zoomed chart end date

    Example usage:

    <my-custom-mango-chart id="8ec0e029-4b0b-4f53-aa0d-6c25b4ds22sssdsdbfa991" style="position: absolute; left: 1058px; top: 1022px; width: 798px; height: 500px;"  series-1-values="tank1Values" series-1-point="tank1" series-1-type="line" series-1-color="blue" legend="true" balloon="true" cursor-sync-id="graphs" series-1-graph-options="{id:'graph-id-2'}" end="start2.time" hours="6" options="{ zoomOutText: '',chartScrollbar:{graph:'graph-id-2' }}">
    </my-custom-mango-chart>
    

    These dates can be used as variables for ma-point-statistics directive to get current selection statistics for example.

    As Angular is still quite hard I'll keep learnin and askin. But as @Jared-Wiltshire and all of you in IAS staff are publishing all online it is relatively easier to customize and learn.

    Huge thanks and cheers!

    Thomas

    posted in How-To read more
  • ThomasEinasto ThomasEinasto

    Hi @fleh

    It depends on what are you actually trying to do. In new UI it is simple. Go to Administration => UI settings and change logo source and it will be changed after you save your UI settings. Note that it should be in public folder because mango might restrict access to other parts of the system for not logged in users.

    If you want to change via overrides then you are mostly doing changes to the old UI and Mango system itself.

    posted in User help read more
  • ThomasEinasto ThomasEinasto

    Dear IAS staff,

    There is a bug in the modbus serial data point saving in the new UI (core 3.6.4, modbus 3.6.4, production).

    When trying to save a modbus point as anything else besides ASCII then it reverts back to ASCII after clicking save. As we have our own solution which we have sold in years which requires points to be saved as UTF-16, the new UI does not let us unfortunately.

    Example: make a fixed length string variable with 36 registers and try saving it in UTF-16BE.

    I can save it in legacy mode but then I guess I should not use the new UI after saving the points. And as copying in legacy is broken because it issues out that "Subclass DWRs must implement method to use" I guess I should bounce between legacy and new UI for creating similar points in the datasource.

    Edit: Or just export the JSON of the points and edit manually and then import the settings back. :)

    Console is also clean and does not show any errors after saving unfortunately. ( Tried using Chrome / Edge )

    Thomas

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

    Sure there is, look in the forums and you have a lot of information based on what object has permissions variable. i.e
    one can use User.current variable to see what user has been logged in and its options.

    Example:

    {"username":"admin","email":"admin@admin.net","oldHashAlgorithm":false,"grantedPermissions":["excelReports.fileStoreWritePermission","graphical.view.addView","internal.status","action.purgeAllPointValues","SNMP_MIB_STORE_READ","alarms.view","reports.view","graphical.view.upload","filestore.user.create","permissionDatasource","action.log4jUtil","excelreports.view","legacypointdetails.view","graphical.view","filestore.docs.read","dataFileDataSourceREST","watchlist.view","haystack.server","action.noSqlBackup","action.noSqlRestore","mailingLists.create","action.purgeAllEvents","datapointdetails.view","users.view","action.purgeUsingSettings","action.sqlRestore","action.excelReportPurge","SNMP_MIB_STORE_WRITE","filestore.docs.write","filestore.public.write","pointlinks.view","action.configurationBackup","action.reloadLinks","dataImport.view","filestore.core.read","action.reportPurge","permissions.user.editSelf","jsonData.create","permissions.superadmin","filestore.core.write","action.sqlBackup","excelReports.fileStoreReadPermission"],"sessionExpirationOverride":false,"sessionExpirationPeriod":null,"lastLogin":"2019-09-26T17:10:17.653+03:00","lastPasswordChange":"2019-04-17T11:15:25.795+03:00","validationMessages":null,"password":"","phone":"","disabled":false,"homeUrl":"/ui/administration/home","receiveAlarmEmails":"IGNORE","timezone":"","systemTimezone":"Europe/Tallinn","admin":true,"receiveOwnAuditEvents":false,"systemLocale":"en-US","passwordLocked":false,"muted":true,"id":1,"permissions":"superadmin","locale":"","name":"Administrator","originalId":"admin"}
    

    You can see that it has permissions variable. You can use this with ng-disabled directive of an md-switch to something like this

    <md-switch ng-disabled="User.current.permissions !== 'superadmin'" ng-model="myPoint.valueFn" ng-model-options="{getterSetter:true}"></md-switch>
    

    This switch is disabled if user does not have superadmin permissions. One can also leverage the ID of an user and use it like this so that you would not have to explicitly set the permissions to your required user.

    Cheers,
    Thomas

    posted in How-To read more
  • ThomasEinasto ThomasEinasto

    Hi Bela,

    I assume you are trying to use the new UI dashboards?

    If so take a look at /ui/examples/basics/style-via-value

    Following is there:

    <style>
        .default {
            background-color: black;
            color: white;
        }
    
        .good {
            background-color: green;
        }
    
        .warn {
            background-color: orange;
        }
    
        .bad {
            background-color: red;
        }
    </style>
    
    <ma-filtering-point-list ng-model="myPoint" auto-init="true" data-type="NUMERIC"></ma-filtering-point-list>
    
    <h3>CSS class based on range (numeric points)</h3>
    <div class="default" ng-class="{'good': myPoint.value < 100, 'warn': myPoint.value >= 100 &amp;&amp; myPoint.value < 200, 'bad': myPoint.value >= 200}">
        <label>Point value:</label>
        <ma-point-value point="myPoint"></ma-point-value>
    </div>
    
    <h3>CSS class based on exact value (multistate/binary points)</h3>
    <div class="default" ng-class="{'good': myPoint.value === 0, 'warn': myPoint.value === 1, 'bad': myPoint.value === 2}">
        <label>Point value:</label>
        <ma-point-value point="myPoint"></ma-point-value>
    </div>
    
    <h3>Hide/show based on value</h3>
    <div class="default good" ng-show="myPoint.value === 0">
        <label>Point value:</label>
        <ma-point-value point="myPoint"></ma-point-value>
    </div>
    <div class="default bad" ng-hide="myPoint.value === 0">
        <label>Point value:</label>
        <ma-point-value point="myPoint"></ma-point-value>
    </div>
    
    <h3>Switch based on value</h3>
    <div ng-switch="myPoint.value">
        <div ng-switch-when="0">Point is zero</div>
        <div ng-switch-when="1">Point is one</div>
        <div ng-switch-default>Point has other value</div>
    </div>
    

    Here is documentation about the directive used in example. https://docs.angularjs.org/api/ng/directive/ngClass

    Example about your case.

    <style>
    
        .default {
            background-color: black;
            color: white;
        }
    
        .ONclass{
            background-color: green;
        }
    
        .OFFclass {
            background-color: orange;
        }
    
    
    </style>
    <!-- Get our point from Mango -->
    <ma-get-point-value point-xid="MQTTdeviceXID" point="MQTTdevice"></ma-get-point-value>
    
    <div class="default" ng-class="{'ONclass': MQTTdevice.value === 'ON', 'OFFclass': MQTTdevice.value === 'OFF'}">
        <label>Point value:</label>
        <ma-point-value point="MQTTdevice"></ma-point-value>
    </div>
    
    

    One can also do it another way without using class but using ngStyle i.e https://docs.angularjs.org/api/ng/directive/ngStyle

    <!-- Get our point from Mango -->
    <ma-get-point-value point-xid="MQTTdeviceXID" point="MQTTdevice"></ma-get-point-value>
    
    <!-- if ON then green else red -->
    <div class="default" ng-style="{ background-color: MQTTdevice.value == 'ON' ? 'green' : 'red' }">
        <label>Point value:</label>
        <ma-point-value point="MQTTdevice"></ma-point-value>
    </div>
    
    

    posted in User help read more
  • ThomasEinasto ThomasEinasto

    Thanks @Jared-Wiltshire for helping out.

    This solved it, I edited the previous post for css also, so that users would be able to copy-paste without missing out the ordering.

    Final result :

    0_1571203579903_442354f8-87b5-455c-9e3f-8cb1682201f2-image.png

    Thomas

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

    I wanted to copy this response from years ago by you which I found by search but as Mango has changed over the years this was not working anymore.

    @jared-wiltshire said in User permissions to view pages:

    @shaun
    Phillip's post contains a lot of useful information. As he has indicated the best way to restrict users from seeing data they should not be seeing is to set the permissions on the data points and on the JSON store objects.

    However it is also very useful to hide certain navigation links inside your app so your users can't navigate to a page that they will not be able to access any data on. This can be done for menu items by adding a permission property to an object in the MENU_ITEMS array. If you need to hide something in the content of your page you can add a ng-show or ng-if directive, e.g. ng-show="user.hasPermission('superadmin')"

    But as Mango has changed over the years this function was not working anymore :), hence why I tried to provide the best solution I could leverage.

    posted in How-To read more
  • ThomasEinasto ThomasEinasto

    This is because you have no variable assigned to ng-class and currently you probably have multiple same conditions on multiple classes. i.e 'red-fill', 'blue-fill and 'green-fill' are assigned currently as 0?.

    Correct way would be something like this:

    <style>
    .grey-fill {
    fill: grey;
    }
    .red-fill {
    fill: red;
    }
    .blue-fill {
    fill: blue;
    }
    .green-fill {
    fill: green;
    }
    </style>
    
    <div class="ma-designer-root" id="445b6000b-362e-407f-aa27-05545fea5884" style="width: inherit; height: inherit; position: relative; bottom: inherit; left: inherit;">
    <ma-svg ng-include="'/rest/v2/file-stores/default/sss/demo.svg'">
    <div ma-selector="#t1" ng-class="{'grey-fill': point.value == 1, 'red-fill': point.value == 2, 'blue-fill': point.value == 3, 'green-fill': point.value == 4}"></div>
    </ma-svg>
    </div>
    

    See /ui/examples/basics/style-via-value for a correct example on how to use ng-class or https://docs.angularjs.org/api/ng/directive/ngClass

    posted in User help read more
  • ThomasEinasto ThomasEinasto

    Hi @Phillip-Weeks ,

    One can create a new usermodule component to handle like ng-init.

    userModule.component('gettime', {
        bindings:{
            timestampIn: '@?',
            tsFormat: '@?',
            newDateo: '=?',
            newDates: '=?'
        },
        controller:['$scope',
            function($scope){
    
                $scope.$watch('$ctrl.timestampIn', () => {
    
                    let dateobject = moment(this.timestampIn);
                    
                    let datestring = moment(this.timestampIn).format(this.tsFormat);
                    
                    if (typeof this.timestampIn !== "undefined"){
                        
                            this.newDateo = dateobject;
                            this.newDates = datestring;
                            
                            //console.log(typeof(this.newDateo)); << returns dateobject
                            //console.log(typeof(this.newDates)); << returns string
                    }
                    
                }, true);
            
            
        }]
        
    });
    
    

    new-dateo is date object which you should be able to use as your date.from / date.to variable.
    new-dates is date string which is formatted like you want based on momentjs format function.

    Usage in dashboard:

    <gettime timestamp-in="10/05/2019 22:10:10" ts-format="DD/MM/YYYY HH:mm:ss" new-dateo="js" new-dates="jss"></gettime>
    
    {{js}}
    <br>
    {{jss}}
    

    Result in dashboard:

    Sat Oct 05 2019 22:10:10 GMT+0300
    05/10/2019 22:10:10
    

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

    Hi,

    Does your customer want to use their existing MS SQL server as their Mango database? If so then I guess you are out of luck because to my knowledge mango can use 3 main types of databases: H2 (default), Derby, MySQL and also their own fast NoSQL database.

    If your customer wants to use their SQL server so that Mango gathers data from it then you should look into the SQL Datasource module which supports MS SQL server connection. As I have never used this module I cannot help but there is help in the datasource module if you click the blue questionmark while creating the datasource.

    Thomas

    posted in Mango Automation general Discussion read more
  • ThomasEinasto ThomasEinasto

    If I understand it correctly you would like to create some dialog window where you can override some settings or set some point values and then if user clicks outside of the window the window will close automatically.

    I would use md-dialog for something like that which Mango has...
    https://material.angularjs.org/latest/demo/dialog

    This however needs programming to be customized to your needs.

    Thomas

    posted in Wishlist read more
  • ThomasEinasto ThomasEinasto

    @steve-o said in Calculation using ^ (to the power of) in a Meta Data Point:

    (610.7*10^((7.5x23)/(237.3+23))/1000)

    Steve, what is your temp variable? Is it the name of your variable? Then you should use this:

    (610.7*Math.pow(10,((7.5*temp.value))/(237.3+23))/1000) 
    

    Following works as it should on math pow

    (610.7*Math.pow(10,((7.5*23))/(237.3+23))/1000) 
    // returns 2.808825816730143
    

    posted in User help read more