web47core 2.0.1 → 2.2.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +111 -41
  3. data/app/controllers/status_controller.rb +8 -3
  4. data/app/helpers/core_form_helper.rb +6 -6
  5. data/app/helpers/core_helper.rb +1 -1
  6. data/app/helpers/core_link_helper.rb +47 -8
  7. data/app/helpers/core_nav_bar_helper.rb +5 -4
  8. data/app/helpers/core_table_helper.rb +80 -0
  9. data/app/helpers/model_modal_helper.rb +3 -3
  10. data/app/views/common/_create_actions.html.haml +12 -0
  11. data/app/views/common/_update_actions.html.haml +10 -0
  12. data/app/views/cron/_edit.html.haml +15 -17
  13. data/app/views/cron/_index.html.haml +74 -67
  14. data/app/views/delayed_job_metrics/_index.html.haml +27 -0
  15. data/app/views/delayed_job_metrics/index.html.haml +1 -0
  16. data/app/views/delayed_job_workers/_index.html.haml +27 -0
  17. data/app/views/delayed_job_workers/index.html.haml +1 -0
  18. data/app/views/delayed_jobs/_index.html.haml +47 -52
  19. data/app/views/delayed_jobs/_show.html.haml +15 -13
  20. data/app/views/system_configurations/_edit.html.haml +14 -9
  21. data/app/views/system_configurations/_show.html.haml +18 -12
  22. data/config/brakeman.ignore +26 -0
  23. data/config/brakeman.yml +2 -0
  24. data/config/locales/en.yml +21 -3
  25. data/lib/app/controllers/concerns/core_delayed_job_metrics_controller.rb +35 -0
  26. data/lib/app/controllers/concerns/core_delayed_job_workers_controller.rb +35 -0
  27. data/lib/app/controllers/concerns/core_delayed_jobs_controller.rb +2 -3
  28. data/lib/app/jobs/cron/command.rb +1 -4
  29. data/lib/app/jobs/cron/record_delayed_job_metrics.rb +25 -0
  30. data/lib/app/jobs/cron/restart_orphaned_delayed_jobs.rb +44 -0
  31. data/lib/app/jobs/cron/server.rb +32 -15
  32. data/lib/app/jobs/cron/switchboard_sync_configuration.rb +2 -0
  33. data/lib/app/jobs/cron/switchboard_sync_models.rb +2 -0
  34. data/lib/app/jobs/cron/trim_collection.rb +1 -1
  35. data/lib/app/jobs/cron/trim_delayed_job_metrics.rb +29 -0
  36. data/lib/app/jobs/cron/trim_delayed_job_workers.rb +39 -0
  37. data/lib/app/jobs/cron/trim_failed_delayed_jobs.rb +2 -0
  38. data/lib/app/models/api_token.rb +9 -0
  39. data/lib/app/models/command_job.rb +12 -11
  40. data/lib/app/models/concerns/api_tokenable.rb +38 -0
  41. data/lib/app/models/concerns/aws_configuration.rb +65 -0
  42. data/lib/app/models/concerns/cdn_url.rb +7 -0
  43. data/lib/app/models/concerns/core_smtp_configuration.rb +65 -0
  44. data/lib/app/models/concerns/core_system_configuration.rb +18 -201
  45. data/lib/app/models/concerns/delayed_job_configuration.rb +24 -0
  46. data/lib/app/models/concerns/email_able.rb +6 -2
  47. data/lib/app/models/concerns/google_sso_configuration.rb +32 -0
  48. data/lib/app/models/concerns/search_able.rb +16 -0
  49. data/lib/app/models/concerns/server_process_able.rb +69 -0
  50. data/lib/app/models/concerns/slack_configuration.rb +38 -0
  51. data/lib/app/models/concerns/standard_model.rb +5 -2
  52. data/lib/app/models/concerns/switchboard_configuration.rb +43 -0
  53. data/lib/app/models/concerns/twilio_configuration.rb +37 -0
  54. data/lib/app/models/concerns/zendesk_configuration.rb +92 -0
  55. data/lib/app/models/{delayed_job.rb → delayed/backend/delayed_job.rb} +41 -0
  56. data/lib/app/models/delayed/jobs/metric.rb +61 -0
  57. data/lib/app/models/delayed/jobs/run.rb +40 -0
  58. data/lib/app/models/delayed/jobs/worker.rb +43 -0
  59. data/lib/app/models/delayed/plugins/time_keeper.rb +33 -0
  60. data/lib/app/models/delayed/worker.rb +24 -0
  61. data/lib/app/models/email_notification.rb +2 -1
  62. data/lib/app/models/email_template.rb +5 -6
  63. data/lib/app/models/notification.rb +12 -2
  64. data/lib/app/models/sms_notification.rb +9 -6
  65. data/lib/app/models/template.rb +12 -12
  66. data/lib/web47core/version.rb +1 -1
  67. data/lib/web47core.rb +33 -9
  68. metadata +114 -69
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dbf707fe805b12f85070027a7f991404b327d1abf62b633b2b0489740e902e5b
4
- data.tar.gz: c0fef2df3709e4319297a1f55c0c0b0968c83a89451f264511e2663f236925f0
3
+ metadata.gz: 8e3b62063f81c04f52de1b3c56a36801555c8294f69e677142754897ec64fd6e
4
+ data.tar.gz: e2cad54d84e6155e83819d8ea5691df3f4eeba9625f60ffd52ad9ac996967b97
5
5
  SHA512:
