Browse Source

Added confirmation modals, fixed reply to emails, and added premailer

development
Godwin 9 years ago
parent
commit
718d77a3fc
  1. 1
      Gemfile
  2. 67
      app/assets/javascripts/main.js
  3. 143
      app/assets/stylesheets/_application.scss
  4. 59
      app/assets/stylesheets/user-mailer.scss
  5. 26
      app/controllers/application_controller.rb
  6. 2
      app/controllers/conferences_controller.rb
  7. 7
      app/helpers/application_helper.rb
  8. 21
      app/mailers/user_mailer.rb
  9. 6
      app/models/user.rb
  10. 10
      app/views/layouts/application.html.haml
  11. 4
      app/views/layouts/user_mailer.html.haml
  12. 3
      app/views/user_mailer/activation_needed_email.text.haml
  13. 3
      app/views/user_mailer/activation_success_email.text.haml
  14. 1
      app/views/user_mailer/broadcast.text.haml
  15. 9
      app/views/user_mailer/conference_registration_confirmed_email.text.haml
  16. 1
      app/views/user_mailer/conference_registration_email.text.haml
  17. 3
      app/views/user_mailer/email_confirmation.text.haml
  18. 10
      app/views/user_mailer/error_report.html.haml
  19. 8
      app/views/user_mailer/registration_confirmation.text.haml
  20. 4
      app/views/user_mailer/workshop_facilitator_request.html.haml
  21. 11
      app/views/user_mailer/workshop_facilitator_request.text.haml
  22. 3
      app/views/user_mailer/workshop_facilitator_request_approved.text.haml
  23. 3
      app/views/user_mailer/workshop_facilitator_request_denied.text.haml
  24. 25
      app/views/user_mailer/workshop_original_content_changed.text.haml
  25. 25
      app/views/user_mailer/workshop_translated.text.haml
  26. 6
      app/views/workshops/_show.html.haml
  27. 1
      app/views/workshops/delete.html.haml
  28. 2
      config/initializers/assets.rb
  29. 11
      config/locales/en.yml
  30. 1
      config/routes.rb

1
Gemfile

@ -36,6 +36,7 @@ gem 'sitemap_generator'
gem 'activerecord-session_store' gem 'activerecord-session_store'
gem 'paypal-express', '0.7.1' gem 'paypal-express', '0.7.1'
gem 'sass-json-vars' gem 'sass-json-vars'
gem 'premailer-rails'
gem 'delayed_job_active_record' gem 'delayed_job_active_record'
gem 'redcarpet' gem 'redcarpet'

67
app/assets/javascripts/main.js

