From caa067be8dc44f5bdfaed2ed40916ed52772332e Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Mon, 17 Oct 2016 18:35:49 +0100 Subject: [PATCH 01/16] WIP: Impac Express Developer Workspace Adjusted and improved the dev workspace to use mno-enterprise devise to authenticate impac-angular, and use the new Impac! JPI. --- bower.json | 4 +- gulp/server.js | 11 ++ gulp/workspace.js | 9 +- package.json | 1 + workspace/app/app.js | 151 +++++++++++++++ workspace/app/services/dev-user.svc.js | 52 +++++ workspace/app/services/settings.svc.js | 41 ++++ .../views/workspace/impac/impac.controller.js | 11 ++ .../app/views/workspace/impac/impac.html | 3 + .../views/workspace/login/login.controller.js | 19 ++ .../app/views/workspace/login/login.html | 4 + .../views/workspace/workspace.controller.js | 21 ++ .../views/workspace/workspace.css} | 21 +- workspace/app/views/workspace/workspace.html | 9 + workspace/index.html | 31 +-- workspace/index.js | 180 ------------------ workspace/settings.json | 5 - 17 files changed, 360 insertions(+), 213 deletions(-) create mode 100644 workspace/app/app.js create mode 100644 workspace/app/services/dev-user.svc.js create mode 100644 workspace/app/services/settings.svc.js create mode 100644 workspace/app/views/workspace/impac/impac.controller.js create mode 100644 workspace/app/views/workspace/impac/impac.html create mode 100644 workspace/app/views/workspace/login/login.controller.js create mode 100644 workspace/app/views/workspace/login/login.html create mode 100644 workspace/app/views/workspace/workspace.controller.js rename workspace/{index.css => app/views/workspace/workspace.css} (60%) create mode 100644 workspace/app/views/workspace/workspace.html delete mode 100644 workspace/index.js delete mode 100644 workspace/settings.json diff --git a/bower.json b/bower.json index aefa7fff..a32d3526 100755 --- a/bower.json +++ b/bower.json @@ -38,7 +38,9 @@ }, "devDependencies": { "angular-mocks": "~1.4.0", - "angular-scenario": "~1.4.0" + "angular-scenario": "~1.4.0", + "AngularDevise": "angular-devise#^1.3.0", + "angular-ui-router": "^0.3.1" }, "license": "Copyright 2015 Maestrano Pty Ltd", "repository": { diff --git a/gulp/server.js b/gulp/server.js index cf44320e..460c575d 100644 --- a/gulp/server.js +++ b/gulp/server.js @@ -11,6 +11,8 @@ var $ = require('gulp-load-plugins')({ pattern: ['browser-*'] }); +var proxyMiddleware = require('http-proxy-middleware'); + function browserSyncInit(baseDir, browser) { browser = browser === undefined ? 'default' : browser; @@ -26,6 +28,15 @@ function browserSyncInit(baseDir, browser) { routes: routes }; + /* + * You can add a proxy to your backend by uncommenting the line below. + * You just have to configure a context which will we redirected and the target url. + * Example: $http.get('/users') requests will be automatically proxified. + * + * For more details and option, https://github.com/chimurai/http-proxy-middleware/blob/v0.9.0/README.md + */ + server.middleware = proxyMiddleware(['/auth', '/mnoe'], { target: 'http://localhost:7000' }); + $.browserSync.instance = $.browserSync.init({ port: 7001, startPath: '/', diff --git a/gulp/workspace.js b/gulp/workspace.js index a12c2274..9d83d594 100644 --- a/gulp/workspace.js +++ b/gulp/workspace.js @@ -2,12 +2,19 @@ var gulp = require('gulp'); var wiredep = require('wiredep').stream; +var $ = require('gulp-load-plugins')(); /** * Builds and injects dependencies into workspace/index.html */ gulp.task('workspace', ['build'], function () { + var injectFiles = gulp.src(['workspace/app/**/*.js', 'workspace/app/**/*.css'], {read: false}); + var injectOptions = { relative: true }; + return gulp.src('workspace/index.html') - .pipe(wiredep({})) + .pipe(wiredep({ + devDependencies: true + })) + .pipe($.inject(injectFiles, injectOptions)) .pipe(gulp.dest('workspace')); }); diff --git a/package.json b/package.json index 1d3ea7b3..d464a161 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "gulp-sourcemaps": "^1.6.0", "gulp-uglify": "^0.3.1", "gulp-util": "^3.0.6", + "http-proxy-middleware": "^0.17.2", "jasmine-core": "^2.4.1", "karma": "~0.12.22", "karma-chrome-launcher": "^0.1.4", diff --git a/workspace/app/app.js b/workspace/app/app.js new file mode 100644 index 00000000..a69d45c5 --- /dev/null +++ b/workspace/app/app.js @@ -0,0 +1,151 @@ +// IMPAC! WORKSPACE +//-------------------------------------------------------- +// PLEASE DO NOT COMMIT CHANGES TO THIS FILE. +// You can use `git add -p ./` to selectively add files to your git index. +// ------------------------------------------------------- +var module = angular.module('impacWorkspace', [ + 'maestrano.impac', + 'toastr', + 'Devise', + 'ui.router' +]); + +// -- +// The Developer Toolkit Workspace States. +// ------------------------------------------------------- +module.config(function ($stateProvider, $urlRouterProvider) { + + $urlRouterProvider.otherwise('/login'); + + $stateProvider + .state('workspace', { + abstract: true, + templateUrl: 'app/views/workspace/workspace.html', + controller: 'WorkspaceController', + controllerAs: 'main' + }) + .state('workspace.login', { + url: '/login', + templateUrl: 'app/views/workspace/login/login.html', + controller: 'LoginController', + controllerAs: 'vm' + }) + .state('workspace.impac', { + url: '/impac', + templateUrl: 'app/views/workspace/impac/impac.html', + controller: 'ImpacController', + controllerAs: 'vm' + }); + +}); + +// -- +// Configure Angular Devise paths for mno-enterprise. +// ------------------------------------------------------- +module.config(function (AuthProvider) { + // Customize login + AuthProvider.loginMethod('POST') + AuthProvider.loginPath('mnoe/auth/users/sign_in.json') + + // Customize logout + AuthProvider.logoutMethod('DELETE') + AuthProvider.logoutPath('mnoe/auth/users/sign_out.json') + + // Customize register + AuthProvider.registerMethod('POST') + AuthProvider.registerPath('mnoe/auth/users') +}); + +// -- +// Impac! Angular Provider Service Configurations +// ------------------------------------------------------- +module.run(function (ImpacLinking, ImpacAssets, ImpacRoutes, ImpacTheming, ImpacDeveloper, DevUser, settings) { + + // Check have been provided + if (!settings.email || !settings.password) { + DevUser.fail('Missing login credentials!'); + } + + // Configure ImpacRoutes + // ------------------------------------------------------- + var mnoHub = settings.mno_url; + var impacPrefix = "/impac"; + var routesConfig = { + mnoHub: mnoHub, + impacPrefix: impacPrefix, + impacApi: settings.impac_url + "/api", + dashboards: { + index: mnoHub + impacPrefix + "/dashboards" + }, + widgets: { + index: mnoHub + impacPrefix + "/widgets", + create: mnoHub + impacPrefix + "/dashboards/:dashboard_id/widgets" + }, + kpis: { + index: mnoHub + impacPrefix + "/kpis", + create: mnoHub + impacPrefix + "/dashboards/:dashboard_id/kpis", + update: mnoHub + impacPrefix + "/kpis/:id", + del: mnoHub + impacPrefix + "/kpis/:id" + }, + alerts: { + index: mnoHub + impacPrefix + "/alerts", + create: mnoHub + impacPrefix + "/kpis/:kpi_id/alerts", + del: mnoHub + impacPrefix + "/alerts/:id" + } + }; + // Removes custom index path, defaulting kpi discovery to impac api, where KPIs with + // multiple watchables are returned. + if (settings.multiple_watchables_mode) { delete routesConfig.kpis.index; } + ImpacRoutes.configureRoutes(routesConfig); + + + // Configure ImpacTheming - aesthetic and feature customisations across the app + // ------------------------------------------------------- + ImpacTheming.configure({ + dhbKpisConfig: { + enableKpis: true + }, + alertsConfig: { + enableAlerts: true + }, + dhbConfig: { + showDhbHeading: true, + dhbHeadingText: 'Your business at a glance, in real-time' + }, + dhbSelectorConfig: { + selectorType: 'dropdown', + pdfModeEnabled: true + }, + dhbSettings: { + syncApps: { + show: function() { return false; } + } + } + }); + + // Configure ImpacAssets - app asset file configurations + // ------------------------------------------------------- + ImpacAssets.configure({ + defaultImagesPath: '/dist/images', + }) + + // Configure ImpacDeveloper - developer toolkit specifc customisations + // ------------------------------------------------------- + ImpacDeveloper.configure({ + status: true, + widgetsTemplates: settings.widgetsTemplates || [] + }); + + // Configure ImpacLinking - Links core callbacks required for impac-angular lib to run. + // ------------------------------------------------------- + ImpacLinking.linkData({ + organizations: function () { + return DevUser.getOrganizations(settings.org_uid); + }, + user: function () { + return DevUser.getUser(); + }, + pusher_key: 'e98dfd8e4a359a7faf48' // Maestrano pusher account key. + }); + +}); diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js new file mode 100644 index 00000000..a40d995e --- /dev/null +++ b/workspace/app/services/dev-user.svc.js @@ -0,0 +1,52 @@ +// Impac! Angular DevUser Service - providing core authentication logic for Impac! developers. +// -------------------------------------------------------- +angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, Auth, settings, toastr) { + _self = this; + + this.login = Auth.login; + this.logout = Auth.logout; + this.isAuthenticated = Auth.isAuthenticated; + + this.getUserData = function() { + return $http.get(settings.mno_url + '/current_user') + .then(function (response) { + var user = (response.data && response.data.current_user); + if (!user.logged_in) { + return $q.reject(); + } + return user || {}; + }, function (error) { + var msg = 'Unable to retrieve Organizations'; + _self.fail(msg, error); + return $q.reject(msg); + }); + }; + + this.getOrganizations = function(orgUid) { + return _self.getUserData().then(function (user) { + var orgs = (user.organizations || []); + var orga = orgs.find(function(orga) { return orga.uid == orgUid }); + var orgId = (orga && orga.id) || orgs[0].id || null; + + return { organizations: orgs, currentOrgId: orgId }; + }, function (err) { + return $q.reject(err); + }); + }; + + this.getUser = function() { + return _self.getUserData().then(function (user) { + return user; + }, function (err) { + return $q.reject(err); + }); + }; + + this.fail = function (msg, error) { + if (error == null) { error = ''; } + $log.error('Develop Workspace Error: ' + msg, error); + toastr.error(msg, 'Error'); + }; + + return this; +}); diff --git a/workspace/app/services/settings.svc.js b/workspace/app/services/settings.svc.js new file mode 100644 index 00000000..0e01c0ac --- /dev/null +++ b/workspace/app/services/settings.svc.js @@ -0,0 +1,41 @@ +// ------------------------------------------------------- +// Impac Workspace Settings +// ------------------------------------------------------- +// Provide important configurations for the impacWorkspace. +angular.module('impacWorkspace').factory('settings', function () { + return { + // Credentials and endpoints + mno_url: '/mnoe/jpi/v1', // rename to mnoe_url + impac_url: 'http://localhost:4000', + // TODO: build login form + email: 'xaun.lopez@maestrano.com', + password: 'Test1234', + org_uid: '', // First organisations if unspecified + + // ----------------------------------------------- + // Kpis configurations + // ----------------------------------------------- + // Change this to `true` to force kpi's to allow multiple watchables, instead of + // using the mno_hub kpis#discover action maps kpis to have single watchables per kpi. + multiple_watchables_mode: false, + // Stub widget templates - add new widgets! + //------------------------------------------------ + // Widget templates are stored on Maestrano API, stub your + // new widget templates here, and contact us for permenant additions or + // changes to existing widget templates. + widgetsTemplates: [ + // Example widget template, please see documentation "How-To: Create a Widget" for available + // options, and importantly, note how the path & metadata.template attributes work. + // -- + // { + // path: 'accounts/assets_summary', + // name: 'Assets / Liabilities summary', + // metadata: { template: 'accounts/assets_liability_summary' }, + // desc: 'Compare Assets and Liabilities accounts', + // icon: 'pie-chart', + // width: 3 + // }, + ] + // -- + }; +}); diff --git a/workspace/app/views/workspace/impac/impac.controller.js b/workspace/app/views/workspace/impac/impac.controller.js new file mode 100644 index 00000000..202dffd3 --- /dev/null +++ b/workspace/app/views/workspace/impac/impac.controller.js @@ -0,0 +1,11 @@ +angular.module('impacWorkspace').controller('ImpacController', function ($state, DevUser) { + vm = this; + + vm.showImpac = DevUser.isAuthenticated(); + + if (!vm.showImpac) { + $state.go('workspace.login'); + } + + return vm; +}); diff --git a/workspace/app/views/workspace/impac/impac.html b/workspace/app/views/workspace/impac/impac.html new file mode 100644 index 00000000..8bd0dba8 --- /dev/null +++ b/workspace/app/views/workspace/impac/impac.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/workspace/app/views/workspace/login/login.controller.js b/workspace/app/views/workspace/login/login.controller.js new file mode 100644 index 00000000..617836b2 --- /dev/null +++ b/workspace/app/views/workspace/login/login.controller.js @@ -0,0 +1,19 @@ +angular.module('impacWorkspace').controller('LoginController', function ($state, DevUser, settings) { + vm = this; + + if (DevUser.isAuthenticated()) { + $state.go('workspace.impac'); + } + + vm.login = function () { + DevUser.login({email: settings.email, password: settings.password}).then( + function () { + $state.go('workspace.impac'); + }, function (error) { + DevUser.fail('Unable to login', error); + } + ); + }; + + return vm; +}); diff --git a/workspace/app/views/workspace/login/login.html b/workspace/app/views/workspace/login/login.html new file mode 100644 index 00000000..33d877b3 --- /dev/null +++ b/workspace/app/views/workspace/login/login.html @@ -0,0 +1,4 @@ +
+

Login Controller

+ +
diff --git a/workspace/app/views/workspace/workspace.controller.js b/workspace/app/views/workspace/workspace.controller.js new file mode 100644 index 00000000..556bd6f5 --- /dev/null +++ b/workspace/app/views/workspace/workspace.controller.js @@ -0,0 +1,21 @@ +angular.module('impacWorkspace').controller('WorkspaceController', function ($state, DevUser) { + main = this; + + main.isAuthenticated = function () { + return DevUser.isAuthenticated(); + }; + + main.logout = function () { + DevUser.logout().then( + function () { + $state.go('workspace.login'); + }, + function (error) { + DevUser.fail('Unable to logout', error); + } + ); + }; + + return main; + +}); diff --git a/workspace/index.css b/workspace/app/views/workspace/workspace.css similarity index 60% rename from workspace/index.css rename to workspace/app/views/workspace/workspace.css index b75b5eab..1398f834 100644 --- a/workspace/index.css +++ b/workspace/app/views/workspace/workspace.css @@ -3,29 +3,28 @@ body { background-color: #E6EDEE; } -#workspace-header { +#workspace .workspace-header { + position: relative; text-align: center; background-color: black; color: white; font-family: 'Share Tech Mono', 'Helvetica Neue', Helvetica, Arial, sans-serif; } -#workspace-header h1 { +#workspace .workspace-header h1 { margin: 0; padding: 15px 40px; } -#workspace-dashboard { - margin: 0 auto; - width: 91%; -} - -footer#workspace-footer { - padding: 20px 40px; +#workspace .workspace-header button { + position: absolute; + right: 70px; + bottom: 17px; } -footer#workspace-footer p { - margin: 0; +#workspace .workspace-dashboard { + margin: 0 auto; + width: 91%; } /* IMPAC OVERRIDES */ diff --git a/workspace/app/views/workspace/workspace.html b/workspace/app/views/workspace/workspace.html new file mode 100644 index 00000000..6363882b --- /dev/null +++ b/workspace/app/views/workspace/workspace.html @@ -0,0 +1,9 @@ +
+
+

IMPAC! DEVELOPER WORKSPACE

+ +
+ +
+
+ diff --git a/workspace/index.html b/workspace/index.html index 2fc92851..21e50f58 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -10,7 +10,9 @@ - + + + @@ -19,19 +21,7 @@ -
-

IMPAC! DEVELOPER WORKSPACE

-
- -
- -
- - +
@@ -48,9 +38,20 @@

IMPAC! DEVELOPER WORKSPACE

+ + + + - + + + + + + + + diff --git a/workspace/index.js b/workspace/index.js deleted file mode 100644 index 717e7ecf..00000000 --- a/workspace/index.js +++ /dev/null @@ -1,180 +0,0 @@ -// IMPAC! WORKSPACE -//-------------------------------------------------------- -// PLEASE DO NOT COMMIT CHANGES TO THIS FILE. -// You can use `git add -p ./` to selectively add files to your git index. -// ------------------------------------------------------- -var module = angular.module('impacWorkspace', ['maestrano.impac', 'toastr']); - -// ------------------------------------------------------- -// Impac Workspace Settings -// ------------------------------------------------------- -// Provide important configurations for the impacWorkspace. -module.factory('settings', function () { - return { - // Credentials and endpoints - mno_url: 'https://get-uat.maestrano.io', - impac_url: 'https://api-impac-uat.maestrano.io', - api_key: '', - api_secret: '', - org_uid: '', // First organisations if unspecified - - // ----------------------------------------------- - // Kpis configurations - // ----------------------------------------------- - // Change this to `true` to force kpi's to allow multiple watchables, instead of - // using the mno_hub kpis#discover action maps kpis to have single watchables per kpi. - multiple_watchables_mode: false, - // Stub widget templates - add new widgets! - //------------------------------------------------ - // Widget templates are stored on Maestrano API, stub your - // new widget templates here, and contact us for permenant additions or - // changes to existing widget templates. - widgetsTemplates: [ - // Example widget template, please see documentation "How-To: Create a Widget" for available - // options, and importantly, note how the path & metadata.template attributes work. - // -- - // { - // path: 'accounts/assets_summary', - // name: 'Assets / Liabilities summary', - // metadata: { template: 'accounts/assets_liability_summary' }, - // desc: 'Compare Assets and Liabilities accounts', - // icon: 'pie-chart', - // width: 3 - // }, - ] - // -- - }; -}); - -//-------------------------------------------------------- -// Do not edit below unless you know what you're doing. -//-------------------------------------------------------- - -// HTTP Interceptor -//-------------------------------------------------------- -// Applies headers / configurations to certain requests. -module.factory('domainSpecificAuthorization', function($window, settings){ - return { - request: function(config) { - // encodes a base64 string - Basic Authentication. - var credentials = $window.btoa(settings.api_key + ':' + settings.api_secret); - var url = config.url; - // merges basic auth with headers if url is to Maestrano's ecosystem. - if (url.indexOf(settings.mno_url) >= 0 || url.indexOf(settings.impac_url) >= 0) { - angular.extend(config.headers, { Authorization: 'Basic ' + credentials }); - } - return config; - } - }; -}); -module.config(function ($httpProvider) { - $httpProvider.interceptors.push('domainSpecificAuthorization'); -}); -// -- -// Impac! Angular Provider configurations -// ------------------------------------------------------- -module.run(function ($log, $q, $http, ImpacLinking, ImpacAssets, ImpacRoutes, ImpacTheming, ImpacDeveloper, settings, toastr) { - - // Check credentials have been provided - if (!settings.api_key || !settings.api_secret) { - fail('Missing authentication credentials!'); - } - - // Configure the ImpacRoutes service options. - var routesConfig = { - mnoHub: settings.mno_url + '/api/v2', - impacPrefix: '/impac', - impacApi: settings.impac_url + '/api', - kpis: { - index: settings.mno_url + '/api/v2/impac/kpis' - } - }; - if (settings.multiple_watchables_mode) { delete routesConfig.kpis; } - ImpacRoutes.configureRoutes(routesConfig); - - // Configure the ImpacTheming service options. - ImpacTheming.configure({ - dhbKpisConfig: { - enableKpis: true - }, - alertsConfig: { - enableAlerts: true - }, - dhbConfig: { - showDhbHeading: true, - dhbHeadingText: 'Your business at a glance, in real-time' - }, - dhbSelectorConfig: { - selectorType: 'dropdown', - pdfModeEnabled: true - }, - dhbSettings: { - syncApps: { - show: function() { return false; } - } - } - }); - - // Link Impac! Assets - ImpacAssets.configure({ - defaultImagesPath: '/dist/images', - }) - - // Configure the ImpacDeveloper service options. - ImpacDeveloper.configure({ - status: true, - widgetsTemplates: settings.widgetsTemplates || [] - }); - - // Link core callbacks required for impac-angular lib to run. - ImpacLinking.linkData({ - organizations: function () { - return getOrganizations(settings.org_uid); - }, - user: function () { - return getUser(); - }, - pusher_key: 'e98dfd8e4a359a7faf48' // Maestrano pusher account key. - }); - - function getOrganizations(orgUid) { - var deferred = $q.defer(); - getUserData().then(function (user) { - var orgs = (user.organizations || []); - var orga = orgs.find(function(orga) { return orga.uid == orgUid }); - var orgId = (orga && orga.id) || orgs[0].id || null; - - deferred.resolve({ organizations: orgs, currentOrgId: orgId }); - }, function (err) { - deferred.reject(err); - }); - return deferred.promise; - } - - function getUser() { - var deferred = $q.defer(); - getUserData().then(function (user) { - deferred.resolve(user); - }, function (err) { - deferred.reject(err); - }); - return deferred.promise; - } - - function getUserData() { - return $http.get(settings.mno_url + '/api/v2/current_user') - .then(function (response) { - return response.data; - }, function () { - var msg = 'Unable to retrieve Organizations'; - fail(msg); - return $q.reject(msg); - }); - } - - function fail(msg) { - $log.error('workspace/index.js Error: ' + msg); - toastr.error(msg, 'Error'); - } - -}); diff --git a/workspace/settings.json b/workspace/settings.json deleted file mode 100644 index 7f8bb0a1..00000000 --- a/workspace/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "url": "http://localhost:3000", - "api_key": "7149f0c91d7e995c10be79ed4881c035d662632995e852f550313345e0f0b982", - "api_secret": "4a776ea4-8134-4f38-b632-85cbe951524e" -} From a5234afa781e47c8e8116caade01d44e58e021b5 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Tue, 18 Oct 2016 15:40:05 +0100 Subject: [PATCH 02/16] Dev workspace add login via form --- workspace/app/app.js | 5 --- workspace/app/services/dev-user.svc.js | 37 +++++++++++-------- workspace/app/services/settings.svc.js | 5 +-- .../views/workspace/login/login.controller.js | 11 ++++-- .../app/views/workspace/login/login.html | 20 ++++++++-- workspace/app/views/workspace/workspace.css | 18 ++++++++- workspace/index.html | 1 + 7 files changed, 64 insertions(+), 33 deletions(-) diff --git a/workspace/app/app.js b/workspace/app/app.js index a69d45c5..9102e30c 100644 --- a/workspace/app/app.js +++ b/workspace/app/app.js @@ -61,11 +61,6 @@ module.config(function (AuthProvider) { // ------------------------------------------------------- module.run(function (ImpacLinking, ImpacAssets, ImpacRoutes, ImpacTheming, ImpacDeveloper, DevUser, settings) { - // Check have been provided - if (!settings.email || !settings.password) { - DevUser.fail('Missing login credentials!'); - } - // Configure ImpacRoutes // ------------------------------------------------------- var mnoHub = settings.mno_url; diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js index a40d995e..279a264e 100644 --- a/workspace/app/services/dev-user.svc.js +++ b/workspace/app/services/dev-user.svc.js @@ -8,8 +8,8 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A this.isAuthenticated = Auth.isAuthenticated; this.getUserData = function() { - return $http.get(settings.mno_url + '/current_user') - .then(function (response) { + return $http.get(settings.mno_url + '/current_user').then( + function (response) { var user = (response.data && response.data.current_user); if (!user.logged_in) { return $q.reject(); @@ -19,27 +19,32 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A var msg = 'Unable to retrieve Organizations'; _self.fail(msg, error); return $q.reject(msg); - }); + } + ); }; this.getOrganizations = function(orgUid) { - return _self.getUserData().then(function (user) { - var orgs = (user.organizations || []); - var orga = orgs.find(function(orga) { return orga.uid == orgUid }); - var orgId = (orga && orga.id) || orgs[0].id || null; + return _self.getUserData().then( + function (user) { + var orgs = (user.organizations || []); + var orga = orgs.find(function(orga) { return orga.uid == orgUid }); + var orgId = (orga && orga.id) || orgs[0].id || null; - return { organizations: orgs, currentOrgId: orgId }; - }, function (err) { - return $q.reject(err); - }); + return { organizations: orgs, currentOrgId: orgId }; + }, function (err) { + return $q.reject(err); + } + ); }; this.getUser = function() { - return _self.getUserData().then(function (user) { - return user; - }, function (err) { - return $q.reject(err); - }); + return _self.getUserData().then( + function (user) { + return user; + }, function (err) { + return $q.reject(err); + } + ); }; this.fail = function (msg, error) { diff --git a/workspace/app/services/settings.svc.js b/workspace/app/services/settings.svc.js index 0e01c0ac..5b725587 100644 --- a/workspace/app/services/settings.svc.js +++ b/workspace/app/services/settings.svc.js @@ -2,16 +2,13 @@ // Impac Workspace Settings // ------------------------------------------------------- // Provide important configurations for the impacWorkspace. +// TODO: create a /settings page for this. angular.module('impacWorkspace').factory('settings', function () { return { // Credentials and endpoints mno_url: '/mnoe/jpi/v1', // rename to mnoe_url impac_url: 'http://localhost:4000', - // TODO: build login form - email: 'xaun.lopez@maestrano.com', - password: 'Test1234', org_uid: '', // First organisations if unspecified - // ----------------------------------------------- // Kpis configurations // ----------------------------------------------- diff --git a/workspace/app/views/workspace/login/login.controller.js b/workspace/app/views/workspace/login/login.controller.js index 617836b2..720a863b 100644 --- a/workspace/app/views/workspace/login/login.controller.js +++ b/workspace/app/views/workspace/login/login.controller.js @@ -1,16 +1,19 @@ -angular.module('impacWorkspace').controller('LoginController', function ($state, DevUser, settings) { +angular.module('impacWorkspace').controller('LoginController', function ($scope, $state, DevUser, settings) { vm = this; if (DevUser.isAuthenticated()) { $state.go('workspace.impac'); } + vm.creds = { email: '', password: '' }; + vm.login = function () { - DevUser.login({email: settings.email, password: settings.password}).then( + DevUser.login(vm.creds).then( function () { $state.go('workspace.impac'); - }, function (error) { - DevUser.fail('Unable to login', error); + }, function (response) { + var msg = (response.data && response.data.error) || 'Unable to login'; + DevUser.fail(msg, response); } ); }; diff --git a/workspace/app/views/workspace/login/login.html b/workspace/app/views/workspace/login/login.html index 33d877b3..8ad1de20 100644 --- a/workspace/app/views/workspace/login/login.html +++ b/workspace/app/views/workspace/login/login.html @@ -1,4 +1,18 @@ -
-

Login Controller

- + diff --git a/workspace/app/views/workspace/workspace.css b/workspace/app/views/workspace/workspace.css index 1398f834..11bce082 100644 --- a/workspace/app/views/workspace/workspace.css +++ b/workspace/app/views/workspace/workspace.css @@ -1,8 +1,20 @@ -/* WORKSPACE */ +html, body { + box-sizing: border-box; + height: 100%; +} + +*, *:before, *:after { + box-sizing: inherit; +} + body { background-color: #E6EDEE; } +#workspace { + height: 100%; +} + #workspace .workspace-header { position: relative; text-align: center; @@ -22,6 +34,10 @@ body { bottom: 17px; } +#workspace .workspace-login { + font-family: 'Share Tech Mono', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + #workspace .workspace-dashboard { margin: 0 auto; width: 91%; diff --git a/workspace/index.html b/workspace/index.html index 21e50f58..b47ae2ec 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -12,6 +12,7 @@ + From 1471d4c4941941c290bf4905b64fa5dc91ea2e95 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Tue, 18 Oct 2016 16:21:30 +0100 Subject: [PATCH 03/16] Fix redirection to login on refresh with session --- workspace/app/services/dev-user.svc.js | 5 +++++ workspace/app/views/workspace/impac/impac.controller.js | 6 +++--- workspace/app/views/workspace/impac/impac.html | 2 +- workspace/app/views/workspace/login/login.controller.js | 7 ++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js index 279a264e..a736abdf 100644 --- a/workspace/app/services/dev-user.svc.js +++ b/workspace/app/services/dev-user.svc.js @@ -3,10 +3,13 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, Auth, settings, toastr) { _self = this; + // Angular Devise methods exposed via this service this.login = Auth.login; this.logout = Auth.logout; this.isAuthenticated = Auth.isAuthenticated; + this.currentUser = Auth.currentUser; + // Get logged in user & organizations from mno-hub this.getUserData = function() { return $http.get(settings.mno_url + '/current_user').then( function (response) { @@ -23,6 +26,7 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A ); }; + // Get organizations with the currentOrgId from workspace settings this.getOrganizations = function(orgUid) { return _self.getUserData().then( function (user) { @@ -47,6 +51,7 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A ); }; + // Logging and Toastr notifications method this.fail = function (msg, error) { if (error == null) { error = ''; } $log.error('Develop Workspace Error: ' + msg, error); diff --git a/workspace/app/views/workspace/impac/impac.controller.js b/workspace/app/views/workspace/impac/impac.controller.js index 202dffd3..05357901 100644 --- a/workspace/app/views/workspace/impac/impac.controller.js +++ b/workspace/app/views/workspace/impac/impac.controller.js @@ -1,11 +1,11 @@ angular.module('impacWorkspace').controller('ImpacController', function ($state, DevUser) { vm = this; - vm.showImpac = DevUser.isAuthenticated(); + vm.showImpac = DevUser.isAuthenticated; - if (!vm.showImpac) { + DevUser.currentUser().then(null, function () { $state.go('workspace.login'); - } + }); return vm; }); diff --git a/workspace/app/views/workspace/impac/impac.html b/workspace/app/views/workspace/impac/impac.html index 8bd0dba8..342e5680 100644 --- a/workspace/app/views/workspace/impac/impac.html +++ b/workspace/app/views/workspace/impac/impac.html @@ -1,3 +1,3 @@
- +
diff --git a/workspace/app/views/workspace/login/login.controller.js b/workspace/app/views/workspace/login/login.controller.js index 720a863b..f2160350 100644 --- a/workspace/app/views/workspace/login/login.controller.js +++ b/workspace/app/views/workspace/login/login.controller.js @@ -1,8 +1,13 @@ -angular.module('impacWorkspace').controller('LoginController', function ($scope, $state, DevUser, settings) { +angular.module('impacWorkspace').controller('LoginController', function ($state, DevUser, settings) { vm = this; + if (DevUser.isAuthenticated()) { $state.go('workspace.impac'); + } else { + DevUser.currentUser().then(function () { + $state.go('workspace.impac'); + }); } vm.creds = { email: '', password: '' }; From 3e5a1e18fdeaa86d166c1be7c35655f189b0f3f6 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Tue, 18 Oct 2016 17:07:38 +0100 Subject: [PATCH 04/16] Current User Organization top bar info display --- workspace/app/services/dev-user.svc.js | 11 +++++++++++ .../views/workspace/workspace.controller.js | 19 +++++++++++++++---- workspace/app/views/workspace/workspace.css | 14 ++++++++++++++ workspace/app/views/workspace/workspace.html | 19 ++++++++++++++++++- 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js index a736abdf..33095c19 100644 --- a/workspace/app/services/dev-user.svc.js +++ b/workspace/app/services/dev-user.svc.js @@ -26,6 +26,17 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A ); }; + this.getCurrentOrganization = function() { + var deferred = $q.defer(); + _self.getOrganizations(settings.org_uid).then(function (response) { + currentOrg = _.find(response.organizations, function (org) { + return org.id == response.currentOrgId; + }); + deferred.notify(currentOrg); + }); + return deferred.promise; + }; + // Get organizations with the currentOrgId from workspace settings this.getOrganizations = function(orgUid) { return _self.getUserData().then( diff --git a/workspace/app/views/workspace/workspace.controller.js b/workspace/app/views/workspace/workspace.controller.js index 556bd6f5..2e2d0140 100644 --- a/workspace/app/views/workspace/workspace.controller.js +++ b/workspace/app/views/workspace/workspace.controller.js @@ -1,13 +1,18 @@ -angular.module('impacWorkspace').controller('WorkspaceController', function ($state, DevUser) { +angular.module('impacWorkspace').controller('WorkspaceController', function ($scope, $state, DevUser) { main = this; - main.isAuthenticated = function () { - return DevUser.isAuthenticated(); - }; + main.isAuthenticated = DevUser.isAuthenticated; + + main.currentOrganization = {}; + + $scope.$on('devise:login', function () { + setCurrentOrganization(); + }); main.logout = function () { DevUser.logout().then( function () { + main.currentOrganization = {}; $state.go('workspace.login'); }, function (error) { @@ -16,6 +21,12 @@ angular.module('impacWorkspace').controller('WorkspaceController', function ($st ); }; + function setCurrentOrganization() { + DevUser.getCurrentOrganization().then(null, null, function(org) { + main.currentOrganization = org; + }); + } + return main; }); diff --git a/workspace/app/views/workspace/workspace.css b/workspace/app/views/workspace/workspace.css index 11bce082..1ed80124 100644 --- a/workspace/app/views/workspace/workspace.css +++ b/workspace/app/views/workspace/workspace.css @@ -34,6 +34,20 @@ body { bottom: 17px; } +#workspace .workspace-header .current-org { + position: absolute; + top: 13px; + left: 75px; +} +#workspace .workspace-header .current-org td, +#workspace .workspace-header .current-org th { + padding: 0px 10px; +} + +#workspace .workspace-header .current-org .current-org-results { + color: #74dd74; +} + #workspace .workspace-login { font-family: 'Share Tech Mono', 'Helvetica Neue', Helvetica, Arial, sans-serif; } diff --git a/workspace/app/views/workspace/workspace.html b/workspace/app/views/workspace/workspace.html index 6363882b..f5af535b 100644 --- a/workspace/app/views/workspace/workspace.html +++ b/workspace/app/views/workspace/workspace.html @@ -1,9 +1,26 @@
+
+ + + + + + + + + + + + + + + +
UIDNameRole
{{main.currentOrganization.uid || '-'}}{{main.currentOrganization.name || '-'}}{{main.currentOrganization.current_user_role || '-'}}
+

IMPAC! DEVELOPER WORKSPACE

- From 0254075bbf5215db049989623a9327b0e24d25c9 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Tue, 18 Oct 2016 17:24:13 +0100 Subject: [PATCH 05/16] Add login page styles --- workspace/app/views/workspace/login/login.css | 17 +++++++++++++++++ workspace/app/views/workspace/login/login.html | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 workspace/app/views/workspace/login/login.css diff --git a/workspace/app/views/workspace/login/login.css b/workspace/app/views/workspace/login/login.css new file mode 100644 index 00000000..cd893443 --- /dev/null +++ b/workspace/app/views/workspace/login/login.css @@ -0,0 +1,17 @@ +.workspace-login .login-box-container { + text-align: center; + margin-top: 100px; +} + +.workspace-login .login-box { + width: 360px; + margin: auto; + padding: 10px 20px 20px 20px; + border-radius: 3px; +} + +.workspace-login .login-box-title { + color: rgb(117, 129, 146); + margin-bottom: 15px; + text-transform: uppercase; +} diff --git a/workspace/app/views/workspace/login/login.html b/workspace/app/views/workspace/login/login.html index 8ad1de20..3825839f 100644 --- a/workspace/app/views/workspace/login/login.html +++ b/workspace/app/views/workspace/login/login.html @@ -11,7 +11,7 @@

Sign In

- +
From ad58f7a4349a9135cbdd1782992de46f7830a124 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Wed, 19 Oct 2016 17:53:40 +0100 Subject: [PATCH 06/16] Edit settings via a settings page --- workspace/app/app.js | 67 +++-------- workspace/app/services/dev-settings.svc.js | 113 ++++++++++++++++++ workspace/app/services/dev-user.svc.js | 22 ++-- workspace/app/services/settings.svc.js | 38 ------ .../views/workspace/login/login.controller.js | 2 +- workspace/app/views/workspace/login/login.css | 10 +- .../app/views/workspace/login/login.html | 2 +- .../workspace/settings/settings.controller.js | 53 ++++++++ .../app/views/workspace/settings/settings.css | 39 ++++++ .../views/workspace/settings/settings.html | 41 +++++++ .../views/workspace/workspace.controller.js | 14 ++- workspace/app/views/workspace/workspace.css | 28 ++--- workspace/app/views/workspace/workspace.html | 49 ++++---- workspace/index.html | 4 +- 14 files changed, 342 insertions(+), 140 deletions(-) create mode 100644 workspace/app/services/dev-settings.svc.js delete mode 100644 workspace/app/services/settings.svc.js create mode 100644 workspace/app/views/workspace/settings/settings.controller.js create mode 100644 workspace/app/views/workspace/settings/settings.css create mode 100644 workspace/app/views/workspace/settings/settings.html diff --git a/workspace/app/app.js b/workspace/app/app.js index 9102e30c..f8576b8b 100644 --- a/workspace/app/app.js +++ b/workspace/app/app.js @@ -35,6 +35,12 @@ module.config(function ($stateProvider, $urlRouterProvider) { templateUrl: 'app/views/workspace/impac/impac.html', controller: 'ImpacController', controllerAs: 'vm' + }) + .state('workspace.settings', { + url: '/settings', + templateUrl: 'app/views/workspace/settings/settings.html', + controller: 'SettingsController', + controllerAs: 'vm' }); }); @@ -44,54 +50,28 @@ module.config(function ($stateProvider, $urlRouterProvider) { // ------------------------------------------------------- module.config(function (AuthProvider) { // Customize login - AuthProvider.loginMethod('POST') - AuthProvider.loginPath('mnoe/auth/users/sign_in.json') + AuthProvider.loginMethod('POST'); + AuthProvider.loginPath('mnoe/auth/users/sign_in.json'); // Customize logout - AuthProvider.logoutMethod('DELETE') - AuthProvider.logoutPath('mnoe/auth/users/sign_out.json') + AuthProvider.logoutMethod('DELETE'); + AuthProvider.logoutPath('mnoe/auth/users/sign_out.json'); // Customize register - AuthProvider.registerMethod('POST') - AuthProvider.registerPath('mnoe/auth/users') + AuthProvider.registerMethod('POST'); + AuthProvider.registerPath('mnoe/auth/users'); }); // -- // Impac! Angular Provider Service Configurations // ------------------------------------------------------- -module.run(function (ImpacLinking, ImpacAssets, ImpacRoutes, ImpacTheming, ImpacDeveloper, DevUser, settings) { +module.run(function (ImpacLinking, ImpacAssets, ImpacRoutes, ImpacTheming, ImpacDeveloper, DevUser, DevSettings) { + + var defaults = DevSettings.defaults(); // Configure ImpacRoutes // ------------------------------------------------------- - var mnoHub = settings.mno_url; - var impacPrefix = "/impac"; - var routesConfig = { - mnoHub: mnoHub, - impacPrefix: impacPrefix, - impacApi: settings.impac_url + "/api", - dashboards: { - index: mnoHub + impacPrefix + "/dashboards" - }, - widgets: { - index: mnoHub + impacPrefix + "/widgets", - create: mnoHub + impacPrefix + "/dashboards/:dashboard_id/widgets" - }, - kpis: { - index: mnoHub + impacPrefix + "/kpis", - create: mnoHub + impacPrefix + "/dashboards/:dashboard_id/kpis", - update: mnoHub + impacPrefix + "/kpis/:id", - del: mnoHub + impacPrefix + "/kpis/:id" - }, - alerts: { - index: mnoHub + impacPrefix + "/alerts", - create: mnoHub + impacPrefix + "/kpis/:kpi_id/alerts", - del: mnoHub + impacPrefix + "/alerts/:id" - } - }; - // Removes custom index path, defaulting kpi discovery to impac api, where KPIs with - // multiple watchables are returned. - if (settings.multiple_watchables_mode) { delete routesConfig.kpis.index; } - ImpacRoutes.configureRoutes(routesConfig); + ImpacRoutes.configureRoutes(DevSettings.buildRoutesConfig(defaults.mnoeUrl, defaults.impacUrl, defaults.multipleWatchableMode)); // Configure ImpacTheming - aesthetic and feature customisations across the app @@ -126,21 +106,10 @@ module.run(function (ImpacLinking, ImpacAssets, ImpacRoutes, ImpacTheming, Impac // Configure ImpacDeveloper - developer toolkit specifc customisations // ------------------------------------------------------- - ImpacDeveloper.configure({ - status: true, - widgetsTemplates: settings.widgetsTemplates || [] - }); + ImpacDeveloper.configure(DevSettings.buildDeveloperConfig(defaults.widgetsTemplates)); // Configure ImpacLinking - Links core callbacks required for impac-angular lib to run. // ------------------------------------------------------- - ImpacLinking.linkData({ - organizations: function () { - return DevUser.getOrganizations(settings.org_uid); - }, - user: function () { - return DevUser.getUser(); - }, - pusher_key: 'e98dfd8e4a359a7faf48' // Maestrano pusher account key. - }); + ImpacLinking.linkData(DevSettings.buildLinkingConfig(defaults.orgUid, defaults.mnoeUrl)); }); diff --git a/workspace/app/services/dev-settings.svc.js b/workspace/app/services/dev-settings.svc.js new file mode 100644 index 00000000..c2a47144 --- /dev/null +++ b/workspace/app/services/dev-settings.svc.js @@ -0,0 +1,113 @@ +// ------------------------------------------------------- +// Impac Workspace Settings +// ------------------------------------------------------- +// Provide important configurations for the impacWorkspace. +// TODO: create a /settings page for this. +angular.module('impacWorkspace').service('DevSettings', function ($q, ImpacRoutes, ImpacLinking, ImpacDeveloper, DevUser) { + var _self = this; + + var DEFAULTS = { + // Credentials and endpoints + mnoeUrl: '/mnoe/jpi/v1', + impacUrl: 'http://localhost:4000', + orgUid: '', // First organisations if unspecified + // ----------------------------------------------- + // Kpis configurations + // ----------------------------------------------- + // Change this to `true` to force kpi's to allow multiple watchables, instead of + // using the mno_hub kpis#discover action maps kpis to have single watchables per kpi. + multipleWatchableMode: false, + // Stub widget templates - add new widgets! + //------------------------------------------------ + // Widget templates are stored on Maestrano API, stub your + // new widget templates here, and contact us for permenant additions or + // changes to existing widget templates. + widgetsTemplates: [ + // Example widget template, please see documentation "How-To: Create a Widget" for available + // options, and importantly, note how the path & metadata.template attributes work. + // -- + // { + // path: 'accounts/assets_summary', + // name: 'Assets / Liabilities summary', + // metadata: { template: 'accounts/assets_liability_summary' }, + // desc: 'Compare Assets and Liabilities accounts', + // icon: 'pie-chart', + // width: 3 + // }, + ] + }; + + this._defaults = angular.copy(DEFAULTS); + + this.defaults = function () { + return angular.copy(_self._defaults); + }; + + this.resetDefaults = function () { + return _self._defaults = angular.copy(DEFAULTS); + } + + + // NOTE: this will be refactored a lot when mnoe routes are added as default + // in impac-angular. + this.buildRoutesConfig = function (mnoeUrl, impacUrl, multipleWatchableMode) { + var routesConfig = { + mnoHub: mnoeUrl, + impacPrefix: "/impac", + impacApi: impacUrl + "/api", + dashboards: { + index: mnoeUrl + "/impac/dashboards" + }, + widgets: { + index: mnoeUrl + "/impac/widgets", + create: mnoeUrl + "/impac/dashboards/:dashboard_id/widgets" + }, + kpis: { + index: mnoeUrl + "/impac/kpis", + create: mnoeUrl + "/impac/dashboards/:dashboard_id/kpis", + update: mnoeUrl + "/impac/kpis/:id", + del: mnoeUrl + "/impac/kpis/:id" + }, + alerts: { + index: mnoeUrl + "/impac/alerts", + create: mnoeUrl + "/impac/kpis/:kpi_id/alerts", + del: mnoeUrl + "/impac/alerts/:id" + } + } + // Removes custom index path, defaulting kpi discovery to impac api, where KPIs with + // multiple watchables are returned. + if (multipleWatchableMode) { delete routesConfig.kpis.index; } + return angular.copy(routesConfig) + }; + + this.buildLinkingConfig = function (orgUid, mnoeUrl) { + return { + organizations: function () { + return DevUser.getOrganizations(orgUid, mnoeUrl); + }, + user: function () { + return DevUser.getUser(mnoeUrl); + }, + pusher_key: 'e98dfd8e4a359a7faf48' // Maestrano pusher account key. + } + } + + this.buildDeveloperConfig = function (widgetsTemplates) { + return { + status: true, + widgetsTemplates: widgetsTemplates + } + }; + + this.updateProviders = function (data) { + console.log('data: ', data) + ImpacRoutes.configureRoutes(_self.buildRoutesConfig(data.mnoeUrl, data.impacUrl, data.multipleWatchableMode)); + ImpacLinking.linkData(_self.buildLinkingConfig(data.orgUid, data.mnoeUrl)); + ImpacDeveloper.configure(_self.buildDeveloperConfig(data.widgetsTemplates)); + + // Save settings data to this service's copy of defaults. + _self._defaults = data; + }; + + return this; +}); diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js index 33095c19..fc4b745f 100644 --- a/workspace/app/services/dev-user.svc.js +++ b/workspace/app/services/dev-user.svc.js @@ -1,7 +1,7 @@ // Impac! Angular DevUser Service - providing core authentication logic for Impac! developers. // -------------------------------------------------------- -angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, Auth, settings, toastr) { - _self = this; +angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, Auth, toastr) { + var _self = this; // Angular Devise methods exposed via this service this.login = Auth.login; @@ -10,8 +10,8 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A this.currentUser = Auth.currentUser; // Get logged in user & organizations from mno-hub - this.getUserData = function() { - return $http.get(settings.mno_url + '/current_user').then( + this.getUserData = function(mnoeUrl) { + return $http.get(mnoeUrl + '/current_user').then( function (response) { var user = (response.data && response.data.current_user); if (!user.logged_in) { @@ -26,10 +26,10 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A ); }; - this.getCurrentOrganization = function() { + this.getCurrentOrganization = function(orgUid, mnoeUrl) { var deferred = $q.defer(); - _self.getOrganizations(settings.org_uid).then(function (response) { - currentOrg = _.find(response.organizations, function (org) { + _self.getOrganizations(orgUid, mnoeUrl).then(function (response) { + var currentOrg = _.find(response.organizations, function (org) { return org.id == response.currentOrgId; }); deferred.notify(currentOrg); @@ -38,8 +38,8 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A }; // Get organizations with the currentOrgId from workspace settings - this.getOrganizations = function(orgUid) { - return _self.getUserData().then( + this.getOrganizations = function(orgUid, mnoeUrl) { + return _self.getUserData(mnoeUrl).then( function (user) { var orgs = (user.organizations || []); var orga = orgs.find(function(orga) { return orga.uid == orgUid }); @@ -52,8 +52,8 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A ); }; - this.getUser = function() { - return _self.getUserData().then( + this.getUser = function(mnoeUrl) { + return _self.getUserData(mnoeUrl).then( function (user) { return user; }, function (err) { diff --git a/workspace/app/services/settings.svc.js b/workspace/app/services/settings.svc.js deleted file mode 100644 index 5b725587..00000000 --- a/workspace/app/services/settings.svc.js +++ /dev/null @@ -1,38 +0,0 @@ -// ------------------------------------------------------- -// Impac Workspace Settings -// ------------------------------------------------------- -// Provide important configurations for the impacWorkspace. -// TODO: create a /settings page for this. -angular.module('impacWorkspace').factory('settings', function () { - return { - // Credentials and endpoints - mno_url: '/mnoe/jpi/v1', // rename to mnoe_url - impac_url: 'http://localhost:4000', - org_uid: '', // First organisations if unspecified - // ----------------------------------------------- - // Kpis configurations - // ----------------------------------------------- - // Change this to `true` to force kpi's to allow multiple watchables, instead of - // using the mno_hub kpis#discover action maps kpis to have single watchables per kpi. - multiple_watchables_mode: false, - // Stub widget templates - add new widgets! - //------------------------------------------------ - // Widget templates are stored on Maestrano API, stub your - // new widget templates here, and contact us for permenant additions or - // changes to existing widget templates. - widgetsTemplates: [ - // Example widget template, please see documentation "How-To: Create a Widget" for available - // options, and importantly, note how the path & metadata.template attributes work. - // -- - // { - // path: 'accounts/assets_summary', - // name: 'Assets / Liabilities summary', - // metadata: { template: 'accounts/assets_liability_summary' }, - // desc: 'Compare Assets and Liabilities accounts', - // icon: 'pie-chart', - // width: 3 - // }, - ] - // -- - }; -}); diff --git a/workspace/app/views/workspace/login/login.controller.js b/workspace/app/views/workspace/login/login.controller.js index f2160350..054f2a3c 100644 --- a/workspace/app/views/workspace/login/login.controller.js +++ b/workspace/app/views/workspace/login/login.controller.js @@ -1,4 +1,4 @@ -angular.module('impacWorkspace').controller('LoginController', function ($state, DevUser, settings) { +angular.module('impacWorkspace').controller('LoginController', function ($state, DevUser) { vm = this; diff --git a/workspace/app/views/workspace/login/login.css b/workspace/app/views/workspace/login/login.css index cd893443..09588a74 100644 --- a/workspace/app/views/workspace/login/login.css +++ b/workspace/app/views/workspace/login/login.css @@ -1,16 +1,20 @@ -.workspace-login .login-box-container { +#workspace .workspace-login { + font-family: 'Share Tech Mono', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +#workspace .workspace-login .login-box-container { text-align: center; margin-top: 100px; } -.workspace-login .login-box { +#workspace .workspace-login .login-box { width: 360px; margin: auto; padding: 10px 20px 20px 20px; border-radius: 3px; } -.workspace-login .login-box-title { +#workspace .workspace-login .login-box-title { color: rgb(117, 129, 146); margin-bottom: 15px; text-transform: uppercase; diff --git a/workspace/app/views/workspace/login/login.html b/workspace/app/views/workspace/login/login.html index 3825839f..a64a983a 100644 --- a/workspace/app/views/workspace/login/login.html +++ b/workspace/app/views/workspace/login/login.html @@ -11,7 +11,7 @@

Sign In

- + diff --git a/workspace/app/views/workspace/settings/settings.controller.js b/workspace/app/views/workspace/settings/settings.controller.js new file mode 100644 index 00000000..c8e20397 --- /dev/null +++ b/workspace/app/views/workspace/settings/settings.controller.js @@ -0,0 +1,53 @@ +angular.module('impacWorkspace').controller('SettingsController', function ($scope, $state, DevUser, DevSettings) { + vm = this; + + vm.settings = DevSettings.defaults(); + vm.settings.orgUid = main.currentOrganization.uid || ''; + vm.updateError = ''; + + DevUser.currentUser().then(null, function () { + $state.go('workspace.login'); + }); + + DevUser.getOrganizations(vm.settings.orgUid, vm.settings.mnoeUrl).then(function (data) { + vm.availableOrgUids = _.map(data.organizations, function (org) { + return org.uid; + }); + }); + + // On new session (load), current org uid is broadcasted here when it is has been set in the + // workspace.controller. + $scope.$on('current-org-uid', function (event, orgUid) { + vm.settings.orgUid = orgUid; + }); + + vm.update = function () { + if (validateJson() == false) { return; } + DevSettings.updateProviders(vm.settings); + $scope.$emit('updated-providers'); + $state.go('workspace.impac'); + }; + + vm.back = function () { + $state.go('workspace.impac'); + }; + + vm.resetDefaults = function () { + vm.settings = DevSettings.resetDefaults(); + vm.settings.orgUid = main.currentOrganization.uid || ''; + } + + function validateJson () { + var json = document.getElementById('widgets-templates-textarea').value; + try { + var obj = JSON.parse(json); + } catch (e) { + vm.updateError = 'Invalid JSON for Widgets Templates'; + return false; + } + vm.settings.widgetsTemplates = [obj]; + return true; + } + + return vm; +}); diff --git a/workspace/app/views/workspace/settings/settings.css b/workspace/app/views/workspace/settings/settings.css new file mode 100644 index 00000000..457e5c21 --- /dev/null +++ b/workspace/app/views/workspace/settings/settings.css @@ -0,0 +1,39 @@ +#workspace .workspace-settings { + font-family: 'Share Tech Mono', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +#workspace .workspace-settings .settings-box-container { + text-align: center; + margin-top: 100px; +} + +#workspace .workspace-settings .settings-box { + width: 360px; + margin: auto; + padding: 10px 20px 20px 20px; + border-radius: 3px; +} + +#workspace .workspace-settings .settings-box .checkbox { + text-align: left; + margin-left:10px; +} + +#workspace .workspace-settings .settings-box .settings-actions { + margin-top: 30px; +} + +#workspace .workspace-settings .settings-box-container .settings-box .form-group { + text-align: left; +} + +#workspace .workspace-settings .settings-box-title { + color: rgb(117, 129, 146); + margin-bottom: 15px; + text-transform: uppercase; +} + +#workspace .workspace-settings .settings-error { + margin-top: 20px; + color: red; +} diff --git a/workspace/app/views/workspace/settings/settings.html b/workspace/app/views/workspace/settings/settings.html new file mode 100644 index 00000000..6dc497b5 --- /dev/null +++ b/workspace/app/views/workspace/settings/settings.html @@ -0,0 +1,41 @@ +
+
+
+

Workspace Settings

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ + + +
+
+

{{vm.updateError}}

+
+
+
+
+
diff --git a/workspace/app/views/workspace/workspace.controller.js b/workspace/app/views/workspace/workspace.controller.js index 2e2d0140..b28440bd 100644 --- a/workspace/app/views/workspace/workspace.controller.js +++ b/workspace/app/views/workspace/workspace.controller.js @@ -1,4 +1,4 @@ -angular.module('impacWorkspace').controller('WorkspaceController', function ($scope, $state, DevUser) { +angular.module('impacWorkspace').controller('WorkspaceController', function ($scope, $state, DevUser, DevSettings) { main = this; main.isAuthenticated = DevUser.isAuthenticated; @@ -9,6 +9,14 @@ angular.module('impacWorkspace').controller('WorkspaceController', function ($sc setCurrentOrganization(); }); + $scope.$on('updated-providers', function () { + setCurrentOrganization(); + }); + + main.settings = function () { + $state.go('workspace.settings'); + }; + main.logout = function () { DevUser.logout().then( function () { @@ -22,8 +30,10 @@ angular.module('impacWorkspace').controller('WorkspaceController', function ($sc }; function setCurrentOrganization() { - DevUser.getCurrentOrganization().then(null, null, function(org) { + defaults = DevSettings.defaults(); + DevUser.getCurrentOrganization(defaults.orgUid, defaults.mnoeUrl).then(null, null, function(org) { main.currentOrganization = org; + $scope.$broadcast('current-org-uid', org.uid) }); } diff --git a/workspace/app/views/workspace/workspace.css b/workspace/app/views/workspace/workspace.css index 1ed80124..ed4db28a 100644 --- a/workspace/app/views/workspace/workspace.css +++ b/workspace/app/views/workspace/workspace.css @@ -17,28 +17,32 @@ body { #workspace .workspace-header { position: relative; - text-align: center; background-color: black; color: white; + min-width: 100%; + min-height: 70px; font-family: 'Share Tech Mono', 'Helvetica Neue', Helvetica, Arial, sans-serif; } +#workspace .workspace-header .workspace-title { + text-align: center; +} + #workspace .workspace-header h1 { - margin: 0; - padding: 15px 40px; + margin: 15px 0 0 0; + font-size: 32px; } -#workspace .workspace-header button { - position: absolute; - right: 70px; - bottom: 17px; +#workspace .workspace-header .workspace-actions { + text-align: right; + margin: 17px 60px 10px 0px; } #workspace .workspace-header .current-org { - position: absolute; - top: 13px; - left: 75px; + margin-top: 14px; + margin-left: 70px; } + #workspace .workspace-header .current-org td, #workspace .workspace-header .current-org th { padding: 0px 10px; @@ -48,10 +52,6 @@ body { color: #74dd74; } -#workspace .workspace-login { - font-family: 'Share Tech Mono', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - #workspace .workspace-dashboard { margin: 0 auto; width: 91%; diff --git a/workspace/app/views/workspace/workspace.html b/workspace/app/views/workspace/workspace.html index f5af535b..6bc80a1d 100644 --- a/workspace/app/views/workspace/workspace.html +++ b/workspace/app/views/workspace/workspace.html @@ -1,25 +1,34 @@
-
-
- - - - - - - - - - - - - - - -
UIDNameRole
{{main.currentOrganization.uid || '-'}}{{main.currentOrganization.name || '-'}}{{main.currentOrganization.current_user_role || '-'}}
+
+
+
+ + + + + + + + + + + + + + + +
UIDNameRole
{{main.currentOrganization.uid || '-'}}{{main.currentOrganization.name || '-'}}{{main.currentOrganization.current_user_role || '-'}}
+
+
+
+

IMPAC! DEVELOPER WORKSPACE

+
+
+
+ + +
-

IMPAC! DEVELOPER WORKSPACE

-
diff --git a/workspace/index.html b/workspace/index.html index b47ae2ec..95cd6a7d 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -12,6 +12,7 @@ + @@ -47,10 +48,11 @@ + - + From f662e171d20bc2cef7a688178f46d8dda2e60c84 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Wed, 19 Oct 2016 17:58:31 +0100 Subject: [PATCH 07/16] Settings page display stringified widgetTemplates --- .../app/views/workspace/settings/settings.controller.js | 5 +++-- workspace/app/views/workspace/settings/settings.html | 2 +- workspace/index.html | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/workspace/app/views/workspace/settings/settings.controller.js b/workspace/app/views/workspace/settings/settings.controller.js index c8e20397..c228c9d3 100644 --- a/workspace/app/views/workspace/settings/settings.controller.js +++ b/workspace/app/views/workspace/settings/settings.controller.js @@ -3,6 +3,7 @@ angular.module('impacWorkspace').controller('SettingsController', function ($sco vm.settings = DevSettings.defaults(); vm.settings.orgUid = main.currentOrganization.uid || ''; + vm.settings.widgetsTemplates = JSON.stringify(vm.settings.widgetsTemplates, undefined, 4) vm.updateError = ''; DevUser.currentUser().then(null, function () { @@ -40,12 +41,12 @@ angular.module('impacWorkspace').controller('SettingsController', function ($sco function validateJson () { var json = document.getElementById('widgets-templates-textarea').value; try { - var obj = JSON.parse(json); + var array = JSON.parse(json); } catch (e) { vm.updateError = 'Invalid JSON for Widgets Templates'; return false; } - vm.settings.widgetsTemplates = [obj]; + vm.settings.widgetsTemplates = array; return true; } diff --git a/workspace/app/views/workspace/settings/settings.html b/workspace/app/views/workspace/settings/settings.html index 6dc497b5..51199005 100644 --- a/workspace/app/views/workspace/settings/settings.html +++ b/workspace/app/views/workspace/settings/settings.html @@ -19,7 +19,7 @@

Workspace Settings

- +
-
- - +
+ +
+
+
+
+ + +
+
+
+
+ + +
+
- - +
+ +
+
+
+
+ + +
+
+
+
+ + +
+
+
From 9e314272421e935fac31ca734c27d358bebcec94 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Thu, 20 Oct 2016 14:11:41 +0100 Subject: [PATCH 10/16] Cleaned up comments & todos --- src/services/routes/routes.svc.coffee | 1 + workspace/app/services/dev-settings.svc.js | 10 ++++++---- workspace/app/services/dev-user.svc.js | 15 ++++++++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/services/routes/routes.svc.coffee b/src/services/routes/routes.svc.coffee index bf0e85db..040b0dd1 100644 --- a/src/services/routes/routes.svc.coffee +++ b/src/services/routes/routes.svc.coffee @@ -1,4 +1,5 @@ # provider for configuring http endpoints. +# TODO: REFACTOR THIS FOR MNOE AS DEFAULT + REVISE BASE PATHS DEFAULTS. angular .module('impac.services.routes', []) .provider('ImpacRoutes', () -> diff --git a/workspace/app/services/dev-settings.svc.js b/workspace/app/services/dev-settings.svc.js index e035b109..d7ecac3f 100644 --- a/workspace/app/services/dev-settings.svc.js +++ b/workspace/app/services/dev-settings.svc.js @@ -1,13 +1,13 @@ // ------------------------------------------------------- // Impac Workspace Settings +// -------- +// Providing Impac! Angular defaults and configuration abilities. // ------------------------------------------------------- -// Provide important configurations for the impacWorkspace. -// TODO: create a /settings page for this. angular.module('impacWorkspace').service('DevSettings', function ($q, ImpacRoutes, ImpacLinking, ImpacDeveloper, DevUser) { var _self = this; var DEFAULTS = { - // Credentials and endpoints + // API Endpoints mnoeUrl: { host: '', base: '/mnoe/jpi/v1' @@ -16,7 +16,8 @@ angular.module('impacWorkspace').service('DevSettings', function ($q, ImpacRoute host: 'http://localhost:4000', base: '/api' }, - orgUid: '', // First organisations if unspecified + // Selected Organization - first organisations if unspecified + orgUid: '', // ----------------------------------------------- // Kpis configurations // ----------------------------------------------- @@ -94,6 +95,7 @@ angular.module('impacWorkspace').service('DevSettings', function ($q, ImpacRoute user: function () { return DevUser.getUser(mnoeUrl); }, + // TODO: add pusher key to advance settings on #/settings. pusher_key: 'e98dfd8e4a359a7faf48' // Maestrano pusher account key. } } diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js index 5cefed0f..f05059fe 100644 --- a/workspace/app/services/dev-user.svc.js +++ b/workspace/app/services/dev-user.svc.js @@ -1,15 +1,20 @@ -// Impac! Angular DevUser Service - providing core authentication logic for Impac! developers. -// -------------------------------------------------------- +// ------------------------------------------------------- +// Impac! Angular DevUser Service +// -------- +// Providing Auth & User data for the Impac! Workspace. +// ------------------------------------------------------- angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, Auth, toastr) { var _self = this; // Angular Devise methods exposed via this service + // ------ this.login = Auth.login; this.logout = Auth.logout; this.isAuthenticated = Auth.isAuthenticated; this.currentUser = Auth.currentUser; - // Get logged in user & organizations from mno-hub + // MnoExpress User & Organization retrieval + // ------ this.getUserData = function(mnoeUrl) { var url = mnoeUrl.host + mnoeUrl.base + '/current_user'; return $http.get(url).then( @@ -38,7 +43,6 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A return deferred.promise; }; - // Get organizations with the currentOrgId from workspace settings this.getOrganizations = function(orgUid, mnoeUrl) { return _self.getUserData(mnoeUrl).then( function (user) { @@ -63,7 +67,8 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A ); }; - // Logging and Toastr notifications method + // Logging and Toastr notifications + // ------ this.fail = function (msg, error) { if (error == null) { error = ''; } $log.error('Develop Workspace Error: ' + msg, error); From b1e3554d98699aa873c71a05db4916600c6a49d9 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Thu, 20 Oct 2016 17:59:58 +0100 Subject: [PATCH 11/16] Add ability to signup on #/login --- workspace/app/services/dev-user.svc.js | 1 + .../views/workspace/login/login.controller.js | 23 ++++++++++++++++--- workspace/app/views/workspace/login/login.css | 7 ++++++ .../app/views/workspace/login/login.html | 14 ++++++++++- .../views/workspace/workspace.controller.js | 4 ++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js index f05059fe..f279ec94 100644 --- a/workspace/app/services/dev-user.svc.js +++ b/workspace/app/services/dev-user.svc.js @@ -10,6 +10,7 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A // ------ this.login = Auth.login; this.logout = Auth.logout; + this.register = Auth.register; this.isAuthenticated = Auth.isAuthenticated; this.currentUser = Auth.currentUser; diff --git a/workspace/app/views/workspace/login/login.controller.js b/workspace/app/views/workspace/login/login.controller.js index 054f2a3c..00e04612 100644 --- a/workspace/app/views/workspace/login/login.controller.js +++ b/workspace/app/views/workspace/login/login.controller.js @@ -10,14 +10,31 @@ angular.module('impacWorkspace').controller('LoginController', function ($state, }); } - vm.creds = { email: '', password: '' }; + vm.showRegisterForm = false; + vm.creds = { email: '', password: '', company: '' }; + + vm.toggleRegisterForm = function () { + vm.showRegisterForm = !vm.showRegisterForm; + }; vm.login = function () { - DevUser.login(vm.creds).then( + DevUser.login(_.omit(vm.creds, ['company'])).then( function () { $state.go('workspace.impac'); }, function (response) { - var msg = (response.data && response.data.error) || 'Unable to login'; + var msg = (response.data && response.data.error) || 'Unable to login :('; + DevUser.fail(msg, response); + } + ); + }; + + vm.register = function () { + DevUser.register(vm.creds).then( + function (res) { + console.log(res); + $state.go('workspace.impac'); + }, function (err) { + var msg = (response.data && response.data.error) || 'Unable to sign up :('; DevUser.fail(msg, response); } ); diff --git a/workspace/app/views/workspace/login/login.css b/workspace/app/views/workspace/login/login.css index 09588a74..0faa660d 100644 --- a/workspace/app/views/workspace/login/login.css +++ b/workspace/app/views/workspace/login/login.css @@ -14,6 +14,13 @@ border-radius: 3px; } +#workspace .workspace-login .login-box-actions a { + color: rgb(117, 129, 146); +} +#workspace .workspace-login .login-box-actions a:hover { + color: black; +} + #workspace .workspace-login .login-box-title { color: rgb(117, 129, 146); margin-bottom: 15px; diff --git a/workspace/app/views/workspace/login/login.html b/workspace/app/views/workspace/login/login.html index a64a983a..53932dbb 100644 --- a/workspace/app/views/workspace/login/login.html +++ b/workspace/app/views/workspace/login/login.html @@ -11,7 +11,19 @@

Sign In

- +
+ +
+
diff --git a/workspace/app/views/workspace/workspace.controller.js b/workspace/app/views/workspace/workspace.controller.js index b28440bd..7c19cd5f 100644 --- a/workspace/app/views/workspace/workspace.controller.js +++ b/workspace/app/views/workspace/workspace.controller.js @@ -9,6 +9,10 @@ angular.module('impacWorkspace').controller('WorkspaceController', function ($sc setCurrentOrganization(); }); + $scope.$on('devise:new-registration', function() { + setCurrentOrganization(); + }); + $scope.$on('updated-providers', function () { setCurrentOrganization(); }); From 45c411e88938ef94885ae3c498e75ce9da073cb6 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Tue, 1 Nov 2016 15:41:31 +0000 Subject: [PATCH 12/16] Improve getUserData error when user not logged_in --- workspace/app/services/dev-user.svc.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/workspace/app/services/dev-user.svc.js b/workspace/app/services/dev-user.svc.js index f279ec94..148da8de 100644 --- a/workspace/app/services/dev-user.svc.js +++ b/workspace/app/services/dev-user.svc.js @@ -17,18 +17,19 @@ angular.module('impacWorkspace').service('DevUser', function ($log, $http, $q, A // MnoExpress User & Organization retrieval // ------ this.getUserData = function(mnoeUrl) { + var errMsg = 'Unable to retrieve User data'; var url = mnoeUrl.host + mnoeUrl.base + '/current_user'; return $http.get(url).then( function (response) { var user = (response.data && response.data.current_user); if (!user.logged_in) { - return $q.reject(); + _self.fail(errMsg); + return $q.reject(errMsg); } return user || {}; }, function (error) { - var msg = 'Unable to retrieve Organizations'; - _self.fail(msg, error); - return $q.reject(msg); + _self.fail(errMsg, error); + return $q.reject(errMsg); } ); }; From 37fd1a3a3f5f70b8e2a9badcb448f7d79c86025b Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Tue, 1 Nov 2016 15:42:34 +0000 Subject: [PATCH 13/16] Remove proxy, config angular devise for cors as default --- gulp/server.js | 9 --------- workspace/app/app.js | 9 +++++---- workspace/app/services/dev-settings.svc.js | 2 +- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/gulp/server.js b/gulp/server.js index 460c575d..e4f018f2 100644 --- a/gulp/server.js +++ b/gulp/server.js @@ -28,15 +28,6 @@ function browserSyncInit(baseDir, browser) { routes: routes }; - /* - * You can add a proxy to your backend by uncommenting the line below. - * You just have to configure a context which will we redirected and the target url. - * Example: $http.get('/users') requests will be automatically proxified. - * - * For more details and option, https://github.com/chimurai/http-proxy-middleware/blob/v0.9.0/README.md - */ - server.middleware = proxyMiddleware(['/auth', '/mnoe'], { target: 'http://localhost:7000' }); - $.browserSync.instance = $.browserSync.init({ port: 7001, startPath: '/', diff --git a/workspace/app/app.js b/workspace/app/app.js index f8576b8b..4f6ac37e 100644 --- a/workspace/app/app.js +++ b/workspace/app/app.js @@ -48,18 +48,19 @@ module.config(function ($stateProvider, $urlRouterProvider) { // -- // Configure Angular Devise paths for mno-enterprise. // ------------------------------------------------------- -module.config(function (AuthProvider) { +module.config(function (AuthProvider, DevSettingsProvider) { + var mnoeHostUrl = DevSettingsProvider.$get().defaults().mnoeUrl.host; // Customize login AuthProvider.loginMethod('POST'); - AuthProvider.loginPath('mnoe/auth/users/sign_in.json'); + AuthProvider.loginPath(mnoeHostUrl + '/mnoe/auth/users/sign_in.json'); // Customize logout AuthProvider.logoutMethod('DELETE'); - AuthProvider.logoutPath('mnoe/auth/users/sign_out.json'); + AuthProvider.logoutPath(mnoeHostUrl + '/mnoe/auth/users/sign_out.json'); // Customize register AuthProvider.registerMethod('POST'); - AuthProvider.registerPath('mnoe/auth/users'); + AuthProvider.registerPath(mnoeHostUrl + '/mnoe/auth/users'); }); // -- diff --git a/workspace/app/services/dev-settings.svc.js b/workspace/app/services/dev-settings.svc.js index d7ecac3f..1b01f537 100644 --- a/workspace/app/services/dev-settings.svc.js +++ b/workspace/app/services/dev-settings.svc.js @@ -9,7 +9,7 @@ angular.module('impacWorkspace').service('DevSettings', function ($q, ImpacRoute var DEFAULTS = { // API Endpoints mnoeUrl: { - host: '', + host: 'http://localhost:7000', base: '/mnoe/jpi/v1' }, impacUrl: { From 92e3daad8694ff5fec02f05e1169a0d47b75fcfc Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Wed, 16 Nov 2016 18:50:48 +0000 Subject: [PATCH 14/16] Provide CSRF support for Dev Toolkit --- bower.json | 6 ++-- workspace/app/app.js | 21 ++++++++++++-- workspace/app/services/dev-session.svc.js | 29 +++++++++++++++++++ .../views/workspace/workspace.controller.js | 10 ++++++- workspace/index.html | 2 ++ 5 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 workspace/app/services/dev-session.svc.js diff --git a/bower.json b/bower.json index a32d3526..9cbca1f5 100755 --- a/bower.json +++ b/bower.json @@ -40,7 +40,8 @@ "angular-mocks": "~1.4.0", "angular-scenario": "~1.4.0", "AngularDevise": "angular-devise#^1.3.0", - "angular-ui-router": "^0.3.1" + "angular-ui-router": "^0.3.1", + "angular-cookies": "^1.5.8" }, "license": "Copyright 2015 Maestrano Pty Ltd", "repository": { @@ -48,6 +49,7 @@ "url": "git://github.com/maestrano/impac-angular.git" }, "resolutions": { - "angular": "~1.4.0" + "angular": "1.4.14", + "angular-cookies": "^1.5.8" } } diff --git a/workspace/app/app.js b/workspace/app/app.js index 4f6ac37e..dde52ce2 100644 --- a/workspace/app/app.js +++ b/workspace/app/app.js @@ -7,7 +7,8 @@ var module = angular.module('impacWorkspace', [ 'maestrano.impac', 'toastr', 'Devise', - 'ui.router' + 'ui.router', + 'ngCookies' ]); // -- @@ -64,7 +65,23 @@ module.config(function (AuthProvider, DevSettingsProvider) { }); // -- -// Impac! Angular Provider Service Configurations +// Configure Angular $http to apply XSRF Token headers to CORS requests. +// ------------------------------------------------------- +module.constant('CSRF', { + "headerTokenKey": 'X-XSRF-TOKEN', + "cookieTokenKey": 'XSRF-TOKEN' +}); +module.config(function($httpProvider) { + // Allow "credentialed" requests that are aware of HTTP cookies and HTTP + // Authentication information. + $httpProvider.defaults.withCredentials = true; +}); +module.run(function($http, DevSession) { + DevSession.create(); +}); + +// -- +// Impac! Angular Provider Service Configurations. // ------------------------------------------------------- module.run(function (ImpacLinking, ImpacAssets, ImpacRoutes, ImpacTheming, ImpacDeveloper, DevUser, DevSettings) { diff --git a/workspace/app/services/dev-session.svc.js b/workspace/app/services/dev-session.svc.js new file mode 100644 index 00000000..fd12c40f --- /dev/null +++ b/workspace/app/services/dev-session.svc.js @@ -0,0 +1,29 @@ +// ------------------------------------------------------- +// Impac! Angular DevSession Service +// -------- +// Providing CSRF Support for Impac! Workspace. +// ------------------------------------------------------- +angular.module('impacWorkspace').service('DevSession', function ($log, $http, $cookies, CSRF, DevSettings) { + var _self = this; + + // Create a session and xsrf token - ping mnoe api so we get a valid XSRF cookie. + this.create = function () { + return $http.get(DevSettings.defaults().mnoeUrl.host + '/mnoe/auth/users/sign_in.json') + .success(function() { + _self.setCsrfHttpHeader(); + }); + }; + + // Angular Devise methods (e.g `Auth.currentUser()`) generate new sessions, this keeps the + // default http headers up to date, ensuring the session is maintained. + this.update = function () { + this.setCsrfHttpHeader(); + }; + + // Set stored XSRF cookie as $http headers common. + this.setCsrfHttpHeader = function () { + $http.defaults.headers.common[CSRF.headerTokenKey] = $cookies.get(CSRF.cookieTokenKey); + }; + + return this; +}); diff --git a/workspace/app/views/workspace/workspace.controller.js b/workspace/app/views/workspace/workspace.controller.js index 7c19cd5f..9552a033 100644 --- a/workspace/app/views/workspace/workspace.controller.js +++ b/workspace/app/views/workspace/workspace.controller.js @@ -1,4 +1,4 @@ -angular.module('impacWorkspace').controller('WorkspaceController', function ($scope, $state, DevUser, DevSettings) { +angular.module('impacWorkspace').controller('WorkspaceController', function ($scope, $state, DevUser, DevSettings, DevSession) { main = this; main.isAuthenticated = DevUser.isAuthenticated; @@ -13,6 +13,14 @@ angular.module('impacWorkspace').controller('WorkspaceController', function ($sc setCurrentOrganization(); }); + $scope.$on('devise:new-session', function () { + DevSession.update(); + }); + + $scope.$on('devise:logout', function () { + DevSession.update(); + }); + $scope.$on('updated-providers', function () { setCurrentOrganization(); }); diff --git a/workspace/index.html b/workspace/index.html index ca811bf3..da7092fd 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -44,10 +44,12 @@ + + From bc1583c519004c1e9614f55b102e32762e061ee3 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Fri, 25 Nov 2016 13:18:27 +0000 Subject: [PATCH 15/16] Point default impac to api-impac-uat. --- workspace/app/services/dev-settings.svc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/app/services/dev-settings.svc.js b/workspace/app/services/dev-settings.svc.js index 1b01f537..a775bc86 100644 --- a/workspace/app/services/dev-settings.svc.js +++ b/workspace/app/services/dev-settings.svc.js @@ -13,7 +13,7 @@ angular.module('impacWorkspace').service('DevSettings', function ($q, ImpacRoute base: '/mnoe/jpi/v1' }, impacUrl: { - host: 'http://localhost:4000', + host: 'https://api-impac-uat.maestrano.io', base: '/api' }, // Selected Organization - first organisations if unspecified From c1c6be5cf6d5378f518191c1ffd2f754d69691c3 Mon Sep 17 00:00:00 2001 From: Xaun Lopez Date: Fri, 25 Nov 2016 13:19:16 +0000 Subject: [PATCH 16/16] Update DEVELOPER.md with temporary workspace instructions --- DEVELOPER.md | 75 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/DEVELOPER.md b/DEVELOPER.md index 5fc2d358..d009e422 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -16,33 +16,70 @@ Now you should an api key, api secret, and an organization associated to your Us ##### Steps to get impac loaded: -1. Terminal commands to load dependancies +Temporary instructions to get Impac! Angular running for development: + +1. Create an account on http://impac-mnoe-uat.maestrano.io. +2. Fork impac-express (https://github.com/maestrano/impac-express) and clone it to your local machine +3. In the impac-express project, modify config/settings/development.yml as follow: + + ```ruby + impac: + protocol: https + host: api-impac-uat.maestrano.io + mno: + protocol: https + host: api-hub-uat.maestrano.io ``` - npm install - bower install +4. In the impac-express project, create config/application.yml as follow: + + ```ruby + # Tenant Credentials + tenant_id: c6b44271-7334-0134-8df7-35f23abf243c + tenant_key: 4Vcpt_2GnCfhlyBYbN_bUQ + + # Emailing platform + SPARKPOST_API_KEY: changeme + + # Rails secret key + SECRET_KEY_BASE: e48e21d80b2943c1872f69fb3cf4f8a8c24bc9fa3abdc14549df2dc181d46bfb5698271fb4bc1511e45ba0633ef02b494985b67f6e418182014f95a5e600f808 + + # Google Tag Manager + google_tag_container: GTM-TH3MLB ``` - -2. Configuring with credentials & launching workspace - - Add your api_key & api_secret to the settings factory in the `workspace/index.js` file +5. Build and start the impac-express project: + + ```bash + bundle install + foreman start + ``` +6. Fork impac-angular (https://github.com/maestrano/impac-angular) and clone it to your local machine. _Note this method for running impac-angular is only valid from versions >= 1.4.5_. +7. In the impac-angular project, modify workspace/app/services/dev-settings.svc.js as follow: ```javascript - module.factory('settings', function () { - return { - // Credentials and endpoints - mno_url: 'https://uat.maestrano.io', - impac_url: 'https://api-impac-uat.maestrano.io', - api_key: 'YOUR_KEY', - api_secret: 'YOUR_SECRET', + var DEFAULTS = { + // API Endpoints + mnoeUrl: { + host: 'http://localhost:7000', + base: '/mnoe/jpi/v1' + }, + impacUrl: { + host: 'https://api-impac-uat.maestrano.io', + base: '/api' + } ... - } - }); ``` +8. build and start the impac-angular project -3. There a few ways to prepare & launch the Impac Developer Workspace.. - 1. Run `gulp` or `gulp serve`, this will inject dependencies, serve impac-angular, and **live reload** on change. - 2. Run `gulp serve:noreload`, if rebuilding the library on every change is using too much cpu - **you will need to run `gulp workspace` and refresh the page after every change** - 2. Run `gulp workspace` to build and inject dependencies, the open the `workspace/index.html` file in a browser - **you will need to run `gulp workspace` and refresh the page after every change** + ```bash + npm install + bower install + gulp + ``` +9. A new tab with the Developer Workspace will open in your browser, log-in with the email/password you've created at step 1. +10. You should be able to start coding in the project impac-angular: just saving any .coffee or .html file will automatically reload your Developer Workspace, applying your code. +11. To populate the Widgets and KPIs with data, integrate an App! I recommend Xero. +Note: Coming in a patch version soon you will be able to skip steps 2. to 5. ##### Workspace Architecture