tramway-admin 1.32.2 → 1.33

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f29f2296ff326aa4bcdeb569ba6f9c0e8f9afd9a307b53d9c79860bf1a98b9ea
4
- data.tar.gz: cfb493f04f4240ff6234c2a94d927c5a5f8e8a8b458e7204d4d814bcd00b2ea1
3
+ metadata.gz: cd63c513ef46a0b0b80b96cc51f28c1ba69f1bc70c5e426da288887f4885cad7
4
+ data.tar.gz: '03884d0741244a9d7d33b0716c351fa68c05f9df09eb8a6b16994315c2940cfc'
5
5
  SHA512:
6
- metadata.gz: b8bb82d5139135bbbf8608105d3ba4bcf3a75ad53a24ac653e76f7bcbad62f683fcadf5a86d0f350fb9a6e20fe545751f8cfbd46dbfd2039a82bb778a3fb8724
7
- data.tar.gz: 7515b06e5c9534eb2c6099b32287b0e6e3ea2efd232af314eccb29b59a1c55907585c29281624fbd9a275ae381542406add206af599103cfc4b0b2287f48be89
6
+ metadata.gz: 560e2d59668bfe3559a225dc03163bf2a61f032600e05568456d1c10ee97a7a6c0375c1ade4358fa5a536572582ed3c51c27a6f1cf144c433e3db3aaca254157
7
+ data.tar.gz: 61e0eda22ab3383e748a451a997303d9bd9130e23a7bb6575c056598838994a598642ee5ebcbc748464e47208ef67ba79c26973bea16e50846ff198336cce507
data/README.md CHANGED
@@ -43,7 +43,7 @@ Rails.application.routes.draw do
43
43
  end
44
44
  ```
45
45
 
46
- #### 4. Then make `tramway-core` installation. [How-to](https://github.com/ulmic/tramway-dev/blob/develop/tramway-core/README.md#installation)
46
+ #### 4. Then make `tramway-core` installation. [How-to](https://github.com/Purple-Magic/tramway-core/blob/develop/README.md#installation)
47
47
 
48
48
 
49
49
  #### 5. And then execute:
@@ -88,31 +88,46 @@ Tramway::Admin.navbar_structure(
88
88
  project: :your_application_name
89
89
  )
90
90
  ```
91
+ #### 9. Create decorators and forms for all available_models.
92
+ You can run generator that will create all necessary files
93
+ ```bash
94
+ $ rails g tramway:admin:install
95
+ ```
96
+ Or generate decorator and form for only one model
97
+ ```bash
98
+ $ rails g tramway:admin:model Coworking
99
+ ```
100
+ If you're using several user roles in your admin dashboard, then you can specify scope for the form(default scope is `admin`)
101
+ ```bash
102
+ $ rails g tramway:admin:install --user-role=partner
103
+ ```
91
104
 
92
- #### 9. Create decorator for models
105
+ Or you can create forms and decorators manually as it written below:
106
+
107
+ #### 9a. Create decorator for models [manual option]
93
108
 
94
109
  *app/decorators/your_model_decorator.rb*
95
110
  ```ruby
96
111
  class YourModelDecorator < Tramway::Core::ApplicationDecorator
97
112
  decorate_associations :messages, :posts
98
-
113
+
99
114
  class << self
100
115
  def collections
101
116
  [ :all, :scope1, :scope2 ]
102
117
  end
103
-
118
+
104
119
  def list_attributes
105
120
  [ :begin_date, :end_date ]
106
121
  end
107
-
122
+
108
123
  def show_attributes
109
124
  [ :begin_date, :end_date ]
110
125
  end
111
-
126
+
112
127
  def show_associations
113
128
  [ :messages ]
114
129
  end
115
-
130
+
116
131
  def list_filters
117
132
  {
118
133
  filter_name: {
@@ -131,7 +146,7 @@ class YourModelDecorator < Tramway::Core::ApplicationDecorator
131
146
  }
132
147
  end
133
148
  end
134
-
149
+
135
150
  delegate_attributes :title
136
151
  end
137
152
  ```
@@ -171,15 +186,7 @@ en:
171
186
  end_date Your end date filter
