diff --git a/main/css/base.css b/main/css/base.css index 9205c8b2b0..3e439ffce2 100644 --- a/main/css/base.css +++ b/main/css/base.css @@ -4628,3 +4628,10 @@ data table i.size-32.icon-new-work{ background-image: url('../img/icons/32/new_work.png'); } + + +.skill_partition { + cursor: pointer; + stroke: #000000; + stroke-width: 1.5; +} \ No newline at end of file diff --git a/main/inc/lib/skill.lib.php b/main/inc/lib/skill.lib.php index f81dac832b..1277d17bb6 100644 --- a/main/inc/lib/skill.lib.php +++ b/main/inc/lib/skill.lib.php @@ -113,6 +113,7 @@ class SkillRelSkill extends Model { } return $parents; } + public function get_children($skill_id, $load_user_data = false, $user_id = false) { $skills = $this->find('all', array('where'=> array('parent_id = ? '=> $skill_id))); @@ -122,12 +123,12 @@ class SkillRelSkill extends Model { if ($load_user_data) { $passed_skills = $skill_rel_user->get_user_skills($user_id); $done_skills = array(); - foreach($passed_skills as $done_skill) { + foreach ($passed_skills as $done_skill) { $done_skills[] = $done_skill['skill_id']; } } + if (!empty($skills)) { - foreach ($skills as &$skill) { $skill['data'] = $skill_obj->get($skill['skill_id']); if (isset($skill['data']) && !empty($skill['data'])) { @@ -339,8 +340,9 @@ class Skill extends Model { } } - $sql = "SELECT s.id, s.name, s.description, ss.parent_id, ss.relation_type". - " FROM {$this->table} s INNER JOIN {$this->table_skill_rel_skill} ss ON (s.id = ss.skill_id) $id_condition"; + $sql = "SELECT s.id, s.name, s.description, ss.parent_id, ss.relation_type + FROM {$this->table} s INNER JOIN {$this->table_skill_rel_skill} ss ON (s.id = ss.skill_id) $id_condition + ORDER BY ss.id, ss.parent_id"; $result = Database::query($sql); $skills = array(); @@ -388,6 +390,21 @@ class Skill extends Model { } return $skills; } + + function get_all_children($skill_id) { + $skill_rel_skill = new SkillRelSkill(); + + $children = $skill_rel_skill->get_children($skill_id); + + foreach ($children as $child) { + $sub_children = $this->get_all_children($child['skill_id']); + } + if (!empty($sub_children)) { + $children = array_merge($children, $sub_children); + } + return $children; + } + /** * All parents from root to n @@ -566,15 +583,22 @@ class Skill extends Model { $css_attributes = array('fill' => 'red'); //var_dump($skills); + + $family = array(); if (!empty($skills)) { foreach ($skills as &$skill) { + if ($skill['parent_id'] == 0) { $skill['parent_id'] = 'root'; } - + + if ($skill['parent_id'] == 1) { + $family[$skill['id']] = $this->get_all_children($skill['id']); + } + $skill['data'] = array('parent_id' => $skill['parent_id']); // because except main keys (id, name, children) others keys are not saved while in the space tree - $skill['data']['achieved'] = 'no'; + $skill['data']['achieved'] = false; if ($user_id) { $css_attributes = array('fill' => 'green'); $skill['data']['achieved'] = $this->user_has_skill($user_id, $skill['id']); @@ -585,12 +609,26 @@ class Skill extends Model { $refs[$skill['id']] = &$skill; $flat_array[$skill['id']] = &$skill; } - + + $family_id = 1; + $new_family_array = array(); + foreach ($family as $main_family_id => $family_items) { + if (!empty($family_items)) { + foreach ($family_items as $item) { + $new_family_array[$item['skill_id']] = $family_id; + } + } + $new_family_array[$main_family_id] = $family_id; + + $family_id++; + } + // Moving node to the children index of their parents - foreach($skills as $skillInd => &$skill) { + foreach ($skills as $skillInd => &$skill) { + $skill['data']['family_id'] = $new_family_array[$skill['id']]; $refs[$skill['parent_id']]['children'][] = &$skill; $flat_array[$skillInd] = $skill; - } + } $skills_tree = array( 'name' => get_lang('SkillRootName'), @@ -600,8 +638,6 @@ class Skill extends Model { ); } - - //var_dump($flat_array);exit; if ($return_flat_array) { return $flat_array; } @@ -633,18 +669,21 @@ class Skill extends Model { public function get_skill_json($subtree, $depth = 1) { $simple_sub_tree = array(); if (is_array($subtree)) { + $counter = 1; foreach ($subtree as $elem) { $tmp = array(); $tmp['name'] = $elem['name']; $tmp['id'] = $elem['id']; if (is_array($elem['children'])) { - $tmp['children'] = $this->get_skill_json($elem['children'], $depth+1); + $tmp['children'] = $this->get_skill_json($elem['children'], $depth+1); } else { $tmp['colour'] = $this->colours[$depth][rand(0,3)]; } - + $tmp['depth'] = $depth; + $tmp['counter'] = $counter; + $counter++; if (isset($elem['data']) && is_array($elem['data'])) { foreach ($elem['data'] as $key => $item) { diff --git a/main/template/default/skill/skill_wheel.tpl b/main/template/default/skill/skill_wheel.tpl index 02ebbf9325..e925114961 100644 --- a/main/template/default/skill/skill_wheel.tpl +++ b/main/template/default/skill/skill_wheel.tpl @@ -4,7 +4,7 @@ $(document).ready(function() { /** Define constants and size of the wheel */ /** Total width of the wheel (also counts for the height) */ - var w = 800, + var w = 940, h = w, r = w / 2, /** x/y positionning of the center of the wheel */ @@ -15,7 +15,7 @@ $(document).ready(function() { /** Duration of click animations */ duration = 1000, /** Levels to show */ - l = 3; + levels_to_show = 3; /* Locate the #div id element */ var div = d3.select("#vis"); @@ -66,22 +66,51 @@ $(document).ready(function() { /* Exexute the calculation based on a JSON file provided */ /*d3.json("wheel.json", function(json) {*/ /** Get the JSON list of skills and work on it */ + + var my_domain = [1,2,3,4,5,6,7,8,9]; - //var achieved_fill = d3.scale.category10().domain(["yes","no"]); - var normal_fill = d3.scale.category20c(); + var col = 9; + var color_patterns = []; - /*var colorScale = d3.scale.quantize() - .domain([1.0, 5.0]) - .range(colorbrewer.YlGnBu[5]); -*/ - - var z = d3.scale.ordinal().domain(["1", "2", "3"]).range(colorbrewer.RdBu[9]); + color_patterns[1] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Blues[col]); + color_patterns[2] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Purples[col]); + //color_patterns[2] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Blues[6]); + color_patterns[3] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Greens[col]); + color_patterns[4] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Reds[col]); + color_patterns[5] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Oranges[col]); + color_patterns[6] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlOrBr[col]); + + color_patterns[7] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlGn[col]); + color_patterns[8] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlGnBu[col]); + color_patterns[9] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.GnBu[col]); + color_patterns[10] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.BuGn[col]); + color_patterns[11] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuBuGn[col]); + color_patterns[12] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuBu[col]); + color_patterns[13] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.BuPu[col]); + color_patterns[14] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.RdPu[col]); + color_patterns[15] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.PuRd[col]); + color_patterns[16] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.OrRd[col]); + color_patterns[17] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.YlOrRd[col]); + color_patterns[18] = d3.scale.ordinal().domain(my_domain).range(colorbrewer.Greys[col]); + + //var normal_fill = d3.scale.category10().domain(my_domain); + + function get_color(d) { + depth = d.depth; + if (d.family_id) { + //console.log(d.family_id); + var p = color_patterns[d.family_id]; + color = p(depth -1 + d.counter); + d.color = color; + return color; + } + return '#fefefe'; //missing colors + } - function set_skill_style(d, attribute) { - return_fill = normal_fill; - return_fill = z(d.depth); - return_background = 'blue'; - + function set_skill_style(d, attribute) { + + return_fill = get_color(d); + return_background = 'blue'; if (d.achieved) { //return_fill = 'green'; return_background = 'blue'; @@ -98,8 +127,7 @@ $(document).ready(function() { return return_background; break; } - } - + } d3.json("{{ wheel_url }}", function(json) { /** Define the list of nodes based on the JSON */ @@ -114,15 +142,15 @@ $(document).ready(function() { .attr("id", function(d, i) { return "path-" + i; }) - .attr("class", function(d) { return "q" + "1-9"; }) .attr("d", arc) .attr("fill-rule", "evenodd") - //.style("fill", colour) + .attr("class", "skill_partition") +// .style("fill", colour) .style("fill", function(d) { return set_skill_style(d, 'fill'); }) .style("background", function(d) { - return set_skill_style(d, 'background'); + //return set_skill_style(d, 'background'); }) .on("click", click); @@ -133,8 +161,10 @@ $(document).ready(function() { var textEnter = text.enter().append("text") .style("fill-opacity", 1) .style("fill", function(d) { - return brightness(d3.rgb(colour(d))) < 125 ? "#eee" : "#000"; - }) + console.log(d.color); + return brightness(d3.rgb(d.color)) < 125 ? "#eee" : "#000"; + //return "#444"; + }) .attr("text-anchor", function(d) { return x(d.x + d.dx / 2) > Math.PI ? "end" : "start"; }) @@ -206,21 +236,17 @@ $(document).ready(function() { /* Generated random colour */ function colour(d) { + if (d.children) { // There is a maximum of two children! var colours = d.children.map(colour), a = d3.hsl(colours[0]), b = d3.hsl(colours[1]); // L*a*b* might be better here... - return d3.hsl((a.h + b.h) / 2, a.s * 1.2, a.l / 1.2); + return d3.hsl((a.h + b.h) / 2, a.s * 1.2, a.levels_to_show / 1.2); } return d.colour || "#fff"; } - - function set_attributes(d) { - console.log(d); - return d.style('fill', 'green'); - } /* Interpolate the scales! */ function arcTween(d) {