ab_admin 0.10.0 → 0.12.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 +2 -2
- data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +1 -1
- data/app/assets/javascripts/ab_admin/core/batch_actions.js.coffee +7 -3
- data/app/controllers/admin/assets_controller.rb +6 -2
- data/config/routes.rb +30 -10
- data/lib/ab_admin/carrierwave/base_uploader.rb +31 -4
- data/lib/ab_admin/concerns/utilities.rb +1 -1
- data/lib/ab_admin/core_ext/array.rb +5 -3
- data/lib/ab_admin/core_ext/hash.rb +11 -7
- data/lib/ab_admin/core_ext/string.rb +2 -2
- data/lib/ab_admin/engine.rb +4 -0
- data/lib/ab_admin/models/asset.rb +1 -1
- data/lib/ab_admin/models/settings.rb +1 -1
- data/lib/ab_admin/models/track.rb +2 -2
- data/lib/ab_admin/models/type_model.rb +1 -1
- data/lib/ab_admin/version.rb +1 -1
- data/lib/ab_admin/views/admin_helpers.rb +16 -17
- data/lib/ab_admin/views/form_builder.rb +1 -1
- data/lib/ab_admin.rb +11 -0
- metadata +9 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fb0ea0be238f876e8ef98daa6bbebf85f46894948f62a69bbe21bdd5536b3762
|
|
4
|
+
data.tar.gz: 62dc60a35278dc9adad7bc59fcd2ff0a4be46e7db4c67768c21875ca3751ed70
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e35c066aa098cf2d947c25a2c6712a8c5c587af84bfd7f55034128db4b8aec66f731e987baa690c7f39326c5f27b30ec77ec6a0c4b41c57ac8c6321a14d91d8b
|
|
7
|
+
data.tar.gz: af7a163e88da0ff71562a7f497eb8914fe6394508be6c4b9a0c733994cd5f8807ba5d32596241924754a42f6c1a327059418a126dcf7204648bf971ad1d46718
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Simple and real-life tested Rails::Engine admin interface based on slim, bootstr
|
|
|
6
6
|
|
|
7
7
|
Add this line to your application's Gemfile:
|
|
8
8
|
|
|
9
|
-
gem '
|
|
9
|
+
gem 'ab_admin'
|
|
10
10
|
|
|
11
11
|
And then execute:
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ And then execute:
|
|
|
14
14
|
|
|
15
15
|
Or install it yourself as:
|
|
16
16
|
|
|
17
|
-
$ gem install
|
|
17
|
+
$ gem install ab_admin
|
|
18
18
|
|
|
19
19
|
Run generators
|
|
20
20
|
|
|
@@ -45,7 +45,7 @@ window.initInPlaceEditable = ->
|
|
|
45
45
|
if response && $(this).data().options?.accept == 'script'
|
|
46
46
|
$.globalEval(response.responseText)
|
|
47
47
|
datetimepicker:
|
|
48
|
-
format: "dd
|
|
48
|
+
format: "yyyy-mm-dd hh:ii"
|
|
49
49
|
autoclose: true
|
|
50
50
|
todayBtn: true
|
|
51
51
|
language: I18n.locale
|
|
@@ -42,7 +42,7 @@ $ ->
|
|
|
42
42
|
$form.append($idsInputs)
|
|
43
43
|
$form.append($extraData)
|
|
44
44
|
$form.submit()
|
|
45
|
-
|
|
45
|
+
bootbox.hideAll() if window.bootbox?
|
|
46
46
|
$extraData?.remove()
|
|
47
47
|
$idsInputs.remove()
|
|
48
48
|
|
|
@@ -63,11 +63,15 @@ $ ->
|
|
|
63
63
|
$form = $($el.data('form'))
|
|
64
64
|
unless $form.find('.js-batch_form_submit').length
|
|
65
65
|
$form.append("<div class='btn btn-primary js-batch_form_submit' data-form=#{$el.data('form')} data-action=#{$el.data('action')}><i class='icon-ok icon-white'></i></div>")
|
|
66
|
-
$form.append("<div class='btn
|
|
67
|
-
|
|
66
|
+
$form.append("<div class='btn js-batch_form_cancel'><i class='icon-remove'></i></div>")
|
|
67
|
+
bootbox.dialog({message: $form.show(), className: 'batch-action-form'})
|
|
68
68
|
else
|
|
69
69
|
submitBatch(this)
|
|
70
70
|
|
|
71
|
+
$(document).on 'click', '.js-batch_form_cancel', (e) ->
|
|
72
|
+
e.preventDefault()
|
|
73
|
+
bootbox.hideAll() if window.bootbox?
|
|
74
|
+
|
|
71
75
|
$(document).on 'click', '.js-batch_form_submit', (e) ->
|
|
72
76
|
e.preventDefault()
|
|
73
77
|
submitBatch(this, $($(this).data('form')).find('input,textarea,select').clone())
|
|
@@ -34,7 +34,7 @@ class Admin::AssetsController < ApplicationController
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def batch_update
|
|
37
|
-
Asset.update(params[:data].keys, params[:data].values)
|
|
37
|
+
Asset.update(params[:data].keys, params[:data].values.map{ _1.permit(*permitted_assets_attributes) })
|
|
38
38
|
@assets = Asset.find(params[:data].keys)
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -53,7 +53,11 @@ class Admin::AssetsController < ApplicationController
|
|
|
53
53
|
protected
|
|
54
54
|
|
|
55
55
|
def permitted_params
|
|
56
|
-
params[:asset].try!(:permit, :data,
|
|
56
|
+
params[:asset].try!(:permit, :data, *permitted_assets_attributes)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def permitted_assets_attributes
|
|
60
|
+
[:is_main, :original_name, :human_filename, *Asset.all_translated_attribute_names.map(&:to_sym)]
|
|
57
61
|
end
|
|
58
62
|
|
|
59
63
|
def find_asset
|
data/config/routes.rb
CHANGED
|
@@ -4,29 +4,49 @@ Rails.application.routes.draw do
|
|
|
4
4
|
get 'dashboards', as: 'dashboards'
|
|
5
5
|
|
|
6
6
|
resources :structures do
|
|
7
|
-
|
|
7
|
+
collection do
|
|
8
|
+
post :batch
|
|
9
|
+
post :rebuild
|
|
10
|
+
end
|
|
8
11
|
resource :static_page
|
|
9
12
|
end
|
|
10
13
|
|
|
11
14
|
resources :users do
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
collection do
|
|
16
|
+
post :batch
|
|
17
|
+
end
|
|
18
|
+
member do
|
|
19
|
+
post :activate
|
|
20
|
+
post :suspend
|
|
21
|
+
end
|
|
14
22
|
end
|
|
15
23
|
|
|
16
24
|
resources :assets, only: [:create, :destroy] do
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
member do
|
|
26
|
+
post :rotate
|
|
27
|
+
post :main
|
|
28
|
+
post :crop
|
|
29
|
+
end
|
|
30
|
+
collection do
|
|
31
|
+
post :sort
|
|
32
|
+
get :batch_edit
|
|
33
|
+
post :batch_update
|
|
34
|
+
end
|
|
21
35
|
end
|
|
22
36
|
|
|
23
37
|
resource :settings, only: [:edit, :update] do
|
|
24
|
-
|
|
38
|
+
collection do
|
|
39
|
+
post :cache_clear
|
|
40
|
+
end
|
|
25
41
|
end
|
|
26
42
|
|
|
27
43
|
resource :locators do
|
|
28
|
-
|
|
29
|
-
|
|
44
|
+
collection do
|
|
45
|
+
post :prepare
|
|
46
|
+
post :reload
|
|
47
|
+
post :import
|
|
48
|
+
get :export
|
|
49
|
+
end
|
|
30
50
|
end
|
|
31
51
|
|
|
32
52
|
resources :admin_comments
|
|
@@ -10,6 +10,8 @@ module AbAdmin
|
|
|
10
10
|
class_attribute :human_filenames
|
|
11
11
|
self.human_filenames = true
|
|
12
12
|
|
|
13
|
+
CACHE_ID_REGEXP = /\A(?:\d+[-_]){4}/.freeze
|
|
14
|
+
|
|
13
15
|
attr_accessor :internal_identifier
|
|
14
16
|
|
|
15
17
|
before :cache, :save_original_name
|
|
@@ -28,6 +30,12 @@ module AbAdmin
|
|
|
28
30
|
"#{[human_part, secure_token].compact.join('_')}#{extension}"
|
|
29
31
|
end
|
|
30
32
|
|
|
33
|
+
def identifier
|
|
34
|
+
raw = super
|
|
35
|
+
return raw unless raw.is_a?(String) && raw.match?(CACHE_ID_REGEXP)
|
|
36
|
+
raw.sub(CACHE_ID_REGEXP, '')
|
|
37
|
+
end
|
|
38
|
+
|
|
31
39
|
def full_filename(*)
|
|
32
40
|
return filename unless version_name
|
|
33
41
|
base = "#{version_filename_part}#{version_extension}"
|
|
@@ -35,8 +43,26 @@ module AbAdmin
|
|
|
35
43
|
[human_part, base].compact.join('_')
|
|
36
44
|
end
|
|
37
45
|
|
|
38
|
-
def human_part
|
|
39
|
-
|
|
46
|
+
def human_part(index = nil)
|
|
47
|
+
raw = model.public_send("#{mounted_as}_file_name").to_s.strip
|
|
48
|
+
raw = strip_extension(raw)
|
|
49
|
+
raw = strip_cache_id(raw)
|
|
50
|
+
normalized = normalize_filename(raw)
|
|
51
|
+
normalized = normalized.remove(secure_token).chomp('_')
|
|
52
|
+
normalized = strip_index(normalized) if index
|
|
53
|
+
[normalized, index].compact.join('_')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def strip_cache_id(name)
|
|
57
|
+
name.remove(CACHE_ID_REGEXP)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def strip_extension(name)
|
|
61
|
+
name.remove(/\.\w+$/)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def strip_index(name)
|
|
65
|
+
name.remove(/_\d{3}$/)
|
|
40
66
|
end
|
|
41
67
|
|
|
42
68
|
def extension
|
|
@@ -74,7 +100,8 @@ module AbAdmin
|
|
|
74
100
|
end
|
|
75
101
|
|
|
76
102
|
def save_original_name(file)
|
|
77
|
-
|
|
103
|
+
return unless file.respond_to?(:original_filename)
|
|
104
|
+
model.original_name ||= strip_cache_id(file.original_filename.to_s)
|
|
78
105
|
end
|
|
79
106
|
|
|
80
107
|
def model_filename(base_filename, record)
|
|
@@ -87,7 +114,7 @@ module AbAdmin
|
|
|
87
114
|
def normalize_filename(raw_filename)
|
|
88
115
|
I18n.transliterate(raw_filename.unicode_normalize).parameterize(separator: '_').gsub(/[\-_]+/, '_').downcase
|
|
89
116
|
end
|
|
90
|
-
|
|
117
|
+
|
|
91
118
|
def rename_via_move(new_filename)
|
|
92
119
|
dir = File.dirname(path)
|
|
93
120
|
old_names = versions.values.unshift(self).map(&:full_filename)
|
|
@@ -94,7 +94,7 @@ module AbAdmin
|
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
def all_columns_names
|
|
97
|
-
|
|
97
|
+
AbAdmin.deprecator.warn('#all_columns_names is deprecated without replacement')
|
|
98
98
|
if translates?
|
|
99
99
|
column_names + all_translated_attribute_names + translated_attribute_names.map(&:to_s)
|
|
100
100
|
else
|
|
@@ -12,7 +12,7 @@ class Array
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def without!(*values)
|
|
15
|
-
|
|
15
|
+
AbAdmin.deprecator.warn('Array#without! is deprecated without replacement')
|
|
16
16
|
values.flatten.each { |value| self.delete(value) }
|
|
17
17
|
self
|
|
18
18
|
end
|
|
@@ -21,7 +21,9 @@ class Array
|
|
|
21
21
|
(other - self).empty?
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
unless method_defined?(:intersect?)
|
|
25
|
+
def intersect?(other)
|
|
26
|
+
!(self & other).empty?
|
|
27
|
+
end
|
|
26
28
|
end
|
|
27
29
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'active_support/core_ext/hash/deep_transform_values'
|
|
2
|
+
|
|
1
3
|
class Hash
|
|
2
4
|
def reverse_deep_merge!(other_hash)
|
|
3
5
|
other_hash.each_pair do |k, v|
|
|
@@ -18,15 +20,17 @@ class Hash
|
|
|
18
20
|
self
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
unless method_defined?(:deep_transform_values!)
|
|
24
|
+
def deep_transform_values!(&block)
|
|
25
|
+
self.each_key do |key|
|
|
26
|
+
if self[key].is_a?(Hash)
|
|
27
|
+
self[key] = self[key].deep_transform_values!(&block)
|
|
28
|
+
else
|
|
29
|
+
self[key] = block.call(self[key])
|
|
30
|
+
end
|
|
27
31
|
end
|
|
32
|
+
self
|
|
28
33
|
end
|
|
29
|
-
self
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
def clear_values
|
data/lib/ab_admin/engine.rb
CHANGED
|
@@ -2,6 +2,10 @@ module AbAdmin
|
|
|
2
2
|
class Engine < ::Rails::Engine
|
|
3
3
|
engine_name 'ab_admin'
|
|
4
4
|
|
|
5
|
+
initializer 'ab_admin.deprecator', before: :load_environment_config do |app|
|
|
6
|
+
app.deprecators[:ab_admin] = AbAdmin.deprecator if app.respond_to?(:deprecators)
|
|
7
|
+
end
|
|
8
|
+
|
|
5
9
|
initializer 'ab_admin.assets_precompile', group: :all do |app|
|
|
6
10
|
app.config.assets.precompile += AbAdmin.assets
|
|
7
11
|
end
|
|
@@ -113,7 +113,7 @@ module AbAdmin
|
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def rename!(name=nil)
|
|
116
|
-
normalized_name = name ? data.normalize_filename(name) :
|
|
116
|
+
normalized_name = name ? data.normalize_filename(name) : data.human_part(SecureRandom.random_number(100..999))
|
|
117
117
|
return if normalized_name.blank?
|
|
118
118
|
data.rename_via_move normalized_name
|
|
119
119
|
end
|
|
@@ -25,7 +25,7 @@ module AbAdmin
|
|
|
25
25
|
|
|
26
26
|
module ClassMethods
|
|
27
27
|
def load_config
|
|
28
|
-
|
|
28
|
+
AbAdmin.deprecator.warn('`Settings.load_config` is deprecated, use `Settings.data` instead')
|
|
29
29
|
data
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -9,8 +9,8 @@ module AbAdmin
|
|
|
9
9
|
belongs_to :owner, class_name: 'User'
|
|
10
10
|
belongs_to :user, class_name: 'User'
|
|
11
11
|
|
|
12
|
-
serialize :parameters, Hash
|
|
13
|
-
serialize :trackable_changes, Hash
|
|
12
|
+
serialize :parameters, coder: YAML, type: Hash
|
|
13
|
+
serialize :trackable_changes, coder: YAML, type: Hash
|
|
14
14
|
|
|
15
15
|
before_create :make_trackable, if: :trackable
|
|
16
16
|
|
data/lib/ab_admin/version.rb
CHANGED
|
@@ -49,24 +49,23 @@ module AbAdmin
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
if opts[:source]
|
|
53
|
+
opts[:type] ||= 'select'
|
|
54
|
+
else
|
|
55
|
+
case attr.to_s
|
|
56
|
+
when /_at$/
|
|
57
|
+
opts[:type] ||= 'date'
|
|
58
|
+
opts[:title] ||= html_title
|
|
59
|
+
opts[:value] ||= item[attr].try! { _1.to_fs(:db).split.first.html_safe }
|
|
60
|
+
when /^is_/
|
|
61
|
+
opts[:type] ||= 'select'
|
|
62
|
+
opts[:source] ||= { 1 => 'yes', 0 => 'no' }
|
|
63
|
+
opts[:value] ||= item[attr] ? 1 : 0
|
|
64
|
+
opts[:title] ||= item[attr] ? 'yes' : 'no'
|
|
65
|
+
when /description|body|content/
|
|
66
|
+
opts[:type] ||= 'textarea'
|
|
55
67
|
else
|
|
56
|
-
|
|
57
|
-
when /_at$/
|
|
58
|
-
opts[:type] ||= 'date'
|
|
59
|
-
opts[:title] ||= html_title
|
|
60
|
-
when /^is_/
|
|
61
|
-
opts[:type] ||= 'select'
|
|
62
|
-
opts[:source] ||= {1 => 'yes', 0 => 'no'}
|
|
63
|
-
opts[:value] ||= item[attr] ? 1 : 0
|
|
64
|
-
opts[:title] ||= item[attr] ? 'yes' : 'no'
|
|
65
|
-
when /description|body|content/
|
|
66
|
-
opts[:type] ||= 'textarea'
|
|
67
|
-
else
|
|
68
|
-
opts[:type] ||= 'text'
|
|
69
|
-
end
|
|
68
|
+
opts[:type] ||= 'text'
|
|
70
69
|
end
|
|
71
70
|
end
|
|
72
71
|
|
|
@@ -73,7 +73,7 @@ module AbAdmin
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def disable_not_accessible_for(roles)
|
|
76
|
-
|
|
76
|
+
AbAdmin.deprecator.warn('#disable_not_accessible_for is deprecated without replacement')
|
|
77
77
|
@disable_not_accessible_for = roles
|
|
78
78
|
end
|
|
79
79
|
|
data/lib/ab_admin.rb
CHANGED
|
@@ -2,6 +2,13 @@ require 'inherited_resources'
|
|
|
2
2
|
require 'rack-pjax'
|
|
3
3
|
require 'cancan'
|
|
4
4
|
|
|
5
|
+
# Rack 3.x removed Rack::Utils::HeaderHash in favor of Rack::Headers.
|
|
6
|
+
# rack-pjax (1.1.0) still references HeaderHash, so we restore the constant
|
|
7
|
+
# for compatibility. See https://github.com/eval/rack-pjax/issues/
|
|
8
|
+
if defined?(Rack::Headers) && !defined?(Rack::Utils::HeaderHash)
|
|
9
|
+
Rack::Utils::HeaderHash = Rack::Headers
|
|
10
|
+
end
|
|
11
|
+
|
|
5
12
|
require 'ab_admin/version'
|
|
6
13
|
require 'ab_admin/core_ext'
|
|
7
14
|
require 'ab_admin/engine'
|
|
@@ -212,6 +219,10 @@ module AbAdmin
|
|
|
212
219
|
def self.setup
|
|
213
220
|
yield self
|
|
214
221
|
end
|
|
222
|
+
|
|
223
|
+
def self.deprecator
|
|
224
|
+
@deprecator ||= ActiveSupport::Deprecation.new(VERSION, 'AbAdmin')
|
|
225
|
+
end
|
|
215
226
|
end
|
|
216
227
|
|
|
217
228
|
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ab_admin
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex Leschenko
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rails
|
|
@@ -16,14 +15,14 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
18
|
+
version: 8.1.3
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
25
|
+
version: 8.1.3
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: jquery-rails
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -112,16 +111,16 @@ dependencies:
|
|
|
112
111
|
name: simple_slug
|
|
113
112
|
requirement: !ruby/object:Gem::Requirement
|
|
114
113
|
requirements:
|
|
115
|
-
- - "
|
|
114
|
+
- - ">="
|
|
116
115
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: 0
|
|
116
|
+
version: '0'
|
|
118
117
|
type: :runtime
|
|
119
118
|
prerelease: false
|
|
120
119
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
120
|
requirements:
|
|
122
|
-
- - "
|
|
121
|
+
- - ">="
|
|
123
122
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: 0
|
|
123
|
+
version: '0'
|
|
125
124
|
- !ruby/object:Gem::Dependency
|
|
126
125
|
name: devise
|
|
127
126
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -651,7 +650,6 @@ files:
|
|
|
651
650
|
homepage: https://github.com/leschenko/ab_admin
|
|
652
651
|
licenses: []
|
|
653
652
|
metadata: {}
|
|
654
|
-
post_install_message:
|
|
655
653
|
rdoc_options: []
|
|
656
654
|
require_paths:
|
|
657
655
|
- lib
|
|
@@ -666,8 +664,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
666
664
|
- !ruby/object:Gem::Version
|
|
667
665
|
version: '0'
|
|
668
666
|
requirements: []
|
|
669
|
-
rubygems_version:
|
|
670
|
-
signing_key:
|
|
667
|
+
rubygems_version: 4.0.10
|
|
671
668
|
specification_version: 4
|
|
672
669
|
summary: Simple and real-life tested Rails::Engine admin interface based on slim,
|
|
673
670
|
bootstrap, inherited_resources, simple_form, device, cancan
|