tiny_admin 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d203e48b821f195f95847a646e32787c9ffd953212326f64e65ca09d563ed55e
4
- data.tar.gz: a133ad428942d240ec8852e4885e12a51bc6a96f9a4bcf426470180671dddf6f
3
+ metadata.gz: 6eb4a218cc1a4ff6acc940c402d74202582d2092b39f920e6551e5b395da752e
4
+ data.tar.gz: fb137625f9f5faa5b33dd5c7633a68eec7a4a2d2bb31db6f70758d6ed9ec3750
5
5
  SHA512:
6
- metadata.gz: 8955bf003179333debcf4c43dd7091b4d81fc9c1e90a6116119dc33f51b4ab7dca394d90f6f8aa6bb0385339dc5eb07b64bd546f0a92e02497d5c000cc835769
7
- data.tar.gz: 5cabb3dc010e73b416068cca3afda56dc07ac7b024c70d734b9409298d2082798a8e5e276d892be81e82dcbfa68bad20360f0d99e4c8e7199a7bdb5067f72124
6
+ metadata.gz: fd7800ab65bd0e92ce5646210f08823d031fdd217f5230bc99207a0e00375b068ad2337805ddce196ca317fe6f0df60ad3e209fc885e31c765c68c125f83d900
7
+ data.tar.gz: f1df2bd938781a04c4af36c9653a7efffcc075cf72accd8f9fbaedbcc74286d860a1953bab159ec833c6a2cf5851a00633f555966b915fedec625af9ef2f85fa
data/README.md CHANGED
@@ -16,7 +16,7 @@ Please ⭐ if you like it.
16
16
 
17
17
  ## Install
18
18
 
19
- - Add to your Gemfile: `gem 'tiny_admin', '~> 0.3'`
19
+ - Add to your Gemfile: `gem 'tiny_admin', '~> 0.4'`
20
20
  - Mount the app in a route (check some examples with: Hanami, Rails, Roda and standalone in [extra](extra))
21
21
  + in Rails, update _config/routes.rb_: `mount TinyAdmin::Router => '/admin'`
