Commit 075fa370 authored by Tim Zallmann's avatar Tim Zallmann

Contribution Analytics Promotion

parent d2cd261f
class Groups::AnalyticsController < Groups::ApplicationController class Groups::AnalyticsController < Groups::ApplicationController
before_action :group before_action :group
before_action :check_contribution_analytics_available!
layout 'group' layout 'group'
......
- page_title "Contribution Analytics" - page_title "Contribution Analytics"
- header_title group_title(@group, "Contribution Analytics", group_analytics_path(@group)) - header_title group_title(@group, "Contribution Analytics", group_analytics_path(@group))
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('graphs')
.sub-header-block - if @group.feature_available?(:contribution_analytics)
.pull-right - content_for :page_specific_javascripts do
.dropdown.inline = page_specific_javascript_bundle_tag('common_d3')
%button.dropdown-toggle.btn{ type: 'button', 'data-toggle' => 'dropdown' } = page_specific_javascript_bundle_tag('graphs')
= icon('calendar-o')
%b.caret .sub-header-block
%ul.dropdown-menu.dropdown-menu-align-right .pull-right
.dropdown.inline
%button.dropdown-toggle.btn{ type: 'button', 'data-toggle' => 'dropdown' }
= icon('calendar-o')
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
%li
= link_to group_analytics_path(@group, start_date: Date.today - 1.week) do
Last week
%li
= link_to group_analytics_path(@group, start_date: Date.today - 1.month) do
Last month
%li
= link_to group_analytics_path(@group, start_date: Date.today - 3.months) do
Last 3 months
.oneline
Contribution analytics for issues, merge requests and push events since #{@start_date}
%h3 Push
.row
.col-md-4
%ul
%li %li
= link_to group_analytics_path(@group, start_date: Date.today - 1.week) do = @events.code_push.count
Last week times
%li %li
= link_to group_analytics_path(@group, start_date: Date.today - 1.month) do more than
Last month = @events.code_push.map(&:commits_count).sum
commits
%li %li
= link_to group_analytics_path(@group, start_date: Date.today - 3.months) do by
Last 3 months = pluralize @events.code_push.pluck(:author_id).uniq.count, 'person'
.oneline
Contribution analytics 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 .col-md-8
%div %div
%p.light Push events per group member %p.light Push events per group member
%canvas#push{ height: 250 } %canvas#push{ height: 250 }
%h3 Merge Requests %h3 Merge Requests
.row .row
.col-md-4 .col-md-4
%ul %ul
%li %li
= @events.merge_requests.created.count = @events.merge_requests.created.count
created created
%li %li
= @events.merge_requests.merged.count = @events.merge_requests.merged.count
accepted accepted
.col-md-8 .col-md-8
%div %div
%p.light Merge requests created per group member %p.light Merge requests created per group member
%canvas#merge_requests_created{ height: 250 } %canvas#merge_requests_created{ height: 250 }
%h3 Issues %h3 Issues
.row .row
.col-md-4 .col-md-4
%ul %ul
%li %li
= @events.issues.created.count = @events.issues.created.count
created created
%li %li
= @events.issues.closed.pluck(:target_id).uniq.count = @events.issues.closed.pluck(:target_id).uniq.count
closed closed
.col-md-8 .col-md-8
%div %div
%p.light Issues closed per group member %p.light Issues closed per group member
%canvas#issues_closed{ height: 250 } %canvas#issues_closed{ height: 250 }
.gray-content-block .gray-content-block
.oneline .oneline
Contributions per group member Contributions per group member
.table-holder .table-holder
%table.table.sortable-table#event-stats %table.table.sortable-table#event-stats
%thead %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_with_index do |user, index|
%tr %tr
%td %th.sortable
%strong Name
= link_to user.name, user = icon('sort')
%td= @stats[:push][index] %th.sortable
%td= @stats[:issues_created][index] Pushed
%td= @stats[:issues_closed][index] = icon('sort')
%td= @stats[:merge_requests_created][index] %th.sortable
%td= @stats[:merge_requests_merged][index] Opened issues
%td= @stats[:total_events][index] = 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_with_index do |user, index|
%tr
%td
%strong
= link_to user.name, user
%td= @stats[:push][index]
%td= @stats[:issues_created][index]
%td= @stats[:issues_closed][index]
%td= @stats[:merge_requests_created][index]
%td= @stats[:merge_requests_merged][index]
%td= @stats[:total_events][index]
%script#js-analytics-data{ type: "application/json" } %script#js-analytics-data{ type: "application/json" }
- data = {} - data = {}
- data[:labels] = @users.map(&:name) - data[:labels] = @users.map(&:name)
- [:push, :issues_closed, :merge_requests_created].each do |scope| - [:push, :issues_closed, :merge_requests_created].each do |scope|
- data[scope] = {} - data[scope] = {}
- data[scope][:data] = @stats[scope] - data[scope][:data] = @stats[scope]
= data.to_json.html_safe = data.to_json.html_safe
- else
= render 'shared/promotions/promote_contribution_analytics'
...@@ -24,11 +24,10 @@ ...@@ -24,11 +24,10 @@
= link_to group_group_members_path(@group), title: 'Members' do = link_to group_group_members_path(@group), title: 'Members' do
%span %span
Members Members
- if @group.feature_available?(:contribution_analytics) = nav_link(path: 'analytics#show') do
= nav_link(path: 'analytics#show') do = link_to group_analytics_path(@group), title: 'Contribution Analytics', data: {placement: 'right'} do
= link_to group_analytics_path(@group), title: 'Contribution Analytics', data: {placement: 'right'} do %span
%span Contribution Analytics
Contribution Analytics
- if current_user && can?(current_user, :admin_group, @group) - if current_user && can?(current_user, :admin_group, @group)
= nav_link(path: %w[groups#projects groups#edit ldap_group_links#index hooks#index audit_events#index pipeline_quota#index]) do = nav_link(path: %w[groups#projects groups#edit ldap_group_links#index hooks#index audit_events#index pipeline_quota#index]) do
= link_to edit_group_path(@group), title: 'Settings' do = link_to edit_group_path(@group), title: 'Settings' do
......
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82">
<g fill="none" fill-rule="evenodd">
<path fill="#F9F9F9" d="M2.11986346,42 C2.04046544,42.9895269 2,43.9900378 2,45 C2,65.4345357 18.5654643,82 39,82 C59.4345357,82 76,65.4345357 76,45 C76,43.9900378 75.9595346,42.9895269 75.8801365,42 C74.3530766,61.0315425 58.4245736,76 39,76 C19.5754264,76 3.64692341,61.0315425 2.11986346,42 Z"/>
<path fill="#EEEEEE" fill-rule="nonzero" d="M39,78 C17.4608948,78 0,60.5391052 0,39 C0,17.4608948 17.4608948,0 39,0 C60.5391052,0 78,17.4608948 78,39 C78,60.5391052 60.5391052,78 39,78 Z M39,74 C58.3299662,74 74,58.3299662 74,39 C74,19.6700338 58.3299662,4 39,4 C19.6700338,4 4,19.6700338 4,39 C4,58.3299662 19.6700338,74 39,74 Z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M39.670936,22.3541589 C38.0983891,22.716355 36.7037657,23.1741464 35.4859588,23.7326005 C34.4819249,24.193024 34.0412416,25.3802012 34.501665,26.3842351 C34.9620885,27.388269 36.1492657,27.8289523 37.1532996,27.3685289 C38.1094554,26.9300611 39.2483006,26.55623 40.5687283,26.252103 C41.6451158,26.0041845 42.3167227,24.9306224 42.0688042,23.8542348 C41.8208857,22.7778472 40.7473235,22.1062404 39.670936,22.3541589 Z M29.6758858,30.0170788 C29.4780579,30.7816803 29.3836179,31.5837814 29.3901446,32.4195311 C29.4045873,33.4859725 29.5976087,34.4314808 29.9757846,35.3060759 C30.4141738,36.3199243 31.5914451,36.7864262 32.6052935,36.3480369 C33.6191419,35.9096477 34.0856438,34.7323765 33.6472546,33.718528 C33.4838878,33.3407149 33.3972215,32.9161831 33.3898994,32.3767671 C33.3861622,31.8939624 33.4397509,31.438821 33.5483677,31.019019 C33.8250458,29.9496626 33.1824532,28.8584861 32.1130968,28.5818079 C31.0437405,28.3051298 29.952564,28.9477224 29.6758858,30.0170788 Z M36.6272376,40.4932998 C37.7133168,40.8851469 38.7297008,41.1918271 40.5894013,41.7131118 C41.6529776,42.0112383 42.7568557,41.3907187 43.0549822,40.3271425 C43.3531087,39.2635663 42.7325891,38.1596881 41.6690129,37.8615616 C39.899684,37.3656086 38.9517195,37.0795731 37.9847486,36.7306991 C36.9457351,36.3558328 35.7995591,36.8942304 35.4246928,37.9332439 C35.0498265,38.9722574 35.5882242,40.1184335 36.6272376,40.4932998 Z M46.7875829,43.8511503 C47.8524563,44.422726 48.5019906,45.0252727 48.8111047,45.6925961 C49.2753683,46.6948601 50.4642238,47.1309957 51.4664878,46.6667321 C52.4687518,46.2024686 52.9048873,45.0136131 52.4406238,44.0113491 C51.7210658,42.457949 50.4457724,41.2749108 48.6793167,40.3267577 C47.7060826,39.8043698 46.4936414,40.169853 45.9712535,41.1430871 C45.4488657,42.1163213 45.8143488,43.3287625 46.7875829,43.8511503 Z M48.230047,50.5614784 C47.7707449,51.2398807 47.0579604,51.7552716 45.9583537,52.1623784 C44.9224975,52.5458828 44.3936619,53.696502 44.7771664,54.7323582 C45.1606709,55.7682144 46.3112901,56.29705 47.3471463,55.9135455 C49.185476,55.2329417 50.5810001,54.2238844 51.5423128,52.8039983 C52.1615676,51.8893414 51.9220968,50.6458602 51.0074399,50.0266055 C50.092783,49.4073507 48.8493018,49.6468214 48.230047,50.5614784 Z M39.6938681,53.1746657 C38.5642199,53.2416635 37.289592,53.2865495 35.7764848,53.3153389 C34.6721152,53.3363513 33.7938807,54.2486538 33.8148931,55.3530234 C33.8359056,56.457393 34.748208,57.3356275 35.8525776,57.3146151 C37.4153285,57.2848811 38.7414211,57.2381828 39.9306863,57.1676492 C41.0333182,57.1022536 41.8741644,56.1553803 41.8087689,55.0527483 C41.7433734,53.9501164 40.7965,53.1092701 39.6938681,53.1746657 Z"/>
<path fill="#6B4FBB" fill-rule="nonzero" d="M26,62 C22.1340068,62 19,58.8659932 19,55 C19,51.1340068 22.1340068,48 26,48 C29.8659932,48 33,51.1340068 33,55 C33,58.8659932 29.8659932,62 26,62 Z M26,58 C27.6568542,58 29,56.6568542 29,55 C29,53.3431458 27.6568542,52 26,52 C24.3431458,52 23,53.3431458 23,55 C23,56.6568542 24.3431458,58 26,58 Z M52,30 C48.1340068,30 45,26.8659932 45,23 C45,19.1340068 48.1340068,16 52,16 C55.8659932,16 59,19.1340068 59,23 C59,26.8659932 55.8659932,30 52,30 Z M52,26 C53.6568542,26 55,24.6568542 55,23 C55,21.3431458 53.6568542,20 52,20 C50.3431458,20 49,21.3431458 49,23 C49,24.6568542 50.3431458,26 52,26 Z"/>
</g>
</svg>
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
- if current_application_settings.should_check_namespace_plan? - if current_application_settings.should_check_namespace_plan?
Upgrade your plan to activate Service Desk. Upgrade your plan to activate Service Desk.
- else - else
Track your project with Audit Events Upgrade your plan to activate Audit Events
%p %p
Audit Events is a tool for GitLab Enterprise Edition administrators to be able to track important events such as user access level, target user, and user addition or removal. With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members.
%a{ href: '/help/administration/audit_events.html', target: '_blank' } Read more %a{ href: '/help/administration/audit_events.html', target: '_blank' } Read more
= render 'shared/promotions/promotion_link_project' = render 'shared/promotions/promotion_link_project'
.center.promotion-backdrop
.svg-container
= custom_icon('icon_contribution_analytics')
.user-callout-copy
%h4
- if current_application_settings.should_check_namespace_plan?
Upgrade your plan to activate Contribution analytics.
- else
Track activity with Contribution analytics and GitLab Enterprise Edition.
%p
With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members.
%a{ href: '/user/analytics/contribution_analytics.html', target: '_blank' } Read more
= render 'shared/promotions/promotion_link_project'
...@@ -38,14 +38,6 @@ describe Groups::AnalyticsController do ...@@ -38,14 +38,6 @@ describe Groups::AnalyticsController do
create_push_event(user3, project) create_push_event(user3, project)
end end
it 'returns 404 when feature is not available' do
stub_licensed_features(contribution_analytics: false)
get :show, group_id: group.path
expect(response).to have_http_status(404)
end
it 'sets instance variables properly' do it 'sets instance variables properly' do
get :show, group_id: group.path get :show, group_id: group.path
......
...@@ -6,15 +6,7 @@ describe 'layouts/nav/_group' do ...@@ -6,15 +6,7 @@ describe 'layouts/nav/_group' do
end end
describe 'contribution analytics tab' do describe 'contribution analytics tab' do
it 'is not visible when there is no valid license' do it 'is visible' do
stub_licensed_features(contribution_analytics: false)
render
expect(rendered).not_to have_text 'Contribution Analytics'
end
it 'is not visible when there is no valid license' do
stub_licensed_features(contribution_analytics: true) stub_licensed_features(contribution_analytics: true)
render render
......
...@@ -212,7 +212,7 @@ describe 'Promotions', js: true do ...@@ -212,7 +212,7 @@ describe 'Promotions', js: true do
end end
end end
describe 'for audit events', js: true do describe 'for project audit events', js: true do
let!(:license) { nil } let!(:license) { nil }
before do before do
...@@ -221,8 +221,25 @@ describe 'Promotions', js: true do ...@@ -221,8 +221,25 @@ describe 'Promotions', js: true do
it 'should appear on the page' do it 'should appear on the page' do
visit project_audit_events_path(project) visit project_audit_events_path(project)
expect(find('.issues-export-modal')).to have_content 'Track your project with Audit Events' expect(find('.user-callout-copy')).to have_content 'Track your project with Audit Events'
expect(find('.issues-export-modal')).to have_content 'Audit Events is a tool for GitLab Enterprise Edition administrators to be able to track important events such as user access level, target user, and user addition or removal.' expect(find('.user-callout-copy')).to have_content 'Audit Events is a tool for GitLab Enterprise Edition administrators to be able to track important events such as user access level, target user, and user addition or removal.'
end end
end end
describe 'for group contribution analytics', js: true do
let!(:license) { nil }
before do
sign_in(user)
end
it 'should appear on the page' do
visit group_analytics_path(project)
expect(find('.user-callout-copy')).to have_content 'Track activity with Contribution analytics and GitLab Enterprise Edition.'
expect(find('.user-callout-copy')).to have_content 'Audit Events is a tool for GitLab Enterprise Edition administrators to be able to track important events such as user access level, target user, and user addition or removal.'
end
end
end end
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