action_smser 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +61 -9
- data/app/controllers/action_smser/delivery_reports_controller.rb +21 -4
- data/app/models/action_smser/delivery_report.rb +35 -2
- data/app/views/action_smser/delivery_reports/index.html.erb +46 -62
- data/app/views/action_smser/delivery_reports/list.html.erb +52 -0
- data/app/views/layouts/action_smser/delivery_reports.html.erb +7 -2
- data/config/routes.rb +3 -1
- data/db/migrate/20120102215215_create_action_smser_delivery_reports.rb +4 -0
- data/lib/action_smser.rb +12 -3
- data/lib/action_smser/base.rb +15 -8
- data/lib/action_smser/delivery_methods/nexmo.rb +67 -0
- data/lib/action_smser/delivery_methods/simple_http.rb +5 -3
- data/lib/action_smser/version.rb +1 -1
- data/test/dummy/app/mailers/hello_smser.rb +5 -0
- data/test/dummy/config/initializers/action_smser.rb +11 -0
- data/test/dummy/config/initializers/git_ignored_passwords.rb +5 -0
- data/test/dummy/db/production.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +1 -14
- data/test/dummy/log/development.log +44 -0
- data/test/dummy/log/production.log +1 -0
- data/test/dummy/log/test.log +17502 -0
- data/test/functional/action_smser/delivery_reports_controller_test.rb +35 -10
- data/test/unit/action_smser/base_test.rb +12 -2
- data/test/unit/action_smser/delivery_methods/nexmo_test.rb +93 -0
- data/test/unit/action_smser/delivery_methods/simple_http_test.rb +0 -4
- data/test/unit/action_smser/delivery_report_test.rb +44 -0
- metadata +16 -6
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# ActionSmser
|
2
2
|
|
3
|
-
Simple way to use SMS (Short Message Service) in the same way as ActionMailer
|
3
|
+
ActionSmser == SMS && ActionMailer. Simple way to use SMS (Short Message Service) in the same way as ActionMailer.
|
4
4
|
Includes also delivery reports and easy way to add custom gateways. See examples below.
|
5
5
|
|
6
6
|
[<img src="https://secure.travis-ci.org/holli/action_smser.png" />](http://travis-ci.org/holli/action_smser)
|
@@ -16,7 +16,7 @@ Gemfile ->
|
|
16
16
|
gem 'action_smser'
|
17
17
|
|
18
18
|
# To use delivery reports
|
19
|
-
bundle exec rake railties:install:migrations
|
19
|
+
bundle exec rake railties:install:migrations
|
20
20
|
rake db:migrate
|
21
21
|
```
|
22
22
|
|
@@ -68,6 +68,37 @@ Optional delivery methods can be used by creating classes under "ActionSmser::De
|
|
68
68
|
them as downcase infos. See example of :simple_http at
|
69
69
|
https://github.com/holli/action_smser/blob/master/lib/action_smser/delivery_methods/simple_http.rb
|
70
70
|
|
71
|
+
Simplest case is to use simple_http and override path
|
72
|
+
|
73
|
+
```
|
74
|
+
# Example of changing simple_http delivery path. Options are the same options that were presented above.
|
75
|
+
|
76
|
+
module ActionSmser::DeliveryMethods
|
77
|
+
class SimpleHttp
|
78
|
+
def self.deliver_path(sms, options)
|
79
|
+
"/my_gateways_api/send?user=#{options[:username]}&password=#{options[:password]}&ValidityPeriod=24:00&sender=#{sms.from_encoded}&SMSText=#{sms.body_encoded_escaped}&GSM=#{sms.to_encoded}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
```
|
85
|
+
|
86
|
+
**Nexmo** (http://nexmo.com/) is supported also.
|
87
|
+
|
88
|
+
```
|
89
|
+
ActionSmser.delivery_options[:delivery_method] = :nexmo
|
90
|
+
ActionSmser.delivery_options[:nexmo] = {
|
91
|
+
:username => 'key', :password => "password"
|
92
|
+
}
|
93
|
+
|
94
|
+
# set callback url to nexmo http://localhost:3000/action_smser/delivery_reports/gateway_commit/nexmo
|
95
|
+
ActionSmser.delivery_options[:gateway_commit]['nexmo'] = ActionSmser::DeliveryMethods::Nexmo
|
96
|
+
|
97
|
+
```
|
98
|
+
|
99
|
+
If you add other common gateways to this framework, plz generate tests and send us a patch.
|
100
|
+
|
101
|
+
|
71
102
|
## Delivery reports
|
72
103
|
|
73
104
|
Gem handles collecting and analysing of delivery reports. This enables you to make sure that your gateway works.
|
@@ -110,23 +141,24 @@ class ActionSmserConfigExample
|
|
110
141
|
end
|
111
142
|
end
|
112
143
|
|
113
|
-
|
114
144
|
# This is simple proc that is used in a before filter, if it returns true it allows access to
|
115
145
|
# http://localhost.inv:3000/action_smser/delivery_reports/ with infos about delivery reports
|
116
146
|
ActionSmser.delivery_options[:admin_access] = ActionSmserConfigExample
|
117
147
|
|
118
|
-
# This gives ActionSmser way to parse infos from pushed to gateway
|
119
|
-
# Params is all params gotten in the request
|
120
|
-
test_gateway = lambda
|
121
|
-
|
122
148
|
# Parser is used with urls like
|
123
149
|
# /action_smser/delivery_reports/gateway_commit/test_gateway
|
124
150
|
# where 'test_gateway' is the part that is used for locating right parser.
|
125
|
-
ActionSmser.delivery_options[:gateway_commit]
|
126
|
-
|
151
|
+
ActionSmser.delivery_options[:gateway_commit]['test_gateway'] = ActionSmserConfigExample
|
127
152
|
|
128
153
|
```
|
129
154
|
|
155
|
+
DeliveryReports can be searched by "dr = ::ActionSmser::DeliveryReport.where(xxx).first".
|
156
|
+
Some helpers in delivery_reports include
|
157
|
+
|
158
|
+
- dr.to_sms => creates new sms message from deliveryreport.
|
159
|
+
- dr.resent(:gateway) => creates new sms and sends it through given gateway.
|
160
|
+
|
161
|
+
|
130
162
|
## Other options
|
131
163
|
|
132
164
|
Observers can be used by implementing "delivery_observer" in your sms class
|
@@ -138,12 +170,32 @@ class TestSms < ActionSmser::Base
|
|
138
170
|
sms(:to => to, :from => from, :body => str)
|
139
171
|
end
|
140
172
|
|
173
|
+
def before_delivery()
|
174
|
+
puts "Called just before delivery"
|
175
|
+
end
|
176
|
+
|
141
177
|
def after_delivery(response_from_delivery_method)
|
142
178
|
puts "Done with delivery"
|
143
179
|
end
|
144
180
|
end
|
145
181
|
```
|
146
182
|
|
183
|
+
Gateway committed status updates can also have observers
|
184
|
+
|
185
|
+
```
|
186
|
+
in /config/initializers/active_smser.rb
|
187
|
+
|
188
|
+
class ActionSmserConfigGatewayObserver
|
189
|
+
def self.after_gateway_commit(delivery_reports)
|
190
|
+
puts delivery_reports.inspect
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
ActionSmser.gateway_commit_observer_add(ActionSmserConfigGatewayObserver)
|
195
|
+
|
196
|
+
```
|
197
|
+
|
198
|
+
|
147
199
|
## Testing
|
148
200
|
|
149
201
|
Default delivery method is "test_array". It saves delivered sms to ActionSmser::DeliveryMethods::TestArray.deliveries to help test your own software.
|
@@ -11,10 +11,11 @@ module ActionSmser
|
|
11
11
|
|
12
12
|
ActionSmser::Logger.info("Gateway_commit found parser for gateway: #{params['gateway']}")
|
13
13
|
|
14
|
-
|
14
|
+
dr_var_array = ActionSmser.delivery_options[:gateway_commit][params['gateway']].send(:process_delivery_report, params)
|
15
|
+
dr_array = []
|
15
16
|
|
16
|
-
if !
|
17
|
-
|
17
|
+
if !dr_var_array.blank?
|
18
|
+
dr_var_array.each do |dr_update|
|
18
19
|
msg_id = dr_update["msg_id"]
|
19
20
|
dr = ActionSmser::DeliveryReport.where(:msg_id => msg_id).first
|
20
21
|
|
@@ -23,9 +24,9 @@ module ActionSmser
|
|
23
24
|
dr.send("#{key}=", value) if dr.attribute_names.include?(key.to_s)
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
27
|
if dr.save
|
28
28
|
updated_count += 1
|
29
|
+
dr_array << dr
|
29
30
|
ActionSmser::Logger.info("Gateway_commit updated item with id: #{msg_id}, params: #{dr_update.inspect}")
|
30
31
|
else
|
31
32
|
ActionSmser::Logger.info("Gateway_commit problem updating item with id: #{msg_id}, params: #{dr_update.inspect}")
|
@@ -35,6 +36,16 @@ module ActionSmser
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
ActionSmser.delivery_options[:gateway_commit_observers].each do |observer|
|
42
|
+
observer.after_gateway_commit(dr_array)
|
43
|
+
end
|
44
|
+
rescue Exception => e
|
45
|
+
ActionSmser::Logger.error("Problem with gateway_commit_observers: #{e}")
|
46
|
+
end
|
47
|
+
|
48
|
+
|
38
49
|
end
|
39
50
|
|
40
51
|
if updated_count > 0
|
@@ -44,12 +55,18 @@ module ActionSmser
|
|
44
55
|
end
|
45
56
|
end
|
46
57
|
|
58
|
+
|
47
59
|
before_filter :admin_access_only, :except => :gateway_commit
|
48
60
|
|
49
61
|
def index
|
50
62
|
|
51
63
|
end
|
52
64
|
|
65
|
+
def list
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
53
70
|
def admin_access_only
|
54
71
|
if !ActionSmser.delivery_options[:admin_access].blank? && ActionSmser.delivery_options[:admin_access].send(:admin_access, self)
|
55
72
|
return true
|
@@ -1,15 +1,20 @@
|
|
1
1
|
module ActionSmser
|
2
2
|
class DeliveryReport < ActiveRecord::Base
|
3
3
|
|
4
|
+
has_many :re_deliveries, :class_name => self.to_s, :foreign_key => :re_delivery_of_delivery_report_id
|
5
|
+
puts self
|
6
|
+
belongs_to :re_delivery_of, :class_name => self.to_s, :foreign_key => :re_delivery_of_delivery_report_id
|
7
|
+
|
4
8
|
def self.build_from_sms(sms, to, msg_id)
|
5
9
|
@delivery_report = self.new
|
6
10
|
|
7
|
-
[:from, :body, :sms_type].each do |var|
|
11
|
+
[:from, :body, :sms_type, :re_delivery_of_delivery_report_id].each do |var|
|
8
12
|
@delivery_report.send("#{var}=", sms.send(var))
|
9
13
|
end
|
10
14
|
@delivery_report.to = to
|
11
15
|
@delivery_report.msg_id = msg_id
|
12
16
|
@delivery_report.status = "LOCAL_SENT"
|
17
|
+
@delivery_report.gateway = sms.delivery_options[:delivery_method].to_s
|
13
18
|
@delivery_report
|
14
19
|
end
|
15
20
|
|
@@ -22,8 +27,36 @@ module ActionSmser
|
|
22
27
|
def status=(stat, skip_log = false)
|
23
28
|
self[:status] = stat
|
24
29
|
self.status_updated_at = Time.now
|
30
|
+
add_log("#{Time.now.to_s(:db)}: #{stat}") unless skip_log
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_log(str)
|
25
34
|
self.log = "" if self.log.nil?
|
26
|
-
self.log += "#{
|
35
|
+
self.log += "#{str}\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Copy this delivery_report information to a new sms object
|
39
|
+
def to_sms
|
40
|
+
sms_new = ActionSmser::Base.new()
|
41
|
+
[:sms_type, :to, :from, :body, :sms_type].each do |var|
|
42
|
+
sms_new.send("#{var}=", self.send(var))
|
43
|
+
end
|
44
|
+
sms_new
|
45
|
+
end
|
46
|
+
|
47
|
+
def re_deliver(gateway = :default)
|
48
|
+
ActionSmser::Logger.info("Re_delivering: #{self.inspect}")
|
49
|
+
self.update_attribute(:re_delivered, true)
|
50
|
+
|
51
|
+
sms_new = self.to_sms
|
52
|
+
sms_new.sms_type = "#{sms_new.sms_type}.re_delivery"
|
53
|
+
sms_new.re_delivery_of_delivery_report_id = self.id
|
54
|
+
|
55
|
+
unless gateway == :default
|
56
|
+
sms_new.delivery_options[:delivery_method] = gateway
|
57
|
+
end
|
58
|
+
|
59
|
+
[sms_new, sms_new.deliver]
|
27
60
|
end
|
28
61
|
|
29
62
|
end
|
@@ -14,28 +14,53 @@ time_span = case params['time_span'].to_s.downcase
|
|
14
14
|
else
|
15
15
|
1.week.ago..10.minutes.ago
|
16
16
|
end
|
17
|
+
|
18
|
+
ar_timespan = ActionSmser::DeliveryReport.where(:created_at => time_span)
|
19
|
+
|
20
|
+
ar_gateway = ar_timespan
|
21
|
+
ar_gateway = ar_gateway.where(:gateway => params[:gateway]) if (params[:gateway] && params[:gateway].to_s != 'all')
|
22
|
+
|
17
23
|
%>
|
18
24
|
|
19
25
|
|
20
|
-
<h1>Delivery Reports Summary for <%= params['time_span'] %></h1>
|
26
|
+
<h1>Delivery Reports Summary for <%= params['time_span'] %> <%= "for #{params[:gateway]}" unless params[:gateway].blank? %></h1>
|
21
27
|
|
22
28
|
<p>
|
23
29
|
Show summary:
|
24
|
-
<%= link_to 'Last 24 hours', delivery_reports_path(:time_span => 'Last 24 Hours') %>,
|
25
|
-
<%= link_to '24 hours before that', delivery_reports_path(:time_span => 'Previous 24 Hours') %>,
|
26
|
-
<%= link_to 'Last week', delivery_reports_path(:time_span => 'Last Week') %>,
|
27
|
-
<%= link_to 'Week before that', delivery_reports_path(:time_span => 'Previous Week') %> or
|
28
|
-
<%= link_to 'Last month', delivery_reports_path(:time_span => 'Last Month') %>.
|
30
|
+
<%= link_to 'Last 24 hours', delivery_reports_path(:time_span => 'Last 24 Hours', :gateway => params[:gateway]) %>,
|
31
|
+
<%= link_to '24 hours before that', delivery_reports_path(:time_span => 'Previous 24 Hours', :gateway => params[:gateway]) %>,
|
32
|
+
<%= link_to 'Last week', delivery_reports_path(:time_span => 'Last Week', :gateway => params[:gateway]) %>,
|
33
|
+
<%= link_to 'Week before that', delivery_reports_path(:time_span => 'Previous Week', :gateway => params[:gateway]) %> or
|
34
|
+
<%= link_to 'Last month', delivery_reports_path(:time_span => 'Last Month', :gateway => params[:gateway]) %>.
|
29
35
|
</p>
|
30
36
|
|
31
|
-
<h2>
|
37
|
+
<h2>Select gateway</h2>
|
32
38
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
<ul>
|
40
|
+
<li>
|
41
|
+
<strong>
|
42
|
+
<%= link_to('all', delivery_reports_path(:time_span => params[:time_span]) ) %>
|
43
|
+
</strong>
|
44
|
+
|
45
|
+
(you can select only gateways that have messages in this period)
|
46
|
+
</li>
|
47
|
+
<%
|
48
|
+
total = ar_timespan.count
|
49
|
+
grouped_by_status = ar_timespan.group(:gateway).count.each do |key, val| %>
|
50
|
+
<li>
|
51
|
+
<strong>
|
52
|
+
<%= link_to(key, delivery_reports_path(:time_span => params[:time_span], :gateway => key) ) %>
|
53
|
+
</strong>
|
54
|
+
|
55
|
+
<%= val %> sms
|
56
|
+
|
57
|
+
(<strong><%= number_to_percentage(100.0 * val / total, :precision => 2) %></strong>)
|
58
|
+
</li>
|
59
|
+
<% end %>
|
60
|
+
</ul>
|
61
|
+
|
62
|
+
|
63
|
+
<h2>Delivered Within (hour:min:sec)</h2>
|
39
64
|
|
40
65
|
<% if ActiveRecord::Base.connection.adapter_name.downcase.to_s.include?("mysql") %>
|
41
66
|
|
@@ -47,6 +72,10 @@ Show summary:
|
|
47
72
|
<th>% of delivered sms</th>
|
48
73
|
</tr>
|
49
74
|
|
75
|
+
<% ar_delivered = ar_gateway.where(:status => 'delivered')
|
76
|
+
total = ar_gateway.count
|
77
|
+
total_delivered = ar_delivered.count
|
78
|
+
%>
|
50
79
|
<% ["00:00:30", "00:01:00", "00:02:00", "00:10:00", "00:30:00", "00:90:00", "24:00:00", "48:00:00"].each do |time| %>
|
51
80
|
<% dev_count = ar_delivered.where('TIMEDIFF(status_updated_at, created_at) < ?', time).count %>
|
52
81
|
<tr>
|
@@ -66,9 +95,8 @@ Show summary:
|
|
66
95
|
<h2>DeliveryReport Statuses</h2>
|
67
96
|
<ul>
|
68
97
|
<%
|
69
|
-
|
70
|
-
|
71
|
-
grouped_by_status = quest.group(:status).count.each do |key, val| %>
|
98
|
+
total = ar_gateway.count
|
99
|
+
grouped_by_status = ar_gateway.group(:status).count.each do |key, val| %>
|
72
100
|
|
73
101
|
<li>
|
74
102
|
<strong><%= key %></strong>:
|
@@ -91,9 +119,8 @@ Show summary:
|
|
91
119
|
</tr>
|
92
120
|
|
93
121
|
<%
|
94
|
-
|
95
|
-
|
96
|
-
grouped_by_status = quest.group(:sms_type).count.each do |key, val| %>
|
122
|
+
total = ar_gateway.count
|
123
|
+
grouped_by_status = ar_gateway.group(:sms_type).count.each do |key, val| %>
|
97
124
|
<tr>
|
98
125
|
<td><strong><%= key %></strong></td>
|
99
126
|
<td><%= val %></td>
|
@@ -105,46 +132,3 @@ Show summary:
|
|
105
132
|
</table>
|
106
133
|
|
107
134
|
|
108
|
-
<hr>
|
109
|
-
|
110
|
-
<% items_within_page = 20 %>
|
111
|
-
<h1 id="delivery_reports_list"><%= items_within_page %> delivery_reports ordered by created_at</h1>
|
112
|
-
|
113
|
-
<%
|
114
|
-
offset = params[:offset].to_i
|
115
|
-
offset = 0 if offset < -0
|
116
|
-
%>
|
117
|
-
|
118
|
-
<p>
|
119
|
-
<strong>List offset: <%= offset %>.</strong>
|
120
|
-
Add
|
121
|
-
<%= link_to("- #{items_within_page}", delivery_reports_path(:offset => offset-items_within_page, :anchor => 'delivery_reports_list')) unless offset == 0 %>
|
122
|
-
<%= link_to "+ #{items_within_page}", delivery_reports_path(:offset => offset+items_within_page, :anchor => 'delivery_reports_list') %>
|
123
|
-
to offset
|
124
|
-
</p>
|
125
|
-
|
126
|
-
<table style="margin-top: 20px;">
|
127
|
-
<tr>
|
128
|
-
<th>Created_at</th>
|
129
|
-
<th>Msg id</th>
|
130
|
-
<th>Status</th>
|
131
|
-
<th>Status updated at</th>
|
132
|
-
<th>Recipient</th>
|
133
|
-
<th>Sender</th>
|
134
|
-
<th>Text body</th>
|
135
|
-
</tr>
|
136
|
-
|
137
|
-
<% ActionSmser::DeliveryReport.order('created_at DESC').offset(offset).first(items_within_page).each do |delivery_report| %>
|
138
|
-
<tr>
|
139
|
-
<td style="white-space: nowrap;"><%= delivery_report.created_at %></td>
|
140
|
-
<td><%= delivery_report.msg_id %></td>
|
141
|
-
<td><%= delivery_report.status %></td>
|
142
|
-
<td style="white-space: nowrap;"><%= delivery_report.status_updated_at %></td>
|
143
|
-
<td><%= delivery_report.to %></td>
|
144
|
-
<td><%= delivery_report.from %></td>
|
145
|
-
<td><%= delivery_report.body %></td>
|
146
|
-
</tr>
|
147
|
-
<% end %>
|
148
|
-
</table>
|
149
|
-
|
150
|
-
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
<% items_within_page = 20 %>
|
3
|
+
<h1 id="delivery_reports_list"><%= items_within_page %> delivery_reports ordered by created_at</h1>
|
4
|
+
|
5
|
+
<%
|
6
|
+
offset = params[:offset].to_i
|
7
|
+
offset = 0 if offset < -0
|
8
|
+
%>
|
9
|
+
|
10
|
+
<p>
|
11
|
+
<strong>List offset: <%= offset %>.</strong>
|
12
|
+
Add
|
13
|
+
<%= link_to("- #{items_within_page}", list_delivery_reports_path(:offset => offset-items_within_page)) unless offset == 0 %>
|
14
|
+
<%= link_to "+ #{items_within_page}", list_delivery_reports_path(:offset => offset+items_within_page) %>
|
15
|
+
to offset
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<table style="margin-top: 20px; font-size: 10px;">
|
19
|
+
<tr>
|
20
|
+
<th>Id</th>
|
21
|
+
<th>Created_at</th>
|
22
|
+
<th>Msg id</th>
|
23
|
+
<th>Gateway</th>
|
24
|
+
<th>Status</th>
|
25
|
+
<th>Status updated at</th>
|
26
|
+
<th>Recipient</th>
|
27
|
+
<th>Sender</th>
|
28
|
+
<th>Sms Type</th>
|
29
|
+
<th>Re Delivered</th>
|
30
|
+
<th>Re Delivery Of</th>
|
31
|
+
<th> O</th>
|
32
|
+
</tr>
|
33
|
+
|
34
|
+
<% ActionSmser::DeliveryReport.order('created_at DESC').offset(offset).first(items_within_page).each do |delivery_report| %>
|
35
|
+
<tr>
|
36
|
+
<td style="white-space: nowrap;"><%= delivery_report.id %></td>
|
37
|
+
<td style="white-space: nowrap;"><%= delivery_report.created_at %></td>
|
38
|
+
<td><%= delivery_report.msg_id %></td>
|
39
|
+
<td><%= delivery_report.gateway %></td>
|
40
|
+
<td><%= delivery_report.status %></td>
|
41
|
+
<td style="white-space: nowrap;"><%= delivery_report.status_updated_at %></td>
|
42
|
+
<td><%= delivery_report.to %></td>
|
43
|
+
<td><%= delivery_report.from %></td>
|
44
|
+
<td><%= delivery_report.sms_type %></td>
|
45
|
+
<td><%= delivery_report.re_delivered? %></td>
|
46
|
+
<td><%= delivery_report.re_delivery_of.msg_id unless delivery_report.re_delivery_of.blank? %></td>
|
47
|
+
<td title="<%= delivery_report.body %>"> O</td>
|
48
|
+
</tr>
|
49
|
+
<% end %>
|
50
|
+
</table>
|
51
|
+
|
52
|
+
|
@@ -14,7 +14,7 @@
|
|
14
14
|
}
|
15
15
|
th, td {
|
16
16
|
border: 1px solid gray;
|
17
|
-
padding: 1px
|
17
|
+
padding: 1px 8px 1px 3px;
|
18
18
|
}
|
19
19
|
|
20
20
|
h1 { margin-top: 40px; }
|
@@ -29,6 +29,9 @@
|
|
29
29
|
|
30
30
|
}
|
31
31
|
hr { margin-top: 20px; margin-bottom: 10px; }
|
32
|
+
|
33
|
+
.menu { margin-top: 30px; }
|
34
|
+
.menu a { margin-right: 20px; font-size: 16px; }
|
32
35
|
|
33
36
|
</STYLE>
|
34
37
|
|
@@ -37,7 +40,9 @@
|
|
37
40
|
|
38
41
|
<h1>ActionSmser infos</h1>
|
39
42
|
|
40
|
-
|
43
|
+
<div class="menu">
|
44
|
+
<%= link_to 'Main application', '/' %> <%= link_to 'Summary of SMS', delivery_reports_path -%> <%= link_to 'List All SMS', list_delivery_reports_path %>
|
45
|
+
</div>
|
41
46
|
|
42
47
|
<hr>
|
43
48
|
|