Module: Backend::BaseHelper

Defined in:
app/helpers/backend/base_helper.rb

Defined Under Namespace

Classes: BasicCalendar, Menu

Instance Method Summary collapse

Instance Method Details

#accented_sort(list) ⇒ Object

Sort list of array (with label and id) with accent


57
58
59
# File 'app/helpers/backend/base_helper.rb', line 57

def accented_sort(list)
  list.sort_by { |e, _i| I18n.transliterate e }
end

#add_snippets(place, _options = {}) ⇒ Object


112
113
114
115
116
117
118
# File 'app/helpers/backend/base_helper.rb', line 112

def add_snippets(place, _options = {})
  Ekylibre::Snippet.at(place).each do |s|
    snippet(s.name, { icon: :plug }.merge(s.options)) do
      render(file: s.path)
    end
  end
end

#basic_calendar(all_records, options = {}, &block) ⇒ Object

Emulate old simple_calendar API


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'app/helpers/backend/base_helper.rb', line 83

def basic_calendar(all_records, options = {}, &block)
  # options[:events] = all_records
  options[:param_name] ||= :started_on
  BasicCalendar.new(self, options).render do |event_on, _records|
    records = all_records.select do |event|
      event_on == event.started_at.to_date
    end
    (:div) do
      (:span, event_on.day, class: 'day-number') +
        records.collect do |event|
          capture(event, &block)
        end.join.html_safe
    end
  end
end

#campaign_selector(campaign = nil, options = {}) ⇒ Object


249
250
251
252
253
254
255
256
# File 'app/helpers/backend/base_helper.rb', line 249

def campaign_selector(campaign = nil, options = {})
  unless Campaign.any?
    @current_campaign = Campaign.find_or_create_by!(harvest_year: Date.current.year)
    current_user.current_campaign = @current_campaign
  end
  campaign ||= current_campaign
  render 'backend/shared/campaign_selector', campaign: campaign, param_name: options[:param_name] || :current_campaign
end

#chronology_period(margin, width, background_color, url_options = {}, html_options = {}) ⇒ Object


425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
# File 'app/helpers/backend/base_helper.rb', line 425

def chronology_period(margin, width, background_color, url_options = {}, html_options = {})
  direction = reading_ltr? ? 'left' : 'right'
  period_margin = 100 * margin.round(6)
  period_width = 100 * width.round(6)

  style = "#{direction}: #{period_margin}%;"
  style += "width: #{period_width}%;"
  style += "background-color: #{background_color}"

  element_class = html_options[:class] || ''
  title = html_options[:title] || ''
  nested_element = html_options[:nested_element] || nil

  if nested_element.nil?
    link_to('', url_options, style: style, class: "period #{element_class}", title: title)
  else
    link_to(url_options, style: style, class: "period #{element_class}", title: title) do
      nested_element
    end
  end
end

#chronology_period_icon(positioned_at, picto_class, html_options = {}) ⇒ Object


447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
# File 'app/helpers/backend/base_helper.rb', line 447

def chronology_period_icon(positioned_at, picto_class, html_options = {})
  style = ''

  if positioned_at != 'initial'

    direction = reading_ltr? ? 'left' : 'right'
    period_icon_margin = 100 * positioned_at.round(6)
    style = "#{direction}: #{period_icon_margin}%;"
  end

  element_class = html_options[:class] || 'period'
  title = html_options[:title] || ''
  url = html_options[:url] || nil
  data_toggle = html_options['data-toggle'] || nil

  (:div, style: style, class: element_class, data: html_options[:data]) do
    if url.nil?
      (:i, '', class: "picto picto-#{picto_class}", 'data-toggle': data_toggle, title: title)
    else
      link_to(url, 'data-toggle': data_toggle, title: title) do
        (:i, '', class: "picto picto-#{picto_class}")
      end
    end
  end
end

#collectionObject


29
30
31
# File 'app/helpers/backend/base_helper.rb', line 29

def collection
  instance_variable_get('@' + controller_name)
end

#extensions_tag(place) ⇒ Object


42
43
44
# File 'app/helpers/backend/base_helper.rb', line 42

def extensions_tag(place)
  Ekylibre::View::Addon.render("extensions_#{place}", self)
