activate-admin 0.0.1
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/.components +9 -0
- data/.gitignore +29 -0
- data/Gemfile +57 -0
- data/Gemfile.lock +184 -0
- data/Procfile +1 -0
- data/README.md +54 -0
- data/Rakefile +6 -0
- data/activate-admin.gemspec +19 -0
- data/admin/app.rb +160 -0
- data/admin/assets/fonts/FontAwesome.otf +0 -0
- data/admin/assets/fonts/fontawesome-webfont.eot +0 -0
- data/admin/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/admin/assets/fonts/fontawesome-webfont.woff +0 -0
- data/admin/assets/javascripts/bootstrap-wysihtml5-0.0.2.js +321 -0
- data/admin/assets/javascripts/bootstrap.min.js +6 -0
- data/admin/assets/javascripts/jquery-1.9.1.min.js +5 -0
- data/admin/assets/javascripts/jquery-migrate-1.1.1.js +511 -0
- data/admin/assets/javascripts/jquery-ujs.js +95 -0
- data/admin/assets/javascripts/jquery.ba-bbq.min.js +18 -0
- data/admin/assets/javascripts/wysihtml5-0.3.0.js +9530 -0
- data/admin/assets/stylesheets/bootstrap-responsive.min.css +9 -0
- data/admin/assets/stylesheets/bootstrap-wysihtml5-0.0.2.css +44 -0
- data/admin/assets/stylesheets/bootstrap.min.css +9 -0
- data/admin/assets/stylesheets/font-awesome.min.css +34 -0
- data/admin/helpers/helpers.rb +19 -0
- data/admin/views/build.erb +111 -0
- data/admin/views/home.erb +24 -0
- data/admin/views/index.erb +108 -0
- data/admin/views/layouts/application.erb +75 -0
- data/admin/views/login_page.erb +31 -0
- data/config/apps.rb +5 -0
- data/config/boot.rb +26 -0
- data/config/mongoid.yml +14 -0
- data/config/navigation.rb +3 -0
- data/config.ru +9 -0
- data/lib/activate-admin/version.rb +3 -0
- data/lib/activate-admin.rb +6 -0
- data/lib/assetpack_patch.rb +18 -0
- data/lib/date_formats.rb +11 -0
- data/lib/datetime_helpers.rb +32 -0
- data/lib/dragonfly.rb +30 -0
- data/lib/kaminari/_first_page.html.erb +12 -0
- data/lib/kaminari/_gap.html.erb +8 -0
- data/lib/kaminari/_last_page.html.erb +13 -0
- data/lib/kaminari/_next_page.html.erb +13 -0
- data/lib/kaminari/_page.html.erb +12 -0
- data/lib/kaminari/_paginator.html.erb +25 -0
- data/lib/kaminari/_prev_page.html.erb +13 -0
- data/lib/kaminari.rb +51 -0
- data/lib/param_helpers.rb +41 -0
- metadata +113 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
|
2
|
+
<div class="page-header">
|
3
|
+
<h1><%=human_model_name(model).pluralize%></h1>
|
4
|
+
<a href="<%=url_for(:new, :model => model.to_s)%>" class="btn btn-primary"><i class="icon-pencil"></i> New</a>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<div class="row-fluid">
|
8
|
+
<div class="span6">
|
9
|
+
<p>
|
10
|
+
<%= page_entries_info @resources %>
|
11
|
+
<a class="btn" title="Download results as csv" target="_blank" href="<%=url_for(:index, params.merge(:model => model.to_s, :format => :csv))%>"><i class="icon-download-alt"></i></a>
|
12
|
+
</p>
|
13
|
+
</div>
|
14
|
+
<div class="span6" style="text-align: right">
|
15
|
+
<form style="display: inline" class="form-search">
|
16
|
+
<%= search_field_tag :q, :class => 'input-medium search-query', :value => @q %>
|
17
|
+
<% @f.each { |k,v| %>
|
18
|
+
<%= hidden_field_tag :"f[#{k}]", :value => v %>
|
19
|
+
<% } if @f %>
|
20
|
+
<%= hidden_field_tag :o, :value => @o %>
|
21
|
+
<%= hidden_field_tag :d, :value => @d %>
|
22
|
+
<button type="submit" name="qf" value="search" class="btn">Search</button>
|
23
|
+
<button type="submit" name="qf" value="eval" class="btn">Eval</button>
|
24
|
+
</form>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<style>
|
29
|
+
th[data-fieldname] a { color:black; text-decoration: none !important }
|
30
|
+
a.fn, a.odn { visibility:hidden; }
|
31
|
+
</style>
|
32
|
+
<script>
|
33
|
+
$(function() {
|
34
|
+
var params = $.deparam.querystring();
|
35
|
+
$('th').hover(function() { $('a.fn, a.odn', this).css('visibility','visible') }, function() { $('a.fn, a.odn', this).css('visibility','hidden') });
|
36
|
+
$('a.od').click(function() {
|
37
|
+
params['o'] = $(this).closest('th').data('fieldname')
|
38
|
+
params['d'] = params['d'] == 'asc' ? 'desc' : 'asc'
|
39
|
+
location.assign(location.pathname+'?'+$.param(params));
|
40
|
+
});
|
41
|
+
$('a.f').click(function() {
|
42
|
+
console.log(this);
|
43
|
+
if (!params['f'])
|
44
|
+
params['f'] = {}
|
45
|
+
params['f'][$(this).closest('th').data('fieldname')] = prompt('Search for:');
|
46
|
+
location.assign(location.pathname+'?'+$.param(params));
|
47
|
+
});
|
48
|
+
});
|
49
|
+
</script>
|
50
|
+
<table class="table table-striped table-condensed">
|
51
|
+
<thead>
|
52
|
+
<tr>
|
53
|
+
<% model.fields_for_index.each { |fieldname| %>
|
54
|
+
<th data-fieldname="<%=fieldname%>">
|
55
|
+
<%= model.human_attribute_name(fieldname) %>
|
56
|
+
|
57
|
+
<% if @o == fieldname.to_sym %>
|
58
|
+
<a title="Ordered by <%=fieldname%>; click to reverse" href="javascript:;" class="od">
|
59
|
+
<% if @d == :asc %>
|
60
|
+
<i class="icon-caret-down"></i>
|
61
|
+
<% elsif @d == :desc %>
|
62
|
+
<i class="icon-caret-up"></i>
|
63
|
+
<% end %>
|
64
|
+
</a>
|
65
|
+
<% else %>
|
66
|
+
<a title="Order by <%=fieldname%>" href="javascript:;" class="od odn">
|
67
|
+
<i class="icon-caret-right"></i>
|
68
|
+
</a>
|
69
|
+
<% end %>
|
70
|
+
|
71
|
+
<% if @f and @f[fieldname] %>
|
72
|
+
<a title="Searching for '<%=@f[fieldname]%>'; click to search again" href="javascript:;" class="f"><i class="icon-search"></i></a>
|
73
|
+
<% else %>
|
74
|
+
<a title="Search in <%=fieldname%>" href="javascript:;" class="f fn"><i class="icon-search"></i></a>
|
75
|
+
<% end %>
|
76
|
+
</th>
|
77
|
+
<% } %>
|
78
|
+
<th style="width: 70px"></th>
|
79
|
+
<th style="width: 88px"></th>
|
80
|
+
</tr>
|
81
|
+
</thead>
|
82
|
+
<tbody>
|
83
|
+
<% @resources.each { |resource| %>
|
84
|
+
<tr>
|
85
|
+
<% model.fields_for_index.each { |fieldname| %>
|
86
|
+
<td>
|
87
|
+
<% if fieldname.match(/_id/) && Object.const_defined?(fieldname.to_s.gsub('_id','').camelize) && resource.send(fieldname) %>
|
88
|
+
<a target="_blank" href="<%=url_for(:edit, :model => fieldname.to_s.gsub('_id','').camelize.constantize, :id => resource.send(fieldname))%>"><%= fieldname.to_s.gsub('_id','').camelize.constantize.find(resource.send(fieldname)).lookup %></a>
|
89
|
+
<% elsif fieldname.match(/_url/) %>
|
90
|
+
<a href="<%=resource.send(fieldname)%>"><%=resource.send(fieldname)%></a>
|
91
|
+
<% else %>
|
92
|
+
<%= truncate(strip_tags(resource.send(fieldname).to_s), :length => 30) %>
|
93
|
+
<% end %>
|
94
|
+
</td>
|
95
|
+
<% } %>
|
96
|
+
<td>
|
97
|
+
<a href="<%=url_for(:edit, :model => model.to_s, :id => resource.id)%>" class="btn"><i class="icon-edit"></i> Edit</a>
|
98
|
+
</td>
|
99
|
+
<td>
|
100
|
+
<a class="btn btn-danger" data-confirm="Are you sure you want to delete this <%=human_model_name(model).downcase%>?" href="<%=url_for(:destroy, :model => model.to_s, :id => resource.id)%>"><i class="icon-trash"></i> Delete</a>
|
101
|
+
</td>
|
102
|
+
</tr>
|
103
|
+
<% } %>
|
104
|
+
</tbody>
|
105
|
+
</table>
|
106
|
+
|
107
|
+
<%= paginate @resources %>
|
108
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
|
8
|
+
<title>ActivateAdmin</title>
|
9
|
+
|
10
|
+
<%= (css :app).html_safe %>
|
11
|
+
<%= (js :app).html_safe %>
|
12
|
+
|
13
|
+
<style>
|
14
|
+
body { padding: 60px 0; }
|
15
|
+
.page-header { margin-top: 0; padding-bottom: 10px }
|
16
|
+
.page-header h1 { display: inline }
|
17
|
+
.page-header a { margin-left: 10px; position: relative; top: -6px }
|
18
|
+
</style>
|
19
|
+
|
20
|
+
</head>
|
21
|
+
<body>
|
22
|
+
<!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
|
23
|
+
|
24
|
+
<div class="navbar navbar-fixed-top">
|
25
|
+
<div class="navbar-inner">
|
26
|
+
<div class="container-fluid">
|
27
|
+
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
28
|
+
<span class="icon-bar"></span>
|
29
|
+
<span class="icon-bar"></span>
|
30
|
+
<span class="icon-bar"></span>
|
31
|
+
</a>
|
32
|
+
<a style="font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;" class="brand" href="<%=url_for(:home)%>">ActivateAdmin</a>
|
33
|
+
<% if current_account %>
|
34
|
+
<div class="nav-collapse">
|
35
|
+
<%= render_navigation :items => models.map { |model|
|
36
|
+
{:key => :left, :name => human_model_name(model).pluralize, :url => url_for(:index, :model => model.to_s), :options => {:container_class => 'nav'}}
|
37
|
+
}
|
38
|
+
%>
|
39
|
+
<ul class="nav pull-right">
|
40
|
+
<li><a href="<%=url_for(:logout)%>">Sign out</a></li>
|
41
|
+
</ul>
|
42
|
+
</div><!--/.nav-collapse -->
|
43
|
+
<% end %>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
|
48
|
+
<div class="container-fluid">
|
49
|
+
<div class="row-fluid">
|
50
|
+
<div class="span12">
|
51
|
+
|
52
|
+
<div style="z-index: 1040; width: 40%; margin-left: -20%; left: 50%; position: absolute; margin-top: -40px">
|
53
|
+
<% {:error => 'alert-error', :warning => '', :notice => 'alert-info'}.each { |k,v| %>
|
54
|
+
<% if flash[k] %>
|
55
|
+
<div class="fade in alert <%=v%>" style="box-shadow: 1px 1px 3px #ccc;">
|
56
|
+
<button data-dismiss="alert" class="close" type="button">×</button>
|
57
|
+
<%= flash[k].html_safe %>
|
58
|
+
</div>
|
59
|
+
<% end %>
|
60
|
+
<% } %>
|
61
|
+
</div>
|
62
|
+
<script>
|
63
|
+
$(function() {
|
64
|
+
$(".alert").alert()
|
65
|
+
window.setTimeout(function() { $(".alert").alert('close'); }, 3000);
|
66
|
+
});
|
67
|
+
</script>
|
68
|
+
|
69
|
+
<%= yield %>
|
70
|
+
</div>
|
71
|
+
</div>
|
72
|
+
</div>
|
73
|
+
|
74
|
+
</body>
|
75
|
+
</html>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
<% form_tag url_for(:login), :class => 'form-horizontal' do %>
|
3
|
+
|
4
|
+
<div class="control-group">
|
5
|
+
<label class="control-label">Email</label>
|
6
|
+
<div class="controls">
|
7
|
+
<%= text_field_tag :email, :value => params[:email] %>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class="control-group">
|
12
|
+
<label class="control-label">Password</label>
|
13
|
+
<div class="controls">
|
14
|
+
<%= password_field_tag :password, :value => params[:password] %>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<% if Padrino.env == :development %>
|
19
|
+
<div class="control-group">
|
20
|
+
<label class="control-label">Bypass login?</label>
|
21
|
+
<div class="controls">
|
22
|
+
<%= check_box_tag :bypass %>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
<div class="form-actions">
|
28
|
+
<button class="btn btn-primary" type="submit">Sign in</button>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<% end %>
|
data/config/apps.rb
ADDED
data/config/boot.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Defines our constants
|
2
|
+
PADRINO_ENV = ENV['PADRINO_ENV'] ||= ENV['RACK_ENV'] ||= 'development' unless defined?(PADRINO_ENV)
|
3
|
+
PADRINO_ROOT = File.expand_path('../..', __FILE__) unless defined?(PADRINO_ROOT)
|
4
|
+
|
5
|
+
# Load our dependencies
|
6
|
+
require 'rubygems' unless defined?(Gem)
|
7
|
+
require 'bundler/setup'
|
8
|
+
require 'pp'
|
9
|
+
require 'csv'
|
10
|
+
require 'backtrace_shortener'
|
11
|
+
BacktraceShortener.monkey_patch_the_exception_class!
|
12
|
+
BacktraceShortener.filters.unshift(Proc.new do |backtrace|
|
13
|
+
backtrace.reject { |line| line.include?(Gem.dir) }
|
14
|
+
end)
|
15
|
+
Bundler.require(:default, PADRINO_ENV)
|
16
|
+
|
17
|
+
Padrino.before_load do
|
18
|
+
end
|
19
|
+
|
20
|
+
Padrino.after_load do
|
21
|
+
end
|
22
|
+
|
23
|
+
Padrino.load!
|
24
|
+
|
25
|
+
Mongoid.load!("#{ActivateAdmin.root}/config/mongoid.yml")
|
26
|
+
Mongoid.raise_not_found_error = false
|
data/config/mongoid.yml
ADDED
data/config.ru
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class Sinatra::AssetPack::Package
|
2
|
+
|
3
|
+
def production_path
|
4
|
+
app_root = Padrino.mounted_apps.find{ |app| app.name == @assets.app.name }.uri_root
|
5
|
+
asset_path = add_cache_buster( @path, *files )
|
6
|
+
app_root == '/' ? asset_path : ( app_root + asset_path )
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_development_html(options={})
|
10
|
+
app_root = Padrino.mounted_apps.find{ |app| app.name == @assets.app.name }.uri_root
|
11
|
+
path_prefix = app_root == '/' ? '' : app_root
|
12
|
+
paths_and_files.map { |path, file|
|
13
|
+
path = add_cache_buster(path_prefix + path, file) # app.css => app.829378.css
|
14
|
+
link_tag(path, options)
|
15
|
+
}.join("\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/date_formats.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'active_support/core_ext/integer/inflections'
|
2
|
+
|
3
|
+
Time::DATE_FORMATS.merge!(
|
4
|
+
:default => lambda { |time| time.to_s(:date) + ', ' + time.to_s(:time) },
|
5
|
+
:date => lambda { |time| time.to_date.to_s },
|
6
|
+
:time => lambda { |time| time.strftime("#{(t = time.hour%12) == 0 ? 12 : t}:%M#{time.strftime('%p').downcase}") }
|
7
|
+
)
|
8
|
+
|
9
|
+
Date::DATE_FORMATS.merge!(
|
10
|
+
:default => lambda { |date| date.strftime("%a #{date.day.ordinalize} %b %Y") }
|
11
|
+
)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module DatetimeHelpers
|
2
|
+
|
3
|
+
def datetime_select_tags(name, options)
|
4
|
+
v = options[:value] || Time.zone.now
|
5
|
+
c = options[:class]
|
6
|
+
id = options[:id]
|
7
|
+
s = []
|
8
|
+
s << "<style>.datetime select { width: auto }</style>"
|
9
|
+
s << "<span id=\"#{id if id}\" class=\"datetime #{c if c}\">"
|
10
|
+
s << select_tag(:"#{name}[day]", :options => (1..31).to_a, :selected => v.day )
|
11
|
+
s << select_tag(:"#{name}[month]", :options => Date::MONTHNAMES[1..-1].each_with_index.map { |x,i| [x,i+1] }, :selected => v.month)
|
12
|
+
s << select_tag(:"#{name}[year]", :options => (2012..2020).to_a, :selected => v.year )
|
13
|
+
s << '@'
|
14
|
+
s << select_tag(:"#{name}[hour]", :options => (0..23).to_a.map { |x| [x < 10 ? "0#{x}" : x,x] }, :selected => v.hour )
|
15
|
+
s << ':'
|
16
|
+
s << select_tag(:"#{name}[min]", :options => (0..59).to_a.map { |x| [x < 10 ? "0#{x}" : x,x] }, :selected => v.min )
|
17
|
+
s << '</span>'
|
18
|
+
s.join(' ')
|
19
|
+
end
|
20
|
+
|
21
|
+
def compact_time_ago(t)
|
22
|
+
d = Time.now - t
|
23
|
+
if d < 1.day
|
24
|
+
time_ago_in_words(t) + ' ago'
|
25
|
+
elsif d < 3.days
|
26
|
+
t.strftime('%A') + " at #{t.to_s(:time)}"
|
27
|
+
else
|
28
|
+
t
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/dragonfly.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
if defined? Dragonfly
|
2
|
+
|
3
|
+
app = Dragonfly[:dragonfly].configure_with(:imagemagick) do |c|
|
4
|
+
c.url_format = '/media/:job/:basename.:format'
|
5
|
+
end
|
6
|
+
|
7
|
+
app.analyser.register(Dragonfly::Analysis::FileCommandAnalyser)
|
8
|
+
|
9
|
+
if Padrino.env == :production
|
10
|
+
# app.datastore = Dragonfly::DataStorage::S3DataStore.new
|
11
|
+
# app.datastore.configure do |d|
|
12
|
+
# d.bucket_name = ENV['S3_BUCKET_NAME']
|
13
|
+
# d.access_key_id = ENV['S3_ACCESS_KEY']
|
14
|
+
# d.secret_access_key = ENV['S3_SECRET']
|
15
|
+
# end
|
16
|
+
app.datastore = Dragonfly::DataStorage::MongoDataStore.new
|
17
|
+
app.datastore.configure do |c|
|
18
|
+
c.host = ENV['MONGOHQ_URL'].split('@').last.split(':').first
|
19
|
+
c.port = ENV['MONGOHQ_URL'].split('@').last.split(':').last.split('/').first
|
20
|
+
c.database = ENV['MONGOHQ_URL'].split('/')[3]
|
21
|
+
c.username = ENV['MONGOHQ_URL'].split('://').last.split(':').first
|
22
|
+
c.password = ENV['MONGOHQ_URL'].split('://').last.split('@').first.split(':').last
|
23
|
+
end
|
24
|
+
else
|
25
|
+
app.datastore = Dragonfly::DataStorage::MongoDataStore.new
|
26
|
+
end
|
27
|
+
|
28
|
+
app.define_macro_on_include(Mongoid::Document, :dragonfly_accessor)
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%# Link to the "First" page
|
2
|
+
- available local variables
|
3
|
+
url: url to the first page
|
4
|
+
current_page: a page object for the currently displayed page
|
5
|
+
num_pages: total number of pages
|
6
|
+
per_page: number of items to fetch per page
|
7
|
+
remote: data-remote
|
8
|
+
-%>
|
9
|
+
|
10
|
+
<li class="first <%='disabled' if current_page.first?%>">
|
11
|
+
<%= link_to raw(t 'views.pagination.first'), url, :remote => remote %>
|
12
|
+
</li>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%# Non-link tag that stands for skipped pages...
|
2
|
+
- available local variables
|
3
|
+
current_page: a page object for the currently displayed page
|
4
|
+
num_pages: total number of pages
|
5
|
+
per_page: number of items to fetch per page
|
6
|
+
remote: data-remote
|
7
|
+
-%>
|
8
|
+
<li class="page gap disabled"><a href="#" onclick="return false;"><%= raw(t 'views.pagination.truncate') %></a></li>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%# Link to the "Last" page
|
2
|
+
- available local variables
|
3
|
+
url: url to the last page
|
4
|
+
current_page: a page object for the currently displayed page
|
5
|
+
num_pages: total number of pages
|
6
|
+
per_page: number of items to fetch per page
|
7
|
+
remote: data-remote
|
8
|
+
-%>
|
9
|
+
|
10
|
+
<li class="last next <%='disabled' if current_page.last?%>"><%# "next" class present for border styling in twitter bootstrap %>
|
11
|
+
<%= link_to raw(t 'views.pagination.last'), url, {:remote => remote} %>
|
12
|
+
</li>
|
13
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%# Link to the "Next" page
|
2
|
+
- available local variables
|
3
|
+
url: url to the next page
|
4
|
+
current_page: a page object for the currently displayed page
|
5
|
+
num_pages: total number of pages
|
6
|
+
per_page: number of items to fetch per page
|
7
|
+
remote: data-remote
|
8
|
+
-%>
|
9
|
+
|
10
|
+
<li class="next_page <%='disabled' if current_page.last?%>">
|
11
|
+
<%= link_to raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote %>
|
12
|
+
</li>
|
13
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%# Link showing page number
|
2
|
+
- available local variables
|
3
|
+
page: a page object for "this" page
|
4
|
+
url: url to this page
|
5
|
+
current_page: a page object for the currently displayed page
|
6
|
+
num_pages: total number of pages
|
7
|
+
per_page: number of items to fetch per page
|
8
|
+
remote: data-remote
|
9
|
+
-%>
|
10
|
+
<li class="page<%= ' active' if page.current? %>">
|
11
|
+
<%= link_to page, url, opts = {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} %>
|
12
|
+
</li>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<%# The container tag
|
2
|
+
- available local variables
|
3
|
+
current_page: a page object for the currently displayed page
|
4
|
+
num_pages: total number of pages
|
5
|
+
per_page: number of items to fetch per page
|
6
|
+
remote: data-remote
|
7
|
+
paginator: the paginator that renders the pagination tags inside
|
8
|
+
-%>
|
9
|
+
<%= paginator.render do -%>
|
10
|
+
<div class="pagination">
|
11
|
+
<ul>
|
12
|
+
<%= first_page_tag %>
|
13
|
+
<%= prev_page_tag %>
|
14
|
+
<% each_page do |page| -%>
|
15
|
+
<% if page.left_outer? || page.right_outer? || page.inside_window? -%>
|
16
|
+
<%= page_tag page %>
|
17
|
+
<% elsif !page.was_truncated? -%>
|
18
|
+
<%= gap_tag %>
|
19
|
+
<% end -%>
|
20
|
+
<% end -%>
|
21
|
+
<%= next_page_tag %>
|
22
|
+
<%= last_page_tag %>
|
23
|
+
</ul>
|
24
|
+
</div>
|
25
|
+
<% end -%>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%# Link to the "Previous" page
|
2
|
+
- available local variables
|
3
|
+
url: url to the previous page
|
4
|
+
current_page: a page object for the currently displayed page
|
5
|
+
num_pages: total number of pages
|
6
|
+
per_page: number of items to fetch per page
|
7
|
+
remote: data-remote
|
8
|
+
-%>
|
9
|
+
|
10
|
+
<li class="prev <%='disabled' if current_page.first?%>">
|
11
|
+
<%= link_to raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
|
12
|
+
</li>
|
13
|
+
|
data/lib/kaminari.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
if defined? Kaminari
|
2
|
+
module Kaminari::Helpers
|
3
|
+
module SinatraHelpers
|
4
|
+
|
5
|
+
class ActionViewTemplateProxy
|
6
|
+
def render(*args)
|
7
|
+
base = ActionView::Base.new.tap do |a|
|
8
|
+
a.view_paths << File.expand_path("#{ActivateAdmin.root}/lib", __FILE__)
|
9
|
+
end
|
10
|
+
base.render(*args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def page_entries_info(collection, options = {})
|
15
|
+
entry_name = if options[:entry_name]
|
16
|
+
options[:entry_name]
|
17
|
+
elsif collection.empty? || collection.is_a?(Array)
|
18
|
+
'entry'
|
19
|
+
else
|
20
|
+
if collection.respond_to? :model # DataMapper
|
21
|
+
collection.model.model_name.human.downcase
|
22
|
+
else # AR
|
23
|
+
collection.model_name.human.downcase
|
24
|
+
end
|
25
|
+
end
|
26
|
+
entry_name = entry_name.pluralize unless collection.total_count == 1
|
27
|
+
|
28
|
+
if collection.total_pages < 2
|
29
|
+
t('helpers.page_entries_info.one_page.display_entries', :entry_name => entry_name, :count => collection.total_count)
|
30
|
+
else
|
31
|
+
first = collection.offset_value + 1
|
32
|
+
last = collection.last_page? ? collection.total_count : collection.offset_value + collection.limit_value
|
33
|
+
t('helpers.page_entries_info.more_pages.display_entries', :entry_name => entry_name, :first => first, :last => last, :total => collection.total_count)
|
34
|
+
end.html_safe
|
35
|
+
end
|
36
|
+
|
37
|
+
module HelperMethods
|
38
|
+
def paginate(scope, options = {}, &block)
|
39
|
+
current_path = env['REQUEST_PATH'] rescue nil
|
40
|
+
current_params = Rack::Utils.parse_query(env['QUERY_STRING']).symbolize_keys rescue {}
|
41
|
+
paginator = Kaminari::Helpers::Paginator.new(
|
42
|
+
ActionViewTemplateProxy.new(:current_params => current_params, :current_path => current_path, :param_name => options[:param_name] || Kaminari.config.param_name),
|
43
|
+
options.reverse_merge(:current_page => scope.current_page, :total_pages => scope.total_pages, :per_page => scope.limit_value, :param_name => Kaminari.config.param_name, :remote => false)
|
44
|
+
)
|
45
|
+
paginator.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ParamHelpers
|
2
|
+
|
3
|
+
def fix_params!
|
4
|
+
datetime_hashes_to_datetimes!(params)
|
5
|
+
file_hashes_to_files!(params)
|
6
|
+
blanks_to_nils!(params)
|
7
|
+
end
|
8
|
+
|
9
|
+
def datetime_hashes_to_datetimes!(hash)
|
10
|
+
hash.each { |k,v|
|
11
|
+
if v.is_a?(Hash) and [:year, :month, :day, :hour, :min].all? { |x| v.has_key?(x.to_s) }
|
12
|
+
hash[k] = Time.zone.local(v[:year].to_i, v[:month].to_i, v[:day].to_i, v[:hour].to_i, v[:min].to_i)
|
13
|
+
elsif v.is_a?(Hash)
|
14
|
+
datetime_hashes_to_datetimes!(v)
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def file_hashes_to_files!(hash)
|
20
|
+
hash.each { |k, v|
|
21
|
+
if v.is_a?(Hash) and v[:tempfile]
|
22
|
+
hash[k] = v[:tempfile]
|
23
|
+
elsif v.is_a?(Hash)
|
24
|
+
file_hashes_to_files!(v)
|
25
|
+
end
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def blanks_to_nils!(hash)
|
30
|
+
hash.each { |k,v|
|
31
|
+
if v.blank?
|
32
|
+
hash[k] = nil
|
33
|
+
elsif v.is_a? Array
|
34
|
+
v.each_with_index { |x,i| v[i] = nil if x.blank? }.compact!
|
35
|
+
elsif v.is_a? Hash
|
36
|
+
blanks_to_nils!(v)
|
37
|
+
end
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|