Commit c3254358 authored by Valery Sizov's avatar Valery Sizov

Merge remote-tracking branch 'ee_com/master' into ce_upstream

parents ada1ea2a 4b8154af
Please view this file on the master branch, on stable branches it's out of date.
v 8.3.0 (unreleased)
- Merge when build succeeds (Zeger-Jan van de Weg)
- Bump gollum-lib to 4.1.0 (Stan Hu)
- Fix broken group avatar upload under "New group" (Stan Hu)
- Update project repositorize size and commit count during import:repos task (Stan Hu)
......@@ -25,6 +26,7 @@ v 8.3.0 (unreleased)
- Add languages page to graphs
- Block LDAP user when they are no longer found in the LDAP server
- Improve wording on project visibility levels (Zeger-Jan van de Weg)
- Automatically select default clone protocol based on user preferences (Eirik Lygre)
v 8.2.3
- Fix application settings cache not expiring after changes (Stan Hu)
......@@ -32,6 +34,10 @@ v 8.2.3
v 8.2.3
- Webhook payload has an added, modified and removed properties for each commit
- Update documentation for "Guest" permissions
- Properly convert Emoji-only comments into Award Emojis
- Webhook payload has an added, modified and removed properties for each commit
- Fix 500 error when creating a merge request that removes a submodule
v 8.2.2
- Fix 404 in redirection after removing a project (Stan Hu)
......@@ -39,6 +45,7 @@ v 8.2.2
- Fix Error 500 when viewing user's personal projects from admin page (Stan Hu)
- Fix: Raw private snippets access workflow
- Prevent "413 Request entity too large" errors when pushing large files with LFS
- Fix: As an admin, cannot add oneself as a member to a group/project
- Fix invalid links within projects dashboard header
- Make current user the first user in assignee dropdown in issues detail page (Stan Hu)
- Fix: duplicate email notifications on issue comments
......@@ -47,16 +54,7 @@ v 8.2.1
- Forcefully update builds that didn't want to update with state machine
- Fix: saving GitLabCiService as Admin Template
v 8.2.0
v 8.0.1
v 8.1.0 (unreleased)
v 8.2.0 (unreleased)
v 8.3.0 (unreleased)
v 8.2.0
- Improved performance of finding projects and groups in various places
- Improved performance of rendering user profile pages and Atom feeds
- Fix grouping of contributors by email in graph.
- Improved performance of finding projects and groups in various places
- Improved performance of rendering user profile pages and Atom feeds
- Expose build artifacts path as config option
......@@ -100,7 +98,6 @@ v 8.2.0
- Add email notification to former assignee upon unassignment (Adam Lieskovský)
- New design for project graphs page
- Remove deprecated dumped yaml file generated from previous job definitions
- Fix incoming email config defaults
- Show specific runners from projects where user is master or owner
- MR target branch is now visible on a list view when it is different from project's default one
- Improve Continuous Integration graphs page
......@@ -258,7 +255,6 @@ v 8.0.2
- Allow AWS S3 Server-Side Encryption with Amazon S3-Managed Keys for backups (Paul Beattie)
v 8.0.1
- Remove git refs used internally by GitLab from network graph (Stan Hu)
- Improve CI migration procedure and documentation
v 8.0.0
......
v 8.3.0 (unreleased)
- License information can now be retrieved via the API
- Fix bug with negative approvals required
- Add group contribution statistics page
v 8.2.3
- No EE-specific changes
v 8.2.2
- Fix 404 in redirection after removing a project (Stan Hu)
- Ensure cached application settings are refreshed at startup (Stan Hu)
- Fix Error 500 when viewing user's personal projects from admin page (Stan Hu)
- Fix: Raw private snippets access workflow
- Prevent "413 Request entity too large" errors when pushing large files with LFS
- Ensure GitLab fires custom update hooks after commit via UI
v 8.2.1
- Forcefully update builds that didn't want to update with state machine
- Fix: saving GitLabCiService as Admin Template
v 8.2.0
- Invalidate stored jira password if the endpoint URL is changed
......
......@@ -16,6 +16,7 @@
#= require jquery.scrollTo
#= require jquery.blockUI
#= require jquery.turbolinks
#= require jquery.tablesorter
#= require turbolinks
#= require autosave
#= require bootstrap
......
......@@ -7,7 +7,7 @@
table {
&.table {
margin-bottom: $gl-padding;
.dropdown-menu a {
text-decoration: none;
}
......@@ -35,6 +35,10 @@ table {
font-weight: normal;
font-size: 15px;
border-bottom: 1px solid $border-color !important;
&.sortable {
cursor: pointer;
}
}
td {
......
class Groups::StatsController < Groups::ApplicationController
before_action :group
layout 'group'
def show
@users = @group.users
@start_date = params[:start_date] || Date.today - 1.week
@events = Event.contributions.
where("created_at > ?", @start_date).
where(project_id: @group.projects)
@stats = {}
@stats[:merge_requests] = @users.map do |user|
@events.merge_requests.created.where(author_id: user).count
end
@stats[:issues] = @users.map do |user|
@events.issues.closed.where(author_id: user).count
end
@stats[:push] = @users.map do |user|
@events.code_push.where(author_id: user).count
end
end
end
......@@ -50,6 +50,12 @@ class Event < ActiveRecord::Base
scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
scope :with_associations, -> { includes(project: :namespace) }
scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) }
scope :issues, -> { where(target_type: 'Issue') }
scope :merge_requests, -> { where(target_type: 'MergeRequest') }
scope :created, -> { where(action: CREATED) }
scope :closed, -> { where(action: CLOSED) }
scope :merged, -> { where(action: MERGED) }
class << self
def reset_event_cache_for(target)
......
- page_title "Statistics"
- header_title group_title(@group, "Statistics", group_stats_path(@group))
.gray-content-block
.pull-right
.dropdown.inline
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
= icon('calendar-o')
%b.caret
%ul.dropdown-menu
%li
= link_to group_stats_path(@group, start_date: Date.today - 1.week) do
Last week
%li
= link_to group_stats_path(@group, start_date: Date.today - 1.month) do
Last month
%li
= link_to group_stats_path(@group, start_date: Date.today - 3.months) do
Last 3 months
.oneline
Contribution statistics for issues, merge requests and push events since #{@start_date}
%h3 Push
.row
.col-md-4
%ul
%li
= @events.code_push.count
times
%li
more than
= @events.code_push.map(&:commits_count).sum
commits
%li
by
= pluralize @events.code_push.pluck(:author_id).uniq.count, 'person'
.col-md-8
%div
%p.light Push events per group member
%canvas#push{height: 250}
%h3 Merge Requests
.row
.col-md-4
%ul
%li
= @events.merge_requests.created.count
created
%li
= @events.merge_requests.merged.count
accepted
.col-md-8
%div
%p.light Merge requests created per group member
%canvas#merge_requests{height: 250}
%h3 Issues
.row
.col-md-4
%ul
%li
= @events.issues.created.count
created
%li
= @events.issues.closed.pluck(:target_id).uniq.count
closed
.col-md-8
%div
%p.light Issues closed per group member
%canvas#issues{height: 250}
.gray-content-block
.oneline
Contributions per group member
.table-holder
%table.table.sortable-table#event-stats
%thead
%tr
%th.sortable
Name
= icon('sort')
%th.sortable
Pushed
= icon('sort')
%th.sortable
Opened issues
= icon('sort')
%th.sortable
Closed issues
= icon('sort')
%th.sortable
Opened MR
= icon('sort')
%th.sortable
Accepted MR
= icon('sort')
%th.sortable
Total Contributions
= icon('sort')
%tbody
- @users.each do |user|
%tr
%td
%strong
= link_to user.name, user
%td= @events.code_push.where(author_id: user).count
%td= @events.issues.created.where(author_id: user).count
%td= @events.issues.closed.where(author_id: user).count
%td= @events.merge_requests.created.where(author_id: user).count
%td= @events.merge_requests.merged.where(author_id: user).count
%td= @events.where(author_id: user).count
- [:push, :issues, :merge_requests].each do |scope|
:javascript
var data = {
labels : #{@users.map(&:name).to_json},
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,1)",
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
data : #{@stats[scope].to_json}
}
]
}
var ctx = $("##{scope}").get(0).getContext("2d");
new Chart(ctx).Bar(data,{"scaleOverlay": true, responsive: true, maintainAspectRatio: false});
:javascript
$("#event-stats").tablesorter();
......@@ -38,6 +38,11 @@
= icon('users fw')
%span
Members
= nav_link(controller: [:stats]) do
= link_to group_stats_path(@group), title: 'Stats', data: {placement: 'right'} do
= icon('table fw')
%span
Statistics
- if can?(current_user, :admin_group, @group)
= nav_link(html_options: { class: "separate-item" }) do
= link_to edit_group_path(@group), title: 'Settings' do
......
......@@ -386,6 +386,7 @@ Rails.application.routes.draw do
end
scope module: :groups do
resource :stats, only: [:show]
resource :ldap, only: [] do
member do
put :reset_access
......
Feature: Group Statistics
Background:
Given I sign in as "John Doe"
And "John Doe" is owner of group "Owned"
Scenario: I should see group "Owned" statistics page
When I visit group "Owned" page
And I click on group statistics
Then I should see group statistics page
class Spinach::Features::GroupStatistics < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedGroup
include SharedUser
step 'I click on group statistics' do
click_link 'Statistics'
end
step 'I should see group statistics page' do
expect(page).to have_content "Contribution statistics for issues, merge requests and push"
end
end
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment