Commit e7464a3d47aa5a204943ccec669355fb4eede45b

Authored by Rodrigo Souto
Committed by Daniela Feitosa
1 parent 4456c409

Multitask

+ Multi-processing tasks.
  + Graciously show/hide functions with the smooth slide of
  + Jquery. ^^
  + Using Unobtrusive Javascript.
  + Customized messages for each task type.
  + Button "Set all to approve/reject/skip".
  + Icons related to the task action.

  * Missing
    - Need to make selenium tests.

(ActionItem1527)
Showing 69 changed files with 1528 additions and 513 deletions   Show diff stats
app/controllers/my_profile/tasks_controller.rb
... ... @@ -4,26 +4,38 @@ class TasksController < MyProfileController
4 4  
5 5 def index
6 6 @tasks = profile.all_pending_tasks.sort_by(&:created_at)
  7 + @failed = params ? params[:failed] : {}
7 8 end
8 9  
9 10 def processed
10 11 @tasks = profile.all_finished_tasks.sort_by(&:created_at)
11 12 end
12 13  
13   - VALID_DECISIONS = [ 'finish', 'cancel' ]
  14 + VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ]
14 15  
15 16 def close
16   - decision = params[:decision]
17   - if request.post? && VALID_DECISIONS.include?(decision) && params[:id]
18   - task = profile.find_in_all_tasks(params[:id])
19   - task.update_attributes(params[:task])
20   - begin
21   - task.send(decision)
22   - rescue Exception => ex
23   - session[:notice] = ex.clean_message
  17 + failed = {}
  18 +
  19 + params[:tasks].each do |id, value|
  20 + decision = value[:decision]
  21 + if request.post? && VALID_DECISIONS.include?(decision) && id && decision != 'skip'
  22 + task = profile.find_in_all_tasks(id)
  23 + task.update_attributes!(value[:task])
  24 + begin
  25 + task.send(decision)
  26 + rescue Exception => ex
  27 + message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"
  28 + failed[ex.clean_message] ? failed[ex.clean_message] << message : failed[ex.clean_message] = [message]
  29 + end
24 30 end
25 31 end
26   - redirect_to :action => 'index'
  32 +
  33 + if failed.blank?
  34 + session[:notice] = _("All decisions were applied successfully.")
  35 + else
  36 + session[:notice] = _("Some tasks couldn't be applied.")
  37 + end
  38 + redirect_to params.merge!(:action => 'index', :failed => failed)
27 39 end
28 40  
29 41 def new
... ...
app/helpers/application_helper.rb
... ... @@ -279,6 +279,19 @@ module ApplicationHelper
279 279 end
280 280 end
281 281  
  282 + def partial_for_task_class(klass, action)
  283 + if klass.nil?
  284 + raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?'
  285 + end
  286 +
  287 + name = "#{klass.name.underscore}_#{action.to_s}"
  288 + if File.exists?(File.join(RAILS_ROOT, 'app', 'views', params[:controller], "_#{name}.rhtml"))
  289 + name
  290 + else
  291 + partial_for_task_class(klass.superclass, action)
  292 + end
  293 + end
  294 +
282 295 def user
283 296 @controller.send(:user)
284 297 end
... ... @@ -621,7 +634,16 @@ module ApplicationHelper
621 634 end
622 635  
623 636 def select_folder(label, object, method, collection, html_options = {}, js_options = {})
624   - labelled_form_field(label, select(object, method, collection.map {|f| [ profile.identifier + '/' + f.full_name, f.id ] }, html_options.merge({:include_blank => "#{profile.identifier}"}), js_options))
  637 + root = profile ? profile.identifier : _("root")
  638 + labelled_form_field(label, select(object, method,
  639 + collection.map {|f| [ root + '/' + f.full_name, f.id ]},
  640 + {:include_blank => root}, html_options.merge(js_options)))
  641 + end
  642 +
  643 + def select_profile_folder(label, object, method, profile, html_options = {}, js_options = {})
  644 + labelled_form_field(label, select(object, method,
  645 + profile.folders.map {|f| [ profile.identifier + '/' + f.full_name, f.id ]},
  646 + {:include_blank => profile.identifier}, html_options.merge(js_options)))
625 647 end
626 648  
627 649 def theme_option(opt = nil)
... ... @@ -1094,10 +1116,16 @@ module ApplicationHelper
1094 1116 end
1095 1117  
1096 1118 def usermenu_logged_in
  1119 + pending_tasks_count = ''
  1120 + if user && user.all_pending_tasks.count > 0
  1121 + pending_tasks_count = link_to(user.all_pending_tasks.count.to_s, '/myprofile/{login}/tasks', :id => 'pending-tasks-count')
  1122 + end
  1123 +
1097 1124 (_('Welcome, %s') % link_to('<i></i><strong>{login}</strong>', '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) +
1098 1125 render_environment_features(:usermenu) +
1099 1126 link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', { :controller => 'admin_panel', :action => 'index' }, :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') +
1100 1127 link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) +
  1128 + pending_tasks_count +
1101 1129 link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system"))
1102 1130 end
1103 1131  
... ... @@ -1164,4 +1192,13 @@ module ApplicationHelper
1164 1192 content_tag(:div, _('Source: %s') % source_url, :id => 'article-source') unless source_url.nil?
1165 1193 end
1166 1194  
  1195 + def task_information(task)
  1196 + values = {}
  1197 + values.merge!({:requestor => link_to(task.requestor.name, task.requestor.public_profile_url)}) if task.requestor
  1198 + values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject
  1199 + values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject
  1200 + values.merge!(task.information[:variables]) if task.information[:variables]
  1201 + task.information[:message] % values
  1202 + end
  1203 +
1167 1204 end
... ...
app/models/add_friend.rb
... ... @@ -6,7 +6,7 @@ class AddFriend &lt; Task
6 6  
7 7 validates_uniqueness_of :target_id, :scope => [ :requestor_id ]
8 8  
9   - validates_length_of :group_for_person, :group_for_friend, :maximum => 150, :allow_nil => true
  9 + validates_length_of :group_for_person, :group_for_friend, :maximum => 150, :allow_nil => true
10 10  
11 11 alias :person :requestor
12 12 alias :person= :requestor=
... ... @@ -19,17 +19,29 @@ class AddFriend &lt; Task
19 19 requestor.add_friend(target, group_for_person)
20 20 end
21 21  
22   - def description
23   - _('%s wants to be your friend.') % requestor.name
24   - end
25   -
26 22 def permission
27 23 :manage_friends
28 24 end
29 25  
30 26 def target_notification_message
31   - description + "\n\n" +
  27 + _('%{requestor} wants to be your friend.') % {:requestor => requestor.name} + "\n\n" +
32 28 _('You need to login to %{system} in order to accept %{requestor} as your friend.') % { :system => target.environment.name, :requestor => requestor.name }
33 29 end
34 30  
  31 + def title
  32 + _("New friend")
  33 + end
  34 +
  35 + def information
  36 + {:message => _('%{requestor} wants to be your friend.') }
  37 + end
  38 +
  39 + def accept_details
  40 + true
  41 + end
  42 +
  43 + def icon
  44 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
  45 + end
  46 +
35 47 end
... ...
app/models/add_member.rb
... ... @@ -15,8 +15,20 @@ class AddMember &lt; Task
15 15 target.affiliate(requestor, self.roles.select{|r| !r.to_i.zero? }.map{|i| Role.find(i)})
16 16 end
17 17  
18   - def description
19   - _('%s wants to be a member of "%s".') % [requestor.name, organization.name]
  18 + def title
  19 + _("New member")
  20 + end
  21 +
  22 + def information
  23 + {:message => _('%{requestor} wants to be a member of this community.')}
  24 + end
  25 +
  26 + def accept_details
  27 + true
  28 + end
  29 +
  30 + def icon
  31 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
20 32 end
21 33  
22 34 def permission
... ... @@ -24,7 +36,7 @@ class AddMember &lt; Task
24 36 end
25 37  
26 38 def target_notification_message
27   - description + "\n\n" +
  39 + _('%{requestor} wants to be a member of this community.') % {:requestor => requestor.name} + "\n\n" +
28 40 _('You will need login to %{system} in order to accept or reject %{requestor} as a member of %{organization}.') % { :system => target.environment.name, :requestor => requestor.name, :organization => organization.name }
29 41 end
30 42  
... ...
app/models/approve_article.rb
... ... @@ -3,10 +3,6 @@ class ApproveArticle &lt; Task
3 3  
4 4 validates_presence_of :requestor_id, :target_id
5 5  
6   - def description
7   - _('%{author} wants to publish "%{article}" on %{community}') % { :author => requestor.name, :article => article_title, :community => target.name }
8   - end
9   -
10 6 def article_title
11 7 article ? article.title : _('(The original text was removed)')
12 8 end
... ... @@ -24,7 +20,7 @@ class ApproveArticle &lt; Task
24 20 end
25 21  
26 22 def name
27   - data[:name].blank? ? article.name : data[:name]
  23 + data[:name].blank? ? (article ? article.name : _("Article removed.")) : data[:name]
28 24 end
29 25  
30 26 def name= value
... ... @@ -68,7 +64,7 @@ class ApproveArticle &lt; Task
68 64 end
69 65  
70 66 def abstract
71   - data[:abstract].blank? ? article.abstract : data[:abstract]
  67 + data[:abstract].blank? ? (article ? article.abstract : '') : data[:abstract]
72 68 end
73 69  
74 70 def body= value
... ... @@ -76,17 +72,63 @@ class ApproveArticle &lt; Task
76 72 end
77 73  
78 74 def body
79   - data[:body].blank? ? article.body : data[:body]
  75 + data[:body].blank? ? (article ? article.body : "") : data[:body]
80 76 end
81 77  
82 78 def perform
83 79 article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source)
84 80 end
85 81  
  82 + def title
  83 + _("New article")
  84 + end
  85 +
  86 + def icon
  87 + result = {:type => :defined_image, :src => '/images/icons-app/article-minor.png', :name => name}
  88 + result.merge({:url => article.url}) if article
  89 + return result
  90 + end
  91 +
  92 + def linked_subject
  93 + {:text => name, :url => article.url} if article
  94 + end
  95 +
  96 + def information
  97 + if article
  98 + {:message => _('%{requestor} wants to publish the article: %{linked_subject}.')}
  99 + else
  100 + {:message => _("The article was removed.")}
  101 + end
  102 + end
  103 +
  104 + def accept_details
  105 + true
  106 + end
  107 +
  108 + def default_decision
  109 + if article
  110 + 'skip'
  111 + else
  112 + 'reject'
  113 + end
  114 + end
  115 +
  116 + def accept_disabled?
  117 + article.blank?
  118 + end
  119 +
86 120 def target_notification_message
87 121 return nil if target.organization? && !target.moderated_articles?
88   - description + "\n\n" +
  122 + _('%{requestor} wants to publish the article: %{article}.') % {:requestor => requestor.name, :article => article.name} + "\n\n"
89 123 _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name }
90 124 end
91 125  
  126 + def task_finished_message
  127 + if !closing_statment.blank?
  128 + _("Your request for publishing the article \"%{article}\" was approved. Here is the comment left by the admin who approved your article:\n\n%{comment} ") % {:article => name, :comment => closing_statment}
  129 + else
  130 + _('Your request for publishing the article "%{article}" was approved.') % {:article => name}
  131 + end
  132 + end
  133 +
92 134 end
... ...
app/models/change_password.rb
... ... @@ -61,6 +61,18 @@ class ChangePassword &lt; Task
61 61 self[:data] = {}
62 62 end
63 63  
  64 + def title
  65 + _("Change password")
  66 + end
  67 +
  68 + def information
  69 + {:message => _('%{requestor} wants to change its password.')}
  70 + end
  71 +
  72 + def icon
  73 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
  74 + end
  75 +
64 76 def perform
65 77 user = self.requestor.user
66 78 user.force_change_password!(self.password, self.password_confirmation)
... ... @@ -87,10 +99,6 @@ class ChangePassword &lt; Task
87 99 end
88 100 end
89 101  
90   - def description
91   - _('Password change request')
92   - end
93   -
94 102 def environment
95 103 self.requestor.environment
96 104 end
... ...
app/models/community.rb
... ... @@ -39,6 +39,10 @@ class Community &lt; Organization
39 39 end
40 40 end
41 41  
  42 + def display_name
  43 + self.name
  44 + end
  45 +
42 46 def active_fields
43 47 environment ? environment.active_community_fields : []
44 48 end
... ...
app/models/create_community.rb
... ... @@ -48,16 +48,34 @@ class CreateCommunity &lt; Task
48 48 community.add_admin(self.requestor)
49 49 end
50 50  
51   - def description
52   - _('%s wants to create community %s.') % [requestor.name, self.name]
  51 + def title
  52 + _("New community")
53 53 end
54 54  
55   - def closing_statement
56   - data[:closing_statement]
  55 + def icon
  56 + src = image ? image.public_filename(:minor) : '/images/icons-app/community-minor.png'
  57 + {:type => :defined_image, :src => src, :name => name}
57 58 end
58 59  
59   - def closing_statement= value
60   - data[:closing_statement] = value
  60 + def subject
  61 + name
  62 + end
  63 +
  64 + def information
  65 + if description.blank?
  66 + { :message => _('%{requestor} wants to create community %{subject} with no description.') }
  67 + else
  68 + { :message => _('%{requestor} wants to create community %{subject} with this description:<p><em>%{description}</em></p>'),
  69 + :variables => {:description => description} }
  70 + end
  71 + end
  72 +
  73 + def reject_details
  74 + true
  75 + end
  76 +
  77 + def display_name
  78 + self.name
61 79 end
62 80  
63 81 # tells if this request was rejected
... ... @@ -71,7 +89,6 @@ class CreateCommunity &lt; Task
71 89 end
72 90  
73 91 def target_notification_message
74   - description + "\n\n" +
75 92 _("User \"%{user}\" just requested to create community %{community}. You have to approve or reject it through the \"Pending Validations\" section in your control panel.\n") % { :user => self.requestor.name, :community => self.name }
76 93 end
77 94  
... ... @@ -82,7 +99,7 @@ class CreateCommunity &lt; Task
82 99 end
83 100  
84 101 def task_cancelled_message
85   - _("Your request for registering community %{community} at %{environment} was not approved by the environment administrator. The following explanation was given: \n\n%{explanation}") % { :community => self.name, :environment => self.environment, :explanation => self.closing_statement }
  102 + _("Your request for registering community %{community} at %{environment} was not approved by the environment administrator. The following explanation was given: \n\n%{explanation}") % { :community => self.name, :environment => self.environment, :explanation => self.reject_explanation }