@ -1,4 +1,17 @@
(function() { (function() {
window.onerror = function(message, url, lineNumber) {
//save error and send to server for example.
var request = new XMLHttpRequest();
request.open('POST', '/js_error', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(
'message=' + encodeURI(message) +
'&url=' + encodeURI(url) +
'&lineNumber=' + encodeURI(lineNumber) +
'&location=' + encodeURI(window.location.href)
);
return false;
};
Array.prototype.forEach.call(document.querySelectorAll('.number-field,.email-field,.text-field'), function(field) { Array.prototype.forEach.call(document.querySelectorAll('.number-field,.email-field,.text-field'), function(field) {
var input = field.querySelector('input'); var input = field.querySelector('input');
var positionLabel = function(input) { var positionLabel = function(input) {
@ -9,6 +22,55 @@
input.addEventListener('blur', function(event) { field.classList.remove('focused'); }); input.addEventListener('blur', function(event) { field.classList.remove('focused'); });
input.addEventListener('focus', function(event) { field.classList.add('focused'); }); input.addEventListener('focus', function(event) { field.classList.add('focused'); });
}); });
var body = document.querySelector('body');
var primaryContent = document.getElementById('primary-content');
var overlay = document.getElementById('content-overlay');
primaryContent.addEventListener('keydown', function(event) {
event.stopPropagation();
return false;
//if (body.classList.contains('has-overlay')) {
// return false;
//}
});
document.addEventListener('focus', function(event) {
if (overlay.querySelector('.dlg.open') && !overlay.querySelector('.dlg.open :focus')) {
overlay.querySelector('.dlg.open').focus();
}
}, true);
function openDlg(dlg, link) {
body.setAttribute('style', 'width: ' + body.clientWidth + 'px');
dlg.querySelector('.message').innerHTML = decodeURI(link.dataset.confirmation);
dlg.querySelector('.confirm').setAttribute('href', link.getAttribute('href'));
primaryContent.setAttribute('aria-hidden', 'true');
document.getElementById('overlay').onclick =
dlg.querySelector('.delete').onclick = function() { closeDlg(dlg); };
body.classList.add('has-overlay');
dlg.removeAttribute('aria-hidden');
dlg.setAttribute('role', 'alertdialog');
dlg.setAttribute('tabindex', '0');
dlg.focus();
setTimeout(function() { dlg.classList.add('open'); }, 100);
}
function closeDlg(dlg) {
setTimeout(function() {
body.classList.remove('has-overlay');
body.removeAttribute('style');
}, 250);
primaryContent.removeAttribute('aria-hidden');
dlg.setAttribute('aria-hidden', 'true');
dlg.removeAttribute('tabindex');
dlg.classList.remove('open');
dlg.removeAttribute('role');
}
var confirmationDlg = document.getElementById('confirmation-dlg');
Array.prototype.forEach.call(document.querySelectorAll('a[data-confirmation]'), function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(confirmationDlg, link);
return false;
});
});
var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea'); var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea');
if (errorField) { if (errorField) {
errorField.focus(); errorField.focus();
@ -16,7 +78,10 @@
var htmlNode = document.documentElement; var htmlNode = document.documentElement;
document.addEventListener('keydown', function(event) { document.addEventListener('keydown', function(event) {
if (htmlNode.dataset.input != 'kb' && ["input", "select", "option"].includes("input".toLowerCase())) { if (htmlNode.dataset.input != 'kb' &&
!["input", "textarea", "select", "option"].includes(event.target.nodeName.toLowerCase()) &&
!event.target.attributes.contenteditable) {
console.log()
htmlNode.setAttribute('data-input', 'kb'); htmlNode.setAttribute('data-input', 'kb');
} }
}); });

143
app/assets/stylesheets/_application.scss

@ -90,6 +90,7 @@ table {
button, button,
.button { .button {
@include button; @include button;
vertical-align: top;
#main &[type="submit"] { #main &[type="submit"] {
background-color: $colour-5; background-color: $colour-5;
@ -111,6 +112,7 @@ button,
background-color: $colour-5; background-color: $colour-5;
} }
&.delete,
#main &.delete { #main &.delete {
background-color: $colour-4; background-color: $colour-4;
} }
@ -1280,6 +1282,97 @@ $header-tilt: 8deg;
} }
} }
body {
#primary-content {
@include _(transition, 'filter 250ms ease-in-out, -webkit-filter 250ms ease-in-out');
}
&.has-overlay {
overflow: hidden;
#primary-content {
-webkit-filter: blur(5px);
@include _(filter, blur(5px));
}
#overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
cursor: pointer;
z-index: 1000;
}
}
}
#content-overlay {
display: none;
body.has-overlay & {
display: block;
}
.dlg {
@include before {
content: '';
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba($black, 0);
@include _(transition, background-color 250ms ease-in-out);
}
&.open {
@include before {
background-color: rgba($black, 0.5);
}
.dlg-content {
@include _(transform, rotateZ(0deg));
}
}
}
.dlg-content {
position: fixed;
right: 0;
bottom: 0;
left: 0;
max-width: 50rem;
margin: auto;
z-index: 1001;
background-color: $white;
text-align: center;
@include _(transition, transform 500ms ease-in-out);
@include _(transform, rotateX(-90deg));
@include _(transform-origin, center 250%);
}
.title {
padding: 0.5em;
background-color: $colour-5;
color: $white;
@include _(text-stroke, 1px rgba(0, 0, 0, 0.25));
}
.dlg-inner {
padding: 0 2em 2em;
}
button, .button {
margin: 0 0.25em;
}
.message {
font-size: 1.5em;
margin-bottom: 2em;
}
}
@include keyframes(fade-out) { @include keyframes(fade-out) {
to { to {
@include _(opacity, 0.25); @include _(opacity, 0.25);
@ -1296,33 +1389,6 @@ html :focus {
outline: 0; outline: 0;
} }
html[data-input="kb"] {
:focus,
input[type="submit"]:focus,
.check-box-field input:focus + label,
.radio-button-field input:focus + label,
.select-field select:focus,
.workshop-link:focus .title,
#main-nav .nav a:focus .title {
outline: 0.25rem solid rgba($colour-2, 0.5);
outline-offset: 0.2rem;
z-index: 1;
}
#main-nav .logo:focus {
outline-offset: -0.2em;
}
/*input:focus,
textarea:focus,
select:focus,
.textarea {*/
.workshop-link:focus,
#main-nav .nav a:focus {
outline: none;
}
}
@mixin header-colour($page, $colour) { @mixin header-colour($page, $colour) {
body.#{$page} { body.#{$page} {
#header-title { #header-title {
@ -2259,6 +2325,29 @@ html[data-lingua-franca-example="html"] {
} }
@include breakpoint(medium) { @include breakpoint(medium) {
html[data-input="kb"] {
:focus,
input[type="submit"]:focus,
.check-box-field input:focus + label,
.radio-button-field input:focus + label,
.select-field select:focus,
.workshop-link:focus .title,
#main-nav .nav a:focus .title {
outline: 0.25rem solid rgba($colour-2, 0.5);
outline-offset: 0.2rem;
z-index: 1;
}
#main-nav .logo:focus {
outline-offset: -0.2em;
}
.workshop-link:focus,
#main-nav .nav a:focus {
outline: none;
}
}
body { body {
padding-bottom: 0; padding-bottom: 0;
} }