end

#financial_year_selector(financial_year_id = nil, options = {}) ⇒ Object


292
293
294
295
296
297
298
# File 'app/helpers/backend/base_helper.rb', line 292

def financial_year_selector(financial_year_id = nil, options = {})
  unless FinancialYear.any?
    @current_financial_year = FinancialYear.on(Date.current)
  end
  current_user.current_financial_year = @current_financial_year || FinancialYear.find_by(id: financial_year_id)
  render 'backend/shared/financial_year_selector', financial_year: current_user.current_financial_year, param_name: options[:param_name] || :current_financial_year
end

#financial_year_started_on_stopped_onObject


300
301
302
303
# File 'app/helpers/backend/base_helper.rb', line 300

def financial_year_started_on_stopped_on
  fy = FinancialYear.current
  { data: { started_on: fy.started_on, stopped_on: fy.stopped_on } }
end

#form_action_content(side = :after, &block) ⇒ Object


268
269
270
# File 'app/helpers/backend/base_helper.rb', line 268

def form_action_content(side = :after, &block)
  content_for(:"#{side}_form_actions", &block)
end

#heading_toolbar(&block) ⇒ Object


264
265
266
# File 'app/helpers/backend/base_helper.rb', line 264

def heading_toolbar(&block)
  content_for(:heading_toolbar, &block)
end

#historic_of(record = nil) ⇒ Object


33
34
35
36
# File 'app/helpers/backend/base_helper.rb', line 33

def historic_of(record = nil)
  record ||= resource
  render(partial: 'backend/shared/historic', locals: { resource: resource })
end

#info(label, value, options = {}, &_block) ⇒ Object


401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'app/helpers/backend/base_helper.rb', line 401

def info(label, value, options = {}, &_block)
  css_class = "#{options.delete(:level) || :med}-info"
  options[:class] = if options[:class]
                      options[:class].to_s + ' ' + css_class
                    else
                      css_class
                    end
  options[:class] << ' important' if options.delete(:important)
  (:div, options) do
    (:span, label, class: 'title') +
      (:span, value, class: 'value')
  end
end

#infos(options = {}, &block) ⇒ Object


415
416
417
418
419
420
421
422
423
# File 'app/helpers/backend/base_helper.rb', line 415

def infos(options = {}, &block)
  css_class = 'big-infos'
  if options[:class]
    options[:class] += ' ' + css_class
  else
    options[:class] = css_class
  end
  (:div, options, &block)
end

#janus(*args) {|lister| ... } ⇒ Object

Yields:

  • (lister)

323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'app/helpers/backend/base_helper.rb', line 323

def janus(*args, &_block)
  options = args.extract_options!
  name = args.shift || ("#{controller_path}-#{action_name}-" + caller.first.split(/\:/).second).parameterize

  lister = Ekylibre::Support::Lister.new(:face)
  yield lister
  faces = lister.faces

  return '' unless faces.any?

  faces_names = faces.map { |f| f.args.first.to_s }

  active_face = nil
  if pref = current_user.preferences.find_by(name: "interface.janus.#{name}.current_face")
    face = pref.value.to_s
    active_face = face if faces_names.include? face
  end
  active_face ||= faces_names.first

  load_all_faces = false # For performance

  # Adds views
  html_code = faces.map do |face|
    face_name = face.args.first.to_s
    classes = ['face']
    classes << 'active' if active_face == face_name
    unless load_all_faces || active_face == face_name # load_all_faces toggle a few lines above
      next (:div, nil, id: "face-#{face_name}", data: { face: face_name }, class: classes)
    end
    (:div, id: "face-#{face_name}", data: { face: face_name }, class: classes, &face.block)
  end.join.html_safe

  # Adds toggle buttons
  if faces.count > 1
    content_for :view_toolbar do
      (:div, data: { janus: url_for(controller: '/backend/januses', action: :toggle, id: name, default: faces_names.first) }, class: 'btn-group') do
        faces.collect do |face|
          face_name = face.args.first.to_s
          classes = ['btn', 'btn-default']
          classes << 'active' if face_name == active_face
          get_url = url_for(controller: '/backend/januses', action: :toggle, default: faces_names.first, id: name, face: face_name, redirect: request.fullpath)
          link_to(get_url, data: { janus_href: face_name, toggle: 'face' }, class: classes, title: face_name.tl) do
            (:i, '', class: "icon icon-#{face_name}") + ' '.html_safe + face_name.tl
          end
        end.join.html_safe
      end
    end
  end
  html_code
end

#labels_info(labels) ⇒ Object


391
392
393
394
395
396
397
398
399
# File 'app/helpers/backend/base_helper.rb', line 391

def labels_info(labels)
  if labels.any?
    (:div, class: 'info-labels') do
      labels.map do |label|
        (:div, label.name, class: 'label', style: "background-color: #{label.color}; color: #{contrasted_color(label.color)}") + ' '.html_safe
      end.join.html_safe
    end
  end
end

#lights(status, html_options = {}) ⇒ Object


305
306
307
308
309
310
311
312
313
314
315
316
# File 'app/helpers/backend/base_helper.rb', line 305

def lights(status, html_options = {})
  if html_options.key?(:class)
    html_options[:class] << " lights lights-#{status}"
  else
    html_options[:class] = "lights lights-#{status}"
  end
  (:span, html_options) do
    (:span, nil, class: 'go') +
      (:span, nil, class: 'caution') +
      (:span, nil, class: 'stop')
  end
end

#main_campaign_selectorObject


243
244
245
246
247
# File 'app/helpers/backend/base_helper.rb', line 243

def main_campaign_selector
  content_for(:heading_toolbar) do
    campaign_selector
  end
end

#main_financial_year_selector(financial_year) ⇒ Object


286
287
288
289
290
# File 'app/helpers/backend/base_helper.rb', line 286

def main_financial_year_selector(financial_year)
  content_for(:heading_toolbar) do
    financial_year_selector(financial_year)
  end
end

#main_list(*args) ⇒ Object


318
319
320
321
# File 'app/helpers/backend/base_helper.rb', line 318

def main_list(*args)
  options = args.extract_options!
  list *args, options.deep_merge(content_for: { settings: :meta_toolbar, pagination: :meta_toolbar, actions: :main_toolbar })
end

#main_period_selector(*intervals) ⇒ Object


258
259
260
261
262
# File 'app/helpers/backend/base_helper.rb', line 258

def main_period_selector(*intervals)
  content_for(:heading_toolbar) do
    period_selector(*intervals)
  end
end

It's the menu generated for the current user Therefore: No current user => No menu


52
53
54
# File 'app/helpers/backend/base_helper.rb', line 52

def menus
  Ekylibre.menu
end

#movements_chart(resource) ⇒ Object

chart for product movements


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'app/helpers/backend/base_helper.rb', line 221

def movements_chart(resource)
  populations = resource.populations.reorder(:started_at)
  series = []
  now = (Time.zone.now + 7.days)
  window = 1.day
  min = (resource.born_at ? resource.born_at : now - window) - 7.days
  min = now - window if (now - min) < window
  if populations.any?
    data = []
    data += populations.each_with_object({}) do |pair, hash|
      time_pos = pair.started_at < min ? min : pair.started_at
      hash[time_pos.to_usec] = pair.value.to_d
      hash
    end.collect { |k, v| [k, v.to_s.to_f] }
    # current population
    data << [now.to_usec, resource.population.to_d.to_s.to_f]
    series << { name: resource.name, data: data.sort_by(&:first), step: 'left' }
  end
  return no_data if series.empty?
  line_highcharts(series, legend: {}, y_axis: { title: { text: :indicator.tl } }, x_axis: { type: 'datetime', title: { enabled: true, text: :months.tl }, min: min.to_usec })
end

46
47
48
# File 'app/helpers/backend/base_helper.rb', line 46

def navigation_tag
  render(partial: 'layouts/navigation')
end

#part_authorized?(part) ⇒ Boolean

Returns:

  • (Boolean)

99
100
101
102
103
104
105
106
# File 'app/helpers/backend/base_helper.rb', line 99

def part_authorized?(part)
  part.children.each do |group|
    group.children.each do |item|
      return true if authorized?(item.default_page.to_hash)
    end
  end
  false
end

#period_selector(*intervals) ⇒ Object


