tramway 0.3.2 → 0.4
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 +4 -4
- data/README.md +28 -0
- data/app/components/tailwind_component.rb +2 -2
- data/app/components/tailwinds/form/builder.rb +27 -6
- data/app/components/tailwinds/form/file_field_component.html.haml +1 -1
- data/app/components/tailwinds/form/file_field_component.rb +1 -0
- data/app/components/tailwinds/form/select_component.html.haml +1 -1
- data/app/components/tailwinds/form/text_field_component.html.haml +1 -1
- data/app/views/kaminari/_first_page.html.haml +9 -0
- data/app/views/kaminari/_gap.html.haml +8 -0
- data/app/views/kaminari/_last_page.html.haml +9 -0
- data/app/views/kaminari/_next_page.html.haml +9 -0
- data/app/views/kaminari/_page.html.haml +14 -0
- data/app/views/kaminari/_paginator.html.haml +12 -0
- data/app/views/kaminari/_prev_page.html.haml +9 -0
- data/lib/tramway/config.rb +8 -8
- data/lib/tramway/engine.rb +36 -0
- data/lib/tramway/version.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 68a5dd780d7427b0c2075f140c891af3a4c33210c88a00d86e33279dc27e6c28
|
|
4
|
+
data.tar.gz: 63701d608f5545ea95e98fac522624cc34092199fe839b16ba579d9c461c0383
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8e6c295607acc32db6b7a0bea211ddb9ba2d8e2ca141804bce78b7b51fb74a08478c38ead05962f56ecd226a57b2e7398b97c86ac6dcc7aa46c3862bd8a49f30
|
|
7
|
+
data.tar.gz: bd89050c6d5b3391f457eea7a277cdaaa53c3fbe1f20a0567c39b659ab8a3187d2f161bed38a6b9226782191b884fe94eb63d7e7f8aa292e8ff121dcf149c521
|
data/README.md
CHANGED
|
@@ -8,6 +8,7 @@ Unite Ruby on Rails brilliance. Streamline development with Tramway.
|
|
|
8
8
|
* [Tramway Form](https://github.com/Purple-Magic/tramway#tramway-form)
|
|
9
9
|
* [Tramway Navbar](https://github.com/Purple-Magic/tramway#tramway-navbar)
|
|
10
10
|
* [Tailwind-styled forms](https://github.com/Purple-Magic/tramway#tailwind-styled-forms)
|
|
11
|
+
* [Tailwind-styled pagination](https://github.com/Purple-Magic/tramway#tailwind-styled-pagination)
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
13
14
|
Add this line to your application's Gemfile:
|
|
@@ -362,6 +363,32 @@ Available form helpers:
|
|
|
362
363
|
* select
|
|
363
364
|
* submit
|
|
364
365
|
|
|
366
|
+
### Tailwind-styled pagination for Kaminari
|
|
367
|
+
|
|
368
|
+
Tramway uses [Tailwind](https://tailwindcss.com/) by default. It has tailwind-styled pagination for [kaminari](https://github.com/kaminari/kaminari).
|
|
369
|
+
|
|
370
|
+
#### How to use
|
|
371
|
+
|
|
372
|
+
*Gemfile*
|
|
373
|
+
```ruby
|
|
374
|
+
gem 'tramway'
|
|
375
|
+
gem 'kaminari'
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
*config/initializers/tramway.rb*
|
|
379
|
+
```ruby
|
|
380
|
+
Tramway.configure do |config|
|
|
381
|
+
config.pagination = { enabled: true } # enabled is false by default
|
|
382
|
+
end
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
*app/views/users/index.html.haml*
|
|
386
|
+
```haml
|
|
387
|
+
= paginate @users # it will render tailwind-styled pagination buttons by default
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Pagination buttons looks like [this](https://play.tailwindcss.com/mqgDS5l9oY)
|
|
391
|
+
|
|
365
392
|
## Contributing
|
|
366
393
|
|
|
367
394
|
Install [lefthook](https://github.com/evilmartians/lefthook)
|
|
@@ -369,6 +396,7 @@ Install [lefthook](https://github.com/evilmartians/lefthook)
|
|
|
369
396
|
```
|
|
370
397
|
bundle
|
|
371
398
|
lefthook install
|
|
399
|
+
rspec
|
|
372
400
|
```
|
|
373
401
|
|
|
374
402
|
## License
|
|
@@ -6,9 +6,9 @@ require 'view_component'
|
|
|
6
6
|
class TailwindComponent < ViewComponent::Base
|
|
7
7
|
extend Dry::Initializer[undefined: false]
|
|
8
8
|
|
|
9
|
-
option :
|
|
9
|
+
option :input
|
|
10
10
|
option :attribute
|
|
11
|
-
option :
|
|
11
|
+
option :value, optional: true
|
|
12
12
|
option :options
|
|
13
13
|
option :label
|
|
14
14
|
option :for
|
|
@@ -6,19 +6,33 @@ module Tailwinds
|
|
|
6
6
|
# :reek:InstanceVariableAssumption
|
|
7
7
|
class Builder < Tramway::Views::FormBuilder
|
|
8
8
|
def text_field(attribute, **options, &)
|
|
9
|
-
render(Tailwinds::Form::TextFieldComponent.new(
|
|
9
|
+
render(Tailwinds::Form::TextFieldComponent.new(
|
|
10
|
+
input: input(:text_field),
|
|
11
|
+
value: get_value(attribute, options),
|
|
12
|
+
**default_options(attribute, options)
|
|
13
|
+
), &)
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
def password_field(attribute, **options, &)
|
|
13
|
-
render(Tailwinds::Form::TextFieldComponent.new(
|
|
17
|
+
render(Tailwinds::Form::TextFieldComponent.new(
|
|
18
|
+
input: input(:password_field),
|
|
19
|
+
**default_options(attribute, options)
|
|
20
|
+
), &)
|
|
14
21
|
end
|
|
15
22
|
|
|
16
23
|
def file_field(attribute, **options, &)
|
|
17
|
-
|
|
24
|
+
input = super(attribute, **options.merge(class: :hidden))
|
|
25
|
+
|
|
26
|
+
render(Tailwinds::Form::FileFieldComponent.new(input:, **default_options(attribute, options)), &)
|
|
18
27
|
end
|
|
19
28
|
|
|
20
29
|
def select(attribute, collection, **options, &)
|
|
21
|
-
render(Tailwinds::Form::SelectComponent.new(
|
|
30
|
+
render(Tailwinds::Form::SelectComponent.new(
|
|
31
|
+
input: input(:select),
|
|
32
|
+
value: options[:selected] || object.public_send(attribute),
|
|
33
|
+
collection:,
|
|
34
|
+
**default_options(attribute, options)
|
|
35
|
+
), &)
|
|
22
36
|
end
|
|
23
37
|
|
|
24
38
|
def submit(action, **options, &)
|
|
@@ -27,11 +41,18 @@ module Tailwinds
|
|
|
27
41
|
|
|
28
42
|
private
|
|
29
43
|
|
|
44
|
+
def input(method_name)
|
|
45
|
+
unbound_method = self.class.superclass.instance_method(method_name)
|
|
46
|
+
unbound_method.bind(self)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get_value(attribute, options)
|
|
50
|
+
options[:value] || object.public_send(attribute)
|
|
51
|
+
end
|
|
52
|
+
|
|
30
53
|
def default_options(attribute, options)
|
|
31
54
|
{
|
|
32
|
-
template: @template,
|
|
33
55
|
attribute:,
|
|
34
|
-
object_name:,
|
|
35
56
|
label: label(attribute, options),
|
|
36
57
|
for: for_id(attribute),
|
|
37
58
|
options:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
.mb-4
|
|
2
2
|
%label.block.text-gray-700.text-sm.font-bold.mb-2{ for: @for }
|
|
3
3
|
= @label
|
|
4
|
-
= @
|
|
4
|
+
= @input.call(@attribute, @collection, { selected: @value }, @options.merge(class: 'bg-white border border-gray-300 text-gray-700 py-2 px-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent'))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
.mb-4
|
|
2
2
|
%label.block.text-gray-700.text-sm.font-bold.mb-2{ for: @for }
|
|
3
3
|
= @label
|
|
4
|
-
= @
|
|
4
|
+
= @input.call @attribute, **@options.merge(class: 'w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-red-500'), value: @value
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
-# total_pages: total number of pages
|
|
6
|
+
-# per_page: number of items to fetch per page
|
|
7
|
+
-# remote: data-remote
|
|
8
|
+
%span.first{ class: 'px-3 py-2 text-sm font-medium text-purple-700 bg-white rounded-md hover:bg-purple-100' }
|
|
9
|
+
= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote
|
|
@@ -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
|
+
-# total_pages: total number of pages
|
|
5
|
+
-# per_page: number of items to fetch per page
|
|
6
|
+
-# remote: data-remote
|
|
7
|
+
%span.page.gap{ class: 'px-3 py-2 text-sm font-medium text-purple-700' }
|
|
8
|
+
= t('views.pagination.truncate').html_safe
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
-# total_pages: total number of pages
|
|
6
|
+
-# per_page: number of items to fetch per page
|
|
7
|
+
-# remote: data-remote
|
|
8
|
+
%span.last{ class: 'px-3 py-2 text-sm font-medium text-purple-700 bg-white rounded-md hover:bg-purple-100' }
|
|
9
|
+
= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
-# total_pages: total number of pages
|
|
6
|
+
-# per_page: number of items to fetch per page
|
|
7
|
+
-# remote: data-remote
|
|
8
|
+
%span.next{ class: 'px-3 py-2 text-sm font-medium text-purple-700 bg-white rounded-md hover:bg-purple-100' }
|
|
9
|
+
= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
-# total_pages: total number of pages
|
|
7
|
+
-# per_page: number of items to fetch per page
|
|
8
|
+
-# remote: data-remote
|
|
9
|
+
- if page.current?
|
|
10
|
+
%span{class: "px-3 py-2 font-medium rounded-md bg-purple-500 text-white" }
|
|
11
|
+
= page
|
|
12
|
+
- else
|
|
13
|
+
%span{class: "cursor px-3 py-2 font-medium text-purple-700 bg-white rounded-md hover:bg-purple-100"}
|
|
14
|
+
= link_to_unless page.current?, page, url, {remote: remote, rel: page.rel}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
= paginator.render do
|
|
2
|
+
%nav.pagination.flex.items-center.justify-center.space-x-1
|
|
3
|
+
= first_page_tag unless current_page.first?
|
|
4
|
+
= prev_page_tag unless current_page.first?
|
|
5
|
+
- each_page do |page|
|
|
6
|
+
- if page.display_tag?
|
|
7
|
+
= page_tag page
|
|
8
|
+
- elsif !page.was_truncated?
|
|
9
|
+
= gap_tag
|
|
10
|
+
= next_page_tag unless current_page.last?
|
|
11
|
+
= last_page_tag unless current_page.last?
|
|
12
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
-# total_pages: total number of pages
|
|
6
|
+
-# per_page: number of items to fetch per page
|
|
7
|
+
-# remote: data-remote
|
|
8
|
+
%span.prev{ class: 'px-3 py-2 text-sm font-medium text-purple-700 bg-white rounded-md hover:bg-purple-100' }
|
|
9
|
+
= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote
|
data/lib/tramway/config.rb
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'anyway'
|
|
3
4
|
require 'singleton'
|
|
4
5
|
require 'tramway/configs/entity'
|
|
5
6
|
|
|
6
7
|
module Tramway
|
|
7
8
|
# Basic configuration of Tramway
|
|
8
9
|
#
|
|
9
|
-
class Config
|
|
10
|
+
class Config < Anyway::Config
|
|
10
11
|
include Singleton
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
attr_config(
|
|
14
|
+
pagination: { enabled: false },
|
|
15
|
+
entities: []
|
|
16
|
+
)
|
|
15
17
|
|
|
16
18
|
def entities=(collection)
|
|
17
|
-
|
|
19
|
+
super(collection.map do |entity|
|
|
18
20
|
entity_options = entity.is_a?(Hash) ? entity : { name: entity }
|
|
19
21
|
|
|
20
22
|
Tramway::Configs::Entity.new(**entity_options)
|
|
21
|
-
end
|
|
23
|
+
end)
|
|
22
24
|
end
|
|
23
|
-
|
|
24
|
-
attr_reader :entities
|
|
25
25
|
end
|
|
26
26
|
end
|
data/lib/tramway/engine.rb
CHANGED
|
@@ -7,29 +7,65 @@ module Tramway
|
|
|
7
7
|
isolate_namespace Tramway
|
|
8
8
|
|
|
9
9
|
initializer 'tramway.load_helpers' do
|
|
10
|
+
load_navbar_helper
|
|
11
|
+
load_views_helper
|
|
12
|
+
load_decorator_helper
|
|
13
|
+
load_form_helper
|
|
14
|
+
configure_pagination if Tramway.config.pagination[:enabled]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def load_navbar_helper
|
|
10
20
|
ActiveSupport.on_load(:action_view) do |loaded_class|
|
|
11
21
|
require 'tramway/helpers/navbar_helper'
|
|
12
22
|
|
|
13
23
|
loaded_class.include Tramway::Helpers::NavbarHelper
|
|
14
24
|
end
|
|
25
|
+
end
|
|
15
26
|
|
|
27
|
+
def load_views_helper
|
|
16
28
|
ActiveSupport.on_load(:action_view) do |loaded_class|
|
|
17
29
|
require 'tramway/helpers/views_helper'
|
|
18
30
|
|
|
19
31
|
loaded_class.include Tramway::Helpers::ViewsHelper
|
|
20
32
|
end
|
|
33
|
+
end
|
|
21
34
|
|
|
35
|
+
def load_decorator_helper
|
|
22
36
|
ActiveSupport.on_load(:action_controller) do |loaded_class|
|
|
23
37
|
require 'tramway/helpers/decorate_helper'
|
|
24
38
|
|
|
25
39
|
loaded_class.include Tramway::Helpers::DecorateHelper
|
|
26
40
|
end
|
|
41
|
+
end
|
|
27
42
|
|
|
43
|
+
def load_form_helper
|
|
28
44
|
ActiveSupport.on_load(:action_controller) do |loaded_class|
|
|
29
45
|
require 'tramway/helpers/form_helper'
|
|
30
46
|
|
|
31
47
|
loaded_class.include Tramway::Helpers::FormHelper
|
|
32
48
|
end
|
|
33
49
|
end
|
|
50
|
+
|
|
51
|
+
# :reek:NestedIterators { enabled: false }
|
|
52
|
+
# :reek:TooManyStatements { enabled: false }
|
|
53
|
+
def configure_pagination
|
|
54
|
+
ActiveSupport.on_load(:action_controller) do
|
|
55
|
+
# Detecting tramway views path
|
|
56
|
+
tramway_spec = Gem.loaded_specs['tramway']
|
|
57
|
+
tramway_views_path = File.join(tramway_spec.full_gem_path, 'app/views')
|
|
58
|
+
|
|
59
|
+
paths = view_paths.to_ary
|
|
60
|
+
|
|
61
|
+
# Determine index to insert tramway views path
|
|
62
|
+
rails_views_index = paths.find_index { |path| path.to_s.ends_with?('app/views') }
|
|
63
|
+
insert_index = rails_views_index ? rails_views_index + 1 : 0
|
|
64
|
+
|
|
65
|
+
# Inserting tramway views path
|
|
66
|
+
paths.insert(insert_index, tramway_views_path)
|
|
67
|
+
self.view_paths = paths
|
|
68
|
+
end
|
|
69
|
+
end
|
|
34
70
|
end
|
|
35
71
|
end
|
data/lib/tramway/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tramway
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: '0.4'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kalashnikovisme
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2024-01-
|
|
12
|
+
date: 2024-01-20 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: dry-struct
|
|
@@ -106,6 +106,13 @@ files:
|
|
|
106
106
|
- app/components/tailwinds/nav/item_component.rb
|
|
107
107
|
- app/components/tailwinds/navbar_component.html.haml
|
|
108
108
|
- app/components/tailwinds/navbar_component.rb
|
|
109
|
+
- app/views/kaminari/_first_page.html.haml
|
|
110
|
+
- app/views/kaminari/_gap.html.haml
|
|
111
|
+
- app/views/kaminari/_last_page.html.haml
|
|
112
|
+
- app/views/kaminari/_next_page.html.haml
|
|
113
|
+
- app/views/kaminari/_page.html.haml
|
|
114
|
+
- app/views/kaminari/_paginator.html.haml
|
|
115
|
+
- app/views/kaminari/_prev_page.html.haml
|
|
109
116
|
- config/routes.rb
|
|
110
117
|
- lib/rules/turbo_html_attributes_rules.rb
|
|
111
118
|
- lib/tasks/tramway_tasks.rake
|