59
app/assets/stylesheets/user-mailer.scss

@ -4,7 +4,7 @@ body {
width: 100% !important; width: 100% !important;
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%; -ms-text-size-adjust: 100%;
margin: 0; margin: 1em;
padding: 0; padding: 0;
} }
@ -69,12 +69,25 @@ a {
} }
p { p {
margin: 1em;
color: $black !important; color: $black !important;
}
p, blockquote {
margin: 1em;
font-size: 1.5em; font-size: 1.5em;
line-height: 1.3333em; line-height: 1.3333em;
} }
blockquote {
font-style: italic;
margin-bottom: 2em;
color: #666 !important;
border: 0.1em solid #CCC;
padding: 1em;
border-style: none none solid solid;
background-color: #F8F8F8;
}
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
color: $black !important; color: $black !important;
@ -117,6 +130,48 @@ table#ecxbb_full_width {
} }
} }
.error-report {
width: 100%;
max-width: 100%;
border: 0.15em solid #CCC;
background-color: #EEE;
font-size: 1.25em;
margin-bottom: 2em;
th {
background-color: #CCC;
}
td, th {
padding: 0.25em 0.5em;
&:last-child {
border-left: 0.15em solid #CCC;
min-width: 40em;
}
}
td:last-child {
font-family: monospace;
word-break: break-word;
background-color: #FFF;
font-size: 0.75em;
}
}
code {
color: #C33;
font-size: 0.9em;
}
pre {
font-size: 1.5em;
padding: 1em;
background-color: #333;
color: antiquewhite;
word-break: break-word;
}
.diff, .ecxdiff { .diff, .ecxdiff {
margin: 1em 0 5em 1em; margin: 1em 0 5em 1em;
overflow: auto; overflow: auto;

26
app/controllers/application_controller.rb

@ -8,7 +8,7 @@ class ApplicationController < LinguaFrancaApplicationController
# Prevent CSRF attacks by raising an exception. # Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead. # For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception, :except => [:do_confirm] protect_from_forgery with: :exception, :except => [:do_confirm, :js_error]
before_filter :capture_page_info before_filter :capture_page_info
@ -100,7 +100,6 @@ class ApplicationController < LinguaFrancaApplicationController
end end
def error_500(exception) def error_500(exception)
@page_title = 'page_titles.500.An_Error_Occurred' @page_title = 'page_titles.500.An_Error_Occurred'
@main_title = 'error.500.title' @main_title = 'error.500.title'
params[:_original_action] = params[:action] params[:_original_action] = params[:action]
@ -108,6 +107,26 @@ class ApplicationController < LinguaFrancaApplicationController
render 'application/500', status: 500 render 'application/500', status: 500
end end
def js_error
# send and email if this is production
report = "A JavaScript error has occurred on <code>#{params[:location]}</code>"
if params[:location] == params[:url]
report += " on line <code>#{params[:lineNumber]}</code>"
else
report += " in <code>#{params[:url]}:#{params[:lineNumber]}</code>"
end
UserMailer.error_report(
"A JavaScript error has occurred",
report,
params[:message],
nil,
request,
params,
current_user,
).deliver_now if Rails.env.preview? || Rails.env.production?
render json: {}
end
rescue_from ActiveRecord::RecordNotFound do |exception| rescue_from ActiveRecord::RecordNotFound do |exception|
do_404 do_404
end end
@ -143,6 +162,7 @@ class ApplicationController < LinguaFrancaApplicationController
# show the error page # show the error page
error_500 exception error_500 exception
raise exception
end end
def generate_confirmation(user, url, expiry = nil) def generate_confirmation(user, url, expiry = nil)
@ -276,7 +296,7 @@ class ApplicationController < LinguaFrancaApplicationController
# send and email if this is production # send and email if this is production
UserMailer.error_report( UserMailer.error_report(
"A missing translation found in #{Rails.env}", "A missing translation found in #{Rails.env}",
"A translation for #{key} in #{locale.to_s} was found. The text that was rendered to the user was \"#{str || 'nil'}\".", "<p>A translation for <code>#{key}</code> in <code>#{locale.to_s}</code> was found. The text that was rendered to the user was:</p><blockquote>#{str || 'nil'}</blockquote>",
exception.to_s, exception.to_s,
exception, exception,
request, request,

2
app/controllers/conferences_controller.rb

@ -1002,7 +1002,7 @@ class ConferencesController < ApplicationController
return redirect_to workshops_url return redirect_to workshops_url
end end
return redirect_to edit_workshop_url(@this_conference.slug, @workshop.id) return redirect_to view_workshop_url(@this_conference.slug, @workshop.id)
end end
render 'workshops/delete' render 'workshops/delete'

7
app/helpers/application_helper.rb

@ -161,15 +161,12 @@ module ApplicationHelper
classes << 'fixed-banner' if is_header_fixed? classes << 'fixed-banner' if is_header_fixed?
if params[:controller] if params[:controller]
if params[:controller] == 'application'
if params[:action]
classes << params[:action] classes << params[:action]
end unless params[:controller] == 'application'
else
classes << params[:controller] classes << params[:controller]
if params[:action] if params[:action]
classes << params[:controller] + '-' + params[:action] classes << "#{params[:controller]}-#{params[:action]}"
end end
end end
end end

21
app/mailers/user_mailer.rb

@ -49,7 +49,7 @@ class UserMailer < ActionMailer::Base
def email_confirmation(confirmation) def email_confirmation(confirmation)
@confirmation = confirmation @confirmation = confirmation
@subject = _'email.subject.confirm_email','Please confirm your email address' @subject = _'email.subject.confirm_email','Please confirm your email address'
mail to: confirmation.user.email, subject: @subject mail to: confirmation.user.named_email, subject: @subject
end end
def registration_confirmation(registration) def registration_confirmation(registration)
@ -66,7 +66,7 @@ class UserMailer < ActionMailer::Base
"Thank you for registering for #{@conference.title}", "Thank you for registering for #{@conference.title}",
:vars => {:conference_title => @conference.title} :vars => {:conference_title => @conference.title}
) )
mail to: @user.email, subject: @subject mail to: @user.named_email, subject: @subject
end end
def broadcast(host, subject, content, user, conference) def broadcast(host, subject, content, user, conference)
@ -74,8 +74,8 @@ class UserMailer < ActionMailer::Base
@content = content @content = content
@banner = nil#(@host || 'http://localhost/') + (conference ? (conference.poster.preview.url || '') : image_url('logo.png')) @banner = nil#(@host || 'http://localhost/') + (conference ? (conference.poster.preview.url || '') : image_url('logo.png'))
@subject = "[#{conference ? conference.title : 'Bike!Bike!'}] #{subject}" @subject = "[#{conference ? conference.title : 'Bike!Bike!'}] #{subject}"
if user && user.email if user && user.named_email
email = user.email email = user.named_email
mail to: email, subject: @subject mail to: email, subject: @subject
end end
end end
@ -85,14 +85,15 @@ class UserMailer < ActionMailer::Base
@requester = requester @requester = requester
addresses = [] addresses = []
@workshop.active_facilitators.each do |f| @workshop.active_facilitators.each do |f|
addresses << f.email addresses << f.named_email
end end
addresses << 'michael.allen.godwin@gmail.com'
@message = message @message = message
@conference = Conference.find(@workshop.conference_id) @conference = Conference.find(@workshop.conference_id)
@subject = _('email.subject.workshop_facilitator_request', @subject = _('email.subject.workshop_facilitator_request',
"Request to facilitate #{@workshop.title} from #{@requester.name}", "Request to facilitate #{@workshop.title} from #{@requester.name}",
:vars => {:workshop_title => @workshop.title, :requester_name => @requester.firstname}) :vars => {:workshop_title => @workshop.title, :requester_name => @requester.firstname})
mail to: addresses, from: @requester.email, subject: @subject mail to: addresses, reply_to: addresses + [@requester.named_email], subject: @subject
end end
def workshop_facilitator_request_approved(workshop, user) def workshop_facilitator_request_approved(workshop, user)
@ -102,7 +103,7 @@ class UserMailer < ActionMailer::Base
@subject = (_'email.subject.workshop_request_approved', @subject = (_'email.subject.workshop_request_approved',
"You have been added as a facilitator of #{@workshop.title}", "You have been added as a facilitator of #{@workshop.title}",
:vars => {:workshop_title => @workshop.title}) :vars => {:workshop_title => @workshop.title})
mail to: user.email, subject: @subject mail to: user.named_email, subject: @subject
end end
def workshop_facilitator_request_denied(workshop, user) def workshop_facilitator_request_denied(workshop, user)
@ -112,7 +113,7 @@ class UserMailer < ActionMailer::Base
@subject = (_'email.subject.workshop_request_denied', @subject = (_'email.subject.workshop_request_denied',
"Your request to facilitate #{@workshop.title} has been denied", "Your request to facilitate #{@workshop.title} has been denied",
:vars => {:workshop_title => @workshop.title}) :vars => {:workshop_title => @workshop.title})
mail to: user.email, subject: @subject mail to: user.named_email, subject: @subject
end end
def workshop_translated(workshop, data, locale, user, translator) def workshop_translated(workshop, data, locale, user, translator)
@ -135,7 +136,7 @@ class UserMailer < ActionMailer::Base
@wrapper_id = :full_width @wrapper_id = :full_width
mail to: user.email, subject: @subject mail to: user.named_email, subject: @subject
end end
def workshop_original_content_changed(workshop, data, user, translator) def workshop_original_content_changed(workshop, data, user, translator)
@ -156,7 +157,7 @@ class UserMailer < ActionMailer::Base
@wrapper_id = :full_width @wrapper_id = :full_width
mail to: user.email, subject: @subject mail to: user.named_email, subject: @subject
end end
def error_report(subject, message, report, exception, request, params, user) def error_report(subject, message, report, exception, request, params, user)

6
app/models/user.rb

@ -35,4 +35,10 @@ class User < ActiveRecord::Base
firstname || username || email firstname || username || email
end end
def named_email
name = firstname || username
return email unless name
return "#{name} <#{email}>"
end
end end

10
app/views/layouts/application.html.haml

@ -17,6 +17,7 @@
= yield :head = yield :head
%body{ class: page_style } %body{ class: page_style }
#primary-content
= render 'shared/navbar' = render 'shared/navbar'
%main#main %main#main
- if content_for?(:side_bar) - if content_for?(:side_bar)
@ -37,6 +38,15 @@
= yield = yield
#footer #footer
%footer= render 'shared/footer' %footer= render 'shared/footer'
#content-overlay
#overlay
.dlg#confirmation-dlg
.dlg-content
%h2.title=_'modals.confirm'
.dlg-inner
%p.message=''
%a.button.confirm=_'modals.yes_button'
%button.delete=_'modals.no_button'
= yield :footer_scripts if content_for?(:footer_scripts) = yield :footer_scripts if content_for?(:footer_scripts)
- add_inline_script :main - add_inline_script :main

4
app/views/layouts/user_mailer.html.haml

@ -4,7 +4,7 @@
%meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}/ %meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}/
%meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}/ %meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}/
%title=@subject %title=@subject
%style{type: 'text/css'}=Rails.application.assets.find_asset("user-mailer.css").to_s = stylesheet_link_tag 'user-mailer'
%body %body
%table{:border => "0", :cellpadding => "0", :cellspacing => "0", id: @wrapper_id.present? ? "bb_#{@wrapper_id.to_s}" : 'backgroundTable'} %table{:border => "0", :cellpadding => "0", :cellspacing => "0", id: @wrapper_id.present? ? "bb_#{@wrapper_id.to_s}" : 'backgroundTable'}
%tr %tr
@ -20,7 +20,7 @@
%td{colspan: 2, style: 'height: 16px'}='&nbsp;'.html_safe %td{colspan: 2, style: 'height: 16px'}='&nbsp;'.html_safe
%tr %tr
%td{style: 'width: 50%; text-align: left'} %td{style: 'width: 50%; text-align: left'}
%img.image_fix{:src => (@host + image_url('bblogo-paypal'))} %img.image_fix{:src => ((Rails.env.development? || Rails.env.test? ? 'https://preview-en.bikebike.org/' : @host) + image_url('bblogo-paypal'))}
%td{style: 'width: 50%; text-align: left'} %td{style: 'width: 50%; text-align: left'}
%a{href: @host}="&copy; Bike!Bike! #{Date.today.year}".html_safe %a{href: @host}="&copy; Bike!Bike! #{Date.today.year}".html_safe
%tr %tr

