motor-admin 0.3.17 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/app/channels/motor/application_cable/channel.rb +14 -0
  3. data/app/channels/motor/application_cable/connection.rb +27 -0
  4. data/app/channels/motor/notes_channel.rb +9 -0
  5. data/app/channels/motor/notifications_channel.rb +9 -0
  6. data/app/controllers/concerns/motor/current_user_method.rb +2 -0
  7. data/app/controllers/motor/note_tags_controller.rb +13 -0
  8. data/app/controllers/motor/notes_controller.rb +58 -0
  9. data/app/controllers/motor/notifications_controller.rb +33 -0
  10. data/app/controllers/motor/reminders_controller.rb +38 -0
  11. data/app/controllers/motor/run_queries_controller.rb +1 -1
  12. data/app/controllers/motor/send_alerts_controller.rb +2 -2
  13. data/app/controllers/motor/slack_conversations_controller.rb +11 -0
  14. data/app/controllers/motor/tags_controller.rb +1 -1
  15. data/app/controllers/motor/ui_controller.rb +9 -1
  16. data/app/controllers/motor/users_for_autocomplete_controller.rb +23 -0
  17. data/app/jobs/motor/alert_sending_job.rb +1 -1
  18. data/app/jobs/motor/notify_note_mentions_job.rb +9 -0
  19. data/app/jobs/motor/notify_reminder_job.rb +9 -0
  20. data/app/mailers/motor/alerts_mailer.rb +6 -29
  21. data/app/mailers/motor/application_mailer.rb +27 -1
  22. data/app/mailers/motor/notifications_mailer.rb +33 -0
  23. data/app/models/motor/note.rb +18 -0
  24. data/app/models/motor/note_tag.rb +7 -0
  25. data/app/models/motor/note_tag_tag.rb +8 -0
  26. data/app/models/motor/notification.rb +14 -0
  27. data/app/models/motor/reminder.rb +13 -0
  28. data/app/views/layouts/motor/application.html.erb +4 -1
  29. data/app/views/layouts/motor/mailer.html.erb +72 -0
  30. data/app/views/motor/alerts_mailer/alert_email.html.erb +52 -124
  31. data/app/views/motor/notifications_mailer/notify_mention_email.html.erb +28 -0
  32. data/app/views/motor/notifications_mailer/notify_reminder_email.html.erb +28 -0
  33. data/config/locales/el.yml +25 -0
  34. data/config/locales/en.yml +33 -2
  35. data/config/locales/es.yml +33 -2
  36. data/config/locales/pt.yml +33 -2
  37. data/config/routes.rb +9 -0
  38. data/lib/generators/motor/install_notes_generator.rb +22 -0
  39. data/lib/generators/motor/templates/install.rb +77 -0
  40. data/lib/generators/motor/templates/install_notes.rb +83 -0
  41. data/lib/generators/motor/upgrade_generator.rb +13 -6
  42. data/lib/motor/admin.rb +13 -1
  43. data/lib/motor/alerts/slack_sender.rb +74 -0
  44. data/lib/motor/alerts.rb +42 -0
  45. data/lib/motor/api_query/apply_scope.rb +1 -0
  46. data/lib/motor/build_schema/apply_permissions.rb +8 -0
  47. data/lib/motor/build_schema/defaults.rb +15 -1
  48. data/lib/motor/build_schema/load_from_rails.rb +4 -1
  49. data/lib/motor/build_schema.rb +7 -0
  50. data/lib/motor/configs/build_ui_app_tag.rb +73 -8
  51. data/lib/motor/configs.rb +3 -4
  52. data/lib/motor/notes/notify_mentions.rb +73 -0
  53. data/lib/motor/notes/notify_reminder.rb +49 -0
  54. data/lib/motor/notes/persist.rb +36 -0
  55. data/lib/motor/notes/reminders_scheduler.rb +39 -0
  56. data/lib/motor/notes/tags.rb +34 -0
  57. data/lib/motor/notes.rb +12 -0
  58. data/lib/motor/queries/run_query.rb +66 -3
  59. data/lib/motor/resources/fetch_configured_model.rb +19 -3
  60. data/lib/motor/resources.rb +1 -1
  61. data/lib/motor/slack/client.rb +62 -0
  62. data/lib/motor/slack.rb +16 -0
  63. data/lib/motor/version.rb +1 -1
  64. data/lib/motor.rb +19 -0
  65. data/ui/dist/{main-726aa7f6805676af4d21.css.gz → main-99bab2664944ee03d10f.css.gz} +0 -0
  66. data/ui/dist/main-99bab2664944ee03d10f.js.gz +0 -0
  67. data/ui/dist/manifest.json +5 -5
  68. metadata +36 -4
  69. data/ui/dist/main-726aa7f6805676af4d21.js.gz +0 -0
