Commit 946bd81026a5103e75454301a0118840015a5d4c
1 parent
f0141cef
Exists in
staging
and in
42 other branches
ActionItem791: 'contact us' feature for enterprises
users can send message to enterprises
the enterprise must choose if 'contact us' is available or not
Showing
17 changed files
with
223 additions
and
4 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | +class ContactController < PublicController | |
| 2 | + | |
| 3 | + needs_profile | |
| 4 | + | |
| 5 | + def new | |
| 6 | + @contact = Contact.new(params[:contact]) | |
| 7 | + if request.post? | |
| 8 | + if @contact.save | |
| 9 | + flash[:notice] = _('Contact successfully sent') | |
| 10 | + redirect_to :controller => 'profile', :profile => profile.identifier | |
| 11 | + else | |
| 12 | + flash[:notice] = _('Contact not sent') | |
| 13 | + end | |
| 14 | + end | |
| 15 | + end | |
| 16 | + | |
| 17 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | +class Contact < Task | |
| 2 | + | |
| 3 | + validates_presence_of :target_id, :subject, :email, :message | |
| 4 | + validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT | |
| 5 | + | |
| 6 | + acts_as_having_settings :field => :data | |
| 7 | + settings_items :subject, :message, :city_and_state, :email, :phone | |
| 8 | + | |
| 9 | + def description | |
| 10 | + _('%s sent a new message') % (requestor ? requestor.name : _('Someone')) | |
| 11 | + end | |
| 12 | + | |
| 13 | +end | ... | ... |
app/models/enterprise.rb
| ... | ... | @@ -57,7 +57,6 @@ class Enterprise < Organization |
| 57 | 57 | end |
| 58 | 58 | end |
| 59 | 59 | |
| 60 | - | |
| 61 | 60 | def default_set_of_blocks |
| 62 | 61 | blocks = [ |
| 63 | 62 | [MainBlock], |
| ... | ... | @@ -74,6 +73,8 @@ class Enterprise < Organization |
| 74 | 73 | environment.enterprise_template |
| 75 | 74 | end |
| 76 | 75 | |
| 76 | + settings_items :enable_contact_us, :type => :boolean, :default => true | |
| 77 | + | |
| 77 | 78 | protected |
| 78 | 79 | |
| 79 | 80 | def default_homepage(attrs) | ... | ... |
app/views/blocks/profile_info_actions/enterprise.rhtml
| ... | ... | @@ -9,4 +9,7 @@ |
| 9 | 9 | <li><%= link_to content_tag('span', _('Join')), { :profile => user.identifier, :controller => 'memberships', :action => 'join', :id => profile.id }, :class => 'button with-text icon-add', :title => __('Join this enterprise') %></li> |
| 10 | 10 | <% end %> |
| 11 | 11 | <% end %> |
| 12 | + <% if profile.enable_contact_us %> | |
| 13 | + <li> <%= link_to content_tag('span', _('Contact us')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, :class => 'button with-text icon-menu-mail' %> </li> | |
| 14 | + <% end %> | |
| 12 | 15 | </ul> | ... | ... |
| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | +<h1><%= _('Contact %s') % profile.name %></h1> | |
| 2 | + | |
| 3 | +<%= error_messages_for 'contact' %> | |
| 4 | + | |
| 5 | +<% labelled_form_for :contact, @contact do |f| %> | |
| 6 | + | |
| 7 | + <%= hidden_field_tag 'contact[target_id]', profile.id %> | |
| 8 | + <%= hidden_field_tag 'contact[requestor_id]', (logged_in? ? current_user.person.id : nil) %> | |
| 9 | + <%= f.text_field :subject %> | |
| 10 | + <%= f.text_field :email %> | |
| 11 | + <%= f.text_field :city_and_state %> | |
| 12 | + <%= f.text_field :phone %> | |
| 13 | + <%= f.text_area :message, :rows => 5 %> | |
| 14 | + | |
| 15 | + <%= submit_button(:send, _('Send')) %> | |
| 16 | + | |
| 17 | +<% end %> | ... | ... |
app/views/profile_editor/_organization.rhtml
| ... | ... | @@ -9,12 +9,13 @@ |
| 9 | 9 | |
| 10 | 10 | </div> |
| 11 | 11 | <%= f.text_field(:acronym) %> |
| 12 | - <%= f.text_field(:address, 'size' => 50) if @profile.kind_of?(Enterprise) %> | |
| 12 | + <%= f.text_field(:address, 'size' => 50) if @profile.enterprise? %> | |
| 13 | 13 | <%= f.text_field(:foundation_year) %> |
| 14 | 14 | <%= f.text_field(:contact_person) %> |
| 15 | 15 | <%= f.text_field(:contact_email) %> |
| 16 | 16 | <%= f.text_field(:economic_activity) %> |
| 17 | - <%= f.text_area(:description, :rows => 5) if @profile.kind_of?(Community) %> | |
| 17 | + <%= f.text_area(:description, :rows => 5) if @profile.community? %> | |
| 18 | + <%= f.check_box(:enable_contact_us) if @profile.enterprise? %> | |
| 18 | 19 | <h1><%= _('Moderation options') %></h1> |
| 19 | 20 | <div style='margin-bottom: 1em'> |
| 20 | 21 | <%= _('New members must be approved:')%> | ... | ... |
| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | +<h2><%= task.description %></h2> | |
| 2 | + | |
| 3 | +<% form_for('task', task, :url => { :action => 'close', :id => task.id}) do |f| %> | |
| 4 | + | |
| 5 | + <%= hidden_field_tag(:decision, :finish) %> | |
| 6 | + <table> | |
| 7 | + <% %w[ subject email phone city_and_state message ].each do |field| %> | |
| 8 | + <% if task.respond_to?(field) and !task.send(field).nil? and !task.send(field).empty? %> | |
| 9 | + <tr> <td><strong><%= _(field.humanize) %></strong></td> <td><%= task.send(field) %></td> </tr> | |
| 10 | + <% end %> | |
| 11 | + <% end %> | |
| 12 | + </table> | |
| 13 | + | |
| 14 | + <% button_bar do %> | |
| 15 | + <%= submit_button(:ok, _('Ok!')) %> | |
| 16 | + <% end %> | |
| 17 | + | |
| 18 | +<% end %> | ... | ... |
config/routes.rb
| ... | ... | @@ -53,6 +53,9 @@ ActionController::Routing::Routes.draw do |map| |
| 53 | 53 | map.catalog 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format}/ |
| 54 | 54 | map.product 'catalog/:profile/:id', :controller => 'catalog', :action => 'show', :profile => /#{Noosfero.identifier_format}/ |
| 55 | 55 | |
| 56 | + # contact | |
| 57 | + map.contact 'contact/:profile/:action/:id', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/ | |
| 58 | + | |
| 56 | 59 | ###################################################### |
| 57 | 60 | ## Controllers that are profile-specific (for profile admins ) |
| 58 | 61 | ###################################################### | ... | ... |
public/designs/icons/default/style.css
| ... | ... | @@ -5,6 +5,7 @@ |
| 5 | 5 | .icon-open { background-image: url(folder-open.gif) } |
| 6 | 6 | .icon-cms { background-image: url(abiword_48.png) } |
| 7 | 7 | .icon-save { background-image: url(save-HC.gif) } |
| 8 | +.icon-send { background-image: url(mail-HC.gif) } | |
| 8 | 9 | .icon-up { background-image: url(go-up-HC.gif) } |
| 9 | 10 | .icon-cancel { background-image: url(cancel-HC.gif) } |
| 10 | 11 | .icon-person { background-image: url(user_icon.png) } | ... | ... |
| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | +require 'contact_controller' | |
| 3 | + | |
| 4 | +# Re-raise errors caught by the controller. | |
| 5 | +class ContactController; def rescue_action(e) raise e end; end | |
| 6 | + | |
| 7 | +class ContactControllerTest < Test::Unit::TestCase | |
| 8 | + | |
| 9 | + all_fixtures | |
| 10 | + | |
| 11 | + def setup | |
| 12 | + @controller = ContactController.new | |
| 13 | + @request = ActionController::TestRequest.new | |
| 14 | + @response = ActionController::TestResponse.new | |
| 15 | + | |
| 16 | + @profile = create_user('contact_test_user').person | |
| 17 | + @enterprise = Enterprise.create!(:identifier => 'contact_test_enterprise', :name => 'Test contact enteprise') | |
| 18 | + end | |
| 19 | + attr_reader :profile, :enterprise | |
| 20 | + | |
| 21 | + should 'respond to new' do | |
| 22 | + get :new, :profile => enterprise.identifier | |
| 23 | + assert_response :success | |
| 24 | + end | |
| 25 | + | |
| 26 | + should 'display destinatary name in title' do | |
| 27 | + get :new, :profile => enterprise.identifier | |
| 28 | + assert_tag :tag => 'h1', :content => "Contact #{enterprise.name}" | |
| 29 | + end | |
| 30 | + | |
| 31 | + should 'add form to create contact via post' do | |
| 32 | + get :new, :profile => enterprise.identifier | |
| 33 | + assert_tag :tag => 'form', :attributes => { :action => "/contact/#{enterprise.identifier}/new", :method => 'post' } | |
| 34 | + end | |
| 35 | + | |
| 36 | + should 'display input for destinatary email' do | |
| 37 | + get :new, :profile => enterprise.identifier | |
| 38 | + assert_tag :tag => 'input', :attributes => { :name => 'contact[email]', :type => 'text' } | |
| 39 | + end | |
| 40 | + | |
| 41 | + should 'display input for message' do | |
| 42 | + get :new, :profile => enterprise.identifier | |
| 43 | + assert_tag :tag => 'textarea', :attributes => { :name => 'contact[message]' } | |
| 44 | + end | |
| 45 | + | |
| 46 | + should 'add hidden field with target_id' do | |
| 47 | + get :new, :profile => enterprise.identifier | |
| 48 | + assert_tag :tag => 'input', :attributes => { :name => 'contact[target_id]', :value => enterprise.id, :type => 'hidden' } | |
| 49 | + end | |
| 50 | + | |
| 51 | + should 'add requestor id if logged in' do | |
| 52 | + login_as(profile.identifier) | |
| 53 | + @controller.stubs(:current_user).returns(profile.user) | |
| 54 | + get :new, :profile => enterprise.identifier | |
| 55 | + assert_tag :tag => 'input', :attributes => { :name => 'contact[requestor_id]', :value => profile.id } | |
| 56 | + end | |
| 57 | + | |
| 58 | + should 'nil requestor id if not logged in' do | |
| 59 | + get :new, :profile => enterprise.identifier | |
| 60 | + assert_tag :tag => 'input', :attributes => { :name => 'contact[requestor_id]', :value => nil } | |
| 61 | + end | |
| 62 | + | |
| 63 | + should 'redirect to profile page after contact' do | |
| 64 | + post :new, :profile => enterprise.identifier, :contact => {:subject => 'Hi', :email => 'visitor@mail.invalid', :message => 'Hi, all', :target_id => enterprise.id} | |
| 65 | + assert_response :redirect | |
| 66 | + assert_redirected_to :controller => 'profile', :profile => enterprise.identifier | |
| 67 | + end | |
| 68 | + | |
| 69 | + should 'be able to send contact' do | |
| 70 | + assert_difference Contact, :count do | |
| 71 | + post :new, :profile => enterprise.identifier, :contact => {:subject => 'Hi', :email => 'visitor@mail.invalid', :message => 'Hi, all', :target_id => enterprise.id} | |
| 72 | + end | |
| 73 | + end | |
| 74 | + | |
| 75 | +end | ... | ... |
test/functional/profile_controller_test.rb
| ... | ... | @@ -249,7 +249,7 @@ class ProfileControllerTest < Test::Unit::TestCase |
| 249 | 249 | get :index, :profile => 'my-test-enterprise' |
| 250 | 250 | assert_tag :tag => 'a', :attributes => { :href => '/catalog/my-test-enterprise'}, :content => /Products\/Services/ |
| 251 | 251 | end |
| 252 | - | |
| 252 | + | |
| 253 | 253 | should 'not display "Products" link for enterprise if environment do not let' do |
| 254 | 254 | env = Environment.default |
| 255 | 255 | env.enable('disable_products_for_enterprises') |
| ... | ... | @@ -304,4 +304,21 @@ class ProfileControllerTest < Test::Unit::TestCase |
| 304 | 304 | assert_no_tag :content => /t2@t2.com/ |
| 305 | 305 | end |
| 306 | 306 | |
| 307 | + should 'display contact us for enterprises' do | |
| 308 | + ent = Enterprise.create!(:name => 'my test enterprise', :identifier => 'my-test-enterprise') | |
| 309 | + get :index, :profile => 'my-test-enterprise' | |
| 310 | + assert_tag :tag => 'a', :attributes => { :href => "/contact/my-test-enterprise/new" }, :content => 'Contact us' | |
| 311 | + end | |
| 312 | + | |
| 313 | + should 'not display contact us for non-enterprises' do | |
| 314 | + get :index, :profile => @profile.identifier | |
| 315 | + assert_no_tag :tag => 'a', :attributes => { :href => "/contact/#{@profile.identifier}/new" }, :content => 'Contact us' | |
| 316 | + end | |
| 317 | + | |
| 318 | + should 'display contact us only if enabled' do | |
| 319 | + ent = Enterprise.create!(:name => 'my test enterprise', :identifier => 'my-test-enterprise', :enable_contact_us => false) | |
| 320 | + get :index, :profile => 'my-test-enterprise' | |
| 321 | + assert_no_tag :tag => 'a', :attributes => { :href => "/contact/my-test-enterprise/new" }, :content => 'Contact us' | |
| 322 | + end | |
| 323 | + | |
| 307 | 324 | end | ... | ... |
test/functional/profile_editor_controller_test.rb
| ... | ... | @@ -517,4 +517,10 @@ class ProfileEditorControllerTest < Test::Unit::TestCase |
| 517 | 517 | :attributes => { :name=>'profile_data[email]', :value=>'teste_user@teste.com' } |
| 518 | 518 | end |
| 519 | 519 | |
| 520 | + should 'display enable contact us for enterprise' do | |
| 521 | + org = Enterprise.create!(:name => 'test org', :identifier => 'testorg') | |
| 522 | + get :edit, :profile => 'testorg' | |
| 523 | + assert_tag :tag => 'input', :attributes => {:name => 'profile_data[enable_contact_us]', :type => 'checkbox'} | |
| 524 | + end | |
| 525 | + | |
| 520 | 526 | end | ... | ... |
test/functional/tasks_controller_test.rb
| ... | ... | @@ -151,4 +151,16 @@ class TasksControllerTest < Test::Unit::TestCase |
| 151 | 151 | |
| 152 | 152 | assert_equal f, assigns(:ticket).target |
| 153 | 153 | end |
| 154 | + | |
| 155 | + should 'list enterprise contacts' do | |
| 156 | + ent = Enterprise.create!(:identifier => 'contact_test_enterprise', :name => 'Test contact enteprise') | |
| 157 | + task = Contact.create!(:subject => 'test', :target_id => profile.id, :email => 'visitor@invalid.com', :message => 'Hi, all') | |
| 158 | + | |
| 159 | + login_as(profile.identifier) | |
| 160 | + get :index, :profile => ent.identifier | |
| 161 | + | |
| 162 | + assert_includes assigns(:tasks), task | |
| 163 | + assert_tag :tag => 'li', :attributes => { :class => 'task-Contact' }, :content => 'Someone sent a new message' | |
| 164 | + end | |
| 165 | + | |
| 154 | 166 | end | ... | ... |
test/integration/routing_test.rb
| ... | ... | @@ -186,4 +186,8 @@ class RoutingTest < ActionController::IntegrationTest |
| 186 | 186 | assert_routing('/myprofile/profile.withdot', :controller => 'profile_editor', :action => 'index', :profile => 'profile.withdot') |
| 187 | 187 | end |
| 188 | 188 | |
| 189 | + def test_contact_routing | |
| 190 | + assert_routing('/contact/wintermute/new', :controller => 'contact', :action => 'new', :profile => 'wintermute') | |
| 191 | + end | |
| 192 | + | |
| 189 | 193 | end | ... | ... |
| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | + | |
| 3 | +class ContactTest < ActiveSupport::TestCase | |
| 4 | + | |
| 5 | + should 'have serialized data' do | |
| 6 | + t = Contact.new | |
| 7 | + t.data[:test] = 'test' | |
| 8 | + | |
| 9 | + assert_equal({:test => 'test'}, t.data) | |
| 10 | + end | |
| 11 | + | |
| 12 | + should 'validates required fields' do | |
| 13 | + contact = Contact.new | |
| 14 | + assert !contact.valid? | |
| 15 | + contact.subject = 'Hi' | |
| 16 | + assert !contact.valid? | |
| 17 | + contact.email = 'visitor@invalid.com' | |
| 18 | + assert !contact.valid? | |
| 19 | + contact.message = 'Hi, all' | |
| 20 | + assert !contact.valid? | |
| 21 | + contact.target = create_user('contact_user_test').person | |
| 22 | + assert contact.save! | |
| 23 | + end | |
| 24 | + | |
| 25 | +end | ... | ... |
test/unit/enterprise_test.rb
| ... | ... | @@ -211,5 +211,9 @@ class EnterpriseTest < Test::Unit::TestCase |
| 211 | 211 | assert_kind_of Enterprise, p.template |
| 212 | 212 | end |
| 213 | 213 | |
| 214 | + should 'contact us enabled by default' do | |
| 215 | + e = Enterprise.create!(:name => 'test_com', :identifier => 'test_com', :environment => Environment.default) | |
| 216 | + assert e.enable_contact_us | |
| 217 | + end | |
| 214 | 218 | |
| 215 | 219 | end | ... | ... |