22
22
  - Configure the dashboard using `TinyAdmin.configure` and/or `TinyAdmin.configure_from_file` (see [configuration](#configuration) below):
@@ -82,6 +82,12 @@ root:
82
82
  redirect: posts
83
83
  ```
84
84
 
85
+ `helper_class` (String): class or module with helper methods, used for attributes' formatters.
86
+
87
+ `page_not_found` (String): a view object to render when a missing page is requested.
88
+
89
+ `record_not_found` (String): a view object to render when a missing record is requested.
90
+
85
91
  `authentication` (Hash): define the authentication method, properties:
86
92
  - `plugin` (String): a plugin class to use (ex. `TinyAdmin::Plugins::SimpleAuth`);
87
93
  - `password` (String): a password hash used by _SimpleAuth_ plugin (generated with `Digest::SHA512.hexdigest("some password")`).
@@ -175,65 +181,64 @@ end
175
181
  ---
176
182
  authentication:
177
183
  plugin: TinyAdmin::Plugins::SimpleAuth
178
- # password: 'f1891cea80fc05e433c943254c6bdabc159577a02a7395df...' <= SHA512
179
- page_not_found: Admin::PageNotFound
180
- record_not_found: Admin::RecordNotFound
184
+ # password: 'f1891cea80fc05e433c943254c6bdabc159577a02a7395dfebbfbc4f7661d4af56f2d372131a45936de40160007368a56ef216a30cb202c66d3145fd24380906'
181
185
  root:
182
- title: 'Tiny Admin'
183
- page: Admin::PageRoot
184
- # redirect: posts
186
+ title: Test Admin
187
+ # page: RootPage
188
+ helper_class: AdminHelper
189
+ page_not_found: PageNotFound
190
+ record_not_found: RecordNotFound
185
191
  sections:
186
192
  - slug: google
187
193
  name: Google.it
188
194
  type: url
189
195
  url: https://www.google.it
190
196
  options:
191
- target: '_blank'
192
- - slug: stats
193
- name: Stats
197
+ target: _blank
198
+ - slug: sample
199
+ name: Sample page
194
200
  type: page
195
- page: Admin::Stats
201
+ page: SamplePage
196
202
  - slug: authors
197
203
  name: Authors
198
204
  type: resource
199
205
  model: Author
200
- repository: Admin::AuthorsRepo
201
206
  collection_actions:
202
- - latests: Admin::LatestAuthorsAction
207
+ - sample_col: SampleCollectionAction
203
208
  member_actions:
204
- - csv_export: Admin::CsvExportAuthorAction
205
- # only:
206
- # - index
207
- # options:
208
- # - hidden
209
+ - sample_mem: SampleMemberAction
209
210
  - slug: posts
210
211
  name: Posts
211
212
  type: resource
212
213
  model: Post
213
214
  index:
214
- sort:
215
- - author_id DESC
216
- pagination: 15
215
+ pagination: 5
217
216
  attributes:
218
217
  - id
219
218
  - title
220
219
  - field: author_id
221
220
  link_to: authors
222
- - state
221
+ - category: upcase
222
+ - state: downcase
223
223
  - published
224
- - dt
224
+ - position: round, 1
225
+ - dt: to_date
225
226
  - field: created_at
226
- converter: Admin::Utils
227
+ converter: AdminUtils
227
228
  method: datetime_formatter
229
+ - updated_at: strftime, %Y%m%d %H:%M
228
230
  filters:
229
231
  - title
230
- - field: state
232
+ - author_id
233
+ - field: category
231
234
  type: select
232
235
  values:
233
- - available
234
- - unavailable
235
- - arriving
236
+ - news
237
+ - sport
238
+ - tech
236
239
  - published
240
+ - dt
241
+ - created_at
237
242
  show:
238
243
  attributes:
239
244
  - id
@@ -243,7 +248,8 @@ sections:
243
248
  link_to: authors
244
249
  - category
245
250
  - published
246
- - state
251
+ - position: format, %f
252
+ - dt
247
253
  - created_at
248
254
  style_links:
249
255
  - href: /bootstrap.min.css
@@ -5,12 +5,21 @@ module TinyAdmin
5
5
  class BasicAction
6
6
  include Utils
7
7
 
8
- attr_reader :params, :path, :repository
9
-
10
- def initialize(repository, path:, params:)
11
- @repository = repository
12
- @path = path
13
- @params = params
8
+ def attribute_options(options)
9
+ options&.each_with_object({}) do |field, result|
10
+ field_data =
11
+ if field.is_a?(Hash)
12
+ if field.one?
13
+ field, method = field.first
14
+ { field.to_s => { field: field.to_s, method: method } }
15
+ else
16
+ { field[:field] => field }
17
+ end
18
+ else
19
+ { field => { field: field } }
20
+ end
21
+ result.merge!(field_data)
22
+ end
14
23
  end
15
24
  end
16
25
  end
@@ -3,7 +3,15 @@
3
3
  module TinyAdmin
4
4
  module Actions
5
5
  class Index < BasicAction
6
- attr_reader :current_page, :fields_options, :filters_list, :pagination, :pages, :query_string, :sort
6
+ attr_reader :current_page,
7
+ :fields_options,
8
+ :filters_list,
9
+ :pagination,
10
+ :pages,
11
+ :params,
12
+ :query_string,
13
+ :repository,
14
+ :sort
7
15
 
8
16
  def call(app:, context:, options:, actions:)
9
17
  evaluate_options(options)
@@ -27,9 +35,9 @@ module TinyAdmin
27
35
  private
28
36
 
29
37
  def evaluate_options(options)
30
- @fields_options = options[:attributes]&.each_with_object({}) do |field, result|
31
- result.merge!(field.is_a?(Hash) ? { field[:field] => field } : { field => { field: field } })
32
- end
38
+ @fields_options = attribute_options(options[:attributes])
39
+ @params = context.request.params
40
+ @repository = context.repository
33
41
  @filters_list = options[:filters]
34
42
  @pagination = options[:pagination] || 10
35
43
  @sort = options[:sort] || ['id']
@@ -42,8 +50,8 @@ module TinyAdmin
42
50
  filters = (filters_list || []).map { _1.is_a?(Hash) ? _1 : { field: _1 } }
43
51
  filters = filters.each_with_object({}) { |filter, result| result[filter[:field]] = filter }
44
52
  values = (params['q'] || {})
45
- fields.each_with_object({}) do |field, result|
46
- result[field] = { value: values[field.name], filter: filters[field.name] } if filters.key?(field.name)
53
+ fields.each_with_object({}) do |(name, field), result|
54
+ result[field] = { value: values[name], filter: filters[name] } if filters.key?(name)
47
55
  end
48
56
  end
49
57
 
@@ -3,17 +3,21 @@
3
3
  module TinyAdmin
4
4
  module Actions
5
5
  class Show < BasicAction
6
+ attr_reader :repository
7
+
6
8
  def call(app:, context:, options:, actions:)
7
- fields_options = (options[:attributes] || []).each_with_object({}) do |field, result|
8
- result.merge!(field.is_a?(Hash) ? { field[:field] => field } : { field => { field: field } })
9
- end
9
+ @repository = context.repository
10
+ fields_options = attribute_options(options[:attributes])
10
11
  record = repository.find(context.reference)
11
- prepare_record = ->(record_data) { repository.show_record_attrs(record_data, fields: fields_options) }
12
- fields = repository.fields(options: fields_options)
13
12
 
14
13
  prepare_page(Views::Actions::Show) do |page|
15
- page.setup_record(record: record, fields: fields, prepare_record: prepare_record)
16
- page.update_attributes(actions: actions, title: repository.show_title(record))
14
+ page.update_attributes(
15
+ actions: actions,
16
+ fields: repository.fields(options: fields_options),
17
+ prepare_record: ->(record_data) { repository.show_record_attrs(record_data, fields: fields_options) },
18
+ record: record,
19
+ title: repository.show_title(record)
20
+ )
17
21
  end
18
22
  rescue Plugins::BaseRepository::RecordNotFound => _e
19
23
  prepare_page(options[:record_not_found_page] || Views::Pages::RecordNotFound)
@@ -4,6 +4,6 @@ module TinyAdmin
4
4
  class Context
5
5
  include Singleton
6
6
 
7
- attr_accessor :reference, :slug
7
+ attr_accessor :reference, :repository, :request, :router, :settings, :slug
8
8
  end
9
9
  end
@@ -4,7 +4,7 @@ module TinyAdmin
4
4
  class Field
5
5
  attr_reader :name, :options, :title, :type
6
6
 
7
- def initialize(type:, name:, title:, options: {})
7
+ def initialize(name:, title:, type:, options: {})
8
8
  @type = type
9
9
  @name = name
10
10
  @title = title || name
@@ -12,8 +12,14 @@ module TinyAdmin
12
12
  end
13
13
 
14
14
  class << self
15
- def create_field(name:, title:, type: nil, options: {})
16
- new(type: type, name: name, title: title, options: options)
15
+ def create_field(name:, title: nil, type: nil, options: {})
16
+ field_name = name.to_s
17
+ new(
18
+ name: field_name,
19
+ title: title || field_name.respond_to?(:humanize) ? field_name.humanize : field_name.tr('_', ' ').capitalize,
20
+ type: type || :string,
21
+ options: options
22
+ )
17
23
  end
18
24
  end
19
25
  end
@@ -4,17 +4,11 @@ module TinyAdmin
4
4
  module Plugins
5
5
  class ActiveRecordRepository < BaseRepository
6
6
  def index_record_attrs(record, fields: nil)
7
- return record.attributes.transform_values(&:to_s) if !fields || fields.empty?
7
+ return record.attributes.transform_values(&:to_s) unless fields
8
8
 
9
- record.attributes.slice(*fields.keys).each_with_object({}) do |(key, value), result|
10
- field_data = fields[key]
11
- result[key] =
12
- if field_data[:converter] && field_data[:method]
13
- converter = Object.const_get(field_data[:converter])
14
- converter.send(field_data[:method], value)
15
- else
16
- value&.to_s
17
- end
9
+ fields.to_h do |name, field|
10
+ value = record.send(name)
11
+ [name, translate_value(value, field)]
18
12
  end
19
13
  end
20
14
 
@@ -24,25 +18,19 @@ module TinyAdmin
24
18
  end
25
19
 
26
20
  def fields(options: nil)
27
- opts = options || {}
28
- columns = model.columns
29
- if !opts.empty?
30
- extra_fields = opts.keys - model.column_names
31
- raise "Some requested fields are not available: #{extra_fields.join(', ')}" if extra_fields.any?
32
-
33
- columns = opts.keys.map { |field| columns.find { _1.name == field } }
34
- end
35
- columns.map do |column|
36
- name = column.name
37
- type = opts.dig(column.name, :type) || column.type
38
- TinyAdmin::Field.create_field(name: name, title: name.humanize, type: type, options: opts[name])
21
+ if options
22
+ types = model.columns.to_h { [_1.name, _1.type] }
23
+ options.each_with_object({}) do |(name, field_options), result|
24
+ result[name] = TinyAdmin::Field.create_field(name: name, type: types[name], options: field_options)
25
+ end
26
+ else
27
+ model.columns.each_with_object({}) do |column, result|
28
+ result[column.name] = TinyAdmin::Field.create_field(name: column.name, type: column.type)
29
+ end
39
30
  end
40
31
  end
41
32
 
42
- def show_record_attrs(record, fields: nil)
43
- attrs = !fields || fields.empty? ? record.attributes : record.attributes.slice(*fields.keys)
44
- attrs.transform_values(&:to_s)
45
- end
33
+ alias show_record_attrs index_record_attrs
46
34
 
47
35
  def show_title(record)
48
36
  "#{model} ##{record.id}"
@@ -54,10 +42,10 @@ module TinyAdmin
54
42
  raise BaseRepository::RecordNotFound, e.message
55
43
  end
56
44
 
57
- def list(page: 1, limit: 10, filters: nil, sort: ['id'])
58
- page_offset = page.positive? ? (page - 1) * limit : 0
45
+ def list(page: 1, limit: 10, sort: ['id'], filters: nil)
59
46
  query = model.all.order(sort)
60
47
  query = apply_filters(query, filters) if filters
48
+ page_offset = page.positive? ? (page - 1) * limit : 0
61
49
  records = query.offset(page_offset).limit(limit).to_a
62
50
  [records, query.count]
63
51
  end
@@ -10,6 +10,20 @@ module TinyAdmin
10
10
  def initialize(model)
11
11
  @model = model
12
12
  end
13
+
14
+ def translate_value(value, field)
15
+ if field[:method]
16
+ method, *options = field[:method].split(',').map(&:strip)
17
+ if field[:converter]
18
+ converter = Object.const_get(field[:converter])
19
+ converter.send(method, value, options: options || [])
20
+ else
21
+ Settings.instance.helper_class.send(method, value, options: options || [])
22
+ end
23
+ else
24
+ value&.to_s
25
+ end
26
+ end
13
27
  end
14
28
  end
15
29
  end
@@ -2,9 +2,11 @@
2
2
 
3
3
  module TinyAdmin
4
4
  class Router < BasicApp
5
- TinyAdmin::Settings.instance.load_settings
6
-
7
5
  route do |r|
6
+ context.settings = TinyAdmin::Settings.instance
7
+ context.settings.load_settings
8
+ context.router = r
9
+
8
10
  r.on 'auth' do
9
11
  context.slug = nil
10
12
  r.run Authentication
@@ -27,11 +29,11 @@ module TinyAdmin
27
29
  r.redirect settings.root_path
28
30
  end
29
31
 
30
- TinyAdmin::Settings.instance.pages.each do |slug, data|
32
+ context.settings.pages.each do |slug, data|
31
33
  setup_page_route(r, slug, data)
32
34
  end
33
35
 
34
- TinyAdmin::Settings.instance.resources.each do |slug, options|
36
+ context.settings.resources.each do |slug, options|
35
37
  setup_resource_routes(r, slug, options: options || {})
36
38
  end
37
39
 
@@ -74,14 +76,14 @@ module TinyAdmin
74
76
  end
75
77
 
76
78
  def setup_collection_routes(router, options:)
77
- repository = options[:repository].new(options[:model])
79
+ context.repository = options[:repository].new(options[:model])
78
80
  action_options = options[:index] || {}
79
81
 
80
82
  # Custom actions
81
83
  custom_actions = setup_custom_actions(
82
84
  router,
83
85
  options[:collection_actions],
84
- repository: repository,
86
+ repository: context.repository,
85
87
  options: action_options
86
88
  )
87
89
 
@@ -89,14 +91,15 @@ module TinyAdmin
89
91
  actions = options[:only]
90
92
  if !actions || actions.include?(:index) || actions.include?('index')
91
93
  router.is do
92
- index_action = TinyAdmin::Actions::Index.new(repository, path: request.path, params: request.params)
94
+ context.request = request
95
+ index_action = TinyAdmin::Actions::Index.new
93
96
  render_page index_action.call(app: self, context: context, options: action_options, actions: custom_actions)
94
97
  end
95
98
  end
96
99
  end
97
100
 
98
101
  def setup_member_routes(router, options:)
99
- repository = options[:repository].new(options[:model])
102
+ context.repository = options[:repository].new(options[:model])
100
103
  action_options = (options[:show] || {}).merge(record_not_found_page: settings.record_not_found)
101
104
 
102
105
  router.on String do |reference|
@@ -106,7 +109,7 @@ module TinyAdmin
106
109
  custom_actions = setup_custom_actions(
107
110
  router,
108
111
  options[:member_actions],
109
- repository: repository,
112
+ repository: context.repository,
110
113
  options: action_options
111
114
  )
112
115
 
@@ -114,7 +117,8 @@ module TinyAdmin
114
117
  actions = options[:only]
115
118
  if !actions || actions.include?(:show) || actions.include?('show')
116
119
  router.is do
117
- show_action = TinyAdmin::Actions::Show.new(repository, path: request.path, params: request.params)
120
+ context.request = request
121
+ show_action = TinyAdmin::Actions::Show.new
118
122
  render_page show_action.call(app: self, context: context, options: action_options, actions: custom_actions)
119
123
  end
120
124
  end
@@ -122,16 +126,18 @@ module TinyAdmin
122
126
  end
123
127
 
124
128
  def setup_custom_actions(router, custom_actions, repository:, options:)
125
- (custom_actions || []).map do |custom_action|
129
+ context.repository = repository
130
+ (custom_actions || []).each_with_object({}) do |custom_action, result|
126
131
  action_slug, action = custom_action.first
127
132
  action_class = action.is_a?(String) ? Object.const_get(action) : action
128
133
 
129
134
  router.get action_slug.to_s do
130
- custom_action = action_class.new(repository, path: request.path, params: request.params)
135
+ context.request = request
136
+ custom_action = action_class.new
131
137
  render_page custom_action.call(app: self, context: context, options: options)
132
138
  end
133
139
 
134
- action_slug.to_s
140
+ result[action_slug.to_s] = action_class
135
141
  end
136
142
  end
137
143
  end
@@ -5,9 +5,26 @@ module TinyAdmin
5
5
  include Singleton
6
6
  include Utils
7
7
 
8
+ DEFAULTS = {
9
+ %i[authentication plugin] => Plugins::NoAuth,
10
+ %i[authentication login] => Views::Pages::SimpleAuthLogin,
11
+ %i[components flash] => Views::Components::Flash,
12
+ %i[components head] => Views::Components::Head,
13
+ %i[components navbar] => Views::Components::Navbar,
14
+ %i[components pagination] => Views::Components::Pagination,
15
+ %i[helper_class] => Support,
16
+ %i[page_not_found] => Views::Pages::PageNotFound,
17
+ %i[record_not_found] => Views::Pages::RecordNotFound,
18
+ %i[repository] => Plugins::ActiveRecordRepository,
19
+ %i[root_path] => '/admin',
20
+ %i[root page] => Views::Pages::Root,
21
+ %i[root title] => 'TinyAdmin'
22
+ }.freeze
23
+
8
24
  attr_accessor :authentication,
9
25
  :components,
10
26
  :extra_styles,
27
+ :helper_class,
11
28
  :navbar,
12
29
  :page_not_found,
13
30
  :record_not_found,
@@ -20,38 +37,33 @@ module TinyAdmin
20
37
 
21
38
  attr_reader :pages, :resources
22
39
 
23
- def load_settings
24
- @authentication ||= {}
25
- @authentication[:plugin] ||= Plugins::NoAuth
26
- @authentication[:login] ||= Views::Pages::SimpleAuthLogin
27
- @authentication[:plugin] = Object.const_get(authentication[:plugin]) if authentication[:plugin].is_a?(String)
40
+ def [](key)
41
+ send(key)
42
+ end
43
+
44
+ def []=(key, value)
45
+ send("#{key}=", value)
46
+ convert_value(key, value)
47
+ end
28
48
 
29
- @page_not_found ||= Views::Pages::PageNotFound
30
- @page_not_found = Object.const_get(@page_not_found) if @page_not_found.is_a?(String)
31
- @record_not_found ||= Views::Pages::RecordNotFound
32
- @record_not_found = Object.const_get(@record_not_found) if @record_not_found.is_a?(String)
49
+ def load_settings
50
+ # default values
51
+ DEFAULTS.each do |(option, param), default|
52
+ if param
53
+ self[option] ||= {}
54
+ self[option][param] ||= default
55
+ else
56
+ self[option] ||= default
57
+ end
58
+ end
33
59
 
34
60
  @pages ||= {}
35
- @repository ||= Plugins::ActiveRecordRepository
36
61
  @resources ||= {}
37
- @root_path ||= '/admin'
38
- @root_path = '/' if @root_path == ''
39
62
  @sections ||= []
40
-
41
- @root ||= {}
42
- @root[:title] ||= 'TinyAdmin'
43
- @root[:page] ||= Views::Pages::Root
44
-
63
+ @root_path = '/' if @root_path == ''
45
64
  if @authentication[:plugin] == Plugins::SimpleAuth
46
65
  @authentication[:logout] ||= ['logout', "#{root_path}/auth/logout"]
47
66
  end
48
-
49
- @components ||= {}
50
- @components[:flash] ||= Views::Components::Flash
51
- @components[:head] ||= Views::Components::Head
52
- @components[:navbar] ||= Views::Components::Navbar
53
- @components[:pagination] ||= Views::Components::Pagination
54
-
55
67
  @navbar = prepare_navbar(sections, logout: authentication[:logout])
56
68
  end
57
69
 
@@ -79,5 +91,20 @@ module TinyAdmin
79
91
  items['auth/logout'] = logout if logout
80
92
  items
81
93
  end
94
+
95
+ private
96
+
97
+ def convert_value(key, value)
98
+ if value.is_a?(Hash)
99
+ value.each_key do |key2|
100
+ path = [key, key2]
101
+ if DEFAULTS[path].is_a?(Class) || DEFAULTS[path].is_a?(Module)
102
+ self[key][key2] = Object.const_get(self[key][key2])
103
+ end
104
+ end
105
+ elsif value.is_a?(String) && (DEFAULTS[[key]].is_a?(Class) || DEFAULTS[[key]].is_a?(Module))
106
+ self[key] = Object.const_get(self[key])
107
+ end
108
+ end
82
109
  end
83
110
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TinyAdmin
4
+ class Support
5
+ class << self
6
+ def call(value, options: [])
7
+ value && options&.any? ? options.inject(value) { |result, message| result&.send(message) } : value
8
+ end
9
+
10
+ def downcase(value, options: [])
11
+ value&.downcase
12
+ end
13
+
14
+ def format(value, options: [])
15
+ value && options&.any? ? Kernel.format(options.first, value) : value
16
+ end
17
+
18
+ def round(value, options: [])
19
+ value&.round(options&.first&.to_i || 2)
20
+ end
21
+
22
+ def strftime(value, options: [])
23
+ value ? value.strftime(options&.first || '%Y-%m-%d %H:%M') : ''
24
+ end
25
+
26
+ def to_date(value, options: [])
27
+ value ? value.to_date.to_s : value
28
+ end
29
+
30
+ def upcase(value, options: [])
31
+ value&.upcase
32
+ end
33
+ end
34
+ end
35
+ end
@@ -29,9 +29,10 @@ module TinyAdmin
29
29
  end
30
30
  end
31
31
 
32
- def route_for(section, reference: nil, action: nil)
32
+ def route_for(section, reference: nil, action: nil, query: nil)
33
33
  root_path = settings.root_path == '/' ? nil : settings.root_path
34
34
  route = [root_path, section, reference, action].compact.join("/")
35
+ route << "?#{query}" if query
35
36
  route[0] == '/' ? route : route.prepend('/')
36
37
  end
37
38
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TinyAdmin
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
@@ -7,9 +7,6 @@ module TinyAdmin
7
7
  attr_accessor :actions, :fields, :filters, :pagination_component, :prepare_record, :records
8
8
 
9
9
  def template
10
- @fields = fields.each_with_object({}) { |field, result| result[field.name] = field }
11
- @filters ||= {}
12
-
13
10
  super do
14
11
  div(class: 'index') {
15
12
  div(class: 'row') {
@@ -17,19 +14,12 @@ module TinyAdmin
17
14
  h1(class: 'title') { title }
18
15
  }
19
16
  div(class: 'col-8') {
20
- ul(class: 'nav justify-content-end') {
21
- (actions || []).each do |action|
22
- li(class: 'nav-item') {
23
- href = route_for(context.slug, action: action)
24
- a(href: href, class: 'nav-link btn btn-outline-secondary') { action }
25
- }
26
- end
27
- }
17
+ actions_buttons
28
18
  }
29
19
  }
30
20
 
31
21
  div(class: 'row') {
32
- div_class = filters.any? ? 'col-9' : 'col-12'
22
+ div_class = filters&.any? ? 'col-9' : 'col-12'
33
23
  div(class: div_class) {
34
24
  table(class: 'table') {
35
25
  table_header if fields.any?
@@ -38,7 +28,7 @@ module TinyAdmin
38
28
  }
39
29
  }
40
30
 
41
- if filters.any?
31
+ if filters&.any?
42
32
  div(class: 'col-3') {
43
33
  filters_form_attrs = { section_path: route_for(context.slug), filters: filters }
44
34
  render TinyAdmin::Views::Components::FiltersForm.new(**filters_form_attrs)
@@ -57,7 +47,9 @@ module TinyAdmin
57
47
  thead {
58
48
  tr {
59
49
  fields.each_value do |field|
60
- td(class: "field-header-#{field.name} field-header-type-#{field.type}") { field.title }
50
+ td(class: "field-header-#{field.name} field-header-type-#{field.type}") {
51
+ field.options[:header] || field.title
52
+ }
61
53
  end
62
54
  td { whitespace }
63
55
  }
@@ -73,8 +65,9 @@ module TinyAdmin
73
65
  field = fields[key]
74
66
  td(class: "field-value-#{field.name} field-value-type-#{field.type}") {
75
67
  if field.options && field.options[:link_to]
76
- reference = record.send(field.options[:field])
77
- a(href: route_for(field.options[:link_to], reference: reference)) { value }
68
+ messages = (field.options[:call] || '').split(',').map(&:strip)
69
+ label = messages.any? ? messages.inject(record) { |result, msg| result&.send(msg) } : value
70
+ a(href: route_for(field.options[:link_to], reference: value)) { label }
78
71
  else
79
72
  value
80
73
  end
@@ -87,6 +80,18 @@ module TinyAdmin
87
80
  end
88
81
  }
89
82
  end
83
+
84
+ def actions_buttons
85
+ ul(class: 'nav justify-content-end') {
86
+ (actions || {}).each do |action, action_class|
87
+ li(class: 'nav-item mx-1') {
88
+ href = route_for(context.slug, action: action)
89
+ title = action_class.respond_to?(:title) ? action_class.title : action
90
+ a(href: href, class: 'nav-link btn btn-outline-secondary') { title }
91
+ }
92
+ end
93
+ }
94
+ end
90
95
  end
91
96
  end
92
97
  end
@@ -4,14 +4,7 @@ module TinyAdmin
4
4
  module Views
5
5
  module Actions
6
6
  class Show < DefaultLayout
7
- attr_reader :fields, :prepare_record, :record
8
- attr_accessor :actions
9
-
10
- def setup_record(record:, fields:, prepare_record:)
11
- @record = record
12
- @fields = fields
13
- @prepare_record = prepare_record
14
- end
7
+ attr_accessor :actions, :fields, :prepare_record, :record
15
8
 
16
9
  def template
17
10
  super do
@@ -21,27 +14,21 @@ module TinyAdmin
21
14
  h1(class: 'title') { title }
22
15
  }
23
16
  div(class: 'col-8') {
24
- ul(class: 'nav justify-content-end') {
25
- (actions || []).each do |action|
26
- li(class: 'nav-item') {
27
- href = route_for(context.slug, reference: context.reference, action: action)
28
- a(href: href, class: 'nav-link btn btn-outline-secondary') { action }
29
- }
30
- end
31
- }
17
+ actions_buttons
32
18
  }
33
19
  }
34
20
 
35
- prepare_record.call(record).each_with_index do |(_key, value), index|
36
- field = fields[index]
21
+ prepare_record.call(record).each do |key, value|
22
+ field = fields[key]
37
23
  div(class: "field-#{field.name} row lh-lg") {
38
24
  if field
39
- div(class: 'field-header col-2') { field.title }
25
+ div(class: 'field-header col-2') { field.options[:header] || field.title }
40
26
  end
41
27
  div(class: 'field-value col-10') {
42
28
  if field.options && field.options[:link_to]
43
- reference = record.send(field.options[:field])
44
- a(href: route_for(field.options[:link_to], reference: reference)) { value }
29
+ messages = (field.options[:call] || '').split(',').map(&:strip)
30
+ label = messages.any? ? messages.inject(record) { |result, msg| result&.send(msg) } : value
31
+ a(href: route_for(field.options[:link_to], reference: value)) { label }
45
32
  else
46
33
  value
47
34
  end
@@ -51,6 +38,20 @@ module TinyAdmin
51
38
  }
52
39
  end
53
40
  end
41
+
42
+ private
43
+
44
+ def actions_buttons
45
+ ul(class: 'nav justify-content-end') {
46
+ (actions || {}).each do |action, action_class|
47
+ li(class: 'nav-item mx-1') {
48
+ href = route_for(context.slug, reference: context.reference, action: action)
49
+ title = action_class.respond_to?(:title) ? action_class.title : action
50
+ a(href: href, class: 'nav-link btn btn-outline-secondary') { title }
51
+ }
52
+ end
53
+ }
54
+ end
54
55
  end
55
56
  end
56
57
  end
data/lib/tiny_admin.rb CHANGED
@@ -18,7 +18,7 @@ module TinyAdmin
18
18
  def configure_from_file(file)
19
19
  config = YAML.load_file(file, symbolize_names: true)
20
20
  config.each do |key, value|
21
- TinyAdmin::Settings.instance.send("#{key}=", value)
21
+ TinyAdmin::Settings.instance[key] = value
22
22
  end
23
23
  end
24
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiny_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-14 00:00:00.000000000 Z
11
+ date: 2023-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex
@@ -88,6 +88,7 @@ files:
88
88
  - lib/tiny_admin/plugins/simple_auth.rb
89
89
  - lib/tiny_admin/router.rb
90
90
  - lib/tiny_admin/settings.rb
91
+ - lib/tiny_admin/support.rb
91
92
  - lib/tiny_admin/utils.rb
92
93
  - lib/tiny_admin/version.rb
93
94
  - lib/tiny_admin/views/actions/index.rb