86 103 end
87 104  
88 105 def task_finished_message
... ...
app/models/create_enterprise.rb
... ... @@ -11,7 +11,7 @@ class CreateEnterprise &lt; Task
11 11 N_('Economic activity')
12 12 N_('Management information')
13 13  
14   - DATA_FIELDS = Enterprise.fields + %w[name identifier region_id reject_explanation]
  14 + DATA_FIELDS = Enterprise.fields + %w[name identifier region_id]
15 15  
16 16 serialize :data, Hash
17 17 attr_protected :data
... ... @@ -48,7 +48,6 @@ class CreateEnterprise &lt; Task
48 48  
49 49 # check for explanation when rejecting
50 50 validates_presence_of :reject_explanation, :if => (lambda { |record| record.status == Task::Status::CANCELLED } )
51   -
52 51 xss_terminate :only => [ :acronym, :address, :contact_person, :contact_phone, :economic_activity, :legal_form, :management_information, :name ], :on => 'validation'
53 52  
54 53 def validate
... ... @@ -153,8 +152,24 @@ class CreateEnterprise &lt; Task
153 152 enterprise.add_admin(enterprise.user.person)
154 153 end
155 154  
156   - def description
157   - __('Enterprise registration: "%s"') % self.name
  155 + def title
  156 + _("Enterprise registration")
  157 + end
  158 +
  159 + def icon
  160 + {:type => :defined_image, :src => '/images/icons-app/enterprise-minor.png', :name => name}
  161 + end
  162 +
  163 + def subject
  164 + name
  165 + end
  166 +
  167 + def information
  168 + {:message => _('%{requestor} wants to create enterprise %{subject}.')}
  169 + end
  170 +
  171 + def reject_details
  172 + true
158 173 end
159 174  
160 175 def task_created_message
... ...
app/models/email_activation.rb
... ... @@ -11,8 +11,20 @@ class EmailActivation &lt; Task
11 11 end
12 12 end
13 13  
14   - def description
15   - _("'%{user} wants to activate email '%{email}'") % { :user => person.name, :email => person.email_addresses.join(', ') }
  14 + def title
  15 + _("Email activation")
  16 + end
  17 +
  18 + def subject
  19 + person.email_addresses.join(', ')
  20 + end
  21 +
  22 + def information
  23 + {:message => _("%{requestor} wants to activate the following email: %{subject}.")}
  24 + end
  25 +
  26 + def icon
  27 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
16 28 end
17 29  
18 30 def perform
... ...
app/models/enterprise_activation.rb
... ... @@ -20,4 +20,20 @@ class EnterpriseActivation &lt; Task
20 20 self.enterprise.enable(requestor)
21 21 end
22 22  
  23 + def title
  24 + _("Enterprise activation")
  25 + end
  26 +
  27 + def linked_subject
  28 + {:text => target.name, :url => target.public_profile_url}
  29 + end
  30 +
  31 + def information
  32 + {:message => _('%{requestor} wants to activate enterprise %{linked_subject}.')}
  33 + end
  34 +
  35 + def icon
  36 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
  37 + end
  38 +
23 39 end
... ...
app/models/invite_friend.rb
... ... @@ -7,8 +7,20 @@ class InviteFriend &lt; Invitation
7 7 friend.add_friend(person, group_for_friend)
8 8 end
9 9  
10   - def description
11   - _('%s invited you to join %s') % [person.name, person.environment.name]
  10 + def title
  11 + _("New friend")
  12 + end
  13 +
  14 + def information
  15 + {:message => _('%{requestor} wants to be your friend.')}
  16 + end
  17 +
  18 + def accept_details
  19 + true
  20 + end
  21 +
  22 + def icon
  23 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
12 24 end
13 25  
14 26 def permission
... ...
app/models/invite_member.rb
... ... @@ -15,8 +15,24 @@ class InviteMember &lt; Invitation
15 15 community.add_member(friend)
16 16 end
17 17  
18   - def description
19   - _('%s invited you to join the community %s') % [person.name, community.name]
  18 + def title
  19 + _("Community invitation")
  20 + end
  21 +
  22 + def linked_subject
  23 + {:text => community.name, :url => community.public_profile_url}
  24 + end
  25 +
  26 + def information
  27 + {:message => _('%{requestor} invited you to join %{linked_subject}.')}
  28 + end
  29 +
  30 + def url
  31 + community.url
  32 + end
  33 +
  34 + def icon
  35 + {:type => :profile_image, :profile => community, :url => community.url}
20 36 end
21 37  
22 38 def expanded_message
... ...
app/models/suggest_article.rb
... ... @@ -7,10 +7,6 @@ class SuggestArticle &lt; Task
7 7  
8 8 validates_presence_of :target_id, :article_name, :email, :name, :article_body
9 9  
10   - def description
11   - _('%{sender} suggested to publish "%{article}" on %{community}') % { :sender => sender, :article => article_name, :community => target.name }
12   - end
13   -
14 10 settings_items :email, :type => String
15 11 settings_items :name, :type => String
16 12 settings_items :article_name, :type => String
... ... @@ -39,8 +35,30 @@ class SuggestArticle &lt; Task
39 35 )
40 36 end
41 37  
  38 + def title
  39 + _("Article suggestion")
  40 + end
  41 +
  42 + def subject
  43 + article_name
  44 + end
  45 +
  46 + def information
  47 + { :message => _('%{sender} suggested the publication of the article: %{subject}.'),
  48 + :variables => {:sender => sender} }
  49 + end
  50 +
  51 + def accept_details
  52 + true
  53 + end
  54 +
  55 + def icon
  56 + result = {:type => :defined_image, :src => '/images/icons-app/article-minor.png', :name => article_name}
  57 + end
  58 +
42 59 def target_notification_message
43   - description + "\n\n" +
  60 + _('%{sender} suggested the publication of the article: %{article}.') %
  61 + {:sender => sender, :article => article_name} + "\n\n" +
44 62 _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name }
45 63 end
46 64  
... ...
app/models/task.rb
... ... @@ -11,6 +11,8 @@
11 11 # will need to declare <ttserialize</tt> itself).
12 12 class Task < ActiveRecord::Base
13 13  
  14 + acts_as_having_settings :field => :data
  15 +
14 16 module Status
15 17 # the status of tasks just created
16 18 ACTIVE = 1
... ... @@ -86,6 +88,14 @@ class Task &lt; ActiveRecord::Base
86 88 def after_finish
87 89 end
88 90  
  91 + def reject_explanation=(reject_explanation='')
  92 + self.data[:reject_explanation] = reject_explanation
  93 + end
  94 +
  95 + def reject_explanation
  96 + self.data[:reject_explanation]
  97 + end
  98 +
89 99 # this method cancels the task. At the end a message (as returned by
90 100 # #cancel_message) is sent to the requestor with #notify_requestor.
91 101 def cancel
... ... @@ -101,13 +111,50 @@ class Task &lt; ActiveRecord::Base
101 111 end
102 112 end
103 113  
  114 + # Here are the tasks customizable options.
104 115  
105   - # Returns the description of the task.
106   - #
107   - # This method +must+ be overriden in subclasses to return something
108   - # meaningful for each kind of task
109   - def description
110   - _('Generic task')
  116 + def title
  117 + _("Task")
  118 + end
  119 +
  120 + def subject
  121 + nil
  122 + end
  123 +
  124 + def linked_subject
  125 + nil
  126 + end
  127 +
  128 + def information
  129 + {:message => _('%{requestor} sent you a task.')}
  130 + end
  131 +
  132 + def accept_details
  133 + false
  134 + end
  135 +
  136 + def reject_details
  137 + false
  138 + end
  139 +
  140 + def icon
  141 + {:type => :defined_image, :src => "/images/icons-app/user-minor.png", :name => requestor.name, :url => requestor.url}
  142 + end
  143 +
  144 + def default_decision
  145 + 'skip'
  146 + end
  147 +
  148 + def accept_disabled?
  149 + false
  150 + end
  151 +
  152 + def reject_disabled?
  153 + false
  154 + end
  155 +
  156 + def skip_disabled?
  157 + false
111 158 end
112 159  
113 160 # The message that will be sent to the requestor of the task when the task is
... ...
app/models/task_mailer.rb
... ... @@ -17,7 +17,7 @@ class TaskMailer &lt; ActionMailer::Base
17 17 url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.url.merge(:controller => 'tasks', :action => 'index'))
18 18  
19 19 from self.class.generate_from(task)
20   - subject '[%s] %s' % [task.environment.name, task.description]
  20 + subject '[%s] %s' % [task.environment.name, task.information]
21 21 body :target => task.target.name,
22 22 :message => msg,
23 23 :environment => task.environment.name,
... ... @@ -32,7 +32,7 @@ class TaskMailer &lt; ActionMailer::Base
32 32 recipients task.friend_email
33 33  
34 34 from self.class.generate_from(task)
35   - subject '[%s] %s' % [ task.requestor.environment.name, task.description ]
  35 + subject '[%s] %s' % [ task.requestor.environment.name, task.information ]
36 36 body :message => msg
37 37 end
38 38  
... ... @@ -52,7 +52,7 @@ class TaskMailer &lt; ActionMailer::Base
52 52  
53 53 recipients task.requestor.notification_emails
54 54 from self.class.generate_from(task)
55   - subject '[%s] %s' % [task.requestor.environment.name, task.description]
  55 + subject '[%s] %s' % [task.requestor.environment.name, task.information]
56 56 body :requestor => task.requestor.name,
57 57 :message => text,
58 58 :environment => task.requestor.environment.name,
... ...
app/models/ticket.rb
1 1 class Ticket < Task
2 2 acts_as_having_settings :field => :data
3   - settings_items :title, :description, :closing_statment
  3 + settings_items :title, :message
4 4 end
... ...
app/views/pending_task_notifier/notification.rhtml
... ... @@ -11,7 +11,7 @@
11 11 <% pending_tasks = @person.pending_tasks_for_organization(organization) %>
12 12 <%= _("%s has %d pending task(s).") % [organization.name, pending_tasks.size] %>
13 13  
14   -<%= pending_tasks.map{|i| " * #{i.description}"}.join("\n") %>
  14 +<%= pending_tasks.map{|i| " * #{i.information}"}.join("\n") %>
15 15  
16 16 <%= _("Click in address below to process task(s):") %>
17 17  
... ...
app/views/profile_editor/_pending_tasks.rhtml
  1 +<%= stylesheet_link_tag 'tasks' %>
  2 +
1 3 <% unless @pending_tasks.empty? %>
2 4 <div class='pending-tasks'>
3 5 <h2><%= _('You have pending requests') %></h2>
4 6 <ul>
5   - <%= @pending_tasks.map {|item| content_tag('li', item.description)} %>
  7 + <%= @pending_tasks.map {|task| content_tag('li', task_information(task))} %>
6 8 </ul>
7 9 <%= button(:todo, _('Process requests'), :controller => 'tasks', :action => 'index') %>
8 10 </div>
... ...
app/views/tasks/_add_friend.rhtml
... ... @@ -1,40 +0,0 @@
1   -<h2><%= _('New friend') %></h2>
2   -
3   -<%= link_to( profile_image(task.requestor, :minor, :border => 0), task.requestor.public_profile_url ) %>
4   -
5   -<%= _('%s wants to be your friend.') %
6   - content_tag('strong', link_to( task.requestor.name, task.requestor.public_profile_url ) ) %>
7   -
8   -<% form_for('task', task, :url => { :action => 'close', :id => task.id } ) do |f| %>
9   -
10   - <div>
11   -
12   - <%= radio_button_tag(:decision, 'finish', true,
13   - :id => "decision-finish-#{task.id}",
14   - :onclick => "Element.show('group-for-friend-#{task.id}')") %>
15   - <label for="<%= "decision-finish-#{task.id}" %>"><b><%= _('Accept') %></b></label>
16   -
17   - &nbsp; &nbsp;
18   -
19   - <%= radio_button_tag(:decision, 'cancel', false,
20   - :id => "decision-cancel-#{task.id}",
21   - :onclick => "Element.hide('group-for-friend-#{task.id}')") %>
22   - <label for="<%= "decision-cancel-#{task.id}" %>"><b><%= _('Ignore') %></b></label>
23   -
24   - <% content_tag('div', :id => "group-for-friend-#{task.id}", :class => "add-friend-tags") do %>
25   - <%= _('Classify your new friend:') %>
26   - <%= text_field_with_local_autocomplete("task[group_for_friend]",
27   - profile.suggested_friend_groups,
28   - {:id => "field-group-for-friend-#{task.id}", :maxlength => 150}) %>
29   -
30   - <p class="friend-classify-suggestions">
31   - <%= _('Suggestions: %s') % profile.suggested_friend_groups.join(', ') %>
32   - </p>
33   - <% end %>
34   -
35   - </div>
36   -
37   - <% button_bar do %>
38   - <%= submit_button(:ok, _('Ok!')) %>
39   - <% end %>
40   -<% end %>
app/views/tasks/_add_friend_accept_details.rhtml 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<%=_('Classify your new friend:') +
  2 +text_field_with_local_autocomplete("tasks[#{task.id}][task][group_for_friend]",
  3 + task.target.suggested_friend_groups,
  4 + {:id => "field-group-for-friend-#{task.id}", :maxlength => 150})
  5 +%>
  6 +<p class="friend-classify-suggestions">
  7 + <%=_('Suggestions: %s') % task.target.suggested_friend_groups.join(', ') %>
  8 +</p>
... ...
app/views/tasks/_add_member.rhtml
... ... @@ -1,38 +0,0 @@
1   -<h2><%= _('New member') %></h2>
2   -
3   -<%= link_to( profile_image(task.requestor, :minor, :border => 0), task.requestor.public_profile_url ) %>
4   -
5   -<%= _('%s wants to be a member of %s.') %
6   - [content_tag('strong', link_to( task.requestor.name, task.requestor.public_profile_url ) ),
7   - content_tag('strong', link_to( task.target.name, task.target.public_profile_url ) )] %>
8   -
9   -<% form_for('task', task, :url => { :action => 'close', :id => task.id } ) do |f| %>
10   -
11   - <div>
12   - <%= radio_button_tag(:decision, 'finish', true,
13   - :id => "decision-finish-#{task.id}",
14   - :onclick => "Element.show('group-for-friend-#{task.id}')") %>
15   - <label for="<%= "decision-finish-#{task.id}" %>"><b><%= _('Accept') %></b></label>
16   -
17   - &nbsp; &nbsp;
18   -
19   - <%= radio_button_tag(:decision, 'cancel', false,
20   - :id => "decision-cancel-#{task.id}",
21   - :onclick => "Element.hide('group-for-friend-#{task.id}')") %>
22   - <label for="<%= "decision-cancel-#{task.id}" %>"><b><%= _('Ignore') %></b></label>
23   -
24   - <p class="member-classify-suggestions">
25   - <%= _('Roles:') %> <br>
26   - <%
27   - @roles = task.target.environment.roles.find(:all).select{ |r| r.has_kind?('Profile') }
28   - %>
29   - <% @roles.each do |r| %>
30   - <%= labelled_check_box(r.name, 'task[roles][]', r.id, ( task.target.members.empty? ? true : ( r.id == Profile::Roles.member(r.environment.id).id ) ) ) %><br/>
31   - <% end %>
32   - </p>
33   - </div>
34   -
35   - <% button_bar do %>
36   - <%= submit_button(:ok, _('Ok!')) %>
37   - <% end %>
38   -<% end %>
app/views/tasks/_add_member_accept_details.rhtml 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<%= content = _("Roles:")+"<br />"
  2 +roles = Profile::Roles.organization_member_roles(task.target.environment.id)
  3 +roles.each do |role|
  4 + content += labelled_check_box(role.name, "tasks[#{task.id}][roles][]", role.id, false)+"<br />"
  5 +end
  6 +content_tag('p', content, :class => 'member-classify-suggestion')
  7 +%>
  8 +