3
app/views/user_mailer/activation_needed_email.text.haml

@ -1,3 +0,0 @@
UserMailer#activation_needed_email
= @greeting + ", find me in app/views/user_mailer/activation_needed_email.text.haml"

3
app/views/user_mailer/activation_success_email.text.haml

@ -1,3 +0,0 @@
UserMailer#activation_success_email
= @greeting + ", find me in app/views/user_mailer/activation_success_email.text.haml"

1
app/views/user_mailer/broadcast.text.haml

@ -1 +0,0 @@
=@content

9
app/views/user_mailer/conference_registration_confirmed_email.text.haml

@ -1,9 +0,0 @@
=_'register.email.registration_confirmed.thank_you',"Hi #{@data[:user][:username]}, thank you for completing your registration. We'll see you at Bike!Bike!"
=_'register.email.registration_confirmed.please_pay',"If you have not already done so, we ask that you pay the registration donation as soon as you can. At your convenience please visit the link below."
= @confirmation_url
=_'register.email.registration_confirmed.info',"We'll have housing, loaner bikes, and food arranged for your arrival. If you have any other questions or concerns, please email bikebike2014columbus@gmail.com."
=_'register.email.registration_confirmed.contact',"For urgent/emergency matters, you can reach our Outreach Coordinator, Reda, at 503-984-9191 or Jason at 614-364-3636."