172
187
  ```
173
188
 
174
- #### 10. Add inheritance to YourModel
175
-
176
- *app/models/your_model.rb*
177
- ```ruby
178
- class YourModel < Tramway::Core::ApplicationRecord
179
- end
180
- ```
181
-
182
- #### 11. Create `Admin::YourModelForm`
189
+ #### 9b. Create `Admin::YourModelForm` [manual option]
183
190
 
184
191
  *app/forms/admin/your_model_form.rb
185
192
  ```ruby
@@ -192,13 +199,27 @@ class Admin::YourModelForm < Tramway::Core::ApplicationForm
192
199
  logo: :file,
193
200
  description: :ckeditor,
194
201
  date: :date_picker,
195
- text: :text
202
+ text: :text,
203
+ birth_date: {
204
+ type: :default,
205
+ input_options: {
206
+ hint: 'It should be more than 18'
207
+ }
208
+ }
196
209
  end
197
210
  end
198
211
  end
199
212
  ```
200
213
 
201
- ### 12. You can add search to your index page
214
+ #### 10. Add inheritance to YourModel
215
+
216
+ *app/models/your_model.rb*
217
+ ```ruby
218
+ class YourModel < Tramway::Core::ApplicationRecord
219
+ end
220
+ ```
221
+
222
+ ### 11. You can add search to your index page
202
223
 
203
224
  Tramway use gem [PgSearch](https://github.com/Casecommons/pg_search`) as search engine
204
225
 
@@ -450,5 +471,36 @@ en:
450
471
 
451
472
  * **Model or Form is not available** - `params[:model]` or `params[:form]` is empty **OR** current user does not have access to model or form in `params[:model]` or `params[:form]`
452
473
 
474
+ ## Good features
475
+
476
+ ### Get actions log in admin panel
477
+
478
+ Tramway uses [audited](https://github.com/collectiveidea/audited) to log actions of models. That's why all we need it's creating view for model `Audited::Audit`
479
+
480
+ #### 1. Add Audited::Audit model to available models
481
+
482
+ *config/initializers/tramway.rb*
483
+ ```
484
+ Tramway::Admin.set_available_models(
485
+ Audited::Audit,
486
+ project: :your_project_name
487
+ )
488
+ ```
489
+
490
+ #### 2. Add this model to navbar
491
+
492
+ ```
493
+ Tramway::Admin.set_navbar_structure(
494
+ Audited::Audit,
495
+ project: :your_project_name
496
+ )
497
+ ```
498
+
499
+ #### 3. Generate decorator for Audited::Audit
500
+
501
+ ```
502
+ rails g tramway:admin:model Audited::Audit
503
+ ```
504
+
453
505
  ## License
454
506
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -92,7 +92,12 @@ module Tramway
92
92
  end
93
93
 
94
94
  def admin_form_class
95
- "::#{current_admin.role.camelize}::#{model_class}Form".constantize
95
+ class_name = "::#{current_admin.role.camelize}::#{model_class}Form"
96
+ if defined? class_name
97
+ class_name.constantize
98
+ else
99
+ raise "Tramway::Admin - you should create form for role `#{current_admin.role}` to edit #{model_class} model. It should be named #{class_name}"
100
+ end
96
101
  end
97
102
 
98
103
  def model_given?
@@ -16,6 +16,7 @@ module Tramway
16
16
  include ::Tramway::Admin::ActionsHelper
17
17
  include ::Tramway::Collections::Helper
18
18
  include ::Tramway::Core::CopyToClipboardHelper
19
+ include ::Tramway::Admin::TramwayModelHelper
19
20
 
20
21
  def object_type(object)
21
22
  object_class_name = if object.class.ancestors.include? ::Tramway::Core::ApplicationDecorator
@@ -99,5 +99,9 @@ module Tramway::Admin
99
99
  }
100
100
  end
101
101
  end
102
+
103
+ def is_there_any_filters?(model_class)
104
+ decorator_class(model_class).list_filters&.any?
105
+ end
102
106
  end
103
107
  end
@@ -0,0 +1,5 @@
1
+ class MultipleFileInput < SimpleForm::Inputs::FileInput
2
+ def input(wrapper_options)
3
+ super(wrapper_options.merge! multiple: true)
4
+ end
5
+ end
@@ -11,8 +11,8 @@
11
11
  %ul.navbar-nav
