wheelhouse-forms 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/LICENSE +22 -0
- data/README.md +39 -0
- data/app/assets/images/wheelhouse-forms/checkbox.png +0 -0
- data/app/assets/images/wheelhouse-forms/checkboxes.png +0 -0
- data/app/assets/images/wheelhouse-forms/content.png +0 -0
- data/app/assets/images/wheelhouse-forms/countries.png +0 -0
- data/app/assets/images/wheelhouse-forms/csv.png +0 -0
- data/app/assets/images/wheelhouse-forms/custom.png +0 -0
- data/app/assets/images/wheelhouse-forms/drag.png +0 -0
- data/app/assets/images/wheelhouse-forms/field-set.png +0 -0
- data/app/assets/images/wheelhouse-forms/form.png +0 -0
- data/app/assets/images/wheelhouse-forms/radio-buttons.png +0 -0
- data/app/assets/images/wheelhouse-forms/select.png +0 -0
- data/app/assets/images/wheelhouse-forms/states.png +0 -0
- data/app/assets/images/wheelhouse-forms/submit-button.png +0 -0
- data/app/assets/images/wheelhouse-forms/text-area.png +0 -0
- data/app/assets/images/wheelhouse-forms/text-field.png +0 -0
- data/app/assets/javascripts/wheelhouse-forms/admin.js +125 -0
- data/app/assets/javascripts/wheelhouse-forms/jquery.autogrow.js +50 -0
- data/app/assets/javascripts/wheelhouse-forms/jquery.options.js +24 -0
- data/app/assets/stylesheets/wheelhouse-forms/admin.css.sass +244 -0
- data/app/controllers/forms/forms_controller.rb +9 -0
- data/app/controllers/forms/submissions_controller.rb +19 -0
- data/app/handlers/forms/form_handler.rb +17 -0
- data/app/helpers/forms/forms_helper.rb +36 -0
- data/app/helpers/forms/mailer_helper.rb +67 -0
- data/app/helpers/forms/submissions_helper.rb +71 -0
- data/app/mailers/forms/mailer.rb +11 -0
- data/app/models/forms/field_collection.rb +21 -0
- data/app/models/forms/fields/checkbox.rb +8 -0
- data/app/models/forms/fields/checkboxes.rb +10 -0
- data/app/models/forms/fields/content_field.rb +7 -0
- data/app/models/forms/fields/countries_dropdown.rb +14 -0
- data/app/models/forms/fields/custom_field.rb +8 -0
- data/app/models/forms/fields/field.rb +28 -0
- data/app/models/forms/fields/field_set.rb +14 -0
- data/app/models/forms/fields/optioned_field.rb +17 -0
- data/app/models/forms/fields/radio_buttons.rb +10 -0
- data/app/models/forms/fields/select_field.rb +10 -0
- data/app/models/forms/fields/states_dropdown.rb +15 -0
- data/app/models/forms/fields/submit_button.rb +7 -0
- data/app/models/forms/fields/text_area.rb +8 -0
- data/app/models/forms/fields/text_field.rb +21 -0
- data/app/models/forms/form.rb +65 -0
- data/app/models/forms/submission.rb +53 -0
- data/app/renderers/forms/checkbox_renderer.rb +7 -0
- data/app/renderers/forms/checkboxes_renderer.rb +18 -0
- data/app/renderers/forms/content_field_renderer.rb +5 -0
- data/app/renderers/forms/custom_field_renderer.rb +5 -0
- data/app/renderers/forms/field_collection_renderer.rb +13 -0
- data/app/renderers/forms/field_renderer.rb +57 -0
- data/app/renderers/forms/field_set_renderer.rb +10 -0
- data/app/renderers/forms/form_renderer.rb +30 -0
- data/app/renderers/forms/labelled_field_renderer.rb +10 -0
- data/app/renderers/forms/radio_buttons_renderer.rb +18 -0
- data/app/renderers/forms/select_field_renderer.rb +9 -0
- data/app/renderers/forms/submit_button_renderer.rb +5 -0
- data/app/renderers/forms/text_area_renderer.rb +7 -0
- data/app/renderers/forms/text_field_renderer.rb +7 -0
- data/app/templates/form.html.haml +9 -0
- data/app/templates/form.xhr.haml +4 -0
- data/app/templates/form/submission.html.haml +15 -0
- data/app/views/forms/forms/_checkbox.haml +3 -0
- data/app/views/forms/forms/_checkboxes.haml +10 -0
- data/app/views/forms/forms/_content_field.haml +3 -0
- data/app/views/forms/forms/_countries_dropdown.haml +4 -0
- data/app/views/forms/forms/_custom_field.haml +4 -0
- data/app/views/forms/forms/_field_set.haml +16 -0
- data/app/views/forms/forms/_radio_buttons.haml +10 -0
- data/app/views/forms/forms/_select_field.haml +10 -0
- data/app/views/forms/forms/_states_dropdown.haml +4 -0
- data/app/views/forms/forms/_submissions.haml +20 -0
- data/app/views/forms/forms/_submit_button.haml +2 -0
- data/app/views/forms/forms/_text_area.haml +3 -0
- data/app/views/forms/forms/_text_field.haml +4 -0
- data/app/views/forms/forms/designer.haml +56 -0
- data/app/views/forms/forms/edit.html.haml +5 -0
- data/app/views/forms/forms/form.haml +22 -0
- data/app/views/forms/forms/new.html.haml +4 -0
- data/app/views/forms/forms/show.html.haml +4 -0
- data/app/views/forms/submissions/form.haml +16 -0
- data/app/views/forms/submissions/show.html.haml +4 -0
- data/config/countries.yml +245 -0
- data/config/locales/en.yml +7 -0
- data/config/routes.rb +7 -0
- data/config/states.yml +62 -0
- data/lib/forms/csv_exporter.rb +41 -0
- data/lib/wheelhouse-forms.rb +26 -0
- metadata +149 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module Forms::Fields
|
2
|
+
class TextField < Field
|
3
|
+
property :label, String, :required => true
|
4
|
+
property :input_type, String, :default => "text"
|
5
|
+
property :required, Boolean, :default => false
|
6
|
+
|
7
|
+
self.renderer = Forms::TextFieldRenderer
|
8
|
+
|
9
|
+
INPUT_TYPES = [
|
10
|
+
["Text", "text"],
|
11
|
+
["Email", "email"],
|
12
|
+
["Telephone", "tel"],
|
13
|
+
["URL", "url"],
|
14
|
+
["Date", "date"],
|
15
|
+
["Date & Time", "datetime"],
|
16
|
+
["Number", "number"],
|
17
|
+
["Search", "search"],
|
18
|
+
["Color", "color"]
|
19
|
+
]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class Forms::Form < Wheelhouse::Resource
|
2
|
+
include Wheelhouse::Resource::Node
|
3
|
+
include Wheelhouse::Resource::Renderable
|
4
|
+
include Wheelhouse::Resource::Addressable
|
5
|
+
include Wheelhouse::Resource::Versioned
|
6
|
+
include Wheelhouse::Resource::Content
|
7
|
+
|
8
|
+
property :title, String, :required => true, :translate => true
|
9
|
+
property :fields, FieldCollection, :default => [Forms::Fields::FieldSet.new]
|
10
|
+
property :recipients, MongoModel::Collection[String]
|
11
|
+
property :subject, String, :default => "Form Submission"
|
12
|
+
|
13
|
+
validates_associated :fields
|
14
|
+
|
15
|
+
has_many :submissions, :class => "Forms::Submission"
|
16
|
+
|
17
|
+
activities :all
|
18
|
+
|
19
|
+
icon "wheelhouse-forms/form.png"
|
20
|
+
|
21
|
+
attr_accessor :view_context, :current_submission
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
render(view_context)
|
25
|
+
end
|
26
|
+
|
27
|
+
def render(template)
|
28
|
+
Forms::FormRenderer.new(self, current_submission, template).render
|
29
|
+
end
|
30
|
+
|
31
|
+
def submit(params)
|
32
|
+
submission = submissions.build(:params => params)
|
33
|
+
|
34
|
+
if submission.save
|
35
|
+
deliver(submission)
|
36
|
+
@success = true
|
37
|
+
else
|
38
|
+
self.current_submission = submission
|
39
|
+
@success = false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def deliver(submission)
|
44
|
+
Forms::Mailer.submission(self, submission).deliver unless recipients.empty?
|
45
|
+
rescue
|
46
|
+
# Mail delivery failed
|
47
|
+
end
|
48
|
+
|
49
|
+
def success?
|
50
|
+
@success
|
51
|
+
end
|
52
|
+
|
53
|
+
def first_content_field
|
54
|
+
@first_content_field ||= fields.flatten.find { |f| f.respond_to?(:label) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def recipients=(recipients)
|
58
|
+
recipients = recipients.split(/,/) if recipients.is_a?(String)
|
59
|
+
write_attribute(:recipients, recipients.map(&:strip))
|
60
|
+
end
|
61
|
+
|
62
|
+
def handler
|
63
|
+
Forms::FormHandler
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Forms::Submission < Wheelhouse::BasicResource
|
2
|
+
class Parameters < Hash
|
3
|
+
def to_mongo
|
4
|
+
result = []
|
5
|
+
each do |key, value|
|
6
|
+
result << [key, value]
|
7
|
+
end
|
8
|
+
result
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.cast(params)
|
12
|
+
case params
|
13
|
+
when Hash
|
14
|
+
self[params]
|
15
|
+
when Array
|
16
|
+
params.each_with_object({}) { |v, hash| hash[v[0]] = v[1] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_mongo(params)
|
21
|
+
cast(params)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
include Wheelhouse::Resource::AdminPath
|
26
|
+
|
27
|
+
property :params, Parameters
|
28
|
+
timestamps!
|
29
|
+
|
30
|
+
belongs_to :form, :class => "Forms::Form"
|
31
|
+
|
32
|
+
default_scope order(:created_at.desc)
|
33
|
+
|
34
|
+
validate do
|
35
|
+
form.fields.flatten.each do |field|
|
36
|
+
if field.required? && value_for(field).blank?
|
37
|
+
errors.add(field.label, "This field is required")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def value_for(field)
|
43
|
+
params[field.label]
|
44
|
+
end
|
45
|
+
|
46
|
+
def admin_path
|
47
|
+
form_submission_path(form_id, id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def admin_url
|
51
|
+
form_submission_url(form, id, :host => form.site.domain)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Forms::CheckboxesRenderer < Forms::FieldRenderer
|
2
|
+
include Forms::LabelledFieldRenderer
|
3
|
+
|
4
|
+
def render
|
5
|
+
super { content_tag(:ul, safe_join(list_items, "\n")) }
|
6
|
+
end
|
7
|
+
|
8
|
+
protected
|
9
|
+
def list_items
|
10
|
+
field.options.map { |o| content_tag(:li, checkbox(o)) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def checkbox(option)
|
14
|
+
content_tag(:label, :class => "option #{option.parameterize}") do
|
15
|
+
check_box_tag("#{name}[]", option, (value || []).include?(option), :id => nil) + " " + option
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Forms::FieldCollectionRenderer
|
2
|
+
include ActionView::Helpers::OutputSafetyHelper
|
3
|
+
|
4
|
+
attr_reader :collection, :submission, :template
|
5
|
+
|
6
|
+
def initialize(collection, submission, template)
|
7
|
+
@collection, @submission, @template = collection, submission, template
|
8
|
+
end
|
9
|
+
|
10
|
+
def render
|
11
|
+
safe_join(collection.map { |field| field.render(submission, template) }, "\n")
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Forms::FieldRenderer
|
2
|
+
include ActionView::Helpers::FormTagHelper
|
3
|
+
include ActionView::Helpers::OutputSafetyHelper
|
4
|
+
|
5
|
+
attr_accessor :output_buffer
|
6
|
+
attr_reader :field, :submission, :template
|
7
|
+
|
8
|
+
def initialize(field, submission, template)
|
9
|
+
@field, @submission, @template = field, submission, template
|
10
|
+
end
|
11
|
+
|
12
|
+
def render
|
13
|
+
content_tag(:div, :class => classes.join(" ")) do
|
14
|
+
concat yield if block_given?
|
15
|
+
concat content_tag(:p, error, :class => "error") if has_errors?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def name
|
21
|
+
"submission[#{reference}]"
|
22
|
+
end
|
23
|
+
|
24
|
+
def reference
|
25
|
+
field.label
|
26
|
+
end
|
27
|
+
|
28
|
+
def field_class
|
29
|
+
field.class.partial.dasherize
|
30
|
+
end
|
31
|
+
|
32
|
+
def classes
|
33
|
+
classes = ["field", field_class]
|
34
|
+
classes << reference.parameterize
|
35
|
+
classes << "required" if field.required?
|
36
|
+
classes << "error" if has_errors?
|
37
|
+
classes.uniq
|
38
|
+
end
|
39
|
+
|
40
|
+
def value
|
41
|
+
submission.value_for(field) if submission
|
42
|
+
end
|
43
|
+
|
44
|
+
def has_errors?
|
45
|
+
submission && submission.errors[field.label].any?
|
46
|
+
end
|
47
|
+
|
48
|
+
def error
|
49
|
+
submission.errors[field.label].first
|
50
|
+
end
|
51
|
+
|
52
|
+
def html_options
|
53
|
+
options = {}
|
54
|
+
options[:required] = "required" if field.required?
|
55
|
+
options
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Forms::FieldSetRenderer < Forms::FieldRenderer
|
2
|
+
def render
|
3
|
+
content_tag(:fieldset, :class => field.legend? ? field.legend.parameterize : '') do
|
4
|
+
ActiveSupport::SafeBuffer.new.tap do |result|
|
5
|
+
result << content_tag(:legend, field.legend) if field.legend?
|
6
|
+
result << field.fields.render(submission, template)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Forms::FormRenderer
|
2
|
+
include ActionView::Helpers::FormTagHelper
|
3
|
+
|
4
|
+
attr_accessor :output_buffer
|
5
|
+
attr_reader :form, :submission, :template
|
6
|
+
|
7
|
+
def initialize(form, submission, template)
|
8
|
+
@form, @submission, @template = form, submission, template
|
9
|
+
end
|
10
|
+
|
11
|
+
def render
|
12
|
+
form_tag(form.path) do
|
13
|
+
concat form.fields.render(submission, template)
|
14
|
+
concat default_submit_button unless has_submit_button?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def protect_against_forgery?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def has_submit_button?
|
24
|
+
form.fields.flatten.any? { |f| f.is_a?(Forms::Fields::SubmitButton) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_submit_button
|
28
|
+
content_tag(:div, submit_tag("Submit"), :class => "submit")
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Forms::RadioButtonsRenderer < Forms::FieldRenderer
|
2
|
+
include Forms::LabelledFieldRenderer
|
3
|
+
|
4
|
+
def render
|
5
|
+
super { content_tag(:ul, safe_join(list_items, "\n")) }
|
6
|
+
end
|
7
|
+
|
8
|
+
protected
|
9
|
+
def list_items
|
10
|
+
field.options.map { |o| content_tag(:li, radio_button(o)) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def radio_button(option)
|
14
|
+
content_tag(:label, :class => "option #{option.parameterize}") do
|
15
|
+
radio_button_tag(name, option, value == option, :id => nil) + " " + option
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
= form_field(checkboxes, :index => index, :prefix => prefix, :class => "checkboxes") do |f|
|
2
|
+
= f.text_field :label, :title => "Checkboxes Label", :placeholder => "Checkboxes Label", :id => nil
|
3
|
+
= f.required_field_checkbox
|
4
|
+
|
5
|
+
%ul.options
|
6
|
+
%li
|
7
|
+
%label Options:
|
8
|
+
|
9
|
+
- checkboxes.options(true).each do |option|
|
10
|
+
%li= text_field_tag "#{prefix}[options][]", option, :id => nil
|
@@ -0,0 +1,4 @@
|
|
1
|
+
= form_field(countries_dropdown, :index => index, :prefix => prefix, :class => "countries-dropdown", :icon => "countries") do |f|
|
2
|
+
= f.text_field :label, :title => "Countries Dropdown Label", :placeholder => "Countries Dropdown Label", :id => nil
|
3
|
+
= f.required_field_checkbox
|
4
|
+
|
@@ -0,0 +1,4 @@
|
|
1
|
+
= form_field(custom_field, :index => index, :prefix => prefix, :class => "custom-field", :icon => "custom") do |f|
|
2
|
+
= f.text_field :label, :title => "Custom Field Label", :placeholder => "Custom Field Label", :id => nil
|
3
|
+
= f.text_field :partial, :title => "Partial", :placeholder => "Partial", :id => nil
|
4
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
.field-set{ "data-index" => index }
|
2
|
+
= hidden_field_tag "#{prefix}[type]", field_set.type.demodulize, :id => nil
|
3
|
+
|
4
|
+
.drag
|
5
|
+
|
6
|
+
.drag-area
|
7
|
+
= label_tag "fieldset_#{index}_legend", "Fieldset Legend:"
|
8
|
+
= text_field_tag "#{prefix}[legend]", field_set.legend, :id => "fieldset_#{index}_legend"
|
9
|
+
|
10
|
+
%span.note (leave blank for none)
|
11
|
+
|
12
|
+
.fields{ "data-prefix" => "form[fields][#{index}][fields]" }
|
13
|
+
= render_fields(field_set.fields, "form[fields][#{index}][fields]")
|
14
|
+
|
15
|
+
= link_to "Delete", '#', :class => 'delete'
|
16
|
+
|