beautiful_scaffold 0.1.4 → 0.1.5

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.
Files changed (25) hide show
  1. data/beautiful_scaffold.gemspec +1 -1
  2. data/lib/generators/beautiful_scaffold_generator.rb +19 -4
  3. data/lib/generators/templates/app/assets/images/ui-anim_basic_16x16.gif +0 -0
  4. data/lib/generators/templates/app/assets/javascripts/bootstrap-datetimepicker-for-beautiful-scaffold.js +20 -5
  5. data/lib/generators/templates/app/assets/javascripts/jquery.jstree.js +4551 -0
  6. data/lib/generators/templates/app/assets/javascripts/tagit.js +489 -0
  7. data/lib/generators/templates/app/assets/stylesheets/tagit-dark-grey.css +135 -0
  8. data/lib/generators/templates/app/assets/stylesheets/themes/default/d.gif +0 -0
  9. data/lib/generators/templates/app/assets/stylesheets/themes/default/d.png +0 -0
  10. data/lib/generators/templates/app/assets/stylesheets/themes/default/style.css +74 -0
  11. data/lib/generators/templates/app/assets/stylesheets/themes/default/throbber.gif +0 -0
  12. data/lib/generators/templates/app/controllers/base.rb +11 -0
  13. data/lib/generators/templates/app/controllers/master_base.rb +39 -0
  14. data/lib/generators/templates/app/helpers/beautiful_helper.rb +53 -19
  15. data/lib/generators/templates/app/locales/beautiful_scaffold.en.yml +1 -0
  16. data/lib/generators/templates/app/locales/beautiful_scaffold.fr.yml +2 -1
  17. data/lib/generators/templates/app/views/_form_habtm_tag.html.erb +47 -0
  18. data/lib/generators/templates/app/views/_treeview_js.html.erb +42 -0
  19. data/lib/generators/templates/app/views/edit.html.erb +1 -1
  20. data/lib/generators/templates/app/views/index.html.erb +3 -0
  21. data/lib/generators/templates/app/views/layout.html.erb +1 -7
  22. data/lib/generators/templates/app/views/partials/_form_field.html.erb +1 -1
  23. data/lib/generators/templates/app/views/partials/_index_search.html.erb +4 -0
  24. data/lib/generators/templates/app/views/treeview.html.erb +22 -0
  25. metadata +14 -3
