Yes, when I upgraded to 3.0 dashboards I also upgraded all the other modules that could be upgraded at the time. It included Mango API as well.
Best posts made by nyoa
-
RE: Custom dashboards v3.0 home page tutorials not working
Latest posts made by nyoa
-
RE: How to use mangos own login to secure an AngularJS custom dashboard
Thank you a lot brad! Thanks to your reference I got it working. I really can't thank you enough for sharing your experience here!
I also got a lot clearer idea of the new dashboard module thanks to this discussion.
So to summarize all the steps that a newbie like me had to take to get authentication work in my custom dashboard:
- Copy the files in adminTemplate (found at {mango root}\web\modules\dashboards\web) to my custom dashboard directory
- Change the content of my app.js directory to reflect brads.
- Copy the html data between the <body> tags in my old index.html to home.html found in views/dasboard/ directory
- Replace my old index.html file with adminTemplate index.html with the require line modified to point to my dashboard (eg. <script>require(['dashboards/fosfaattifosfori/app']);</script>)
- Changed my main.html to reflect what brad posted earlier
I believe steps 2 and 5 aren't necessary to get the thing working, but without those I'd have the side nav and the extra pages.
Thank you a lot for all the help you provided!
-
RE: How to use mangos own login to secure an AngularJS custom dashboard
Thank you a lot for your reference. I tried copying your app.js and see if it would work. It does the redirect to /#/login when the user is not logged in but the page shows my index.html for some reason. I'll upload a picture about the situation.
My index.html is the same it was before with the exception that the only require line I have includes the app.js.
-
RE: How to use mangos own login to secure an AngularJS custom dashboard
Thank you a lot. I've used your templates for creating the dashboard so 'mango-3.0/bootstrap' was a remnant from before copying app.js over. The login page isn't required to be standard for mango so it should be for the dashboard only.
export.js is there for my custom directives. I'll copy it's content here
/** * @copyright 2016 {@link http://infiniteautomation.com|Infinite Automation Systems, Inc.} All rights reserved. * @author Jared Wiltshire */ define([ 'angular', 'mango-3.0/maMaterialDashboards' ], function(angular, maMaterialDashboards) { 'use strict'; var myApp = angular.module('myApp', ['maMaterialDashboards']); myApp.run(['$rootScope', function($rootScope) { $rootScope.pi = function() { return Math.PI; } }]); myApp.directive('myCustomComponent', function() { return { restrict: 'E', scope: { name: '@' }, template: '<span>Hello {{name}}!</span>' }; }); myApp.controller('myCtrl',['$scope', $scope.exportData = function(values){ $scope.list = []; for (var i = 0, len = values.length; i < len; i++) { $scope.d = new Date(values*.timestamp); $scope.list.splice(0,0,{"timestamp":$scope.d.toLocaleString(),"value":values*.value}); }; }; }]); angular.element(document).ready(function() { angular.bootstrap(document.documentElement, ['myApp']); }); }); // define
I haven't done any changes to app.js, although it looks like I should change the "state: 'dashboard.home'" to point to the directory I have my index.html in?
Here is the content of app.js
/** * @copyright 2016 {@link http://infiniteautomation.com|Infinite Automation Systems, Inc.} All rights reserved. * @author Jared Wiltshire */ define([ 'angular', './directives/menu/menuLink', './directives/menu/menuToggle', './directives/login/login', 'mango-3.0/maMaterialDashboards', 'mango-3.0/maAppComponents', 'angular-ui-router', 'angular-loading-bar' ], function(angular, menuLink, menuToggle, login, maMaterialDashboards, maAppComponents) { 'use strict'; var myAdminApp = angular.module('myAdminApp', [ 'ui.router', 'angular-loading-bar', 'maMaterialDashboards', 'maAppComponents', 'ngMessages' ]); myAdminApp .directive('menuLink', menuLink) .directive('menuToggle', menuToggle) .directive('login', login); myAdminApp.constant('PAGES', [ { state: 'dashboard', url: '/dashboard', templateUrl: 'views/dashboard/main.html', resolve: { auth: ['$rootScope', 'User', function($rootScope, User) { $rootScope.user = User.current(); return $rootScope.user.$promise; }] } }, { state: 'login', url: '/login', templateUrl: 'views/login.html' }, { state: 'dashboard.home', url: '/home', templateUrl: 'views/dashboard/home.html', menuTr: 'dashboards.v3.dox.home', menuIcon: 'fa fa-home', menuType: 'link' }, { state: 'dashboard.apiErrors', url: '/api-errors', templateUrl: 'views/dashboard/errors.html', menuTr: 'dashboards.v3.dox.apiErrors' }, { state: 'dashboard.section1', url: '/section-1', menuText: 'Section 1', menuIcon: 'fa fa-building', menuType: 'toggle', children: [ { state: 'dashboard.section1.page1', templateUrl: 'views/section1/page1.html', url: '/page-1', menuText: 'Page 1', menuType: 'link' }, { state: 'dashboard.section1.page2', templateUrl: 'views/section1/page2.html', url: '/page-2', menuText: 'Page 2', menuType: 'link' } ] }, { state: 'dashboard.section2', url: '/section-2', menuText: 'Section 2', menuIcon: 'fa fa-bolt', menuType: 'toggle', children: [ { state: 'dashboard.section2.page1', templateUrl: 'views/section2/page1.html', url: '/page-1', menuText: 'Page 1', menuType: 'link' }, { state: 'dashboard.section2.page2', templateUrl: 'views/section2/page2.html', url: '/page-2', menuText: 'Page 2', menuType: 'link' } ] } ]); myAdminApp.config([ 'PAGES', '$stateProvider', '$urlRouterProvider', '$httpProvider', '$mdThemingProvider', '$injector', function(PAGES, $stateProvider, $urlRouterProvider, $httpProvider, $mdThemingProvider, $injector) { $mdThemingProvider .theme('default') .primaryPalette('yellow') .accentPalette('red'); $httpProvider.interceptors.push('errorInterceptor'); $urlRouterProvider.otherwise('/dashboard/home'); addStates(PAGES); function addStates(pages, parent) { angular.forEach(pages, function(page, area) { if (page.state) { var state = { url: page.url } if (page.menuTr) { state.menuTr = page.menuTr; } if (page.menuText) { state.menuText = page.menuText; } if (parent) { state.parentPage = parent; } if (page.templateUrl) { state.templateUrl = page.templateUrl; } else { state.template = '<div ui-view></div>'; state['abstract'] = true; } if (page.resolve) { state.resolve = page.resolve; } $stateProvider.state(page.state, state); } addStates(page.children, page); }); } }]); myAdminApp.run([ 'PAGES', '$rootScope', '$state', '$timeout', '$mdSidenav', '$mdColors', '$MD_THEME_CSS', function(PAGES, $rootScope, $state, $timeout, $mdSidenav, $mdColors, $MD_THEME_CSS) { $rootScope.pages = PAGES; $rootScope.Math = Math; // inserts a style tag to style <a> tags with accent color if ($MD_THEME_CSS) { var acc = $mdColors.getThemeColor('accent-500-1.0'); var accT = $mdColors.getThemeColor('accent-500-0.2'); var accD = $mdColors.getThemeColor('accent-700-1.0'); var styleContent = 'a:not(.md-button) {color: ' + acc +'; border-bottom-color: ' + accT + ';}\n' + 'a:not(.md-button):hover, a:not(.md-button):focus {color: ' + accD + '; border-bottom-color: ' + accD + ';}\n'; var style = document.createElement('style'); style.appendChild(document.createTextNode(styleContent)); document.head.appendChild(style); } $rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) { if (error && (error.status === 401 || error.status === 403)) { event.preventDefault(); $state.loginRedirect = toState; $state.go('login'); } }); $rootScope.$on("$stateChangeSuccess", function(event, toState, toParams, fromState, fromParams) { var crumbs = []; var state = toState; do { if (state.menuTr) { crumbs.unshift({maTr: state.menuTr}); } else if (state.menuText) { crumbs.unshift({text: state.menuText}); } } while (state = state.parentPage); $rootScope.crumbs = crumbs; }); $rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) { if ($state.includes('dashboard')) { $rootScope.closeMenu(); } }); $rootScope.closeMenu = function() { $mdSidenav('left').close(); } $rootScope.openMenu = function() { angular.element('#menu-button').blur(); $mdSidenav('left').open(); } }]); angular.element(document).ready(function() { angular.bootstrap(document.documentElement, ['myAdminApp']); }); }); // define
-
RE: How to use mangos own login to secure an AngularJS custom dashboard
Thank you for your fast replies. I followed Jareds advice and copied the files inside admin template to my dashboard folder at C:\Program Files\mango automation\overrides\web\modules\dashboards\web\FosfaattiFosfori
I also copied the head part of the template index.html to my own index.html and copied the modified require to the bottom of the file. I didn't quite get it to work with just this so there must be something I missed. It would be great if a custom dashboard login example was added to the tutorials! You have been doing a great job thus far!
Sometimes when not logged in it redirects me to the login page which is empty and sometimes the login page just loads my index data and displays it. It's quite weird.
Here is my index.html so you can check if there is something obviously wrong. I didn't touch either of the login files other than copying.
<!DOCTYPE html> <html lang="en" ma-app="maMaterialDashboards" class="no-js"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>JAMK Fosfaattianalysaattori</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes"> <link rel="icon" type="image/png" sizes="192x192" href="../img/icon192.png"> <link rel="icon" type="image/png" sizes="128x128" href="../img/icon128.png"> <link rel="apple-touch-icon" type="image/png" sizes="128x128" href="../img/icon128.png"> <link rel="apple-touch-icon" type="image/png" sizes="128x128" href="../img/icon128.png"> <link rel="manifest" href="manifest.json"> <link rel="stylesheet" type="text/css" href="tyylit.css"> <link rel="stylesheet" href="/resources/angular-csp.css"></link> <link rel="stylesheet" href="../vendor/angular-material/angular-material.css"> <link rel="stylesheet" href="../vendor/angular-loading-bar/loading-bar.css"> <link rel="stylesheet" href="../vendor/material-design-icons/iconfont/material-icons.css"> <link rel="stylesheet" href="../vendor/font-awesome/css/font-awesome.css"> <link rel="stylesheet" href="../vendor/mdPickers/mdPickers.css"> <link rel="stylesheet" href="../vendor/angular-material-data-table/md-data-table.css"> <link rel="stylesheet" href="styles/main.css"> </head> <body layout="column"> <div ng-if="appLoading"> <img src="images/loader.gif" alt="App loading.." style="margin-left:50%;margin-top:25%"> </div> <div id="maincontainer" ng-cloak> <header> <img src="images/jamkfi_tunnus_sininen_suomi.png" alt="jamk.fi" style="width:50%;height:50%;margin-left:25%;"> </header> <div id="textContainer"> <img src="images/header.jpg" alt="Fosfaattifosfori PO4-P [µg/l]" style="width:50%;height:50%;margin-left:25%;"> </div> <div> <ma-get-point-value point-xid="DP_355369" point="point1"></ma-get-point-value> <ma-point-values id="testi" point="point1" values="point1Values" from="from" to="to" rollup="AVERAGE" rollup-interval="1 minutes"> </ma-point-values> <ma-serial-chart id="chartti" style="height: 500px; width: 100%" series-1-values="point1Values" series-1-point="point1" options="{chartCursor:{categoryBalloonDateFormat:'YYYY-MM-DD HH:NN'}, chartScrollbar:{oppositeAxis: false, scrollbarHeight: 40,offset: 25, graph:'DP_355369'}}"> </ma-serial-chart> <div id = "control"> <div id="selectorDiv" layout="row"> <div class="selectorContainer"> <md-input-container flex="33" class="no-errors-spacer timeSelector"> <label>Date preset</label> <ma-date-range-picker from="from" to="to" preset="LAST_1_DAYS" update-interval="1 minutes"></ma-date-range-picker> </md-input-container> </div> <div class="selectorContainer"> <md-input-container flex="33" class="no-errors-spacer timeSelector"> <label>From date</label> <ma-date-picker ng-model="from"></ma-date-picker> </md-input-container> </div> <div class="selectorContainer"> <md-input-container flex="33" class="no-errors-spacer timeSelector"> <label>To date</label> <ma-date-picker ng-model="to"></ma-date-picker> </md-input-container> </div> </div> <div> <div> <md-button class="md-raised" ng-click="showStats=true;showData=false" ng-hide="showStats">Statistics</md-button> <md-button class="md-raised" ng-click="showStats=false;showData=false" ng-show="showStats">Statistics</md-button> <md-button class="md-raised" ng-click="showData=true;showStats=false" ng-hide="showData">Data</md-button> <md-button class="md-raised" ng-click="showData=false;showStats=false" ng-show="showData">Data</md-button> </div> <div ng-controller="myCtrl"> <md-button class="md-raised" ng-click="testi()">Push me</md-button> </div> <div layout="row" ng-show="showStats" class="ng-hide"> <ma-point-statistics point="point1" from="from" to="to" statistics="statsObj"></ma-point-statistics> <ma-statistics-table id="statsTable" statistics="statsObj"></ma-statistics-table> </div> <div layout="row" ng-show="showData" class="ng-hide"> <table width="100%" height="500px"> <thead> <tr> <th>Value</th> <th>Time</th> </tr> </thead> <tbody> <tr ng-repeat="item in point1Values"> <td>{{item.value}}</td> <td>{{item.timestamp | moment:'format':'lll' }}</td> </tr> </tbody> </table> </div> </div> </div> </div> </div> <script src="https://rawgithub.com/eligrey/FileSaver.js/master/FileSaver.js" type="text/javascript"></script> <script src="/resources/require.js"></script> <script src="/resources/loaderConfig.js"></script> <script src="../js/loaderConfig.js"></script> <script>require(['dashboards/fosfaattifosfori/app']);</script> <script type="text/javascript">require(['mango-3.0/bootstrap']);</script> <script type="text/javascript">require(['dashboards/fosfaattifosfori/export']);</script> </body> </html>
I'll upload a picture of my custom dashboard directory so you can tell if I've copied the right things. Thanks for all the help!
-
How to use mangos own login to secure an AngularJS custom dashboard
I believe it was mentioned in your new tutorials that one could use the mdAdmin page as a template which is secured to only allow logged in users, but how would you do the same functionality for your own dashboard? The login page itself seems to only contain some beautiful eye candy and an AngularJS element called <login>, So I should be able to use it as is in my own dashboard, but the thing I'm confused about is how to make the page require it.
If there is an existing demo that demonstrates how to do this I would be glad if someone pointed me to it.
-
RE: How to use my own AngularJS controllers with 3.0.1 dashboards?
I finally got it to work. Thank you a lot, this would have been quite a bit harder for me to achieve without your fast and accurate help!
-
RE: How to use my own AngularJS controllers with 3.0.1 dashboards?
Thank you for your help so far. Should my .js file look like this with the added custom function? I'm getting ReferenceError: $scope is not defined
/** * @copyright 2016 {@link http://infiniteautomation.com|Infinite Automation Systems, Inc.} All rights reserved. * @author Jared Wiltshire */ define([ 'angular', 'mango-3.0/maMaterialDashboards' ], function(angular, maMaterialDashboards) { 'use strict'; var myApp = angular.module('myApp', ['maMaterialDashboards']); myApp.run(['$rootScope', function($rootScope) { $rootScope.pi = function() { return Math.PI; } }]); myApp.directive('myCustomComponent', function() { return { restrict: 'E', scope: { name: '@' }, template: '<span>Hello {{name}}!</span>' }; }); myApp.controller('myCtrl',[$scope, function ($scope) { $scope.test = function(){ console.log('Logg meh'); }; }]); angular.element(document).ready(function() { angular.bootstrap(document.documentElement, ['myApp']); }); }); // define
Here is the HTML file just in case. I changed it to the template file because i thought it would be a lot easier to troubleshoot in case it was needed. The main thing I need right now in any case is to get the custom functions work before actually adding them to my dashboard
<!DOCTYPE html> <html lang="en" ma-app="maMaterialDashboards"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>My Custom App</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/resources/angular-csp.css"></link> <link rel="stylesheet" href="../vendor/angular-material/angular-material.css"> <link rel="stylesheet" href="../vendor/material-design-icons/iconfont/material-icons.css"> <link rel="stylesheet" href="../vendor/mdPickers/mdPickers.css"> </head> <body layout="column"> <div ng-if="appLoading"> <span>App is loading..</span> </div> <div ng-cloak layout="column" flex> <!-- Your content here --> <span>Pi is {{pi() | number:5}}.</span> <my-custom-component name="John Smith"><my-custom-component> </div> <div ng-controller="myCtrl"> <md-button class="md-raised" ng-click="test()">Push me</md-button> </div> <script src="/resources/require.js"></script> <script src="/resources/loaderConfig.js"></script> <script src="../js/loaderConfig.js"></script> <script type="text/javascript">require(['dashboards/fosfaattifosfori/export']);</script> </body> </html>
Thanks a lot for your help!
-
RE: How to use my own AngularJS controllers with 3.0.1 dashboards?
Thank you for a fast reply!
Here is my complete HTML file called index.html
<!DOCTYPE html> <html lang="en" ma-app="maMaterialDashboards"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>JAMK Fosfaattianalysaattori</title> <link rel="icon" href="/images/favicon.ico"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="tyylit.css"> <link rel="stylesheet" href="/resources/angular-csp.css"></link> <link rel="stylesheet" href="../vendor/angular-material/angular-material.css"> <link rel="stylesheet" href="../vendor/material-design-icons/iconfont/material-icons.css"> <link rel="stylesheet" href="../vendor/mdPickers/mdPickers.css"> </head> <body layout="column"> <div ng-if="appLoading"> <img src="loader.gif" alt="App loading.." style="margin-left:50%;margin-top:25%"> </div> <div id="maincontainer" ng-cloak> <header> <img src="jamkfi_tunnus_sininen_suomi.png" alt="jamk.fi" style="width:50%;height:50%;margin-left:25%;"> </header> <div id="textContainer"> <img src="header.jpg" alt="Fosfaattifosfori PO4-P [mg/l]" style="width:50%;height:50%;margin-left:25%;"> </div> <div> <ma-get-point-value point-xid="DP_355369" point="point1"></ma-get-point-value> <ma-point-values id="testi" point="point1" values="point1Values" from="from" to="to" rollup="AVERAGE" rollup-interval="1 minutes"> </ma-point-values> <ma-serial-chart id="chartti" style="height: 500px; width: 100%" series-1-values="point1Values" series-1-point="point1" options="{chartCursor:{categoryBalloonDateFormat:'YYYY-MM-DD HH:NN'}, chartScrollbar:{oppositeAxis: false, scrollbarHeight: 40,offset: 25, graph:'DP_355369',updateOnReleaseOnly: true}}"> </ma-serial-chart> <div layout="row"> <md-input-container flex="33" class="no-errors-spacer"> <label>Date preset</label> <ma-date-range-picker from="from" to="to" preset="LAST_1_DAYS" update-interval="1 minutes"></ma-date-range-picker> </md-input-container> <md-input-container flex="33" class="no-errors-spacer"> <label>From date</label> <ma-date-picker ng-model="from"></ma-date-picker> </md-input-container> <md-input-container flex="33" class="no-errors-spacer"> <label>To date</label> <ma-date-picker ng-model="to"></ma-date-picker> </md-input-container> </div> <div> <div> <md-button class="md-raised" ng-click="showStats=true;showData=false" ng-hide="showStats">Statistics</md-button> <md-button class="md-raised" ng-click="showStats=false;showData=false" ng-show="showStats">Statistics</md-button> <md-button class="md-raised" ng-click="showData=true;showStats=false" ng-hide="showData">Data</md-button> <md-button class="md-raised" ng-click="showData=false;showStats=false" ng-show="showData">Data</md-button> </div> <div ng-controller="myCtrl"> <md-button class="md-raised" ng-click="test()">Push me</md-button> </div> <div layout="row" ng-show="showStats" class="ng-hide"> <ma-point-statistics point="point1" from="from" to="to" statistics="statsObj"></ma-point-statistics> <ma-statistics-table id="statsTable" statistics="statsObj"></ma-statistics-table> </div> <div layout="row" ng-show="showData" class="ng-hide"> <table width="100%" height="500px"> <thead> <tr> <th>Value</th> <th>Time</th> </tr> </thead> <tbody> <tr ng-repeat="item in point1Values"> <td>{{item.value}}</td> <td>{{item.timestamp | moment:'format':'lll' }}</td> </tr> </tbody> </table> </div> </div> </div> </div> <script src="export.js"></script> <script src="/resources/require.js"></script> <script src="/resources/loaderConfig.js"></script> <script src="../js/loaderConfig.js"></script> <script type="text/javascript">require(['mango-3.0/bootstrap']);</script> </body> </html>
And here is my .js file called export.js. Right now it only has this one test function.
var testing = angular.module('testing', []); testing.controller('myCtrl',[$scope, function ($scope) { $scope.test = function(){ console.log('Logg meh'); } }]);
-
How to use my own AngularJS controllers with 3.0.1 dashboards?
I need to export point data in xlsx form and would rather not meddle with excel-reports due to only being able to have one report in the free version of the module. For this I planned to use something like in this example
http://jsfiddle.net/TheSharpieOne/XNVj3/1/
However, I'm facing problems when trying to get any of my own angular functions work. This is how I tried to test things out:
In my HTML file:
<div ng-controller="myCtrl"> <md-button class="md-raised" ng-click="test()">Push me</md-button> </div> <script src="export.js"></script>
In my .JS file
var testing = angular.module('testing', []); testing.controller('myCtrl',[$scope, function ($scope) { $scope.test = function(){ console.log('Logg meh'); } }]);
I'm getting a reference error stating that angular is not defined. So should I have the reference in my export.js file? Or is there a mango file in which I should include my own controllers?
-
RE: AngularJS date-range-picker gives an error
Thank you a lot, everything is running just like it should right now! It's a good thing you are able to fix these hiccups fast.