git_stats 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/.gitignore +21 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +13 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +44 -0
  7. data/Rakefile +1 -0
  8. data/bin/git_stats +11 -0
  9. data/config/locales/en.yml +56 -0
  10. data/config/locales/pl.yml +56 -0
  11. data/config/locales/pl_default.yml +224 -0
  12. data/git_stats.gemspec +27 -0
  13. data/lib/git_stats.rb +15 -0
  14. data/lib/git_stats/base.rb +30 -0
  15. data/lib/git_stats/by_field_finder.rb +7 -0
  16. data/lib/git_stats/cli.rb +17 -0
  17. data/lib/git_stats/core_extensions/hash.rb +9 -0
  18. data/lib/git_stats/core_extensions/string.rb +6 -0
  19. data/lib/git_stats/core_extensions/symbol.rb +6 -0
  20. data/lib/git_stats/generator.rb +32 -0
  21. data/lib/git_stats/git_data/activity.rb +78 -0
  22. data/lib/git_stats/git_data/author.rb +67 -0
  23. data/lib/git_stats/git_data/blob.rb +38 -0
  24. data/lib/git_stats/git_data/command_parser.rb +33 -0
  25. data/lib/git_stats/git_data/command_runner.rb +10 -0
  26. data/lib/git_stats/git_data/commit.rb +63 -0
  27. data/lib/git_stats/git_data/repo.rb +137 -0
  28. data/lib/git_stats/git_data/short_stat.rb +33 -0
  29. data/lib/git_stats/hash_initializable.rb +7 -0
  30. data/lib/git_stats/i18n.rb +2 -0
  31. data/lib/git_stats/stats_view/charts/activity_charts.rb +70 -0
  32. data/lib/git_stats/stats_view/charts/authors_charts.rb +35 -0
  33. data/lib/git_stats/stats_view/charts/chart.rb +119 -0
  34. data/lib/git_stats/stats_view/charts/charts.rb +35 -0
  35. data/lib/git_stats/stats_view/charts/repo_charts.rb +53 -0
  36. data/lib/git_stats/stats_view/template.rb +20 -0
  37. data/lib/git_stats/stats_view/view.rb +72 -0
  38. data/lib/git_stats/stats_view/view_data.rb +31 -0
  39. data/lib/git_stats/version.rb +4 -0
  40. data/spec/by_field_finder_spec.rb +25 -0
  41. data/spec/factories.rb +25 -0
  42. data/spec/git_data/activity_spec.rb +38 -0
  43. data/spec/git_data/author_spec.rb +25 -0
  44. data/spec/git_data/blob_spec.rb +25 -0
  45. data/spec/git_data/cli_spec.rb +20 -0
  46. data/spec/git_data/command_observer_spec.rb +35 -0
  47. data/spec/git_data/commit_range_spec.rb +47 -0
  48. data/spec/git_data/commit_spec.rb +48 -0
  49. data/spec/git_data/generator_spec.rb +46 -0
  50. data/spec/git_data/repo_spec.rb +46 -0
  51. data/spec/git_data/short_stat_spec.rb +28 -0
  52. data/spec/hash_extension_spec.rb +26 -0
  53. data/spec/integration/activity_spec.rb +33 -0
  54. data/spec/integration/author_spec.rb +67 -0
  55. data/spec/integration/file_spec.rb +31 -0
  56. data/spec/integration/repo_spec.rb +68 -0
  57. data/spec/integration/shared.rb +37 -0
  58. data/spec/spec_helper.rb +13 -0
  59. data/templates/activity/_activity.haml +101 -0
  60. data/templates/activity/by_date.haml +1 -0
  61. data/templates/activity/day_of_week.haml +1 -0
  62. data/templates/activity/hour_of_day.haml +1 -0
  63. data/templates/activity/hour_of_week.haml +1 -0
  64. data/templates/activity/month_of_year.haml +1 -0
  65. data/templates/activity/year.haml +1 -0
  66. data/templates/activity/year_month.haml +1 -0
  67. data/templates/assets/bootstrap/css/bootstrap-responsive.css +1058 -0
  68. data/templates/assets/bootstrap/css/bootstrap-responsive.min.css +9 -0
  69. data/templates/assets/bootstrap/css/bootstrap.css +5774 -0
  70. data/templates/assets/bootstrap/css/bootstrap.min.css +9 -0
  71. data/templates/assets/bootstrap/img/glyphicons-halflings-white.png +0 -0
  72. data/templates/assets/bootstrap/img/glyphicons-halflings.png +0 -0
  73. data/templates/assets/bootstrap/js/bootstrap.js +2027 -0
  74. data/templates/assets/bootstrap/js/bootstrap.min.js +6 -0
  75. data/templates/assets/highstock.js +305 -0
  76. data/templates/assets/jquery.min.js +2 -0
  77. data/templates/authors/_authors.haml +66 -0
  78. data/templates/authors/best_authors.haml +1 -0
  79. data/templates/authors/changed_lines_by_author_by_date.haml +1 -0
  80. data/templates/authors/commits_sum_by_author_by_date.haml +1 -0
  81. data/templates/authors/deletions_by_author_by_date.haml +1 -0
  82. data/templates/authors/insertions_by_author_by_date.haml +1 -0
  83. data/templates/files/_files.haml +15 -0
  84. data/templates/files/by_date.haml +1 -0
  85. data/templates/files/by_extension.haml +1 -0
  86. data/templates/general.haml +28 -0
  87. data/templates/layout.haml +29 -0
  88. data/templates/lines/_lines.haml +15 -0
  89. data/templates/lines/by_date.haml +1 -0
  90. data/templates/lines/by_extension.haml +1 -0
  91. data/templates/static/index.html +5 -0
  92. metadata +268 -0