1
app/views/user_mailer/conference_registration_email.text.haml

@ -1 +0,0 @@
=_('register.email.registration.please_confirm',"Hi #{@data[:user][:username]}, please confirm your registration for #{@conference.title}", vars: {:username => @data[:user][:username]}) + ": #{@confirmation_url}"

3
app/views/user_mailer/email_confirmation.text.haml

@ -1,3 +0,0 @@
=_'email.confirmation.paragraph.please_confirm','Hello! To gain access to registration and other features of Bike!Bike!, please confirm your email address by clicking on following link:'
=''
="#{@host}/confirm/#{@confirmation.token}"

10
app/views/user_mailer/error_report.html.haml

@ -1,12 +1,12 @@
%p=@message if @message.present? %p=@message.html_safe if @message.present?
%p=@report %pre=@report
- if @exception.present? && @exception.respond_to?(:backtrace) - if @exception.present? && @exception.respond_to?(:backtrace)
%h1 Backtrace %h1 Backtrace
%pre=@exception.backtrace.join("\n") %pre=@exception.backtrace.join("\n")
%h1 Details %h1 Details
%table %table.error-report
%tr %tr
%th Key %th Key
%th Value %th Value
@ -30,7 +30,7 @@
%td=@request.original_url %td=@request.original_url
%h1 Params %h1 Params
%table %table.error-report
%tr %tr
%th Key %th Key
%th Value %th Value
@ -40,7 +40,7 @@
%td=value.to_s %td=value.to_s
%h1 Request Environment %h1 Request Environment
%table %table.error-report
%tr %tr
%th Key %th Key
%th Value %th Value

