tramway 0.5.2.1 → 0.5.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 +27 -2
- data/app/components/tailwinds/form/builder.rb +8 -0
- data/app/components/tailwinds/form/select_component.html.haml +1 -1
- data/app/components/tailwinds/form/submit_button_component.html.haml +1 -1
- data/app/components/tailwinds/form/text_area_component.html.haml +5 -0
- data/app/components/tailwinds/form/text_area_component.rb +9 -0
- data/app/components/tailwinds/nav/item_component.rb +1 -1
- data/app/components/tailwinds/navbar_component.html.haml +1 -1
- data/app/components/tailwinds/table/header_component.html.haml +1 -1
- data/app/components/tailwinds/table/row_component.html.haml +4 -16
- data/app/components/tailwinds/table/row_component.rb +5 -2
- data/app/components/tailwinds/table_component.html.haml +2 -1
- data/app/components/tailwinds/table_component.rb +1 -0
- data/app/controllers/tramway/entities_controller.rb +10 -1
- data/app/helpers/tramway/application_helper.rb +1 -0
- data/app/views/tramway/entities/_entity.html.haml +3 -3
- data/app/views/tramway/entities/_list.html.haml +8 -5
- data/config/routes.rb +16 -15
- data/config/tailwind.config.js +12 -0
- data/lib/kaminari/helpers/tag.rb +23 -0
- data/lib/tramway/base_decorator.rb +9 -0
- data/lib/tramway/configs/entities/page.rb +14 -0
- data/lib/tramway/configs/entity.rb +11 -4
- data/lib/tramway/decorators/association.rb +13 -7
- data/lib/tramway/decorators/class_helper.rb +11 -7
- data/lib/tramway/forms/properties.rb +17 -1
- data/lib/tramway/helpers/decorate_helper.rb +2 -2
- data/lib/tramway/helpers/navbar_helper.rb +4 -4
- data/lib/tramway/navbar.rb +6 -4
- data/lib/tramway/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3edafce1c744c1e57499e5682ee75f749dbf5bdefd1a9137d70ccaa95f1381f
|
4
|
+
data.tar.gz: fbb70ec105b76caad025797238eb09a7e21d5892e90be6b77c1c2858f301c666
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4deef971e492a823f04475bc6e915193735844521f8ae65ba8f07da1b1b0edb40e35d944000b648e0c36f1e33d8b2e770b6b62117f52df1a81443fb034132032
|
7
|
+
data.tar.gz: fcbea51c9f88495f24110ccac4f473a3a76f2583621fb952ec849fc77c690ee081bcba7a4e789c04f1c77bda02c41dac2d607f7c9b5a6572cdd03172cf31ac0c
|
data/README.md
CHANGED
@@ -8,6 +8,7 @@ Unite Ruby on Rails brilliance. Streamline development with Tramway.
|
|
8
8
|
* [Tramway Decorators](https://github.com/Purple-Magic/tramway#tramway-decorators)
|
9
9
|
* [Tramway Form](https://github.com/Purple-Magic/tramway#tramway-form)
|
10
10
|
* [Tramway Navbar](https://github.com/Purple-Magic/tramway#tramway-navbar)
|
11
|
+
* [Tramway Table Component](https://github.com/Purple-Magic/tramway#tramway-table-component)
|
11
12
|
* [Tailwind-styled forms](https://github.com/Purple-Magic/tramway#tailwind-styled-forms)
|
12
13
|
* [Stimulus-based inputs](https://github.com/Purple-Magic/tramway#stimulus-based-inputs)
|
13
14
|
* [Tailwind-styled pagination](https://github.com/Purple-Magic/tramway?tab=readme-ov-file#tailwind-styled-pagination-for-kaminari)
|
@@ -26,7 +27,7 @@ gem "view_component"
|
|
26
27
|
OR
|
27
28
|
|
28
29
|
```shell
|
29
|
-
bundle add tramway view_component
|
30
|
+
bundle add tramway view_component kaminari view_component
|
30
31
|
```
|
31
32
|
|
32
33
|
## Getting Started
|
@@ -194,6 +195,8 @@ end
|
|
194
195
|
|
195
196
|
#### Decorate associations
|
196
197
|
|
198
|
+
**Decorate single association**
|
199
|
+
|
197
200
|
```ruby
|
198
201
|
class UserDecorator < Tramway::BaseDecorator
|
199
202
|
association :posts
|
@@ -203,6 +206,14 @@ user = tramway_decorate User.first
|
|
203
206
|
user.posts # => decorated collection of posts with PostDecorator
|
204
207
|
```
|
205
208
|
|
209
|
+
**Decorate multiple associations**
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
class UserDecorator < Tramway::BaseDecorator
|
213
|
+
associations :posts, :users
|
214
|
+
end
|
215
|
+
```
|
216
|
+
|
206
217
|
#### Decorate nil
|
207
218
|
|
208
219
|
Tramway Decorator does not decorate nil objects
|
@@ -225,7 +236,7 @@ Tramway provides **convenient** form objects for Rails applications. List proper
|
|
225
236
|
class UserForm < Tramway::BaseForm
|
226
237
|
properties :email, :password, :first_name, :last_name, :phone
|
227
238
|
|
228
|
-
normalizes :email, ->(value) { value.strip.downcase }
|
239
|
+
normalizes :email, with: ->(value) { value.strip.downcase }
|
229
240
|
end
|
230
241
|
```
|
231
242
|
|
@@ -491,6 +502,20 @@ tramway_navbar title: 'Purple Magic' do |nav|
|
|
491
502
|
end
|
492
503
|
```
|
493
504
|
|
505
|
+
### Tramway Table Component
|
506
|
+
|
507
|
+
Tramway provides a responsive, tailwind-styled table with light and dark themes.
|
508
|
+
|
509
|
+
```haml
|
510
|
+
= component 'tailwinds/table' do
|
511
|
+
= component 'tailwinds/table/header', headers: ['Column 1', 'Column 2']
|
512
|
+
= component 'tailwinds/table/row' do
|
513
|
+
= component 'tailwinds/table/cell' do
|
514
|
+
Something
|
515
|
+
= component 'tailwinds/table/cell' do
|
516
|
+
Another
|
517
|
+
```
|
518
|
+
|
494
519
|
### Tailwind-styled forms
|
495
520
|
|
496
521
|
Tramway uses [Tailwind](https://tailwindcss.com/) by default. All UI helpers are implemented with [ViewComponent](https://github.com/viewcomponent/view_component).
|
@@ -13,6 +13,14 @@ module Tailwinds
|
|
13
13
|
), &)
|
14
14
|
end
|
15
15
|
|
16
|
+
def text_area(attribute, **options, &)
|
17
|
+
render(Tailwinds::Form::TextAreaComponent.new(
|
18
|
+
input: input(:text_area),
|
19
|
+
value: get_value(attribute, options),
|
20
|
+
**default_options(attribute, options)
|
21
|
+
), &)
|
22
|
+
end
|
23
|
+
|
16
24
|
def password_field(attribute, **options, &)
|
17
25
|
render(Tailwinds::Form::TextFieldComponent.new(
|
18
26
|
input: input(:password_field),
|
@@ -2,4 +2,4 @@
|
|
2
2
|
- if @label
|
3
3
|
= component('tailwinds/form/label', for: @for) do
|
4
4
|
= @label
|
5
|
-
= @input.call(@attribute, @collection, { selected: @value }, @options.merge(class: 'bg-white border border-gray-300 text-gray-700
|
5
|
+
= @input.call(@attribute, @collection, { selected: @value }, @options.merge(class: 'bg-white border border-gray-300 text-gray-700 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent py-2 px-3 disabled:bg-gray-100 disabled:text-gray-400 disabled:cursor-not-allowed'))
|
@@ -1,4 +1,4 @@
|
|
1
1
|
.flex.items-center.justify-between
|
2
|
-
%button.bg-red-500.hover:bg-red-700.text-white.font-bold.py-2.px-4.rounded.focus:outline-none.focus:shadow-outline.cursor-pointer{ type: :submit, name: :commit, **@options }
|
2
|
+
%button.bg-red-500.hover:bg-red-700.text-white.font-bold.py-2.px-4.rounded.focus:outline-none.focus:shadow-outline.cursor-pointer.dark:text-white{ type: :submit, name: :commit, **@options }
|
3
3
|
= @text
|
4
4
|
= @content
|
@@ -0,0 +1,5 @@
|
|
1
|
+
.mb-4
|
2
|
+
- if @label
|
3
|
+
= component('tailwinds/form/label', for: @for) do
|
4
|
+
= @label
|
5
|
+
= @input.call @attribute, **@options.merge(class: 'w-full bg-white px-3 py-2 border border-gray-300 rounded focus:outline-none focus:border-red-500 dark:placeholder-gray-400'), value: @value
|
@@ -8,7 +8,7 @@ module Tailwinds
|
|
8
8
|
def style
|
9
9
|
@style ||= [
|
10
10
|
'text-white', 'hover:bg-gray-300', 'hover:text-gray-800', 'px-4', 'py-2', 'rounded', 'whitespace-nowrap',
|
11
|
-
'dark:hover:bg-gray-700', 'dark:hover:text-gray-400'
|
11
|
+
'dark:hover:bg-gray-700', 'dark:hover:text-gray-400', 'dark:text-white'
|
12
12
|
].join(' ')
|
13
13
|
end
|
14
14
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.div-table-row.
|
1
|
+
.div-table-row.grid.text-white.text-small.gap-4.bg-purple-700.dark:bg-gray-700.dark:text-gray-400{ class: "grid-cols-#{headers.count}", aria: { label: "Table Header" }, role: "row" }
|
2
2
|
- if headers.any?
|
3
3
|
- headers.each do |header|
|
4
4
|
.div-table-cell.py-4.px-6
|
@@ -1,27 +1,15 @@
|
|
1
1
|
- if cells.any?
|
2
|
-
|
3
|
-
= row_tag class: desktop_row_classes(cells.count) do
|
2
|
+
= row_tag class: desktop_row_classes(cells.count), **options do
|
4
3
|
- cells.each do |(_, value)|
|
5
4
|
.div-table-cell.px-6.py-4.font-medium.text-gray-900.whitespace-nowrap.dark:text-white.text-xs.sm:text-base
|
6
5
|
= value
|
7
6
|
|
8
|
-
-# mobile view
|
9
|
-
.div-table-row.xl:hidden.border-b.dark:bg-gray-800.dark:border-gray-700.mb-2{ "data-action" => "click->preview#toggle", "data-controller" => "preview", "data-items" => cells.to_json }
|
10
|
-
.w-full.p-4.bg-purple-100.text-gray-700.dark:bg-gray-700.dark:text-gray-400
|
11
|
-
= cells.values.first
|
12
|
-
|
13
|
-
.flex.overflow-x-auto.whitespace-nowrap
|
14
|
-
- cells.each_with_index do |(_, value), index|
|
15
|
-
- next if index == 0
|
16
|
-
|
17
|
-
.text-gray-900.dark:text-white.p-4.text-xs.sm:text-base.inline-block.w-auto
|
18
|
-
= value
|
19
7
|
- else
|
20
|
-
- cells = Nokogiri::HTML.fragment(content).
|
8
|
+
- cells = Nokogiri::HTML.fragment(content).xpath('./*[@class and contains(concat(" ", normalize-space(@class), " "), " div-table-cell ")]')
|
21
9
|
|
22
10
|
- if href.present?
|
23
|
-
= tag.a href:, class: [desktop_row_classes(cells.count), link_row_classes].join(' ') do
|
11
|
+
= tag.a href:, class: [desktop_row_classes(cells.count), link_row_classes].join(' '), **options do
|
24
12
|
= content
|
25
13
|
- else
|
26
|
-
= tag.div class: desktop_row_classes(cells.count) do
|
14
|
+
= tag.div class: desktop_row_classes(cells.count), **options do
|
27
15
|
= content
|
@@ -6,16 +6,19 @@ module Tailwinds
|
|
6
6
|
class RowComponent < Tramway::Component::Base
|
7
7
|
option :cells, optional: true, default: -> { [] }
|
8
8
|
option :href, optional: true
|
9
|
+
option :options, optional: true, default: -> { {} }
|
9
10
|
|
10
11
|
def row_tag(**options, &)
|
12
|
+
default_attributes = { role: :row }
|
13
|
+
|
11
14
|
if href.present?
|
12
15
|
klass = "#{options[:class] || ''} #{link_row_classes}"
|
13
16
|
|
14
|
-
link_to(href, options.merge(class: klass)) do
|
17
|
+
link_to(href, options.merge(class: klass, **default_attributes)) do
|
15
18
|
yield if block_given?
|
16
19
|
end
|
17
20
|
else
|
18
|
-
tag.div(**options) do
|
21
|
+
tag.div(**options.merge(default_attributes)) do
|
19
22
|
yield if block_given?
|
20
23
|
end
|
21
24
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
= helpers.component 'tailwinds/table/row/preview'
|
2
2
|
|
3
|
-
|
3
|
+
- width_class = options[:class]&.include?('w-') ? '' : 'w-full'
|
4
|
+
.div-table.text-left.rtl:text-right.text-gray-500.dark:text-gray-400.mt-4{ class: "#{options[:class]} #{width_class}", **options.except(:class) }
|
4
5
|
= content
|
@@ -11,7 +11,12 @@ module Tramway
|
|
11
11
|
include Rails.application.routes.url_helpers
|
12
12
|
|
13
13
|
def index
|
14
|
-
@entities =
|
14
|
+
@entities = if entity.page(:index).scope.present?
|
15
|
+
model_class.public_send(entity.page(:index).scope)
|
16
|
+
else
|
17
|
+
model_class.order(id: :desc)
|
18
|
+
end.page(params[:page])
|
19
|
+
@namespace = entity.route.namespace
|
15
20
|
end
|
16
21
|
|
17
22
|
private
|
@@ -19,5 +24,9 @@ module Tramway
|
|
19
24
|
def model_class
|
20
25
|
@model_class ||= params[:entity][:name].classify.constantize
|
21
26
|
end
|
27
|
+
|
28
|
+
def entity
|
29
|
+
@entity ||= Tramway.config.entities.find { |e| e.name == params[:entity][:name] }
|
30
|
+
end
|
22
31
|
end
|
23
32
|
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
- decorator =
|
2
|
-
- decorated_object = decorator.decorate(entity)
|
3
|
-
= component 'tailwinds/table/row', cells: decorator.list_attributes.reduce({}) { |hash, attribute| hash.merge! attribute => decorated_object.public_send(attribute) }, href: decorated_object.show_path
|
1
|
+
- decorator = decorator_class_name(entity, @namespace)
|
2
|
+
- decorated_object = decorator.constantize.decorate(entity)
|
3
|
+
= component 'tailwinds/table/row', cells: decorator.constantize.list_attributes.reduce({}) { |hash, attribute| hash.merge! attribute => decorated_object.public_send(attribute) }, href: decorated_object.show_path
|
@@ -1,15 +1,17 @@
|
|
1
|
-
- decorator = Tramway::Decorators::
|
1
|
+
- decorator = Tramway::Decorators::ClassHelper.decorator_class_name(@model_class, @namespace)
|
2
2
|
- list_attributes = decorator.constantize.list_attributes
|
3
3
|
|
4
4
|
.mt-8.w-full
|
5
5
|
- content_for :title, page_title
|
6
6
|
|
7
|
-
.flex.justify-between.items-center
|
7
|
+
.flex.justify-between.items-center
|
8
8
|
%h1.font-bold.text-4xl.dark:text-white
|
9
9
|
= content_for(:title)
|
10
10
|
|
11
11
|
- if Tramway.config.pagination[:enabled]
|
12
|
-
= paginate @entities
|
12
|
+
= paginate @entities, custom_path_method: "#{@model_class.model_name.plural}_path"
|
13
|
+
.flex.justify-end.mt-2
|
14
|
+
= decorator.constantize.index_header_content.call(@entities) if decorator.constantize.index_header_content.present?
|
13
15
|
|
14
16
|
- if list_attributes.empty?
|
15
17
|
%p.text-center.mt-10
|
@@ -21,5 +23,6 @@
|
|
21
23
|
- @entities.each do |item|
|
22
24
|
= render 'tramway/entities/entity', entity: item
|
23
25
|
|
24
|
-
.
|
25
|
-
|
26
|
+
- if Tramway.config.pagination[:enabled]
|
27
|
+
.flex.mt-4
|
28
|
+
= paginate @entities, custom_path_method: "#{@model_class.model_name.plural}_path"
|
data/config/routes.rb
CHANGED
@@ -2,29 +2,30 @@
|
|
2
2
|
|
3
3
|
Tramway::Engine.routes.draw do
|
4
4
|
Tramway.config.entities.each do |entity|
|
5
|
-
|
5
|
+
segments = entity.name.split('/')
|
6
|
+
resource_name = segments.pop
|
7
|
+
|
8
|
+
define_resource = proc do
|
6
9
|
resources resource_name.pluralize.to_sym,
|
7
|
-
only:
|
8
|
-
controller:
|
9
|
-
defaults:
|
10
|
+
only: [:index],
|
11
|
+
controller:'/tramway/entities',
|
12
|
+
defaults: { entity: entity }
|
10
13
|
end
|
11
14
|
|
12
|
-
if
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
namespace
|
17
|
-
if
|
18
|
-
|
15
|
+
if segments.empty?
|
16
|
+
define_resource.call
|
17
|
+
else
|
18
|
+
nest = lambda do |names|
|
19
|
+
namespace names.first.to_sym do
|
20
|
+
if names.size > 1
|
21
|
+
nest.call(names.drop(1))
|
19
22
|
else
|
20
|
-
|
23
|
+
define_resource.call
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
25
|
-
|
26
|
-
else
|
27
|
-
define_resource.call(entity.name, entity)
|
28
|
+
nest.call(segments)
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
data/config/tailwind.config.js
CHANGED
@@ -23,7 +23,11 @@ module.exports = {
|
|
23
23
|
'flex',
|
24
24
|
'bg-purple-700',
|
25
25
|
'px-6',
|
26
|
+
'px-3',
|
27
|
+
'px-4',
|
26
28
|
'py-4',
|
29
|
+
'py-2',
|
30
|
+
'mb-2',
|
27
31
|
'dark:placeholder-gray-400',
|
28
32
|
'dark:text-white',
|
29
33
|
'dark:bg-gray-800',
|
@@ -41,6 +45,14 @@ module.exports = {
|
|
41
45
|
'hover:bg-gray-100',
|
42
46
|
'hover:bg-gray-300',
|
43
47
|
'hover:text-gray-800',
|
48
|
+
'mt-8',
|
49
|
+
'justify-between',
|
50
|
+
'space-x-1',
|
51
|
+
'justify-end',
|
52
|
+
'mt-2',
|
53
|
+
'disabled:bg-gray-100',
|
54
|
+
'disabled:text-gray-400',
|
55
|
+
'disabled:cursor-not-allowed',
|
44
56
|
// pagination
|
45
57
|
'bg-white', 'rounded-md', 'hover:bg-purple-100', 'dark:text-white', 'dark:bg-gray-800', 'dark:hover:bg-gray-700',
|
46
58
|
// multiselect styles
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kaminari
|
4
|
+
module Helpers
|
5
|
+
# Monkey patch for Kaminari::Helpers::Tag to support :custom_path_method
|
6
|
+
# :reek:InstanceVariableAssumption { enabled: false }
|
7
|
+
class Tag
|
8
|
+
def page_url_for(page)
|
9
|
+
custom_path_method = @options[:custom_path_method]
|
10
|
+
|
11
|
+
if custom_path_method.present?
|
12
|
+
Tramway::Engine.routes.url_helpers.public_send(
|
13
|
+
custom_path_method,
|
14
|
+
@params.except(:controller, :action).merge(page: page)
|
15
|
+
)
|
16
|
+
else
|
17
|
+
params = params_for(page)
|
18
|
+
@template.url_for params.merge(only_path: true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -4,6 +4,7 @@ require 'tramway/decorators/name_builder'
|
|
4
4
|
require 'tramway/decorators/association'
|
5
5
|
require 'tramway/decorators/collection_decorator'
|
6
6
|
require 'tramway/helpers/decorate_helper'
|
7
|
+
require 'tramway/helpers/component_helper'
|
7
8
|
require 'tramway/utils/render'
|
8
9
|
require 'tramway/duck_typing'
|
9
10
|
|
@@ -15,6 +16,7 @@ module Tramway
|
|
15
16
|
include Tramway::Utils::Render
|
16
17
|
include Tramway::DuckTyping::ActiveRecordCompatibility
|
17
18
|
include Tramway::Helpers::DecorateHelper
|
19
|
+
include Tramway::Helpers::ComponentHelper
|
18
20
|
|
19
21
|
attr_reader :object
|
20
22
|
|
@@ -23,6 +25,9 @@ module Tramway
|
|
23
25
|
end
|
24
26
|
|
25
27
|
class << self
|
28
|
+
include Tramway::Helpers::ComponentHelper
|
29
|
+
include Tramway::Utils::Render
|
30
|
+
|
26
31
|
# :reek:NilCheck { enabled: false } because checking for nil is not a type-checking issue but business logic
|
27
32
|
def decorate(object_or_array)
|
28
33
|
return if object_or_array.nil?
|
@@ -47,6 +52,10 @@ module Tramway
|
|
47
52
|
[]
|
48
53
|
end
|
49
54
|
|
55
|
+
def index_header_content
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
50
59
|
include Tramway::Decorators::AssociationClassMethods
|
51
60
|
end
|
52
61
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tramway
|
4
|
+
module Configs
|
5
|
+
module Entities
|
6
|
+
# Route struct describes rules for route management
|
7
|
+
#
|
8
|
+
class Page < Dry::Struct
|
9
|
+
attribute :action, Types::Coercible::String
|
10
|
+
attribute? :scope, Types::Coercible::String
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,19 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'tramway/configs/entities/route'
|
4
|
+
require 'tramway/configs/entities/page'
|
4
5
|
|
5
6
|
module Tramway
|
6
7
|
module Configs
|
7
8
|
# Tramway is an entity-based framework
|
8
9
|
class Entity < Dry::Struct
|
9
10
|
attribute :name, Types::Coercible::String
|
10
|
-
attribute? :pages, Types::Array.of(
|
11
|
+
attribute? :pages, Types::Array.of(Tramway::Configs::Entities::Page).default([].freeze)
|
11
12
|
attribute? :route, Tramway::Configs::Entities::Route
|
12
13
|
|
13
14
|
# Route Struct contains implemented in Tramway CRUD and helpful routes for the entity
|
14
15
|
RouteStruct = Struct.new(:index)
|
15
16
|
|
16
|
-
#
|
17
|
+
# HumanName Struct contains human names forms for the entity
|
17
18
|
HumanNameStruct = Struct.new(:single, :plural)
|
18
19
|
|
19
20
|
def routes
|
@@ -31,6 +32,10 @@ module Tramway
|
|
31
32
|
HumanNameStruct.new(single, plural)
|
32
33
|
end
|
33
34
|
|
35
|
+
def page(name)
|
36
|
+
pages.find { |page| page.action == name.to_s }
|
37
|
+
end
|
38
|
+
|
34
39
|
private
|
35
40
|
|
36
41
|
def pluralized(model_name)
|
@@ -48,7 +53,7 @@ module Tramway
|
|
48
53
|
def route_helper_method
|
49
54
|
underscored_name = name.parameterize.pluralize.underscore
|
50
55
|
|
51
|
-
method_name = if
|
56
|
+
method_name = if set_page?(:index) || route.blank?
|
52
57
|
"#{underscored_name}_path"
|
53
58
|
else
|
54
59
|
route.helper_method_by(underscored_name)
|
@@ -58,8 +63,10 @@ module Tramway
|
|
58
63
|
end
|
59
64
|
|
60
65
|
def route_helper_engine
|
61
|
-
|
66
|
+
set_page?(:index) ? Tramway::Engine : Rails.application
|
62
67
|
end
|
68
|
+
|
69
|
+
alias set_page? page
|
63
70
|
end
|
64
71
|
end
|
65
72
|
end
|
@@ -22,14 +22,14 @@ module Tramway
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# has_and_belongs_to_many is not supported for now
|
25
|
-
def association(association)
|
25
|
+
def association(association, decorator: nil)
|
26
26
|
define_method(association) do
|
27
27
|
assoc = object.send(association)
|
28
28
|
|
29
29
|
if assoc.is_a?(ActiveRecord::Relation)
|
30
|
-
AssocDecoratorHelper.decorate_has_many_association assoc
|
30
|
+
AssocDecoratorHelper.decorate_has_many_association assoc, decorator_class: decorator
|
31
31
|
elsif assoc.present?
|
32
|
-
AssocDecoratorHelper.decorate_associated_object(assoc)
|
32
|
+
AssocDecoratorHelper.decorate_associated_object(assoc, decorator_class: decorator)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -38,12 +38,18 @@ module Tramway
|
|
38
38
|
# Helper module for association decorators
|
39
39
|
module AssocDecoratorHelper
|
40
40
|
class << self
|
41
|
-
def decorate_has_many_association(assoc)
|
42
|
-
|
41
|
+
def decorate_has_many_association(assoc, decorator_class: nil)
|
42
|
+
return [] if assoc.empty?
|
43
|
+
|
44
|
+
decorator_class ||= decorator(assoc.klass)
|
45
|
+
|
46
|
+
decorator_class.decorate(assoc)
|
43
47
|
end
|
44
48
|
|
45
|
-
def decorate_associated_object(assoc)
|
46
|
-
decorator(assoc.class)
|
49
|
+
def decorate_associated_object(assoc, decorator_class: nil)
|
50
|
+
decorator_class ||= decorator(assoc.class)
|
51
|
+
|
52
|
+
decorator_class.decorate(assoc)
|
47
53
|
end
|
48
54
|
|
49
55
|
def decorator(class_name)
|
@@ -6,27 +6,31 @@ module Tramway
|
|
6
6
|
module ClassHelper
|
7
7
|
module_function
|
8
8
|
|
9
|
-
def decorator_class(object_or_array, decorator = nil)
|
9
|
+
def decorator_class(object_or_array, decorator = nil, namespace = nil)
|
10
10
|
raise_error_if_object_empty object_or_array, decorator
|
11
11
|
|
12
12
|
return decorator if decorator.present?
|
13
13
|
|
14
14
|
begin
|
15
|
-
class_name = decorator_class_name(object_or_array)
|
15
|
+
class_name = decorator_class_name(object_or_array, namespace)
|
16
16
|
class_name.constantize
|
17
17
|
rescue NameError
|
18
18
|
raise NameError, "You should define #{class_name} decorator class."
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def decorator_class_name(
|
23
|
-
klass = if Tramway::Decorators::CollectionDecorators.collection?(
|
24
|
-
|
22
|
+
def decorator_class_name(object_or_array_or_class, namespace)
|
23
|
+
klass = if Tramway::Decorators::CollectionDecorators.collection?(object_or_array_or_class)
|
24
|
+
object_or_array_or_class.first.class
|
25
|
+
elsif object_or_array_or_class.is_a?(Class)
|
26
|
+
object_or_array_or_class
|
25
27
|
else
|
26
|
-
|
28
|
+
object_or_array_or_class.class
|
27
29
|
end
|
28
30
|
|
29
|
-
Tramway::Decorators::NameBuilder.default_decorator_class_name(klass)
|
31
|
+
base_class_name = Tramway::Decorators::NameBuilder.default_decorator_class_name(klass)
|
32
|
+
|
33
|
+
namespace.present? ? "#{namespace.to_s.camelize}::#{base_class_name}" : base_class_name
|
30
34
|
end
|
31
35
|
|
32
36
|
# :reek:NilCheck { enabled: false }
|
@@ -9,7 +9,23 @@ module Tramway
|
|
9
9
|
def property(attribute)
|
10
10
|
@properties << attribute
|
11
11
|
|
12
|
-
|
12
|
+
define_method(attribute) do
|
13
|
+
if object.respond_to?(attribute)
|
14
|
+
object.public_send(attribute)
|
15
|
+
else
|
16
|
+
raise NoMethodError, "#{self.class}##{attribute} is not defined"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
set_method = "#{attribute}="
|
21
|
+
|
22
|
+
define_method(set_method) do |value|
|
23
|
+
if object.respond_to?(set_method)
|
24
|
+
object.public_send(set_method, value)
|
25
|
+
else
|
26
|
+
raise NoMethodError, "#{self.class}##{set_method} is not defined"
|
27
|
+
end
|
28
|
+
end
|
13
29
|
end
|
14
30
|
|
15
31
|
def properties(*attributes)
|
@@ -8,12 +8,12 @@ module Tramway
|
|
8
8
|
#
|
9
9
|
module DecorateHelper
|
10
10
|
# :reek:NilCheck { enabled: false } because checking for nil is not a type-checking issue but business logic
|
11
|
-
def tramway_decorate(object_or_array, decorator: nil)
|
11
|
+
def tramway_decorate(object_or_array, decorator: nil, namespace: nil)
|
12
12
|
return [] if Tramway::Decorators::CollectionDecorators.collection?(object_or_array) && object_or_array.empty?
|
13
13
|
|
14
14
|
return if object_or_array.nil?
|
15
15
|
|
16
|
-
Tramway::Decorators::ClassHelper.decorator_class(object_or_array, decorator).decorate object_or_array
|
16
|
+
Tramway::Decorators::ClassHelper.decorator_class(object_or_array, decorator, namespace).decorate object_or_array
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -6,8 +6,8 @@ module Tramway
|
|
6
6
|
module Helpers
|
7
7
|
# Provides navbar helpers for ActionView
|
8
8
|
module NavbarHelper
|
9
|
-
def tramway_navbar(**options)
|
10
|
-
initialize_navbar
|
9
|
+
def tramway_navbar(with_entities: true, **options)
|
10
|
+
initialize_navbar(with_entities:)
|
11
11
|
|
12
12
|
yield @navbar if block_given?
|
13
13
|
|
@@ -18,8 +18,8 @@ module Tramway
|
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
-
def initialize_navbar
|
22
|
-
@navbar = Tramway::Navbar.new self
|
21
|
+
def initialize_navbar(with_entities:)
|
22
|
+
@navbar = Tramway::Navbar.new self, with_entities:
|
23
23
|
end
|
24
24
|
|
25
25
|
def assign_navbar_items(options)
|
data/lib/tramway/navbar.rb
CHANGED
@@ -5,16 +5,18 @@ module Tramway
|
|
5
5
|
class Navbar
|
6
6
|
attr_reader :items, :context
|
7
7
|
|
8
|
-
def initialize(context)
|
8
|
+
def initialize(context, with_entities:)
|
9
9
|
@context = context
|
10
10
|
@items = { left: [], right: [] }
|
11
11
|
@filling = nil
|
12
12
|
|
13
|
-
|
13
|
+
if with_entities
|
14
|
+
entities = Tramway.config.entities
|
14
15
|
|
15
|
-
|
16
|
+
return unless entities.any?
|
16
17
|
|
17
|
-
|
18
|
+
preset_left entities
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
def left
|
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.5.
|
4
|
+
version: 0.5.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: 2025-
|
12
|
+
date: 2025-06-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: anyway_config
|
@@ -162,6 +162,8 @@ files:
|
|
162
162
|
- app/components/tailwinds/form/select_component.rb
|
163
163
|
- app/components/tailwinds/form/submit_button_component.html.haml
|
164
164
|
- app/components/tailwinds/form/submit_button_component.rb
|
165
|
+
- app/components/tailwinds/form/text_area_component.html.haml
|
166
|
+
- app/components/tailwinds/form/text_area_component.rb
|
165
167
|
- app/components/tailwinds/form/text_field_component.html.haml
|
166
168
|
- app/components/tailwinds/form/text_field_component.rb
|
167
169
|
- app/components/tailwinds/nav/item/button_component.html.haml
|
@@ -210,12 +212,14 @@ files:
|
|
210
212
|
- app/views/tramway/layouts/application.html.haml
|
211
213
|
- config/routes.rb
|
212
214
|
- config/tailwind.config.js
|
215
|
+
- lib/kaminari/helpers/tag.rb
|
213
216
|
- lib/rules/turbo_html_attributes_rules.rb
|
214
217
|
- lib/tasks/tramway_tasks.rake
|
215
218
|
- lib/tramway.rb
|
216
219
|
- lib/tramway/base_decorator.rb
|
217
220
|
- lib/tramway/base_form.rb
|
218
221
|
- lib/tramway/config.rb
|
222
|
+
- lib/tramway/configs/entities/page.rb
|
219
223
|
- lib/tramway/configs/entities/route.rb
|
220
224
|
- lib/tramway/configs/entity.rb
|
221
225
|
- lib/tramway/decorators/association.rb
|