web47core 2.0.0 → 3.0.0
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.
- checksums.yaml +4 -4
- data/README.md +111 -41
- data/app/controllers/status_controller.rb +15 -4
- data/app/helpers/core_form_helper.rb +6 -6
- data/app/helpers/core_helper.rb +1 -1
- data/app/helpers/core_link_helper.rb +47 -8
- data/app/helpers/core_nav_bar_helper.rb +5 -4
- data/app/helpers/core_table_helper.rb +80 -0
- data/app/helpers/model_modal_helper.rb +3 -3
- data/app/views/common/_create_actions.html.haml +12 -0
- data/app/views/common/_update_actions.html.haml +10 -0
- data/app/views/cron/_edit.html.haml +15 -17
- data/app/views/cron/_index.html.haml +74 -67
- data/app/views/delayed_job_metrics/_index.html.haml +27 -0
- data/app/views/delayed_job_metrics/index.html.haml +1 -0
- data/app/views/delayed_job_workers/_index.html.haml +27 -0
- data/app/views/delayed_job_workers/index.html.haml +1 -0
- data/app/views/delayed_jobs/_index.html.haml +47 -52
- data/app/views/delayed_jobs/_show.html.haml +15 -13
- data/app/views/system_configurations/_edit.html.haml +14 -9
- data/app/views/system_configurations/_show.html.haml +18 -12
- data/config/brakeman.ignore +26 -0
- data/config/brakeman.yml +2 -0
- data/config/locales/en.yml +21 -3
- data/lib/app/controllers/concerns/core_delayed_job_metrics_controller.rb +35 -0
- data/lib/app/controllers/concerns/core_delayed_job_workers_controller.rb +35 -0
- data/lib/app/controllers/concerns/core_delayed_jobs_controller.rb +2 -3
- data/lib/app/jobs/application_job.rb +0 -1
- data/lib/app/jobs/cron/command.rb +1 -4
- data/lib/app/jobs/cron/record_delayed_job_metrics.rb +25 -0
- data/lib/app/jobs/cron/restart_orphaned_delayed_jobs.rb +44 -0
- data/lib/app/jobs/cron/server.rb +32 -15
- data/lib/app/jobs/cron/switchboard_sync_configuration.rb +2 -0
- data/lib/app/jobs/cron/switchboard_sync_models.rb +2 -0
- data/lib/app/jobs/cron/tab.rb +1 -1
- data/lib/app/jobs/cron/trim_collection.rb +1 -1
- data/lib/app/jobs/cron/trim_command_jobs.rb +28 -0
- data/lib/app/jobs/cron/trim_delayed_job_metrics.rb +29 -0
- data/lib/app/jobs/cron/trim_delayed_job_workers.rb +39 -0
- data/lib/app/jobs/cron/trim_failed_delayed_jobs.rb +2 -0
- data/lib/app/models/api_token.rb +9 -0
- data/lib/app/models/command_job.rb +375 -0
- data/lib/app/models/command_job_log.rb +33 -0
- data/lib/app/models/concerns/api_tokenable.rb +38 -0
- data/lib/app/models/concerns/aws_configuration.rb +41 -0
- data/lib/app/models/concerns/cdn_url.rb +7 -0
- data/lib/app/models/concerns/core_smtp_configuration.rb +65 -0
- data/lib/app/models/concerns/core_system_configuration.rb +21 -204
- data/lib/app/models/concerns/delayed_job_configuration.rb +24 -0
- data/lib/app/models/concerns/email_able.rb +7 -3
- data/lib/app/models/concerns/search_able.rb +16 -0
- data/lib/app/models/concerns/server_process_able.rb +69 -0
- data/lib/app/models/concerns/slack_configuration.rb +38 -0
- data/lib/app/models/concerns/standard_model.rb +8 -9
- data/lib/app/models/concerns/switchboard_configuration.rb +43 -0
- data/lib/app/models/concerns/twilio_configuration.rb +37 -0
- data/lib/app/models/concerns/zendesk_configuration.rb +92 -0
- data/lib/app/models/{delayed_job.rb → delayed/backend/delayed_job.rb} +41 -0
- data/lib/app/models/delayed/jobs/metric.rb +61 -0
- data/lib/app/models/delayed/jobs/run.rb +40 -0
- data/lib/app/models/delayed/jobs/worker.rb +43 -0
- data/lib/app/models/delayed/plugins/time_keeper.rb +33 -0
- data/lib/app/models/delayed/worker.rb +24 -0
- data/lib/app/models/email_notification.rb +2 -1
- data/lib/app/models/email_template.rb +5 -6
- data/lib/app/models/notification.rb +12 -2
- data/lib/app/models/notification_template.rb +1 -1
- data/lib/app/models/sms_notification.rb +9 -6
- data/lib/app/models/smtp_configuration.rb +3 -3
- data/lib/app/models/template.rb +12 -12
- data/lib/web47core/version.rb +1 -1
- data/lib/web47core.rb +35 -9
- metadata +147 -216
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 566b3144e56826da109dad9c9aae596d8ae7f875d92d253f846dda027a44911b
|
4
|
+
data.tar.gz: 1e3688dcb0aea6d837b27a9417f085f6c0243577c2cc012cb65946ae22a3564f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d355f655ffa529310e5b482b9cf24aec78dee43058214b48804f71db4aab8998bca051f5a6bff384dc5e3d4aa3f593b0ef65d6ff345598cb9dc2b03cdf556240
|
7
|
+
data.tar.gz: 2b57edd50900933a14f46bc39c8e382d5562cc422e542a5380b357544789972a2af1d3bbc636a5c118b17210086cc20fc1276613930d3b09dfacbe9a5adea7c9
|
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
|
-
*
|
7
|
-
*
|
8
|
-
*
|
9
|
-
*
|
6
|
+
* [](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Grade)
|
7
|
+
* [](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Coverage)
|
8
|
+
* Develop: [](https://circleci.com/gh/App47/web47core/tree/develop)
|
9
|
+
* Master: [](https://circleci.com/gh/App47/web47core/tree/master)
|
10
10
|
|
11
11
|
## Requirements
|
12
12
|
|
13
|
-
*
|
13
|
+
* Ruby 2.7.0
|
14
14
|
|
15
|
-
### Working with Bundler and
|
15
|
+
### Working with Bundler and RBENV
|
16
16
|
|
17
|
-
This project manages
|
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
|
20
|
-
Then install Ruby 2.7.0
|
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
|
-
|
22
|
+
rbenv install 2.7.0
|
23
23
|
```
|
24
|
-
You'll now notice that this project (as well as other App47 ones) contains a .
|
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.
|
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.
|
47
|
-
2.
|
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 `
|
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
|
-
|
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.
|
81
|
-
11.
|
82
|
-
12.
|
83
|
-
13.
|
84
|
-
14.
|
85
|
-
15.
|
86
|
-
16.
|
87
|
-
17.
|
88
|
-
18.
|
89
|
-
19.
|
90
|
-
20.
|
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
|
-
*
|
138
|
-
*
|
139
|
-
*
|
140
|
-
*
|
141
|
-
*
|
142
|
-
*
|
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
|
-
####
|
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
|
-
|
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
|
-
|
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.
|
81
|
-
|
82
|
-
|
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
|
@@ -91,7 +96,13 @@ class StatusController < ActionController::Base
|
|
91
96
|
#
|
92
97
|
def delayed_jobs_status
|
93
98
|
count = Delayed::Backend::Mongoid::Job.count
|
94
|
-
|
99
|
+
oldest = Delayed::Backend::Mongoid::Job.asc(:_id).limit(1).first
|
100
|
+
job_age = if oldest.present?
|
101
|
+
Time.now.utc.to_i - oldest.created_at.to_i
|
102
|
+
else
|
103
|
+
0
|
104
|
+
end
|
105
|
+
report_success "#{count} Jobs", count: count, job_age: job_age
|
95
106
|
rescue StandardError => error
|
96
107
|
report_error(error)
|
97
108
|
end
|
@@ -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]
|
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]
|
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(
|
250
|
+
concat(" #{error.join(', ')}") if error.present?
|
251
251
|
end
|
252
252
|
end
|
253
253
|
|
data/app/helpers/core_helper.rb
CHANGED
@@ -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: '
|
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,
|
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.
|
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:
|
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
|
-
|
21
|
+
case names
|
22
|
+
when String
|
22
23
|
states << 'active' if names.eql?(controller.controller_name)
|
23
|
-
|
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
|
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
|
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
|
-
|
4
|
-
%
|
5
|
-
%
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|