http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/Demo/Demo.module.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/Demo/Demo.module.js b/modules/web-console/frontend/app/modules/Demo/Demo.module.js deleted file mode 100644 index a3700ca..0000000 --- a/modules/web-console/frontend/app/modules/Demo/Demo.module.js +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import angular from 'angular'; - -import DEMO_INFO from 'app/data/demo-info.json'; - -angular -.module('ignite-console.demo', [ - 'ignite-console.socket' -]) -.config(['$stateProvider', ($stateProvider) => { - $stateProvider - .state('demo', { - abstract: true, - template: '<ui-view></ui-view>' - }) - .state('demo.resume', { - url: '/demo', - controller: ['$state', ($state) => { - $state.go('base.configuration.clusters'); - }], - metaTags: { - } - }) - .state('demo.reset', { - url: '/demo/reset', - controller: ['$state', '$http', 'IgniteMessages', ($state, $http, Messages) => { - $http.post('/api/v1/demo/reset') - .then(() => $state.go('base.configuration.clusters')) - .catch((res) => { - $state.go('base.configuration.clusters'); - - Messages.showError(res); - }); - }], - metaTags: {} - }); -}]) -.provider('Demo', ['$stateProvider', '$httpProvider', 'igniteSocketFactoryProvider', function($state, $http, socketFactory) { - if (/(\/demo.*)/ig.test(location.pathname)) - sessionStorage.setItem('IgniteDemoMode', 'true'); - - const enabled = sessionStorage.getItem('IgniteDemoMode') === 'true'; - - if (enabled) { - socketFactory.set({query: 'IgniteDemoMode=true'}); - - $http.interceptors.push('demoInterceptor'); - } - - this.$get = ['$rootScope', ($root) => { - $root.IgniteDemoMode = enabled; - - return {enabled}; - }]; -}]) -.factory('demoInterceptor', ['Demo', (Demo) => { - const isApiRequest = (url) => /\/api\/v1/ig.test(url); - - return { - request(cfg) { - if (Demo.enabled && isApiRequest(cfg.url)) - cfg.headers.IgniteDemoMode = true; - - return cfg; - } - }; -}]) -.controller('demoController', ['$scope', '$state', '$window', 'IgniteConfirm', ($scope, $state, $window, Confirm) => { - const _openTab = (stateName) => $window.open($state.href(stateName), '_blank'); - - $scope.startDemo = () => { - if (!$scope.user.demoCreated) - return _openTab('demo.reset'); - - Confirm.confirm('Would you like to continue with previous demo session?', true, false) - .then((resume) => { - if (resume) - return _openTab('demo.resume'); - - _openTab('demo.reset'); - }); - }; - - $scope.closeDemo = () => { - $window.close(); - }; -}]) -.provider('igniteDemoInfo', [function() { - const items = DEMO_INFO; - - this.update = (data) => items[0] = data; - - this.$get = [() => { - return items; - }]; -}]) -.service('DemoInfo', ['$rootScope', '$modal', '$state', '$q', 'igniteDemoInfo', 'IgniteAgentMonitor', ($rootScope, $modal, $state, $q, igniteDemoInfo, agentMonitor) => { - const scope = $rootScope.$new(); - - let closePromise = null; - - function _fillPage() { - const model = igniteDemoInfo; - - scope.title = model[0].title; - scope.message = model[0].message.join(' '); - } - - const dialog = $modal({ - templateUrl: '/templates/demo-info.html', - scope, - placement: 'center', - show: false, - backdrop: 'static' - }); - - scope.close = () => { - dialog.hide(); - - closePromise && closePromise.resolve(); - }; - - scope.downloadAgent = () => { - const lnk = document.createElement('a'); - - lnk.setAttribute('href', '/api/v1/agent/download/zip'); - lnk.setAttribute('target', '_self'); - lnk.setAttribute('download', null); - lnk.style.display = 'none'; - - document.body.appendChild(lnk); - - lnk.click(); - - document.body.removeChild(lnk); - }; - - return { - show: () => { - closePromise = $q.defer(); - - _fillPage(); - - return dialog.$promise - .then(dialog.show) - .then(() => Promise.race([agentMonitor.awaitAgent(), closePromise.promise])) - .then(() => scope.hasAgents = true); - } - }; -}]);
http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/demo/Demo.module.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/demo/Demo.module.js b/modules/web-console/frontend/app/modules/demo/Demo.module.js new file mode 100644 index 0000000..bd759df --- /dev/null +++ b/modules/web-console/frontend/app/modules/demo/Demo.module.js @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import angular from 'angular'; + +import DEMO_INFO from 'app/data/demo-info.json'; + +angular +.module('ignite-console.demo', [ + 'ignite-console.socket' +]) +.config(['$stateProvider', 'AclRouteProvider', ($stateProvider, AclRoute) => { + $stateProvider + .state('demo', { + abstract: true, + url: '/demo', + template: '<ui-view></ui-view>' + }) + .state('demo.resume', { + url: '/resume', + onEnter: AclRoute.checkAccess('demo'), + controller: ['$state', ($state) => { + $state.go('base.configuration.clusters'); + }], + metaTags: { + title: 'Demo resume' + } + }) + .state('demo.reset', { + url: '/reset', + onEnter: AclRoute.checkAccess('demo'), + controller: ['$state', '$http', 'IgniteMessages', ($state, $http, Messages) => { + $http.post('/api/v1/demo/reset') + .then(() => $state.go('base.configuration.clusters')) + .catch((res) => { + $state.go('base.configuration.clusters'); + + Messages.showError(res); + }); + }], + metaTags: { + title: 'Demo reset' + } + }); +}]) +.provider('Demo', ['$stateProvider', '$httpProvider', 'igniteSocketFactoryProvider', function($state, $http, socketFactory) { + if (/(\/demo.*)/ig.test(location.pathname)) + sessionStorage.setItem('IgniteDemoMode', 'true'); + + const enabled = sessionStorage.getItem('IgniteDemoMode') === 'true'; + + if (enabled) { + socketFactory.set({query: 'IgniteDemoMode=true'}); + + $http.interceptors.push('demoInterceptor'); + } + + this.$get = ['$rootScope', ($root) => { + $root.IgniteDemoMode = enabled; + + return {enabled}; + }]; +}]) +.factory('demoInterceptor', ['Demo', (Demo) => { + const isApiRequest = (url) => /\/api\/v1/ig.test(url); + + return { + request(cfg) { + if (Demo.enabled && isApiRequest(cfg.url)) + cfg.headers.IgniteDemoMode = true; + + return cfg; + } + }; +}]) +.controller('demoController', ['$scope', '$state', '$window', 'IgniteConfirm', ($scope, $state, $window, Confirm) => { + const _openTab = (stateName) => $window.open($state.href(stateName), '_blank'); + + $scope.startDemo = () => { + if (!$scope.user.demoCreated) + return _openTab('demo.reset'); + + Confirm.confirm('Would you like to continue with previous demo session?', true, false) + .then((resume) => { + if (resume) + return _openTab('demo.resume'); + + _openTab('demo.reset'); + }); + }; + + $scope.closeDemo = () => { + $window.close(); + }; +}]) +.provider('igniteDemoInfo', [function() { + const items = DEMO_INFO; + + this.update = (data) => items[0] = data; + + this.$get = [() => { + return items; + }]; +}]) +.service('DemoInfo', ['$rootScope', '$modal', '$state', '$q', 'igniteDemoInfo', 'IgniteAgentMonitor', ($rootScope, $modal, $state, $q, igniteDemoInfo, agentMonitor) => { + const scope = $rootScope.$new(); + + let closePromise = null; + + function _fillPage() { + const model = igniteDemoInfo; + + scope.title = model[0].title; + scope.message = model[0].message.join(' '); + } + + const dialog = $modal({ + templateUrl: '/templates/demo-info.html', + scope, + placement: 'center', + show: false, + backdrop: 'static' + }); + + scope.close = () => { + dialog.hide(); + + closePromise && closePromise.resolve(); + }; + + scope.downloadAgent = () => { + const lnk = document.createElement('a'); + + lnk.setAttribute('href', '/api/v1/agent/download/zip'); + lnk.setAttribute('target', '_self'); + lnk.setAttribute('download', null); + lnk.style.display = 'none'; + + document.body.appendChild(lnk); + + lnk.click(); + + document.body.removeChild(lnk); + }; + + return { + show: () => { + closePromise = $q.defer(); + + _fillPage(); + + return dialog.$promise + .then(dialog.show) + .then(() => Promise.race([agentMonitor.awaitAgent(), closePromise.promise])) + .then(() => scope.hasAgents = true); + } + }; +}]); http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/sql/sql.controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js index 0d0b171..4e972ef 100644 --- a/modules/web-console/frontend/app/modules/sql/sql.controller.js +++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js @@ -186,8 +186,8 @@ class Paragraph { } // Controller for SQL notebook screen. -export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$filter', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'IgniteNotebook', 'IgniteNodes', 'uiGridExporterConstants', 'IgniteVersion', - function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $filter, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, Notebook, Nodes, uiGridExporterConstants, Version) { +export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$filter', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'IgniteNotebook', 'IgniteNodes', 'uiGridExporterConstants', 'IgniteVersion', 'IgniteActivitiesData', + function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $filter, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, Notebook, Nodes, uiGridExporterConstants, Version, ActivitiesData) { let stopTopology = null; const _tryStopRefresh = function(paragraph) { @@ -965,6 +965,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', $scope.addQuery = function() { const sz = $scope.notebook.paragraphs.length; + ActivitiesData.post({ action: '/queries/add/query' }); + const paragraph = new Paragraph($animate, $timeout, { name: 'Query' + (sz === 0 ? '' : sz), query: '', @@ -991,6 +993,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', $scope.addScan = function() { const sz = $scope.notebook.paragraphs.length; + ActivitiesData.post({ action: '/queries/add/scan' }); + const paragraph = new Paragraph($animate, $timeout, { name: 'Scan' + (sz === 0 ? '' : sz), query: '', @@ -1379,6 +1383,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', const qry = args.maxPages ? addLimit(args.query, args.pageSize * args.maxPages) : paragraph.query; + ActivitiesData.post({ action: '/queries/execute' }); + return agentMonitor.query(nid, args.cacheName, qry, nonCollocatedJoins, local, args.pageSize); }) .then((res) => { @@ -1430,6 +1436,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', pageSize: paragraph.pageSize }; + ActivitiesData.post({ action: '/queries/explain' }); + return agentMonitor.query(nid, args.cacheName, args.query, false, false, args.pageSize); }) .then(_processQueryResult.bind(this, paragraph, true)) @@ -1466,6 +1474,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', localNid: local ? nid : null }; + ActivitiesData.post({ action: '/queries/scan' }); + return agentMonitor.query(nid, args.cacheName, query, false, local, args.pageSize); }) .then((res) => _processQueryResult(paragraph, true, res)) http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/sql/sql.module.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/sql/sql.module.js b/modules/web-console/frontend/app/modules/sql/sql.module.js index a1ffde9..5875961 100644 --- a/modules/web-console/frontend/app/modules/sql/sql.module.js +++ b/modules/web-console/frontend/app/modules/sql/sql.module.js @@ -30,7 +30,7 @@ angular.module('ignite-console.sql', [ // set up the states $stateProvider .state('base.sql', { - url: '/sql', + url: '/queries', abstract: true, template: '<ui-view></ui-view>' }) http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/states/admin.state.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/states/admin.state.js b/modules/web-console/frontend/app/modules/states/admin.state.js index c3151e1..35c6fbb 100644 --- a/modules/web-console/frontend/app/modules/states/admin.state.js +++ b/modules/web-console/frontend/app/modules/states/admin.state.js @@ -29,7 +29,7 @@ angular templateUrl: '/settings/admin.html', onEnter: AclRoute.checkAccess('admin_page'), metaTags: { - title: 'List of registered users' + title: 'Admin panel' } }); }]); http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js index cfc6df9..16d2fae 100644 --- a/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js +++ b/modules/web-console/frontend/app/modules/states/configuration/summary/summary.controller.js @@ -21,8 +21,8 @@ import saver from 'file-saver'; const escapeFileName = (name) => name.replace(/[\\\/*\"\[\],\.:;|=<>?]/g, '-').replace(/ /g, '_'); export default [ - '$rootScope', '$scope', '$http', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteLoading', '$filter', 'IgniteConfigurationResource', 'JavaTypes', 'IgniteVersion', 'IgniteConfigurationGenerator', 'SpringTransformer', 'JavaTransformer', 'IgniteDockerGenerator', 'IgniteMavenGenerator', 'IgnitePropertiesGenerator', 'IgniteReadmeGenerator', 'IgniteFormUtils', 'IgniteSummaryZipper', - function($root, $scope, $http, LegacyUtils, Messages, Loading, $filter, Resource, JavaTypes, Version, generator, spring, java, docker, pom, propsGenerator, readme, FormUtils, SummaryZipper) { + '$rootScope', '$scope', '$http', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteLoading', '$filter', 'IgniteConfigurationResource', 'JavaTypes', 'IgniteVersion', 'IgniteConfigurationGenerator', 'SpringTransformer', 'JavaTransformer', 'IgniteDockerGenerator', 'IgniteMavenGenerator', 'IgnitePropertiesGenerator', 'IgniteReadmeGenerator', 'IgniteFormUtils', 'IgniteSummaryZipper', 'IgniteActivitiesData', + function($root, $scope, $http, LegacyUtils, Messages, Loading, $filter, Resource, JavaTypes, Version, generator, spring, java, docker, pom, propsGenerator, readme, FormUtils, SummaryZipper, ActivitiesData) { const ctrl = this; $scope.ui = { @@ -304,6 +304,8 @@ export default [ $scope.isPrepareDownloading = true; + ActivitiesData.post({ action: '/configuration/download' }); + return new SummaryZipper({ cluster, data: ctrl.data || {}, IgniteDemoMode: $root.IgniteDemoMode }) .then((data) => { saver.saveAs(data, escapeFileName(cluster.name) + '-project.zip'); http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/user/AclRoute.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/user/AclRoute.provider.js b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js index 40abea5..4225bc4 100644 --- a/modules/web-console/frontend/app/modules/user/AclRoute.provider.js +++ b/modules/web-console/frontend/app/modules/user/AclRoute.provider.js @@ -17,31 +17,36 @@ export default [() => { class AclRoute { - static checkAccess = (permissions, failState) => { + static checkAccess(permissions, failState) { failState = failState || '403'; - return ['$state', 'AclService', 'User', ($state, AclService, User) => { - User.read() - .then(() => { - if (AclService.can(permissions)) - return; + return ['$q', '$state', 'AclService', 'User', 'IgniteActivitiesData', function($q, $state, AclService, User, Activities) { + const action = this.name ? $state.href(this.name) : null; - return $state.go(failState); - }) + return User.read() .catch(() => { User.clean(); if ($state.current.name !== 'signin') $state.go('signin'); + + return $q.reject('Failed to detect user'); + }) + .then(() => { + if (AclService.can(permissions)) + return Activities.post({ action }); + + $state.go(failState); + + return $q.reject('User are not authorized'); }); }]; } - } - return { - checkAccess: AclRoute.checkAccess, - $get: () => { + static $get() { return AclRoute; } - }; + } + + return AclRoute; }]; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/user/Auth.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/user/Auth.service.js b/modules/web-console/frontend/app/modules/user/Auth.service.js index e0f905d..95ff4c3 100644 --- a/modules/web-console/frontend/app/modules/user/Auth.service.js +++ b/modules/web-console/frontend/app/modules/user/Auth.service.js @@ -21,7 +21,7 @@ export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteErro forgotPassword(userInfo) { $http.post('/api/v1/password/forgot', userInfo) .then(() => $state.go('password.send')) - .cacth(({data}) => ErrorPopover.show('forgot_email', Messages.errorMessage(null, data))); + .catch(({data}) => ErrorPopover.show('forgot_email', Messages.errorMessage(null, data))); }, auth(action, userInfo) { $http.post('/api/v1/' + action, userInfo) http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/user/permissions.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/user/permissions.js b/modules/web-console/frontend/app/modules/user/permissions.js index e13509c..b6f7c3a 100644 --- a/modules/web-console/frontend/app/modules/user/permissions.js +++ b/modules/web-console/frontend/app/modules/user/permissions.js @@ -16,7 +16,7 @@ */ const guest = ['login']; -const becomed = ['profile', 'configuration', 'query']; +const becomed = ['profile', 'configuration', 'query', 'demo']; const user = becomed.concat(['logout']); const admin = user.concat(['admin_page']); http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/modules/user/user.module.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/user/user.module.js b/modules/web-console/frontend/app/modules/user/user.module.js index 11798d0..b86a62e 100644 --- a/modules/web-console/frontend/app/modules/user/user.module.js +++ b/modules/web-console/frontend/app/modules/user/user.module.js @@ -22,10 +22,10 @@ import Auth from './Auth.service'; import User from './User.service'; import AclRouteProvider from './AclRoute.provider'; -angular -.module('ignite-console.user', [ +angular.module('ignite-console.user', [ 'mm.acl', - 'ignite-console.config' + 'ignite-console.config', + 'ignite-console.core' ]) .factory('sessionRecoverer', ['$injector', '$q', ($injector, $q) => { return { http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/vendor.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/vendor.js b/modules/web-console/frontend/app/vendor.js index a9e8844..3bbb322 100644 --- a/modules/web-console/frontend/app/vendor.js +++ b/modules/web-console/frontend/app/vendor.js @@ -25,6 +25,7 @@ import 'angular-strap/dist/angular-strap.tpl'; import 'angular-socket-io'; import 'angular-retina'; import 'angular-ui-router'; +import 'angular-translate'; import 'ui-router-metatags/dist/ui-router-metatags'; import 'angular-smart-table'; import 'angular-ui-grid/ui-grid'; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/controllers/admin-controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/controllers/admin-controller.js b/modules/web-console/frontend/controllers/admin-controller.js deleted file mode 100644 index cf7fd71..0000000 --- a/modules/web-console/frontend/controllers/admin-controller.js +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const ICON_SORT = '<span ui-grid-one-bind-id-grid="col.uid + \'-sortdir-text\'" ui-grid-visible="col.sort.direction" aria-label="Sort Descending"><i ng-class="{ \'ui-grid-icon-up-dir\': col.sort.direction == asc, \'ui-grid-icon-down-dir\': col.sort.direction == desc, \'ui-grid-icon-blank\': !col.sort.direction }" title="" aria-hidden="true"></i></span>'; - -const CLUSTER_HEADER_TEMPLATE = `<div class='ui-grid-cell-contents' bs-tooltip data-title='{{ col.headerTooltip(col) }}' data-placement='top'><i class='fa fa-sitemap'></i>${ICON_SORT}</div>`; -const MODEL_HEADER_TEMPLATE = `<div class='ui-grid-cell-contents' bs-tooltip data-title='{{ col.headerTooltip(col) }}' data-placement='top'><i class='fa fa-object-group'></i>${ICON_SORT}</div>`; -const CACHE_HEADER_TEMPLATE = `<div class='ui-grid-cell-contents' bs-tooltip data-title='{{ col.headerTooltip(col) }}' data-placement='top'><i class='fa fa-database'></i>${ICON_SORT}</div>`; -const IGFS_HEADER_TEMPLATE = `<div class='ui-grid-cell-contents' bs-tooltip data-title='{{ col.headerTooltip(col) }}' data-placement='top'><i class='fa fa-folder-o'></i>${ICON_SORT}</div>`; - -const ACTIONS_TEMPLATE = ` -<div class='text-center ui-grid-cell-actions'> - <a class='btn btn-default dropdown-toggle' bs-dropdown='' ng-show='row.entity._id != $root.user._id' data-placement='bottom-right' data-container='.panel'> - <i class='fa fa-gear'></i> - <span class='caret'></span> - </a> - <ul class='dropdown-menu' role='menu'> - <li> - <a ng-click='grid.api.becomeUser(row.entity)'>Become this user</a> - </li> - <li> - <a ng-click='grid.api.toggleAdmin(row.entity)' ng-if='row.entity.admin && row.entity._id !== $root.user._id'>Revoke admin</a> - <a ng-click='grid.api.toggleAdmin(row.entity)' ng-if='!row.entity.admin && row.entity._id !== $root.user._id'>Grant admin</a> - </li> - <li> - <a ng-click='grid.api.removeUser(row.entity)'>Remove user</a> - </li> -</div>`; - -const EMAIL_TEMPLATE = '<div class="ui-grid-cell-contents"><a ng-href="mailto:{{ COL_FIELD }}">{{ COL_FIELD }}</a></div>'; - -// Controller for Admin screen. -export default ['adminController', [ - '$rootScope', '$scope', '$http', '$q', '$state', '$filter', 'uiGridConstants', 'IgniteMessages', 'IgniteConfirm', 'User', 'IgniteNotebookData', 'IgniteCountries', - ($rootScope, $scope, $http, $q, $state, $filter, uiGridConstants, Messages, Confirm, User, Notebook, Countries) => { - $scope.users = null; - - const companySelectOptions = []; - const countrySelectOptions = []; - - const COLUMNS_DEFS = [ - {displayName: 'Actions', cellTemplate: ACTIONS_TEMPLATE, field: 'test', minWidth: 80, width: 80, enableFiltering: false, enableSorting: false}, - {displayName: 'User', field: 'userName', minWidth: 65, enableFiltering: true, filter: { placeholder: 'Filter by name...' }}, - {displayName: 'Email', field: 'email', cellTemplate: EMAIL_TEMPLATE, minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by email...' }}, - {displayName: 'Company', field: 'company', minWidth: 160, filter: { - selectOptions: companySelectOptions, type: uiGridConstants.filter.SELECT, condition: uiGridConstants.filter.EXACT } - }, - {displayName: 'Country', field: 'countryCode', minWidth: 80, filter: { - selectOptions: countrySelectOptions, type: uiGridConstants.filter.SELECT, condition: uiGridConstants.filter.EXACT } - }, - {displayName: 'Last login', field: 'lastLogin', cellFilter: 'date:"medium"', minWidth: 175, width: 175, enableFiltering: false, sort: { direction: 'desc', priority: 0 }}, - {displayName: 'Clusters count', headerCellTemplate: CLUSTER_HEADER_TEMPLATE, field: '_clusters', type: 'number', headerTooltip: 'Clusters count', minWidth: 50, width: 50, enableFiltering: false}, - {displayName: 'Models count', headerCellTemplate: MODEL_HEADER_TEMPLATE, field: '_models', type: 'number', headerTooltip: 'Models count', minWidth: 50, width: 50, enableFiltering: false}, - {displayName: 'Caches count', headerCellTemplate: CACHE_HEADER_TEMPLATE, field: '_caches', type: 'number', headerTooltip: 'Caches count', minWidth: 50, width: 50, enableFiltering: false}, - {displayName: 'IGFS count', headerCellTemplate: IGFS_HEADER_TEMPLATE, field: '_igfs', type: 'number', headerTooltip: 'IGFS count', minWidth: 50, width: 50, enableFiltering: false} - ]; - - const ctrl = $scope.ctrl = {}; - - const becomeUser = function(user) { - $http.get('/api/v1/admin/become', { params: {viewedUserId: user._id}}) - .then(() => User.load()) - .then(() => $state.go('base.configuration.clusters')) - .then(() => Notebook.load()) - .catch(Messages.showError); - }; - - const removeUser = (user) => { - Confirm.confirm(`Are you sure you want to remove user: "${user.userName}"?`) - .then(() => { - $http.post('/api/v1/admin/remove', {userId: user._id}) - .then(() => { - const i = _.findIndex($scope.users, (u) => u._id === user._id); - - if (i >= 0) - $scope.users.splice(i, 1); - - Messages.showInfo(`User has been removed: "${user.userName}"`); - }) - .catch(({data, status}) => { - if (status === 503) - Messages.showInfo(data); - else - Messages.showError('Failed to remove user: ', data); - }); - }); - }; - - const toggleAdmin = (user) => { - if (user.adminChanging) - return; - - user.adminChanging = true; - - $http.post('/api/v1/admin/save', {userId: user._id, adminFlag: !user.admin}) - .then(() => { - user.admin = !user.admin; - - Messages.showInfo(`Admin right was successfully toggled for user: "${user.userName}"`); - }) - .catch((res) => { - Messages.showError('Failed to toggle admin right for user: ', res); - }) - .finally(() => user.adminChanging = false); - }; - - - ctrl.gridOptions = { - data: [], - columnVirtualizationThreshold: 30, - columnDefs: COLUMNS_DEFS, - categories: [ - {name: 'Actions', visible: true, selectable: true}, - {name: 'User', visible: true, selectable: true}, - {name: 'Email', visible: true, selectable: true}, - {name: 'Company', visible: true, selectable: true}, - {name: 'Country', visible: true, selectable: true}, - {name: 'Last login', visible: true, selectable: true}, - - {name: 'Clusters count', visible: true, selectable: true}, - {name: 'Models count', visible: true, selectable: true}, - {name: 'Caches count', visible: true, selectable: true}, - {name: 'IGFS count', visible: true, selectable: true} - ], - enableFiltering: true, - enableRowSelection: false, - enableRowHeaderSelection: false, - enableColumnMenus: false, - multiSelect: false, - modifierKeysToMultiSelect: true, - noUnselect: true, - flatEntityAccess: true, - fastWatch: true, - onRegisterApi: (api) => { - ctrl.gridApi = api; - - api.becomeUser = becomeUser; - api.removeUser = removeUser; - api.toggleAdmin = toggleAdmin; - } - }; - - /** - * Set grid height. - * - * @param {Number} rows Rows count. - * @private - */ - const adjustHeight = (rows) => { - const height = Math.min(rows, 20) * 30 + 75; - - // Remove header height. - ctrl.gridApi.grid.element.css('height', height + 'px'); - - ctrl.gridApi.core.handleWindowResize(); - }; - - const usersToFilterOptions = (column) => { - return _.sortBy( - _.map( - _.groupBy($scope.users, (usr) => { - const fld = usr[column]; - - return _.isNil(fld) ? fld : fld.toUpperCase(); - }), - (arr, value) => ({label: `${_.head(arr)[column] || 'Not set'} (${arr.length})`, value}) - ), - 'value'); - }; - - const _reloadUsers = () => { - $http.post('/api/v1/admin/list') - .then(({ data }) => { - $scope.users = data; - - companySelectOptions.length = 0; - countrySelectOptions.length = 0; - - _.forEach($scope.users, (user) => { - user.userName = user.firstName + ' ' + user.lastName; - user.countryCode = Countries.getByName(user.country).code; - - user._clusters = user.counters.clusters; - user._models = user.counters.models; - user._caches = user.counters.caches; - user._igfs = user.counters.igfs; - }); - - companySelectOptions.push(...usersToFilterOptions('company')); - countrySelectOptions.push(...usersToFilterOptions('countryCode')); - - $scope.ctrl.gridOptions.data = data; - - adjustHeight(data.length); - }) - .catch(Messages.showError); - }; - - _reloadUsers(); - - const _enableColumns = (categories, visible) => { - _.forEach(categories, (cat) => { - cat.visible = visible; - - _.forEach(ctrl.gridOptions.columnDefs, (col) => { - if (col.displayName === cat.name) - col.visible = visible; - }); - }); - - ctrl.gridApi.grid.refresh(); - }; - - const _selectableColumns = () => _.filter(ctrl.gridOptions.categories, (cat) => cat.selectable); - - ctrl.toggleColumns = (category, visible) => _enableColumns([category], visible); - ctrl.selectAllColumns = () => _enableColumns(_selectableColumns(), true); - ctrl.clearAllColumns = () => _enableColumns(_selectableColumns(), false); - } -]]; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/controllers/domains-controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/controllers/domains-controller.js b/modules/web-console/frontend/controllers/domains-controller.js index 303110e..bfffe92 100644 --- a/modules/web-console/frontend/controllers/domains-controller.js +++ b/modules/web-console/frontend/controllers/domains-controller.js @@ -17,8 +17,8 @@ // Controller for Domain model screen. export default ['domainsController', [ - '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteAgentMonitor', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'JavaTypes', 'SqlTypes', - function($root, $scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Focus, Confirm, ConfirmBatch, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, IgniteAgentMonitor, LegacyTable, Resource, ErrorPopover, FormUtils, JavaTypes, SqlTypes) { + '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteAgentMonitor', 'IgniteLegacyTable', 'IgniteConfigurationResource', 'IgniteErrorPopover', 'IgniteFormUtils', 'JavaTypes', 'SqlTypes', 'IgniteActivitiesData', + function($root, $scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Focus, Confirm, ConfirmBatch, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, IgniteAgentMonitor, LegacyTable, Resource, ErrorPopover, FormUtils, JavaTypes, SqlTypes, ActivitiesData) { UnsavedChangesGuard.install($scope); const emptyDomain = {empty: true}; @@ -460,6 +460,14 @@ export default ['domainsController', [ $scope.importDomain.loadingOptions = LOADING_JDBC_DRIVERS; IgniteAgentMonitor.startWatch({text: 'Back to Domain models', goal: 'import domain model from database'}) + .then(() => { + ActivitiesData.post({ + group: 'configuration', + action: 'configuration/import/model' + }); + + return true; + }) .then(importDomainModal.$promise) .then(importDomainModal.show) .then(() => { http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/package.json ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/package.json b/modules/web-console/frontend/package.json index fd50d5b..ff52ba4 100644 --- a/modules/web-console/frontend/package.json +++ b/modules/web-console/frontend/package.json @@ -44,6 +44,7 @@ "angular-socket-io": "~0.7.0", "angular-strap": "~2.3.8", "angular-touch": "~1.5.9", + "angular-translate": "~2.13.1", "angular-tree-control": "~0.2.26", "angular-ui-grid": "~3.2.9", "angular-ui-router": "~0.3.1", http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/public/stylesheets/_font-awesome-custom.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/public/stylesheets/_font-awesome-custom.scss b/modules/web-console/frontend/public/stylesheets/_font-awesome-custom.scss index bfa6c6c..47555a7 100644 --- a/modules/web-console/frontend/public/stylesheets/_font-awesome-custom.scss +++ b/modules/web-console/frontend/public/stylesheets/_font-awesome-custom.scss @@ -69,3 +69,31 @@ $fa-font-path: '~font-awesome/fonts'; cursor: default; } + +.icon-user { + @extend .fa; + @extend .fa-user-o; + + cursor: default; +} + +.icon-admin { + @extend .fa; + @extend .fa-user-secret; + + cursor: default; +} + +.icon-datepicker-left { + @extend .fa; + @extend .fa-chevron-left; + + margin: 0; +} + +.icon-datepicker-right { + @extend .fa; + @extend .fa-chevron-right; + + margin: 0; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/public/stylesheets/style.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss index 4318fc2..67cfed1 100644 --- a/modules/web-console/frontend/public/stylesheets/style.scss +++ b/modules/web-console/frontend/public/stylesheets/style.scss @@ -2302,12 +2302,13 @@ html,body,.splash-screen { cursor: default; i { + margin-top: 2px; margin-right: 10px; } label { cursor: default; - line-height: 24px; + line-height: 28px; } sub { @@ -2326,4 +2327,40 @@ html,body,.splash-screen { .ui-grid-filter-select { width: calc(100% - 10px); } + + .ui-grid-cell-contents > i { + line-height: $line-height-base; + } + + .ui-grid-row:nth-child(odd):hover .ui-grid-cell { + background: $ignite-row-hover; + } + + .ui-grid-row:nth-child(even):hover .ui-grid-cell { + background: $ignite-row-hover; + } } + +.datepicker.dropdown-menu { + width: 250px; + height: 270px; + + button { + outline: none; + border: 0; + } + + tbody { + height: 180px; + } + + tbody button { + padding: 6px; + } + + &.datepicker-mode-1, &.datepicker-mode-2 { + tbody button { + height: 65px; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/public/stylesheets/variables.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/public/stylesheets/variables.scss b/modules/web-console/frontend/public/stylesheets/variables.scss index 8500eac..e30bbdd 100644 --- a/modules/web-console/frontend/public/stylesheets/variables.scss +++ b/modules/web-console/frontend/public/stylesheets/variables.scss @@ -26,3 +26,4 @@ $ignite-border-bottom-color: $brand-primary; $ignite-background-color: #fff; $ignite-header-color: #555; $ignite-invalid-color: $brand-primary; +$ignite-row-hover: #c9dde1; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/views/settings/admin.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/views/settings/admin.jade b/modules/web-console/frontend/views/settings/admin.jade index c985826..a09fda9 100644 --- a/modules/web-console/frontend/views/settings/admin.jade +++ b/modules/web-console/frontend/views/settings/admin.jade @@ -14,38 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. -mixin grid-settings() - i.fa.fa-bars(data-animation='am-flip-x' bs-dropdown='' aria-haspopup='true' aria-expanded='expanded' data-auto-close='1' data-trigger='click') - ul.select.dropdown-menu(role='menu') - li(ng-repeat='item in ctrl.gridOptions.categories|filter:{selectable:true}') - a(ng-click='ctrl.toggleColumns(item, !item.visible)') - i.fa.fa-check-square-o.pull-left(ng-if='item.visible') - i.fa.fa-square-o.pull-left(ng-if='!item.visible') - span {{::item.name}} - li.divider - li - a(ng-click='ctrl.selectAllColumns()') Select all - li - a(ng-click='ctrl.clearAllColumns()') Clear all - li.divider - li - a(ng-click='$hide()') Close - -.admin-page.row(ng-controller='adminController') +.admin-page.row .docs-content.greedy .docs-header - h1 List of registered users + h1 Admin panel hr .docs-body .row .col-xs-12 - .panel.panel-default - .panel-heading.ui-grid-settings - +grid-settings - label Total users: - strong {{ users.length }} - label Showing users: - strong {{ ctrl.gridApi.grid.getVisibleRows().length }} - sub(ng-show='users.length === ctrl.gridApi.grid.getVisibleRows().length') all - .panel-collapse - .grid(ui-grid='ctrl.gridOptions' ui-grid-resize-columns ui-grid-selection ui-grid-pinning) + ignite-list-of-registered-users(data-options='ctrl.data') http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/views/sql/sql.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/views/sql/sql.jade b/modules/web-console/frontend/views/sql/sql.jade index 03015e8..61d5b30 100644 --- a/modules/web-console/frontend/views/sql/sql.jade +++ b/modules/web-console/frontend/views/sql/sql.jade @@ -15,7 +15,7 @@ limitations under the License. include /app/helpers/jade/mixins.jade -include /app/directives/ui-grid-settings/ui-grid-settings.jade +include /app/components/ui-grid-settings/ui-grid-settings.jade mixin btn-toolbar(btn, click, tip, focusId) i.btn.btn-default.fa(class=btn ng-click=click bs-tooltip='' data-title=tip ignite-on-click-focus=focusId data-trigger='hover' data-placement='bottom') @@ -195,7 +195,7 @@ mixin paragraph-scan +table-result-body .footer.clearfix() .pull-left - | Showing results for scan of #[b{{ paragraph.queryArgs.cacheName | defaultName }}] + | Showing results for scan of #[b {{ paragraph.queryArgs.cacheName | defaultName }}] span(ng-if='paragraph.queryArgs.filter') with filter: #[b {{ paragraph.queryArgs.filter }}] span(ng-if='paragraph.queryArgs.localNid') on node: #[b {{ paragraph.queryArgs.localNid | limitTo:8 }}]