@@ -14,6 +14,13 @@ module Motor
14
14
 
15
15
  RESERVED_VARIABLES = %w[current_user_id current_user_email].freeze
16
16
 
17
+ DATABASE_URL_VARIABLE_SUFFIX = '_database_url'
18
+
19
+ DB_LINK_VALIDATE_REGEXP = /(.*?)\s*\{\{\s*\w+_database_url\s*\}\}/i.freeze
20
+
21
+ UnknownDatabase = Class.new(StandardError)
22
+ UnsafeDatabaseUrlUsage = Class.new(StandardError)
23
+
17
24
  module_function
18
25
 
19
26
  # @param query [Motor::Query]
@@ -23,6 +30,7 @@ module Motor
23
30
  # @return [Motor::Queries::RunQuery::QueryResult]
24
31
  def call!(query, variables_hash: nil, limit: nil, filters: nil)
25
32
  variables_hash ||= {}
33
+ variables_hash = variables_hash.with_indifferent_access
26
34
  limit ||= DEFAULT_LIMIT
27
35
  filters ||= {}
28
36
 
@@ -54,6 +62,9 @@ module Motor
54
62
  # @return [ActiveRecord::Result]
55
63
  def execute_query(query, limit, variables_hash, filters)
56
64
  result = nil
65
+
66
+ connection_class = fetch_connection_class(query)
67
+
57
68
  statement = prepare_sql_statement(connection_class, query, limit, variables_hash, filters)
58
69
 
59
70
  connection_class.transaction do
@@ -73,6 +84,12 @@ module Motor
73
84
  result
74
85
  end
75
86
 
87
+ def validate_query!(sql)
88
+ return if sql.scan(DB_LINK_VALIDATE_REGEXP).flatten.all? { |line| line.ends_with?('dblink(') }
89
+
90
+ raise UnsafeDatabaseUrlUsage, 'Database URL variable is allowed only with dblink'
91
+ end
92
+
76
93
  # @param result [ActiveRecord::Result]
77
94
  # @return [Hash]
78
95
  def build_columns_hash(result)
@@ -131,6 +148,8 @@ module Motor
131
148
  def prepare_sql_statement(connection_class, query, limit, variables_hash, filters)
132
149
  variables = merge_variable_default_values(query.preferences.fetch(:variables, []), variables_hash)
133
150
 
151
+ validate_query!(query.sql_body)
152
+
134
153
  sql, query_variables = RenderSqlTemplate.call(query.sql_body, variables)
135
154
  select_sql = build_select_sql(connection_class, sql, limit, filters)
136
155
 
@@ -177,6 +196,8 @@ module Motor
177
196
  def build_statement_attributes(variables)
178
197
  variables.map do |variable_name, value|
179
198
  [value].flatten.map do |val|
