tiny_admin 0.7.0 → 0.9.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: d8059ea24a18bfb14f8e868a70203db8045099e20196f5098f1c63b121421e49
4
- data.tar.gz: d0da80d718362c58a50e963b2e79dff550e77a763d7872a0ba96efea43f408b3
3
+ metadata.gz: de3ed265839998db96c8e220f1b66576a8a37325e0726f3597e0b1ef315087a4
4
+ data.tar.gz: 828309ff8139a11c3e73fcbeb82ffea7f752191e5c4e99e9dc19fbaa29a2180e
5
5
  SHA512:
6
- metadata.gz: 3067f890f10f10f5dc7379c7b147f01f5cb62b8d59f06ad7b4387c685cd2e32cdeb1f87fbfe36b0e2c388c854ce461f1a18b2659ee479e401ba74ed3c5559a3a
7
- data.tar.gz: 0a4b4129b33e0dbf2ab2d01df14ead0ec3971a098dbed39a5b50c287e2a00c5c8448011de81a233c7bb1dda58bb42b648d44069684a65cdb4e42e3faf2a453bb
6
+ metadata.gz: 3648b175fd028a82bc7c3ae35fc51d3380a4d22fc6dd38dfd5da5ed375d94b4b45358b36c17c955482574756700bd2889ba57348e4ed3453491e2112c9d1471f
7
+ data.tar.gz: 4ea2a1301b70a3b88e07829e5755976482d22b2f18c1752ab7b7626e93b19b20527a7944c9da634fdf92a4bed53cf20d56c1e7e6738bc8c3b519de4147cd810b
data/README.md CHANGED
@@ -19,7 +19,7 @@ Please ⭐ if you like it.
19
19
 
20
20
  ## Install
21
21
 
22
- - Add to your Gemfile: `gem 'tiny_admin', '~> 0.7'`
22
+ - Add to your Gemfile: `gem 'tiny_admin', '~> 0.9'`
23
23
  - Mount the app in a route (check some examples with: Hanami, Rails, Roda and standalone in [extra](extra))
24
24
  + in Rails, update _config/routes.rb_: `mount TinyAdmin::Router => '/admin'`
