Repository: ignite Updated Branches: refs/heads/master 3b89a5ce7 -> 827befb7f
IGNITE-4686 Added ability to group registered users in admin panel. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/827befb7 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/827befb7 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/827befb7 Branch: refs/heads/master Commit: 827befb7f368afd1a42ec52e559dee01ab57113a Parents: 3b89a5c Author: Dmitriy Shabalin <dshaba...@gridgain.com> Authored: Wed Mar 22 10:37:05 2017 +0700 Committer: Andrey Novikov <anovi...@gridgain.com> Committed: Wed Mar 22 10:37:05 2017 +0700 ---------------------------------------------------------------------- modules/web-console/frontend/app/app.js | 1 + .../form-field-datepicker.pug | 12 +- .../list-of-registered-users/index.js | 2 + .../list-of-registered-users.column-defs.js | 48 ++--- .../list-of-registered-users.controller.js | 193 ++++++++++++++----- .../list-of-registered-users.scss | 28 +++ .../list-of-registered-users.tpl.pug | 50 +++-- .../ui-grid-header/ui-grid-header.scss | 6 + .../ui-grid-header/ui-grid-header.tpl.pug | 4 +- .../ui-grid-settings/ui-grid-settings.scss | 10 + .../frontend/app/primitives/badge/index.scss | 36 ++++ .../frontend/app/primitives/index.js | 19 ++ .../frontend/app/primitives/tabs/index.scss | 73 +++++++ .../frontend/public/stylesheets/style.scss | 2 + 14 files changed, 389 insertions(+), 95 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/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 1e21d24..26d3ad5 100644 --- a/modules/web-console/frontend/app/app.js +++ b/modules/web-console/frontend/app/app.js @@ -16,6 +16,7 @@ */ import '../public/stylesheets/style.scss'; +import '../app/primitives'; import './components/ui-grid-header/ui-grid-header.scss'; import './components/ui-grid-settings/ui-grid-settings.scss'; import './components/form-field-datepicker/form-field-datepicker.scss'; http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.pug ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.pug b/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.pug index c9d382c..d70476f 100644 --- a/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.pug +++ b/modules/web-console/frontend/app/components/form-field-datepicker/form-field-datepicker.pug @@ -14,7 +14,7 @@ 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 ignite-form-field-datepicker(label, model, name, mindate, maxdate, disabled, required, placeholder, tip) mixin form-field-input() input.form-control( id=`{{ ${name} }}Input` @@ -30,8 +30,10 @@ mixin ignite-form-field-datepicker(label, model, name, disabled, required, place bs-datepicker data-date-format='MMM yyyy' data-start-view='1' - data-min-view='1' - data-max-date='today' + data-min-view='1' + + data-min-date=mindate ? `{{ ${mindate} }}` : false + data-max-date=maxdate ? `{{ ${maxdate} }}` : `today` data-container='body > .wrapper' @@ -43,7 +45,9 @@ mixin ignite-form-field-datepicker(label, model, name, disabled, required, place )&attributes(attributes.attributes) .ignite-form-field - +ignite-form-field__label(label, name, required) + if name + +ignite-form-field__label(label, name, required) + .ignite-form-field__control if tip i.tipField.icon-help(bs-tooltip='' data-title=tip) http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/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 index 22a89da..4e5061f 100644 --- 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 @@ -15,6 +15,8 @@ * limitations under the License. */ +import './list-of-registered-users.scss'; + import templateUrl from './list-of-registered-users.tpl.pug'; import controller from './list-of-registered-users.controller'; http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/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 index e6ba842..e859acf 100644 --- 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 @@ -49,32 +49,32 @@ const ACTIONS_TEMPLATE = ` const EMAIL_TEMPLATE = '<div class="ui-grid-cell-contents"><a ng-href="mailto:{{ COL_FIELD }}">{{ COL_FIELD }}</a></div>'; export default [ - {displayName: 'Actions', categoryDisplayName: 'Actions', cellTemplate: ACTIONS_TEMPLATE, field: 'actions', minWidth: 65, width: 65, 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 }}, + {name: 'actions', displayName: 'Actions', categoryDisplayName: 'Actions', cellTemplate: ACTIONS_TEMPLATE, field: 'actions', minWidth: 70, width: 70, enableFiltering: false, enableSorting: false}, + {name: 'user', displayName: 'User', categoryDisplayName: 'User', field: 'userName', cellTemplate: USER_TEMPLATE, minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by name...' }}, + {name: 'email', displayName: 'Email', categoryDisplayName: 'Email', field: 'email', cellTemplate: EMAIL_TEMPLATE, minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by email...' }}, + {name: 'company', displayName: 'Company', categoryDisplayName: 'Company', field: 'company', minWidth: 160, enableFiltering: true, filter: { placeholder: 'Filter by company...' }}, + {name: 'country', displayName: 'Country', categoryDisplayName: 'Country', field: 'countryCode', minWidth: 80, enableFiltering: true, filter: { placeholder: 'Filter by country...' }}, + {name: 'lastlogin', displayName: 'Last login', categoryDisplayName: 'Last login', field: 'lastLogin', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 105, width: 105, enableFiltering: false, visible: false}, + {name: 'lastactivity', displayName: 'Last activity', categoryDisplayName: 'Last activity', field: 'lastActivity', cellFilter: 'date:"M/d/yy HH:mm"', minWidth: 115, width: 115, 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}, + {name: 'cfg_clusters', displayName: 'Clusters count', categoryDisplayName: 'Configurations', headerCellTemplate: CLUSTER_HEADER_TEMPLATE, field: 'counters.clusters', type: 'number', headerTooltip: 'Clusters count', minWidth: 55, width: 55, enableFiltering: false, visible: false}, + {name: 'cfg_models', displayName: 'Models count', categoryDisplayName: 'Configurations', headerCellTemplate: MODEL_HEADER_TEMPLATE, field: 'counters.models', type: 'number', headerTooltip: 'Models count', minWidth: 55, width: 55, enableFiltering: false, visible: false}, + {name: 'cfg_caches', displayName: 'Caches count', categoryDisplayName: 'Configurations', headerCellTemplate: CACHE_HEADER_TEMPLATE, field: 'counters.caches', type: 'number', headerTooltip: 'Caches count', minWidth: 55, width: 55, enableFiltering: false, visible: false}, + {name: 'cfg_igfs', displayName: 'IGFS count', categoryDisplayName: 'Configurations', headerCellTemplate: IGFS_HEADER_TEMPLATE, field: 'counters.igfs', type: 'number', headerTooltip: 'IGFS count', minWidth: 55, width: 55, enableFiltering: false, visible: false}, // Activities Total - {displayName: 'Cfg', categoryDisplayName: 'Total activities', field: 'activitiesTotal["configuration"] || 0', type: 'number', headerTooltip: 'Total count of configuration usages', minWidth: 50, width: 50, enableFiltering: false}, - {displayName: 'Qry', categoryDisplayName: 'Total activities', field: 'activitiesTotal["queries"] || 0', type: 'number', headerTooltip: 'Total count of queries usages', minWidth: 50, width: 50, enableFiltering: false}, - {displayName: 'Demo', categoryDisplayName: 'Total activities', field: 'activitiesTotal["demo"] || 0', type: 'number', headerTooltip: 'Total count of demo startup', minWidth: 60, width: 60, enableFiltering: false}, - {displayName: 'Dnld', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/download"] || 0', type: 'number', headerTooltip: 'Total count of agent downloads', minWidth: 55, width: 55, enableFiltering: false}, - {displayName: 'Starts', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/start"] || 0', type: 'number', headerTooltip: 'Total count of agent startup', minWidth: 60, width: 60, enableFiltering: false}, + {name: 'cfg', displayName: 'Cfg', categoryDisplayName: 'Total activities', field: 'activitiesTotal["configuration"] || 0', type: 'number', headerTooltip: 'Total count of configuration usages', minWidth: 55, width: 55, enableFiltering: false}, + {name: 'qry', displayName: 'Qry', categoryDisplayName: 'Total activities', field: 'activitiesTotal["queries"] || 0', type: 'number', headerTooltip: 'Total count of queries usages', minWidth: 55, width: 55, enableFiltering: false}, + {name: 'demo', displayName: 'Demo', categoryDisplayName: 'Total activities', field: 'activitiesTotal["demo"] || 0', type: 'number', headerTooltip: 'Total count of demo startup', minWidth: 65, width: 65, enableFiltering: false}, + {name: 'dnld', displayName: 'Dnld', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/download"] || 0', type: 'number', headerTooltip: 'Total count of agent downloads', minWidth: 55, width: 55, enableFiltering: false}, + {name: 'starts', displayName: 'Starts', categoryDisplayName: 'Total activities', field: 'activitiesDetail["/agent/start"] || 0', type: 'number', headerTooltip: 'Total count of agent startup', minWidth: 65, width: 65, 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}, + {name: 'clusters', displayName: 'Clusters', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/clusters"] || 0', type: 'number', headerTooltip: 'Configuration clusters', minWidth: 55, width: 80, enableFiltering: false, visible: false}, + {name: 'model', displayName: 'Model', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/domains"] || 0', type: 'number', headerTooltip: 'Configuration model', minWidth: 55, width: 80, enableFiltering: false, visible: false}, + {name: 'caches', displayName: 'Caches', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/caches"] || 0', type: 'number', headerTooltip: 'Configuration caches', minWidth: 55, width: 80, enableFiltering: false, visible: false}, + {name: 'igfs', displayName: 'IGFS', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/igfs"] || 0', type: 'number', headerTooltip: 'Configuration IGFS', minWidth: 55, width: 80, enableFiltering: false, visible: false}, + {name: 'summary', displayName: 'Summary', categoryDisplayName: 'Configuration\'s activities', field: 'activitiesDetail["/configuration/summary"] || 0', type: 'number', headerTooltip: 'Configuration summary', minWidth: 55, width: 80, enableFiltering: false, visible: false}, // Activities Queries - {displayName: 'Execute', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/execute"] || 0', type: 'number', headerTooltip: 'Query executions', minWidth: 50, width: 80, enableFiltering: false, visible: false}, - {displayName: 'Explain', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/explain"] || 0', type: 'number', headerTooltip: 'Query explain executions', minWidth: 50, width: 80, enableFiltering: false, visible: false}, - {displayName: 'Scan', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/scan"] || 0', type: 'number', headerTooltip: 'Scan query executions', minWidth: 50, width: 80, enableFiltering: false, visible: false} + {name: 'execute', displayName: 'Execute', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/execute"] || 0', type: 'number', headerTooltip: 'Query executions', minWidth: 55, width: 80, enableFiltering: false, visible: false}, + {name: 'explain', displayName: 'Explain', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/explain"] || 0', type: 'number', headerTooltip: 'Query explain executions', minWidth: 55, width: 80, enableFiltering: false, visible: false}, + {name: 'scan', displayName: 'Scan', categoryDisplayName: 'Queries\' activities', field: 'activitiesDetail["/queries/scan"] || 0', type: 'number', headerTooltip: 'Scan query executions', minWidth: 55, width: 80, enableFiltering: false, visible: false} ]; http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/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 index 54971b1..acf76fa 100644 --- 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 @@ -30,34 +30,21 @@ const rowTemplate = `<div ui-grid-cell/>`; export default class IgniteListOfRegisteredUsersCtrl { - static $inject = ['$scope', '$state', '$filter', 'User', 'uiGridConstants', 'IgniteAdminData', 'IgniteNotebookData', 'IgniteConfirm', 'IgniteActivitiesUserDialog']; + static $inject = ['$scope', '$state', '$filter', 'User', 'uiGridGroupingConstants', 'IgniteAdminData', 'IgniteNotebookData', 'IgniteConfirm', 'IgniteActivitiesUserDialog']; - constructor($scope, $state, $filter, User, uiGridConstants, AdminData, NotebookData, Confirm, ActivitiesUserDialog) { + constructor($scope, $state, $filter, User, uiGridGroupingConstants, AdminData, NotebookData, Confirm, ActivitiesUserDialog) { const $ctrl = this; - const companySelectOptions = []; - const countrySelectOptions = []; - const dtFilter = $filter('date'); + $ctrl.groupBy = 'user'; + $ctrl.params = { - startDate: new Date() + startDate: new Date(), + endDate: new Date() }; - 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 - }; + $ctrl.uiGridGroupingConstants = uiGridGroupingConstants; const becomeUser = (user) => { AdminData.becomeUser(user._id) @@ -105,6 +92,11 @@ export default class IgniteListOfRegisteredUsersCtrl { return renderableRows; }; + $ctrl._userGridOptions = { + columnDefs, + categories + }; + $ctrl.gridOptions = { data: [], columnVirtualizationThreshold: 30, @@ -134,19 +126,6 @@ export default class IgniteListOfRegisteredUsersCtrl { } }; - 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: number, endDate: number}} params */ @@ -154,31 +133,32 @@ export default class IgniteListOfRegisteredUsersCtrl { AdminData.loadUsers(params) .then((data) => $ctrl.gridOptions.data = data) .then((data) => { - companySelectOptions.length = 0; - countrySelectOptions.length = 0; - - companySelectOptions.push(...usersToFilterOptions('company')); - countrySelectOptions.push(...usersToFilterOptions('countryCode')); - this.gridApi.grid.refresh(); + this.companies = _.values(_.groupBy(data, (b) => b.company.toLowerCase())); + this.countries = _.values(_.groupBy(data, (b) => b.countryCode)); + return data; - }) - .then((data) => $ctrl.adjustHeight(data.length)); + }); + }; + + const fitlerDates = (sdt, edt) => { + $ctrl.gridOptions.exporterCsvFilename = `web_console_users_${dtFilter(sdt, 'yyyy_MM')}.csv`; + + const startDate = Date.UTC(sdt.getFullYear(), sdt.getMonth(), 1); + const endDate = Date.UTC(edt.getFullYear(), edt.getMonth() + 1, 1); + + reloadUsers({ startDate, endDate }); }; $scope.$watch(() => $ctrl.params.companiesExclude, () => { $ctrl.gridApi.grid.refreshRows(); }); - $scope.$watch(() => $ctrl.params.startDate, (dt) => { - $ctrl.gridOptions.exporterCsvFilename = `web_console_users_${dtFilter(dt, 'yyyy_MM')}.csv`; + $scope.$watch(() => $ctrl.params.startDate, (sdt) => fitlerDates(sdt, $ctrl.params.endDate)); + $scope.$watch(() => $ctrl.params.endDate, (edt) => fitlerDates($ctrl.params.startDate, edt)); - const startDate = Date.UTC(dt.getFullYear(), dt.getMonth(), 1); - const endDate = Date.UTC(dt.getFullYear(), dt.getMonth() + 1, 1); - - reloadUsers({ startDate, endDate }); - }); + $scope.$watch(() => $ctrl.gridApi.grid.getVisibleRows().length, (length) => $ctrl.adjustHeight(length >= 20 ? 20 : length)); } adjustHeight(rows) { @@ -235,4 +215,121 @@ export default class IgniteListOfRegisteredUsersCtrl { exportCsv() { this.gridApi.exporter.csvExport('visible', 'visible'); } + + groupByUser() { + this.groupBy = 'user'; + + this.gridApi.grouping.clearGrouping(); + + this.gridOptions.categories = this._userGridOptions.categories; + this.gridOptions.columnDefs = this._userGridOptions.columnDefs; + } + + groupByCompany() { + this.groupBy = 'company'; + + this.gridApi.grouping.clearGrouping(); + this.gridApi.grouping.groupColumn('company'); + this.gridApi.grouping.aggregateColumn('user', this.uiGridGroupingConstants.aggregation.COUNT); + + if (this._companyGridOptions) { + this.gridOptions.categories = this._companyGridOptions.categories; + this.gridOptions.columnDefs = this._companyGridOptions.columnDefs; + + return; + } + + const _categories = _.cloneDeep(categories); + const _columnDefs = _.cloneDeep(columnDefs); + + // Cut company category; + const company = _categories.splice(3, 1)[0]; + + // Hide Actions category; + _categories.splice(0, 1); + + _.forEach(_.filter(_columnDefs, {displayName: 'Actions'}), (col) => { + col.visible = false; + }); + + // Add company as first column; + _categories.unshift(company); + + _.forEach(_columnDefs, (col) => { + col.enableSorting = true; + + if (col.type !== 'number') + return; + + col.treeAggregationType = this.uiGridGroupingConstants.aggregation.SUM; + col.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value; + }); + + // Set grouping to last activity column + const lastactivity = _.find(_columnDefs, { name: 'lastactivity' }); + + if (_.nonNil(lastactivity)) { + lastactivity.treeAggregationType = this.uiGridGroupingConstants.aggregation.MAX; + lastactivity.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value; + } + + this._companyGridOptions = { + categories: this.gridOptions.categories = _categories, + columnDefs: this.gridOptions.columnDefs = _columnDefs + }; + } + + groupByCountry() { + this.groupBy = 'country'; + + this.gridApi.grouping.clearGrouping(); + this.gridApi.grouping.groupColumn('country'); + this.gridApi.grouping.aggregateColumn('user', this.uiGridGroupingConstants.aggregation.COUNT); + + if (this._countryGridOptions) { + this.gridOptions.categories = this._countryGridOptions.categories; + this.gridOptions.columnDefs = this._countryGridOptions.columnDefs; + + return; + } + + const _categories = _.cloneDeep(categories); + const _columnDefs = _.cloneDeep(columnDefs); + + // Cut country category; + const country = _categories.splice(4, 1)[0]; + + // Hide Actions category; + _categories.splice(0, 1); + + _.forEach(_.filter(_columnDefs, {displayName: 'Actions'}), (col) => { + col.visible = false; + }); + + // Add company as first column; + _categories.unshift(country); + + _.forEach(_columnDefs, (col) => { + col.enableSorting = true; + + if (col.type !== 'number') + return; + + col.treeAggregationType = this.uiGridGroupingConstants.aggregation.SUM; + col.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value; + }); + + // Set grouping to last activity column + const lastactivity = _.find(_columnDefs, { name: 'lastactivity' }); + + if (_.nonNil(lastactivity)) { + lastactivity.treeAggregationType = this.uiGridGroupingConstants.aggregation.MAX; + lastactivity.customTreeAggregationFinalizerFn = (agg) => agg.rendered = agg.value; + } + + this._countryGridOptions = { + categories: this.gridOptions.categories = _categories, + columnDefs: this.gridOptions.columnDefs = _columnDefs + }; + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.scss b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.scss new file mode 100644 index 0000000..8059d70 --- /dev/null +++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.scss @@ -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. + */ + +.list-of-registered-users { + & > a { + display: inline-block; + margin: 10px; + margin-left: 0; + + &.active { + font-weight: bold; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug index 52975b9..ec4b4fd 100644 --- a/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug +++ b/modules/web-console/frontend/app/components/list-of-registered-users/list-of-registered-users.tpl.pug @@ -34,25 +34,39 @@ mixin grid-settings() 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 - - form.pull-right(ng-form=form novalidate) - -var form = 'admin' - button.btn.btn-primary(ng-click='$ctrl.exportCsv()' bs-tooltip data-title='Export table to csv') Export +.list-of-registered-users + ul.tabs + li(role='presentation' ng-class='{ active: $ctrl.groupBy === "user" }') + a(ng-click='$ctrl.groupByUser()') + span Users + span.badge {{ $ctrl.gridOptions.data.length }} + li(role='presentation' ng-class='{ active: $ctrl.groupBy === "company" }') + a(ng-click='$ctrl.groupByCompany()') + span Companies + span.badge {{ $ctrl.companies.length }} + li(role='presentation' ng-class='{ active: $ctrl.groupBy === "country" }') + a(ng-click='$ctrl.groupByCountry()') + span Countries + span.badge {{ $ctrl.countries.length }} + + .panel.panel-default + .panel-heading.ui-grid-settings + +grid-settings + label(ng-show='$ctrl.groupBy === "user"') Showing users: + strong {{ $ctrl.gridApi.grid.getVisibleRows().length }} + sub(ng-show='users.length === $ctrl.gridApi.grid.getVisibleRows().length') all + + -var form = 'admin' + form.pull-right(name=form novalidate) + button.btn.btn-primary(ng-click='$ctrl.exportCsv()' bs-tooltip data-title='Export table to csv') Export - .ui-grid-settings-dateperiod - +ignite-form-field-datepicker('Period:', '$ctrl.params.startDate', '"period"') + .ui-grid-settings-dateperiod + +ignite-form-field-datepicker('Period:', '$ctrl.params.startDate', '"period"', null, '$ctrl.params.endDate') + +ignite-form-field-datepicker('Period:', '$ctrl.params.endDate', null, '$ctrl.params.startDate', null) - .ui-grid-settings-filter - +ignite-form-field-text('Exclude:', '$ctrl.params.companiesExclude', '"exclude"', false, false, 'Exclude by company name...') + .ui-grid-settings-filter + +ignite-form-field-text('Exclude:', '$ctrl.params.companiesExclude', '"exclude"', false, false, 'Exclude by company name...') - .panel-collapse - .grid.ui-grid--ignite(ui-grid='$ctrl.gridOptions' ui-grid-resize-columns ui-grid-selection ui-grid-exporter ui-grid-pinning) + .panel-collapse + .grid.ui-grid--ignite(ui-grid='$ctrl.gridOptions' ui-grid-resize-columns ui-grid-selection ui-grid-exporter ui-grid-pinning ui-grid-grouping) http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/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 index c6e7bdf..4530c02 100644 --- 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 @@ -28,6 +28,12 @@ height: 30px; } + .ui-grid-header-cell { + .ui-grid-cell-contents > span:not(.ui-grid-header-cell-label) { + right: 3px; + } + } + .ui-grid-header-cell [role="columnheader"] { display: flex; http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.tpl.pug ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.tpl.pug b/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.tpl.pug index 7e44d94..9b14fca 100644 --- a/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.tpl.pug +++ b/modules/web-console/frontend/app/components/ui-grid-header/ui-grid-header.tpl.pug @@ -20,8 +20,10 @@ .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') + .ui-grid-header-span.ui-grid-header-cell.ui-grid-clearfix.ui-grid-category(ng-repeat='cat in grid.options.categories', ng-if='cat.visible && \ + (colContainer.renderedColumns | uiGridSubcategories: cat.name).length > 0') 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') + .ui-grid-header-cell.ui-grid-clearfix(ng-if='col.colDef.name === "treeBaseRowHeaderCol"' ng-repeat='col in colContainer.renderedColumns track by col.uid' ui-grid-header-cell='' col='col' render-index='$index') http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/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 index 24f4d9b..d0a31f0 100644 --- 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 @@ -129,6 +129,16 @@ width: 60%; } } + + &:nth-child(2) { + float: left; + + width: 100px; + + .ignite-form-field__control { + width: 100%; + } + } } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/modules/web-console/frontend/app/primitives/badge/index.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/primitives/badge/index.scss b/modules/web-console/frontend/app/primitives/badge/index.scss new file mode 100644 index 0000000..837ab5b --- /dev/null +++ b/modules/web-console/frontend/app/primitives/badge/index.scss @@ -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 '../../../public/stylesheets/variables'; + +.badge { + display: inline-block; + min-width: 26px; + height: 18px; + + padding: 2px 9px; + + border-radius: 9px; + + color: white; + font-family: Roboto; + font-size: 12px; + text-align: center; + line-height: 12px; + + background-color: $brand-primary; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/modules/web-console/frontend/app/primitives/index.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/primitives/index.js b/modules/web-console/frontend/app/primitives/index.js new file mode 100644 index 0000000..7940f7a --- /dev/null +++ b/modules/web-console/frontend/app/primitives/index.js @@ -0,0 +1,19 @@ +/* + * 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 './badge/index.scss'; +import './tabs/index.scss'; http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/modules/web-console/frontend/app/primitives/tabs/index.scss ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/primitives/tabs/index.scss b/modules/web-console/frontend/app/primitives/tabs/index.scss new file mode 100644 index 0000000..eed88cb --- /dev/null +++ b/modules/web-console/frontend/app/primitives/tabs/index.scss @@ -0,0 +1,73 @@ +/* + * 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 '../../../public/stylesheets/variables'; + +ul.tabs { + $width: auto; + $height: 40px; + $offset-vertical: 11px; + $offset-horizontal: 25px; + $font-size: 14px; + + list-style: none; + + padding-left: 0; + border-bottom: 1px solid $nav-tabs-border-color; + + li { + position: relative; + top: 1px; + + display: inline-block; + + border-bottom: 5px solid transparent; + + a { + display: inline-block; + width: $width; + height: $height; + + padding: $offset-vertical $offset-horizontal; + + color: $text-color; + font-size: $font-size; + text-align: center; + line-height: $height - 2*$offset-vertical; + + &:hover { + text-decoration: none; + } + + .badge { + margin-left: $offset-vertical; + } + } + + &.active { + border-color: $brand-primary; + } + + &:not(.active):hover { + border-color: lighten($brand-primary, 25%); + } + + & + li { + margin-left: 45px; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/827befb7/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 a07472e..2f4966f 100644 --- a/modules/web-console/frontend/public/stylesheets/style.scss +++ b/modules/web-console/frontend/public/stylesheets/style.scss @@ -2302,6 +2302,8 @@ html,body,.splash-screen { .admin-page { .panel-heading { + height: 38px; + border-bottom: 0; padding-bottom: 0;