Module: Karafka::Web::Ui::Helpers::ApplicationHelper

Included in:
Base
Defined in:
lib/karafka/web/ui/helpers/application_helper.rb

Overview

Main application helper

Instance Method Summary collapse

Instance Method Details

#deep_merge(hash1, hash2) ⇒ Hash

Merges two hashes deeply, combining nested hashes recursively.

Parameters:

  • hash1 (Hash)

    The first hash to merge.

  • hash2 (Hash)

    The second hash to merge.

Returns:

  • (Hash)

    A new hash that is the result of a deep merge of the two provided hashes.



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 378

def deep_merge(hash1, hash2)
  merged_hash = hash1.dup

  hash2.each_pair do |k, v|
    tv = merged_hash[k]

    merged_hash[k] = if tv.is_a?(Hash) && v.is_a?(Hash)
                       deep_merge(tv, v)
                     else
                       v
                     end
  end

  merged_hash
end

#flat_hash(hash, parent_key = nil, result = {}) ⇒ Hash

Parameters:

  • hash (Hash)

    we want to flatten

  • parent_key (String) (defaults to: nil)

    key for recursion

  • result (Hash) (defaults to: {})

    result for recursion

Returns:

  • (Hash)


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 277

def flat_hash(hash, parent_key = nil, result = {})
  hash.each do |key, value|
    current_key = parent_key ? "#{parent_key}.#{key}" : key.to_s
    if value.is_a?(Hash)
      flat_hash(value, current_key, result)
    elsif value.is_a?(Array)
      value.each_with_index do |item, index|
        flat_hash({ index => item }, current_key, result)
      end
    else
      result[current_key] = value
    end
  end

  result
end

#format_memory(mem_kb) ⇒ String

Returns formatted memory usage.

Parameters:

  • mem_kb (Integer)

    memory used in KB

Returns:

  • (String)

    formatted memory usage



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 108

def format_memory(mem_kb)
  return '0' if !mem_kb || mem_kb.zero?

  if mem_kb < 10_240
    "#{number_with_delimiter(mem_kb.round(4))} KB"
  elsif mem_kb < 1_000_000
    "#{number_with_delimiter((mem_kb / 1024.0).to_i)} MB"
  else
    "#{number_with_delimiter((mem_kb / (1024.0 * 1024.0)).round(1))} GB"
  end
end

#human_readable_time(seconds) ⇒ String

Converts raw second count into human readable form like “12.2 minutes”. etc based on number of seconds

Parameters:

  • seconds (Numeric)

    number of seconds

Returns:

  • (String)

    human readable time



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 152

def human_readable_time(seconds)
  case seconds
  when 0..59
    "#{seconds.round(2)} seconds"
  when 60..3_599
    minutes = seconds / 60.0
    "#{minutes.round(2)} minutes"
  when 3_600..86_399
    hours = seconds / 3_600.0
    "#{hours.round(2)} hours"
  else
    days = seconds / 86_400.0
    "#{days.round(2)} days"
  end
end

#icon(name) ⇒ String

Renders the svg icon out of our icon set

Parameters:

  • name (String, Symbol)

    name of the icon

Returns:

  • (String)

    svg icon



369
370
371
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 369

def icon(name)
  render "shared/icons/_#{name}"
end

#kafka_state_badge(state) ⇒ String

Takes a kafka report state and recommends background style color

Parameters:

  • state (String)

    state

Returns:

  • (String)

    background style



96
97
98
99
100
101
102
103
104
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 96

def kafka_state_badge(state)
  case state
  when 'up' then 'badge-success'
  when 'active' then 'badge-success'
  when 'steady' then 'badge-success'
  else
    'badge-warning'
  end
end

#lag_trend_badge(trend) ⇒ String

Takes the lag trend and gives it appropriate background style color for badge

Parameters:

  • trend (Numeric)

    lag trend

Returns:

  • (String)

    bg classes



76
77
78
79
80
81
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 76

def lag_trend_badge(trend)
  bg = 'badge-success' if trend.negative?
  bg ||= 'badge-warning' if trend.positive?
  bg ||= 'badge-secondary'
  bg
end

#lag_with_label(lag) ⇒ String

Returns lag if correct or N/A with labeled explanation.

Parameters:

  • lag (Integer)

    lag

Returns:

  • (String)

    lag if correct or N/A with labeled explanation

See Also:



205
206
207
208
209
210
211
212
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 205

def lag_with_label(lag)
  if lag.negative?
    title = 'Not available until first offset commit'
    %(<span class="badge badge-secondary" title="#{title}">N/A</span>)
  else
    lag.to_s
  end