... ...
app/views/tasks/_approve_article.rhtml
... ... @@ -1,43 +0,0 @@
1   -<h2><%= _('New article') %></h2>
2   -
3   -<% form_for('task', task, :url => { :action => 'close', :id => task.id } ) do |f| %>
4   -
5   - <% if task.article.nil? %>
6   - <%= _('%s wanted to publish some content, but this content was deleted and cannot be published anymore.') % content_tag('strong', link_to( task.requestor.name, task.requestor.public_profile_url ) ) %>
7   - <%= hidden_field_tag(:decision, 'cancel') %>
8   - <% else %>
9   - <%= _('%s wants to publish content: %s.') %
10   - [content_tag('strong', link_to( task.requestor.name, task.requestor.public_profile_url ) ),
11   - content_tag('strong', link_to( task.article.name, task.article.url ) )] %>
12   -
13   - <div>
14   - <%= radio_button_tag(:decision, 'finish', true,
15   - :id => "decision-finish-#{task.id}",
16   - :onclick => "Element.show('group-for-friend-#{task.id}')") %>
17   - <label for="<%= "decision-finish-#{task.id}" %>"><b><%= _('Accept') %></b></label>
18   -
19   - &nbsp; &nbsp;
20   -
21   - <%= radio_button_tag(:decision, 'cancel', false,
22   - :id => "decision-cancel-#{task.id}",
23   - :onclick => "Element.hide('group-for-friend-#{task.id}')") %>
24   - <label for="<%= "decision-cancel-#{task.id}" %>"><b><%= _('Ignore') %></b></label>
25   -
26   - <%= labelled_form_field _('Name for publishing'), f.text_field(:name, :style => 'width:80%;') %>
27   -
28   - <%= select_folder(_('Select the folder where the article must be published'), 'task', 'article_parent_id', task.target.folders) %>
29   - <div>
30   - <%= f.check_box(:highlighted) %>
31   - <label for="article_highlighted"><%= _('Highlight this article')%></label>
32   - </div>
33   -
34   - <%= labelled_form_field _('Comment for author'), f.text_field(:closing_statment, :style => 'width:80%;') %>
35   - <%= render :partial => partial_for_class(task.article.class), :locals => { :f => f } %>
36   -
37   - </div>
38   - <% end %>
39   -
40   - <% button_bar do %>
41   - <%= submit_button(:ok, _('Ok!')) %>
42   - <% end %>
43   -<% end %>
app/views/tasks/_approve_article_accept_details.rhtml 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +<%= labelled_form_field(_('Name for publishing'), f.text_field(:name)) %>
  2 +<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task]", 'article_parent_id', task.target) %>
  3 +<%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %>
  4 +
  5 +<div>
  6 + <%= labelled_form_field(_('Lead'), f.text_area(:abstract, :style => 'width: 482px; height: 200px;')) %>
  7 +</div>
  8 +<em><%= _('Used when a short version your text is needed.') %></em>
  9 +
  10 +<div style="margin-top: 10px;">
  11 + <%= labelled_form_field(_('Text'), f.text_area(:body, :style => 'width:482px; height: 500px;')) %>
  12 +</div>
  13 +<%= labelled_form_field _('Comment for author'), f.text_field(:closing_statment, :style => 'width: 488px;') %>
  14 +
... ...
app/views/tasks/_create_community.rhtml
... ... @@ -1,47 +0,0 @@
1   -<h2><%= _('New community') %></h2>
2   -
3   -<%= link_to( profile_image(task.requestor, :minor, :border => 0), task.requestor.public_profile_url ) %>
4   -
5   -<%= _('%s wants to create community %s.') %
6   - [content_tag('strong', link_to( task.requestor.name, task.requestor.public_profile_url ) ),
7   - content_tag('strong', task.name )] %>
8   -
9   -<% form_for('task', task, :url => { :action => 'close', :id => task.id } ) do |f| %>
10   -
11   - <div>
12   - <% if !Profile.is_available?(task.name.to_slug, environment) %>
13   - <p><b><%= _('This name was already taken, this community cannot be approved') %></b></p>
14   - <%= hidden_field_tag(:decision, 'cancel') %>
15   - <% else %>
16   - <%= radio_button_tag(:decision, 'finish', true,
17   - :id => "decision-finish-#{task.id}",
18   - :onclick => "hide_closing_statement_area(#{task.id})") %>
19   - <label for="<%= "decision-finish-#{task.id}" %>"><b><%= _('Approve') %></b></label>
20   -
21   - &nbsp; &nbsp;
22   -
23   - <%= radio_button_tag(:decision, 'cancel', false,
24   - :id => "decision-cancel-#{task.id}",
25   - :onclick => "show_closing_statement_area(#{task.id})") %>
26   - <label for="<%= "decision-cancel-#{task.id}" %>"><b><%= _('Reject') %></b></label>
27   - <% end %>
28   -
29   - <script type='text/javascript'>
30   - function show_closing_statement_area(id) {
31   - $('task-closing-statement-' + id).show();
32   - }
33   - function hide_closing_statement_area(id) {
34   - $('task-closing-statement-' + id).hide();
35   - }
36   - </script>
37   -
38   - <div style='display:none' id=<%= "task-closing-statement-#{task.id}" %> >
39   - <%= labelled_form_field _('Please provide an explanation for the rejection'), f.text_area(:closing_statement, :style => 'height:200px; width:80%;') %>
40   - </div>
41   -
42   - </div>
43   -
44   - <% button_bar do %>
45   - <%= submit_button(:ok, _('Ok!')) %>
46   - <% end %>
47   -<% end %>
app/views/tasks/_create_enterprise_reject_details.rhtml 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +<%= required labelled_form_field(_('Rejection explanation'), f.text_area(:reject_explanation, :rows => 5)) %>
  2 +
... ...
app/views/tasks/_invite_friend.rhtml
... ... @@ -1 +0,0 @@
1   -<%= render :partial => 'add_friend', :locals => {:task => task} %>
app/views/tasks/_invite_friend_accept_details.rhtml 0 → 120000
... ... @@ -0,0 +1 @@
  1 +_add_friend_accept_details.rhtml
0 2 \ No newline at end of file
... ...
app/views/tasks/_invite_member.rhtml
... ... @@ -1,29 +0,0 @@
1   -<h2><%= _('Join community') %></h2>
2   -
3   -<%= link_to( profile_image(task.requestor, :minor, :border => 0), task.requestor.public_profile_url ) %>
4   -
5   -<%= _('%s invited you to join the community %s') %
6   - [content_tag('strong', link_to( task.requestor.name, task.requestor.public_profile_url ) ),
7   - content_tag('strong', link_to( task.community.name, task.community.public_profile_url ) )] %>
8   -
9   -<% form_for('task', task, :url => { :action => 'close', :id => task.id } ) do |f| %>
10   -
11   - <div>
12   - <%= radio_button_tag(:decision, 'finish', true,
13   - :id => "decision-finish-#{task.id}",
14   - :onclick => "Element.show('group-for-friend-#{task.id}')") %>
15   - <label for="<%= "decision-finish-#{task.id}" %>"><b><%= _('Accept') %></b></label>
16   -
17   - &nbsp; &nbsp;
18   -
19   - <%= radio_button_tag(:decision, 'cancel', false,
20   - :id => "decision-cancel-#{task.id}",
21   - :onclick => "Element.hide('group-for-friend-#{task.id}')") %>
22   - <label for="<%= "decision-cancel-#{task.id}" %>"><b><%= _('Reject') %></b></label>
23   -
24   - </div>
25   -
26   - <% button_bar do %>
27   - <%= submit_button(:ok, _('Ok!')) %>
28   - <% end %>
29   -<% end %>
app/views/tasks/_suggest_article.rhtml
... ... @@ -1,41 +0,0 @@
1   -<h2><%= _('Processing task: %s') % task.description %></h2>
2   -
3   -<%= render :file => 'shared/tiny_mce' %>
4   -
5   -<% form_for('task', task, :url => { :action => 'close', :id => task.id}) do |f| %>
6   -
7   -
8   - <%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>
9   - <p><%= label_tag(_("Email: %s") % task.email) %> </p>
10   - <%= required labelled_form_field(_('Title'), f.text_field(:article_name, :size => 50)) %>
11   - <%= labelled_form_field(_('Source'), f.text_field(:source_name)) %>
12   - <%= labelled_form_field(_("Source URL"), f.text_field(:source)) %>
13   -
14   - <%= select_folder(_('Select the folder where the article must be published'), 'task', 'article_parent_id', task.target.folders) %>
15   -
16   - <br style="clear: both;"/>
17   - <%= button :add, _("Lead"), '#', :id => "lead-button", :style => "margin-left: 0px;" %>
18   - <em><%= _('Used when a short version your text is needed.') %></em>
19   -
20   - <div id="article-lead">
21   - <%= labelled_form_field(_('Lead'), text_area_tag('task[article_abstract]', task.article_abstract, :style => 'width: 100%; height: 200px;')) %>
22   - </div>
23   - <div style="margin-top: 10px;">
24   - <%= labelled_form_field(_('Text'), text_area_tag('task[article_body]', task.article_body, :style => 'width:100%; height: 500px;')) %>
25   - </div>
26   -
27   - <div>
28   - <%= labelled_radio_button _('OK'), :decision, 'finish', true, :onclick => "if(this.checked) $('rejection-field-#{task.id}').style.display='none'" %>
29   - </div>
30   - <div>
31   - <%= labelled_radio_button _('Cancel'), :decision, 'cancel', false, :onclick => "if(this.checked) $('rejection-field-#{task.id}').style.display='block'" %>
32   - </div>
33   -
34   - <% button_bar do %>
35   - <%= submit_button(:ok, _('OK')) %>
36   - <% end %>
37   -
38   -<% end %>
39   -
40   -<%= javascript_include_tag 'article' %>
41   -
app/views/tasks/_suggest_article_accept_details.rhtml 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +<%= render :file => 'shared/tiny_mce' %>
  2 +
  3 +<%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>
  4 +<p><%= label_tag(_("Email: %s") % task.email) %> </p>
  5 +<%= required labelled_form_field(_('Title'), f.text_field(:article_name, :size => 50)) %>
  6 +<%= labelled_form_field(_('Source'), f.text_field(:source_name)) %>
  7 +<%= labelled_form_field(_("Source URL"), f.text_field(:source)) %>
  8 +
  9 +<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task]", 'article_parent_id', task.target) %>
  10 +
  11 +<div>
  12 + <%= labelled_form_field(_('Lead'), f.text_area(:article_abstract, :style => 'width: 482px; height: 200px;')) %>
  13 +</div>
  14 +<em><%= _('Used when a short version your text is needed.') %></em>
  15 +
  16 +<div style="margin-top: 10px;">
  17 + <%= labelled_form_field(_('Text'), f.text_area(:article_body, :style => 'width:482px; height: 500px;')) %>
  18 +</div>
... ...
app/views/tasks/_task.rhtml
1   -<%# a generic task solver %>
2   -<h2><%= _('Processing task: %s') % task.description %></h2>
  1 +<div class="task_box">
3 2  
4   -<% form_for('task', task, :url => { :action => 'close', :id => task.id}) do |f| %>
  3 + <div class="task_icon">
  4 + <%
  5 + icon_info = task.icon
  6 + if icon_info[:type] == :profile_image
  7 + icon = profile_image(icon_info[:profile], :minor)
  8 + elsif icon_info[:type] == :defined_image
  9 + icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />"
  10 + end
  11 + %>
  12 + <%=
  13 + if icon_info[:url]
  14 + link_to(icon, icon_info[:url])
  15 + else
  16 + icon
  17 + end
  18 + %>
5 19  
6   - <div>
7   - <%= labelled_radio_button _('OK'), :decision, 'finish', true, :onclick => "if(this.checked) $('rejection-field-#{task.id}').style.display='none'" %>
8   - </div>
9   - <div>
10   - <%= labelled_radio_button _('Cancel'), :decision, 'cancel', false, :onclick => "if(this.checked) $('rejection-field-#{task.id}').style.display='block'" %>
11 20 </div>
12 21  
13   - <div id="rejection-field-<%= task.id %>" style='display: none'>
14   - <%= required labelled_form_field(_('Rejection explanation'), text_area(:task, :reject_explanation, :rows => 5))%>
  22 + <div class="task_decisions">
  23 + <%=
  24 + labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept',
  25 + :id => "decision-finish-#{task.id}",
  26 + :class => 'task_accept_radio',
  27 + :disabled => task.accept_disabled?,
  28 + :task_id => "#{task.id}") +
  29 + labelled_radio_button(_("Reject"), "tasks[#{task.id}][decision]", 'cancel', task.default_decision == 'reject',
  30 + :id => "decision-cancel-#{task.id}",
  31 + :class => 'task_reject_radio',
  32 + :disabled => task.reject_disabled?,
  33 + :task_id => "#{task.id}") +
  34 + labelled_radio_button(_("Skip"), "tasks[#{task.id}][decision]", 'skip', task.default_decision == 'skip',
  35 + :id => "decision-skip-#{task.id}",
  36 + :class => 'task_skip_radio',
  37 + :disabled => task.skip_disabled?,
  38 + :task_id => "#{task.id}")
  39 + %>
  40 + </div><!-- class="task_decisions" -->
  41 +
  42 + <strong class="task_title">
  43 + <%= task.title %>
  44 + </strong>
  45 +
  46 + <div class="task_information">
  47 + <%= task_information(task) %>
15 48 </div>
16 49  
17   - <% button_bar do %>
18   - <%= submit_button(:ok, _('OK')) %>
  50 + <% fields_for "tasks[#{task.id}][task]", task do |f| %>
  51 + <% if task.accept_details %>
  52 + <div id="on-accept-information-<%=task.id%>" style="display: none">
  53 + <%= render :partial => partial_for_task_class(task.class, :accept_details), :locals => {:task => task, :f => f} %>
  54 + </div>
  55 + <% end %>
  56 +
  57 + <% if task.reject_details %>
  58 + <div id="on-reject-information-<%=task.id%>" style="display: none">
  59 + <%= render :partial => partial_for_task_class(task.class, :reject_details), :locals => {:task => task, :f => f} %>
  60 + </div>
  61 + <% end %>