272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'app/helpers/backend/base_helper.rb', line 272

def period_selector(*intervals)
  options = intervals.extract_options!
  current_period = current_user.current_period.to_date
  current_interval = current_user.current_period_interval.to_sym
  current_user.current_campaign = Campaign.find_or_create_by!(harvest_year: current_period.year)

  default_intervals = %i[day week month year]
  intervals = default_intervals if intervals.empty?
  intervals &= default_intervals
  current_interval = intervals.last unless intervals.include?(current_interval)

  render 'backend/shared/period_selector', current_period: current_period, intervals: intervals, period_interval: current_interval
end

#resourceObject


21
22
23
# File 'app/helpers/backend/base_helper.rb', line 21

def resource
  instance_variable_get('@' + controller_name.singularize)
end

#resource_info(name, options = {}, &block) ⇒ Object


374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'app/helpers/backend/base_helper.rb', line 374

def resource_info(name, options = {}, &block)
  value = options[:value] || resource.send(name)
  return nil if value.blank? && !options[:force]
  nomenclature = options.delete(:nomenclature)
  if nomenclature.is_a?(TrueClass)
    value = Nomen.find(name.to_s.pluralize, value)
  elsif nomenclature.is_a?(Symbol)
    value = Nomen.find(nomenclature, value)
  end
  label = options.delete(:label) || resource_model.human_attribute_name(name)
  if block_given?
    info(label, capture(value, &block), options)
  else
    info(label, value.respond_to?(:l) ? value.l : value, options)
  end
end

#resource_modelObject


25
26
27
# File 'app/helpers/backend/base_helper.rb', line 25

def resource_model
  controller_name.classify.constantize
end

#root_modelsObject


38
39
40
# File 'app/helpers/backend/base_helper.rb', line 38

def root_models
  Ekylibre::Schema.models.collect { |a| [Ekylibre::Record.human_name(a.to_s.singularize), a.to_s.singularize] }.sort_by { |a| a[0].ascii }
end

#side_menu(*args) {|menu| ... } ⇒ Object

Yields:

  • (menu)

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'app/helpers/backend/base_helper.rb', line 120

def side_menu(*args, &_block)
  return '' unless block_given?
  main_options = (args[-1].is_a?(Hash) ? args.delete_at(-1) : {})
  menu = Menu.new
  yield menu

  main_name = args[0].to_s.to_sym
  main_options[:icon] ||= main_name.to_s.parameterize.tr('_', '-')

  html = ''.html_safe
  for name, url, options in menu.items
    li_options = {}
    li_options[:class] = 'active' if options.delete(:active)

    kontroller = (url.is_a?(Hash) ? url[:controller] : nil) || controller_name
    options[:title] ||= ::I18n.t("actions.#{kontroller}.#{name}".to_sym, { default: ["labels.#{name}".to_sym] }.merge(options.delete(:i18n) || {}))
    if icon = options.delete(:icon)
      item[:title] = (:i, '', class: 'icon-' + icon.to_s) + ' '.html_safe + h(item[:title])
    end
    url[:action] ||= name if name != :back && url.is_a?(Hash)
    html << (:li, link_to(options[:title], url, options), li_options) if authorized?(url)
  end

  if html.present?
    html = (:ul, html)
    snippet(main_name, main_options) { html }
  end

  nil
end

#side_tagObject


108
109
110
# File 'app/helpers/backend/base_helper.rb', line 108

def side_tag
  render(partial: 'layouts/side')
end

#snippet(name, options = {}, &block) ⇒ Object


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'app/helpers/backend/base_helper.rb', line 163