8
app/views/user_mailer/registration_confirmation.text.haml

@ -1,8 +0,0 @@
=_'email.general.paragraph.thank_you', "Thank you #{@user.firstname},", :vars => {:name => @user.firstname}
- if @conference.registration_status.to_sym == :pre
=_'email.general.paragraph.pre_registered', "You have successfully pre-registered for #{@conference.title}. We will let you know when registration is fully open and if there is any important news about the conference that you should know about. We encourage you to create or volunteer to facilitate workshops soon. You can do that, or change your registration details at any time by clicking on the pre-register link again.", :vars => {:conference_title => @conference.title}
- else
=_'email.registration.paragraph.confirmed', :vars => {:conference_title => @conference.title}
=_'email.general.paragraph.see_you', :vars => {:conference_location => @conference.location.city}

4
app/views/user_mailer/workshop_facilitator_request.html.haml

@ -1,6 +1,6 @@
%p=_'email.workshop.paragraph.request_message',"Below is a message from #{@requester.firstname}:", :vars => {:workshop_title => @workshop.title, :user_name => @requester.firstname} %p=_'email.workshop.paragraph.request_message',"Below is a message from #{@requester.firstname}:", :vars => {:workshop_title => @workshop.title, :user_name => @requester.name}
%blockquote=markdown @message %blockquote=CGI::escapeHTML(@message || '').gsub(/\n/, '<br>').html_safe
%p %p
=_'email.workshop.paragraph.request_instructions',"You can approve or deny this request on your workshop page: " =_'email.workshop.paragraph.request_instructions',"You can approve or deny this request on your workshop page: "

11
app/views/user_mailer/workshop_facilitator_request.text.haml

@ -1,11 +0,0 @@
=_'email.workshop.paragraph.request_message',"Below is a message from #{@requester.firstname}:", :vars => {:workshop_title => @workshop.title, :user_name => @requester.firstname}
=' ------------------------- '
=@message
=' ------------------------- '
=_'email.workshop.paragraph.request_instructions',"You can approve or deny this request on your workshop page: "
=@host + view_workshop_path(@conference.slug, @workshop.id)
=_'email.workshop.paragraph.request_reply_instructions',"You can also reply directly to this email to ask follow-up questions."

3
app/views/user_mailer/workshop_facilitator_request_approved.text.haml

@ -1,3 +0,0 @@
=_'email.workshop.paragraph.request_approved',"Your request to become a facilitator of #{@workshop.title} has been approved and you may now edit the workshop.", :vars => {:workshop_title => @workshop.title}
=@host + view_workshop_path(@conference.slug, @workshop.id)