19 62 <% end %>
20 63  
21   -<% end %>
  64 +</div><!-- class="task_box" -->
... ...
app/views/tasks/_task_reject_details.rhtml 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= labelled_form_field(_('Rejection explanation'), f.text_area(:reject_explanation, :rows => 5)) %>
... ...
app/views/tasks/_ticket.rhtml
... ... @@ -1,22 +0,0 @@
1   -<h2><%= _('Processing ticket: %s') % task.title %></h2>
2   -
3   -<%= task.description %>
4   -
5   -<% form_for('task', task, :url => { :action => 'close', :id => task.id}) do |f| %>
6   -
7   - <%= labelled_form_field(_('Closing statment'), f.text_area(:closing_statment) ) %>
8   -
9   - <div>
10   - <%= radio_button_tag(:decision, 'finish', true) %>
11   - <%= _('OK') %>
12   - </div>
13   - <div>
14   - <%= radio_button_tag(:decision, 'cancel', false) %>
15   - <%= _('Cancel') %>
16   - </div>
17   -
18   - <% button_bar do %>
19   - <%= submit_button(:ok, _('OK')) %>
20   - <% end %>
21   -
22   -<% end %>
app/views/tasks/index.rhtml
1   -<h1><%= _("%s's pending tasks") % profile.name %></h1>
  1 +<%= stylesheet_link_tag 'tasks' %>
2 2  
  3 +<h1><%= _("%s's pending tasks") % profile.name %></h1>
3 4 <p>
  5 +
  6 +<% if !@failed.blank? %>
  7 + <div id="errorExplanation">
  8 + <% @failed.each do |error, tasks_descriptions|%>
  9 + <h2> <%= error %></h2>
  10 + <p><%=_("This error happened with the following tasks: ")%></p>
  11 + <ul>
  12 + <% tasks_descriptions.each do |description| %>
  13 + <li> <%= description %> </li>
  14 + <% end %>
  15 + </ul>
  16 + <% end %>
  17 + </div>
  18 +<% end %>
  19 +
4 20 <% if @tasks.empty? %>
5 21 <em><%= _('No pending tasks for %s') % profile.name %></em>
6 22 <% else %>
7   - <ul class='task-list'>
8   - <% @tasks.each do |item| %>
9   - <li class="task-<%= item.class %>"><%= render :partial => partial_for_class(item.class), :locals => { :task => item } %></li>
  23 + <% form_tag :action => 'close' do%>
  24 + <% button_bar do %>
  25 + <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
  26 + <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
  27 + <%= submit_button :save, _("Apply!") %>
  28 + <%= button(:edit, _('View processed tasks'), :action => 'processed') %>
  29 + <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
10 30 <% end %>
11   - </ul>
  31 +
  32 + <ul class='task-list'>
  33 + <p>
  34 + <%= labelled_select(_("Set all to: "), 'set-decisions', 'downcase', 'to_s', nil, ["","Accept", "Reject", "Skip"], :id => "up-set-all-tasks-to") %>
  35 + </p>
  36 + <% @tasks.each do |task| %>
  37 + <%= render :partial => 'task', :locals => { :task => task } %>
  38 + <% end %>
  39 + <p>
  40 + <%= labelled_select(_("Set all to: "), 'set-decisions', 'downcase', 'to_s', nil, ["","Accept", "Reject", "Skip"], :id => "down-set-all-tasks-to") %>
  41 + </p>
  42 + </ul>
  43 +
  44 + <% button_bar do %>
  45 + <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
  46 + <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
  47 + <%= submit_button :save, _("Apply!") %>
  48 + <%= button(:edit, _('View processed tasks'), :action => 'processed') %>
  49 + <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
  50 + <% end %>
  51 + <% end %>
12 52 <% end %>
13 53 </p>
14 54  
15   -<% button_bar do %>
16   - <%= button(:edit, _('View processed tasks'), :action => 'processed') %>
17   - <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %>
18   - <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %>
19   - <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
20   -<% end %>
  55 +
  56 +<%= javascript_include_tag 'tasks' %>
... ...
app/views/tasks/list_requested.rhtml
... ... @@ -3,7 +3,7 @@
3 3 <ul>
4 4 <% @tasks.each do |task| %>
5 5 <li>
6   - <strong><%= task.respond_to?(:title) ? link_to( task.title, :action => 'ticket_details', :id => task.id) : task.description %></strong><br/>
  6 + <strong><%= task.respond_to?(:title) ? link_to( task.title, :action => 'ticket_details', :id => task.id) : task.information %></strong><br/>
7 7 <small>
8 8 <%= _('Created:') + ' ' + show_date(task.created_at) %>
9 9 &nbsp; &#151; &nbsp;
... ...
app/views/tasks/new.rhtml
... ... @@ -9,7 +9,7 @@
9 9 <% end %>
10 10 <%= hidden_field_tag 'ticket[target_type]', 'Profile' %>
11 11 <%= f.text_field :title, :style => 'width:80%;' %>
12   - <%= f.text_area :description, :style => 'height:200px; width:80%;' %>
  12 + <%= f.text_area :message, :style => 'height:200px; width:80%;' %>
13 13  
14 14 <% button_bar do %>
15 15 <%= submit_button(:ok, _('Send'), :cancel => {:action => 'index'}) %>
... ...
app/views/tasks/processed.rhtml
... ... @@ -7,7 +7,7 @@
7 7 <ul>
8 8 <% @tasks.each do |item| %>
9 9 <li>
10   - <strong><%= item.description %></strong> <br/>
  10 + <strong><%= item.information %></strong> <br/>
11 11 <small>
12 12 <%= _('Created:') +' '+ show_date(item.created_at) %>
13 13 &nbsp; &#151; &nbsp;
... ...
features/approve_article.feature
... ... @@ -28,7 +28,8 @@ Feature: approve article
28 28 And I go to Sample Community's control panel
29 29 And I follow "Process requests"
30 30 And I fill in "Text" with "This is an article edited"
31   - And I press "Ok!"
  31 + And I choose "Accept"
  32 + And I press "Apply!"
32 33 And I go to Sample Community's sitemap
33 34 When I follow "Sample Article"
34 35 Then I should see "This is an article edited"
... ...
features/create_community.feature
... ... @@ -51,8 +51,8 @@ Feature: create community
51 51 And I go to the Control panel
52 52 And I follow "Process requests"
53 53 And I should see "admin_user wants to create community Community for approval"
54   - And I choose "Approve"
55   - When I press "Ok!"
  54 + And I choose "Accept"
  55 + When I press "Apply!"
56 56 Then I should not see "admin_user wants to create community Community for approval"
57 57 When I go to the Control panel
58 58 And I follow "Manage my groups"
... ... @@ -66,7 +66,7 @@ Feature: create community
66 66 And I follow "Process requests"
67 67 And I should see "admin_user wants to create community Community for approval"
68 68 And I choose "Reject"
69   - When I press "Ok!"
  69 + When I press "Apply!"
70 70 Then I should not see "admin_user wants to create community Community for approval"
71 71 When I go to the Control panel
72 72 And I follow "Manage my groups"
... ... @@ -89,12 +89,3 @@ Feature: create community
89 89 When I go to the Control panel
90 90 And I follow "Manage my groups"
91 91 Then I should not see "Community for approval"
92   -
93   - Scenario: environment admin accepts new community task but identifier was already taken
94   - Given I am logged in as admin
95   - And feature "admin_must_approve_new_communities" is enabled on environment
96   - And I create community "Community for approval"
97   - And I create community "Community for approval"
98   - When I approve community "Community for approval"
99   - Then I should see "This name was already taken, this community cannot be approved"
100   - And I should see "admin_user wants to create community Community for approval"
... ...
features/invitation.feature
... ... @@ -93,7 +93,7 @@ Feature: invitation
93 93 Given there are no pending jobs
94 94 When I am logged in as "josesantos"
95 95 And I go to the Control panel
96   - And I should see "josesilva invited you to join the community 26 Bsslines"
  96 + And I should see "josesilva invited you to join 26 Bsslines."
97 97  
98 98 Scenario: noosfero user accepts to join community
99 99 Given I invite email "santos@invalid.br" to join community "26 Bsslines"
... ... @@ -101,10 +101,10 @@ Feature: invitation
101 101 When I am logged in as "josesantos"
102 102 And I go to the Control panel
103 103 And I follow "Process requests"
104   - And I should see "josesilva invited you to join the community 26 Bsslines"
  104 + And I should see "josesilva invited you to join 26 Bsslines."
105 105 And I choose "Accept"
106   - When I press "Ok!"
107   - Then I should not see "josesilva invited you to join the community 26 Bsslines"
  106 + When I press "Apply!"
  107 + Then I should not see "josesilva invited you to join 26 Bsslines."
108 108 When I go to the Control panel
109 109 And I follow "Manage my groups"
110 110 Then I should see "26 Bsslines"
... ... @@ -115,10 +115,10 @@ Feature: invitation
115 115 When I am logged in as "josesantos"
116 116 And I go to the Control panel
117 117 And I follow "Process requests"
118   - And I should see "josesilva invited you to join the community 26 Bsslines"
  118 + And I should see "josesilva invited you to join 26 Bsslines."
119 119 And I choose "Reject"
120   - When I press "Ok!"
121   - Then I should not see "josesilva invited you to join the community 26 Bsslines"
  120 + When I press "Apply!"
  121 + Then I should not see "josesilva invited you to join 26 Bsslines."
122 122 When I go to the Control panel
123 123 And I follow "Manage my groups"
124 124 Then I should not see "26 Bsslines"
... ... @@ -135,7 +135,7 @@ Feature: invitation
135 135 When I am logged in as "josesantos"
136 136 And I go to the Control panel
137 137 And I follow "Process requests"
138   - And I should see "josesilva wants to be your friend."
  138 + Then I should see "josesilva wants to be your friend."
139 139  
140 140 Scenario: noosfero user accepts to be friend
141 141 Given I invite email "santos@invalid.br" to be my friend
... ... @@ -145,7 +145,7 @@ Feature: invitation
145 145 And I follow "Process requests"
146 146 And I should see "josesilva wants to be your friend."
147 147 And I choose "Accept"
148   - When I press "Ok!"
  148 + When I press "Apply!"
149 149 And I should not see "josesilva wants to be your friend."
150 150 When I go to the Control panel
151 151 And I follow "Manage friends"
... ... @@ -158,8 +158,8 @@ Feature: invitation
158 158 And I go to the Control panel
159 159 And I follow "Process requests"
160 160 And I should see "josesilva wants to be your friend."
161   - And I choose "Ignore"
162   - When I press "Ok!"
  161 + And I choose "Reject"
  162 + When I press "Apply!"
163 163 And I should not see "josesilva wants to be your friend."
164 164 When I go to the Control panel
165 165 And I follow "Manage friends"
... ...
features/publish_article.feature
... ... @@ -95,6 +95,33 @@ Feature: publish article
95 95 When I go to Another Community2's sitemap
96 96 Then I should see "Sample Article"
97 97  
  98 + Scenario: publishing articles with the same name in a moderated community
  99 + Given I am logged in as "joaosilva"
  100 + And "Joao Silva" is a member of "Sample Community"
  101 + And "Joao Silva" is admin of "Sample Community"
  102 + And I am on Sample Community's control panel
  103 + And I follow "Community Info and settings"
  104 + And I choose "profile_data_moderated_articles_true"
  105 + And I press "Save"
  106 + And I am on Joao Silva's control panel
  107 + And I follow "Manage Content"
  108 + And I follow "Spread"
  109 + And I check "Sample Community"
  110 + And I press "Spread this"
  111 + And I am on Joao Silva's control panel
  112 + And I follow "Manage Content"
  113 + And I follow "Spread"
  114 + And I check "Sample Community"
  115 + And I press "Spread this"
  116 + And I am on Sample Community's control panel
  117 + And I follow "Tasks"
  118 + And I choose "Accept"
  119 + And I press "Apply!"
  120 + And I should not see "The title (article name) is already being used by another article, please use another title."
  121 + And I choose "Accept"
  122 + When I press "Apply!"
  123 + Then I should see "The title (article name) is already being used by another article, please use another title."
  124 +
98 125 Scenario: ask to publish an article that was deleted before approval
99 126 Given I am logged in as "joaosilva"
100 127 And "Joao Silva" is admin of "Sample Community"
... ... @@ -110,6 +137,6 @@ Feature: publish article
110 137 And "joaosilva" has no articles
111 138 And I am on Sample Community's control panel
112 139 When I follow "Tasks"
113   - Then I should see /Joao Silva wanted.*deleted/
114   - And I press "Ok!"
115   - Then I should not see /Joao Silva wanted.*deleted/
  140 + Then I should see "The article was removed."
  141 + And I press "Apply!"
  142 + Then I should not see "The article was removed."
... ...
features/register_enterprise.feature
... ... @@ -94,9 +94,10 @@ Feature: register enterprise
94 94 And I am logged in as admin
95 95 And I go to the Control panel
96 96 When I follow "Tasks"
97   - Then I should see /Processing task: Enterprise registration: "My Enterprise"/
  97 + Then I should see "Joao Silva wants to create enterprise My Enterprise."
98 98 And the first mail is to admin_user@example.com
99   - And I press "Ok"
  99 + And I choose "Accept"
  100 + And I press "Apply!"
100 101 Then the last mail is to joaosilva@example.com
101 102 And I am logged in as "joaosilva"
102 103 And I am on Joao Silva's control panel
... ... @@ -120,11 +121,11 @@ Feature: register enterprise
120 121 And I am logged in as admin
121 122 And I go to the Control panel
122 123 When I follow "Tasks"
123   - Then I should see /Processing task: Enterprise registration: "My Enterprise"/
  124 + Then I should see "Joao Silva wants to create enterprise My Enterprise."
124 125 And the first mail is to admin_user@example.com
125   - And I choose "Cancel"
  126 + And I choose "Reject"
126 127 And I fill in "Rejection explanation" with "This enterprise has some irregularities."
127   - When I press "Ok"
  128 + And I press "Apply!"
128 129 Then the last mail is to joaosilva@example.com
129 130 And I am logged in as "joaosilva"
130 131 And I am on Joao Silva's control panel
... ... @@ -157,9 +158,9 @@ Feature: register enterprise
157 158 Then I should see "Enterprise registration completed"
158 159 And I am on Validator's control panel
159 160 When I follow "Tasks"
160   - Then I should see /Processing task: Enterprise registration: "My Enterprise"/
161   - And I choose "Ok"
162   - And I press "Ok"
  161 + Then I should see "Joao Silva wants to create enterprise My Enterprise."
  162 + And I choose "Accept"
  163 + And I press "Apply!"
