web47core 0.8.1 → 0.9.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85a1b6e625ef9c79d09fca54ade10cc6b7198582ef753e0ca0cb153af3d01d48
4
- data.tar.gz: f5e8926a67eb5667222cdb6eb420a532b8f589ac697c4d9ed89f8b2f9e955f2e
3
+ metadata.gz: 331b65fbd9561ea834ab58be8f8a541ed8a25879649d7fda6f52a4f2fa7213b1
4
+ data.tar.gz: cffa42c73158759ef60ed79a1f93f8dab010ed670b56c4c687c2a218cfd903d5
5
5
  SHA512:
6
- metadata.gz: c6426b56a727ac5ba567a99e586737f98e02d1959da73736869ad872c1e9059dab0826691ff71546e3e35830d7307404981ffb0fdb96900854d1bbd6f2e167ea
7
- data.tar.gz: ab293fdf38d406356d332eba27ea0be7a61d2b3e6799589caf8477dea227bad039a12d94bc121ff08a5a50c800552e815242bed9b6b944881ee70520214fa6b0
6
+ metadata.gz: 1a45eed2e90bc93d1330df86e0d5e0ecbb83fe1868f697ec5b55835fbe72fa373498167e0784068d4f415d2d3e8465022cfe5372d7989d563146fa43181083c2
7
+ data.tar.gz: 3b8b1d55228cbe1344db41315addca98a47b0cf32e15fe9cb34b6efd3ecd3cb4bf8d6344fb04de677cc2286e771bfee305fc511499bded3713d15734c100af0f
@@ -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: text_status(components) }
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 text_status(components)
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
- content_tag(:select, id: form_name, name: form_name, class: options[:input_classes]) do
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.first,
106
- value: option_value.last,
107
- selected: value.to_s.eql?(option_value.first.to_s) }
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
- # Create a copy tag for data to be copied to the clipboard
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-button', data: datum) do
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 an thingy
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
- 'edit'
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
- content_tag(:a, href: path, class: options[:link_classes]) do
160
+ icon = options[:icon] || 'info'
161
+ content_tag(:a, href: path) do
140
162
  concat(content_tag(:i, class: 'material-icons') do
141
- 'info'
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
- content_tag(:a, href: path, class: options[:link_classes]) do
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? :delete, obj
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? :delete, obj
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?(:manage, klass)
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(content_tag(:a, href: path, class: 'btn-floating btn-large right', style: 'padding: 0;margin: 0px 15px') do
222
- concat(content_tag(:i, class: 'material-icons') { 'add' })
223
- end)
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('ui_form.actions.cancel'))
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(obj)
241
- return unless can? :update, obj
383
+ def form_submit_button_tag(condition = true, options = {})
384
+ return unless condition
242
385
 
243
- options = { class: 'btn-large waves-effect waves-light', type: :submit }
244
- content_tag(:button, options) do
245
- concat(t('ui_form.actions.save'))
246
- concat(content_tag(:i, class: 'material-icons right') { 'save' })
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
@@ -19,8 +19,12 @@ module CoreSystemConfigurationsController
19
19
  def update
20
20
  # @system_configuration.update_attributes_and_log! @current_admin_user, system_configuration_params
21
21
  SystemConfiguration.configuration.update! system_configuration_params
22
- flash[:info] = 'System Configuration Updated, sync job running in the background'
23
- Cron::SwitchboardSyncConfiguration.perform_later
22
+ if SystemConfiguration.switchboard_configured?
23
+ flash[:info] = 'System Configuration Updated, sync job running in the background'
24
+ Cron::SwitchboardSyncConfiguration.perform_later
25
+ else
26
+ flash[:info] = 'System Configuration Updated'
27
+ end
24
28
  redirect_to index_path
25
29
  rescue StandardError => error
26
30
  log_controller_error error
@@ -55,6 +55,7 @@ module Cron
55
55
  def daemonize
56
56
  dir = @options[:pid_dir]
57
57
  FileUtils.mkdir_p(dir) unless File.exist?(dir)
58
+ GC.enable
58
59
 
59
60
  Cron::JobTab.ensure_cron_tabs
60
61
  Daemons.run_proc('cron_server', dir: @options[:pid_dir], monitor: @options[:monitor], ARGV: @args) do
@@ -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[Job TrimCollection Command Server Tab JobTab].freeze unless defined? FRAMEWORK_CLASSES
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 ||= Cron.constants.collect do |job|
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
@@ -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
  #
@@ -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('/').last.to_i
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
  #
@@ -75,6 +77,8 @@ module CoreSystemConfiguration
75
77
  validates :slack_support_channel, presence: true
76
78
  validates :slack_sales_channel, presence: true
77
79
  validates :default_time_zone, presence: true
80
+ validates :switchboard_base_url, url: true
81
+ validates :zendesk_base_url, url: true
78
82
  end
79
83
  base.extend ClassMethods
80
84
  end
@@ -16,7 +16,7 @@ module SearchAble
16
16
  #
17
17
  # Call backs
18
18
  #
19
- before_validation :update_search_and_sort_text
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(sort_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, dependent: :nullify, optional: true
26
- belongs_to :created_by, polymorphic: true, dependent: :nullify, optional: 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
@@ -51,20 +51,47 @@ module StandardModel
51
51
  # Turn the array into a list of options
52
52
  #
53
53
  def make_options(options)
54
- options.collect { |t| [t, t.humanize] }
54
+ options.collect { |t| [t.humanize, t] }
55
55
  end
56
56
 
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
- field_names(filter_names)
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
- log_change(user, model, attributes) if model.new_record? && model.valid?
93
- model.save!
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 = create(attributes)
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 = create!(attributes)
144
+ model = new(attributes)
114
145
  model.last_modified_by = user
115
146
  model.created_by = user
116
147
  model.save!
@@ -175,7 +206,7 @@ module StandardModel
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.name
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.name
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
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Web47core
4
- VERSION = '0.8.1'
4
+ VERSION = '0.9.6'
5
5
  end
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.1
4
+ version: 0.9.6
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-06-03 00:00:00.000000000 Z
11
+ date: 2020-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -306,6 +306,20 @@ dependencies:
306
306
  - - ">="
307
307
  - !ruby/object:Gem::Version
308
308
  version: '0'
309
+ - !ruby/object:Gem::Dependency
310
+ name: validate_url
311
+ requirement: !ruby/object:Gem::Requirement
312
+ requirements:
313
+ - - ">="
314
+ - !ruby/object:Gem::Version
315
+ version: '0'
316
+ type: :runtime
317
+ prerelease: false
318
+ version_requirements: !ruby/object:Gem::Requirement
319
+ requirements:
320
+ - - ">="
321
+ - !ruby/object:Gem::Version
322
+ version: '0'
309
323
  - !ruby/object:Gem::Dependency
310
324
  name: bundler
311
325
  requirement: !ruby/object:Gem::Requirement