'use strict'; angular.module('hyperion', ['ui.router', 'hl.css.ui.router', 'ngResource', 'ngMessages', 'ngStorage', 'ngSanitize', 'ngWebsocket', 'angular-jwt', 'infinite-scroll', 'ngMaterial', 'ngAria', 'ngAnimate', 'md.data.table', 'fixed.table.header', 'rzSlider', 'debounce']) .constant('CONFIG', {}) .service('loadEnvConfig',['$http', function ($http) { return { getEnv: function() { return $http.get('env.json') .then(function(response) { return response.data; }); } }; }]) .service('AuthService', ['AuthenticationService', function (AuthenticationService) { this.isAuthenticated = function() { return AuthenticationService.isAuthenticated(); }; }]) .directive('onlyNumbers', [function () { return { restrict: 'A', link: function (scope, elm, attrs, ctrl) { elm.on('keydown', function (event) { if(event.shiftKey){event.preventDefault(); return false;} if ([8, 9, 13, 27, 35, 36, 37, 38, 39, 40, 46].indexOf(event.which) > -1) { // backspace, tab, enter, escape, arrows, del return true; } else if (event.which >= 48 && event.which <= 57) { // numbers 0 to 9 return true; } else if (event.which >= 96 && event.which <= 105) { // numpad number return true; } else if (event.which === 32) { // space character return true; } else { event.preventDefault(); return false; } }); } } }]) .directive('spinner', ['$http', 'CONFIG', function($http, CONFIG) { return { restrict: 'A', link: function(scope, element, attrs) { scope.isLoading = function() { if($http.pendingRequests.length > 0) { // is there are any pending requests? // show "loading" if pending request doesn't have parameter "hide" set to TRUE // this way we can hide recurrent/automatic ajax requests (E.g.: alerts check) // -> $http.get(URL, {params: {hide: true}}) if(!$http.pendingRequests[0].params || !$http.pendingRequests[0].params.hide) { return true; } } }; scope.$watch(scope.isLoading, function(isLoading) { if(isLoading) { $('.alert-login').hide(); $(element).fadeIn(CONFIG.UI_SPEED); } else { $(element).fadeOut(CONFIG.UI_SPEED, function(){ $('.alert-login').show(); }); } }); } }; }]) .directive('financialInput', [function() { return { restrict: 'A', link: function(scope, element, attrs) { element.on('input', function(event) { let inputValue = element.val(); // Regex pattern: only numbers, one separator (.), and max 2 digits after the separator let regex = /^(\d+)(\.\d{2})?$/; if(!regex.test(inputValue)) { console.log('FAILED: ', inputValue); // Remove invalid characters and enforce the rule of a single separator and two decimal places inputValue = inputValue.replace(/[^0-9.]/g, ''); // Remove non-numeric and invalid characters // Split the input into the part before and after the separator let parts = inputValue.split('.'); // If more than one separator is entered, remove extras if(parts.length > 2) { inputValue = parts[0] + '.' + parts[1]; // Keep only one separator } // Limit to two digits after the separator if(parts[1]) { parts[1] = parts[1].substring(0, 2); // Keep only two digits after the separator } element.val(parts.join('.')); // Set the corrected value back into the input } }); } }; }]) .filter('i18n', ['languageService', function(languageService) { function i18n(key) { return languageService.getMessage(key); } i18n.$stateful = true; return i18n; }]) .filter('formatByte', [function() { function formatByte(size) { var base = 1024; var prefixes = ['Ki','Mi','Gi','Ti','Pi','Ei','Zi','Yi']; var exp = Math.log(size) / Math.log(base) | 0; return (size / Math.pow(base, exp)).toFixed(0) + ' ' + ((exp > 0) ? prefixes[exp - 1] + 'B' : 'Bytes'); } formatByte.$stateful = true; return formatByte; }]) .filter('temperature', ['CONFIG', function(CONFIG) { function temperature(value, showScale) { if(!value || value === '') return 'N/A'; // CONFIG.TEMPERATURE: 'F', // F:Fahrenheit | C:Celsius if(CONFIG.TEMPERATURE === 'F') { return parseInt(((value * 9/5) + 32), 10) + (showScale?' °F':''); } else { return parseInt(value, 10) + (showScale?' °C':''); } } temperature.$stateful = true; return temperature; }]) .filter('humidity', [function() { function humidity(value, showScale) { if(!value || value === '') return 'N/A'; return parseInt(value, 10) + (showScale?' RH%':''); } humidity.$stateful = true; return humidity; }]) .filter('power', [function() { var SI_SYMBOL = [" W", " kW", " MW", " GW", " TW", " PW", " EW"]; function power(value) { // in Watts if(value === '') return 'N/A'; var tier = Math.log10(Math.abs(value)) / 3 | 0; var suffix = SI_SYMBOL[tier]; var scale = Math.pow(10, tier * 3); var scaled = value / scale; return scaled.toFixed(1) + suffix; } power.$stateful = true; return power; }]) .filter('energy', [function() { var SI_SYMBOL = [" kWh", " MWh", " GWh", " TWh", " PWh", " EWh"]; function energy(value) { // in kWh if(value === '') return 'N/A'; var tier = Math.log10(Math.abs(value)) / 3 | 0; var suffix = SI_SYMBOL[tier]; var scale = Math.pow(10, tier * 3); var scaled = value / scale; return scaled.toFixed(2) + suffix; } energy.$stateful = true; return energy; }]) .filter('emission', [function() { var SI_SYMBOL = [" kg", " Mg", " Gg", " Tg", " Pg", " Eg"]; function emission(value) { // in kWh if(value === '') return 'N/A'; var tier = Math.log10(Math.abs(value)) / 3 | 0; var suffix = SI_SYMBOL[tier]; var scale = Math.pow(10, tier * 3); var scaled = value / scale; return scaled.toFixed(2) + suffix; } emission.$stateful = true; return emission; }]) .filter('unit', [function() { function unit(value) { // number if (value === null || value === undefined || isNaN(value)) { return value; } var units = ['k', 'M', 'B', 'T']; var unitIndex = -1; while(value >= 1000 && unitIndex < units.length - 1) { value /= 1000; unitIndex++; } return unitIndex === -1 ? value : value.toFixed(1) + units[unitIndex]; } unit.$stateful = true; return unit; }]) .filter('brightness', [function() { function brightness(value) { if(value <= 0) { value = 0; } if(value >= 100) { value = 100; } return value + '%'; } brightness.$stateful = true; return brightness; }]) .filter('status', [function() { function status(indicator) { switch(indicator) { case 0: return 'NORMAL'; break; case 1: return 'TROUBLE'; break; case 2: return 'ALARM'; break; } } status.$stateful = true; return status; }]) .filter('secondsToTime', [function() { function padTime(t) { return t < 10 ? "0"+t : t; } return function(_seconds) { if (typeof _seconds !== "number" || _seconds < 0) return "00:00:00"; var hours = Math.floor(_seconds / 3600), minutes = Math.floor((_seconds % 3600) / 60), seconds = Math.floor(_seconds % 60); return padTime(hours) + "h " + padTime(minutes) + "m " + padTime(seconds) + "s"; }; }]) .filter('secondsToTimeLong', [function() { function padTime(t) { return t < 10 ? "0"+t : t; } return function(_seconds) { if(typeof _seconds !== "number" || _seconds < 0) { return "00:00:00"; } if(_seconds == 0) { return "N/A"; } var days = Math.floor(_seconds / 86400), hours = Math.floor((_seconds % 86400) / 3600), minutes = Math.floor((_seconds % 3600) / 60) return (days?(padTime(days) + "d "):'') + (days||hours?(padTime(hours) + "h "):'') + (days||hours||minutes?(padTime(minutes) + "m"):''); }; }]) .filter('hdatetime', ['sysClock', function(sysClock) { function hdatetime(postgresDateTime, ifempty) { if(postgresDateTime) { var tzabbr = moment.tz.zone(sysClock.getTimeZone()).abbr(moment(postgresDateTime)); var tztime = moment.utc(postgresDateTime, 'YYYY-MM-DD HH:mm:ss').tz(sysClock.getTimeZone()).format('lll'); return tztime+' '+tzabbr; } else { return ifempty?ifempty:'no data'; } } hdatetime.$stateful = true; return hdatetime; }]) .filter('hdateshort', ['sysClock', function(sysClock) { function hdateshort(postgresDateTime) { if(postgresDateTime !== null) { return moment.utc(postgresDateTime, 'YYYY-MM-DD HH:mm:ss').tz(sysClock.getTimeZone()).format('MMM DD, YYYY'); } else { return 'no data'; } } hdateshort.$stateful = true; return hdateshort; }]) .filter('htime', ['sysClock', function(sysClock) { function htime(postgresDateTime){ if(postgresDateTime !== null) { var tzabbr = moment.tz.zone(sysClock.getTimeZone()).abbr(moment(postgresDateTime)); var tztime = moment.utc(postgresDateTime, 'YYYY-MM-DD HH:mm:ss').tz(sysClock.getTimeZone()).format('LTS'); return tztime+' '+tzabbr; } else { return 'no data'; } } htime.$stateful = true; return htime; }]) .filter('htimeshort', ['sysClock', function(sysClock) { function htimeshort(postgresDateTime){ if(postgresDateTime !== null) { var tzabbr = moment.tz.zone(sysClock.getTimeZone()).abbr(moment(postgresDateTime)); var tztime = moment.utc(postgresDateTime, 'YYYY-MM-DD HH:mm:ss').tz(sysClock.getTimeZone()).format('MMM DD, YYYY HH:mm'); return tztime+' '+tzabbr; } else { return 'no data'; } } htimeshort.$stateful = true; return htimeshort; }]) .filter('expcounter', [function(){ //expected output: time diff in format (example): 05d:01h:12m:43s // if null then: --:--:--:-- function pad(num, size){ var nlen = 0; if(num !== undefined || num !== null) { nlen = Math.ceil(Math.log10(num + 1)); } return ('000000000' + num).substr(-(size>=nlen?size:nlen)); } return function(time) { if(time === undefined || time === null) { return '--:--:--:--'; } else { var diff = moment.utc(time).valueOf() - moment().valueOf(); if(diff>0) { var jdiff = isNaN(diff)?NaN:{ diff : diff, ms : Math.floor( diff % 1000 ), s : Math.floor( diff / 1000 % 60 ), m : Math.floor( diff / 60000 % 60 ), h : Math.floor( diff / 3600000 % 24 ), d : Math.floor( diff / 86400000 ) }; return pad(jdiff.d, 2) + 'd:' + pad(jdiff.h, 2) + 'h:' + pad(jdiff.m, 2) + 'm:' + pad(jdiff.s, 2) + 's'; } else { return 'EXPIRED'; } } } }]) .filter('timecounter', [function(){ //expected output: time diff in format (example): 05d:01h:12m:43s // if null then: --:--:--:-- function pad(num, size){ var nlen = 0; if(num !== undefined || num !== null) { nlen = Math.ceil(Math.log10(num + 1)); } return ('000000000' + num).substr(-(size>=nlen?size:nlen)); } return function(time) { if(time === undefined || time === null) { return '--:--:--:--'; } else { var diff = moment().valueOf() - moment.utc(time).valueOf(); var jdiff = isNaN(diff)?NaN:{ diff : diff, ms : Math.floor( diff % 1000 ), s : Math.floor( diff / 1000 % 60 ), m : Math.floor( diff / 60000 % 60 ), h : Math.floor( diff / 3600000 % 24 ), d : Math.floor( diff / 86400000 ) }; return pad(jdiff.d, 2) + 'd:' + pad(jdiff.h, 2) + 'h:' + pad(jdiff.m, 2) + 'm:' + pad(jdiff.s, 2) + 's'; } } }]) .filter('pad', [function(){ return function(input, char, size){ var nlen = input.toString().length; size = parseInt(size, 10); var filler = "".toString(); for(var x = 0; x < (size-nlen<0?0:size-nlen); x++){ filler = filler.concat(char); } return filler + input; } }]) .filter('phone', [function() { return function(phonestring) { if(phonestring === undefined || phonestring === null) { return 'no data'; } else { var phone = phonestring.split("#"); var phone1 = phone[1].substring(0,3); var phone2 = phone[1].substring(3,6); var phone3 = phone[1].substring(6); return '+'+phone[0]+' '+phone1+'-'+phone2+'-'+phone3; } } }]) .factory('authService', ['$http', '$q', '$sessionStorage', 'jwtHelper', 'CONFIG', function($http, $q, $sessionStorage, jwtHelper, CONFIG) { return { getJWTAuth() { const storage = $sessionStorage.currentUser; if(storage.auth_token_str && storage.auth_token_exp > moment(new Date().getTime()).unix()) { return $q.when( { 'Authorization': 'Bearer ' + storage.auth_token_str, 'Content-Type': 'application/json', 'Accept': 'application/json', 'Cache-Control': 'no-cache', 'Request-Origin': CONFIG.APP_NAME } ); } else { if(storage.auth_token_exp) { return $http.post( CONFIG.APP_API, {"query": "mutation{refresh(token: \"" + storage.refr_token_str + "\")}"}, {"Content-Type": "application/json", 'Accept': 'application/json'} ).then( function(response) { // resolve var decodedToken = jwtHelper.decodeToken(response.data.data.refresh.accessToken); console.warn('Token refreshed'); storage.auth_token_str = response.data.data.refresh.accessToken; storage.auth_token_iat = response.data.data.refresh.expiresAt; storage.auth_token_exp = decodedToken.exp; storage.refr_token_str = response.data.data.refresh.refreshToken; return $q.when( { 'Authorization': 'Bearer ' + storage.auth_token_str, 'Content-Type': 'application/json', 'Accept': 'application/json', 'Cache-Control': 'no-cache', 'Request-Origin': CONFIG.APP_NAME } ); } ); } } } } }]) .factory('authHttpResponseInterceptor',['$q','$location', function($q, $location){ return { response: function(response){ if(response.data.errors) { response.data.errors.forEach(element => { console.error(element); }); } return response || $q.when(response); }, responseError: function(rejection) { /* if(rejection.status === 401) { console.error("Response Error 401", rejection); $location.path('/').search('returnTo', $location.path()); } */ return $q.reject(rejection); } } }]) .factory('languageService', ['CONFIG', '$http', '$log', '$sessionStorage', function(CONFIG, $http, $log, $sessionStorage) { var setLocale = function(newlocale) { CONFIG.i18n_LOCALE = $sessionStorage.currentUser.locale = newlocale; $http.get("/i18n/" + CONFIG.i18n_LOCALE + ".json", {cache: true}) .then(function(dictionary) { CONFIG.i18n_DICTIONARY = dictionary.data; }).catch(function(error) { $log.error(error); if(error.status === 401) { $location.path('/'); } return error.$promise; }).finally(function(data){ }); }; var getMessage = function(key) { if(!(key in CONFIG.i18n_DICTIONARY)) { return key; } else { return CONFIG.i18n_DICTIONARY[key].message; } }; return { setLocale: setLocale, getMessage: getMessage } }]) .factory('sysClock', ['$log', '$sessionStorage', function($log, $sessionStorage) { var _timezone = 'UTC'; // default timezone var _clock = '24h'; // default clock var setClock = function(type) { var clocktype = type.toLowerCase().trim(); if(clocktype === '12h' || clocktype === '24h') { _clock = clocktype; } else { $log.error('invalid clock type! expected: [12h|24h], given: '+type); } }; var setTimeZone = function(timezone) { $sessionStorage.currentUser.timezone = _timezone = timezone; }; var getTimeZone = function() { return _timezone; }; var getClock = function() { return _clock; }; var flipClock = function() { _clock = _clock === '12h'?'24h':'12h'; }; var isClock12 = function() { return _clock === '12h'; }; var isClock24 = function() { return _clock === '24h'; }; return { setTimeZone : setTimeZone, getTimeZone : getTimeZone, setClock : setClock, getClock : getClock, flipClock : flipClock, isClock12 : isClock12, isClock24 : isClock24 } }]) .factory('modalDialog', ['$sessionStorage', '$mdDialog', function($sessionStorage, $mdDialog) { var showDialog = function(dialogObject){ return new Promise(function(resolve, reject) { var dialogSpec = $mdDialog.confirm({ controller: dialogObject.controller, templateUrl: dialogObject.template, locals: {object: dialogObject}, autoWrap: false, parent: angular.element(document.body), clickOutsideToClose: false, escapeToClose: false }); $mdDialog.show(dialogSpec).then( function(object){ // resolve resolve(object); }, function(){/* reject */}); }); }; return { showDialog: showDialog } }]) .factory('hBlob', [function() { var b64toBlob = function(b64Data, contentType, sliceSize) { contentType = contentType || ''; sliceSize = sliceSize || 512; var byteCharacters = atob(b64Data); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { var slice = byteCharacters.slice(offset, offset + sliceSize); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, {type: contentType}); return blob; }; return { b64toBlob: b64toBlob } }]) .factory('link', ['$location', '$sessionStorage', function($location, $sessionStorage) { var getMenuElementIndex = function(element) { var result = { major:0, minor:0 }; if($(element).closest('ul').hasClass('menu')) { result.minor = -1; result.major = parseInt($(element).parents('li').index(), 10); } else { result.minor = parseInt($(element).parents('li').index(), 10); result.major = parseInt($(element).closest('ul').parents('li').index(), 10); } return result; }; var redirect = function(href, link) { var $ = angular.element; $(".menu > li").find("span").each(function(index) { if(!$(this).hasClass('logout')) { // ignore LOGOUT element $(this).removeClass('active subactive'); } if($(this).parents().attr("href") === href) { $sessionStorage.menuActiveElement = getMenuElementIndex($(this)); $(this).addClass('active'); } }); $location.path(link); return true; }; return { redirect: redirect } }]) .factory('timerange', ['$sessionStorage', function($sessionStorage) { var tickInterval = 86400000; // 1d in ms var calc = function(days) { let date = new Date(); let today = Date.UTC( date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds() ); let start = today-(tickInterval * (days - 1)); return {start: start, today: today}; }; return { calc: calc } }]) .factory('wiz', [function() { // conversion from whats showed on UI to WiZ API dimm value var dimm2wiz = function(level) { var caluclated = 0; level = parseInt(level, 10); if(level<5) { caluclated = 0; } else if(level>=5 && level<15) { caluclated = level + 5; } else if(level>=15 && level<34) { caluclated = level + 4; } else if(level>=34 && level<53) { caluclated = level + 3; } else if(level>=53 && level<72) { caluclated = level + 2; } else if(level>=72 && level<91) { caluclated = level + 1; } else if(level>=91) { caluclated = level; } else if(level>=100) { caluclated = 100; } return caluclated; }; // conversion from WiZ API dimm value to whats showed on UI var wiz2dimm = function(level) { var caluclated = 0; level = parseInt(level, 10); if(level<10) { caluclated = 0; } else if(level>=10 && level<19) { caluclated = level - 5; } else if(level>=19 && level<37) { caluclated = level - 4; } else if(level>=37 && level<55) { caluclated = level - 3; } else if(level>=55 && level<73) { caluclated = level - 2; } else if(level>=73 && level<91) { caluclated = level - 1; } else if(level>=91) { caluclated = level; } else if(level>=100) { caluclated = 100; } return caluclated; }; return { dimm2wiz: dimm2wiz, wiz2dimm: wiz2dimm } }]) .run(['$state', '$rootScope', '$http', '$location', '$stateParams', '$sessionStorage', 'sysClock', 'loadEnvConfig', 'AuthenticationService', 'CONFIG', function($state, $rootScope, $http, $location, $stateParams, $sessionStorage, sysClock, loadEnvConfig, AuthenticationService, CONFIG) { $rootScope.dateCurrentYear = new Date().getFullYear(); loadEnvConfig.getEnv() .then((data) => { angular.extend(CONFIG, data); /////////////////////////////////////////////////////////////////////// /// GLOBAL (ROOT) VARIABLES ////////////////////////////////////////// if($sessionStorage.currentUser !== undefined) { if(!$rootScope.project) { $rootScope.project = $sessionStorage.currentUser.project_selected?$sessionStorage.currentUser.project_selected:$sessionStorage.currentUser.project; } } $rootScope.light_settings_changed = false; /////////////////////////////////////////////////////////////////////// /// CATCH RESOLVE ERRORS ////////////////////////////////////////////// // Handle Transition Rejection errors: $state.defaultErrorHandler(function(error) { //window.myAppErrorLog.push(error); //console.error('defaultErrorHandler ', error); if(error.detail.status === 401) { $location.path('/'); } }); $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error){ event.preventDefault(); console.error(error); }); /////////////////////////////////////////////////////////////////////// /// GET & SET USER PREFERENCES //////////////////////////////////////// if($sessionStorage.currentUser !== undefined) { sysClock.setClock($sessionStorage.currentUser.clock12h?'12h':'24h'); } if($sessionStorage.currentUser !== undefined) { sysClock.setTimeZone($sessionStorage.currentUser.timezone); } if($sessionStorage.currentUser !== undefined) { CONFIG.i18n_LOCALE = $sessionStorage.currentUser.locale; } $http.get("/i18n/" + CONFIG.i18n_LOCALE + ".json", {cache: true}) .then(function(dictionary) { CONFIG.i18n_DICTIONARY = dictionary.data; }).catch(function(error) { if(error.status === 401) { $location.path('/'); } return error.$promise; }).finally(function(data){ }); /////////////////////////////////////////////////////////////////////// }); }]) .config(['$httpProvider', '$stateProvider', '$urlRouterProvider', '$mdThemingProvider', '$mdDateLocaleProvider', '$mdAriaProvider', '$mdIconProvider', function($httpProvider, $stateProvider, $urlRouterProvider,$mdThemingProvider, $mdDateLocaleProvider, $mdAriaProvider, $mdIconProvider) { // Globally disables all ARIA warnings. $mdAriaProvider.disableWarnings(); $mdThemingProvider.theme('default') .primaryPalette('indigo') .accentPalette('red'); $mdDateLocaleProvider.formatDate = function(date) { return date ? moment(date).format('MMMM DD, YYYY') : ''; }; $mdDateLocaleProvider.parseDate = function(dateString) { var m = moment(dateString, 'MMMM DD, YYYY', true); return m.isValid() ? m.toDate() : new Date(NaN); }; $httpProvider.interceptors.push('authHttpResponseInterceptor'); $mdIconProvider .iconSet('social', 'img/icons/sets/social-icons.svg', 24) .defaultIconSet('img/icons/sets/core-icons.svg', 24); // application routes $stateProvider .state('login', { url: '/', templateUrl: 'auth.login.html', controller: 'login.LoginController', data: { requiresAuthentication: false, css: [ 'css/login.css', 'css/fonts.css', 'css/angular-material.min.css', 'css/angular-material-icons.css' ] } }) .state('logout', { url: '/logout', controller: 'login.LogoutController', data: { requiresAuthentication: true, css: [ 'css/login.css', 'css/fonts.css', 'css/angular-material.min.css', 'css/angular-material-icons.css' ] } }) .state('system', { url: '/system', templateUrl: 'system.index.html', controller: 'system.MainController', data: { requiresAuthentication: true, css: [ 'css/angular-material.min.css', 'css/angular-material-icons.css', 'css/md-data-table.min.css', 'css/rzslider.css', 'css/font-awesome.min.css', 'css/fonts.css', 'css/clock.css', 'css/spinner.css', 'css/sidebar.css', 'css/hyperion-ng.css', 'css/farbtastic.css' ] }, resolve: { // Check authentication before allowing access 'auth': function(AuthService, $state) { if(!AuthService.isAuthenticated()) { $state.go('login'); // Redirect unauthenticated users to login page } } } }).state('system.dashboard', { url: '/dashboard', templateUrl: 'system.dashboard.html', controller: 'system.DashboardController', data: { requiresAuthentication: true } }).state('system.projects', { url: '/projects', templateUrl: 'system.projects.html', controller: 'system.ProjectsController', data: { requiresAuthentication: true } }).state('system.events_default', { url: '/events', templateUrl: 'system.events.html', controller: 'system.EventsController', data: { requiresAuthentication: true } }).state('system.events_by_date', { url: '/events/:event_date', templateUrl: 'system.events.html', controller: 'system.EventsController', data: { requiresAuthentication: true } }).state('system.resources', { url: '/resources', templateUrl: 'system.resources.index.html', controller: 'system.ResourcesController.index', data: { requiresAuthentication: true } }).state('system.locations', { url: '/locations', templateUrl: 'system.locations.index.html', controller: 'system.LocationsController.index', data: { requiresAuthentication: true } }).state('system.viewLocation', { url: '/locations/view/:location_id', templateUrl: 'system.locations.view.html', controller: 'system.LocationsController.view', data: { requiresAuthentication: true } }) .state('system.editLocation', { url: '/locations/edit/:location_id', templateUrl: 'system.locations.edit.html', controller: 'system.LocationsController.edit', data: { requiresAuthentication: true } }).state('system.groups', { url: '/groups', templateUrl: 'system.groups.index.html', controller: 'system.GroupsController.index', data: { requiresAuthentication: true } }).state('system.newgroup', { url: '/groups/new', templateUrl: 'system.groups.new.html', controller: 'system.GroupsController.new', data: { requiresAuthentication: true } }).state('system.viewgroup', { url: '/groups/view/:group_id', templateUrl: 'system.groups.view.html', controller: 'system.GroupsController.view', data: { requiresAuthentication: true } }).state('system.editgroup', { url: '/groups/edit/:group_id', templateUrl: 'system.groups.edit.html', controller: 'system.GroupsController.edit', data: { requiresAuthentication: true } }).state('system.scenes', { url: '/scenes', templateUrl: 'system.scenes.index.html', controller: 'system.ScenesController.index', data: { requiresAuthentication: true } }).state('system.newscene', { url: '/scenes/new', templateUrl: 'system.scenes.new.html', controller: 'system.ScenesController.new', data: { requiresAuthentication: true } }).state('system.viewscene', { url: '/scenes/view/:scene_id', templateUrl: 'system.scenes.view.html', controller: 'system.ScenesController.view', data: { requiresAuthentication: true } }).state('system.editscene', { url: '/scenes/edit/:scene_id', templateUrl: 'system.scenes.edit.html', controller: 'system.ScenesController.edit', data: { requiresAuthentication: true } }).state('system.viewFloor', { url: '/floors/:floor_id', templateUrl: 'system.floors.view.html', controller: 'system.FloorsController.view', data: { requiresAuthentication: true } }).state('system.viewRoom', { url: '/rooms/:room_id', templateUrl: 'system.rooms.view.html', controller: 'system.RoomsController.view', data: { requiresAuthentication: true } }).state('system.viewEquipment', { url: '/equipment/:equipment_id', templateUrl: 'system.equipment.view.html', controller: 'system.EquipmentController.view', data: { requiresAuthentication: true } }).state('system.editEquipment', { url: '/equipment/edit/:equipment_id', templateUrl: 'system.equipment.edit.html', controller: 'system.EquipmentController.edit', data: { requiresAuthentication: true } }).state('system.password', { url: '/password', templateUrl: 'system.password.html', controller: 'system.PasswordController', data: { requiresAuthentication: true } }).state('system.myaccount', { url: '/myaccount', templateUrl: 'system.account.my.html', controller: 'system.MyAccountController', data: { requiresAuthentication: true } }).state('system.mycompany', { url: '/mycompany', templateUrl: 'system.mycompany.html', controller: 'system.CompanyController', data: { requiresAuthentication: true } }).state('system.newaccount', { url: '/newaccount', templateUrl: 'system.account.new.html', controller: 'system.NewAccountController', data: { requiresAuthentication: true } }).state('system.account', { url: '/account/:account_id', templateUrl: 'system.account.view.html', controller: 'system.ViewAccountController', data: { requiresAuthentication: true } }).state('system.cost', { url: '/cost', templateUrl: 'system.cost.view.html', controller: 'system.UtilitiesCostController.view', data: { requiresAuthentication: true } }).state('system.costConfig', { url: '/cost/configuration', templateUrl: 'system.cost.config.html', controller: 'system.UtilitiesCostController.config', data: { requiresAuthentication: true } }); // default route $urlRouterProvider.otherwise("/system/dashboard"); }]);