Commit d215b23272bc035473d4d686d57f81bb5e99f412
1 parent
e083ea4a
Exists in
staging
and in
4 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 @@ |
| 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 | 353 | |
| 354 | 354 | def send_mail |
| 355 | 355 | @mailing = profile.mailings.build(params[:mailing]) |
| 356 | + @email_templates = profile.email_templates | |
| 356 | 357 | if request.post? |
| 357 | 358 | @mailing.locale = locale |
| 358 | 359 | @mailing.person = user | ... | ... |
app/models/email_template.rb
app/models/environment.rb
app/models/profile.rb
| ... | ... | @@ -151,6 +151,8 @@ class Profile < ActiveRecord::Base |
| 151 | 151 | |
| 152 | 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 | 156 | # Although this should be a has_one relation, there are no non-silly names for |
| 155 | 157 | # a foreign key on article to reference the template to which it is |
| 156 | 158 | # welcome_page... =P |
| ... | ... | @@ -471,6 +473,10 @@ class Profile < ActiveRecord::Base |
| 471 | 473 | self.articles.find(:all, options) |
| 472 | 474 | end |
| 473 | 475 | |
| 476 | + def to_liquid | |
| 477 | + HashWithIndifferentAccess.new :name => name, :identifier => identifier | |
| 478 | + end | |
| 479 | + | |
| 474 | 480 | class << self |
| 475 | 481 | |
| 476 | 482 | # finds a profile by its identifier. This method is a shortcut to | ... | ... |
| ... | ... | @@ -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 @@ |
| 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 | 4 | |
| 5 | 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 | 13 | <%= form_for :mailing, :url => {:action => 'send_mail'}, :html => {:id => 'mailing-form'} do |f| %> |
| 8 | 14 | |
| 9 | 15 | <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> | ... | ... |
app/views/profile_editor/index.html.erb
| ... | ... | @@ -72,6 +72,8 @@ |
| 72 | 72 | |
| 73 | 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 | 77 | <% @plugins.dispatch(:control_panel_buttons).each do |button| %> |
| 76 | 78 | <%= control_panel_button(button[:title], button[:icon], button[:url], button[:html_options]) %> |
| 77 | 79 | <% end %> | ... | ... |
public/javascripts/application.js
| ... | ... | @@ -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 @@ |
| 1 | +Subproject commit e7ad7849b3ef685639d4c5c0bef7b323255e2afa | ... | ... |
public/stylesheets/application.css
| ... | ... | @@ -14,6 +14,7 @@ |
| 14 | 14 | * views specifics |
| 15 | 15 | *= require chat |
| 16 | 16 | *= require search |
| 17 | + *= require email-templates | |
| 17 | 18 | */ |
| 18 | 19 | |
| 19 | 20 | /* browser fixes */ |
| ... | ... | @@ -4658,6 +4659,9 @@ h1#agenda-title { |
| 4658 | 4659 | .controller-profile_editor a.control-panel-design-editor { |
| 4659 | 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 | 4665 | .controller-profile_editor .msie6 a.control-panel-design-editor { |
| 4662 | 4666 | background-image: url(../images/control-panel/preferences-desktop-wallpaper.gif) |
| 4663 | 4667 | } | ... | ... |
| ... | ... | @@ -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 @@ |
| 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 | 626 | assert_tag :tag => 'a', :attributes => { :href => '/myprofile/default_user/cms' } |
| 627 | 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 | 640 | should 'offer to create blog in control panel' do |
| 630 | 641 | get :index, :profile => profile.identifier |
| 631 | 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 | 3 | class EmailTemplateTest < ActiveSupport::TestCase |
| 4 | 4 | |
| 5 | 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 | 10 | end |
| 11 | 11 | |
| 12 | 12 | should 'parse body using params' do | ... | ... |