163 164 And I am on Joao Silva's control panel
164 165 When I follow "Manage my groups"
165 166 Then I should see "My Enterprise"
... ... @@ -190,10 +191,10 @@ Feature: register enterprise
190 191 Then I should see "Enterprise registration completed"
191 192 And I am on Validator's control panel
192 193 When I follow "Tasks"
193   - Then I should see /Processing task: Enterprise registration: "My Enterprise"/
194   - And I choose "Cancel"
  194 + Then I should see "Joao Silva wants to create enterprise My Enterprise."
  195 + And I choose "Reject"
195 196 And I fill in "Rejection explanation" with "This enterprise has some irregularities."
196   - And I press "Ok"
  197 + And I press "Apply"
197 198 And I am on Joao Silva's control panel
198 199 When I follow "Manage my groups"
199 200 Then I should not see "My Enterprise"
... ...
features/step_definitions/create_community_steps.rb
... ... @@ -11,7 +11,7 @@ Given /^I approve community &quot;(.+)&quot;$/ do |community|
11 11 Given 'I go to the Control panel'
12 12 click_link('Process requests')
13 13 choose("decision-finish-#{task.id}")
14   - click_button('OK!')
  14 + click_button('Apply!')
15 15 end
16 16  
17 17 Given /^I reject community "(.+)"$/ do |community|
... ... @@ -19,5 +19,5 @@ Given /^I reject community &quot;(.+)&quot;$/ do |community|
19 19 Given 'I go to the Control panel'
20 20 click_link('Process requests')
21 21 choose("decision-cancel-#{task.id}")
22   - click_button('OK!')
  22 + click_button('Apply!')
23 23 end
... ...
public/images/icons-app/article-minor.png 0 → 100644

3 KB

public/images/icons-app/article-portrait.png 0 → 100644

2.69 KB

public/images/icons-app/article-thumb.png 0 → 100644

4.85 KB

public/images/icons-task/closed-arrow-hover.png 0 → 100644

216 Bytes

public/images/icons-task/closed-arrow.png 0 → 100644

204 Bytes

public/images/icons-task/opened-arrow-hover.png 0 → 100644

189 Bytes

public/images/icons-task/opened-arrow.png 0 → 100644

199 Bytes