@@ -0,0 +1,135 @@
1
+ .ui-autocomplete {
2
+ background-color: #fff;
3
+ position: absolute;
4
+ cursor: default;
5
+ list-style: none;
6
+ margin: 25px 0 0;
7
+ padding: 0;
8
+ border: 1px solid #E5E5E5;
9
+ border-top: none;
10
+ -moz-border-radius: 0 0 10px 10px;
11
+ border-radius: 0 0 10px 10px;
12
+ -moz-box-shadow: 0 3px 5px #888;
13
+ -webkit-box-shadow: 0 3px 5px #888;
14
+ box-shadow: 0 3px 5px #888;
15
+ font-size: 12px;
16
+ }
17
+
18
+ .ui-autocomplete .ui-menu-item {
19
+ padding: 0;
20
+ margin: 0;
21
+ }
22
+
23
+ .ui-autocomplete .ui-menu-item a {
24
+ display: block;
25
+ padding: 4px 6px;
26
+ margin: 0;
27
+ text-decoration: none;
28
+ line-height: 12px;
29
+ border-bottom: 1px solid #E5E5E5;
30
+ border-top: 1px solid #fff;
31
+ color: #78959D;
32
+
33
+ }
34
+
35
+ .ui-autocomplete .ui-menu-item a.ui-state-hover,
36
+ .ui-autocomplete .ui-menu-item a.ui-state-active {
37
+ background-color: #c0d1e2;
38
+ color: #555;
39
+ border-color: #a6cef7;
40
+ }
41
+
42
+ .ui-autocomplete-loading {
43
+ background: white url(/assets/ui-anim_basic_16x16.gif) right center no-repeat;
44
+ }
45
+
46
+ ul.tagit {
47
+ cursor: text;
48
+ overflow: auto;
49
+ font-size: 14px;
50
+ width: 97%;
51
+ padding: 0px;
52
+ margin: 0px;
53
+ background: #fff;
54
+ color: #fff;
55
+ }
56
+
57
+ ul.tagit li {
58
+ -moz-border-radius: 5px;
59
+ border-radius: 5px;
60
+ display: block;
61
+ float: left;
62
+ margin: 2px 5px 2px 0;
63
+ position: relative;
64
+ }
65
+
66
+ ul.tagit.ui-sortable li.tagit-choice a.ui-icon.ui-icon-grip-dotted-vertical{
67
+ float: left;
68
+ width: 12px;
69
+ margin-left: -5px;
70
+ cursor: move;
71
+ }
72
+
73
+ ul.tagit li.tagit-choice {
74
+ background-color: #333;
75
+ border: 1px solid #333;
76
+ padding: 2px 13px 3px 4px;
77
+ }
78
+
79
+ ul.tagit li.tagit-choice.selected {
80
+ background-color: #633;
81
+ border-color: #f76464;
82
+ }
83
+
84
+ ul.tagit li.tagit-choice:hover {
85
+ background-color: #555;
86
+ border-color: #444;
87
+ }
88
+
89
+ ul.tagit li.tagit-new {
90
+ clear: left;
91
+ padding: 2px 4px 3px;
92
+ padding: 2px 4px 1px;
93
+ padding: 2px 4px 1px 0;
94
+ }
95
+
96
+ ul.tagit li.tagit-choice input {
97
+ display: block;
98
+ float: left;
99
+ margin: 0 5px 0 0;
100
+ padding-top: 2px;
101
+ padding-bottom: 2px;
102
+ }
103
+
104
+ ul.tagit li.tagit-choice a.tagit-close {
105
+ color: #ccc;
106
+ cursor: pointer;
107
+ font-size: 12px;
108
+ font-weight: bold;
109
+ outline: medium none;
110
+ padding: 2px 0 2px 3px;
111
+ text-decoration: none;
112
+ position: absolute;
113
+ display: block;
114
+ top: 0;
115
+ right: 3px;
116
+ text-shadow: 1px 1px 0 rgba(100, 100, 100, 0.7);
117
+ }
118
+
119
+ ul.tagit li.tagit-choice a.tagit-close:hover {
120
+ color: #fff;
121
+ text-shadow: none;
122
+ }
123
+ /*
124
+ ul.tagit input[type="text"] {
125
+ -moz-box-sizing: border-box;
126
+ border: none !important;
127
+ margin: 0 !important;
128
+ padding: 0 !important;
129
+ width: inherit !important;
130
+ outline: none;
131
+ }
132
+ */
133
+ select.tagit-hiddenSelect {
134
+ display:none;
135
+ }
@@ -0,0 +1,74 @@
1
+ /*
2
+ * jsTree default theme 1.0
3
+ * Supported features: dots/no-dots, icons/no-icons, focused, loading
4
+ * Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search
5
+ */
6
+
7
+ .jstree-default li,
8
+ .jstree-default ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; }
9
+ .jstree-default li { background-position:-90px 0; background-repeat:repeat-y; }
10
+ .jstree-default li.jstree-last { background:transparent; }
11
+ .jstree-default .jstree-open > ins { background-position:-72px 0; }
12
+ .jstree-default .jstree-closed > ins { background-position:-54px 0; }
13
+ .jstree-default .jstree-leaf > ins { background-position:-36px 0; }
14
+
15
+ .jstree-default .jstree-hovered { background:#e7f4f9; border:1px solid #d8f0fa; padding:0 2px 0 1px; }
16
+ .jstree-default .jstree-clicked { background:#beebff; border:1px solid #99defd; padding:0 2px 0 1px; }
17
+ .jstree-default a .jstree-icon { background-position:-56px -19px; }
18
+ .jstree-default a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; }
19
+
20
+ /*.jstree-default.jstree-focused { background:#ffffee; }*/
21
+
22
+ .jstree-default .jstree-no-dots li,
23
+ .jstree-default .jstree-no-dots .jstree-leaf > ins { background:transparent; }
24
+ .jstree-default .jstree-no-dots .jstree-open > ins { background-position:-18px 0; }
25
+ .jstree-default .jstree-no-dots .jstree-closed > ins { background-position:0 0; }
26
+
27
+ .jstree-default .jstree-no-icons a .jstree-icon { display:none; }
28
+
29
+ .jstree-default .jstree-search { font-style:italic; }
30
+
31
+ .jstree-default .jstree-no-icons .jstree-checkbox { display:inline-block; }
32
+ .jstree-default .jstree-no-checkboxes .jstree-checkbox { display:none !important; }
33
+ .jstree-default .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; }
34
+ .jstree-default .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; }
35
+ .jstree-default .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; }
36
+ .jstree-default .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; }
37
+ .jstree-default .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; }
38
+ .jstree-default .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; }
39
+
40
+ #vakata-dragged.jstree-default ins { background:transparent !important; }
41
+ #vakata-dragged.jstree-default .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; }
42
+ #vakata-dragged.jstree-default .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; }
43
+ #jstree-marker.jstree-default { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; }
44
+
45
+ .jstree-default a.jstree-search { color:aqua; }
46
+ .jstree-default .jstree-locked a { color:silver; cursor:default; }
47
+
48
+ #vakata-contextmenu.jstree-default-context,
49
+ #vakata-contextmenu.jstree-default-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; }
50
+ #vakata-contextmenu.jstree-default-context li { }
51
+ #vakata-contextmenu.jstree-default-context a { color:black; }
52
+ #vakata-contextmenu.jstree-default-context a:hover,
53
+ #vakata-contextmenu.jstree-default-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
54
+ #vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a,
55
+ #vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; }
56
+ #vakata-contextmenu.jstree-default-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; }
57
+ #vakata-contextmenu.jstree-default-context li ul { margin-left:-4px; }
58
+
59
+ /* IE6 BEGIN */
60
+ .jstree-default li,
61
+ .jstree-default ins,
62
+ #vakata-dragged.jstree-default .jstree-invalid,
63
+ #vakata-dragged.jstree-default .jstree-ok,
64
+ #jstree-marker.jstree-default { _background-image:url("d.gif"); }
65
+ .jstree-default .jstree-open ins { _background-position:-72px 0; }
66
+ .jstree-default .jstree-closed ins { _background-position:-54px 0; }
67
+ .jstree-default .jstree-leaf ins { _background-position:-36px 0; }
68
+ .jstree-default a ins.jstree-icon { _background-position:-56px -19px; }
69
+ #vakata-contextmenu.jstree-default-context ins { _display:none; }
70
+ #vakata-contextmenu.jstree-default-context li { _zoom:1; }
71
+ .jstree-default .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; }
72
+ .jstree-default .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; }
73
+ .jstree-default .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; }
74
+ /* IE6 END */
@@ -180,6 +180,17 @@ class <%= namespace_for_class %><%= model_camelize.pluralize %>Controller < Beau
180
180
 
