motor-admin-cstham8 0.4.35

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.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +661 -0
  3. data/README.md +230 -0
  4. data/Rakefile +11 -0
  5. data/app/channels/motor/application_cable/channel.rb +14 -0
  6. data/app/channels/motor/application_cable/connection.rb +27 -0
  7. data/app/channels/motor/notes_channel.rb +9 -0
  8. data/app/channels/motor/notifications_channel.rb +9 -0
  9. data/app/controllers/concerns/motor/current_ability.rb +21 -0
  10. data/app/controllers/concerns/motor/current_user_method.rb +18 -0
  11. data/app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb +73 -0
  12. data/app/controllers/concerns/motor/wrap_io_params.rb +25 -0
  13. data/app/controllers/motor/active_storage_attachments_controller.rb +64 -0
  14. data/app/controllers/motor/alerts_controller.rb +82 -0
  15. data/app/controllers/motor/api_base_controller.rb +33 -0
  16. data/app/controllers/motor/api_configs_controller.rb +54 -0
  17. data/app/controllers/motor/application_controller.rb +8 -0
  18. data/app/controllers/motor/assets_controller.rb +43 -0
  19. data/app/controllers/motor/audits_controller.rb +16 -0
  20. data/app/controllers/motor/auth_tokens_controller.rb +36 -0
  21. data/app/controllers/motor/configs_controller.rb +33 -0
  22. data/app/controllers/motor/dashboards_controller.rb +64 -0
  23. data/app/controllers/motor/data_controller.rb +88 -0
  24. data/app/controllers/motor/forms_controller.rb +61 -0
  25. data/app/controllers/motor/icons_controller.rb +22 -0
  26. data/app/controllers/motor/note_tags_controller.rb +13 -0
  27. data/app/controllers/motor/notes_controller.rb +58 -0
  28. data/app/controllers/motor/notifications_controller.rb +33 -0
  29. data/app/controllers/motor/queries_controller.rb +64 -0
  30. data/app/controllers/motor/reminders_controller.rb +38 -0
  31. data/app/controllers/motor/resource_default_queries_controller.rb +23 -0
  32. data/app/controllers/motor/resource_methods_controller.rb +23 -0
  33. data/app/controllers/motor/resources_controller.rb +26 -0
  34. data/app/controllers/motor/run_api_requests_controller.rb +56 -0
  35. data/app/controllers/motor/run_graphql_requests_controller.rb +48 -0
  36. data/app/controllers/motor/run_queries_controller.rb +77 -0
  37. data/app/controllers/motor/schema_controller.rb +31 -0
  38. data/app/controllers/motor/send_alerts_controller.rb +26 -0
  39. data/app/controllers/motor/sessions_controller.rb +23 -0
  40. data/app/controllers/motor/slack_conversations_controller.rb +11 -0
  41. data/app/controllers/motor/tags_controller.rb +11 -0
  42. data/app/controllers/motor/ui_controller.rb +51 -0
  43. data/app/controllers/motor/users_for_autocomplete_controller.rb +23 -0
  44. data/app/jobs/motor/alert_sending_job.rb +13 -0
  45. data/app/jobs/motor/application_job.rb +6 -0
  46. data/app/jobs/motor/notify_note_mentions_job.rb +9 -0
  47. data/app/jobs/motor/notify_reminder_job.rb +9 -0
  48. data/app/mailers/motor/alerts_mailer.rb +39 -0
  49. data/app/mailers/motor/application_mailer.rb +33 -0
  50. data/app/mailers/motor/notifications_mailer.rb +33 -0
  51. data/app/models/motor/alert.rb +30 -0
  52. data/app/models/motor/alert_lock.rb +7 -0
  53. data/app/models/motor/api_config.rb +28 -0
  54. data/app/models/motor/application_record.rb +18 -0
  55. data/app/models/motor/audit.rb +13 -0
  56. data/app/models/motor/config.rb +13 -0
  57. data/app/models/motor/dashboard.rb +26 -0
  58. data/app/models/motor/form.rb +23 -0
  59. data/app/models/motor/note.rb +18 -0
  60. data/app/models/motor/note_tag.rb +7 -0
  61. data/app/models/motor/note_tag_tag.rb +8 -0
  62. data/app/models/motor/notification.rb +14 -0
  63. data/app/models/motor/query.rb +33 -0
  64. data/app/models/motor/reminder.rb +13 -0
  65. data/app/models/motor/resource.rb +15 -0
  66. data/app/models/motor/tag.rb +7 -0
  67. data/app/models/motor/taggable_tag.rb +8 -0
  68. data/app/views/layouts/motor/application.html.erb +17 -0
  69. data/app/views/layouts/motor/mailer.html.erb +72 -0
  70. data/app/views/motor/alerts_mailer/alert_email.html.erb +54 -0
  71. data/app/views/motor/notifications_mailer/notify_mention_email.html.erb +28 -0
  72. data/app/views/motor/notifications_mailer/notify_reminder_email.html.erb +28 -0
  73. data/app/views/motor/ui/show.html.erb +1 -0
  74. data/config/locales/el.yml +420 -0
  75. data/config/locales/en.yml +340 -0
  76. data/config/locales/es.yml +420 -0
  77. data/config/locales/ja.yml +340 -0
  78. data/config/locales/pt.yml +416 -0
  79. data/config/routes.rb +65 -0
  80. data/lib/generators/motor/install_generator.rb +24 -0
  81. data/lib/generators/motor/install_notes_generator.rb +22 -0
  82. data/lib/generators/motor/migration.rb +17 -0
  83. data/lib/generators/motor/templates/install.rb +271 -0
  84. data/lib/generators/motor/templates/install_api_configs.rb +86 -0
  85. data/lib/generators/motor/templates/install_notes.rb +83 -0
  86. data/lib/generators/motor/templates/upgrade_motor_api_actions.rb +71 -0
  87. data/lib/generators/motor/upgrade_generator.rb +43 -0
  88. data/lib/motor/active_record_utils/action_text_attribute_patch.rb +19 -0
  89. data/lib/motor/active_record_utils/active_record_connection_column_patch.rb +14 -0
  90. data/lib/motor/active_record_utils/active_record_filter.rb +405 -0
  91. data/lib/motor/active_record_utils/active_storage_blob_patch.rb +30 -0
  92. data/lib/motor/active_record_utils/active_storage_links_extension.rb +11 -0
  93. data/lib/motor/active_record_utils/defined_scopes_extension.rb +25 -0
  94. data/lib/motor/active_record_utils/fetch_methods.rb +24 -0
  95. data/lib/motor/active_record_utils/types.rb +64 -0
  96. data/lib/motor/active_record_utils.rb +45 -0
  97. data/lib/motor/admin.rb +141 -0
  98. data/lib/motor/alerts/persistance.rb +97 -0
  99. data/lib/motor/alerts/scheduled_alerts_cache.rb +29 -0
  100. data/lib/motor/alerts/scheduler.rb +30 -0
  101. data/lib/motor/alerts/slack_sender.rb +74 -0
  102. data/lib/motor/alerts.rb +52 -0
  103. data/lib/motor/api_configs.rb +41 -0
  104. data/lib/motor/api_query/apply_scope.rb +44 -0
  105. data/lib/motor/api_query/build_json.rb +171 -0
  106. data/lib/motor/api_query/build_meta.rb +20 -0
  107. data/lib/motor/api_query/filter.rb +125 -0
  108. data/lib/motor/api_query/paginate.rb +19 -0
  109. data/lib/motor/api_query/search.rb +60 -0
  110. data/lib/motor/api_query/sort.rb +64 -0
  111. data/lib/motor/api_query.rb +24 -0
  112. data/lib/motor/assets.rb +62 -0
  113. data/lib/motor/build_schema/active_storage_attachment_schema.rb +125 -0
  114. data/lib/motor/build_schema/adjust_devise_model_schema.rb +60 -0
  115. data/lib/motor/build_schema/apply_permissions.rb +64 -0
  116. data/lib/motor/build_schema/defaults.rb +66 -0
  117. data/lib/motor/build_schema/find_display_column.rb +65 -0
  118. data/lib/motor/build_schema/find_icon.rb +135 -0
  119. data/lib/motor/build_schema/find_searchable_columns.rb +33 -0
  120. data/lib/motor/build_schema/load_from_rails.rb +361 -0
  121. data/lib/motor/build_schema/merge_schema_configs.rb +157 -0
  122. data/lib/motor/build_schema/reorder_schema.rb +88 -0
  123. data/lib/motor/build_schema/utils.rb +31 -0
  124. data/lib/motor/build_schema.rb +125 -0
  125. data/lib/motor/cancan_utils/ability_patch.rb +31 -0
  126. data/lib/motor/cancan_utils/can_manage_all.rb +14 -0
  127. data/lib/motor/cancan_utils.rb +9 -0
  128. data/lib/motor/configs/build_configs_hash.rb +90 -0
  129. data/lib/motor/configs/build_ui_app_tag.rb +177 -0
  130. data/lib/motor/configs/load_from_cache.rb +110 -0
  131. data/lib/motor/configs/sync_from_file.rb +35 -0
  132. data/lib/motor/configs/sync_from_hash.rb +159 -0
  133. data/lib/motor/configs/sync_middleware.rb +72 -0
  134. data/lib/motor/configs/sync_with_remote.rb +47 -0
  135. data/lib/motor/configs/write_to_file.rb +36 -0
  136. data/lib/motor/configs.rb +39 -0
  137. data/lib/motor/dashboards/persistance.rb +73 -0
  138. data/lib/motor/dashboards.rb +8 -0
  139. data/lib/motor/forms/persistance.rb +93 -0
  140. data/lib/motor/forms.rb +8 -0
  141. data/lib/motor/hash_serializer.rb +21 -0
  142. data/lib/motor/net_http_utils.rb +50 -0
  143. data/lib/motor/notes/notify_mentions.rb +71 -0
  144. data/lib/motor/notes/notify_reminder.rb +48 -0
  145. data/lib/motor/notes/persist.rb +36 -0
  146. data/lib/motor/notes/reminders_scheduler.rb +39 -0
  147. data/lib/motor/notes/tags.rb +34 -0
  148. data/lib/motor/notes.rb +12 -0
  149. data/lib/motor/queries/persistance.rb +90 -0
  150. data/lib/motor/queries/postgresql_exec_query.rb +28 -0
  151. data/lib/motor/queries/render_sql_template.rb +61 -0
  152. data/lib/motor/queries/run_query.rb +289 -0
  153. data/lib/motor/queries.rb +11 -0
  154. data/lib/motor/railtie.rb +11 -0
  155. data/lib/motor/resources/custom_sql_columns_cache.rb +17 -0
  156. data/lib/motor/resources/fetch_configured_model.rb +269 -0
  157. data/lib/motor/resources/persist_configs.rb +232 -0
  158. data/lib/motor/resources.rb +19 -0
  159. data/lib/motor/slack/client.rb +62 -0
  160. data/lib/motor/slack.rb +16 -0
  161. data/lib/motor/tags.rb +32 -0
  162. data/lib/motor/tasks/motor.rake +54 -0
  163. data/lib/motor/version.rb +5 -0
  164. data/lib/motor-admin-cstham8.rb +3 -0
  165. data/lib/motor.rb +87 -0
  166. data/ui/dist/manifest.json +1990 -0
  167. metadata +303 -0
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module Resources
5
+ module PersistConfigs
6
+ COLUMN_DEFAULTS = BuildSchema::COLUMN_DEFAULTS
7
+ ACTION_DEFAULTS = BuildSchema::ACTION_DEFAULTS
8
+ TAB_DEFAULTS = BuildSchema::TAB_DEFAULTS
9
+ SCOPE_DEFAULTS = BuildSchema::SCOPE_DEFAULTS
10
+ ASSOCIATION_DEFAULTS = BuildSchema::ASSOCIATION_DEFAULTS
11
+
12
+ module_function
13
+
14
+ # @param resource [Motor::Resource]
15
+ # @return [Motor::Resource]
16
+ def call(resource)
17
+ preferences = resource.preferences
18
+
19
+ resource = Motor::Resource.find_or_initialize_by(name: resource.name)
20
+
21
+ assign_preferences!(resource, preferences)
22
+
23
+ resource.save!
24
+
25
+ resource
26
+ rescue ActiveRecord::RecordNotUnique
27
+ retry
28
+ end
29
+
30
+ # @param resource [Motor::Resource]
31
+ # @param preferences [HashWithIndifferentAccess]
32
+ # @return [Motor::Resource]
33
+ def assign_preferences!(resource, preferences)
34
+ default_schema = fetch_default_schema(resource.name)
35
+
36
+ resource.preferences = normalize_preferences(
37
+ default_schema,
38
+ resource.preferences,
39
+ preferences
40
+ )
41
+
42
+ resource
43
+ end
44
+
45
+ # @param default_prefs [HashWithIndifferentAccess]
46
+ # @param existing_prefs [HashWithIndifferentAccess]
47
+ # @param new_prefs [HashWithIndifferentAccess]
48
+ # @return [HashWithIndifferentAccess]
49
+ def normalize_preferences(default_prefs, existing_prefs, new_prefs)
50
+ normalized_preferences = new_prefs.slice(*RESOURCE_ATTRS).with_indifferent_access
51
+ normalized_preferences = existing_prefs.merge(normalized_preferences)
52
+ normalized_preferences = reject_default(default_prefs, normalized_preferences)
53
+
54
+ normalize_configs!(normalized_preferences, :columns, default_prefs, existing_prefs, new_prefs)
55
+ normalize_configs!(normalized_preferences, :associations, default_prefs, existing_prefs, new_prefs)
56
+ normalize_configs!(normalized_preferences, :actions, default_prefs, existing_prefs, new_prefs)
57
+ normalize_configs!(normalized_preferences, :tabs, default_prefs, existing_prefs, new_prefs)
58
+ normalize_configs!(normalized_preferences, :scopes, default_prefs, existing_prefs, new_prefs)
59
+
60
+ normalized_preferences.compact
61
+ end
62
+
63
+ def normalize_configs!(preferences, configs_name, default_prefs, existing_prefs, new_prefs)
64
+ return preferences if new_prefs[configs_name].blank?
65
+
66
+ normalized_configs = public_send(:"normalize_#{configs_name}",
67
+ default_prefs[configs_name],
68
+ existing_prefs.fetch(configs_name, []),
69
+ new_prefs.fetch(configs_name, []))
70
+
71
+ preferences[configs_name] = normalized_configs
72
+
73
+ preferences
74
+ end
75
+
76
+ # @param default_columns [Array<HashWithIndifferentAccess>]
77
+ # @param existing_columns [Array<HashWithIndifferentAccess>]
78
+ # @param new_columns [Array<HashWithIndifferentAccess>]
79
+ # @return [Array<HashWithIndifferentAccess>]
80
+ def normalize_columns(default_columns, existing_columns, new_columns)
81
+ fetch_update_names(existing_columns, new_columns).uniq.map do |name|
82
+ new_column = safe_fetch_by_name(new_columns, name)
83
+
84
+ next if new_column[:_remove]
85
+
86
+ existing_column = safe_fetch_by_name(existing_columns, name)
87
+ default_column = safe_fetch_by_name(default_columns, name)
88
+ column_attrs = new_column.slice(*COLUMN_ATTRS)
89
+
90
+ normalized_column = existing_column.merge(column_attrs)
91
+ normalized_column = reject_default(default_column, normalized_column)
92
+
93
+ next if normalized_column.blank?
94
+
95
+ normalized_column[:name] ||= name
96
+
97
+ normalized_column
98
+ end.compact.presence
99
+ end
100
+
101
+ # @param default_actions [Array<HashWithIndifferentAccess>]
102
+ # @param existing_actions [Array<HashWithIndifferentAccess>]
103
+ # @param new_actions [Array<HashWithIndifferentAccess>]
104
+ # @return [Array<HashWithIndifferentAccess>]
105
+ def normalize_actions(default_actions, existing_actions, new_actions)
106
+ fetch_update_names(existing_actions, new_actions).map do |name|
107
+ new_action = safe_fetch_by_name(new_actions, name)
108
+
109
+ next if new_action[:_remove]
110
+
111
+ existing_action = safe_fetch_by_name(existing_actions, name)
112
+ default_action = safe_fetch_by_name(default_actions, name)
113
+ action_attrs = new_action.slice(*ACTION_ATTRS)
114
+
115
+ normalized_action = existing_action.merge(action_attrs)
116
+ normalized_action = reject_default(default_action.presence || ACTION_DEFAULTS, normalized_action)
117
+
118
+ next if normalized_action.blank?
119
+
120
+ normalized_action[:name] ||= name
121
+
122
+ normalized_action
123
+ end.compact.presence
124
+ end
125
+
126
+ # @param default_tabs [Array<HashWithIndifferentAccess>]
127
+ # @param existing_tabs [Array<HashWithIndifferentAccess>]
128
+ # @param new_tabs [Array<HashWithIndifferentAccess>]
129
+ # @return [Array<HashWithIndifferentAccess>]
130
+ def normalize_tabs(default_tabs, existing_tabs, new_tabs)
131
+ fetch_update_names(existing_tabs, new_tabs).uniq.map do |name|
132
+ new_tab = safe_fetch_by_name(new_tabs, name)
133
+
134
+ next if new_tab[:_remove]
135
+
136
+ existing_tab = safe_fetch_by_name(existing_tabs, name)
137
+ default_tab = safe_fetch_by_name(default_tabs, name)
138
+ tab_attrs = new_tab.slice(*TAB_ATTRS)
139
+
140
+ normalized_tab = existing_tab.merge(tab_attrs)
141
+ normalized_tab = reject_default(default_tab.presence || TAB_DEFAULTS, normalized_tab)
142
+
143
+ next if normalized_tab.blank?
144
+
145
+ normalized_tab[:name] ||= name
146
+
147
+ normalized_tab
148
+ end.compact.presence
149
+ end
150
+
151
+ # @param default_scopes [Array<HashWithIndifferentAccess>]
152
+ # @param existing_scopes [Array<HashWithIndifferentAccess>]
153
+ # @param new_scopes [Array<HashWithIndifferentAccess>]
154
+ # @return [Array<HashWithIndifferentAccess>]
155
+ def normalize_scopes(default_scopes, existing_scopes, new_scopes)
156
+ fetch_update_names(existing_scopes, new_scopes).uniq.map do |name|
157
+ new_scope = safe_fetch_by_name(new_scopes, name)
158
+
159
+ next if new_scope[:_remove]
160
+
161
+ existing_scope = safe_fetch_by_name(existing_scopes, name)
162
+ default_scope = safe_fetch_by_name(default_scopes, name)
163
+ scope_attrs = new_scope.slice(*SCOPE_ATTRS)
164
+
165
+ normalized_scope = existing_scope.merge(scope_attrs)
166
+ normalized_scope = reject_default(default_scope.presence || SCOPE_DEFAULTS, normalized_scope)
167
+
168
+ next if normalized_scope.blank?
169
+
170
+ normalized_scope[:name] ||= name
171
+
172
+ normalized_scope
173
+ end.compact.presence
174
+ end
175
+
176
+ # @param default_assocs [Array<HashWithIndifferentAccess>]
177
+ # @param existing_assocs [Array<HashWithIndifferentAccess>]
178
+ # @param new_assocs [Array<HashWithIndifferentAccess>]
179
+ # @return [Array<HashWithIndifferentAccess>]
180
+ def normalize_associations(default_assocs, existing_assocs, new_assocs)
181
+ (existing_assocs.pluck(:name) + new_assocs.pluck(:name)).uniq.map do |name|
182
+ new_assoc = safe_fetch_by_name(new_assocs, name)
183
+
184
+ next if new_assoc[:_remove]
185
+
186
+ existing_assoc = safe_fetch_by_name(existing_assocs, name)
187
+ default_assoc = safe_fetch_by_name(default_assocs, name)
188
+ assoc_attrs = new_assoc.slice(*ASSOCIATION_ATTRS)
189
+
190
+ normalized_assoc = existing_assoc.merge(assoc_attrs)
191
+ normalized_assoc = reject_default(default_assoc.presence || ASSOCIATION_DEFAULTS, normalized_assoc)
192
+
193
+ normalized_assoc.merge(name: name) if normalized_assoc.present?
194
+ end.compact.presence
195
+ end
196
+
197
+ def fetch_update_names(existing_items, new_items)
198
+ new_names = new_items.map { |e| e[:_update] || e[:name] }
199
+
200
+ (existing_items.pluck(:name) + new_names).uniq
201
+ end
202
+
203
+ def safe_fetch_by_name(list, name)
204
+ list.find { |e| e[:_update] == name || e[:name] == name } || {}
205
+ end
206
+
207
+ # @param resource_name [String]
208
+ # @return [HashWithIndifferentAccess]
209
+ def fetch_default_schema(resource_name)
210
+ model = resource_name.classify.constantize
211
+
212
+ BuildSchema::LoadFromRails.build_model_schema(model).merge(custom_sql: model.all.to_sql)
213
+ end
214
+
215
+ # @param default [HashWithIndifferentAccess]
216
+ # @param new [HashWithIndifferentAccess]
217
+ # @return [HashWithIndifferentAccess]
218
+ def reject_default(default, new)
219
+ return new unless default
220
+
221
+ new.reject do |key, value|
222
+ default[key].to_json ==
223
+ if value.is_a?(Hash) || value.is_a?(ActiveSupport::HashWithIndifferentAccess)
224
+ value.select { |_, v| v.present? }.to_json
225
+ else
226
+ value.to_json
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module Resources
5
+ RESOURCE_ATTRS = %w[display_name display_column icon custom_sql visible display_primary_key
6
+ searchable_columns preferences].freeze
7
+ COLUMN_ATTRS = %w[name display_name column_type access_type default_value reference virtual format
8
+ validators description].freeze
9
+ ASSOCIATION_ATTRS = %w[name display_name model_name icon visible foreign_key primary_key options virtual
10
+ polymorphic slug].freeze
11
+ SCOPE_ATTRS = %w[name display_name scope_type preferences visible].freeze
12
+ ACTION_ATTRS = %w[name display_name action_type preferences apply_on visible].freeze
13
+ TAB_ATTRS = %w[name display_name tab_type preferences visible].freeze
14
+ end
15
+ end
16
+
17
+ require_relative 'resources/fetch_configured_model'
18
+ require_relative 'resources/persist_configs'
19
+ require_relative 'resources/custom_sql_columns_cache'
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module Slack
5
+ module Client
6
+ BASE_API_URL = 'https://slack.com/api'
7
+ POST_MESSAGE_ENPOINT = "#{BASE_API_URL}/chat.postMessage"
8
+ LOAD_CONVERSATIONS_ENPOINT = "#{BASE_API_URL}/conversations.list"
9
+ LOAD_USERS_ENPOINT = "#{BASE_API_URL}/users.list"
10
+ SEND_FILE_ENPOINT = "#{BASE_API_URL}/files.upload"
11
+
12
+ ApiError = Class.new(StandardError)
13
+
14
+ module_function
15
+
16
+ def send_message(params = {})
17
+ resp = Motor::NetHttpUtils.post(POST_MESSAGE_ENPOINT, params.merge(token: auth_token))
18
+
19
+ parse_json_response_or_throw_error(resp)
20
+ end
21
+
22
+ def send_file(params = {})
23
+ content = params.delete(:content)
24
+ body = { content: content }.to_query
25
+
26
+ resp = Motor::NetHttpUtils.post(SEND_FILE_ENPOINT, params.merge(token: auth_token), {}, body)
27
+
28
+ parse_json_response_or_throw_error(resp)
29
+ end
30
+
31
+ def load_conversations(params = {})
32
+ resp = Motor::NetHttpUtils.get(LOAD_CONVERSATIONS_ENPOINT, params.merge(token: auth_token))
33
+
34
+ parse_json_response_or_throw_error(resp)
35
+ end
36
+
37
+ def load_users(params = {})
38
+ resp = Motor::NetHttpUtils.get(LOAD_USERS_ENPOINT, params.merge(token: auth_token))
39
+
40
+ parse_json_response_or_throw_error(resp)
41
+ end
42
+
43
+ def parse_json_response_or_throw_error(resp)
44
+ data = JSON.parse(resp.body)
45
+
46
+ raise ApiError, resp.body unless data['ok']
47
+
48
+ data
49
+ end
50
+
51
+ def auth_token
52
+ return ENV['SLACK_AUTH_TOKEN'] unless defined?(Motor::EncryptedConfig)
53
+
54
+ config = Motor::EncryptedConfig.find_by(key: EncryptedConfig::SLACK_CREDENTIALS_KEY)
55
+
56
+ return '' unless config
57
+
58
+ config.value[:api_key]
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module Slack
5
+ ITEMS_LIMIT = 1000
6
+
7
+ module_function
8
+
9
+ def conversations
10
+ Slack::Client.load_conversations(limit: ITEMS_LIMIT)['channels'] +
11
+ Slack::Client.load_users(limit: ITEMS_LIMIT)['members']
12
+ end
13
+ end
14
+ end
15
+
16
+ require_relative 'slack/client'
data/lib/motor/tags.rb ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module Tags
5
+ module_function
6
+
7
+ def assign_tags(taggable, tags)
8
+ return taggable unless tags
9
+
10
+ tags.each do |tag_name|
11
+ next if taggable.taggable_tags.find { |tt| tt.tag.name.casecmp(tag_name).zero? }
12
+
13
+ tag = Tag.find_or_initialize_by(name: tag_name)
14
+
15
+ taggable.taggable_tags.new(tag: tag)
16
+ end
17
+
18
+ remove_missing_tags(taggable, tags) if taggable.persisted?
19
+
20
+ taggable
21
+ end
22
+
23
+ def remove_missing_tags(taggable, tags)
24
+ downcase_tags = tags.map(&:downcase)
25
+ tags_to_remove = taggable.tags.reject { |tt| tt.name.downcase.in?(downcase_tags) }
26
+
27
+ taggable.tags -= tags_to_remove
28
+
29
+ taggable
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :motor do
4
+ desc 'Create migratione and add route'
5
+
6
+ task install: :environment do
7
+ Rails::Generators.invoke('motor:install')
8
+ end
9
+
10
+ desc 'Update configs/motor.yml file'
11
+
12
+ task dump: :environment do
13
+ Motor::Configs::WriteToFile.write_with_lock
14
+
15
+ puts '✅ configs/motor.yml has been updated'
16
+ end
17
+
18
+ desc 'Load configs from configs/motor.yml file'
19
+
20
+ task load: :environment do
21
+ Motor::Configs::SyncFromFile.call(with_exception: true)
22
+
23
+ puts '✅ configs have been loaded from configs/motor.yml'
24
+ end
25
+
26
+ desc 'Reload configs from configs/motor.yml file'
27
+
28
+ task reload: :environment do
29
+ ActiveRecord::Base.transaction do
30
+ Motor::Configs.clear
31
+ Motor::Configs::SyncFromFile.call(with_exception: true)
32
+ end
33
+
34
+ puts '✅ configs have been loaded from configs/motor.yml'
35
+ end
36
+
37
+ desc 'Synchronize configs with remote application'
38
+
39
+ task sync: :environment do
40
+ remote_url = ENV['MOTOR_SYNC_REMOTE_URL']
41
+ api_key = ENV['MOTOR_SYNC_API_KEY']
42
+
43
+ raise 'Specify target app url using `MOTOR_SYNC_REMOTE_URL` env variable' if remote_url.blank?
44
+ raise 'Specify sync api key using `MOTOR_SYNC_API_KEY` env variable' if api_key.blank?
45
+
46
+ Motor::Configs::SyncWithRemote.call(remote_url, api_key)
47
+ Motor::Configs::WriteToFile.write_with_lock
48
+
49
+ puts "✅ Motor Admin configurations have been synced with #{remote_url}"
50
+ rescue Motor::Configs::SyncWithRemote::ApiNotFound
51
+ puts '⚠️ Synchronization failed: you need to specify `MOTOR_SYNC_API_KEY` ' \
52
+ 'env variable in your remote app in order to enable this feature'
53
+ end
54
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ VERSION = '0.4.35'
5
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'motor'
data/lib/motor.rb ADDED
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'concurrent/executor/fixed_thread_pool'
4
+ require 'concurrent/timer_task'
5
+ require 'cancancan'
6
+ require 'ar_lazy_preload'
7
+ require 'fugit'
8
+ require 'csv'
9
+ require 'audited'
10
+ require 'uri'
11
+ require 'net/http'
12
+ require 'net/https'
13
+
14
+ module Motor
15
+ PATH = Pathname.new(__dir__)
16
+
17
+ module DatabaseClasses
18
+ end
19
+
20
+ module_function
21
+
22
+ def reload!
23
+ Kernel.silence_warnings do
24
+ Dir[PATH.join('./motor/**/*.rb')].each do |f|
25
+ next if f.ends_with?('alerts/scheduler.rb')
26
+ next if f.ends_with?('notes/reminders_scheduler.rb')
27
+ next if f.ends_with?('alerts/scheduled_alerts_cache.rb')
28
+ next if f.ends_with?('configs/load_from_cache.rb')
29
+ next if f.ends_with?('configs/sync_from_file.rb')
30
+ next if f.ends_with?('resources/custom_sql_columns_cache.rb')
31
+
32
+ load f
33
+ end
34
+ end
35
+
36
+ true
37
+ end
38
+
39
+ def server?
40
+ defined?(::Rails::Server) ||
41
+ defined?(::Thin::Server) ||
42
+ defined?(::PhusionPassenger) ||
43
+ (defined?(::Puma) && File.basename($PROGRAM_NAME) == 'puma') ||
44
+ defined?(::Unicorn::HttpServer) ||
45
+ defined?(::Mongrel::HttpServer) ||
46
+ defined?(JRuby::Rack::VERSION) ||
47
+ defined?(::Trinidad::Server)
48
+ end
49
+
50
+ def app_host
51
+ Rails.application.config.action_dispatch.default_url_options&.fetch(:host) ||
52
+ ENV.fetch('HOST', 'example.com')
53
+ end
54
+
55
+ def company_name
56
+ 'Motor Admin'
57
+ end
58
+
59
+ def with_public_access?
60
+ ENV['MOTOR_PUBLIC_ACCESS'].to_s == 'true'
61
+ end
62
+
63
+ def development?
64
+ ENV['MOTOR_DEVELOPMENT'].present?
65
+ end
66
+ end
67
+
68
+ require 'motor/version'
69
+ require 'motor/admin'
70
+ require 'motor/assets'
71
+ require 'motor/active_record_utils'
72
+ require 'motor/cancan_utils'
73
+ require 'motor/build_schema'
74
+ require 'motor/api_query'
75
+ require 'motor/tags'
76
+ require 'motor/configs'
77
+ require 'motor/queries'
78
+ require 'motor/dashboards'
79
+ require 'motor/forms'
80
+ require 'motor/api_configs'
81
+ require 'motor/alerts'
82
+ require 'motor/slack'
83
+ require 'motor/resources'
84
+ require 'motor/notes'
85
+ require 'motor/hash_serializer'
86
+ require 'motor/net_http_utils'
87
+ require 'motor/railtie'