table_me 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.
Files changed (63) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/images/table_me/orderable.png +0 -0
  5. data/app/assets/stylesheets/table_me/table_me.sass +171 -0
  6. data/config/routes.rb +2 -0
  7. data/lib/table_me/builder.rb +36 -0
  8. data/lib/table_me/column.rb +19 -0
  9. data/lib/table_me/engine.rb +28 -0
  10. data/lib/table_me/filter.rb +81 -0
  11. data/lib/table_me/table_for_helper/table_for_helper.rb +112 -0
  12. data/lib/table_me/table_for_presenter.rb +229 -0
  13. data/lib/table_me/table_me_helper/table_me_helper.rb +28 -0
  14. data/lib/table_me/table_me_presenter.rb +105 -0
  15. data/lib/table_me/table_pagination.rb +110 -0
  16. data/lib/table_me/table_vo.rb +48 -0
  17. data/lib/table_me/url_builder.rb +33 -0
  18. data/lib/table_me/url_parser.rb +38 -0
  19. data/lib/table_me/version.rb +3 -0
  20. data/lib/table_me.rb +15 -0
  21. data/lib/tasks/table_me_tasks.rake +4 -0
  22. data/test/dummy/README.rdoc +261 -0
  23. data/test/dummy/Rakefile +7 -0
  24. data/test/dummy/app/assets/javascripts/application.js +15 -0
  25. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  26. data/test/dummy/app/controllers/application_controller.rb +3 -0
  27. data/test/dummy/app/helpers/application_helper.rb +2 -0
  28. data/test/dummy/app/models/users.rb +2 -0
  29. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  30. data/test/dummy/config/application.rb +56 -0
  31. data/test/dummy/config/boot.rb +10 -0
  32. data/test/dummy/config/database.yml +25 -0
  33. data/test/dummy/config/environment.rb +5 -0
  34. data/test/dummy/config/environments/development.rb +46 -0
  35. data/test/dummy/config/environments/production.rb +67 -0
  36. data/test/dummy/config/environments/test.rb +37 -0
  37. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  38. data/test/dummy/config/initializers/inflections.rb +15 -0
  39. data/test/dummy/config/initializers/mime_types.rb +5 -0
  40. data/test/dummy/config/initializers/secret_token.rb +7 -0
  41. data/test/dummy/config/initializers/session_store.rb +8 -0
  42. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  43. data/test/dummy/config/locales/en.yml +5 -0
  44. data/test/dummy/config/routes.rb +58 -0
  45. data/test/dummy/config.ru +4 -0
  46. data/test/dummy/db/development.sqlite3 +0 -0
  47. data/test/dummy/db/migrate/20120223225814_create_users.rb +9 -0
  48. data/test/dummy/db/schema.rb +23 -0
  49. data/test/dummy/db/test.sqlite3 +0 -0
  50. data/test/dummy/log/development.log +52 -0
  51. data/test/dummy/log/test.log +6 -0
  52. data/test/dummy/public/404.html +26 -0
  53. data/test/dummy/public/422.html +26 -0
  54. data/test/dummy/public/500.html +25 -0
  55. data/test/dummy/public/favicon.ico +0 -0
  56. data/test/dummy/script/rails +6 -0
  57. data/test/fixtures/users.yml +9 -0
  58. data/test/integration/navigation_test.rb +10 -0
  59. data/test/integration/table_for_spec.rb +97 -0
  60. data/test/table_me_test.rb +7 -0
  61. data/test/test_helper.rb +10 -0
  62. data/test/unit/table_me_presenter_test.rb +7 -0
  63. metadata +225 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
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.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = TableMe
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'TableMe'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,171 @@
1
+ .table-me
2
+ display: inline-block
3
+ font-size: 1.2em
4
+ .table-me-table
5
+ color: #eee
6
+ display: inline-block
7
+ float: left
8
+ font-family: 'Helvetica', 'Arial', 'Sans-Serif'
9
+ a
10
+ color: #909BAC
11
+ text-decoration: none
12
+ a:visited
13
+ color: #909BAC
14
+ table
15
+ border-collapse: collapse
16
+ th
17
+ border-top: 1px solid #777
18
+ border-left: 1px solid #777
19
+ border-bottom: 1px solid #000
20
+ border-right: 1px solid #000
21
+ color: #fff
22
+ height: 25px
23
+ background: #444 /* Old browsers */
24
+ background: -moz-linear-gradient(top, #444 0%, #212121 99%) /* FF3.6+ */
25
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#444), color-stop(99%,#212121)) /* Chrome,Safari4+ */
26
+ background: -webkit-linear-gradient(top, #444 0%,#212121 99%) /* Chrome10+,Safari5.1+ */
27
+ background: -o-linear-gradient(top, #444 0%,#212121 99%) /* Opera 11.10+ */
28
+ background: -ms-linear-gradient(top, #444 0%,#212121 99%) /* IE10+ */
29
+ background: linear-gradient(top, #444 0%,#212121 99%) /* W3C */
30
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444', endColorstr='#212121',GradientType=0 ) /* IE6-9 */
31
+ a
32
+ padding: 8px 8px 8px 16px
33
+ color: #fff
34
+ vertical-align: center
35
+ background: image-url('table_me/orderable.png') 5px 15px no-repeat
36
+ a:visited
37
+ color: #fff
38
+ a.asc
39
+ background-position: 5px -17px
40
+ a.desc
41
+ background-position: 5px -43px
42
+ td
43
+ border-left: 1px solid #666
44
+ border-right: 1px solid #666
45
+ border-collapse: collapse
46
+ padding: 8px
47
+ .red,
48
+ .orange,
49
+ .green,
50
+ padding: 3px 7px
51
+ border: 1px solid #C55
52
+ font-size: .9em
53
+ .red
54
+ background-color: #F77
55
+ color: #a33
56
+ .green
57
+ background-color: #AfA
58
+ color: #090
59
+ border-color: #2A2
60
+ .orange
61
+ background-color: #FA0
62
+ color: #840
63
+ border-color: #C70
64
+ td:last-child
65
+ border-right: none
66
+ td:first-child
67
+ border-left: none
68
+ tr
69
+ border: none
70
+ .odd
71
+ background-color: rgba(255,255,255,0.1)
72
+ .table-me-pagination-info
73
+ padding-bottom: 8px
74
+ text-align: right
75
+ h3
76
+ position: relative
77
+ top: -7px
78
+ font-size: 1.2em
79
+ color: #FFF
80
+ float: left
81
+ font-family: 'Helvetica', 'Arial', 'Sans-Serif'
82
+ margin: 0
83
+ line-height: 1.4em
84
+ p
85
+ font-size: .8em
86
+ line-height: 1.4em
87
+ margin: 0
88
+ .table-me-pagination-controls
89
+ padding-top: 8px
90
+ text-align: right
91
+
92
+ .table-filters
93
+ color: #fff
94
+ font-family: 'Helvetica', 'Arial', 'Sans-Serif'
95
+ padding: 10px
96
+ border-radius: 5px
97
+ margin: 0 25px
98
+ float: right
99
+ background-color: #333
100
+ border-left: 1px solid #aaa
101
+ border-top: 1px solid #aaa
102
+ border-right: 1px solid #000
103
+ border-bottom: 1px solid #000
104
+ h3
105
+ margin: 0 0 10px 0
106
+ padding: 0
107
+ font-size: 1em
108
+ form
109
+ margin-bottom: 10px
110
+ form:last-child
111
+ margin: 0
112
+ input
113
+ width: auto
114
+ padding: 5px
115
+ margin: 0 8px 0 0
116
+ input[type=submit]
117
+ width: auto
118
+ padding: 5px 8px
119
+ border-left: 1px solid #aaa
120
+ border-top: 1px solid #aaa
121
+ border-right: 1px solid #000
122
+ border-bottom: 1px solid #000
123
+ color: #fff
124
+ background: #444 /* Old browsers */
125
+ background: -moz-linear-gradient(top, #444 0%, #212121 99%) /* FF3.6+ */
126
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#444), color-stop(99%,#212121)) /* Chrome,Safari4+ */
127
+ background: -webkit-linear-gradient(top, #444 0%,#212121 99%) /* Chrome10+,Safari5.1+ */
128
+ background: -o-linear-gradient(top, #444 0%,#212121 99%) /* Opera 11.10+ */
129
+ background: -ms-linear-gradient(top, #444 0%,#212121 99%) /* IE10+ */
130
+ background: linear-gradient(top, #444 0%,#212121 99%) /* W3C */
131
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444', endColorstr='#212121',GradientType=0 ) /* IE6-9 */
132
+
133
+ .table-me-table.light
134
+ color: #555
135
+ a
136
+ color: #707a8b
137
+ a:visited
138
+ color: #7079ba
139
+ table
140
+ th
141
+ border-top: 1px solid #eee
142
+ border-left: 1px solid #eee
143
+ border-bottom: 1px solid #999
144
+ border-right: 1px solid #999
145
+ color: #FFF
146
+ background: #ccc /* Old browsers */
147
+ background: -moz-linear-gradient(top, #ccc 0%, #aaa 99%) /* FF3.6+ */
148
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ccc), color-stop(99%,#aaa)) /* Chrome,Safari4+ */
149
+ background: -webkit-linear-gradient(top, #ccc 0%,#aaa 99%) /* Chrome10+,Safari5.1+ */
150
+ background: -o-linear-gradient(top, #ccc 0%,#aaa 99%) /* Opera 11.10+ */
151
+ background: -ms-linear-gradient(top, #ccc 0%,#aaa 99%) /* IE10+ */
152
+ background: linear-gradient(top, #ccc 0%,#aaa 99%) /* W3C */
153
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ccc', endColorstr='#aaa',GradientType=0 ) /* IE6-9 */
154
+ td
155
+ border-left: 1px solid #aaa
156
+ border-right: 1px solid #aaa
157
+ td:last-child
158
+ border-right: none
159
+ td:first-child
160
+ border-left: none
161
+ tr
162
+ border: none
163
+ .odd
164
+ background-color: rgba(000,000,000,0.1)
165
+ .table-me-pagination-info
166
+ h3
167
+ color: #444
168
+
169
+
170
+
171
+
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'column'
2
+ require_relative 'filter'
3
+ module TableMe
4
+ # This class is responsible for building the various elements of the
5
+ # table through a blog passed into the table_for_presenter
6
+
7
+ class Builder
8
+ attr_accessor :options
9
+ attr_reader :columns, :names, :filters
10
+ def initialize table_options
11
+ self.options = table_options
12
+ @columns = []
13
+ @names = []
14
+ end
15
+
16
+ # Define a column
17
+ def column name,options = {}, &block
18
+ @columns << TableMe::Column.new(name,options, &block)
19
+ @names << name
20
+ end
21
+
22
+ #define a filter
23
+ def filter name
24
+ TableMe::Filter.new(options, name)
25
+ end
26
+
27
+ def filters
28
+ TableMe::Filter.filters_for options[:name]
29
+ end
30
+
31
+ def clear_filter
32
+ # TODO this seems a bit hacky to me, Will want to rework this at some point
33
+ filters.last.display_clear
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ module TableMe
2
+ # This class is the column object that gets created
3
+ # everytime a column is used in the table_for_presenter block
4
+ # It's basically a value object which keeps track of the data
5
+ # for each individual column.
6
+ class Column
7
+ attr_accessor :name, :content, :sortable
8
+ def initialize column_name, args = {}, &block
9
+ self.name = column_name
10
+ self.content = block
11
+
12
+ if block
13
+ self.sortable = args[:sort_on]
14
+ else
15
+ self.sortable = column_name
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ require_relative '../table_me_helper/table_me_helper'
2
+ require_relative '../table_for_helper/table_for_helper'
3
+
4
+ module TableMe
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace TableMe
7
+
8
+ # send the helper methods to actionview and action controller
9
+ initializer "table_me" do
10
+ ActionView::Base.send :include, TableMe::TableForHelper
11
+ ActionController::Base.send :include, TableMe::TableMeHelper
12
+ end
13
+
14
+ initializer "table_me.load_app_instance_data" do |app|
15
+ TableMe.setup do |config|
16
+ config.app_root = app.root
17
+ end
18
+ end
19
+
20
+ initializer "table_me.load_static_assets" do |app|
21
+ app.middleware.use ::ActionDispatch::Static, "#{root}/public"
22
+ end
23
+
24
+ config.generators do |g|
25
+ g.test_framework :rspec, view_specs: false
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,81 @@
1
+ require_relative 'url_builder'
2
+ module TableMe
3
+ # This class creates the filter forms for searching a table.
4
+ # Unlike the column class, the filter class is responsible
5
+ # for creating it's own view. See the table_for_helper file
6
+ # for documentation on how to use filters
7
+ class Filter
8
+ attr_accessor :options, :column_name
9
+
10
+ @@filters = {}
11
+
12
+ def initialize options, column_name
13
+ self.options = options
14
+ self.column_name = column_name
15
+
16
+ @@filters[options[:name]] ||= []
17
+
18
+
19
+ @@filters[options[:name]].delete_if {|item| item.column_name == column_name}
20
+ @@filters[options[:name]] << self
21
+ end
22
+
23
+ # Display the filter form
24
+ def display
25
+ initial_value = options[:search] && options[:search][:column] == column_name.to_s ? options[:search][:query] : ''
26
+ <<-HTML.strip_heredoc
27
+ <form method='get' action="?">
28
+ <label for='search'>#{column_name.to_s.split('_').join(" ").titleize}</label>
29
+ <input type='text' name="tm_#{options[:name]}[search][query]" value="#{initial_value}"/>
30
+ <input type='hidden' name="tm_#{options[:name]}[search][column]" value="#{column_name}"/>
31
+ <input type='hidden' name="tm_#{options[:name]}[new_search]" value="true"/>
32
+ #{create_other_fields options}
33
+ <input id='search' type='submit' value='Search' />
34
+ </form>
35
+ HTML
36
+
37
+ end
38
+
39
+ # display a clear filters button, this clears the filters if any are active.
40
+ # This could/should be just a link styled like a button, there really isn't a
41
+ # need for it to be a form
42
+ # TODO Change this into a link instead of a form
43
+ def display_clear
44
+ <<-HTML.strip_heredoc if options[:search]
45
+ <form method='get' action="?">
46
+ #{create_other_fields options}
47
+ <input id='search' type='submit' value='Clear Filter' />
48
+ </form>
49
+ HTML
50
+ end
51
+
52
+ # getter for all the filters
53
+ def self.filters_for table_name
54
+ @@filters[table_name]
55
+ end
56
+
57
+ private
58
+
59
+ def create_other_fields options
60
+ inputs = []
61
+ TableMe::UrlBuilder.filter_options(options).each do |option|
62
+ option.each do |k,v|
63
+ if k.to_s == 'search'
64
+ # Adon't add the search fields if they are the current table
65
+ unless option[:name] == options[:name]
66
+ inputs << "<input type='hidden' name='tm_#{option[:name]}[search][query]' value='#{v[:query]}'/>"
67
+ inputs << "<input type='hidden' name='tm_#{option[:name]}[search][column]' value='#{v[:column]}'/>"
68
+ end
69
+ else
70
+ inputs << "<input type='hidden' name='tm_#{option[:name]}[#{k.to_s}]' value='#{v}'/>"
71
+ end
72
+ end
73
+ end
74
+ inputs.join("\n")
75
+ end
76
+
77
+ def url_for_tables options
78
+ TableMe::UrlBuilder.url_for options
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,112 @@
1
+ require File.expand_path('../../../table_me/table_for_presenter', __FILE__)
2
+
3
+ # In your view you can create the table from the one initialized in the controller,
4
+ # the first parameter of table_for is the name set in table_me. By default the class
5
+ # name is used if a name isn't set.
6
+
7
+ # table_for :user
8
+ # Now, this will list all columns from the database in your table, which you
9
+ # may not always want to do. You can pass a block of columns to be more specific:
10
+
11
+ # table_for :user do |t|
12
+ # t.column :id
13
+ # t.column :email
14
+ # t.column :created_at
15
+ # end
16
+
17
+ # This will give you a user table with the columns id, email, and created_at.
18
+
19
+ # What if you want to customize the output of the column? Each column can also
20
+ # take a block of content:
21
+
22
+ # table_for :user do |t|
23
+ # t.column :id
24
+ # t.column :email do |c|
25
+ # "<h1>c.email</h1>"
26
+ # end
27
+ # t.column :created_at
28
+ # end
29
+
30
+ # Now, when a block is used to alter the content of a column, the sorting is lost,
31
+ # since the table can no longer assume what is in the column. You need to set a sort_on
32
+ # param to tell the column what to sort by. For example:
33
+
34
+ # table_for :user do |t|
35
+ # t.column :id
36
+ # t.column :email, sort_on: :email do |c|
37
+ # "<h1>c.email</h1>"
38
+ # end
39
+ # t.column :created_at
40
+ # end
41
+
42
+ # Filters
43
+ # You can add basic filter fields to the table by using the filter method. Right now,
44
+ # only one filter can be applied and the filters are search fields. I would like to
45
+ # eventually add different types for different types of data. I would like to eventually
46
+ # add in the ability for multiple filter types with a single search button, but the basic
47
+ # form is all I need at the moment. Ajax enabled filtering would be freaking great as well.
48
+
49
+ # Filter usage:
50
+
51
+ # table_for :user do |t|
52
+ # t.filter :email
53
+ # t.filter :name
54
+ # t.column :id
55
+ # t.column :email
56
+ # t.column :name
57
+ # end
58
+
59
+ module TableMe
60
+ module TableForHelper
61
+ def table_for(model,options = {}, &block)
62
+ table_for_presenter = TableForPresenter.new(model,options,&block)
63
+ table_for_presenter.build_table
64
+ end
65
+
66
+ # Lets say that you want to have a visual que for if a user is an admin:
67
+ # table_for :user do |t|
68
+ # t.column :id
69
+ # t.column :admin do |c|
70
+ # highlight_cell c.admin, green: true
71
+ # end
72
+ # t.column :created_at
73
+ # end
74
+
75
+ # You can put a green box around true in the column by passing an array to the color
76
+ # where the first value is the actual table value your looking for, while the second item
77
+ # is what will be used in the table field. But what if you want to change that true to the
78
+ # word 'Admin' and lets put a red box around all the non admins and make them say 'peons':
79
+
80
+ # table_for :user do |t|
81
+ # t.column :id
82
+ # t.column :admin do |c|
83
+ # highlight_cell c.admin, green: [true, 'Admin'], red: [false, 'peon']
84
+ # end
85
+ # t.column :created_at
86
+ # end
87
+
88
+ def highlight_cell value, colors
89
+ color_value = output_value = color = ''
90
+
91
+ colors.each do |k,v|
92
+ if v.kind_of? Array
93
+ color_value = v[0]
94
+ output_value = v[1]
95
+ else
96
+ output_value = color_value = v
97
+ end
98
+
99
+ if color_value == value
100
+ color = k.to_s
101
+ break
102
+ end
103
+ end
104
+
105
+ unless color.empty?
106
+ "<span class='#{color}'>#{output_value}</span>".html_safe
107
+ else
108
+ value
109
+ end
110
+ end
111
+ end
112
+ end