tiny_admin 0.5.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +37 -3
- data/lib/tiny_admin/actions/index.rb +23 -23
- data/lib/tiny_admin/actions/show.rb +11 -9
- data/lib/tiny_admin/authentication.rb +6 -3
- data/lib/tiny_admin/basic_app.rb +3 -3
- data/lib/tiny_admin/context.rb +9 -14
- data/lib/tiny_admin/plugins/active_record_repository.rb +9 -5
- data/lib/tiny_admin/plugins/base_repository.rb +1 -1
- data/lib/tiny_admin/router.rb +59 -41
- data/lib/tiny_admin/section.rb +14 -0
- data/lib/tiny_admin/settings.rb +53 -72
- data/lib/tiny_admin/store.rb +67 -0
- data/lib/tiny_admin/utils.rb +13 -21
- data/lib/tiny_admin/version.rb +1 -1
- data/lib/tiny_admin/views/actions/index.rb +12 -8
- data/lib/tiny_admin/views/actions/show.rb +5 -3
- data/lib/tiny_admin/views/basic_layout.rb +2 -0
- data/lib/tiny_admin/views/basic_widget.rb +8 -0
- data/lib/tiny_admin/views/components/navbar.rb +5 -5
- data/lib/tiny_admin/views/components/widgets.rb +35 -0
- data/lib/tiny_admin/views/default_layout.rb +3 -3
- data/lib/tiny_admin/views/pages/content.rb +21 -0
- data/lib/tiny_admin/views/pages/root.rb +1 -1
- data/lib/tiny_admin.rb +16 -3
- 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: d8059ea24a18bfb14f8e868a70203db8045099e20196f5098f1c63b121421e49
|
4
|
+
data.tar.gz: d0da80d718362c58a50e963b2e79dff550e77a763d7872a0ba96efea43f408b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3067f890f10f10f5dc7379c7b147f01f5cb62b8d59f06ad7b4387c685cd2e32cdeb1f87fbfe36b0e2c388c854ce461f1a18b2659ee479e401ba74ed3c5559a3a
|
7
|
+
data.tar.gz: 0a4b4129b33e0dbf2ab2d01df14ead0ec3971a098dbed39a5b50c287e2a00c5c8448011de81a233c7bb1dda58bb42b648d44069684a65cdb4e42e3faf2a453bb
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# Tiny Admin
|
2
2
|
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/tiny_admin.svg)](https://badge.fury.io/rb/tiny_admin)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/tiny_admin.svg)](https://badge.fury.io/rb/tiny_admin)
|
4
|
+
[![Gem Downloads](https://badgen.net/rubygems/dt/tiny_admin)](https://rubygems.org/gems/tiny_admin)
|
5
|
+
[![Linters](https://github.com/blocknotes/tiny_admin/actions/workflows/linters.yml/badge.svg)](https://github.com/blocknotes/tiny_admin/actions/workflows/linters.yml)
|
6
|
+
[![Specs](https://github.com/blocknotes/tiny_admin/actions/workflows/specs.yml/badge.svg)](https://github.com/blocknotes/tiny_admin/actions/workflows/specs.yml)
|
4
7
|
|
5
8
|
A compact and composable dashboard component for Ruby.
|
6
9
|
|
@@ -16,7 +19,7 @@ Please ⭐ if you like it.
|
|
16
19
|
|
17
20
|
## Install
|
18
21
|
|
19
|
-
- Add to your Gemfile: `gem 'tiny_admin', '~> 0.
|
22
|
+
- Add to your Gemfile: `gem 'tiny_admin', '~> 0.7'`
|
20
23
|
- Mount the app in a route (check some examples with: Hanami, Rails, Roda and standalone in [extra](extra))
|
21
24
|
+ in Rails, update _config/routes.rb_: `mount TinyAdmin::Router => '/admin'`
|
22
25
|
- Configure the dashboard using `TinyAdmin.configure` and/or `TinyAdmin.configure_from_file` with a YAML config file (see [configuration](#configuration) below):
|
@@ -51,6 +54,7 @@ Plugin available:
|
|
51
54
|
Pages available:
|
52
55
|
|
53
56
|
- **Root**: define how to present the content in the main page of the interface;
|
57
|
+
- **Content**: define how to present page with inline content;
|
54
58
|
- **PageNotFound**: define how to present pages not found;
|
55
59
|
- **RecordNotFound**: define how to present record not found page;
|
56
60
|
- **SimpleAuthLogin**: define how to present the login form for SimpleAuth plugin;
|
@@ -79,6 +83,7 @@ The following options are supported:
|
|
79
83
|
- `title` (String): root section's title;
|
80
84
|
- `page` (String): a view object to render;
|
81
85
|
- `redirect` (String): alternative to _page_ option - redirects to a specific slug;
|
86
|
+
- `widgets` (Array): list of widgets (as View components) to present.
|
82
87
|
|
83
88
|
Example:
|
84
89
|
|
@@ -86,6 +91,9 @@ Example:
|
|
86
91
|
root:
|
87
92
|
title: MyAdmin
|
88
93
|
redirect: posts
|
94
|
+
widgets:
|
95
|
+
- LatestAuthorsWidget
|
96
|
+
- LatestPostsWidget
|
89
97
|
```
|
90
98
|
|
91
99
|
`helper_class` (String): class or module with helper methods, used for attributes' formatters.
|
@@ -122,9 +130,28 @@ authentication:
|
|
122
130
|
|
123
131
|
- `slug` (String): section reference identifier;
|
124
132
|
- `name` (String): section's title;
|
125
|
-
- `type` (String): the type of section: `
|
133
|
+
- `type` (String): the type of section: `content`, `page`, `resource` or `url`;
|
134
|
+
- `widgets` (Array): list of widgets (as View components) to present;
|
126
135
|
- other properties depends on the section's type.
|
127
136
|
|
137
|
+
For _content_ sections:
|
138
|
+
|
139
|
+
- `content` (String): the HTML content to present.
|
140
|
+
|
141
|
+
Example:
|
142
|
+
|
143
|
+
```yml
|
144
|
+
slug: test-content
|
145
|
+
name: Test content
|
146
|
+
type: content
|
147
|
+
content: >
|
148
|
+
<h1>Test content!</h1>
|
149
|
+
<p>Some test content</p>
|
150
|
+
widgets:
|
151
|
+
- LatestAuthorsWidget
|
152
|
+
- LatestPostsWidget
|
153
|
+
```
|
154
|
+
|
128
155
|
For _url_ sections:
|
129
156
|
|
130
157
|
- `url` (String): the URL to load when clicking on the section's menu item;
|
@@ -163,6 +190,7 @@ For _resource_ sections:
|
|
163
190
|
- `show` (Hash): detail's action options (see below);
|
164
191
|
- `collection_actions` (Array of hashes): custom collection's actions;
|
165
192
|
- `member_actions` (Array of hashes): custom details's actions;
|
193
|
+
- `widgets` (Array): list of widgets (as View components) to present;
|
166
194
|
- `only` (Array of strings): list of supported actions (ex. `index`);
|
167
195
|
- `options` (Array of strings): resource options (ex. `hidden`).
|
168
196
|
|
@@ -240,6 +268,9 @@ Example:
|
|
240
268
|
header: The author
|
241
269
|
link_to: authors
|
242
270
|
call: author, name
|
271
|
+
widgets:
|
272
|
+
- LatestAuthorsWidget
|
273
|
+
- LatestPostsWidget
|
243
274
|
```
|
244
275
|
|
245
276
|
### Sample
|
@@ -264,6 +295,9 @@ authentication:
|
|
264
295
|
# password: 'f1891cea80fc05e433c943254c6bdabc159577a02a7395dfebbfbc4f7661d4af56f2d372131a45936de40160007368a56ef216a30cb202c66d3145fd24380906'
|
265
296
|
root:
|
266
297
|
title: Test Admin
|
298
|
+
widgets:
|
299
|
+
- LatestAuthorsWidget
|
300
|
+
- LatestPostsWidget
|
267
301
|
# page: RootPage
|
268
302
|
helper_class: AdminHelper
|
269
303
|
page_not_found: PageNotFound
|
@@ -3,34 +3,38 @@
|
|
3
3
|
module TinyAdmin
|
4
4
|
module Actions
|
5
5
|
class Index < BasicAction
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :context,
|
7
|
+
:current_page,
|
7
8
|
:fields_options,
|
8
|
-
:filters_list,
|
9
9
|
:links,
|
10
|
+
:options,
|
10
11
|
:pagination,
|
11
12
|
:pages,
|
12
13
|
:params,
|
13
14
|
:query_string,
|
14
|
-
:repository
|
15
|
-
:sort
|
15
|
+
:repository
|
16
16
|
|
17
17
|
def call(app:, context:, options:)
|
18
|
+
@context = context
|
19
|
+
@options = options || {}
|
18
20
|
evaluate_options(options)
|
19
21
|
fields = repository.fields(options: fields_options)
|
20
|
-
filters = prepare_filters(fields
|
21
|
-
records,
|
22
|
+
filters = prepare_filters(fields)
|
23
|
+
records, count = repository.list(page: current_page, limit: pagination, filters: filters, sort: options[:sort])
|
24
|
+
attributes = {
|
25
|
+
actions: context.actions,
|
26
|
+
fields: fields,
|
27
|
+
filters: filters,
|
28
|
+
links: options[:links],
|
29
|
+
prepare_record: ->(record) { repository.index_record_attrs(record, fields: fields_options) },
|
30
|
+
records: records,
|
31
|
+
slug: context.slug,
|
32
|
+
title: repository.index_title,
|
33
|
+
widgets: options[:widgets]
|
34
|
+
}
|
22
35
|
|
23
|
-
prepare_page(Views::Actions::Index) do |page|
|
24
|
-
setup_pagination(page, settings.components[:pagination], total_count:
|
25
|
-
page.update_attributes(
|
26
|
-
actions: context.actions,
|
27
|
-
fields: fields,
|
28
|
-
filters: filters,
|
29
|
-
links: links,
|
30
|
-
prepare_record: ->(record) { repository.index_record_attrs(record, fields: fields_options) },
|
31
|
-
records: records,
|
32
|
-
title: repository.index_title
|
33
|
-
)
|
36
|
+
prepare_page(Views::Actions::Index, slug: context.slug, attributes: attributes) do |page|
|
37
|
+
setup_pagination(page, TinyAdmin.settings.components[:pagination], total_count: count)
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
@@ -40,17 +44,13 @@ module TinyAdmin
|
|
40
44
|
@fields_options = attribute_options(options[:attributes])
|
41
45
|
@params = context.request.params
|
42
46
|
@repository = context.repository
|
43
|
-
@filters_list = options[:filters]
|
44
47
|
@pagination = options[:pagination] || 10
|
45
|
-
@sort = options[:sort]
|
46
|
-
@links = options[:links]
|
47
|
-
|
48
48
|
@current_page = (params['p'] || 1).to_i
|
49
49
|
@query_string = params_to_s(params.except('p'))
|
50
50
|
end
|
51
51
|
|
52
|
-
def prepare_filters(fields
|
53
|
-
filters = (
|
52
|
+
def prepare_filters(fields)
|
53
|
+
filters = (options[:filters] || []).map { _1.is_a?(Hash) ? _1 : { field: _1 } }
|
54
54
|
filters = filters.each_with_object({}) { |filter, result| result[filter[:field]] = filter }
|
55
55
|
values = (params['q'] || {})
|
56
56
|
fields.each_with_object({}) do |(name, field), result|
|
@@ -8,16 +8,18 @@ module TinyAdmin
|
|
8
8
|
repository = context.repository
|
9
9
|
record = repository.find(context.reference)
|
10
10
|
prepare_record = ->(record_data) { repository.show_record_attrs(record_data, fields: fields_options) }
|
11
|
+
attributes = {
|
12
|
+
actions: context.actions,
|
13
|
+
fields: repository.fields(options: fields_options),
|
14
|
+
prepare_record: prepare_record,
|
15
|
+
record: record,
|
16
|
+
reference: context.reference,
|
17
|
+
slug: context.slug,
|
18
|
+
title: repository.show_title(record),
|
19
|
+
widgets: options[:widgets]
|
20
|
+
}
|
11
21
|
|
12
|
-
prepare_page(Views::Actions::Show
|
13
|
-
page.update_attributes(
|
14
|
-
actions: context.actions,
|
15
|
-
fields: repository.fields(options: fields_options),
|
16
|
-
prepare_record: prepare_record,
|
17
|
-
record: record,
|
18
|
-
title: repository.show_title(record)
|
19
|
-
)
|
20
|
-
end
|
22
|
+
prepare_page(Views::Actions::Show, slug: context.slug, attributes: attributes)
|
21
23
|
rescue Plugins::BaseRepository::RecordNotFound => _e
|
22
24
|
prepare_page(options[:record_not_found_page] || Views::Pages::RecordNotFound)
|
23
25
|
end
|
@@ -5,7 +5,7 @@ module TinyAdmin
|
|
5
5
|
route do |r|
|
6
6
|
r.get 'unauthenticated' do
|
7
7
|
if current_user
|
8
|
-
r.redirect settings.root_path
|
8
|
+
r.redirect TinyAdmin.settings.root_path
|
9
9
|
else
|
10
10
|
render_login
|
11
11
|
end
|
@@ -17,14 +17,17 @@ module TinyAdmin
|
|
17
17
|
|
18
18
|
r.get 'logout' do
|
19
19
|
logout_user
|
20
|
-
r.redirect settings.root_path
|
20
|
+
r.redirect TinyAdmin.settings.root_path
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def render_login(notices: nil, warnings: nil, errors: nil)
|
27
|
-
|
27
|
+
login = TinyAdmin.settings.authentication[:login]
|
28
|
+
return unless login
|
29
|
+
|
30
|
+
page = prepare_page(login, options: %i[no_menu compact_layout])
|
28
31
|
page.messages = {
|
29
32
|
notices: notices || flash['notices'],
|
30
33
|
warnings: warnings || flash['warnings'],
|
data/lib/tiny_admin/basic_app.rb
CHANGED
@@ -6,7 +6,7 @@ module TinyAdmin
|
|
6
6
|
|
7
7
|
class << self
|
8
8
|
def authentication_plugin
|
9
|
-
plugin = TinyAdmin
|
9
|
+
plugin = TinyAdmin.settings.authentication&.dig(:plugin)
|
10
10
|
plugin_class = plugin.is_a?(String) ? Object.const_get(plugin) : plugin
|
11
11
|
plugin_class || TinyAdmin::Plugins::NoAuth
|
12
12
|
end
|
@@ -17,8 +17,8 @@ module TinyAdmin
|
|
17
17
|
plugin :render, engine: 'html'
|
18
18
|
plugin :sessions, secret: SecureRandom.hex(64)
|
19
19
|
|
20
|
-
plugin authentication_plugin, TinyAdmin
|
20
|
+
plugin authentication_plugin, TinyAdmin.settings.authentication
|
21
21
|
|
22
|
-
not_found { prepare_page(settings.page_not_found).call }
|
22
|
+
not_found { prepare_page(TinyAdmin.settings.page_not_found).call }
|
23
23
|
end
|
24
24
|
end
|
data/lib/tiny_admin/context.rb
CHANGED
@@ -1,18 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinyAdmin
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
:resources,
|
14
|
-
:router,
|
15
|
-
:settings,
|
16
|
-
:slug
|
17
|
-
end
|
4
|
+
Context = Struct.new(
|
5
|
+
:actions,
|
6
|
+
:reference,
|
7
|
+
:repository,
|
8
|
+
:request,
|
9
|
+
:router,
|
10
|
+
:slug,
|
11
|
+
keyword_init: true
|
12
|
+
)
|
18
13
|
end
|
@@ -20,12 +20,12 @@ module TinyAdmin
|
|
20
20
|
def fields(options: nil)
|
21
21
|
if options
|
22
22
|
types = model.columns.to_h { [_1.name, _1.type] }
|
23
|
-
options.
|
24
|
-
|
23
|
+
options.to_h do |name, field_options|
|
24
|
+
[name, TinyAdmin::Field.create_field(name: name, type: types[name], options: field_options)]
|
25
25
|
end
|
26
26
|
else
|
27
|
-
model.columns.
|
28
|
-
|
27
|
+
model.columns.to_h do |column|
|
28
|
+
[column.name, TinyAdmin::Field.create_field(name: column.name, type: column.type)]
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -42,8 +42,12 @@ module TinyAdmin
|
|
42
42
|
raise BaseRepository::RecordNotFound, e.message
|
43
43
|
end
|
44
44
|
|
45
|
+
def collection
|
46
|
+
model.all
|
47
|
+
end
|
48
|
+
|
45
49
|
def list(page: 1, limit: 10, sort: nil, filters: nil)
|
46
|
-
query = sort ?
|
50
|
+
query = sort ? collection.order(sort) : collection
|
47
51
|
query = apply_filters(query, filters) if filters
|
48
52
|
page_offset = page.positive? ? (page - 1) * limit : 0
|
49
53
|
records = query.offset(page_offset).limit(limit).to_a
|
@@ -18,7 +18,7 @@ module TinyAdmin
|
|
18
18
|
converter = Object.const_get(field[:converter])
|
19
19
|
converter.send(method, value, options: options || [])
|
20
20
|
else
|
21
|
-
|
21
|
+
TinyAdmin.settings.helper_class.send(method, value, options: options || [])
|
22
22
|
end
|
23
23
|
else
|
24
24
|
value&.to_s
|
data/lib/tiny_admin/router.rb
CHANGED
@@ -2,13 +2,14 @@
|
|
2
2
|
|
3
3
|
module TinyAdmin
|
4
4
|
class Router < BasicApp
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegator TinyAdmin, :route_for
|
8
|
+
|
5
9
|
route do |r|
|
6
|
-
|
7
|
-
context.settings.load_settings
|
8
|
-
context.router = r
|
10
|
+
TinyAdmin.settings.load_settings
|
9
11
|
|
10
12
|
r.on 'auth' do
|
11
|
-
context.slug = nil
|
12
13
|
r.run Authentication
|
13
14
|
end
|
14
15
|
|
@@ -25,15 +26,14 @@ module TinyAdmin
|
|
25
26
|
end
|
26
27
|
|
27
28
|
r.post '' do
|
28
|
-
|
29
|
-
r.redirect settings.root_path
|
29
|
+
r.redirect TinyAdmin.settings.root_path
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
setup_page_route(r, slug,
|
32
|
+
store.pages.each do |slug, page_data|
|
33
|
+
setup_page_route(r, slug, page_data)
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
store.resources.each do |slug, options|
|
37
37
|
setup_resource_routes(r, slug, options: options || {})
|
38
38
|
end
|
39
39
|
|
@@ -42,6 +42,10 @@ module TinyAdmin
|
|
42
42
|
|
43
43
|
private
|
44
44
|
|
45
|
+
def store
|
46
|
+
@store ||= TinyAdmin.settings.store
|
47
|
+
end
|
48
|
+
|
45
49
|
def render_page(page)
|
46
50
|
if page.respond_to?(:messages=)
|
47
51
|
page.messages = { notices: flash['notices'], warnings: flash['warnings'], errors: flash['errors'] }
|
@@ -50,74 +54,83 @@ module TinyAdmin
|
|
50
54
|
end
|
51
55
|
|
52
56
|
def root_route(router)
|
53
|
-
|
54
|
-
|
55
|
-
router.redirect route_for(settings.root[:redirect])
|
57
|
+
if TinyAdmin.settings.root[:redirect]
|
58
|
+
router.redirect route_for(TinyAdmin.settings.root[:redirect])
|
56
59
|
else
|
57
|
-
|
58
|
-
|
59
|
-
render_page prepare_page(page_class)
|
60
|
+
page_class = to_class(TinyAdmin.settings.root[:page])
|
61
|
+
render_page prepare_page(page_class, attributes: TinyAdmin.settings.root.slice(:content, :title, :widgets))
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
def setup_page_route(router, slug,
|
65
|
+
def setup_page_route(router, slug, page_data)
|
64
66
|
router.get slug do
|
65
|
-
|
66
|
-
render_page prepare_page(
|
67
|
+
attributes = page_data.slice(:content, :title, :widgets)
|
68
|
+
render_page prepare_page(page_data[:class], slug: slug, attributes: attributes)
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
70
72
|
def setup_resource_routes(router, slug, options:)
|
71
73
|
router.on slug do
|
72
|
-
|
73
|
-
|
74
|
-
setup_member_routes(router, options: options)
|
74
|
+
setup_collection_routes(router, slug, options: options)
|
75
|
+
setup_member_routes(router, slug, options: options)
|
75
76
|
end
|
76
77
|
end
|
77
78
|
|
78
|
-
def setup_collection_routes(router, options:)
|
79
|
-
|
79
|
+
def setup_collection_routes(router, slug, options:)
|
80
|
+
repository = options[:repository].new(options[:model])
|
80
81
|
action_options = options[:index] || {}
|
81
82
|
|
82
83
|
# Custom actions
|
83
84
|
custom_actions = setup_custom_actions(
|
84
85
|
router,
|
85
86
|
options[:collection_actions],
|
86
|
-
|
87
|
-
|
87
|
+
options: action_options,
|
88
|
+
repository: repository,
|
89
|
+
slug: slug
|
88
90
|
)
|
89
91
|
|
90
92
|
# Index
|
91
93
|
if options[:only].include?(:index) || options[:only].include?('index')
|
92
94
|
router.is do
|
93
|
-
context
|
94
|
-
|
95
|
+
context = Context.new(
|
96
|
+
actions: custom_actions,
|
97
|
+
repository: repository,
|
98
|
+
request: request,
|
99
|
+
router: router,
|
100
|
+
slug: slug
|
101
|
+
)
|
95
102
|
index_action = TinyAdmin::Actions::Index.new
|
96
103
|
render_page index_action.call(app: self, context: context, options: action_options)
|
97
104
|
end
|
98
105
|
end
|
99
106
|
end
|
100
107
|
|
101
|
-
def setup_member_routes(router, options:)
|
102
|
-
|
103
|
-
action_options = (options[:show] || {}).merge(record_not_found_page: settings.record_not_found)
|
108
|
+
def setup_member_routes(router, slug, options:)
|
109
|
+
repository = options[:repository].new(options[:model])
|
110
|
+
action_options = (options[:show] || {}).merge(record_not_found_page: TinyAdmin.settings.record_not_found)
|
104
111
|
|
105
112
|
router.on String do |reference|
|
106
|
-
context.reference = reference
|
107
|
-
|
108
113
|
# Custom actions
|
109
114
|
custom_actions = setup_custom_actions(
|
110
115
|
router,
|
111
116
|
options[:member_actions],
|
112
|
-
|
113
|
-
|
117
|
+
options: action_options,
|
118
|
+
repository: repository,
|
119
|
+
slug: slug,
|
120
|
+
reference: reference
|
114
121
|
)
|
115
122
|
|
116
123
|
# Show
|
117
124
|
if options[:only].include?(:show) || options[:only].include?('show')
|
118
125
|
router.is do
|
119
|
-
context
|
120
|
-
|
126
|
+
context = Context.new(
|
127
|
+
actions: custom_actions,
|
128
|
+
reference: reference,
|
129
|
+
repository: repository,
|
130
|
+
request: request,
|
131
|
+
router: router,
|
132
|
+
slug: slug
|
133
|
+
)
|
121
134
|
show_action = TinyAdmin::Actions::Show.new
|
122
135
|
render_page show_action.call(app: self, context: context, options: action_options)
|
123
136
|
end
|
@@ -125,15 +138,20 @@ module TinyAdmin
|
|
125
138
|
end
|
126
139
|
end
|
127
140
|
|
128
|
-
def setup_custom_actions(router, custom_actions, repository:,
|
129
|
-
context.repository = repository
|
141
|
+
def setup_custom_actions(router, custom_actions, options:, repository:, slug:, reference: nil)
|
130
142
|
(custom_actions || []).each_with_object({}) do |custom_action, result|
|
131
143
|
action_slug, action = custom_action.first
|
132
|
-
action_class =
|
144
|
+
action_class = to_class(action)
|
133
145
|
|
134
146
|
router.get action_slug.to_s do
|
135
|
-
context
|
136
|
-
|
147
|
+
context = Context.new(
|
148
|
+
actions: {},
|
149
|
+
reference: reference,
|
150
|
+
repository: repository,
|
151
|
+
request: request,
|
152
|
+
router: router,
|
153
|
+
slug: slug
|
154
|
+
)
|
137
155
|
custom_action = action_class.new
|
138
156
|
render_page custom_action.call(app: self, context: context, options: options)
|
139
157
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinyAdmin
|
4
|
+
class Section
|
5
|
+
attr_reader :name, :options, :path, :slug
|
6
|
+
|
7
|
+
def initialize(name:, slug: nil, path: nil, options: {})
|
8
|
+
@name = name
|
9
|
+
@options = options
|
10
|
+
@path = path || TinyAdmin.route_for(slug)
|
11
|
+
@slug = slug
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/tiny_admin/settings.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
module TinyAdmin
|
4
4
|
class Settings
|
5
5
|
include Singleton
|
6
|
-
include Utils
|
7
6
|
|
8
7
|
DEFAULTS = {
|
9
8
|
%i[authentication plugin] => Plugins::NoAuth,
|
@@ -12,34 +11,53 @@ module TinyAdmin
|
|
12
11
|
%i[components head] => Views::Components::Head,
|
13
12
|
%i[components navbar] => Views::Components::Navbar,
|
14
13
|
%i[components pagination] => Views::Components::Pagination,
|
14
|
+
%i[content_page] => Views::Pages::Content,
|
15
15
|
%i[helper_class] => Support,
|
16
16
|
%i[page_not_found] => Views::Pages::PageNotFound,
|
17
17
|
%i[record_not_found] => Views::Pages::RecordNotFound,
|
18
18
|
%i[repository] => Plugins::ActiveRecordRepository,
|
19
19
|
%i[root_path] => '/admin',
|
20
20
|
%i[root page] => Views::Pages::Root,
|
21
|
-
%i[root title] => 'TinyAdmin'
|
21
|
+
%i[root title] => 'TinyAdmin',
|
22
|
+
%i[sections] => []
|
22
23
|
}.freeze
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
OPTIONS = %i[
|
26
|
+
authentication
|
27
|
+
components
|
28
|
+
content_page
|
29
|
+
extra_styles
|
30
|
+
helper_class
|
31
|
+
page_not_found
|
32
|
+
record_not_found
|
33
|
+
repository
|
34
|
+
root
|
35
|
+
root_path
|
36
|
+
sections
|
37
|
+
scripts
|
38
|
+
style_links
|
39
|
+
].freeze
|
40
|
+
|
41
|
+
attr_reader :store
|
42
|
+
|
43
|
+
OPTIONS.each do |option|
|
44
|
+
define_method(option) do
|
45
|
+
self[option]
|
46
|
+
end
|
47
|
+
|
48
|
+
define_method("#{option}=") do |value|
|
49
|
+
self[option] = value
|
50
|
+
end
|
51
|
+
end
|
36
52
|
|
37
|
-
def [](
|
38
|
-
|
53
|
+
def [](*path)
|
54
|
+
key, option = fetch_setting(path)
|
55
|
+
option[key]
|
39
56
|
end
|
40
57
|
|
41
|
-
def []=(
|
42
|
-
|
58
|
+
def []=(*path, value)
|
59
|
+
key, option = fetch_setting(path)
|
60
|
+
option[key] = value
|
43
61
|
convert_value(key, value)
|
44
62
|
end
|
45
63
|
|
@@ -54,24 +72,33 @@ module TinyAdmin
|
|
54
72
|
end
|
55
73
|
end
|
56
74
|
|
57
|
-
|
58
|
-
|
59
|
-
@sections ||= []
|
60
|
-
@root_path = '/' if @root_path == ''
|
75
|
+
@store ||= TinyAdmin::Store.new(self)
|
76
|
+
self.root_path = '/' if root_path == ''
|
61
77
|
|
62
|
-
if
|
63
|
-
|
78
|
+
if authentication[:plugin] <= Plugins::SimpleAuth
|
79
|
+
logout_path = "#{root_path}/auth/logout"
|
80
|
+
authentication[:logout] ||= TinyAdmin::Section.new(name: 'logout', slug: 'logout', path: logout_path)
|
64
81
|
end
|
65
|
-
|
82
|
+
store.prepare_sections(sections, logout: authentication[:logout])
|
83
|
+
end
|
84
|
+
|
85
|
+
def reset!
|
86
|
+
@options = {}
|
66
87
|
end
|
67
88
|
|
68
89
|
private
|
69
90
|
|
91
|
+
def fetch_setting(path)
|
92
|
+
@options ||= {}
|
93
|
+
*parts, last = path.map(&:to_sym)
|
94
|
+
[last, parts.inject(@options) { |result, part| result[part] ||= {} }]
|
95
|
+
end
|
96
|
+
|
70
97
|
def convert_value(key, value)
|
71
98
|
if value.is_a?(Hash)
|
72
99
|
value.each_key do |key2|
|
73
100
|
path = [key, key2]
|
74
|
-
if DEFAULTS[path].is_a?(Class) || DEFAULTS[path].is_a?(Module)
|
101
|
+
if (DEFAULTS[path].is_a?(Class) || DEFAULTS[path].is_a?(Module)) && self[key][key2].is_a?(String)
|
75
102
|
self[key][key2] = Object.const_get(self[key][key2])
|
76
103
|
end
|
77
104
|
end
|
@@ -79,51 +106,5 @@ module TinyAdmin
|
|
79
106
|
self[key] = Object.const_get(self[key])
|
80
107
|
end
|
81
108
|
end
|
82
|
-
|
83
|
-
def prepare_navbar(sections, logout:)
|
84
|
-
items = sections.each_with_object({}) do |section, list|
|
85
|
-
unless section.is_a?(Hash)
|
86
|
-
section_class = Object.const_get(section)
|
87
|
-
next unless section_class.respond_to?(:to_h)
|
88
|
-
|
89
|
-
section = section_class.to_h
|
90
|
-
end
|
91
|
-
|
92
|
-
slug = section[:slug].to_s
|
93
|
-
case section[:type]&.to_sym
|
94
|
-
when :url
|
95
|
-
list[slug] = add_url_section(slug, section)
|
96
|
-
when :page
|
97
|
-
list[slug] = add_page_section(slug, section)
|
98
|
-
when :resource
|
99
|
-
list[slug] = add_resource_section(slug, section)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
items['auth/logout'] = logout if logout
|
103
|
-
items
|
104
|
-
end
|
105
|
-
|
106
|
-
def add_url_section(_slug, section)
|
107
|
-
section.slice(:name, :options).tap { _1[:path] = section[:url] }
|
108
|
-
end
|
109
|
-
|
110
|
-
def add_page_section(slug, section)
|
111
|
-
page = section[:page]
|
112
|
-
context.pages[slug] = page.is_a?(String) ? Object.const_get(page) : page
|
113
|
-
{ name: section[:name], path: route_for(slug), class: context.pages[slug] }
|
114
|
-
end
|
115
|
-
|
116
|
-
def add_resource_section(slug, section)
|
117
|
-
repository = section[:repository] || settings.repository
|
118
|
-
context.resources[slug] = {
|
119
|
-
model: section[:model].is_a?(String) ? Object.const_get(section[:model]) : section[:model],
|
120
|
-
repository: repository.is_a?(String) ? Object.const_get(repository) : repository
|
121
|
-
}
|
122
|
-
resource_options = section.slice(:resource, :only, :index, :show, :collection_actions, :member_actions)
|
123
|
-
resource_options[:only] ||= %i[index show]
|
124
|
-
context.resources[slug].merge!(resource_options)
|
125
|
-
hidden = section[:options] && (section[:options].include?(:hidden) || section[:options].include?('hidden'))
|
126
|
-
{ name: section[:name], path: route_for(slug) } unless hidden
|
127
|
-
end
|
128
109
|
end
|
129
110
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinyAdmin
|
4
|
+
class Store
|
5
|
+
include Utils
|
6
|
+
|
7
|
+
attr_reader :navbar, :pages, :resources, :settings
|
8
|
+
|
9
|
+
def initialize(settings)
|
10
|
+
@pages = {}
|
11
|
+
@resources = {}
|
12
|
+
@settings = settings
|
13
|
+
end
|
14
|
+
|
15
|
+
def prepare_sections(sections, logout:)
|
16
|
+
@navbar = sections.each_with_object([]) do |section, list|
|
17
|
+
unless section.is_a?(Hash)
|
18
|
+
section_class = to_class(section)
|
19
|
+
next unless section_class.respond_to?(:to_h)
|
20
|
+
|
21
|
+
section = section_class.to_h
|
22
|
+
end
|
23
|
+
|
24
|
+
slug = section[:slug].to_s
|
25
|
+
case section[:type]&.to_sym
|
26
|
+
when :content
|
27
|
+
list << add_content_section(slug, section)
|
28
|
+
when :page
|
29
|
+
list << add_page_section(slug, section)
|
30
|
+
when :resource
|
31
|
+
list << add_resource_section(slug, section)
|
32
|
+
when :url
|
33
|
+
list << add_url_section(slug, section)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
navbar << logout if logout
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def add_content_section(slug, section)
|
42
|
+
pages[slug] = { class: settings.content_page, content: section[:content], widgets: section[:widgets] }
|
43
|
+
TinyAdmin::Section.new(name: section[:name], slug: slug)
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_page_section(slug, section)
|
47
|
+
pages[slug] = { class: to_class(section[:page]) }
|
48
|
+
TinyAdmin::Section.new(name: section[:name], slug: slug)
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_resource_section(slug, section)
|
52
|
+
resource = section.slice(:resource, :only, :index, :show, :collection_actions, :member_actions)
|
53
|
+
resource[:only] ||= %i[index show]
|
54
|
+
resources[slug] = resource.merge(
|
55
|
+
model: to_class(section[:model]),
|
56
|
+
repository: to_class(section[:repository] || settings.repository)
|
57
|
+
)
|
58
|
+
|
59
|
+
hidden = section[:options] && (section[:options].include?(:hidden) || section[:options].include?('hidden'))
|
60
|
+
TinyAdmin::Section.new(name: section[:name], slug: slug) unless hidden
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_url_section(slug, section)
|
64
|
+
TinyAdmin::Section.new(name: section[:name], options: section[:options], path: section[:url], slug: slug)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/tiny_admin/utils.rb
CHANGED
@@ -14,27 +14,27 @@ module TinyAdmin
|
|
14
14
|
list.join('&')
|
15
15
|
end
|
16
16
|
|
17
|
-
def prepare_page(page_class, options: nil)
|
17
|
+
def prepare_page(page_class, slug: nil, attributes: nil, options: nil)
|
18
18
|
page_class.new.tap do |page|
|
19
19
|
page.options = options
|
20
|
-
page.head_component = settings.components[:head]&.new
|
21
|
-
page.flash_component = settings.components[:flash]&.new
|
22
|
-
page.navbar_component = settings.components[:navbar]&.new
|
20
|
+
page.head_component = TinyAdmin.settings.components[:head]&.new
|
21
|
+
page.flash_component = TinyAdmin.settings.components[:flash]&.new
|
22
|
+
page.navbar_component = TinyAdmin.settings.components[:navbar]&.new
|
23
23
|
page.navbar_component&.update_attributes(
|
24
|
-
current_slug:
|
25
|
-
root_path: settings.root_path,
|
26
|
-
root_title: settings.root[:title],
|
27
|
-
items: options&.include?(:no_menu) ? [] :
|
24
|
+
current_slug: slug,
|
25
|
+
root_path: TinyAdmin.settings.root_path,
|
26
|
+
root_title: TinyAdmin.settings.root[:title],
|
27
|
+
items: options&.include?(:no_menu) ? [] : TinyAdmin.settings.store&.navbar
|
28
28
|
)
|
29
|
+
attrs = attributes || {}
|
30
|
+
attrs[:widgets] = attrs[:widgets].map { to_class(_1) } if attrs[:widgets]
|
31
|
+
page.update_attributes(attrs) unless attrs.empty?
|
29
32
|
yield(page) if block_given?
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
34
|
-
|
35
|
-
route = [root_path, section, reference, action].compact.join("/")
|
36
|
-
route << "?#{query}" if query
|
37
|
-
route[0] == '/' ? route : route.prepend('/')
|
36
|
+
def to_class(klass)
|
37
|
+
klass.is_a?(String) ? Object.const_get(klass) : klass
|
38
38
|
end
|
39
39
|
|
40
40
|
def to_label(string)
|
@@ -42,13 +42,5 @@ module TinyAdmin
|
|
42
42
|
|
43
43
|
string.respond_to?(:humanize) ? string.humanize : string.tr('_', ' ').capitalize
|
44
44
|
end
|
45
|
-
|
46
|
-
def context
|
47
|
-
TinyAdmin::Context.instance
|
48
|
-
end
|
49
|
-
|
50
|
-
def settings
|
51
|
-
TinyAdmin::Settings.instance
|
52
|
-
end
|
53
45
|
end
|
54
46
|
end
|
data/lib/tiny_admin/version.rb
CHANGED
@@ -4,14 +4,16 @@ module TinyAdmin
|
|
4
4
|
module Views
|
5
5
|
module Actions
|
6
6
|
class Index < DefaultLayout
|
7
|
-
attr_accessor :actions, :fields, :filters, :links, :pagination_component, :prepare_record, :records
|
7
|
+
attr_accessor :actions, :fields, :filters, :links, :pagination_component, :prepare_record, :records, :slug
|
8
8
|
|
9
9
|
def template
|
10
10
|
super do
|
11
11
|
div(class: 'index') {
|
12
12
|
div(class: 'row') {
|
13
13
|
div(class: 'col-4') {
|
14
|
-
h1(class: 'title') {
|
14
|
+
h1(class: 'title') {
|
15
|
+
title
|
16
|
+
}
|
15
17
|
}
|
16
18
|
div(class: 'col-8') {
|
17
19
|
actions_buttons
|
@@ -31,13 +33,15 @@ module TinyAdmin
|
|
31
33
|
if filters&.any?
|
32
34
|
div(class: 'col-3') {
|
33
35
|
filters_form = TinyAdmin::Views::Components::FiltersForm.new
|
34
|
-
filters_form.update_attributes(section_path: route_for(
|
36
|
+
filters_form.update_attributes(section_path: TinyAdmin.route_for(slug), filters: filters)
|
35
37
|
render filters_form
|
36
38
|
}
|
37
39
|
end
|
38
40
|
}
|
39
41
|
|
40
42
|
render pagination_component if pagination_component
|
43
|
+
|
44
|
+
render TinyAdmin::Views::Components::Widgets.new(widgets)
|
41
45
|
}
|
42
46
|
end
|
43
47
|
end
|
@@ -66,7 +70,7 @@ module TinyAdmin
|
|
66
70
|
field = fields[key]
|
67
71
|
td(class: "field-value-#{field.name} field-value-type-#{field.type}") {
|
68
72
|
if field.options && field.options[:link_to]
|
69
|
-
a(href: route_for(field.options[:link_to], reference: value)) {
|
73
|
+
a(href: TinyAdmin.route_for(field.options[:link_to], reference: value)) {
|
70
74
|
field.apply_call_option(record) || value
|
71
75
|
}
|
72
76
|
else
|
@@ -82,15 +86,15 @@ module TinyAdmin
|
|
82
86
|
links.each do |link|
|
83
87
|
whitespace
|
84
88
|
if link == 'show'
|
85
|
-
a(href: route_for(
|
89
|
+
a(href: TinyAdmin.route_for(slug, reference: record.id), class: link_class) { 'show' }
|
86
90
|
else
|
87
|
-
a(href: route_for(
|
91
|
+
a(href: TinyAdmin.route_for(slug, reference: record.id, action: link), class: link_class) {
|
88
92
|
to_label(link)
|
89
93
|
}
|
90
94
|
end
|
91
95
|
end
|
92
96
|
else
|
93
|
-
a(href: route_for(
|
97
|
+
a(href: TinyAdmin.route_for(slug, reference: record.id), class: link_class) { 'show' }
|
94
98
|
end
|
95
99
|
}
|
96
100
|
}
|
@@ -103,7 +107,7 @@ module TinyAdmin
|
|
103
107
|
ul(class: 'nav justify-content-end') {
|
104
108
|
(actions || {}).each do |action, action_class|
|
105
109
|
li(class: 'nav-item mx-1') {
|
106
|
-
href = route_for(
|
110
|
+
href = TinyAdmin.route_for(slug, action: action)
|
107
111
|
a(href: href, class: 'nav-link btn btn-outline-secondary') {
|
108
112
|
action_class.respond_to?(:title) ? action_class.title : action
|
109
113
|
}
|
@@ -4,7 +4,7 @@ module TinyAdmin
|
|
4
4
|
module Views
|
5
5
|
module Actions
|
6
6
|
class Show < DefaultLayout
|
7
|
-
attr_accessor :actions, :fields, :prepare_record, :record
|
7
|
+
attr_accessor :actions, :fields, :prepare_record, :record, :reference, :slug
|
8
8
|
|
9
9
|
def template
|
10
10
|
super do
|
@@ -26,7 +26,7 @@ module TinyAdmin
|
|
26
26
|
end
|
27
27
|
div(class: 'field-value col-10') {
|
28
28
|
if field.options[:link_to]
|
29
|
-
a(href: route_for(field.options[:link_to], reference: value)) {
|
29
|
+
a(href: TinyAdmin.route_for(field.options[:link_to], reference: value)) {
|
30
30
|
field.apply_call_option(record) || value
|
31
31
|
}
|
32
32
|
else
|
@@ -35,6 +35,8 @@ module TinyAdmin
|
|
35
35
|
}
|
36
36
|
}
|
37
37
|
end
|
38
|
+
|
39
|
+
render TinyAdmin::Views::Components::Widgets.new(widgets)
|
38
40
|
}
|
39
41
|
end
|
40
42
|
end
|
@@ -45,7 +47,7 @@ module TinyAdmin
|
|
45
47
|
ul(class: 'nav justify-content-end') {
|
46
48
|
(actions || {}).each do |action, action_class|
|
47
49
|
li(class: 'nav-item mx-1') {
|
48
|
-
href = route_for(
|
50
|
+
href = TinyAdmin.route_for(slug, reference: reference, action: action)
|
49
51
|
a(href: href, class: 'nav-link btn btn-outline-secondary') {
|
50
52
|
action_class.respond_to?(:title) ? action_class.title : action
|
51
53
|
}
|
@@ -23,14 +23,14 @@ module TinyAdmin
|
|
23
23
|
}
|
24
24
|
div(class: 'collapse navbar-collapse', id: 'navbarNav') {
|
25
25
|
ul(class: 'navbar-nav') {
|
26
|
-
items.each do |
|
26
|
+
items.each do |item|
|
27
27
|
classes = %w[nav-link]
|
28
|
-
classes << 'active' if slug == current_slug
|
29
|
-
link_attributes = { class: classes.join(' '), href: item
|
30
|
-
link_attributes.merge!(item
|
28
|
+
classes << 'active' if item.slug == current_slug
|
29
|
+
link_attributes = { class: classes.join(' '), href: item.path, 'aria-current' => 'page' }
|
30
|
+
link_attributes.merge!(item.options) if item.options
|
31
31
|
|
32
32
|
li(class: 'nav-item') {
|
33
|
-
a(**link_attributes) { item
|
33
|
+
a(**link_attributes) { item.name }
|
34
34
|
}
|
35
35
|
end
|
36
36
|
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinyAdmin
|
4
|
+
module Views
|
5
|
+
module Components
|
6
|
+
class Widgets < BasicComponent
|
7
|
+
def initialize(widgets)
|
8
|
+
@widgets = widgets
|
9
|
+
end
|
10
|
+
|
11
|
+
def template
|
12
|
+
return if @widgets.nil? || @widgets.empty?
|
13
|
+
|
14
|
+
div(class: 'container widgets') {
|
15
|
+
@widgets.each_slice(2).each do |row|
|
16
|
+
div(class: 'row') {
|
17
|
+
row.each do |widget|
|
18
|
+
next unless widget < Phlex::HTML
|
19
|
+
|
20
|
+
div(class: 'col') {
|
21
|
+
div(class: 'card') {
|
22
|
+
div(class: 'card-body') {
|
23
|
+
render widget.new
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -6,7 +6,7 @@ module TinyAdmin
|
|
6
6
|
attr_accessor :flash_component, :head_component, :messages, :navbar_component, :options, :title
|
7
7
|
|
8
8
|
def template(&block)
|
9
|
-
extra_styles = settings.extra_styles
|
9
|
+
extra_styles = TinyAdmin.settings.extra_styles
|
10
10
|
flash_component&.messages = messages
|
11
11
|
head_component&.update_attributes(page_title: title, style_links: style_links, extra_styles: extra_styles)
|
12
12
|
|
@@ -49,7 +49,7 @@ module TinyAdmin
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def style_links
|
52
|
-
settings.style_links || [
|
52
|
+
TinyAdmin.settings.style_links || [
|
53
53
|
# Bootstrap CDN
|
54
54
|
{
|
55
55
|
href: 'https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css',
|
@@ -61,7 +61,7 @@ module TinyAdmin
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def render_scripts
|
64
|
-
(settings.scripts || []).each do |script_attrs|
|
64
|
+
(TinyAdmin.settings.scripts || []).each do |script_attrs|
|
65
65
|
script(**script_attrs)
|
66
66
|
end
|
67
67
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinyAdmin
|
4
|
+
module Views
|
5
|
+
module Pages
|
6
|
+
class Content < DefaultLayout
|
7
|
+
def template
|
8
|
+
super do
|
9
|
+
div(class: 'content') {
|
10
|
+
div(class: 'content-data') {
|
11
|
+
unsafe_raw(content)
|
12
|
+
}
|
13
|
+
|
14
|
+
render TinyAdmin::Views::Components::Widgets.new(widgets)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/tiny_admin.rb
CHANGED
@@ -4,6 +4,7 @@ require 'phlex'
|
|
4
4
|
require 'roda'
|
5
5
|
require 'zeitwerk'
|
6
6
|
|
7
|
+
require 'forwardable'
|
7
8
|
require 'singleton'
|
8
9
|
require 'yaml'
|
9
10
|
|
@@ -12,15 +13,27 @@ loader.setup
|
|
12
13
|
|
13
14
|
module TinyAdmin
|
14
15
|
def configure(&block)
|
15
|
-
block&.call(
|
16
|
+
block&.call(settings) || settings
|
16
17
|
end
|
17
18
|
|
18
19
|
def configure_from_file(file)
|
20
|
+
settings.reset!
|
19
21
|
config = YAML.load_file(file, symbolize_names: true)
|
20
22
|
config.each do |key, value|
|
21
|
-
|
23
|
+
settings[key] = value
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
|
27
|
+
def route_for(section, reference: nil, action: nil, query: nil)
|
28
|
+
root_path = settings.root_path == '/' ? nil : settings.root_path
|
29
|
+
route = [root_path, section, reference, action].compact.join("/")
|
30
|
+
route << "?#{query}" if query
|
31
|
+
route[0] == '/' ? route : route.prepend('/')
|
32
|
+
end
|
33
|
+
|
34
|
+
def settings
|
35
|
+
TinyAdmin::Settings.instance
|
36
|
+
end
|
37
|
+
|
38
|
+
module_function :configure, :configure_from_file, :route_for, :settings
|
26
39
|
end
|
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.7.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-
|
11
|
+
date: 2023-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: phlex
|
@@ -87,20 +87,25 @@ files:
|
|
87
87
|
- lib/tiny_admin/plugins/no_auth.rb
|
88
88
|
- lib/tiny_admin/plugins/simple_auth.rb
|
89
89
|
- lib/tiny_admin/router.rb
|
90
|
+
- lib/tiny_admin/section.rb
|
90
91
|
- lib/tiny_admin/settings.rb
|
92
|
+
- lib/tiny_admin/store.rb
|
91
93
|
- lib/tiny_admin/support.rb
|
92
94
|
- lib/tiny_admin/utils.rb
|
93
95
|
- lib/tiny_admin/version.rb
|
94
96
|
- lib/tiny_admin/views/actions/index.rb
|
95
97
|
- lib/tiny_admin/views/actions/show.rb
|
96
98
|
- lib/tiny_admin/views/basic_layout.rb
|
99
|
+
- lib/tiny_admin/views/basic_widget.rb
|
97
100
|
- lib/tiny_admin/views/components/basic_component.rb
|
98
101
|
- lib/tiny_admin/views/components/filters_form.rb
|
99
102
|
- lib/tiny_admin/views/components/flash.rb
|
100
103
|
- lib/tiny_admin/views/components/head.rb
|
101
104
|
- lib/tiny_admin/views/components/navbar.rb
|
102
105
|
- lib/tiny_admin/views/components/pagination.rb
|
106
|
+
- lib/tiny_admin/views/components/widgets.rb
|
103
107
|
- lib/tiny_admin/views/default_layout.rb
|
108
|
+
- lib/tiny_admin/views/pages/content.rb
|
104
109
|
- lib/tiny_admin/views/pages/page_not_found.rb
|
105
110
|
- lib/tiny_admin/views/pages/record_not_found.rb
|
106
111
|
- lib/tiny_admin/views/pages/root.rb
|