199
+ val = fetch_variable_database_url(variable_name) if variable_name.ends_with?(DATABASE_URL_VARIABLE_SUFFIX)
200
+
180
201
  ActiveRecord::Relation::QueryAttribute.new(
181
202
  variable_name,
182
203
  val,
@@ -186,6 +207,14 @@ module Motor
186
207
  end.flatten
187
208
  end
188
209
 
210
+ def fetch_variable_database_url(variable_name)
211
+ class_name = variable_name.delete_suffix(DATABASE_URL_VARIABLE_SUFFIX).classify
212
+
213
+ Motor::DatabaseClasses.const_get(class_name).connection_db_config.url
214
+ rescue NameError
215
+ raise UnknownDatabase, "#{class_name} database is not defined"
216
+ end
217
+
189
218
  # @param array [Array]
190
219
  # @return [Array]
191
220
  def normalize_statement_for_sql(statement)
@@ -213,9 +242,43 @@ module Motor
213
242
  end
214
243
  end
215
244
 
216
- def connection_class
217
- @connection_class ||=
218
- 'ResourceRecord'.safe_constantize ||
245
+ def fetch_connection_class(query)
246
+ database_name = query.preferences[:database]
247
+
248
+ return default_connection_class if database_name.blank? || database_name == 'default'
249
+
250
+ return default_connection_class if database_name == 'primary'
251
+
252
+ ar_configurations = ActiveRecord::Base.configurations.configurations
253
+ .find { |c| c.name == database_name && c.env_name == Rails.env }
254
+
255
+ if ar_configurations
256
+ fetch_ar_configurations_connection(database_name, ar_configurations)
257
+ else
258
+ Motor::DatabaseClasses.const_get(database_name.sub(/\A\d+/, '').parameterize.underscore.classify)
259
+ end
260
+ end
261
+
262
+ def fetch_ar_configurations_connection(database_name, ar_configurations)
263
+ Motor::DatabaseClasses.const_get(database_name.classify)
264
+ rescue NameError
265
+ klass = Class.new(ActiveRecord::Base)
266
+
267
+ Motor::DatabaseClasses.const_set(database_name.classify, klass)
268
+
269
+ klass.establish_connection(ar_configurations.name.to_sym)
270
+
271
+ klass
272
+ end
273
+
274
+ def find_connection_in_pool(database_name)
275
+ ActiveRecord::Base.connection_pool.connections.find do |conn|
276
+ conn.pool.db_config.name == database_name
277
+ end
278
+ end
279
+
280
+ def default_connection_class
281
+ 'ResourceRecord'.safe_constantize ||
219
282
  'ApplicationRecord'.safe_constantize ||
220
283
  Class.new(ActiveRecord::Base).tap { |e| e.abstract_class = true }
221
284
  end
@@ -27,7 +27,7 @@ module Motor
27
27
  klass = Class.new(model)
28
28
  klass.inheritance_column = nil if model.superclass.abstract_class
29
29
 
30
- define_class_name_method(klass, model)
30
+ define_class_properties(klass, model)
31
31
 
32
32
  define_columns_hash(klass, config)
33
33
  define_default_scope(klass, config)
@@ -53,7 +53,23 @@ module Motor
53
53
  klass
54
54
  end
55
55
 
56
- def define_class_name_method(klass, model)
56
+ def define_audited_class(klass)
57
+ default_audit_class = Audited.audit_class
58
+
59
+ Audited.audit_class = Motor::Audit
60
+
61
+ klass.audited
62
+
63
+ klass
64
+ ensure
65
+ Audited.audit_class = default_audit_class
66
+ end
67
+
68
+ def define_class_properties(klass, model)
69
+ define_audited_class(klass) if model != Motor::Audit
70
+
71
+ klass.table_name = model.table_name
72
+
57
73
  klass.instance_variable_set(:@__motor_model_name, model.name)
58
74
 
59
75
  klass.instance_eval do
@@ -228,7 +244,7 @@ module Motor
228
244
  if resource_config
229
245
  build_configured_model(model, resource_config.preferences)
230
246
  else
231
- define_class_name_method(Class.new(model), model)
247
+ define_class_properties(Class.new(model), model)
232
248
  end
233
249
  end
234
250
 
@@ -3,7 +3,7 @@
3
3
  module Motor
4
4
  module Resources
5
5
  RESOURCE_ATTRS = %w[display_name display_column icon custom_sql visible display_primary_key
6
- searchable_columns].freeze
6
+ searchable_columns preferences].freeze
7
7
  COLUMN_ATTRS = %w[name display_name column_type access_type default_value reference virtual format
8
8
  validators description].freeze