def snippet(name, options = {}, &block)
  collapsed = current_user.preference("interface.snippets.#{name}.collapsed", false, :boolean).value
  collapsed = false if collapsed && options[:title].is_a?(FalseClass)

  options[:class] ||= ''
  options[:icon] ||= name
  options[:class] << " snippet-#{options[:icon]}"
  options[:class] << ' active' if options[:active]

  html = ''
  html << "<div id='#{name}' class='snippet#{' ' + options[:class].to_s if options[:class]}#{' collapsed' if collapsed}'>"

  unless options[:title].is_a?(FalseClass)
    html << "<a href='#{url_for(controller: '/backend/snippets', action: :toggle, id: name)}' class='snippet-title' data-toggle-snippet='true'>"
    html << "<i class='collapser'></i>"
    html << '<h3><i></i>' + (options[:title] || "snippets.#{name}".t(default: ["labels.#{name}".to_sym])) + '</h3>'
    html << '</a>'
  end

  html << "<div class='snippet-content'" + (collapsed ? ' style="display: none"' : '') + '>'
  begin
    html << capture(&block)
  rescue Exception => e
    html << (:small, "#{e.class.name}: #{e.message}")
  end
  html << '</div>'

  html << '</div>'
  content_for(:aside, html.html_safe)
  nil
end

#tour(name, _options = {}) {|lister| ... } ⇒ Object

Build a JSON for a data-tour parameter and put it on <body> element

Yields:

  • (lister)

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
# File 'app/helpers/backend/base_helper.rb', line 479

def tour(name, _options = {})
  preference = current_user.preference("interface.tours.#{name}.finished", false, :boolean)
  return if preference.value
  object = {}
  object[:defaults] ||= {}
  object[:defaults][:classes] ||= 'shepherd-theme-arrows'
  object[:defaults][:show_cancel_link] = true unless object[:defaults].key?(:show_cancel_link)
  unless object[:defaults][:buttons]
    buttons = []
    buttons << {
      text: :next.tl,
      classes: 'btn btn-primary',
      action: 'next'
    }
    object[:defaults][:buttons] = buttons
  end
  lister = Ekylibre::Support::Lister.new(:step)
  yield lister
  return nil unless lister.any?
  steps = lister.steps.map do |step|
    id = step.args.first
    on = (step.options[:on] || 'center').to_s
    if reading_ltr?
      if on =~ /right/
        on.gsub!('right', 'left')
      else
        on.gsub!('left', 'right')
      end
    end
    attributes = {
      id: id,
      title: "tours.#{name}.#{id}.title".tl,
      text: "tours.#{name}.#{id}.content".tl,
      attachTo: {
        element: step.options[:element] || '#' + id.to_s,
        on: on.tr('_', ' ')
      }
    }
    if step == lister.steps.last
      attributes[:buttons] = [{ text: :finished.tl, classes: 'btn btn-primary', action: 'next' }]
    end
    attributes
  end
  object[:name] = name
  object[:url] = finish_backend_tour_path(id: name)
  object[:steps] = steps
  content_for(:tour, object.jsonize_keys.to_json)
end

#user_preference_value(name, default = nil) ⇒ Object


473
474
475
476
# File 'app/helpers/backend/base_helper.rb', line 473

def user_preference_value(name, default = nil)
  preference = current_user.preferences.find_by(name: name)
  preference ? preference.value : default
end

#variable_readings(resource) ⇒ Object

chart for variables readings


196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/helpers/backend/base_helper.rb', line 196

def variable_readings(resource)
  indicators = resource.variable_indicators.delete_if { |i| !%i[measure decimal].include?(i.datatype) }
  series = []
  now = (Time.zone.now + 7.days)
  window = 1.day
  min = (resource.born_at ? resource.born_at : now - window)
  min = now - window if (now - min) < window
  indicators.each do |indicator| # [:population, :nitrogen_concentration].collect{|i| Nomen::Indicator[i] }
    items = ProductReading.where(indicator_name: indicator.name, product: resource).where('? < read_at AND read_at < ?', min, now).order(:read_at)
    next unless items.any?
    data = []
    data << [min.to_usec, resource.get(indicator, at: min).to_d.to_s.to_f]
    data += items.each_with_object({}) do |pair, hash|
      hash[pair.read_at.to_usec] = pair.value.to_d
      hash
    end.collect { |k, v| [k, v.to_s.to_f] }
    data << [now.to_usec, resource.get(indicator, at: now).to_d.to_s.to_f]
    series << { name: indicator.human_name, data: data, step: 'left' }
  end
  return no_data if series.empty?

  line_highcharts(series, legend: {}, y_axis: { title: { text: :indicator.tl } }, x_axis: { type: 'datetime', title: { enabled: true, text: :months.tl }, min: min.to_usec })
end