public/img-source/article-icon.svg 0 → 100644
... ... @@ -0,0 +1,788 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
  3 +
  4 +<svg
  5 + xmlns:dc="http://purl.org/dc/elements/1.1/"
  6 + xmlns:cc="http://creativecommons.org/ns#"
  7 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  8 + xmlns:svg="http://www.w3.org/2000/svg"
  9 + xmlns="http://www.w3.org/2000/svg"
  10 + xmlns:xlink="http://www.w3.org/1999/xlink"
  11 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  12 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  13 + inkscape:export-ydpi="900"
  14 + inkscape:export-xdpi="900"
  15 + inkscape:export-filename="article.png"
  16 + sodipodi:docname="article-icon.svg"
  17 + inkscape:version="0.47pre4 r22446"
  18 + sodipodi:version="0.32"
  19 + id="svg249"
  20 + height="50"
  21 + width="50"
  22 + inkscape:output_extension="org.inkscape.output.svg.inkscape"
  23 + version="1.1">
  24 + <defs
  25 + id="defs3">
  26 + <linearGradient
  27 + inkscape:collect="always"
  28 + id="linearGradient4248">
  29 + <stop
  30 + style="stop-color:#ffcc00;stop-opacity:1"
  31 + offset="0"
  32 + id="stop4250" />
  33 + <stop
  34 + style="stop-color:#d40000;stop-opacity:1"
  35 + offset="1"
  36 + id="stop4252" />
  37 + </linearGradient>
  38 + <inkscape:perspective
  39 + sodipodi:type="inkscape:persp3d"
  40 + inkscape:vp_x="0 : 24 : 1"
  41 + inkscape:vp_y="0 : 1000 : 0"
  42 + inkscape:vp_z="48 : 24 : 1"
  43 + inkscape:persp3d-origin="24 : 16 : 1"
  44 + id="perspective91" />
  45 + <radialGradient
  46 + inkscape:collect="always"
  47 + xlink:href="#linearGradient5060"
  48 + id="radialGradient6719"
  49 + gradientUnits="userSpaceOnUse"
  50 + gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
  51 + cx="605.71429"
  52 + cy="486.64789"
  53 + fx="605.71429"
  54 + fy="486.64789"
  55 + r="117.14286" />
  56 + <linearGradient
  57 + inkscape:collect="always"
  58 + id="linearGradient5060">
  59 + <stop
  60 + style="stop-color:black;stop-opacity:1;"
  61 + offset="0"
  62 + id="stop5062" />
  63 + <stop
  64 + style="stop-color:black;stop-opacity:0;"
  65 + offset="1"
  66 + id="stop5064" />
  67 + </linearGradient>
  68 + <radialGradient
  69 + inkscape:collect="always"
  70 + xlink:href="#linearGradient5060"
  71 + id="radialGradient6717"
  72 + gradientUnits="userSpaceOnUse"
  73 + gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
  74 + cx="605.71429"
  75 + cy="486.64789"
  76 + fx="605.71429"
  77 + fy="486.64789"
  78 + r="117.14286" />
  79 + <linearGradient
  80 + id="linearGradient5048">
  81 + <stop
  82 + style="stop-color:black;stop-opacity:0;"
  83 + offset="0"
  84 + id="stop5050" />
  85 + <stop
  86 + id="stop5056"
  87 + offset="0.5"
  88 + style="stop-color:black;stop-opacity:1;" />
  89 + <stop
  90 + style="stop-color:black;stop-opacity:0;"
  91 + offset="1"
  92 + id="stop5052" />
  93 + </linearGradient>
  94 + <linearGradient
  95 + inkscape:collect="always"
  96 + xlink:href="#linearGradient5048"
  97 + id="linearGradient6715"
  98 + gradientUnits="userSpaceOnUse"
  99 + gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
  100 + x1="302.85715"
  101 + y1="366.64789"
  102 + x2="302.85715"
  103 + y2="609.50507" />
  104 + <linearGradient
  105 + id="linearGradient7648"
  106 + gradientUnits="userSpaceOnUse"
  107 + x1="21.9326"
  108 + y1="24.627399"
  109 + x2="21.9326"
  110 + y2="7.1090999">
  111 + <stop
  112 + offset="0"
  113 + style="stop-color:#8595bc;stop-opacity:1;"
  114 + id="stop7650" />
  115 + <stop
  116 + offset="1"
  117 + style="stop-color:#041a3b;stop-opacity:1;"
  118 + id="stop7652" />
  119 + </linearGradient>
  120 + <linearGradient
  121 + inkscape:collect="always"
  122 + id="linearGradient4542">
  123 + <stop
  124 + style="stop-color:#000000;stop-opacity:1;"
  125 + offset="0"
  126 + id="stop4544" />
  127 + <stop
  128 + style="stop-color:#000000;stop-opacity:0;"
  129 + offset="1"
  130 + id="stop4546" />
  131 + </linearGradient>
  132 + <linearGradient
  133 + id="linearGradient15662">
  134 + <stop
  135 + id="stop15664"
  136 + offset="0.0000000"
  137 + style="stop-color:#ffffff;stop-opacity:1.0000000;" />
  138 + <stop
  139 + id="stop15666"
  140 + offset="1.0000000"
  141 + style="stop-color:#f8f8f8;stop-opacity:1.0000000;" />
  142 + </linearGradient>
  143 + <radialGradient
  144 + id="aigrd3"
  145 + cx="20.892099"
  146 + cy="64.567902"
  147 + r="5.257"
  148 + fx="20.892099"
  149 + fy="64.567902"
  150 + gradientUnits="userSpaceOnUse">
  151 + <stop
  152 + offset="0"
  153 + style="stop-color:#F0F0F0"
  154 + id="stop15573" />
  155 + <stop
  156 + offset="1"
  157 + style="stop-color:#515151;stop-opacity:1;"
  158 + id="stop15575" />
  159 + </radialGradient>
  160 + <radialGradient
  161 + id="aigrd2"
  162 + cx="20.892099"
  163 + cy="114.5684"
  164 + r="5.256"
  165 + fx="20.892099"
  166 + fy="114.5684"
  167 + gradientUnits="userSpaceOnUse">
  168 + <stop
  169 + offset="0"
  170 + style="stop-color:#F0F0F0"
  171 + id="stop15566" />
  172 + <stop
  173 + offset="1.0000000"
  174 + style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
  175 + id="stop15568" />
  176 + </radialGradient>
  177 + <linearGradient
  178 + id="linearGradient269">
  179 + <stop
  180 + id="stop270"
  181 + offset="0.0000000"
  182 + style="stop-color:#a3a3a3;stop-opacity:1.0000000;" />
  183 + <stop
  184 + id="stop271"
  185 + offset="1.0000000"
  186 + style="stop-color:#4c4c4c;stop-opacity:1.0000000;" />
  187 + </linearGradient>
  188 + <linearGradient
  189 + id="linearGradient259">
  190 + <stop
  191 + id="stop260"
  192 + offset="0.0000000"
  193 + style="stop-color:#fafafa;stop-opacity:1.0000000;" />
  194 + <stop
  195 + id="stop261"
  196 + offset="1.0000000"
  197 + style="stop-color:#bbbbbb;stop-opacity:1.0000000;" />
  198 + </linearGradient>
  199 + <radialGradient
  200 + inkscape:collect="always"
  201 + xlink:href="#linearGradient269"
  202 + id="radialGradient15656"
  203 + gradientUnits="userSpaceOnUse"
  204 + gradientTransform="matrix(0.9980597,0,0,1.1091725,4.1760961,-0.6958675)"
  205 + cx="8.824419"
  206 + cy="3.7561285"
  207 + fx="8.824419"
  208 + fy="3.7561285"
  209 + r="37.751713" />
  210 + <radialGradient
  211 + inkscape:collect="always"
  212 + xlink:href="#linearGradient259"
  213 + id="radialGradient15658"
  214 + gradientUnits="userSpaceOnUse"
  215 + gradientTransform="matrix(0.99004037,0,0,1.1181563,0.71937872,-1.3901395)"
  216 + cx="33.966679"
  217 + cy="35.736916"
  218 + fx="33.966679"
  219 + fy="35.736916"
  220 + r="86.70845" />
  221 + <radialGradient
  222 + inkscape:collect="always"
  223 + xlink:href="#linearGradient15662"
  224 + id="radialGradient15668"
  225 + gradientUnits="userSpaceOnUse"
  226 + gradientTransform="matrix(1.0027787,0,0,1.1122543,4.0618664,-0.7125018)"
  227 + cx="8.1435566"
  228 + cy="7.2678967"
  229 + fx="8.1435566"
  230 + fy="7.2678967"
  231 + r="38.158695" />
  232 + <radialGradient
  233 + inkscape:collect="always"
  234 + xlink:href="#linearGradient4542"
  235 + id="radialGradient4548"
  236 + cx="24.306795"
  237 + cy="42.07798"
  238 + fx="24.306795"
  239 + fy="42.07798"
  240 + r="15.821514"
  241 + gradientTransform="matrix(1,0,0,0.284916,0,30.08928)"
  242 + gradientUnits="userSpaceOnUse" />
  243 + <inkscape:perspective
  244 + id="perspective3216"
  245 + inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
  246 + inkscape:vp_z="1 : 0.5 : 1"
  247 + inkscape:vp_y="0 : 1000 : 0"
  248 + inkscape:vp_x="0 : 0.5 : 1"
  249 + sodipodi:type="inkscape:persp3d" />
  250 + <radialGradient
  251 + r="28.622223"
  252 + fy="21.208994"
  253 + fx="25.103651"
  254 + cy="25.913044"
  255 + cx="28.347824"
  256 + gradientTransform="translate(2.0080471e-6,0)"
  257 + gradientUnits="userSpaceOnUse"
  258 + id="radialGradient3909"
  259 + xlink:href="#linearGradient3942"
  260 + inkscape:collect="always" />
  261 + <linearGradient
  262 + id="linearGradient3942">
  263 + <stop
  264 + id="stop3944"
  265 + offset="0"
  266 + style="stop-color:#f57900;stop-opacity:0;" />
  267 + <stop
  268 + id="stop3946"
  269 + offset="1"
  270 + style="stop-color:#cc0000;stop-opacity:1" />
  271 + </linearGradient>
  272 + <mask
  273 + maskUnits="userSpaceOnUse"
  274 + id="mask3951">
  275 + <rect
  276 + style="color:#000000;fill:url(#linearGradient3955);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  277 + id="rect3953"
  278 + width="60.666664"
  279 + height="60.666664"
  280 + x="1.6666656"
  281 + y="1.6666654" />
  282 + </mask>
  283 + <linearGradient
  284 + inkscape:collect="always"
  285 + xlink:href="#linearGradient3795-2"
  286 + id="linearGradient3955"
  287 + gradientUnits="userSpaceOnUse"
  288 + gradientTransform="matrix(4.6666665,0,0,4.6666665,-10.000001,-28.666667)"
  289 + x1="9.500001"
  290 + y1="8.5"
  291 + x2="9.5"
  292 + y2="12.5" />
  293 + <linearGradient
  294 + inkscape:collect="always"
  295 + id="linearGradient3795-2">
  296 + <stop
  297 + style="stop-color:#000000;stop-opacity:1"
  298 + offset="0"
  299 + id="stop3797-1" />
  300 + <stop
  301 + style="stop-color:#ffffff;stop-opacity:1"
  302 + offset="1"
  303 + id="stop3799-3" />
  304 + </linearGradient>
  305 + <clipPath
  306 + clipPathUnits="userSpaceOnUse"
  307 + id="clipPath3975">
  308 + <path
  309 + sodipodi:nodetypes="cssscccsc"
  310 + id="path3977"
  311 + d="M 60,32 C 60,47.456 47.456,60 32,60 16.544,60 4,47.456 4,32 4,24.272 7.136,17.272 12.204,12.204 c 5.068,-5.068 13.334459,-23.280923 21.949843,-29.742461 -1.025992,6.66895 0,14.2153844 4.307693,18.52307669 0,0 0,-8.61538459 4.307692,-12.92307669 C 47.07692,0.98461569 50.523074,8.3076924 52.67692,12.172942 55.418861,17.093574 59.999999,22.388434 60,32 z"
  312 + style="opacity:0.6;color:#000000;fill:#73d216;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.30769205;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
  313 + </clipPath>
  314 + <filter
  315 + color-interpolation-filters="sRGB"
  316 + inkscape:collect="always"
  317 + id="filter3963"
  318 + x="-0.28615385"
  319 + width="1.5723077"
  320 + y="-0.20666666"
  321 + height="1.4133333">
  322 + <feGaussianBlur
  323 + inkscape:collect="always"
  324 + stdDeviation="6.676923"
  325 + id="feGaussianBlur3965" />
  326 + </filter>
  327 + <clipPath
  328 + clipPathUnits="userSpaceOnUse"
  329 + id="clipPath3878">
  330 + <path
  331 + sodipodi:nodetypes="csssssssc"
  332 + id="path3880"
  333 + d="m 27.200893,15.993392 c 0,6.150858 -4.991999,11.142858 -11.142856,11.142858 -6.150858,0 -11.142858,-4.992 -11.142858,-11.142858 0,-2.185214 1.714285,-5.954659 1.714285,-7.7142849 0,-8.57142868 5.832926,-12.0000001 10.285715,-12.0000001 1.714286,0 2.493799,1.946371 1.714286,3.42857146 -0.661208,1.25725054 -3.428572,1.71428574 -1.714286,3.42857144 1.212183,1.2121831 6.215414,4.1736984 7.020858,4.9791428 2.016856,2.0168573 3.264856,4.8025713 3.264856,7.8779993 z"
  334 + style="color:#000000;fill:#cc0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.71428561;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
  335 + </clipPath>
  336 + <filter
  337 + color-interpolation-filters="sRGB"
  338 + inkscape:collect="always"
  339 + id="filter3870"
  340 + x="-0.29058462"
  341 + width="1.5811692"
  342 + y="-0.20441557"
  343 + height="1.4088312">
  344 + <feGaussianBlur
  345 + inkscape:collect="always"
  346 + stdDeviation="2.459375"
  347 + id="feGaussianBlur3872" />
  348 + </filter>
  349 + <radialGradient
  350 + inkscape:collect="always"
  351 + xlink:href="#linearGradient3471-4"
  352 + id="radialGradient2759-9"
  353 + gradientUnits="userSpaceOnUse"
  354 + gradientTransform="translate(2.0080471e-6,0)"
  355 + cx="28.347824"
  356 + cy="25.913044"
  357 + fx="25.103651"
  358 + fy="21.208994"
  359 + r="28.622223" />
  360 + <linearGradient
  361 + id="linearGradient3471-4">
  362 + <stop
  363 + style="stop-color:#729fcf;stop-opacity:0;"
  364 + offset="0"
  365 + id="stop3473-7" />
  366 + <stop
  367 + style="stop-color:#204a87;stop-opacity:1"
  368 + offset="1"
  369 + id="stop3475-8" />
  370 + </linearGradient>
  371 + <mask
  372 + maskUnits="userSpaceOnUse"
  373 + id="mask3828">
  374 + <rect
  375 + y="1.6666656"
  376 + x="1.6666653"
  377 + height="60.666664"
  378 + width="60.666664"
  379 + id="rect3830"
  380 + style="color:#000000;fill:url(#linearGradient3832);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
  381 + </mask>
  382 + <linearGradient
  383 + inkscape:collect="always"
  384 + xlink:href="#linearGradient3795"
  385 + id="linearGradient3832"
  386 + gradientUnits="userSpaceOnUse"
  387 + gradientTransform="matrix(4.6666666,0,0,4.6666666,-10.000001,-28.666667)"
  388 + x1="8.5"
  389 + y1="8.5"
  390 + x2="9.5"
  391 + y2="12.5" />
  392 + <linearGradient
  393 + inkscape:collect="always"
  394 + id="linearGradient3795">
  395 + <stop
  396 + style="stop-color:#000000;stop-opacity:1"
  397 + offset="0"
  398 + id="stop3797" />
  399 + <stop
  400 + style="stop-color:#ffffff;stop-opacity:1"
  401 + offset="1"
  402 + id="stop3799" />
  403 + </linearGradient>
  404 + <radialGradient
  405 + inkscape:collect="always"
  406 + xlink:href="#linearGradient3471-4"
  407 + id="radialGradient3416"
  408 + gradientUnits="userSpaceOnUse"
  409 + gradientTransform="translate(2.0080471e-6,0)"
  410 + cx="28.347824"
  411 + cy="25.913044"
  412 + fx="25.103651"
  413 + fy="21.208994"
  414 + r="28.622223" />
  415 + <radialGradient
  416 + inkscape:collect="always"
  417 + xlink:href="#linearGradient3942"
  418 + id="radialGradient3428"
  419 + gradientUnits="userSpaceOnUse"
  420 + gradientTransform="translate(2.0080471e-6,0)"
  421 + cx="28.347824"
  422 + cy="25.913044"
  423 + fx="25.103651"
  424 + fy="21.208994"
  425 + r="28.622223" />
  426 + <radialGradient
  427 + inkscape:collect="always"
  428 + xlink:href="#linearGradient3942"
  429 + id="radialGradient3442"
  430 + gradientUnits="userSpaceOnUse"
  431 + gradientTransform="translate(2.0080471e-6,0)"
  432 + cx="28.347824"
  433 + cy="25.913044"
  434 + fx="25.103651"
  435 + fy="21.208994"
  436 + r="28.622223" />
  437 + <radialGradient
  438 + inkscape:collect="always"
  439 + xlink:href="#linearGradient4248"
  440 + id="radialGradient4254"
  441 + cx="16.000992"
  442 + cy="11.373981"
  443 + fx="16.000992"
  444 + fy="11.373981"
  445 + r="9.5902691"
  446 + gradientTransform="matrix(1.1061205,-0.39028044,0.43577759,1.235069,-6.3491962,4.30218)"
  447 + gradientUnits="userSpaceOnUse" />
  448 + </defs>
  449 + <sodipodi:namedview
  450 + inkscape:window-y="25"
  451 + inkscape:window-x="0"
  452 + inkscape:window-height="694"
  453 + inkscape:window-width="1024"
  454 + inkscape:document-units="px"
  455 + inkscape:grid-bbox="true"
  456 + showgrid="false"
  457 + inkscape:current-layer="layer5"
  458 + inkscape:cy="25"
  459 + inkscape:cx="24.886621"
  460 + inkscape:zoom="8.82"
  461 + inkscape:pageshadow="2"
  462 + inkscape:pageopacity="0.0"
  463 + borderopacity="0.25490196"
  464 + bordercolor="#666666"
  465 + pagecolor="#ffffff"
  466 + id="base"
  467 + inkscape:showpageshadow="false"
  468 + fill="#729fcf"
  469 + inkscape:window-maximized="1" />
  470 + <metadata
  471 + id="metadata4">
  472 + <rdf:RDF>
  473 + <cc:Work
  474 + rdf:about="">
  475 + <dc:format>image/svg+xml</dc:format>
  476 + <dc:type
  477 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  478 + <dc:title></dc:title>
  479 + <dc:subject>
  480 + <rdf:Bag>
  481 + <rdf:li>rich</rdf:li>
  482 + <rdf:li>text</rdf:li>
  483 + <rdf:li>document</rdf:li>
  484 + <rdf:li>pdf</rdf:li>
  485 + <rdf:li>openoffice</rdf:li>
  486 + <rdf:li>word</rdf:li>
  487 + <rdf:li>rtf</rdf:li>
  488 + </rdf:Bag>
  489 + </dc:subject>
  490 + <cc:license
  491 + rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
  492 + <dc:creator>
  493 + <cc:Agent>
  494 + <dc:title>Jakub Steiner</dc:title>
  495 + </cc:Agent>
  496 + </dc:creator>
  497 + <dc:source>http://jimmac.musichall.cz</dc:source>
  498 + </cc:Work>
  499 + <cc:License
  500 + rdf:about="http://creativecommons.org/licenses/publicdomain/">
  501 + <cc:permits
  502 + rdf:resource="http://creativecommons.org/ns#Reproduction" />
  503 + <cc:permits
  504 + rdf:resource="http://creativecommons.org/ns#Distribution" />
  505 + <cc:permits
  506 + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
  507 + </cc:License>
  508 + </rdf:RDF>
  509 + </metadata>
  510 + <g
  511 + inkscape:groupmode="layer"
  512 + id="layer6"
  513 + inkscape:label="Shadow">
  514 + <g
  515 + style="display:inline"
  516 + transform="matrix(0.02203962,0,0,0.02086758,45.477817,43.162522)"
  517 + id="g6707">
  518 + <rect
  519 + style="opacity:0.40206185;color:#000000;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
  520 + id="rect6709"
  521 + width="1339.6335"
  522 + height="478.35718"
  523 + x="-1559.2523"
  524 + y="-150.69685" />
  525 + <path
  526 + style="opacity:0.40206185;color:#000000;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
  527 + d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z"
  528 + id="path6711"
  529 + sodipodi:nodetypes="cccc" />
  530 + <path
  531 + sodipodi:nodetypes="cccc"
  532 + id="path6713"
  533 + d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z"
  534 + style="opacity:0.40206185;color:#000000;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
  535 + </g>
  536 + </g>
  537 + <g
  538 + style="display:inline"
  539 + inkscape:groupmode="layer"
  540 + inkscape:label="Base"
  541 + id="layer1">
  542 + <rect
  543 + style="color:#000000;fill:url(#radialGradient15658);fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1.05215013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:block;overflow:visible"
  544 + id="rect15391"
  545 + width="35.947849"
  546 + height="43.947849"
  547 + x="7.5260749"
  548 + y="2.5260756"
  549 + ry="1.2340567" />
  550 + <rect
  551 + style="color:#000000;fill:none;stroke:url(#radialGradient15668);stroke-width:1.05609882;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:block;overflow:visible"
  552 + id="rect15660"
  553 + width="33.943901"
  554 + height="41.943901"
  555 + x="8.5280485"
  556 + y="3.528048"
  557 + ry="0.16052011"
  558 + rx="0.1543601" />
  559 + <g
  560 + transform="translate(1.6464467,-0.0379893)"
  561 + id="g2270">
  562 + <g
  563 + id="g1440"
  564 + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4"
  565 + transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)">
  566 + <radialGradient
  567 + id="radialGradient1442"
  568 + cx="20.892099"
  569 + cy="114.5684"
  570 + r="5.256"
  571 + fx="20.892099"
  572 + fy="114.5684"
  573 + gradientUnits="userSpaceOnUse">
  574 + <stop
  575 + offset="0"
  576 + style="stop-color:#F0F0F0"
  577 + id="stop1444" />
  578 + <stop
  579 + offset="1"
  580 + style="stop-color:#474747"
  581 + id="stop1446" />
  582 + </radialGradient>
  583 + <path
  584 + style="stroke:none"
  585 + d="m 23.428,113.07 c 0,1.973 -1.6,3.572 -3.573,3.572 -1.974,0 -3.573,-1.6 -3.573,-3.572 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z"
  586 + id="path1448" />
  587 + <radialGradient
  588 + id="radialGradient1450"
  589 + cx="20.892099"
  590 + cy="64.567902"
  591 + r="5.257"
  592 + fx="20.892099"
  593 + fy="64.567902"
  594 + gradientUnits="userSpaceOnUse">
  595 + <stop
  596 + offset="0"
  597 + style="stop-color:#F0F0F0"
  598 + id="stop1452" />
  599 + <stop
  600 + offset="1"
  601 + style="stop-color:#474747"
  602 + id="stop1454" />
  603 + </radialGradient>
  604 + <path
  605 + style="stroke:none"
  606 + d="m 23.428,63.07 c 0,1.973 -1.6,3.573 -3.573,3.573 -1.974,0 -3.573,-1.6 -3.573,-3.573 0,-1.974 1.6,-3.573 3.573,-3.573 1.973,0 3.573,1.6 3.573,3.573 z"
  607 + id="path1456" />
  608 + </g>
  609 + <path
  610 + style="fill:#4d4d4d;fill-rule:nonzero;stroke:none"
  611 + d="m 9.9950109,29.952326 c 0,0.453204 -0.3675248,0.820499 -0.8207288,0.820499 -0.4534338,0 -0.8207289,-0.367524 -0.8207289,-0.820499 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z"
  612 + id="path15570" />
  613 + <path
  614 + style="fill:#4d4d4d;fill-rule:nonzero;stroke:none"
  615 + d="m 9.9950109,18.467176 c 0,0.453204 -0.3675248,0.820729 -0.8207288,0.820729 -0.4534338,0 -0.8207289,-0.367525 -0.8207289,-0.820729 0,-0.453434 0.3675248,-0.820729 0.8207289,-0.820729 0.453204,0 0.8207288,0.367525 0.8207288,0.820729 z"
  616 + id="path15577" />
  617 + </g>
  618 + <path
  619 + style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.01333487;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
  620 + d="m 12.506667,4.0973012 0,40.8551318"
  621 + id="path15672"
  622 + sodipodi:nodetypes="cc" />
  623 + <path
  624 + style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1.02506876;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
  625 + d="m 13.512534,4.0125702 0,40.9748958"
  626 + id="path15674"
  627 + sodipodi:nodetypes="cc" />
  628 + </g>
  629 + <g
  630 + inkscape:groupmode="layer"
  631 + id="layer5"
  632 + inkscape:label="Text"
  633 + style="display:inline">
  634 + <rect
  635 + ry="0.065390877"
  636 + rx="0.096450485"
  637 + y="41"
  638 + x="17"
  639 + height="1"
  640 + width="14.000014"
  641 + id="rect15744"
  642 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
  643 + <rect
  644 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
  645 + id="rect1768"
  646 + width="20.000006"
  647 + height="1"
  648 + x="17"
  649 + y="11.000006"
  650 + rx="0.13778631"
  651 + ry="0.065390877" />
  652 + <g
  653 + transform="matrix(0.58333333,0,0,0.58333333,23.082298,18.666667)"
  654 + id="g2782">
  655 + <path
  656 + sodipodi:nodetypes="cscccss"
  657 + id="path3991"
  658 + d="M 16.186589,21.142857 C 10.932592,21.442092 5.8719316,14.98028 8.1220005,8.1219995 9.0674911,5.2401146 13.42857,-1.1428578 16.857142,-3.7142862 c -0.408303,2.6539699 0,5.6571428 1.714286,7.3714286 0,0 0,-3.42857151 1.714285,-5.1428572 1.714286,5.1428572 3.271486,7.9716527 3.942857,9.5953544 2.058215,4.9777654 0.483956,12.5476324 -8.041981,13.0332174 z"
  659 + style="color:#000000;fill:url(#radialGradient4254);fill-opacity:1;stroke:#a40000;stroke-width:1.71428561;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
  660 + <path
  661 + sodipodi:type="inkscape:offset"
  662 + inkscape:radius="-1.5"
  663 + inkscape:original="M 16.84375 -3.71875 C 13.415178 -1.1473216 9.0704906 5.2431151 8.125 8.125 C 5.8749311 14.983281 10.933503 21.455485 16.1875 21.15625 C 24.713437 20.670665 26.276965 13.102765 24.21875 8.125 C 23.547379 6.5012983 21.995536 3.6428572 20.28125 -1.5 C 18.566965 0.21428569 18.5625 3.65625 18.5625 3.65625 C 16.848214 1.9419642 16.435447 -1.0647801 16.84375 -3.71875 z "
  664 + xlink:href="#path3991"
  665 + style="opacity:0.5;color:#000000;fill:none;stroke:#fcaf3e;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:9;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  666 + id="path3997"
  667 + inkscape:href="#path3991"
  668 + d="m 15.40625,-0.3125 c -0.903867,0.99041796 -1.796184,2.124373 -2.625,3.28125 -1.575827,2.1995678 -2.8557776,4.5186488 -3.21875,5.625 -1.9553465,5.959958 2.557716,11.288808 6.53125,11.0625 3.8265,-0.217934 5.732916,-1.852251 6.71875,-3.96875 0.985834,-2.116499 0.906542,-4.883117 0.03125,-7 -0.430922,-1.0421792 -1.493333,-3.2862791 -2.65625,-6.21875 -0.07263,0.5661553 -0.125,1.1875 -0.125,1.1875 A 1.50015,1.50015 0 0 1 17.5,4.71875 C 16.13821,3.3569603 15.617625,1.5548002 15.40625,-0.3125 z" />
  669 + </g>
  670 + <rect
  671 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
  672 + id="rect3450"
  673 + width="9.1020555"
  674 + height="1"
  675 + x="17"
  676 + y="22.538467"
  677 + rx="0.06270691"
  678 + ry="0.065390877" />
  679 + <rect
  680 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
  681 + id="rect3464"
  682 + width="20.000006"
  683 + height="1"
  684 + x="17"
  685 + y="38.692307"
  686 + rx="0.13778631"
  687 + ry="0.065390877" />
  688 + <rect
  689 + ry="0.065390877"
  690 + rx="0.13778631"
  691 + y="13.307699"
  692 + x="17"
  693 + height="1"
  694 + width="20.000006"
  695 + id="rect3466"
  696 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
  697 + <rect
  698 + ry="0.065390877"
  699 + rx="0.06270691"
  700 + y="24.846159"
  701 + x="17"
  702 + height="1"
  703 + width="9.1020555"
  704 + id="rect4256"
  705 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
  706 + <rect
  707 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
  708 + id="rect4258"
  709 + width="9.1020555"
  710 + height="1"
  711 + x="17"
  712 + y="27.153851"
  713 + rx="0.06270691"
  714 + ry="0.065390877" />
  715 + <rect
  716 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
  717 + id="rect4262"
  718 + width="9.1020555"
  719 + height="1"
  720 + x="17"
  721 + y="29.461542"
  722 + rx="0.06270691"
  723 + ry="0.065390877" />
  724 + <rect
  725 + ry="0.065390877"
  726 + rx="0.06270691"
  727 + y="31.769234"
  728 + x="17"
  729 + height="1"
  730 + width="9.1020555"
  731 + id="rect4264"
  732 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
  733 + <rect
  734 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
  735 + id="rect4268"
  736 + width="20.000006"
  737 + height="1"
  738 + x="17"
  739 + y="36.384617"
  740 + rx="0.13778631"
  741 + ry="0.065390877" />
  742 + <rect
  743 + ry="0.065390877"
  744 + rx="0.13778631"
  745 + y="34.076923"
  746 + x="17"
  747 + height="1"
  748 + width="20.000006"
  749 + id="rect4270"
  750 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
  751 + <rect
  752 + ry="0.065390877"
  753 + rx="0.06270691"
  754 + y="17.923084"
  755 + x="17"
  756 + height="1"
  757 + width="9.1020555"
  758 + id="rect4272"
  759 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
  760 + <rect
  761 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible"
  762 + id="rect4274"
  763 + width="9.1020555"
  764 + height="1"
  765 + x="17"
  766 + y="15.615393"
  767 + rx="0.06270691"
  768 + ry="0.065390877" />
  769 + <rect
  770 + ry="0.065390877"
  771 + rx="0.06270691"
  772 + y="20.230776"
  773 + x="17"
  774 + height="1"
  775 + width="9.1020555"
  776 + id="rect4278"
  777 + style="opacity:0.4;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible" />
  778 + <rect
  779 + ry="0.13078175"
  780 + rx="0.13778631"
  781 + y="7"
  782 + x="17"
  783 + height="2"
  784 + width="20.000006"
  785 + id="rect4280"
  786 + style="opacity:0.5;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:block;overflow:visible" />
  787 + </g>
  788 +</svg>