181
181
  redirect_to :back
182
182
  end
183
+
184
+ def treeview
185
+
186
+ end
187
+
188
+ def treeview_update
189
+ modelclass = <%= model_camelize %>
190
+ foreignkey = :<%= model %>_id
191
+
192
+ render :nothing => true, :status => (update_treeview(modelclass, foreignkey) ? 200 : 500)
193
+ end
183
194
 
184
195
  private
185
196
 
@@ -55,4 +55,43 @@ class BeautifulController < ApplicationController
55
55
  return false if string == false || string.nil? || string =~ (/(false|f|no|n|0)$/i)
56
56
  raise ArgumentError.new("invalid value for Boolean: \"#{string}\"")
57
57
  end
58
+
59
+ def update_treeview(modelclass, foreignkey)
60
+ parent_id = (params[foreignkey].to_i == 0 ? nil : params[foreignkey].to_i)
61
+ index = params[:position].to_i
62
+
63
+ elt = modelclass.find(params[:id])
64
+ elt.attributes = { foreignkey => parent_id }
65
+
66
+ if modelclass.column_names.include?("position") then
67
+ new_pos = 0
68
+ modelclass.transaction do
69
+ all_elt = modelclass.where(foreignkey => parent_id).order("position ASC").all
70
+
71
+ begin
72
+ if index == all_elt.length then
73
+ new_pos = all_elt.last.position + 1
74
+ elsif index == 0 then
75
+ new_pos = all_elt.first.position - 1
76
+ else
77
+ new_pos = all_elt[index].position
78
+
79
+ end_of_array = all_elt[index..-1]
80
+ end_of_array.each{ |g|
81
+ next if g == elt
82
+ g.position = g.position.to_i + 1
83
+ g.save
84
+
85
+ next_elt = end_of_array[end_of_array.index(g) + 1]
86
+ break if not next_elt.nil? and next_elt.position > g.position
87
+ }
88
+ end
89
+ rescue
90
+ new_pos = 0
91
+ end
92
+ end
93
+ elt.position = new_pos
94
+ end
95
+ return elt.save
96
+ end
58
97
  end
@@ -73,47 +73,65 @@ module BeautifulHelper
73
73
  type_of_column ||= :other
74
74
  case type_of_column
