#435: added filter by users and groups

This commit is contained in:
Vokhmin Alexey V 2014-10-22 00:56:36 +04:00
parent acd57203c7
commit f39c9e0bb5
9 changed files with 91 additions and 23 deletions

View File

@ -1,9 +1,10 @@
RosaABF.controller 'StatisticsController', ['$scope', '$http', ($scope, $http) -> RosaABF.controller 'StatisticsController', ['$scope', '$http', '$timeout', ($scope, $http, $timeout) ->
$scope.users_or_groups = null
$scope.range = 'last_30_days' $scope.range = 'last_30_days'
$scope.range_start = $('#range_start').attr('value') $scope.range_start = $('#range_start').attr('value')
$scope.range_end = $('#range_end').attr('value') $scope.range_end = $('#range_end').attr('value')
$scope.loading = true $scope.loading = false
$scope.statistics = {} $scope.statistics = {}
$scope.statistics_path = '/statistics' $scope.statistics_path = '/statistics'
@ -12,22 +13,24 @@ RosaABF.controller 'StatisticsController', ['$scope', '$http', ($scope, $http) -
'77, 169, 68', '77, 169, 68',
'241, 128, 73', '241, 128, 73',
'174, 199, 232', '174, 199, 232',
'255, 187, 120', # '255, 187, 120',
'152, 223, 138', # '152, 223, 138',
'214, 39, 40', # '214, 39, 40',
'31, 119, 180' # '31, 119, 180'
] ]
$scope.charts = {} $scope.charts = {}
$('#users_or_groups').on 'autocompleteselect', (e) ->
$timeout($scope.update, 100)
$scope.init = -> $scope.init = ->
$('#range-form .date_picker').datepicker $('#statistics-form .date_picker').datepicker
'dateFormat': 'yy-mm-dd' 'dateFormat': 'yy-mm-dd'
maxDate: 0 maxDate: 0
minDate: -366 minDate: -366
showButtonPanel: true showButtonPanel: true
$scope.rangeChange() $scope.update()
true true
$scope.prepareRange = -> $scope.prepareRange = ->
@ -39,18 +42,27 @@ RosaABF.controller 'StatisticsController', ['$scope', '$http', ($scope, $http) -
$scope.range_start = $scope.range_end $scope.range_start = $scope.range_end
$scope.range_end = tmp $scope.range_end = tmp
$scope.prepareUsersOrGroups = ->
if $scope.users_or_groups
items = _.uniq $('#users_or_groups').val().replace(/\s/g, '').split(/,/)
items = _.reject items, (i) ->
_.isEmpty(i)
$scope.users_or_groups = _.first(items, 3).join(', ') + ', '
$scope.rangeChange = -> $scope.update = ->
return if $scope.loading
$scope.loading = true $scope.loading = true
$scope.statistics = {} $scope.statistics = {}
$scope.prepareRange() $scope.prepareRange()
$scope.prepareUsersOrGroups()
$('.doughnut-legend').remove() $('.doughnut-legend').remove()
params = params =
range: $scope.range range: $scope.range
range_start: $scope.range_start range_start: $scope.range_start
range_end: $scope.range_end range_end: $scope.range_end
users_or_groups: $scope.users_or_groups
format: 'json' format: 'json'
$http.get($scope.statistics_path, params: params).success (results) -> $http.get($scope.statistics_path, params: params).success (results) ->

View File

@ -4,6 +4,13 @@ class AutocompletesController < ApplicationController
autocomplete :group, :uname autocomplete :group, :uname
autocomplete :user, :uname autocomplete :user, :uname
def autocomplete_user_or_group
results = []
results << User.opened.search(params[:term]).search_order.limit(5).pluck(:uname)
results << Group.search(params[:term]).search_order.limit(5).pluck(:uname)
render json: results.flatten.sort.map{ |r| { label: r } }
end
def autocomplete_extra_build_list def autocomplete_extra_build_list
bl = BuildList.for_extra_build_lists(params[:term], current_ability, save_to_platform).first bl = BuildList.for_extra_build_lists(params[:term], current_ability, save_to_platform).first
results << { :id => bl.id, results << { :id => bl.id,

View File

@ -16,7 +16,12 @@ class StatisticsController < ApplicationController
format.html format.html
format.json do format.json do
init_variables init_variables
render json: StatisticPresenter.new(range_start: @range_start, range_end: @range_end, unit: @unit) render json: StatisticPresenter.new(
range_start: @range_start,
range_end: @range_end,
unit: @unit,
users_or_groups: params[:users_or_groups]
)
end end
end end
end end

View File

@ -48,7 +48,24 @@ class Statistic < ActiveRecord::Base
:counter, :counter,
:activity_at :activity_at
scope :for_period, -> (start_date, end_date) { where(activity_at: (start_date..end_date)) } scope :for_period, -> (start_date, end_date) {
where(activity_at: (start_date..end_date))
}
scope :for_users, -> (user_ids) {
where(user_id: user_ids) if user_ids.present?
}
scope :for_groups, -> (group_ids) {
where(["project_id = ANY (
ARRAY (
SELECT target_id
FROM relations
INNER JOIN projects ON projects.id = relations.target_id
WHERE relations.target_type = 'Project' AND
relations.actor_type = 'Group' AND relations.actor_id IN (:groups)
)
)", { user: @user, groups: group_ids }
]) if group_ids.present?
}
scope :build_lists_started, -> { where(key: KEY_BUILD_LIST_BUILD_STARTED) } scope :build_lists_started, -> { where(key: KEY_BUILD_LIST_BUILD_STARTED) }
scope :build_lists_success, -> { where(key: KEY_BUILD_LIST_SUCCESS) } scope :build_lists_success, -> { where(key: KEY_BUILD_LIST_SUCCESS) }

View File

@ -1,11 +1,12 @@
class StatisticPresenter < ApplicationPresenter class StatisticPresenter < ApplicationPresenter
attr_accessor :range_start, :range_end, :unit attr_accessor :range_start, :range_end, :unit, :users_or_groups
def initialize(range_start: nil, range_end: nil, unit: nil) def initialize(range_start: nil, range_end: nil, unit: nil, users_or_groups: nil)
@range_start = range_start @range_start = range_start
@range_end = range_end @range_end = range_end
@unit = unit @unit = unit
@users_or_groups = users_or_groups.to_s.split(/,/).map(&:strip).select(&:present?).first(3)
end end
def as_json(options = nil) def as_json(options = nil)
@ -46,8 +47,17 @@ class StatisticPresenter < ApplicationPresenter
private private
def user_ids
@user_ids ||= User.where(uname: users_or_groups).pluck(:id)
end
def group_ids
@group_ids ||= Group.where(uname: users_or_groups).map(&:member_ids).flatten.uniq
end
def scope def scope
@scope ||= Statistic.for_period(range_start, range_end). @scope ||= Statistic.for_period(range_start, range_end).
for_users(user_ids).for_groups(group_ids).
select("SUM(counter) as count, date_trunc('#{ unit }', activity_at) as activity_at"). select("SUM(counter) as count, date_trunc('#{ unit }', activity_at) as activity_at").
group("date_trunc('#{ unit }', activity_at)").order('activity_at') group("date_trunc('#{ unit }', activity_at)").order('activity_at')
end end

View File

@ -4,11 +4,19 @@
%h3.text-info %h3.text-info
= t('.header') = t('.header')
= form_tag '#', class: 'form-inline alert alert-info centered', id: 'range-form' do %form#statistics-form.form-inline.alert.alert-info.centered
%label.control-label %label.control-label
= t('.range_label') = t('.range_label')
= select_tag 'range', statistics_range_options, id: 'range_select', class: 'select input-medium', ng_model: 'range', ng_change: 'rangeChange()' = select_tag 'range', statistics_range_options, id: 'range_select', class: 'select input-medium', ng_model: 'range', ng_change: 'update()', ng_disabled: 'loading'
%span{ ng_show: "range == 'custom'" } %span{ ng_show: "range == 'custom'" }
= text_field_tag :range_start, Date.today - 1.month, class: 'date_picker input-medium', placeholder: t('.range_start_placeholder'), ng_model: 'range_start', ng_change: 'rangeChange()', readonly: true = text_field_tag :range_start, Date.today - 1.month, class: 'date_picker input-medium', placeholder: t('.range_start_placeholder'), ng_model: 'range_start', ng_change: 'update()', readonly: true, size: 10, ng_disabled: 'loading'
= t('.range_separator') = t('.range_separator')
= text_field_tag :range_end, Date.today, class: 'date_picker input-medium', placeholder: t('.range_end_placeholder'), ng_model: 'range_end', ng_change: 'rangeChange()', readonly: true = text_field_tag :range_end, Date.today, class: 'date_picker input-medium', placeholder: t('.range_end_placeholder'), ng_model: 'range_end', ng_change: 'update()', readonly: true, size: 10, ng_disabled: 'loading'
%label.control-label
= t('.users_or_groups_label')
= autocomplete_field_tag 'users_or_groups', nil,autocomplete_user_or_group_autocompletes_path, multiple: true, 'data-delimiter' => ', ', ng_model: 'users_or_groups', placeholder: t('.users_or_groups_placeholder'), ng_disabled: 'loading'
%a{ href: '#', ng_click: 'update()' }
%b
= t('.refresh')

View File

@ -10,6 +10,10 @@ en:
range_separator: " and " range_separator: " and "
range_end_placeholder: "Select an end date" range_end_placeholder: "Select an end date"
users_or_groups_label: "for users or groups"
refresh: "refresh"
users_or_groups_placeholder: "Enter a nickname here."
build_lists: build_lists:
header: "Build lists" header: "Build lists"
build_started_title: "Build started" build_started_title: "Build started"

View File

@ -10,6 +10,10 @@ ru:
range_separator: " и " range_separator: " и "
range_end_placeholder: "Выберите конечную дату" range_end_placeholder: "Выберите конечную дату"
users_or_groups_label: "для пользователей или групп"
refresh: "обновить"
users_or_groups_placeholder: "Введите никнейм здесь."
build_lists: build_lists:
header: "Сборочные листы" header: "Сборочные листы"
build_started_title: "Cобирается" build_started_title: "Cобирается"

View File

@ -233,6 +233,7 @@ Rosa::Application.routes.draw do
get :autocomplete_extra_build_list get :autocomplete_extra_build_list
get :autocomplete_extra_mass_build get :autocomplete_extra_mass_build
get :autocomplete_extra_repositories get :autocomplete_extra_repositories
get :autocomplete_user_or_group
end end
end end