25
25
  - Configure the dashboard using `TinyAdmin.configure` and/or `TinyAdmin.configure_from_file` with a YAML config file (see [configuration](#configuration) below):
@@ -85,6 +85,8 @@ The following options are supported:
85
85
  - `redirect` (String): alternative to _page_ option - redirects to a specific slug;
86
86
  - `widgets` (Array): list of widgets (as View components) to present.
87
87
 
88
+ > 📚 [Wiki Root page](https://github.com/blocknotes/tiny_admin/wiki/Root) available
89
+
88
90
  Example:
89
91
 
90
92
  ```yml
@@ -98,6 +100,8 @@ root:
98
100
 
99
101
  `helper_class` (String): class or module with helper methods, used for attributes' formatters.
100
102
 
103
+ > 📚 [Wiki Helper methods page](https://github.com/blocknotes/tiny_admin/wiki/Helper-methods) available
104
+
101
105
  `page_not_found` (String): a view object to render when a missing page is requested.
102
106
 
103
107
  `record_not_found` (String): a view object to render when a missing record is requested.
@@ -113,11 +117,15 @@ root:
113
117
 
114
118
  `extra_styles` (String): inline CSS styles.
115
119
 
120
+ > 📚 [Wiki Styles and scripts page](https://github.com/blocknotes/tiny_admin/wiki/Styles-and-scripts) available
121
+
116
122
  `authentication` (Hash): define the authentication method, properties:
117
123
 
118
124
  - `plugin` (String): a plugin class to use (ex. `TinyAdmin::Plugins::SimpleAuth`);
119
125
  - `password` (String): a password hash used by _SimpleAuth_ plugin (generated with `Digest::SHA512.hexdigest("some password")`).
120
126
 
127
+ > 📚 [Wiki Authentication page](https://github.com/blocknotes/tiny_admin/wiki/Authentication) available
128
+
121
129
  Example:
122
130
 
123
131
  ```yml
@@ -134,6 +142,8 @@ authentication:
134
142
  - `widgets` (Array): list of widgets (as View components) to present;
135
143
  - other properties depends on the section's type.
136
144
 
145
+ > 📚 [Wiki Pages page](https://github.com/blocknotes/tiny_admin/wiki/Pages) available
146
+
137
147
  For _content_ sections:
138
148
 
139
149
  - `content` (String): the HTML content to present.
@@ -186,6 +196,9 @@ For _resource_ sections:
186
196
 
187
197
  - `model` (String): the class to use to fetch the data on an item of a collection;
188
198
  - `repository` (String): the class to get the properties related to the model;
199
+
200
+ > 📚 [Wiki Repository page](https://github.com/blocknotes/tiny_admin/wiki/Repository) available
201
+
189
202
  - `index` (Hash): collection's action options (see below);
190
203
  - `show` (Hash): detail's action options (see below);
191
204
  - `collection_actions` (Array of hashes): custom collection's actions;
@@ -205,6 +218,8 @@ model: Post
205
218
 
206
219
  #### Resource index options
207
220
 
221
+ > 📚 [Wiki Resource index page](https://github.com/blocknotes/tiny_admin/wiki/Resource-index) available
222
+
208
223
  The Index hash supports the following options:
209
224
 
210
225
  - `attributes` (Array): fields to expose in the resource list page;
@@ -244,6 +259,8 @@ Example:
244
259
 
245
260
  #### Resource show options
246
261
 
262
+ > 📚 [Wiki Resource show page](https://github.com/blocknotes/tiny_admin/wiki/Resource-show) available
263
+
247
264
  The Show hash supports the following options:
248
265
 
249
266
  - `attributes` (Array): fields to expose in the resource details page.
@@ -62,8 +62,9 @@ module TinyAdmin
62
62
  @pages = (total_count / pagination.to_f).ceil
63
63
  return if pages <= 1 || !pagination_component_class
64
64
 
65
+ attributes = { current: current_page, pages: pages, query_string: query_string, total_count: total_count }
65
66
  page.pagination_component = pagination_component_class.new
66
- page.pagination_component.update_attributes(current: current_page, pages: pages, query_string: query_string)
67
+ page.pagination_component.update_attributes(attributes)
67
68
  end
68
69
  end
69
70
  end
@@ -12,7 +12,11 @@ module TinyAdmin
12
12
  end
13
13
 
14
14
  r.post 'unauthenticated' do
15
- render_login(warnings: ['Failed to authenticate'])
15
+ warning = TinyAdmin.settings.helper_class.label_for(
16
+ 'Failed to authenticate',
17
+ options: ['authentication.unauthenticated']
18
+ )
19
+ render_login(warnings: [warning])
16
20
  end
17
21
 
18
22
  r.get 'logout' do
@@ -16,6 +16,19 @@ module TinyAdmin
16
16
  messages.inject(target) { |result, msg| result&.send(msg) } if messages.any?
17
17
  end
18
18
 
19
+ def translate_value(value)
20
+ if options && options[:method]
21
+ method, *args = options[:method].split(',').map(&:strip)
22
+ if options[:converter]
23
+ Object.const_get(options[:converter]).send(method, value, options: args || [])
24
+ else
25
+ TinyAdmin.settings.helper_class.send(method, value, options: args || [])
26
+ end
27
+ else
28
+ value&.to_s
29
+ end
30
+ end
31
+
19
32
  class << self
20
33
  def create_field(name:, title: nil, type: nil, options: {})
21
34
  field_name = name.to_s
@@ -6,10 +6,7 @@ module TinyAdmin
6
6
  def index_record_attrs(record, fields: nil)
7
7
  return record.attributes.transform_values(&:to_s) unless fields
8
8
 
9
- fields.to_h do |name, field|
10
- value = record.send(name)
11
- [name, translate_value(value, field)]
12
- end
9
+ fields.to_h { [_1, record.send(_1)] }
13
10
  end
14
11
 
15
12
  def index_title
@@ -10,20 +10,6 @@ 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
- TinyAdmin.settings.helper_class.send(method, value, options: options || [])
22
- end
23
- else
24
- value&.to_s
25
- end
26
- end
27
13
  end
28
14
  end
29
15
  end
@@ -58,14 +58,15 @@ module TinyAdmin
58
58
  router.redirect route_for(TinyAdmin.settings.root[:redirect])
59
59
  else
60
60
  page_class = to_class(TinyAdmin.settings.root[:page])
61
- render_page prepare_page(page_class, attributes: TinyAdmin.settings.root.slice(:content, :title, :widgets))
61
+ attributes = TinyAdmin.settings.root.slice(:content, :title, :widgets)
62
+ render_page prepare_page(page_class, attributes: attributes, params: request.params)
62
63
  end
63
64
  end
64
65
 
65
66
  def setup_page_route(router, slug, page_data)
66
67
  router.get slug do
67
68
  attributes = page_data.slice(:content, :title, :widgets)
68
- render_page prepare_page(page_data[:class], slug: slug, attributes: attributes)
69
+ render_page prepare_page(page_data[:class], slug: slug, attributes: attributes, params: request.params)
69
70
  end
70
71
  end
71
72
 
@@ -7,6 +7,7 @@ module TinyAdmin
7
7
  DEFAULTS = {
8
8
  %i[authentication plugin] => Plugins::NoAuth,
9
9
  %i[authentication login] => Views::Pages::SimpleAuthLogin,
10
+ %i[components field_value] => Views::Components::FieldValue,
10
11
  %i[components flash] => Views::Components::Flash,
11
12
  %i[components head] => Views::Components::Head,
12
13
  %i[components navbar] => Views::Components::Navbar,
@@ -15,6 +15,10 @@ module TinyAdmin
15
15
  Kernel.format(options.first, value) if value && options&.any?
16
16
  end
17
17
 
18
+ def label_for(value, options: [])
19
+ value
20
+ end
21
+
18
22
  def round(value, options: [])
19
23
  value&.round(options&.first&.to_i || 2)
20
24
  end
@@ -14,7 +14,7 @@ module TinyAdmin
14
14
  list.join('&')
15
15
  end
16
16
 
17
- def prepare_page(page_class, slug: nil, attributes: nil, options: nil)
17
+ def prepare_page(page_class, slug: nil, attributes: nil, options: nil, params: nil)
18
18
  page_class.new.tap do |page|
19
19
  page.options = options
20
20
  page.head_component = TinyAdmin.settings.components[:head]&.new
@@ -27,9 +27,11 @@ module TinyAdmin
27
27
  items: options&.include?(:no_menu) ? [] : TinyAdmin.settings.store&.navbar
28
28
  )
29
29
  attrs = attributes || {}
30
+ attrs[:params] = params if params
30
31
  attrs[:widgets] = attrs[:widgets].map { to_class(_1) } if attrs[:widgets]
31
32
  page.update_attributes(attrs) unless attrs.empty?
32
33
  yield(page) if block_given?
34
+ page.setup if page.respond_to?(:setup)
33
35
  end
34
36
  end
35
37
 
@@ -37,7 +39,7 @@ module TinyAdmin
37
39
  klass.is_a?(String) ? Object.const_get(klass) : klass
38
40
  end
39
41
 
40
- def to_label(string)
42
+ def humanize(string)
41
43
  return '' unless string
42
44
 
43
45
  string.respond_to?(:humanize) ? string.humanize : string.tr('_', ' ').capitalize
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TinyAdmin
4
- VERSION = '0.7.0'
4
+ VERSION = '0.9.0'
5
5
  end
@@ -28,6 +28,8 @@ module TinyAdmin
28
28
 
29
29
  table_body
30
30
  }
31
+
32
+ render pagination_component if pagination_component
31
33
  }
32
34
 
33
35
  if filters&.any?
@@ -39,8 +41,6 @@ module TinyAdmin
39
41
  end
40
42
  }
41
43
 
42
- render pagination_component if pagination_component
43
-
44
44
  render TinyAdmin::Views::Components::Widgets.new(widgets)
45
45
  }
46
46
  end
@@ -69,13 +69,7 @@ module TinyAdmin
69
69
  attributes.each do |key, value|
70
70
  field = fields[key]
71
71
  td(class: "field-value-#{field.name} field-value-type-#{field.type}") {
72
- if field.options && field.options[:link_to]
73
- a(href: TinyAdmin.route_for(field.options[:link_to], reference: value)) {
74
- field.apply_call_option(record) || value
75
- }
76
- else
77
- value
78
- end
72
+ render TinyAdmin.settings.components[:field_value].new(field, value, record: record)
79
73
  }
80
74
  end
81
75
 
@@ -86,15 +80,20 @@ module TinyAdmin
86
80
  links.each do |link|
87
81
  whitespace
88
82
  if link == 'show'
89
- a(href: TinyAdmin.route_for(slug, reference: record.id), class: link_class) { 'show' }
83
+ a(href: TinyAdmin.route_for(slug, reference: record.id), class: link_class) {
84
+ label_for('Show', options: ['actions.index.links.show'])
85
+ }
90
86
  else
91
87
  a(href: TinyAdmin.route_for(slug, reference: record.id, action: link), class: link_class) {
92
- to_label(link)
88
+ fallback = humanize(link)
89
+ label_for(fallback, options: ["actions.index.links.#{link}"])
93
90
  }
94
91
  end
95
92
  end
96
93
  else
97
- a(href: TinyAdmin.route_for(slug, reference: record.id), class: link_class) { 'show' }
94
+ a(href: TinyAdmin.route_for(slug, reference: record.id), class: link_class) {
95
+ label_for('Show', options: ['actions.index.links.show'])
96
+ }
98
97
  end
99
98
  }
100
99
  }
@@ -25,13 +25,7 @@ module TinyAdmin
25
25
  div(class: 'field-header col-2') { field.options[:header] || field.title }
26
26
  end
27
27
  div(class: 'field-value col-10') {
28
- if field.options[:link_to]
29
- a(href: TinyAdmin.route_for(field.options[:link_to], reference: value)) {
30
- field.apply_call_option(record) || value
31
- }
32
- else
33
- value
34
- end
28
+ render TinyAdmin.settings.components[:field_value].new(field, value, record: record)
35
29
  }
36
30
  }
