web47core 0.8.3 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/status_controller.rb +3 -3
- data/app/helpers/core_form_helper.rb +68 -4
- data/app/helpers/core_link_helper.rb +176 -24
- data/app/helpers/model_modal_helper.rb +1 -1
- data/app/views/delayed_jobs/_index.html.haml +1 -1
- data/app/views/delayed_jobs/_show.html.haml +1 -1
- data/lib/app/jobs/cron/command.rb +1 -0
- data/lib/app/jobs/cron/job.rb +11 -0
- data/lib/app/jobs/cron/job_tab.rb +10 -2
- data/lib/app/jobs/cron/server.rb +2 -1
- data/lib/app/jobs/cron/tab.rb +11 -9
- data/lib/app/jobs/cron/trim_audit_logs.rb +0 -12
- data/lib/app/models/concerns/core_system_configuration.rb +2 -0
- data/lib/app/models/concerns/search_able.rb +2 -2
- data/lib/app/models/concerns/standard_model.rb +44 -13
- data/lib/app/models/concerns/time_zone_able.rb +10 -0
- data/lib/web47core/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e0b1664a0cf7a2a9b435dd224f6f5399564c83340097c794e3c4ae345ca1767
|
4
|
+
data.tar.gz: 046b4c0fedefdb6dcedbc788073ea1853c4aa5ff5ccd2412759f51f717733586
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee44f34b70c2730d80af477a134dba80f0398313219cfcc49dbe4d0c339c746c8dd89821ffa5c974e4cbdc455859f0f4df6d9740a45fe29660b32f359a9c6267
|
7
|
+
data.tar.gz: 603080da29cc1ca86b9d97b6710aa9e60529335182d9c8010db7ae769b6a69a9420946c8dbef68b82fcc213f130e3edd375e19905cef4e1832d66e6ff24f76ed
|
@@ -17,8 +17,8 @@ class StatusController < ActionController::Base
|
|
17
17
|
|
18
18
|
respond_to do |format|
|
19
19
|
format.html { render :index, locals: { components: ui_decorators(components) }, layout: false }
|
20
|
-
format.json { render json: components.to_json }
|
21
|
-
format.text { render plain: components.flatten, status:
|
20
|
+
format.json { render json: components.to_json, status: db_status(components) }
|
21
|
+
format.text { render plain: components.flatten, status: db_status(components) }
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -27,7 +27,7 @@ class StatusController < ActionController::Base
|
|
27
27
|
#
|
28
28
|
# Return the status of the key components, mongo, redis
|
29
29
|
#
|
30
|
-
def
|
30
|
+
def db_status(components)
|
31
31
|
components[:mongo][:success] && components[:redis][:success] ? 200 : 500
|
32
32
|
rescue StandardError
|
33
33
|
500
|
@@ -10,6 +10,30 @@ module CoreFormHelper
|
|
10
10
|
form.render_form(&block)
|
11
11
|
end
|
12
12
|
|
13
|
+
#
|
14
|
+
# Text area
|
15
|
+
#
|
16
|
+
def form_text_area(model, field, options = {})
|
17
|
+
classes = options[:classes] || %w[s12]
|
18
|
+
value = model.send(field)
|
19
|
+
# options[:value] = value
|
20
|
+
# options[:disabled] ||= false
|
21
|
+
# tag_options = {class: []} # text_field_options(model, field, options)
|
22
|
+
# tag_options[:class] += ['materialize-textarea']
|
23
|
+
content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
|
24
|
+
concat(text_area(model, field, value, options))
|
25
|
+
concat(form_label_tag(model, field, value, options))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def text_area(model, field, value, options = {})
|
30
|
+
tag_options = text_field_options(model, field, options)
|
31
|
+
tag_options[:class] += ['materialize-textarea']
|
32
|
+
content_tag(:textarea, tag_options) do
|
33
|
+
concat(value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
13
37
|
#
|
14
38
|
# Text field
|
15
39
|
#
|
@@ -18,6 +42,7 @@ module CoreFormHelper
|
|
18
42
|
value = model.send(field)
|
19
43
|
options[:type] = :text
|
20
44
|
options[:value] = value
|
45
|
+
options[:disabled] ||= false
|
21
46
|
tag_options = text_field_options(model, field, options)
|
22
47
|
content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
|
23
48
|
concat(tag(:input, tag_options))
|
@@ -30,6 +55,7 @@ module CoreFormHelper
|
|
30
55
|
value = model.send(field)
|
31
56
|
options[:value] = value.strftime('%d %B, %Y') if value.present?
|
32
57
|
options[:type] = :text
|
58
|
+
options[:disabled] ||= false
|
33
59
|
tag_options = text_field_options(model, field, options)
|
34
60
|
tag_options[:class] = options[:date_picker_type] || 'simple-date-picker'
|
35
61
|
content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
|
@@ -38,6 +64,23 @@ module CoreFormHelper
|
|
38
64
|
end
|
39
65
|
end
|
40
66
|
|
67
|
+
#
|
68
|
+
# Time picker field
|
69
|
+
#
|
70
|
+
def form_time_field(model, field, options = {})
|
71
|
+
classes = options[:classes] || %w[s12 m6 l4 xl3]
|
72
|
+
value = model.send(field)
|
73
|
+
options[:value] = value
|
74
|
+
options[:type] = :text
|
75
|
+
options[:disabled] ||= false
|
76
|
+
tag_options = text_field_options(model, field, options)
|
77
|
+
tag_options[:class] = options[:time_picker_type] || 'time-picker'
|
78
|
+
content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
|
79
|
+
concat(tag(:input, tag_options))
|
80
|
+
concat(form_label_tag(model, field, value, options))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
41
84
|
#
|
42
85
|
# Password field
|
43
86
|
#
|
@@ -80,7 +123,13 @@ module CoreFormHelper
|
|
80
123
|
#
|
81
124
|
def form_select_tag(model, field, options = {})
|
82
125
|
form_name = form_field_name(model, field, options)
|
83
|
-
|
126
|
+
select_content = {
|
127
|
+
id: form_name,
|
128
|
+
name: form_name,
|
129
|
+
class: options[:input_classes],
|
130
|
+
disabled: options[:disabled]
|
131
|
+
}
|
132
|
+
content_tag(:select, select_content) do
|
84
133
|
form_select_option_key_values(model.send(field), options).each do |value|
|
85
134
|
concat(content_tag(:option, value: value[:key], selected: value[:selected]) do
|
86
135
|
concat(value[:value])
|
@@ -96,15 +145,16 @@ module CoreFormHelper
|
|
96
145
|
select_options << { key: '', value: options[:prompt], selected: false } if options[:prompt].present?
|
97
146
|
options[:options].each do |option_value|
|
98
147
|
option_value[:display_name] = option_value.display_name if option_value.respond_to?(:display_name)
|
148
|
+
option_value[:display_name] = option_value.user_display_name if option_value.respond_to?(:user_display_name)
|
99
149
|
select_options << case option_value
|
100
150
|
when String, Integer
|
101
151
|
{ key: option_value,
|
102
152
|
value: option_value,
|
103
153
|
selected: value.eql?(option_value) }
|
104
154
|
when Array
|
105
|
-
{ key: option_value.
|
106
|
-
value: option_value.
|
107
|
-
selected: value.to_s.eql?(option_value.
|
155
|
+
{ key: option_value.last,
|
156
|
+
value: option_value.first,
|
157
|
+
selected: value.to_s.eql?(option_value.last.to_s) }
|
108
158
|
when Hash
|
109
159
|
{ key: option_value[:key],
|
110
160
|
value: option_value[:value],
|
@@ -164,6 +214,20 @@ module CoreFormHelper
|
|
164
214
|
end
|
165
215
|
end
|
166
216
|
|
217
|
+
#
|
218
|
+
# File field
|
219
|
+
#
|
220
|
+
def form_file(model, field, file_types = '.xlsx', classes = %w[s12 m6 l4 xl3])
|
221
|
+
form_name = form_field_name(model, field)
|
222
|
+
form_id = "#{model.class.to_s.underscore}_#{field}"
|
223
|
+
value = model.send(field)
|
224
|
+
file_tag = tag(:input, id: form_id, name: form_name, type: :file, accept: file_types)
|
225
|
+
content_tag(:div, class: (%w[input-field col] + classes).join(' ')) do
|
226
|
+
concat(file_tag)
|
227
|
+
concat(form_label_tag(model, field, value))
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
167
231
|
#
|
168
232
|
# get the label for field
|
169
233
|
#
|
@@ -5,12 +5,22 @@
|
|
5
5
|
#
|
6
6
|
module CoreLinkHelper
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# Generate a download link with the download icon
|
9
|
+
#
|
10
|
+
def download_tag(url, options = {})
|
11
|
+
content_tag(:a, href: url) do
|
12
|
+
concat(materialize_icon(options[:download_icon_name] || 'cloud_download'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Setup the text as copy text
|
9
18
|
#
|
10
19
|
def copy_tag(copy_text, options = {})
|
11
20
|
content_tag(:p, class: 'stack-tight') do
|
12
|
-
concat(copy_text)
|
21
|
+
concat(content_tag(:span) { copy_text })
|
13
22
|
concat(copy_text_tag(copy_text, options))
|
23
|
+
concat(download_tag(options[:download_url], options)) if options[:download_url].present?
|
14
24
|
end
|
15
25
|
end
|
16
26
|
|
@@ -34,11 +44,21 @@ module CoreLinkHelper
|
|
34
44
|
constrainWidth: false,
|
35
45
|
gutter: 28,
|
36
46
|
alignment: 'right' }
|
37
|
-
content_tag(:a, class: 'dropdown-
|
47
|
+
content_tag(:a, class: 'dropdown-trigger', data: datum) do
|
38
48
|
concat(materialize_icon(icon_name))
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
52
|
+
#
|
53
|
+
# Add a favorite tag
|
54
|
+
#
|
55
|
+
def favorite_tag(favorite)
|
56
|
+
content_tag(:i,
|
57
|
+
class: 'material-icons pointer favorite',
|
58
|
+
id: favorite.id.to_s,
|
59
|
+
type: favorite.favorite_type) { concat('favorite_border') }
|
60
|
+
end
|
61
|
+
|
42
62
|
#
|
43
63
|
# Add a material icon by name
|
44
64
|
#
|
@@ -52,7 +72,7 @@ module CoreLinkHelper
|
|
52
72
|
# Generic link tag
|
53
73
|
#
|
54
74
|
def link_tag(title, path, options = {})
|
55
|
-
content_tag(:a, href: path) do
|
75
|
+
content_tag(:a, href: path, class: options[:class]) do
|
56
76
|
concat(content_tag(:i, class: 'material-icons left') { options[:icon_name] }) if options[:icon_name].present?
|
57
77
|
concat(title)
|
58
78
|
end
|
@@ -71,14 +91,15 @@ module CoreLinkHelper
|
|
71
91
|
end
|
72
92
|
|
73
93
|
#
|
74
|
-
# Edit
|
94
|
+
# Edit a thingy
|
75
95
|
#
|
76
96
|
def edit_link_tag(obj, path, options = {})
|
77
97
|
return unless can? :edit, obj
|
78
98
|
|
99
|
+
icon = options[:icon] || 'edit'
|
79
100
|
content_tag(:a, href: path) do
|
80
101
|
concat(content_tag(:i, class: 'material-icons') do
|
81
|
-
|
102
|
+
icon
|
82
103
|
end)
|
83
104
|
concat(options[:label]) if options[:label].present?
|
84
105
|
end
|
@@ -136,9 +157,10 @@ module CoreLinkHelper
|
|
136
157
|
def info_link_tag(obj, path, options = {})
|
137
158
|
return unless can? :read, obj
|
138
159
|
|
139
|
-
|
160
|
+
icon = options[:icon] || 'info'
|
161
|
+
content_tag(:a, href: path) do
|
140
162
|
concat(content_tag(:i, class: 'material-icons') do
|
141
|
-
|
163
|
+
icon
|
142
164
|
end)
|
143
165
|
concat(options[:label]) if options[:label].present?
|
144
166
|
end
|
@@ -149,6 +171,7 @@ module CoreLinkHelper
|
|
149
171
|
#
|
150
172
|
def action_list_tag(condition, path, options = {})
|
151
173
|
return unless condition
|
174
|
+
|
152
175
|
raise('Label Required') if options[:label].blank?
|
153
176
|
|
154
177
|
content_tag(:li) do
|
@@ -162,7 +185,9 @@ module CoreLinkHelper
|
|
162
185
|
def action_link_tag(condition, path, options = {})
|
163
186
|
return unless condition
|
164
187
|
|
165
|
-
|
188
|
+
confirmation = options[:confirmation] || t('links.action_confirmation')
|
189
|
+
confirmation_required = options[:confirmation].present? ? { confirm: confirmation } : {}
|
190
|
+
content_tag(:a, href: path, class: options[:classes], data: confirmation_required) do
|
166
191
|
concat(content_tag(:i, class: 'material-icons') do
|
167
192
|
options[:icon_name] || 'info'
|
168
193
|
end)
|
@@ -174,7 +199,7 @@ module CoreLinkHelper
|
|
174
199
|
# Delete a thingy in a pull down list
|
175
200
|
#
|
176
201
|
def delete_list_tag(obj, path, options = {})
|
177
|
-
return unless can? :
|
202
|
+
return unless can? :destroy, obj
|
178
203
|
|
179
204
|
options[:label] ||= I18n.t('ui_form.actions.delete')
|
180
205
|
content_tag(:li) do
|
@@ -186,7 +211,7 @@ module CoreLinkHelper
|
|
186
211
|
# Delete an thingy
|
187
212
|
#
|
188
213
|
def delete_link_tag(obj, path, options = {})
|
189
|
-
return unless can? :
|
214
|
+
return unless can? :destroy, obj
|
190
215
|
|
191
216
|
data = { method: :delete,
|
192
217
|
confirm: options[:confirm] || t('links.deletion_confirmation', name: obj.class.to_s.underscore.humanize) }
|
@@ -198,6 +223,111 @@ module CoreLinkHelper
|
|
198
223
|
end
|
199
224
|
end
|
200
225
|
|
226
|
+
#
|
227
|
+
# Create a thingy in a pull-down list
|
228
|
+
#
|
229
|
+
def create_list_tag(obj, path, options = {})
|
230
|
+
return unless can? :create, obj
|
231
|
+
|
232
|
+
options[:label] ||= I18n.t('ui_form.actions.create')
|
233
|
+
content_tag(:li) do
|
234
|
+
create_link_tag(obj, path, options)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
#
|
239
|
+
# Create a thingy
|
240
|
+
#
|
241
|
+
def create_link_tag(obj, path, options = {})
|
242
|
+
return unless can? :create, obj
|
243
|
+
|
244
|
+
confirmation = options[:confirmation] || t('links.action_confirmation', name: obj.class.to_s.underscore.humanize)
|
245
|
+
content_tag(:a, href: path, data: { confirm: confirmation }) do
|
246
|
+
concat(content_tag(:i, class: 'material-icons') do
|
247
|
+
options[:icon_name] || 'add'
|
248
|
+
end)
|
249
|
+
concat(options[:label]) if options[:label].present?
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
#
|
254
|
+
# Send notification in a pull down list
|
255
|
+
#
|
256
|
+
def notification_list_tag(obj, path, options = {})
|
257
|
+
return unless can? :manage, obj
|
258
|
+
|
259
|
+
options[:label] ||= I18n.t('customer_account_users.index.reset_password')
|
260
|
+
content_tag(:li) do
|
261
|
+
notification_link_tag(obj, path, options)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
#
|
266
|
+
# Send notification
|
267
|
+
#
|
268
|
+
def notification_link_tag(obj, path, options = {})
|
269
|
+
return unless can? :manage, obj
|
270
|
+
|
271
|
+
content_tag(:a, href: path) do
|
272
|
+
concat(content_tag(:i, class: 'material-icons') do
|
273
|
+
options[:icon_name] || 'email'
|
274
|
+
end)
|
275
|
+
concat(options[:label]) if options[:label].present?
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
#
|
280
|
+
# Promote a publishable kb object in a pull down list
|
281
|
+
#
|
282
|
+
def promote_list_tag(obj, path, options = {})
|
283
|
+
return unless can? :promote, obj
|
284
|
+
|
285
|
+
options[:label] ||= I18n.t('links.promote')
|
286
|
+
content_tag(:li) do
|
287
|
+
promote_link_tag(obj, path, options)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
#
|
292
|
+
# Promote a publishable kb object
|
293
|
+
#
|
294
|
+
def promote_link_tag(obj, path, options = {})
|
295
|
+
return unless can? :promote, obj
|
296
|
+
|
297
|
+
content_tag(:a, href: path) do
|
298
|
+
concat(content_tag(:i, class: 'material-icons') do
|
299
|
+
'file_upload'
|
300
|
+
end)
|
301
|
+
concat(options[:label]) if options[:label].present?
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# Demote a publishable kb object in a pull down list
|
307
|
+
#
|
308
|
+
def demote_list_tag(obj, path, options = {})
|
309
|
+
return unless can? :demote, obj
|
310
|
+
|
311
|
+
options[:label] ||= I18n.t('links.demote')
|
312
|
+
content_tag(:li) do
|
313
|
+
demote_link_tag(obj, path, options)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
#
|
318
|
+
# Demote a publishable kb object
|
319
|
+
#
|
320
|
+
def demote_link_tag(obj, path, options = {})
|
321
|
+
return unless can? :demote, obj
|
322
|
+
|
323
|
+
content_tag(:a, href: path) do
|
324
|
+
concat(content_tag(:i, class: 'material-icons') do
|
325
|
+
'file_download'
|
326
|
+
end)
|
327
|
+
concat(options[:label]) if options[:label].present?
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
201
331
|
#
|
202
332
|
# Edit a page
|
203
333
|
#
|
@@ -214,36 +344,58 @@ module CoreLinkHelper
|
|
214
344
|
#
|
215
345
|
# Add a thingy
|
216
346
|
#
|
217
|
-
def add_link_tag(klass, path)
|
218
|
-
return unless can?(:
|
347
|
+
def add_link_tag(klass, path, options = {})
|
348
|
+
return unless can?(:create, klass)
|
219
349
|
|
220
350
|
content_tag(:div, class: 'fixed-action-btn horizontal') do
|
221
|
-
concat(
|
222
|
-
|
223
|
-
|
351
|
+
concat(add_link_button(path, options))
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
#
|
356
|
+
# Add the `Add` button
|
357
|
+
#
|
358
|
+
def add_link_button(path, options)
|
359
|
+
options[:title] ||= t('ui_form.actions.add')
|
360
|
+
options[:icon] ||= 'add'
|
361
|
+
content_tag(:a,
|
362
|
+
href: path,
|
363
|
+
class: 'btn-floating btn-large right',
|
364
|
+
style: 'padding: 0;margin: 0px 15px',
|
365
|
+
title: options[:title]) do
|
366
|
+
concat(content_tag(:i, class: 'material-icons') { options[:icon] })
|
224
367
|
end
|
225
368
|
end
|
226
369
|
|
227
370
|
#
|
228
371
|
# Form cancel button
|
229
372
|
#
|
230
|
-
def form_cancel_button_tag(path)
|
373
|
+
def form_cancel_button_tag(path, name = 'cancel')
|
231
374
|
options = { class: 'btn-large waves-effect waves-light secondary', href: path }
|
232
375
|
content_tag(:a, options) do
|
233
|
-
concat(t(
|
376
|
+
concat(t("ui_form.actions.#{name}"))
|
234
377
|
end
|
235
378
|
end
|
236
379
|
|
237
380
|
#
|
238
381
|
# Form submit button
|
239
382
|
#
|
240
|
-
def form_submit_button_tag(
|
241
|
-
return unless
|
383
|
+
def form_submit_button_tag(condition = true, options = {})
|
384
|
+
return unless condition
|
242
385
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
386
|
+
tag_options = { class: 'btn-large waves-effect waves-light', type: :submit }
|
387
|
+
if options[:action].present?
|
388
|
+
tag_options[:name] = options[:name] || 'button_action'
|
389
|
+
tag_options[:value] = options[:action]
|
390
|
+
end
|
391
|
+
tag_options[:class] += ' disabled' if options[:disabled]
|
392
|
+
tag_options[:class] += ' disabled' if options[:disabled]
|
393
|
+
|
394
|
+
button_text = options[:text] || t('ui_form.actions.save')
|
395
|
+
button_icon = options[:icon] || 'save'
|
396
|
+
content_tag(:button, tag_options) do
|
397
|
+
concat(button_text)
|
398
|
+
concat(content_tag(:i, class: 'material-icons right') { button_icon })
|
247
399
|
end
|
248
400
|
end
|
249
401
|
end
|
@@ -160,7 +160,7 @@ module ModelModalHelper
|
|
160
160
|
end
|
161
161
|
|
162
162
|
def model_modal_standard(model, _options = {})
|
163
|
-
content_tag(:table, class: 'center-align
|
163
|
+
content_tag(:table, class: 'center-align highlight') do
|
164
164
|
concat(content_tag(:tbody) do
|
165
165
|
%w[_id _type created_at updated_at search_text sort_text].each do |field_name|
|
166
166
|
concat(model_modal_field(model, field_name))
|
@@ -34,7 +34,7 @@
|
|
34
34
|
.container
|
35
35
|
.row
|
36
36
|
.col.s12
|
37
|
-
%table.
|
37
|
+
%table.highlight.bordered.extended{data: {sort: {column: 'Run At,Priority', direction: 'desc,asc'}}}
|
38
38
|
%thead
|
39
39
|
%tr
|
40
40
|
%th=t('.run_at')
|
data/lib/app/jobs/cron/job.rb
CHANGED
@@ -27,5 +27,16 @@ module Cron
|
|
27
27
|
email.from_template('support_ticket_notification', params)
|
28
28
|
email.send_notification
|
29
29
|
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Sends support a notification if something goes awry
|
33
|
+
#
|
34
|
+
def notify_job_failure(error, event)
|
35
|
+
message = { job_name: self.class.to_s.titleize,
|
36
|
+
event: event,
|
37
|
+
error_message: error.message,
|
38
|
+
stack_trace: error.backtrace }
|
39
|
+
SlackNotification.say message, to: SystemConfiguration.slack_support_channel, template: :job_failure
|
40
|
+
end
|
30
41
|
end
|
31
42
|
end
|
@@ -5,7 +5,7 @@ module Cron
|
|
5
5
|
# Value object for a cron tab entry
|
6
6
|
#
|
7
7
|
class JobTab < Tab
|
8
|
-
FRAMEWORK_CLASSES = %w[
|
8
|
+
FRAMEWORK_CLASSES = %w[job trim_collection command server tab job_tab].freeze unless defined? FRAMEWORK_CLASSES
|
9
9
|
#
|
10
10
|
# Validations
|
11
11
|
#
|
@@ -36,7 +36,7 @@ module Cron
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def job_names
|
39
|
-
@job_names ||=
|
39
|
+
@job_names ||= all_jobs.collect do |job|
|
40
40
|
job_name = job.to_s
|
41
41
|
next if FRAMEWORK_CLASSES.include?(job_name) || job_name.end_with?('Test') || job_name.start_with?('Base')
|
42
42
|
|
@@ -46,6 +46,14 @@ module Cron
|
|
46
46
|
|
47
47
|
private
|
48
48
|
|
49
|
+
def all_jobs
|
50
|
+
(list_jobs("#{__dir__}/*.rb") + list_jobs(Rails.root.join('app/jobs/cron/*.rb'))).compact.uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
def list_jobs(directory)
|
54
|
+
Dir[directory].collect { |file| file.split('/cron/').last.split('.rb').first }
|
55
|
+
end
|
56
|
+
|
49
57
|
def configure_cron_tab(tab, type)
|
50
58
|
case type
|
51
59
|
when :always
|
data/lib/app/jobs/cron/server.rb
CHANGED
@@ -48,6 +48,7 @@ module Cron
|
|
48
48
|
time_to_next_run
|
49
49
|
ensure
|
50
50
|
check_in
|
51
|
+
GC.start
|
51
52
|
end
|
52
53
|
|
53
54
|
def run_cron_jobs
|
@@ -151,7 +152,7 @@ module Cron
|
|
151
152
|
# Perform a check in for the server
|
152
153
|
#
|
153
154
|
def check_in
|
154
|
-
set last_check_in_at: Time.now.utc
|
155
|
+
set({ last_check_in_at: Time.now.utc })
|
155
156
|
end
|
156
157
|
|
157
158
|
#
|
data/lib/app/jobs/cron/tab.rb
CHANGED
@@ -11,6 +11,8 @@ module Cron
|
|
11
11
|
# Constants
|
12
12
|
#
|
13
13
|
WILDCARD = '*' unless defined? WILDCARD
|
14
|
+
COMMA_DELIM = ',' unless defined? COMMA_DELIM
|
15
|
+
SLASH_DEMO = '/' unless defined? SLASH_DEMO
|
14
16
|
TIME_UNITS = %i[min hour wday mday month].freeze unless defined? TIME_UNITS
|
15
17
|
#
|
16
18
|
# Fields
|
@@ -45,7 +47,7 @@ module Cron
|
|
45
47
|
# For completion of class, but must be implemented by child class
|
46
48
|
#
|
47
49
|
def run
|
48
|
-
set last_run_at: Time.now.utc
|
50
|
+
set({ last_run_at: Time.now.utc })
|
49
51
|
end
|
50
52
|
|
51
53
|
private
|
@@ -69,11 +71,11 @@ module Cron
|
|
69
71
|
when Integer
|
70
72
|
range.include?(value)
|
71
73
|
else
|
72
|
-
if value.include?(
|
73
|
-
(numerator, divisor) = value.split(
|
74
|
+
if value.include?(SLASH_DEMO)
|
75
|
+
(numerator, divisor) = value.split(SLASH_DEMO)
|
74
76
|
range.include?(divisor.to_i) && numerator.eql?(WILDCARD)
|
75
|
-
elsif value.include?(
|
76
|
-
options = value.split(
|
77
|
+
elsif value.include?(COMMA_DELIM)
|
78
|
+
options = value.split(COMMA_DELIM)
|
77
79
|
options.collect { |o| range.include?(o.to_i) }.all?
|
78
80
|
else
|
79
81
|
range.include?(value.to_i)
|
@@ -96,11 +98,11 @@ module Cron
|
|
96
98
|
when Integer
|
97
99
|
time.send(unit).eql?(target)
|
98
100
|
else
|
99
|
-
if target.include?(
|
100
|
-
divisor = target.split(
|
101
|
+
if target.include?(SLASH_DEMO)
|
102
|
+
divisor = target.split(SLASH_DEMO).last.to_i
|
101
103
|
(time.send(unit) % divisor).zero?
|
102
|
-
elsif target.include?(
|
103
|
-
options = target.split(
|
104
|
+
elsif target.include?(COMMA_DELIM)
|
105
|
+
options = target.split(COMMA_DELIM)
|
104
106
|
options.collect { |o| time.send(unit.eql?(o.to_i)) }.any?
|
105
107
|
else
|
106
108
|
time.send(unit).eql?(target.to_i)
|
@@ -12,18 +12,6 @@ module Cron
|
|
12
12
|
AuditLog.all
|
13
13
|
end
|
14
14
|
|
15
|
-
#
|
16
|
-
# Check which audit logs we wanted deleted
|
17
|
-
#
|
18
|
-
# Should be older than 90 days and either not a user model audit log or the model associated with
|
19
|
-
# the UserModelAuditLog has been deleted
|
20
|
-
#
|
21
|
-
def archive?(item)
|
22
|
-
super && (!item.is_a?(UserModelAuditLog) || item.model.blank?)
|
23
|
-
rescue StandardError
|
24
|
-
super
|
25
|
-
end
|
26
|
-
|
27
15
|
#
|
28
16
|
# Allowed time the amount of time allowed to exists before deleting
|
29
17
|
#
|
@@ -68,6 +68,8 @@ module CoreSystemConfiguration
|
|
68
68
|
field :switchboard_stack_id, type: String
|
69
69
|
field :switchboard_stack_api_token, type: String
|
70
70
|
field :switchboard_last_sync_at, type: Time
|
71
|
+
# Audit Logs TTL
|
72
|
+
field :user_model_audit_log_ttl, type: Integer, default: 365
|
71
73
|
#
|
72
74
|
# Validations
|
73
75
|
#
|
@@ -16,7 +16,7 @@ module SearchAble
|
|
16
16
|
#
|
17
17
|
# Call backs
|
18
18
|
#
|
19
|
-
|
19
|
+
before_save :update_search_and_sort_text
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -31,7 +31,7 @@ module SearchAble
|
|
31
31
|
#
|
32
32
|
module ClassMethods
|
33
33
|
def matching_search_text(search_text = nil)
|
34
|
-
(search_text.blank? ? all : where(search_text: /#{search_text.downcase}/)).order(
|
34
|
+
(search_text.blank? ? all : where(search_text: /#{search_text.downcase}/)).order([:sort_text, 1])
|
35
35
|
end
|
36
36
|
|
37
37
|
def sort_order
|
@@ -22,8 +22,8 @@ module StandardModel
|
|
22
22
|
#
|
23
23
|
# Relationships
|
24
24
|
#
|
25
|
-
belongs_to :last_modified_by, polymorphic: true,
|
26
|
-
belongs_to :created_by, polymorphic: true,
|
25
|
+
belongs_to :last_modified_by, polymorphic: true, optional: true
|
26
|
+
belongs_to :created_by, polymorphic: true, optional: true
|
27
27
|
has_many Web47core::Config.audit_model_log_symbol, dependent: :nullify, inverse_of: :model
|
28
28
|
#
|
29
29
|
# Callbacks
|
@@ -57,14 +57,41 @@ module StandardModel
|
|
57
57
|
#
|
58
58
|
# Return the complete list of key names that would appear in the form.
|
59
59
|
#
|
60
|
-
def allowed_param_names(filter_names = [])
|
60
|
+
def allowed_param_names(filter_names = [], include_relationships = true)
|
61
61
|
# Always filter out the mongoid reserved items
|
62
|
-
filter_names += %w[created_at updated_at _type _id]
|
63
|
-
|
62
|
+
filter_names += %w[created_at updated_at _type _id search_text sort_text]
|
63
|
+
associations = many_to_many_associations
|
64
|
+
# filter out the relationship names so we don't have dups
|
65
|
+
associations.each { |association| filter_names << association.keys.first }
|
66
|
+
names = field_names(filter_names)
|
67
|
+
names += associations if include_relationships
|
68
|
+
names.delete_if { |name| filter_names.include?(name) }
|
64
69
|
rescue StandardError
|
65
70
|
attribute_names.delete_if { |name| filter_names.include?(name) }
|
66
71
|
end
|
67
72
|
|
73
|
+
#
|
74
|
+
# Return a collection of many to many associations. We basically
|
75
|
+
# need to turn the current value returned by attribute names
|
76
|
+
#
|
77
|
+
# relationship_ids
|
78
|
+
#
|
79
|
+
# to
|
80
|
+
#
|
81
|
+
# { relationship_ids => [] }
|
82
|
+
#
|
83
|
+
# Telling the permit command to accept the value as an array of items.
|
84
|
+
#
|
85
|
+
def many_to_many_associations
|
86
|
+
associations = []
|
87
|
+
reflect_on_all_associations.each do |association|
|
88
|
+
next unless association.macro == :has_and_belongs_to_many
|
89
|
+
|
90
|
+
associations << { association.key => [] }
|
91
|
+
end
|
92
|
+
associations
|
93
|
+
end
|
94
|
+
|
68
95
|
#
|
69
96
|
# allow the model to filter out a name if they want to, meaning the model
|
70
97
|
# can return a subset of attribute names
|
@@ -89,8 +116,12 @@ module StandardModel
|
|
89
116
|
#
|
90
117
|
def find_or_create_by_and_log!(user, attributes)
|
91
118
|
model = find_or_initialize_by(attributes)
|
92
|
-
|
93
|
-
|
119
|
+
if model.new_record?
|
120
|
+
model.last_modified_by = user
|
121
|
+
model.created_by = user
|
122
|
+
model.save!
|
123
|
+
log_change(user, model, attributes)
|
124
|
+
end
|
94
125
|
model
|
95
126
|
end
|
96
127
|
|
@@ -98,7 +129,7 @@ module StandardModel
|
|
98
129
|
# Record the creation with this user
|
99
130
|
#
|
100
131
|
def create_and_log(user, attributes)
|
101
|
-
model =
|
132
|
+
model = new(attributes)
|
102
133
|
model.last_modified_by = user
|
103
134
|
model.created_by = user
|
104
135
|
model.save
|
@@ -110,7 +141,7 @@ module StandardModel
|
|
110
141
|
# Record the creation with this user
|
111
142
|
#
|
112
143
|
def create_and_log!(user, attributes)
|
113
|
-
model =
|
144
|
+
model = new(attributes)
|
114
145
|
model.last_modified_by = user
|
115
146
|
model.created_by = user
|
116
147
|
model.save!
|
@@ -169,13 +200,13 @@ module StandardModel
|
|
169
200
|
Rails.cache.delete_matched "*#{account.id}*"
|
170
201
|
true # Force a return of true so that we don't break the callback chain.
|
171
202
|
rescue StandardError
|
172
|
-
|
203
|
+
true
|
173
204
|
end
|
174
205
|
|
175
206
|
#
|
176
207
|
# record a change for the object instance
|
177
208
|
#
|
178
|
-
def log_change(user, changes, action)
|
209
|
+
def log_change(user, changes, action = nil)
|
179
210
|
Web47core::Config.audit_model_log_class.create!(Web47core::Config.audit_model => user,
|
180
211
|
model: self,
|
181
212
|
action: action,
|
@@ -190,7 +221,7 @@ module StandardModel
|
|
190
221
|
# Safely get the display name of who last modified this object
|
191
222
|
#
|
192
223
|
def last_modified_by_display_name
|
193
|
-
last_modified_by.
|
224
|
+
last_modified_by.display_name
|
194
225
|
rescue StandardError
|
195
226
|
"#{last_modified_by_name} (#{last_modified_by_email}) - deleted"
|
196
227
|
end
|
@@ -199,7 +230,7 @@ module StandardModel
|
|
199
230
|
# Safely get the display name of who created this object
|
200
231
|
#
|
201
232
|
def created_by_display_name
|
202
|
-
created_by.
|
233
|
+
created_by.display_name
|
203
234
|
rescue StandardError
|
204
235
|
"#{created_by_name} (#{created_by_email}) - deleted"
|
205
236
|
end
|
@@ -27,6 +27,16 @@ module TimeZoneAble
|
|
27
27
|
TZInfo::Timezone.all_identifiers
|
28
28
|
end
|
29
29
|
|
30
|
+
#
|
31
|
+
# Return the given time in the localized time for this object
|
32
|
+
#
|
33
|
+
def local_date(date, format = :medium, default = 'N/A')
|
34
|
+
tz = TZInfo::Timezone.get(time_zone || 'GMT')
|
35
|
+
date.present? ? I18n.l(date.in_time_zone(tz).to_date, format: format) : default
|
36
|
+
rescue StandardError
|
37
|
+
default
|
38
|
+
end
|
39
|
+
|
30
40
|
#
|
31
41
|
# Return the given time in the localized time for this object
|
32
42
|
#
|
data/lib/web47core/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web47core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8
|
4
|
+
version: 0.9.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Schroeder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|