3
app/views/user_mailer/workshop_facilitator_request_denied.text.haml

@ -1,3 +0,0 @@
=_'email.workshop.paragraph.request_denied',"Your request to become a facilitator of #{@workshop.title} has been denied. If you think this was in error, you may contact the current facilitators by making another request to facilitate.", :vars => {:workshop_title => @workshop.title}
=@host + view_workshop_path(@conference.slug, @workshop.id)

25
app/views/user_mailer/workshop_original_content_changed.text.haml

@ -1,25 +0,0 @@
=_('email.translations.paragraph.workshop_translated', "#{@translator.name} has modified the #{@locale_name} translation for #{@workshop.title}.", vars: {user_name: @translator.firstname, language: @locale_name, workshop_title: @workshop.title})
- @data.each do |field, values|
=(_!'** ') + (_"forms.labels.generic.#{field.to_s}")
=(_!' - ') + (_'email.translations.headings.new_value')
=(_!' ------------------------------ ')
=_!values[:new]
=(_!' ------------------------------ ')
=(_!' - ') + (_'email.translations.headings.old_value')
=(_!' ------------------------------ ')
=_!values[:old]
=(_!' ------------------------------ ')
=(_!' - ') + (_'email.translations.headings.diff')
=(_!' ------------------------------ ')
=(_!values[:diff][:text])
=(_!' ------------------------------ ')
=_'email.workshop.paragraph.view_workshop',"You can view the workshop here: "
= @host + view_workshop_path(@workshop.conference.slug, @workshop.id)

25
app/views/user_mailer/workshop_translated.text.haml

@ -1,25 +0,0 @@
=_('email.translations.paragraph.workshop_translated', "#{@translator.firstname} has modified the #{@locale_name} translation for #{@workshop.title}.", vars: {user_name: @translator.firstname, language: @locale_name, workshop_title: @workshop.title})
- @data.each do |field, values|
=(_!'** ') + (_"forms.labels.generic.#{field.to_s}")
=(_!' - ') + (_'email.translations.headings.new_value')
=(_!' ------------------------------ ')
=_!values[:new]
=(_!' ------------------------------ ')
=(_!' - ') + (_'email.translations.headings.old_value')
=(_!' ------------------------------ ')
=_!values[:old]
=(_!' ------------------------------ ')
=(_!' - ') + (_'email.translations.headings.diff')
=(_!' ------------------------------ ')
=(_!values[:diff][:text])
=(_!' ------------------------------ ')
=_'email.workshop.paragraph.view_workshop',"You can view the workshop here: "
= view_workshop_path(@workshop.conference.slug, @workshop.id)

6
app/views/workshops/_show.html.haml