12
12
  - ::Tramway::Admin.navbar_items_for(@application_engine || @application.name, role: current_admin.role)&.each do |item|
13
13
  - case item.keys.first
14
- - when Class
15
- - model = item.keys.first
14
+ - when Class, String
15
+ - model = item.keys.first.is_a?(String) ? item.keys.first.constantize : item.keys.first
16
16
  - case item.values.first
17
17
  - when :singleton
18
18
  = model_menu_item model: model, route: ::Tramway::Admin::Engine.routes.url_helpers.singleton_path(model: model)
@@ -28,10 +28,13 @@
28
28
  - if sub_item.values.first == :singleton
29
29
  = dropdown_model_item model: model, route: ::Tramway::Admin::Engine.routes.url_helpers.singleton_path(model: model)
30
30
  - if sub_item.values.first == :record
31
- = dropdown_model_item model: model, route: ::Tramway::Admin::Engine.routes.url_helpers.records_path(model: model, scope: decorator_class(model).collections.first), pluralize: plural(model.model_name).capitalize
31
+ = dropdown_model_item model: model, route: ::Tramway::Admin::Engine.routes.url_helpers.records_path(model: model, scope: decorator_class(model).collections.first), pluralize: plural(model.constantize.model_name).capitalize
32
32
 
33
33
  %ul.nav.navbar-nav.ml-auto
34
34
  - if current_admin
35
+ %li.nav-item
36
+ %span.nav-link
37
+ = "#{current_admin.first_name} #{current_admin.last_name}"
35
38
  - if @notifications_count.present?
36
39
  - if @notifications_count > 0
37
40
  %li.nav-item.dropdown.notifications
@@ -24,10 +24,11 @@
24
24
  &nbsp;&nbsp;
25
25
  = delete_button url: current_model_record_path(record.id), form_options: { class: :smart_button }, button_options: { class: 'btn btn-xs btn-danger' } do
26
26
  = fa_icon 'trash-alt'
27
- %br
28
- %br
29
- .btn-group{ data: { toggle: :buttons } }
30
- - record.model.class.state_machines.keys.each do |state_method|
31
- - unless state_method == :state
32
- = state_events_buttons record, state_method: state_method, model_param_name: :record, controller: 'tramway/admin/records', action: :update, parameters: { redirect: current_model_records_path(page: params[:page], scope: params[:scope], filter: params[:filter], focus: focus_selector(index)), model: record.class.model_name }, button_options: { class: :smart_button }
27
+ - if tramway_model?(model_class)
28
+ %br
29
+ %br
30
+ .btn-group{ data: { toggle: :buttons } }
31
+ - record.model.class.state_machines.keys.each do |state_method|
32
+ - unless state_method == :state
33
+ = state_events_buttons record, state_method: state_method, model_param_name: :record, controller: 'tramway/admin/records', action: :update, parameters: { redirect: current_model_records_path(page: params[:page], scope: params[:scope], filter: params[:filter], focus: focus_selector(index)), model: record.class.model_name }, button_options: { class: :smart_button }
33
34
  = paginate @records, theme: 'twitter-bootstrap-4'
@@ -1,4 +1,4 @@
1
- - if searchable_model?(model_class) || decorator_class(model_class).list_filters.any?
1
+ - if searchable_model?(model_class) || is_there_any_filters?(model_class)
2
2
  .col-md-8
3
3
  .search
4
4
  = form_tag records_path, class: 'form-inline', method: :get do |f|
@@ -5,7 +5,7 @@
5
5
  - tabs = get_collection
6
6
  .page-header
7
7
  .row
8
- - search_render_show = searchable_model?(model_class) || decorator_class(model_class).list_filters.any?
8
+ - search_render_show = searchable_model?(model_class) || is_there_any_filters?(model_class)
9
9
  %div{ class: "col-md-#{search_render_show ? 4 : 12}" }
10
10
  %h1
11
11
  = current_title
@@ -4,5 +4,6 @@
4
4
  %td
5
5
  = value
6
6
  %td
