renderer.php 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Competence Graph
  18. *
  19. * Competence graph format allows the visualization of courses with competencies in a graph.
  20. * In the course structure, teacher associates activities to competencies. Each course module
  21. * can have restrictions between them, so a module is opened only when the student accomplish
  22. * its requirements. In student visualization, the structure of the course is presented as a
  23. * graph. In such graph, each node is a resource available to the student that can be handled.
  24. * Subgraphs in the main graph represent competences. As students can have different paths in
  25. * the course, the plugin registers all the steps that a student produces.
  26. *
  27. * @package course/format
  28. * @subpackage competencegraph
  29. * @version 0.1
  30. * @author Laboratório de Informática na Educação <http://www.usp.br/line>
  31. * @link http://www.usp.br/line/competencegraph
  32. * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  33. */
  34. defined('MOODLE_INTERNAL') || die();
  35. use core_competency\course_competency;
  36. use core_competency\api;
  37. use core_competency\course_module_competency;
  38. require_once($CFG->dirroot . '/course/format/renderer.php');
  39. require_once($CFG->dirroot . '/course/format/competencegraph/lib.php');
  40. class format_competencegraph_renderer extends format_section_renderer_base {
  41. public function __construct(moodle_page $page, $target) {
  42. parent::__construct($page, $target);
  43. global $PAGE;
  44. //$this->courserenderer = $PAGE->get_renderer('core','course');
  45. $this->courseformat = course_get_format($page->course); // Needed for collapsed topics settings retrieval.
  46. $page->set_other_editing_capability('moodle/course:setcurrentsection');
  47. $this->userisediting = $page->user_is_editing();
  48. $this->rtl = right_to_left();
  49. if (strcmp($page->theme->name, 'boost') === 0) {
  50. $this->bsnewgrid = true;
  51. } else if (!empty($page->theme->parents)) {
  52. if (in_array('boost', $page->theme->parents) === true) {
  53. $this->bsnewgrid = true;
  54. }
  55. }
  56. }
  57. protected function start_section_list() {
  58. if ($this->bsnewgrid) {
  59. return html_writer::start_tag('ul', array('class' => 'ctopics bsnewgrid'));
  60. } else {
  61. return html_writer::start_tag('ul', array('class' => 'ctopics'));
  62. }
  63. }
  64. protected function end_section_list() {
  65. return html_writer::end_tag('ul');
  66. }
  67. protected function page_title() {
  68. return get_string('sectionname', 'format_competencegrah');
  69. }
  70. public function set_portable($portable) {
  71. switch ($portable) {
  72. case 1:
  73. $this->mobiletheme = true;
  74. break;
  75. case 2:
  76. $this->tablettheme = true;
  77. break;
  78. default:
  79. $this->mobiletheme = false;
  80. $this->tablettheme = false;
  81. break;
  82. }
  83. }
  84. public function print_graph_teacher_view($course, $sections, $mods, $modnames, $modnamesused) {
  85. $context = context_course::instance($course->id);
  86. echo '<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>';
  87. if (has_capability('moodle/course:update', $context)) {
  88. $maintabs = array(
  89. new tabobject( 'tab_list', '?id='.$course->id.'&format=list', get_string('listview', 'format_competencegraph'), get_string('listview', 'format_competencegraph') ),
  90. new tabobject( 'tab_graph', '?id='.$course->id.'&format=graph', get_string('graphview', 'format_competencegraph'), get_string('graphview', 'format_competencegraph') )
  91. );
  92. $active = 'tab_graph';
  93. print_tabs( array($maintabs), $active );
  94. //echo $this->get_js_dependencies_sigma_graph();
  95. //$this->print_test_graph($course, $sections, $mods, $modnames, $modnamesused);
  96. echo '<script src="https://d3js.org/d3.v4.min.js"></script>';
  97. $this->print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused);
  98. } else {
  99. echo '<script src="https://d3js.org/d3.v4.min.js"></script>';
  100. $this->print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused);
  101. }
  102. }
  103. public function print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused) {
  104. echo "<script>";
  105. echo 'var svgContainer = d3.select(".course-content").append("svg")
  106. .attr("width", 800)
  107. .attr("height", 1000);';
  108. echo 'svgContainer.append("svg:defs").append("svg:marker")
  109. .attr("id", "triangle")
  110. .attr("refX", 36)
  111. .attr("refY", 6)
  112. .attr("markerWidth", 30)
  113. .attr("markerHeight", 30)
  114. .attr("markerUnits","userSpaceOnUse")
  115. .attr("orient", "auto")
  116. .append("path")
  117. .attr("d", "M 0 0 12 6 0 12 3 6")
  118. .style("fill", "#9e9e9f");';
  119. echo 'var jsonCircles = [';
  120. $context = context_course::instance($course->id);
  121. $colors = ['#617db4', '#668f3c', '#c6583e', '#b956af', '#fcba03', '#03fcf0', '#fc0339', '#a6ffc8', '#000000'];
  122. // Print the competencies as name section:
  123. $list_competencies = course_competency::list_course_competencies($course->id);
  124. $all_mod_info_printed = array();
  125. $modinfo = get_fast_modinfo($course);
  126. $count = 0;
  127. $atual_competence = 0;
  128. $vet_id = 0;
  129. $distancia_quadrantes = 100;
  130. $tamanho_quadrante = 250;
  131. $quadrante_da_vez = 1;
  132. $para_y = 0;
  133. $para_x = 0;
  134. $arestas = [];
  135. foreach ($list_competencies as $competence) {
  136. $idcompetence = $competence->get('competencyid');
  137. api::read_competency($idcompetence)->get('shortname');
  138. $list_modules = course_module_competency::list_course_modules($idcompetence, $course->id);
  139. foreach ($list_modules as $item) {
  140. array_push($all_mod_info_printed, $item);
  141. }
  142. if ($quadrante_da_vez % 2 != 0) {
  143. $para_y = $quadrante_da_vez / 2 * ($distancia_quadrantes + $tamanho_quadrante) - 100;
  144. $para_x = 0;
  145. } else {
  146. $para_y -= 00;
  147. $para_x = $distancia_quadrantes + $tamanho_quadrante;
  148. }
  149. $para_x = intval($para_x);
  150. $para_y = intval($para_y);
  151. $linha = 1;
  152. $contPorLinha = 1;
  153. $contItens = 1;
  154. $andou = 0;
  155. foreach ($list_modules as $modnumber) {
  156. $andou ++;
  157. $mod = $modinfo->cms[$modnumber];
  158. $teste = new moodle_url($mod->url);
  159. if ($contPorLinha == 4) {
  160. $contPorLinha = 1;
  161. $linha ++;
  162. }
  163. $xx = -500;
  164. $yy = -500;
  165. switch ($contItens) {
  166. case 1:
  167. $xx = 100;
  168. $yy = 100;
  169. break;
  170. case 2:
  171. $xx = 180;
  172. $yy = 10;
  173. break;
  174. case 3:
  175. $xx = 305;
  176. $yy = 45;
  177. break;
  178. case 4:
  179. $xx = 280;
  180. $yy = 150;
  181. break;
  182. case 5:
  183. $xx = 175;
  184. $yy = 170;
  185. break;
  186. case 6:
  187. $xx = 80;
  188. $yy = 250;
  189. break;
  190. case 7:
  191. $xx = 240;
  192. $yy = 260;
  193. break;
  194. }
  195. echo '
  196. { "vet_id": '.$vet_id.', "cm_id": '.$mod->id.', "x_axis": ' . ($para_x + ($xx)) . ', "y_axis": ' . ($para_y + ($yy)) .', "radius": 25, "color" : "'.$colors[$count].'", "name": "'.$mod->name.'", "icon": "'.$mod->get_icon_url().'", "url": "'.$mod->url.'" },';
  197. if ($mod->availability) {
  198. $temp = json_decode($mod->availability);
  199. for ($k = 0; $k < count($temp->c); $k++) {
  200. array_push($arestas, [$temp->c[$k]->cm, $mod->id]);
  201. }
  202. }
  203. $contPorLinha ++;
  204. $contItens ++;
  205. $vet_id ++;
  206. }
  207. if ($andou != 0) {
  208. $count ++;
  209. $quadrante_da_vez ++;
  210. }
  211. }
  212. $list_mod_without_competences = array();
  213. foreach ($modinfo->cms as $tempmod) {
  214. if (!in_array($tempmod->id, $all_mod_info_printed)) {
  215. array_push($list_mod_without_competences, $tempmod->id);
  216. }
  217. }
  218. echo '];';
  219. echo "var tempCircles = jsonCircles;
  220. var bloqueados = [];
  221. ";
  222. for ($i = 0; $i < count($arestas); $i++) {
  223. /*print '
  224. ' . $arestas[$i][0];*/
  225. // $arestas[$i][0] -> dependência
  226. // $arestas[$i][1] -> recurso que depende do [0]
  227. echo "var dependencia = " . $arestas[$i][1] . ";";
  228. echo "var depende = " . $arestas[$i][0] . ";";
  229. echo "var x1 = 0; var x2 = 0; var y1 = 0; var y2 = 0;";
  230. echo '
  231. for (i = 0; i < tempCircles.length; i++) {
  232. if (tempCircles[i].cm_id == depende) {
  233. x1 = tempCircles[i].x_axis;
  234. y1 = tempCircles[i].y_axis;
  235. break;
  236. }
  237. }
  238. for (i = 0; i < tempCircles.length; i++) {
  239. if (tempCircles[i].cm_id == dependencia) {
  240. x2 = tempCircles[i].x_axis;
  241. y2 = tempCircles[i].y_axis;
  242. break;
  243. }
  244. }
  245. var enc = false;
  246. for (i = 0; i < bloqueados.length; i++) {
  247. if (bloqueados[i] == dependencia) {
  248. enc = true;
  249. break;
  250. }
  251. }
  252. if (enc == false) {
  253. bloqueados.push(dependencia);
  254. }
  255. ';
  256. echo 'svgContainer.append("line")
  257. .attr("x1", x1)
  258. .attr("y1", y1)
  259. .attr("x2", x2)
  260. .attr("y2", y2)
  261. .attr("stroke-width", 2)
  262. .attr("stroke", "#9e9e9e")
  263. .attr("marker-end", "url(#triangle)");';
  264. }
  265. echo 'var circles = svgContainer.selectAll("circle")
  266. .data(jsonCircles)
  267. .enter()
  268. .append("circle");';
  269. echo 'var circleAttributes = circles
  270. .attr("cx", function (d) { return d.x_axis; })
  271. .attr("cy", function (d) { return d.y_axis; })
  272. .attr("r", function (d) { return d.radius; })
  273. .style("fill", function(d) { return d.color; })
  274. .on("click", function(d) {
  275. openId(d.vet_id);
  276. console.log(d.url);
  277. });';
  278. echo "for (var i = 0; i < tempCircles.length; i++) {
  279. var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
  280. svgimg.setAttributeNS(null,'height','25');
  281. svgimg.setAttributeNS(null,'width','35');
  282. svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', tempCircles[i].icon);
  283. svgimg.setAttributeNS(null,'x', tempCircles[i].x_axis - 18);
  284. svgimg.setAttributeNS(null,'y', tempCircles[i].y_axis - 12);
  285. svgimg.setAttributeNS(null, 'visibility', 'visible');
  286. svgimg.setAttributeNS(null, 'id', tempCircles[i].vet_id);
  287. svgimg.setAttributeNS(null, 'alt', tempCircles[i].name);
  288. svgimg.onclick = function (e) {
  289. openId(e.originalTarget.id);
  290. };
  291. document.getElementsByTagName('svg')[0].append(svgimg);
  292. }";
  293. echo "
  294. function showTitles() {
  295. for (var i = 0; i < tempCircles.length; i++) {
  296. var txt = document.createElementNS('http://www.w3.org/2000/svg', 'text');
  297. txt.setAttributeNS(null, 'x', tempCircles[i].x_axis);
  298. txt.setAttributeNS(null, 'y', tempCircles[i].y_axis + 32);
  299. txt.setAttributeNS(null,'font-size','12');
  300. txt.setAttributeNS(null,'dominant-baseline','middle');
  301. txt.setAttributeNS(null,'text-anchor','middle');
  302. txt.innerHTML = tempCircles[i].name;
  303. document.getElementsByTagName('svg')[0].append(txt);
  304. }
  305. }";
  306. echo "
  307. function openId(vet_id) {
  308. if (naoabrir.indexOf(tempCircles[vet_id].cm_id) >= 0)
  309. return;
  310. $('#janela').remove();
  311. $('#sup_janela').append($(\"<iframe src='\" + tempCircles[vet_id].url + \"' id='janela'>\" ));
  312. modal.style.display = 'block';
  313. }";
  314. print '';
  315. print "</script>";
  316. print '<button id="modal-btn"> click me, I make a modal</button><div class="modal">
  317. <div class="modal-content">
  318. <div class="close-btn">&times;</div>
  319. <div id="sup_janela"><iframe src="" id="janela"></iframe></div>
  320. </div>
  321. </div>';
  322. print '<style>
  323. svg circle, svg image {
  324. cursor: pointer;
  325. }
  326. .modal {
  327. display: none;
  328. position: fixed;
  329. padding-top: 50px;
  330. left: 0;
  331. top: 0;
  332. width: 100%;
  333. height: 100%;
  334. background-color: rgb(0, 0, 0);
  335. background-color: rgba(0, 0, 0, 0.5);
  336. }
  337. #modal-btn {
  338. display: none;
  339. }
  340. #janela {
  341. height: 100%;
  342. border: none;
  343. width: 100%;
  344. }
  345. #sup_janela {
  346. height: 100%;
  347. width: 100% !important;
  348. }
  349. .modal-content {
  350. position: relative;
  351. background-color: white;
  352. padding: 20px;
  353. margin: auto;
  354. width: 85%;
  355. height: 90%;
  356. -webkit-animation-name: animatetop;
  357. -webkit-animation-duration: 0.4s;
  358. animation-name: animatetop;
  359. animation-duration: 0.4s
  360. }.close-btn {
  361. float: right;
  362. color: lightgray;
  363. font-weight: bold;
  364. text-align: right;
  365. font-size: 2em;
  366. margin-top: -20px;
  367. margin-right: -5px;
  368. cursor: pointer;
  369. }.close-btn:hover {
  370. color: darkgray;
  371. }@-webkit-keyframes animatetop {
  372. from {top:-300px; opacity:0}
  373. to {top:0; opacity:1}
  374. }@keyframes animatetop {
  375. from {top:-300px; opacity:0}
  376. to {top:0; opacity:1}
  377. }</style>';
  378. print '<script>
  379. var modalBtn = document.getElementById("modal-btn") ;
  380. var modal = document.querySelector(".modal");
  381. var closeBtn = document.querySelector(".close-btn");
  382. modalBtn.onclick = function(){
  383. }
  384. closeBtn.onclick = function(){
  385. modal.style.display = "none";
  386. }
  387. window.onclick = function(e){
  388. if(e.target == modal){
  389. modal.style.display = "none";
  390. }
  391. }</script>';
  392. print '
  393. <script>
  394. var naoabrir = [];
  395. for (i = 0; i < bloqueados.length; i++) {
  396. for (j = 0; j < tempCircles.length; j++) {
  397. if (bloqueados[i] == tempCircles[j].cm_id) {
  398. $.ajax({url: tempCircles[j].url, vet_id: j, cm: tempCircles[j].cm_id, success: function(e){
  399. if (e.indexOf("activityinstance-error") > 0) {
  400. changeOpacity(this.vet_id);
  401. naoabrir.push(this.cm);
  402. }
  403. }});
  404. break;
  405. }
  406. }
  407. }
  408. function changeOpacity(vet_id) {
  409. //circles._groups[0][vet_id].attr("fill-opacity", function(d) { return .25; });
  410. //console.log(circles);
  411. $(circles._groups[0][vet_id]).get(0).style.fillOpacity = .8;'.
  412. "
  413. var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
  414. svgimg.setAttributeNS(null,'height','25');
  415. svgimg.setAttributeNS(null,'width','35');
  416. svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', 'format/competencegraph/img/alert.png');
  417. svgimg.setAttributeNS(null,'x', tempCircles[vet_id].x_axis);
  418. svgimg.setAttributeNS(null,'y', tempCircles[vet_id].y_axis);
  419. svgimg.setAttributeNS(null, 'visibility', 'visible');
  420. svgimg.setAttributeNS(null, 'id', tempCircles[vet_id].vet_id);
  421. svgimg.onclick = function (e) {
  422. openId(e.originalTarget.id);
  423. };
  424. document.getElementsByTagName('svg')[0].append(svgimg);"
  425. .
  426. '
  427. }
  428. </script>
  429. <input type="button" value="Mostrar títulos" onclick="showTitles()">';
  430. }
  431. public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) {
  432. $context = context_course::instance($course->id);
  433. global $OUTPUT;
  434. if (has_capability('moodle/course:update', $context)) {
  435. echo $this->get_css_list_teacher();
  436. //$this->print_modules_page_teacher_list($course, $sections, $mods, $modnames, $modnamesused);
  437. $modinfo = get_fast_modinfo($course);
  438. $course = $this->courseformat->get_course();
  439. $context = context_course::instance($course->id);
  440. $sections = $modinfo->get_section_info_all();
  441. // General section if non-empty.
  442. $thissection = $sections[0];
  443. if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) {
  444. print('<div class="tohidden firstitem">');
  445. echo $this->section_header($thissection, $course, false, 0);
  446. print('</div>');
  447. echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  448. }
  449. $maintabs = array(
  450. new tabobject( 'tab_list', '?id='.$course->id.'&format=list', get_string('listview', 'format_competencegraph'), get_string('listview', 'format_competencegraph') ),
  451. new tabobject( 'tab_graph', '?id='.$course->id.'&format=graph', get_string('graphview', 'format_competencegraph'), get_string('graphview', 'format_competencegraph') )
  452. );
  453. $active = 'tab_list';
  454. print_tabs( array($maintabs), $active );
  455. // Print the competencies as name section:
  456. $list_competencies = course_competency::list_course_competencies($course->id);
  457. if (count($list_competencies) < 1) {
  458. echo '<div class="coursewithoutcompetence"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>' . get_string('coursewithoutcompetence', 'format_competencegraph') . '</div>';
  459. }
  460. $all_mod_info_printed = array();
  461. foreach ($list_competencies as $competence) {
  462. $idcompetence = $competence->get('competencyid');
  463. echo '<h4 class="sectionname"><span><a href="#">' . api::read_competency($idcompetence)->get('shortname') . '</a></span></h4>';
  464. $list_modules = course_module_competency::list_course_modules($idcompetence, $course->id);
  465. if (!$list_modules || count($list_modules) < 1) {
  466. echo '<div class="emptycompetence"><i class="fa fa-info-circle" aria-hidden="true"></i>' . get_string('emptycompetence', 'format_competencegraph') . "</div>";
  467. }
  468. echo $this->course_section_cm_list($course, null, 0, array(), $list_modules);
  469. foreach ($list_modules as $item) {
  470. array_push($all_mod_info_printed, $item);
  471. }
  472. }
  473. $list_mod_without_competences = array();
  474. foreach ($modinfo->cms as $tempmod) {
  475. if (!in_array($tempmod->id, $all_mod_info_printed)) {
  476. array_push($list_mod_without_competences, $tempmod->id);
  477. }
  478. }
  479. if (count($list_mod_without_competences) > 0) {
  480. echo '<h4 class="withoutcompetence"><span><a href="#">' . get_string('itemswithoutcompetence', 'format_competencegraph') . '</a></span></h4>';
  481. echo $this->course_section_cm_list($course, null, 0, array(), $list_mod_without_competences);
  482. }
  483. $sections = $modinfo->get_section_info_all();
  484. // General section if non-empty.
  485. $thissection = $sections[0];
  486. if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) {
  487. print('<div class="tohidden">');
  488. echo $this->section_header($thissection, $course, false, 0);
  489. print('</div>');
  490. echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  491. }
  492. }
  493. }
  494. public function course_section_cm_list($course, $section, $sectionreturn = null, $displayoptions = array(), $includeditems = array()) {
  495. global $USER;
  496. $output = '';
  497. $modinfo = get_fast_modinfo($course);
  498. $completioninfo = new completion_info($course);
  499. // check if we are currently in the process of moving a module with JavaScript disabled
  500. $ismoving = $this->page->user_is_editing() && ismoving($course->id);
  501. if ($ismoving) {
  502. $movingpix = new pix_icon('movehere', get_string('movehere'), 'moodle', array('class' => 'movetarget'));
  503. $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'"));
  504. }
  505. // Get the list of modules visible to user (excluding the module being moved if there is one)
  506. $moduleshtml = array();
  507. foreach ($includeditems as $modnumber) {
  508. $mod = $modinfo->cms[$modnumber];
  509. /*if ($mod->availability) {
  510. echo $modnumber . ':: ';
  511. print_r($mod->availability);
  512. }*/
  513. if ($ismoving and $mod->id == $USER->activitycopy) {
  514. // do not display moving mod
  515. continue;
  516. }
  517. if ($modulehtml = $this->courserenderer->course_section_cm_list_item($course,
  518. $completioninfo, $mod, $sectionreturn, $displayoptions)) {
  519. $moduleshtml[$modnumber] = $modulehtml;
  520. }
  521. }
  522. $sectionoutput = '';
  523. if (!empty($moduleshtml) || $ismoving) {
  524. foreach ($moduleshtml as $modnumber => $modulehtml) {
  525. if ($ismoving) {
  526. $movingurl = new moodle_url('/course/mod.php', array('moveto' => $modnumber, 'sesskey' => sesskey()));
  527. $sectionoutput .= html_writer::tag('li',
  528. html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)),
  529. array('class' => 'movehere'));
  530. }
  531. $sectionoutput .= $modulehtml;
  532. }
  533. if ($ismoving) {
  534. $movingurl = new moodle_url('/course/mod.php', array('movetosection' => $section->id, 'sesskey' => sesskey()));
  535. $sectionoutput .= html_writer::tag('li',
  536. html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)),
  537. array('class' => 'movehere'));
  538. }
  539. }
  540. // Always output the section module list.
  541. $output .= html_writer::tag('ul', $sectionoutput, array('class' => 'section img-text'));
  542. return $output;
  543. }
  544. public function print_modules_page_teacher_list($course, $sections, $mods, $modnames, $modnamesused) {
  545. $modinfo = get_fast_modinfo($course);
  546. $course = $this->courseformat->get_course();
  547. $context = context_course::instance($course->id);
  548. //echo $this->start_section_list();
  549. $sections = $modinfo->get_section_info_all();
  550. // General section if non-empty.
  551. $thissection = $sections[0];
  552. if ($thissection->summary or ! empty($modinfo->sections[0]) or $this->userisediting) {
  553. echo $this->section_header($thissection, $course, false, 0);
  554. //echo $this->course_section_cm_list($course, $thissection, 0);
  555. echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  556. }
  557. $coursenumsections = $this->courseformat->get_last_section_number();
  558. if ($coursenumsections > 0) {
  559. $sectiondisplayarray = array();
  560. $currentsectionfirst = false;
  561. if ((!$this->userisediting)) {
  562. $currentsectionfirst = true;
  563. }
  564. if (($this->userisediting)) {
  565. $section = 1;
  566. } else {
  567. $timenow = time();
  568. $weekofseconds = 604800;
  569. $course->enddate = $course->startdate + ($weekofseconds * $coursenumsections);
  570. $section = $coursenumsections;
  571. $weekdate = $course->enddate; // This should be 0:00 Monday of that week.
  572. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems.
  573. }
  574. $numsections = $coursenumsections; // Because we want to manipulate this for column breakpoints.
  575. if (($this->userisediting == false)) {
  576. $loopsection = 1;
  577. $numsections = 0;
  578. while ($loopsection <= $coursenumsections) {
  579. $nextweekdate = $weekdate - ($weekofseconds);
  580. if ((($thissection->uservisible ||
  581. ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo))) &&
  582. ($nextweekdate <= $timenow)) == true) {
  583. $numsections++; // Section not shown so do not count in columns calculation.
  584. }
  585. $weekdate = $nextweekdate;
  586. $section--;
  587. $loopsection++;
  588. }
  589. // Reset.
  590. $section = $coursenumsections;
  591. $weekdate = $course->enddate; // This should be 0:00 Monday of that week.
  592. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems.
  593. }
  594. echo $this->end_section_list();
  595. $loopsection = 1;
  596. $breaking = false; // Once the first section is shown we can decide if we break on another column.
  597. while ($loopsection <= $coursenumsections) {
  598. $thissection = $modinfo->get_section_info($section);
  599. /* Show the section if the user is permitted to access it, OR if it's not available
  600. but there is some available info text which explains the reason & should display. */
  601. if (($this->userisediting)) {
  602. $showsection = $thissection->uservisible ||
  603. ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo));
  604. } else {
  605. $showsection = ($thissection->uservisible ||
  606. ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo))) &&
  607. ($nextweekdate <= $timenow);
  608. }
  609. if (($currentsectionfirst == true) && ($showsection == true)) {
  610. // Show the section if we were meant to and it is the current section:....
  611. $showsection = ($course->marker == $section);
  612. }
  613. if (!$showsection) {
  614. // Hidden section message is overridden by 'unavailable' control.
  615. $testhidden = false;
  616. if ($testhidden) {
  617. if (!$course->hiddensections && $thissection->available) {
  618. $thissection->ishidden = true;
  619. $sectiondisplayarray[] = $thissection;
  620. }
  621. }
  622. } else {
  623. $thissection->isshown = true;
  624. $sectiondisplayarray[] = $thissection;
  625. }
  626. if (($this->userisediting)) {
  627. $section++;
  628. } else {
  629. $section--;
  630. if (($this->userisediting == false)) {
  631. $weekdate = $nextweekdate;
  632. }
  633. }
  634. $loopsection++;
  635. if (($currentsectionfirst == true) && ($loopsection > $coursenumsections)) {
  636. // Now show the rest.
  637. $currentsectionfirst = false;
  638. $loopsection = 1;
  639. $section = 1;
  640. }
  641. if ($section > $coursenumsections) {
  642. // Activities inside this section are 'orphaned', this section will be printed as 'stealth' below.
  643. break;
  644. }
  645. }
  646. foreach ($sectiondisplayarray as $thissection) {
  647. if (!empty($thissection->ishidden)) {
  648. echo $this->section_hidden($thissection);
  649. } else if (!empty($thissection->issummary)) {
  650. echo $this->section_summary($thissection, $course, null);
  651. } else if (!empty($thissection->isshown)) {
  652. //echo $this->section_header($thissection, $course, false, 0);
  653. if ($thissection->uservisible) {
  654. //echo $this->course_section_cm_list($course, $thissection, 0);
  655. //echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0);
  656. }
  657. echo html_writer::end_tag('div');
  658. }
  659. unset($sections[$thissection->section]);
  660. }
  661. }
  662. }
  663. private function get_css_list_teacher() {
  664. $style = "<style>";
  665. $style .= ".sectionname, .withoutcompetence {
  666. border-top: 1px solid #cfdacf;
  667. margin-top: 1em;
  668. padding-top: .3em;
  669. }
  670. .emptycompetence {
  671. margin-left: 1.5em;
  672. opacity: .8;
  673. }
  674. .emptycompetence i {
  675. margin-right: .5em;
  676. }
  677. .tohidden .right.side {
  678. display: none;
  679. }
  680. .tohidden li {
  681. list-style-type: none;
  682. }
  683. .coursewithoutcompetence {
  684. border: 1px solid gray;
  685. padding: 1em;
  686. border-radius: .5em;
  687. margin: 1em;
  688. color: #c63100;
  689. }
  690. .coursewithoutcompetence i {
  691. opacity: .8;
  692. margin-right: .5em;
  693. }
  694. .firstitem .section-modchooser-link {
  695. float: right;
  696. }";
  697. return $style . "</style>";
  698. }
  699. private function print_test_graph($course, $sections, $mods, $modnames, $modnamesused) {
  700. echo '<div id="container">
  701. <style>
  702. #graph-container {
  703. top: 4em;
  704. bottom: 0;
  705. left: 0;
  706. right: 0;
  707. border: 1px solid red;
  708. }
  709. </style>
  710. <div id="graph-container"></div>
  711. </div>';
  712. echo "<script>
  713. var i,
  714. s,
  715. img,
  716. N = 10,
  717. E = 50,
  718. g = {
  719. nodes: [],
  720. edges: []
  721. },
  722. colors = [
  723. '#617db4',
  724. '#668f3c',
  725. '#c6583e',
  726. '#b956af'
  727. ];";
  728. $this->print_nodes_graph($course, $sections, $mods, $modnames, $modnamesused);
  729. echo "
  730. /*for (i = 0; i < E; i++) {
  731. g.edges.push({
  732. id: 'e' + i,
  733. source: 'n' + (Math.random() * N | 0),
  734. target: 'n' + (Math.random() * N | 0),
  735. type: ['arrow'][0],
  736. size: 1,
  737. color: '#bdbdbd'
  738. });
  739. }*/
  740. s = new sigma({
  741. graph: g,
  742. renderer: {
  743. container: document.getElementById('graph-container'),
  744. type: 'svg'
  745. },
  746. settings: {
  747. minNodeSize: 1,
  748. maxNodeSize: 10,
  749. minEdgeSize: 0.1,
  750. maxEdgeSize: 2,
  751. enableEdgeHovering: true,
  752. edgeHoverSizeRatio: 2,
  753. sideMargin: 0,
  754. enableCamera: false
  755. }
  756. });
  757. </script>
  758. ";
  759. }
  760. private function get_js_dependencies_sigma_graph() {
  761. global $CFG;
  762. $dirjs = $CFG->wwwroot . '/course/format/competencegraph/js/sigma';
  763. $o = '<script src="'.$dirjs.'/src/sigma.core.js"></script>
  764. <script src="'.$dirjs.'/src/conrad.js"></script>
  765. <script src="'.$dirjs.'/src/utils/sigma.utils.js"></script>
  766. <script src="'.$dirjs.'/src/utils/sigma.polyfills.js"></script>
  767. <script src="'.$dirjs.'/src/sigma.settings.js"></script>
  768. <script src="'.$dirjs.'/src/classes/sigma.classes.dispatcher.js"></script>
  769. <script src="'.$dirjs.'/src/classes/sigma.classes.configurable.js"></script>
  770. <script src="'.$dirjs.'/src/classes/sigma.classes.graph.js"></script>
  771. <script src="'.$dirjs.'/src/classes/sigma.classes.camera.js"></script>
  772. <script src="'.$dirjs.'/src/classes/sigma.classes.quad.js"></script>
  773. <script src="'.$dirjs.'/src/classes/sigma.classes.edgequad.js"></script>
  774. <script src="'.$dirjs.'/src/captors/sigma.captors.mouse.js"></script>
  775. <script src="'.$dirjs.'/src/captors/sigma.captors.touch.js"></script>
  776. <script src="'.$dirjs.'/src/renderers/sigma.renderers.canvas.js"></script>
  777. <script src="'.$dirjs.'/src/renderers/sigma.renderers.webgl.js"></script>
  778. <script src="'.$dirjs.'/src/renderers/sigma.renderers.svg.js"></script>
  779. <script src="'.$dirjs.'/src/renderers/sigma.renderers.def.js"></script>
  780. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.nodes.def.js"></script>
  781. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.nodes.fast.js"></script>
  782. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.def.js"></script>
  783. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.fast.js"></script>
  784. <script src="'.$dirjs.'/src/renderers/webgl/sigma.webgl.edges.arrow.js"></script>
  785. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.labels.def.js"></script>
  786. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.hovers.def.js"></script>
  787. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.nodes.def.js"></script>
  788. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.def.js"></script>
  789. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.curve.js"></script>
  790. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.arrow.js"></script>
  791. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edges.curvedArrow.js"></script>
  792. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.def.js"></script>
  793. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.curve.js"></script>
  794. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.arrow.js"></script>
  795. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.edgehovers.curvedArrow.js"></script>
  796. <script src="'.$dirjs.'/src/renderers/canvas/sigma.canvas.extremities.def.js"></script>
  797. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.utils.js"></script>
  798. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.nodes.def.js"></script>
  799. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.edges.def.js"></script>
  800. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.edges.curve.js"></script>
  801. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.labels.def.js"></script>
  802. <script src="'.$dirjs.'/src/renderers/svg/sigma.svg.hovers.def.js"></script>
  803. <script src="'.$dirjs.'/src/middlewares/sigma.middlewares.rescale.js"></script>
  804. <script src="'.$dirjs.'/src/middlewares/sigma.middlewares.copy.js"></script>
  805. <script src="'.$dirjs.'/src/misc/sigma.misc.animation.js"></script>
  806. <script src="'.$dirjs.'/src/misc/sigma.misc.bindEvents.js"></script>
  807. <script src="'.$dirjs.'/src/misc/sigma.misc.bindDOMEvents.js"></script>
  808. <script src="'.$dirjs.'/src/misc/sigma.misc.drawHovers.js"></script>
  809. <!-- END SIGMA IMPORTS -->
  810. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.dashed.js"></script>
  811. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.dotted.js"></script>
  812. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.parallel.js"></script>
  813. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edges.tapered.js"></script>
  814. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.dashed.js"></script>
  815. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.dotted.js"></script>
  816. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.parallel.js"></script>
  817. <script src="'.$dirjs.'/sigma.renderers.customEdgeShapes/sigma.canvas.edgehovers.tapered.js"></script>';
  818. return $o;
  819. }
  820. }