backlog 0.19.0 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -1
- data/app/controllers/user_controller.rb +21 -4
- data/app/models/user_notify.rb +11 -0
- data/app/models/work.rb +2 -2
- data/app/views/user/change_password.rhtml +4 -3
- data/app/views/user/delete.rhtml +14 -0
- data/app/views/user/edit.rhtml +28 -26
- data/app/views/user/toggle_work_lock_monitoring.rjs +1 -1
- data/app/views/user_notify/monitoring_invitation_en.rhtml +7 -0
- data/app/views/user_notify/monitoring_invitation_no.rhtml +7 -0
- data/app/views/works/daily_work_sheet.rhtml +1 -1
- data/app/views/works/timeliste.rhtml +3 -2
- data/lang/en.yaml +2 -0
- data/lang/no.yaml +2 -0
- metadata +4 -7
- data/config/deploy_datek.rb +0 -20
- data/config/deploy_kubosch.rb +0 -20
- data/config/environments/datek_production.rb +0 -26
- data/config/environments/development_mysql.rb +0 -27
- data/config/environments/kubosch_production.rb +0 -21
- data/config/environments/kubosch_production_mysql.rb +0 -21
data/History.txt
CHANGED
@@ -1,4 +1,17 @@
|
|
1
|
-
== 0.
|
1
|
+
== 0.20.0 2008-01-29
|
2
|
+
|
3
|
+
=== Features
|
4
|
+
|
5
|
+
* Added option to invite associates to monitor time sheets.
|
6
|
+
* Divided user actions for changing password and deleting a user into separate views
|
7
|
+
to make each view simpler.
|
8
|
+
|
9
|
+
=== Fixes
|
10
|
+
|
11
|
+
* Fixed Excel export to print work account ids and work account names.
|
12
|
+
* Fixed application error when trying to register a work record without a work account.
|
13
|
+
|
14
|
+
== 0.19.0 2008-01-28
|
2
15
|
|
3
16
|
=== Features
|
4
17
|
|
@@ -157,16 +157,32 @@ class UserController < ApplicationController
|
|
157
157
|
|
158
158
|
def toggle_work_lock_monitoring
|
159
159
|
@user = User.find(params[:id])
|
160
|
-
|
160
|
+
@subscriber = params[:subscriber_id] ? User.find(params[:subscriber_id]) : current_user
|
161
|
+
already_monitoring = @user.work_lock_subscribers.include? @subscriber
|
161
162
|
if already_monitoring
|
162
|
-
@user.work_lock_subscribers.delete
|
163
|
+
@user.work_lock_subscribers.delete @subscriber
|
163
164
|
action = 'stopped'
|
164
165
|
else
|
165
|
-
@user.work_lock_subscribers <<
|
166
|
+
@user.work_lock_subscribers << @subscriber
|
166
167
|
action = 'started'
|
167
168
|
end
|
168
169
|
flash[:notice] = "Monitoring #{action}"
|
169
|
-
UserNotify.deliver_monitoring(@user,
|
170
|
+
UserNotify.deliver_monitoring(@user, @subscriber, action)
|
171
|
+
redirect_to :action => :edit, :id => @user.id unless request.xhr?
|
172
|
+
end
|
173
|
+
|
174
|
+
def invite_work_lock_subscriber
|
175
|
+
@user = current_user
|
176
|
+
@subscriber = User.find(params[:id])
|
177
|
+
already_monitoring = @user.work_lock_subscribers.include? @subscriber
|
178
|
+
if already_monitoring
|
179
|
+
flash[:notice] = "#{@subscriber.name} is already monitoring your work sheets."
|
180
|
+
else
|
181
|
+
flash[:notice] = "Invitation sent to #{@subscriber.name}"
|
182
|
+
monitoring_url = url_for :action => :toggle_work_lock_monitoring, :id => @user
|
183
|
+
UserNotify.deliver_monitoring_invitation(@user, @subscriber, monitoring_url)
|
184
|
+
end
|
185
|
+
render :template => '/display_notice', :layout => false
|
170
186
|
end
|
171
187
|
|
172
188
|
protected
|
@@ -201,6 +217,7 @@ class UserController < ApplicationController
|
|
201
217
|
@user = User.find_by_id(params[:id]) || current_user || User.find_by_id(session[:user_id])
|
202
218
|
@groups = Group.find(:all, :order => 'name')
|
203
219
|
@periods = @user.periods
|
220
|
+
@associates = User.find(:all) - @user.work_lock_subscribers - [current_user]
|
204
221
|
case request.method
|
205
222
|
when :get
|
206
223
|
render
|
data/app/models/user_notify.rb
CHANGED
@@ -53,6 +53,17 @@ class UserNotify < ActionMailer::Base
|
|
53
53
|
@body["action"] = action
|
54
54
|
end
|
55
55
|
|
56
|
+
def monitoring_invitation(user, monitoring_user, monitor_url)
|
57
|
+
setup_email(user)
|
58
|
+
|
59
|
+
@subject += "#{user.name} has invited you to monitor his/her time sheets."
|
60
|
+
|
61
|
+
@body["app_name"] = UserSystem::CONFIG[:app_name].to_s
|
62
|
+
@body["user"] = user
|
63
|
+
@body["monitoring_user"] = monitoring_user
|
64
|
+
@body["monitor_url"] = monitor_url
|
65
|
+
end
|
66
|
+
|
56
67
|
private
|
57
68
|
|
58
69
|
def setup_email(user)
|
data/app/models/work.rb
CHANGED
@@ -7,8 +7,8 @@ class Work < ActiveRecord::Base
|
|
7
7
|
belongs_to :work_account
|
8
8
|
|
9
9
|
validates_associated :task
|
10
|
-
validates_presence_of :started_at, :if => :track_times?
|
11
10
|
validates_presence_of :work_account
|
11
|
+
validates_presence_of :started_at, :if => :track_times?
|
12
12
|
|
13
13
|
def validate
|
14
14
|
errors.add(:work, "Work account is missing") unless work_account
|
@@ -20,7 +20,7 @@ class Work < ActiveRecord::Base
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def track_times?
|
23
|
-
work_account.track_times?
|
23
|
+
work_account && work_account.track_times?
|
24
24
|
end
|
25
25
|
|
26
26
|
# Return an array with an array of works per day:
|
@@ -1,7 +1,9 @@
|
|
1
1
|
<% @page_title = l(:change_password) %>
|
2
2
|
|
3
|
-
<div id="spotlight">
|
4
|
-
<div
|
3
|
+
<div id="spotlight" title="<%= title_helper %>" class="form">
|
4
|
+
<div class="btitle">
|
5
|
+
<h4><%=l :password %></h4>
|
6
|
+
</div>
|
5
7
|
|
6
8
|
<div class="form-padding">
|
7
9
|
Enter your new password in the fields below and click 'Change Password' to have a new password sent to your email inbox.
|
@@ -15,4 +17,3 @@
|
|
15
17
|
</form>
|
16
18
|
</div>
|
17
19
|
</div>
|
18
|
-
</div>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% @page_title = l(:delete_user) %>
|
2
|
+
|
3
|
+
<div id="spotlight" title="<%= title_helper %>" class="form">
|
4
|
+
<div class="btitle">
|
5
|
+
<h4><%=l :delete %></h4>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<%= start_form_tag_helper %>
|
9
|
+
<div class="user_delete">
|
10
|
+
<%= hidden_field 'user', 'form', :value => 'delete' %>
|
11
|
+
<%= submit_tag l(:delete) %>
|
12
|
+
</div>
|
13
|
+
</form>
|
14
|
+
</div>
|
data/app/views/user/edit.rhtml
CHANGED
@@ -1,41 +1,43 @@
|
|
1
1
|
<% @page_title = "#{l :editing} #{l :user}" %>
|
2
2
|
|
3
|
-
<div id="spotlight" title="<%= title_helper %>" class="form">
|
3
|
+
<div id="spotlight" title="<%= title_helper %>" class="form">
|
4
|
+
<div class="btitle">
|
5
|
+
<div style="float: right">
|
6
|
+
<%=link_to l(:change_password), :action => :change_password%>
|
7
|
+
<%=link_to l(:delete), :action => :delete%>
|
8
|
+
</div>
|
9
|
+
<h4><%=l :edit %></h4>
|
10
|
+
</div>
|
11
|
+
|
4
12
|
<% if @user == current_user %>
|
5
|
-
<% unless @user.work_lock_subscribers.empty? %>
|
6
13
|
<table align="right">
|
7
|
-
|
8
|
-
|
9
|
-
|
14
|
+
<% unless @user.work_lock_subscribers.empty? %>
|
15
|
+
<tr><th>Subscribers</th></tr>
|
16
|
+
<% for subscriber in @user.work_lock_subscribers %>
|
17
|
+
<tr>
|
18
|
+
<td align="right"><%=detour_to subscriber.name, :action => :edit%></td>
|
19
|
+
<td align="left"><%=image_link_to_remote 'email.png', "#{l :stop} #{l :monitoring}", {:action => :toggle_work_lock_monitoring, :id => current_user.id, :subscriber_id => subscriber.id}, :id => "work_lock_monitor_icon_#{subscriber.id}"%></td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
<% unless @associates.empty? %>
|
24
|
+
<tr><td>
|
25
|
+
<% remote_form_for :user, :url => {:action => :invite_work_lock_subscriber} do |f| %>
|
26
|
+
<%=select :id, nil, @associates.map{|u| [u.name, u.id]}, {}, :name => 'id'%>
|
27
|
+
<td align="left"><%=submit_tag l(:invite)%></td>
|
28
|
+
<% end %>
|
29
|
+
</td></tr>
|
10
30
|
<% end %>
|
11
31
|
</table>
|
12
|
-
<% end %>
|
13
32
|
<% else %>
|
14
33
|
<% monitoring = @user.work_lock_subscribers.include? current_user %>
|
15
|
-
<%=image_link_to_remote "email#{'_grey' unless monitoring}.png", "#{l(monitoring ? :stop : :start)} #{l(:monitoring)}", {:action => :toggle_work_lock_monitoring, :id => @user.id}, {:id =>
|
34
|
+
<%=image_link_to_remote "email#{'_grey' unless monitoring}.png", "#{l(monitoring ? :stop : :start)} #{l(:monitoring)}", {:action => :toggle_work_lock_monitoring, :id => @user.id}, {:id => "work_lock_monitor_icon_#{current_user.id}", :style => 'float: right'} %>
|
16
35
|
<% end %>
|
17
36
|
<%= start_form_tag_helper %>
|
18
37
|
<%= render_partial 'edit', :user => @user, :submit => true %>
|
19
38
|
</form>
|
20
39
|
</div>
|
21
40
|
|
22
|
-
<div id="rfeature">
|
23
|
-
<div class="btitle">
|
24
|
-
<h4><%=l :password %></h4>
|
25
|
-
</div>
|
26
|
-
|
27
|
-
<%= start_form_tag_helper %>
|
28
|
-
<%= render_partial 'password', :submit => true %>
|
29
|
-
</form>
|
30
|
-
|
31
|
-
<%= start_form_tag_helper %>
|
32
|
-
<div class="user_delete">
|
33
|
-
<%= hidden_field 'user', 'form', :value => 'delete' %>
|
34
|
-
<%= submit_tag l(:delete) %>
|
35
|
-
</div>
|
36
|
-
</form>
|
37
|
-
</div>
|
38
|
-
|
39
41
|
<div id="lfeature">
|
40
42
|
<div class="btitle">
|
41
43
|
<h4><%=l :groups %></h4>
|
@@ -56,8 +58,6 @@
|
|
56
58
|
</table>
|
57
59
|
</div>
|
58
60
|
|
59
|
-
<br clear="right"/>
|
60
|
-
|
61
61
|
<div id="rfeature">
|
62
62
|
<div class="btitle">
|
63
63
|
<h4><%=l :periods %></h4>
|
@@ -72,3 +72,5 @@
|
|
72
72
|
</table>
|
73
73
|
</div>
|
74
74
|
|
75
|
+
<br clear="right"/>
|
76
|
+
|
@@ -1,2 +1,2 @@
|
|
1
1
|
display_notice(page)
|
2
|
-
page[
|
2
|
+
page["work_lock_monitor_icon_#{@subscriber.id}"].src = image_path("email#{'_grey' unless @user.work_lock_subscribers.include? @subscriber}.png")
|
@@ -81,6 +81,7 @@
|
|
81
81
|
<Font x:Family="Swiss" ss:Size="14" ss:Bold="1"/>
|
82
82
|
</Style>
|
83
83
|
<Style ss:ID="s24">
|
84
|
+
<Alignment ss:Horizontal="Center"/>
|
84
85
|
<Borders>
|
85
86
|
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
|
86
87
|
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="3"/>
|
@@ -471,8 +472,8 @@
|
|
471
472
|
<% internal_works_per_day = @work_totals_per_work_account[work_account_id][1]%>
|
472
473
|
<% if internal_works_per_day.find{|total| total > 0} %>
|
473
474
|
<Row>
|
474
|
-
<Cell ss:StyleID="s24"><Data ss:Type="String"><%=
|
475
|
-
<Cell ss:StyleID="s25"><Data ss:Type="String"
|
475
|
+
<Cell ss:StyleID="s24"><Data ss:Type="String"><%=work_account_id%></Data></Cell>
|
476
|
+
<Cell ss:StyleID="s25"><Data ss:Type="String"><%=WorkAccount.find(work_account_id).name %></Data></Cell>
|
476
477
|
<Cell ss:StyleID="s25"/>
|
477
478
|
<Cell ss:StyleID="s25"/>
|
478
479
|
<Cell ss:StyleID="s25"/>
|
data/lang/en.yaml
CHANGED
@@ -40,6 +40,7 @@ group: Group
|
|
40
40
|
groups: Groups
|
41
41
|
home: Home
|
42
42
|
hours: Hours
|
43
|
+
invite: Invite
|
43
44
|
invoice: Invoice
|
44
45
|
invoice_code: Invoice Code
|
45
46
|
invoice_short: Inv.
|
@@ -113,3 +114,4 @@ weekly_work_sheet: Weekly work sheet
|
|
113
114
|
welcome_link: Start getting things done.
|
114
115
|
work: Work
|
115
116
|
work_account: Work Account
|
117
|
+
work_accounts: Work Accounts
|
data/lang/no.yaml
CHANGED
@@ -40,6 +40,7 @@ group: Gruppe
|
|
40
40
|
groups: Grupper
|
41
41
|
home: Hjem
|
42
42
|
hours: Timer
|
43
|
+
invite: Invitèr
|
43
44
|
invoice: Fakturerbart
|
44
45
|
invoice_code: Faktureringskode
|
45
46
|
invoice_short: Fakt
|
@@ -112,3 +113,4 @@ weekly_work_sheet: Timeoversikt for uke
|
|
112
113
|
welcome_link: Få ting gjort.
|
113
114
|
work: Arbeid
|
114
115
|
work_account: Timeføringskonto
|
116
|
+
work_accounts: Timeføringskonti
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backlog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uwe Kubosch
|
@@ -161,7 +161,9 @@ files:
|
|
161
161
|
- app/views/user_notify/change_password_no.rhtml
|
162
162
|
- app/views/user_notify/forgot_password_en.rhtml
|
163
163
|
- app/views/user_notify/monitoring_en.rhtml
|
164
|
+
- app/views/user_notify/monitoring_invitation_en.rhtml
|
164
165
|
- app/views/user_notify/change_password_en.rhtml
|
166
|
+
- app/views/user_notify/monitoring_invitation_no.rhtml
|
165
167
|
- app/views/user_notify/signup_en.rhtml
|
166
168
|
- app/views/user_notify/monitoring_no.rhtml
|
167
169
|
- app/views/customers
|
@@ -178,6 +180,7 @@ files:
|
|
178
180
|
- app/views/user/welcome.rhtml
|
179
181
|
- app/views/user/_edit.rhtml
|
180
182
|
- app/views/user/edit.rhtml
|
183
|
+
- app/views/user/delete.rhtml
|
181
184
|
- app/views/user/change_password.rhtml
|
182
185
|
- app/views/user/login.rhtml
|
183
186
|
- app/views/user/_password.rhtml
|
@@ -586,19 +589,13 @@ files:
|
|
586
589
|
- config/database.yml
|
587
590
|
- config/routes.rb
|
588
591
|
- config/environments
|
589
|
-
- config/environments/kubosch_production.rb
|
590
592
|
- config/environments/test.rb
|
591
593
|
- config/environments/localization_environment.rb
|
592
|
-
- config/environments/datek_production.rb
|
593
594
|
- config/environments/user_environment.rb
|
594
|
-
- config/environments/development_mysql.rb
|
595
|
-
- config/environments/kubosch_production_mysql.rb
|
596
595
|
- config/environments/production.rb
|
597
596
|
- config/environments/development.rb
|
598
|
-
- config/deploy_datek.rb
|
599
597
|
- config/environment.rb
|
600
598
|
- config/mime_types.yaml
|
601
|
-
- config/deploy_kubosch.rb
|
602
599
|
- config/war.rb
|
603
600
|
- config/boot.rb
|
604
601
|
- config/deploy.rb
|
data/config/deploy_datek.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
set :application, "backlog"
|
2
|
-
set :repository, "svn://rubyforge.org/var/svn/#{application}/trunk"
|
3
|
-
|
4
|
-
role :app, "sandra"
|
5
|
-
role :db, "sandra", :primary => true
|
6
|
-
|
7
|
-
set :deploy_to, "/usr/local/#{application}"
|
8
|
-
set :user, "capistrano"
|
9
|
-
|
10
|
-
set :use_sudo, false
|
11
|
-
|
12
|
-
desc "The spinner task is used by :cold_deploy to start the application up"
|
13
|
-
task :spinner, :roles => :app do
|
14
|
-
send(run_method, "/sbin/service #{application} start")
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "Restart the mongrel server"
|
18
|
-
task :restart, :roles => :app do
|
19
|
-
send(run_method, "/sbin/service #{application} restart")
|
20
|
-
end
|
data/config/deploy_kubosch.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
set :application, "backlog"
|
2
|
-
set :repository, "svn://rubyforge.org/var/svn/#{application}/trunk"
|
3
|
-
set :rails_env, :production
|
4
|
-
|
5
|
-
role :web, "www.kubosch.no"
|
6
|
-
role :app, "www.kubosch.no"
|
7
|
-
role :db, "www.kubosch.no", :primary => true
|
8
|
-
|
9
|
-
set :user, "donv"
|
10
|
-
set :use_sudo, false
|
11
|
-
|
12
|
-
desc "The spinner task is used by :cold_deploy to start the application up"
|
13
|
-
task :spinner, :roles => :app do
|
14
|
-
send(run_method, "/sbin/service #{application} start")
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "Restart the mongrel server"
|
18
|
-
task :restart, :roles => :app do
|
19
|
-
send(run_method, "/sbin/service #{application} restart")
|
20
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
-
|
3
|
-
# The production environment is meant for finished, "live" apps.
|
4
|
-
# Code is not reloaded between requests
|
5
|
-
config.cache_classes = true
|
6
|
-
|
7
|
-
# Use a different logger for distributed setups
|
8
|
-
# config.logger = SyslogLogger.new
|
9
|
-
|
10
|
-
# Full error reports are disabled and caching is turned on
|
11
|
-
config.action_controller.consider_all_requests_local = false
|
12
|
-
config.action_controller.perform_caching = true
|
13
|
-
|
14
|
-
# Enable serving of images, stylesheets, and javascripts from an asset server
|
15
|
-
# config.action_controller.asset_host = "http://assets.example.com"
|
16
|
-
|
17
|
-
# Disable delivery errors if you bad email addresses should just be ignored
|
18
|
-
config.action_mailer.raise_delivery_errors = false
|
19
|
-
|
20
|
-
#ActionMailer::Base.delivery_method = :sendmail
|
21
|
-
ActionMailer::Base.delivery_method = :smtp
|
22
|
-
|
23
|
-
ActionMailer::Base.smtp_settings = {
|
24
|
-
:address => "mail.datek.no",
|
25
|
-
:port => 25
|
26
|
-
}
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
-
|
3
|
-
# In the development environment your application's code is reloaded on
|
4
|
-
# every request. This slows down response time but is perfect for development
|
5
|
-
# since you don't have to restart the webserver when you make code changes.
|
6
|
-
config.cache_classes = false
|
7
|
-
|
8
|
-
# Log error messages when you accidentally call methods on nil.
|
9
|
-
config.whiny_nils = true
|
10
|
-
|
11
|
-
# Show full error reports and disable caching
|
12
|
-
config.action_controller.consider_all_requests_local = true
|
13
|
-
config.action_controller.perform_caching = false
|
14
|
-
config.action_view.cache_template_extensions = false
|
15
|
-
config.action_view.debug_rjs = true
|
16
|
-
|
17
|
-
# Raise exceptions when mailer fails
|
18
|
-
config.action_mailer.raise_delivery_errors = true
|
19
|
-
|
20
|
-
#ActionMailer::Base.delivery_method = :sendmail
|
21
|
-
ActionMailer::Base.delivery_method = :smtp
|
22
|
-
|
23
|
-
ActionMailer::Base.smtp_settings = {
|
24
|
-
:address => "mail.datek.no",
|
25
|
-
:port => 25
|
26
|
-
}
|
27
|
-
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
-
|
3
|
-
# The production environment is meant for finished, "live" apps.
|
4
|
-
# Code is not reloaded between requests
|
5
|
-
config.cache_classes = true
|
6
|
-
|
7
|
-
# Use a different logger for distributed setups
|
8
|
-
# config.logger = SyslogLogger.new
|
9
|
-
|
10
|
-
# Full error reports are disabled and caching is turned on
|
11
|
-
config.action_controller.consider_all_requests_local = false
|
12
|
-
config.action_controller.perform_caching = true
|
13
|
-
|
14
|
-
# Enable serving of images, stylesheets, and javascripts from an asset server
|
15
|
-
# config.action_controller.asset_host = "http://assets.example.com"
|
16
|
-
|
17
|
-
# Disable delivery errors if you bad email addresses should just be ignored
|
18
|
-
config.action_mailer.raise_delivery_errors = false
|
19
|
-
|
20
|
-
ActionMailer::Base.delivery_method = :sendmail
|
21
|
-
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# Settings specified here will take precedence over those in config/environment.rb
|
2
|
-
|
3
|
-
# The production environment is meant for finished, "live" apps.
|
4
|
-
# Code is not reloaded between requests
|
5
|
-
config.cache_classes = true
|
6
|
-
|
7
|
-
# Use a different logger for distributed setups
|
8
|
-
# config.logger = SyslogLogger.new
|
9
|
-
|
10
|
-
# Full error reports are disabled and caching is turned on
|
11
|
-
config.action_controller.consider_all_requests_local = false
|
12
|
-
config.action_controller.perform_caching = true
|
13
|
-
|
14
|
-
# Enable serving of images, stylesheets, and javascripts from an asset server
|
15
|
-
# config.action_controller.asset_host = "http://assets.example.com"
|
16
|
-
|
17
|
-
# Disable delivery errors if you bad email addresses should just be ignored
|
18
|
-
config.action_mailer.raise_delivery_errors = false
|
19
|
-
|
20
|
-
ActionMailer::Base.delivery_method = :sendmail
|
21
|
-
|