9
9
  ASSOCIATION_ATTRS = %w[name display_name model_name icon visible foreign_key primary_key options virtual
@@ -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/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Motor
4
- VERSION = '0.3.17'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/motor.rb CHANGED
@@ -14,12 +14,16 @@ require 'net/https'
14
14
  module Motor
15
15
  PATH = Pathname.new(__dir__)
16
16
 
17
+ module DatabaseClasses
18
+ end
19
+
17
20
  module_function
18
21
 
19
22
  def reload!
20
23
  Kernel.silence_warnings do
21
24
  Dir[PATH.join('./motor/**/*.rb')].each do |f|
22
25
  next if f.ends_with?('alerts/scheduler.rb')
26
+ next if f.ends_with?('notes/reminders_scheduler.rb')
23
27
  next if f.ends_with?('alerts/scheduled_alerts_cache.rb')
24
28
  next if f.ends_with?('configs/load_from_cache.rb')
25
29
  next if f.ends_with?('configs/sync_from_file.rb')
@@ -43,6 +47,19 @@ module Motor
43
47
  defined?(::Trinidad::Server)
44
48
  end
45
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
+
46
63
  def development?
47
64
  ENV['MOTOR_DEVELOPMENT'].present?
48
65
  end
@@ -62,7 +79,9 @@ require 'motor/dashboards'
62
79
  require 'motor/forms'
63
80
  require 'motor/api_configs'
64
81
  require 'motor/alerts'
82
+ require 'motor/slack'
65
83
  require 'motor/resources'
84
+ require 'motor/notes'
66
85
  require 'motor/hash_serializer'
67
86
  require 'motor/net_http_utils'
68
87
  require 'motor/railtie'
@@ -3964,9 +3964,9 @@
3964
3964
  "images/layers-2x.png": "images/layers-2x.png",
3965
3965
  "images/layers.png": "images/layers.png",
3966
3966
  "images/marker-icon.png": "images/marker-icon.png",
3967
- "main-726aa7f6805676af4d21.css.gz": "main-726aa7f6805676af4d21.css.gz",
3968
- "main-726aa7f6805676af4d21.js.LICENSE.txt": "main-726aa7f6805676af4d21.js.LICENSE.txt",
3969
- "main-726aa7f6805676af4d21.js.gz": "main-726aa7f6805676af4d21.js.gz",
3970
- "main.css": "main-726aa7f6805676af4d21.css",
3971
- "main.js": "main-726aa7f6805676af4d21.js"
3967
+ "main-99bab2664944ee03d10f.css.gz": "main-99bab2664944ee03d10f.css.gz",
3968
+ "main-99bab2664944ee03d10f.js.LICENSE.txt": "main-99bab2664944ee03d10f.js.LICENSE.txt",
3969
+ "main-99bab2664944ee03d10f.js.gz": "main-99bab2664944ee03d10f.js.gz",
3970
+ "main.css": "main-99bab2664944ee03d10f.css",
3971
+ "main.js": "main-99bab2664944ee03d10f.js"
3972
3972
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motor-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.17
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pete Matsyburka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-12 00:00:00.000000000 Z
11
+ date: 2022-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ar_lazy_preload
@@ -93,6 +93,10 @@ files:
93
93
  - LICENSE
94
94
  - README.md
95
95
  - Rakefile
96
+ - app/channels/motor/application_cable/channel.rb
97
+ - app/channels/motor/application_cable/connection.rb
98
+ - app/channels/motor/notes_channel.rb
99
+ - app/channels/motor/notifications_channel.rb
96
100
  - app/controllers/concerns/motor/current_ability.rb
97
101
  - app/controllers/concerns/motor/current_user_method.rb
98
102
  - app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb
@@ -110,7 +114,11 @@ files:
110
114
  - app/controllers/motor/data_controller.rb
111
115
  - app/controllers/motor/forms_controller.rb
112
116
  - app/controllers/motor/icons_controller.rb
117
+ - app/controllers/motor/note_tags_controller.rb
118
+ - app/controllers/motor/notes_controller.rb
119
+ - app/controllers/motor/notifications_controller.rb
113
120
  - app/controllers/motor/queries_controller.rb
121
+ - app/controllers/motor/reminders_controller.rb
114
122
  - app/controllers/motor/resource_default_queries_controller.rb
115
123
  - app/controllers/motor/resource_methods_controller.rb
116
124
  - app/controllers/motor/resources_controller.rb
@@ -120,12 +128,17 @@ files:
120
128
  - app/controllers/motor/schema_controller.rb
121
129
  - app/controllers/motor/send_alerts_controller.rb
122
130
  - app/controllers/motor/sessions_controller.rb
131
+ - app/controllers/motor/slack_conversations_controller.rb
123
132
  - app/controllers/motor/tags_controller.rb
124
133
  - app/controllers/motor/ui_controller.rb
134
+ - app/controllers/motor/users_for_autocomplete_controller.rb
125
135
  - app/jobs/motor/alert_sending_job.rb
126
136
  - app/jobs/motor/application_job.rb
137
+ - app/jobs/motor/notify_note_mentions_job.rb
138
+ - app/jobs/motor/notify_reminder_job.rb
127
139
  - app/mailers/motor/alerts_mailer.rb
128
140
  - app/mailers/motor/application_mailer.rb
141
+ - app/mailers/motor/notifications_mailer.rb
129
142
  - app/models/motor/alert.rb
130
143
  - app/models/motor/alert_lock.rb
131
144
  - app/models/motor/api_config.rb
@@ -134,12 +147,20 @@ files:
134
147
  - app/models/motor/config.rb
135
148
  - app/models/motor/dashboard.rb
136
149
  - app/models/motor/form.rb
150
+ - app/models/motor/note.rb
151
+ - app/models/motor/note_tag.rb
152
+ - app/models/motor/note_tag_tag.rb
153
+ - app/models/motor/notification.rb
137
154
  - app/models/motor/query.rb
155
+ - app/models/motor/reminder.rb
138
156
  - app/models/motor/resource.rb
139
157
  - app/models/motor/tag.rb
140
158
  - app/models/motor/taggable_tag.rb
141
159
  - app/views/layouts/motor/application.html.erb
160
+ - app/views/layouts/motor/mailer.html.erb
142
161
  - app/views/motor/alerts_mailer/alert_email.html.erb
162
+ - app/views/motor/notifications_mailer/notify_mention_email.html.erb
163
+ - app/views/motor/notifications_mailer/notify_reminder_email.html.erb
143
164
  - app/views/motor/ui/show.html.erb
144
165
  - config/locales/el.yml
145
166
  - config/locales/en.yml
@@ -147,9 +168,11 @@ files:
147
168
  - config/locales/pt.yml
148
169
  - config/routes.rb
149
170
  - lib/generators/motor/install_generator.rb
171
+ - lib/generators/motor/install_notes_generator.rb
150
172
  - lib/generators/motor/migration.rb
151
173
  - lib/generators/motor/templates/install.rb
152
174
  - lib/generators/motor/templates/install_api_configs.rb
175
+ - lib/generators/motor/templates/install_notes.rb
153
176
  - lib/generators/motor/templates/upgrade_motor_api_actions.rb
154
177
  - lib/generators/motor/upgrade_generator.rb
155
178
  - lib/motor-admin.rb
@@ -168,6 +191,7 @@ files:
168
191
  - lib/motor/alerts/persistance.rb
169
192
  - lib/motor/alerts/scheduled_alerts_cache.rb
170
193
  - lib/motor/alerts/scheduler.rb
194
+ - lib/motor/alerts/slack_sender.rb
171
195
  - lib/motor/api_configs.rb
172
196
  - lib/motor/api_query.rb
173
197
  - lib/motor/api_query/apply_scope.rb
@@ -208,6 +232,12 @@ files:
208
232
  - lib/motor/forms/persistance.rb
209
233
  - lib/motor/hash_serializer.rb
210
234
  - lib/motor/net_http_utils.rb
235
+ - lib/motor/notes.rb
236
+ - lib/motor/notes/notify_mentions.rb
237
+ - lib/motor/notes/notify_reminder.rb
238
+ - lib/motor/notes/persist.rb
239
+ - lib/motor/notes/reminders_scheduler.rb
240
+ - lib/motor/notes/tags.rb
211
241
  - lib/motor/queries.rb
212
242
  - lib/motor/queries/persistance.rb
213
243
  - lib/motor/queries/postgresql_exec_query.rb
@@ -218,6 +248,8 @@ files:
218
248
  - lib/motor/resources/custom_sql_columns_cache.rb
219
249
  - lib/motor/resources/fetch_configured_model.rb
220
250
  - lib/motor/resources/persist_configs.rb
251
+ - lib/motor/slack.rb
252
+ - lib/motor/slack/client.rb
221
253
  - lib/motor/tags.rb
222
254
  - lib/motor/tasks/motor.rake
223
255
  - lib/motor/version.rb
@@ -2203,8 +2235,8 @@ files:
2203
2235
  - ui/dist/images/layers-2x.png
2204
2236
  - ui/dist/images/layers.png
2205
2237
  - ui/dist/images/marker-icon.png
2206
- - ui/dist/main-726aa7f6805676af4d21.css.gz
2207
- - ui/dist/main-726aa7f6805676af4d21.js.gz
2238
+ - ui/dist/main-99bab2664944ee03d10f.css.gz
2239
+ - ui/dist/main-99bab2664944ee03d10f.js.gz
2208
2240
  - ui/dist/manifest.json
2209
2241
  homepage:
2210
2242
  licenses: