tablets 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +90 -0
- data/Rakefile +19 -0
- data/app/assets/javascripts/tablets/callbacks.js.coffee +3 -0
- data/app/assets/javascripts/tablets/tablet.js.coffee +35 -0
- data/app/assets/javascripts/tablets.js.coffee +4 -0
- data/app/controllers/tablets/ajax_controller.rb +31 -0
- data/app/views/tablets/_tablet.html.erb +21 -0
- data/config/routes.rb +3 -0
- data/lib/tablets/data/processing/base.rb +23 -0
- data/lib/tablets/data/processing/filter.rb +47 -0
- data/lib/tablets/data/processing/order.rb +34 -0
- data/lib/tablets/data/processing/paginate.rb +40 -0
- data/lib/tablets/data/query.rb +61 -0
- data/lib/tablets/data.rb +58 -0
- data/lib/tablets/engine.rb +9 -0
- data/lib/tablets/global/configurator.rb +49 -0
- data/lib/tablets/global/loader.rb +37 -0
- data/lib/tablets/global/store.rb +25 -0
- data/lib/tablets/railtie.rb +27 -0
- data/lib/tablets/renderer.rb +84 -0
- data/lib/tablets/tablet.rb +60 -0
- data/lib/tablets/utils/arel.rb +34 -0
- data/lib/tablets/utils/config.rb +75 -0
- data/lib/tablets/version.rb +3 -0
- data/lib/tablets/view_helpers.rb +14 -0
- data/lib/tablets.rb +19 -0
- data/spec/lib/tablets/data/processing/base_spec.rb +19 -0
- data/spec/lib/tablets/data/processing/paginate_spec.rb +73 -0
- data/spec/lib/tablets/global/store_spec.rb +33 -0
- data/spec/lib/tablets/renderer_spec.rb +102 -0
- data/spec/lib/tablets/utils/config_spec.rb +104 -0
- data/spec/lib/tablets/view_helpers_spec.rb +42 -0
- data/spec/spec_helper.rb +92 -0
- metadata +169 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1a1fa5246fe01b026cb2cb2eea4d8a1bdf1bb864
|
4
|
+
data.tar.gz: d41e7ccd372d8f2a63b702c77521a874e4baf4bc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ab12d327506c9abfc4083855019fadffcddd399db62098b44f788a5abc91e823969df57e140214f9c5d38fb6047de374dc920281c128ae84c649d7c51235ac42
|
7
|
+
data.tar.gz: 8a0c9608f4dfb7deb525674287114fef5f6090bca34ec10daa1a0e8b8df4342c0cb7ae6b99382ff5053323774d63d2fa64b4c30cdfa16357b14a45a22bcb9563
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Yevhen Shemet
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# Tablets
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's `Gemfile`:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'tablets'
|
9
|
+
```
|
10
|
+
|
11
|
+
Include tablets and jquery datatables scripts in your `app/assets/application.js`:
|
12
|
+
```
|
13
|
+
//= require dataTables/jquery.dataTables
|
14
|
+
//= require tablets
|
15
|
+
```
|
16
|
+
|
17
|
+
Include jquery datatables styles in your `app/assets/application.css`:
|
18
|
+
```
|
19
|
+
*= require dataTables/jquery.dataTables
|
20
|
+
```
|
21
|
+
|
22
|
+
Mount engine in `config/routes.rb`:
|
23
|
+
```
|
24
|
+
mount Tablets::Engine, at: '/tablets'
|
25
|
+
```
|
26
|
+
|
27
|
+
## Examples
|
28
|
+
|
29
|
+
In `app/tablets/posts.rb`:
|
30
|
+
```ruby
|
31
|
+
Tablets.register :posts do
|
32
|
+
# Authorization logic.
|
33
|
+
authorize do |controller|
|
34
|
+
controller.current_user.id == params[:author_id]
|
35
|
+
end
|
36
|
+
|
37
|
+
# jQuery-datatables options overrides.
|
38
|
+
options do
|
39
|
+
{ order: [0, 'asc'] }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Columns definitions.
|
43
|
+
columns do
|
44
|
+
[{
|
45
|
+
title: 'Title',
|
46
|
+
order: 'posts.title',
|
47
|
+
data: :title,
|
48
|
+
options: { className: 'post-title' }
|
49
|
+
}, {
|
50
|
+
title: 'User',
|
51
|
+
order: ['users.first_name', 'users.last_name'],
|
52
|
+
data: ->(user) { [user.first_name, user.last_name].compact.join(' ') },
|
53
|
+
search: ['users.first_name', 'users.last_name']
|
54
|
+
}]
|
55
|
+
end
|
56
|
+
|
57
|
+
# HTML for details area.
|
58
|
+
details do |post|
|
59
|
+
post.content.html_safe
|
60
|
+
end
|
61
|
+
|
62
|
+
# Process records before extracting data.
|
63
|
+
process do |posts|
|
64
|
+
posts.map { |post| post.use_wrapper }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Data relation.
|
68
|
+
relation do |params|
|
69
|
+
# Note: User joined to enable ordering.
|
70
|
+
User.joins(:users).where(user_id: params[:user_id])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
In `app/views/posts/index.html.erb`
|
76
|
+
```erb
|
77
|
+
<%= render_tablet :posts, user_id: current_user.id %>
|
78
|
+
```
|
79
|
+
|
80
|
+
## JavaScripts callbacks
|
81
|
+
|
82
|
+
Called just before datatable initialization.
|
83
|
+
```javascript
|
84
|
+
Tablets.Callbacks.beforeInit = function(element, options) {}
|
85
|
+
```
|
86
|
+
|
87
|
+
Called after datatable initialization.
|
88
|
+
```javascript
|
89
|
+
Tablets.Callbacks.afterInit = function(table) {}
|
90
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Tablets'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
14
|
+
end
|
15
|
+
|
16
|
+
Bundler::GemHelper.install_tasks
|
17
|
+
|
18
|
+
require 'rspec/core'
|
19
|
+
require 'rspec/core/rake_task'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Tablets.Tablet
|
2
|
+
constructor: (@element, @options, @params) ->
|
3
|
+
@initTable()
|
4
|
+
@initDetails()
|
5
|
+
|
6
|
+
dataTableOptions: ->
|
7
|
+
$.extend {}, @options,
|
8
|
+
fnServerParams: (data) =>
|
9
|
+
data.params = @params
|
10
|
+
|
11
|
+
initTable: ->
|
12
|
+
options = @dataTableOptions()
|
13
|
+
|
14
|
+
Tablets.Callbacks.beforeInit(@element, options)
|
15
|
+
|
16
|
+
@table = $(@element).DataTable(options)
|
17
|
+
|
18
|
+
Tablets.Callbacks.afterInit(@table)
|
19
|
+
|
20
|
+
initDetails: ->
|
21
|
+
table = @table
|
22
|
+
table.on 'click', 'tbody > tr[role=row] > td:first-child', ->
|
23
|
+
tr = $(this).closest 'tr'
|
24
|
+
row = table.row tr
|
25
|
+
|
26
|
+
if row.child.isShown()
|
27
|
+
row.child.hide()
|
28
|
+
tr.removeClass 'expanded'
|
29
|
+
tr.removeClass 'shown'
|
30
|
+
else
|
31
|
+
data = row.data().details
|
32
|
+
if data
|
33
|
+
row.child("<span>#{data}</span>").show()
|
34
|
+
tr.addClass 'expanded'
|
35
|
+
tr.addClass 'shown'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Tablets
|
2
|
+
# Responsible to provide data to tablet on ajax request.
|
3
|
+
class AjaxController < ApplicationController
|
4
|
+
before_filter :authorize!
|
5
|
+
|
6
|
+
def data
|
7
|
+
render json: Tablets::Data.new(tablet, data_params)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def tablet
|
13
|
+
@tablet ||= Tablets[params[:name].to_sym]
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorize!
|
17
|
+
render nothing: true, status: 401 unless authorized?
|
18
|
+
end
|
19
|
+
|
20
|
+
def authorized?
|
21
|
+
tablet.authorize(self)
|
22
|
+
rescue
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def data_params
|
27
|
+
params.slice(:name, :start, :length, :search,
|
28
|
+
:order, :params, :draw, :columns)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<table class="table tablet" id="<%= id %>" data-name="<%= name %>">
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<% columns.each.with_index do |column, index| %>
|
5
|
+
<th class="<%= 'nosort' unless column[:order].present? %>">
|
6
|
+
<%= column[:title] %>
|
7
|
+
</th>
|
8
|
+
<% end %>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
12
|
+
</tbody>
|
13
|
+
</table>
|
14
|
+
|
15
|
+
<script>
|
16
|
+
new Tablets.Tablet(
|
17
|
+
$('#<%= id %>'),
|
18
|
+
<%= raw options.to_json %>,
|
19
|
+
<%= raw params.to_json %>
|
20
|
+
);
|
21
|
+
</script>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tablets
|
2
|
+
class Data
|
3
|
+
module Processing
|
4
|
+
# Base class for relation processings.
|
5
|
+
class Base
|
6
|
+
# Initializes processor with relation and data reqired for processing.
|
7
|
+
def initialize(params, columns)
|
8
|
+
@params = params
|
9
|
+
@columns = columns
|
10
|
+
end
|
11
|
+
|
12
|
+
# Applies processing on relation. Need to be implemented in descendants.
|
13
|
+
def apply(relation)
|
14
|
+
fail NotImplementedError, '#apply need to be overrided by processing.'
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :params, :columns
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'tablets/utils/arel'
|
2
|
+
|
3
|
+
require 'tablets/data/processing/base'
|
4
|
+
|
5
|
+
module Tablets
|
6
|
+
class Data
|
7
|
+
module Processing
|
8
|
+
# Incapsulate relation filtering logic.
|
9
|
+
class Filter < Tablets::Data::Processing::Base
|
10
|
+
# Applies filter processing on relation.
|
11
|
+
def apply(relation)
|
12
|
+
search(relation)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Applies search conditions if need.
|
18
|
+
def search(relation)
|
19
|
+
return relation unless params[:search].try(:[], :value).present?
|
20
|
+
|
21
|
+
conditions = build_conditions_for(params[:search][:value])
|
22
|
+
relation = relation.where(conditions) if conditions
|
23
|
+
relation
|
24
|
+
end
|
25
|
+
|
26
|
+
# Builds search conditions.
|
27
|
+
def build_conditions_for(query)
|
28
|
+
query.split(' ').map do |value|
|
29
|
+
searchable_columns.map do |column|
|
30
|
+
search_condition(column, value)
|
31
|
+
end.reduce(:or)
|
32
|
+
end.reduce(:and)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns searchable columns.
|
36
|
+
def searchable_columns
|
37
|
+
columns.map { |column| column[:search] }.flatten.compact
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returs search condition.
|
41
|
+
def search_condition(column, value)
|
42
|
+
Tablets::Utils::Arel.column(column).matches("%#{value}%")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'tablets/data/processing/base'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
class Data
|
5
|
+
module Processing
|
6
|
+
# Incapsulate relation ordering logic.
|
7
|
+
class Order < Tablets::Data::Processing::Base
|
8
|
+
# Applies order processing on relation.
|
9
|
+
def apply(relation)
|
10
|
+
params[:order].values.inject(relation) do |relation, item|
|
11
|
+
relation.order("#{column(item)} #{direction(item)}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Determines order column from params.
|
18
|
+
def column(item)
|
19
|
+
columns[item[:column].to_i][:order]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Determines order direction from params.
|
23
|
+
# ASC by default.
|
24
|
+
def direction(item)
|
25
|
+
if %w(ASC DESC).include?(item[:dir].upcase)
|
26
|
+
item[:dir].upcase
|
27
|
+
else
|
28
|
+
'ASC'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'tablets/data/processing/base'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
class Data
|
5
|
+
module Processing
|
6
|
+
# Incapsulate relation pagination logic.
|
7
|
+
class Paginate < Tablets::Data::Processing::Base
|
8
|
+
# Applies :start and :length from params to relation
|
9
|
+
# as offset and limit.
|
10
|
+
# :length is optional. Default value is used if no length is provided.
|
11
|
+
# :start recalculated to match beginnning of page.
|
12
|
+
def apply(relation)
|
13
|
+
relation.offset(offset).limit(per_page)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Calculates offset as beginning of page.
|
19
|
+
def offset
|
20
|
+
(page - 1) * per_page
|
21
|
+
end
|
22
|
+
|
23
|
+
# Calculates page from start.
|
24
|
+
def page
|
25
|
+
(params[:start].to_i / per_page) + 1
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns default length.
|
29
|
+
def default_length
|
30
|
+
10
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns length or default value.
|
34
|
+
def per_page
|
35
|
+
params.fetch(:length, default_length).to_i
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'tablets/data/processing/filter'
|
2
|
+
require 'tablets/data/processing/paginate'
|
3
|
+
require 'tablets/data/processing/order'
|
4
|
+
|
5
|
+
module Tablets
|
6
|
+
class Data
|
7
|
+
# Incapsulates database query.
|
8
|
+
class Query
|
9
|
+
# Initializes query with relation, params and columns.
|
10
|
+
def initialize(relation, params, columns)
|
11
|
+
@relation = relation
|
12
|
+
@params = params
|
13
|
+
@columns = columns
|
14
|
+
end
|
15
|
+
|
16
|
+
# Applies all processings on relation and returns it.
|
17
|
+
def fetch
|
18
|
+
result = relation
|
19
|
+
result = order(result)
|
20
|
+
result = filter(result)
|
21
|
+
result = paginate(result)
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns total records count before filter and pagination is applied.
|
26
|
+
def total
|
27
|
+
relation.count(:all)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns records count after filter is applied but before pagination.
|
31
|
+
def filtered
|
32
|
+
filter(relation).count(:all)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :relation, :params, :columns
|
38
|
+
|
39
|
+
# Applies order processing.
|
40
|
+
def order(records)
|
41
|
+
return records unless params[:order].present?
|
42
|
+
|
43
|
+
Tablets::Data::Processing::Order.new(params, columns).apply(records)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Applies filter processing.
|
47
|
+
def filter(records)
|
48
|
+
return records unless params[:search].present?
|
49
|
+
|
50
|
+
Tablets::Data::Processing::Filter.new(params, columns).apply(records)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Applies paginate processing.
|
54
|
+
def paginate(records)
|
55
|
+
return records if params.try(:[], :length) == '-1'
|
56
|
+
|
57
|
+
Tablets::Data::Processing::Paginate.new(params, columns).apply(records)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/tablets/data.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'tablets/data/query'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
# Responsible to fetch and prepare data for jquery-datatables.
|
5
|
+
class Data
|
6
|
+
# Initializes data with tablet and params.
|
7
|
+
def initialize(tablet, params)
|
8
|
+
@tablet = tablet
|
9
|
+
@params = params
|
10
|
+
end
|
11
|
+
|
12
|
+
# Prepares data to render as json.
|
13
|
+
def as_json(_options = {})
|
14
|
+
{
|
15
|
+
draw: params[:draw].to_i,
|
16
|
+
recordsTotal: query.total,
|
17
|
+
recordsFiltered: query.filtered,
|
18
|
+
data: data
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :params, :tablet
|
25
|
+
|
26
|
+
# Initializes query with concretized relation.
|
27
|
+
def query
|
28
|
+
@query ||= Tablets::Data::Query.new(tablet.relation(params[:params]),
|
29
|
+
params,
|
30
|
+
tablet.columns)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Fetching records and applies process tablet callback on it.
|
34
|
+
def records
|
35
|
+
@records ||= tablet.process(query.fetch)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Fetching columns data for each row using column[:data] value.
|
39
|
+
# If column[:data] is symbol send it to the record.
|
40
|
+
# If column[:data] is proc calls it on the record.
|
41
|
+
# Also appends details.
|
42
|
+
def data
|
43
|
+
records.map do |record|
|
44
|
+
tablet.columns.map.with_index do |column, index|
|
45
|
+
[index, cell(record, column)]
|
46
|
+
end.to_h.merge(details: tablet.details(record))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns single cell value, for specified record and for specified column.
|
51
|
+
def cell(record, column)
|
52
|
+
case column[:data]
|
53
|
+
when Symbol then record.send(column[:data])
|
54
|
+
when Proc then column[:data].call(record)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
module Global
|
5
|
+
# Responsible to make application configurable.
|
6
|
+
module Configurator
|
7
|
+
attr_accessor :options
|
8
|
+
attr_accessor :tablets_dir
|
9
|
+
|
10
|
+
# Setup configuration. Used in initializers.
|
11
|
+
def setup
|
12
|
+
yield self
|
13
|
+
end
|
14
|
+
|
15
|
+
# Initialize default config values.
|
16
|
+
def self.extended(base)
|
17
|
+
base.options = DEFAULT_OPTIONS
|
18
|
+
base.tablets_dir = File.expand_path('app/tablets', Rails.root)
|
19
|
+
end
|
20
|
+
|
21
|
+
DEFAULT_OPTIONS = {
|
22
|
+
pageLength: 15,
|
23
|
+
processing: false,
|
24
|
+
info: true,
|
25
|
+
lengthChange: false,
|
26
|
+
serverSide: true,
|
27
|
+
pagingType: 'full_numbers',
|
28
|
+
order: [0, 'asc'],
|
29
|
+
autoWidth: true,
|
30
|
+
orderCellsTop: true,
|
31
|
+
language: {
|
32
|
+
lengthMenu: '<span class=\'seperator\'>|</span>View _MENU_ records',
|
33
|
+
info: '<span class=\'seperator\'>|</span>Found total _TOTAL_ records',
|
34
|
+
infoEmpty: '',
|
35
|
+
emptyTable: 'No records found to show',
|
36
|
+
zeroRecords: 'No matching records found',
|
37
|
+
paginate: {
|
38
|
+
previous: 'Prev',
|
39
|
+
next: 'Next',
|
40
|
+
last: 'Last',
|
41
|
+
first: 'First',
|
42
|
+
page: 'Page',
|
43
|
+
pageOf: 'of'
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Tablets
|
2
|
+
module Global
|
3
|
+
# Tablets loader. Manages files loading from app tablets directory.
|
4
|
+
module Loader
|
5
|
+
# Unloads tablet.
|
6
|
+
def unload!
|
7
|
+
@tablets = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
# Checks if tablet is loading.
|
11
|
+
# Tablets is not loaded only if tablets is nil.
|
12
|
+
def loaded?
|
13
|
+
!@tablets.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Loads tablets files.
|
17
|
+
def load!
|
18
|
+
@tablets = {}
|
19
|
+
files.each { |file| load file }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Load paths.
|
25
|
+
def load_paths
|
26
|
+
[Tablets.tablets_dir]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Prepares files list using load paths.
|
30
|
+
def files
|
31
|
+
load_paths.flatten.compact.uniq.flat_map do |path|
|
32
|
+
Dir["#{path}/**/*.rb"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'tablets/tablet'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
module Global
|
5
|
+
# Tables store.
|
6
|
+
# Expects @tablets to be defined elsewhere.
|
7
|
+
module Store
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
attr_reader :tablets
|
11
|
+
|
12
|
+
def_delegators :tablets, :[]
|
13
|
+
|
14
|
+
# Initializes tablet and put tablet into store.
|
15
|
+
#
|
16
|
+
# Tablets.register(:user) do
|
17
|
+
# # Tablet configuration.
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
def register(name, &block)
|
21
|
+
@tablets[name] = Tablets::Tablet.new(name, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rails/railtie'
|
2
|
+
|
3
|
+
require 'tablets/view_helpers'
|
4
|
+
|
5
|
+
module Tablets
|
6
|
+
# Rails hooks.
|
7
|
+
class Railtie < ::Rails::Railtie
|
8
|
+
# Allows tablets view helper to be used anywhere in rails views.
|
9
|
+
initializer 'tablets.view_helpers' do
|
10
|
+
ActionView::Base.send :include, Tablets::ViewHelpers
|
11
|
+
end
|
12
|
+
|
13
|
+
# Manages tablets loading and cleanup.
|
14
|
+
# Also ensures tablets reloading in development environment.
|
15
|
+
initializer 'tablets.reloader' do |app|
|
16
|
+
if app.config.reload_classes_only_on_change
|
17
|
+
ActionDispatch::Reloader.to_prepare(prepend: true) { Tablets.unload! }
|
18
|
+
else
|
19
|
+
ActionDispatch::Reloader.to_cleanup { Tablets.unload! }
|
20
|
+
end
|
21
|
+
|
22
|
+
ActionDispatch::Reloader.to_prepare do
|
23
|
+
Tablets.load! unless Tablets.loaded?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|