motor-admin-cstham8 0.4.35
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +661 -0
- data/README.md +230 -0
- data/Rakefile +11 -0
- data/app/channels/motor/application_cable/channel.rb +14 -0
- data/app/channels/motor/application_cable/connection.rb +27 -0
- data/app/channels/motor/notes_channel.rb +9 -0
- data/app/channels/motor/notifications_channel.rb +9 -0
- data/app/controllers/concerns/motor/current_ability.rb +21 -0
- data/app/controllers/concerns/motor/current_user_method.rb +18 -0
- data/app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb +73 -0
- data/app/controllers/concerns/motor/wrap_io_params.rb +25 -0
- data/app/controllers/motor/active_storage_attachments_controller.rb +64 -0
- data/app/controllers/motor/alerts_controller.rb +82 -0
- data/app/controllers/motor/api_base_controller.rb +33 -0
- data/app/controllers/motor/api_configs_controller.rb +54 -0
- data/app/controllers/motor/application_controller.rb +8 -0
- data/app/controllers/motor/assets_controller.rb +43 -0
- data/app/controllers/motor/audits_controller.rb +16 -0
- data/app/controllers/motor/auth_tokens_controller.rb +36 -0
- data/app/controllers/motor/configs_controller.rb +33 -0
- data/app/controllers/motor/dashboards_controller.rb +64 -0
- data/app/controllers/motor/data_controller.rb +88 -0
- data/app/controllers/motor/forms_controller.rb +61 -0
- data/app/controllers/motor/icons_controller.rb +22 -0
- data/app/controllers/motor/note_tags_controller.rb +13 -0
- data/app/controllers/motor/notes_controller.rb +58 -0
- data/app/controllers/motor/notifications_controller.rb +33 -0
- data/app/controllers/motor/queries_controller.rb +64 -0
- data/app/controllers/motor/reminders_controller.rb +38 -0
- data/app/controllers/motor/resource_default_queries_controller.rb +23 -0
- data/app/controllers/motor/resource_methods_controller.rb +23 -0
- data/app/controllers/motor/resources_controller.rb +26 -0
- data/app/controllers/motor/run_api_requests_controller.rb +56 -0
- data/app/controllers/motor/run_graphql_requests_controller.rb +48 -0
- data/app/controllers/motor/run_queries_controller.rb +77 -0
- data/app/controllers/motor/schema_controller.rb +31 -0
- data/app/controllers/motor/send_alerts_controller.rb +26 -0
- data/app/controllers/motor/sessions_controller.rb +23 -0
- data/app/controllers/motor/slack_conversations_controller.rb +11 -0
- data/app/controllers/motor/tags_controller.rb +11 -0
- data/app/controllers/motor/ui_controller.rb +51 -0
- data/app/controllers/motor/users_for_autocomplete_controller.rb +23 -0
- data/app/jobs/motor/alert_sending_job.rb +13 -0
- data/app/jobs/motor/application_job.rb +6 -0
- data/app/jobs/motor/notify_note_mentions_job.rb +9 -0
- data/app/jobs/motor/notify_reminder_job.rb +9 -0
- data/app/mailers/motor/alerts_mailer.rb +39 -0
- data/app/mailers/motor/application_mailer.rb +33 -0
- data/app/mailers/motor/notifications_mailer.rb +33 -0
- data/app/models/motor/alert.rb +30 -0
- data/app/models/motor/alert_lock.rb +7 -0
- data/app/models/motor/api_config.rb +28 -0
- data/app/models/motor/application_record.rb +18 -0
- data/app/models/motor/audit.rb +13 -0
- data/app/models/motor/config.rb +13 -0
- data/app/models/motor/dashboard.rb +26 -0
- data/app/models/motor/form.rb +23 -0
- data/app/models/motor/note.rb +18 -0
- data/app/models/motor/note_tag.rb +7 -0
- data/app/models/motor/note_tag_tag.rb +8 -0
- data/app/models/motor/notification.rb +14 -0
- data/app/models/motor/query.rb +33 -0
- data/app/models/motor/reminder.rb +13 -0
- data/app/models/motor/resource.rb +15 -0
- data/app/models/motor/tag.rb +7 -0
- data/app/models/motor/taggable_tag.rb +8 -0
- data/app/views/layouts/motor/application.html.erb +17 -0
- data/app/views/layouts/motor/mailer.html.erb +72 -0
- data/app/views/motor/alerts_mailer/alert_email.html.erb +54 -0
- data/app/views/motor/notifications_mailer/notify_mention_email.html.erb +28 -0
- data/app/views/motor/notifications_mailer/notify_reminder_email.html.erb +28 -0
- data/app/views/motor/ui/show.html.erb +1 -0
- data/config/locales/el.yml +420 -0
- data/config/locales/en.yml +340 -0
- data/config/locales/es.yml +420 -0
- data/config/locales/ja.yml +340 -0
- data/config/locales/pt.yml +416 -0
- data/config/routes.rb +65 -0
- data/lib/generators/motor/install_generator.rb +24 -0
- data/lib/generators/motor/install_notes_generator.rb +22 -0
- data/lib/generators/motor/migration.rb +17 -0
- data/lib/generators/motor/templates/install.rb +271 -0
- data/lib/generators/motor/templates/install_api_configs.rb +86 -0
- data/lib/generators/motor/templates/install_notes.rb +83 -0
- data/lib/generators/motor/templates/upgrade_motor_api_actions.rb +71 -0
- data/lib/generators/motor/upgrade_generator.rb +43 -0
- data/lib/motor/active_record_utils/action_text_attribute_patch.rb +19 -0
- data/lib/motor/active_record_utils/active_record_connection_column_patch.rb +14 -0
- data/lib/motor/active_record_utils/active_record_filter.rb +405 -0
- data/lib/motor/active_record_utils/active_storage_blob_patch.rb +30 -0
- data/lib/motor/active_record_utils/active_storage_links_extension.rb +11 -0
- data/lib/motor/active_record_utils/defined_scopes_extension.rb +25 -0
- data/lib/motor/active_record_utils/fetch_methods.rb +24 -0
- data/lib/motor/active_record_utils/types.rb +64 -0
- data/lib/motor/active_record_utils.rb +45 -0
- data/lib/motor/admin.rb +141 -0
- data/lib/motor/alerts/persistance.rb +97 -0
- data/lib/motor/alerts/scheduled_alerts_cache.rb +29 -0
- data/lib/motor/alerts/scheduler.rb +30 -0
- data/lib/motor/alerts/slack_sender.rb +74 -0
- data/lib/motor/alerts.rb +52 -0
- data/lib/motor/api_configs.rb +41 -0
- data/lib/motor/api_query/apply_scope.rb +44 -0
- data/lib/motor/api_query/build_json.rb +171 -0
- data/lib/motor/api_query/build_meta.rb +20 -0
- data/lib/motor/api_query/filter.rb +125 -0
- data/lib/motor/api_query/paginate.rb +19 -0
- data/lib/motor/api_query/search.rb +60 -0
- data/lib/motor/api_query/sort.rb +64 -0
- data/lib/motor/api_query.rb +24 -0
- data/lib/motor/assets.rb +62 -0
- data/lib/motor/build_schema/active_storage_attachment_schema.rb +125 -0
- data/lib/motor/build_schema/adjust_devise_model_schema.rb +60 -0
- data/lib/motor/build_schema/apply_permissions.rb +64 -0
- data/lib/motor/build_schema/defaults.rb +66 -0
- data/lib/motor/build_schema/find_display_column.rb +65 -0
- data/lib/motor/build_schema/find_icon.rb +135 -0
- data/lib/motor/build_schema/find_searchable_columns.rb +33 -0
- data/lib/motor/build_schema/load_from_rails.rb +361 -0
- data/lib/motor/build_schema/merge_schema_configs.rb +157 -0
- data/lib/motor/build_schema/reorder_schema.rb +88 -0
- data/lib/motor/build_schema/utils.rb +31 -0
- data/lib/motor/build_schema.rb +125 -0
- data/lib/motor/cancan_utils/ability_patch.rb +31 -0
- data/lib/motor/cancan_utils/can_manage_all.rb +14 -0
- data/lib/motor/cancan_utils.rb +9 -0
- data/lib/motor/configs/build_configs_hash.rb +90 -0
- data/lib/motor/configs/build_ui_app_tag.rb +177 -0
- data/lib/motor/configs/load_from_cache.rb +110 -0
- data/lib/motor/configs/sync_from_file.rb +35 -0
- data/lib/motor/configs/sync_from_hash.rb +159 -0
- data/lib/motor/configs/sync_middleware.rb +72 -0
- data/lib/motor/configs/sync_with_remote.rb +47 -0
- data/lib/motor/configs/write_to_file.rb +36 -0
- data/lib/motor/configs.rb +39 -0
- data/lib/motor/dashboards/persistance.rb +73 -0
- data/lib/motor/dashboards.rb +8 -0
- data/lib/motor/forms/persistance.rb +93 -0
- data/lib/motor/forms.rb +8 -0
- data/lib/motor/hash_serializer.rb +21 -0
- data/lib/motor/net_http_utils.rb +50 -0
- data/lib/motor/notes/notify_mentions.rb +71 -0
- data/lib/motor/notes/notify_reminder.rb +48 -0
- data/lib/motor/notes/persist.rb +36 -0
- data/lib/motor/notes/reminders_scheduler.rb +39 -0
- data/lib/motor/notes/tags.rb +34 -0
- data/lib/motor/notes.rb +12 -0
- data/lib/motor/queries/persistance.rb +90 -0
- data/lib/motor/queries/postgresql_exec_query.rb +28 -0
- data/lib/motor/queries/render_sql_template.rb +61 -0
- data/lib/motor/queries/run_query.rb +289 -0
- data/lib/motor/queries.rb +11 -0
- data/lib/motor/railtie.rb +11 -0
- data/lib/motor/resources/custom_sql_columns_cache.rb +17 -0
- data/lib/motor/resources/fetch_configured_model.rb +269 -0
- data/lib/motor/resources/persist_configs.rb +232 -0
- data/lib/motor/resources.rb +19 -0
- data/lib/motor/slack/client.rb +62 -0
- data/lib/motor/slack.rb +16 -0
- data/lib/motor/tags.rb +32 -0
- data/lib/motor/tasks/motor.rake +54 -0
- data/lib/motor/version.rb +5 -0
- data/lib/motor-admin-cstham8.rb +3 -0
- data/lib/motor.rb +87 -0
- data/ui/dist/manifest.json +1990 -0
- metadata +303 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module BuildSchema
|
5
|
+
module MergeSchemaConfigs
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# @param schema [Array<HashWithIndifferentAccess>]
|
9
|
+
# @param cache_keys [Hash]
|
10
|
+
# @return [Array<HashWithIndifferentAccess>]
|
11
|
+
def call(schema, cache_keys = {})
|
12
|
+
configs = load_configs(cache_keys)
|
13
|
+
|
14
|
+
schema.map do |model|
|
15
|
+
merge_model(model, configs.fetch(model[:name], {}))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param model [HashWithIndifferentAccess]
|
20
|
+
# @param configs [HashWithIndifferentAccess]
|
21
|
+
# @return [HashWithIndifferentAccess]
|
22
|
+
def merge_model(model, configs)
|
23
|
+
updated_model = model.merge(configs.slice(*Resources::RESOURCE_ATTRS))
|
24
|
+
|
25
|
+
merge_actions!(updated_model, configs)
|
26
|
+
merge_associations!(updated_model, configs)
|
27
|
+
merge_columns!(updated_model, configs)
|
28
|
+
merge_tabs!(updated_model, configs)
|
29
|
+
merge_scopes!(updated_model, configs)
|
30
|
+
|
31
|
+
updated_model
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param model [HashWithIndifferentAccess]
|
35
|
+
# @param configs [HashWithIndifferentAccess]
|
36
|
+
# @return [HashWithIndifferentAccess]
|
37
|
+
def merge_associations!(model, configs)
|
38
|
+
model[:associations] = merge_by_name(
|
39
|
+
model[:associations],
|
40
|
+
configs[:associations],
|
41
|
+
ASSOCIATION_DEFAULTS,
|
42
|
+
->(scope) { !scope[:virtual] }
|
43
|
+
)
|
44
|
+
|
45
|
+
model
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param model [HashWithIndifferentAccess]
|
49
|
+
# @param configs [HashWithIndifferentAccess]
|
50
|
+
# @return [HashWithIndifferentAccess]
|
51
|
+
def merge_columns!(model, configs)
|
52
|
+
model[:columns] = merge_by_name(
|
53
|
+
merge_custom_sql_columns(model[:columns], configs[:custom_sql]),
|
54
|
+
configs[:columns],
|
55
|
+
COLUMN_DEFAULTS,
|
56
|
+
->(scope) { !scope[:virtual] }
|
57
|
+
)
|
58
|
+
|
59
|
+
model
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param model [HashWithIndifferentAccess]
|
63
|
+
# @param configs [HashWithIndifferentAccess]
|
64
|
+
# @return [HashWithIndifferentAccess]
|
65
|
+
def merge_actions!(model, configs)
|
66
|
+
model[:actions] = merge_by_name(
|
67
|
+
model[:actions],
|
68
|
+
configs[:actions],
|
69
|
+
ACTION_DEFAULTS
|
70
|
+
)
|
71
|
+
|
72
|
+
model
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param model [HashWithIndifferentAccess]
|
76
|
+
# @param configs [HashWithIndifferentAccess]
|
77
|
+
# @return [HashWithIndifferentAccess]
|
78
|
+
def merge_tabs!(model, configs)
|
79
|
+
model[:tabs] = merge_by_name(
|
80
|
+
model[:tabs],
|
81
|
+
configs[:tabs],
|
82
|
+
TAB_DEFAULTS
|
83
|
+
)
|
84
|
+
|
85
|
+
model
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param model [HashWithIndifferentAccess]
|
89
|
+
# @param configs [HashWithIndifferentAccess]
|
90
|
+
# @return [HashWithIndifferentAccess]
|
91
|
+
def merge_scopes!(model, configs)
|
92
|
+
model[:scopes] = merge_by_name(
|
93
|
+
model[:scopes],
|
94
|
+
configs[:scopes],
|
95
|
+
SCOPE_DEFAULTS,
|
96
|
+
->(scope) { scope[:scope_type] != 'filter' }
|
97
|
+
)
|
98
|
+
|
99
|
+
model
|
100
|
+
end
|
101
|
+
|
102
|
+
# @param defaults [Array<HashWithIndifferentAccess>]
|
103
|
+
# @param configs [Array<HashWithIndifferentAccess>]
|
104
|
+
# @return [Array<HashWithIndifferentAccess>]
|
105
|
+
def merge_by_name(defaults, configs, default_attrs = {}, default_item_check = nil)
|
106
|
+
return defaults if configs.blank?
|
107
|
+
|
108
|
+
(defaults.pluck(:name) + configs.pluck(:name)).uniq.map do |name|
|
109
|
+
config_item = configs.find { |e| e[:name] == name }
|
110
|
+
default_item = defaults.find { |e| e[:name] == name }
|
111
|
+
|
112
|
+
next if default_item.nil? && default_item_check&.call(config_item)
|
113
|
+
|
114
|
+
(default_item || default_attrs).merge(config_item || {})
|
115
|
+
end.compact
|
116
|
+
end
|
117
|
+
|
118
|
+
# @param columns [Array<HashWithIndifferentAccess>]
|
119
|
+
# @param sql [String]
|
120
|
+
# @return [Array<HashWithIndifferentAccess>]
|
121
|
+
def merge_custom_sql_columns(columns, sql)
|
122
|
+
return columns if sql.blank?
|
123
|
+
|
124
|
+
query_columns = Resources::CustomSqlColumnsCache.call(sql)
|
125
|
+
|
126
|
+
columns_index = columns.index_by { |e| e[:name] }
|
127
|
+
|
128
|
+
merged_columns =
|
129
|
+
query_columns.map do |column|
|
130
|
+
existing_column = columns_index.delete(column[:name])
|
131
|
+
|
132
|
+
next existing_column if existing_column
|
133
|
+
|
134
|
+
column.merge(COLUMN_DEFAULTS).merge(
|
135
|
+
access_type: ColumnAccessTypes::READ_ONLY,
|
136
|
+
column_source: ColumnSources::QUERY,
|
137
|
+
virtual: false
|
138
|
+
).with_indifferent_access
|
139
|
+
end
|
140
|
+
|
141
|
+
reflection_columns = columns_index.values.select { |c| c[:column_source] == ColumnSources::REFLECTION }
|
142
|
+
|
143
|
+
reflection_columns + merged_columns
|
144
|
+
end
|
145
|
+
|
146
|
+
# @param cache_keys [Hash]
|
147
|
+
# @return [HashWithIndifferentAccess<String, HashWithIndifferentAccess>]
|
148
|
+
def load_configs(cache_keys)
|
149
|
+
resources = Motor::Configs::LoadFromCache.load_resources(cache_key: cache_keys[:resources])
|
150
|
+
|
151
|
+
resources.each_with_object(ActiveSupport::HashWithIndifferentAccess.new) do |resource, acc|
|
152
|
+
acc[resource.name] = resource.preferences
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module ReorderSchema
|
5
|
+
COLUMNS_DEFAULT_ORDER_WEIGHTS = {
|
6
|
+
id: 0,
|
7
|
+
updated_at: 2,
|
8
|
+
edited_at: 2,
|
9
|
+
created_at: 3,
|
10
|
+
inserted_at: 3,
|
11
|
+
deleted_at: 4,
|
12
|
+
archived_at: 4
|
13
|
+
}.with_indifferent_access
|
14
|
+
|
15
|
+
COLUMNS_DEFAULT_ORDER_WEIGHT = 1
|
16
|
+
|
17
|
+
module_function
|
18
|
+
|
19
|
+
# @param cache_keys [Hash]
|
20
|
+
# @param schema [Array<HashWithIndifferentAccess>]
|
21
|
+
# @return [Array<HashWithIndifferentAccess>]
|
22
|
+
def call(schema, cache_keys = {})
|
23
|
+
configs = load_configs(cache_keys)
|
24
|
+
|
25
|
+
schema = sort_by_name(schema, configs['resources.order'])
|
26
|
+
|
27
|
+
schema.map { |model| reorder_model(model, configs) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def reorder_model(model, configs)
|
31
|
+
order_configs = build_order_configs(model[:name], configs)
|
32
|
+
|
33
|
+
model.merge(
|
34
|
+
columns: sort_by_name(sort_columns(model[:columns]), order_configs[:columns], sort_alphabetically: false),
|
35
|
+
associations: sort_by_name(model[:associations], order_configs[:associations]),
|
36
|
+
actions: sort_by_name(model[:actions], order_configs[:actions], sort_alphabetically: false),
|
37
|
+
tabs: sort_by_name(model[:tabs], order_configs[:tabs], sort_alphabetically: false),
|
38
|
+
scopes: sort_by_name(model[:scopes], order_configs[:scopes])
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_order_configs(model_name, configs)
|
43
|
+
{
|
44
|
+
columns: configs["resources.#{model_name}.columns.order"],
|
45
|
+
associations: configs["resources.#{model_name}.associations.order"],
|
46
|
+
actions: configs["resources.#{model_name}.actions.order"],
|
47
|
+
tabs: configs["resources.#{model_name}.tabs.order"],
|
48
|
+
scopes: configs["resources.#{model_name}.scopes.order"]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param list [Array<HashWithIndifferentAccess>]
|
53
|
+
# @param sort_alphabetically [Boolean]
|
54
|
+
# @param order [Array<String>]
|
55
|
+
# @return [Array<HashWithIndifferentAccess>]
|
56
|
+
def sort_by_name(list, order, sort_alphabetically: true)
|
57
|
+
return list if order.blank? && !sort_alphabetically
|
58
|
+
|
59
|
+
list.sort_by do |item|
|
60
|
+
if order.present?
|
61
|
+
order.index(item[:name]) || Float::MAX
|
62
|
+
else
|
63
|
+
item[:display_name].to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param columns [Array<HashWithIndifferentAccess>]
|
69
|
+
# @return [Array<HashWithIndifferentAccess>]
|
70
|
+
def sort_columns(columns)
|
71
|
+
columns.each_with_object([]) do |column, acc|
|
72
|
+
weight = COLUMNS_DEFAULT_ORDER_WEIGHTS.fetch(column[:name], COLUMNS_DEFAULT_ORDER_WEIGHT)
|
73
|
+
|
74
|
+
(acc[weight] ||= []) << column
|
75
|
+
end.flatten.compact
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param cache_keys [Hash]
|
79
|
+
# @return [Hash<String, HashWithIndifferentAccess>]
|
80
|
+
def load_configs(cache_keys = {})
|
81
|
+
configs = Motor::Configs::LoadFromCache.load_configs(cache_key: cache_keys[:configs])
|
82
|
+
|
83
|
+
configs.each_with_object({}) do |config, acc|
|
84
|
+
acc[config.key] = config.value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module BuildSchema
|
5
|
+
module Utils
|
6
|
+
ABBREVIATIONS = {
|
7
|
+
'Id' => 'ID',
|
8
|
+
'Uuid' => 'UUID',
|
9
|
+
'Url' => 'URL',
|
10
|
+
'Iso' => 'ISO',
|
11
|
+
'vip' => 'VIP',
|
12
|
+
'Ip' => 'IP',
|
13
|
+
'Zip' => 'ZIP'
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def slugify(model)
|
19
|
+
model.name.underscore.pluralize.gsub('/', '__')
|
20
|
+
end
|
21
|
+
|
22
|
+
def classify_slug(slug)
|
23
|
+
slug.singularize.gsub('__', '/').classify.constantize
|
24
|
+
end
|
25
|
+
|
26
|
+
def humanize_column_name(column_name)
|
27
|
+
ABBREVIATIONS.fetch(column_name, column_name.humanize)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
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
|
+
|
14
|
+
module ColumnTypes
|
15
|
+
ALL = [
|
16
|
+
STRING = 'string',
|
17
|
+
INTEGER = 'integer',
|
18
|
+
FLOAT = 'float',
|
19
|
+
REFERENCE = 'reference',
|
20
|
+
DATETIME = 'datetime',
|
21
|
+
DATE = 'date',
|
22
|
+
BOOLEAN = 'boolean',
|
23
|
+
TEXTAREA = 'textarea',
|
24
|
+
RICHTEXT = 'richtext',
|
25
|
+
CURRENCY = 'currency',
|
26
|
+
PERCENTAGE = 'percentage',
|
27
|
+
CHANGE = 'change',
|
28
|
+
CHART = 'chart',
|
29
|
+
TAG = 'tag',
|
30
|
+
LINK = 'link',
|
31
|
+
COLOR = 'color',
|
32
|
+
IMAGE = 'image',
|
33
|
+
FILE = 'file',
|
34
|
+
JSON = 'json'
|
35
|
+
].freeze
|
36
|
+
end
|
37
|
+
|
38
|
+
module ColumnSources
|
39
|
+
ALL = [
|
40
|
+
TABLE = 'table',
|
41
|
+
QUERY = 'query',
|
42
|
+
REFLECTION = 'reflection'
|
43
|
+
].freeze
|
44
|
+
end
|
45
|
+
|
46
|
+
SEARCHABLE_COLUMN_TYPES = %i[citext text string bitstring].freeze
|
47
|
+
|
48
|
+
DEFAULT_TYPE = 'default'
|
49
|
+
DEFAULT_ICON = 'database'
|
50
|
+
|
51
|
+
COLUMN_NAME_ACCESS_TYPES = {
|
52
|
+
id: ColumnAccessTypes::READ_ONLY,
|
53
|
+
created_at: ColumnAccessTypes::READ_ONLY,
|
54
|
+
created_on: ColumnAccessTypes::READ_ONLY,
|
55
|
+
inserted_at: ColumnAccessTypes::READ_ONLY,
|
56
|
+
updated_at: ColumnAccessTypes::READ_ONLY,
|
57
|
+
updated_on: ColumnAccessTypes::READ_ONLY,
|
58
|
+
modified_at: ColumnAccessTypes::READ_ONLY,
|
59
|
+
deleted_at: ColumnAccessTypes::READ_ONLY
|
60
|
+
}.with_indifferent_access.freeze
|
61
|
+
|
62
|
+
COLUMN_DEFAULTS = {
|
63
|
+
access_type: ColumnAccessTypes::READ_WRITE,
|
64
|
+
column_source: ColumnSources::TABLE,
|
65
|
+
default_value: nil,
|
66
|
+
reference: nil,
|
67
|
+
format: {},
|
68
|
+
validators: [],
|
69
|
+
description: ''
|
70
|
+
}.with_indifferent_access
|
71
|
+
|
72
|
+
ACTION_DEFAULTS = {
|
73
|
+
visible: true,
|
74
|
+
apply_on: 'member',
|
75
|
+
preferences: {}
|
76
|
+
}.with_indifferent_access
|
77
|
+
|
78
|
+
TAB_DEFAULTS = {
|
79
|
+
visible: true,
|
80
|
+
tab_type: DEFAULT_TYPE,
|
81
|
+
preferences: {}
|
82
|
+
}.with_indifferent_access
|
83
|
+
|
84
|
+
SCOPE_DEFAULTS = {
|
85
|
+
visible: true,
|
86
|
+
scope_type: DEFAULT_TYPE,
|
87
|
+
preferences: {}
|
88
|
+
}.with_indifferent_access
|
89
|
+
|
90
|
+
ASSOCIATION_DEFAULTS = {
|
91
|
+
visible: true,
|
92
|
+
icon: DEFAULT_ICON,
|
93
|
+
options: {}
|
94
|
+
}.with_indifferent_access
|
95
|
+
|
96
|
+
module_function
|
97
|
+
|
98
|
+
def call(cache_keys = {}, current_ability = nil)
|
99
|
+
schema = LoadFromRails.call
|
100
|
+
schema = MergeSchemaConfigs.call(schema, cache_keys)
|
101
|
+
schema = ApplyPermissions.call(schema, current_ability) if current_ability
|
102
|
+
|
103
|
+
ReorderSchema.call(schema, cache_keys)
|
104
|
+
end
|
105
|
+
|
106
|
+
def for_model(model)
|
107
|
+
schema = Motor::BuildSchema::LoadFromRails.build_model_schema(model)
|
108
|
+
configs = Motor::Resource.find_by(name: schema[:name]).preferences
|
109
|
+
|
110
|
+
MergeSchemaConfigs.merge_model(schema, configs)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
require_relative 'build_schema/active_storage_attachment_schema'
|
116
|
+
require_relative 'build_schema/adjust_devise_model_schema'
|
117
|
+
require_relative 'build_schema/load_from_rails'
|
118
|
+
require_relative 'build_schema/find_display_column'
|
119
|
+
require_relative 'build_schema/find_icon'
|
120
|
+
require_relative 'build_schema/reorder_schema'
|
121
|
+
require_relative 'build_schema/merge_schema_configs'
|
122
|
+
require_relative 'build_schema/apply_permissions'
|
123
|
+
require_relative 'build_schema/utils'
|
124
|
+
require_relative 'build_schema/defaults'
|
125
|
+
require_relative 'build_schema/find_searchable_columns'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module CancanUtils
|
5
|
+
module AbilityPatch
|
6
|
+
def serialized_rules
|
7
|
+
return [] unless @rules
|
8
|
+
|
9
|
+
@rules.map do |rule|
|
10
|
+
{
|
11
|
+
base_behavior: rule.base_behavior,
|
12
|
+
actions: expand_actions(rule.actions),
|
13
|
+
subjects: rule.subjects.map(&:to_s),
|
14
|
+
attributes: rule.attributes,
|
15
|
+
conditions: rule.conditions.as_json
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def rules_hash
|
21
|
+
serialized_rules.hash
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def default_alias_actions
|
27
|
+
super.merge(destroy: %i[remove delete])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Motor
|
4
|
+
module Configs
|
5
|
+
module BuildConfigsHash
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def call
|
9
|
+
cache_keys = LoadFromCache.load_cache_keys
|
10
|
+
|
11
|
+
normalize_hash(
|
12
|
+
engine_version: Motor::VERSION,
|
13
|
+
file_version: cache_keys.values.compact.max.to_time,
|
14
|
+
resources: build_resources_hash(cache_keys[:resources]),
|
15
|
+
configs: build_configs_hash(cache_keys[:configs]),
|
16
|
+
queries: build_queries_hash(cache_keys[:queries]),
|
17
|
+
dashboards: build_dashboards_hash(cache_keys[:dashboards]),
|
18
|
+
forms: build_forms_hash(cache_keys[:forms]),
|
19
|
+
alerts: build_alerts_hash(cache_keys[:alerts]),
|
20
|
+
api_configs: build_api_configs_hash(cache_keys[:api_configs])
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_queries_hash(cache_key = nil)
|
25
|
+
Motor::Configs::LoadFromCache.load_queries(cache_key: cache_key).sort_by(&:id).map do |query|
|
26
|
+
query.slice(%i[id name sql_body description preferences])
|
27
|
+
.merge(tags: query.tags.map(&:name), updated_at: query.updated_at.to_time)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_dashboards_hash(cache_key = nil)
|
32
|
+
Motor::Configs::LoadFromCache.load_dashboards(cache_key: cache_key).sort_by(&:id).map do |dashboard|
|
33
|
+
dashboard.slice(%i[id title description preferences])
|
34
|
+
.merge(tags: dashboard.tags.map(&:name), updated_at: dashboard.updated_at.to_time)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_alerts_hash(cache_key = nil)
|
39
|
+
Motor::Configs::LoadFromCache.load_alerts(cache_key: cache_key).sort_by(&:id).map do |alert|
|
40
|
+
alert.slice(%i[id name query_id to_emails is_enabled description preferences])
|
41
|
+
.merge(tags: alert.tags.map(&:name), updated_at: alert.updated_at.to_time)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_forms_hash(cache_key = nil)
|
46
|
+
Motor::Configs::LoadFromCache.load_forms(cache_key: cache_key).sort_by(&:id).map do |form|
|
47
|
+
form.slice(%i[id name http_method api_path description preferences api_config_name])
|
48
|
+
.merge(tags: form.tags.map(&:name), updated_at: form.updated_at.to_time)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def build_api_configs_hash(cache_key = nil)
|
53
|
+
Motor::Configs::LoadFromCache.load_api_configs(cache_key: cache_key).sort_by(&:id).map do |config|
|
54
|
+
config.slice(%i[id name url preferences description]).merge(updated_at: config.updated_at.to_time)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_configs_hash(cache_key = nil)
|
59
|
+
Motor::Configs::LoadFromCache.load_configs(cache_key: cache_key).sort_by(&:key).map do |config|
|
60
|
+
{
|
61
|
+
key: config.key,
|
62
|
+
value: config.value,
|
63
|
+
updated_at: config.updated_at.to_time
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_resources_hash(cache_key = nil)
|
69
|
+
Motor::Configs::LoadFromCache.load_resources(cache_key: cache_key).sort_by(&:name).map do |resource|
|
70
|
+
{
|
71
|
+
name: resource.name,
|
72
|
+
preferences: resource.preferences,
|
73
|
+
updated_at: resource.updated_at.to_time
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def normalize_hash(value)
|
79
|
+
case value
|
80
|
+
when Hash, ActiveSupport::HashWithIndifferentAccess
|
81
|
+
value.to_h.stringify_keys.transform_values { |v| normalize_hash(v) }
|
82
|
+
when Array
|
83
|
+
value.map { |e| normalize_hash(e) }
|
84
|
+
else
|
85
|
+
value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|