mxit-rails 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +40 -0
- data/app/assets/images/mxit_rails/favicon.ico +0 -0
- data/app/assets/images/mxit_rails/go.png +0 -0
- data/app/assets/images/mxit_rails/in.png +0 -0
- data/app/assets/images/mxit_rails/nokia-5310-frame.png +0 -0
- data/app/assets/images/mxit_rails/out.png +0 -0
- data/app/assets/javascripts/mxit_rails/emulator.js +93 -0
- data/app/assets/javascripts/mxit_rails/jquery-1.8.0.min.js +2 -0
- data/app/assets/javascripts/mxit_rails/jquery.cookie.js +72 -0
- data/app/assets/stylesheets/mxit_rails/emulator.css.scss +173 -0
- data/app/assets/stylesheets/mxit_rails/included.css.scss +6 -0
- data/app/controllers/emulator_controller.rb +6 -0
- data/app/helpers/mxit_rails_helper.rb +35 -0
- data/app/views/emulator/index.html.erb +54 -0
- data/app/views/layouts/mxit.html.erb +53 -0
- data/app/views/mxit_rails/error.html.erb +2 -0
- data/config/routes.rb +5 -0
- data/lib/mxit-rails.rb +13 -0
- data/lib/mxit_rails/controller_extensions.rb +8 -0
- data/lib/mxit_rails/descriptor.rb +54 -0
- data/lib/mxit_rails/engine.rb +4 -0
- data/lib/mxit_rails/exception.rb +10 -0
- data/lib/mxit_rails/page.rb +187 -0
- data/lib/mxit_rails/railtie.rb +5 -0
- data/lib/mxit_rails/redirect_exception.rb +5 -0
- data/lib/mxit_rails/router.rb +11 -0
- data/lib/mxit_rails/styles.rb +25 -0
- data/lib/mxit_rails/validations.rb +21 -0
- data/lib/mxit_rails/version.rb +3 -0
- data/lib/tasks/mxit-rails_tasks.rake +4 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +12 -0
- data/test/dummy/app/controllers/form_controller.rb +42 -0
- data/test/dummy/app/controllers/index_controller.rb +12 -0
- data/test/dummy/app/controllers/welcome_controller.rb +26 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/form/index/age.html.erb +4 -0
- data/test/dummy/app/views/form/index/done.html.erb +7 -0
- data/test/dummy/app/views/form/index/name.html.erb +4 -0
- data/test/dummy/app/views/form/index/start.html.erb +4 -0
- data/test/dummy/app/views/form/index/surname.html.erb +4 -0
- data/test/dummy/app/views/index/index.html.erb +6 -0
- data/test/dummy/app/views/index/success.html.erb +4 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/welcome/easter_egg.html.erb +4 -0
- data/test/dummy/app/views/welcome/index.html.erb +6 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +59 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/production.sqlite3 +0 -0
- data/test/dummy/log/development.log +29445 -0
- data/test/dummy/log/production.log +14 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/index.html +26 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/tmp/cache/assets/BF5/8C0/sprockets%2F78975330b80238b099744a81b812c803 +0 -0
- data/test/dummy/tmp/cache/assets/C9C/740/sprockets%2F3a56000c06453c8f0d7338c02df2a619 +0 -0
- data/test/dummy/tmp/cache/assets/CB3/340/sprockets%2F6176074062dc4ee8b1c0e9293973b8c1 +0 -0
- data/test/dummy/tmp/cache/assets/CBB/4B0/sprockets%2F84565b3ec7483468474ec41cbc1568b4 +0 -0
- data/test/dummy/tmp/cache/assets/CE1/DB0/sprockets%2F23cf9970f3b73a4a159e83fd1903d216 +0 -0
- data/test/dummy/tmp/cache/assets/CEB/750/sprockets%2F25cdf6f38dd877ab9524149059160ef1 +0 -0
- data/test/dummy/tmp/cache/assets/D03/D30/sprockets%2F039aef99b893884717dd47cbd5a47788 +0 -0
- data/test/dummy/tmp/cache/assets/D23/9D0/sprockets%2Fed6b8ea6bc85059f50a6257e47b86765 +0 -0
- data/test/dummy/tmp/cache/assets/D39/AA0/sprockets%2Fc45eb3a08b640eae8da941722428e38c +0 -0
- data/test/dummy/tmp/cache/assets/D45/960/sprockets%2Ff7a27b05b4c84c32ca5a49887a7b29c8 +0 -0
- data/test/dummy/tmp/cache/assets/D54/750/sprockets%2Fc16371b1a234c7c56cb01cb28a8bc5c3 +0 -0
- data/test/dummy/tmp/cache/assets/D56/060/sprockets%2F457df65dbf8649db0b377d828388db4b +0 -0
- data/test/dummy/tmp/cache/assets/D5B/540/sprockets%2Fe0e490354c54e5a850a6e3c3aa1ecb15 +0 -0
- data/test/dummy/tmp/cache/assets/D66/470/sprockets%2Facf17b280a44ef81b7a37d2c8e08070f +0 -0
- data/test/dummy/tmp/cache/assets/D6F/560/sprockets%2Fa572b066d908bae0d01dbc85f86a57d9 +0 -0
- data/test/dummy/tmp/cache/assets/D79/080/sprockets%2F9bba43c936e8d34a0d6bc9c6169c4f75 +0 -0
- data/test/dummy/tmp/cache/assets/D7A/C20/sprockets%2Fdbbf63c650611194adfc9276d6efa599 +0 -0
- data/test/dummy/tmp/cache/assets/D86/040/sprockets%2Fe7b969ffa4b195f4dd8553a3d62766ec +0 -0
- data/test/dummy/tmp/cache/assets/D99/110/sprockets%2Facbeeb823134865dd66d0489a7bcd00e +0 -0
- data/test/dummy/tmp/cache/assets/D9A/FD0/sprockets%2Ffadbf876155a124ed34b2e990f1c1cf4 +0 -0
- data/test/dummy/tmp/cache/assets/DAA/B80/sprockets%2Ff8082150f8c8beafcd445cc79a9a6a85 +0 -0
- data/test/dummy/tmp/cache/assets/DC7/E00/sprockets%2Fd24f3d9b3af0f25db8dd735d1564bdb1 +0 -0
- data/test/dummy/tmp/cache/assets/DF4/A00/sprockets%2F52e0cb214d2b778e61edb46c3b8eecca +0 -0
- data/test/dummy/tmp/cache/assets/DFB/940/sprockets%2F2faff4be90929be6a1b1de49ea25e33b +0 -0
- data/test/dummy/tmp/cache/assets/E15/260/sprockets%2Fea9c788716af4ccb19ff8e1d7ea47b8e +0 -0
- data/test/dummy/tmp/cache/assets/E26/4F0/sprockets%2F1cd8dafcb93f36aea8c2cf9d04c322d3 +0 -0
- data/test/dummy/tmp/cache/assets/E4F/E70/sprockets%2Fd9fffd76ac7c8ee08bedf3e257c81f99 +0 -0
- data/test/dummy/tmp/cache/assets/E76/0D0/sprockets%2Fcc9ce9eb21f4b4f9dbabfa0a3ca60b01 +0 -0
- data/test/dummy/tmp/pids/server.pid +1 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/mxit_rails_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- metadata +283 -0
@@ -0,0 +1,173 @@
|
|
1
|
+
html, body {
|
2
|
+
margin: 0;
|
3
|
+
padding: 0;
|
4
|
+
overflow: hidden;
|
5
|
+
font-family: 'HelveticaNeue';
|
6
|
+
font-weight: normal;
|
7
|
+
}
|
8
|
+
|
9
|
+
#phone {
|
10
|
+
width: 240px;
|
11
|
+
height: 320px;
|
12
|
+
padding: 133px 56px 351px 56px;
|
13
|
+
margin: 35px auto 0 auto;
|
14
|
+
position: relative;
|
15
|
+
}
|
16
|
+
#phone.collapse {
|
17
|
+
background: none;
|
18
|
+
position: absolute;
|
19
|
+
top: 37px;
|
20
|
+
left: 0;
|
21
|
+
right: 0;
|
22
|
+
bottom: 0;
|
23
|
+
margin: 0;
|
24
|
+
padding: 0;
|
25
|
+
width: auto;
|
26
|
+
height: auto;
|
27
|
+
}
|
28
|
+
#screen {
|
29
|
+
width: 240px;
|
30
|
+
height: 320px;
|
31
|
+
position: relative;
|
32
|
+
overflow: hidden;
|
33
|
+
}
|
34
|
+
#phone.collapse #screen {
|
35
|
+
position: static;
|
36
|
+
width: 100%;
|
37
|
+
height: 100%;
|
38
|
+
}
|
39
|
+
|
40
|
+
iframe {
|
41
|
+
border: none;
|
42
|
+
margin: 0;
|
43
|
+
padding: 0;
|
44
|
+
}
|
45
|
+
|
46
|
+
.content {
|
47
|
+
width: 240px;
|
48
|
+
height: 320px;
|
49
|
+
position: absolute;
|
50
|
+
z-index: 1;
|
51
|
+
}
|
52
|
+
#phone.collapse .content {
|
53
|
+
width: 100%;
|
54
|
+
height: 100%;
|
55
|
+
}
|
56
|
+
|
57
|
+
#controls {
|
58
|
+
position: absolute;
|
59
|
+
top: 0;
|
60
|
+
left: 0;
|
61
|
+
right: 0;
|
62
|
+
height: 36px;
|
63
|
+
background-color: #eee;
|
64
|
+
border-bottom: 1px solid #999;
|
65
|
+
font-size: 14px;
|
66
|
+
line-height: 36px;
|
67
|
+
font-family: 'HelveticaNeue';
|
68
|
+
font-weight: normal;
|
69
|
+
text-align: center;
|
70
|
+
z-index: 1;
|
71
|
+
}
|
72
|
+
#not-registered, #registered {
|
73
|
+
float: left;
|
74
|
+
margin-left: 20px;
|
75
|
+
}
|
76
|
+
#registered {
|
77
|
+
display: none;
|
78
|
+
}
|
79
|
+
#mxit-id {
|
80
|
+
font-family: 'HelveticaNeue-Bold';
|
81
|
+
font-weight: normal;
|
82
|
+
}
|
83
|
+
#unlink, #link {
|
84
|
+
position: relative;
|
85
|
+
top: 0px;
|
86
|
+
float: right;
|
87
|
+
margin-right: 20px;
|
88
|
+
cursor: default;
|
89
|
+
}
|
90
|
+
#inputs {
|
91
|
+
display: none;
|
92
|
+
}
|
93
|
+
|
94
|
+
|
95
|
+
.link .icon {
|
96
|
+
width: 56px;
|
97
|
+
height: 56px;
|
98
|
+
border-radius: 56px;
|
99
|
+
border: 5px solid #fff;
|
100
|
+
box-shadow: 0 2px 2px rgba(64,64,64,0.4);
|
101
|
+
display: block;
|
102
|
+
background: -webkit-linear-gradient(-75deg, #f5a627 0%, #de6003 100%);
|
103
|
+
}
|
104
|
+
.link:active .icon { background: -webkit-linear-gradient(-75deg, #F58A27 0%, #CF3A00 100%); }
|
105
|
+
.link.disabled .icon { background: -webkit-linear-gradient(-75deg, #c6c6c6 0%, #7a7a7a 100%); }
|
106
|
+
.link .icon .image {
|
107
|
+
background-position: center;
|
108
|
+
background-repeat: no-repeat;
|
109
|
+
background-size: 50px;
|
110
|
+
width: 100%;
|
111
|
+
height: 100%;
|
112
|
+
display: block;
|
113
|
+
}
|
114
|
+
|
115
|
+
a.link {
|
116
|
+
padding: 0;
|
117
|
+
text-decoration: none;
|
118
|
+
font-family: 'HelveticaNeue-Medium';
|
119
|
+
font-weight: normal;
|
120
|
+
font-size: 14px;
|
121
|
+
color: #333;
|
122
|
+
position: relative;
|
123
|
+
top: 2px;
|
124
|
+
}
|
125
|
+
.link .icon {
|
126
|
+
width: 26px;
|
127
|
+
height: 26px;
|
128
|
+
border-radius: 26px;
|
129
|
+
border: 2px solid #fff;
|
130
|
+
display: inline-block;
|
131
|
+
vertical-align: middle;
|
132
|
+
position: relative;
|
133
|
+
top: -1px;
|
134
|
+
margin: 0 4px 4px 6px;
|
135
|
+
}
|
136
|
+
.link .icon .image {
|
137
|
+
background-size: 24px;
|
138
|
+
}
|
139
|
+
.in .icon .image, .out .icon .image {
|
140
|
+
background-size: 22px;
|
141
|
+
}
|
142
|
+
|
143
|
+
#expand {
|
144
|
+
position: absolute;
|
145
|
+
display: block;
|
146
|
+
right: 19px;
|
147
|
+
top: 27px;
|
148
|
+
}
|
149
|
+
|
150
|
+
#collapse {
|
151
|
+
position: absolute;
|
152
|
+
z-index: 10;
|
153
|
+
display: block;
|
154
|
+
right: 1px;
|
155
|
+
top: 5px;
|
156
|
+
display: none;
|
157
|
+
}
|
158
|
+
#phone.collapse #expand {
|
159
|
+
display: none;
|
160
|
+
}
|
161
|
+
#phone.collapse #collapse {
|
162
|
+
display: block;
|
163
|
+
}
|
164
|
+
|
165
|
+
#fadeout {
|
166
|
+
position: fixed;
|
167
|
+
height: 100px;
|
168
|
+
bottom: 0;
|
169
|
+
left: 0;
|
170
|
+
right: 0;
|
171
|
+
background: -webkit-linear-gradient(90deg, #fff 0%, #fff 5%, rgba(255,255,255,0.95) 15%, rgba(255,255,255,0) 100%);;
|
172
|
+
z-index: 10;
|
173
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module MxitRailsHelper
|
2
|
+
|
3
|
+
def mxit_path route
|
4
|
+
MxitRails::Router.url route
|
5
|
+
end
|
6
|
+
|
7
|
+
def mxit_link route, label, variables=nil
|
8
|
+
unless variables.nil?
|
9
|
+
var_strings = []
|
10
|
+
#TODO: Use default Rails get encoding
|
11
|
+
variables.each do |key, value|
|
12
|
+
var_strings << "#{key}=#{value}"
|
13
|
+
end
|
14
|
+
route += "?#{var_strings.join('&')}"
|
15
|
+
end
|
16
|
+
output = "<a href=\"#{route}\">#{label}</a>".html_safe
|
17
|
+
end
|
18
|
+
|
19
|
+
def mxit_style *names
|
20
|
+
content = []
|
21
|
+
names.each do |name|
|
22
|
+
content << MxitRails::Styles.get(name) || ''
|
23
|
+
end
|
24
|
+
content.join(' ').html_safe
|
25
|
+
end
|
26
|
+
|
27
|
+
def mxit_nav_link target, label
|
28
|
+
"<p style=\"#{ mxit_style :right }\">#{ mxit_link target, label }</p>".html_safe
|
29
|
+
end
|
30
|
+
|
31
|
+
def mxit_proceed content
|
32
|
+
"<p><b style=\"#{ mxit_style :link }\">> #{content}</b></p>".html_safe
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Mxit Emulator</title>
|
5
|
+
<meta charset="UTF-8" />
|
6
|
+
|
7
|
+
<%= stylesheet_link_tag "mxit_rails/emulator" %>
|
8
|
+
<%= javascript_include_tag "mxit_rails/emulator" %>
|
9
|
+
|
10
|
+
<link rel="icon" type="image/x-icon" href="<%= image_path("mxit_rails/favicon.ico"); %>" />
|
11
|
+
|
12
|
+
<script type="text/javascript">
|
13
|
+
MXIT_ROOT = '<%= Rails.application.config.mxit_root %>';
|
14
|
+
</script>
|
15
|
+
|
16
|
+
<!-- The asset image-path helper isn't working in scss files, so moving those to here. sigh. -->
|
17
|
+
<style type="text/css">
|
18
|
+
#phone { background: url(<%= image_path("mxit_rails/nokia-5310-frame.png") %>) no-repeat; }
|
19
|
+
.go > .icon .image { background-image: url(<%= image_path("mxit_rails/go.png"); %>) }
|
20
|
+
.in > .icon .image { background-image: url(<%= image_path("mxit_rails/in.png"); %>) }
|
21
|
+
.out > .icon .image { background-image: url(<%= image_path("mxit_rails/out.png"); %>) }
|
22
|
+
</style>
|
23
|
+
</head>
|
24
|
+
<body>
|
25
|
+
|
26
|
+
<div id="controls">
|
27
|
+
<div id="default">
|
28
|
+
<span id="not-registered">No credentials</span>
|
29
|
+
<span id="registered">Mxit ID: <span id="mxit-id"></span></span>
|
30
|
+
|
31
|
+
<a id="unlink" class="go link" onclick="Emulator.clearCredentials()">Clear Credentials <span class="icon"><span class="image"></span></span></a>
|
32
|
+
<a id="link" class="go link" onclick="Emulator.enterCredentials()">Set Credentials <span class="icon"><span class="image"></span></span></a>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="inputs">
|
36
|
+
<input type="text" placeholder="Mxit ID" id="mxit-id-input" />
|
37
|
+
<input type="text" placeholder="MSISDN" id="msisdn-input" />
|
38
|
+
|
39
|
+
<a id="link" class="go link" onclick="Emulator.saveCredentials()">Save <span class="icon"><span class="image"></span></span></a>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
<div id="phone">
|
44
|
+
<a id="expand" class="out link" onclick="Emulator.expand()"><span class="icon"><span class="image"></span></span></a>
|
45
|
+
<a id="collapse" class="in link" onclick="Emulator.collapse()"><span class="icon"><span class="image"></span></span></a>
|
46
|
+
<div id="screen">
|
47
|
+
<iframe id="center" class="content" onLoad="Emulator.updateIframe(this)"></iframe>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<div id="fadeout"></div>
|
52
|
+
|
53
|
+
</body>
|
54
|
+
</html>
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
4
|
+
|
5
|
+
<head>
|
6
|
+
<title>Mxit App</title>
|
7
|
+
|
8
|
+
<meta name="mxit" content="no_prefix,show_progress,clear_on_new,no_heading" />
|
9
|
+
|
10
|
+
<% if request.headers['x-mxit-login'].nil? %>
|
11
|
+
<!-- Include a CSS file, but only in a browser/emulator, not on mxit -->
|
12
|
+
<%= stylesheet_link_tag "mxit_rails/included" %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<style type="text/css">
|
16
|
+
a:hover { <%= mxit_style :link_hover %> }
|
17
|
+
a { <%= mxit_style :link %> }
|
18
|
+
</style>
|
19
|
+
</head>
|
20
|
+
|
21
|
+
<body style="<%= mxit_style :body %>">
|
22
|
+
|
23
|
+
<table title="mxit:table:full" style="width:100%" name="title_table" cellspacing="0" cellpadding="0">
|
24
|
+
<colgroup span="1" width="100%"></colgroup>
|
25
|
+
<tr>
|
26
|
+
<td style="<%= mxit_style :title %>">
|
27
|
+
<b><%= yield :title %></b>
|
28
|
+
</td>
|
29
|
+
</tr>
|
30
|
+
</table>
|
31
|
+
|
32
|
+
<%= yield :navigation %>
|
33
|
+
|
34
|
+
<% if !@_mxit_validated %>
|
35
|
+
<%= @_mxit_validation_messages.first %>
|
36
|
+
|
37
|
+
<% else %>
|
38
|
+
<%= yield %>
|
39
|
+
<% end %>
|
40
|
+
|
41
|
+
<% if @_mxit.input %>
|
42
|
+
<%= mxit_proceed @_mxit.input_label %>
|
43
|
+
<form method="POST" action="<%= @_mxit.url %>">
|
44
|
+
<input type="text" name="<%= @_mxit.input %>" />
|
45
|
+
<input type="submit" name="_mxit_rails_submit" value="Proceed" />
|
46
|
+
</form>
|
47
|
+
|
48
|
+
<% elsif @_mxit.proceed %>
|
49
|
+
<%= mxit_proceed mxit_link(@_mxit.url, @_mxit.proceed.to_s.capitalize, {_mxit_rails_submit: 'Proceed'}) %>
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
</body>
|
53
|
+
</html>
|
data/config/routes.rb
ADDED
data/lib/mxit-rails.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "mxit_rails/railtie"
|
2
|
+
require "mxit_rails/exception"
|
3
|
+
require "mxit_rails/redirect_exception"
|
4
|
+
require "mxit_rails/descriptor"
|
5
|
+
require "mxit_rails/engine"
|
6
|
+
require "mxit_rails/styles"
|
7
|
+
require "mxit_rails/controller_extensions"
|
8
|
+
require "mxit_rails/validations"
|
9
|
+
require "mxit_rails/router"
|
10
|
+
require "mxit_rails/page"
|
11
|
+
|
12
|
+
module MxitRails
|
13
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module MxitRails
|
2
|
+
class Descriptor
|
3
|
+
def self.descr_accessor variable
|
4
|
+
# Custom accessor macro that will look in a parent descriptor if a value isn't found (i.e. is nil)
|
5
|
+
attr_writer variable
|
6
|
+
define_method "#{variable}" do
|
7
|
+
value = instance_variable_get("@#{variable}")
|
8
|
+
if value.nil? && !parent_descriptor.nil?
|
9
|
+
value = parent_descriptor.send("#{variable}")
|
10
|
+
end
|
11
|
+
value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :parent_descriptor
|
16
|
+
|
17
|
+
attr_accessor :name
|
18
|
+
attr_accessor :type
|
19
|
+
|
20
|
+
descr_accessor :proceed
|
21
|
+
|
22
|
+
attr_accessor :input
|
23
|
+
attr_accessor :input_label
|
24
|
+
|
25
|
+
attr_accessor :validations
|
26
|
+
|
27
|
+
def initialize name, parent=nil
|
28
|
+
@parent_descriptor = parent
|
29
|
+
self.name = name.to_sym
|
30
|
+
@validations = []
|
31
|
+
@steps = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_validation type, message, parameter
|
35
|
+
@validations << {type: type, message: message, parameter: parameter}
|
36
|
+
end
|
37
|
+
|
38
|
+
def url
|
39
|
+
MxitRails::Router.url name
|
40
|
+
end
|
41
|
+
|
42
|
+
def view
|
43
|
+
view = MxitRails::Router.url name
|
44
|
+
unless step.nil?
|
45
|
+
view += "/#{step}"
|
46
|
+
end
|
47
|
+
view
|
48
|
+
end
|
49
|
+
|
50
|
+
def form?
|
51
|
+
type == :form
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
module MxitRails
|
2
|
+
module Page
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def mxit_params
|
6
|
+
@_mxit_params
|
7
|
+
end
|
8
|
+
|
9
|
+
def set_descriptor name, parent_name=:default
|
10
|
+
@descriptors ||= {}
|
11
|
+
@descriptors[name] ||= MxitRails::Descriptor.new controller_name, @descriptors[parent_name]
|
12
|
+
@descriptor_name = name
|
13
|
+
end
|
14
|
+
def descriptor
|
15
|
+
@descriptors[@descriptor_name]
|
16
|
+
end
|
17
|
+
|
18
|
+
included do
|
19
|
+
if self.ancestors.include? ApplicationController
|
20
|
+
send :rescue_from, MxitRails::Exception, :with => :handle_mxit_exception
|
21
|
+
send :layout, 'mxit'
|
22
|
+
send :before_filter, :setup
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def redirect! route
|
27
|
+
exception = MxitRails::RedirectException.new('', :redirect)
|
28
|
+
exception.route = route
|
29
|
+
raise exception
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate! input
|
33
|
+
descriptor.validations.each do |validation|
|
34
|
+
method = validation[:type].to_s + '?' #All validations are defined with a trailing question mark
|
35
|
+
parameter = validation[:parameter]
|
36
|
+
# Call with/out a parameter, depending on whether one is specified
|
37
|
+
valid = parameter ? MxitRails::Validations.send(method, input, parameter) : MxitRails::Validations.send(method, input)
|
38
|
+
if !valid
|
39
|
+
@_mxit_validated = false
|
40
|
+
@_mxit_validation_messages << validation[:message]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_mxit_header_field key
|
46
|
+
request.headers[key] || cookies[key.downcase]
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_mxit_info
|
50
|
+
@_mxit_params = {}
|
51
|
+
@_mxit_params[:m_id] = get_mxit_header_field 'X-Mxit-UserId-R'
|
52
|
+
@_mxit_params[:username] = get_mxit_header_field 'x-mxit-login'
|
53
|
+
|
54
|
+
device_info = get_mxit_header_field('X-Mxit-Device-Info')
|
55
|
+
unless device_info.blank?
|
56
|
+
device_info.split(',')
|
57
|
+
@_mxit_params[:distribution_code] = device_info.first
|
58
|
+
@_mxit_params[:mobile_number] = device_info[1] if device_info.length == 2
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Rails controller stuff
|
64
|
+
#========================
|
65
|
+
|
66
|
+
def setup
|
67
|
+
set_descriptor :default
|
68
|
+
|
69
|
+
get_mxit_info
|
70
|
+
|
71
|
+
@_mxit = descriptor
|
72
|
+
@_mxit_validated = true
|
73
|
+
@_mxit_validation_messages = []
|
74
|
+
|
75
|
+
clean_session
|
76
|
+
end
|
77
|
+
|
78
|
+
def clean_session
|
79
|
+
# Drop all mxit items from session if the page doesn't match the current one
|
80
|
+
if session[:_mxit_rails_page] != "#{controller_name}##{action_name}"
|
81
|
+
session.each do |key, value|
|
82
|
+
if key.to_s.match(/_mxit_rails_/)
|
83
|
+
session[key] = nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
session[:_mxit_rails_page] = "#{controller_name}##{action_name}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def handle_mxit_exception exception
|
91
|
+
if exception.kind_of? MxitRails::RedirectException
|
92
|
+
redirect_to(exception.route) and return
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def input input_name, input_label
|
97
|
+
descriptor.input = input_name
|
98
|
+
descriptor.input_label = input_label
|
99
|
+
end
|
100
|
+
def proceed label
|
101
|
+
descriptor.proceed = label
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate *arguments
|
105
|
+
type = arguments[0]
|
106
|
+
message = arguments[-1]
|
107
|
+
parameter = arguments[1..-2][0] # Will return nil if there isn't an argument
|
108
|
+
descriptor.add_validation type, message, parameter
|
109
|
+
end
|
110
|
+
|
111
|
+
def submit &block
|
112
|
+
set_descriptor :default
|
113
|
+
|
114
|
+
if descriptor.form? && next_step?
|
115
|
+
instance_eval &block
|
116
|
+
|
117
|
+
elsif params.include?(:_mxit_rails_submit)
|
118
|
+
unless descriptor.input.nil?
|
119
|
+
input = descriptor.input.to_sym
|
120
|
+
validate! params[input]
|
121
|
+
end
|
122
|
+
|
123
|
+
instance_eval &block if @_mxit_validated
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
def current_step
|
129
|
+
return nil if session[:_mxit_rails_step].nil?
|
130
|
+
session[:_mxit_rails_step].to_sym
|
131
|
+
end
|
132
|
+
def current_step= new_step
|
133
|
+
session[:_mxit_rails_step] = new_step.to_sym
|
134
|
+
end
|
135
|
+
def next_step?
|
136
|
+
@next_step
|
137
|
+
end
|
138
|
+
|
139
|
+
def step step_name, &block
|
140
|
+
# Is the current step blank
|
141
|
+
if next_step?
|
142
|
+
self.current_step = step_name
|
143
|
+
@next_step = false
|
144
|
+
end
|
145
|
+
|
146
|
+
set_descriptor step_name
|
147
|
+
instance_eval &block
|
148
|
+
|
149
|
+
# Process the form if it is the current step
|
150
|
+
if current_step == step_name
|
151
|
+
if params.include?(:_mxit_rails_submit)
|
152
|
+
# Validate the current input if present
|
153
|
+
unless descriptor.input.nil?
|
154
|
+
input = descriptor.input.to_sym
|
155
|
+
validate! params[input]
|
156
|
+
session[:_mxit_rails_params][input] = params[input] if @_mxit_validated
|
157
|
+
end
|
158
|
+
|
159
|
+
if @_mxit_validated
|
160
|
+
params.delete :_mxit_rails_submit
|
161
|
+
@next_step = true
|
162
|
+
return
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Render the form if appropriate
|
167
|
+
@_mxit = descriptor
|
168
|
+
render "#{controller_name}/#{action_name}/#{current_step}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def form &block
|
173
|
+
descriptor.type = :form
|
174
|
+
session[:_mxit_rails_params] ||= {}
|
175
|
+
|
176
|
+
# Ensure previous inputs are in the params hash
|
177
|
+
session[:_mxit_rails_params].each do |key, value|
|
178
|
+
params[key.to_sym] = value
|
179
|
+
end
|
180
|
+
|
181
|
+
# Proceed to the (first) step if no step is in the session
|
182
|
+
@next_step = true if session[:_mxit_rails_step].nil?
|
183
|
+
|
184
|
+
instance_eval &block
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MxitRails
|
2
|
+
module Styles
|
3
|
+
|
4
|
+
# Not sure whether a Constant is the neatest/nicest way of storing these?
|
5
|
+
StyleList = {}
|
6
|
+
|
7
|
+
def self.get name
|
8
|
+
StyleList[name.to_sym]
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.add name, content
|
12
|
+
content.strip!
|
13
|
+
if content[-1] != ';'
|
14
|
+
content += ';'
|
15
|
+
end
|
16
|
+
StyleList[name.to_sym] = content
|
17
|
+
end
|
18
|
+
|
19
|
+
# Default styles
|
20
|
+
add :left, 'text-align:left;'
|
21
|
+
add :center, 'text-align:center;'
|
22
|
+
add :right, 'text-align:right;'
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MxitRails
|
2
|
+
class Validations
|
3
|
+
|
4
|
+
def self.not_blank? input
|
5
|
+
return !input.blank?
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.numeric? input
|
9
|
+
return !input.blank? && input.match(/^[0-9]+$/)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.min_length? input, max
|
13
|
+
return !input.blank? && (input.length >= max)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.max_length? input, max
|
17
|
+
return input.blank? || (input.length <= max)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|