tiny_admin 0.2.0 → 0.3.0
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 +16 -6
- data/lib/tiny_admin/actions/index.rb +20 -9
- data/lib/tiny_admin/actions/show.rb +1 -1
- data/lib/tiny_admin/plugins/simple_auth.rb +1 -1
- data/lib/tiny_admin/router.rb +2 -2
- data/lib/tiny_admin/utils.rb +10 -2
- data/lib/tiny_admin/version.rb +1 -1
- data/lib/tiny_admin/views/actions/index.rb +3 -16
- data/lib/tiny_admin/views/basic_layout.rb +0 -4
- data/lib/tiny_admin/views/components/flash.rb +8 -8
- data/lib/tiny_admin/views/components/head.rb +6 -6
- data/lib/tiny_admin/views/components/pagination.rb +33 -12
- data/lib/tiny_admin/views/default_layout.rb +8 -14
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d203e48b821f195f95847a646e32787c9ffd953212326f64e65ca09d563ed55e
|
4
|
+
data.tar.gz: a133ad428942d240ec8852e4885e12a51bc6a96f9a4bcf426470180671dddf6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8955bf003179333debcf4c43dd7091b4d81fc9c1e90a6116119dc33f51b4ab7dca394d90f6f8aa6bb0385339dc5eb07b64bd546f0a92e02497d5c000cc835769
|
7
|
+
data.tar.gz: 5cabb3dc010e73b416068cca3afda56dc07ac7b024c70d734b9409298d2082798a8e5e276d892be81e82dcbfa68bad20360f0d99e4c8e7199a7bdb5067f72124
|
data/README.md
CHANGED
@@ -4,11 +4,11 @@
|
|
4
4
|
|
5
5
|
A compact and composable dashboard component for Ruby.
|
6
6
|
|
7
|
-
|
8
|
-
- a Rack app that can be mounted in any Rack-enabled framework
|
7
|
+
Main features:
|
8
|
+
- a Rack app that can be mounted in any Rack-enabled framework or used standalone;
|
9
9
|
- structured with plugins also for main components that can be replaced with little effort;
|
10
|
-
- routing is provided by Roda
|
11
|
-
- views are Phlex components, so plain Ruby objects for views
|
10
|
+
- routing is provided by Roda which is small and performant;
|
11
|
+
- views are Phlex components, so plain Ruby objects for views, no assets are needed.
|
12
12
|
|
13
13
|
Please ⭐ if you like it.
|
14
14
|
|
@@ -16,9 +16,19 @@ Please ⭐ if you like it.
|
|
16
16
|
|
17
17
|
## Install
|
18
18
|
|
19
|
-
- Add to your Gemfile: `gem 'tiny_admin', '~> 0.
|
19
|
+
- Add to your Gemfile: `gem 'tiny_admin', '~> 0.3'`
|
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
|
+
- Configure the dashboard using `TinyAdmin.configure` and/or `TinyAdmin.configure_from_file` (see [configuration](#configuration) below):
|
23
|
+
|
24
|
+
```rb
|
25
|
+
TinyAdmin.configure do |settings|
|
26
|
+
settings.root = {
|
27
|
+
title: 'Home',
|
28
|
+
page: Admin::PageRoot
|
29
|
+
}
|
30
|
+
end
|
31
|
+
```
|
22
32
|
|
23
33
|
## Plugins and components
|
24
34
|
|
@@ -3,21 +3,24 @@
|
|
3
3
|
module TinyAdmin
|
4
4
|
module Actions
|
5
5
|
class Index < BasicAction
|
6
|
-
attr_reader :current_page, :fields_options, :filters_list, :pagination, :query_string, :sort
|
6
|
+
attr_reader :current_page, :fields_options, :filters_list, :pagination, :pages, :query_string, :sort
|
7
7
|
|
8
8
|
def call(app:, context:, options:, actions:)
|
9
9
|
evaluate_options(options)
|
10
10
|
fields = repository.fields(options: fields_options)
|
11
11
|
filters = prepare_filters(fields, filters_list)
|
12
12
|
records, total_count = repository.list(page: current_page, limit: pagination, filters: filters, sort: sort)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
|
14
|
+
prepare_page(Views::Actions::Index) do |page|
|
15
|
+
setup_pagination(page, settings.components[:pagination], total_count: total_count)
|
16
|
+
page.update_attributes(
|
17
|
+
actions: actions,
|
18
|
+
fields: fields,
|
19
|
+
filters: filters,
|
20
|
+
prepare_record: ->(record) { repository.index_record_attrs(record, fields: fields_options) },
|
21
|
+
records: records,
|
22
|
+
title: repository.index_title
|
23
|
+
)
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
@@ -43,6 +46,14 @@ module TinyAdmin
|
|
43
46
|
result[field] = { value: values[field.name], filter: filters[field.name] } if filters.key?(field.name)
|
44
47
|
end
|
45
48
|
end
|
49
|
+
|
50
|
+
def setup_pagination(page, pagination_component_class, total_count:)
|
51
|
+
@pages = (total_count / pagination.to_f).ceil
|
52
|
+
return if pages <= 1 || !pagination_component_class
|
53
|
+
|
54
|
+
page.pagination_component = pagination_component_class.new
|
55
|
+
page.pagination_component.update(current: current_page, pages: pages, query_string: query_string)
|
56
|
+
end
|
46
57
|
end
|
47
58
|
end
|
48
59
|
end
|
@@ -11,7 +11,7 @@ module TinyAdmin
|
|
11
11
|
prepare_record = ->(record_data) { repository.show_record_attrs(record_data, fields: fields_options) }
|
12
12
|
fields = repository.fields(options: fields_options)
|
13
13
|
|
14
|
-
prepare_page(Views::Actions::Show
|
14
|
+
prepare_page(Views::Actions::Show) do |page|
|
15
15
|
page.setup_record(record: record, fields: fields, prepare_record: prepare_record)
|
16
16
|
page.update_attributes(actions: actions, title: repository.show_title(record))
|
17
17
|
end
|
@@ -8,7 +8,7 @@ module TinyAdmin
|
|
8
8
|
class << self
|
9
9
|
def configure(app, opts = {})
|
10
10
|
@@opts = opts || {} # rubocop:disable Style/ClassVars
|
11
|
-
@@opts[:password] ||= ENV.fetch('ADMIN_PASSWORD_HASH') # NOTE: fallback value
|
11
|
+
@@opts[:password] ||= ENV.fetch('ADMIN_PASSWORD_HASH', nil) # NOTE: fallback value
|
12
12
|
|
13
13
|
Warden::Strategies.add(:secret) do
|
14
14
|
def authenticate!
|
data/lib/tiny_admin/router.rb
CHANGED
@@ -54,14 +54,14 @@ module TinyAdmin
|
|
54
54
|
else
|
55
55
|
page = settings.root[:page]
|
56
56
|
page_class = page.is_a?(String) ? Object.const_get(page) : page
|
57
|
-
render_page prepare_page(page_class
|
57
|
+
render_page prepare_page(page_class)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
61
|
def setup_page_route(router, slug, page_class)
|
62
62
|
router.get slug do
|
63
63
|
context.slug = slug
|
64
|
-
render_page prepare_page(page_class
|
64
|
+
render_page prepare_page(page_class)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
data/lib/tiny_admin/utils.rb
CHANGED
@@ -13,10 +13,18 @@ module TinyAdmin
|
|
13
13
|
list.join('&')
|
14
14
|
end
|
15
15
|
|
16
|
-
def prepare_page(page_class,
|
16
|
+
def prepare_page(page_class, options: nil)
|
17
17
|
page_class.new.tap do |page|
|
18
|
-
page.context = context
|
19
18
|
page.options = options
|
19
|
+
page.head_component = settings.components[:head]&.new
|
20
|
+
page.flash_component = settings.components[:flash]&.new
|
21
|
+
page.navbar_component = settings.components[:navbar]&.new(
|
22
|
+
current_slug: context&.slug,
|
23
|
+
root_path: settings.root_path,
|
24
|
+
root_title: settings.root[:title],
|
25
|
+
items: options&.include?(:no_menu) ? [] : settings.navbar
|
26
|
+
)
|
27
|
+
|
20
28
|
yield(page) if block_given?
|
21
29
|
end
|
22
30
|
end
|
data/lib/tiny_admin/version.rb
CHANGED
@@ -4,21 +4,10 @@ module TinyAdmin
|
|
4
4
|
module Views
|
5
5
|
module Actions
|
6
6
|
class Index < DefaultLayout
|
7
|
-
|
8
|
-
attr_accessor :actions, :filters, :query_string
|
9
|
-
|
10
|
-
def setup_pagination(current_page:, pages:)
|
11
|
-
@current_page = current_page
|
12
|
-
@pages = pages
|
13
|
-
end
|
14
|
-
|
15
|
-
def setup_records(records:, fields:, prepare_record:)
|
16
|
-
@records = records
|
17
|
-
@fields = fields.each_with_object({}) { |field, result| result[field.name] = field }
|
18
|
-
@prepare_record = prepare_record
|
19
|
-
end
|
7
|
+
attr_accessor :actions, :fields, :filters, :pagination_component, :prepare_record, :records
|
20
8
|
|
21
9
|
def template
|
10
|
+
@fields = fields.each_with_object({}) { |field, result| result[field.name] = field }
|
22
11
|
@filters ||= {}
|
23
12
|
|
24
13
|
super do
|
@@ -57,9 +46,7 @@ module TinyAdmin
|
|
57
46
|
end
|
58
47
|
}
|
59
48
|
|
60
|
-
if
|
61
|
-
render components[:pagination].new(current: current_page, pages: pages, query_string: query_string)
|
62
|
-
end
|
49
|
+
render pagination_component if pagination_component
|
63
50
|
}
|
64
51
|
end
|
65
52
|
end
|
@@ -6,14 +6,6 @@ module TinyAdmin
|
|
6
6
|
class Flash < Phlex::HTML
|
7
7
|
attr_reader :errors, :notices, :warnings
|
8
8
|
|
9
|
-
def initialize(messages:)
|
10
|
-
return unless messages
|
11
|
-
|
12
|
-
@notices = messages[:notices]
|
13
|
-
@warnings = messages[:warnings]
|
14
|
-
@errors = messages[:errors]
|
15
|
-
end
|
16
|
-
|
17
9
|
def template
|
18
10
|
div(class: 'flash') {
|
19
11
|
div(class: 'notices alert alert-success', role: 'alert') { notices.join(', ') } if notices&.any?
|
@@ -21,6 +13,14 @@ module TinyAdmin
|
|
21
13
|
div(class: 'notices alert alert-danger', role: 'alert') { errors.join(', ') } if errors&.any?
|
22
14
|
}
|
23
15
|
end
|
16
|
+
|
17
|
+
def update(messages:)
|
18
|
+
return unless messages
|
19
|
+
|
20
|
+
@notices = messages[:notices]
|
21
|
+
@warnings = messages[:warnings]
|
22
|
+
@errors = messages[:errors]
|
23
|
+
end
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -6,12 +6,6 @@ module TinyAdmin
|
|
6
6
|
class Head < Phlex::HTML
|
7
7
|
attr_reader :extra_styles, :page_title, :style_links
|
8
8
|
|
9
|
-
def initialize(page_title, style_links: [], extra_styles: nil)
|
10
|
-
@page_title = page_title
|
11
|
-
@style_links = style_links
|
12
|
-
@extra_styles = extra_styles
|
13
|
-
end
|
14
|
-
|
15
9
|
def template
|
16
10
|
head {
|
17
11
|
meta charset: 'utf-8'
|
@@ -25,6 +19,12 @@ module TinyAdmin
|
|
25
19
|
style { extra_styles } if extra_styles
|
26
20
|
}
|
27
21
|
end
|
22
|
+
|
23
|
+
def update(page_title, style_links: [], extra_styles: nil)
|
24
|
+
@page_title = page_title
|
25
|
+
@style_links = style_links
|
26
|
+
@extra_styles = extra_styles
|
27
|
+
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -6,27 +6,48 @@ module TinyAdmin
|
|
6
6
|
class Pagination < Phlex::HTML
|
7
7
|
attr_reader :current, :pages, :query_string
|
8
8
|
|
9
|
-
def initialize(current:, pages:, query_string:)
|
10
|
-
@current = current
|
11
|
-
@pages = pages
|
12
|
-
@query_string = query_string
|
13
|
-
end
|
14
|
-
|
15
9
|
def template
|
16
10
|
div(class: 'pagination-div') {
|
17
11
|
nav('aria-label' => 'Pagination') {
|
18
12
|
ul(class: 'pagination justify-content-center') {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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)
|
25
22
|
end
|
26
23
|
}
|
27
24
|
}
|
28
25
|
}
|
29
26
|
end
|
27
|
+
|
28
|
+
def update(current:, pages:, query_string:)
|
29
|
+
@current = current
|
30
|
+
@pages = pages
|
31
|
+
@query_string = query_string
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def pages_range(range, with_dots: false)
|
37
|
+
range.each do |page|
|
38
|
+
li(class: page == current ? 'page-item active' : 'page-item') {
|
39
|
+
href = query_string.empty? ? "?p=#{page}" : "?#{query_string}&p=#{page}"
|
40
|
+
a(class: 'page-link', href: href) { page }
|
41
|
+
}
|
42
|
+
end
|
43
|
+
dots if with_dots
|
44
|
+
end
|
45
|
+
|
46
|
+
def dots
|
47
|
+
li(class: 'page-item disabled') {
|
48
|
+
a(class: 'page-link') { '...' }
|
49
|
+
}
|
50
|
+
end
|
30
51
|
end
|
31
52
|
end
|
32
53
|
end
|
@@ -3,24 +3,22 @@
|
|
3
3
|
module TinyAdmin
|
4
4
|
module Views
|
5
5
|
class DefaultLayout < BasicLayout
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :flash_component, :head_component, :messages, :navbar_component, :options, :title
|
7
7
|
|
8
8
|
def template(&block)
|
9
|
+
flash_component&.update(messages: messages)
|
10
|
+
head_component&.update(title, style_links: style_links, extra_styles: settings.extra_styles)
|
11
|
+
|
9
12
|
doctype
|
10
13
|
html {
|
11
|
-
render
|
14
|
+
render head_component if head_component
|
12
15
|
|
13
16
|
body(class: body_class) {
|
14
|
-
|
15
|
-
current_slug: context&.slug,
|
16
|
-
root_path: settings.root_path,
|
17
|
-
root_title: settings.root[:title],
|
18
|
-
items: navbar_items
|
19
|
-
}
|
20
|
-
render components[:navbar].new(**navbar_attrs)
|
17
|
+
render navbar_component if navbar_component
|
21
18
|
|
22
19
|
main_content {
|
23
|
-
render
|
20
|
+
render flash_component if flash_component
|
21
|
+
|
24
22
|
yield_content(&block)
|
25
23
|
}
|
26
24
|
|
@@ -35,10 +33,6 @@ module TinyAdmin
|
|
35
33
|
"module-#{self.class.to_s.split('::').last.downcase}"
|
36
34
|
end
|
37
35
|
|
38
|
-
def navbar_items
|
39
|
-
options&.include?(:no_menu) ? [] : settings.navbar
|
40
|
-
end
|
41
|
-
|
42
36
|
def main_content
|
43
37
|
div(class: 'container main-content py-4') do
|
44
38
|
if options&.include?(:compact_layout)
|
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.
|
4
|
+
version: 0.3.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-
|
11
|
+
date: 2023-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: phlex
|