end

#lso_risk_state_badge(details) ⇒ String

Returns background classes for row marking.

Parameters:

Returns:

  • (String)

    background classes for row marking



252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 252

def lso_risk_state_badge(details)
  case details.lso_risk_state
  when :active
    ''
  when :at_risk
    'badge-warning'
  when :stopped
    'badge-error'
  else
    raise ::Karafka::Errors::UnsupportedCaseError
  end
end

#lso_risk_state_bg(details) ⇒ String

Returns background classes for row marking.

Parameters:

Returns:

  • (String)

    background classes for row marking



236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 236

def lso_risk_state_bg(details)
  case details.lso_risk_state
  when :active
    ''
  when :at_risk
    'bg-warning bg-opacity-25'
  when :stopped
    'bg-error bg-opacity-25'
  else
    raise ::Karafka::Errors::UnsupportedCaseError
  end
end

Adds active class to the current location in the nav if needed

Parameters:

  • location (Hash)


36
37
38
39
40
41
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 36

def nav_class(location)
  comparator, value = location.to_a.first

  local_location = request.path.gsub(env.fetch('SCRIPT_NAME'), '')
  local_location.public_send(:"#{comparator}?", value) ? 'active' : ''
end

#number_with_delimiter(number, delimiter = ',') ⇒ String

Converts number to a more friendly delimiter based version

Parameters:

  • number (Numeric)
  • delimiter (String) (defaults to: ',')

    delimiter (comma by default)

Returns:

  • (String)

    number with delimiter



124
125
126
127
128
129
130
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 124

def number_with_delimiter(number, delimiter = ',')
  return '' unless number

  parts = number.to_s.to_str.split('.')
  parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
  parts.join('.')
end

#object_value_to_s(object) ⇒ String

Converts object into a string and for objects that would anyhow return their stringified instance value, it replaces it with the class name instead. Useful for deserializers, etc presentation.

Parameters:

  • object (Object)

Returns:

  • (String)


49
50
51
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 49

def object_value_to_s(object)
  object.to_s.include?('#<') ? object.class.to_s : object.to_s
end

#offset_with_label(topic_name, partition_id, offset, explore: false) ⇒ String

Returns offset if correct or N/A with labeled explanation for offsets that are less than 0. Offset with less than 0 indicates, that the offset was not yet committed and there is no value we know of.

Parameters:

  • topic_name (String)

    name of the topic for explorer path

  • partition_id (Integer)

    partition for the explorer path

  • offset (Integer)

    offset

  • explore (Boolean) (defaults to: false)

    should we generate (when allowed) a link to message explorer

Returns:

  • (String)

    offset if correct or N/A with labeled explanation for offsets that are less than 0. Offset with less than 0 indicates, that the offset was not yet committed and there is no value we know of



221
222
223
224
225
226
227
228
229
230
231
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 221