@@ -0,0 +1,46 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe GitStats::Generator do
5
+ let(:repo_path) { 'repo_path' }
6
+ let(:out_path) { 'out_path' }
7
+ let(:generator) { GitStats::Generator.new(repo_path, out_path) }
8
+
9
+ before { Dir.stub!(:exists? => true) }
10
+
11
+ it 'should raise exception if given repo path is not a git repository' do
12
+ Dir.should_receive(:exists?).with("#{repo_path}/.git").and_return(false)
13
+ expect { generator }.to raise_error(ArgumentError)
14
+ end
15
+
16
+ it "should raise exception if given out directory doesn't exist" do
17
+ Dir.should_receive(:exists?).with(out_path).and_return(false)
18
+ expect { generator }.to raise_error(ArgumentError)
19
+ end
20
+
21
+ it 'should pass command observer to repo' do
22
+ repo = double('repo')
23
+ GitStats::GitData::Repo.should_receive(:new).with(path: repo_path).and_return(repo)
24
+
25
+ generator = GitStats::Generator.new(repo_path, out_path)
26
+
27
+ observer = double('observer')
28
+ repo.should_receive(:add_command_observer).with(observer)
29
+
30
+ generator.add_command_observer observer
31
+ end
32
+
33
+ it 'should render all templates with view data for this repo' do
34
+ repo = double('repo')
35
+ GitStats::GitData::Repo.should_receive(:new).with(path: repo_path).and_return(repo)
36
+
37
+ view_data = double('view_data')
38
+ GitStats::StatsView::ViewData.should_receive(:new).with(repo).and_return(view_data)
39
+
40
+ view = double('view')
41
+ GitStats::StatsView::View.should_receive(:new).with(view_data, out_path).and_return(view)
42
+ view.should_receive(:render_all)
43
+
44
+ generator.render_all
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe GitStats::GitData::Repo do
5
+ let(:repo) { build(:repo) }
6
+
7
+ describe 'git output parsing' do
8
+ context 'invoking authors command' do
9
+ before do
10
+ repo.should_receive(:run).with('git shortlog -se HEAD').and_return(" 156 John Doe <john.doe@gmail.com>
11
+ 53 Joe Doe <joe.doe@gmail.com>
12
+ ")
13
+ end
14
+ it 'should parse git shortlog output to authors hash' do
15
+ repo.authors.should == [
16
+ build(:author, repo: repo, name: "John Doe", email: "john.doe@gmail.com"),
17
+ build(:author, repo: repo, name: "Joe Doe", email: "joe.doe@gmail.com")
18
+ ]
19
+ end
20
+
21
+ it 'should parse git revlist output to date sorted commits array' do
22
+ repo.should_receive(:run).with("git rev-list --pretty=format:'%h|%at|%ai|%aE' HEAD | grep -v commit").and_return(
23
+ "e4412c3|1348603824|2012-09-25 22:10:24 +0200|john.doe@gmail.com
24
+ ce34874|1347482927|2012-09-12 22:48:47 +0200|joe.doe@gmail.com
25
+ 5eab339|1345835073|2012-08-24 21:04:33 +0200|john.doe@gmail.com
26
+ ")
27
+
28
+ repo.commits.should == [
29
+ GitStats::GitData::Commit.new(
30
+ repo: repo, sha: "5eab339", stamp: "1345835073", date: DateTime.parse("2012-08-24 21:04:33 +0200"),
31
+ author: repo.authors.by_email("john.doe@gmail.com")),
32
+ GitStats::GitData::Commit.new(
33
+ repo: repo, sha: "ce34874", stamp: "1347482927", date: DateTime.parse("2012-09-12 22:48:47 +0200"),
34
+ author: repo.authors.by_email("joe.doe@gmail.com")),
35
+ GitStats::GitData::Commit.new(
36
+ repo: repo, sha: "e4412c3", stamp: "1348603824", date: DateTime.parse("2012-09-25 22:10:24 +0200"),
37
+ author: repo.authors.by_email("john.doe@gmail.com"))
38
+ ]
39
+ end
40
+ end
41
+ it 'should parse git rev-parse command to project version' do
42
+ repo.should_receive(:run).with('git rev-parse --short HEAD').and_return('xyz')
43
+ repo.project_version.should == 'xyz'
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe GitStats::GitData::ShortStat do
5
+ let(:commit) { build(:commit, sha: 'abc') }
6
+
7
+ describe 'git output parsing' do
8
+ context 'parsing git show output' do
9
+ [
10
+ {content: '2 files changed, 17 insertions(+), 3 deletions(-)', expect: [2, 17, 3]},
11
+ {content: '1 file changed, 1 insertion(+), 1 deletion(-)', expect: [1, 1, 1]},
12
+ {content: '2 files changed, 3 deletions(-)', expect: [2, 0, 3]},
13
+ {content: '2 files changed, 5 insertions(+)', expect: [2, 5, 0]},
14
+ {content: '', expect: [0, 0, 0]},
15
+ ].each do |test|
16
+ it "#{test[:content]} parsing" do
17
+ commit.repo.should_receive(:run).with("git show --shortstat --oneline abc").and_return("abc some commit\n#{test[:content]}")
18
+
19
+
20
+ commit.short_stat.should be_a(GitStats::GitData::ShortStat)
21
+ commit.short_stat.files_changed.should == test[:expect][0]
22
+ commit.short_stat.insertions.should == test[:expect][1]
23
+ commit.short_stat.deletions.should == test[:expect][2]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe Hash do
5
+ context 'to_key_indexed_array' do
6
+ it 'should convert hash to array using keys as indexes' do
7
+ hash = {1 => 'x', 2 => 1, 5 => 'a'}
8
+ hash.to_key_indexed_array.should == [nil, 'x', 1, nil, nil, 'a']
9
+ end
10
+
11
+ it 'should throw exception if not all of the keys are numbers' do
12
+ hash = {1 => 'x', 'b' => 2}
13
+ expect { hash.to_key_indexed_array }.to raise_error(ArgumentError)
14
+ end
15
+
16
+ context 'should take optional min_size and default parameters' do
17
+ let(:hash) { {1 => 'x', 2 => 1, 5 => 'a'} }
18
+ it 'should fill array with defaults up to min_size' do
19
+ hash.to_key_indexed_array(min_size: 8, default: 0).should == [0, 'x', 1, 0, 0, 'a', 0, 0]
20
+ end
21
+ it 'should use default value where key is not in hash' do
22
+ hash.to_key_indexed_array(min_size: 2, default: 0).should == [0, 'x', 1, 0, 0, 'a']
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'integration/shared'
3
+
4
+ describe GitStats::GitData::Activity do
5
+ include_context "shared"
6
+
7
+ let(:activity) { repo.activity }
8
+
9
+ it 'should count commits by hour' do
10
+ activity.by_hour.should == {10 => 4, 12 => 3, 13 => 1, 15 => 1, 17 => 1}
11
+ end
12
+
13
+ it 'should count commits by day of week' do
14
+ activity.by_wday.should == {0 => 3, 3 => 1, 5 => 5, 6 => 1}
15
+ end
16
+
17
+ it 'should count commits by day of week and hour' do
18
+ activity.by_wday_hour.should == {0 => {12 => 2, 13 => 1}, 3 => {15 => 1}, 5 => {10 => 4, 17 => 1}, 6 => {12 => 1}}
19
+ end
20
+
21
+ it 'should count commits by month' do
22
+ activity.by_month.should == {10 => 10}
23
+ end
24
+
25
+ it 'should count commits by year' do
26
+ activity.by_year.should == {2012 => 10}
27
+ end
28
+
29
+ it 'should count commits by year and month' do
30
+ activity.by_year_month.should == {2012 => {10 => 10}}
31
+ end
32
+
33
+ end
@@ -0,0 +1,67 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'integration/shared'
3
+
4
+ describe GitStats::GitData::Activity do
5
+ include_context "shared"
6
+
7
+ let(:tg) { repo.authors.by_email('tomasz.gieniusz@gmail.com') }
8
+ let(:jd) { repo.authors.by_email('john.doe@gmail.com') }
9
+
10
+ it 'should filter commits to author' do
11
+ tg.commits.map(&:sha).should =~ %w(b3b4f81 d60b5ec ab47ef8 2c11f5e c87ecf9 b621a5d 4e7d0e9 872955c)
12
+ jd.commits.map(&:sha).should =~ %w(fd66657 81e8bef)
13
+ end
14
+
15
+ context 'activity' do
16
+ it 'should count commits by hour' do
17
+ tg.activity.by_hour.should == {10 => 4, 12 => 2, 13 => 1, 17 => 1}
18
+ jd.activity.by_hour.should == {12 => 1, 15 => 1}
19
+ end
20
+
21
+ it 'should count commits by day of week' do
22
+ tg.activity.by_wday.should == {0 => 2, 5 => 5, 6 => 1}
23
+ jd.activity.by_wday.should == {0 => 1, 3 => 1}
24
+ end
25
+
26
+ it 'should count commits by day of week and hour' do
27
+ tg.activity.by_wday_hour.should == {0 => {12 => 1, 13 => 1}, 5 => {10 => 4, 17 => 1}, 6 => {12 => 1}}
28
+ jd.activity.by_wday_hour.should == {0 => {12 => 1}, 3 => {15 => 1}}
29
+ end
30
+
31
+ it 'should count commits by month' do
32
+ tg.activity.by_month.should == {10 => 8}
33
+ jd.activity.by_month.should == {10 => 2}
34
+ end
35
+
36
+ it 'should count commits by year' do
37
+ tg.activity.by_year.should == {2012 => 8}
38
+ jd.activity.by_year.should == {2012 => 2}
39
+ end
40
+
41
+ it 'should count commits by year and month' do
42
+ tg.activity.by_year_month.should == {2012 => {10 => 8}}
43
+ jd.activity.by_year_month.should == {2012 => {10 => 2}}
44
+ end
45
+
46
+ it 'should count commits_sum_by_date' do
47
+ tg.commits_sum_by_date.map { |d, s| d }.should == tg_commit_dates
48
+ tg.commits_sum_by_date.map { |d, s| s }.should == [1, 2, 3, 4, 5, 6, 7, 8]
49
+ jd.commits_sum_by_date.map { |d, s| d }.should == jd_commit_dates
50
+ jd.commits_sum_by_date.map { |d, s| s }.should == [1, 2]
51
+ end
52
+
53
+ it 'should count insertions_by_date' do
54
+ tg.insertions_by_date.map { |d, s| d }.should == tg_commit_dates
55
+ tg.insertions_by_date.map { |d, s| s }.should == [4, 9, 14, 15, 20, 1020, 1021, 1021]
56
+ jd.insertions_by_date.map { |d, s| d }.should == jd_commit_dates
57
+ jd.insertions_by_date.map { |d, s| s }.should == [3, 103]
58
+ end
59
+
60
+ it 'should count deletions_by_date' do
61
+ tg.deletions_by_date.map { |d, s| d }.should == tg_commit_dates
62
+ tg.deletions_by_date.map { |d, s| s }.should == [0, 0, 4, 4, 9, 9, 10, 10]
63
+ jd.deletions_by_date.map { |d, s| d }.should == jd_commit_dates
64
+ jd.deletions_by_date.map { |d, s| s }.should == [0, 0]
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'integration/shared'
3
+
4
+ describe GitStats::GitData::Repo do
5
+ include_context "shared"
6
+
7
+ it 'should gather all files in repo' do
8
+ repo.files.map(&:filename).should =~ %w(long_second.haml long.txt second.txt test2.rb test.rb test.txt)
9
+ end
10
+
11
+ it 'should retrieve correct file content for old file' do
12
+ repo.commits.by_sha('c87ecf9').files.by_filename('test.txt').content.should == "bb
13
+
14
+
15
+
16
+ test
17
+ "
18
+ end
19
+
20
+ it 'should retrieve correct file content for the newest file' do
21
+ file = repo.files.by_filename('test.txt')
22
+ file.content.should == "bb
23
+
24
+ testtest
25
+
26
+ test
27
+ "
28
+ end
29
+
30
+
31
+ end
@@ -0,0 +1,68 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'integration/shared'
3
+
4
+ describe GitStats::GitData::Repo do
5
+ include_context "shared"
6
+
7
+ it 'should gather all authors' do
8
+ repo.authors.should =~ expected_authors
9
+ end
10
+
11
+ it 'should calculate correct commits period' do
12
+ repo.commits_period.should == [DateTime.parse('2012-10-19 10:44:34 +0200'), DateTime.parse('2012-10-26 17:05:25 +0200')]
13
+ end
14
+
15
+ it 'should gather all commits sorted by date' do
16
+ repo.commits.map(&:sha).should =~ %w(b3b4f81 d60b5ec ab47ef8 2c11f5e c87ecf9 b621a5d fd66657 81e8bef 4e7d0e9 872955c)
17
+ end
18
+
19
+ it 'should return project name from dir' do
20
+ repo.project_name.should == 'test_repo'
21
+ end
22
+
23
+ it 'should return project version as last commit hash' do
24
+ repo.project_version.should == '872955c'
25
+ end
26
+
27
+ it 'should count files in repo' do
28
+ repo.files_count.should == 6
29
+ end
30
+
31
+ it 'should count files by date' do
32
+ repo.files_count_by_date.keys.should == commit_dates
33
+ repo.files_count_by_date.values.should == [1, 2, 2, 3, 3, 4, 5, 5, 6, 6]
34
+ end
35
+
36
+ it 'should count lines by date' do
37
+ repo.lines_count_by_date.keys.should == commit_dates
38
+ repo.files_count_by_date.values.should == [1, 2, 2, 3, 3, 4, 5, 5, 6, 6]
39
+ end
40
+
41
+ it 'should count all lines in repo' do
42
+ repo.lines_count.should == 1114
43
+ end
44
+
45
+ it 'should count files by extension in repo' do
46
+ repo.files_by_extension_count.should == {'.haml' => 1, '.txt' => 3, '.rb' => 2}
47
+ end
48
+
49
+ it 'should count lines by extension in repo' do
50
+ repo.lines_by_extension.should == {'.haml' => 100, '.txt' => 1008, '.rb' => 6}
51
+ end
52
+
53
+ it 'should count commits_count_by_author' do
54
+ repo.commits_count_by_author.keys.should == expected_authors
55
+ repo.commits_count_by_author.values.should == [8, 2]
56
+ end
57
+
58
+ it 'should count lines_added_by_author' do
59
+ repo.insertions_by_author.keys.should == expected_authors
60
+ repo.insertions_by_author.values.should == [1021, 103]
61
+ end
62
+
63
+ it 'should count lines_deleted_by_author' do
64
+ repo.deletions_by_author.keys.should == expected_authors
65
+ repo.deletions_by_author.values.should == [10, 0]
66
+ end
67
+
68
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ shared_context "shared" do
5
+ let(:repo) { build(:test_repo, last_commit_sha: '872955c') }
6
+ let(:commit_dates) { [
7
+ DateTime.parse('2012-10-19 10:44:34 +0200'),
8
+ DateTime.parse('2012-10-19 10:46:10 +0200'),
9
+ DateTime.parse('2012-10-19 10:46:56 +0200'),
10
+ DateTime.parse('2012-10-19 10:47:35 +0200'),
11
+ DateTime.parse('2012-10-20 12:49:02 +0200'),
12
+ DateTime.parse('2012-10-21 12:49:02 +0200'),
13
+ DateTime.parse('2012-10-21 12:54:02 +0200'),
14
+ DateTime.parse('2012-10-21 13:20:00 +0200'),
15
+ DateTime.parse('2012-10-24 15:49:02 +0200'),
16
+ DateTime.parse('2012-10-26 17:05:25 +0200'),
17
+ ] }
18
+ let(:tg_commit_dates) { [
19
+ DateTime.parse('2012-10-19 10:44:34 +0200'),
20
+ DateTime.parse('2012-10-19 10:46:10 +0200'),
21
+ DateTime.parse('2012-10-19 10:46:56 +0200'),
22
+ DateTime.parse('2012-10-19 10:47:35 +0200'),
23
+ DateTime.parse('2012-10-20 12:49:02 +0200'),
24
+ DateTime.parse('2012-10-21 12:49:02 +0200'),
25
+ DateTime.parse('2012-10-21 13:20:00 +0200'),
26
+ DateTime.parse('2012-10-26 17:05:25 +0200'),
27
+ ] }
28
+ let(:jd_commit_dates) { [
29
+ DateTime.parse('2012-10-21 12:54:02 +0200'),
30
+ DateTime.parse('2012-10-24 15:49:02 +0200'),
31
+ ] }
32
+
33
+ let(:expected_authors) { [
34
+ build(:author, repo: repo, name: "Tomasz Gieniusz", email: "tomasz.gieniusz@gmail.com"),
35
+ build(:author, repo: repo, name: "John Doe", email: "john.doe@gmail.com"),
36
+ ] }
37
+ end
@@ -0,0 +1,13 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+
5
+ require 'git_stats'
6
+
7
+ require 'factory_girl'
8
+ FactoryGirl.find_definitions
9
+
10
+ RSpec.configure do |config|
11
+ config.include FactoryGirl::Syntax::Methods
12
+ end
13
+
@@ -0,0 +1,101 @@
1
+ .tabbable.tabs-left
2
+ %ul.nav.nav-tabs
3
+ %li{class: page == :activity_by_date ? "active" : "" }
4
+ %a{href: "by_date.html"}= :activity_by_date.t
5
+ %li{class: page == :hour_of_day ? "active" : "" }
6
+ %a{href: "hour_of_day.html"}= :hour_of_day.t
7
+ %li{class: page == :day_of_week ? "active" : "" }
8
+ %a{href: "day_of_week.html"}= :day_of_week.t
9
+ %li{class: page == :hour_of_week ? "active" : "" }
10
+ %a{href: "hour_of_week.html"}= :hour_of_week.t
11
+ %li{class: page == :month_of_year ? "active" : "" }
12
+ %a{href: "month_of_year.html"}= :month_of_year.t
13
+ %li{class: page == :year ? "active" : "" }
14
+ %a{href: "year.html"}= :year.t
15
+ %li{class: page == :year_month ? "active" : "" }
16
+ %a{href: "year_month.html"}= :year_month.t
17
+
18
+ .tab-content
19
+ .tab-pane.active
20
+ .page-header.pagination-centered
21
+ %h1= page.t
22
+ %h3= "#{author.respond_to?(:name) ? author.name : ""} #{author.respond_to?(:email) ? "&lt;#{author.email}&gt;" : ""}"
23
+ - if page == :activity_by_date
24
+ = high_stock("charts.activity_by_date", charts.activity_by_date(author))
25
+
26
+ - elsif page == :hour_of_day
27
+ %table{:class => "table table-bordered table-condensed"}
28
+ %tr
29
+ %th= :hour.t
30
+ - (0..23).each do |h|
31
+ %th= h
32
+ %tr
33
+ %th= :commits.t
34
+ - author.activity.by_hour_array.each do |commits|
35
+ %td= commits
36
+ %tr
37
+ %th= :percentage.t
38
+ - author.activity.by_hour_array.each do |commits|
39
+ %td= (commits * 100.0 / author.activity.by_hour_array.sum).round(1)
40
+ = high_chart("charts.activity_by_hour", charts.activity_by_hour(author))
41
+
42
+ - elsif page == :day_of_week
43
+ %table{:class => "table table-bordered table-condensed"}
44
+ %tr
45
+ %th= :day.t
46
+ - I18n.t('date.abbr_day_names').each do |d|
47
+ %th= d
48
+ %tr
49
+ %th= :commits.t
50
+ - author.activity.by_wday_array.each do |commits|
51
+ %td= commits
52
+ %tr
53
+ %th= :percentage.t
54
+ - author.activity.by_wday_array.each do |commits|
55
+ %td= (commits * 100.0 / author.activity.by_wday_array.sum).round(1)
56
+ = high_chart("charts.activity_by_wday", charts.activity_by_wday(author))
57
+
58
+ - elsif page == :hour_of_week
59
+ %table{:class => "table table-bordered table-condensed"}
60
+ %tr
61
+ %th
62
+ - (0..23).each do |h|
63
+ %th= h
64
+ - max = author.activity.by_wday_hour.values.map {|h| h.values.empty? ? 0 : h.values.max }.max
65
+ - (0..6).each do |day|
66
+ %tr
67
+ %th= I18n.t('date.abbr_day_names')[day]
68
+ - (0..23).each do |hour|
69
+ - color = max ? "%02x" % (255 - author.activity.by_wday_hour[day][hour] * 100 / max) : "FF"
70
+ %td{style: "background-color: ##{color}#{color}#{color};"}= author.activity.by_wday_hour[day][hour]
71
+
72
+ - elsif page == :month_of_year
73
+ %table{:class => "table table-bordered table-condensed"}
74
+ %tr
75
+ %th= :month.t
76
+ - I18n.t('date.abbr_month_names')[1..-1].each do |m|
77
+ %th= m
78
+ %tr
79
+ %th= :commits.t
80
+ - author.activity.by_month_array.each do |commits|
81
+ %td= commits
82
+ %tr
83
+ %th= :percentage.t
84
+ - author.activity.by_month_array.each do |commits|
85
+ %td= (commits * 100.0 / author.activity.by_month_array.sum).round(1)
86
+ = high_chart("charts.activity_by_month", charts.activity_by_month(author))
87
+
88
+ - elsif page == :year
89
+ = high_chart("charts.activity_by_year", charts.activity_by_year(author))
90
+
91
+ - elsif page == :year_month
92
+ %table{:class => "table table-bordered table-condensed"}
93
+ %tr
94
+ %th
95
+ - I18n.t('date.abbr_month_names')[1..-1].each do |h|
96
+ %th= h
97
+ - author.activity.by_year_month.each do |year, months|
98
+ %tr
99
+ %th= year
100
+ - (1..12).each do |month|
101
+ %td= months[month]