75
75
  when :date, :datetime then
76
- # DatePicker
76
+ dt = (type_of_column == :datetime)
77
+ interval = (dt ? (1..5) : (1..3))
78
+
79
+ # Greater than
77
80
  response += '<div class="input-prepend input-append input-' + type_of_column.to_s + '">'
78
81
  response += '<span class="add-on"><i class="icon-chevron-right"></i></span>'
79
- response += f.text_field((name_field + "_gteq").to_sym, :class => "span8 dpicker")
82
+ response += f.text_field(
83
+ (name_field + "_dp_gt").to_sym,
84
+ :value => (begin params[:q][(name_field + "_dp_gt").to_sym] rescue '' end),
85
+ :class => "span8 dpicker",
86
+ "data-id" => ("q_" + name_field + "_gteq"))
80
87
  response += '<span class="add-on"><i class="icon-calendar"></i></span>'
81
88
  response += '</div>'
82
89
 
83
- response += f.hidden_field(name_field + '_gteq(3i)', :id => ('q_' + name_field + '_gteq_3i')) # Day
84
- response += f.hidden_field(name_field + '_gteq(2i)', :id => ('q_' + name_field + '_gteq_2i')) # Mois
85
- response += f.hidden_field(name_field + '_gteq(1i)', :id => ('q_' + name_field + '_gteq_1i')) # Year
86
-
87
- if type_of_column == :datetime then
90
+ if dt then
88
91
  response += '<div class="input-prepend input-append input-' + type_of_column.to_s + '">'
89
92
  response += '<span class="add-on"><i class="icon-chevron-right"></i></span>'
90
- response += f.text_field((name_field + "_lteq").to_sym, :class => "span8 tpicker")
93
+ response += f.text_field(
94
+ (name_field + "_tp_gt").to_sym,
95
+ :value => (begin params[:q][(name_field + "_tp_gt").to_sym] rescue '' end),
96
+ :class => "span8 tpicker",
97
+ "data-id" => ("q_" + name_field + "_gteq"))
91
98
  response += '<span class="add-on"><i class="icon-time"></i></span>'
92
99
  response += '</div>'
100
+ end
93
101
 
94
- response += f.hidden_field(name_field + '_gteq(4i)', :id => ('q_' + name_field + '_gteq_4i')) # Hour
95
- response += f.hidden_field(name_field + '_gteq(5i)', :id => ('q_' + name_field + '_gteq_5i')) # Minute
102
+ for i in interval
103
+ response += f.hidden_field(name_field + "_gteq(#{i}i)",
104
+ :value => (begin params[:q][(name_field + "_gteq(#{i}i)").to_sym] rescue '' end),
105
+ :id => ('q_' + name_field + "_gteq_#{i}i"))
96
106
  end
97
107
 
108
+ # Less than
98
109
  response += '<div class="input-prepend input-append input-' + type_of_column.to_s + '">'
99
110
  response += '<span class="add-on"><i class="icon-chevron-left"></i></span>'
100
- response += f.text_field((name_field + "_lteq").to_sym, :class => "span8 dpicker")
111
+ response += f.text_field(
112
+ (name_field + "_dp_lt").to_sym,
113
+ :value => (begin params[:q][(name_field + "_dp_lt").to_sym] rescue '' end),
114
+ :class => "span8 dpicker",
115
+ "data-id" => ("q_" + name_field + "_lteq"))
101
116
  response += '<span class="add-on"><i class="icon-calendar"></i></span>'
102
117
  response += '</div>'
103
118
 
104
- response += f.hidden_field(name_field + '_lteq(3i)', :id => ('q_' + name_field + '_lteq_3i')) # Day
105
- response += f.hidden_field(name_field + '_lteq(2i)', :id => ('q_' + name_field + '_lteq_2i')) # Mois
106
- response += f.hidden_field(name_field + '_lteq(1i)', :id => ('q_' + name_field + '_lteq_1i')) # Year
107
-
108
- if type_of_column == :datetime then
119
+ if dt then
109
120
  response += '<div class="input-prepend input-append input-' + type_of_column.to_s + '">'
110
121
  response += '<span class="add-on"><i class="icon-chevron-left"></i></span>'
111
- response += f.text_field((name_field + "_lteq").to_sym, :class => "span8 tpicker")
122
+ response += f.text_field(
123
+ (name_field + "_tp_lt").to_sym,
124
+ :value => (begin params[:q][(name_field + "_tp_lt").to_sym] rescue '' end),
125
+ :class => "span8 tpicker",
126
+ "data-id" => ("q_" + name_field + "_lteq"))
112
127
  response += '<span class="add-on"><i class="icon-time"></i></span>'
