app/helpers/views_widgets_helper.rb
#encoding: utf-8
#############################################################################
#
# Estimancy, Open Source project estimation web application
# Copyright (c) 2014 Estimancy (http://www.estimancy.com)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
module ViewsWidgetsHelper
# Get the label widget data
def get_label_widget_data(view_widget_id)
view_widget = ViewsWidget.find(view_widget_id)
widget_data = {}
initial_width = 60; initial_height = 60
value_to_show = nil # according to the widget type
############################ Get the view_widget size ############################
ft_maxFontSize_without_mm = 75
icon_font_size = 2
# The widget size with : margin-right = 10px
height = (initial_height*view_widget.height.to_i) + 5*(view_widget.height.to_i - 1) #margin is now 5 unless of 10
width = (initial_width*view_widget.width.to_i) + 5*(view_widget.width.to_i - 1)
# update size in the results hash
widget_data[:width] = width
widget_data[:height] = height
case view_widget.height.to_i
when 1..2
icon_font_size = 2
if view_widget.height.to_i == 3
icon_font_size = 3
end
ft_maxFontSize_without_mm = 20
if view_widget.width.to_i <= 1
ft_minMax_minFontSize = 3.5
else
ft_minMax_minFontSize = 6.5
end
when 3
icon_font_size = 2.5
ft_maxFontSize_without_mm = 20
else
icon_font_size = ((height+width)/2) * 0.025
if icon_font_size > 3 && icon_font_size < 6
icon_font_size = 3
elsif icon_font_size > 6
icon_font_size = 4
end
end
text_size = ((height+width)/2) * 0.006 # 0.015
# get the fitText minFontSize and maxFontSize
widget_data[:icon_font_size] = icon_font_size
widget_data[:text_size] = text_size
widget_data[:ft_maxFontSize_without_mm] = ft_maxFontSize_without_mm
widget_data[:value_to_show] = view_widget.name
widget_data
end
# Get the view_widget data for each view/widget/module_project
def get_view_widget_data(module_project_id, view_widget_id)
# General data
view_widget = ViewsWidget.find(view_widget_id)
pbs_project_elt = current_component
module_project = ModuleProject.find(module_project_id)
project = module_project.project
pemodule = module_project.pemodule
widget_data = {}
data_probable = ""; min_value = ""; max_value = ""; value_to_show = ""
initial_width = 60; initial_height = 60
value_to_show = nil # according to the widget type
data_low = nil; data_most_likely=nil; data_high=nil; data_probable=nil
widget_data = { data_low: data_low, data_high: data_high, data_most_likely: data_most_likely, data_probable: data_probable }
############################ Get the view_widget size ############################
ft_maxFontSize_without_mm = 75
ft_maxFontSize_with_mm = 60
ft_minMax_maxFontSize = 20
icon_font_size = 2
# The widget size with : margin-right = 10px
height = (initial_height*view_widget.height.to_i) + 5*(view_widget.height.to_i - 1) #margin is now 5 unless of 10
width = (initial_width*view_widget.width.to_i) + 5*(view_widget.width.to_i - 1)
# update size in the results hash
widget_data[:width] = width
widget_data[:height] = height
case view_widget.height.to_i
when 1..2
icon_font_size = 2
if view_widget.height.to_i == 3
icon_font_size = 3
end
ft_maxFontSize_without_mm = 30
ft_maxFontSize_with_mm = 30
ft_minMax_minFontSize = 6
ft_minMax_maxFontSize = 12
if view_widget.width.to_i <= 1
ft_minMax_minFontSize = 4.5
else
ft_minMax_minFontSize = 7.5
end
when 3
icon_font_size = 2.5 #3
ft_maxFontSize_without_mm = 30
ft_maxFontSize_with_mm = 30
ft_minMax_maxFontSize = 12
else
icon_font_size = ((height+width)/2) * 0.025
if icon_font_size > 3 && icon_font_size < 6
icon_font_size = 3 #4
elsif icon_font_size > 6
icon_font_size = 4 #5
end
end
text_size = ((height+width)/2) * 0.015
min_max_size = ((height+width)/2) * 0.009
# get the fitText minFontSize and maxFontSize
widget_data[:icon_font_size] = icon_font_size
widget_data[:text_size] = text_size
widget_data[:min_max_size] = min_max_size
# fitText parameters
widget_data[:ft_maxFontSize_without_mm] = ft_maxFontSize_without_mm
widget_data[:ft_maxFontSize_with_mm] = ft_maxFontSize_with_mm
widget_data[:ft_minMax_minFontSize] = ft_minMax_minFontSize
widget_data[:ft_minMax_maxFontSize] = ft_minMax_maxFontSize
############################ Get the view_widget estimation value ############################
view_widget_est_val = view_widget.estimation_value
unless view_widget_est_val.nil?
est_val_in_out = view_widget_est_val.in_out
view_widget_attribute = view_widget_est_val.pe_attribute #view_widget.pe_attribute
view_widget_attribute_name = view_widget_attribute.nil? ? "" : view_widget_attribute.name
estimation_value = module_project.estimation_values.where('pe_attribute_id = ? AND in_out = ?', view_widget_attribute.id, view_widget_est_val.in_out).last
unless estimation_value.nil?
data_low = estimation_value.string_data_low[pbs_project_elt.id]
data_high = estimation_value.string_data_high[pbs_project_elt.id]
data_most_likely = estimation_value.string_data_most_likely[pbs_project_elt.id]
data_probable = estimation_value.string_data_probable[pbs_project_elt.id]
# Get the project wbs_project_element root if module with activities
if estimation_value.module_project.pemodule.alias == Projestimate::Application::EFFORT_BREAKDOWN
if estimation_value.in_out == "output"
unless estimation_value.pe_attribute.alias == "ratio" || estimation_value.pe_attribute.alias == "ratio_name"
wbs_activity_elt_root = module_project.wbs_activity.wbs_activity_elements.first.root
wbs_data_low = data_low.nil? ? nil : data_low
wbs_data_high = data_high.nil? ? nil : data_high
wbs_data_probable = data_probable.nil? ? nil : data_probable
data_low = wbs_data_low.nil? ? nil : wbs_data_low
data_high = wbs_data_high.nil? ? nil : wbs_data_high
if wbs_data_probable.nil?
wbs_activity_elt_root_data_probable = nil
else
wbs_activity_elt_root_data_probable = wbs_data_probable[wbs_activity_elt_root.id]
end
if wbs_activity_elt_root_data_probable.nil? || wbs_activity_elt_root_data_probable.empty?
data_probable = nil
else
data_probable = (wbs_data_probable.nil? || wbs_data_probable.empty?) ? nil : wbs_activity_elt_root_data_probable[:value]
end
end
end
end
if data_probable.nil?
probable_value_text = display_value(data_probable.to_f, estimation_value, module_project_id)
else
if is_number?(data_probable)
probable_value_text = display_value(data_probable.to_f, estimation_value, module_project_id)
else
probable_value_text = data_probable
end
end
max_value_text = "Max: #{data_high.nil? ? '-' : display_value(data_high, estimation_value, module_project_id)}" #max_value_text = "Max: #{data_high.nil? ? '-' : data_high.round(user_number_precision)}"
min_value_text = "Min: #{data_low.nil? ? '-' : display_value(data_low, estimation_value, module_project_id)}" #min_value_text = "Min: #{data_low.nil? ? '-' : data_low.round(user_number_precision)}"
#Update the widget data
#widget_data = { data_low: data_low, data_high: data_high, data_most_likely: data_most_likely, data_probable: data_probable, max_value_text: max_value_text, min_value_text: min_value_text, probable_value_text: probable_value_text }
widget_data[:data_low] = data_low
widget_data[:data_high] = data_high
widget_data[:data_most_likely] = data_most_likely
widget_data[:data_probable] = data_probable
widget_data[:max_value_text] = max_value_text
widget_data[:min_value_text] = min_value_text
widget_data[:probable_value_text] = probable_value_text
#WIDGETS_TYPE = [["Simple text", "text"], ["Line chart", "line_chart"], ["Bar chart", "bar_chart"], ["Area chart", "area_chart"], ["Pie chart","pie_chart"], ["Timeline", "timeline"], ["Stacked bar chart", "stacked_bar_chart"] ]
#According to the widget type, we will show simple text, charts, timeline, etc
#get rounded values before use
user_precision = user_number_precision
data_low = data_low.is_a?(Hash) ? data_low.update(data_low){|key,value| value.round(user_precision)} : data_low
data_most_likely = data_most_likely.is_a?(Hash) ? data_most_likely.update(data_most_likely){|key,value| value.round(user_precision)} : data_most_likely
data_high = data_high.is_a?(Hash) ? data_high.update(data_high){|key,value| value.round(user_precision)} : data_high
data_probable = data_probable.is_a?(Hash) ? data_probable.update(data_probable){|key,value| value.round(user_precision)} : data_probable
chart_level_values = []
chart_level_values << ["low", data_low]
chart_level_values << ["ml", data_most_likely]
chart_level_values << ["high", data_high]
chart_level_values << ["probable", data_probable]
widget_data[:chart_level_values] = chart_level_values
chart_height = height-50
chart_width = width -40
chart_title = view_widget.name
chart_vAxis = "#{view_widget_attribute_name} (#{get_attribute_unit(view_widget_attribute)})"
chart_hAxis = "Level"
case view_widget.widget_type
when "text"
value_to_show = probable_value_text
is_simple_text = true
when "line_chart"
#value_to_show = line_chart(chart_level_values, height: "#{chart_height}px", library: {backgroundColor: view_widget.color})
value_to_show = line_chart([ {name: I18n.t(:low), data: {Time.new => data_low} }, #10
{name: I18n.t(:most_likely), data: {Time.new => data_most_likely} }, #30
{name: I18n.t(:high), data: {Time.new => data_high} } ], #50
{height: "#{chart_height}px", library: {backgroundColor: "transparent", title: chart_title, hAxis: {title: "Level", format: 'MMM y'}, vAxis: {title: chart_vAxis}}})
when "bar_chart"
value_to_show = column_chart(chart_level_values, height: "#{chart_height}px", library: {backgroundColor: "transparent", title: chart_title, vAxis: {title: chart_vAxis}})
when "area_chart"
value_to_show = area_chart(chart_level_values, height: "#{chart_height}px", library: {backgroundColor: "transparent", title: chart_title, vAxis: {title: chart_vAxis}})
when "pie_chart"
value_to_show = pie_chart(chart_level_values, height: "#{chart_height}px", library: {backgroundColor: "transparent", title: chart_title})
when "stacked_bar_chart"
value_to_show = probable_value_text
when "timeline"
timeline_data = []
delay = PeAttribute.where(alias: "delay").first
end_date = PeAttribute.where(alias: "end_date").first
staffing = PeAttribute.where(alias: "staffing").first
effort = PeAttribute.where(alias: "effort").first
is_ok = false
# Get the component/PBS children
products = pbs_project_elt.root.subtree.all
products.each_with_index do |element, i|
dev = nil
est_val = module_project.estimation_values.where(pe_attribute_id: delay.id).first
unless est_val.nil?
str_data_probable = est_val.string_data_probable
str_data_probable.nil? ? nil : (dev = str_data_probable[element.id])
end
if !dev.nil?
d = dev.to_f
if d.nil?
dh = 1.hours
else
dh = d.hours
end
ed = module_project.estimation_values.where(pe_attribute_id: end_date.id).first.string_data_probable[element.id]
begin
timeline_data << [
element.name,
element.start_date,
element.start_date + dh
]
is_ok = true
rescue
is_ok = false
end
end
end
if is_ok == true
value_to_show = timeline(timeline_data, library: {backgroundColor: "transparent", title: view_widget_attribute_name})
else
value_to_show = "" #I18n.t(:error_invalid_date)
end
when "table_effort_per_phase", "table_cost_per_phase"
unless estimation_value.in_out == "input"
value_to_show = raw estimation_value.nil? ? "#{ content_tag(:div, I18n.t(:notice_no_estimation_saved), :class => 'no_estimation_value')}" : display_effort_or_cost_per_phase(pbs_project_elt, module_project, estimation_value, view_widget_id)
end
when "histogram_effort_per_phase", "histogram_cost_per_phase"
unless estimation_value.in_out == "input"
chart_height = height-90
chart_data = get_chart_data_effort_and_cost(pbs_project_elt, module_project, estimation_value, view_widget)
value_to_show = column_chart(chart_data, height: "#{chart_height}px", library: {backgroundColor: "transparent", weight: "normal", title: chart_title, vAxis: {title: chart_vAxis}})
end
when "pie_chart_effort_per_phase", "pie_chart_cost_per_phase"
chart_height = height-90
unless estimation_value.in_out == "input"
chart_data = get_chart_data_effort_and_cost(pbs_project_elt, module_project, estimation_value, view_widget)
end
value_to_show = pie_chart(chart_data, height: "#{chart_height}px", library: {backgroundColor: "transparent", title: chart_title})
when "effort_per_phases_profiles_table", "cost_per_phases_profiles_table"
unless estimation_value.in_out == "input"
value_to_show = get_chart_data_by_phase_and_profile(pbs_project_elt, module_project, estimation_value, view_widget)
end
when "stacked_bar_chart_effort_per_phases_profiles"
unless estimation_value.in_out == "input"
chart_height = height-90
stacked_chart_data = get_chart_data_by_phase_and_profile(pbs_project_elt, module_project, estimation_value, view_widget)
value_to_show = column_chart(stacked_chart_data, stacked: true, height: "#{chart_height}px", library: {backgroundColor: "transparent", title: chart_title, vAxis: {title: chart_vAxis}})
end
when "stacked_bar_chart_cost_per_phases_profiles"
else
value_to_show = probable_value_text
end
widget_data[:value_to_show] = value_to_show
end
end
# Return the view_widget HASH
widget_data
end
# Get Effort and Cost data by Phases and by Profiles
def get_chart_data_by_phase_and_profile(pbs_project_element, module_project, estimation_value, view_widget)
result = String.new
stacked_data = Array.new
profiles_wbs_data = Hash.new
probable_est_value = estimation_value.send("string_data_probable")
pbs_probable_est_value = probable_est_value[pbs_project_element.id]
return result if probable_est_value.nil? || pbs_probable_est_value.nil?
wbs_activity = module_project.wbs_activity
wbs_activity_element_root = wbs_activity.wbs_activity_elements.first.root
wai = WbsActivityInput.where(wbs_activity_id: wbs_activity, module_project_id: module_project.id).first
begin
ratio_reference = wai.wbs_activity_ratio
rescue
ratio_reference = wbs_activity.wbs_activity_ratios.first
end
project_organization = module_project.project.organization
wbs_activity_elements = wbs_activity.wbs_activity_elements
# We don't want to show element with nil ratio value
project_organization_profiles = []
ratio_profiles_with_nil_ratio = []
wbs_activity_ratio_profiles = []
unless ratio_reference.nil?
ratio_reference.wbs_activity_ratio_elements.each do |ratio_elt|
ratio_profiles_with_nil_ratio << ratio_elt.wbs_activity_ratio_profiles
end
# Reject all RatioProfile with nil ratio_value
wbs_activity_ratio_profiles = ratio_profiles_with_nil_ratio.flatten.reject{|i| i.ratio_value.nil? }
end
wbs_activity_ratio_profiles.each do |ratio_profile|
project_organization_profiles << ratio_profile.organization_profile
end
project_organization_profiles = project_organization_profiles.uniq
case view_widget.widget_type
when "effort_per_phases_profiles_table"
result = raw(render :partial => 'views_widgets/effort_by_phases_profiles', :locals => { project_wbs_activity_elements: wbs_activity_elements,
pe_attribute: estimation_value.pe_attribute,
module_project: module_project,
project_organization_profiles: project_organization_profiles,
estimation_pbs_probable_results: pbs_probable_est_value,
ratio_reference: ratio_reference } )
when "cost_per_phases_profiles_table"
result = raw(render :partial => 'views_widgets/cost_by_phases_profiles', :locals => { project_wbs_activity_elements: wbs_activity_elements,
pe_attribute: estimation_value.pe_attribute,
module_project: module_project,
project_organization_profiles: project_organization_profiles,
estimation_pbs_probable_results: pbs_probable_est_value,
ratio_reference: ratio_reference } )
when "stacked_bar_chart_effort_per_phases_profiles"
if project_organization_profiles.length > 0
project_organization_profiles.each do |profile|
#Create individual hash for the profile data
profiles_wbs_data["profile_id_#{profile.id}"] = Hash.new
end
#Update chart data
wbs_activity_elements.each do |wbs_activity_elt|
wbs_probable_value = pbs_probable_est_value[wbs_activity_elt.id]
unless wbs_probable_value.nil?
wbs_estimation_profiles_values = wbs_probable_value["profiles"]
project_organization_profiles.each do |profile|
wbs_profiles_value = nil
unless wbs_estimation_profiles_values.nil? || wbs_estimation_profiles_values.empty? || wbs_estimation_profiles_values["profile_id_#{profile.id}"].nil?
if !wbs_estimation_profiles_values["profile_id_#{profile.id}"]["ratio_id_#{ratio_reference.id}"].nil?
wbs_profiles_value = wbs_estimation_profiles_values["profile_id_#{profile.id}"]["ratio_id_#{ratio_reference.id}"][:value]
end
end
if !wbs_activity_elt.is_root?
if wbs_profiles_value.nil?
profiles_wbs_data["profile_id_#{profile.id}"]["#{wbs_activity_elt.name}"] = 0
else
value = number_with_delimiter(wbs_profiles_value.round(estimation_value.pe_attribute.precision.nil? ? user_number_precision : estimation_value.pe_attribute.precision))
profiles_wbs_data["profile_id_#{profile.id}"]["#{wbs_activity_elt.name}"] = value
end
end
end
end
end
# Update stacked chart data
project_organization_profiles.each do |profile|
#Prepare the final Stacked data hash for each profile
profile_hash = Hash.new
profile_hash["name"] = profile.name
profile_hash["data"] = Hash.new
profile_hash["data"] = profiles_wbs_data["profile_id_#{profile.id}"]
stacked_data << profile_hash
end
end
stacked_data
when "stacked_bar_chart_cost_per_phases_profiles"
end
###result
end
# Get the BAR or PIE CHART data for effort per phase or Cost per phase
def get_chart_data_effort_and_cost(pbs_project_element, module_project, estimation_value, view_widget)
chart_data = []
effort_breakdown_stacked_bar_dataset = {}
return chart_data if (!module_project.pemodule.alias.eql?(Projestimate::Application::EFFORT_BREAKDOWN) || estimation_value.nil?)
wbs_activity = module_project.wbs_activity
wbs_activity_root = wbs_activity.wbs_activity_elements.first.root
view_widget.show_min_max ? (levels = ['low', 'most_likely', 'high', 'probable']) : (levels = ['probable'])
if view_widget.show_min_max
# # get all project's wbs-project_elements
wbs_activity_elements = wbs_activity.wbs_activity_elements
wbs_activity_elements.each do |wbs_activity_elt|
effort_breakdown_stacked_bar_dataset["#{wbs_activity_elt.name.parameterize.underscore}"] = Array.new
end
else
probable_est_value = estimation_value.send("string_data_probable")
pbs_probable_for_consistency = probable_est_value.nil? ? nil : probable_est_value[pbs_project_element.id]
wbs_activity.wbs_activity_elements.each do |wbs_activity_elt|
if wbs_activity_elt != wbs_activity_root
level_estimation_values = probable_est_value
if level_estimation_values.nil? || level_estimation_values[pbs_project_element.id].nil? || level_estimation_values[pbs_project_element.id][wbs_activity_elt.id].nil? || level_estimation_values[pbs_project_element.id][wbs_activity_elt.id][:value].nil?
chart_data << ["#{wbs_activity_elt.name}", 0]
else
wbs_value = level_estimation_values[pbs_project_element.id][wbs_activity_elt.id][:value]
chart_data << ["#{wbs_activity_elt.name}", wbs_value.round(user_number_precision)]
end
end
end
end
chart_data
end
#The view to display result with ACTIVITIES : EFFORT PER PHASE AND COST PER PHASE TABLE
def display_effort_or_cost_per_phase(pbs_project_element, module_project_id, estimation_value, view_widget_id)
res = String.new
view_widget = ViewsWidget.find(view_widget_id)
module_project = ModuleProject.find(module_project_id)
pemodule = module_project.pemodule
precision = estimation_value.pe_attribute.precision.nil? ? user_number_precision : estimation_value.pe_attribute.precision
# Only the Modules with activities
with_activities = pemodule.yes_for_output_with_ratio? || pemodule.yes_for_output_without_ratio? || pemodule.yes_for_input_output_with_ratio? || pemodule.yes_for_input_output_without_ratio?
return res unless with_activities
wbs_activity = module_project.wbs_activity
wbs_activity_elements = wbs_activity.wbs_activity_elements
if view_widget.show_min_max
levels = ['low', 'most_likely', 'high', 'probable']
colspan = 4
rowspan = 2
else
levels = ['probable']
colspan = 1
rowspan = 1
end
res << " <table class='table table-condensed table-bordered table_effort_per_phase'>
<tr><th rowspan=#{rowspan}>Phases</th>"
# Get the module_project probable estimation values for showing element consistency
probable_est_value_for_consistency = nil
pbs_level_data_for_consistency = Hash.new
probable_est_value_for_consistency = estimation_value.send("string_data_probable")
res << "<th colspan='#{colspan}'>
<span class='attribute_tooltip' title='#{estimation_value.pe_attribute.description} #{display_rule(estimation_value)}'>
#{estimation_value.pe_attribute.name} (#{estimation_value.pe_attribute.alias == "cost" ? @project.organization.currency : ''})
</span>
</th>"
# For is_consistent purpose
levels.each do |level|
unless level.eql?("probable")
pbs_data_level = estimation_value.send("string_data_#{level}")
pbs_data_level.nil? ? pbs_level_data_for_consistency[level] = nil : pbs_level_data_for_consistency[level] = pbs_data_level[pbs_project_element.id]
end
end
res << '</tr>'
# We are showing for each PBS and/or ACTIVITY the (low, most_likely, high) values
if view_widget.show_min_max
res << '<tr>'
levels.each do |level|
res << "<th>#{level.humanize}</th>"
end
res << '</tr>'
end
module_project.wbs_activity.wbs_activity_elements.each do |wbs_activity_elt|
#For wbs-activity-completion node consistency
completion_consistency = ""
title = ""
res << "<tr>
<td>
<span class='tree_element_in_out' title='#{title}' style='margin-left:#{wbs_activity_elt.depth}em;'> #{wbs_activity_elt.name} </span>
</td>"
levels.each do |level|
res << "<td class=''>"
res << "<span class='pull-right'>"
level_estimation_values = Hash.new
level_estimation_values = estimation_value.send("string_data_#{level}")
pbs_estimation_values = level_estimation_values[pbs_project_element.id]
if wbs_activity_elt.is_root?
begin
if estimation_value.pe_attribute.alias == "cost"
@wbs_unit = get_attribute_unit(estimation_value.pe_attribute)
else
@wbs_unit = convert_label(pbs_estimation_values[wbs_activity_elt.id][:value], @project.organization)
end
rescue
if estimation_value.pe_attribute.alias == "cost"
@wbs_unit = get_attribute_unit(estimation_value.pe_attribute)
else
@wbs_unit = convert_label(pbs_estimation_values[wbs_activity_elt.id], @project.organization) unless pbs_estimation_values.nil?
end
end
end
begin
if estimation_value.pe_attribute.alias == "cost"
if pbs_estimation_values.nil?
res << "-"
else
res << "#{convert_with_precision(pbs_estimation_values[wbs_activity_elt.id][:value], 2)}"
end
else
res << "#{convert_with_precision(convert(pbs_estimation_values[wbs_activity_elt.id][:value], @project.organization), 2)} #{@wbs_unit}"
end
rescue
if estimation_value.pe_attribute.alias == "cost"
if pbs_estimation_values.nil?
res << "-"
else
res << "#{ convert_with_precision(pbs_estimation_values[wbs_activity_elt.id], 2) }"
end
else
res << "#{ convert_with_precision(convert(pbs_estimation_values[wbs_activity_elt.id], @project.organization), precision) } #{@wbs_unit}" unless pbs_estimation_values.nil?
end
end
res << "</span>"
res << "</td>"
end
res << '</tr>'
end
res << '</table>'
res
end
def view_widget_title(view_widget)
title = String.new
title << "#{view_widget.name} \n"
title << "#{I18n.t(:associate_pbs_element)} : #{current_component.to_s} \n"
title << "Module : #{view_widget.module_project.to_s}"
title
end
end