Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 5161A200C41 for ; Thu, 16 Feb 2017 18:36:08 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 4FFB1160B52; Thu, 16 Feb 2017 17:36:08 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id B22CB160B6F for ; Thu, 16 Feb 2017 18:36:04 +0100 (CET) Received: (qmail 10541 invoked by uid 500); 16 Feb 2017 17:36:03 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 10018 invoked by uid 99); 16 Feb 2017 17:36:03 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 16 Feb 2017 17:36:03 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id F1FF9E109B; Thu, 16 Feb 2017 17:36:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: yzhdanov@apache.org To: commits@ignite.apache.org Date: Thu, 16 Feb 2017 17:36:13 -0000 Message-Id: <6161f0f84e60423e8497581593abe65e@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [12/50] [abbrv] ignite git commit: IGNITE-4472 Added user activities in Web Console. archived-at: Thu, 16 Feb 2017 17:36:08 -0000 IGNITE-4472 Added user activities in Web Console. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/26ee9c28 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/26ee9c28 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/26ee9c28 Branch: refs/heads/ignite-comm-balance-master Commit: 26ee9c2865648118da97ee8ef84df990359edb96 Parents: e6ea938 Author: Andrey Novikov Authored: Wed Feb 8 11:43:22 2017 +0700 Committer: Andrey Novikov Committed: Wed Feb 8 11:43:22 2017 +0700 ---------------------------------------------------------------------- modules/web-console/backend/app/agent.js | 10 +- modules/web-console/backend/app/mongo.js | 49 ++-- modules/web-console/backend/app/routes.js | 5 +- .../web-console/backend/routes/activities.js | 52 +++++ modules/web-console/backend/routes/admin.js | 2 +- modules/web-console/backend/routes/agent.js | 10 +- modules/web-console/backend/routes/public.js | 1 - .../web-console/backend/services/activities.js | 136 +++++++++++ modules/web-console/backend/services/users.js | 13 +- modules/web-console/frontend/app/app.config.js | 9 + modules/web-console/frontend/app/app.js | 29 ++- .../activities-user-dialog.controller.js | 60 +++++ .../activities-user-dialog.jade | 36 +++ .../components/activities-user-dialog/index.js | 36 +++ .../form-field-datepicker.jade | 55 +++++ .../form-field-datepicker.scss | 20 ++ .../list-of-registered-users/index.js | 28 +++ .../list-of-registered-users.categories.js | 30 +++ .../list-of-registered-users.column-defs.js | 80 +++++++ .../list-of-registered-users.controller.js | 207 ++++++++++++++++ .../list-of-registered-users.jade | 54 +++++ .../ui-grid-header/ui-grid-header.jade | 27 +++ .../ui-grid-header/ui-grid-header.scss | 84 +++++++ .../ui-grid-settings/ui-grid-settings.jade | 33 +++ .../ui-grid-settings/ui-grid-settings.scss | 70 ++++++ .../app/core/activities/Activities.data.js | 39 ++++ .../frontend/app/core/admin/Admin.data.js | 77 ++++++ modules/web-console/frontend/app/core/index.js | 25 ++ modules/web-console/frontend/app/data/i18n.js | 38 +++ .../ui-grid-settings/ui-grid-settings.jade | 33 --- .../ui-grid-settings/ui-grid-settings.scss | 38 --- .../app/filters/uiGridSubcategories.filter.js | 24 ++ .../frontend/app/modules/Demo/Demo.module.js | 166 ------------- .../frontend/app/modules/demo/Demo.module.js | 172 ++++++++++++++ .../frontend/app/modules/sql/sql.controller.js | 14 +- .../frontend/app/modules/sql/sql.module.js | 2 +- .../frontend/app/modules/states/admin.state.js | 2 +- .../configuration/summary/summary.controller.js | 6 +- .../app/modules/user/AclRoute.provider.js | 31 +-- .../frontend/app/modules/user/Auth.service.js | 2 +- .../frontend/app/modules/user/permissions.js | 2 +- .../frontend/app/modules/user/user.module.js | 6 +- modules/web-console/frontend/app/vendor.js | 1 + .../frontend/controllers/admin-controller.js | 234 ------------------- .../frontend/controllers/domains-controller.js | 12 +- modules/web-console/frontend/package.json | 1 + .../stylesheets/_font-awesome-custom.scss | 28 +++ .../frontend/public/stylesheets/style.scss | 39 +++- .../frontend/public/stylesheets/variables.scss | 1 + .../frontend/views/settings/admin.jade | 32 +-- modules/web-console/frontend/views/sql/sql.jade | 4 +- 51 files changed, 1603 insertions(+), 562 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/app/agent.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/agent.js b/modules/web-console/backend/app/agent.js index 961253f..8170280 100644 --- a/modules/web-console/backend/app/agent.js +++ b/modules/web-console/backend/app/agent.js @@ -24,7 +24,7 @@ */ module.exports = { implements: 'agent-manager', - inject: ['require(lodash)', 'require(fs)', 'require(path)', 'require(jszip)', 'require(socket.io)', 'settings', 'mongo'] + inject: ['require(lodash)', 'require(fs)', 'require(path)', 'require(jszip)', 'require(socket.io)', 'settings', 'mongo', 'services/activities'] }; /** @@ -35,9 +35,10 @@ module.exports = { * @param socketio * @param settings * @param mongo + * @param {ActivitiesService} activitiesService * @returns {AgentManager} */ -module.exports.factory = function(_, fs, path, JSZip, socketio, settings, mongo) { +module.exports.factory = function(_, fs, path, JSZip, socketio, settings, mongo, activitiesService) { /** * */ @@ -823,6 +824,11 @@ module.exports.factory = function(_, fs, path, JSZip, socketio, settings, mongo) const sockets = this._browsers[accountId]; _.forEach(sockets, (socket) => socket.emit('agent:count', {count: agents.length})); + + activitiesService.merge(accountId, { + group: 'agent', + action: '/agent/start' + }); }); } http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/app/mongo.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/mongo.js b/modules/web-console/backend/app/mongo.js index dd71f3a..2d252b9 100644 --- a/modules/web-console/backend/app/mongo.js +++ b/modules/web-console/backend/app/mongo.js @@ -48,6 +48,7 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose company: String, country: String, lastLogin: Date, + lastActivity: Date, admin: Boolean, token: String, resetPasswordToken: String @@ -59,22 +60,26 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose usernameLowerCase: true }); + const transform = (doc, ret) => { + return { + _id: ret._id, + email: ret.email, + firstName: ret.firstName, + lastName: ret.lastName, + company: ret.company, + country: ret.country, + admin: ret.admin, + token: ret.token, + lastLogin: ret.lastLogin, + lastActivity: ret.lastActivity + }; + }; + // Configure transformation to JSON. - AccountSchema.set('toJSON', { - transform: (doc, ret) => { - return { - _id: ret._id, - email: ret.email, - firstName: ret.firstName, - lastName: ret.lastName, - company: ret.company, - country: ret.country, - admin: ret.admin, - token: ret.token, - lastLogin: ret.lastLogin - }; - } - }); + AccountSchema.set('toJSON', { transform }); + + // Configure transformation to JSON. + AccountSchema.set('toObject', { transform }); result.errCodes = { DUPLICATE_KEY_ERROR: 11000, @@ -902,6 +907,20 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose res.status(err.code || 500).send(err.message); }; + // Define Activities schema. + const ActivitiesSchema = new Schema({ + owner: {type: ObjectId, ref: 'Account'}, + date: Date, + group: String, + action: String, + amount: { type: Number, default: 1 } + }); + + ActivitiesSchema.index({ owner: 1, group: 1, action: 1, date: 1}, { unique: true }); + + // Define Activities model. + result.Activities = mongoose.model('Activities', ActivitiesSchema); + // Registering the routes of all plugin modules for (const name in pluginMongo) { if (pluginMongo.hasOwnProperty(name)) http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/app/routes.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/app/routes.js b/modules/web-console/backend/app/routes.js index 6961173..6b5d052 100644 --- a/modules/web-console/backend/app/routes.js +++ b/modules/web-console/backend/app/routes.js @@ -22,11 +22,11 @@ module.exports = { implements: 'routes', inject: ['routes/public', 'routes/admin', 'routes/profiles', 'routes/demo', 'routes/clusters', 'routes/domains', - 'routes/caches', 'routes/igfss', 'routes/notebooks', 'routes/agents', 'routes/configurations'] + 'routes/caches', 'routes/igfss', 'routes/notebooks', 'routes/agents', 'routes/configurations', 'routes/activities'] }; module.exports.factory = function(publicRoute, adminRoute, profilesRoute, demoRoute, - clustersRoute, domainsRoute, cachesRoute, igfssRoute, notebooksRoute, agentsRoute, configurationsRoute) { + clustersRoute, domainsRoute, cachesRoute, igfssRoute, notebooksRoute, agentsRoute, configurationsRoute, activitiesRoute) { return { register: (app) => { const _mustAuthenticated = (req, res, next) => { @@ -59,6 +59,7 @@ module.exports.factory = function(publicRoute, adminRoute, profilesRoute, demoRo app.use('/notebooks', _mustAuthenticated, notebooksRoute); app.use('/agent', _mustAuthenticated, agentsRoute); + app.use('/activities', _mustAuthenticated, activitiesRoute); } }; }; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/routes/activities.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/routes/activities.js b/modules/web-console/backend/routes/activities.js new file mode 100644 index 0000000..08c27cf --- /dev/null +++ b/modules/web-console/backend/routes/activities.js @@ -0,0 +1,52 @@ +/* + * 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. + */ + +'use strict'; + +// Fire me up! + +module.exports = { + implements: 'routes/activities', + inject: ['require(express)', 'services/activities'] +}; + +/** + * @param express + * @param {ActivitiesService} activitiesService + * @returns {Promise} + */ +module.exports.factory = function(express, activitiesService) { + return new Promise((factoryResolve) => { + const router = new express.Router(); + + // Get user activities. + router.get('/user/:userId', (req, res) => { + activitiesService.listByUser(req.params.userId, req.query) + .then(res.api.ok) + .catch(res.api.error); + }); + + // Post user activities to page. + router.post('/page', (req, res) => { + activitiesService.merge(req.user._id, req.body) + .then(res.api.ok) + .catch(res.api.error); + }); + + factoryResolve(router); + }); +}; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/routes/admin.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/routes/admin.js b/modules/web-console/backend/routes/admin.js index 70736d0..5b0896a 100644 --- a/modules/web-console/backend/routes/admin.js +++ b/modules/web-console/backend/routes/admin.js @@ -43,7 +43,7 @@ module.exports.factory = function(_, express, settings, mongo, spacesService, ma * Get list of user accounts. */ router.post('/list', (req, res) => { - usersService.list() + usersService.list(req.body) .then(res.api.ok) .catch(res.api.error); }); http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/routes/agent.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/routes/agent.js b/modules/web-console/backend/routes/agent.js index 477363f..5ae807b 100644 --- a/modules/web-console/backend/routes/agent.js +++ b/modules/web-console/backend/routes/agent.js @@ -21,21 +21,27 @@ module.exports = { implements: 'routes/agents', - inject: ['require(lodash)', 'require(express)', 'services/agents'] + inject: ['require(lodash)', 'require(express)', 'services/agents', 'services/activities'] }; /** * @param _ * @param express * @param {AgentsService} agentsService + * @param {ActivitiesService} activitiesService * @returns {Promise} */ -module.exports.factory = function(_, express, agentsService) { +module.exports.factory = function(_, express, agentsService, activitiesService) { return new Promise((resolveFactory) => { const router = new express.Router(); /* Get grid topology. */ router.get('/download/zip', (req, res) => { + activitiesService.merge(req.user._id, { + group: 'agent', + action: '/agent/download' + }); + agentsService.getArchive(req.origin(), req.user.token) .then(({fileName, buffer}) => { // Set the archive name. http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/routes/public.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/routes/public.js b/modules/web-console/backend/routes/public.js index 590d395..860e267 100644 --- a/modules/web-console/backend/routes/public.js +++ b/modules/web-console/backend/routes/public.js @@ -25,7 +25,6 @@ module.exports = { }; /** - * * @param express * @param passport * @param mongo http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/services/activities.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/services/activities.js b/modules/web-console/backend/services/activities.js new file mode 100644 index 0000000..7f3a777 --- /dev/null +++ b/modules/web-console/backend/services/activities.js @@ -0,0 +1,136 @@ +/* + * 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. + */ + +'use strict'; + +// Fire me up! + +module.exports = { + implements: 'services/activities', + inject: ['require(lodash)', 'mongo'] +}; + +/** + * @param _ + * @param mongo + * @returns {ActivitiesService} + */ +module.exports.factory = (_, mongo) => { + class ActivitiesService { + /** + * Update page activities. + * + * @param {String} owner - User ID + * @param {Object} page - The page + * @returns {Promise.} that resolve activity + */ + static merge(owner, {action, group}) { + mongo.Account.findById(owner) + .then((user) => { + user.lastActivity = new Date(); + + return user.save(); + }); + + const date = new Date(); + + date.setDate(1); + date.setHours(0, 0, 0, 0); + + return mongo.Activities.findOne({owner, action, date}).exec() + .then((activity) => { + if (activity) { + activity.amount++; + + return activity.save(); + } + + return mongo.Activities.create({owner, action, group, date}); + }); + } + + /** + * Get user activities + * @param {String} owner - User ID + * @returns {Promise.} that resolve activities + */ + static listByUser(owner, {startDate, endDate}) { + const $match = {owner}; + + if (startDate) + $match.date = {$gte: new Date(startDate)}; + + if (endDate) { + $match.date = $match.date || {}; + $match.date.$lt = new Date(endDate); + } + + return mongo.Activities.find($match); + } + + static total({startDate, endDate}) { + const $match = {}; + + if (startDate) + $match.date = {$gte: new Date(startDate)}; + + if (endDate) { + $match.date = $match.date || {}; + $match.date.$lt = new Date(endDate); + } + + return mongo.Activities.aggregate([ + {$match}, + {$group: { + _id: {owner: '$owner', group: '$group'}, + amount: {$sum: '$amount'} + }} + ]).exec().then((data) => { + return _.reduce(data, (acc, { _id, amount }) => { + const {owner, group} = _id; + acc[owner] = _.merge(acc[owner] || {}, { [group]: amount }); + return acc; + }, {}); + }); + } + + static detail({startDate, endDate}) { + const $match = { }; + + if (startDate) + $match.date = {$gte: new Date(startDate)}; + + if (endDate) { + $match.date = $match.date || {}; + $match.date.$lt = new Date(endDate); + } + + return mongo.Activities.aggregate([ + {$match}, + {$group: {_id: {owner: '$owner', action: '$action'}, total: {$sum: '$amount'}}} + ]).exec().then((data) => { + return _.reduce(data, (acc, { _id, total }) => { + const {owner, action} = _id; + acc[owner] = _.merge(acc[owner] || {}, { [action]: total }); + return acc; + }, {}); + }); + } + } + + return ActivitiesService; +}; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/backend/services/users.js ---------------------------------------------------------------------- diff --git a/modules/web-console/backend/services/users.js b/modules/web-console/backend/services/users.js index 8058b25..2dd603f 100644 --- a/modules/web-console/backend/services/users.js +++ b/modules/web-console/backend/services/users.js @@ -21,7 +21,7 @@ module.exports = { implements: 'services/users', - inject: ['require(lodash)', 'mongo', 'settings', 'services/spaces', 'services/mails', 'agent-manager', 'errors'] + inject: ['require(lodash)', 'mongo', 'settings', 'services/spaces', 'services/mails', 'services/activities', 'agent-manager', 'errors'] }; /** @@ -30,11 +30,12 @@ module.exports = { * @param settings * @param {SpacesService} spacesService * @param {MailsService} mailsService + * @param {ActivitiesService} activitiesService * @param agentMgr * @param errors * @returns {UsersService} */ -module.exports.factory = (_, mongo, settings, spacesService, mailsService, agentMgr, errors) => { +module.exports.factory = (_, mongo, settings, spacesService, mailsService, activitiesService, agentMgr, errors) => { const _randomString = () => { const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const possibleLen = possible.length; @@ -143,7 +144,7 @@ module.exports.factory = (_, mongo, settings, spacesService, mailsService, agent * Get list of user accounts and summary information. * @returns {mongo.Account[]} - returns all accounts with counters object */ - static list() { + static list(params) { return Promise.all([ mongo.Space.aggregate([ {$match: {demo: false}}, @@ -161,13 +162,17 @@ module.exports.factory = (_, mongo, settings, spacesService, mailsService, agent } } ]).exec(), + activitiesService.total(params), + activitiesService.detail(params), mongo.Account.find({}).sort('firstName lastName').lean().exec() ]) - .then(([counters, users]) => { + .then(([counters, activitiesTotal, activitiesDetail, users]) => { const countersMap = _.keyBy(counters, 'owner'); _.forEach(users, (user) => { user.counters = _.omit(countersMap[user._id], '_id', 'owner'); + user.activitiesTotal = activitiesTotal[user._id]; + user.activitiesDetail = activitiesDetail[user._id]; }); return users; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/app.config.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/app.config.js b/modules/web-console/frontend/app/app.config.js index 7416ce9..0e85711 100644 --- a/modules/web-console/frontend/app/app.config.js +++ b/modules/web-console/frontend/app/app.config.js @@ -94,3 +94,12 @@ igniteConsoleCfg.config(['$dropdownProvider', ($dropdownProvider) => { templateUrl: 'templates/dropdown.html' }); }]); + +// AngularStrap dropdowns () configuration. +igniteConsoleCfg.config(['$datepickerProvider', ($datepickerProvider) => { + angular.extend($datepickerProvider.defaults, { + autoclose: true, + iconLeft: 'icon-datepicker-left', + iconRight: 'icon-datepicker-right' + }); +}]); http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/app.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/app.js b/modules/web-console/frontend/app/app.js index 4ecd9b5..9958cb5 100644 --- a/modules/web-console/frontend/app/app.js +++ b/modules/web-console/frontend/app/app.js @@ -16,7 +16,9 @@ */ import '../public/stylesheets/style.scss'; -import '../app/directives/ui-grid-settings/ui-grid-settings.scss'; +import '../app/components/ui-grid-header/ui-grid-header.scss'; +import '../app/components/ui-grid-settings/ui-grid-settings.scss'; +import '../app/components/form-field-datepicker/form-field-datepicker.scss'; import './helpers/jade/mixins.jade'; import './app.config'; @@ -25,10 +27,10 @@ import './decorator/select'; import './decorator/tooltip'; import './modules/form/form.module'; -import './modules/agent/agent.module.js'; +import './modules/agent/agent.module'; import './modules/sql/sql.module'; import './modules/nodes/nodes.module'; -import './modules/Demo/Demo.module.js'; +import './modules/demo/Demo.module'; import './modules/states/signin.state'; import './modules/states/logout.state'; @@ -39,6 +41,7 @@ import './modules/states/admin.state'; import './modules/states/errors.state'; // ignite:modules +import './core'; import './modules/user/user.module'; import './modules/branding/branding.module'; import './modules/navbar/navbar.module'; @@ -50,6 +53,9 @@ import './modules/socket.module'; import './modules/loading/loading.module'; // endignite +// Data +import i18n from './data/i18n'; + // Directives. import igniteAutoFocus from './directives/auto-focus.directive.js'; import igniteBsAffixUpdate from './directives/bs-affix-update.directive'; @@ -98,9 +104,9 @@ import defaultName from './filters/default-name.filter'; import domainsValidation from './filters/domainsValidation.filter'; import duration from './filters/duration.filter'; import hasPojo from './filters/hasPojo.filter'; +import uiGridSubcategories from './filters/uiGridSubcategories.filter'; // Controllers -import admin from 'controllers/admin-controller'; import caches from 'controllers/caches-controller'; import clusters from 'controllers/clusters-controller'; import domains from 'controllers/domains-controller'; @@ -109,6 +115,10 @@ import profile from 'controllers/profile-controller'; import auth from './controllers/auth.controller'; import resetPassword from './controllers/reset-password.controller'; +// Components +import igniteListOfRegisteredUsers from './components/list-of-registered-users'; +import IgniteActivitiesUserDialog from './components/activities-user-dialog'; + // Inject external modules. import 'ignite_modules_temp/index'; @@ -129,6 +139,7 @@ angular 'nvd3', 'smart-table', 'treeControl', + 'pascalprecht.translate', 'ui.grid', 'ui.grid.saveState', 'ui.grid.selection', @@ -136,6 +147,7 @@ angular 'ui.grid.autoResize', 'ui.grid.exporter', // Base modules. + 'ignite-console.core', 'ignite-console.ace', 'ignite-console.Form', 'ignite-console.user', @@ -186,6 +198,7 @@ angular .directive(...igniteRetainSelection) .directive('igniteOnFocusOut', igniteOnFocusOut) .directive('igniteRestoreInputFocus', igniteRestoreInputFocus) +.directive('igniteListOfRegisteredUsers', igniteListOfRegisteredUsers) // Services. .service('IgniteErrorPopover', ErrorPopover) .service('JavaTypes', JavaTypes) @@ -204,8 +217,8 @@ angular .service(...FormUtils) .service(...LegacyUtils) .service(...UnsavedChangesGuard) +.service('IgniteActivitiesUserDialog', IgniteActivitiesUserDialog) // Controllers. -.controller(...admin) .controller(...auth) .controller(...resetPassword) .controller(...caches) @@ -219,7 +232,11 @@ angular .filter(...domainsValidation) .filter(...duration) .filter(...hasPojo) -.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', ($stateProvider, $locationProvider, $urlRouterProvider) => { +.filter('uiGridSubcategories', uiGridSubcategories) +.config(['$translateProvider', '$stateProvider', '$locationProvider', '$urlRouterProvider', ($translateProvider, $stateProvider, $locationProvider, $urlRouterProvider) => { + $translateProvider.translations('en', i18n); + $translateProvider.preferredLanguage('en'); + // Set up the states. $stateProvider .state('base', { http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.controller.js b/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.controller.js new file mode 100644 index 0000000..46853b2 --- /dev/null +++ b/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.controller.js @@ -0,0 +1,60 @@ +/* + * 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 COLUMNS_DEFS = [ + {displayName: 'Action', field: 'action', minWidth: 65 }, + {displayName: 'Description', field: 'title', minWidth: 65 }, + {displayName: 'Visited', field: 'amount', minWidth: 65 } +]; + +export default class ActivitiesCtrl { + static $inject = ['$state', 'user', 'params', 'IgniteActivitiesData']; + + constructor($state, user, params, ActivitiesData) { + const $ctrl = this; + const userId = user._id; + + $ctrl.user = user; + + $ctrl.gridOptions = { + data: [], + columnVirtualizationThreshold: 30, + columnDefs: COLUMNS_DEFS, + categories: [ + {name: 'Action', visible: true, selectable: true}, + {name: 'Description', visible: true, selectable: true}, + {name: 'Visited', visible: true, selectable: true} + ], + enableRowSelection: false, + enableRowHeaderSelection: false, + enableColumnMenus: false, + multiSelect: false, + modifierKeysToMultiSelect: true, + noUnselect: true, + flatEntityAccess: true, + fastWatch: true, + onRegisterApi: (api) => { + $ctrl.gridApi = api; + } + }; + + ActivitiesData.listByUser(userId, params) + .then((data) => { + $ctrl.data = data; + }); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.jade b/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.jade new file mode 100644 index 0000000..2c55ebd --- /dev/null +++ b/modules/web-console/frontend/app/components/activities-user-dialog/activities-user-dialog.jade @@ -0,0 +1,36 @@ +//- + 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. + +.modal(tabindex='-1' role='dialog') + .modal-dialog + .modal-content + .modal-header + h4.modal-title + i.fa.fa-info-circle + | Activities: {{ ctrl.user.userName }} + .modal-body.modal-body-with-scroll(id='activities-user-dialog') + table.table.table-striped.table-bordered.table-hover(scrollable-container='#activities-user-dialog' st-table='displayedRows' st-safe-src='ctrl.data') + thead + th.text-center(st-sort='title') Description + th.text-center(st-sort='action') Action + th.text-center(st-sort='amount') Visited + tbody + tr(ng-repeat='row in displayedRows') + td.text-left {{ row.action | translate }} + td.text-left {{ row.action }} + td.text-left {{ row.amount }} + .modal-footer + button.btn.btn-primary(id='confirm-btn-confirm' ng-click='$hide()') Close http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/activities-user-dialog/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/activities-user-dialog/index.js b/modules/web-console/frontend/app/components/activities-user-dialog/index.js new file mode 100644 index 0000000..03d3585 --- /dev/null +++ b/modules/web-console/frontend/app/components/activities-user-dialog/index.js @@ -0,0 +1,36 @@ +/* + * 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 controller from './activities-user-dialog.controller'; + import templateUrl from './activities-user-dialog.jade'; + + export default ['$modal', ($modal) => ({ show = true, user, params }) => { + const ActivitiesUserDialog = $modal({ + templateUrl, + show, + resolve: { + user: () => user, + params: () => params + }, + placement: 'center', + controller, + controllerAs: 'ctrl' + }); + + return ActivitiesUserDialog.$promise + .then(() => ActivitiesUserDialog); + }]; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.jade b/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.jade new file mode 100644 index 0000000..6792977 --- /dev/null +++ b/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.jade @@ -0,0 +1,55 @@ +//- + 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. + +mixin ignite-form-field-datepicker(label, model, name, disabled, required, placeholder, tip) + mixin form-field-input() + input.form-control( + id='{{ #{name} }}Input' + name='{{ #{name} }}' + + placeholder=placeholder + + data-ng-model=model + + data-ng-required=required && '#{required}' + data-ng-disabled=disabled && '#{disabled}' + + bs-datepicker + data-date-format='MMM yyyy' + data-start-view='1' + data-min-view='1' + data-max-date='today' + + data-container='body > .wrapper' + + tabindex='0' + + onkeydown="return false" + + data-ignite-form-panel-field='' + )&attributes(attributes.attributes) + + .ignite-form-field + +ignite-form-field__label(label, name, required) + .ignite-form-field__control + if tip + i.tipField.icon-help(bs-tooltip='' data-title=tip) + + if block + block + + .input-tip + +form-field-input(attributes=attributes) http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.scss b/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.scss new file mode 100644 index 0000000..0f6fe6e --- /dev/null +++ b/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.scss @@ -0,0 +1,20 @@ +/* + * 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. + */ + +.datepicker.dropdown-menu tbody button { + height: 100%; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/list-of-registered-users/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/index.js b/modules/web-console/frontend/app/components/list-of-registered-users/index.js new file mode 100644 index 0000000..32a34f4 --- /dev/null +++ b/modules/web-console/frontend/app/components/list-of-registered-users/index.js @@ -0,0 +1,28 @@ +/* + * 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 templateUrl from './list-of-registered-users.jade'; +import controller from './list-of-registered-users.controller'; + +export default [() => { + return { + scope: true, + templateUrl, + controller, + controllerAs: '$ctrl' + }; +}]; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.categories.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.categories.js b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.categories.js new file mode 100644 index 0000000..95edf8b --- /dev/null +++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.categories.js @@ -0,0 +1,30 @@ +/* + * 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. + */ + +export default [ + {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: false, selectable: true}, + {name: 'Last activity', visible: true, selectable: true}, + {name: 'Configurations', visible: false, selectable: true}, + {name: 'Total activities', visible: true, selectable: true}, + {name: 'Configuration\'s activities', visible: false, selectable: true}, + {name: 'Queries\' activities', visible: false, selectable: true} +]; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js new file mode 100644 index 0000000..61e1bd8 --- /dev/null +++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.column-defs.js @@ -0,0 +1,80 @@ +/* + * 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 = ''; + +const USER_TEMPLATE = '
{{ COL_FIELD }}
'; + +const CLUSTER_HEADER_TEMPLATE = `
${ICON_SORT}
`; +const MODEL_HEADER_TEMPLATE = `
${ICON_SORT}
`; +const CACHE_HEADER_TEMPLATE = `
${ICON_SORT}
`; +const IGFS_HEADER_TEMPLATE = `
${ICON_SORT}
`; + +const ACTIONS_TEMPLATE = ` +`; + +const EMAIL_TEMPLATE = ''; + +export default [ + {displayName: 'Actions', categoryDisplayName: 'Actions', cellTemplate: ACTIONS_TEMPLATE, field: 'test', minWidth: 70, width: 70, enableFiltering: false, enableSorting: false, pinnedLeft: true}, + {displayName: 'User', categoryDisplayName: 'User', field: 'userName', cellTemplate: USER_TEMPLATE, minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by name...' }, pinnedLeft: true}, + {displayName: 'Email', categoryDisplayName: 'Email', field: 'email', cellTemplate: EMAIL_TEMPLATE, minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by email...' }}, + {displayName: 'Company', categoryDisplayName: 'Company', field: 'company', minWidth: 160, enableFiltering: true}, + {displayName: 'Country', categoryDisplayName: 'Country', field: 'countryCode', minWidth: 80, enableFiltering: true}, + {displayName: 'Last login', categoryDisplayName: 'Last login', field: 'lastLogin', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 105, width: 105, enableFiltering: false, visible: false}, + {displayName: 'Last activity', categoryDisplayName: 'Last activity', field: 'lastActivity', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 105, width: 105, enableFiltering: false, visible: true, sort: { direction: 'desc', priority: 0 }}, + // Configurations + {displayName: 'Clusters count', categoryDisplayName: 'Configurations', headerCellTemplate: CLUSTER_HEADER_TEMPLATE, field: 'counters.clusters', type: 'number', headerTooltip: 'Clusters count', minWidth: 50, width: 50, enableFiltering: false, visible: false}, + {displayName: 'Models count', categoryDisplayName: 'Configurations', headerCellTemplate: MODEL_HEADER_TEMPLATE, field: 'counters.models', type: 'number', headerTooltip: 'Models count', minWidth: 50, width: 50, enableFiltering: false, visible: false}, + {displayName: 'Caches count', categoryDisplayName: 'Configurations', headerCellTemplate: CACHE_HEADER_TEMPLATE, field: 'counters.caches', type: 'number', headerTooltip: 'Caches count', minWidth: 50, width: 50, enableFiltering: false, visible: false}, + {displayName: 'IGFS count', categoryDisplayName: 'Configurations', headerCellTemplate: IGFS_HEADER_TEMPLATE, field: 'counters.igfs', type: 'number', headerTooltip: 'IGFS count', minWidth: 50, width: 50, enableFiltering: false, visible: false}, + // Activities Total + {displayName: 'Cfg', categoryDisplayName: 'Total activities', field: 'activitiesTotal["configuration"] || 0', type: 'number', headerTooltip: 'Configuration', minWidth: 50, width: 50, enableFiltering: false}, + {displayName: 'Qry', categoryDisplayName: 'Total activities', field: 'activitiesTotal["queries"] || 0', type: 'number', headerTooltip: 'Queries', minWidth: 50, width: 50, enableFiltering: false}, + {displayName: 'Demo', categoryDisplayName: 'Total activities', field: 'activitiesTotal["demo"] || 0', type: 'number', headerTooltip: 'Demo', minWidth: 50, width: 50, enableFiltering: false}, + {displayName: 'AD', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/download"] || 0', type: 'number', headerTooltip: 'Agent Download', minWidth: 50, width: 50, enableFiltering: false}, + {displayName: 'AS', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/start"] || 0', type: 'number', headerTooltip: 'Agent Start', minWidth: 50, width: 50, enableFiltering: false}, + // Activities Configuration + {displayName: 'Clusters', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/clusters"] || 0', type: 'number', headerTooltip: 'Configuration Clusters', minWidth: 50, width: 80, enableFiltering: false, visible: false}, + {displayName: 'Model', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/domains"] || 0', type: 'number', headerTooltip: 'Configuration Model', minWidth: 50, width: 80, enableFiltering: false, visible: false}, + {displayName: 'Caches', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/caches"] || 0', type: 'number', headerTooltip: 'Configuration Caches', minWidth: 50, width: 80, enableFiltering: false, visible: false}, + {displayName: 'IGFS', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/igfs"] || 0', type: 'number', headerTooltip: 'Configuration IGFS', minWidth: 50, width: 80, enableFiltering: false, visible: false}, + {displayName: 'Summary', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/summary"] || 0', type: 'number', headerTooltip: 'Configuration Summary', minWidth: 50, width: 80, enableFiltering: false, visible: false}, + // Activities Queries + {displayName: 'Execute', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/execute"] || 0', type: 'number', headerTooltip: 'Query execute', minWidth: 50, width: 80, enableFiltering: false, visible: false}, + {displayName: 'Explain', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/explain"] || 0', type: 'number', headerTooltip: 'Query explain', minWidth: 50, width: 80, enableFiltering: false, visible: false}, + {displayName: 'Scan', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/scan"] || 0', type: 'number', headerTooltip: 'Scan', minWidth: 50, width: 80, enableFiltering: false, visible: false} +]; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js new file mode 100644 index 0000000..19f7921 --- /dev/null +++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.controller.js @@ -0,0 +1,207 @@ +/* + * 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 headerTemplate from 'app/components/ui-grid-header/ui-grid-header.jade'; + +import columnDefs from './list-of-registered-users.column-defs'; +import categories from './list-of-registered-users.categories'; + +export default class IgniteListOfRegisteredUsersCtrl { + static $inject = ['$scope', '$state', '$templateCache', 'User', 'uiGridConstants', 'IgniteAdminData', 'IgniteNotebookData', 'IgniteConfirm', 'IgniteActivitiesUserDialog']; + + constructor($scope, $state, $templateCache, User, uiGridConstants, AdminData, NotebookData, Confirm, ActivitiesUserDialog) { + const $ctrl = this; + + const companySelectOptions = []; + const countrySelectOptions = []; + + $ctrl.params = { + startDate: new Date() + }; + + $ctrl.params.startDate.setDate(1); + $ctrl.params.startDate.setHours(0, 0, 0, 0); + + const columnCompany = _.find(columnDefs, { displayName: 'Company' }); + const columnCountry = _.find(columnDefs, { displayName: 'Country' }); + + columnCompany.filter = { + selectOptions: companySelectOptions, + type: uiGridConstants.filter.SELECT, + condition: uiGridConstants.filter.EXACT + }; + + columnCountry.filter = { + selectOptions: countrySelectOptions, + type: uiGridConstants.filter.SELECT, + condition: uiGridConstants.filter.EXACT + }; + + const becomeUser = (user) => { + AdminData.becomeUser(user._id) + .then(() => User.load()) + .then(() => $state.go('base.configuration.clusters')) + .then(() => NotebookData.load()); + }; + + const removeUser = (user) => { + Confirm.confirm(`Are you sure you want to remove user: "${user.userName}"?`) + .then(() => AdminData.removeUser(user)) + .then(() => { + const i = _.findIndex($ctrl.gridOptions.data, (u) => u._id === user._id); + + if (i >= 0) + $ctrl.gridOptions.data.splice(i, 1); + }) + .then(() => $ctrl.adjustHeight($ctrl.gridOptions.data.length)); + }; + + const toggleAdmin = (user) => { + if (user.adminChanging) + return; + + user.adminChanging = true; + + AdminData.toggleAdmin(user) + .then(() => user.admin = !user.admin) + .finally(() => user.adminChanging = false); + }; + + const showActivities = (user) => { + return new ActivitiesUserDialog({ user, params: $ctrl.params }); + }; + + $ctrl.gridOptions = { + data: [], + columnVirtualizationThreshold: 30, + columnDefs, + categories, + headerTemplate: $templateCache.get(headerTemplate), + enableFiltering: true, + enableRowSelection: false, + enableRowHeaderSelection: false, + enableColumnMenus: false, + multiSelect: false, + modifierKeysToMultiSelect: true, + noUnselect: true, + fastWatch: true, + onRegisterApi: (api) => { + $ctrl.gridApi = api; + + api.becomeUser = becomeUser; + api.removeUser = removeUser; + api.toggleAdmin = toggleAdmin; + api.showActivities = showActivities; + } + }; + + const usersToFilterOptions = (column) => { + return _.sortBy( + _.map( + _.groupBy($ctrl.gridOptions.data, (usr) => { + const fld = usr[column]; + + return _.isNil(fld) ? fld : fld.toUpperCase(); + }), + (arr, value) => ({label: `${_.head(arr)[column] || 'Not set'} (${arr.length})`, value}) + ), + 'value'); + }; + + /** + * @param {{startDate: Date, endDate: Date}} params + */ + const reloadUsers = (params) => { + AdminData.loadUsers(params) + .then((data) => $ctrl.gridOptions.data = data) + .then((data) => { + companySelectOptions.push(...usersToFilterOptions('company')); + countrySelectOptions.push(...usersToFilterOptions('countryCode')); + + this.gridApi.grid.refresh(); + + return data; + }) + .then((data) => $ctrl.adjustHeight(data.length)); + }; + + $scope.$watch(() => $ctrl.params.startDate, () => { + const endDate = new Date($ctrl.params.startDate); + + endDate.setMonth(endDate.getMonth() + 1); + + $ctrl.params.endDate = endDate; + + reloadUsers($ctrl.params); + }); + } + + adjustHeight(rows) { + const height = Math.min(rows, 20) * 30 + 75; + + // Remove header height. + this.gridApi.grid.element.css('height', height + 'px'); + + this.gridApi.core.handleWindowResize(); + } + + _enableColumns(_categories, visible) { + _.forEach(_categories, (cat) => { + cat.visible = visible; + + _.forEach(this.gridOptions.columnDefs, (col) => { + if (col.categoryDisplayName === cat.name) + col.visible = visible; + }); + }); + + // Workaround for this.gridApi.grid.refresh() didn't return promise. + this.gridApi.grid.processColumnsProcessors(this.gridApi.grid.columns) + .then((renderableColumns) => this.gridApi.grid.setVisibleColumns(renderableColumns)) + .then(() => this.gridApi.grid.redrawInPlace()) + .then(() => this.gridApi.grid.refreshCanvas(true)) + .then(() => { + if (visible) { + const categoryDisplayName = _.last(_categories).name; + + const col = _.findLast(this.gridOptions.columnDefs, {categoryDisplayName}); + + this.gridApi.grid.scrollTo(null, col); + } + }); + } + + _selectableColumns() { + return _.filter(this.gridOptions.categories, (cat) => cat.selectable); + } + + toggleColumns(category, visible) { + this._enableColumns([category], visible); + } + + selectAllColumns() { + this._enableColumns(this._selectableColumns(), true); + } + + clearAllColumns() { + this._enableColumns(this._selectableColumns(), false); + } + + exportCsv() { + this.gridApi.exporter.csvExport('all', 'visible'); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.jade b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.jade new file mode 100644 index 0000000..efed9c0 --- /dev/null +++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.jade @@ -0,0 +1,54 @@ +//- + 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. + +include /app/helpers/jade/mixins.jade +include /app/components/form-field-datepicker/form-field-datepicker.jade + +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 + +.panel.panel-default + .panel-heading.ui-grid-settings + +grid-settings + label Total users: + strong {{ $ctrl.gridOptions.data.length }}    + label Showing users: + strong {{ $ctrl.gridApi.grid.getVisibleRows().length }} + sub(ng-show='users.length === $ctrl.gridApi.grid.getVisibleRows().length') all + div.ui-grid-settings-dateperiod + form(ng-form=form novalidate) + -var form = 'admin' + + +ignite-form-field-datepicker('Period:', '$ctrl.params.startDate', '"period"') + + button.btn.btn-primary(ng-click='$ctrl.exportCsv()' bs-tooltip data-title='Export table to csv') Export + + .panel-collapse + .grid.ui-grid--ignite(ui-grid='$ctrl.gridOptions' ui-grid-resize-columns ui-grid-selection ui-grid-exporter ui-grid-pinning) http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.jade b/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.jade new file mode 100644 index 0000000..7e44d94 --- /dev/null +++ b/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.jade @@ -0,0 +1,27 @@ +//- + 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. + +.ui-grid-header.ui-grid-header--subcategories(role='rowgroup') + .ui-grid-top-panel + .ui-grid-header-viewport + .ui-grid-header-canvas + .ui-grid-header-cell-wrapper(ng-style='colContainer.headerCellWrapperStyle()') + .ui-grid-header-cell-row(role='row') + .ui-grid-header-span.ui-grid-header-cell.ui-grid-clearfix(ng-repeat='cat in grid.options.categories') + div(ng-show='(colContainer.renderedColumns|uiGridSubcategories:cat.name).length > 1') + .ui-grid-cell-contents {{ cat.name }} + .ui-grid-header-cell-row + .ui-grid-header-cell.ui-grid-clearfix(ng-repeat='col in (colContainer.renderedColumns|uiGridSubcategories:cat.name) track by col.uid' ui-grid-header-cell='' col='col' render-index='$index') http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.scss b/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.scss new file mode 100644 index 0000000..c390504 --- /dev/null +++ b/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.scss @@ -0,0 +1,84 @@ +/* + * 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. + */ + +.ui-grid-header--subcategories { + .ui-grid-row:nth-child(even) .ui-grid-cell.cell-total { + background-color: rgba(102,175,233,.6); + } + + .ui-grid-row:nth-child(odd) .ui-grid-cell.cell-total { + background-color: rgba(102,175,233,.3); + } + + .ui-grid-header-cell-row { + height: 30px; + } + + .ui-grid-header-cell [role="columnheader"] { + display: flex; + + flex-wrap: wrap; + align-items: center; + justify-content: center; + + height: 100%; + + & > div { + flex: 1 100%; + height: auto; + } + + & > div[ui-grid-filter] { + flex: auto; + } + } + + .ui-grid-header-span { + position: relative; + border-right: 0; + + .ng-hide + .ui-grid-header-cell-row .ui-grid-header-cell { + height: 58px; + } + + .ng-hide + .ui-grid-header-cell-row .ui-grid-cell-contents { + padding: 5px 5px; + } + + .ui-grid-column-resizer.right { + top: -100px; + } + .ng-hide + .ui-grid-header-cell-row .ui-grid-column-resizer.right { + bottom: -100px; + } + + &.ui-grid-header-cell .ui-grid-header-cell .ui-grid-column-resizer.right { + border-right-width: 0; + } + &.ui-grid-header-cell .ui-grid-header-cell:last-child .ui-grid-column-resizer.right { + border-right-width: 1px; + } + + & > div > .ui-grid-cell-contents { + border-bottom: 1px solid #d4d4d4; + } + } + + input { + line-height: 21px; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.jade b/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.jade new file mode 100644 index 0000000..8f1487e --- /dev/null +++ b/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.jade @@ -0,0 +1,33 @@ +//- + 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. + +mixin ui-grid-settings() + .ui-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 paragraph.gridOptions.categories|filter:{selectable:true}') + a(ng-click='paragraph.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='paragraph.selectAllColumns()') Select all + li + a(ng-click='paragraph.clearAllColumns()') Clear all + li.divider + li + a(ng-click='$hide()') Close http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.scss b/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.scss new file mode 100644 index 0000000..3016488 --- /dev/null +++ b/modules/web-console/frontend/app/components/ui-grid-settings/ui-grid-settings.scss @@ -0,0 +1,70 @@ +/* + * 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. + */ + +.ui-grid-settings { + ul.select.dropdown-menu > li > a { + padding-top: 0; + padding-bottom: 0; + } + + ul.select.dropdown-menu > li > a > i { + position: relative; + line-height: 26px; + width: 14px; + margin-left: 0; + color: inherit; + } + + ul.select.dropdown-menu > li > a > span { + line-height: 26px; + padding-left: 5px; + padding-right: 8px; + cursor: pointer; + } + + &-dateperiod { + float: right; + + .ignite-form-field { + width: 160px; + margin-right: 10px; + + &__label { + } + + &__control { + } + + &:nth-child(1) { + float: left; + + .ignite-form-field__label { + width: 40%; + } + + .ignite-form-field__control { + width: 60%; + } + } + } + + .btn { + line-height: 20px; + margin-right: 0; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/core/activities/Activities.data.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/core/activities/Activities.data.js b/modules/web-console/frontend/app/core/activities/Activities.data.js new file mode 100644 index 0000000..8a67a97 --- /dev/null +++ b/modules/web-console/frontend/app/core/activities/Activities.data.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +export default class ActivitiesData { + static $inject = ['$http', '$state']; + + constructor($http, $state) { + this.$http = $http; + this.$state = $state; + } + + post(options = {}) { + let { group, action } = options; + + action = action || this.$state.$current.url.source; + group = group || action.match(/^\/([^/]+)/)[1]; + + return this.$http.post('/api/v1/activities/page', { group, action }); + } + + listByUser(userId, params) { + return this.$http.get(`/api/v1/activities/user/${userId}`, { params }) + .then(({ data }) => data); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/core/admin/Admin.data.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/core/admin/Admin.data.js b/modules/web-console/frontend/app/core/admin/Admin.data.js new file mode 100644 index 0000000..66d82f0 --- /dev/null +++ b/modules/web-console/frontend/app/core/admin/Admin.data.js @@ -0,0 +1,77 @@ +/* + * 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. + */ + +export default class IgniteAdminData { + static $inject = ['$http', 'IgniteMessages', 'IgniteCountries']; + + constructor($http, Messages, Countries) { + this.$http = $http; + this.Messages = Messages; + this.Countries = Countries; + } + + becomeUser(viewedUserId) { + return this.$http.get('/api/v1/admin/become', { + params: {viewedUserId} + }) + .catch(this.Messages.showError); + } + + removeUser(user) { + return this.$http.post('/api/v1/admin/remove', { + userId: user._id + }) + .then(() => { + this.Messages.showInfo(`User has been removed: "${user.userName}"`); + }) + .catch(({data, status}) => { + if (status === 503) + this.Messages.showInfo(data); + else + this.Messages.showError('Failed to remove user: ', data); + }); + } + + toggleAdmin(user) { + return this.$http.post('/api/v1/admin/save', { + userId: user._id, + adminFlag: !user.admin + }) + .then(() => { + this.Messages.showInfo(`Admin right was successfully toggled for user: "${user.userName}"`); + }) + .catch((res) => { + this.Messages.showError('Failed to toggle admin right for user: ', res); + }); + } + + prepareUsers(user) { + const { Countries } = this; + + user.userName = user.firstName + ' ' + user.lastName; + user.countryCode = Countries.getByName(user.country).code; + + return user; + } + + loadUsers(params) { + return this.$http.post('/api/v1/admin/list', params) + .then(({ data }) => data) + .then((users) => _.map(users, this.prepareUsers.bind(this))) + .catch(this.Messages.showError); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/core/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/core/index.js b/modules/web-console/frontend/app/core/index.js new file mode 100644 index 0000000..7f72ee3 --- /dev/null +++ b/modules/web-console/frontend/app/core/index.js @@ -0,0 +1,25 @@ +/* + * 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 IgniteAdminData from './admin/Admin.data'; +import IgniteActivitiesData from './activities/Activities.data'; + +angular.module('ignite-console.core', []) + .service('IgniteAdminData', IgniteAdminData) + .service('IgniteActivitiesData', IgniteActivitiesData); http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/data/i18n.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/data/i18n.js b/modules/web-console/frontend/app/data/i18n.js new file mode 100644 index 0000000..bc8c700 --- /dev/null +++ b/modules/web-console/frontend/app/data/i18n.js @@ -0,0 +1,38 @@ +/* + * 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. + */ + +export default { + '/agent/start': 'Agent start', + '/agent/download': 'Agent download', + '/configuration/clusters': 'Configure clusters', + '/configuration/caches': 'Configure caches', + '/configuration/domains': 'Configure domain model', + '/configuration/igfs': 'Configure IGFS', + '/configuration/summary': 'Configurations summary', + '/demo/resume': 'Demo resume', + '/demo/reset': 'Demo reset', + '/queries/execute': 'Query execute', + '/queries/explain': 'Query explain', + '/queries/scan': 'Scan', + '/queries/add/query': 'Add query', + '/queries/add/scan': 'Add scan', + '/queries/demo': 'SQL demo', + '/queries/notebook/': 'Query notebook', + '/settings/profile': 'User profile', + '/settings/admin': 'Admin panel', + '/logout': 'Logout' +}; http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.jade ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.jade b/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.jade deleted file mode 100644 index 8f1487e..0000000 --- a/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.jade +++ /dev/null @@ -1,33 +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. - -mixin ui-grid-settings() - .ui-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 paragraph.gridOptions.categories|filter:{selectable:true}') - a(ng-click='paragraph.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='paragraph.selectAllColumns()') Select all - li - a(ng-click='paragraph.clearAllColumns()') Clear all - li.divider - li - a(ng-click='$hide()') Close http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.scss b/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.scss deleted file mode 100644 index 6517a60..0000000 --- a/modules/web-console/frontend/app/directives/ui-grid-settings/ui-grid-settings.scss +++ /dev/null @@ -1,38 +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. - */ - -.ui-grid-settings { - ul.select.dropdown-menu > li > a { - padding-top: 0; - padding-bottom: 0; - } - - ul.select.dropdown-menu > li > a > i { - position: relative; - line-height: 26px; - width: 14px; - margin-left: 0; - color: inherit; - } - - ul.select.dropdown-menu > li > a > span { - line-height: 26px; - padding-left: 5px; - padding-right: 8px; - cursor: pointer; - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/26ee9c28/modules/web-console/frontend/app/filters/uiGridSubcategories.filter.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/filters/uiGridSubcategories.filter.js b/modules/web-console/frontend/app/filters/uiGridSubcategories.filter.js new file mode 100644 index 0000000..f36ae6e --- /dev/null +++ b/modules/web-console/frontend/app/filters/uiGridSubcategories.filter.js @@ -0,0 +1,24 @@ +/* + * 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. + */ + +export default [() => { + return (arr, category) => { + return _.filter(arr, (item) => { + return item.colDef.categoryDisplayName === category; + }); + }; +}];