eac_rails_utils 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +18 -0
- data/lib/assets/javascripts/currency_field.js +21 -0
- data/lib/assets/javascripts/eac_rails_utils.js +6 -0
- data/lib/assets/javascripts/input_searchable.js +78 -0
- data/lib/assets/javascripts/jMenu.jquery.min.js +12 -0
- data/lib/assets/javascripts/jquery.maskMoney.js +409 -0
- data/lib/assets/stylesheets/autocomplete.scss +33 -0
- data/lib/assets/stylesheets/bootstrap3-dropdown.scss +47 -0
- data/lib/assets/stylesheets/eac_rails_utils.scss +44 -0
- data/lib/assets/stylesheets/jmenu.scss +78 -0
- data/lib/eac/common_form_helper.rb +37 -0
- data/lib/eac/common_form_helper/form_builder.rb +88 -0
- data/lib/eac/common_form_helper/form_builder/association_select_field.rb +40 -0
- data/lib/eac/common_form_helper/form_builder/common_text_fields.rb +18 -0
- data/lib/eac/common_form_helper/form_builder/currency_field.rb +39 -0
- data/lib/eac/common_form_helper/form_builder/date_field.rb +20 -0
- data/lib/eac/common_form_helper/form_builder/fields_for.rb +44 -0
- data/lib/eac/common_form_helper/form_builder/radio_select_field.rb +44 -0
- data/lib/eac/common_form_helper/form_builder/searchable_association_field.rb +77 -0
- data/lib/eac/cpf_validator.rb +60 -0
- data/lib/eac/formatter_helper.rb +27 -0
- data/lib/eac/htmlbeautifier.rb +25 -0
- data/lib/eac/menus_helper.rb +17 -0
- data/lib/eac/menus_helper/bootstrap_gui_builder.rb +90 -0
- data/lib/eac/menus_helper/data_builder.rb +57 -0
- data/lib/eac/menus_helper/gui_builder.rb +51 -0
- data/lib/eac/model.rb +87 -0
- data/lib/eac/simple_cache.rb +29 -0
- data/lib/eac/source_target_fixtures.rb +51 -0
- data/lib/eac_rails_utils.rb +29 -0
- data/lib/eac_rails_utils/patches/model_attribute_required.rb +31 -0
- data/lib/eac_rails_utils/rails/engine.rb +5 -0
- data/lib/eac_rails_utils/version.rb +3 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/models/job.rb +4 -0
- data/test/dummy/app/models/user.rb +7 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +12 -0
- data/test/dummy/config/boot.rb +4 -0
- data/test/dummy/config/database.yml +5 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/routes.rb +8 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/migrate/20160415125333_create_users.rb +9 -0
- data/test/dummy/db/migrate/20160415143123_create_jobs.rb +7 -0
- data/test/dummy/db/migrate/20160415143229_add_job_to_users.rb +5 -0
- data/test/dummy/db/schema.rb +25 -0
- data/test/lib/eac/common_form_helper_test.rb +31 -0
- data/test/lib/eac/cpf_validator_test.rb +33 -0
- data/test/lib/eac/formatter_helper_test.rb +19 -0
- data/test/lib/eac/model_test.rb +76 -0
- data/test/lib/eac/simple_cache_test.rb +56 -0
- data/test/lib/eac_rails_utils/patches/model_attribute_required_test.rb +39 -0
- data/test/test_helper.rb +11 -0
- metadata +189 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
$jquery-autocomplete-bg-color: #ffffff !default;
|
2
|
+
$jquery-autocomplete-bg-highlight-color: #ccc !default;
|
3
|
+
$jquery-autocomplete-border-color: #DDD !default;
|
4
|
+
|
5
|
+
.ui-autocomplete {
|
6
|
+
position: absolute;
|
7
|
+
z-index: 5000;
|
8
|
+
cursor: default;
|
9
|
+
padding: 0;
|
10
|
+
margin-top: 2px;
|
11
|
+
list-style: none;
|
12
|
+
background-color: $jquery-autocomplete-bg-color;
|
13
|
+
border: 1px solid $jquery-autocomplete-border-color;
|
14
|
+
-webkit-border-radius: 5px;
|
15
|
+
-moz-border-radius: 5px;
|
16
|
+
border-radius: 5px;
|
17
|
+
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
18
|
+
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
19
|
+
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
20
|
+
|
21
|
+
> li {
|
22
|
+
padding: 3px 20px;
|
23
|
+
background-color: $jquery-autocomplete-bg-color;
|
24
|
+
}
|
25
|
+
|
26
|
+
> li.ui-state-focus {
|
27
|
+
background-color: $jquery-autocomplete-bg-highlight-color;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
.ui-helper-hidden-accessible {
|
32
|
+
display: none;
|
33
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
.dropdown-submenu {
|
2
|
+
position: relative;
|
3
|
+
}
|
4
|
+
|
5
|
+
.dropdown-submenu>.dropdown-menu {
|
6
|
+
top: 0;
|
7
|
+
left: 100%;
|
8
|
+
margin-top: -6px;
|
9
|
+
margin-left: -1px;
|
10
|
+
-webkit-border-radius: 0 6px 6px 6px;
|
11
|
+
-moz-border-radius: 0 6px 6px;
|
12
|
+
border-radius: 0 6px 6px 6px;
|
13
|
+
}
|
14
|
+
|
15
|
+
.dropdown-submenu:hover>.dropdown-menu {
|
16
|
+
display: block;
|
17
|
+
}
|
18
|
+
|
19
|
+
.dropdown-submenu>a:after {
|
20
|
+
display: block;
|
21
|
+
content: " ";
|
22
|
+
float: right;
|
23
|
+
width: 0;
|
24
|
+
height: 0;
|
25
|
+
border-color: transparent;
|
26
|
+
border-style: solid;
|
27
|
+
border-width: 5px 0 5px 5px;
|
28
|
+
border-left-color: #ccc;
|
29
|
+
margin-top: 5px;
|
30
|
+
margin-right: -10px;
|
31
|
+
}
|
32
|
+
|
33
|
+
.dropdown-submenu:hover>a:after {
|
34
|
+
border-left-color: #fff;
|
35
|
+
}
|
36
|
+
|
37
|
+
.dropdown-submenu.pull-left {
|
38
|
+
float: none;
|
39
|
+
}
|
40
|
+
|
41
|
+
.dropdown-submenu.pull-left>.dropdown-menu {
|
42
|
+
left: -100%;
|
43
|
+
margin-left: 10px;
|
44
|
+
-webkit-border-radius: 6px 0 6px 6px;
|
45
|
+
-moz-border-radius: 6px 0 6px 6px;
|
46
|
+
border-radius: 6px 0 6px 6px;
|
47
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
@import "bootstrap-sprockets";
|
2
|
+
@import "bootstrap";
|
3
|
+
@import "jmenu";
|
4
|
+
@import "bootstrap3-dropdown";
|
5
|
+
@import 'autocomplete';
|
6
|
+
|
7
|
+
.form-control-complex {
|
8
|
+
display: block;
|
9
|
+
width: 100%;
|
10
|
+
|
11
|
+
select {
|
12
|
+
@extend .form-control;
|
13
|
+
display: inline;
|
14
|
+
width: auto;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
.nested_form {
|
19
|
+
margin-bottom: 1.0em;
|
20
|
+
padding-bottom: 1.0em;
|
21
|
+
border-bottom: 1px solid #e5e5e5;
|
22
|
+
}
|
23
|
+
|
24
|
+
.nested_form_row {
|
25
|
+
margin-left: 1.0em;
|
26
|
+
padding-bottom: 1.0em;
|
27
|
+
margin-bottom: 1.0em;
|
28
|
+
border-bottom: 1px solid #e5e5e5;
|
29
|
+
}
|
30
|
+
|
31
|
+
form.CommonFormHelper {
|
32
|
+
div.form-group {
|
33
|
+
label.required {
|
34
|
+
font-weight: bold;
|
35
|
+
}
|
36
|
+
|
37
|
+
label.optional {
|
38
|
+
font-weight: normal;
|
39
|
+
&:after {
|
40
|
+
content: ' (Opcional)'
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
$menu-entry-background-color: #322f32;
|
2
|
+
$menu-entry-hover-background-color: #3a3a3a;
|
3
|
+
$menu-entry-color: white;
|
4
|
+
$submenu-entry-border-color: #484548;
|
5
|
+
$submenu-entry-hover-background-color: #514c52;
|
6
|
+
|
7
|
+
.jMenu {
|
8
|
+
display: table;
|
9
|
+
margin: 0;
|
10
|
+
padding: 0;
|
11
|
+
list-style: none;
|
12
|
+
float: left;
|
13
|
+
|
14
|
+
/* First level */
|
15
|
+
li {
|
16
|
+
display: table-cell;
|
17
|
+
background-color: $menu-entry-background-color;
|
18
|
+
margin: 0;
|
19
|
+
list-style: none;
|
20
|
+
margin-right: 0.3em;
|
21
|
+
float: left;
|
22
|
+
|
23
|
+
a {
|
24
|
+
display: block;
|
25
|
+
background-color: transparent;
|
26
|
+
color: $menu-entry-color;
|
27
|
+
cursor: pointer;
|
28
|
+
|
29
|
+
&:hover {
|
30
|
+
background-color: $menu-entry-hover-background-color;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
&:hover>a {
|
35
|
+
background-color: $menu-entry-hover-background-color;
|
36
|
+
};
|
37
|
+
|
38
|
+
// Sub-menus
|
39
|
+
ul {
|
40
|
+
display: none;
|
41
|
+
position: absolute;
|
42
|
+
z-index: 9999;
|
43
|
+
padding: 0;
|
44
|
+
margin: 0;
|
45
|
+
list-style: none;
|
46
|
+
|
47
|
+
li {
|
48
|
+
background-color: $menu-entry-background-color;
|
49
|
+
display: block;
|
50
|
+
border-bottom: 1px solid $submenu-entry-border-color;
|
51
|
+
padding: 0;
|
52
|
+
list-style: none;
|
53
|
+
position: relative;
|
54
|
+
float: none;
|
55
|
+
margin: 0;
|
56
|
+
|
57
|
+
a {
|
58
|
+
font-size: 80%;
|
59
|
+
text-transform: none;
|
60
|
+
display: block;
|
61
|
+
padding: 7px;
|
62
|
+
border-top: 1px solid transparent;
|
63
|
+
border-bottom: 1px solid transparent;
|
64
|
+
|
65
|
+
&.isParent {
|
66
|
+
background-color: $menu-entry-hover-background-color;
|
67
|
+
}
|
68
|
+
|
69
|
+
&:hover {
|
70
|
+
background-color: $submenu-entry-hover-background-color;
|
71
|
+
border-top: 1px solid $menu-entry-background-color;
|
72
|
+
border-bottom: 1px solid $menu-entry-background-color;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Eac
|
2
|
+
module CommonFormHelper
|
3
|
+
def common_form(model_instance, options = {}, &block)
|
4
|
+
submit_label = options.delete(:submit_label)
|
5
|
+
options[:html] ||= {}
|
6
|
+
options[:html][:class] = 'CommonFormHelper'
|
7
|
+
form_for(model_instance, options) do |form|
|
8
|
+
fb = FormBuilder.new(form, self)
|
9
|
+
errors(model_instance) <<
|
10
|
+
capture(fb, &block) <<
|
11
|
+
errors_not_showed(model_instance, fb.field_errors_showed) <<
|
12
|
+
form.submit(submit_label, class: 'btn btn-primary')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def errors(model_instance)
|
19
|
+
if model_instance.errors.any?
|
20
|
+
content_tag(:div, class: 'alert alert-danger', id: 'flash_alert') do
|
21
|
+
'Há pendências no preenchimento do formulário.'
|
22
|
+
end
|
23
|
+
else
|
24
|
+
ActiveSupport::SafeBuffer.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def errors_not_showed(model_instance, field_errors_showed)
|
29
|
+
s = ActiveSupport::SafeBuffer.new
|
30
|
+
model_instance.errors.each do |k, v|
|
31
|
+
next if field_errors_showed.include?(k)
|
32
|
+
s << content_tag(:div, "#{k}: #{v}", class: 'error')
|
33
|
+
end
|
34
|
+
s
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Eac
|
2
|
+
module CommonFormHelper
|
3
|
+
class FormBuilder
|
4
|
+
include AssociationSelectField
|
5
|
+
include CommonTextFields
|
6
|
+
include CurrencyField
|
7
|
+
include DateField
|
8
|
+
include RadioSelectField
|
9
|
+
include FieldsFor
|
10
|
+
|
11
|
+
attr_reader :form, :helper, :field_errors_showed
|
12
|
+
|
13
|
+
def initialize(form, helper)
|
14
|
+
@form = form
|
15
|
+
@helper = helper
|
16
|
+
@field_errors_showed = Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def model_instance
|
20
|
+
form.object
|
21
|
+
end
|
22
|
+
|
23
|
+
def hidden_field(field_name, options = {})
|
24
|
+
@form.hidden_field(field_name, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_box_field(field_name, options = {})
|
28
|
+
field(field_name, options) { @form.check_box(field_name, options) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def file_field(field_name, options = {})
|
32
|
+
field(field_name, options) { @form.file_field(field_name, options) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def searchable_association_field(field_name, options = {})
|
36
|
+
saf = SearchableAssociationField.new(self, field_name, options)
|
37
|
+
saf.hidden_input <<
|
38
|
+
field(field_name, options) { saf.visible_input } <<
|
39
|
+
saf.javascript_tag
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def field(field_name, options)
|
45
|
+
@helper.content_tag(:div, class: 'form-group') do
|
46
|
+
s = field_label(field_name, options[:label], options[:required])
|
47
|
+
s << ' '
|
48
|
+
s << yield()
|
49
|
+
s << ' '
|
50
|
+
s << field_errors(field_name)
|
51
|
+
s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def field_errors(field_name)
|
56
|
+
s = ActiveSupport::SafeBuffer.new
|
57
|
+
field_errors_fields(field_name).each do |frf|
|
58
|
+
s << field_errors_errors(frf)
|
59
|
+
end
|
60
|
+
s
|
61
|
+
end
|
62
|
+
|
63
|
+
def field_errors_errors(field_name)
|
64
|
+
return nil unless model_instance.errors.messages[field_name]
|
65
|
+
s = ActiveSupport::SafeBuffer.new
|
66
|
+
model_instance.errors.messages[field_name].each { |error| s << field_error(error) }
|
67
|
+
@field_errors_showed.add(field_name)
|
68
|
+
s
|
69
|
+
end
|
70
|
+
|
71
|
+
def field_errors_fields(field_name)
|
72
|
+
m = /^(.+)_id$/.match(field_name)
|
73
|
+
(m ? [m[1], field_name] : [field_name, "#{field_name}_id"]).map(&:to_sym)
|
74
|
+
end
|
75
|
+
|
76
|
+
def field_error(error_message)
|
77
|
+
@helper.content_tag(:div, class: 'error') do
|
78
|
+
error_message
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def field_label(field_name, label, required)
|
83
|
+
required = model_instance.attribute_required?(field_name) if required.nil?
|
84
|
+
@form.label(field_name, label, class: required ? 'required' : 'optional')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Eac
|
2
|
+
module CommonFormHelper
|
3
|
+
class FormBuilder
|
4
|
+
module AssociationSelectField
|
5
|
+
def association_select_field(field_name, options = {})
|
6
|
+
options = options.dup
|
7
|
+
methods = extract_methods(options)
|
8
|
+
select_options = extract_select_options(options)
|
9
|
+
collection = extract_association_key(field_name, options, :collection, :all)
|
10
|
+
foreign_key = extract_association_key(field_name, options, :foreign_key,
|
11
|
+
:association_foreign_key)
|
12
|
+
field(field_name, options) do
|
13
|
+
form.collection_select(foreign_key, collection, methods[:value], methods[:text],
|
14
|
+
select_options, class: 'form-control')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def extract_methods(options)
|
21
|
+
{ value: options.delete(:value_method) || :id, text:
|
22
|
+
options.delete(:text_method) || :to_s }
|
23
|
+
end
|
24
|
+
|
25
|
+
def extract_select_options(options)
|
26
|
+
options.extract!(:prompt, :include_blank)
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_association_key(field_name, options, key, method)
|
30
|
+
return options.delete(key) if options.key?(key)
|
31
|
+
if model_instance.class.respond_to?(:reflect_on_association)
|
32
|
+
return model_instance.class.reflect_on_association(field_name).send(method)
|
33
|
+
end
|
34
|
+
fail "#{model_instance.class} não possui um método \"reflect_on_association\". " \
|
35
|
+
"Defina explicitamente a opção :#{key}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Eac
|
2
|
+
module CommonFormHelper
|
3
|
+
class FormBuilder
|
4
|
+
module CommonTextFields
|
5
|
+
%w(email password text).each do |t|
|
6
|
+
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
7
|
+
def #{t}_field(field_name, options = {}) # def text_field(field_name, options = {})
|
8
|
+
field(field_name, options) do # field(field_name, options) do
|
9
|
+
@form.#{t}_field(field_name, # @form.text_field(field_name,
|
10
|
+
class: 'form-control') # class: 'form-control')
|
11
|
+
end # end
|
12
|
+
end # end
|
13
|
+
RUBY_EVAL
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Eac
|
2
|
+
module CommonFormHelper
|
3
|
+
class FormBuilder
|
4
|
+
module CurrencyField
|
5
|
+
def currency_field(field_name, options = {})
|
6
|
+
hidden_id = SecureRandom.hex(5)
|
7
|
+
visible_id = SecureRandom.hex(5)
|
8
|
+
cf = field(field_name, options) do
|
9
|
+
form.hidden_field(field_name, id: hidden_id) <<
|
10
|
+
helper.text_field_tag("#{field_name}_visible", '',
|
11
|
+
id: visible_id, class: 'form-control')
|
12
|
+
end
|
13
|
+
cf << javascript_currency_mask(hidden_id, visible_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def javascript_currency_mask(hidden_id, visible_id)
|
19
|
+
helper.content_tag :script do
|
20
|
+
helper.raw("new CurrencyField('#{hidden_id}', '#{visible_id}', " \
|
21
|
+
"#{mask_money_options});")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def mask_money_options
|
26
|
+
<<-eos
|
27
|
+
{
|
28
|
+
prefix: '#{I18n.t('number.currency.format.unit')} ',
|
29
|
+
allowNegative: true,
|
30
|
+
thousands: '#{I18n.t('number.currency.format.delimiter')}',
|
31
|
+
decimal: '#{I18n.t('number.currency.format.separator')}',
|
32
|
+
affixesStay: false
|
33
|
+
}
|
34
|
+
eos
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Eac
|
2
|
+
module CommonFormHelper
|
3
|
+
class FormBuilder
|
4
|
+
module DateField
|
5
|
+
def date_field(field_name, options = {})
|
6
|
+
field_options = options.extract!(:use_month_numbers, :use_two_digit_numbers,
|
7
|
+
:use_short_month, :add_month_numbers, :use_month_names,
|
8
|
+
:month_format_string, :date_separator, :start_year,
|
9
|
+
:end_year, :discard_day, :discard_month, :discard_year,
|
10
|
+
:order, :include_blank, :default, :selected, :disabled,
|
11
|
+
:prompt, :with_css_classes)
|
12
|
+
field(field_name, options) do
|
13
|
+
@helper.content_tag(:div, @form.date_select(field_name, field_options),
|
14
|
+
class: 'form-control-complex')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|