git_stats 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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]