tramway-admin 1.32.2.2 → 1.32.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -17
- data/app/inputs/multiple_file_input.rb +5 -0
- data/app/views/layouts/tramway/admin/shared/_navbar.html.haml +3 -3
- data/lib/tramway/admin.rb +1 -0
- data/lib/tramway/admin/generators/install_generator.rb +20 -0
- data/lib/tramway/admin/generators/model_generator.rb +109 -0
- data/lib/tramway/admin/generators/templates/decorator.rb.erb +52 -0
- data/lib/tramway/admin/generators/templates/form.rb.erb +22 -0
- data/lib/tramway/admin/navbar.rb +5 -5
- data/lib/tramway/admin/records_models.rb +7 -4
- data/lib/tramway/admin/singleton_models.rb +2 -2
- data/lib/tramway/admin/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f79d0aa9d04ed68aef471f0dc570d73e4d601270521be63081ae558a18a5f1be
|
4
|
+
data.tar.gz: 2d57de82ee1b753978a5ad2ac0534a0a93a67b2b41ff456606265ab12f3e5097
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c3a64f26bfcce263809d2a7b2a2d906b53966855866b90bb6500da180a09c577a59ea6a2d092d93f8a40a32b929989c5095f74884fcd5a542e87b7380d16f12
|
7
|
+
data.tar.gz: bfe8a88ee5c4c903f280a56bdeffdb2352e1953456f836aff20f66d11c52e15ce784e659472c201f4717ba0118458181fd1fa3573459dc5b9a00233c890a34e5
|
data/README.md
CHANGED
@@ -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
|
-
|
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
|
-
####
|
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
|
@@ -204,7 +211,15 @@ class Admin::YourModelForm < Tramway::Core::ApplicationForm
|
|
204
211
|
end
|
205
212
|
```
|
206
213
|
|
207
|
-
|
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
|
208
223
|
|
209
224
|
Tramway use gem [PgSearch](https://github.com/Casecommons/pg_search`) as search engine
|
210
225
|
|
@@ -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,7 +28,7 @@
|
|
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
|
data/lib/tramway/admin.rb
CHANGED
@@ -10,6 +10,7 @@ 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'
|
13
14
|
|
14
15
|
module Tramway
|
15
16
|
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_name}_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_name}_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,52 @@
|
|
1
|
+
class <%= class_name %>Decorator < Tramway::Core::ApplicationDecorator
|
2
|
+
# Associations you want to show in admin dashboard
|
3
|
+
# decorate_associations :messages, :posts
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def collections
|
7
|
+
# [ :all, :scope1, :scope2 ]
|
8
|
+
[ :all ]
|
9
|
+
end
|
10
|
+
|
11
|
+
def list_attributes
|
12
|
+
[
|
13
|
+
<% attributes.first(COLLECTION_ATTRIBUTE_LIMIT).each do |attr| -%>
|
14
|
+
:<%= attr %>,
|
15
|
+
<% end -%>
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
def show_attributes
|
20
|
+
[
|
21
|
+
<% attributes.each do |attr| -%>
|
22
|
+
:<%= attr %>,
|
23
|
+
<% end -%>
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
def show_associations
|
28
|
+
# Associations you want to show in admin dashboard
|
29
|
+
# [ :messages ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def list_filters
|
33
|
+
# {
|
34
|
+
# filter_name: {
|
35
|
+
# type: :select,
|
36
|
+
# select_collection: filter_collection,
|
37
|
+
# query: lambda do |list, value|
|
38
|
+
# list.where some_attribute: value
|
39
|
+
# end
|
40
|
+
# },
|
41
|
+
# date_filter_name: {
|
42
|
+
# type: :dates,
|
43
|
+
# query: lambda do |list, begin_date, end_date|
|
44
|
+
# list.where 'created_at > ? AND created_at < ?', begin_date, end_date
|
45
|
+
# end
|
46
|
+
# }
|
47
|
+
# }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# delegate_attributes :title
|
52
|
+
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
|
data/lib/tramway/admin/navbar.rb
CHANGED
@@ -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?
|
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,10 +6,10 @@ 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
|
-
@available_models[project][role].merge! model
|
12
|
+
@available_models[project][role].merge! model.to_s
|
13
13
|
end
|
14
14
|
end
|
15
15
|
@available_models = @available_models.with_indifferent_access
|
@@ -32,7 +32,10 @@ module Tramway::Admin::RecordsModels
|
|
32
32
|
end
|
33
33
|
end.flatten.compact
|
34
34
|
end
|
35
|
-
|
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
|
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.32.2.4
|
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-
|
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,6 +291,10 @@ 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
|