@@ -0,0 +1,20 | |||||
|
1 | Copyright (c) 2007 West Arete Computing, Inc. | |||
|
2 | ||||
|
3 | Permission is hereby granted, free of charge, to any person obtaining | |||
|
4 | a copy of this software and associated documentation files (the | |||
|
5 | "Software"), to deal in the Software without restriction, including | |||
|
6 | without limitation the rights to use, copy, modify, merge, publish, | |||
|
7 | distribute, sublicense, and/or sell copies of the Software, and to | |||
|
8 | permit persons to whom the Software is furnished to do so, subject to | |||
|
9 | the following conditions: | |||
|
10 | ||||
|
11 | The above copyright notice and this permission notice shall be | |||
|
12 | included in all copies or substantial portions of the Software. | |||
|
13 | ||||
|
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
|
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
|
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
|
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |||
|
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
|
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
|
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. No newline at end of file |
@@ -0,0 +1,52 | |||||
|
1 | == Gravatar Plugin | |||
|
2 | ||||
|
3 | This plugin provides a handful of view helpers for displaying gravatars | |||
|
4 | (globally-recognized avatars). | |||
|
5 | ||||
|
6 | Gravatars allow users to configure an avatar to go with their email address at | |||
|
7 | a central location: http://gravatar.com. Gravatar-aware websites (such | |||
|
8 | as yours) can then look up and display each user's preferred avatar, without | |||
|
9 | having to handle avatar management. The user gets the benefit of not having to | |||
|
10 | set up an avatar for each site that they post on. | |||
|
11 | ||||
|
12 | == Installation | |||
|
13 | ||||
|
14 | cd ~/myapp | |||
|
15 | ruby script/plugin install svn://rubyforge.org//var/svn/gravatarplugin/plugins/gravatar | |||
|
16 | ||||
|
17 | or, if you're using piston[http://piston.rubyforge.org] (worth it!): | |||
|
18 | ||||
|
19 | cd ~/myapp/vendor/plugins | |||
|
20 | piston import svn://rubyforge.org//var/svn/gravatarplugin/plugins/gravatar | |||
|
21 | ||||
|
22 | == Example | |||
|
23 | ||||
|
24 | If you represent your users with a model that has an +email+ method (typical | |||
|
25 | for most rails authentication setups), then you can simply use this method | |||
|
26 | in your views: | |||
|
27 | ||||
|
28 | <%= gravatar_for @user %> | |||
|
29 | ||||
|
30 | This will be replaced with the full HTML +img+ tag necessary for displaying | |||
|
31 | that user's gravatar. | |||
|
32 | ||||
|
33 | Other helpers are documented under GravatarHelper::PublicMethods. | |||
|
34 | ||||
|
35 | == Acknowledgments | |||
|
36 | ||||
|
37 | The following people have also written gravatar-related Ruby libraries: | |||
|
38 | * Seth Rasmussen created the gravatar gem[http://gravatar.rubyforge.org] | |||
|
39 | * Matt McCray has also created a gravatar | |||
|
40 | plugin[http://mattmccray.com/svn/rails/plugins/gravatar_helper] | |||
|
41 | ||||
|
42 | == Author | |||
|
43 | ||||
|
44 | Scott A. Woods | |||
|
45 | West Arete Computing, Inc. | |||
|
46 | http://westarete.com | |||
|
47 | scott at westarete dot com | |||
|
48 | ||||
|
49 | == TODO | |||
|
50 | ||||
|
51 | * Get full spec coverage | |||
|
52 | * Finish rdoc documentation No newline at end of file |
@@ -0,0 +1,33 | |||||
|
1 | require 'spec/rake/spectask' | |||
|
2 | require 'rake/rdoctask' | |||
|
3 | ||||
|
4 | desc 'Default: run all specs' | |||
|
5 | task :default => :spec | |||
|
6 | ||||
|
7 | desc 'Run all application-specific specs' | |||
|
8 | Spec::Rake::SpecTask.new(:spec) do |t| | |||
|
9 | t.warning = true | |||
|
10 | t.rcov = true | |||
|
11 | end | |||
|
12 | ||||
|
13 | desc "Report code statistics (KLOCs, etc) from the application" | |||
|
14 | task :stats do | |||
|
15 | RAILS_ROOT = File.dirname(__FILE__) | |||
|
16 | STATS_DIRECTORIES = [ | |||
|
17 | %w(Libraries lib/), | |||
|
18 | %w(Specs spec/), | |||
|
19 | ].collect { |name, dir| [ name, "#{RAILS_ROOT}/#{dir}" ] }.select { |name, dir| File.directory?(dir) } | |||
|
20 | require 'code_statistics' | |||
|
21 | CodeStatistics.new(*STATS_DIRECTORIES).to_s | |||
|
22 | end | |||
|
23 | ||||
|
24 | namespace :doc do | |||
|
25 | desc 'Generate documentation for the assert_request plugin.' | |||
|
26 | Rake::RDocTask.new(:plugin) do |rdoc| | |||
|
27 | rdoc.rdoc_dir = 'rdoc' | |||
|
28 | rdoc.title = 'Gravatar Rails Plugin' | |||
|
29 | rdoc.options << '--line-numbers' << '--inline-source' << '--accessor' << 'cattr_accessor=rw' | |||
|
30 | rdoc.rdoc_files.include('README') | |||
|
31 | rdoc.rdoc_files.include('lib/**/*.rb') | |||
|
32 | end | |||
|
33 | end |
@@ -0,0 +1,7 | |||||
|
1 | author: Scott Woods, West Arete Computing | |||
|
2 | summary: View helpers for displaying gravatars. | |||
|
3 | homepage: http://gravatarplugin.rubyforge.org/ | |||
|
4 | plugin: svn://rubyforge.org//var/svn/gravatarplugin/plugins/gravatar | |||
|
5 | license: MIT | |||
|
6 | version: 0.1 | |||
|
7 | rails_version: 1.0+ |
@@ -0,0 +1,67 | |||||
|
1 | require 'digest/md5' | |||
|
2 | require 'cgi' | |||
|
3 | ||||
|
4 | module GravatarHelper | |||
|
5 | ||||
|
6 | # These are the options that control the default behavior of the public | |||
|
7 | # methods. They can be overridden during the actual call to the helper, | |||
|
8 | # or you can set them in your environment.rb as such: | |||
|
9 | # | |||
|
10 | # # Allow racier gravatars | |||
|
11 | # GravatarHelper::DEFAULT_OPTIONS[:rating] = 'R' | |||
|
12 | # | |||
|
13 | DEFAULT_OPTIONS = { | |||
|
14 | # The URL of a default image to display if the given email address does | |||
|
15 | # not have a gravatar. | |||
|
16 | :default => nil, | |||
|
17 | ||||
|
18 | # The default size in pixels for the gravatar image (they're square). | |||
|
19 | :size => 50, | |||
|
20 | ||||
|
21 | # The maximum allowed MPAA rating for gravatars. This allows you to | |||
|
22 | # exclude gravatars that may be out of character for your site. | |||
|
23 | :rating => 'PG', | |||
|
24 | ||||
|
25 | # The alt text to use in the img tag for the gravatar. | |||
|
26 | :alt => 'avatar', | |||
|
27 | ||||
|
28 | # The class to assign to the img tag for the gravatar. | |||
|
29 | :class => 'gravatar', | |||
|
30 | } | |||
|
31 | ||||
|
32 | # The methods that will be made available to your views. | |||
|
33 | module PublicMethods | |||
|
34 | ||||
|
35 | # Return the HTML img tag for the given user's gravatar. Presumes that | |||
|
36 | # the given user object will respond_to "email", and return the user's | |||
|
37 | # email address. | |||
|
38 | def gravatar_for(user, options={}) | |||
|
39 | gravatar(user.email, options) | |||
|
40 | end | |||
|
41 | ||||
|
42 | # Return the HTML img tag for the given email address's gravatar. | |||
|
43 | def gravatar(email, options={}) | |||
|
44 | src = h(gravatar_url(email, options)) | |||
|
45 | options = DEFAULT_OPTIONS.merge(options) | |||
|
46 | [:class, :alt, :size].each { |opt| options[opt] = h(options[opt]) } | |||
|
47 | "<img class=\"#{options[:class]}\" alt=\"#{options[:alt]}\" width=\"#{options[:size]}\" height=\"#{options[:size]}\" src=\"#{src}\" />" | |||
|
48 | end | |||
|
49 | ||||
|
50 | # Return the gravatar URL for the given email address. | |||
|
51 | def gravatar_url(email, options={}) | |||
|
52 | email_hash = Digest::MD5.hexdigest(email) | |||
|
53 | options = DEFAULT_OPTIONS.merge(options) | |||
|
54 | options[:default] = CGI::escape(options[:default]) unless options[:default].nil? | |||
|
55 | returning "http://www.gravatar.com/avatar.php?gravatar_id=#{email_hash}" do |url| | |||
|
56 | [:rating, :size, :default].each do |opt| | |||
|
57 | unless options[opt].nil? | |||
|
58 | value = h(options[opt]) | |||
|
59 | url << "&#{opt}=#{value}" | |||
|
60 | end | |||
|
61 | end | |||
|
62 | end | |||
|
63 | end | |||
|
64 | ||||
|
65 | end | |||
|
66 | ||||
|
67 | end No newline at end of file |
@@ -0,0 +1,37 | |||||
|
1 | require 'rubygems' | |||
|
2 | require 'erb' # to get "h" | |||
|
3 | require 'active_support' # to get "returning" | |||
|
4 | require File.dirname(__FILE__) + '/../lib/gravatar' | |||
|
5 | include GravatarHelper, GravatarHelper::PublicMethods, ERB::Util | |||
|
6 | ||||
|
7 | context "gravatar_url with a custom default URL" do | |||
|
8 | setup do | |||
|
9 | @original_options = DEFAULT_OPTIONS.dup | |||
|
10 | DEFAULT_OPTIONS[:default] = "no_avatar.png" | |||
|
11 | @url = gravatar_url("somewhere") | |||
|
12 | end | |||
|
13 | ||||
|
14 | specify "should include the \"default\" argument in the result" do | |||
|
15 | @url.should match(/&default=no_avatar.png/) | |||
|
16 | end | |||
|
17 | ||||
|
18 | teardown do | |||
|
19 | DEFAULT_OPTIONS.merge!(@original_options) | |||
|
20 | end | |||
|
21 | ||||
|
22 | end | |||
|
23 | ||||
|
24 | context "gravatar_url with default settings" do | |||
|
25 | setup do | |||
|
26 | @url = gravatar_url("somewhere") | |||
|
27 | end | |||
|
28 | ||||
|
29 | specify "should have a nil default URL" do | |||
|
30 | DEFAULT_OPTIONS[:default].should be_nil | |||
|
31 | end | |||
|
32 | ||||
|
33 | specify "should not include the \"default\" argument in the result" do | |||
|
34 | @url.should_not match(/&default=/) | |||
|
35 | end | |||
|
36 | ||||
|
37 | end No newline at end of file |
@@ -1,14 +1,15 | |||||
1 | <% reply_links = authorize_for('issues', 'edit') -%> |
|
1 | <% reply_links = authorize_for('issues', 'edit') -%> | |
2 | <% for journal in journals %> |
|
2 | <% for journal in journals %> | |
3 |
|
|
3 | <div id="change-<%= journal.id %>" class="journal"> | |
4 | <h4><div style="float:right;"><%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %></div> |
|
4 | <%= gravatar(journal.user.mail.blank? ? "" : journal.user.mail, :size => "48") %> | |
5 | <%= content_tag('a', '', :name => "note-#{journal.indice}")%> |
|
5 | <h4><div style="float:right;"><%= link_to "##{journal.indice}", :anchor => "note-#{journal.indice}" %></div> | |
6 | <%= format_time(journal.created_on) %> - <%= journal.user.name %></h4> |
|
6 | <%= content_tag('a', '', :name => "note-#{journal.indice}")%> | |
7 | <ul> |
|
7 | <%= format_time(journal.created_on) %> - <%= journal.user.name %></h4> | |
8 | <% for detail in journal.details %> |
|
8 | <ul> | |
9 | <li><%= show_detail(detail) %></li> |
|
9 | <% for detail in journal.details %> | |
10 | <% end %> |
|
10 | <li><%= show_detail(detail) %></li> | |
11 | </ul> |
|
11 | <% end %> | |
12 | <%= render_notes(journal, :reply_links => reply_links) unless journal.notes.blank? %> |
|
12 | </ul> | |
13 | </div> |
|
13 | <%= render_notes(journal, :reply_links => reply_links) unless journal.notes.blank? %> | |
|
14 | </div> | |||
14 | <% end %> |
|
15 | <% end %> |
@@ -10,6 +10,7 | |||||
10 | <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2> |
|
10 | <h2><%= @issue.tracker.name %> #<%= @issue.id %></h2> | |
11 |
|
11 | |||
12 | <div class="issue <%= "status-#{@issue.status.position} priority-#{@issue.priority.position}" %>"> |
|
12 | <div class="issue <%= "status-#{@issue.status.position} priority-#{@issue.priority.position}" %>"> | |
|
13 | <%= gravatar(@issue.author.mail, :size => "64") %> | |||
13 | <h3><%=h @issue.subject %></h3> |
|
14 | <h3><%=h @issue.subject %></h3> | |
14 | <p class="author"> |
|
15 | <p class="author"> | |
15 | <%= authoring @issue.created_on, @issue.author %>. |
|
16 | <%= authoring @issue.created_on, @issue.author %>. | |
@@ -18,28 +19,28 | |||||
18 |
|
19 | |||
19 | <table width="100%"> |
|
20 | <table width="100%"> | |
20 | <tr> |
|
21 | <tr> | |
21 | <td style="width:15%"><b><%=l(:field_status)%>:</b></td><td style="width:35%"><%= @issue.status.name %></td> |
|
22 | <td style="width:15%" class="status"><b><%=l(:field_status)%>:</b></td><td style="width:35%" class="status status-<%= @issue.status.name %>"><%= @issue.status.name %></td> | |
22 | <td style="width:15%"><b><%=l(:field_start_date)%>:</b></td><td style="width:35%"><%= format_date(@issue.start_date) %></td> |
|
23 | <td style="width:15%" class="start-date"><b><%=l(:field_start_date)%>:</b></td><td style="width:35%"><%= format_date(@issue.start_date) %></td> | |
23 | </tr> |
|
24 | </tr> | |
24 | <tr> |
|
25 | <tr> | |
25 | <td><b><%=l(:field_priority)%>:</b></td><td><%= @issue.priority.name %></td> |
|
26 | <td class="priority"><b><%=l(:field_priority)%>:</b></td><td class="priority priority-<%= @issue.priority.name %>"><%= @issue.priority.name %></td> | |
26 | <td><b><%=l(:field_due_date)%>:</b></td><td><%= format_date(@issue.due_date) %></td> |
|
27 | <td class="due-date"><b><%=l(:field_due_date)%>:</b></td><td class="due-date"><%= format_date(@issue.due_date) %></td> | |
27 | </tr> |
|
28 | </tr> | |
28 | <tr> |
|
29 | <tr> | |
29 | <td><b><%=l(:field_assigned_to)%>:</b></td><td><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td> |
|
30 | <td class="assigned-to"><b><%=l(:field_assigned_to)%>:</b></td><td><%= gravatar(@issue.assigned_to.mail, :size => "24") %><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td> | |
30 | <td><b><%=l(:field_done_ratio)%>:</b></td><td><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td> |
|
31 | <td class="progress"><b><%=l(:field_done_ratio)%>:</b></td><td class="progress"><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td> | |
31 | </tr> |
|
32 | </tr> | |
32 | <tr> |
|
33 | <tr> | |
33 | <td><b><%=l(:field_category)%>:</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td> |
|
34 | <td class="category"><b><%=l(:field_category)%>:</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td> | |
34 | <% if User.current.allowed_to?(:view_time_entries, @project) %> |
|
35 | <% if User.current.allowed_to?(:view_time_entries, @project) %> | |
35 | <td><b><%=l(:label_spent_time)%>:</b></td> |
|
36 | <td class="spent-time"><b><%=l(:label_spent_time)%>:</b></td> | |
36 | <td><%= @issue.spent_hours > 0 ? (link_to lwr(:label_f_hour, @issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time') : "-" %></td> |
|
37 | <td class="spent-hours"><%= @issue.spent_hours > 0 ? (link_to lwr(:label_f_hour, @issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time') : "-" %></td> | |
37 | <% end %> |
|
38 | <% end %> | |
38 | </tr> |
|
39 | </tr> | |
39 | <tr> |
|
40 | <tr> | |
40 | <td><b><%=l(:field_fixed_version)%>:</b></td><td><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td> |
|
41 | <td class="fixed-version"><b><%=l(:field_fixed_version)%>:</b></td><td><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td> | |
41 | <% if @issue.estimated_hours %> |
|
42 | <% if @issue.estimated_hours %> | |
42 | <td><b><%=l(:field_estimated_hours)%>:</b></td><td><%= lwr(:label_f_hour, @issue.estimated_hours) %></td> |
|
43 | <td class="estimated-hours"><b><%=l(:field_estimated_hours)%>:</b></td><td><%= lwr(:label_f_hour, @issue.estimated_hours) %></td> | |
43 | <% end %> |
|
44 | <% end %> | |
44 | </tr> |
|
45 | </tr> | |
45 | <tr> |
|
46 | <tr> |
@@ -6,7 +6,10 | |||||
6 | <h3><%= format_activity_day(day) %></h3> |
|
6 | <h3><%= format_activity_day(day) %></h3> | |
7 | <dl> |
|
7 | <dl> | |
8 | <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%> |
|
8 | <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%> | |
9 | <dt class="<%= e.event_type %> <%= User.current.logged? && e.respond_to?(:event_author) && User.current == e.event_author ? 'me' : nil %>"> |
|
9 | <dt class="<%= e.event_type %> <%= User.current.logged? && e.respond_to?(:event_author) && User.current == e.event_author ? 'me' : nil %>"> | |
|
10 | <%= gravatar(e.user.mail, :size => "24") if e.respond_to?(:user) rescue nil%> | |||
|
11 | <%= gravatar(e.author.mail, :size => "24") if e.respond_to?(:author) rescue nil%> | |||
|
12 | <%= gravatar(e.committer.match('\\<.+?\\>')[0].gsub(/[<>]/, ''), :size => "24") if e.respond_to?(:committer) rescue nil%> | |||
10 | <span class="time"><%= format_time(e.event_datetime, false) %></span> |
|
13 | <span class="time"><%= format_time(e.event_datetime, false) %></span> | |
11 | <%= content_tag('span', h(e.project), :class => 'project') if @project.nil? || @project != e.project %> |
|
14 | <%= content_tag('span', h(e.project), :class => 'project') if @project.nil? || @project != e.project %> | |
12 | <%= link_to format_activity_title(e.event_title), e.event_url %></dt> |
|
15 | <%= link_to format_activity_title(e.event_title), e.event_url %></dt> |
@@ -29,7 +29,7 | |||||
29 | <tbody> |
|
29 | <tbody> | |
30 | <% for user in @users -%> |
|
30 | <% for user in @users -%> | |
31 | <tr class="user <%= cycle("odd", "even") %> <%= %w(anon active registered locked)[user.status] %>"> |
|
31 | <tr class="user <%= cycle("odd", "even") %> <%= %w(anon active registered locked)[user.status] %>"> | |
32 | <td class="username"><%= link_to h(user.login), :action => 'edit', :id => user %></td> |
|
32 | <td class="username"><%= gravatar(user.mail, :size => "24") %><%= link_to h(user.login), :action => 'edit', :id => user %></td> | |
33 | <td class="firstname"><%= h(user.firstname) %></td> |
|
33 | <td class="firstname"><%= h(user.firstname) %></td> | |
34 | <td class="lastname"><%= h(user.lastname) %></td> |
|
34 | <td class="lastname"><%= h(user.lastname) %></td> | |
35 | <td class="email"><%= mail_to(h(user.mail)) %></td> |
|
35 | <td class="email"><%= mail_to(h(user.mail)) %></td> |
@@ -615,6 +615,42 vertical-align: middle; | |||||
615 | .icon22-settings { background-image: url(../images/22x22/settings.png); } |
|
615 | .icon22-settings { background-image: url(../images/22x22/settings.png); } | |
616 | .icon22-plugin { background-image: url(../images/22x22/plugin.png); } |
|
616 | .icon22-plugin { background-image: url(../images/22x22/plugin.png); } | |
617 |
|
617 | |||
|
618 | img.gravatar { | |||
|
619 | padding: 2px; | |||
|
620 | border: solid 1px #d5d5d5; | |||
|
621 | background: #fff; | |||
|
622 | } | |||
|
623 | ||||
|
624 | div.issue img.gravatar { | |||
|
625 | float: right; | |||
|
626 | margin: 0 0 1em 1em; | |||
|
627 | padding: 5px; | |||
|
628 | } | |||
|
629 | ||||
|
630 | div.issue table img.gravatar { | |||
|
631 | height: 24px; | |||
|
632 | width: 24px; | |||
|
633 | padding: 2px; | |||
|
634 | float: left; | |||
|
635 | margin: 0 1em 0 0; | |||
|
636 | } | |||
|
637 | ||||
|
638 | #history img.gravatar { | |||
|
639 | padding: 3px; | |||
|
640 | margin: 0 2em 1em 0; | |||
|
641 | float: left; | |||
|
642 | } | |||
|
643 | ||||
|
644 | td.username img.gravatar { | |||
|
645 | float: left; | |||
|
646 | margin: 0 1em 0 0; | |||
|
647 | } | |||
|
648 | ||||
|
649 | #activity dt img.gravatar { | |||
|
650 | float: left; | |||
|
651 | margin: 0 1em 1em 0; | |||
|
652 | } | |||
|
653 | ||||
618 | /***** Media print specific styles *****/ |
|
654 | /***** Media print specific styles *****/ | |
619 | @media print { |
|
655 | @media print { | |
620 | #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; } |
|
656 | #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; } |
General Comments 0
You need to be logged in to leave comments.
Login now