Commit d215b23272bc035473d4d686d57f81bb5e99f412
1 parent
e083ea4a
Exists in
staging
and in
7 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 |