beautiful_scaffold 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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>