Commit e4b455c6 by tady

mail view

parent 4311c1e2
...@@ -19,3 +19,6 @@ IfUnlessModifier: ...@@ -19,3 +19,6 @@ IfUnlessModifier:
CyclomaticComplexity: CyclomaticComplexity:
Max: 10 Max: 10
RaiseArgs:
Enabled: false
...@@ -14,6 +14,8 @@ gem 'uglifier' ...@@ -14,6 +14,8 @@ gem 'uglifier'
# Use CoffeeScript for .js.coffee assets and views # Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails' gem 'coffee-rails'
gem 'jquery-rails'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes # See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby # gem 'therubyracer', platforms: :ruby
...@@ -110,3 +112,6 @@ gem 'nokogiri' ...@@ -110,3 +112,6 @@ gem 'nokogiri'
gem 'premailer' gem 'premailer'
gem 'faraday' gem 'faraday'
# Check mail format
gem 'validates_email_format_of'
...@@ -134,6 +134,9 @@ GEM ...@@ -134,6 +134,9 @@ GEM
jbuilder (2.0.1) jbuilder (2.0.1)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
multi_json (>= 1.2.0) multi_json (>= 1.2.0)
jquery-rails (3.0.4)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.8.1) json (1.8.1)
jwt (0.1.8) jwt (0.1.8)
multi_json (>= 1.5) multi_json (>= 1.5)
...@@ -297,6 +300,7 @@ GEM ...@@ -297,6 +300,7 @@ GEM
unf (0.1.3) unf (0.1.3)
unf_ext unf_ext
unf_ext (0.0.6) unf_ext (0.0.6)
validates_email_format_of (1.5.3)
warden (1.2.3) warden (1.2.3)
rack (>= 1.0) rack (>= 1.0)
webrobots (0.1.1) webrobots (0.1.1)
...@@ -325,6 +329,7 @@ DEPENDENCIES ...@@ -325,6 +329,7 @@ DEPENDENCIES
guard-spring guard-spring
i18n_generators i18n_generators
jbuilder jbuilder
jquery-rails
launchy launchy
mail mail
mysql2 mysql2
...@@ -344,3 +349,4 @@ DEPENDENCIES ...@@ -344,3 +349,4 @@ DEPENDENCIES
sqlite3 sqlite3
thin thin
uglifier uglifier
validates_email_format_of
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
// //
//= require_self //= require_self
// require jquery // require jquery
// require jquery_ujs //= require jquery_ujs
// require turbolinks // require turbolinks
//= require_tree ./lib //= require_tree ./lib
//= require_tree . //= require_tree .
......
...@@ -11,7 +11,9 @@ if window.location.pathname.match /^\/posts\/?$/ ...@@ -11,7 +11,9 @@ if window.location.pathname.match /^\/posts\/?$/
$this.addClass('active') $this.addClass('active')
id = $this.data('postId') id = $this.data('postId')
$.get('/posts/show_fragment', { id: id }) $.get("/posts/#{id}", {
fragment: 1
})
.done (data) -> .done (data) ->
$('#list_post').html(data) $('#list_post').html(data)
prettyPrint() prettyPrint()
...@@ -21,8 +23,8 @@ if window.location.pathname.match /^\/posts\/?$/ ...@@ -21,8 +23,8 @@ if window.location.pathname.match /^\/posts\/?$/
id_param = RV.tools.getQueryParams()["id"] id_param = RV.tools.getQueryParams()["id"]
if id_param? if id_param?
$("a.post-list[data-post-id='#{id_param}']").addClass('active') $("a.post-list[data-post-id='#{id_param}']").addClass('active')
$.get('/posts/show_fragment', { $.get("/posts/#{id_param}", {
'id': id_param, fragment: 1
}) })
.done (data) -> .done (data) ->
$('#list_post').html(data) $('#list_post').html(data)
...@@ -30,8 +32,8 @@ if window.location.pathname.match /^\/posts\/?$/ ...@@ -30,8 +32,8 @@ if window.location.pathname.match /^\/posts\/?$/
else else
$el = $("a.post-list:eq(0)") $el = $("a.post-list:eq(0)")
$el.addClass('active') $el.addClass('active')
$.get('/posts/show_fragment', { $.get("/posts/#{$el.data('postId')}", {
'id': $el.data('postId'), fragment: 1
}) })
.done (data) -> .done (data) ->
$('#list_post').html(data) $('#list_post').html(data)
......
...@@ -9,4 +9,9 @@ class ApplicationController < ActionController::Base ...@@ -9,4 +9,9 @@ class ApplicationController < ActionController::Base
redirect_to root_path redirect_to root_path
end end
end end
rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception|
render text: "Required parameter missing: #{parameter_missing_exception.param}", status: :bad_request
end
end end
...@@ -5,12 +5,17 @@ require 'premailer' ...@@ -5,12 +5,17 @@ require 'premailer'
module RV::Mailer module RV::Mailer
include ApplicationHelper include ApplicationHelper
def compose_mail(post, user) def compose_mail(post, opts = {})
fail ArgumentError.new('post missing') unless post.present?
fail ArgumentError.new('user missing') unless opts[:user].present? && opts[:user].is_a?(User)
fail ArgumentError.new('to missing') unless opts[:to].present?
fail ArgumentError.new('to mail format invalid') unless ValidatesEmailFormatOf.validate_email_format(opts[:to]).nil?
html_body = generate_html_mail(post.body) html_body = generate_html_mail(post.body)
mail = Mail.new do mail = Mail.new do
from user.email from opts[:user].email
to user.email to opts[:to]
subject post.title subject post.title
body post.body body post.body
...@@ -22,8 +27,8 @@ module RV::Mailer ...@@ -22,8 +27,8 @@ module RV::Mailer
# set ActionGmailer # set ActionGmailer
config = { config = {
oauth2_token: user.google_auth_token, oauth2_token: opts[:user].google_auth_token,
account: user.email account: opts[:user].email
}.merge(Rendezvous::Application.config.action_mailer.smtp_settings) }.merge(Rendezvous::Application.config.action_mailer.smtp_settings)
mail.delivery_method(ActionGmailer::DeliveryMethod, config) mail.delivery_method(ActionGmailer::DeliveryMethod, config)
......
...@@ -21,14 +21,14 @@ class PostsController < ApplicationController ...@@ -21,14 +21,14 @@ class PostsController < ApplicationController
render text: h_application_format_markdown(params[:text]) render text: h_application_format_markdown(params[:text])
end end
def show_fragment
@post = Post.find(params[:id])
render layout: false, partial: 'posts/show_fragment'
end
# GET /posts/1 # GET /posts/1
# GET /posts/1.json # GET /posts/1.json
def show def show
if params[:fragment].present?
render layout: false, partial: 'posts/show_fragment'
else
render
end
end end
# GET /posts/new # GET /posts/new
...@@ -47,10 +47,12 @@ class PostsController < ApplicationController ...@@ -47,10 +47,12 @@ class PostsController < ApplicationController
# refresh google oauth token if expired # refresh google oauth token if expired
current_user.google_oauth_token_refresh! if current_user.google_oauth_token_expired? current_user.google_oauth_token_refresh! if current_user.google_oauth_token_expired?
compose_mail(@post, current_user).deliver compose_mail(@post, user: current_user, to: mail_params[:to]).deliver
redirect_to root_path(id: @post.id) redirect_to root_path(id: @post.id)
rescue ActionGmailer::DeliveryError rescue ActionGmailer::DeliveryError
redirect_to root_path(id: @post.id), flash: { notice: 'Gmail authentication expired.' } redirect_to root_path(id: @post.id), flash: { notice: 'Gmail authentication expired.' }
rescue ArgumentError => err
render text: err.to_s, status: :bad_request
end end
# GET /posts/1/edit # GET /posts/1/edit
...@@ -123,4 +125,8 @@ class PostsController < ApplicationController ...@@ -123,4 +125,8 @@ class PostsController < ApplicationController
_param_hash _param_hash
end end
end end
def mail_params
params.require(:mail).permit(:to).to_hash.symbolize_keys
end
end end
...@@ -13,20 +13,6 @@ ...@@ -13,20 +13,6 @@
</head> </head>
<body> <body>
<% if notice %>
<script type="text/javascript">
alert('<%= notice %>');
</script>
<!-- <p class="notice"><%= notice %></p> -->
<% end %>
<% if alert %>
<script type="text/javascript">
alert('<%= alert %>');
</script>
<!-- <p class="notice"><%= notice %></p> -->
<p class="alert"><%= alert %></p>
<% end %>
<%= yield %> <%= yield %>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<div class="input-group"> <div class="input-group">
<input type="text" name="q" class="form-control" value="<%= params[:q] %>" placeholder="Search"> <input type="text" name="q" class="form-control" value="<%= params[:q] %>" placeholder="Search">
<span class="input-group-btn"> <span class="input-group-btn">
<button type="submit" class="btn btn-default"> <button type="submit" class="btn btn-default" data-disable-with="Searching...">
<span class="glyphicon glyphicon-search"></span> <span class="glyphicon glyphicon-search"></span>
</button> </button>
</span> </span>
......
<% if notice %>
<div class="alert alert-warning fade in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<strong>Notice</strong> <%= notice %>
</div>
<% end %>
<% if alert %>
<div class="alert alert-danger fade in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<strong>Alert</strong> <%= alert %>
</div>
<% end %>
<div style="text-align:right">
<a href="<%= mail_post_path(@post) %>" class="btn navbar-btn" style!="position:absolute;right:0;top:0;margin-top:2px;margin-top:3px;margin-right:3px;">
Mail
</a>
<a href="<%= fork_post_path(@post) %>" class="btn navbar-btn" style!="position:absolute;right:0;top:0;margin-top:2px;margin-top:3px;margin-right:3px;">
Fork
</a>
<a href="<%= edit_post_path(@post) %>" class="btn btn-primary navbar-btn" style!="position:absolute;right:0;top:0;margin-top:2px;margin-top:3px;margin-right:3px;">
<span class="glyphicon glyphicon-pencil"></span>
</a>
</div>
<div class="text-box title" style!="position:relative;"> <div class="text-box title" style!="position:relative;">
<a href="<%= post_path(@post) %>"><%= @post.title %></a> <a href="<%= post_path(@post) %>"><%= @post.title %></a>
</div> </div>
<div class="text-box meta"> <div class="text-box meta">
<% @post.tags.each do |tag| %> <% @post.tags.each do |tag| %>
<span class="label label-info"> <span class="label label-info">
...@@ -24,8 +14,80 @@ ...@@ -24,8 +14,80 @@
<span class="label label-danger"> <span class="label label-danger">
<a href="<%= root_path(q: "date:#{@post.updated_at.strftime('%Y-%m-%d')}") %>"><%= @post.updated_at.strftime('%Y-%m-%d') %></a> <a href="<%= root_path(q: "date:#{@post.updated_at.strftime('%Y-%m-%d')}") %>"><%= @post.updated_at.strftime('%Y-%m-%d') %></a>
</span> </span>
<!-- Split button -->
<div class="btn-group pull-right" style="margin: -7px -12px 0 0;">
<button type="button" class="btn btn-primary">
<span class="glyphicon glyphicon-pencil"></span>
</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="<%= fork_post_path(@post) %>">Fork</a></li>
<li><a href="#" data-toggle="modal" data-target="#myModal">Mail to...</a></li>
<li class="divider"></li>
<li><%= link_to 'Delete', post_path(@post), method: :delete, data: { confirm: 'Are you sure?' } %></li>
</ul>
</div>
<!-- /Split button -->
</div> </div>
<div class="text-box body viewer github"> <div class="text-box body viewer github">
<%= h_application_format_markdown(@post.body) %> <%= h_application_format_markdown(@post.body) %>
</div> </div>
<!-- Button trigger modal -->
<!-- <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Launch demo modal
</button>
-->
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<%= form_tag mail_post_path(@post), method: :post, class: 'form-horizontal', role: 'form' do %>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel">Mail this post to...</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label class="col-sm-2 control-label">Title</label>
<div class="col-sm-10">
<input type="text" class="form-control" value="<%= @post.title %>" readonly>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">To</label>
<div class="col-sm-10">
<input type="email" name="mail[to]" class="form-control" id="inputEmail3" placeholder="Email">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">From</label>
<div class="col-sm-10">
<input type="text" class="form-control" value="<%= current_user.email %>" readonly>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" data-disable-with="Sending...">Send</button>
</div>
</div><!-- /.modal-content -->
<% end %><%# form %>
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
...@@ -6,22 +6,13 @@ ...@@ -6,22 +6,13 @@
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-12">
<div id="xxxxxxxx"> <div id="xxxxxxxx">
<%= render partial: 'posts/show_fragment' %> <%= render partial: 'posts/show_fragment' %>
</div> </div>
</div><!--/span-->
</div><!--/row--> </div><!--/row-->
<hr> <hr>
<footer>
</footer>
</div><!--/.container--> </div><!--/.container-->
</div> </div>
# Be sure to restart your server when you modify this file. # Be sure to restart your server when you modify this file.
Rendezvous::Application.config.session_store :cookie_store, key: '_rendezvous_session' Rendezvous::Application.config.session_store :cookie_store,
key: '__rv__'
...@@ -3,9 +3,9 @@ Rendezvous::Application.routes.draw do ...@@ -3,9 +3,9 @@ Rendezvous::Application.routes.draw do
root 'home#top', as: 'root' root 'home#top', as: 'root'
post 'posts/preview' => 'posts#preview' post 'posts/preview' => 'posts#preview'
get 'posts/show_fragment' => 'posts#show_fragment' # get 'posts/show_fragment' => 'posts#show_fragment'
get 'posts/:id/fork' => 'posts#fork', as: 'fork_post' get 'posts/:id/fork' => 'posts#fork', as: 'fork_post'
get 'posts/:id/mail' => 'posts#mail', as: 'mail_post' post 'posts/:id/mail' => 'posts#mail', as: 'mail_post'
resources :posts resources :posts
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
......
require 'spec_helper'
class DummyClass; end
describe RV::Mailer do
let(:klass) { DummyClass.new.extend(RV::Mailer) }
let(:alice) { FactoryGirl.create(:alice) }
let(:post) { Post.create title: 'ruby rspec', body: 'This is first espec test: ruby' }
it 'valid' do
expect { klass.compose_mail(post, user: alice, to: 'dummy@example.com') }.not_to raise_error(ArgumentError)
end
it 'missing post' do
expect { klass.compose_mail(nil, user: alice, to: 'dummy@example.com') }.to raise_error(ArgumentError)
end
it 'missing user' do
expect { klass.compose_mail(post, user: nil, to: 'dummy@example.com') }.to raise_error(ArgumentError)
end
it 'missing to' do
expect { klass.compose_mail(post, user: alice, to: nil) }.to raise_error(ArgumentError)
end
it 'invalid to' do
expect { klass.compose_mail(post, user: alice, to: 'invalid.email') }.to raise_error(ArgumentError)
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment