doop 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +203 -0
- data/Rakefile +5 -0
- data/app/assets/images/dash.gif +0 -0
- data/app/assets/images/info-icon.png +0 -0
- data/app/assets/images/progress-tick-large.png +0 -0
- data/app/helpers/doop_helper.rb +51 -0
- data/bin/.gitignore +0 -0
- data/doop.gemspec +26 -0
- data/lib/doop.rb +313 -0
- data/lib/doop/version.rb +3 -0
- data/lib/doop_controller.rb +164 -0
- data/lib/generators/doopgovuk/USAGE +10 -0
- data/lib/generators/doopgovuk/doopgovuk_generator.rb +34 -0
- data/lib/generators/doopgovuk/templates/app/assets/stylesheets/demo.css.scss +188 -0
- data/lib/generators/doopgovuk/templates/app/controllers/demo_controller.rb +155 -0
- data/lib/generators/doopgovuk/templates/app/views/demo/_preamble.html.erb +33 -0
- data/lib/generators/doopgovuk/templates/app/views/demo/_summary.html.erb +10 -0
- data/lib/generators/doopgovuk/templates/app/views/demo/_your_details.html.erb +55 -0
- data/lib/generators/doopgovuk/templates/app/views/demo/index.html.erb +3 -0
- data/lib/generators/doopgovuk/templates/app/views/demo/index.js.erb +4 -0
- data/lib/generators/doopgovuk/templates/app/views/doop/_error.html.erb +3 -0
- data/lib/generators/doopgovuk/templates/app/views/doop/_info_box.html.erb +4 -0
- data/lib/generators/doopgovuk/templates/app/views/doop/_navbar.html.erb +23 -0
- data/lib/generators/doopgovuk/templates/app/views/doop/_question.html.erb +19 -0
- data/lib/generators/doopgovuk/templates/app/views/doop/_question_form.html.erb +15 -0
- data/lib/generators/doopgovuk/templates/app/views/layouts/application.html.erb +22 -0
- data/spec/doop_spec.rb +448 -0
- data/spec/spec_helper.rb +2 -0
- metadata +136 -0
data/lib/doop/version.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module Doop
|
5
|
+
|
6
|
+
class DoopController
|
7
|
+
|
8
|
+
delegate :set_yaml, :unanswer_path, :add, :renumber, :on_answer, :answer_with, :enable, :remove, to: :@doop
|
9
|
+
|
10
|
+
attr_reader :doop
|
11
|
+
|
12
|
+
def initialize application_controller, &block
|
13
|
+
@controller = application_controller
|
14
|
+
@block = block
|
15
|
+
@debug_on_block = nil
|
16
|
+
@current_page_block = method( :default_current_page )
|
17
|
+
@all_pages_block = method( :default_all_pages )
|
18
|
+
end
|
19
|
+
|
20
|
+
def index
|
21
|
+
render_page in_doop { |doop| doop.ask_next }
|
22
|
+
end
|
23
|
+
|
24
|
+
def answer
|
25
|
+
back_val = @controller.params["back_a_page"]
|
26
|
+
nav_path = @controller.params["nav_path"]
|
27
|
+
change_answer_path = @controller.params["change_answer_path"]
|
28
|
+
return back if back_val != nil && !back_val.empty?
|
29
|
+
return change_page nav_path if nav_path != nil && !nav_path.empty?
|
30
|
+
return change change_answer_path if change_answer_path != nil && !change_answer_path.empty?
|
31
|
+
|
32
|
+
render_page in_doop { |doop| doop.answer( @controller.params ) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def back
|
36
|
+
in_doop do |doop|
|
37
|
+
page = get_page_path
|
38
|
+
pages = get_all_pages
|
39
|
+
i = pages.index(page)
|
40
|
+
if i!=0
|
41
|
+
path = pages[i-1]
|
42
|
+
doop.change( path )
|
43
|
+
pages[pages.index(path), pages.length].each do |n|
|
44
|
+
doop[n]["_answered"] = false
|
45
|
+
end
|
46
|
+
|
47
|
+
doop.ask_next
|
48
|
+
end
|
49
|
+
end
|
50
|
+
render_page
|
51
|
+
end
|
52
|
+
|
53
|
+
def change path
|
54
|
+
res = in_doop do
|
55
|
+
|doop| doop.change( path )
|
56
|
+
end
|
57
|
+
render_page res
|
58
|
+
end
|
59
|
+
|
60
|
+
def change_page path
|
61
|
+
in_doop do |doop|
|
62
|
+
#path = @controller.params["path"]
|
63
|
+
doop.change( path )
|
64
|
+
|
65
|
+
# unanswer all pages after path
|
66
|
+
pages = @all_pages_block.call
|
67
|
+
pages[pages.index(path), pages.length].each do |n|
|
68
|
+
doop[n]["_answered"] = false
|
69
|
+
end
|
70
|
+
|
71
|
+
doop.ask_next
|
72
|
+
end
|
73
|
+
render_page
|
74
|
+
end
|
75
|
+
|
76
|
+
def parent_of path
|
77
|
+
p = path.split("/")
|
78
|
+
p.pop
|
79
|
+
p.join("/")
|
80
|
+
end
|
81
|
+
|
82
|
+
def render_page res = {}
|
83
|
+
res[:page] = get_page
|
84
|
+
res[:page_path] = get_page_path
|
85
|
+
res[:page_title] = @doop[res[:page_path]]["_nav_name"]
|
86
|
+
res[:all_pages] = get_all_pages
|
87
|
+
res[:debug_on] = @debug_on_block != nil ? @debug_on_block.call : false
|
88
|
+
@controller.render "index", :locals => { :res => res, :doop => @doop }
|
89
|
+
end
|
90
|
+
|
91
|
+
def load
|
92
|
+
@doop = Doop.new()
|
93
|
+
@self_before_instance_eval = eval "self", @block.binding
|
94
|
+
instance_exec @doop, &@block
|
95
|
+
@doop.yaml = @load_yaml_block.call
|
96
|
+
@doop.init
|
97
|
+
@doop
|
98
|
+
end
|
99
|
+
|
100
|
+
def in_doop
|
101
|
+
load
|
102
|
+
res = yield(@doop)
|
103
|
+
@save_yaml_block.call @doop.dump
|
104
|
+
return res if res.kind_of? Hash
|
105
|
+
{}
|
106
|
+
end
|
107
|
+
|
108
|
+
def evaluate(block)
|
109
|
+
@self_before_instance_eval = eval "self", block.binding
|
110
|
+
instance_eval &block
|
111
|
+
end
|
112
|
+
|
113
|
+
def method_missing(method, *args, &block)
|
114
|
+
@self_before_instance_eval.send method, *args, &block
|
115
|
+
end
|
116
|
+
|
117
|
+
def current_page &block
|
118
|
+
@current_page_block = block
|
119
|
+
end
|
120
|
+
|
121
|
+
def all_pages &block
|
122
|
+
@all_pages_block = block
|
123
|
+
end
|
124
|
+
|
125
|
+
def get_page
|
126
|
+
path = @doop.currently_asked
|
127
|
+
@doop[@current_page_block.call( path )]["_page"]
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_page_path
|
131
|
+
path = @doop.currently_asked
|
132
|
+
@current_page_block.call( path )
|
133
|
+
end
|
134
|
+
|
135
|
+
def get_all_pages
|
136
|
+
@all_pages_block.call
|
137
|
+
end
|
138
|
+
|
139
|
+
def debug_on &block
|
140
|
+
@debug_on_block = block
|
141
|
+
end
|
142
|
+
|
143
|
+
def load_yaml &block
|
144
|
+
@load_yaml_block = block
|
145
|
+
end
|
146
|
+
|
147
|
+
def save_yaml &block
|
148
|
+
@save_yaml_block = block
|
149
|
+
end
|
150
|
+
|
151
|
+
def default_current_page path
|
152
|
+
a = path.split("/").reject {|s| s.empty? }[1]
|
153
|
+
"/page/#{a}"
|
154
|
+
end
|
155
|
+
|
156
|
+
def default_all_pages
|
157
|
+
l = []
|
158
|
+
doop.each_question_with_regex_filter "^\/page/\\w+$" do |question,path|
|
159
|
+
l << path if doop[path]["_enabled"]
|
160
|
+
end
|
161
|
+
l
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Description:
|
2
|
+
Creates a demo govuk questionaire. It's fully functional and demonstrates the various integration points with the doop framework.
|
3
|
+
|
4
|
+
Use this as a starting point for generating any govuk branded website.
|
5
|
+
|
6
|
+
Example:
|
7
|
+
rails generate doopgovuk dvla
|
8
|
+
rails s
|
9
|
+
|
10
|
+
Naviagte to http://localhost:3000
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class DoopgovukGenerator < Rails::Generators::Base
|
2
|
+
source_root File.expand_path('../templates', __FILE__)
|
3
|
+
argument :name, :type => :string, :default => "demo"
|
4
|
+
|
5
|
+
|
6
|
+
def generate_layout
|
7
|
+
copy_file "app/assets/stylesheets/demo.css.scss", "app/assets/stylesheets/#{name}.css.scss"
|
8
|
+
template "app/controllers/demo_controller.rb", "app/controllers/#{name}_controller.rb"
|
9
|
+
copy_file "app/views/demo/index.html.erb", "app/views/#{name}/index.html.erb"
|
10
|
+
copy_file "app/views/demo/index.js.erb", "app/views/#{name}/index.js.erb"
|
11
|
+
copy_file "app/views/demo/_preamble.html.erb", "app/views/#{name}/_preamble.html.erb"
|
12
|
+
copy_file "app/views/demo/_summary.html.erb", "app/views/#{name}/_summary.html.erb"
|
13
|
+
copy_file "app/views/demo/_your_details.html.erb", "app/views/#{name}/_your_details.html.erb"
|
14
|
+
copy_file "app/views/layouts/application.html.erb", "app/views/layouts/application.html.erb"
|
15
|
+
copy_file "app/views/doop/_error.html.erb", "app/views/doop/_error.html.erb"
|
16
|
+
copy_file "app/views/doop/_info_box.html.erb", "app/views/doop/_info_box.html.erb"
|
17
|
+
copy_file "app/views/doop/_navbar.html.erb", "app/views/doop/_navbar.html.erb"
|
18
|
+
copy_file "app/views/doop/_question_form.html.erb", "app/views/doop/_question_form.html.erb"
|
19
|
+
copy_file "app/views/doop/_question.html.erb", "app/views/doop/_question.html.erb"
|
20
|
+
|
21
|
+
|
22
|
+
route "root '#{name}#index'"
|
23
|
+
route "get '#{name}/index'"
|
24
|
+
route "post '#{name}/answer'"
|
25
|
+
|
26
|
+
gem 'govuk_frontend_toolkit'
|
27
|
+
gem 'govuk_template'
|
28
|
+
|
29
|
+
Bundler.with_clean_env do
|
30
|
+
run "bundle install"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
// Place all the styles related to the demo controller here.
|
2
|
+
// They will automatically be included in application.css.
|
3
|
+
// You can use Sass (SCSS) here: http://sass-lang.com/
|
4
|
+
|
5
|
+
@import "design-patterns/alpha-beta";
|
6
|
+
@import "_conditionals";
|
7
|
+
@import "_typography";
|
8
|
+
@import "_colours";
|
9
|
+
@import "_css3";
|
10
|
+
@import "design-patterns/buttons";
|
11
|
+
|
12
|
+
$question_completed_color: #D2E6DB;
|
13
|
+
$question_completed_line_color: #84BA9D;
|
14
|
+
$question_completed_font_color: $black;
|
15
|
+
$question-fg-color: #014c73;
|
16
|
+
|
17
|
+
|
18
|
+
* {
|
19
|
+
-webkit-box-sizing: border-box;
|
20
|
+
-moz-box-sizing: border-box;
|
21
|
+
box-sizing: border-box;
|
22
|
+
}
|
23
|
+
|
24
|
+
.phase-banner {
|
25
|
+
@include phase-banner(alpha);
|
26
|
+
}
|
27
|
+
|
28
|
+
.outer-block {
|
29
|
+
@include outer-block;
|
30
|
+
}
|
31
|
+
|
32
|
+
.inner-block {
|
33
|
+
@include inner-block;
|
34
|
+
margin: 0 0 15px 0;
|
35
|
+
}
|
36
|
+
|
37
|
+
.info_box {
|
38
|
+
display: block;
|
39
|
+
margin: 15px 0 15px 0;
|
40
|
+
max-width: 100%;
|
41
|
+
min-height: 60px;
|
42
|
+
//outline: solid #a1bfd8 1px;
|
43
|
+
border: solid #d1e4f2 5px;
|
44
|
+
padding: 0 0 0 0;
|
45
|
+
background: #e1effa;
|
46
|
+
border-radius: 0.15em;
|
47
|
+
p {
|
48
|
+
margin: 0.75em 0.75em 0.75em 0.75em;
|
49
|
+
}
|
50
|
+
|
51
|
+
.info_img {
|
52
|
+
float: right;
|
53
|
+
margin: 10px 10px 10px 10px;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
.question-open {
|
58
|
+
margin: 16px 0 16px 0;
|
59
|
+
|
60
|
+
}
|
61
|
+
|
62
|
+
.indent {
|
63
|
+
margin: 0 0 0 10px;
|
64
|
+
}
|
65
|
+
|
66
|
+
.question-closed {
|
67
|
+
background: $question_completed_color;
|
68
|
+
border-bottom: solid $question_completed_line_color 1px;
|
69
|
+
color: $question_completed_font_color;
|
70
|
+
display: table;
|
71
|
+
padding: 0.5em 0.5em 0.5em 0.5em;
|
72
|
+
margin: 0 0 0 0;
|
73
|
+
width: 100%;
|
74
|
+
|
75
|
+
.title {
|
76
|
+
padding: 0 0 0 0;
|
77
|
+
display: table-cell;
|
78
|
+
width: 80%;
|
79
|
+
vertical-align: middle;
|
80
|
+
}
|
81
|
+
|
82
|
+
.answer {
|
83
|
+
display: table-cell;
|
84
|
+
max-width: 20%;
|
85
|
+
text-align: right;
|
86
|
+
vertical-align: middle;
|
87
|
+
.button {
|
88
|
+
@include button($question-fg-color);
|
89
|
+
margin: 0 0 0 0;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
}
|
94
|
+
|
95
|
+
.question_form {
|
96
|
+
@include core-16();
|
97
|
+
width: 100%;
|
98
|
+
h1 {
|
99
|
+
@include bold-36();
|
100
|
+
border-width: 0 0 2px 0;
|
101
|
+
border-style: solid;
|
102
|
+
border-color: #d43783;
|
103
|
+
margin: 0 0 0 0;
|
104
|
+
padding: 5px 0 5px 0;
|
105
|
+
}
|
106
|
+
|
107
|
+
h2 {
|
108
|
+
@include bold-27();
|
109
|
+
padding: 0 0 10px 0;
|
110
|
+
}
|
111
|
+
|
112
|
+
input {
|
113
|
+
@include core-16();
|
114
|
+
width: 200px;
|
115
|
+
}
|
116
|
+
|
117
|
+
}
|
118
|
+
|
119
|
+
|
120
|
+
.textfield {
|
121
|
+
|
122
|
+
margin: 0 0 10px 0;
|
123
|
+
|
124
|
+
label {
|
125
|
+
display: block;
|
126
|
+
@include bold-16();
|
127
|
+
margin: 0 0 1px 0;
|
128
|
+
}
|
129
|
+
|
130
|
+
}
|
131
|
+
|
132
|
+
button {
|
133
|
+
@include button;
|
134
|
+
margin: 16px 0 0 0;
|
135
|
+
|
136
|
+
}
|
137
|
+
|
138
|
+
.button-secondary{
|
139
|
+
@include button($grey-3);
|
140
|
+
}
|
141
|
+
|
142
|
+
.button-warning {
|
143
|
+
@include button($red);
|
144
|
+
}
|
145
|
+
|
146
|
+
.error {
|
147
|
+
margin: 0 0 10px 0;
|
148
|
+
span {
|
149
|
+
color: red;
|
150
|
+
border: 1px solid #B01117;
|
151
|
+
background-color: #FFF3CF;
|
152
|
+
padding: 5px 5px 5px 5px;
|
153
|
+
border-radius: 5px;
|
154
|
+
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
.navbar {
|
159
|
+
|
160
|
+
border-width: 0 0 1px 0;
|
161
|
+
border-style: dotted;
|
162
|
+
border-color: #bfc1c3;
|
163
|
+
|
164
|
+
ol {
|
165
|
+
list-style-type: none;
|
166
|
+
margin: 0;
|
167
|
+
padding: 10px;
|
168
|
+
text-align: center;
|
169
|
+
}
|
170
|
+
li.todo {
|
171
|
+
display: inline;
|
172
|
+
margin: 0 30px 0 0;
|
173
|
+
@include core-16();
|
174
|
+
}
|
175
|
+
|
176
|
+
li.doing {
|
177
|
+
display: inline;
|
178
|
+
margin: 0 30px 0 0;
|
179
|
+
@include bold-16();
|
180
|
+
}
|
181
|
+
|
182
|
+
li.done {
|
183
|
+
display: inline;
|
184
|
+
margin: 0 30px 0 0;
|
185
|
+
@include core-16();
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
@@ -0,0 +1,155 @@
|
|
1
|
+
|
2
|
+
require 'doop'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
class <%=name.capitalize%>Controller < ApplicationController
|
6
|
+
|
7
|
+
delegate :index, :answer, to: :@doop_controller
|
8
|
+
before_filter :setup_doop
|
9
|
+
|
10
|
+
def setup_doop
|
11
|
+
@doop_controller = Doop::DoopController.new self do |doop|
|
12
|
+
|
13
|
+
load_yaml do
|
14
|
+
data = params["doop_data"]
|
15
|
+
if data != nil
|
16
|
+
crypt = ActiveSupport::MessageEncryptor.new(Rails.application.secrets.secret_key_base)
|
17
|
+
next crypt.decrypt_and_verify data
|
18
|
+
end
|
19
|
+
|
20
|
+
<<-EOS
|
21
|
+
page: {
|
22
|
+
preamble: {
|
23
|
+
_page: "preamble",
|
24
|
+
_nav_name: "Apply Online",
|
25
|
+
|
26
|
+
debug_on: {
|
27
|
+
_question: "Turn debug on ?",
|
28
|
+
_answer: "No"
|
29
|
+
},
|
30
|
+
enrolled_before: {
|
31
|
+
_question: "Have you enrolled for this service before ?"
|
32
|
+
},
|
33
|
+
year_last_applied: {
|
34
|
+
_question: "What year did you last apply?"
|
35
|
+
},
|
36
|
+
reason_for_applying: {
|
37
|
+
_question: "Why are you applying?"
|
38
|
+
}
|
39
|
+
},
|
40
|
+
your_details: {
|
41
|
+
_page: "your_details",
|
42
|
+
_nav_name: "Your Details",
|
43
|
+
|
44
|
+
your_name: {
|
45
|
+
_question: "What is your name?",
|
46
|
+
_answer: {},
|
47
|
+
},
|
48
|
+
address_history: {
|
49
|
+
_question: "What is your address ?",
|
50
|
+
address__1: { _answer: {} }
|
51
|
+
}
|
52
|
+
|
53
|
+
},
|
54
|
+
summary: {
|
55
|
+
_page: "summary",
|
56
|
+
_nav_name: "Summary",
|
57
|
+
|
58
|
+
terms_and_conditions: {
|
59
|
+
_question: "Terms and conditions"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
}
|
64
|
+
EOS
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
save_yaml do |yaml|
|
69
|
+
crypt = ActiveSupport::MessageEncryptor.new(Rails.application.secrets.secret_key_base)
|
70
|
+
data = crypt.encrypt_and_sign(yaml)
|
71
|
+
request["doop_data"] = data
|
72
|
+
end
|
73
|
+
|
74
|
+
debug_on do
|
75
|
+
doop["/page/preamble/debug_on/_answer"] == "Yes"
|
76
|
+
end
|
77
|
+
|
78
|
+
# On answer call backs
|
79
|
+
|
80
|
+
on_answer "/page/preamble/debug_on" do |question,path, params, answer|
|
81
|
+
answer_with( question, { "_summary" => answer } )
|
82
|
+
end
|
83
|
+
|
84
|
+
on_answer "/page/preamble/enrolled_before" do |question,path, params, answer|
|
85
|
+
answer_with( question, { "_summary" => answer } )
|
86
|
+
enable( "/page/preamble/year_last_applied", answer == "Yes" )
|
87
|
+
end
|
88
|
+
|
89
|
+
on_answer "/page/preamble/year_last_applied" do |question,path,params,answer|
|
90
|
+
answer_with( question, { "_summary" => answer } )
|
91
|
+
end
|
92
|
+
|
93
|
+
on_answer "/page/preamble/reason_for_applying" do |question,path,params,answer|
|
94
|
+
if answer.empty?
|
95
|
+
next { :reason_for_applying_error => "This can not be blank" }
|
96
|
+
end
|
97
|
+
|
98
|
+
answer_with( question, { "_summary" => "Provided" } )
|
99
|
+
end
|
100
|
+
|
101
|
+
on_answer( "/page/preamble" ) do |question, path, params, answer|
|
102
|
+
answer_with( question, { "_summary" => "Provided" } )
|
103
|
+
end
|
104
|
+
|
105
|
+
on_answer( "/page/your_details/your_name" ) do |question, path, params, answer|
|
106
|
+
firstname = answer["firstname"].capitalize
|
107
|
+
surname = answer["surname"].capitalize
|
108
|
+
answer_with( question, { "_summary" => "#{firstname} #{surname}" } )
|
109
|
+
end
|
110
|
+
|
111
|
+
on_answer( "/page/your_details/address_history/address__(\\d+)" ) do |question, path, params, answer|
|
112
|
+
|
113
|
+
if params.include?("remove_address")
|
114
|
+
remove path
|
115
|
+
next
|
116
|
+
end
|
117
|
+
|
118
|
+
address1 = answer["address1"]
|
119
|
+
address2 = answer["address2"]
|
120
|
+
address3 = answer["address3"]
|
121
|
+
postcode = answer["postcode"]
|
122
|
+
summary = [address1, address2, address3, postcode].select{ |n| !n.empty? }.join( ", ")
|
123
|
+
answer_with( question, { "_summary" => summary } )
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
on_answer( "/page/your_details/address_history" ) do |question, path, params, answer|
|
128
|
+
if params.include?("add_address")
|
129
|
+
address = YAML.load("{ _answer: {}}")
|
130
|
+
add( "/page/your_details/address_history/address__99", address )
|
131
|
+
renumber( "/page/your_details/address_history" )
|
132
|
+
next
|
133
|
+
end
|
134
|
+
|
135
|
+
answer_with( question, { "_summary" => "Provided" } )
|
136
|
+
end
|
137
|
+
|
138
|
+
on_answer( "/page/your_details" ) do |question, path, params, answer|
|
139
|
+
answer_with( question, { "_summary" => "Provided" } )
|
140
|
+
end
|
141
|
+
|
142
|
+
on_answer( "/page/your_details" ) do |question, path, params, answer|
|
143
|
+
answer_with( question, { "_summary" => "Provided" } )
|
144
|
+
end
|
145
|
+
|
146
|
+
on_answer( "/page/summary/terms_and_conditions" ) do |question, path, params, answer|
|
147
|
+
answer_with( question, { "_summary" => "Accepted" } )
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
end
|
155
|
+
|