def offset_with_label(topic_name, partition_id, offset, explore: false)
  if offset.negative?
    title = 'Not available until first offset commit'
    %(<span class="badge badge-secondary" title="#{title}">N/A</span>)
  elsif explore
    path = explorer_path(topic_name, partition_id, offset)
    %(<a href="#{path}">#{offset}</a>)
  else
    offset.to_s
  end
end

#poll_state_with_change_time_label(state, state_ch) ⇒ String

Returns span tag with label and title with change time if present.

Parameters:

  • state (String)

    poll state

  • state_ch (Integer)

    time until next change of the poll state (from paused to active)

Returns:

  • (String)

    span tag with label and title with change time if present



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 172

def poll_state_with_change_time_label(state, state_ch)
  year_in_seconds = 131_556_926
  state_ch_in_seconds = state_ch / 1_000.0

  # If state is active, there is no date of change
  if state == 'active'
    %(
      <span class="badge #{kafka_state_badge(state)}">#{state}</span>
    )
  elsif state_ch_in_seconds > year_in_seconds
    %(
      <span
        class="badge #{kafka_state_badge(state)}"
        title="until manual resume"
      >
        #{state}
      </span>
    )
  else
    %(
      <span
        class="badge #{kafka_state_badge(state)} time-title"
        title="#{Time.now + state_ch_in_seconds}"
      >
        #{state}
      </span>
    )
  end
end

#relative_time(time) ⇒ String

Returns relative time tag for timeago.js.

Parameters:

  • time (Float)

    UTC time float

Returns:

  • (String)

    relative time tag for timeago.js



134
135
136
137
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 134

def relative_time(time)
  stamp = Time.at(time).getutc.iso8601(3)
  %(<time class="ltr" dir="ltr" title="#{stamp}" datetime="#{stamp}">#{time}</time>)
end

Returns html link for sorting with arrow when attribute sort enabled.

Parameters:

  • name (String)

    link value

  • attribute (Symbol, nil) (defaults to: nil)

    sorting attribute or nil if we provide only symbol name

  • rev (Boolean) (defaults to: false)

    when set to true, arrows will be in the reverse position. This is used when the description in the link is reverse to data we sort. For example we have order on when processes were started and we display “x hours” ago but we sort on their age, meaning that it looks like it is the other way around. This flag allows us to reverse just he arrow making it look consistent with the presented data order

Returns:

  • (String)

    html link for sorting with arrow when attribute sort enabled



302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 302

def sort_link(name, attribute = nil, rev: false)
  unless attribute
    attribute = name

    if SORT_NAMES[attribute]
      name = SORT_NAMES[attribute]
    else
      name = attribute.to_s.tr('_', ' ').tr('?', '')
      # Always capitalize the name
      name = name.split(' ').map(&:capitalize).join(' ')
    end
  end

  arrow_both = '&#x21D5;'
  arrow_down = '&#9662;'
  arrow_up = '&#9652;'

  desc = "#{attribute} desc"
  asc = "#{attribute} asc"
  path = current_path(sort: desc)
  full_name = "#{name}&nbsp;#{arrow_both}"

  if params.current_sort == desc
    path = current_path(sort: asc)
    full_name = "#{name}&nbsp;#{rev ? arrow_up : arrow_down}"
  end

  if params.current_sort == asc
    path = current_path(sort: desc)
    full_name = "#{name}&nbsp;#{rev ? arrow_down : arrow_up}"
  end

  "<a class=\"sort\" href=\"#{path}\">#{full_name}</a>"
end

#status_badge(status) ⇒ String

Takes a status and recommends background style color

Parameters:

  • status (String)

    status

Returns:

  • (String)

    background style



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 57

def status_badge(status)
  case status
  when 'initialized' then 'badge-success'
  when 'supervising' then 'badge-success'
  when 'running' then 'badge-success'
  when 'quieting' then 'badge-warning'
  when 'quiet' then 'badge-warning'
  when 'stopping' then 'badge-warning'
  when 'stopped' then 'badge-error'
  when 'terminated' then 'badge-error'
  else
    raise ::Karafka::Errors::UnsupportedCaseError, status
  end
end

#tags(tags_array) ⇒ String

Renders tags one after another

Parameters:

  • tags_array (Array<String>)

Returns:

  • (String)

    tags badges



87
88
89
90
91
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 87

def tags(tags_array)
  tags_array
    .map { |tag| %(<span class="badge badge-info">#{tag}</span>) }
    .join(' ')
end

#time_with_label(time) ⇒ String

Returns span tag with raw timestamp as a title and time as a value.

Parameters:

  • time (Time)

    time object we want to present with detailed ms label

Returns:

  • (String)

    span tag with raw timestamp as a title and time as a value



141
142
143
144
145
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 141

def time_with_label(time)
  stamp = (time.to_f * 1000).to_i

  %(<span title="#{stamp}">#{time}</span>)
end

#truncate(string, length: 50, omission: '...', strategy: :default) ⇒ String

Truncates given text if it is too long and wraps it with a title with full text. Can use a middle-based strategy that keeps beginning and ending of a string instead of keeping just the beginning.

The :middle strategy is useful when we have strings such as really long process names that have important beginning and end but middle can be removed without risk of not allowing user to recognize the content.

Parameters:

  • string (String)

    string we want to truncate

  • length (Integer) (defaults to: 50)

    max length of the final string that we accept before truncating

  • omission (String) (defaults to: '...')

    truncation omission

  • strategy (Symbol) (defaults to: :default)

    :default or :middle how should we truncate

Returns:

  • (String)

    HTML span tag with truncated content and full content title



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 350

def truncate(string, length: 50, omission: '...', strategy: :default)
  return string if string.length <= length

  case strategy
  when :default
    truncated = string[0...(length - omission.length)] + omission
  when :middle
    part_length = (length - omission.length) / 2
    truncated = string[0...part_length] + omission + string[-part_length..]
  else
    raise Karafka::Errors::UnsupportedCaseError, "Unknown strategy: #{strategy}"
  end

  %(<span title="#{string}">#{truncated}</span>)
end

#view_title(title) ⇒ String

Sets the particular page title

Parameters:

  • title (String)

    page title

Returns:

  • (String)

    title html



269
270
271
# File 'lib/karafka/web/ui/helpers/application_helper.rb', line 269

def view_title(title)
  content_for(:title) { title }
end