Commit d215b23272bc035473d4d686d57f81bb5e99f412
1 parent
e083ea4a
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
Option to choose template to send email to members
Showing
20 changed files
with
262 additions
and
4 deletions
Show diff stats
app/controllers/my_profile/email_templates_controller.rb
0 → 100644
@@ -0,0 +1,63 @@ | @@ -0,0 +1,63 @@ | ||
1 | +class EmailTemplatesController < MyProfileController | ||
2 | + | ||
3 | + protect 'send_mail_to_members', :profile | ||
4 | + | ||
5 | + def index | ||
6 | + @email_templates = profile.email_templates | ||
7 | + end | ||
8 | + | ||
9 | + def show | ||
10 | + @email_template = profile.email_templates.find(params[:id]) | ||
11 | + | ||
12 | + respond_to do |format| | ||
13 | + format.html # show.html.erb | ||
14 | + format.json { render json: @email_template } | ||
15 | + end | ||
16 | + end | ||
17 | + | ||
18 | + def show_parsed | ||
19 | + @email_template = profile.email_templates.find(params[:id]) | ||
20 | + template_params = {:profile => profile, :environment => environment} | ||
21 | + render json: {:parsed_body => @email_template.parsed_body(template_params), :parsed_subject => @email_template.parsed_subject(template_params)} | ||
22 | + end | ||
23 | + | ||
24 | + def new | ||
25 | + @email_template = profile.email_templates.build | ||
26 | + end | ||
27 | + | ||
28 | + def edit | ||
29 | + @email_template = profile.email_templates.find(params[:id]) | ||
30 | + end | ||
31 | + | ||
32 | + def create | ||
33 | + @email_template = profile.email_templates.build(params[:email_template], :owner => profile) | ||
34 | + | ||
35 | + if @email_template.save | ||
36 | + session[:notice] = _('Email template was successfully created.') | ||
37 | + redirect_to url_for(:action => :index) | ||
38 | + else | ||
39 | + render action: "new" | ||
40 | + end | ||
41 | + end | ||
42 | + | ||
43 | + def update | ||
44 | + @email_template = profile.email_templates.find(params[:id]) | ||
45 | + | ||
46 | + if @email_template.update_attributes(params[:email_template]) | ||
47 | + session[:notice] = _('Email template was successfully updated.') | ||
48 | + redirect_to url_for(:action => :index) | ||
49 | + else | ||
50 | + render action: "edit" | ||
51 | + end | ||
52 | + end | ||
53 | + | ||
54 | + def destroy | ||
55 | + @email_template = profile.email_templates.find(params[:id]) | ||
56 | + @email_template.destroy | ||
57 | + | ||
58 | + respond_to do |format| | ||
59 | + format.html { redirect_to url_for(:action => :index)} | ||
60 | + format.json { head :no_content } | ||
61 | + end | ||
62 | + end | ||
63 | +end |
app/controllers/public/profile_controller.rb
@@ -353,6 +353,7 @@ class ProfileController < PublicController | @@ -353,6 +353,7 @@ class ProfileController < PublicController | ||
353 | 353 | ||
354 | def send_mail | 354 | def send_mail |
355 | @mailing = profile.mailings.build(params[:mailing]) | 355 | @mailing = profile.mailings.build(params[:mailing]) |
356 | + @email_templates = profile.email_templates | ||
356 | if request.post? | 357 | if request.post? |
357 | @mailing.locale = locale | 358 | @mailing.locale = locale |
358 | @mailing.person = user | 359 | @mailing.person = user |
app/models/email_template.rb
@@ -4,6 +4,8 @@ class EmailTemplate < ActiveRecord::Base | @@ -4,6 +4,8 @@ class EmailTemplate < ActiveRecord::Base | ||
4 | 4 | ||
5 | attr_accessible :template_type, :subject, :body, :owner, :name | 5 | attr_accessible :template_type, :subject, :body, :owner, :name |
6 | 6 | ||
7 | + validates_presence_of :name | ||
8 | + | ||
7 | def parsed_body(params) | 9 | def parsed_body(params) |
8 | @parsed_body ||= parse(body, params) | 10 | @parsed_body ||= parse(body, params) |
9 | end | 11 | end |
app/models/environment.rb
@@ -982,6 +982,10 @@ class Environment < ActiveRecord::Base | @@ -982,6 +982,10 @@ class Environment < ActiveRecord::Base | ||
982 | self.licenses.any? | 982 | self.licenses.any? |
983 | end | 983 | end |
984 | 984 | ||
985 | + def to_liquid | ||
986 | + HashWithIndifferentAccess.new :name => name | ||
987 | + end | ||
988 | + | ||
985 | private | 989 | private |
986 | 990 | ||
987 | def default_language_available | 991 | def default_language_available |
app/models/profile.rb
@@ -151,6 +151,8 @@ class Profile < ActiveRecord::Base | @@ -151,6 +151,8 @@ class Profile < ActiveRecord::Base | ||
151 | 151 | ||
152 | has_many :comments_received, :class_name => 'Comment', :through => :articles, :source => :comments | 152 | has_many :comments_received, :class_name => 'Comment', :through => :articles, :source => :comments |
153 | 153 | ||
154 | + has_many :email_templates, :foreign_key => :owner_id | ||
155 | + | ||
154 | # Although this should be a has_one relation, there are no non-silly names for | 156 | # Although this should be a has_one relation, there are no non-silly names for |
155 | # a foreign key on article to reference the template to which it is | 157 | # a foreign key on article to reference the template to which it is |
156 | # welcome_page... =P | 158 | # welcome_page... =P |
@@ -471,6 +473,10 @@ class Profile < ActiveRecord::Base | @@ -471,6 +473,10 @@ class Profile < ActiveRecord::Base | ||
471 | self.articles.find(:all, options) | 473 | self.articles.find(:all, options) |
472 | end | 474 | end |
473 | 475 | ||
476 | + def to_liquid | ||
477 | + HashWithIndifferentAccess.new :name => name, :identifier => identifier | ||
478 | + end | ||
479 | + | ||
474 | class << self | 480 | class << self |
475 | 481 | ||
476 | # finds a profile by its identifier. This method is a shortcut to | 482 | # finds a profile by its identifier. This method is a shortcut to |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +<%= form_for(@email_template, :url => {:controller => :email_templates, :action => @email_template.persisted? ? :update : :create, :id => @email_template.id}) do |f| %> | ||
2 | + | ||
3 | + <%= error_messages_for :email_template if @email_template.errors.any? %> | ||
4 | + | ||
5 | + <div class="template-fields"> | ||
6 | + <div class="header-fields"> | ||
7 | + <%= labelled_form_field(_('Template Name:'), f.text_field(:name)) %> | ||
8 | + <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> | ||
9 | + </div> | ||
10 | + <div class="available-params"> | ||
11 | + <div class="reference"> | ||
12 | + <a target="_blank" href="https://github.com/Shopify/liquid/wiki/Liquid-for-Designers"><%= _('Template language reference') %></a> | ||
13 | + </div> | ||
14 | + <div class="label"> | ||
15 | + <%= _('The following parameters may be used in subject and body:') %> | ||
16 | + </div> | ||
17 | + <div class="values"> | ||
18 | + {{profile.name}}, {{profile.identifier}}, {{environment.name}} | ||
19 | + </div> | ||
20 | + </div> | ||
21 | + <%= render :file => 'shared/tiny_mce' %> | ||
22 | + <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => 'mceEditor')) %> | ||
23 | + </div> | ||
24 | + | ||
25 | + <div class="actions"> | ||
26 | + <%= submit_button(:save, _('Save')) %> | ||
27 | + <%= button(:back, _('Back'), :controller => :email_templates) %> | ||
28 | + </div> | ||
29 | + | ||
30 | +<% end %> |
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +<h1><%= _('Email Templates') %></h1> | ||
2 | + | ||
3 | +<table> | ||
4 | + <tr> | ||
5 | + <th><%= _('Name') %></th> | ||
6 | + <th></th> | ||
7 | + </tr> | ||
8 | + | ||
9 | +<% @email_templates.each do |email_template| %> | ||
10 | + <tr> | ||
11 | + <td><%= email_template.name %></td> | ||
12 | + <td> | ||
13 | + <%= link_to 'Edit', url_for(:controller => :email_templates, :action => :edit, :id => email_template.id) %> | ||
14 | + <%= link_to 'Destroy', url_for(:controller => :email_templates, :action => :destroy, :id => email_template.id), method: :delete, data: { confirm: 'Are you sure?' } %> | ||
15 | + </td> | ||
16 | + </tr> | ||
17 | +<% end %> | ||
18 | +</table> | ||
19 | + | ||
20 | +<br /> | ||
21 | + | ||
22 | +<%= button(:new, _('New template'), :controller => :email_templates, :action => :new) %> | ||
23 | +<%= button(:back, _('Back to control panel'), :controller => :profile_editor) %> |
app/views/profile/send_mail.html.erb
@@ -4,6 +4,12 @@ | @@ -4,6 +4,12 @@ | ||
4 | 4 | ||
5 | <%= error_messages_for :mailing %> | 5 | <%= error_messages_for :mailing %> |
6 | 6 | ||
7 | +<div class="template-selection"> | ||
8 | + <% if @email_templates.present? %> | ||
9 | + <%= labelled_form_field(_('Select a template:'), select_tag(:template, options_from_collection_for_select(@email_templates, :id, :name), :include_blank => true, 'data-url' => url_for(:controller => 'email_templates', :action => 'show_parsed'))) %> | ||
10 | + <% end %> | ||
11 | +</div> | ||
12 | + | ||
7 | <%= form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> | 13 | <%= form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> |
8 | 14 | ||
9 | <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> | 15 | <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> |
app/views/profile_editor/index.html.erb
@@ -72,6 +72,8 @@ | @@ -72,6 +72,8 @@ | ||
72 | 72 | ||
73 | <%= control_panel_button(_('Edit welcome page'), 'welcome-page', :action => 'welcome_page') if has_welcome_page %> | 73 | <%= control_panel_button(_('Edit welcome page'), 'welcome-page', :action => 'welcome_page') if has_welcome_page %> |
74 | 74 | ||
75 | + <%= control_panel_button(_('Email Templates'), 'email-templates', :controller => :email_templates) if profile.organization? %> | ||
76 | + | ||
75 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> | 77 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
76 | <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> | 78 | <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> |
77 | <% end %> | 79 | <% end %> |
public/javascripts/application.js
@@ -28,6 +28,7 @@ | @@ -28,6 +28,7 @@ | ||
28 | *= require catalog.js | 28 | *= require catalog.js |
29 | *= require autogrow.js | 29 | *= require autogrow.js |
30 | *= require require_login.js | 30 | *= require require_login.js |
31 | +*= require email_templates.js | ||
31 | */ | 32 | */ |
32 | 33 | ||
33 | // scope for noosfero stuff | 34 | // scope for noosfero stuff |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +jQuery(document).ready(function($) { | ||
2 | + $('.template-selection select').change(function() { | ||
3 | + if(!$(this).val()) return; | ||
4 | + | ||
5 | + $.getJSON($(this).data('url'), {id: $(this).val()}, function(data) { | ||
6 | + $('#mailing-form #mailing_subject').val(data.parsed_subject); | ||
7 | + $('#mailing-form .mceEditor').val(data.parsed_body); | ||
8 | + }); | ||
9 | + }); | ||
10 | +}); |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +Subproject commit e7ad7849b3ef685639d4c5c0bef7b323255e2afa |
public/stylesheets/application.css
@@ -14,6 +14,7 @@ | @@ -14,6 +14,7 @@ | ||
14 | * views specifics | 14 | * views specifics |
15 | *= require chat | 15 | *= require chat |
16 | *= require search | 16 | *= require search |
17 | + *= require email-templates | ||
17 | */ | 18 | */ |
18 | 19 | ||
19 | /* browser fixes */ | 20 | /* browser fixes */ |
@@ -4658,6 +4659,9 @@ h1#agenda-title { | @@ -4658,6 +4659,9 @@ h1#agenda-title { | ||
4658 | .controller-profile_editor a.control-panel-design-editor { | 4659 | .controller-profile_editor a.control-panel-design-editor { |
4659 | background-image: url(../images/control-panel/preferences-desktop-wallpaper.png) | 4660 | background-image: url(../images/control-panel/preferences-desktop-wallpaper.png) |
4660 | } | 4661 | } |
4662 | +.controller-profile_editor a.control-panel-email-templates { | ||
4663 | + background-image: url(../images/control-panel/email.png) | ||
4664 | +} | ||
4661 | .controller-profile_editor .msie6 a.control-panel-design-editor { | 4665 | .controller-profile_editor .msie6 a.control-panel-design-editor { |
4662 | background-image: url(../images/control-panel/preferences-desktop-wallpaper.gif) | 4666 | background-image: url(../images/control-panel/preferences-desktop-wallpaper.gif) |
4663 | } | 4667 | } |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +.template-fields .header-fields, .template-fields .available-params { | ||
2 | + width: 48%; | ||
3 | + display: inline-block; | ||
4 | +} | ||
5 | +.template-fields .available-params .values { | ||
6 | + color: rgb(111, 111, 111); | ||
7 | +} | ||
8 | +.template-fields .available-params .reference { | ||
9 | + text-align: right; | ||
10 | +} | ||
11 | +.template-fields .available-params .reference a { | ||
12 | + color: rgb(32, 101, 229); | ||
13 | + text-decoration: none; | ||
14 | + font-size: 10px; | ||
15 | +} |
@@ -0,0 +1,68 @@ | @@ -0,0 +1,68 @@ | ||
1 | +require 'test_helper' | ||
2 | + | ||
3 | +class EmailTemplatesControllerTest < ActionController::TestCase | ||
4 | + | ||
5 | + setup do | ||
6 | + @profile = fast_create(Community) | ||
7 | + @email_template = EmailTemplate.create!(:name => 'template', :owner => @profile) | ||
8 | + @person = create_user_with_permission('templatemanager', 'send_mail_to_members', @profile) | ||
9 | + login_as(@person.user.login) | ||
10 | + end | ||
11 | + | ||
12 | + attr_accessor :profile, :person | ||
13 | + | ||
14 | + test "should get index" do | ||
15 | + get :index, :profile => profile.identifier | ||
16 | + assert_response :success | ||
17 | + assert_not_nil assigns(:email_templates) | ||
18 | + end | ||
19 | + | ||
20 | + test "should get new" do | ||
21 | + get :new, :profile => profile.identifier | ||
22 | + assert_response :success | ||
23 | + end | ||
24 | + | ||
25 | + test "should create email_template" do | ||
26 | + assert_difference('EmailTemplate.count') do | ||
27 | + post :create, email_template: { :name => 'test' }, :profile => profile.identifier | ||
28 | + end | ||
29 | + | ||
30 | + assert_redirected_to url_for(:action => :index) | ||
31 | + end | ||
32 | + | ||
33 | + test "should show email_template" do | ||
34 | + get :show, id: @email_template, :profile => profile.identifier | ||
35 | + assert_response :success | ||
36 | + end | ||
37 | + | ||
38 | + test "should get edit" do | ||
39 | + get :edit, id: @email_template, :profile => profile.identifier | ||
40 | + assert_response :success | ||
41 | + end | ||
42 | + | ||
43 | + test "should update email_template" do | ||
44 | + put :update, id: @email_template, email_template: { }, :profile => profile.identifier | ||
45 | + assert_redirected_to url_for(:action => :index) | ||
46 | + end | ||
47 | + | ||
48 | + test "should destroy email_template" do | ||
49 | + assert_difference('EmailTemplate.count', -1) do | ||
50 | + delete :destroy, id: @email_template, :profile => profile.identifier | ||
51 | + end | ||
52 | + | ||
53 | + assert_redirected_to url_for(:action => :index) | ||
54 | + end | ||
55 | + | ||
56 | + test "should get parsed template" do | ||
57 | + environment = Environment.default | ||
58 | + @email_template.subject = '{{profile.name}} - {{profile.identifier}}' | ||
59 | + @email_template.body = '{{profile.name}} - {{profile.identifier}} - {{environment.name}}' | ||
60 | + @email_template.save! | ||
61 | + get :show_parsed, id: @email_template, :profile => profile.identifier | ||
62 | + assert_response :success | ||
63 | + json_response = ActiveSupport::JSON.decode(@response.body) | ||
64 | + assert_equal "#{profile.name} - #{profile.identifier}", json_response['parsed_subject'] | ||
65 | + assert_equal "#{profile.name} - #{profile.identifier} - #{environment.name}", json_response['parsed_body'] | ||
66 | + end | ||
67 | + | ||
68 | +end |
test/functional/profile_editor_controller_test.rb
@@ -626,6 +626,17 @@ class ProfileEditorControllerTest < ActionController::TestCase | @@ -626,6 +626,17 @@ class ProfileEditorControllerTest < ActionController::TestCase | ||
626 | assert_tag :tag => 'a', :attributes => { :href => '/myprofile/default_user/cms' } | 626 | assert_tag :tag => 'a', :attributes => { :href => '/myprofile/default_user/cms' } |
627 | end | 627 | end |
628 | 628 | ||
629 | + should 'display email template link for organizations in control panel' do | ||
630 | + profile = fast_create(Organization) | ||
631 | + get :index, :profile => profile.identifier | ||
632 | + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/email_templates" } | ||
633 | + end | ||
634 | + | ||
635 | + should 'not display email template link in control panel for person' do | ||
636 | + get :index, :profile => profile.identifier | ||
637 | + assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{profile.identifier}/email_templates" } | ||
638 | + end | ||
639 | + | ||
629 | should 'offer to create blog in control panel' do | 640 | should 'offer to create blog in control panel' do |
630 | get :index, :profile => profile.identifier | 641 | get :index, :profile => profile.identifier |
631 | assert_tag :tag => 'a', :attributes => { :href => "/myprofile/default_user/cms/new?type=Blog" } | 642 | assert_tag :tag => 'a', :attributes => { :href => "/myprofile/default_user/cms/new?type=Blog" } |
test/unit/email_template_test.rb
@@ -3,10 +3,10 @@ require_relative "../test_helper" | @@ -3,10 +3,10 @@ require_relative "../test_helper" | ||
3 | class EmailTemplateTest < ActiveSupport::TestCase | 3 | class EmailTemplateTest < ActiveSupport::TestCase |
4 | 4 | ||
5 | should 'filter templates by type' do | 5 | should 'filter templates by type' do |
6 | - EmailTemplate.create!(:template_type => :type1, :subject => 'template1') | ||
7 | - EmailTemplate.create!(:template_type => :type2, :subject => 'template2') | ||
8 | - EmailTemplate.create!(:template_type => :type2, :subject => 'template3') | ||
9 | - assert_equal ['template2', 'template3'], EmailTemplate.find_all_by_template_type(:type2).map(&:subject) | 6 | + EmailTemplate.create!(:template_type => :type1, :name => 'template1') |
7 | + EmailTemplate.create!(:template_type => :type2, :name => 'template2') | ||
8 | + EmailTemplate.create!(:template_type => :type2, :name => 'template3') | ||
9 | + assert_equal ['template2', 'template3'], EmailTemplate.find_all_by_template_type(:type2).map(&:name) | ||
10 | end | 10 | end |
11 | 11 | ||
12 | should 'parse body using params' do | 12 | should 'parse body using params' do |