forked from 3scale/porta
/
application_helper.rb
380 lines (318 loc) · 11.4 KB
/
application_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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
150
151
152
153
154
155
156
157
158
159
160
161
162
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
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
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
373
374
375
376
377
378
379
380
# TODO: Let's try to find new homes for these guys. It's getting crowded here...
# Methods added to this helper will be available to all templates in the
# application.
module ApplicationHelper
# this is used just to not load font awesome in tests
def capybara_webkit?
Rails.env.test? && defined?(Capybara.current_driver) && Capybara.current_driver == :webkit
end
include ColumnSortingHelper
def base_url
options = {
host: request.headers['X-Forwarded-For-Domain']
}.delete_if{|_, value| !value }
root_url(options)
end
def title(page_title)
content_for(:title) { h(page_title.to_s) }
end
def default_title
name = controller.class.name.underscore.tr('/', '.').sub(/_controller$/, '')
controller_name = t(name,
scope: [:controller, :title],
default: controller.controller_name.humanize)
action_name = t(action = controller.action_name,
scope: [:controller, :action, name],
default: action.humanize)
"#{controller_name} - #{action_name}"
end
def link_to_unless_current_styled(text, url, options = {})
link_to_unless_current text, url, options do |active_text|
content_tag 'span', active_text, :class => 'active is-active'
end
end
# Ensure that url starts with protocol (http or https)
#
# == Examples:
#
# absolutize_url("http://example.com") # returns http://example.com
# absolutize_url("example.com") # returns http://example.com
#
def absolutize_url(url)
url =~ /\Ahttps?/ ? url : "http://#{url}"
end
def active?(current, stage)
"class=\"active\"" if current == stage
end
# Used with URLs which were entered by users
def render_url(url)
url.blank? ? 'link not available' : absolutize_url(url)
end
# Render tab. This automaticaly handles ajax as well as non-ajax calls.
#
# == Arguments
#
# * +id+: id of current tab
#
# == Options
#
# * +of+: name of resource under which this tab belongs. (:service, :plan,
# ...)
def tab(id, options = {}, &block)
if request.xhr?
yield
else
@tab = id
layout = options[:of] ? "#{options[:of].to_s.pluralize}/" : ''
layout << 'tabs'
render :layout => layout, &block
end
end
##
# Forum imported helpers
def feed_icon_tag(title, url)
(@feed_icons ||= []) << { :url => url, :title => title }
link_to image_tag('forum/feed-icon.png', :size => '14x14', :alt => "Subscribe to #{title}"), url
end
def pagination(collection)
if collection.total_entries > 1
"<p class='pages'>" + 'Pages'[:pages_title] + ": <strong>" +
will_paginate(collection, :inner_window => 10, :next_label => "next"[], :prev_label => "previous"[]) +
"</strong></p>"
end
end
def next_page(collection)
unless collection.current_page == collection.total_entries || collection.total_entries == 0
"<p style='float:right;'>" + link_to("Next page"[], { :page => collection.current_page.next }.merge(params.reject{|k,v| k=="page"})) + "</p>"
end
end
def search_posts_title
returning(params[:q].blank? ? 'Recent Posts'[] : "Searching for"[] + " '#{h params[:q]}'") do |title|
title << " "+'by {user}'[:by_user,h(@user.display_name)] if @user
title << " "+'in {forum}'[:in_forum,h(@forum.name)] if @forum
end
end
def topic_title_link(topic, options)
if topic.title =~ /\A\[([^\]]{1,15})\]((\s+)\w+.*)/
"<span class='flag'>#{$1}</span>" +
link_to(h($2.strip), forum_topic_path(@forum, topic), options)
else
link_to(h(topic.title), forum_topic_path(@forum, topic), options)
end
end
def avatar_for(user, size=62)
email_hash = Digest::MD5.hexdigest(user.try!(:email) || "")
image_tag "https://secure.gravatar.com/avatar.php?gravatar_id=#{email_hash}&rating=PG&size=#{size}", :size => "#{size}x#{size}", :class => 'photo'
end
def search_path(atom = false)
options = params[:q].blank? ? {} : {:q => params[:q]}
prefix =
if @topic
options.update :topic_id => @topic, :forum_id => @forum
:forum_topic
elsif @forum
options.update :forum_id => @forum
:forum
elsif @user
options.update :user_id => @user
:user
else
:search
end
atom ? send("formatted_#{prefix}_posts_path", options.update(:format => :atom)) : send("#{prefix}_posts_path", options)
end
# Join CSS classes to single space-separated string, ready for inserting into a "class"
# attribute of a html element.
#
# Handles well empty or nil class names (does not include them).
#
# == Examples
#
# join_dom_classes('foo') # "foo"
# join_dom_classes('foo', 'bar') # "foo bar"
# join_dom_classes('foo', '') # "foo"
# join_dom_classes('foo', false) # "foo"
# join_dom_classes('foo', nil) # "foo"
# join_dom_classes('', nil, ' ') # nil
def join_dom_classes(*names)
names.reject(&:blank?).join(' ')
end
# Join CSS classes to single string. Can accept Array or Hash like Slim template.
#
# :reek:NestedIterators {enabled: false}
def css_class(*args)
args.map do |arg|
case arg
when Array then arg.select(&:present?)
when Hash then arg.select { |_,value| value.present? }.keys
else arg
end
end.join(' ')
end
def boolean_status_img(enabled, opts = {})
if enabled
'<i class="included fa fa-check-circle-o" title="Enabled"></i>'.html_safe
else
'<i class="excluded fa fa-times-circle-o" title="Disabled"></i>'.html_safe
end
end
# Returns sentence about used timezone with linking to its change.
#
def timezone_information(timezone = current_account.timezone)
name = ActiveSupport::TimeZone.new(timezone).to_s
name_or_link = if can?(:update, current_account) && current_account.provider?
link_to(name, edit_provider_admin_account_path)
else
name
end
"Using time zone ".html_safe + name_or_link
end
def help_url
"http://www.3scale.net/support/product-configuration/"
end
def favicon_for account
return if account.nil?
return if account.settings.favicon.blank?
ThreeScale::Warnings.deprecated_method!(:favicon_for)
types = {'ico' => 'x-icon', 'png' => 'png', 'gif' => 'gif'}
type = account.settings.favicon.split('.').last
type = types[type] or return
"<link rel=\"icon\" href=\"#{account.settings.favicon}\" type=\"image/#{type}\" />".html_safe
end
def error_messages_for(*params)
ignore_me = ['Account is invalid', 'Bought cinstances is invalid']
options = params.extract_options!.symbolize_keys
objects = if object = options.delete(:object)
[object].flatten
else
params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
end
count = objects.inject(0) {|sum, object| sum + object.errors.count }
unless count.zero?
html = {}
[:id, :class].each do |key|
if options.include?(key)
value = options[key]
html[key] = value unless value.blank?
else
html[key] = 'errorExplanation'
end
end
options[:object_name] ||= params.first
I18n.with_options :locale => options[:locale], :scope => [:activerecord, :errors, :template] do |locale|
header_message = if options.include?(:header_message)
options[:header_message]
else
object_name = options[:object_name].to_s.tr('_', ' ')
object_name = I18n.t(object_name, :default => object_name, :scope => [:activerecord, :models], :count => 1)
locale.t :header, :count => count, :model => object_name
end
message = options.include?(:message) ? options[:message] : locale.t(:body)
error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) unless ignore_me.include?(msg) } }.join
contents = ''
contents << content_tag(options[:header_tag] || :h2, header_message.html_safe) unless header_message.blank?
contents << content_tag(:p, message.html_safe) unless message.blank?
contents << content_tag(:ul, error_messages.html_safe)
content_tag(:div, contents.html_safe, html)
end
else
''
end
end
def format_text(text)
RedCloth.new(text).to_html
end
def chop(name, l = 15)
name.length > l ? name[0...l]+'...' : name
end
def partner_accounts_plural_text_or_link
text = h(pluralize(current_account.buyer_accounts.count, "account"))
if can? :manage, :partners
link_to text, admin_buyers_accounts_path
else
text
end
end
def link_or_text_to_settings_or_site
# complicated ain't it? welcome to the realm of reusing everything
if can? :manage, :settings
link_to "Settings", admin_site_settings_path
else
"Settings"
end
end
def account_plan_link_or_text
text = 'Account plan'
if can? :manage, :plans
link_to text, admin_buyers_account_plans_path(current_account)
else
text
end
end
def account_plans_count_link_or_text
text = current_account.account_plans.stock.size
if can? :manage, :plans
link_to text, admin_buyers_account_plans_path
else
text
end
end
def partner_accounts_count_link_or_text
text = current_account.buyers.size
if can? :manage, :partners
link_to text, admin_buyers_accounts_path
else
text
end
end
def can_be_destroyed?(object)
!object.respond_to?(:can_be_destroyed?) ||
( object.respond_to?(:can_be_destroyed?) && object.can_be_destroyed? )
end
def link_to_export_widget_for(collection)
return unless can?(:export, :data)
link_to(new_provider_admin_account_data_exports_path, id: 'export-to-csv', class: 'ExportLink', title: 'Export to CSV') do
content_tag(:i, '', class: 'fa fa-file-excel-o') + ' Export all ' + collection.capitalize
end
end
def impersonating?
current_user.impersonation_admin? && !current_account.master?
end
def saas?
ThreeScale.tenant_mode.multitenant?
end
def major_and_minor_version_path
info = System::Deploy.info
if saas?
"red_hat_3scale/#{info.major_version}-saas"
else
"red_hat_3scale_api_management/#{info.major_version}.#{info.minor_version}"
end
end
def docs_base_url
I18n.t('docs.base_url', major_and_minor_version_path: major_and_minor_version_path)
end
def call_to_action?
return false unless ThreeScale.config.redhat_customer_portal.enabled
return false unless current_user.admin?
# This also prevents a bug in the fields definition feature to throw an unexpected exception when Account.master.field_value is invoked
return false if current_account.master?
unlinked_paid_account?
end
def unlinked_paid_account?
!current_account.field_value('red_hat_account_verified_by').presence && current_account.paid?
end
def has_out_of_date_configuration?(service)
return unless service
service.pending_affecting_changes?
end
def rails_asset_url_tag
javascript_tag("window.rails_asset_host = '#{rails_asset_host_url}'", { type: "text/javascript"})
end
def rails_asset_host_url
asset_host_enabled = Rails.configuration.asset_host.present?
asset_host_url = Rails.configuration.three_scale.asset_host.presence
return '' unless asset_host_enabled && asset_host_url
"#{request.protocol}#{asset_host_url}"
end
end