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,271 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def self.up
3
+ create_table :motor_queries do |t|
4
+ t.column :name, :string, null: false
5
+ t.column :description, :text
6
+ t.column :sql_body, :text, null: false
7
+ t.column :preferences, :text, null: false
8
+ t.column :author_id, :bigint
9
+ t.column :author_type, :string
10
+ t.column :deleted_at, :datetime
11
+
12
+ t.timestamps
13
+
14
+ t.index :updated_at
15
+ t.index 'name',
16
+ name: 'motor_queries_name_unique_index',
17
+ unique: true,
18
+ where: 'deleted_at IS NULL'
19
+ end
20
+
21
+ create_table :motor_dashboards do |t|
22
+ t.column :title, :string, null: false
23
+ t.column :description, :text
24
+ t.column :preferences, :text, null: false
25
+ t.column :author_id, :bigint
26
+ t.column :author_type, :string
27
+ t.column :deleted_at, :datetime
28
+
29
+ t.timestamps
30
+
31
+ t.index :updated_at
32
+ t.index 'title',
33
+ name: 'motor_dashboards_title_unique_index',
34
+ unique: true,
35
+ where: 'deleted_at IS NULL'
36
+ end
37
+
38
+ create_table :motor_forms do |t|
39
+ t.column :name, :string, null: false
40
+ t.column :description, :text
41
+ t.column :api_path, :text, null: false
42
+ t.column :http_method, :string, null: false
43
+ t.column :preferences, :text, null: false
44
+ t.column :author_id, :bigint
45
+ t.column :author_type, :string
46
+ t.column :deleted_at, :datetime
47
+ t.column :api_config_name, :string, null: false
48
+
49
+ t.timestamps
50
+
51
+ t.index :updated_at
52
+ t.index 'name',
53
+ name: 'motor_forms_name_unique_index',
54
+ unique: true,
55
+ where: 'deleted_at IS NULL'
56
+ end
57
+
58
+ create_table :motor_resources do |t|
59
+ t.column :name, :string, null: false, index: { unique: true }
60
+ t.column :preferences, :text, null: false
61
+
62
+ t.timestamps
63
+
64
+ t.index :updated_at
65
+ end
66
+
67
+ create_table :motor_configs do |t|
68
+ t.column :key, :string, null: false, index: { unique: true }
69
+ t.column :value, :text, null: false
70
+
71
+ t.timestamps
72
+
73
+ t.index :updated_at
74
+ end
75
+
76
+ create_table :motor_alerts do |t|
77
+ t.references :query, null: false, foreign_key: { to_table: :motor_queries }, index: true
78
+ t.column :name, :string, null: false
79
+ t.column :description, :text
80
+ t.column :to_emails, :text, null: false
81
+ t.column :is_enabled, :boolean, null: false, default: true
82
+ t.column :preferences, :text, null: false
83
+ t.column :author_id, :bigint
84
+ t.column :author_type, :string
85
+ t.column :deleted_at, :datetime
86
+
87
+ t.timestamps
88
+
89
+ t.index :updated_at
90
+ t.index 'name',
91
+ name: 'motor_alerts_name_unique_index',
92
+ unique: true,
93
+ where: 'deleted_at IS NULL'
94
+ end
95
+
96
+ create_table :motor_alert_locks do |t|
97
+ t.references :alert, null: false, foreign_key: { to_table: :motor_alerts }
98
+ t.column :lock_timestamp, :string, null: false
99
+
100
+ t.timestamps
101
+
102
+ t.index %i[alert_id lock_timestamp], unique: true
103
+ end
104
+
105
+ create_table :motor_tags do |t|
106
+ t.column :name, :string, null: false
107
+
108
+ t.timestamps
109
+
110
+ t.index 'name',
111
+ name: 'motor_tags_name_unique_index',
112
+ unique: true
113
+ end
114
+
115
+ create_table :motor_taggable_tags do |t|
116
+ t.references :tag, null: false, foreign_key: { to_table: :motor_tags }, index: true
117
+ t.column :taggable_id, :bigint, null: false
118
+ t.column :taggable_type, :string, null: false
119
+
120
+ t.index %i[taggable_id taggable_type tag_id],
121
+ name: 'motor_polymorphic_association_tag_index',
122
+ unique: true
123
+ end
124
+
125
+ create_table :motor_audits do |t|
126
+ t.column :auditable_id, :string
127
+ t.column :auditable_type, :string
128
+ t.column :associated_id, :string
129
+ t.column :associated_type, :string
130
+ t.column :user_id, :bigint
131
+ t.column :user_type, :string
132
+ t.column :username, :string
133
+ t.column :action, :string
134
+ t.column :audited_changes, :text
135
+ t.column :version, :bigint, default: 0
136
+ t.column :comment, :text
137
+ t.column :remote_address, :string
138
+ t.column :request_uuid, :string
139
+ t.column :created_at, :datetime
140
+ end
141
+
142
+ create_table :motor_api_configs do |t|
143
+ t.column :name, :string, null: false
144
+ t.column :url, :string, null: false
145
+ t.column :preferences, :text, null: false
146
+ t.column :credentials, :text, null: false
147
+ t.column :description, :text
148
+ t.column :deleted_at, :datetime
149
+
150
+ t.timestamps
151
+
152
+ t.index 'name',
153
+ name: 'motor_api_configs_name_unique_index',
154
+ unique: true,
155
+ where: 'deleted_at IS NULL'
156
+ end
157
+
158
+ create_table :motor_notes do |t|
159
+ t.column :body, :text
160
+ t.column :author_id, :bigint
161
+ t.column :author_type, :string
162
+ t.column :record_id, :string, null: false
163
+ t.column :record_type, :string, null: false
164
+ t.column :deleted_at, :datetime
165
+
166
+ t.timestamps
167
+
168
+ t.index %i[record_id record_type],
169
+ name: 'motor_notes_record_id_record_type_index'
170
+
171
+ t.index %i[author_id author_type],
172
+ name: 'motor_notes_author_id_author_type_index'
173
+ end
174
+
175
+ create_table :motor_note_tags do |t|
176
+ t.column :name, :string, null: false
177
+
178
+ t.timestamps
179
+
180
+ t.index 'name',
181
+ name: 'motor_note_tags_name_unique_index',
182
+ unique: true
183
+ end
184
+
185
+ create_table :motor_note_tag_tags do |t|
186
+ t.references :tag, null: false, foreign_key: { to_table: :motor_note_tags }, index: true
187
+ t.references :note, null: false, foreign_key: { to_table: :motor_notes }, index: false
188
+
189
+ t.index %i[note_id tag_id],
190
+ name: 'motor_note_tags_note_id_tag_id_index',
191
+ unique: true
192
+ end
193
+
194
+ create_table :motor_reminders do |t|
195
+ t.column :author_id, :bigint, null: false
196
+ t.column :author_type, :string, null: false
197
+ t.column :recipient_id, :bigint, null: false
198
+ t.column :recipient_type, :string, null: false
199
+ t.column :record_id, :string
200
+ t.column :record_type, :string
201
+ t.column :scheduled_at, :datetime, null: false, index: true
202
+
203
+ t.timestamps
204
+
205
+ t.index %i[author_id author_type],
206
+ name: 'motor_reminders_author_id_author_type_index'
207
+
208
+ t.index %i[recipient_id recipient_type],
209
+ name: 'motor_reminders_recipient_id_recipient_type_index'
210
+
211
+ t.index %i[record_id record_type],
212
+ name: 'motor_reminders_record_id_record_type_index'
213
+ end
214
+
215
+ create_table :motor_notifications do |t|
216
+ t.column :title, :string, null: false
217
+ t.column :description, :text
218
+ t.column :recipient_id, :bigint, null: false
219
+ t.column :recipient_type, :string, null: false
220
+ t.column :record_id, :string
221
+ t.column :record_type, :string
222
+ t.column :status, :string, null: false
223
+
224
+ t.timestamps
225
+
226
+ t.index %i[recipient_id recipient_type],
227
+ name: 'motor_notifications_recipient_id_recipient_type_index'
228
+
229
+ t.index %i[record_id record_type],
230
+ name: 'motor_notifications_record_id_record_type_index'
231
+ end
232
+
233
+ add_index :motor_audits, %i[auditable_type auditable_id version], name: 'motor_auditable_index'
234
+ add_index :motor_audits, %i[associated_type associated_id], name: 'motor_auditable_associated_index'
235
+ add_index :motor_audits, %i[user_id user_type], name: 'motor_auditable_user_index'
236
+ add_index :motor_audits, :request_uuid
237
+ add_index :motor_audits, :created_at
238
+
239
+ model = Class.new(ApplicationRecord)
240
+
241
+ model.table_name = 'motor_configs'
242
+
243
+ model.create!(key: 'header.links', value: [{
244
+ name: '⭐ Star on GitHub',
245
+ path: 'https://github.com/motor-admin/motor-admin-rails'
246
+ }].to_json)
247
+
248
+ model.table_name = 'motor_api_configs'
249
+
250
+ model.create!(name: 'origin', url: '/', preferences: {}, credentials: {})
251
+ end
252
+
253
+ def self.down
254
+ drop_table :motor_audits
255
+ drop_table :motor_alert_locks
256
+ drop_table :motor_alerts
257
+ drop_table :motor_forms
258
+ drop_table :motor_taggable_tags
259
+ drop_table :motor_tags
260
+ drop_table :motor_resources
261
+ drop_table :motor_configs
262
+ drop_table :motor_queries
263
+ drop_table :motor_dashboards
264
+ drop_table :motor_api_configs
265
+ drop_table :motor_note_tag_tags
266
+ drop_table :motor_note_tags
267
+ drop_table :motor_notes
268
+ drop_table :motor_notifications
269
+ drop_table :motor_reminders
270
+ end
271
+ end
@@ -0,0 +1,86 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ class MotorApiConfig < ActiveRecord::Base
3
+ self.table_name = 'motor_api_configs'
4
+
5
+ encrypts :credentials if defined?(::Motor::EncryptedConfig)
6
+
7
+ serialize :credentials, Motor::HashSerializer
8
+ serialize :preferences, Motor::HashSerializer
9
+
10
+ attribute :preferences, default: -> { HashWithIndifferentAccess.new }
11
+ attribute :credentials, default: -> { HashWithIndifferentAccess.new }
12
+ end
13
+
14
+ class MotorForm < ActiveRecord::Base
15
+ self.table_name = 'motor_forms'
16
+ end
17
+
18
+ class MotorQuery < ActiveRecord::Base
19
+ self.table_name = 'motor_queries'
20
+
21
+ serialize :preferences, Motor::HashSerializer
22
+ end
23
+
24
+ def up
25
+ create_table :motor_api_configs do |t|
26
+ t.column :name, :string, null: false
27
+ t.column :url, :string, null: false
28
+ t.column :preferences, :text, null: false
29
+ t.column :credentials, :text, null: false
30
+ t.column :description, :text
31
+ t.column :deleted_at, :datetime
32
+
33
+ t.timestamps
34
+
35
+ t.index 'name',
36
+ name: 'motor_api_configs_name_unique_index',
37
+ unique: true,
38
+ where: 'deleted_at IS NULL'
39
+ end
40
+
41
+ add_column :motor_forms, :api_config_name, :string
42
+
43
+ MotorForm.reset_column_information
44
+
45
+ MotorForm.all.each do |form|
46
+ if form.api_path.starts_with?('http')
47
+ url = form.api_path[%r{\Ahttps?://[^/]+}]
48
+
49
+ if form.preferences[:default_values_api_path].present?
50
+ form.preferences[:default_values_api_path] =
51
+ form.preferences[:default_values_api_path].delete_prefix(url).sub(/\A\/?/, '/')
52
+ end
53
+
54
+ form.update!(api_config_name: MotorApiConfig.find_or_create_by!(name: url, url: url).name,
55
+ api_path: form.api_path.delete_prefix(url).sub(/\A\/?/, '/'))
56
+ else
57
+ form.update!(api_config_name: MotorApiConfig.find_or_create_by!(name: 'origin', url: '/').name)
58
+ end
59
+ end
60
+
61
+ MotorQuery.all.each do |query|
62
+ next if query.preferences['api_path'].blank?
63
+
64
+ if query.preferences['api_path'].starts_with?('http')
65
+ url = query.preferences['api_path'][%r{\Ahttps?://[^/]+}]
66
+
67
+ query.preferences['api_path'].delete(url)
68
+
69
+ query.preferences['api_config_name'] = MotorApiConfig.find_or_create_by!(name: url, url: url).name
70
+ else
71
+ query.preferences['api_config_name'] = MotorApiConfig.find_or_create_by!(name: 'origin', url: '/').name
72
+ end
73
+
74
+ query.save!
75
+ end
76
+
77
+ change_column_null :motor_forms, :api_config_name, false
78
+
79
+ MotorApiConfig.find_or_create_by!(name: 'origin', url: '/')
80
+ end
81
+
82
+ def down
83
+ remove_column :motor_forms, :api_config_name
84
+ drop_table :motor_api_configs
85
+ end
86
+ end
@@ -0,0 +1,83 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def self.up
3
+ create_table :motor_notes do |t|
4
+ t.column :body, :text
5
+ t.column :author_id, :bigint
6
+ t.column :author_type, :string
7
+ t.column :record_id, :string, null: false
8
+ t.column :record_type, :string, null: false
9
+ t.column :deleted_at, :datetime
10
+
11
+ t.timestamps
12
+
13
+ t.index %i[author_id author_type],
14
+ name: 'motor_notes_author_id_author_type_index'
15
+ end
16
+
17
+ create_table :motor_note_tags do |t|
18
+ t.column :name, :string, null: false
19
+
20
+ t.timestamps
21
+
22
+ t.index 'name',
23
+ name: 'motor_note_tags_name_unique_index',
24
+ unique: true
25
+ end
26
+
27
+ create_table :motor_note_tag_tags do |t|
28
+ t.references :tag, null: false, foreign_key: { to_table: :motor_note_tags }, index: true
29
+ t.references :note, null: false, foreign_key: { to_table: :motor_notes }, index: false
30
+
31
+ t.index %i[note_id tag_id],
32
+ name: 'motor_note_tags_note_id_tag_id_index',
33
+ unique: true
34
+ end
35
+
36
+ create_table :motor_reminders do |t|
37
+ t.column :author_id, :bigint, null: false
38
+ t.column :author_type, :string, null: false
39
+ t.column :recipient_id, :bigint, null: false
40
+ t.column :recipient_type, :string, null: false
41
+ t.column :record_id, :string
42
+ t.column :record_type, :string
43
+ t.column :scheduled_at, :datetime, null: false, index: true
44
+
45
+ t.timestamps
46
+
47
+ t.index %i[author_id author_type],
48
+ name: 'motor_reminders_author_id_author_type_index'
49
+
50
+ t.index %i[recipient_id recipient_type],
51
+ name: 'motor_reminders_recipient_id_recipient_type_index'
52
+
53
+ t.index %i[record_id record_type],
54
+ name: 'motor_reminders_record_id_record_type_index'
55
+ end
56
+
57
+ create_table :motor_notifications do |t|
58
+ t.column :title, :string, null: false
59
+ t.column :description, :text
60
+ t.column :recipient_id, :bigint, null: false
61
+ t.column :recipient_type, :string, null: false
62
+ t.column :record_id, :string
63
+ t.column :record_type, :string
64
+ t.column :status, :string, null: false
65
+
66
+ t.timestamps
67
+
68
+ t.index %i[recipient_id recipient_type],
69
+ name: 'motor_notifications_recipient_id_recipient_type_index'
70
+
71
+ t.index %i[record_id record_type],
72
+ name: 'motor_notifications_record_id_record_type_index'
73
+ end
74
+ end
75
+
76
+ def self.down
77
+ drop_table :motor_note_tag_tags
78
+ drop_table :motor_note_tags
79
+ drop_table :motor_notes
80
+ drop_table :motor_notifications
81
+ drop_table :motor_reminders
82
+ end
83
+ end
@@ -0,0 +1,71 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ class MotorApiConfig < ActiveRecord::Base
3
+ self.table_name = 'motor_api_configs'
4
+
5
+ encrypts :credentials if defined?(::Motor::EncryptedConfig)
6
+
7
+ serialize :credentials, Motor::HashSerializer
8
+ serialize :preferences, Motor::HashSerializer
9
+
10
+ attribute :preferences, default: -> { HashWithIndifferentAccess.new }
11
+ attribute :credentials, default: -> { HashWithIndifferentAccess.new }
12
+ end
13
+
14
+ class MotorForm < ActiveRecord::Base
15
+ self.table_name = 'motor_forms'
16
+
17
+ serialize :preferences, Motor::HashSerializer
18
+ end
19
+
20
+ class MotorResource < ActiveRecord::Base
21
+ self.table_name = 'motor_resources'
22
+
23
+ serialize :preferences, Motor::HashSerializer
24
+ end
25
+
26
+ def up
27
+ MotorResource.all.each do |resource|
28
+ resource.preferences.fetch(:actions, []).each do |action|
29
+ next unless action[:action_type] == 'api'
30
+
31
+ api_path = action[:preferences][:api_path]
32
+ api_url = api_path[%r{\Ahttps?://[^/]+}]
33
+ api_path = api_path.delete_prefix(api_url).sub(/\A\/?/, '/') if api_url
34
+
35
+ api_config =
36
+ if api_url
37
+ MotorApiConfig.create_with(url: api_url).find_or_create_by!(name: api_url.sub(%r{\Ahttps?://}))
38
+ else
39
+ MotorApiConfig.create_with(url: '/').find_or_create_by!(name: 'origin')
40
+ end
41
+
42
+ resource_display_name = (resource[:preferences][:display_name] || resource.name).titleize.singularize
43
+
44
+ form = MotorForm.create_with(
45
+ api_config_name: api_config.name,
46
+ api_path: api_path.sub(/\{{1,2}\w+\}{1,2}/, '{{id}}'),
47
+ http_method: 'POST',
48
+ preferences: {
49
+ fields: [{
50
+ name: 'id',
51
+ display_name: resource_display_name,
52
+ default_value: '',
53
+ field_type: 'reference',
54
+ reference: { model_name: resource.name },
55
+ validators: [{ required: true }]
56
+ }]
57
+ }
58
+ ).find_or_create_by!(
59
+ name: "#{action[:display_name]} #{resource_display_name}"
60
+ )
61
+
62
+ action[:action_type] = 'form'
63
+ action[:preferences] = { form_id: form.id }
64
+ end
65
+
66
+ resource.save!
67
+ end
68
+ end
69
+
70
+ def down; end
71
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/migration'
5
+ require 'active_record'
6
+ require 'rails/generators/active_record'
7
+ require 'generators/motor/migration'
8
+
9
+ module Motor
10
+ module Generators
11
+ class UpgradeGenerator < Rails::Generators::Base
12
+ include Rails::Generators::Migration
13
+ extend Motor::Generators::Migration
14
+
15
+ source_root File.expand_path('templates', __dir__)
16
+
17
+ def copy_migration
18
+ unless Motor::ApiConfig.table_exists?
19
+ migration_template 'install_api_configs.rb', 'db/migrate/install_motor_api_configs.rb'
20
+ end
21
+
22
+ if with_api_actions?
23
+ migration_template 'upgrade_motor_api_actions.rb', 'db/migrate/upgrade_motor_api_actions.rb'
24
+ end
25
+
26
+ migration_template 'install_notes.rb', 'db/migrate/install_motor_notes.rb' unless Motor::Note.table_exists?
27
+
28
+ if Motor::ApiConfig.table_exists? && !with_api_actions? && Motor::Note.table_exists?
29
+ puts 'The latest Motor Admin features are already configured'
30
+ else
31
+ puts 'Run `rake db:migrate` to update DB schema'
32
+ end
33
+ end
34
+
35
+ def with_api_actions?
36
+ @with_api_actions ||=
37
+ Motor::Resource.all.any? do |resource|
38
+ resource.preferences[:actions]&.any? { |action| action[:action_type] == 'api' }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(ActionText::Attribute)
4
+ ActionText::Attribute::ClassMethods.prepend(Module.new do
5
+ # rubocop:disable Naming/PredicateName
6
+ def has_rich_text(*args)
7
+ super
8
+
9
+ name = args.first
10
+
11
+ alias_method :"#{name}_body=", :"#{name}="
12
+
13
+ define_method(:"#{name}_body") do
14
+ send(name).body&.to_trix_html
15
+ end
16
+ end
17
+ # rubocop:enable Naming/PredicateName
18
+ end)
19
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'active_record/connection_adapters/deduplicable'
5
+ rescue LoadError
6
+ nil
7
+ end
8
+
9
+ ActiveRecord::ConnectionAdapters::Column.class_eval do
10
+ def array
11
+ false
12
+ end
13
+ alias_method :array?, :array
14
+ end