puffer 0.0.23 → 0.0.24
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +55 -53
- data/VERSION +1 -1
- data/app/assets/javascripts/puffer/application.js +6 -3
- data/app/assets/javascripts/puffer/paginator.js +223 -0
- data/app/assets/javascripts/puffer/puffer.js +12 -0
- data/app/assets/javascripts/puffer/rails.js +1 -0
- data/app/assets/javascripts/puffer/{right-autocompleter.js → right-autocompleter-src.js} +45 -41
- data/app/assets/javascripts/puffer/{right-calendar.js → right-calendar-src.js} +53 -50
- data/app/assets/javascripts/puffer/right-dialog-src.js +768 -0
- data/app/assets/javascripts/puffer/right-slider-src.js +507 -0
- data/app/assets/javascripts/puffer/{right.js → right-src.js} +1000 -230
- data/app/assets/stylesheets/puffer/application.css +2 -0
- data/app/assets/stylesheets/puffer/paginator.css +33 -0
- data/app/assets/stylesheets/puffer/right.css +4 -0
- data/app/components/base/form.html.erb +15 -0
- data/app/components/base_component.rb +15 -0
- data/app/components/boolean/form.html.erb +3 -0
- data/app/components/boolean/index.html.erb +3 -0
- data/app/components/boolean_component.rb +13 -0
- data/app/components/date_time/form.html.erb +5 -0
- data/app/components/date_time_component.rb +12 -0
- data/app/components/file/form.html.erb +5 -0
- data/app/components/file_component.rb +3 -0
- data/app/components/hidden/form.html.erb +1 -0
- data/app/components/hidden_component.rb +3 -0
- data/app/components/password/form.html.erb +5 -0
- data/app/components/password_component.rb +7 -0
- data/app/components/references_many/form.html.erb +1 -0
- data/app/components/references_many_component.rb +7 -0
- data/app/components/references_one/choose.html.erb +9 -0
- data/app/components/references_one/form.html.erb +28 -0
- data/app/components/references_one_component.rb +12 -0
- data/app/components/select/form.html.erb +5 -0
- data/app/components/select_component.rb +15 -0
- data/app/components/string/form.html.erb +5 -0
- data/app/components/string_component.rb +3 -0
- data/app/components/text/form.html.erb +5 -0
- data/app/components/text_component.rb +3 -0
- data/app/controllers/puffer/base.rb +4 -0
- data/app/views/puffer/base/_form.html.erb +0 -1
- data/app/views/puffer/base/_table.html.erb +25 -0
- data/app/views/puffer/base/index.html.erb +14 -28
- data/app/views/puffer/tree_base/_record.html.erb +1 -1
- data/lib/generators/puffer/component/USAGE +12 -0
- data/lib/generators/puffer/component/component_generator.rb +19 -0
- data/lib/generators/puffer/component/templates/component.rb +15 -0
- data/lib/generators/puffer/component/templates/component_spec.rb +19 -0
- data/lib/puffer/component.rb +141 -0
- data/lib/puffer/controller/dsl.rb +25 -12
- data/lib/puffer/engine.rb +5 -0
- data/lib/puffer/extensions/controller.rb +11 -9
- data/lib/puffer/extensions/form.rb +2 -1
- data/lib/puffer/extensions/mapper.rb +2 -0
- data/lib/puffer/field.rb +30 -19
- data/lib/puffer/field_set.rb +17 -2
- data/lib/puffer.rb +25 -8
- data/puffer.gemspec +59 -28
- data/spec/app/components/base_component_spec.rb +19 -0
- data/spec/app/components/boolean_component_spec.rb +36 -0
- data/spec/app/components/date_time_component_spec.rb +26 -0
- data/spec/app/components/file_component_spec.rb +25 -0
- data/spec/app/components/hidden_component_spec.rb +24 -0
- data/spec/app/components/password_component_spec.rb +37 -0
- data/spec/app/components/references_many_component_spec.rb +19 -0
- data/spec/app/components/references_one_component_spec.rb +19 -0
- data/spec/app/components/select_component_spec.rb +30 -0
- data/spec/app/components/string_component_spec.rb +25 -0
- data/spec/app/components/text_component_spec.rb +25 -0
- data/spec/dummy/app/controllers/admin/categories_controller.rb +3 -3
- data/spec/dummy/app/controllers/admin/posts_controller.rb +3 -0
- data/spec/dummy/app/controllers/{puffer → admin}/sessions_controller.rb +1 -1
- data/spec/dummy/app/controllers/admin/users_controller.rb +2 -2
- data/spec/dummy/app/models/post.rb +4 -0
- data/spec/dummy/db/migrate/20100930132656_create_posts.rb +2 -0
- data/spec/dummy/db/migrate/20100930132726_create_categories.rb +1 -0
- data/spec/dummy/db/schema.rb +3 -0
- data/spec/dummy/db/seeds.rb +6 -1
- data/spec/fabricators/categories_fabricator.rb +1 -0
- data/spec/fabricators/posts_fabricator.rb +1 -0
- data/spec/lib/component_spec.rb +7 -0
- data/spec/lib/fields_spec.rb +0 -4
- metadata +85 -56
- data/app/views/puffer/base/associated/_many.html.erb +0 -56
- data/app/views/puffer/base/associated/many.rjs +0 -1
- data/app/views/puffer/base/associated/one.js.erb +0 -13
- data/app/views/puffer/base/association/_many.html.erb +0 -7
- data/lib/puffer/controller/generated.rb +0 -65
- data/lib/puffer/customs.rb +0 -64
- data/lib/puffer/inputs/association.rb +0 -38
- data/lib/puffer/inputs/base.rb +0 -51
- data/lib/puffer/inputs/boolean.rb +0 -19
- data/lib/puffer/inputs/collection_association.rb +0 -11
- data/lib/puffer/inputs/date_time.rb +0 -16
- data/lib/puffer/inputs/file.rb +0 -11
- data/lib/puffer/inputs/hidden.rb +0 -15
- data/lib/puffer/inputs/password.rb +0 -11
- data/lib/puffer/inputs/select.rb +0 -19
- data/lib/puffer/inputs/text.rb +0 -11
@@ -0,0 +1,33 @@
|
|
1
|
+
.rui-paginator {
|
2
|
+
margin: 10px 0;
|
3
|
+
}
|
4
|
+
|
5
|
+
.rui-paginator .rui-slider {
|
6
|
+
width: 100%;
|
7
|
+
}
|
8
|
+
|
9
|
+
.rui-paginator .rui-paginator-pages-wrapper {
|
10
|
+
width: 100%;
|
11
|
+
overflow: hidden;
|
12
|
+
}
|
13
|
+
|
14
|
+
.rui-paginator .rui-paginator-pages {
|
15
|
+
display: inline-block;
|
16
|
+
white-space: nowrap;
|
17
|
+
}
|
18
|
+
|
19
|
+
.rui-paginator .rui-paginator-pages li {
|
20
|
+
display: inline-block;
|
21
|
+
width: 40px;
|
22
|
+
height: 20px;
|
23
|
+
text-align: center;
|
24
|
+
}
|
25
|
+
|
26
|
+
.rui-paginator .rui-paginator-pages li a, .rui-paginator .rui-paginator-pages li span {
|
27
|
+
line-height: 20px;
|
28
|
+
padding: 0 5px;
|
29
|
+
}
|
30
|
+
|
31
|
+
.rui-paginator .rui-paginator-pages li.current span {
|
32
|
+
background: #ccc;
|
33
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% content_for :label do %>
|
2
|
+
<%= opts[:form].label field %>
|
3
|
+
<% end unless content_for? :label %>
|
4
|
+
|
5
|
+
<% content_for :error do %>
|
6
|
+
<%= opts[:form].object.errors[field.name.to_sym].first %>
|
7
|
+
<% end unless content_for? :error %>
|
8
|
+
|
9
|
+
<div class="label">
|
10
|
+
<%= yield :label %>
|
11
|
+
<div class="field_error">
|
12
|
+
<%= yield :error %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<%= yield :input %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= opts[:form].hidden_field field, field.input_options %>
|
@@ -0,0 +1 @@
|
|
1
|
+
# I'm form
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<%= render :layout => '../views/puffer/base/table', :locals => { :table_fields => field.children, :controller => controller.parent_controller } do |record| %>
|
2
|
+
<% link_to t('.choose'), '#' %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<div id="paginator"></div>
|
6
|
+
|
7
|
+
<%= javascript_tag do %>
|
8
|
+
new Paginator({total: <%= records.num_pages %>, current: <%= params[:page] || 1 %>, link: {'data-dialog-uri': '<%= event_path(:choose, :page => '%{page}') %>'}}).insertTo('paginator', 'instead');
|
9
|
+
<% end %>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% content_for :input do %>
|
2
|
+
<% value = [
|
3
|
+
swallow_nil{opts[:form].object.send(field.name)[field.reflection.primary_key_column.name.to_sym]},
|
4
|
+
swallow_nil{opts[:form].object.send(field.name).to_title}
|
5
|
+
].compact.join(' - ')
|
6
|
+
%>
|
7
|
+
|
8
|
+
<div class="association">
|
9
|
+
<%= text_field_tag field, value, field.input_options.merge(
|
10
|
+
:autocomplete => :off,
|
11
|
+
:disabled => (true if opts[:form].object.send(field.name)),
|
12
|
+
'data-autocompleter' => "{url: '#{event_path :choose}', onDone: association_done}"
|
13
|
+
) %>
|
14
|
+
<div class="association_clear">×</div>
|
15
|
+
<%= opts[:form].hidden_field field.reflection.foreign_key %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<% clean_content_for :input do %>
|
20
|
+
<% link_to "Choose", '#', :"data-dialog-uri" => event_path(:choose) %>
|
21
|
+
<% end %>
|
22
|
+
|
23
|
+
<% content_for :error do %>
|
24
|
+
<%= opts[:form].object.errors[field.reflection.foreign_key.to_sym].first ||
|
25
|
+
opts[:form].object.errors[field.name.to_sym].first.presence %>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<%= render :file => 'base/form' %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class ReferencesOneComponent < Puffer::Component::Base
|
2
|
+
|
3
|
+
def form
|
4
|
+
render
|
5
|
+
end
|
6
|
+
|
7
|
+
def choose
|
8
|
+
@records = field.reflection.klass.includes(field.children.includes).where(field.children.searches(params[:search])).page(params[:page])
|
9
|
+
render
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class SelectComponent < BaseComponent
|
2
|
+
|
3
|
+
def form
|
4
|
+
@options = case field.options[:select]
|
5
|
+
when Symbol then
|
6
|
+
parent_controller.send field.options[:select]
|
7
|
+
when Proc then
|
8
|
+
field.options[:select].bind(self).call
|
9
|
+
else
|
10
|
+
field.options[:select]
|
11
|
+
end
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<table class="list_table">
|
2
|
+
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<% table_fields.each do |field| -%>
|
6
|
+
<th><%= render_head field %></th>
|
7
|
+
<% end -%>
|
8
|
+
<th class="actions">Actions</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
|
12
|
+
<tbody>
|
13
|
+
<% records.each do |record| -%>
|
14
|
+
<tr>
|
15
|
+
<% table_fields.each do |field| -%>
|
16
|
+
<td><%= field.render controller, :index, :record => record %></td>
|
17
|
+
<% end -%>
|
18
|
+
<td class="actions">
|
19
|
+
<%= yield record %>
|
20
|
+
</td>
|
21
|
+
</tr>
|
22
|
+
<% end -%>
|
23
|
+
</tbody>
|
24
|
+
|
25
|
+
</table>
|
@@ -1,34 +1,20 @@
|
|
1
1
|
<% @title = resource.human %>
|
2
2
|
<h1><%= @title %></h1>
|
3
|
-
|
3
|
+
|
4
|
+
|
4
5
|
<% if records.present? %>
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
<tr>
|
17
|
-
<% index_fields.each do |field| -%>
|
18
|
-
<td><%= render_field field, record %></td>
|
19
|
-
<% end -%>
|
20
|
-
<td class="actions">
|
21
|
-
<%= link_to 'edit', resource.edit_path(record) if update_fields.present? %>
|
22
|
-
<% controller._members.each do |member| %>
|
23
|
-
<%= link_to member.label, resource.member_path(record, :action => member.action) if member.display? %>
|
24
|
-
<% end %>
|
25
|
-
<%= link_to 'destroy', resource.member_path(record), :confirm => "Are you sure?", :method => :delete if configuration.destroy %>
|
26
|
-
</td>
|
27
|
-
</tr>
|
28
|
-
<% end -%>
|
29
|
-
</tbody>
|
30
|
-
</table>
|
6
|
+
<div class="rui-paginator" data-paginator="{total: <%= records.num_pages %>, current: <%= params[:page] || 1 %>, link: {href: '<%= resource.collection_path(:page => '%{page}') %>'}}"></div>
|
7
|
+
|
8
|
+
<%= render :layout => 'table', :locals => {:table_fields => index_fields} do |record| %>
|
9
|
+
<%= link_to 'edit', resource.edit_path(record) if update_fields.present? %>
|
10
|
+
<% _members.each do |member| %>
|
11
|
+
<%= link_to member.label, resource.member_path(record, :action => member.action) if member.display? %>
|
12
|
+
<% end %>
|
13
|
+
<%= link_to 'destroy', resource.member_path(record), :confirm => "Are you sure?", :method => :delete if configuration.destroy %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<div class="rui-paginator" data-paginator="{total: <%= records.num_pages %>, current: <%= params[:page] || 1 %>, link: {href: '<%= resource.collection_path(:page => '%{page}') %>'}}"></div>
|
31
17
|
<% else %>
|
32
18
|
<p>Sorry, but there is no records in <%= resource.human %></p>
|
33
19
|
<% end %>
|
34
|
-
|
20
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Description:
|
2
|
+
Create puffer component
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate puffer:component password
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
app/components/password_component.rb
|
9
|
+
app/components/password/index.html.erb
|
10
|
+
app/components/password/form.html.erb
|
11
|
+
app/components/password/filter.html.erb
|
12
|
+
spec/app/components/password_component_spec.rb
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Puffer::ComponentGenerator < Rails::Generators::NamedBase
|
2
|
+
source_root File.expand_path('../templates', __FILE__)
|
3
|
+
|
4
|
+
def generate_component
|
5
|
+
@name = name.underscore
|
6
|
+
|
7
|
+
template 'component.rb', "app/components/#{@name}_component.rb"
|
8
|
+
template 'component_spec.rb', "spec/app/components/#{@name}_component_spec.rb"
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate_views
|
12
|
+
@name = name.underscore
|
13
|
+
|
14
|
+
create_file "app/components/#{@name}/index.html.erb", "# I'm index"
|
15
|
+
create_file "app/components/#{@name}/form.html.erb", "# I'm form"
|
16
|
+
create_file "app/components/#{@name}/filter.html.erb", "# I'm filter"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe <%= @name.camelize %>Component do
|
4
|
+
|
5
|
+
include RSpec::Rails::RequestExampleGroup
|
6
|
+
|
7
|
+
context 'index' do
|
8
|
+
|
9
|
+
it 'should render index component'
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'form' do
|
14
|
+
|
15
|
+
it 'should render form component'
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Puffer
|
2
|
+
module Component
|
3
|
+
|
4
|
+
# <tt>Puffer::Component::Base</tt> is a base component low-level for puffer
|
5
|
+
# fields. It provides all the base functionality for rendering visual fields
|
6
|
+
# components.
|
7
|
+
# Every component belongs to field by field's type
|
8
|
+
# Every component should have some basic actions, based on parent controller
|
9
|
+
# fieldsets, so they can be fallbacked as fieldsets.
|
10
|
+
#
|
11
|
+
# Also, every component can have additional actions for ajax requests
|
12
|
+
# handling and component state changing
|
13
|
+
class Base < AbstractController::Base
|
14
|
+
|
15
|
+
module ComponentHelper
|
16
|
+
def component_wrap name = :span, options = {}, &block
|
17
|
+
content_tag name, options.merge(:id => component_id), &block
|
18
|
+
end
|
19
|
+
|
20
|
+
def clean_content_for name, *args, &block
|
21
|
+
@view_flow.set name, ''
|
22
|
+
content_for name, *args, &block
|
23
|
+
end
|
24
|
+
|
25
|
+
def paginate(scope, options = {}, &block)
|
26
|
+
paginator = Kaminari::Helpers::Paginator.new parent_controller.view_context, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :param_name => Kaminari.config.param_name, :remote => false)
|
27
|
+
paginator.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module SingletonMethods
|
32
|
+
def render_component parent_controller, field, context, *args
|
33
|
+
klass = "#{field.type}_component".camelize.constantize rescue StringComponent
|
34
|
+
component = klass.new field
|
35
|
+
component.process parent_controller, context, *args
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module ClassMethods
|
40
|
+
def controller_path
|
41
|
+
@controller_path ||= name.sub(/Component$/, '').underscore unless anonymous?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
abstract!
|
46
|
+
|
47
|
+
include AbstractController::Rendering
|
48
|
+
include AbstractController::Helpers
|
49
|
+
include AbstractController::Translation
|
50
|
+
include AbstractController::Logger
|
51
|
+
include AbstractController::Layouts
|
52
|
+
|
53
|
+
include ActionController::RequestForgeryProtection
|
54
|
+
include ActionController::UrlFor
|
55
|
+
include Rails.application.routes.url_helpers
|
56
|
+
|
57
|
+
extend SingletonMethods
|
58
|
+
extend ClassMethods
|
59
|
+
|
60
|
+
helper ComponentHelper, PufferHelper
|
61
|
+
|
62
|
+
attr_accessor :parent_controller, :field, :opts, :identifer
|
63
|
+
delegate :env, :request, :params, :session, :resource, :_members, :_collections, :to => :parent_controller
|
64
|
+
helper_method :params, :session, :resource, :_members, :_collections, :parent_controller, :field, :opts, :identifer, :component_id, :event_url, :event_path, :record, :records
|
65
|
+
|
66
|
+
def initialize field
|
67
|
+
super()
|
68
|
+
@field = field
|
69
|
+
end
|
70
|
+
|
71
|
+
def process parent_controller, context, *args
|
72
|
+
@parent_controller = parent_controller
|
73
|
+
@identifer = params[:identifer] || generate_identifer
|
74
|
+
super context, *args
|
75
|
+
end
|
76
|
+
|
77
|
+
def send_action method_name, *args
|
78
|
+
@opts = args.extract_options!
|
79
|
+
send method_name, *args
|
80
|
+
end
|
81
|
+
|
82
|
+
def render *args, &block
|
83
|
+
options = _normalize_render(*args, &block)
|
84
|
+
options[:template] = fallback_action(options[:template])
|
85
|
+
render_to_body(options).html_safe
|
86
|
+
end
|
87
|
+
|
88
|
+
def replace *args
|
89
|
+
javascript_wrap :replace, render(*args)
|
90
|
+
end
|
91
|
+
|
92
|
+
def javascript_wrap type, html
|
93
|
+
case type
|
94
|
+
when :replace then
|
95
|
+
"$('#{component_id}').replace('#{view_context.escape_javascript html}')".html_safe
|
96
|
+
else
|
97
|
+
html
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def method_for_action action_name
|
102
|
+
fallback_action(action_name) || super
|
103
|
+
end
|
104
|
+
|
105
|
+
def fallback_action action_name
|
106
|
+
((parent_controller._fieldset_fallbacks[action_name] || []).detect {|name| action_method? name.to_s} || action_name).to_s
|
107
|
+
end
|
108
|
+
|
109
|
+
def event_url name, options = {}
|
110
|
+
resource.collection_url :event, (options || {}).merge(event_options(name))
|
111
|
+
end
|
112
|
+
|
113
|
+
def event_path name, options = {}
|
114
|
+
resource.collection_path :event, (options || {}).merge(event_options(name))
|
115
|
+
end
|
116
|
+
|
117
|
+
def event_options name
|
118
|
+
{:event => name, :field => field.to_s, :fieldset => field.field_set.name, :identifer => identifer}
|
119
|
+
end
|
120
|
+
|
121
|
+
def record
|
122
|
+
@record || instance_variable_get("@#{resource.model_name}")
|
123
|
+
end
|
124
|
+
|
125
|
+
def records
|
126
|
+
@records || instance_variable_get("@#{resource.model_name.pluralize}")
|
127
|
+
end
|
128
|
+
|
129
|
+
def component_id
|
130
|
+
@component_id ||= "component_#{identifer}"
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def generate_identifer
|
136
|
+
Digest::MD5.hexdigest(SecureRandom.uuid)
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|