parent
78ec9585b4
commit
ee59bb488c
|
@ -0,0 +1,6 @@ |
|||||||
|
<?php |
||||||
|
require '../inc/global.inc.php'; |
||||||
|
$skills = new Skill(); |
||||||
|
//$all = $skills->get_all(false,false,null,0); |
||||||
|
$all = $skills->get_skills_tree_json(); |
||||||
|
echo $all; |
||||||
@ -0,0 +1,312 @@ |
|||||||
|
<?php |
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
/** |
||||||
|
* This tool allows platform admins to add skills by uploading a CSV or XML file |
||||||
|
* @package chamilo.admin |
||||||
|
* @documentation Some interesting basic skills can be found in the "Skills" section here: http://en.wikipedia.org/wiki/Personal_knowledge_management |
||||||
|
*/ |
||||||
|
/** |
||||||
|
* Validate the imported data. |
||||||
|
*/ |
||||||
|
$language_file = array ('admin', 'registration'); |
||||||
|
|
||||||
|
$cidReset = true; |
||||||
|
require '../inc/global.inc.php'; |
||||||
|
require_once api_get_path(LIBRARY_PATH).'mail.lib.inc.php'; |
||||||
|
require_once api_get_path(LIBRARY_PATH).'fileManage.lib.php'; |
||||||
|
require_once api_get_path(LIBRARY_PATH).'classmanager.lib.php'; |
||||||
|
require_once api_get_path(LIBRARY_PATH).'import.lib.php'; |
||||||
|
|
||||||
|
function validate_data($skills) { |
||||||
|
$errors = array(); |
||||||
|
$skills = array(); |
||||||
|
// 1. Check if mandatory fields are set. |
||||||
|
$mandatory_fields = array('id', 'parent_id', 'name'); |
||||||
|
foreach ($skills as $index => $skill) { |
||||||
|
foreach ($mandatory_fields as $field) { |
||||||
|
if (empty($skill[$field])) { |
||||||
|
$skill['error'] = get_lang(ucfirst($field).'Mandatory'); |
||||||
|
$errors[] = $skill; |
||||||
|
} |
||||||
|
} |
||||||
|
// 2. Check skill ID is not empty |
||||||
|
if (!isset($skill['id']) || empty($skill['id'])) { |
||||||
|
$skill['error'] = get_lang('SkillImportNoID'); |
||||||
|
$errors[] = $skill; |
||||||
|
} |
||||||
|
// 3. Check skill Parent |
||||||
|
if (!isset($skill['parent_id'])) { |
||||||
|
$skill['error'] = get_lang('SkillImportNoParent'); |
||||||
|
$errors[] = $skill; |
||||||
|
} |
||||||
|
// 4. Check skill Name |
||||||
|
if (!isset($skill['name'])) { |
||||||
|
$skill['error'] = get_lang('SkillImportNoName'); |
||||||
|
$errors[] = $skill; |
||||||
|
} |
||||||
|
} |
||||||
|
return $errors; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Save the imported data |
||||||
|
* @param array List of users |
||||||
|
* @return void |
||||||
|
* @uses global variable $inserted_in_course, which returns the list of courses the user was inserted in |
||||||
|
*/ |
||||||
|
function save_data($skills) { |
||||||
|
if (is_array($skills)) { |
||||||
|
$parents = array(); |
||||||
|
foreach ($skills as $index => $skill) { |
||||||
|
if (isset($parents[$skill['parent_id']])) { |
||||||
|
$skill['parent_id'] = $parents[$skill['parent_id']]; |
||||||
|
} else { |
||||||
|
$skill['parent_id'] = 1; |
||||||
|
} |
||||||
|
$skill['a'] = 'add'; |
||||||
|
$saved_id = $skill['id']; |
||||||
|
$skill['id'] = null; |
||||||
|
$oskill = new Skill(); |
||||||
|
$skill_id = $oskill->add($skill); |
||||||
|
$parents[$saved_id] = $skill_id; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Read the CSV-file |
||||||
|
* @param string $file Path to the CSV-file |
||||||
|
* @return array All userinformation read from the file |
||||||
|
*/ |
||||||
|
function parse_csv_data($file) { |
||||||
|
$skills = Import :: csv_to_array($file); |
||||||
|
foreach ($skills as $index => $skill) { |
||||||
|
$skills[$index] = $skill; |
||||||
|
} |
||||||
|
return $skills; |
||||||
|
} |
||||||
|
/** |
||||||
|
* XML-parser: handle start of element |
||||||
|
*/ |
||||||
|
function element_start($parser, $data) { |
||||||
|
$data = api_utf8_decode($data); |
||||||
|
global $skill; |
||||||
|
global $current_tag; |
||||||
|
switch ($data) { |
||||||
|
case 'Skill' : |
||||||
|
$skill = array (); |
||||||
|
break; |
||||||
|
default : |
||||||
|
$current_tag = $data; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* XML-parser: handle end of element |
||||||
|
*/ |
||||||
|
function element_end($parser, $data) { |
||||||
|
$data = api_utf8_decode($data); |
||||||
|
global $skill; |
||||||
|
global $skills; |
||||||
|
global $current_value; |
||||||
|
switch ($data) { |
||||||
|
case 'Skill' : |
||||||
|
$skills[] = $skill; |
||||||
|
break; |
||||||
|
default : |
||||||
|
$skill[$data] = $current_value; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* XML-parser: handle character data |
||||||
|
*/ |
||||||
|
function character_data($parser, $data) { |
||||||
|
$data = trim(api_utf8_decode($data)); |
||||||
|
global $current_value; |
||||||
|
$current_value = $data; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Read the XML-file |
||||||
|
* @param string $file Path to the XML-file |
||||||
|
* @return array All userinformation read from the file |
||||||
|
*/ |
||||||
|
function parse_xml_data($file) { |
||||||
|
global $current_tag; |
||||||
|
global $current_value; |
||||||
|
global $skill; |
||||||
|
global $skills; |
||||||
|
$skills = array(); |
||||||
|
$parser = xml_parser_create('UTF-8'); |
||||||
|
xml_set_element_handler($parser, 'element_start', 'element_end'); |
||||||
|
xml_set_character_data_handler($parser, 'character_data'); |
||||||
|
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false); |
||||||
|
xml_parse($parser, api_utf8_encode_xml(file_get_contents($file))); |
||||||
|
xml_parser_free($parser); |
||||||
|
return $skills; |
||||||
|
} |
||||||
|
|
||||||
|
$this_section = SECTION_PLATFORM_ADMIN; |
||||||
|
api_protect_admin_script(true); |
||||||
|
|
||||||
|
|
||||||
|
//$tool_name = get_lang('ImportSkillsListXMLCSV'); |
||||||
|
$tool_name = get_lang('ImportSkillsListCSV'); |
||||||
|
$interbreadcrumb[] = array ("url" => 'index.php', "name" => get_lang('PlatformAdmin')); |
||||||
|
|
||||||
|
set_time_limit(0); |
||||||
|
$extra_fields = UserManager::get_extra_fields(0, 0, 5, 'ASC', true); |
||||||
|
$user_id_error = array(); |
||||||
|
$error_message = ''; |
||||||
|
|
||||||
|
if ($_POST['formSent'] AND $_FILES['import_file']['size'] !== 0) { |
||||||
|
$file_type = $_POST['file_type']; |
||||||
|
Security::clear_token(); |
||||||
|
$tok = Security::get_token(); |
||||||
|
$allowed_file_mimetype = array('csv','xml'); |
||||||
|
$error_kind_file = false; |
||||||
|
|
||||||
|
$ext_import_file = substr($_FILES['import_file']['name'],(strrpos($_FILES['import_file']['name'],'.')+1)); |
||||||
|
|
||||||
|
if (in_array($ext_import_file,$allowed_file_mimetype)) { |
||||||
|
if (strcmp($file_type, 'csv') === 0 && $ext_import_file == $allowed_file_mimetype[0]) { |
||||||
|
$skills = parse_csv_data($_FILES['import_file']['tmp_name']); |
||||||
|
$errors = validate_data($skills); |
||||||
|
$error_kind_file = false; |
||||||
|
} elseif (strcmp($file_type, 'xml') === 0 && $ext_import_file == $allowed_file_mimetype[1]) { |
||||||
|
$skills = parse_xml_data($_FILES['import_file']['tmp_name']); |
||||||
|
$errors = validate_data($skills); |
||||||
|
$error_kind_file = false; |
||||||
|
} else { |
||||||
|
$error_kind_file = true; |
||||||
|
} |
||||||
|
} else { |
||||||
|
$error_kind_file = true; |
||||||
|
} |
||||||
|
|
||||||
|
// List skill id whith error. |
||||||
|
$skills_to_insert = $skill_id_error = array(); |
||||||
|
if (is_array($errors)) { |
||||||
|
foreach ($errors as $my_errors) { |
||||||
|
$skill_id_error[] = $my_errors['SkillName']; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (is_array($skills)) { |
||||||
|
foreach ($skills as $my_skill) { |
||||||
|
if (!in_array($my_skill['SkillName'], $skill_id_error)) { |
||||||
|
$skills_to_insert[] = $my_skill; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (strcmp($file_type, 'csv') === 0) { |
||||||
|
save_data($skills_to_insert); |
||||||
|
} elseif (strcmp($file_type, 'xml') === 0) { |
||||||
|
save_data($skills_to_insert); |
||||||
|
} else { |
||||||
|
$error_message = get_lang('YouMustImportAFileAccordingToSelectedOption'); |
||||||
|
} |
||||||
|
|
||||||
|
if (count($errors) > 0) { |
||||||
|
$see_message_import = get_lang('FileImportedJustSkillsThatAreNotRegistered'); |
||||||
|
} else { |
||||||
|
$see_message_import = get_lang('FileImported'); |
||||||
|
} |
||||||
|
|
||||||
|
if (count($errors) != 0) { |
||||||
|
$warning_message = '<ul>'; |
||||||
|
foreach ($errors as $index => $error_skill) { |
||||||
|
$warning_message .= '<li><b>'.$error_skill['error'].'</b>: '; |
||||||
|
$warning_message .= '<strong>'.$error_skill['SkillName'].'</strong> ('.$error_skill['SkillName'].')'; |
||||||
|
$warning_message .= '</li>'; |
||||||
|
} |
||||||
|
$warning_message .= '</ul>'; |
||||||
|
} |
||||||
|
|
||||||
|
// if the warning message is too long then we display the warning message trough a session |
||||||
|
if (api_strlen($warning_message) > 150) { |
||||||
|
$_SESSION['session_message_import_skills'] = $warning_message; |
||||||
|
$warning_message = 'session_message'; |
||||||
|
} |
||||||
|
|
||||||
|
if ($error_kind_file) { |
||||||
|
$error_message = get_lang('YouMustImportAFileAccordingToSelectedOption'); |
||||||
|
} else { |
||||||
|
//header('Location: '.api_get_path(WEB_CODE_PATH).'admin/skills_import.php?action=show_message&warn='.urlencode($warning_message).'&message='.urlencode($see_message_import).'&sec_token='.$tok); |
||||||
|
//exit; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
Display :: display_header($tool_name); |
||||||
|
|
||||||
|
if (!empty($error_message)) { |
||||||
|
Display::display_error_message($error_message); |
||||||
|
} |
||||||
|
if (!empty($see_message_import)) { |
||||||
|
Display::display_normal_message($see_message_import); |
||||||
|
} |
||||||
|
|
||||||
|
$form = new FormValidator('user_import','post','skills_import.php'); |
||||||
|
$form->addElement('header', '', $tool_name); |
||||||
|
$form->addElement('hidden', 'formSent'); |
||||||
|
$form->addElement('file', 'import_file', get_lang('ImportFileLocation')); |
||||||
|
$group = array(); |
||||||
|
$group[] = $form->createElement('radio', 'file_type', '', 'CSV (<a href="skill_example.csv" target="_blank">'.get_lang('ExampleCSVFile').'</a>)', 'csv'); |
||||||
|
//$group[] = $form->createElement('radio', 'file_type', null, 'XML (<a href="skill_example.xml" target="_blank">'.get_lang('ExampleXMLFile').'</a>)', 'xml'); |
||||||
|
$form->addGroup($group, '', get_lang('FileType'), '<br/>'); |
||||||
|
|
||||||
|
$form->addElement('style_submit_button', 'submit', get_lang('Import'), 'class="save"'); |
||||||
|
$defaults['formSent'] = 1; |
||||||
|
$defaults['sendMail'] = 0; |
||||||
|
$defaults['file_type'] = 'csv'; |
||||||
|
$form->setDefaults($defaults); |
||||||
|
$form->display(); |
||||||
|
|
||||||
|
$list = array(); |
||||||
|
$list_reponse = array(); |
||||||
|
$result_xml = ''; |
||||||
|
$i = 0; |
||||||
|
$count_fields = count($extra_fields); |
||||||
|
if ($count_fields > 0) { |
||||||
|
foreach ($extra_fields as $extra) { |
||||||
|
$list[] = $extra[1]; |
||||||
|
$list_reponse[] = 'xxx'; |
||||||
|
$spaces = ' '; |
||||||
|
$result_xml .= $spaces.'<'.$extra[1].'>xxx</'.$extra[1].'>'; |
||||||
|
if ($i != $count_fields - 1) { |
||||||
|
$result_xml .= '<br/>'; |
||||||
|
} |
||||||
|
$i++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
?> |
||||||
|
<p><?php echo get_lang('CSVMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
|
||||||
|
|
||||||
|
<blockquote> |
||||||
|
<pre> |
||||||
|
<b>id</b>;<b>parent_id</b>;<b>name</b>;<b>description</b><br /> |
||||||
|
<b>n</b>;<b>m</b>;<b>xxx</b>;xxx<br /> |
||||||
|
</pre> |
||||||
|
</blockquote> |
||||||
|
|
||||||
|
<!--p><?php echo get_lang('XMLMustLookLike').' ('.get_lang('MandatoryFields').')'; ?> :</p>
|
||||||
|
|
||||||
|
<blockquote> |
||||||
|
<pre> |
||||||
|
<?xml version="1.0" encoding="<?php echo api_refine_encoding_id(api_get_system_encoding()); ?>"?>
|
||||||
|
<Skills> |
||||||
|
<Skill> |
||||||
|
<b><id>n</id></b> |
||||||
|
<b><parent_id>n</parent_id></b> |
||||||
|
<b><name>xxx</name></b> |
||||||
|
<description>xxx</description> |
||||||
|
</Skill> |
||||||
|
</Skills> |
||||||
|
</pre> |
||||||
|
</blockquote--> |
||||||
|
<?php |
||||||
|
Display :: display_footer(); |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
<?php |
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
/** |
||||||
|
* @package chamilo.admin |
||||||
|
*/ |
||||||
|
|
||||||
|
// Language files that need to be included. |
||||||
|
$language_file = array('admin'); |
||||||
|
$cidReset = true; |
||||||
|
|
||||||
|
require_once '../inc/global.inc.php'; |
||||||
|
require_once api_get_path(LIBRARY_PATH).'skill.lib.php'; |
||||||
|
|
||||||
|
$this_section = SECTION_PLATFORM_ADMIN; |
||||||
|
|
||||||
|
api_protect_admin_script(); |
||||||
|
|
||||||
|
if (api_get_setting('allow_skills_tool') != 'true') { |
||||||
|
api_not_allowed(); |
||||||
|
} |
||||||
|
|
||||||
|
//Adds the JS needed to use the jqgrid |
||||||
|
$htmlHeadXtra[] = api_get_js('d3.v2.min.js'); |
||||||
|
|
||||||
|
$skill = new Skill(); |
||||||
|
$type = 'edit'; //edit |
||||||
|
//$tree = $skill->get_skills_tree_json(null, true); |
||||||
|
|
||||||
|
//$html = $skill_visualizer->return_html(); |
||||||
|
//$html = $skill_visualizer->return_html(); |
||||||
|
//$url = api_get_path(WEB_AJAX_PATH).'skill.ajax.php?1=1'; |
||||||
|
|
||||||
|
$tpl = new Template(null, false, false); |
||||||
|
|
||||||
|
//$tpl->assign('url', $url); |
||||||
|
//$tpl->assign('html', $html); |
||||||
|
$tpl->assign('html', api_get_js('coffeewheel/wheel.js')); |
||||||
|
//$tpl->assign('skill_visualizer', $skill_visualizer); |
||||||
|
//$tpl->assign('js', $skill_visualizer->return_js()); |
||||||
|
//$tpl->assign('js', api_get_js('coffeewheel/wheel.js')); |
||||||
|
|
||||||
|
// |
||||||
|
$content = $tpl->fetch('default/skill/skill_wheel.tpl'); |
||||||
|
$tpl->assign('content', $content); |
||||||
|
$tpl->display_no_layout_template(); |
||||||
@ -0,0 +1,159 @@ |
|||||||
|
/* Define constants and size of the wheel */ |
||||||
|
/** Total width of the wheel (also counts for the height) */ |
||||||
|
var w = 800, |
||||||
|
h = w, |
||||||
|
r = w / 2, |
||||||
|
/** x/y positionning of the center of the wheel */ |
||||||
|
x = d3.scale.linear().range([0, 2 * Math.PI]), |
||||||
|
y = d3.scale.pow().exponent(1.1).domain([0, 1]).range([0, r]), |
||||||
|
/** Padding in pixels before th string starts */ |
||||||
|
p = 3, |
||||||
|
/** Duration of click animations */ |
||||||
|
duration = 1000, |
||||||
|
/** Levels to show */ |
||||||
|
l = 3; |
||||||
|
/* Locate the #div id element */ |
||||||
|
var div = d3.select("#vis"); |
||||||
|
/* Remove the image (make way for the dynamic stuff */ |
||||||
|
div.select("img").remove(); |
||||||
|
/* Append an element "svg" to the #vis section */ |
||||||
|
var vis = div.append("svg") |
||||||
|
.attr("width", w + p * 2) |
||||||
|
.attr("height", h + p * 2) |
||||||
|
.append("g") |
||||||
|
.attr("transform", "translate(" + (r + p) + "," + (r/1.5 + p) + ")");
|
||||||
|
/* ...update translate variables to change coordinates of wheel's center */ |
||||||
|
/* Add a small label to help the user */ |
||||||
|
div.append("p") |
||||||
|
.attr("id", "intro") |
||||||
|
.text("Click to zoom!"); |
||||||
|
/* Generate the partition layout */ |
||||||
|
var partition = d3.layout.partition() |
||||||
|
.sort(null) |
||||||
|
/** Value here seems to be a calculation of the size of the elements |
||||||
|
depending on the level of depth they're at. Changing it makes |
||||||
|
elements pass over the limits of others... */ |
||||||
|
.value(function(d) { return 5.8 - d.depth; }); |
||||||
|
/* Generate an arc which will define the whole wheel context */ |
||||||
|
var arc = d3.svg.arc() |
||||||
|
.startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); }) |
||||||
|
.endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); }) |
||||||
|
.innerRadius(function(d) { return Math.max(0, d.y ? y(d.y) : d.y); }) |
||||||
|
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); }); |
||||||
|
/* ...adding "+1" to "y" function's params is really funny */ |
||||||
|
/* 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 */ |
||||||
|
d3.json("skills.json.php", function(json) { |
||||||
|
/** Define the list of nodes based on the JSON */ |
||||||
|
var nodes = partition.nodes({children: json}); |
||||||
|
|
||||||
|
var path = vis.selectAll("path").data(nodes); |
||||||
|
path.enter().append("path") |
||||||
|
.attr("id", function(d, i) { return "path-" + i; }) |
||||||
|
.attr("d", arc) |
||||||
|
.attr("fill-rule", "evenodd") |
||||||
|
.style("fill", colour) |
||||||
|
.on("click", click); |
||||||
|
|
||||||
|
var text = vis.selectAll("text").data(nodes); |
||||||
|
var textEnter = text.enter().append("text") |
||||||
|
.style("fill-opacity", 1) |
||||||
|
.style("fill", function(d) { |
||||||
|
return brightness(d3.rgb(colour(d))) < 125 ? "#eee" : "#000"; |
||||||
|
}) |
||||||
|
.attr("text-anchor", function(d) { |
||||||
|
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start"; |
||||||
|
}) |
||||||
|
.attr("dy", ".2em") |
||||||
|
.attr("transform", function(d) { |
||||||
|
/** Get the text details and define the rotation and general position */ |
||||||
|
var multiline = (d.name || "").split(" ").length > 1, |
||||||
|
angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90, |
||||||
|
rotate = angle + (multiline ? -.5 : 0); |
||||||
|
return "rotate(" + rotate + ")translate(" + (y(d.y) + p) + ")rotate(" + (angle > 90 ? -180 : 0) + ")"; |
||||||
|
}) |
||||||
|
.on("click", click); |
||||||
|
/** Managing text - alway maximum two words */ |
||||||
|
textEnter.append("tspan") |
||||||
|
.attr("x", 0) |
||||||
|
.text(function(d) { return d.depth ? d.name.split(" ")[0] : ""; }); |
||||||
|
textEnter.append("tspan") |
||||||
|
.attr("x", 0) |
||||||
|
.attr("dy", "1em") |
||||||
|
.text(function(d) { return d.depth ? d.name.split(" ")[1] || "" : ""; }); |
||||||
|
|
||||||
|
function click(d) { |
||||||
|
path.transition() |
||||||
|
.duration(duration) |
||||||
|
.attrTween("d", arcTween(d)); |
||||||
|
|
||||||
|
// Somewhat of a hack as we rely on arcTween updating the scales.
|
||||||
|
text |
||||||
|
.style("visibility", function(e) { |
||||||
|
return isParentOf(d, e) ? null : d3.select(this).style("visibility"); |
||||||
|
}) |
||||||
|
.transition().duration(duration) |
||||||
|
.attrTween("text-anchor", function(d) { |
||||||
|
return function() { |
||||||
|
return x(d.x + d.dx / 2) > Math.PI ? "end" : "start"; |
||||||
|
}; |
||||||
|
}) |
||||||
|
.attrTween("transform", function(d) { |
||||||
|
var multiline = (d.name || "").split(" ").length > 1; |
||||||
|
return function() { |
||||||
|
var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90, |
||||||
|
rotate = angle + (multiline ? -.5 : 0); |
||||||
|
return "rotate(" + rotate + ")translate(" + (y(d.y) + p) + ")rotate(" + (angle > 90 ? -180 : 0) + ")"; |
||||||
|
}; |
||||||
|
}) |
||||||
|
.style("fill-opacity", function(e) { return isParentOf(d, e) ? 1 : 1e-6; }) |
||||||
|
.each("end", function(e) { |
||||||
|
d3.select(this).style("visibility", isParentOf(d, e) ? null : "hidden"); |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
|
/* Returns whether p is parent of c */ |
||||||
|
function isParentOf(p, c) { |
||||||
|
if (p === c) return true; |
||||||
|
if (p.children) { |
||||||
|
return p.children.some(function(d) { |
||||||
|
return isParentOf(d, c); |
||||||
|
}); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
/* 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 d.colour || "#fff"; |
||||||
|
} |
||||||
|
|
||||||
|
/* Interpolate the scales! */ |
||||||
|
function arcTween(d) { |
||||||
|
var my = maxY(d), |
||||||
|
xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]), |
||||||
|
yd = d3.interpolate(y.domain(), [d.y, my]), |
||||||
|
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, r]); |
||||||
|
return function(d) { |
||||||
|
return function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); }; |
||||||
|
}; |
||||||
|
} |
||||||
|
/* */ |
||||||
|
function maxY(d) { |
||||||
|
return d.children ? Math.max.apply(Math, d.children.map(maxY)) : d.y + d.dy; |
||||||
|
} |
||||||
|
|
||||||
|
/* Use a formula for contrasting colour |
||||||
|
http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
|
||||||
|
*/ |
||||||
|
function brightness(rgb) { |
||||||
|
return rgb.r * .299 + rgb.g * .587 + rgb.b * .114; |
||||||
|
} |
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,50 @@ |
|||||||
|
<div id="menu" class="well" style="top:20px; left:20px; width:380px; z-index: 9000; opacity: 0.9;"> |
||||||
|
<h3>{{'Skills'|get_lang}}</h3> |
||||||
|
<div class="btn-group"> |
||||||
|
<a style="z-index: 1000" class="btn" id="add_item_link" href="#">{{'AddSkill'|get_lang}}</a> |
||||||
|
<a style="z-index: 1000" class="btn" id="return_to_root" href="#">{{'Root'|get_lang}}</a> |
||||||
|
<a style="z-index: 1000" class="btn" id="return_to_admin" href="{{_p.web_main}}admin">{{'BackToAdmin'|get_lang}}</a> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div id="vis"><img src=""></div> |
||||||
|
{{ html }} |
||||||
|
|
||||||
|
<!--div id="dialog-form" style="display:none; z-index:9001;"> |
||||||
|
<p class="validateTips"></p> |
||||||
|
<form class="form-horizontal" id="add_item" name="form"> |
||||||
|
<fieldset> |
||||||
|
<input type="hidden" name="id" id="id"/> |
||||||
|
<div class="control-group"> |
||||||
|
<label class="control-label" for="name">{{'Name'|get_lang}}</label> |
||||||
|
<div class="controls"> |
||||||
|
<input type="text" name="name" id="name" size="40" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="control-group"> |
||||||
|
<label class="control-label" for="name">{{'Parent'|get_lang}}</label> |
||||||
|
<div class="controls"> |
||||||
|
<select id="parent_id" name="parent_id" /> |
||||||
|
</select> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="control-group"> |
||||||
|
<label class="control-label" for="name">{{'Gradebook'|get_lang}}</label> |
||||||
|
<div class="controls"> |
||||||
|
<select id="gradebook_id" name="gradebook_id[]" multiple="multiple"/> |
||||||
|
</select> |
||||||
|
<span class="help-block"> |
||||||
|
{{'WithCertificate'|get_lang}} |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="control-group"> |
||||||
|
<label class="control-label" for="name">{{'Description'|get_lang}}</label> |
||||||
|
<div class="controls"> |
||||||
|
<textarea name="description" id="description" class="span3" rows="7"></textarea> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</fieldset> |
||||||
|
</form> |
||||||
|
</div--> |
||||||
Loading…
Reference in new issue