tablets 0.1.0
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.
- 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
|