... ...
public/javascripts/tasks.js 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +(function($) {
  2 +
  3 + $("input.task_accept_radio").click(function(){
  4 + task_id = this.getAttribute("task_id");
  5 + $('#on-accept-information-' + task_id).show('fast');
  6 + $('#on-reject-information-' + task_id).hide('fast');
  7 + $('#on-skip-information-' + task_id).hide('fast');
  8 + })
  9 +
  10 + $("input.task_reject_radio").click(function(){
  11 + task_id = this.getAttribute("task_id");
  12 + $('#on-accept-information-' + task_id).hide('fast');
  13 + $('#on-reject-information-' + task_id).show('fast');
  14 + $('#on-skip-information-' + task_id).hide('fast');
  15 + })
  16 +
  17 + $("input.task_skip_radio").click(function(){
  18 + task_id = this.getAttribute("task_id");
  19 + $('#on-accept-information-' + task_id).hide('fast');
  20 + $('#on-reject-information-' + task_id).hide('fast');
  21 + $('#on-skip-information-' + task_id).show('fast');
  22 + })
  23 +
  24 + // There is probably an elegant way to do this...
  25 + $('#up-set-all-tasks-to').selectedIndex = 0;
  26 + $('#down-set-all-tasks-to').selectedIndex = 0;
  27 +
  28 + $('#down-set-all-tasks-to').change(function(){
  29 + value = $('#down-set-all-tasks-to').selected().val();
  30 + up = $('#up-set-all-tasks-to')
  31 + up.attr('value', value).change();
  32 + })
  33 +
  34 + $('#up-set-all-tasks-to').change(function(){
  35 + value = $('#up-set-all-tasks-to').selected().val();
  36 + down = $('#down-set-all-tasks-to')
  37 + down.attr('value', value);
  38 + $('.task_'+value+'_radio').each( function(){
  39 + if(!this.disabled){
  40 + $(this).attr('checked', 'checked').click();
  41 + }
  42 + })
  43 + })
  44 +
  45 + $('.task_title').css('margin-right', $('.task_decisions').width()+'px');
  46 + $('.task_title').css('margin-left', $('.task_arrow').width()+'px');
  47 +
  48 +})(jQuery)
  49 +
... ...
public/stylesheets/application.css
... ... @@ -305,7 +305,7 @@ div.auto-complete li.selected {
305 305 color: #204A87;
306 306 }
307 307  
308   -/* pending tasks list */
  308 +/* pending tasks */
309 309  
310 310 div.pending-tasks {
311 311 padding: 10px;
... ... @@ -313,6 +313,19 @@ div.pending-tasks {
313 313 margin-bottom: 20px;
314 314 }
315 315  
  316 +#pending-tasks-count {
  317 + padding-left: 5px;
  318 + padding-right: 5px;
  319 + margin-left: 2px;
  320 + text-decoration: none;
  321 + background-color: #F57900;
  322 + color: #FFFFFF;
  323 + -moz-border-radius: 2px;
  324 + -webkit-border-radius: 2px;
  325 + -khtml-border-radius: 2px;
  326 + border-radius: 2px;
  327 +}
  328 +
316 329 /* sitemap and agenda */
317 330  
318 331 .agenda-item a.icon,
... ...
public/stylesheets/tasks.css 0 → 100644
... ... @@ -0,0 +1,46 @@
  1 +.task_box {
  2 + position: relative;
  3 + border: 1px solid #888;
  4 + -moz-border-radius: 10px;
  5 + -webkit-border-radius: 10px;
  6 + -khtml-border-radius: 10px;
  7 + border-radius: 10px;
  8 + padding: 6px 4px 9px 4px;
  9 + margin-top: 5px;
  10 + background: #EEE;
  11 +}
  12 +
  13 +.task_title {
  14 + margin: 0px;
  15 + display: block;
  16 + line-height: 28px;
  17 + font-size: 120%;
  18 +}
  19 +
  20 +.task_icon {
  21 + float: left;
  22 + margin-right: 10px;
  23 + width: 50px;
  24 + height: 50px;
  25 + text-align: center;
  26 +}
  27 +
  28 +.task_decisions {
  29 + float: right;
  30 + padding-right: 5px;
  31 +}
  32 +
  33 +.task_information {
  34 + line-height: 18px;
  35 + padding: 2px 0px;
  36 + clear: right;
  37 +}
  38 +
  39 +.task_information p {
  40 + margin: 0px;
  41 +}
  42 +
  43 +.task_target {
  44 + text-decoration: underline;
  45 + font-weight: bold;
  46 +}
... ...
test/functional/tasks_controller_test.rb
... ... @@ -46,7 +46,7 @@ class TasksControllerTest &lt; Test::Unit::TestCase
46 46 should 'be able to finish a task' do
47 47 t = profile.tasks.build; t.save!
48 48  
49   - post :close, :decision => 'finish', :id => t.id
  49 + post :close, :tasks => {t.id => {:decision => 'finish', :task => {}}}
50 50 assert_redirected_to :action => 'index'
51 51  
52 52 t.reload
... ... @@ -56,52 +56,46 @@ class TasksControllerTest &lt; Test::Unit::TestCase
56 56 should 'be able to cancel a task' do
57 57 t = profile.tasks.build; t.save!
58 58  
59   - post :close, :decision => 'cancel', :id => t.id
  59 + post :close, :tasks => {t.id => {:decision => 'cancel', :task => {}}}
60 60 assert_redirected_to :action => 'index'
61 61  
62 62 t.reload
63 63 ok('task should be cancelled') { t.status == Task::Status::CANCELLED }
64 64 end
65 65  
66   - should 'affiliate roles to user after finish add member task' do
67   - t = AddMember.create!(:person => profile, :organization => profile)
68   - count = profile.members.size
69   - post :close, :decision => 'finish', :id => t.id
70   - profile = Profile.find(@profile.id)
71   - assert_equal count + 1, profile.members.size
72   - end
  66 + should 'be able to skip a task' do
  67 + t = profile.tasks.build; t.save!
73 68  
74   - should 'display custom form to add members task' do
75   - t = AddMember.create!(:person => profile, :organization => profile)
76   - get :index, :profile => profile.identifier
77   - assert_tag :tag => 'form', :attributes => { :action => "/myprofile/#{profile.identifier}/tasks/close/#{t.id}" }
78   - end
  69 + post :close, :tasks => {t.id => {:decision => 'skip', :task => {}}}
  70 + assert_redirected_to :action => 'index'
79 71  
80   - should 'display member role checked if target has members' do
81   - profile.affiliate(profile, Profile::Roles.admin(profile.environment.id))
82   - assert_equal 1, profile.members.size
83   - t = AddMember.create!(:person => profile, :organization => profile)
84   - get :index, :profile => profile.identifier
85   - assert_tag :tag => 'input', :attributes => { :name => 'task[roles][]', :checked => 'checked', :value => Profile::Roles.member(profile.environment.id).id }
  72 + t.reload
  73 + ok('task should be skipped') { t.status == Task::Status::ACTIVE }
86 74 end
87 75  
88   - should 'display roles besides role member unchecked if target has members' do
89   - profile.affiliate(profile, Profile::Roles.admin(profile.environment.id))
90   - assert_equal 1, profile.members.size
91   - t = AddMember.create!(:person => profile, :organization => profile)
92   - get :index, :profile => profile.identifier
93   - Role.find(:all).select{ |r| r.has_kind?('Profile') and r.id != Profile::Roles.member(profile.environment.id).id }.each do |i|
94   - assert_no_tag :tag => 'input', :attributes => { :name => 'task[roles][]', :checked => 'checked', :value => i.id }
95   - end
  76 + should 'be able to apply different decisions to multiples tasks at the same time' do
  77 + t1 = profile.tasks.build; t1.save!
  78 + t2 = profile.tasks.build; t2.save!
  79 + t3 = profile.tasks.build; t3.save!
  80 +
  81 + post :close, :tasks => {t1.id => {:decision => 'finish', :task => {}}, t2.id => {:decision => 'cancel', :task => {}}, t3.id => {:decision => 'skip', :task => {}}}
  82 + assert_redirected_to :action => 'index'
  83 +
  84 + t1.reload
  85 + t2.reload
  86 + t3.reload
  87 +
  88 + ok('task should be finished') { t1.status == Task::Status::FINISHED }
  89 + ok('task should be canceled') { t2.status == Task::Status::CANCELLED }
  90 + ok('task should be skipped') { t3.status == Task::Status::ACTIVE }
96 91 end
97 92  
98   - should 'display all roles checked if target has no members' do
99   - assert_equal 0, profile.members.size
  93 + should 'affiliate roles to user after finish add member task' do
100 94 t = AddMember.create!(:person => profile, :organization => profile)
101   - get :index, :profile => profile.identifier
102   - Role.find(:all).select{ |r| r.has_kind?('Profile') }.each do |i|
103   - assert_tag :tag => 'input', :attributes => { :name => 'task[roles][]', :checked => 'checked', :value => i.id }
104   - end
  95 + count = profile.members.size
  96 + post :close, :tasks => {t.id => {:decision => 'finish', :task => {}}}
  97 + profile = Profile.find(@profile.id)
  98 + assert_equal count + 1, profile.members.size
105 99 end
106 100  
107 101 should 'display a create ticket form' do
... ... @@ -161,8 +155,8 @@ class TasksControllerTest &lt; Test::Unit::TestCase
161 155 article = profile.articles.create!(:name => 'something interesting', :body => 'ruby on rails')
162 156 t = ApproveArticle.create!(:name => 'test name', :article => article, :target => c, :requestor => profile)
163 157  
164   - post :close, :decision => 'finish', :id => t.id, :task => { :name => 'new name'}
165   - assert_equal article, c.articles.find_by_name('new name').reference_article
  158 + post :close, :tasks => {t.id => {:decision => 'finish', :task => {:name => 'new_name'}}}
  159 + assert_equal article, c.articles.find_by_name('new_name').reference_article
166 160 end
167 161  
168 162 should 'create published article in folder after finish approve article task' do
... ... @@ -174,8 +168,8 @@ class TasksControllerTest &lt; Test::Unit::TestCase
174 168 article = profile.articles.create!(:name => 'something interesting', :body => 'ruby on rails')
175 169 t = ApproveArticle.create!(:name => 'test name', :article => article, :target => c, :requestor => profile)
176 170  
177   - post :close, :decision => 'finish', :id => t.id, :task => { :name => 'new name', :article_parent_id => folder.id}
178   - assert_equal folder, c.articles.find_by_name('new name').parent
  171 + post :close, :tasks => {t.id => {:decision => 'finish', :task => {:name => 'new_name', :article_parent_id => folder.id}}}
  172 + assert_equal folder, c.articles.find_by_name('new_name').parent