6
- metadata.gz: d15d90c313d88d4ad813b98a764508484554b47b790d55b688f1bb156a8b1a0b350ba709fee7be2f26f6db3e83954c461b3f274fedcddb7756c6de9336df7f44
7
- data.tar.gz: feeac4239229604c458fb02a292e820f42ff789c361afa9b1a1b958e1057e3b1b99cff995b0bd12b2c6e5621df092f88eed179b3027d02c83d883fd79ed19249
6
+ metadata.gz: f080ed702713ff2258b811d91de55e53e92e1fe9e3a04ab762ef9a870f4eceda71e048e80440be2efa709bd2c5768e3f0f47070dce2fdbc0c89ea2be97fc9a0d
7
+ data.tar.gz: 62e0a0483e20b47b5c48370f1643a76ad5abc77075033bf76b17b21fdf2642359ff8fb2336c1ab24aadc29e8855dd194e38c65b71376656c0d61869fe66248dd
data/README.md CHANGED
@@ -3,29 +3,29 @@ Core components used commonly among all web apps for both App47 and RedMonocle
3
3
 
4
4
  ## We don't need no sticking badges
5
5
 
6
- * [![Codacy Badge](https://api.codacy.com/project/badge/Grade/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Grade)
7
- * [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Coverage)
8
- * Develop: [![CircleCI](https://circleci.com/gh/App47/web47core/tree/develop.svg?style=svg&circle-token=9999e0634dd96ad5414f4f3e56c39ba6d3e0e4e6)](https://circleci.com/gh/App47/web47core/tree/develop)
9
- * Master: [![CircleCI](https://circleci.com/gh/App47/web47core/tree/master.svg?style=svg&circle-token=9999e0634dd96ad5414f4f3e56c39ba6d3e0e4e6)](https://circleci.com/gh/App47/web47core/tree/master)
6
+ * [![Codacy Badge](https://api.codacy.com/project/badge/Grade/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Grade)
7
+ * [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Coverage)
8
+ * Develop: [![CircleCI](https://circleci.com/gh/App47/web47core/tree/develop.svg?style=svg&circle-token=9999e0634dd96ad5414f4f3e56c39ba6d3e0e4e6)](https://circleci.com/gh/App47/web47core/tree/develop)
9
+ * Master: [![CircleCI](https://circleci.com/gh/App47/web47core/tree/master.svg?style=svg&circle-token=9999e0634dd96ad5414f4f3e56c39ba6d3e0e4e6)](https://circleci.com/gh/App47/web47core/tree/master)
10
10
 
11
11
  ## Requirements
12
12
 
13
- * Ruby 2.7.0
13
+ * Ruby 2.7.0
14
14
 
15
- ### Working with Bundler and RVM
15
+ ### Working with Bundler and RBENV
16
16
 
17
- This project manages Ruby versions via [RVM](http://rvm.beginrescueend.com/) and manages dependencies via [Bundler](http://gembundler.com/).
17
+ This project manages [RBENV](https://github.com/rbenv/rbenv) and manages dependencies via [Bundler](http://gembundler.com/).
18
18
 
19
- You must first [install RVM](http://rvm.beginrescueend.com/rvm/install/).
20
- Then install Ruby 2.7.0 ([version 2.7.0](http://rvm.beginrescueend.com/interpreters/ruby/)) via RVM.
19
+ You must first [install RBENV](https://github.com/rbenv/rbenv#installation).
20
+ Then install Ruby 2.7.0 via RBENV
21
21
  ``` shell script
22
- rvm install 2.7.0
22
+ rbenv install 2.7.0
23
23
  ```
24
- You'll now notice that this project (as well as other App47 ones) contains a .rvmc file, which is executed upon opening the project's root directory in a terminal (and IDE's like RubyMine). The .rvmc file simply states `rvm ruby-2.4.1` which tells RVM to ensure the Ruby version to use for this project is 2.4.1.
24
+ You'll now notice that this project (as well as other App47 ones) contains a .ruby-version file, which is executed upon opening the project's root directory in a terminal (and IDE's like RubyMine). The .ruby-version file simply states `2.7.0` which tells RBENV to ensure the Ruby version to use for this project is 2.7.0.
25
25
 
26
26
  Please note, your Ruby `2.7.0` version might need bundler installed:
27
27
  ``` shell script
28
- gem install bundler -v 2.2.11
28
+ gem install bundler -v 2.1.4
29
29
  ```
30
30
 
31
31
  To set up this project's dependencies, which are defined in the file, `Gemfile`, you should first run
@@ -43,29 +43,28 @@ bundle exec rake test
43
43
  ## Deployment
44
44
  The `web47core` project is a gem that will be deployed via [Ruby Gems](https://rubygems.org). When an update is ready, the following steps should be followed
45
45
 
46
- 1. Build the gem `gem build web47core.gemspec`
47
- 2. Push the new gem to [Ruby Gems](https://rubygems.org) `gem push web47core-version.gem`
48
- 3. There may be a delay when using the gem file
46
+ 1. Build the gem `gem build web47core.gemspec`
47
+ 2. Post the gem to the DevOps channel in slack, ask for it to be added to the S3 repo.
49
48
 
50
49
  ## Usage
51
50
  ### Importing the gem
52
- To use the `app47core` gem in a project, first add the gem to your Gemfile in one of two ways
51
+ To use the `web47core` gem in a project, first add the gem to your Gemfile in one of two ways
53
52
 
54
53
  Using the gem from [Ruby Gems](https://rubygems.org)
55
- ```rbenv-gemsets
54
+ ``` rbenv-gemsets
56
55
  gem 'web47core'
57
56
  ```
58
57
 
59
58
  If you need the gem immediately or need to pull from development branch, you can use the git repo
60
- ```rbenv-gemsets
59
+ ``` rbenv-gemsets
61
60
  gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :master
62
61
  ```
63
62
  or from the develop branch
64
- ```rbenv-gemsets
63
+ ``` rbenv-gemsets
65
64
  gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :develop
66
65
  ```
67
66
 
68
- _Please do not ship to production code using the git repo, as the production servers will not have keys to pull from the web47core repo_
67
+ Please do not ship to production code using the git repo, as the production servers will not have keys to pull from the web47core repo.
69
68
 
70
69
  ### Remove the following files
71
70
  1. `StandardModel` - Includes the common set of includes, Mongoid, Auditable, AutoClearCache, etc.
@@ -77,18 +76,21 @@ _Please do not ship to production code using the git repo, as the production ser
77
76
  7. `Notification`
78
77
  8. `NotificationTemplate`
79
78
  9. `SlackNotification`
80
- 10. `SmsNotification`
81
- 11. `Template`
82
- 12. `App47Logger` and `App47LoggerTest`
83
- 13. `Emailable` or `EmailAble` and `EamailbleTest`, be sure to change `Emailable` to `EmailAble`
84
- 14. `RedisConfiguration` and `RedisConfgurationTest`
85
- 15. `Searchable` and `SearchableTest`, be sure to change `Searchable` to `SearchAble`
86
- 16. `TimezoneAble` and `TimezoneAbleTest`
87
- 17. `CronJobServer` and `CronJobServerTest`
88
- 18. `JobCronTab` and `JobCronTabTest`
89
- 19. `CronTab`
90
- 20. `SecureFields`
91
-
79
+ 10. `SmsNotification`
80
+ 11. `Template`
81
+ 12. `App47Logger` and `App47LoggerTest`
82
+ 13. `Emailable` or `EmailAble` and `EamailbleTest`, be sure to change `Emailable` to `EmailAble`
83
+ 14. `RedisConfiguration` and `RedisConfgurationTest`
84
+ 15. `Searchable` and `SearchableTest`, be sure to change `Searchable` to `SearchAble`
85
+ 16. `TimezoneAble` and `TimezoneAbleTest`
86
+ 17. `CronJobServer` and `CronJobServerTest`
87
+ 18. `JobCronTab` and `JobCronTabTest`
88
+ 19. `CronTab`
89
+ 20. `SecureFields`
90
+ 21. `Job`
91
+ 22. `JobLog`
92
+ 23. `CommandLogLog`
93
+ 24. `TrimJobs`
92
94
  #### Models
93
95
  ##### Concerns
94
96
  1. `StandardModel` - Includes the common set of includes, Mongoid, etc.
@@ -106,6 +108,21 @@ class SystemConfiguration
106
108
  field :google_sso_client_id, type: String
107
109
  end
108
110
  ```
111
+
112
+ Configuration has been broken out, or modularized as of 2.0.10, so if the project uses `AWS`, `SMTP`, `Slack`, `Switchboard`, `Twilio` or `Zendesk` within `SystemConfiguration`, then you will also need to include those configurations in the Project's SystemConfiguration, for example
113
+ ```ruby
114
+ class SystemConfiguration
115
+ include StandardModel
116
+ include CoreSystemConfiguration
117
+ include ZendeskConfiguration
118
+ include TwilioConfiguration
119
+ include SwitchboardConfiguration
120
+ include DelayedJobConfiguration
121
+
122
+ # Include your additional system configuration fields and methods
123
+ field :google_sso_client_id, type: String
124
+ end
125
+ ```
109
126
  ##### Account
110
127
  Define a `Account` class in your project and import the core concern.
111
128
 
@@ -134,19 +151,19 @@ module Cron
134
151
  end
135
152
  ```
136
153
  Allowed values of cron_tab_entry are
137
- * `:always` Run every minute
138
- * `:hourly` Run every hour
139
- * `:daily` Run every day
140
- * `:weekly` Run every week on Sunday
141
- * `:monthly` Run every month on the first day of the month
142
- * `'*/5 1,3 * 2 *'` Run according to unix crontab entry format. This would run every tuesday on the 1st and 3rd hour, for any minute divisible by 5, so 0, 5, 10, 15, etc..
154
+ * `:always` Run every minute
155
+ * `:hourly` Run every hour
156
+ * `:daily` Run every day
157
+ * `:weekly` Run every week on Sunday
158
+ * `:monthly` Run every month on the first day of the month
159
+ * `'*/5 1,3 * 2 *'` Run according to unix crontab entry format. This would run every tuesday on the 1st and 3rd hour, for any minute divisible by 5, so 0, 5, 10, 15, etc..
143
160
 
144
161
  Before starting the server, you need to run the database command
145
162
  ```mongo
146
163
  db.cron_tabs.updateMany({_type: 'JobCronTab'}, {$set: {_type: 'Cron::JobTab'}});
147
164
  ```
148
165
 
149
- #### Routes
166
+ #### Abilities
150
167
  Update abilities to new class names
151
168
  CronTab, JobCronTab, CronJobServer to Cron::Tab, Cron::JobTab, Cron::Server
152
169
 
@@ -203,8 +220,12 @@ end
203
220
  ```
204
221
 
205
222
  To start or stop the cron server, run the bundler command:
223
+ ```bash
224
+ bundle exec cron_server start
206
225
  ```
207
- bundle exec cron_server start|stop
226
+ or
227
+ ```bash
228
+ bundle exec cron_server stop
208
229
  ```
209
230
 
210
231
  ##### DelayedJobController
@@ -223,10 +244,59 @@ end
223
244
  ```
224
245
 
225
246
  To start or stop the delayed jobs, run the bundler command:
247
+ ```bash
248
+ bundle exec delayed_job start
249
+ ```
250
+ or
251
+ ```bash
252
+ bundle exec delayed_job stop
253
+ ```
254
+
255
+ ##### Delayed Job Management
256
+ Since 2.1.0, there is now a built in Delayed Job monitor that will monitor delayed jobs and auto restart them if they
257
+ exceed the max allowed time for a job to run. To configure this, update the delayed job initializer to add the `TimeKeeper` plugin.
258
+
259
+ ```ruby
260
+ Delayed::Worker.plugins += [Delayed::Plugins::TimeKeeper]
261
+ ```
262
+
263
+ This will add a few now cron jobs as well as objects to the project, you can view these by adding the following routes near the delayed jobs area
264
+
265
+ ```ruby
266
+ resources :delayed_job_workers, only: %i[index destroy]
267
+ resources :delayed_job_metrics, only: %i[index destroy]
226
268
  ```
227
- bundle exec delayed_job start|stop
269
+ with the following two controllers
270
+
271
+ ```ruby
272
+ # frozen_string_literal: true
273
+
274
+ #
275
+ # Manage access to metrics
276
+ #
277
+ class DelayedJobMetricsController < BaseStackUiController
278
+ rescue_from Mongoid::Errors::DocumentNotFound, with: :document_not_found_error
279
+ include ::CoreDelayedJobMetricsController
280
+ end
228
281
  ```
282
+ and
283
+ ```ruby
284
+ # frozen_string_literal: true
229
285
 
286
+ #
287
+ # Manage access to workers
288
+ #
289
+ class DelayedJobWorkersController < BaseStackUiController
290
+ rescue_from Mongoid::Errors::DocumentNotFound, with: :document_not_found_error
291
+ include ::CoreDelayedJobWorkersController
292
+ end
293
+ ```
294
+ lastly, add the following three objects to ability to allow access
295
+ ```ruby
296
+ Delayed::Jobs::Worker,
297
+ Delayed::Jobs::Metric,
298
+ Delayed::Jobs::Run
299
+ ```
230
300
  ##### StatusController
231
301
  Remove controller, views and localizations
232
302
  ##### SystemConfigurationsController
@@ -73,13 +73,18 @@ class StatusController < ActionController::Base
73
73
  report_error error, count: 0
74
74
  end
75
75
 
76
+ def pid
77
+ @pid ||= Process.pid
78
+ end
79
+
76
80
  #
77
81
  # Redis DB Status
78
82
  #
79
83
  def redis_status
80
- value = Time.now.to_f
81
- Rails.cache.write 'redis-status-check', value
82
- raise 'Redis not available' unless value.eql?(Rails.cache.fetch('redis-status-check'))
84
+ value = Time.now.to_i
85
+ key = "redis-status-check-#{pid}"
86
+ Rails.cache.write key, value, expires_in: 5.seconds
87
+ raise 'Redis not available' unless value.eql?(Rails.cache.fetch(key))
83
88
 
84
89
  report_success 'Redis Available', count: 1
85
90
  rescue StandardError => error
@@ -40,7 +40,7 @@ module CoreFormHelper
40
40
  def form_text_field(model, field, options = {})
41
41
  classes = options[:classes] || %w[s12 m6 l4 xl3]
42
42
  value = model.send(field)
43
- options[:type] = :text
43
+ options[:type] ||= :text
44
44
  options[:value] = value
45
45
  options[:disabled] ||= false
46
46
  tag_options = text_field_options(model, field, options)
@@ -88,7 +88,7 @@ module CoreFormHelper
88
88
  classes = options[:classes] || %w[s12 m6 l4 xl3]
89
89
  value = model.send(field)
90
90
  options[:type] = :password
91
- options[:place_holder] = mask_value(value)
91
+ options[:place_holder] ||= mask_value(value)
92
92
  tag_options = text_field_options(model, field, options)
93
93
  content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
94
94
  concat(tag(:input, tag_options))
@@ -111,7 +111,7 @@ module CoreFormHelper
111
111
  base_classes = %w[input-field col]
112
112
  data = {}
113
113
  end
114
- classes = (base_classes + (options[:classes] || %w[s12 m6 l4])).join(' ')
114
+ classes = (base_classes + (options[:classes] || %w[s12 m6 l4 xl3])).join(' ')
115
115
  content_tag(:div, class: classes, data: data) do
116
116
  concat(form_select_tag(model, field, options))
117
117
  concat(form_label_tag(model, field, value, options))
@@ -175,8 +175,8 @@ module CoreFormHelper
175
175
  options[:disabled] ||= false
176
176
  properties = {
177
177
  class: 'validate',
178
- id: form_field_id(model, field),
179
- name: form_field_name(model, field),
178
+ id: form_field_id(model, field, options),
179
+ name: form_field_name(model, field, options),
180
180
  type: :checkbox,
181
181
  disabled: options[:disabled]
182
182
  }
@@ -247,7 +247,7 @@ module CoreFormHelper
247
247
  options['data-error'] = error.join(', ') if error.present?
248
248
  content_tag(:label, options) do
249
249
  concat(I18n.exists?(key) ? I18n.t(key) : field.to_s.humanize)
250
- concat(' ' + error.join(', ')) if error.present?
250
+ concat(" #{error.join(', ')}") if error.present?
251
251
  end
252
252
  end
253
253
 
@@ -69,7 +69,7 @@ module CoreHelper
69
69
  when 5..10
70
70
  "#{string_value.first}**********#{string_value.last}"
71
71
  else
72
- "#{string_value[0..2]}**********#{string_value[-3..-1]}"
72
+ "#{string_value[0..2]}**********#{string_value[-3..]}"
73
73
  end
74
74
  end
75
75
 
@@ -54,11 +54,15 @@ module CoreLinkHelper
54
54
  #
55
55
  # Add a favorite tag
56
56
  #
57
- def favorite_tag(favorite)
57
+ def favorite_tag(favorite, options = {})
58
+ data = {}
59
+ link_classes = tooltip_data(options, data, I18n.t('ui_form.actions.favorite'))
60
+ link_classes += %w[material-icons pointer favorite]
58
61
  content_tag(:i,
59
- class: 'material-icons pointer favorite',
62
+ class: link_classes.join(' '),
63
+ data: data,
60
64
  id: favorite.id.to_s,
61
- type: favorite.favorite_type) { concat('favorite_border') }
65
+ type: favorite.favorite_type) { concat(icon_name(options, 'favorite_border')) }
62
66
  end
63
67
 
64
68
  #
@@ -126,6 +130,7 @@ module CoreLinkHelper
126
130
  return unless can? :edit, obj
127
131
 
128
132
  data = {}
133
+ options[:icon_name] ||= 'replay'
129
134
  confirmation_data(options, data, t('links.replay_confirmation', name: obj.class.to_s.underscore.humanize))
130
135
  link_classes = tooltip_data(options, data)
131
136
  content_tag(:a, href: path, data: data, class: link_classes.join(' ')) do
@@ -146,6 +151,23 @@ module CoreLinkHelper
146
151
  end
147
152
  end
148
153
 
154
+ #
155
+ # Restart a thingy
156
+ #
157
+ def replay_button_tag(obj, path, options = {})
158
+ return unless can? :edit, obj
159
+
160
+ data = {}
161
+ options[:icon_name] ||= 'replay'
162
+ confirmation_data(options, data, t('links.replay_confirmation', name: obj.class.to_s.underscore.humanize))
163
+ link_classes = tooltip_data(options, data)
164
+ link_classes << 'btn' unless link_classes.include?('btn')
165
+ content_tag(:a, href: path, data: data, class: link_classes) do
166
+ concat(materialize_icon(icon_name(options), options))
167
+ concat(options[:label]) if options[:label].present?
168
+ end
169
+ end
170
+
149
171
  #
150
172
  # Details of a thingy in a pull down list
151
173
  #
@@ -163,8 +185,9 @@ module CoreLinkHelper
163
185
  return unless can? :read, obj
164
186
 
165
187
  data = {}
188
+ confirmation_data(options, data)
166
189
  link_classes = tooltip_data(options, data)
167
- content_tag(:a, href: path, classes: link_classes, data: data) do
190
+ content_tag(:a, href: path, class: link_classes, data: data) do
168
191
  concat(materialize_icon(icon_name(options, 'info'), options))
169
192
  concat(options[:label]) if options[:label].present?
170
193
  end
@@ -218,13 +241,29 @@ module CoreLinkHelper
218
241
 
219
242
  data = { method: :delete }
220
243
  confirmation_data(options, data, t('links.deletion_confirmation', name: obj.class.to_s.underscore.humanize))
221
- link_classes = tooltip_data(options, data)
244
+ link_classes = tooltip_data(options, data, I18n.t('ui_form.actions.delete'))
222
245
  content_tag(:a, href: path, class: link_classes, data: data) do
223
246
  concat(materialize_icon(icon_name(options, 'delete'), options))
224
247
  concat(options[:label]) if options[:label].present?
225
248
  end
226
249
  end
227
250
 
251
+ #
252
+ # Delete an thingy
253
+ #
254
+ def delete_button_tag(obj, path, options = {})
255
+ return unless can? :destroy, obj
256
+
257
+ data = { method: :delete }
258
+ confirmation_data(options, data, t('links.deletion_confirmation', name: obj.class.to_s.underscore.humanize))
259
+ link_classes = tooltip_data(options, data)
260
+ %w[btn red].each { |c| link_classes << c unless link_classes.include?(c) }
261
+ content_tag(:a, class: link_classes, href: path, data: data) do
262
+ concat(materialize_icon(icon_name(options, 'delete'), options))
263
+ concat(options[:label]) if options[:label].present?
264
+ end
265
+ end
266
+
228
267
  #
229
268
  # Create a thingy in a pull-down list
230
269
  #
@@ -244,9 +283,9 @@ module CoreLinkHelper
244
283
  return unless can? :create, obj
245
284
 
246
285
  data = {}
247
- confirmation_data(options, data, t('links.action_confirmation', name: obj.class.to_s.underscore.humanize))
286
+ confirmation_data(options, data, t('links.creation_confirmation', name: obj.class.to_s.underscore.humanize))
248
287
  link_classes = tooltip_data(options, data)
249
- content_tag(:a, href: path, class: link_classes, data: { confirm: data }) do
288
+ content_tag(:a, href: path, class: link_classes, data: data) do
250
289
  concat(materialize_icon(icon_name(options, 'add'), options))
251
290
  concat(options[:label]) if options[:label].present?
252
291
  end
@@ -410,7 +449,7 @@ module CoreLinkHelper
410
449
  end
411
450
 
412
451
  def tooltip_data(options, data, default = nil)
413
- link_classes = options[:link_classes] || []
452
+ link_classes = Array.wrap(options[:link_classes]) || []
414
453
  tooltip = options[:tooltip] || default
415
454
  if tooltip.present?
416
455
  link_classes << 'tooltipped'
@@ -18,12 +18,13 @@ module CoreNavBarHelper
18
18
  states << 'read-only' if read_only
19
19
  states << 'locked' unless feature_enabled
20
20
  states << 'hidden' unless feature_visible
21
- if names.is_a? String
21
+ case names
22
+ when String
22
23
  states << 'active' if names.eql?(controller.controller_name)
23
- elsif names.is_a? Symbol
24
- states << 'active' if names.to_s.eql?(controller.controller_name)
25
- elsif names.is_a? Array
24
+ when Array
26
25
  states << 'active' if names.include?(controller.controller_name)
26
+ else
27
+ states << 'active' if names.to_s.eql?(controller.controller_name)
27
28
  end
28
29
  states.join(' ')
29
30
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Methods useful for building out tables
5
+ #
6
+ module CoreTableHelper
7
+ #
8
+ # Format the table header
9
+ # @param name - Name of the header, either the text or a localized value
10
+ # @param classes - Additional classes to apply to the header
11
+ # @param priority - Priority to show the column when the screen gets small, the lower value is higher priority
12
+ # @param visible - This column should be visible
13
+ #
14
+ def table_header_actions_tag(name: :actions, classes: %w[actions], priority: 2, visible: true)
15
+ return unless visible
16
+
17
+ table_header_tag(name, classes: classes, priority: priority, visible: visible)
18
+ end
19
+
20
+ #
21
+ # Format the table header
22
+ # @param name - Name of the header, either the text or a localized value
23
+ # @param classes - Additional classes to apply to the header
24
+ # @param priority - Priority to show the column when the screen gets small, the lower value is higher priority
25
+ # @param visible - This column should be visible
26
+ #
27
+ def table_header_tag(name, classes: [], priority: 1, visible: true)
28
+ return unless visible
29
+
30
+ options = { data: { priority: priority } }
31
+ options[:class] = classes if classes.present?
32
+ content_tag(:th, options) { table_header_text(name) }
33
+ end
34
+
35
+ #
36
+ # First look to see if a localized string was passed in,
37
+ # then try to look in table.headers....
38
+ # lastly return the titleized string
39
+ # @param name - Name of the header, either the text or a localized value
40
+ #
41
+ def table_header_text(name)
42
+ if I18n.exists?(name)
43
+ t(name)
44
+ elsif I18n.exists?("table.headers.#{name}")
45
+ t("table.headers.#{name}")
46
+ elsif I18n.exists?("core_table.headers.#{name}")
47
+ t("core_table.headers.#{name}")
48
+ else
49
+ name.to_s.titleize
50
+ end
51
+ rescue StandardError
52
+ name
53
+ end
54
+
55
+ def dynamic_custom_modal(anchor, label, title, view_endpoint, _options = {})
56
+ datum = { view_url: view_endpoint }
57
+ content_tag(:span) do
58
+ concat(content_tag(:a, href: "##{anchor}", class: 'modal-trigger') do
59
+ concat(materialize_icon(label))
60
+ end)
61
+ concat(content_tag(:div, id: anchor, class: 'modal modal-fixed-footer', data: datum) do
62
+ concat(content_tag(:div, class: 'modal-content') do
63
+ concat(content_tag(:h2, class: 'center') do
64
+ concat(content_tag(:span, title))
65
+ end)
66
+ concat(content_tag(:div, class: 'center-align') do
67
+ concat(content_tag(:div, class: 'progress red lighten-4') do
68
+ tag(:div, class: 'indeterminate red')
69
+ end)
70
+ end)
71
+ end)
72
+ concat(content_tag(:div, class: 'modal-footer') do
73
+ concat(content_tag(:a, href: '#', class: 'modal-action modal-close btn btn-flat') do
74
+ concat('Close')
75
+ end)
76
+ end)
77
+ end)
78
+ end
79
+ end
80
+ end
@@ -70,7 +70,7 @@ module ModelModalHelper
70
70
 
71
71
  def model_modal_action(model, _options = {})
72
72
  content_tag(:a, class: 'modal-trigger', href: "#modal-#{model.id}") do
73
- concat(model.name.titleize)
73
+ concat(model.name)
74
74
  end
75
75
  end
76
76
 
@@ -92,7 +92,7 @@ module ModelModalHelper
92
92
  concat(model_modal_tabs(model, options))
93
93
  concat(model_modal_fields_tab(model, options))
94
94
  concat(model_modal_standard_tab(model, options))
95
- concat(model_modal_logs_tab(model, options)) if model.respond_to?(:logs)
95
+ concat(model_modal_logs_tab(model, options)) if model.respond_to?(:logs) && options[:show_audit_logs]
96
96
  end)
97
97
  end
98
98
  end
@@ -172,7 +172,7 @@ module ModelModalHelper
172
172
  def model_modal_field(model, field_name)
173
173
  content_tag(:tr) do
174
174
  concat(content_tag(:th, class: 'right-align') do
175
- field_name.titleize
175
+ field_name
176
176
  end)
177
177
  concat(content_tag(:td) do
178
178
  model_modal_field_value(model, field_name)
@@ -0,0 +1,12 @@
1
+ - create_label ||= t('ui_form.actions.create')
2
+ - cancel_label ||= t('ui_form.actions.cancel')
3
+ .card-action
4
+ .row
5
+ .col.s6.center-align
6
+ %a.btn-large.waves-effect.waves-light.grey{href: form_cancel_path}
7
+ = cancel_label
8
+ %i.material-icons.right cancel
9
+ .col.s6.center-align
10
+ %button.btn-large.waves-effect.waves-light{type: :submit}
11
+ = create_label
12
+ %i.material-icons.right save
@@ -0,0 +1,10 @@
1
+ .card-action
2
+ .row
3
+ .col.s6.center-align
4
+ %a.btn-large.waves-effect.waves-light.grey{href: form_cancel_path}
5
+ = t('ui_form.actions.cancel')
6
+ %i.material-icons.right cancel
7
+ .col.s6.center-align
8
+ %button.btn-large.waves-effect.waves-light{type: :submit}
9
+ = t('ui_form.actions.update')
10
+ %i.material-icons.right save
@@ -1,21 +1,19 @@
1
1
  - title t('.title', name: @cron_tab.name)
2
2
 
3
- - content_for :breadcrumbs do
4
- %a.breadcrumb{href: index_path}= t('cron.index.title')
5
- %a.breadcrumb{href: '#'}= t('.title', name: @cron_tab.name)
6
-
7
- .container
8
- %form{action: model_path(@cron_tab), method: :post}
9
- %input{type: :hidden, value: form_authenticity_token, name: 'authenticity_token'}
10
- %input{type: :hidden, name: '_method', value: 'put'}
3
+ %form{action: model_path(@cron_tab), method: :post}
4
+ %input{type: :hidden, value: form_authenticity_token, name: :authenticity_token}
5
+ %input{type: :hidden, name: '_method', value: :put}
6
+ .container
11
7
  .row
12
8
  .col.s12
13
- %h1=@cron_tab.name.titleize
14
- .row
15
- = form_text_field(@cron_tab, :min)
16
- = form_text_field(@cron_tab, :hour)
17
- = form_text_field(@cron_tab, :mday)
18
- = form_text_field(@cron_tab, :month)
19
- = form_text_field(@cron_tab, :wday)
20
- = form_checkbox(@cron_tab, :enabled)
21
- = render 'common/form_actions', form_cancel_path: index_path
9
+ .card
10
+ .card-content
11
+ .card-title= t('.title', name: @cron_tab.name)
12
+ .row
13
+ = form_text_field(@cron_tab, :min)
14
+ = form_text_field(@cron_tab, :hour)
15
+ = form_text_field(@cron_tab, :mday)
16
+ = form_text_field(@cron_tab, :month)
17
+ = form_text_field(@cron_tab, :wday)
18
+ = form_checkbox(@cron_tab, :enabled)
19
+ = render 'common/update_actions', form_cancel_path: index_path