motor-admin 0.1.36 → 0.1.42

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/motor/alerts_controller.rb +12 -6
  3. data/app/controllers/motor/configs_controller.rb +1 -0
  4. data/app/controllers/motor/dashboards_controller.rb +4 -0
  5. data/app/controllers/motor/forms_controller.rb +4 -0
  6. data/app/controllers/motor/queries_controller.rb +4 -0
  7. data/app/controllers/motor/resources_controller.rb +1 -0
  8. data/app/controllers/motor/ui_controller.rb +4 -0
  9. data/app/models/motor/alert.rb +3 -3
  10. data/app/models/motor/application_record.rb +10 -0
  11. data/app/models/motor/config.rb +1 -1
  12. data/app/models/motor/dashboard.rb +2 -2
  13. data/app/models/motor/form.rb +2 -2
  14. data/app/models/motor/query.rb +3 -2
  15. data/app/models/motor/resource.rb +1 -1
  16. data/app/views/motor/ui/show.html.erb +1 -1
  17. data/lib/generators/motor/templates/install.rb +13 -13
  18. data/lib/motor.rb +11 -4
  19. data/lib/motor/active_record_utils/defined_scopes_extension.rb +1 -1
  20. data/lib/motor/admin.rb +8 -0
  21. data/lib/motor/alerts/persistance.rb +17 -3
  22. data/lib/motor/alerts/scheduler.rb +1 -1
  23. data/lib/motor/api_query/apply_scope.rb +12 -5
  24. data/lib/motor/api_query/sort.rb +1 -1
  25. data/lib/motor/build_schema.rb +3 -3
  26. data/lib/motor/build_schema/find_display_column.rb +31 -29
  27. data/lib/motor/build_schema/load_from_rails.rb +18 -9
  28. data/lib/motor/build_schema/merge_schema_configs.rb +8 -4
  29. data/lib/motor/build_schema/reorder_schema.rb +10 -4
  30. data/lib/motor/configs.rb +17 -0
  31. data/lib/motor/configs/build_configs_hash.rb +83 -0
  32. data/lib/motor/configs/build_ui_app_tag.rb +71 -0
  33. data/lib/motor/configs/load_from_cache.rb +81 -0
  34. data/lib/motor/configs/sync_from_file.rb +36 -0
  35. data/lib/motor/configs/sync_from_hash.rb +126 -0
  36. data/lib/motor/configs/sync_middleware.rb +72 -0
  37. data/lib/motor/configs/sync_with_remote.rb +47 -0
  38. data/lib/motor/configs/write_to_file.rb +36 -0
  39. data/lib/motor/dashboards/persistance.rb +15 -5
  40. data/lib/motor/forms/persistance.rb +15 -5
  41. data/lib/motor/net_http_utils.rb +38 -0
  42. data/lib/motor/queries/persistance.rb +13 -3
  43. data/lib/motor/railtie.rb +11 -0
  44. data/lib/motor/tasks/motor.rake +37 -0
  45. data/lib/motor/version.rb +1 -1
  46. data/ui/dist/{main-358ea31cd7020f915067.css.gz → main-05401628fabd32884fa6.css.gz} +0 -0
  47. data/ui/dist/main-05401628fabd32884fa6.js.gz +0 -0
  48. data/ui/dist/manifest.json +5 -5
  49. metadata +16 -6
  50. data/lib/motor/audited_utils.rb +0 -15
  51. data/lib/motor/ui_configs.rb +0 -82
  52. data/ui/dist/main-358ea31cd7020f915067.js.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e0174dc9b889d34d1cff62947e5f330d04c37a8eea6a1036b88a5735edc3b9c
4
- data.tar.gz: 84136e87872e4bd988055090e602e831f85516286f4dc39b9c15cd635feb5c03
3
+ metadata.gz: 6b5c8de183eb4dca0deba15c13f4e17a5cd4b6042ba2aa72e69e4056f0dd07bb
4
+ data.tar.gz: 5696598a4d1a461fb401b6bd6b9036dbe8ac8d31ce71d8e19edabb0e68b4fa91
5
5
  SHA512:
6
- metadata.gz: 8d637a2d8b014e7c57c6e77b92c9c62c96ccb3a6201173e455122ab1c9f0d0cfe5070380712ce5618bf9975a225d5622336bd4e16ed1f33d689d9f340dcaf9e4
7
- data.tar.gz: 241c173529982aa8403691eb0818f8cf5357a61ae1b7820caca288a7d91faf9f1aa00485c1a716df266777de9bac37b2da36700ed04d0463b98f05299dff8cb9
6
+ metadata.gz: 05e81845c5be4540e7062b945b7ca21a51c197a6c540da1ce747fc478f8105e4e80b375bcf708a1e2b634fffe732c6024fa0626a77baaddfc99eb8bdbdcc6d4e
7
+ data.tar.gz: 581692e4333bdcde696190897b810206cc7cc222d8a82796d8ba098130b76801b843e6a72b791ba0b8a1aca1686ed88cb14c5c0161953f21273628ae811c55c5
@@ -18,12 +18,15 @@ module Motor
18
18
  end
19
19
 
20
20
  def create
21
- ApplicationRecord.transaction { @alert.save! }
22
- Motor::Alerts::ScheduledAlertsCache.clear
23
-
24
- render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
25
- rescue Motor::Alerts::Persistance::NameAlreadyExists
26
- name_already_exists_response
21
+ if Motor::Alerts::Persistance.name_already_exists?(@alert)
22
+ name_already_exists_response
23
+ else
24
+ ApplicationRecord.transaction { @alert.save! }
25
+ Motor::Alerts::ScheduledAlertsCache.clear
26
+ Motor::Configs::WriteToFile.call
27
+
28
+ render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
29
+ end
27
30
  rescue Motor::Alerts::Persistance::InvalidInterval
28
31
  invalid_interval_response
29
32
  end
@@ -31,6 +34,7 @@ module Motor
31
34
  def update
32
35
  Motor::Alerts::Persistance.update_from_params!(@alert, alert_params)
33
36
  Motor::Alerts::ScheduledAlertsCache.clear
37
+ Motor::Configs::WriteToFile.call
34
38
 
35
39
  render json: { data: Motor::ApiQuery::BuildJson.call(@alert, params) }
36
40
  rescue Motor::Alerts::Persistance::NameAlreadyExists
@@ -42,6 +46,8 @@ module Motor
42
46
  def destroy
43
47
  @alert.update!(deleted_at: Time.current)
44
48
 
49
+ Motor::Configs::WriteToFile.call
50
+
45
51
  head :ok
46
52
  end
47
53
 
@@ -17,6 +17,7 @@ module Motor
17
17
  end
18
18
 
19
19
  @config.save!
20
+ Motor::Configs::WriteToFile.call
20
21
 
21
22
  render json: { data: Motor::ApiQuery::BuildJson.call(@config, params) }
22
23
  rescue ActiveRecord::RecordNotUnique
@@ -22,6 +22,7 @@ module Motor
22
22
  render json: { errors: [{ source: 'title', detail: 'Title already exists' }] }, status: :unprocessable_entity
23
23
  else
24
24
  ApplicationRecord.transaction { @dashboard.save! }
25
+ Motor::Configs::WriteToFile.call
25
26
 
26
27
  render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params) }
27
28
  end
@@ -31,6 +32,7 @@ module Motor
31
32
 
32
33
  def update
33
34
  Motor::Dashboards::Persistance.update_from_params!(@dashboard, dashboard_params)
35
+ Motor::Configs::WriteToFile.call
34
36
 
35
37
  render json: { data: Motor::ApiQuery::BuildJson.call(@dashboard, params) }
36
38
  rescue Motor::Dashboards::Persistance::TitleAlreadyExists
@@ -40,6 +42,8 @@ module Motor
40
42
  def destroy
41
43
  @dashboard.update!(deleted_at: Time.current)
42
44
 
45
+ Motor::Configs::WriteToFile.call
46
+
43
47
  head :ok
44
48
  end
45
49
 
@@ -22,6 +22,7 @@ module Motor
22
22
  render json: { errors: [{ source: 'name', detail: 'Name already exists' }] }, status: :unprocessable_entity
23
23
  else
24
24
  ApplicationRecord.transaction { @form.save! }
25
+ Motor::Configs::WriteToFile.call
25
26
 
26
27
  render json: { data: Motor::ApiQuery::BuildJson.call(@form, params) }
27
28
  end
@@ -31,6 +32,7 @@ module Motor
31
32
 
32
33
  def update
33
34
  Motor::Forms::Persistance.update_from_params!(@form, form_params)
35
+ Motor::Configs::WriteToFile.call
34
36
 
35
37
  render json: { data: Motor::ApiQuery::BuildJson.call(@form, params) }
36
38
  rescue Motor::Forms::Persistance::NameAlreadyExists
@@ -40,6 +42,8 @@ module Motor
40
42
  def destroy
41
43
  @form.update!(deleted_at: Time.current)
42
44
 
45
+ Motor::Configs::WriteToFile.call
46
+
43
47
  head :ok
44
48
  end
45
49
 
@@ -22,6 +22,7 @@ module Motor
22
22
  render json: { errors: [{ source: 'name', detail: 'Name already exists' }] }, status: :unprocessable_entity
23
23
  else
24
24
  ApplicationRecord.transaction { @query.save! }
25
+ Motor::Configs::WriteToFile.call
25
26
 
26
27
  render json: { data: Motor::ApiQuery::BuildJson.call(@query, params) }
27
28
  end
@@ -31,6 +32,7 @@ module Motor
31
32
 
32
33
  def update
33
34
  Motor::Queries::Persistance.update_from_params!(@query, query_params)
35
+ Motor::Configs::WriteToFile.call
34
36
 
35
37
  render json: { data: Motor::ApiQuery::BuildJson.call(@query, params) }
36
38
  rescue Motor::Queries::Persistance::NameAlreadyExists
@@ -40,6 +42,8 @@ module Motor
40
42
  def destroy
41
43
  @query.update!(deleted_at: Time.current)
42
44
 
45
+ Motor::Configs::WriteToFile.call
46
+
43
47
  head :ok
44
48
  end
45
49
 
@@ -12,6 +12,7 @@ module Motor
12
12
 
13
13
  def create
14
14
  Motor::BuildSchema::PersistResourceConfigs.call(@resource)
15
+ Motor::Configs::WriteToFile.call
15
16
 
16
17
  render json: { data: Motor::ApiQuery::BuildJson.call(@resource, params) }
17
18
  end
@@ -7,12 +7,16 @@ module Motor
7
7
  def index
8
8
  Motor.reload! if Motor.development?
9
9
 
10
+ Motor::Configs::SyncFromFile.call
11
+
10
12
  render :show
11
13
  end
12
14
 
13
15
  def show
14
16
  Motor.reload! if Motor.development?
15
17
 
18
+ Motor::Configs::SyncFromFile.call
19
+
16
20
  render :show
17
21
  end
18
22
  end
@@ -2,13 +2,13 @@
2
2
 
3
3
  module Motor
4
4
  class Alert < ::Motor::ApplicationRecord
5
- AuditedUtils.with_audit_class(Motor::Audit) { audited }
5
+ audited
6
6
 
7
7
  belongs_to :query
8
8
  belongs_to :author, polymorphic: true, optional: true
9
9
 
10
- has_many :alert_locks
11
- has_many :taggable_tags, as: :taggable
10
+ has_many :alert_locks, dependent: :destroy
11
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
12
12
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
13
13
 
14
14
  serialize :preferences, HashSerializer
@@ -4,5 +4,15 @@ module Motor
4
4
  class ApplicationRecord < ActiveRecord::Base
5
5
  self.abstract_class = true
6
6
  self.table_name_prefix = 'motor_'
7
+
8
+ def self.audited(*args)
9
+ default_class = Audited.audit_class
10
+
11
+ Audited.audit_class = Motor::Audit
12
+
13
+ super
14
+ ensure
15
+ Audited.audit_class = default_class
16
+ end
7
17
  end
8
18
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Motor
4
4
  class Config < ::Motor::ApplicationRecord
5
- AuditedUtils.with_audit_class(Motor::Audit) { audited }
5
+ audited
6
6
 
7
7
  serialize :value, HashSerializer
8
8
  end
@@ -2,11 +2,11 @@
2
2
 
3
3
  module Motor
4
4
  class Dashboard < ::Motor::ApplicationRecord
5
- AuditedUtils.with_audit_class(Motor::Audit) { audited }
5
+ audited
6
6
 
7
7
  belongs_to :author, polymorphic: true, optional: true
8
8
 
9
- has_many :taggable_tags, as: :taggable
9
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
10
10
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
11
11
 
12
12
  serialize :preferences, HashSerializer
@@ -2,11 +2,11 @@
2
2
 
3
3
  module Motor
4
4
  class Form < ::Motor::ApplicationRecord
5
- AuditedUtils.with_audit_class(Motor::Audit) { audited }
5
+ audited
6
6
 
7
7
  belongs_to :author, polymorphic: true, optional: true
8
8
 
9
- has_many :taggable_tags, as: :taggable
9
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
10
10
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
11
11
 
12
12
  serialize :preferences, HashSerializer
@@ -2,12 +2,13 @@
2
2
 
3
3
  module Motor
4
4
  class Query < ::Motor::ApplicationRecord
5
- AuditedUtils.with_audit_class(Motor::Audit) { audited }
5
+ audited
6
6
 
7
7
  belongs_to :author, polymorphic: true, optional: true
8
8
 
9
- has_many :taggable_tags, as: :taggable
9
+ has_many :taggable_tags, as: :taggable, dependent: :destroy
10
10
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
11
+ has_many :alerts, dependent: :destroy
11
12
 
12
13
  serialize :preferences, HashSerializer
13
14
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Motor
4
4
  class Resource < ::Motor::ApplicationRecord
5
- AuditedUtils.with_audit_class(Motor::Audit) { audited }
5
+ audited
6
6
 
7
7
  serialize :preferences, HashSerializer
8
8
  end
@@ -1 +1 @@
1
- <%= raw(Motor::UiConfigs.app_tag) %>
1
+ <%= raw(Motor::Configs::BuildUiAppTag.call) %>
@@ -1,6 +1,6 @@
1
1
  class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
2
  def self.up
3
- create_table :motor_queries, force: true do |t|
3
+ create_table :motor_queries do |t|
4
4
  t.column :name, :string, null: false
5
5
  t.column :description, :string
6
6
  t.column :sql_body, :string, null: false
@@ -18,7 +18,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
18
18
  where: 'deleted_at IS NULL'
19
19
  end
20
20
 
21
- create_table :motor_dashboards, force: true do |t|
21
+ create_table :motor_dashboards do |t|
22
22
  t.column :title, :string, null: false
23
23
  t.column :description, :string
24
24
  t.column :preferences, :string, null: false, default: '{}'
@@ -35,7 +35,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
35
35
  where: 'deleted_at IS NULL'
36
36
  end
37
37
 
38
- create_table :motor_forms, force: true do |t|
38
+ create_table :motor_forms do |t|
39
39
  t.column :name, :string, null: false
40
40
  t.column :description, :string
41
41
  t.column :api_path, :string, null: false
@@ -54,7 +54,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
54
54
  where: 'deleted_at IS NULL'
55
55
  end
56
56
 
57
- create_table :motor_resources, force: true do |t|
57
+ create_table :motor_resources do |t|
58
58
  t.column :name, :string, null: false, index: { unique: true }
59
59
  t.column :preferences, :string, null: false, default: '{}'
60
60
 
@@ -63,7 +63,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
63
63
  t.index :updated_at
64
64
  end
65
65
 
66
- create_table :motor_configs, force: true do |t|
66
+ create_table :motor_configs do |t|
67
67
  t.column :key, :string, null: false, index: { unique: true }
68
68
  t.column :value, :string, null: false, default: '{}'
69
69
 
@@ -72,7 +72,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
72
72
  t.index :updated_at
73
73
  end
74
74
 
75
- create_table :motor_alerts, force: true do |t|
75
+ create_table :motor_alerts do |t|
76
76
  t.references :query, null: false, foreign_key: { to_table: :motor_queries }, index: true
77
77
  t.column :name, :string, null: false
78
78
  t.column :description, :string
@@ -92,7 +92,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
92
92
  where: 'deleted_at IS NULL'
93
93
  end
94
94
 
95
- create_table :motor_alert_locks, force: true do |t|
95
+ create_table :motor_alert_locks do |t|
96
96
  t.references :alert, null: false, foreign_key: { to_table: :motor_alerts }
97
97
  t.column :lock_timestamp, :string, null: false
98
98
 
@@ -101,7 +101,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
101
101
  t.index %i[alert_id lock_timestamp], unique: true
102
102
  end
103
103
 
104
- create_table :motor_tags, force: true do |t|
104
+ create_table :motor_tags do |t|
105
105
  t.column :name, :string, null: false
106
106
 
107
107
  t.timestamps
@@ -111,7 +111,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
111
111
  unique: true
112
112
  end
113
113
 
114
- create_table :motor_taggable_tags, force: true do |t|
114
+ create_table :motor_taggable_tags do |t|
115
115
  t.references :tag, null: false, foreign_key: { to_table: :motor_tags }, index: true
116
116
  t.column :taggable_id, :integer, null: false
117
117
  t.column :taggable_type, :string, null: false
@@ -121,7 +121,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
121
121
  unique: true
122
122
  end
123
123
 
124
- create_table :motor_audits, force: true do |t|
124
+ create_table :motor_audits do |t|
125
125
  t.column :auditable_id, :integer
126
126
  t.column :auditable_type, :string
127
127
  t.column :associated_id, :integer
@@ -138,9 +138,9 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
138
138
  t.column :created_at, :datetime
139
139
  end
140
140
 
141
- add_index :motor_audits, %i[auditable_type auditable_id version], name: 'auditable_index'
142
- add_index :motor_audits, %i[associated_type associated_id], name: 'associated_index'
143
- add_index :motor_audits, %i[user_id user_type], name: 'user_index'
141
+ add_index :motor_audits, %i[auditable_type auditable_id version], name: 'motor_auditable_index'
142
+ add_index :motor_audits, %i[associated_type associated_id], name: 'motor_auditable_associated_index'
143
+ add_index :motor_audits, %i[user_id user_type], name: 'motor_auditable_user_index'
144
144
  add_index :motor_audits, :request_uuid
145
145
  add_index :motor_audits, :created_at
146
146
  end
data/lib/motor.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'concurrent/executor/fixed_thread_pool'
4
+ require 'concurrent/timer_task'
3
5
  require 'cancancan'
4
6
  require 'ar_lazy_preload'
5
7
  require 'js_regex'
@@ -7,6 +9,9 @@ require 'fugit'
7
9
  require 'csv'
8
10
  require 'active_record/filter'
9
11
  require 'audited'
12
+ require 'uri'
13
+ require 'net/http'
14
+ require 'net/https'
10
15
 
11
16
  module Motor
12
17
  PATH = Pathname.new(__dir__)
@@ -18,7 +23,8 @@ module Motor
18
23
  Dir[PATH.join('./motor/**/*.rb')].each do |f|
19
24
  next if f.ends_with?('alerts/scheduler.rb')
20
25
  next if f.ends_with?('alerts/scheduled_alerts_cache.rb')
21
- next if f.ends_with?('ui_configs.rb')
26
+ next if f.ends_with?('configs/load_from_cache.rb')
27
+ next if f.ends_with?('configs/sync_from_file.rb')
22
28
 
23
29
  load f
24
30
  end
@@ -46,15 +52,16 @@ end
46
52
 
47
53
  require 'motor/version'
48
54
  require 'motor/admin'
49
- require 'motor/audited_utils'
50
55
  require 'motor/assets'
56
+ require 'motor/active_record_utils'
51
57
  require 'motor/build_schema'
52
58
  require 'motor/api_query'
53
59
  require 'motor/tags'
54
- require 'motor/ui_configs'
60
+ require 'motor/configs'
55
61
  require 'motor/queries'
56
62
  require 'motor/dashboards'
57
63
  require 'motor/forms'
58
64
  require 'motor/alerts'
59
65
  require 'motor/hash_serializer'
60
- require 'motor/active_record_utils'
66
+ require 'motor/net_http_utils'
67
+ require 'motor/railtie'
@@ -4,7 +4,7 @@ module Motor
4
4
  module ActiveRecordUtils
5
5
  module DefinedScopesExtension
6
6
  def scope(name, _body)
7
- (@__scopes__ ||= []) << name
7
+ (@__scopes__ ||= []) << name.to_sym
8
8
 
9
9
  super
10
10
  end
data/lib/motor/admin.rb CHANGED
@@ -28,6 +28,14 @@ module Motor
28
28
  end
29
29
  end
30
30
 
31
+ initializer 'motor.configs.sync_middleware' do
32
+ next if Motor::Configs::SYNC_ACCESS_KEY.blank?
33
+
34
+ require 'motor/configs/sync_middleware'
35
+
36
+ Rails.application.config.middleware.insert_after(Rails::Rack::Logger, Motor::Configs::SyncMiddleware)
37
+ end
38
+
31
39
  initializer 'motor.filter_params' do
32
40
  Rails.application.config.filter_parameters += %i[io]
33
41
  end
@@ -43,30 +43,44 @@ module Motor
43
43
  retry
44
44
  end
45
45
 
46
- def update_from_params!(alert, params)
46
+ def update_from_params!(alert, params, force_replace: false)
47
+ tag_ids = alert.tags.ids
48
+
47
49
  alert = assign_attributes(alert, params)
48
50
 
49
- raise NameAlreadyExists if name_already_exists?(alert)
51
+ raise NameAlreadyExists if !force_replace && name_already_exists?(alert)
50
52
  raise InvalidInterval unless alert.cron
51
53
 
52
54
  ApplicationRecord.transaction do
55
+ archive_with_existing_name(alert) if force_replace
56
+
53
57
  alert.save!
54
58
  end
55
59
 
56
- alert.tags.reload
60
+ alert.touch if tags_changed?(tag_ids, alert) && params[:updated_at].blank?
57
61
 
58
62
  alert
59
63
  rescue ActiveRecord::RecordNotUnique
60
64
  retry
61
65
  end
62
66
 
67
+ def tags_changed?(previous_ids, alert)
68
+ previous_ids.sort != alert.tags.reload.ids.sort
69
+ end
70
+
63
71
  def assign_attributes(alert, params)
64
72
  alert.assign_attributes(params.slice(*ALERT_ATTRIBUTES))
65
73
  alert.preferences[:interval] = normalize_interval(alert.preferences[:interval])
74
+ alert.updated_at = [params[:updated_at], Time.current].min if params[:updated_at].present?
66
75
 
67
76
  Motor::Tags.assign_tags(alert, params[:tags])
68
77
  end
69
78
 
79
+ def archive_with_existing_name(alert)
80
+ Motor::Alert.where(['lower(name) = ? AND id != ?', alert.name.to_s.downcase, alert.id])
81
+ .update_all(deleted_at: Time.current)
82
+ end
83
+
70
84
  def normalize_interval(interval)
71
85
  interval.to_s.gsub(NORMALIZE_INTERVAL_REGEXP, 'every ')
72
86
  end