app/views/projects/_show_project_tree_history.html.erb
<div id="project_history_actions" style="margin-bottom: 50px;" xmlns="http://www.w3.org/1999/html">
<div class="project_history">
<h4>
<%= hidden_field_tag :select_at_least_one_project, I18n.t(:select_at_least_one_project) %>
<span style="color:#23A4FF; float: left; margin-left: 0px; margin-right: 10px;">Estimation Actions : </span>
<% %>
<%= link_to '', '', :class => 'node_link_to button_attribute_tooltip icon-pencil pull-left', :id => 'edit_node_path', :title => I18n.t('edit'), :remote => true %>
<%= link_to '', '', :class => 'node_link_to button_attribute_tooltip icon-star pull-left', :id => 'activate_node_path', :title => I18n.t('button_activate_project'), :remote => true %>
<%= link_to '', '', :class => 'node_link_to button_attribute_tooltip icon-ok-circle pull-left', :id => 'promote_node_path', :title => I18n.t('button_commit_project'), :remote => true %>
<%= link_to('', '', :class => 'node_link_to button_attribute_tooltip fa fa-code-fork pull-left', :id => 'set_checkout_version_path', style: "margin-top:4px;", :title => I18n.t('button_checkout_project'), remote: true, :confirm => (I18n.t(:confirm_new_branch_project_checkout) unless @project.is_childless?)) %>
<%= link_to '', '', :class => 'node_link_to button_attribute_tooltip icon-info pull-left', :id => 'find_use_projects_from_history', :project_id => @project.id, :title => I18n.t('button_find_use'), :remote => true %>
<%= link_to '', '', :class => 'node_link_to button_attribute_tooltip icon-copy pull-left', :id => 'duplicate_node_path', :title => I18n.t('button_duplicate_project'), :remote => true %>
<%= link_to '', '', :class => 'node_link_to button_attribute_tooltip icon-trash pull-left', :style => 'color:red', :id => 'delete_node_path', :title => I18n.t('delete'), :remote => true %>
</h4>
</div>
</div>
<div id="container">
<div id="center-container">
<div id="infovis" class="infovis_project_history"></div>
</div>
<div id="log"></div>
</div>
<script>
var labelType, useGradients, nativeTextSupport, animate;
(function() {
var ua = navigator.userAgent,
iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
typeOfCanvas = typeof HTMLCanvasElement,
nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
textSupport = nativeCanvasSupport
&& (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
//I'm setting this based on the fact that ExCanvas provides text support for IE
//and that as of today iPhone/iPad current text support is lame
labelType = (!nativeCanvasSupport || (textSupport && !iStuff))? 'Native' : 'HTML';
nativeTextSupport = labelType == 'Native';
useGradients = nativeCanvasSupport;
animate = !(iStuff || !nativeCanvasSupport);
})();
var Log = {
elem: false,
write: function(text){
if (!this.elem)
this.elem = document.getElementById('log');
this.elem.innerHTML = text;
this.elem.style.left = (450 - this.elem.offsetWidth / 2) + 'px';
}
};
// function init(){
//Init data from Rails project history data
// FOr ex. var json = {"id":"301","name":"ggg","title":"ggg","version":"1.0","data":{},"children":[{"id":"305","name":"ggg","title":"ggg","version":"1.0-1.0","data":{},"children":[]},{"id":"304","name":"ggg","title":"ggg","version":"1.1","data":{},"children":[{"id":"306","name":"ggg","title":"ggg","version":"1.2","data":{},"children":[{"id":"30","name":"moi","title":"moi","version":"1.2","data":{},"children":[]}]}]}]};
var json = $("#project_tree_id").data("project_tree");
//end
//init Spacetree
//Create a new ST instance
var st = new $jit.ST({
//id of viz container element
injectInto: 'infovis',
//set orientation
orientation: 'left',
//set duration for the animation
duration: 0, //800,
//set animation transition type
transition: $jit.Trans.Quart.easeInOut,
//set distance between node and its children
levelDistance: 50,
//set the maximum depth/level to show in the Tree
levelsToShow: 9999,
//offsetWidth: 100,
onComplete: function () {
var LastnodeTop = 0;
var LastnodeLeft = 0;
$("div.node").each(function () {
var pos = $(this).position();
if (pos.top > LastnodeTop)
LastnodeTop = pos.top;
if (pos.left > LastnodeLeft)
LastnodeLeft = pos.left;
});
var LastnodeTopStr = LastnodeTop.toString();
var LastnodeLeftStr = LastnodeLeft.toString();
LastnodeTopStr = LastnodeTopStr.substring(0, 4);
LastnodeLeftStr = LastnodeLeftStr.substring(0, 4);
var LastnodeTopInt = parseInt(LastnodeTopStr) + 100;
var LastnodeLeftInt = parseInt(LastnodeLeftStr) + 100;
// $("#center-container").attr("style", "height:" + LastnodeTopInt + "px");
// $("#center-container").attr("style", "width:" + LastnodeLeftInt + "px");
var treeRoot = st.root;
},
//enable panning
Navigation: {
enable:true,
panning:true
},
//set node and edge styles
//set overridable=true for styling individual
//nodes or edges
Node: {
height: 75, //20,
width: 60,
type: 'circle', //'rectangle',
color: '#aaa',
overridable: true
},
Edge: {
type: 'bezier',
overridable: true
},
onBeforeCompute: function(node){
//Log.write("loading " + node.name);
},
onAfterCompute: function(){
//Log.write("Project: Title");
},
//This method is called on DOM label creation.
//Use this method to add event handlers and styles to
//your node.
onCreateLabel: function(label, node){
label.id = node.id;
//label.innerHTML = node.name;
//Display node version and state
var version_maxi_length = 16;
var node_version = "";
if (node.name.length > version_maxi_length)
node_version = node.name.substring(0, 16) + "...";
else
node_version = node.name;
var display = node_version;
var data = node.data;
var my_check_box = document.createElement('input');
my_check_box.type = 'checkbox';
my_check_box.name = 'checkbox_'+node.id;
my_check_box.id = 'checkbox_'+node.id;
my_check_box.value = node.id;
my_check_box.className = 'tree_node_checkbox';
my_check_box.dataset['node_state'] = node.data.state;
var state = document.createElement('Label');
state.type = 'text';
state.innerText = capitaliseFirstLetter(node.data.state).replace('_', ' ');
display += "<br>";
label.innerHTML = display;
label.appendChild(state);
label.appendChild(my_check_box);
//Current project is styled in bold
if ( node.id == $('#current_showed_project_id').val()){
label.innerHTML = "<b style='font-weight: bold; color: #990000;'>"+ label.innerHTML +"</b>";
}
//Enable/disable some actions according to the checked node
label.onclick = function(){
var counter = 0,
checkout_counter = 0,
i = 0;
var states_to_confirm = {checkpoint: "checkpoint", released: "released", rejected: "rejected"};
var states_to_checkout = {checkpoint: "checkpoint", released: "released"};
var checkbox_objects = document.getElementsByClassName('tree_node_checkbox');
// loop through all collected checkbox objects
for (i = 0; i < checkbox_objects.length; i++) {
// if input object is checkbox and checkbox is checked then ... for promote
if (checkbox_objects[i].dataset['node_state'] in states_to_confirm && checkbox_objects[i].checked === true) {
// ... increase counter
counter++;
}
//For checkout button
if ( !(checkbox_objects[i].dataset['node_state'] in states_to_checkout) && checkbox_objects[i].checked === true ) {
// ... increase checkout counter
checkout_counter++;
}
}
//Get promote link_to
var promote_button = document.getElementById('promote_node_path');
if(counter > 0){
promote_button.disabled = true;
$('#promote_node_path').removeClass('icon-ok-circle');
}
else{
promote_button.disabled = false;
$('#promote_node_path').addClass('icon-ok-circle');
}
//Get checkout link_to
var checkout_button = document.getElementById('checkout_node_path');
if(checkout_counter > 0){
checkout_button.disabled = true;
$('#checkout_node_path').removeClass('icon-step-forward');
}
else{
checkout_button.disabled = false;
$('#checkout_node_path').addClass('icon-step-forward');
}
};
// label.onclick = function(){
// if(normal.checked) {
// //if(node.checked) {
// alert($("#checkbox_"+node.id).val());
// st.onClick(node.id);
// } else {
// //alert($(this));
// st.setRoot(node.id, 'animate');
// }
// };
//set label styles
var style = label.style;
style.width = 60 + 'px';
style.height = 17 + 'px';
style.cursor = 'pointer';
style.color = '#333';
style.fontSize = '0.9em'; /*'0.8em';*/
style.textAlign= 'center';
style.paddingTop = '3px';
style.fontWeight = 'bold';
},
//For displaying Tooltips
Tips: {
enable: true,
type: 'HTML',
offsetX: 10,
offsetY: 10,
onShow: function (tip, node)
{
tip.innerHTML = getToolTip(node);
}
},
//This method is called right before plotting
//a node. It's useful for changing an individual node
//style properties before plotting it.
//The data properties prefixed with a dollar
//sign will override the global node style properties.
onBeforePlotNode: function(node){
//add some color to the nodes in the path between the
//root node and the selected node.
if (node.selected) {
node.data.$color = "#ff7";
}
else {
delete node.data.$color;
//if the node belongs to the last plotted level
if(!node.anySubnode("exist")) {
//count children number
var count = 0;
node.eachSubnode(function(n) { count++; });
//assign a node color based on
//how many children it has
node.data.$color = ['#aaa', '#baa', '#caa', '#daa', '#eaa', '#faa'][count];
}
}
},
//This method is called right before plotting
//an edge. It's useful for changing an individual edge
//style properties before plotting it.
//Edge data proprties prefixed with a dollar sign will
//override the Edge global style properties.
onBeforePlotLine: function(adj){
if (adj.nodeFrom.selected && adj.nodeTo.selected) {
adj.data.$color = "#eed";
adj.data.$lineWidth = 3;
}
else {
delete adj.data.$color;
delete adj.data.$lineWidth;
}
}
});
var infovis_canvas = document.getElementById("infovis-canvas");
var infovis_label = document.getElementById("infovis-label");
var infovis_canvas_widget = document.getElementById("infovis-canvaswidget");
// infovis_canvas.style.left = "-300px";
// infovis_label.style.left = "-300px";
//load json data
st.loadJSON(json);
//compute node positions and layout
st.compute();
//optional: make a translation of the tree
st.geom.translate(new $jit.Complex(-200, 0), "current");
//emulate a click on the root node.
///st.onClick(st.root);
//Add offset on the Tree Root
st.onClick(st.root, {
Move: {
offsetX: 400,
offsetY: 100
}
});
//end
//Added by me
//st.each(st, function(node){
// $jit.json.each(json, function(node){
// st.addEvent(node, 'click', function(){ alert('hello'); });
// });
//end added by me
//Add event handlers to switch spacetree orientation.
var top = $jit.id('r-top'),
left = $jit.id('r-left'),
bottom = $jit.id('r-bottom'),
right = $jit.id('r-right'),
normal = $jit.id('s-normal');
function changeHandler() {
if(this.checked) {
top.disabled = bottom.disabled = right.disabled = left.disabled = true;
st.switchPosition(this.value, "animate", {
onComplete: function(){
top.disabled = bottom.disabled = right.disabled = left.disabled = false;
}
});
}
};
top.onchange = left.onchange = bottom.onchange = right.onchange = changeHandler;
//end
// }; // END init
//Function that display Tooltips
function getToolTip(node){
return node.data.title + "-" + node.name;
}
function capitaliseFirstLetter(string)
{
return string.charAt(0).toUpperCase() + string.slice(1);
}
</script>