37
31
  end
@@ -5,7 +5,11 @@ module TinyAdmin
5
5
  class BasicLayout < Phlex::HTML
6
6
  include Utils
7
7
 
8
- attr_accessor :content, :widgets
8
+ attr_accessor :content, :params, :widgets
9
+
10
+ def label_for(value, options: [])
11
+ TinyAdmin.settings.helper_class.label_for(value, options: options)
12
+ end
9
13
 
10
14
  def update_attributes(attributes)
11
15
  attributes.each do |key, value|
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TinyAdmin
4
+ module Views
5
+ module Components
6
+ class FieldValue < BasicComponent
7
+ attr_reader :field, :value, :record
8
+
9
+ def initialize(field, value, record:)
10
+ @field = field
11
+ @value = value
12
+ @record = record
13
+ end
14
+
15
+ def template
16
+ translated_value = field.translate_value(value)
17
+ value_class = field.options[:options]&.include?('value_class') ? "value-#{value}" : nil
18
+ if field.options[:link_to]
19
+ a(href: TinyAdmin.route_for(field.options[:link_to], reference: translated_value)) {
20
+ span(class: value_class) {
21
+ field.apply_call_option(record) || translated_value
22
+ }
23
+ }
24
+ else
25
+ span(class: value_class) {
26
+ translated_value
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -17,8 +17,12 @@ module TinyAdmin
17
17
  when :boolean
18
18
  select(class: 'form-select', id: "filter-#{name}", name: "q[#{name}]") {
19
19
  option(value: '') { '-' }
20
- option(value: '0', selected: filter[:value] == '0') { 'false' }
21
- option(value: '1', selected: filter[:value] == '1') { 'true' }
20
+ option(value: '0', selected: filter[:value] == '0') {
21
+ TinyAdmin.settings.helper_class.label_for('false', options: ['components.filters_form.boolean.false'])
22
+ }
23
+ option(value: '1', selected: filter[:value] == '1') {
24
+ TinyAdmin.settings.helper_class.label_for('true', options: ['components.filters_form.boolean.true'])
25
+ }
22
26
  }
23
27
  when :date
24
28
  input(type: 'date', class: 'form-control', id: "filter-#{name}", name: "q[#{name}]", value: filter[:value])
@@ -40,9 +44,13 @@ module TinyAdmin
40
44
  end
41
45
 
42
46
  div(class: 'mt-3') {
43
- a(href: section_path, class: 'button_clear btn btn-secondary text-white') { 'clear' }
47
+ a(href: section_path, class: 'button_clear btn btn-secondary text-white') {
48
+ TinyAdmin.settings.helper_class.label_for('Clear', options: ['components.filters_form.buttons.clear'])
49
+ }
44
50
  whitespace
45
- button(type: 'submit', class: 'button_filter btn btn-secondary') { 'filter' }
51
+ button(type: 'submit', class: 'button_filter btn btn-secondary') {
52
+ TinyAdmin.settings.helper_class.label_for('Filter', options: ['components.filters_form.buttons.submit'])
53
+ }
46
54
  }
47
55
  }
