pull/3173/head
Alex Aragón 7 years ago
commit a0c34c5d96
  1. 161
      app/Resources/public/css/base.css
  2. 212
      main/inc/lib/myspace.lib.php
  3. 10
      main/inc/lib/sortable_table.class.php
  4. 76
      main/template/default/my_space/partials/tracking_user_overview.tpl
  5. 47
      main/template/default/my_space/user_summary.tpl

@ -9797,10 +9797,167 @@ ul.dropdown-menu.inner > li > a {
position: relative;
}
/* Fix grid with one row and multiples columns. Works for .col-sm-6.col-md-4.col-lg-3 */
.row.clear-rows-6-4-3 {
.table-transparent>tbody>tr>td,
.table-transparent>tbody>tr>th,
.table-transparent>tfoot>tr>td,
.table-transparent>tfoot>tr>th,
.table-transparent>thead>tr>td,
.table-transparent>thead>tr>th{
border: none;
}
.summary-height{
height: calc(100% - 20px);
display: flex;
flex-grow: 1;
flex-direction: column;
box-shadow: 0 0 13px 0 rgba(82,63,105,0.05);
margin-bottom: 0;
border-radius: 4px;
border: 1px solid #cdcdcd;
background-color: #f9f9fc;
}
.summary{
padding: 0;
height: 100%;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
flex-direction: row;
width: 100%;
}
.summary-body{
flex-grow: 1;
padding-left: 10px !important;
padding-right: 10px !important;
margin-top: 15px !important;
}
.summary-item{
display: flex;
-webkit-box-pack: justify;
justify-content: flex-start;
-webkit-box-align: center;
align-items: center;
padding-bottom: 2rem;
}
.summary-item .icon{
padding-right: 1.25rem;
}
.summary-item .icon img{
border: 1px solid #cdcdcd;
}
.summary-item .user .username{
font-size: 12px;
}
.summary-item .user .name{
color: #6c7293;
font-size: 1.56rem;
font-weight: 500;
padding-right: 1.25rem;
margin-top: 1rem;
display: inline-block;
flex-grow: 1;
transition: color 0.3s ease;
}
.summary-item .user .name:hover{
color: #366cf3;
transition: color 0.3s ease;
}
.summary-item .user{
width: 14%;
}
.summary-item .summary-course{
width: 80%;
}
.summary-item .summary-course .alert{
margin-bottom: 0;
}
.summary-item .summary-course .course-item{
padding-bottom: 1rem;
padding-top: 1rem;
border-bottom: 1px dashed #cdcdcd;
display: flex;
flex-wrap: nowrap;
}
.summary-item .summary-course .course-item:last-child{
border-bottom: none;
}
.summary-item .summary-course .course-item .course-info{
margin-right: 20px;
width: 25%;
}
.summary-item .summary-course .course-item .course-info h5{
font-weight: bold;
padding: 0;
margin: 0;
}
.summary-item .summary-course .course-item .course-info .code{
font-size: 12px;
}
.summary-item .summary-course .course-item .box{
width: 10%;
text-align: center;
line-height: 50px;
margin-right: 5px;
font-size: 12px;
border-radius: 5px;
}
.summary-item .summary-course .course-item .box .kt-badge{
height: 0;
width: auto;
padding: 0.5rem 0.5rem;
border-radius: 2px;
font-weight: bold;
border: 1px solid;
}
.summary-legend{
padding: 10px 0;
margin-bottom: 2rem;
}
.summary-legend .list-legend{
margin: 0;
padding: 0;
list-style: none;
}
.summary-legend .list-legend li{
display: inline-block;
font-size: 12px;
}
.summary-legend .cube{
width: 13px;
height: 13px;
display: inline-block;
margin-right: 2px;
border-radius: 2px;
border: 1px solid;
}
.student-progress{
color: #366cf3;
background: rgba(54,108,243,0.35);
}
.student-score{
color: #1dc9b7;
background: rgba(29,201,183,0.35);
}
.student-message{
color: #fd397a;
background: rgba(253,57,122,0.35);
}
.student-assignments{
color: #FF9800;
background: rgba(255,184,34,0.35);
}
.student-exercises{
background-color: #83af3d3b !important;
color: #4f9c53;
}
.questions-answered{
background-color: #fb5f0442 !important;
color: #FF5722;
}
.last-connection{
color: #2196f3;
background: rgba(57, 217, 253, 0.35);
}
@media (min-width: 768px) {
.clear-rows-6-4-3 .col-sm-6:nth-child(2n+1) {
clear: left;

@ -308,93 +308,139 @@ class MySpace
return $return;
}
/**
* Creates a small table in the last column of the table with the user overview.
*
* @param int $user_id the id of the user
*
* @return array List course
*/
public static function returnCourseTracking($user_id)
{
$tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
// getting all the courses of the user
$sql = "SELECT * FROM $tbl_course_user
WHERE
user_id = '" . intval($user_id) . "' AND
relation_type<>" . COURSE_RELATION_TYPE_RRHH . " ";
$result = Database::query($sql);
$list = [];
while ($row = Database::fetch_array($result)) {
$courseInfo = api_get_course_info_by_id($row['c_id']);
$courseId = $courseInfo['real_id'];
$courseCode = $courseInfo['code'];
if (empty($courseInfo)) {
continue;
}
$avg_score = Tracking::get_avg_student_score($user_id, $courseCode);
if (is_numeric($avg_score)) {
$avg_score = round($avg_score, 2);
} else {
$avg_score = '-';
}
// student exercises results (obtained score, maximum score, number of exercises answered, score percentage)
$exercises_results = self::exercises_results($user_id, $courseCode);
$item = [
'code' => $courseInfo['code'],
'real_id' => $courseInfo['real_id'],
'title' => $courseInfo['title'],
'category' => $courseInfo['categoryName'],
'image_small' => $courseInfo['course_image'],
'image_large' => $courseInfo['course_image_large'],
'time_spent' => api_time_to_hms(Tracking::get_time_spent_on_the_course($user_id, $courseId)),
'student_progress' => round(Tracking::get_avg_student_progress($user_id, $courseCode)),
'student_score' => $avg_score,
'student_message' => Tracking::count_student_messages($user_id, $courseCode),
'student_assignments' => Tracking::count_student_assignments($user_id, $courseCode),
'student_exercises' => (is_null($exercises_results['percentage']) ? '' : $exercises_results['score_obtained'] . '/' . $exercises_results['score_possible'] . ' ( ' . $exercises_results['percentage'] . '% )'),
'questions_answered' => $exercises_results['questions_answered'],
'last_connection' => Tracking::get_last_connection_date_on_the_course($user_id, $courseInfo)
];
$list[] = $item;
}
return $list;
}
/**
* Display a sortable table that contains an overview off all the
* reporting progress of all users and all courses the user is subscribed to.
*
* @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
* Alex Aragon <alex.aragon@beeznest.com>, BeezNest, Perú
*
* @version Dokeos 1.8.6
* @version Chamilo 1.11.8
*
* @since October 2008
* @since April 2019
*/
public static function returnTrackingUserOverviewFilter($user_id)
{
$tpl = new Template('', false, false, false, false, false, false);
$userInfo = api_get_user_info($user_id);
$avatar = UserManager::getUserPicture($user_id, USER_IMAGE_SIZE_SMALL);
$user = [
'id' => $user_id,
'code_user' => $userInfo['official_code'],
'complete_name' => $userInfo['complete_name'],
'username' => $userInfo['username'],
'course' => self::returnCourseTracking($user_id),
'avatar' => $avatar
];
$tpl->assign('item', $user);
$templateName = $tpl->get_template('my_space/partials/tracking_user_overview.tpl');
$content = $tpl->fetch($templateName);
return $content;
}
/**
* Display a sortable table that contains an overview off all the
* reporting progress of all users and all courses the user is subscribed to.
*
* @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
* Alex Aragon <alex.aragon@beeznest.com>, BeezNest, Perú
*
* @version Chamilo 1.11.8
*
* @since October 2008, Update April 2019
*/
public static function display_tracking_user_overview()
{
self::display_user_overview_export_options();
$t_head = '<table style="width: 100%;border:0;padding:0;border-collapse:collapse;table-layout: fixed">';
$t_head .= '<tr>';
$t_head .= '<th width="155px" style="border-left:0;border-bottom:0"><span>'.get_lang('Course').'</span></th>';
$t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgTimeSpentInTheCourse'), 6, true).'</span></th>';
$t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgStudentsProgress'), 6, true).'</span></th>';
$t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('AvgCourseScore'), 6, true).'</span></th>';
$t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfMessages'), 6, true).'</span></th>';
$t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalNumberOfAssignments'), 6, true).'</span></th>';
$t_head .= '<th width="105px" style="border-bottom:0"><span>'.get_lang('TotalExercisesScoreObtained').'</span></th>';
$t_head .= '<th style="padding:0;border-bottom:0"><span>'.cut(get_lang('TotalExercisesAnswered'), 6, true).'</span></th>';
$t_head .= '<th style="padding:0;border-bottom:0;border-right:0;"><span>'.get_lang('LatestLogin').'</span></th>';
$t_head .= '</tr></table>';
$addparams = ['view' => 'admin', 'display' => 'user'];
$table = new SortableTable(
'tracking_user_overview',
['MySpace', 'get_number_of_users_tracking_overview'],
['MySpace', 'get_user_data_tracking_overview'],
0
);
$table->additional_parameters = $addparams;
$table->set_header(
0,
get_lang('OfficialCode'),
true,
['style' => 'font-size:8pt'],
['style' => 'font-size:8pt']
);
if (api_is_western_name_order()) {
$table->set_header(
1,
get_lang('FirstName'),
true,
['style' => 'font-size:8pt'],
['style' => 'font-size:8pt']
);
$table->set_header(
2,
get_lang('LastName'),
true,
['style' => 'font-size:8pt'],
['style' => 'font-size:8pt']
);
} else {
$table->set_header(
1,
get_lang('LastName'),
true,
['style' => 'font-size:8pt'],
['style' => 'font-size:8pt']
);
$table->set_header(
2,
get_lang('FirstName'),
true,
['style' => 'font-size:8pt'],
['style' => 'font-size:8pt']
);
}
$table->set_header(
3,
get_lang('LoginName'),
true,
['style' => 'font-size:8pt'],
['style' => 'font-size:8pt']
);
$table->set_header(
4,
$t_head,
false,
['style' => 'width:90%;border:0;padding:0;font-size:7.5pt;'],
['style' => 'width:90%;padding:0;font-size:7.5pt;']
20,
'ASC',
null, [
'class' => 'table table-transparent'
]
);
$table->set_column_filter(4, ['MySpace', 'course_info_tracking_filter']);
$table->display();
$table->additional_parameters = $addparams;
$table->set_column_filter(0, ['MySpace', 'returnTrackingUserOverviewFilter']);
$tableContent = $table->return_table();
$tpl = new Template('', false, false, false, false, false, false);
$tpl->assign('table', $tableContent);
$templateName = $tpl->get_template('my_space/user_summary.tpl');
$tpl->display($templateName);
}
/**
@ -2163,11 +2209,13 @@ class MySpace
public static function get_user_data_tracking_overview($from, $numberItems, $column, $direction)
{
$isWestern = api_is_western_name_order();
switch ($column) {
case '0':
$column = 'official_code';
$column = $isWestern ? 'firstname' : 'lastname';
//$column = 'official_code';
break;
case '1':
/*case '1':
$column = $isWestern ? 'firstname' : 'lastname';
break;
case '2':
@ -2178,7 +2226,7 @@ class MySpace
break;
case '4':
$column = 'username';
break;
break;*/
}
$order = [
@ -2187,23 +2235,15 @@ class MySpace
$userList = UserManager::get_user_list([], $order, $from, $numberItems);
$return = [];
foreach ($userList as $user) {
$firstPosition = $user['lastname'];
$secondPosition = $user['firstname'];
if ($isWestern) {
//$firstPosition = $user['lastname'];
//$secondPosition = $user['firstname'];
/*if ($isWestern) {
$firstPosition = $user['firstname'];
$secondPosition = $user['lastname'];
}
}*/
$return[] = [
'0' => $user['official_code'],
'col0' => $user['official_code'],
'1' => $firstPosition,
'col1' => $firstPosition,
'2' => $secondPosition,
'col2' => $secondPosition,
'3' => $user['username'],
'col3' => $user['username'],
'4' => $user['user_id'],
'col4' => $user['user_id'],
'0' => $user['user_id'],
'col0' => $user['user_id']
];
}

@ -116,6 +116,7 @@ class SortableTable extends HTML_Table
* @param string $default_order_direction The default order direction;
* either the constant 'ASC' or 'DESC'
* @param string $table_id
* @param array $parameters They are custom attributes of the table
*/
public function __construct(
$table_name = 'table',
@ -124,13 +125,18 @@ class SortableTable extends HTML_Table
$default_column = 1,
$default_items_per_page = 20,
$default_order_direction = 'ASC',
$table_id = null
$table_id = null,
$parameters = []
) {
if (empty($table_id)) {
$table_id = $table_name.uniqid();
}
if(isset($parameters) && empty($parameters)){
$parameters = ['class' => 'table table-bordered data_table', 'id' => $table_id];
}
$this->table_id = $table_id;
parent::__construct(['class' => 'table table-bordered data_table', 'id' => $table_id]);
parent::__construct($parameters);
$this->table_name = $table_name;
$this->additional_parameters = [];
$this->param_prefix = $table_name.'_';

@ -0,0 +1,76 @@
<div class="summary-height">
<div class="summary">
<div class="summary-body">
<div id="summary-user-{{ item.id }}" class="summary-item">
<div class="icon">
<img src="{{ item.avatar }}" class="img-circle">
</div>
<div class="user">
<a title="{{ item.complete_name }}" href="{{ _p.web }}main/social/profile.php?u={{ item.id }}" class="name">
{{ item.complete_name }}
</a>
<div class="username">{{ item.username }}</div>
</div>
<div class="summary-course">
{% if item.course %}
{% for course in item.course %}
<div id="course-{{ course.real_id }}" class="course-item">
<div class="course-info">
<h5><a title="{{ 'Course'|get_lang }} - {{ course.title }}" href="{{ _p.web ~ 'main/mySpace/myStudents.php?details=true' ~ _p.web_cid_query ~ '&course=' ~ course.code ~ '&origin=tracking_course&id_session=0&student=' ~ item.id }}" target="_blank">{{ course.title }}</a></h5>
<span class="code">{{ course.code }}</span>
</div>
<div class="box time-spent" data-toggle="tooltip" data-placement="top" title="{{ 'CourseTimeInfo'|get_lang }}">
<i class="fa fa-clock-o" aria-hidden="true"></i>
{{ course.time_spent }}
</div>
<div class="box" data-toggle="tooltip" data-placement="top" title="{{ 'AvgStudentsProgress'|get_lang }}">
<span class="kt-badge student-progress">
{{ course.student_progress }} %
</span>
</div>
<div class="box" data-toggle="tooltip" data-placement="top" title="{{ 'AvgCourseScore'|get_lang }}">
<span class="kt-badge student-score">
{{ course.student_score }}
</span>
</div>
<div class="box" data-toggle="tooltip" data-placement="top" title="{{ 'TotalNumberOfMessages'|get_lang }}">
<span class="kt-badge student-message">
{{ course.student_message }}
</span>
</div>
<div class="box" data-toggle="tooltip" data-placement="top" title="{{ 'TotalNumberOfAssignments'|get_lang }}">
<span class="kt-badge student-assignments">
{{ course.student_assignments }}
</span>
</div>
<div class="box">
<span class="kt-badge student-exercises" data-toggle="tooltip" data-placement="top" title="{{ 'TotalExercisesScoreObtained'|get_lang }}">
{{ course.student_assignments }}
</span>
</div>
<div class="box">
<span class="kt-badge questions-answered" data-toggle="tooltip" data-placement="top" title="{{ 'TotalExercisesAnswered'|get_lang }}">
{{ course.questions_answered }}
</span>
</div>
<div class="box" data-toggle="tooltip" data-placement="top" title="{{ 'LatestLogin'|get_lang }}">
{% if course.last_connection %}
<span class="kt-badge last-connection">
{{ course.last_connection }}
</span>
{% endif %}
</div>
</div>
{% endfor %}
{% else %}
<div class="alert alert-warning" role="alert">
{{ 'HaveNoCourse'|get_lang }}
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,47 @@
<script type="text/javascript">
$(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip();
});
</script>
<div class="summary-legend">
<ul class="list-legend">
<li>
<span class="cube student-progress">
</span>
{{ 'AvgStudentsProgress'|get_lang }}
</li>
<li>
<span class="cube student-score">
</span>
{{ 'AvgCourseScore'|get_lang }}
</li>
<li>
<span class="cube student-message">
</span>
{{ 'TotalNumberOfMessages'|get_lang }}
</li>
<li>
<span class="cube student-assignments">
</span>
{{ 'TotalNumberOfAssignments'|get_lang }}
</li>
<li>
<span class="cube student-exercises">
</span>
{{ 'TotalExercisesScoreObtained'|get_lang }}
</li>
<li>
<span class="cube questions-answered">
</span>
{{ 'TotalExercisesAnswered'|get_lang }}
</li>
<li>
<span class="cube last-connection">
</span>
{{ 'LatestLogin'|get_lang }}
</li>
</ul>
</div>
{{ table }}
Loading…
Cancel
Save