@ -32,11 +32,11 @@
=(link_to (_'actions.workshops.Approve'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'approve'), :class => [:button, :modify]) =(link_to (_'actions.workshops.Approve'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'approve'), :class => [:button, :modify])
=(link_to (_'actions.workshops.Deny'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'deny'), :class => [:button, :delete]) =(link_to (_'actions.workshops.Deny'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'deny'), :class => [:button, :delete])
- elsif workshop.can_remove?(current_user, u) - elsif workshop.can_remove?(current_user, u)
=(link_to (_'actions.workshops.Make_Owner'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'switch_ownership'), :class => [:button, :modify]) unless f.role.to_sym == :creator || !workshop.creator?(current_user) =(link_to (_'actions.workshops.Make_Owner'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'switch_ownership'), :class => [:button, :modify], data: {confirmation: CGI::escapeHTML(_'modals.workshops.facilitators.confirm_transfer_ownership', vars: { user_name: u.name})}) unless f.role.to_sym == :creator || !workshop.creator?(current_user)
=(link_to (_'actions.workshops.Remove'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete]) =(link_to (_'actions.workshops.Remove'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete], data: {confirmation: CGI::escapeHTML(_'modals.workshops.facilitators.confirm_remove', vars: { user_name: u.name})})
- if f.user_id == current_user.id && workshop.requested_collaborator?(current_user) - if f.user_id == current_user.id && workshop.requested_collaborator?(current_user)
.details .details
=(link_to (_'actions.workshops.Remove'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete]) =(link_to (_'actions.workshops.Remove'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => [:button, :delete], data: {confirmation: CGI::escapeHTML(_'modals.workshops.facilitators.confirm_remove_self')})
- unless preview.present? - unless preview.present?
=(link_to (_'actions.workshops.Facilitate'), facilitate_workshop_path(workshop.conference.slug, workshop.id), :class => [:button, workshop.needs_facilitators ? :accented : :subdued]) unless workshop.facilitator?(current_user) =(link_to (_'actions.workshops.Facilitate'), facilitate_workshop_path(workshop.conference.slug, workshop.id), :class => [:button, workshop.needs_facilitators ? :accented : :subdued]) unless workshop.facilitator?(current_user)
- if is_facilitator - if is_facilitator

1
app/views/workshops/delete.html.haml

@ -3,6 +3,7 @@
= row do = row do
= columns(medium: 12) do = columns(medium: 12) do
%h2=_'articles.workshops.headings.Delete_Workshop',"Are you sure you want to delete the workshop: <em>#{@workshop.title}</em>?", :vars => {:title => "<em>#{@workshop.title}</em>".html_safe} %h2=_'articles.workshops.headings.Delete_Workshop',"Are you sure you want to delete the workshop: <em>#{@workshop.title}</em>?", :vars => {:title => "<em>#{@workshop.title}</em>".html_safe}
%p=_'articles.workshops.paragraphs.Delete_Workshop'
= form_tag delete_workshop_path(@this_conference.slug, @workshop.id), class: 'composition' do = form_tag delete_workshop_path(@this_conference.slug, @workshop.id), class: 'composition' do
.actions .actions
= button_tag :confirm, :value => :confirm, :class => :delete = button_tag :confirm, :value => :confirm, :class => :delete

2
config/initializers/assets.rb

@ -8,4 +8,4 @@ Rails.application.config.assets.version = '1.0'
# Precompile additional assets. # Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
Rails.application.config.assets.precompile += %w( map.js pen.js editor.js markdown.js main.js favicon.ico ) Rails.application.config.assets.precompile += %w( user-mailer.css map.js pen.js editor.js markdown.js main.js favicon.ico )

11
config/locales/en.yml

@ -5259,6 +5259,15 @@ en:
conference: conference:
actions: actions:
Register: Register Register: Register
modals:
confirm: Please Confirm
yes_button: 'Yes'
no_button: 'No'
workshops:
facilitators:
confirm_remove: Are you sure you would like to remove %{user_name} as a facilitator of this workshop?
confirm_remove_self: Are you sure you would like to remove yourself as a facilitator of this workshop?
confirm_transfer_ownership: By transferring ownership, you will lose administrative capabilities such as deletion and approving new facilitators. Are you sure you want to transfer ownership to %{user_name}?
articles: articles:
policy: policy:
headings: headings:
@ -5512,6 +5521,7 @@ en:
theme: Which of the themes below best match your workshop? This will help theme: Which of the themes below best match your workshop? This will help
hosts to avoid scheduling conflicts. Select other if none of the options hosts to avoid scheduling conflicts. Select other if none of the options
match in any way. match in any way.
Delete_Workshop: Deleting a workshop cannot be undone, are you sure that you want to proceed?
new_workshop: 'Workshops in the past have tended to fit into a few broad categories: new_workshop: 'Workshops in the past have tended to fit into a few broad categories:
structural/organizational (how to start a shop, how to register a non-profit, structural/organizational (how to start a shop, how to register a non-profit,
consensus decision making, etc,) mechanical (how to weld two tandems to consensus decision making, etc,) mechanical (how to weld two tandems to
@ -5744,6 +5754,7 @@ en:
paragraph: paragraph:
workshop_translated: '%{user_name} has modified the %{language} translation for %{workshop_title}.' workshop_translated: '%{user_name} has modified the %{language} translation for %{workshop_title}.'
workshop_original_content_changed: '%{user_name} has modified the original content for %{workshop_title}. Translations may need to be updated.' workshop_original_content_changed: '%{user_name} has modified the original content for %{workshop_title}. Translations may need to be updated.'
workshop:
paragraph: paragraph:
request_approved: You have been added as a facilitator of %{workshop_title}. request_approved: You have been added as a facilitator of %{workshop_title}.
request_denied: Your request to become a facilitator of %{workshop_title} request_denied: Your request to become a facilitator of %{workshop_title}

1
config/routes.rb

@ -50,6 +50,7 @@ BikeBike::Application.routes.draw do
get '/oauth/:provider' => 'oauths#oauth', :as => :auth_at_provider get '/oauth/:provider' => 'oauths#oauth', :as => :auth_at_provider
post '/translator-request' => 'application#translator_request', :as => :translator_request post '/translator-request' => 'application#translator_request', :as => :translator_request
post '/js_error' => 'application#js_error'
get '/error_403' => 'application#do_403' get '/error_403' => 'application#do_403'
get '/error_404' => 'application#error_404' get '/error_404' => 'application#error_404'
get '/error_500' => 'application#error_500' get '/error_500' => 'application#error_500'

Loading…
Cancel
Save