Plugin: how to add button on issue list?
Added by Stéphane CHÂTEAU over 6 years ago
Hi everybody.
I'm currently develop a plugin suite for a french company that add a geometry (spatial database) to issues.
This first plugin works fine.
The second one add a infos and button on issue details to be able to send issue ID to a QGis plugin via WebSocket to be able to say to QGis to display the geometry.
It's works fine too.
The init.rb:
require 'redmine' Rails.logger.info 'Plugin d’affichage du statut de la présence d’une géométrie pour Redmine' # This is the important line. # It requires the file in lib/geometry_status/view_hook_listeners.rb require_dependency 'geometry_status/view_hook_listeners' Redmine::Plugin.register :geometry_status do name 'Geometry Status plugin' author 'xxxxxx' description 'Ceci est le plugin pour l’intégration du status de la géométrie dans Redmine' version '1.0.0' # Requires the redmine geometry plugin requires_redmine_plugin :geometry, :version_or_higher => '1.0.0' end
view_hook_listeners.rb:
module GeometryStatus
# Voir : http://www.redmine.org/projects/redmine/wiki/Hooks
class Hooks < Redmine::Hook::ViewListener
def view_layouts_base_html_head(context)
stylesheet_link_tag("plugin", :plugin => 'geometry_status') +
javascript_include_tag('plugin', :plugin => 'geometry_status')
end
# rewrite select for trackers on issue form // view_issues_show_details_bottom
def view_issues_show_details_bottom(context={})
issue = context[:issue]
project = context[:project]
html_return = ''
if project != nil && project.id == 24 && issue != nil
# Afficher tous les custom fields :
#==================================
# html_return = "<hr>"
# CustomField.all.each do |custom|
# html_return += "<br/>custom id=#{custom.id} / name=#{custom.name}"
# custom.possible_values.each do |value|
# html_return += "<br/> => #{value}"
# end
# end
# return html_return
# id == 24 => project.name == "Base des défauts"
pointe = Pointes.where(issue_id: issue.id)
if pointe.first != nil
# La géométrie a été trouvée
html_button_click = "onClick=\"call_qgis('#{issue.id}|#{pointe.first.pointe}')\""
html_button = "<button class=\"geometry_status_button\" #{html_button_click}>" + image_tag('geometry.png', :plugin => 'geometry_status', :title => "La FT #{issue.id} a une géométrie\nCliquez sur le bouton pour l'ouvrir dans le plugin Redmine sous QGis", :align => "center") + "</button>"
html_return = "<hr><p>#{html_button}<strong class=\"geometry_status_centered_text\">Géométrie</strong><div class=\"wiki\"><p>La FT a une géométrie => WKT = #{pointe.first.pointe}</p></div>"
else
# La géométrie n'a pas été trouvée
html_button_click = "onClick=\"call_qgis('#{issue.id}|')\""
value = CustomField.select('id, name, possible_values').where(name: 'Portée du Défaut').first
if value
# Obligé de mettre dans "#{xxxxxx}" sinon la comparaison ne fonctionne pas !
portee_du_defaut = "#{issue.custom_value_for(value.id)}"
if portee_du_defaut == "Général"
html_button = "<button class=\"geometry_status_button\" #{html_button_click}>" + image_tag('geometry_none.png', :plugin => 'geometry_status', :title => "La FT #{issue.id} n'a pas de géométrie\nCliquez sur le bouton pour l'ouvrir dans le plugin Redmine sous QGis", :align => "center") + "</button>"
html_return = "<hr><p>#{html_button}<strong class=\"geometry_status_centered_text\">Géométrie</strong><div class=\"wiki\"><p>La FT générale ne contient pas de géométrie</p></div>"
elsif portee_du_defaut == "Local"
html_button = "<button class=\"geometry_status_button\" #{html_button_click}>" + image_tag('geometry_gray.png', :plugin => 'geometry_status', :title => "La FT #{issue.id} n'a pas de géométrie mais elle devrait en avoir une !\nCliquez sur le bouton pour l'ouvrir dans le plugin Redmine sous QGis", :align => "center") + "</button>"
html_return = "<hr><p>#{html_button}<strong class=\"geometry_status_centered_text\">Géométrie</strong><div class=\"wiki\"><p>La FT locale ne contient pas de géométrie mais elle devrait en avoir une !</p></div>"
else
html_return = "<hr><p><strong class=\"geometry_status_centered_text\">Géométrie</strong><div class=\"wiki\"><p>La FT ne contient pas de géométrie. <strong class=\"geometry_unknown_portee_default\">Attention, la portée du défaut '#{portee_du_defaut}' est inconnue !</strong></p></div>"
end
end
end
end
html_return
end
end
end
The websocket is implemented into the plugin.js.
All of this is working fine.
Now, I would like to add a global button on issue list page to be able to send all displayed (and filtered) issue's ID to the QGis plugin.
I try to use hooks:
view_layouts_base_body_top
view_layouts_base_content
view_layouts_base_body_bottom
view_projects_show_right
But none of them is placed where I want: at the top of the list, behind the apply/clear filters line.
And another problem is: i have not the issue's ids list into the context passsed into the view hooks.
I'm sure there is another way (may be by controller hooks?) but I don't know how to use it.
I hope some peaple here can show me the way to do these expected things.
Thanks for all,
Kind regards,
Stéphane.
Replies (2)
RE: Plugin: how to add button on issue list?
-
Added by kumar abhinav over 6 years ago
Use 'view_issues_index_bottom' hook.
It renders at the bottom of issue list page but you can use js to move your element around as desired.
The hook is present in app/views/issues/index.html.erb.
The hook also provides the list of issues in @issues.
RE: Plugin: how to add button on issue list?
-
Added by Stéphane CHÂTEAU over 6 years ago
Wonderfull, thanks a lot !!!!!!!!
In my javascript I have add:
function geometry_status_move_geometry_button()
{
// Move list_geometry_button (if exist) in the correct place
var eltDestination = document.getElementById('query_form_with_buttons');
if (eltDestination != null)
{
var allSelect = eltDestination.getElementsByClassName("buttons");
if (allSelect.length > 1)
{
eltDestination = allSelect[allSelect.length - 1]
if (eltDestination != null)
{
var eltSource = document.getElementById('id_list_geometry_button');
if (eltSource != null)
{
eltDestination.appendChild(eltSource);
}
}
}
}
}
$(document).ready(function()
{
geometry_status_move_geometry_button();
});
It do the job. Just some think that take me a lot of time to understand:
Moving the element where I put it => it seem to be is into a <form> and so clicking on button make the page reload making WenbSocket.send never call.
I shoud modify my js script like :
function call_qgis(evt, issues_ids_and_wtk)
{
// Very important!
// If not these lines, clicking on button after moving it into a form will send the form and
// force the page to be reloaded.
evt = evt || window.event;
evt.preventDefault();
try
{
if ("WebSocket" in window)
{
var bConnected = false;
// Let us open a web socket
ws = new WebSocket("wss://localhost:8025/xxxxxxxx");
ws.onopen = function()
{
bConnected = true;
// Web Socket is connected, send data using send()
var jsonArr = [];
issues_ids_and_wtk.split(",").forEach(function (item)
{
array_ids_wkf = item.split("|");
if (array_ids_wkf.length == 2)
{
jsonArr.push({ issue_id: array_ids_wkf[0], wkt: array_ids_wkf[1]});
}
});
ws.send(JSON.stringify(jsonArr));
};
ws.onmessage = function (evt)
{
if (evt.data != "OK")
{
alert("Error return by QGis plugin:\n" + evt.data);
}
ws.close();
};
ws.onclose = function(evt)
{ // websocket is closed.
if (!bConnected)
{
alert("Not working, server is offline\n");
// Pour Chrome activer : chrome://flags/#allow-insecure-localhost
}
};
window.onbeforeunload = function(event)
{
ws.close();
};
}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!\n");
}
}
catch(error)
{
alert(error);
}
}