179 173 end
180 174  
181 175 should 'be highlighted if asked when approving a published article' do
... ... @@ -187,8 +181,8 @@ class TasksControllerTest &lt; Test::Unit::TestCase
187 181 article = profile.articles.create!(:name => 'something interesting', :body => 'ruby on rails')
188 182 t = ApproveArticle.create!(:article => article, :target => c, :requestor => profile)
189 183  
190   - post :close, :decision => 'finish', :id => t.id, :task => { :name => 'new name', :article_parent_id => folder.id, :highlighted => true}
191   - assert_equal true, c.articles.find_by_name('new name').highlighted
  184 + post :close, :tasks => {t.id => {:decision => 'finish', :task => {:name => 'new_name', :article_parent_id => folder.id, :highlighted => true}}}
  185 + assert_equal true, c.articles.find_by_name('new_name').highlighted
192 186 end
193 187  
194 188 should 'create article of same class after choosing root folder on approve article task' do
... ... @@ -199,8 +193,8 @@ class TasksControllerTest &lt; Test::Unit::TestCase
199 193 article = profile.articles.create!(:name => 'something interesting', :body => 'ruby on rails')
200 194 t = ApproveArticle.create!(:article => article, :target => c, :requestor => profile)
201 195  
202   - post :close, :decision => 'finish', :id => t.id, :task => { :name => 'new name', :article_parent_id => ""}
203   - assert_equal article.class, c.articles.find_by_name('new name').class
  196 + post :close, :tasks => {t.id => {:decision => 'finish', :task => {:name => 'new_name', :article_parent_id => ""}}}
  197 + assert_not_nil c.articles.find_by_name('new_name')
204 198 end
205 199  
206 200 should 'handle blank names for published articles' do
... ... @@ -217,24 +211,24 @@ class TasksControllerTest &lt; Test::Unit::TestCase
217 211 assert_includes c.tasks, a
218 212  
219 213 assert_difference article.class, :count do
220   - post :close, {"commit"=>"Ok!", "id"=> a.id.to_s, "task"=>{"name"=>"", "closing_statment"=>"", "highlighted"=>"0", "article_parent_id"=>c_blog2.id.to_s}, "decision"=>"finish"}
  214 + post :close, :tasks => {a.id => {:decision => 'finish', :task => {:name => "", :highlighted => "0", :article_parent_id => c_blog2.id.to_s}}}
221 215 end
222 216 assert p_article = article.class.find_by_reference_article_id(article.id)
223 217 assert_includes c_blog2.children(true), p_article
224 218 end
225 219  
226   - should 'cancel an enterprise registration task even if there is an enterprise with the same identifier' do
  220 + should 'raise error if there is an enterprise with the same identifier and keep the task active' do
227 221 e = Environment.default
228 222 e.add_admin(profile)
229 223 task = CreateEnterprise.create!(:name => "My Enterprise", :identifier => "my-enterprise", :requestor => profile, :target => e)
230 224 enterprise = fast_create(Enterprise, :name => "My Enterprise", :identifier => "my-enterprise")
231 225  
232   - assert_nothing_raised do
233   - post :close, {:profile => profile.identifier, :id => task.id, :task => {:reject_explanation => "Bla bla"}, :decision => "cancel"}
  226 + assert_raise ActiveRecord::RecordInvalid do
  227 + post :close, :tasks => {task.id => { :task => {:reject_explanation => "Bla bla"}, :decision => "cancel"}}
234 228 end
235 229  
236 230 task.reload
237   - assert_equal Task::Status::CANCELLED, task.status
  231 + assert_equal Task::Status::ACTIVE, task.status
238 232 end
239 233  
240 234 should 'create TinyMceArticle article after finish approve suggested article task' do
... ... @@ -245,7 +239,7 @@ class TasksControllerTest &lt; Test::Unit::TestCase
245 239 SuggestArticle.skip_captcha!
246 240 t = SuggestArticle.create!(:article_name => 'test name', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c)
247 241  
248   - post :close, :decision => 'finish', :id => t.id, :task => {}
  242 + post :close, :tasks => {t.id => { :task => {}, :decision => "finish"}}
249 243 assert_not_nil TinyMceArticle.find(:first)
250 244 end
251 245  
... ... @@ -265,7 +259,7 @@ class TasksControllerTest &lt; Test::Unit::TestCase
265 259 t.target = c
266 260 t.save!
267 261  
268   - post :close, :decision => 'finish', :id => t.id, :task => {:article_name => 'new article name', :article_body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source', :name => 'new name'}
  262 + post :close, :tasks => {t.id => { :task => {:article_name => 'new article name', :article_body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source', :name => 'new name'}, :decision => "finish"}}
269 263 assert_equal 'new article name', TinyMceArticle.find(:first).name
270 264 assert_equal 'new name', TinyMceArticle.find(:first).author_name
271 265 assert_equal 'new body', TinyMceArticle.find(:first).body
... ...
test/unit/add_friend_test.rb
... ... @@ -71,15 +71,6 @@ class AddFriendTest &lt; ActiveSupport::TestCase
71 71 task = AddFriend.create!(:person => p1, :friend => p2)
72 72 end
73 73  
74   - should 'provide proper description' do
75   - p1 = create_user('testuser1').person
76   - p2 = create_user('testuser2').person
77   -
78   - task = fast_create(AddFriend, :requestor_id => p1.id, :target_id => p2.id)
79   -
80   - assert_equal 'testuser1 wants to be your friend.', task.description
81   - end
82   -
83 74 should 'has permission to manage friends' do
84 75 t = AddFriend.new
85 76 assert_equal :manage_friends, t.permission
... ...
test/unit/add_member_test.rb
... ... @@ -49,18 +49,6 @@ class AddMemberTest &lt; ActiveSupport::TestCase
49 49 task = AddMember.create!(:person => p, :organization => c)
50 50 end
51 51  
52   - should 'provide proper description' do
53   - p = create_user('testuser1').person
54   - c = fast_create(Community, :name => 'closed community')
55   - c.update_attribute(:closed, true)
56   -
57   - TaskMailer.stubs(:deliver_target_notification)
58   -
59   - task = fast_create(AddMember, :requestor_id => p.id, :target_id => c.id, :target_type => 'Community')
60   -
61   - assert_equal 'testuser1 wants to be a member of "closed community".', task.description
62   - end
63   -
64 52 should 'has permission to manage members' do
65 53 t = AddMember.new
66 54 assert_equal :manage_memberships, t.permission
... ...
test/unit/application_helper_test.rb
... ... @@ -588,6 +588,12 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase
588 588 assert_equal ["1 for b", "2 for c", "3 for a"], unique_with_count(%w(a b c a c a))
589 589 end
590 590  
  591 + should 'show task information with the requestor' do
  592 + person = create_user('usertest').person
  593 + task = Task.create(:requestor => person)
  594 + assert_match person.name, task_information(task)
  595 + end
  596 +
591 597 protected
592 598  
593 599 def url_for(args = {})
... ...
test/unit/approve_article_test.rb
... ... @@ -62,7 +62,7 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
62 62 article.destroy
63 63 a.reload
64 64  
65   - assert_match /text was removed/, a.description
  65 + assert_equal "The article was removed.", a.information[:message]
66 66 end
67 67  
68 68 should 'preserve article_parent' do
... ...
test/unit/email_activation_test.rb
... ... @@ -37,7 +37,7 @@ class EmailActivationTest &lt; Test::Unit::TestCase
37 37 task = EmailActivation.create!(:requestor => ze.person, :target => Environment.default)
38 38 task.finish
39 39  
40   - assert_equal ['zezinho@colivre.net'], ActionMailer::Base.deliveries.first.to
  40 + assert_equal ["zezinho@#{ze.email_domain}"], ActionMailer::Base.deliveries.first.to
41 41 end
42 42  
43 43 should 'create only once pending task by user' do
... ... @@ -49,11 +49,4 @@ class EmailActivationTest &lt; Test::Unit::TestCase
49 49 assert !anothertask.save
50 50 end
51 51  
52   - should 'display email address on description of task' do
53   - ze = create_user('zezinho', :environment_id => Environment.default.id)
54   - Environment.default.domains = [Domain.create!(:name => 'env_test.invalid')]
55   - task = EmailActivation.new(:requestor => ze.person, :target => Environment.default)
56   - assert_match /zezinho@env_test.invalid/, task.description
57   - end
58   -
59 52 end
... ...
test/unit/invite_friend_test.rb
... ... @@ -105,13 +105,6 @@ class InviteFriendTest &lt; ActiveSupport::TestCase
105 105 task = InviteFriend.create!(:person => p1, :friend => p2)
106 106 end
107 107  
108   - should 'mention inviter in description' do
109   - p1 = create_user('testuser1').person
110   - task = InviteFriend.new(:person => p1)
111   -
112   - assert_match 'testuser1', task.description
113   - end
114   -
115 108 should 'has permission to manage friends' do
116 109 t = InviteFriend.new
117 110 assert_equal :manage_friends, t.permission
... ...
test/unit/invite_member_test.rb
... ... @@ -85,19 +85,6 @@ class InviteMemberTest &lt; ActiveSupport::TestCase
85 85 task = InviteMember.create!(:person => p1, :friend => p2, :community_id => fast_create(Community).id)
86 86 end
87 87  
88   - should 'provide proper description' do
89   - p1 = create_user('testuser1').person
90   - p2 = create_user('testuser2').person
91   -
92   - TaskMailer.expects(:deliver_task_finished).never
93   - TaskMailer.expects(:deliver_task_created).never
94   -
95   - community = fast_create(Community)
96   - task = InviteMember.create!(:person => p1, :friend => p2, :community_id => community.id)
97   -
98   - assert_match(/#{p1.name}.*#{community.name}/, task.description)
99   - end
100   -
101 88 should 'not invite yourself' do
102 89 p = create_user('testuser1').person
103 90  
... ...
test/unit/pending_task_notifier_test.rb
... ... @@ -23,10 +23,10 @@ class PendingTaskNotifierTest &lt; Test::Unit::TestCase
23 23 p = create_user('maelcum').person
24 24 c = fast_create(Community)
25 25 c.add_admin(p)
26   - c.tasks << Task.new
  26 + c.tasks << Task.new(:requestor => p)
27 27  
28 28 response = PendingTaskNotifier.deliver_notification(p)
29   - assert_match /Generic task/, response.body
  29 + assert_match /sent you a task/, response.body
30 30 end
31 31  
32 32 private
... ...
test/unit/rss_feed_test.rb
... ... @@ -206,7 +206,7 @@ class RssFeedTest &lt; Test::Unit::TestCase
206 206 end
207 207  
208 208 should 'display the referenced body of a article published' do
209   - article = fast_create(TextileArticle, :body => 'This is the content of the Sample Article.')
  209 + article = fast_create(TextileArticle, :body => 'This is the content of the Sample Article.', :profile_id => fast_create(Person).id)
210 210 profile = fast_create(Profile)
211 211 blog = fast_create(Blog, :profile_id => profile.id)
212 212 a = ApproveArticle.create!(:name => 'test name', :article => article, :target => profile, :requestor => fast_create(Person))
... ...
test/unit/suggest_article_test.rb
... ... @@ -97,12 +97,6 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
97 97 assert_equal 'http://www.gnu.org/', article.source
98 98 end
99 99  
100   - should 'use sender name in description' do
101   - t = build(SuggestArticle, :target => @profile)
102   - t.stubs(:sender).returns('XYZ')
103   - assert_match(/XYZ/, t.description)
104   - end
105   -
106 100 should 'use name and e-mail as sender info' do
107 101 t = build(SuggestArticle, :target => @profile)
108 102 t.name = 'Some One'
... ...
test/unit/task_mailer_test.rb
... ... @@ -17,7 +17,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
17 17  
18 18 task = Task.new
19 19 task.expects(:task_finished_message).returns('the message')
20   - task.expects(:description).returns('the task')
  20 + task.expects(:information).returns('the task')
21 21  
22 22 requestor = mock()
23 23 requestor.expects(:notification_emails).returns(['requestor@example.com'])
... ... @@ -40,7 +40,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
40 40  
41 41 task = Task.new
42 42 task.expects(:task_cancelled_message).returns('the message')
43   - task.expects(:description).returns('the task')
  43 + task.expects(:information).returns('the task')
44 44  
45 45 requestor = mock()
46 46 requestor.expects(:notification_emails).returns(['requestor@example.com'])
... ... @@ -64,7 +64,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
64 64 task = Task.new
65 65  
66 66 task.expects(:task_created_message).returns('the message')
67   - task.expects(:description).returns('the task')
  67 + task.expects(:information).returns('the task')
68 68  
69 69 requestor = mock()
70 70 requestor.expects(:notification_emails).returns(['requestor@example.com'])
... ... @@ -85,7 +85,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
85 85  
86 86 should 'be able to send a "target notification" message' do
87 87 task = Task.new
88   - task.expects(:description).returns('the task')
  88 + task.expects(:information).returns('the task')
89 89  
90 90 target = mock()
91 91 target.expects(:notification_emails).returns(['target@example.com'])
... ... @@ -104,18 +104,18 @@ class TaskMailerTest &lt; Test::Unit::TestCase
104 104 assert !ActionMailer::Base.deliveries.empty?
105 105 end
106 106  
107   - should 'be able to send a "invitatiom notification" message' do
  107 + should 'be able to send a "invitation notification" message' do
108 108  
109 109 task = InviteFriend.new
110   - task.expects(:description).returns('the task')
111 110 task.expects(:code).returns('123456')
112 111  
113   - task.expects(:message).returns('Hello <friend>, <user> invite you, please follow this link: <url>')
  112 + task.stubs(:message).returns('Hello <friend>, <user> invite you, please follow this link: <url>')
114 113 task.expects(:friend_email).returns('friend@exemple.com')
115 114 task.expects(:friend_name).returns('friend name').at_least_once
116 115  
117 116 requestor = mock()
118   - requestor.expects(:name).returns('my name')
  117 + requestor.stubs(:name).returns('my name')
  118 + requestor.stubs(:public_profile_url).returns('requestor_path')
119 119  
120 120 environment = mock()
121 121 environment.expects(:contact_email).returns('sender@example.com')
... ...
test/unit/task_test.rb
... ... @@ -87,7 +87,8 @@ class TaskTest &lt; Test::Unit::TestCase
87 87 end
88 88  
89 89 should 'provide a description method' do
90   - assert_kind_of String, Task.new.description
  90 + requestor = create_user('requestor').person
  91 + assert_kind_of Hash, Task.new(:requestor => requestor).information
91 92 end
92 93  
93 94 should 'notify just after the task is created' do
... ...