7
- - if attribute_name.to_s != 'state' && object.model.class.state_machines.keys.include?(attribute_name.to_sym)
8
- = state_events_buttons object, state_method: attribute_name, model_param_name: :record, controller: 'tramway/admin/records', action: :update, parameters: { model: object.class.model_name }, button_options: { class: :smart_button }
7
+ - if tramway_model?(model_class)
8
+ - if attribute_name.to_s != 'state' && object.model.class.state_machines.keys.include?(attribute_name.to_sym)
9
+ = state_events_buttons object, state_method: attribute_name, model_param_name: :record, controller: 'tramway/admin/records', action: :update, parameters: { model: object.class.model_name }, button_options: { class: :smart_button }
@@ -10,6 +10,8 @@ require 'tramway/admin/notifications'
10
10
  require 'tramway/admin/welcome_page_actions'
11
11
  require 'tramway/admin/navbar'
12
12
  require 'tramway/error'
13
+ require 'tramway/admin/generators/install_generator'
14
+ require 'tramway/admin/tramway_model_helper'
13
15
 
14
16
  module Tramway
15
17
  Auth.layout_path = 'tramway/admin/application'
@@ -0,0 +1,20 @@
1
+ require 'rails/generators'
2
+ require 'tramway/admin/generators/model_generator'
3
+
4
+ module Tramway
5
+ module Admin
6
+ module Generators
7
+ class InstallGenerator < ::Rails::Generators::Base
8
+ source_root File.expand_path('templates', __dir__)
9
+ class_option :user_role, type: :string, default: 'admin'
10
+
11
+ def run_decorator_generators
12
+ project = Tramway::Core.application.name
13
+ ::Tramway::Admin.available_models_for(project).map do |model|
14
+ generate 'tramway:admin:model', model.to_s, "--user-role=#{options[:user_role]}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,109 @@
1
+ require 'rails/generators/named_base'
2
+
3
+ module Tramway
4
+ module Admin
5
+ module Generators
6
+ class ModelGenerator < ::Rails::Generators::NamedBase
7
+ source_root File.expand_path('templates', __dir__)
8
+ class_option :user_role, type: :string, default: 'admin'
9
+
10
+ COLLECTION_ATTRIBUTE_LIMIT = 4 # limiting columns in #index table
11
+ ATTRIBUTE_TYPE_MAPPING = {
12
+ date: :date_picker,
13
+ datetime: :date_picker,
14
+ time: :date_picker,
15
+ text: :text,
16
+ string: :string,
17
+ uuid: :string,
18
+ float: :float,
19
+ integer: :integer,
20
+ boolean: :boolean,
21
+ }
22
+ DEFAULT_FIELD_TYPE = :string
23
+ READ_ONLY_ATTRIBUTES = %w[id uuid created_at updated_at]
24
+
25
+ def run_decorator_generator
26
+ template(
27
+ 'decorator.rb.erb',
28
+ Rails.root.join("app/decorators/#{file_path}_decorator.rb"),
29
+ )
30
+ end
31
+
32
+ def run_forms_generator
33
+ template(
34
+ 'form.rb.erb',
35
+ Rails.root.join("app/forms/#{user_role}/#{file_path}_form.rb"),
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def user_role
42
+ options[:user_role]
43
+ end
44
+
45
+ def attributes
46
+ # TODO: this for model associations, but they probably should be handled differently
47
+ # klass.reflections.keys +
48
+
49
+ klass.columns.map(&:name) -
50
+ redundant_attributes
51
+ end
52
+
53
+ def form_attributes
54
+ attributes - READ_ONLY_ATTRIBUTES
55
+ end
56
+
57
+ def form_type(attribute)
58
+ type = column_type_for_attribute(attribute.to_s)
59
+
60
+ if type
61
+ ATTRIBUTE_TYPE_MAPPING.fetch(type, DEFAULT_FIELD_TYPE)
62
+ # else
63
+ # association_type(attribute)
64
+ end
65
+ end
66
+
67
+ def redundant_attributes
68
+ klass.reflections.keys.flat_map do |relationship|
69
+ redundant_attributes_for(relationship)
70
+ end.compact
71
+ end
72
+
73
+ def redundant_attributes_for(relationship)
74
+ case association_type(relationship)
75
+ when :polymorphic
76
+ [relationship + '_id', relationship + '_type']
77
+ when :belongs_to
78
+ relationship + '_id'
79
+ end
80
+ end
81
+
82
+ def association_type(attribute)
83
+ relationship = klass.reflections[attribute.to_s]
84
+ if relationship.has_one?
85
+ :has_one
86
+ elsif relationship.collection?
87
+ :has_many
88
+ elsif relationship.polymorphic?
89
+ :polymorphic
90
+ else
91
+ :belongs_to
92
+ end
93
+ end
94
+
95
+ def column_type_for_attribute(attr)
96
+ column_types(attr)
97
+ end
98
+
99
+ def column_types(attr)
100
+ klass.columns.find { |column| column.name == attr }.try(:type)
101
+ end
102
+
103
+ def klass
104
+ @klass ||= Object.const_get(class_name)
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,56 @@
1
+ class <%= class_name %>Decorator < Tramway::Core::ApplicationDecorator
2
+ # Associations you want to show in admin dashboard
3
+ # decorate_associations :messages, :posts
4
+
5
+ delegate_attributes(
6
+ <% attributes.each do |attr| -%>
7
+ :<%= attr %>,
8
+ <% end -%>
9
+ )
10
+
11
+ class << self
12
+ def collections
13
+ # [ :all, :scope1, :scope2 ]
14
+ [ :all ]
15
+ end
16
+
17
+ def list_attributes
18
+ [
19
+ <% attributes.first(COLLECTION_ATTRIBUTE_LIMIT).each do |attr| -%>
20
+ :<%= attr %>,
21
+ <% end -%>
22
+ ]
23
+ end
24
+
25
+ def show_attributes
26
+ [
27
+ <% attributes.each do |attr| -%>
28
+ :<%= attr %>,
29
+ <% end -%>
30
+ ]
31
+ end
32
+
33
+ def show_associations
34
+ # Associations you want to show in admin dashboard
35
+ # [ :messages ]
36
+ end
37
+
38
+ def list_filters
39
+ # {
40
+ # filter_name: {
41
+ # type: :select,
42
+ # select_collection: filter_collection,
43
+ # query: lambda do |list, value|
44
+ # list.where some_attribute: value
45
+ # end
46
+ # },
47
+ # date_filter_name: {
48
+ # type: :dates,
49
+ # query: lambda do |list, begin_date, end_date|
50
+ # list.where 'created_at > ? AND created_at < ?', begin_date, end_date
51
+ # end
52
+ # }
53
+ # }
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,22 @@
1
+ class <%= user_role.capitalize %>::<%= class_name %>Form < Tramway::Core::ApplicationForm
2
+ properties <%= form_attributes.map{ |a| ":#{a}" }.join(', ') %>
3
+
4
+ def initialize(object)
5
+ super(object).tap do
6
+ # Here is the mapping from model attributes to simple_form inputs.
7
+ # form_properties title: :string,
8
+ # logo: :file,
9
+ # description: :ckeditor,
10
+ # games: :association,
11
+ # date: :date_picker,
12
+ # text: :text,
13
+ # birth_date: {
14
+ # type: :default,
15
+ # input_options: {
16
+ # hint: 'It should be more than 18'
17
+ # }
18
+ # }
19
+ form_properties <%= form_attributes.map{ |attr| "#{attr}: :#{form_type(attr)}"}.join(",\n ") %>
20
+ end
21
+ end
22
+ end
@@ -9,7 +9,7 @@ module Tramway::Admin::Navbar
9
9
  def navbar_items_for(project, role:)
10
10
  project = project.underscore.to_sym unless project.is_a? Symbol
11
11
  @navbar_structure[project]&.map do |item|
12
- if item.is_a? Class
12
+ if item.is_a?(Class) || item.is_a?(String)
13
13
  should_be_in_navbar_as item, project, role
14
14
  elsif item.is_a? Hash
15
15
  sub_items = item.values.first.map do |sub_item|
@@ -23,10 +23,10 @@ module Tramway::Admin::Navbar
23
23
  private
24
24
 
25
25
  def should_be_in_navbar_as(item, project, role)
26
- if singleton_models_for(project, role: role).include?(item)
27
- { item => :singleton }
28
- elsif available_models_for(project, role: role).include?(item)
29
- { item => :record }
26
+ if singleton_models_for(project, role: role).map(&:to_s).include?(item.to_s)
27
+ { item.to_s => :singleton }
28
+ elsif available_models_for(project, role: role).map(&:to_s).include?(item.to_s)
29
+ { item.to_s => :record }
30
30
  elsif item.is_a? Symbol
31
31
  :divider
32
32
  end
@@ -6,8 +6,8 @@ module Tramway::Admin::RecordsModels
6
6
  @available_models[project] ||= {}
7
7
  @available_models[project][role] ||= {}
8
8
  models.each do |model|
9
- if model.class == Class
10
- @available_models[project][role].merge! model => %i[index show update create destroy]
9
+ if model.class == Class || model.class == String
10
+ @available_models[project][role].merge! model.to_s => %i[index show update create destroy]
11
11
  elsif model.class == Hash
12
12
  @available_models[project][role].merge! model
13
13
  end
@@ -32,7 +32,10 @@ module Tramway::Admin::RecordsModels
32
32
  end
33
33
  end.flatten.compact
34
34
  end
35
- models
35
+ # TODO: somehow cache results?
36
+ models.map do |model|
37
+ model.class == String ? model.constantize : model
38
+ end
36
39
  end
37
40
 
38
41
  def available_models(role:)
@@ -7,9 +7,9 @@ module Tramway::Admin::SingletonModels
7
7
  @singleton_models[project][role] ||= {}
8
8
  models.each do |model|
9
9
  if model.class == Class
10
- @singleton_models[project][role].merge! model => %i[index show update create destroy]
10
+ @singleton_models[project][role].merge! model.to_s => %i[index show update create destroy]
11
11
  elsif model.class == Hash
12
- @singleton_models[project][role].merge! model
12
+ @singleton_models[project][role].merge! model.to_s
13
13
  end
14
14
  end
15
15
  @singleton_models = @singleton_models.with_indifferent_access
@@ -0,0 +1,5 @@
1
+ module Tramway::Admin::TramwayModelHelper
2
+ def tramway_model?(model_class)
3
+ model_class.ancestors.include? Tramway::Core::ApplicationRecord
4
+ end
5
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Tramway
4
4
  module Admin
5
- VERSION = '1.32.2'
5
+ VERSION = '1.33'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tramway-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.32.2
4
+ version: '1.33'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Kalashnikov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-08 00:00:00.000000000 Z
11
+ date: 2020-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tramway-core
@@ -252,6 +252,7 @@ files:
252
252
  - app/helpers/tramway/admin/records_helper.rb
253
253
  - app/helpers/tramway/admin/russian_cases_helper.rb
254
254
  - app/helpers/tramway/admin/singleton_helper.rb
255
+ - app/inputs/multiple_file_input.rb
255
256
  - app/jobs/tramway/admin/application_job.rb
256
257
  - app/mailers/tramway/admin/application_mailer.rb
257
258
  - app/models/tramway/user/user.rb
@@ -290,11 +291,16 @@ files:
290
291
  - lib/tramway/admin/additional_buttons.rb
291
292
  - lib/tramway/admin/engine.rb
292
293
  - lib/tramway/admin/forms.rb
294
+ - lib/tramway/admin/generators/install_generator.rb
295
+ - lib/tramway/admin/generators/model_generator.rb
296
+ - lib/tramway/admin/generators/templates/decorator.rb.erb
297
+ - lib/tramway/admin/generators/templates/form.rb.erb
293
298
  - lib/tramway/admin/navbar.rb
294
299
  - lib/tramway/admin/notifications.rb
295
300
  - lib/tramway/admin/record_routes_helper.rb
296
301
  - lib/tramway/admin/records_models.rb
297
302
  - lib/tramway/admin/singleton_models.rb
303
+ - lib/tramway/admin/tramway_model_helper.rb
298
304
  - lib/tramway/admin/version.rb
299
305
  - lib/tramway/admin/welcome_page_actions.rb
300
306
  homepage: https://github.com/kalashnikovisme/tramway-dev