motor-admin 0.1.12 → 0.1.13
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/app/controllers/motor/active_storage_attachments_controller.rb +28 -0
- data/app/controllers/motor/alerts_controller.rb +2 -0
- data/app/controllers/motor/configs_controller.rb +2 -0
- data/app/controllers/motor/dashboards_controller.rb +2 -0
- data/app/controllers/motor/data_controller.rb +3 -1
- data/app/controllers/motor/forms_controller.rb +2 -0
- data/app/controllers/motor/queries_controller.rb +2 -0
- data/app/controllers/motor/resources_controller.rb +2 -0
- data/app/controllers/motor/run_queries_controller.rb +2 -0
- data/app/controllers/motor/send_alerts_controller.rb +2 -0
- data/config/routes.rb +1 -0
- data/lib/motor.rb +1 -0
- data/lib/motor/active_record_utils.rb +2 -0
- data/lib/motor/active_record_utils/active_storage_links_extension.rb +15 -0
- data/lib/motor/active_record_utils/defined_scopes_extension.rb +19 -0
- data/lib/motor/admin.rb +15 -3
- data/lib/motor/api_query.rb +2 -0
- data/lib/motor/api_query/apply_scope.rb +26 -0
- data/lib/motor/build_schema.rb +60 -7
- data/lib/motor/build_schema/active_storage_attachment_schema.rb +84 -0
- data/lib/motor/build_schema/load_from_rails.rb +30 -56
- data/lib/motor/build_schema/merge_schema_configs.rb +13 -6
- data/lib/motor/build_schema/persist_resource_configs.rb +37 -1
- data/lib/motor/build_schema/reorder_schema.rb +3 -1
- data/lib/motor/version.rb +1 -1
- data/ui/dist/main-8f36a2746422efd1e8a8.css.gz +0 -0
- data/ui/dist/main-8f36a2746422efd1e8a8.js.gz +0 -0
- data/ui/dist/manifest.json +5 -5
- metadata +9 -4
- data/ui/dist/main-4bdedd7fcff1351efaf6.css.gz +0 -0
- data/ui/dist/main-4bdedd7fcff1351efaf6.js.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9dca132c3a2481191219a518fe66e581988245cbe3212fb105c220285d1a5fa
|
4
|
+
data.tar.gz: e2cb07a305545d2fb01e0c94101f6bdabd705628b8043b8a8a40b320427bc7e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcce9c0ad1fff7e751a91ab366174174421f038ee3ed848e32618d663d1955221295e0cc79904a0702b939630ab4e6b6873b2b141e01b6ac4bc8361233ef265f
|
7
|
+
data.tar.gz: b20916892df27d1a6c5eef23452824034d0559e5954fe44726034269496409358a3755f3b53dcd489d61953743b511e66f4f93c4bea2ea894f6dae856575492b
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
class ActiveStorageAttachmentsController < ApiBaseController
|
5
|
+
wrap_parameters :data, except: %i[include fields]
|
6
|
+
|
7
|
+
load_and_authorize_resource :attachment, class: 'ActiveStorage::Attachment', parent: false
|
8
|
+
|
9
|
+
def create
|
10
|
+
if @attachment.record.respond_to?("#{@attachment.name}_attachment=") || @attachment.record.respond_to?("#{@attachment.name}_attachments=")
|
11
|
+
@attachment.record.public_send(@attachment.name).attach(
|
12
|
+
io: StringIO.new(params.dig(:data, :file, :io).to_s.encode('ISO-8859-1')),
|
13
|
+
filename: params.dig(:data, :file, :filename)
|
14
|
+
)
|
15
|
+
|
16
|
+
head :ok
|
17
|
+
else
|
18
|
+
head :unprocessable_entity
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def attachment_params
|
25
|
+
params.require(:data).except(:file).permit!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -4,6 +4,8 @@ module Motor
|
|
4
4
|
class DataController < ApiBaseController
|
5
5
|
INSTANCE_VARIABLE_NAME = 'resource'
|
6
6
|
|
7
|
+
wrap_parameters :data, except: %i[include fields]
|
8
|
+
|
7
9
|
before_action :load_and_authorize_resource
|
8
10
|
before_action :load_and_authorize_association
|
9
11
|
|
@@ -96,7 +98,7 @@ module Motor
|
|
96
98
|
end
|
97
99
|
|
98
100
|
def resource_params
|
99
|
-
params.
|
101
|
+
params.require(:data).except(resource_class.primary_key).permit!
|
100
102
|
end
|
101
103
|
end
|
102
104
|
end
|
data/config/routes.rb
CHANGED
@@ -13,6 +13,7 @@ Motor::Admin.routes.draw do
|
|
13
13
|
resources :dashboards, only: %i[index show create update destroy]
|
14
14
|
resources :forms, only: %i[index show create update destroy]
|
15
15
|
resources :alerts, only: %i[index show create update destroy]
|
16
|
+
resources :active_storage_attachments, only: %i[create], path: 'data/active_storage__attachments'
|
16
17
|
resource :schema, only: %i[show update]
|
17
18
|
resources :resources, path: '/data/:resource',
|
18
19
|
only: %i[index show update create destroy],
|
data/lib/motor.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative './active_record_utils/types'
|
4
4
|
require_relative './active_record_utils/fetch_methods'
|
5
|
+
require_relative './active_record_utils/defined_scopes_extension'
|
6
|
+
require_relative './active_record_utils/active_storage_links_extension'
|
5
7
|
|
6
8
|
module ActiveRecordUtils
|
7
9
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module ActiveRecordUtils
|
5
|
+
module ActiveStorageLinksExtension
|
6
|
+
def path
|
7
|
+
Rails.application.routes.url_helpers.rails_blob_path(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def url
|
11
|
+
Rails.application.routes.url_helpers.url_for(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module ActiveRecordUtils
|
5
|
+
module DefinedScopesExtension
|
6
|
+
def scope(name, _body)
|
7
|
+
(@__scopes__ ||= []) << name
|
8
|
+
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def defined_scopes
|
13
|
+
@__scopes__ || []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
ActiveRecord::Base.extend(Motor::ActiveRecordUtils::DefinedScopesExtension)
|
data/lib/motor/admin.rb
CHANGED
@@ -2,11 +2,23 @@
|
|
2
2
|
|
3
3
|
module Motor
|
4
4
|
class Admin < ::Rails::Engine
|
5
|
+
initializer 'motor.filter_params' do
|
6
|
+
Rails.application.config.filter_parameters += %i[io]
|
7
|
+
end
|
8
|
+
|
5
9
|
initializer 'motor.alerts.scheduler' do
|
6
|
-
|
10
|
+
config.after_initialize do |_app|
|
11
|
+
next if defined?(Sidekiq) && Sidekiq.server?
|
12
|
+
|
13
|
+
Motor::Alerts::Scheduler::SCHEDULER_TASK.execute
|
14
|
+
Motor::Alerts::ScheduledAlertsCache::UPDATE_ALERTS_TASK.execute
|
15
|
+
end
|
16
|
+
end
|
7
17
|
|
8
|
-
|
9
|
-
|
18
|
+
initializer 'motor.active_storage.extensions' do
|
19
|
+
ActiveSupport.on_load(:active_storage_attachment) do
|
20
|
+
ActiveStorage::Attachment.include(Motor::ActiveRecordUtils::ActiveStorageLinksExtension)
|
21
|
+
end
|
10
22
|
end
|
11
23
|
end
|
12
24
|
end
|
data/lib/motor/api_query.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative './api_query/sort'
|
|
4
4
|
require_relative './api_query/paginate'
|
5
5
|
require_relative './api_query/filter'
|
6
6
|
require_relative './api_query/search'
|
7
|
+
require_relative './api_query/apply_scope'
|
7
8
|
require_relative './api_query/build_meta'
|
8
9
|
require_relative './api_query/build_json'
|
9
10
|
|
@@ -15,6 +16,7 @@ module Motor
|
|
15
16
|
rel = ApiQuery::Sort.call(rel, params[:sort])
|
16
17
|
rel = ApiQuery::Paginate.call(rel, params[:page])
|
17
18
|
rel = ApiQuery::Filter.call(rel, params[:filter])
|
19
|
+
rel = ApiQuery::ApplyScope.call(rel, params[:scope])
|
18
20
|
|
19
21
|
ApiQuery::Search.call(rel, params[:q] || params[:search] || params[:query])
|
20
22
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module ApiQuery
|
5
|
+
module ApplyScope
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def call(rel, scope)
|
9
|
+
return rel if scope.blank?
|
10
|
+
|
11
|
+
scope_symbol = scope.to_sym
|
12
|
+
|
13
|
+
if rel.klass.defined_scopes.include?(scope_symbol)
|
14
|
+
rel.public_send(scope_symbol)
|
15
|
+
else
|
16
|
+
configs = Motor::Resource.find_by_name(rel.klass.name.underscore)
|
17
|
+
scope_configs = configs.preferences[:scopes].find { |s| s[:name] == scope }
|
18
|
+
|
19
|
+
return rel unless scope_configs
|
20
|
+
|
21
|
+
ApiQuery::Filter.call(rel, scope_configs[:preferences][:filter])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/motor/build_schema.rb
CHANGED
@@ -1,16 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './build_schema/load_from_rails'
|
4
|
-
require_relative './build_schema/find_display_column'
|
5
|
-
require_relative './build_schema/persist_resource_configs'
|
6
|
-
require_relative './build_schema/reorder_schema'
|
7
|
-
require_relative './build_schema/merge_schema_configs'
|
8
|
-
require_relative './build_schema/utils'
|
9
|
-
|
10
3
|
module Motor
|
11
4
|
module BuildSchema
|
5
|
+
module ColumnAccessTypes
|
6
|
+
ALL = [
|
7
|
+
READ_ONLY = 'read_only',
|
8
|
+
WRITE_ONLY = 'write_only',
|
9
|
+
READ_WRITE = 'read_write',
|
10
|
+
HIDDEN = 'hidden'
|
11
|
+
].freeze
|
12
|
+
end
|
13
|
+
|
12
14
|
SEARCHABLE_COLUMN_TYPES = %i[citext text string bitstring].freeze
|
13
15
|
|
16
|
+
COLUMN_NAME_ACCESS_TYPES = {
|
17
|
+
id: ColumnAccessTypes::READ_ONLY,
|
18
|
+
created_at: ColumnAccessTypes::READ_ONLY,
|
19
|
+
updated_at: ColumnAccessTypes::READ_ONLY,
|
20
|
+
deleted_at: ColumnAccessTypes::READ_ONLY
|
21
|
+
}.with_indifferent_access.freeze
|
22
|
+
|
23
|
+
DEFAULT_SCOPE_TYPE = 'default'
|
24
|
+
|
25
|
+
DEFAULT_ACTIONS = [
|
26
|
+
{
|
27
|
+
name: 'create',
|
28
|
+
display_name: 'Create',
|
29
|
+
action_type: 'default',
|
30
|
+
preferences: {},
|
31
|
+
visible: true
|
32
|
+
},
|
33
|
+
{
|
34
|
+
name: 'edit',
|
35
|
+
display_name: 'Edit',
|
36
|
+
action_type: 'default',
|
37
|
+
preferences: {},
|
38
|
+
visible: true
|
39
|
+
},
|
40
|
+
{
|
41
|
+
name: 'remove',
|
42
|
+
display_name: 'Remove',
|
43
|
+
action_type: 'default',
|
44
|
+
preferences: {},
|
45
|
+
visible: true
|
46
|
+
}
|
47
|
+
].freeze
|
48
|
+
|
49
|
+
DEFAULT_TABS = [
|
50
|
+
{
|
51
|
+
name: 'summary',
|
52
|
+
display_name: 'Summary',
|
53
|
+
tab_type: 'default',
|
54
|
+
preferences: {},
|
55
|
+
visible: true
|
56
|
+
}
|
57
|
+
].freeze
|
58
|
+
|
14
59
|
module_function
|
15
60
|
|
16
61
|
def call
|
@@ -21,3 +66,11 @@ module Motor
|
|
21
66
|
end
|
22
67
|
end
|
23
68
|
end
|
69
|
+
|
70
|
+
require_relative './build_schema/active_storage_attachment_schema'
|
71
|
+
require_relative './build_schema/load_from_rails'
|
72
|
+
require_relative './build_schema/find_display_column'
|
73
|
+
require_relative './build_schema/persist_resource_configs'
|
74
|
+
require_relative './build_schema/reorder_schema'
|
75
|
+
require_relative './build_schema/merge_schema_configs'
|
76
|
+
require_relative './build_schema/utils'
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module BuildSchema
|
5
|
+
ACTIVE_STORAGE_ATTACHMENT_SCHEMA = {
|
6
|
+
name: 'active_storage/attachment',
|
7
|
+
slug: 'active_storage__attachments',
|
8
|
+
table_name: 'active_storage_attachments',
|
9
|
+
primary_key: 'id',
|
10
|
+
display_name: 'Attachments',
|
11
|
+
display_column: 'filename',
|
12
|
+
columns: [
|
13
|
+
{
|
14
|
+
name: 'id',
|
15
|
+
display_name: 'Id',
|
16
|
+
column_type: 'integer',
|
17
|
+
access_type: 'read_only',
|
18
|
+
default_value: nil,
|
19
|
+
validators: [],
|
20
|
+
virtual: false
|
21
|
+
},
|
22
|
+
{
|
23
|
+
name: 'path',
|
24
|
+
display_name: 'Path',
|
25
|
+
column_type: 'string',
|
26
|
+
access_type: 'read_only',
|
27
|
+
default_value: nil,
|
28
|
+
validators: [],
|
29
|
+
virtual: false
|
30
|
+
},
|
31
|
+
{
|
32
|
+
name: 'name',
|
33
|
+
display_name: 'Name',
|
34
|
+
column_type: 'string',
|
35
|
+
access_type: 'read_write',
|
36
|
+
default_value: nil,
|
37
|
+
validators: [],
|
38
|
+
virtual: false
|
39
|
+
},
|
40
|
+
{
|
41
|
+
name: 'record_type',
|
42
|
+
display_name: 'Record type',
|
43
|
+
column_type: 'string',
|
44
|
+
access_type: 'read_write',
|
45
|
+
default_value: nil,
|
46
|
+
validators: [],
|
47
|
+
virtual: false
|
48
|
+
},
|
49
|
+
{
|
50
|
+
name: 'record_id',
|
51
|
+
display_name: 'Record',
|
52
|
+
column_type: 'integer',
|
53
|
+
access_type: 'read_write',
|
54
|
+
default_value: nil,
|
55
|
+
validators: [],
|
56
|
+
virtual: false
|
57
|
+
},
|
58
|
+
{
|
59
|
+
name: 'file',
|
60
|
+
display_name: 'File',
|
61
|
+
column_type: 'file',
|
62
|
+
access_type: 'write_only',
|
63
|
+
default_value: nil,
|
64
|
+
validators: [],
|
65
|
+
virtual: false
|
66
|
+
},
|
67
|
+
{
|
68
|
+
name: 'created_at',
|
69
|
+
display_name: 'Created at',
|
70
|
+
column_type: 'datetime',
|
71
|
+
access_type: 'read_only',
|
72
|
+
default_value: nil,
|
73
|
+
validators: [],
|
74
|
+
virtual: false
|
75
|
+
}
|
76
|
+
],
|
77
|
+
associations: [],
|
78
|
+
scopes: [],
|
79
|
+
actions: Motor::BuildSchema::DEFAULT_ACTIONS.reject { |e| e[:name] == 'edit' },
|
80
|
+
tabs: Motor::BuildSchema::DEFAULT_TABS,
|
81
|
+
visible: true
|
82
|
+
}.with_indifferent_access
|
83
|
+
end
|
84
|
+
end
|
@@ -3,56 +3,6 @@
|
|
3
3
|
module Motor
|
4
4
|
module BuildSchema
|
5
5
|
module LoadFromRails
|
6
|
-
module ColumnAccessTypes
|
7
|
-
ALL = [
|
8
|
-
READ_ONLY = 'read_only',
|
9
|
-
WRITE_ONLY = 'write_only',
|
10
|
-
READ_WRITE = 'read_write',
|
11
|
-
HIDDEN = 'hidden'
|
12
|
-
].freeze
|
13
|
-
end
|
14
|
-
|
15
|
-
COLUMN_NAME_ACCESS_TYPES = {
|
16
|
-
id: ColumnAccessTypes::READ_ONLY,
|
17
|
-
created_at: ColumnAccessTypes::READ_ONLY,
|
18
|
-
updated_at: ColumnAccessTypes::READ_ONLY,
|
19
|
-
deleted_at: ColumnAccessTypes::READ_ONLY
|
20
|
-
}.with_indifferent_access.freeze
|
21
|
-
|
22
|
-
DEFAULT_ACTIONS = [
|
23
|
-
{
|
24
|
-
name: 'create',
|
25
|
-
display_name: 'Create',
|
26
|
-
action_type: 'default',
|
27
|
-
preferences: {},
|
28
|
-
visible: true
|
29
|
-
},
|
30
|
-
{
|
31
|
-
name: 'edit',
|
32
|
-
display_name: 'Edit',
|
33
|
-
action_type: 'default',
|
34
|
-
preferences: {},
|
35
|
-
visible: true
|
36
|
-
},
|
37
|
-
{
|
38
|
-
name: 'remove',
|
39
|
-
display_name: 'Remove',
|
40
|
-
action_type: 'default',
|
41
|
-
preferences: {},
|
42
|
-
visible: true
|
43
|
-
}
|
44
|
-
].freeze
|
45
|
-
|
46
|
-
DEFAULT_TABS = [
|
47
|
-
{
|
48
|
-
name: 'summary',
|
49
|
-
display_name: 'Summary',
|
50
|
-
tab_type: 'default',
|
51
|
-
preferences: {},
|
52
|
-
visible: true
|
53
|
-
}
|
54
|
-
].freeze
|
55
|
-
|
56
6
|
module_function
|
57
7
|
|
58
8
|
def call
|
@@ -86,21 +36,43 @@ module Motor
|
|
86
36
|
end
|
87
37
|
|
88
38
|
def build_model_schema(model)
|
39
|
+
model_name = model.name
|
40
|
+
|
41
|
+
return Motor::BuildSchema::ACTIVE_STORAGE_ATTACHMENT_SCHEMA if model_name == 'ActiveStorage::Attachment'
|
42
|
+
|
89
43
|
{
|
90
|
-
name:
|
44
|
+
name: model_name.underscore,
|
91
45
|
slug: Utils.slugify(model),
|
92
46
|
table_name: model.table_name,
|
47
|
+
class_name: model.name,
|
93
48
|
primary_key: model.primary_key,
|
94
|
-
display_name:
|
49
|
+
display_name: model_name.titleize.pluralize,
|
95
50
|
display_column: FindDisplayColumn.call(model),
|
96
51
|
columns: fetch_columns(model),
|
97
52
|
associations: fetch_associations(model),
|
53
|
+
scopes: fetch_scopes(model),
|
98
54
|
actions: DEFAULT_ACTIONS,
|
99
55
|
tabs: DEFAULT_TABS,
|
100
56
|
visible: true
|
101
57
|
}.with_indifferent_access
|
102
58
|
end
|
103
59
|
|
60
|
+
def fetch_scopes(model)
|
61
|
+
model.defined_scopes.map do |scope_name|
|
62
|
+
scope_name = scope_name.to_s
|
63
|
+
|
64
|
+
next if scope_name.starts_with?('with_attached')
|
65
|
+
|
66
|
+
{
|
67
|
+
name: scope_name,
|
68
|
+
display_name: scope_name.humanize,
|
69
|
+
scope_type: DEFAULT_SCOPE_TYPE,
|
70
|
+
visible: true,
|
71
|
+
preferences: {}
|
72
|
+
}
|
73
|
+
end.compact
|
74
|
+
end
|
75
|
+
|
104
76
|
def fetch_columns(model)
|
105
77
|
default_attrs = model.new.attributes
|
106
78
|
|
@@ -127,17 +99,19 @@ module Motor
|
|
127
99
|
next
|
128
100
|
end
|
129
101
|
|
130
|
-
|
102
|
+
model_class = ref.klass
|
103
|
+
|
104
|
+
next if model_class.name == 'ActiveStorage::Blob'
|
131
105
|
|
132
106
|
{
|
133
107
|
name: name,
|
134
108
|
display_name: name.humanize,
|
135
109
|
slug: name.underscore,
|
136
|
-
model_name:
|
137
|
-
model_slug: Utils.slugify(
|
110
|
+
model_name: model_class.name.underscore,
|
111
|
+
model_slug: Utils.slugify(model_class),
|
138
112
|
association_type: fetch_association_type(ref),
|
139
113
|
foreign_key: ref.foreign_key,
|
140
|
-
polymorphic: ref.polymorphic
|
114
|
+
polymorphic: ref.polymorphic? || model_class.name == 'ActiveStorage::Attachment',
|
141
115
|
visible: true
|
142
116
|
}
|
143
117
|
end.compact
|
@@ -7,6 +7,7 @@ module Motor
|
|
7
7
|
COLUMN_DEFAULTS = PersistResourceConfigs::COLUMN_DEFAULTS
|
8
8
|
ACTION_DEFAULTS = PersistResourceConfigs::ACTION_DEFAULTS
|
9
9
|
TAB_DEFAULTS = PersistResourceConfigs::TAB_DEFAULTS
|
10
|
+
SCOPE_DEFAULTS = PersistResourceConfigs::SCOPE_DEFAULTS
|
10
11
|
|
11
12
|
module_function
|
12
13
|
|
@@ -26,17 +27,17 @@ module Motor
|
|
26
27
|
def merge_model(model, configs)
|
27
28
|
updated_model = model.merge(configs.slice(*RESOURCE_ATTRS))
|
28
29
|
|
30
|
+
updated_model[:associations] = merge_by_name(
|
31
|
+
model[:associations],
|
32
|
+
configs[:associations]
|
33
|
+
)
|
34
|
+
|
29
35
|
updated_model[:columns] = merge_by_name(
|
30
36
|
model[:columns],
|
31
37
|
configs[:columns],
|
32
38
|
COLUMN_DEFAULTS
|
33
39
|
)
|
34
40
|
|
35
|
-
updated_model[:associations] = merge_by_name(
|
36
|
-
model[:associations],
|
37
|
-
configs[:associations]
|
38
|
-
)
|
39
|
-
|
40
41
|
updated_model[:actions] = merge_by_name(
|
41
42
|
model[:actions],
|
42
43
|
configs[:actions],
|
@@ -46,7 +47,13 @@ module Motor
|
|
46
47
|
updated_model[:tabs] = merge_by_name(
|
47
48
|
model[:tabs],
|
48
49
|
configs[:tabs],
|
49
|
-
|
50
|
+
TAB_DEFAULTS
|
51
|
+
)
|
52
|
+
|
53
|
+
updated_model[:scopes] = merge_by_name(
|
54
|
+
model[:scopes],
|
55
|
+
configs[:scopes],
|
56
|
+
SCOPE_DEFAULTS
|
50
57
|
)
|
51
58
|
|
52
59
|
updated_model
|
@@ -6,6 +6,7 @@ module Motor
|
|
6
6
|
RESOURCE_ATTRS = %w[display_name visible].freeze
|
7
7
|
COLUMN_ATTRS = %w[name display_name column_type access_type default_value virtual].freeze
|
8
8
|
ASSOCIATION_ATTRS = %w[name display_name visible].freeze
|
9
|
+
SCOPE_ATTRS = %w[name display_name scope_type preferences visible].freeze
|
9
10
|
ACTION_ATTRS = %w[name display_name action_type preferences visible].freeze
|
10
11
|
TAB_ATTRS = %w[name display_name tab_type preferences visible].freeze
|
11
12
|
|
@@ -25,6 +26,12 @@ module Motor
|
|
25
26
|
preferences: {}
|
26
27
|
}.with_indifferent_access
|
27
28
|
|
29
|
+
SCOPE_DEFAULTS = {
|
30
|
+
visible: true,
|
31
|
+
scope_type: 'default',
|
32
|
+
preferences: {}
|
33
|
+
}.with_indifferent_access
|
34
|
+
|
28
35
|
module_function
|
29
36
|
|
30
37
|
# @param resource [Motor::Resource]
|
@@ -99,6 +106,14 @@ module Motor
|
|
99
106
|
)
|
100
107
|
end
|
101
108
|
|
109
|
+
if new_prefs[:scopes].present?
|
110
|
+
normalized_preferences[:scopes] = normalize_scopes(
|
111
|
+
default_prefs[:scopes],
|
112
|
+
existing_prefs.fetch(:scopes, []),
|
113
|
+
new_prefs.fetch(:scopes, [])
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
102
117
|
normalized_preferences.compact
|
103
118
|
end
|
104
119
|
|
@@ -138,7 +153,7 @@ module Motor
|
|
138
153
|
action_attrs = new_action.slice(*ACTION_ATTRS)
|
139
154
|
|
140
155
|
normalized_action = existing_action.merge(action_attrs)
|
141
|
-
normalized_action = reject_default(default_action.presence ||
|
156
|
+
normalized_action = reject_default(default_action.presence || ACTION_DEFAULTS, normalized_action)
|
142
157
|
|
143
158
|
normalized_action.merge(name: name) if normalized_action.present?
|
144
159
|
end.compact.presence
|
@@ -165,6 +180,27 @@ module Motor
|
|
165
180
|
end.compact.presence
|
166
181
|
end
|
167
182
|
|
183
|
+
# @param default_scopes [Array<HashWithIndifferentAccess>]
|
184
|
+
# @param existing_scopes [Array<HashWithIndifferentAccess>]
|
185
|
+
# @param new_scopes [Array<HashWithIndifferentAccess>]
|
186
|
+
# @return [Array<HashWithIndifferentAccess>]
|
187
|
+
def normalize_scopes(default_scopes, existing_scopes, new_scopes)
|
188
|
+
(existing_scopes.pluck(:name) + new_scopes.pluck(:name)).uniq.map do |name|
|
189
|
+
new_scope = safe_fetch_by_name(new_scopes, name)
|
190
|
+
|
191
|
+
next if new_scope[:_remove]
|
192
|
+
|
193
|
+
existing_scope = safe_fetch_by_name(existing_scopes, name)
|
194
|
+
default_scope = safe_fetch_by_name(default_scopes, name)
|
195
|
+
scope_attrs = new_scope.slice(*SCOPE_ATTRS)
|
196
|
+
|
197
|
+
normalized_scope = existing_scope.merge(scope_attrs)
|
198
|
+
normalized_scope = reject_default(default_scope.presence || SCOPE_DEFAULTS, normalized_scope)
|
199
|
+
|
200
|
+
normalized_scope.merge(name: name) if normalized_scope.present?
|
201
|
+
end.compact.presence
|
202
|
+
end
|
203
|
+
|
168
204
|
# @param default_assocs [Array<HashWithIndifferentAccess>]
|
169
205
|
# @param existing_assocs [Array<HashWithIndifferentAccess>]
|
170
206
|
# @param new_assocs [Array<HashWithIndifferentAccess>]
|
@@ -16,12 +16,14 @@ module Motor
|
|
16
16
|
associations_order = configs["resources.#{model[:name]}.associations.order"]
|
17
17
|
actions_order = configs["resources.#{model[:name]}.actions.order"]
|
18
18
|
tabs_order = configs["resources.#{model[:name]}.tabs.order"]
|
19
|
+
scopes_order = configs["resources.#{model[:name]}.scopes.order"]
|
19
20
|
|
20
21
|
model.merge(
|
21
22
|
columns: sort_by_name(model[:columns], columns_order, sort_alphabetically: false),
|
22
23
|
associations: sort_by_name(model[:associations], associations_order),
|
23
24
|
actions: sort_by_name(model[:actions], actions_order, sort_alphabetically: false),
|
24
|
-
tabs: sort_by_name(model[:tabs], tabs_order, sort_alphabetically: false)
|
25
|
+
tabs: sort_by_name(model[:tabs], tabs_order, sort_alphabetically: false),
|
26
|
+
scopes: sort_by_name(model[:scopes], scopes_order)
|
25
27
|
)
|
26
28
|
end
|
27
29
|
end
|
data/lib/motor/version.rb
CHANGED
Binary file
|
Binary file
|
data/ui/dist/manifest.json
CHANGED
@@ -5,9 +5,9 @@
|
|
5
5
|
"fonts/ionicons.ttf?v=3.0.0-alpha.3": "fonts/ionicons.ttf",
|
6
6
|
"fonts/ionicons.woff2?v=3.0.0-alpha.3": "fonts/ionicons.woff2",
|
7
7
|
"fonts/ionicons.woff?v=3.0.0-alpha.3": "fonts/ionicons.woff",
|
8
|
-
"main-
|
9
|
-
"main-
|
10
|
-
"main-
|
11
|
-
"main.css": "main-
|
12
|
-
"main.js": "main-
|
8
|
+
"main-8f36a2746422efd1e8a8.css.gz": "main-8f36a2746422efd1e8a8.css.gz",
|
9
|
+
"main-8f36a2746422efd1e8a8.js.LICENSE.txt": "main-8f36a2746422efd1e8a8.js.LICENSE.txt",
|
10
|
+
"main-8f36a2746422efd1e8a8.js.gz": "main-8f36a2746422efd1e8a8.js.gz",
|
11
|
+
"main.css": "main-8f36a2746422efd1e8a8.css",
|
12
|
+
"main.js": "main-8f36a2746422efd1e8a8.js"
|
13
13
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motor-admin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pete Matsyburka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-04-
|
11
|
+
date: 2021-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord-filter
|
@@ -132,6 +132,7 @@ files:
|
|
132
132
|
- LICENSE
|
133
133
|
- README.md
|
134
134
|
- Rakefile
|
135
|
+
- app/controllers/motor/active_storage_attachments_controller.rb
|
135
136
|
- app/controllers/motor/alerts_controller.rb
|
136
137
|
- app/controllers/motor/api_base_controller.rb
|
137
138
|
- app/controllers/motor/application_controller.rb
|
@@ -172,6 +173,8 @@ files:
|
|
172
173
|
- lib/motor-admin.rb
|
173
174
|
- lib/motor.rb
|
174
175
|
- lib/motor/active_record_utils.rb
|
176
|
+
- lib/motor/active_record_utils/active_storage_links_extension.rb
|
177
|
+
- lib/motor/active_record_utils/defined_scopes_extension.rb
|
175
178
|
- lib/motor/active_record_utils/fetch_methods.rb
|
176
179
|
- lib/motor/active_record_utils/types.rb
|
177
180
|
- lib/motor/admin.rb
|
@@ -181,6 +184,7 @@ files:
|
|
181
184
|
- lib/motor/alerts/scheduler.rb
|
182
185
|
- lib/motor/api.rb
|
183
186
|
- lib/motor/api_query.rb
|
187
|
+
- lib/motor/api_query/apply_scope.rb
|
184
188
|
- lib/motor/api_query/build_json.rb
|
185
189
|
- lib/motor/api_query/build_meta.rb
|
186
190
|
- lib/motor/api_query/filter.rb
|
@@ -189,6 +193,7 @@ files:
|
|
189
193
|
- lib/motor/api_query/sort.rb
|
190
194
|
- lib/motor/assets.rb
|
191
195
|
- lib/motor/build_schema.rb
|
196
|
+
- lib/motor/build_schema/active_storage_attachment_schema.rb
|
192
197
|
- lib/motor/build_schema/find_display_column.rb
|
193
198
|
- lib/motor/build_schema/load_from_rails.rb
|
194
199
|
- lib/motor/build_schema/merge_schema_configs.rb
|
@@ -208,8 +213,8 @@ files:
|
|
208
213
|
- lib/motor/ui_configs.rb
|
209
214
|
- lib/motor/version.rb
|
210
215
|
- ui/dist/fonts/ionicons.woff2
|
211
|
-
- ui/dist/main-
|
212
|
-
- ui/dist/main-
|
216
|
+
- ui/dist/main-8f36a2746422efd1e8a8.css.gz
|
217
|
+
- ui/dist/main-8f36a2746422efd1e8a8.js.gz
|
213
218
|
- ui/dist/manifest.json
|
214
219
|
homepage:
|
215
220
|
licenses:
|
Binary file
|
Binary file
|