Index: vue/src/assets/images/devops/DevSupport/github.png =================================================================== diff -u -r2475357c1c378d448dece7e552d1391acc6147cd -r11f26ca6ddd6fd698fc3ccd8cda9117bacce7623 --- vue/src/assets/images/devops/DevSupport/github.png (.../github.png) (revision 2475357c1c378d448dece7e552d1391acc6147cd) +++ vue/src/assets/images/devops/DevSupport/github.png (.../github.png) (revision 11f26ca6ddd6fd698fc3ccd8cda9117bacce7623) @@ -895,8 +895,7 @@ stroke-width: 1.5px; } .node text { - font-size: 10px; - font-family: sans-serif; + font-size: 12px; } .link { fill: none; Index: arms/js/pdServiceJira.js =================================================================== diff -u -r18f16ee8ddbb9d79d981c8ae59124ac69e627939 -r11f26ca6ddd6fd698fc3ccd8cda9117bacce7623 --- arms/js/pdServiceJira.js (.../pdServiceJira.js) (revision 18f16ee8ddbb9d79d981c8ae59124ac69e627939) +++ arms/js/pdServiceJira.js (.../pdServiceJira.js) (revision 11f26ca6ddd6fd698fc3ccd8cda9117bacce7623) @@ -12,6 +12,9 @@ setSideMenu("sidebar_menu_product", "sidebar_menu_product_jira_connect"); dataTableLoad(); + + // 차트 초기화 + rederD3Chart(); } // --- 데이터 테이블 설정 --- // @@ -293,570 +296,647 @@ } }); -/* ---------------------------------------- d3 config ------------------------------------ */ -/* d3 */ -var treeData = { - name: "1.제품(서비스) 선택 → 2.Version 선택 → 3.JIRA 프로젝트 선택", - type: "a-RMS" -}; -//treeJSON = d3.json(flare_data, function(error, treeData) { +//////////////////////////////////////////////////////////////////////////////////////// +// --- 연결 차트 표시 --- // +//////////////////////////////////////////////////////////////////////////////////////// +function rederD3Chart() { + /* ---------------------------------------- d3 config ------------------------------------ */ + /* d3 */ + var treeData = { + name: "1. 제품(서비스) 선택 → 2. Version 선택 → 3. 제품(서비스) ~ Jira 연결", + type: "a-RMS" + }; -// Calculate total nodes, max label length -var totalNodes = 0; -var maxLabelLength = 0; -// variables for drag/drop -var selectedNode = null; -var draggingNode = null; -// panning variables -var panSpeed = 200; -var panBoundary = 20; // Within 20px from edges will pan when dragging. -// Misc. variables -var i = 0; -var duration = 750; -var root; + // Calculate total nodes, max label length + var totalNodes = 0; + var maxLabelLength = 0; + // variables for drag/drop + var selectedNode = null; + var draggingNode = null; + // panning variables + var panSpeed = 200; + var panBoundary = 20; // Within 20px from edges will pan when dragging. + // Misc. variables + var i = 0; + var duration = 750; + var root; -// size of the diagram -//edit 313devops -//var viewerWidth = $(document).width(); -//var viewerHeight = $(document).height(); -var viewerWidth = $("#tree_container").outerHeight(); -var viewerHeight = 295; + // size of the diagram + var viewerWidth = $("#tree_container")[0].clientWidth; + var viewerHeight = 295; -var tree = d3.layout.tree().size([viewerHeight, viewerWidth]); + var tree = d3.layout.tree().size([viewerHeight, viewerWidth]); -// define a d3 diagonal projection for use by the node paths later on. -var diagonal = d3.svg.diagonal().projection(function (d) { - return [d.y, d.x]; -}); + // define a d3 diagonal projection for use by the node paths later on. + var diagonal = d3.svg.diagonal().projection(function (d) { + return [d.y, d.x]; + }); -// A recursive helper function for performing some setup by walking through all nodes -function visit(parent, visitFn, childrenFn) { - if (!parent) return; + // A recursive helper function for performing some setup by walking through all nodes + function visit(parent, visitFn, childrenFn) { + if (!parent) return; - visitFn(parent); + visitFn(parent); - var children = childrenFn(parent); - if (children) { - var count = children.length; - for (var i = 0; i < count; i++) { - visit(children[i], visitFn, childrenFn); + var children = childrenFn(parent); + if (children) { + var count = children.length; + for (var i = 0; i < count; i++) { + visit(children[i], visitFn, childrenFn); + } } } -} -// Call visit function to establish maxLabelLength -visit( - treeData, - function (d) { - totalNodes++; - maxLabelLength = Math.max(d.name.length, maxLabelLength); - }, - function (d) { - return d.children && d.children.length > 0 ? d.children : null; + // Call visit function to establish maxLabelLength + visit( + treeData, + function (d) { + totalNodes++; + maxLabelLength = Math.max(d.name.length, maxLabelLength); + }, + function (d) { + return d.children && d.children.length > 0 ? d.children : null; + } + ); + + // sort the tree according to the node names + function sortTree() { + tree.sort(function (a, b) { + return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1; + }); } -); -// sort the tree according to the node names -function sortTree() { - tree.sort(function (a, b) { - return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1; - }); -} -// Sort the tree initially incase the JSON isn't in a sorted order. -sortTree(); + // Sort the tree initially incase the JSON isn't in a sorted order. + sortTree(); -// TODO: Pan function, can be better implemented. -function pan(domNode, direction) { - var speed = panSpeed; - if (panTimer) { - clearTimeout(panTimer); - translateCoords = d3.transform(svgGroup.attr("transform")); - if (direction == "left" || direction == "right") { - translateX = direction == "left" ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed; - translateY = translateCoords.translate[1]; - } else if (direction == "up" || direction == "down") { - translateX = translateCoords.translate[0]; - translateY = direction == "up" ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed; + // TODO: Pan function, can be better implemented. + function pan(domNode, direction) { + var speed = panSpeed; + if (panTimer) { + clearTimeout(panTimer); + translateCoords = d3.transform(svgGroup.attr("transform")); + if (direction == "left" || direction == "right") { + translateX = direction == "left" ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed; + translateY = translateCoords.translate[1]; + } else if (direction == "up" || direction == "down") { + translateX = translateCoords.translate[0]; + translateY = direction == "up" ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed; + } + scaleX = translateCoords.scale[0]; + scaleY = translateCoords.scale[1]; + scale = zoomListener.scale(); + svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")"); + d3.select(domNode) + .select("g.node") + .attr("transform", "translate(" + translateX + "," + translateY + ")"); + zoomListener.scale(zoomListener.scale()); + zoomListener.translate([translateX, translateY]); + panTimer = setTimeout(function () { + pan(domNode, speed, direction); + }, 50); } - scaleX = translateCoords.scale[0]; - scaleY = translateCoords.scale[1]; - scale = zoomListener.scale(); - svgGroup.transition().attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + scale + ")"); - d3.select(domNode) - .select("g.node") - .attr("transform", "translate(" + translateX + "," + translateY + ")"); - zoomListener.scale(zoomListener.scale()); - zoomListener.translate([translateX, translateY]); - panTimer = setTimeout(function () { - pan(domNode, speed, direction); - }, 50); } -} -// Define the zoom function for the zoomable tree -function zoom() { - //edit 313devops - svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); - //svgGroup.attr("transform", "translate(" + "221,79" + ")scale(" + 1.5 + ")"); -} + // Define the zoom function for the zoomable tree + function zoom() { + //edit 313devops + svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); + //svgGroup.attr("transform", "translate(" + "221,79" + ")scale(" + 1.5 + ")"); + } -// define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents -var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); + // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents + var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); -function initiateDrag(d, domNode) { - draggingNode = d; - d3.select(domNode).select(".ghostCircle").attr("pointer-events", "none"); - d3.selectAll(".ghostCircle").attr("class", "ghostCircle show"); - d3.select(domNode).attr("class", "node activeDrag"); + function initiateDrag(d, domNode) { + draggingNode = d; + d3.select(domNode).select(".ghostCircle").attr("pointer-events", "none"); + d3.selectAll(".ghostCircle").attr("class", "ghostCircle show"); + d3.select(domNode).attr("class", "node activeDrag"); - svgGroup.selectAll("g.node").sort(function (a, b) { - // select the parent and sort the path's - if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back - else return -1; // a is the hovered element, bring "a" to the front - }); - // if nodes has children, remove the links and nodes - if (nodes.length > 1) { - // remove link paths - links = tree.links(nodes); - nodePaths = svgGroup + svgGroup.selectAll("g.node").sort(function (a, b) { + // select the parent and sort the path's + if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back + else return -1; // a is the hovered element, bring "a" to the front + }); + // if nodes has children, remove the links and nodes + if (nodes.length > 1) { + // remove link paths + links = tree.links(nodes); + nodePaths = svgGroup + .selectAll("path.link") + .data(links, function (d) { + return d.target.id; + }) + .remove(); + // remove child nodes + nodesExit = svgGroup + .selectAll("g.node") + .data(nodes, function (d) { + return d.id; + }) + .filter(function (d, i) { + if (d.id == draggingNode.id) { + return false; + } + return true; + }) + .remove(); + } + + // remove parent link + parentLink = tree.links(tree.nodes(draggingNode.parent)); + svgGroup .selectAll("path.link") - .data(links, function (d) { - return d.target.id; - }) - .remove(); - // remove child nodes - nodesExit = svgGroup - .selectAll("g.node") - .data(nodes, function (d) { - return d.id; - }) .filter(function (d, i) { - if (d.id == draggingNode.id) { - return false; + if (d.target.id == draggingNode.id) { + return true; } - return true; + return false; }) .remove(); + + dragStarted = null; } - // remove parent link - parentLink = tree.links(tree.nodes(draggingNode.parent)); - svgGroup - .selectAll("path.link") - .filter(function (d, i) { - if (d.target.id == draggingNode.id) { - return true; + // define the baseSvg, attaching a class for styling and the zoomListener + var baseSvg = d3 + .select("#tree_container") + .append("svg") + .attr("width", viewerWidth) + .attr("height", viewerHeight) + .attr("class", "overlay") + .call(zoomListener); + + // Define the drag listeners for drag/drop behaviour of nodes. + dragListener = d3.behavior + .drag() + .on("dragstart", function (d) { + if (d == root) { + return; } - return false; + dragStarted = true; + nodes = tree.nodes(d); + d3.event.sourceEvent.stopPropagation(); + // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none'); }) - .remove(); + .on("drag", function (d) { + if (d == root) { + return; + } + if (dragStarted) { + domNode = this; + initiateDrag(d, domNode); + } - dragStarted = null; -} + // get coords of mouseEvent relative to svg container to allow for panning + relCoords = d3.mouse($("svg").get(0)); + if (relCoords[0] < panBoundary) { + panTimer = true; + pan(this, "left"); + } else if (relCoords[0] > $("svg").width() - panBoundary) { + panTimer = true; + pan(this, "right"); + } else if (relCoords[1] < panBoundary) { + panTimer = true; + pan(this, "up"); + } else if (relCoords[1] > $("svg").height() - panBoundary) { + panTimer = true; + pan(this, "down"); + } else { + try { + clearTimeout(panTimer); + } catch (e) {} + } -// define the baseSvg, attaching a class for styling and the zoomListener -var baseSvg = d3 - .select("#tree_container") - .append("svg") - .attr("width", viewerWidth) - .attr("height", viewerHeight) - .attr("class", "overlay") - .call(zoomListener); + d.x0 += d3.event.dy; + d.y0 += d3.event.dx; + var node = d3.select(this); + node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")"); + updateTempConnector(); + }) + .on("dragend", function (d) { + if (d == root) { + return; + } + domNode = this; + if (selectedNode) { + // now remove the element from the parent, and insert it into the new elements children + var index = draggingNode.parent.children.indexOf(draggingNode); + if (index > -1) { + draggingNode.parent.children.splice(index, 1); + } + if (typeof selectedNode.children !== "undefined" || typeof selectedNode._children !== "undefined") { + if (typeof selectedNode.children !== "undefined") { + selectedNode.children.push(draggingNode); + } else { + selectedNode._children.push(draggingNode); + } + } else { + selectedNode.children = []; + selectedNode.children.push(draggingNode); + } + // Make sure that the node being added to is expanded so user can see added node is correctly moved + expand(selectedNode); + sortTree(); + endDrag(); + } else { + endDrag(); + } + }); -// Define the drag listeners for drag/drop behaviour of nodes. -dragListener = d3.behavior - .drag() - .on("dragstart", function (d) { - if (d == root) { - return; + function endDrag() { + selectedNode = null; + d3.selectAll(".ghostCircle").attr("class", "ghostCircle"); + d3.select(domNode).attr("class", "node"); + // now restore the mouseover event or we won't be able to drag a 2nd time + d3.select(domNode).select(".ghostCircle").attr("pointer-events", ""); + updateTempConnector(); + if (draggingNode !== null) { + update(root); + centerNode(draggingNode); + draggingNode = null; } - dragStarted = true; - nodes = tree.nodes(d); - d3.event.sourceEvent.stopPropagation(); - // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none'); - }) - .on("drag", function (d) { - if (d == root) { - return; + } + + // Helper functions for collapsing and expanding nodes. + function collapse(d) { + if (d.children) { + d._children = d.children; + d._children.forEach(collapse); + d.children = null; } - if (dragStarted) { - domNode = this; - initiateDrag(d, domNode); - } + } - // get coords of mouseEvent relative to svg container to allow for panning - relCoords = d3.mouse($("svg").get(0)); - if (relCoords[0] < panBoundary) { - panTimer = true; - pan(this, "left"); - } else if (relCoords[0] > $("svg").width() - panBoundary) { - panTimer = true; - pan(this, "right"); - } else if (relCoords[1] < panBoundary) { - panTimer = true; - pan(this, "up"); - } else if (relCoords[1] > $("svg").height() - panBoundary) { - panTimer = true; - pan(this, "down"); - } else { - try { - clearTimeout(panTimer); - } catch (e) {} + function expand(d) { + if (d._children) { + d.children = d._children; + d.children.forEach(expand); + d._children = null; } + } - d.x0 += d3.event.dy; - d.y0 += d3.event.dx; - var node = d3.select(this); - node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")"); + var overCircle = function (d) { + selectedNode = d; updateTempConnector(); - }) - .on("dragend", function (d) { - if (d == root) { - return; - } - domNode = this; - if (selectedNode) { - // now remove the element from the parent, and insert it into the new elements children - var index = draggingNode.parent.children.indexOf(draggingNode); - if (index > -1) { - draggingNode.parent.children.splice(index, 1); - } - if (typeof selectedNode.children !== "undefined" || typeof selectedNode._children !== "undefined") { - if (typeof selectedNode.children !== "undefined") { - selectedNode.children.push(draggingNode); - } else { - selectedNode._children.push(draggingNode); + }; + var outCircle = function (d) { + selectedNode = null; + updateTempConnector(); + }; + + // Function to update the temporary connector indicating dragging affiliation + var updateTempConnector = function () { + var data = []; + if (draggingNode !== null && selectedNode !== null) { + // have to flip the source coordinates since we did this for the existing connectors on the original tree + data = [ + { + source: { + x: selectedNode.y0, + y: selectedNode.x0 + }, + target: { + x: draggingNode.y0, + y: draggingNode.x0 + } } - } else { - selectedNode.children = []; - selectedNode.children.push(draggingNode); - } - // Make sure that the node being added to is expanded so user can see added node is correctly moved - expand(selectedNode); - sortTree(); - endDrag(); - } else { - endDrag(); + ]; } - }); + var link = svgGroup.selectAll(".templink").data(data); -function endDrag() { - selectedNode = null; - d3.selectAll(".ghostCircle").attr("class", "ghostCircle"); - d3.select(domNode).attr("class", "node"); - // now restore the mouseover event or we won't be able to drag a 2nd time - d3.select(domNode).select(".ghostCircle").attr("pointer-events", ""); - updateTempConnector(); - if (draggingNode !== null) { - update(root); - centerNode(draggingNode); - draggingNode = null; + link.enter().append("path").attr("class", "templink").attr("d", d3.svg.diagonal()).attr("pointer-events", "none"); + + link.attr("d", d3.svg.diagonal()); + + link.exit().remove(); + }; + + // Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children. + function centerNode(source) { + var nodes = tree.nodes(root); + console.log(nodes); + + scale = zoomListener.scale(); + scale = 1.0; + x = source.y0; + y = -source.x0; + + console.log("x => " + x); + + translateCoords = d3.transform(svgGroup.attr("transform")); + var speed = panSpeed; + translateCoords = d3.transform(svgGroup.attr("transform")); + translateX = translateCoords.translate[0] + speed; + console.log("translateX = " + translateX); + + x = x * scale + viewerWidth / 2 - translateX; + + console.log("x => " + x); + y = y * scale + viewerHeight / 2; + + d3.select("g") + .transition() + .duration(duration) + .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); + zoomListener.scale(scale); + zoomListener.translate([x, y]); } -} -// Helper functions for collapsing and expanding nodes. -function collapse(d) { - if (d.children) { - d._children = d.children; - d._children.forEach(collapse); - d.children = null; + // Toggle children function + function toggleChildren(d) { + if (d.children) { + d._children = d.children; + d.children = null; + } else if (d._children) { + d.children = d._children; + d._children = null; + } + return d; } -} -function expand(d) { - if (d._children) { - d.children = d._children; - d.children.forEach(expand); - d._children = null; + // Toggle children on click. + function click(d) { + console.log("clickEvent", d); + if (d3.event.defaultPrevented) return; // click suppressed + d = toggleChildren(d); + update(d); + centerNode(d); } -} -var overCircle = function (d) { - selectedNode = d; - updateTempConnector(); -}; -var outCircle = function (d) { - selectedNode = null; - updateTempConnector(); -}; + function update(source) { + // Compute the new height, function counts total children of root node and sets tree height accordingly. + // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed + // This makes the layout more consistent. + var levelWidth = [1]; + var childCount = function (level, n) { + if (n.children && n.children.length > 0) { + if (levelWidth.length <= level + 1) levelWidth.push(0); -// Function to update the temporary connector indicating dragging affiliation -var updateTempConnector = function () { - var data = []; - if (draggingNode !== null && selectedNode !== null) { - // have to flip the source coordinates since we did this for the existing connectors on the original tree - data = [ - { - source: { - x: selectedNode.y0, - y: selectedNode.x0 - }, - target: { - x: draggingNode.y0, - y: draggingNode.x0 - } + levelWidth[level + 1] += n.children.length; + n.children.forEach(function (d) { + childCount(level + 1, d); + }); } - ]; - } - var link = svgGroup.selectAll(".templink").data(data); + }; + childCount(0, root); + var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line + tree = tree.size([newHeight, viewerWidth]); - link.enter().append("path").attr("class", "templink").attr("d", d3.svg.diagonal()).attr("pointer-events", "none"); + // Compute the new tree layout. + var nodes = tree.nodes(root).reverse(), + links = tree.links(nodes); - link.attr("d", d3.svg.diagonal()); + // Set widths between levels based on maxLabelLength. + nodes.forEach(function (d) { + d.y = d.depth * (maxLabelLength * 10); //maxLabelLength * 10px + // alternatively to keep a fixed scale one can set a fixed depth per level + // Normalize for fixed-depth by commenting out below line + // d.y = (d.depth * 500); //500px per level. + }); - link.exit().remove(); -}; + // Update the nodes… + node = svgGroup.selectAll("g.node").data(nodes, function (d) { + return d.id || (d.id = ++i); + }); -// Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children. -function centerNode(source) { - scale = zoomListener.scale(); - scale = 1.5; - x = -source.y0; - y = -source.x0; - x = x * scale + viewerWidth / 2; - y = y * scale + viewerHeight / 2; + // Enter any new nodes at the parent's previous position. + var nodeEnter = node + .enter() + .append("g") + .call(dragListener) + .attr("class", "node") + .attr("transform", function (d) { + return "translate(" + source.y0 + "," + source.x0 + ")"; + }) + .on("click", click); - //edit 313devops - x = x + 200; - //x = $("#tree-container").outerWidth() / 3; - //y = $("#tree-container").outerHeight() / 3; + nodeEnter + .append("circle") + .attr("class", "nodeCircle") + .attr("r", 0) + .style("fill", function (d) { + return d._children ? "lightsteelblue" : "#fff"; + }); - d3.select("g") - .transition() - .duration(duration) - .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")"); - zoomListener.scale(scale); - zoomListener.translate([x, y]); -} + nodeEnter + .append("text") + .attr("x", function (d) { + return d.children || d._children ? -10 : 10; + }) + .attr("dy", ".35em") + .attr("class", "nodeText") + .attr("text-anchor", function (d) { + return d.children || d._children ? "end" : "start"; + }) + .text(function (d) { + return d.name; + }) + .style("fill-opacity", 0); -// Toggle children function -function toggleChildren(d) { - if (d.children) { - d._children = d.children; - d.children = null; - } else if (d._children) { - d.children = d._children; - d._children = null; - } - return d; -} + nodeEnter + .append("text") + .attr("x", function (d) { + return -15; + }) + .attr("y", function (d) { + return 15; + }) + .text(function (d) { + return d.type; + }) + .on("click", function (d) { + window.location = d.url; + }) + .style("font-size", "11px"); -// Toggle children on click. -function click(d) { - console.log("clickEvent", d); - if (d3.event.defaultPrevented) return; // click suppressed - d = toggleChildren(d); - update(d); - centerNode(d); -} + // phantom node to give us mouseover in a radius around it + nodeEnter + .append("circle") + .attr("class", "ghostCircle") + .attr("r", 30) + .attr("opacity", 0.2) // change this to zero to hide the target area + .style("fill", "red") + .attr("pointer-events", "mouseover") + .on("mouseover", function (node) { + overCircle(node); + }) + .on("mouseout", function (node) { + outCircle(node); + }); -function update(source) { - // Compute the new height, function counts total children of root node and sets tree height accordingly. - // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed - // This makes the layout more consistent. - var levelWidth = [1]; - var childCount = function (level, n) { - if (n.children && n.children.length > 0) { - if (levelWidth.length <= level + 1) levelWidth.push(0); + // Update the text to reflect whether node has children or not. + node + .select("text") + .attr("x", function (d) { + return d.children || d._children ? -10 : 10; + }) + .attr("text-anchor", function (d) { + return d.children || d._children ? "end" : "start"; + }) + .text(function (d) { + return d.name; + }); - levelWidth[level + 1] += n.children.length; - n.children.forEach(function (d) { - childCount(level + 1, d); + // Change the circle fill depending on whether it has children and is collapsed + node + .select("circle.nodeCircle") + .attr("r", 4.5) + .style("fill", function (d) { + return d._children ? "lightsteelblue" : "#fff"; }); - } - }; - childCount(0, root); - var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line - tree = tree.size([newHeight, viewerWidth]); - // Compute the new tree layout. - var nodes = tree.nodes(root).reverse(), - links = tree.links(nodes); + // Transition nodes to their new position. + var nodeUpdate = node + .transition() + .duration(duration) + .attr("transform", function (d) { + return "translate(" + d.y + "," + d.x + ")"; + }); - // Set widths between levels based on maxLabelLength. - nodes.forEach(function (d) { - d.y = d.depth * (maxLabelLength * 10); //maxLabelLength * 10px - // alternatively to keep a fixed scale one can set a fixed depth per level - // Normalize for fixed-depth by commenting out below line - // d.y = (d.depth * 500); //500px per level. - }); + // Fade the text in + nodeUpdate.select("text").style("fill-opacity", 1); - // Update the nodes… - node = svgGroup.selectAll("g.node").data(nodes, function (d) { - return d.id || (d.id = ++i); - }); + // Transition exiting nodes to the parent's new position. + var nodeExit = node + .exit() + .transition() + .duration(duration) + .attr("transform", function (d) { + return "translate(" + source.y + "," + source.x + ")"; + }) + .remove(); - // Enter any new nodes at the parent's previous position. - var nodeEnter = node - .enter() - .append("g") - .call(dragListener) - .attr("class", "node") - .attr("transform", function (d) { - return "translate(" + source.y0 + "," + source.x0 + ")"; - }) - .on("click", click); + nodeExit.select("circle").attr("r", 0); - nodeEnter - .append("circle") - .attr("class", "nodeCircle") - .attr("r", 0) - .style("fill", function (d) { - return d._children ? "lightsteelblue" : "#fff"; + nodeExit.select("text").style("fill-opacity", 0); + + // Update the links… + var link = svgGroup.selectAll("path.link").data(links, function (d) { + return d.target.id; }); - nodeEnter - .append("text") - .attr("x", function (d) { - return d.children || d._children ? -10 : 10; - }) - .attr("dy", ".35em") - .attr("class", "nodeText") - .attr("text-anchor", function (d) { - return d.children || d._children ? "end" : "start"; - }) - .text(function (d) { - return d.name; - }) - .style("fill-opacity", 0); + // Enter any new links at the parent's previous position. + link + .enter() + .insert("path", "g") + .attr("class", "link") + .attr("d", function (d) { + var o = { + x: source.x0, + y: source.y0 + }; + return diagonal({ + source: o, + target: o + }); + }); - nodeEnter - .append("text") - .attr("x", function (d) { - return -15; - }) - .attr("y", function (d) { - return 15; - }) - .text(function (d) { - return d.type; - }) - .on("click", function (d) { - window.location = d.url; - }) - .style("font-size", "8px"); + // Transition links to their new position. + link.transition().duration(duration).attr("d", diagonal); - // phantom node to give us mouseover in a radius around it - nodeEnter - .append("circle") - .attr("class", "ghostCircle") - .attr("r", 30) - .attr("opacity", 0.2) // change this to zero to hide the target area - .style("fill", "red") - .attr("pointer-events", "mouseover") - .on("mouseover", function (node) { - overCircle(node); - }) - .on("mouseout", function (node) { - outCircle(node); - }); + // Transition exiting nodes to the parent's new position. + link + .exit() + .transition() + .duration(duration) + .attr("d", function (d) { + var o = { + x: source.x, + y: source.y + }; + return diagonal({ + source: o, + target: o + }); + }) + .remove(); - // Update the text to reflect whether node has children or not. - node - .select("text") - .attr("x", function (d) { - return d.children || d._children ? -10 : 10; - }) - .attr("text-anchor", function (d) { - return d.children || d._children ? "end" : "start"; - }) - .text(function (d) { - return d.name; + // Stash the old positions for transition. + nodes.forEach(function (d) { + d.x0 = d.x; + d.y0 = d.y; }); + } - // Change the circle fill depending on whether it has children and is collapsed - node - .select("circle.nodeCircle") - .attr("r", 4.5) - .style("fill", function (d) { - return d._children ? "lightsteelblue" : "#fff"; - }); + // Append a group which holds all nodes and which the zoom Listener can act upon. + var svgGroup = baseSvg.append("g"); - // Transition nodes to their new position. - var nodeUpdate = node - .transition() - .duration(duration) - .attr("transform", function (d) { - return "translate(" + d.y + "," + d.x + ")"; - }); + // Define the root + root = treeData; + root.x0 = viewerWidth / 2; + root.y0 = viewerHeight / 2; - // Fade the text in - nodeUpdate.select("text").style("fill-opacity", 1); + // Layout the tree initially and center on the root node. + update(root); + centerNode(root); - // Transition exiting nodes to the parent's new position. - var nodeExit = node - .exit() - .transition() - .duration(duration) - .attr("transform", function (d) { - return "translate(" + source.y + "," + source.x + ")"; - }) - .remove(); + function updateD3ByDataTable() { + treeData.children = []; - nodeExit.select("circle").attr("r", 0); + treeData.name = selectName; + treeData.type = "product(service)"; - nodeExit.select("text").style("fill-opacity", 0); + update(treeData); + } - // Update the links… - var link = svgGroup.selectAll("path.link").data(links, function (d) { - return d.target.id; - }); + function updateD3ByVersionList() { + console.log("versionList - " + versionList); - // Enter any new links at the parent's previous position. - link - .enter() - .insert("path", "g") - .attr("class", "link") - .attr("d", function (d) { - var o = { - x: source.x0, - y: source.y0 - }; - return diagonal({ - source: o, - target: o - }); + treeData.children = []; + for (var k in versionList) { + var obj = versionList[k]; + var item = {}; + item["name"] = obj.c_title; + item["type"] = "version"; + item.children = []; + treeData.children.push(item); + } + update(treeData); + } + + function updateD3ByMultiSelect() { + treeData.children = []; + var item = {}; + item["name"] = selectVersionName; + item["type"] = "version"; + item.children = []; + treeData.children.push(item); + + var test = $("#multiselect :selected").val(); + console.log("test-----" + test); + if ($("#multiselect :selected").val() == undefined) { + console.log("test-----"); + item.children = []; + } + $("#multiselect :selected").each(function (i, sel) { + var temp = {}; + temp["name"] = $(sel).text(); + temp["type"] = "jira"; + item.children.push(temp); }); - // Transition links to their new position. - link.transition().duration(duration).attr("d", diagonal); + update(treeData); + } - // Transition exiting nodes to the parent's new position. - link - .exit() - .transition() - .duration(duration) - .attr("d", function (d) { - var o = { - x: source.x, - y: source.y - }; - return diagonal({ - source: o, - target: o - }); - }) - .remove(); + function d3Update() { + if (typeof treeData.children == "undefined" || treeData.children == "" || treeData.children == null) { + console.log("it is not inner element"); + treeData.children = []; + } else { + treeData.children.splice(0, treeData.children.length); + } - // Stash the old positions for transition. - nodes.forEach(function (d) { - d.x0 = d.x; - d.y0 = d.y; - }); + $("#sampleMultiTest :selected").each(function () { + item = {}; + item["name"] = this.text; + item["type"] = "Jira JQL"; + treeData.children.push(item); + }); + update(root); + } } -// Append a group which holds all nodes and which the zoom Listener can act upon. -var svgGroup = baseSvg.append("g"); -// Define the root -root = treeData; -root.x0 = viewerHeight / 2; -root.y0 = 0; - -// Layout the tree initially and center on the root node. -update(root); -centerNode(root); - /* --------------------------- multi select & slim scroll ---------------------------------- */ $(function () { // JIRA 프로젝트 데이터 로드 후 멀티 셀렉트 빌드 하고 슬림스크롤 적용