48
56
  end
@@ -4,23 +4,31 @@ module TinyAdmin
4
4
  module Views
5
5
  module Components
6
6
  class Pagination < BasicComponent
7
- attr_accessor :current, :pages, :query_string
7
+ attr_accessor :current, :pages, :query_string, :total_count
8
8
 
9
9
  def template
10
- div(class: 'pagination-div') {
11
- nav('aria-label' => 'Pagination') {
12
- ul(class: 'pagination justify-content-center') {
13
- if pages <= 10
14
- pages_range(1..pages)
15
- elsif current <= 4 || current >= pages - 3
16
- pages_range(1..(current <= 4 ? current + 2 : 4), with_dots: true)
17
- pages_range((current > pages - 4 ? current - 2 : pages - 2)..pages)
18
- else
19
- pages_range(1..1, with_dots: true)
20
- pages_range(current - 2..current + 2, with_dots: true)
21
- pages_range(pages..pages)
22
- end
10
+ div(class: 'container') {
11
+ div(class: 'row') {
12
+ div(class: 'col total-count') {
13
+ "#{total_count} items"
23
14
  }
15
+ div(class: 'col col-6 text-center pagination-div') {
16
+ nav(class: 'd-inline-block', 'aria-label': 'Pagination') {
17
+ ul(class: 'pagination') {
18
+ if pages <= 10
19
+ pages_range(1..pages)
20
+ elsif current <= 4 || current >= pages - 3
21
+ pages_range(1..(current <= 4 ? current + 2 : 4), with_dots: true)
22
+ pages_range((current > pages - 4 ? current - 2 : pages - 2)..pages)
23
+ else
24
+ pages_range(1..1, with_dots: true)
25
+ pages_range(current - 2..current + 2, with_dots: true)
26
+ pages_range(pages..pages)
27
+ end
28
+ }
29
+ }
30
+ }
31
+ div(class: 'col')
24
32
  }
25
33
  }
26
34
  end
@@ -11,12 +11,16 @@ module TinyAdmin
11
11
 
12
12
  form(class: 'form_login', method: 'post') {
13
13
  div(class: 'mt-3') {
14
- label(for: 'secret', class: 'form-label') { 'Password' }
14
+ label(for: 'secret', class: 'form-label') {
15
+ label_for('Password', options: ['pages.simple_auth_login.inputs.password'])
16
+ }
15
17
  input(type: 'password', name: 'secret', class: 'form-control', id: 'secret')
16
18
  }
17
19
 
18
20
  div(class: 'mt-3') {
19
- button(type: 'submit', class: 'button_login btn btn-primary') { 'login' }
21
+ button(type: 'submit', class: 'button_login btn btn-primary') {
22
+ label_for('Login', options: ['pages.simple_auth_login.buttons.submit'])
23
+ }
20
24
  }
21
25
  }
22
26
  }
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.7.0
4
+ version: 0.9.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-05-01 00:00:00.000000000 Z
11
+ date: 2023-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex
@@ -98,6 +98,7 @@ files:
98
98
  - lib/tiny_admin/views/basic_layout.rb
99
99
  - lib/tiny_admin/views/basic_widget.rb
100
100
  - lib/tiny_admin/views/components/basic_component.rb
101
+ - lib/tiny_admin/views/components/field_value.rb
101
102
  - lib/tiny_admin/views/components/filters_form.rb
102
103
  - lib/tiny_admin/views/components/flash.rb
103
104
  - lib/tiny_admin/views/components/head.rb