doop 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +15 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +203 -0
  6. data/Rakefile +5 -0
  7. data/app/assets/images/dash.gif +0 -0
  8. data/app/assets/images/info-icon.png +0 -0
  9. data/app/assets/images/progress-tick-large.png +0 -0
  10. data/app/helpers/doop_helper.rb +51 -0
  11. data/bin/.gitignore +0 -0
  12. data/doop.gemspec +26 -0
  13. data/lib/doop.rb +313 -0
  14. data/lib/doop/version.rb +3 -0
  15. data/lib/doop_controller.rb +164 -0
  16. data/lib/generators/doopgovuk/USAGE +10 -0
  17. data/lib/generators/doopgovuk/doopgovuk_generator.rb +34 -0
  18. data/lib/generators/doopgovuk/templates/app/assets/stylesheets/demo.css.scss +188 -0
  19. data/lib/generators/doopgovuk/templates/app/controllers/demo_controller.rb +155 -0
  20. data/lib/generators/doopgovuk/templates/app/views/demo/_preamble.html.erb +33 -0
  21. data/lib/generators/doopgovuk/templates/app/views/demo/_summary.html.erb +10 -0
  22. data/lib/generators/doopgovuk/templates/app/views/demo/_your_details.html.erb +55 -0
  23. data/lib/generators/doopgovuk/templates/app/views/demo/index.html.erb +3 -0
  24. data/lib/generators/doopgovuk/templates/app/views/demo/index.js.erb +4 -0
  25. data/lib/generators/doopgovuk/templates/app/views/doop/_error.html.erb +3 -0
  26. data/lib/generators/doopgovuk/templates/app/views/doop/_info_box.html.erb +4 -0
  27. data/lib/generators/doopgovuk/templates/app/views/doop/_navbar.html.erb +23 -0
  28. data/lib/generators/doopgovuk/templates/app/views/doop/_question.html.erb +19 -0
  29. data/lib/generators/doopgovuk/templates/app/views/doop/_question_form.html.erb +15 -0
  30. data/lib/generators/doopgovuk/templates/app/views/layouts/application.html.erb +22 -0
  31. data/spec/doop_spec.rb +448 -0
  32. data/spec/spec_helper.rb +2 -0
  33. metadata +136 -0
@@ -0,0 +1,3 @@
1
+ module Doop
2
+ VERSION = "0.0.1"
3
+ end
@@ -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
+