113
128
  response += '</div>'
129
+ end
114
130
 
115
- response += f.hidden_field(name_field + '_lteq(4i)', :id => ('q_' + name_field + '_lteq_4i')) # Hour
116
- response += f.hidden_field(name_field + '_lteq(5i)', :id => ('q_' + name_field + '_lteq_5i')) # Minute
131
+ for i in interval
132
+ response += f.hidden_field(name_field + "_lteq(#{i}i)",
133
+ :value => (begin params[:q][(name_field + "_lteq(#{i}i)").to_sym] rescue '' end),
134
+ :id => ('q_' + name_field + "_lteq_#{i}i"))
117
135
  end
118
136
  when :boolean then
119
137
  # Specify a default value (false) in rails migration
@@ -180,4 +198,20 @@ module BeautifulHelper
180
198
  def get_belongs_to_model(column)
181
199
  return column[0..-4]
182
200
  end
201
+
202
+ def build_treeview(obj, child_relation)
203
+ out = '
204
+ <li id="treeelt_' + obj.id.to_s + '" data-id="' + obj.id.to_s + '">
205
+ <a href="#" class="nopjax">' + obj.caption + '</a>
206
+ <ul>'
207
+ ar = obj.send(child_relation.to_sym)
208
+ ar = ar.order('position') if obj.class.column_names.include?("position")
209
+ for o in ar.all
210
+ out += build_treeview(o, child_relation)
211
+ end
212
+ out += '
213
+ </ul>
214
+ </li>'
215
+ return out.html_safe
216
+ end
183
217
  end
@@ -32,3 +32,4 @@ en:
32
32
  greater_than: "Greater than"
33
33
  smaller_than: "Smaller than"
34
34
  select_columns: "Select Columns"
35
+ treeview: "Treeview"
@@ -31,4 +31,5 @@ fr:
31
31
  update_success: "%{model} a été mis(e) à jour avec succès."
32
32
  greater_than: "Plus grand que"
33
33
  smaller_than: "Plus petit que"
34
- select_columns: "Selection des colonnes"
34
+ select_columns: "Selection des colonnes"
35
+ treeview: "Arborescence"
@@ -0,0 +1,47 @@
1
+ <%#=
2
+ render :partial => "layouts/form_habtm_tag", :locals => {
3
+ :model_class => @product,
4
+ :model_name => "product",
5
+ :plural_model_name => "products",
6
+ :linked_model_name => "tag",
7
+ :plural_linked_model_name => "tags",
8
+ :namespace_bs => "admin",
9
+ :field_to_search_for_linked_model => "name",
10
+ :f => f
11
+ }
12
+ # Example to put in a _form.html.erb
13
+ %>
14
+
15
+ <div class="control-group">
16
+ <%= f.label plural_linked_model_name.to_sym, t(plural_linked_model_name.to_sym, :default => plural_linked_model_name.capitalize), :class => "control-label" %>
17
+ <div class="controls">
18
+ <ul id="<%= model_name %>_<%= linked_model_name %>_ids" name="<%= model_name %>[<%= linked_model_name %>_ids][]">
19
+ <% for elt in model_class.send(plural_linked_model_name) %>
20
+ <li data-value="<%= elt.id %>"><%= elt.caption %></li>
21
+ <% end %>
22
+ </ul>
23
+ </div>
24
+ </div>
25
+ <script type="text/javascript">
26
+ $('#<%= model_name %>_<%= linked_model_name %>_ids').tagit({
27
+ tagSource : function( request, response ) {
28
+ <% path_namespace = '/' + namespace_bs if not namespace_bs.blank? %>
29
+ $.ajax({
30
+ url: "<%= path_namespace %>/<%= plural_linked_model_name %>/search_and_filter.json",
31
+ type: "POST",
32
+ data: {
33
+ "q[<%= field_to_search_for_linked_model %>_cont]" : request.term
34
+ },
35
+ dataType: "json",
36
+ success: function( data ) {
37
+ response( $.map( data, function( item ) {
38
+ return { label: String(item.<%= field_to_search_for_linked_model %>), value: item.id };
39
+ }));
40
+ }
41
+ });
42
+ },
43
+ triggerKeys:['enter', 'comma', 'tab'],
44
+ select : true,
45
+ allowNewTags : false
46
+ });
47
+ </script>