Actualización

This commit is contained in:
Xes
2025-04-10 12:49:05 +02:00
parent 4aff98e77b
commit 1cdd00920f
9151 changed files with 1800913 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
<?php
/* For licensing terms, see /license.txt */
/**
* View (MVC patter) for adding a attendance.
*
* @author Christian Fasanando <christian1827@gmail.com>
*
* @package chamilo.attendance
*/
// protect a course script
api_protect_course_script(true);
// error messages
if (isset($error)) {
echo Display::return_message(get_lang('FormHasErrorsPleaseComplete'), 'error', false);
}
if (!isset($error)) {
$token = Security::get_token();
}
// display form
$form = new FormValidator(
'attendance_add',
'POST',
'index.php?action=attendance_add&'.api_get_cidreq()
);
$form->addElement('header', '', get_lang('CreateANewAttendance'));
$form->addElement('hidden', 'sec_token', $token);
$form->addText('title', get_lang('Title'), true);
$form->applyFilter('title', 'html_filter');
$form->addHtmlEditor(
'description',
get_lang('Description'),
false,
false,
['ToolbarSet' => 'Basic', 'Width' => '100%', 'Height' => '150']
);
// Advanced Parameters
if ((api_get_session_id() != 0 && Gradebook::is_active()) || api_get_session_id() == 0) {
$form->addButtonAdvancedSettings('id_qualify');
$form->addElement('html', '<div id="id_qualify_options" style="display:none">');
// Qualify Attendance for gradebook option
$form->addElement(
'checkbox',
'attendance_qualify_gradebook',
'',
get_lang('QualifyAttendanceGradebook'),
'onclick="javascript: if(this.checked){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
);
$form->addElement('html', '<div id="options_field" style="display:none">');
GradebookUtils::load_gradebook_select_in_tool($form);
$form->addElement('text', 'attendance_qualify_title', get_lang('TitleColumnGradebook'));
$form->applyFilter('attendance_qualify_title', 'html_filter');
$form->addElement(
'text',
'attendance_weight',
get_lang('QualifyWeight'),
'value="0.00" Style="width:40px" onfocus="javascript: this.select();"'
);
$form->applyFilter('attendance_weight', 'html_filter');
$form->addElement('html', '</div>');
Skill::addSkillsToForm($form, api_get_course_int_id(), api_get_session_id(), ITEM_TYPE_ATTENDANCE, 0);
$form->addElement('html', '</div>');
}
$form->addButtonCreate(get_lang('Save'));
$form->display();

View File

@@ -0,0 +1,231 @@
<?php
/* For licensing terms, see /license.txt */
/**
* View (MVC patter) for attendance calendar (list, edit, add).
*
* @author Christian Fasanando <christian1827@gmail.com>
*
* @package chamilo.attendance
*/
// protect a course script
api_protect_course_script(true);
if (!$is_locked_attendance || api_is_platform_admin()) {
echo '<div class="actions">';
if ($action == 'calendar_add') {
echo '<a href="index.php?'.api_get_cidreq().'&action=calendar_list&attendance_id='.$attendance_id.'">'.
Display::return_icon('back.png', get_lang('AttendanceCalendar'), '', ICON_SIZE_MEDIUM).'</a>';
} else {
echo '<a href="index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance_id.'">'.
Display::return_icon('back.png', get_lang('AttendanceSheet'), '', ICON_SIZE_MEDIUM).'</a>';
if (api_is_allowed_to_edit()) {
echo '<a href="index.php?'.api_get_cidreq().'&action=calendar_add&attendance_id='.$attendance_id.'">'.
Display::return_icon('add.png', get_lang('AddDateAndTime'), '', ICON_SIZE_MEDIUM).'</a>';
echo '<a onclick="javascript:if(!confirm(\''.get_lang('AreYouSureToDeleteAllDates').'\')) return false;" href="index.php?'.api_get_cidreq().'&action=calendar_all_delete&attendance_id='.$attendance_id.'">'.
Display::return_icon('clean.png', get_lang('CleanCalendar'), '', ICON_SIZE_MEDIUM).'</a>';
}
}
echo '</div>';
}
$message_information = get_lang('AttendanceCalendarDescription');
if (!empty($message_information)) {
$message = '<strong>'.get_lang('Information').'</strong><br />';
$message .= $message_information;
echo Display::return_message($message, 'normal', false);
}
if (isset($error_repeat_date) && $error_repeat_date) {
$message = get_lang('EndDateMustBeMoreThanStartDate');
echo Display::return_message($message, 'error', false);
}
if (isset($error_checkdate) && $error_checkdate) {
$message = get_lang('InvalidDate');
echo Display::return_message($message, 'error', false);
}
if (isset($action) && $action == 'calendar_add') {
$groupList = GroupManager::get_group_list(null, null, 1);
$groupIdList = ['--'];
foreach ($groupList as $group) {
$groupIdList[$group['id']] = $group['name'];
}
// calendar add form
$form = new FormValidator(
'attendance_calendar_add',
'POST',
'index.php?action=calendar_add&attendance_id='.$attendance_id.'&'.api_get_cidreq(),
''
);
$form->addElement('header', get_lang('AddADateTime'));
$form->addDateTimePicker(
'date_time',
[get_lang('StartDate')],
['id' => 'date_time']
);
$defaults['date_time'] = date('Y-m-d H:i', api_strtotime(api_get_local_time()));
$form->addElement(
'checkbox',
'repeat',
null,
get_lang('RepeatDate'),
[
'onclick' => "javascript: if(this.checked){document.getElementById('repeat-date-attendance').style.display='block';}else{document.getElementById('repeat-date-attendance').style.display='none';}",
]
);
$defaults['repeat'] = isset($repeat) ? $repeat : null;
if ($defaults['repeat']) {
$form->addElement('html', '<div id="repeat-date-attendance" style="display:block">');
} else {
$form->addElement('html', '<div id="repeat-date-attendance" style="display:none">');
}
$a_repeat_type = [
'daily' => get_lang('RepeatDaily'),
'weekly' => get_lang('RepeatWeekly'),
'biweekly' => get_lang('RepeatBiweekly'),
'xdays' => get_lang('RepeatXDays'),
'monthlyByDate' => get_lang('RepeatMonthlyByDate'),
];
$form->addElement(
'select',
'repeat_type',
get_lang('RepeatType'),
$a_repeat_type,
[
'onchange' => "javascript: if(this.value == 'xdays'){document.getElementById('repeat-date-xdaysnumber').style.display='block';}else{document.getElementById('repeat-date-xdaysnumber').style.display='none';}",
]
);
$form->addElement('html', '<div id="repeat-date-xdaysnumber" style="display:none">');
$form->addText('xdays_number', get_lang('NumberOfDays'));
$form->addElement('html', '</div>');
$form->addElement(
'date_picker',
'end_date_time',
get_lang('RepeatEnd'),
['form_name' => 'attendance_calendar_add']
);
$defaults['end_date_time'] = date('Y-m-d');
$form->addElement('html', '</div>');
$extraField = new ExtraField('attendance_calendar');
$extraField->addElements(
$form,
0,
[], //exclude
false, // filter
false, // tag as select
[], //show only fields
[], // order fields
[] // extra data
);
$defaults['repeat_type'] = 'weekly';
$defaults['xdays_number'] = '0';
$form->addSelect('groups', get_lang('Group'), $groupIdList);
$form->addButtonCreate(get_lang('Save'));
$form->setDefaults($defaults);
$form->display();
} else {
// Calendar list
$groupList = GroupManager::get_group_list();
$groupIdList = ['--'];
foreach ($groupList as $group) {
$groupIdList[$group['id']] = $group['name'];
}
echo Display::page_subheader(get_lang('CalendarList'));
echo '<ul class="list-group">';
if (!empty($attendance_calendar)) {
foreach ($attendance_calendar as $calendar) {
echo '<li class="list-group-item">';
if ((isset($action) && $action === 'calendar_edit') &&
(isset($calendar_id) && $calendar_id == $calendar['id'])
) {
// calendar edit form
echo '<div class="attendance-calendar-edit">';
$form = new FormValidator(
'attendance_calendar_edit',
'POST',
'index.php?action=calendar_edit&attendance_id='.$attendance_id.'&calendar_id='.$calendar_id.'&'.api_get_cidreq(),
''
);
$form->addDateTimePicker(
'date_time',
[get_lang('Date')],
['form_name' => 'attendance_calendar_edit'],
5
);
$extraField = new ExtraField('attendance_calendar');
$extraField->addElements(
$form,
$calendar_id,
[], //exclude
false, // filter
false, // tag as select
[], //show only fields
[], // order fields
[] // extra data
);
$defaults['date_time'] = $calendar['date_time'];
$form->addButtonSave(get_lang('Save'));
$form->addButtonCancel(get_lang('Cancel'), 'cancel');
$form->setDefaults($defaults);
$form->display();
echo '</div>';
} else {
$extraValueDuration = Attendance::getAttendanceCalendarExtraFieldValue('duration', $calendar['id']);
$labelDuration = !empty($extraValueDuration) ? ' - '.get_lang('Duration').': '.$extraValueDuration : '';
echo Display::return_icon(
'lp_calendar_event.png',
get_lang('DateTime'),
null,
ICON_SIZE_MEDIUM
).' '.
substr(
$calendar['date_time'],
0,
strlen($calendar['date_time']) - 3
).
'&nbsp;&nbsp;'.$labelDuration;
if (isset($calendar['groups']) && !empty($calendar['groups'])) {
foreach ($calendar['groups'] as $group) {
echo '&nbsp;'.Display::label($groupIdList[$group['group_id']]);
}
}
if (!$is_locked_attendance || api_is_platform_admin()) {
if (api_is_allowed_to_edit()) {
echo '<div class="pull-right">';
echo '<a href="index.php?'.api_get_cidreq().'&action=calendar_edit&calendar_id='.intval($calendar['id']).'&attendance_id='.$attendance_id.'">'.
Display::return_icon('edit.png', get_lang('Edit'), ['style' => 'vertical-align:middle'], ICON_SIZE_SMALL).'</a>&nbsp;';
echo '<a onclick="javascript:if(!confirm(\''.get_lang('AreYouSureToDelete').'\')) return false;" href="index.php?'.api_get_cidreq().'&action=calendar_delete&calendar_id='.intval($calendar['id']).'&attendance_id='.$attendance_id.'">'.
Display::return_icon('delete.png', get_lang('Delete'), ['style' => 'vertical-align:middle'], ICON_SIZE_SMALL).'</a>';
echo '</div>';
}
}
}
echo '</li>';
}
} else {
echo Display::return_message(get_lang('ThereAreNoRegisteredDatetimeYet'), 'warning');
}
echo '</ul>';
}

View File

@@ -0,0 +1,88 @@
<div id="comment-popup" style="display: none">
<div id="comment-area" class="well">
<textarea id="txt-comment" style="width: 100%;height: 150px;" placeholder="<?php echo get_lang('WriteAComment'); ?>"></textarea>
<div id="comment-author"></div>
</div>
<span id="save-comment-controls">
<span id="comment-results"></span>
<button id="comment-popup-save" class="btn btn-primary" type="submit">
<em class="fa fa-save"></em> <?php echo get_lang('Save'); ?>
</button>
<button id="comment-popup-close" class="btn btn-default" type="submit">
<em class="fa fa-eraser"></em> <?php echo get_lang('Close'); ?>
</button>
</span>
<span class="loading" style="display: none"><em class="fa fa-spinner"></em></span>
<input type="hidden" id="comment-selected" />
</div>
<script>
var urlAjax = "<?php echo api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?'.api_get_cidreq(); ?>";
var attendance_id = "<?php echo $attendance_id; ?>";
$(function() {
$("#comment-popup-save").on("click", function() {
var comment = $("#txt-comment").val();
if (comment == '') {
alert('<?php echo get_lang('ProvideACommentFirst'); ?>');
return false;
}
var selected = $("#comment-selected").val();
$.ajax({
beforeSend: function(result) {
$('#loading').show();
},
type: "POST",
url: urlAjax,
data: "a=comment_attendance&selected="+selected+"&comment="+comment+"&attendance_id="+attendance_id,
success: function(data) {
$('#loading').hide();
$('#save-comment-controls').hide();
$('#comment-area').hide();
if (1 == data) {
$('#comment-results').html('<?php echo get_lang('Saved'); ?>');
} else {
$('#comment-results').html('<?php echo get_lang('Error'); ?>');
}
$("#comment-popup-close").click();
},
});
});
$("#comment-popup-close").on("click", function() {
$("#comment-popup").dialog("close");
$('#loading').hide();
$('#save-comment-controls').show();
$('#comment-area').show();
$("#txt-comment").val('');
$("#comment-author").text('');
});
$(".attendance-comment").on("click", function() {
var selected = $(this).attr("id");
$("#comment-selected").val(selected);
$("#comment-popup").dialog({
autoOpen: true,
width: 500,
height: 'auto'
});
$("#comment-results").hide();
$("#save-comment-controls").show();
$('#comment-area').show();
setComment(selected);
});
function setComment(selected) {
$('#txt-comment').val('...');
$("#comment-author").text('');
$.getJSON(urlAjax + "&a=get_attendance_comment&selected=" + selected).done(function (data) {
if (data.comment) {
$('#txt-comment').val(data.comment);
}
if (data.author) {
$("#comment-author").text(data.author);
}
});
}
});
</script>

View File

@@ -0,0 +1,805 @@
<?php
/* For licensing terms, see /license.txt */
/**
* This file contains class used like controller,
* it should be included inside a dispatcher file (e.g: index.php).
*
* !!! WARNING !!! : ALL DATES IN THIS MODULE ARE STORED IN UTC !
* DO NOT CONVERT DURING THE TRANSITION FROM CHAMILO 1.8.x TO 2.0
*
* @author Christian Fasanando <christian1827@gmail.com>
* @author Julio Montoya <gugli100@gmail.com> lot of bugfixes + improvements
*
* @package chamilo.attendance
*/
class AttendanceController
{
/**
* Constructor.
*/
public function __construct()
{
$this->toolname = 'attendance';
$this->view = new View($this->toolname);
}
/**
* It's used for listing attendance,
* render to attendance_list view.
*/
public function attendance_list()
{
// render to the view
$this->view->set_data([]);
$this->view->set_layout('layout');
$this->view->set_template('attendance_list');
$this->view->render();
}
/**
* It's used for adding attendace,
* render to attendance_add or attendance_list view.
*/
public function attendance_add()
{
$attendance = new Attendance();
$data = [];
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') {
if (!empty($_POST['title'])) {
$check = Security::check_token();
$attendanceId = 0;
if ($check) {
$attendance->set_name($_POST['title']);
$attendance->set_description($_POST['description']);
$attendance->set_attendance_qualify_title($_POST['attendance_qualify_title']);
$attendance->set_attendance_weight($_POST['attendance_weight']);
$link_to_gradebook = false;
if (isset($_POST['attendance_qualify_gradebook']) &&
$_POST['attendance_qualify_gradebook'] == 1
) {
$link_to_gradebook = true;
}
$attendance->category_id = isset($_POST['category_id']) ? $_POST['category_id'] : 0;
$attendanceId = $attendance->attendance_add($link_to_gradebook);
if ($attendanceId) {
$form = new FormValidator('attendance_add');
Skill::saveSkills($form, ITEM_TYPE_ATTENDANCE, $attendanceId);
}
Security::clear_token();
}
header('Location: index.php?action=calendar_add&attendance_id='.$attendanceId.'&'.api_get_cidreq());
exit;
} else {
$data['error'] = true;
$this->view->set_data($data);
$this->view->set_layout('layout');
$this->view->set_template('attendance_add');
$this->view->render();
}
} else {
$this->view->set_data($data);
$this->view->set_layout('layout');
$this->view->set_template('attendance_add');
$this->view->render();
}
}
/**
* It's used for editing attendance,
* render to attendance_edit or attendance_list view.
*
* @param int $attendance_id
*/
public function attendance_edit($attendance_id)
{
$attendance = new Attendance();
$data = [];
$attendance_id = intval($attendance_id);
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') {
if (!empty($_POST['title'])) {
$check = Security::check_token();
if ($check) {
$attendance->set_name($_POST['title']);
$attendance->set_description($_POST['description']);
if (isset($_POST['attendance_qualify_title'])) {
$attendance->set_attendance_qualify_title(
$_POST['attendance_qualify_title']
);
}
if (isset($_POST['attendance_weight'])) {
$attendance->set_attendance_weight(
$_POST['attendance_weight']
);
}
$attendance->category_id = isset($_POST['category_id']) ? $_POST['category_id'] : '';
$link_to_gradebook = false;
if (isset($_POST['attendance_qualify_gradebook']) &&
$_POST['attendance_qualify_gradebook'] == 1
) {
$link_to_gradebook = true;
}
$attendance->attendance_edit($attendance_id, $link_to_gradebook);
$form = new FormValidator('attendance_edit');
Skill::saveSkills($form, ITEM_TYPE_ATTENDANCE, $attendance_id);
Display::addFlash(Display::return_message(get_lang('Updated')));
Security::clear_token();
header('Location:index.php?action=attendance_list&'.api_get_cidreq());
exit;
}
} else {
$data['attendance_id'] = $_POST['attendance_id'];
$data['error'] = true;
$this->view->set_data($data);
$this->view->set_layout('layout');
$this->view->set_template('attendance_edit');
$this->view->render();
}
} else {
// default values
$attendance_data = $attendance->get_attendance_by_id(
$attendance_id
);
$data['attendance_id'] = $attendance_data['id'];
$data['title'] = $attendance_data['name'];
$data['description'] = $attendance_data['description'];
$data['attendance_qualify_title'] = $attendance_data['attendance_qualify_title'];
$data['attendance_weight'] = $attendance_data['attendance_weight'];
$this->view->set_data($data);
$this->view->set_layout('layout');
$this->view->set_template('attendance_edit');
$this->view->render();
}
}
/**
* It's used for delete attendaces
* render to attendance_list view.
*
* @param int $attendance_id
*
* @return bool
*/
public function attendance_delete($attendance_id)
{
$allowDeleteAttendance = api_get_setting('allow_delete_attendance');
if ($allowDeleteAttendance !== 'true') {
$this->attendance_list();
return false;
}
$attendance = new Attendance();
if (!empty($attendance_id)) {
$affected_rows = $attendance->attendance_delete($attendance_id);
Skill::deleteSkillsFromItem($attendance_id, ITEM_TYPE_ATTENDANCE);
}
if ($affected_rows) {
$message['message_attendance_delete'] = true;
}
$this->attendance_list();
return true;
}
/**
* It's used for make attendance visible
* render to attendance_list view.
*
* @param int $attendanceId
*/
public function attendanceSetVisible($attendanceId)
{
$attendance = new Attendance();
$affectedRows = null;
if (!empty($attendanceId)) {
$affectedRows = $attendance->changeVisibility($attendanceId, 1);
}
if ($affectedRows) {
$message['message_attendance_delete'] = true;
}
$this->attendance_list();
}
/**
* It's used for make attendance invisible
* render to attendance_list view.
*
* @param int $attendanceId
*/
public function attendanceSetInvisible($attendanceId)
{
$attendance = new Attendance();
if (!empty($attendanceId)) {
$affectedRows = $attendance->changeVisibility($attendanceId, 0);
}
if ($affectedRows) {
$message['message_attendance_delete'] = true;
}
$this->attendance_list();
}
/**
* Restores an attendance entry and fallback to attendances rendering.
*
* @param int $attendance_id
*/
public function attendance_restore($attendance_id)
{
$attendance = new Attendance();
$affected_rows = false;
if (!empty($attendance_id)) {
$affected_rows = $attendance->attendance_restore($attendance_id);
}
if ($affected_rows) {
$message['message_attendance_restore'] = true;
}
$this->attendance_list();
}
/**
* Lock or unlock an attendance
* render to attendance_list view.
*
* @param string $action (lock_attendance or unlock_attendance)
* @param int $attendance_id
* render to attendance_list view
*/
public function lock_attendance($action, $attendance_id)
{
$attendance = new Attendance();
$attendance_id = intval($attendance_id);
if ($action == 'lock_attendance') {
$result = $attendance->lock_attendance($attendance_id);
} else {
$result = $attendance->lock_attendance($attendance_id, false);
}
if ($result) {
$message['message_locked_attendance'] = true;
}
$this->attendance_list();
}
public function export($id, $type = 'pdf')
{
$attendance = new Attendance();
}
/**
* It's used for controlling attendance sheet (list, add),
* render to attendance_sheet view.
*
* @param string $action
* @param int $attendance_id
* @param int $student_id
* @param bool $edit
*/
public function attendance_sheet(
$action,
$attendance_id,
$student_id = 0,
$edit = true
) {
$attendance = new Attendance();
$data = [];
$data['attendance_id'] = $attendance_id;
$groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : null;
$data['users_in_course'] = $attendance->get_users_rel_course($attendance_id, $groupId);
$data['faults'] = [];
$filter_type = 'today';
if (!empty($_REQUEST['filter'])) {
$filter_type = $_REQUEST['filter'];
}
$isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
api_get_user_id(),
api_get_course_info()
) || api_is_drh();
if ($edit == true) {
if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) {
$data['users_presence'] = $attendance->get_users_attendance_sheet(
$attendance_id,
0,
$groupId
);
}
} else {
if (!empty($student_id)) {
$user_id = intval($student_id);
} else {
$user_id = api_get_user_id();
}
if (api_is_allowed_to_edit(null, true) ||
api_is_coach(api_get_session_id(), api_get_course_int_id()) ||
$isDrhOfCourse
) {
$data['users_presence'] = $attendance->get_users_attendance_sheet(
$attendance_id,
0,
$groupId
);
} else {
$data['users_presence'] = $attendance->get_users_attendance_sheet(
$attendance_id,
$user_id,
$groupId
);
}
$data['faults'] = $attendance->get_faults_of_user($user_id, $attendance_id, $groupId);
$data['user_id'] = $user_id;
}
$data['next_attendance_calendar_id'] = $attendance->get_next_attendance_calendar_id(
$attendance_id
);
$data['next_attendance_calendar_datetime'] = $attendance->getNextAttendanceCalendarDatetime(
$attendance_id
);
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST') {
$check = Security::check_token();
if ($check) {
if (isset($_POST['hidden_input'])) {
foreach ($_POST['hidden_input'] as $cal_id) {
$users_present = [];
if (isset($_POST['check_presence'][$cal_id])) {
$users_present = $_POST['check_presence'][$cal_id];
}
$attendance->attendance_sheet_add(
$cal_id,
$users_present,
$attendance_id
);
}
}
Security::clear_token();
}
$data['users_in_course'] = $attendance->get_users_rel_course($attendance_id, $groupId);
$my_calendar_id = null;
if (is_numeric($filter_type)) {
$my_calendar_id = $filter_type;
$filter_type = 'calendar_id';
}
$data['attendant_calendar'] = $attendance->get_attendance_calendar(
$attendance_id,
$filter_type,
$my_calendar_id,
$groupId
);
$data['attendant_calendar_all'] = $attendance->get_attendance_calendar(
$attendance_id,
'all',
null,
$groupId
);
$data['users_presence'] = $attendance->get_users_attendance_sheet($attendance_id, 0, $groupId);
$data['next_attendance_calendar_id'] = $attendance->get_next_attendance_calendar_id($attendance_id);
$data['next_attendance_calendar_datetime'] = $attendance->getNextAttendanceCalendarDatetime($attendance_id);
} else {
$data['attendant_calendar_all'] = $attendance->get_attendance_calendar(
$attendance_id,
'all',
null,
$groupId
);
$data['attendant_calendar'] = $attendance->get_attendance_calendar(
$attendance_id,
$filter_type,
null,
$groupId
);
}
$attendanceInfo = $attendance->get_attendance_by_id($attendance_id);
$allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
$allowComment = api_get_configuration_value('attendance_allow_comments');
$func = isset($_REQUEST['func']) ? $_REQUEST['func'] : null;
$calendarId = isset($_REQUEST['calendar_id']) ? (int) $_REQUEST['calendar_id'] : null;
$fullScreen = ($func == 'fullscreen' && $calendarId > 0 && $allowSignature);
$data['edit_table'] = intval($edit);
$data['is_locked_attendance'] = $attendance->is_locked_attendance($attendance_id);
$data['allowSignature'] = $allowSignature;
$data['allowComment'] = $allowComment;
$data['fullScreen'] = $fullScreen;
$data['attendanceName'] = $attendanceInfo['name'];
if ($fullScreen) {
if (api_is_allowed_to_edit()) {
$uinfo = api_get_user_info();
$cinfo = api_get_course_info();
$data['calendarId'] = $calendarId;
$data['trainer'] = api_get_person_name($uinfo['firstname'], $uinfo['lastname']);
$data['courseName'] = $cinfo['title'];
$attendanceCalendar = $attendance->get_attendance_calendar(
$attendance_id,
'calendar_id',
$calendarId,
$groupId
);
$data['attendanceCalendar'] = $attendanceCalendar[0];
$this->view->set_template('attendance_sheet_fullscreen');
}
} else {
$this->view->set_template('attendance_sheet');
}
$this->view->set_data($data);
$this->view->set_layout('layout');
$this->view->render();
}
/**
* It's used for controlling attendance calendar (list, add, edit, delete),
* render to attendance_calendar view.
*
* @param string $action (optional, by default 'calendar_list')
* @param int $attendance_id (optional)
* @param int $calendar_id (optional)
*/
public function attendance_calendar($action = 'calendar_list', $attendance_id = 0, $calendar_id = 0)
{
$attendance = new Attendance();
$calendar_id = intval($calendar_id);
$data = [];
$data['attendance_id'] = $attendance_id;
$attendance_id = intval($attendance_id);
$groupList = isset($_POST['groups']) ? [$_POST['groups']] : [];
if ($action == 'calendar_add') {
if (strtoupper($_SERVER['REQUEST_METHOD']) == "POST") {
if (!isset($_POST['cancel'])) {
if (isset($_POST['repeat'])) {
//@todo check this error_logs
$start_datetime = api_strtotime(
api_get_utc_datetime($_POST['date_time']),
'UTC'
);
$end_datetime = api_strtotime(api_get_utc_datetime($_POST['end_date_time'].' 23:59:59'), 'UTC');
$checkdate = api_is_valid_date(api_get_utc_datetime($_POST['end_date_time'].' 23:59:59'));
$repeat_type = $_POST['repeat_type'];
if (($end_datetime > $start_datetime) && $checkdate) {
$attendance->attendance_repeat_calendar_add(
$attendance_id,
$start_datetime,
$end_datetime,
$repeat_type,
$groupList,
$_POST
);
$action = 'calendar_list';
} else {
if (!$checkdate) {
$data['error_checkdate'] = true;
} else {
$data['error_repeat_date'] = true;
}
$data['repeat'] = true;
$action = 'calendar_add';
}
} else {
$datetime = $_POST['date_time'];
$datetimezone = api_get_utc_datetime($datetime);
if (!empty($datetime)) {
$attendance->set_date_time($datetimezone);
$attendance->attendance_calendar_add($attendance_id, $groupList);
$action = 'calendar_list';
} else {
$data['error_date'] = true;
$action = 'calendar_add';
}
}
} else {
$action = 'calendar_list';
}
}
} elseif ($action === 'calendar_edit') {
$data['calendar_id'] = $calendar_id;
if (strtoupper($_SERVER['REQUEST_METHOD']) == "POST") {
if (!isset($_POST['cancel'])) {
$datetime = $_POST['date_time'];
$datetimezone = api_get_utc_datetime($datetime);
$attendance->set_date_time($datetimezone);
$attendance->attendance_calendar_edit($calendar_id, $attendance_id, $_POST);
$data['calendar_id'] = 0;
$action = 'calendar_list';
} else {
$action = 'calendar_list';
}
}
} elseif ($action == 'calendar_delete') {
$attendance->attendance_calendar_delete($calendar_id, $attendance_id);
$action = 'calendar_list';
} elseif ($action == 'calendar_all_delete') {
$attendance->attendance_calendar_delete(0, $attendance_id, true);
$action = 'calendar_list';
}
$data['action'] = $action;
$data['attendance_calendar'] = $attendance->get_attendance_calendar(
$attendance_id,
'all',
null,
null,
true
);
$data['is_locked_attendance'] = $attendance->is_locked_attendance($attendance_id);
// render to the view
$this->view->set_data($data);
$this->view->set_layout('layout');
$this->view->set_template('attendance_calendar');
$this->view->render();
}
/**
* Checks the attendance sheet to export XLS.
*/
public function attendanceSheetExportToXls(
int $attendanceId,
int $studentId = 0,
string $courseCode = '',
?int $groupId,
?string $filter
) {
$attendance = new Attendance();
$courseInfo = api_get_course_info($courseCode);
$attendance->set_course_id($courseInfo['code']);
$filterType = 'today';
if (!empty($filter)) {
$filterType = $filter;
}
$myCalendarId = null;
if (is_numeric($filterType)) {
$myCalendarId = $filterType;
$filterType = 'calendar_id';
}
$attendance->exportAttendanceSheetToXls(
$attendanceId,
$studentId,
$courseCode,
$groupId,
$filterType,
$myCalendarId
);
}
/**
* It's used to print attendance sheet.
*
* @param string $action
* @param int $attendance_id
*/
public function attendance_sheet_export_to_pdf(
$action,
$attendance_id,
$student_id = 0,
$course_id = ''
) {
$attendance = new Attendance();
$courseInfo = api_get_course_info($course_id);
$attendance->set_course_id($courseInfo['code']);
$groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : null;
$data_array = [];
$data_array['attendance_id'] = $attendance_id;
$data_array['users_in_course'] = $attendance->get_users_rel_course($attendance_id, $groupId);
$filter_type = 'today';
if (!empty($_REQUEST['filter'])) {
$filter_type = $_REQUEST['filter'];
}
$my_calendar_id = null;
if (is_numeric($filter_type)) {
$my_calendar_id = $filter_type;
$filter_type = 'calendar_id';
}
$data_array['attendant_calendar'] = $attendance->get_attendance_calendar(
$attendance_id,
$filter_type,
$my_calendar_id,
$groupId
);
if (api_is_allowed_to_edit(null, true) || api_is_drh()) {
$data_array['users_presence'] = $attendance->get_users_attendance_sheet($attendance_id, 0, $groupId);
} else {
if (!empty($student_id)) {
$user_id = intval($student_id);
} else {
$user_id = api_get_user_id();
}
$data_array['users_presence'] = $attendance->get_users_attendance_sheet($attendance_id, $user_id, $groupId);
$data_array['faults'] = $attendance->get_faults_of_user($user_id, $attendance_id, $groupId);
$data_array['user_id'] = $user_id;
}
$data_array['next_attendance_calendar_id'] = $attendance->get_next_attendance_calendar_id($attendance_id);
// Set headers pdf.
$courseCategory = CourseManager::get_course_category($courseInfo['categoryCode']);
$teacherInfo = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
$teacherName = null;
foreach ($teacherInfo as $teacherData) {
if ($teacherName != null) {
$teacherName = $teacherName." / ";
}
$teacherName .= api_get_person_name($teacherData['firstname'], $teacherData['lastname']);
}
// Get data table
$data_table = [];
$head_table = ['#', get_lang('Name')];
foreach ($data_array['attendant_calendar'] as $class_day) {
$labelDuration = !empty($class_day['duration']) ? get_lang('Duration').' : '.$class_day['duration'] : '';
$head_table[] =
api_format_date($class_day['date_time'], DATE_FORMAT_NUMBER_NO_YEAR).' '.
api_format_date($class_day['date_time'], TIME_NO_SEC_FORMAT).' '.
$labelDuration;
}
$data_table[] = $head_table;
$data_attendant_calendar = $data_array['attendant_calendar'];
$data_users_presence = $data_array['users_presence'];
$count = 1;
if (!empty($data_array['users_in_course'])) {
foreach ($data_array['users_in_course'] as $user) {
$cols = 1;
$result = [];
$result['count'] = $count;
$result['full_name'] = api_get_person_name($user['firstname'], $user['lastname']);
foreach ($data_array['attendant_calendar'] as $class_day) {
if ($class_day['done_attendance'] == 1) {
if ($data_users_presence[$user['user_id']][$class_day['id']]['presence'] == 1) {
$result[$class_day['id']] = get_lang('UserAttendedSymbol');
} else {
$result[$class_day['id']] = '<span style="color:red">'.get_lang('UserNotAttendedSymbol').'</span>';
}
} else {
$result[$class_day['id']] = ' ';
}
$cols++;
}
$count++;
$data_table[] = $result;
}
}
$max_cols_per_page = 12; //10 dates + 2 name and number
$max_dates_per_page = $max_dates_per_page_original = $max_cols_per_page - 2; //10
$rows = count($data_table);
if ($cols > $max_cols_per_page) {
$number_tables = round(($cols - 2) / $max_dates_per_page);
$headers = $data_table[0];
$all = [];
$tables = [];
$changed = 1;
for ($i = 0; $i <= $rows; $i++) {
$row = isset($data_table[$i]) ? $data_table[$i] : null;
$key = 1;
$max_dates_per_page = 10;
$item = isset($data_table[$i]) ? $data_table[$i] : null;
$count_j = 0;
if (!empty($item)) {
foreach ($item as $value) {
if ($count_j >= $max_dates_per_page) {
$key++;
$max_dates_per_page = $max_dates_per_page_original * $key;
//magic hack
$tables[$key][$i][] = $tables[1][$i][0];
$tables[$key][$i][] = $tables[1][$i][1];
}
$tables[$key][$i][] = $value;
$count_j++;
}
}
}
$content = null;
if (!empty($tables)) {
foreach ($tables as $sub_table) {
$content .= Export::convert_array_to_html($sub_table).'<br /><br />';
}
}
} else {
$content = Export::convert_array_to_html(
$data_table,
['header_attributes' => ['align' => 'center']]
);
}
$params = [
'filename' => get_lang('Attendance').'-'.api_get_local_time(),
'pdf_title' => $courseInfo['title'],
'course_code' => $courseInfo['code'],
'add_signatures' => ['Drh', 'Teacher', 'Date'],
'orientation' => 'landscape',
'pdf_teachers' => $teacherName,
'pdf_course_category' => $courseCategory['name'],
'format' => 'A4-L',
'orientation' => 'L',
];
Export::export_html_to_pdf($content, $params);
exit;
}
/**
* Gets attendance base in the table:
* TABLE_STATISTIC_TRACK_E_COURSE_ACCESS.
*
* @param bool $showForm
* @param bool $exportToPdf
*/
public function getAttendanceBaseInLogin($showForm = false, $exportToPdf = true)
{
$table = null;
$formToDisplay = null;
$startDate = null;
$endDate = null;
$sessionId = api_get_session_id();
if ($showForm) {
$form = new FormValidator(
'search',
'post',
api_get_self().'?'.api_get_cidreq().'&action=calendar_logins'
);
$form->addDateRangePicker('range', get_lang('DateRange'));
$form->addButton('submit', get_lang('Submit'));
if ($form->validate()) {
$values = $form->getSubmitValues();
$startDate = api_get_utc_datetime($values['range_start']);
$endDate = api_get_utc_datetime($values['range_end']);
}
$formToDisplay = $form->returnForm();
} else {
if (!empty($sessionId)) {
$sessionInfo = api_get_session_info($sessionId);
$startDate = $sessionInfo['access_start_date'];
$endDate = $sessionInfo['access_end_date'];
}
}
$attendance = new Attendance();
if ($exportToPdf) {
$result = $attendance->exportAttendanceLogin($startDate, $endDate);
if (empty($result)) {
api_not_allowed(true, get_lang('NoDataAvailable'));
}
}
$table = $attendance->getAttendanceLoginTable($startDate, $endDate);
$data = [
'form' => $formToDisplay,
'table' => $table,
];
$this->view->set_data($data);
$this->view->set_layout('layout');
$this->view->set_template('calendar_logins');
$this->view->render();
}
}

View File

@@ -0,0 +1,109 @@
<?php
/* For licensing terms, see /license.txt */
/**
* View (MVC patter) for editing an attendance.
*
* @author Christian Fasanando <christian1827@gmail.com>
*/
api_protect_course_script(true);
// error messages
if (isset($error)) {
echo Display::return_message(get_lang('FormHasErrorsPleaseComplete'), 'error', false);
}
if (!isset($error)) {
$token = Security::get_token();
}
$attendance_weight = api_float_val($attendance_weight);
$form = new FormValidator(
'attendance_edit',
'POST',
'index.php?action=attendance_edit&'.api_get_cidreq().'&attendance_id='.$attendance_id
);
$form->addElement('header', '', get_lang('Edit'));
$form->addElement('hidden', 'sec_token', $token);
$form->addElement('hidden', 'attendance_id', $attendance_id);
$form->addText('title', get_lang('Title'), true);
$form->applyFilter('title', 'html_filter');
$form->addHtmlEditor(
'description',
get_lang('Description'),
false,
false,
[
'ToolbarSet' => 'Basic',
'Width' => '100%',
'Height' => '200',
]
);
// Advanced Parameters
$skillList = [];
if (Gradebook::is_active()) {
if (!empty($attendance_qualify_title) || !empty($attendance_weight)) {
$form->addButtonAdvancedSettings('id_qualify');
$form->addElement('html', '<div id="id_qualify_options" style="display:block">');
$form->addElement(
'checkbox',
'attendance_qualify_gradebook',
'',
get_lang('QualifyAttendanceGradebook'),
[
'checked' => 'true',
'onclick' => 'javascript: if(this.checked){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}',
]
);
$form->addElement('html', '<div id="options_field" style="display:block">');
} else {
$form->addButtonAdvancedSettings('id_qualify');
$form->addElement('html', '<div id="id_qualify_options" style="display:none">');
$form->addElement(
'checkbox',
'attendance_qualify_gradebook',
'',
get_lang('QualifyAttendanceGradebook'),
'onclick="javascript: if(this.checked){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
);
$form->addElement('html', '<div id="options_field" style="display:none">');
}
GradebookUtils::load_gradebook_select_in_tool($form);
$form->addElement('text', 'attendance_qualify_title', get_lang('TitleColumnGradebook'));
$form->applyFilter('attendance_qualify_title', 'html_filter');
$form->addElement(
'text',
'attendance_weight',
get_lang('QualifyWeight'),
'value="0.00" Style="width:40px" onfocus="javascript: this.select();"'
);
$form->applyFilter('attendance_weight', 'html_filter');
$form->addElement('html', '</div>');
Skill::addSkillsToForm($form, api_get_course_int_id(), api_get_session_id(), ITEM_TYPE_ATTENDANCE, $attendance_id);
$form->addElement('html', '</div>');
}
$form->addButtonUpdate(get_lang('Save'));
// set default values
$default['title'] = Security::remove_XSS($title);
$default['description'] = Security::remove_XSS($description, STUDENT);
$default['attendance_qualify_title'] = $attendance_qualify_title;
$default['attendance_weight'] = $attendance_weight;
$linkInfo = GradebookUtils::isResourceInCourseGradebook(
api_get_course_id(),
7,
$attendance_id,
api_get_session_id()
);
$default['category_id'] = null;
if ($linkInfo) {
$default['category_id'] = $linkInfo['category_id'];
}
$form->setDefaults($default);
$form->display();

View File

@@ -0,0 +1,56 @@
<?php
/* For licensing terms, see /license.txt */
/**
* View (MVC patter) for listing attendances.
*
* @author Christian Fasanando <christian1827@gmail.com>
*
* @package chamilo.attendance
*/
// protect a course script
api_protect_course_script(true);
if (api_is_allowed_to_edit(null, true)) {
echo '<div class="actions">';
echo '<a href="index.php?'.api_get_cidreq().'&action=attendance_add">'.
Display::return_icon('new_attendance_list.png', get_lang('CreateANewAttendance'), '', ICON_SIZE_MEDIUM).'</a>';
echo '</div>';
}
$attendance = new Attendance();
if ($attendance->getNumberOfAttendances() == 0) {
$attendance->set_name(get_lang('Attendances'));
$attendance->set_description(get_lang('Attendances'));
$attendance->attendance_add();
}
$default_column = $default_column ?? null;
$parameters = $parameters ?? [];
$table = new SortableTable(
'attendance_list',
['Attendance', 'getNumberOfAttendances'],
['Attendance', 'get_attendance_data'],
$default_column
);
$table->set_additional_parameters($parameters);
$table->set_header(0, '', false, ['style' => 'width:20px;']);
$table->set_header(1, get_lang('Name'));
$table->set_header(2, get_lang('Description'));
$table->set_header(3, get_lang('CountDoneAttendance'), true, ['style' => 'width:90px;']);
if (api_is_allowed_to_edit(null, true)) {
$table->set_header(4, get_lang('Actions'), false, ['style' => 'text-align:center']);
$actions = [
'attendance_set_invisible_select' => get_lang('SetInvisible'),
'attendance_set_visible_select' => get_lang('SetVisible'),
];
$allow = api_get_setting('allow_delete_attendance');
if ($allow === 'true') {
$actions['attendance_delete_select'] = get_lang('DeleteAllSelectedAttendances');
}
$table->set_form_actions($actions);
}
if ($table->get_total_number_of_items() > 0) {
$table->display();
}

View File

@@ -0,0 +1,583 @@
<?php
/* For licensing terms, see /license.txt */
/**
* View (MVC patter) for attendance sheet (list, edit, add).
*
* @author Christian Fasanando <christian1827@gmail.com>
* @author Julio Montoya reworked 2010
*
* @package chamilo.attendance
*/
// Protect a course script
api_protect_course_script(true);
$isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
api_get_user_id(),
api_get_course_info()
) || api_is_drh();
$token = Security::get_token();
if (api_is_allowed_to_edit(null, true) ||
api_is_coach(api_get_session_id(), api_get_course_int_id()) ||
$isDrhOfCourse
) {
$groupId = isset($_REQUEST['group_id']) ? intval($_REQUEST['group_id']) : null;
$form = new FormValidator(
'filter',
'post',
'index.php?action=attendance_sheet_list&'.api_get_cidreq().'&attendance_id='.$attendance_id,
null,
[],
'inline'
);
$values = [
'all' => get_lang('All'),
'today' => get_lang('Today'),
'all_done' => get_lang('AllDone'),
'all_not_done' => get_lang('AllNotDone'),
];
$today = api_convert_and_format_date(null, DATE_FORMAT_SHORT);
$exists_attendance_today = false;
if (!empty($attendant_calendar_all)) {
$values[''] = '---------------';
foreach ($attendant_calendar_all as $attendance_date) {
$includeCalendar = true;
if (isset($attendance_date['groups']) && !empty($groupId)) {
foreach ($attendance_date['groups'] as $group) {
if ($groupId == $group['group_id']) {
$includeCalendar = true;
break;
} else {
$includeCalendar = false;
}
}
}
if ($today == $attendance_date['date']) {
$exists_attendance_today = true;
}
if ($includeCalendar) {
$values[$attendance_date['id']] = $attendance_date['date_time'];
}
}
}
if (!$exists_attendance_today) {
echo Display::return_message(
get_lang('ThereIsNoClassScheduledTodayTryPickingAnotherDay'),
'warning'
);
}
$form->addSelect(
'filter',
get_lang('Filter'),
$values,
['id' => 'filter_id', 'onchange' => 'submit();']
);
$groupList = GroupManager::get_group_list(null, null, 1);
$groupIdList = ['--'];
foreach ($groupList as $group) {
$groupIdList[$group['id']] = $group['name'];
}
if (!empty($groupList)) {
$form->addSelect('group_id', get_lang('Group'), $groupIdList);
}
if (isset($_REQUEST['filter'])) {
if (in_array($_REQUEST['filter'], array_keys($values))) {
$default_filter = $_REQUEST['filter'];
}
} else {
$default_filter = 'today';
}
$renderer = $form->defaultRenderer();
$renderer->setCustomElementTemplate('<div class="col-md-2">{label}</div><div class="col-md-10"> {element} </div>');
$form->setDefaults(
[
'filter' => $default_filter,
'group_id' => $groupId,
]
);
if (!$is_locked_attendance || api_is_platform_admin()) {
$actionsLeft = '<a style="float:left;" href="index.php?'.api_get_cidreq().'&action=calendar_list&attendance_id='.$attendance_id.'">'.
Display::return_icon('attendance_calendar.png', get_lang('AttendanceCalendar'), '', ICON_SIZE_MEDIUM).'</a>';
$actionsLeft .= '<a id="pdf_export" style="float:left;" href="index.php?'.api_get_cidreq().'&action=attendance_sheet_export_to_pdf&attendance_id='.$attendance_id.'&filter='.$default_filter.'&group_id='.$groupId.'">'.
Display::return_icon('pdf.png', get_lang('ExportToPDF'), '', ICON_SIZE_MEDIUM).'</a>';
$actionsLeft .= '<a id="pdf_export" style="float:left;" href="index.php?'.api_get_cidreq().'&action=attendance_sheet_export_to_xls&attendance_id='.$attendance_id.'&filter='.$default_filter.'&group_id='.$groupId.'">'.
Display::return_icon('export_excel.png', get_lang('ExportToXls'), '', ICON_SIZE_MEDIUM).'</a>';
$actionsLeft .= '<a class="ajax" data-size="sm" style="float:left;" title="QR" href="index.php?'.api_get_cidreq().'&action=attendance_sheet_qrcode&attendance_id='.$attendance_id.'&filter='.$default_filter.'&group_id='.$groupId.'">'.
Display::return_icon('paint.png', get_lang('DownloadQr'), '', ICON_SIZE_MEDIUM).'</a>';
$actionsRight = $form->returnForm();
$toolbar = Display::toolbarAction('toolbar-attendance', [$actionsLeft, $actionsRight]);
echo $toolbar;
}
$message_information = get_lang('AttendanceSheetDescription');
if (!empty($message_information)) {
$message = '<strong>'.get_lang('Information').'</strong><br />';
$message .= $message_information;
echo Display::return_message($message, 'normal', false);
}
if ($is_locked_attendance) {
echo Display::return_message(get_lang('TheAttendanceSheetIsLocked'), 'warning', false);
}
$param_filter = '&filter='.Security::remove_XSS($default_filter).'&group_id='.$groupId;
if (count($users_in_course) > 0) {
?>
<script>
var original_url = '';
$("#filter_id").on('change', function() {
filter = $(this).val();
if (original_url == '') {
original_url = $("#pdf_export").attr('href');
}
new_url = original_url + "&filter=" +filter
$("#pdf_export").attr('href', new_url);
});
function UpdateTableHeaders() {
$("div.divTableWithFloatingHeader").each(function() {
var originalHeaderRow = $(".tableFloatingHeaderOriginal", this);
var floatingHeaderRow = $(".tableFloatingHeader", this);
var offset = $(this).offset();
var scrollTop = $(window).scrollTop();
if ((scrollTop > offset.top) && (scrollTop < offset.top + $(this).height())) {
floatingHeaderRow.css("visibility", "hidden");
var topbar = 0;
if ($("#topbar").length != 0) {
topbar = $("#topbar").height();
} else {
if ($(".subnav").length != 0) {
topbar = $(".subnav").height();
}
}
var top_value = Math.min(scrollTop - offset.top, $(this).height() - floatingHeaderRow.height()) + topbar;
floatingHeaderRow.css("top", top_value + "px");
// Copy cell widths from original header
$("th", floatingHeaderRow).each(function(index) {
var cellWidth = $("th", originalHeaderRow).eq(index).css('width');
$(this).css('width', cellWidth);
});
// Copy row width from whole table
floatingHeaderRow.css("width", $(this).css("width"));
floatingHeaderRow.css("visibility", "visible");
floatingHeaderRow.css("z-index", "1000");
originalHeaderRow.css("height", "64px");
} else {
floatingHeaderRow.css("visibility", "hidden");
floatingHeaderRow.css("top", "0px");
}
});
}
$(function() {
$("table.tableWithFloatingHeader").each(function() {
$(this).wrap("<div class=\"divTableWithFloatingHeader\" style=\"position:relative\"></div>");
var originalHeaderRow = $("tr:first", this)
originalHeaderRow.before(originalHeaderRow.clone());
var clonedHeaderRow = $("tr:first", this)
clonedHeaderRow.addClass("tableFloatingHeader");
clonedHeaderRow.css("position", "absolute");
clonedHeaderRow.css("top", "0px");
clonedHeaderRow.css("left", $(this).css("margin-left"));
clonedHeaderRow.css("visibility", "hidden");
originalHeaderRow.addClass("tableFloatingHeaderOriginal");
});
UpdateTableHeaders();
$(window).scroll(UpdateTableHeaders);
$(window).resize(UpdateTableHeaders);
});
</script>
<form method="post" action="index.php?action=attendance_sheet_add&<?php echo api_get_cidreq().$param_filter; ?>&attendance_id=<?php echo $attendance_id; ?>" >
<div class="attendance-sheet-content" style="width:100%;background-color:#E1E1E1;margin-top:20px;">
<div class="divTableWithFloatingHeader attendance-users-table" style="width:45%;float:left;margin:0px;padding:0px;">
<table class="tableWithFloatingHeader table table-hover table-striped data_table" width="100%">
<thead>
<tr class="tableFloatingHeader" style="position: absolute; top: 0px; left: 0px; visibility: hidden; margin:0px;padding:0px" >
<th width="10px"><?php echo '#'; ?></th>
<th width="10px"><?php echo get_lang('Photo'); ?></th>
<th width="100px"><?php echo get_lang('LastName'); ?></th>
<th width="100px"><?php echo get_lang('FirstName'); ?></th>
<th width="100px"><?php echo get_lang('AttendancesFaults'); ?></th>
</tr>
<tr class="tableFloatingHeaderOriginal" >
<th width="10px"><?php echo '#'; ?></th>
<th width="10px"><?php echo get_lang('Photo'); ?></th>
<th width="150px"><?php echo get_lang('LastName'); ?></th>
<th width="140px"><?php echo get_lang('FirstName'); ?></th>
<th width="100px"><?php echo get_lang('AttendancesFaults'); ?></th>
</tr>
</thead>
<tbody>
<?php
$i = 1;
$class = '';
foreach ($users_in_course as $data) {
$faults = 0;
if ($i % 2 == 0) {
$class = 'row_odd';
} else {
$class = 'row_even';
}
$username = api_htmlentities(
sprintf(get_lang('LoginX'), $data['username']),
ENT_QUOTES
); ?>
<tr class="<?php echo $class; ?>">
<td><center><?php echo $i; ?></center></td>
<td><?php echo $data['photo']; ?></td>
<td><span title="<?php echo $username; ?>"><?php echo $data['lastname']; ?></span></td>
<td><?php echo $data['firstname']; ?></td>
<td>
<div class="attendance-faults-bar" style="background-color:<?php echo !empty($data['result_color_bar']) ? $data['result_color_bar'] : 'none'; ?>">
<?php echo $data['attendance_result']; ?>
</div>
</td>
</tr>
<?php
$i++;
} ?>
</tbody>
</table>
</div>
<?php
echo '<div class="divTableWithFloatingHeader attendance-calendar-table" style="margin:0px;padding:0px;float:left;width:55%;overflow:auto;overflow-y:hidden;">';
echo '<table class="tableWithFloatingHeader table table-hover table-striped data_table" width="100%">';
echo '<thead>';
$result = null;
if (count($attendant_calendar) > 0) {
foreach ($attendant_calendar as $calendar) {
$date = $calendar['date'];
$time = $calendar['time'];
$duration = !empty($calendar['duration']) ? get_lang('Duration').' : '.$calendar['duration'] : '';
$datetime = '<div class="grey">'.$date.' - '.$time.'</div>';
$img_lock = Display::return_icon(
'lock-closed.png',
get_lang('DateUnLock'),
['class' => 'img_lock', 'id' => 'datetime_column_'.$calendar['id']]
);
$iconFullScreen = '';
$iconBlocked = '';
if ($allowSignature) {
$iconFullScreen = Display::url(
Display::return_icon('view_fullscreen.png', get_lang('SeeForTablet'), [], ICON_SIZE_SMALL),
api_get_self().'?'.api_get_cidreq().'&action=attendance_sheet_list&func=fullscreen&attendance_id='.$attendance_id.'&calendar_id='.$calendar['id']
);
$isBlocked = 0;
$iconBlockName = 'eyes.png';
$iconBlockLabel = get_lang('DisableSignature');
if ((isset($calendar['blocked']) && 1 === (int) $calendar['blocked'])) {
$isBlocked = 1;
$iconBlockName = 'eyes-close.png';
$iconBlockLabel = get_lang('EnableSignature');
}
$iconBlocked = Display::url(
Display::return_icon($iconBlockName, $iconBlockLabel, [], ICON_SIZE_SMALL),
api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?'.api_get_cidreq().'&a=block_attendance_calendar&calendar_id='.$calendar['id'],
['class' => 'block-calendar']
);
}
if (!empty($calendar['done_attendance'])) {
$datetime = '<div class="blue">'.$date.' - '.$time.'</div>';
}
$disabled_check = 'disabled = "true"';
$input_hidden = '<input type="hidden" id="hidden_input_'.$calendar['id'].'" name="hidden_input[]" value="" disabled />';
if ($next_attendance_calendar_id == $calendar['id']) {
$input_hidden = '<input type="hidden" id="hidden_input_'.$calendar['id'].'" name="hidden_input[]" value="'.$calendar['id'].'" />';
$disabled_check = '';
$img_lock = Display::return_icon('lock-closed.png', get_lang('DateLock'), ['class' => 'img_unlock', 'id' => 'datetime_column_'.$calendar['id']]);
}
$result .= '<th>';
$result .= '<div class="date-attendance">'.$datetime.'&nbsp;';
$result .= $duration;
if (api_is_allowed_to_edit(null, true)) {
if (!empty($iconFullScreen)) {
$result .= '<span class="attendance-fullscreen">'.$iconFullScreen.'</span>&nbsp;';
}
if (!empty($iconBlocked)) {
$result .= '<span class="attendance-blocked">'.$iconBlocked.'</span>&nbsp;';
}
$result .= '<span class="attendance_lock" style="cursor:pointer">'.(!$is_locked_attendance || api_is_platform_admin() ? $img_lock : '').'</span>';
}
if ($is_locked_attendance == false) {
if (api_is_allowed_to_edit(null, true)) {
$result .= '<input type="checkbox" class="checkbox_head_'.$calendar['id'].'" id="checkbox_head_'.$calendar['id'].'" '.$disabled_check.' checked="checked" />'.$input_hidden.'</div></th>';
}
}
}
} else {
$result = '<th width="2000px"><span><a href="index.php?'.api_get_cidreq().'&action=calendar_list&attendance_id='.$attendance_id.'">';
$result .= Display::return_icon('attendance_calendar.png', get_lang('AttendanceCalendar'), '', ICON_SIZE_MEDIUM).' '.get_lang('GoToAttendanceCalendar').'</a></span></th>';
}
echo '<tr class="tableFloatingHeader row_odd" style="position: absolute; top: 0px; left: 0px; visibility: hidden; margin:0px;padding:0px">';
echo $result;
echo '</tr>';
echo '<tr class="tableWithFloatingHeader row_odd tableFloatingHeaderOriginal">';
echo $result;
echo '</tr>';
echo '</thead>';
echo '<tbody>';
$i = 0;
foreach ($users_in_course as $user) {
$class = '';
if ($i % 2 == 0) {
$class = 'row_even';
} else {
$class = 'row_odd';
}
echo '<tr class="'.$class.'">';
if (count($attendant_calendar) > 0) {
foreach ($attendant_calendar as $calendar) {
$checked = 'checked';
$presence = -1;
if (isset($users_presence[$user['user_id']][$calendar['id']]['presence'])) {
$presence = $users_presence[$user['user_id']][$calendar['id']]['presence'];
if (intval($presence) == 1) {
$checked = 'checked';
} else {
$checked = '';
}
} else {
//if the user wasn't registered at that time, consider unchecked
if ($next_attendance_calendar_datetime == 0 ||
$calendar['date_time'] < $next_attendance_calendar_datetime
) {
$checked = '';
}
}
$disabled = 'disabled';
$style_td = '';
if ($next_attendance_calendar_id == $calendar['id']) {
if ($i % 2 == 0) {
$style_td = 'background-color:#eee;';
} else {
$style_td = 'background-color:#dcdcdc;';
}
$disabled = '';
}
$signed = false;
if ($allowSignature) {
$attendance = new Attendance();
$signature = $attendance->getSignature($user['user_id'], $calendar['id']);
$signed = !empty($signature);
}
echo '<td style="'.$style_td.'" class="checkboxes_col_'.$calendar['id'].'">';
echo '<div class="check">';
$commentBtnIcon = '';
if ($allowComment) {
$commentBtnIcon = '&nbsp;&nbsp;<a id="comment-'.$user['user_id'].'-'.$calendar['id'].'" title="'.get_lang('Comment').'" class="attendance-comment" href="javascript:void(0)">
<em class="fa fa-commenting-o" style="font-size: 24px;"></em>
</a>';
}
if (api_is_allowed_to_edit(null, true)) {
if (!$is_locked_attendance || api_is_platform_admin()) {
if ($allowSignature) {
if ($signed) {
echo Display::return_icon('checkbox_on.png', get_lang('Presence'), null, ICON_SIZE_TINY);
echo '<input type="hidden" name="check_presence['.$calendar['id'].'][]" value="'.$user['user_id'].'" />';
echo $commentBtnIcon;
echo '&nbsp;<a id="sign-'.$user['user_id'].'-'.$calendar['id'].'" title="'.get_lang('SignView').'" class="attendance-sign-view" href="javascript:void(0)">
<em class="fa fa-search" style="font-size: 24px;"></em>
</a>';
} else {
echo '<input type="checkbox" name="check_presence['.$calendar['id'].'][]" value="'.$user['user_id'].'" '.$disabled.' '.$checked.' />';
echo '<span class="anchor_'.$calendar['id'].'"></span>';
echo $commentBtnIcon;
echo '&nbsp;<a id="sign-'.$user['user_id'].'-'.$calendar['id'].'" title="'.get_lang('Sign').'" class="attendance-sign" href="javascript:void(0)">
<em class="fa fa-pencil" style="font-size: 24px;"></em>
</a>';
}
} else {
echo '<input type="checkbox" name="check_presence['.$calendar['id'].'][]" value="'.$user['user_id'].'" '.$disabled.' '.$checked.' />';
echo '<span class="anchor_'.$calendar['id'].'"></span>';
echo $commentBtnIcon;
}
} else {
echo $presence ? Display::return_icon('checkbox_on.png', get_lang('Presence'), null, ICON_SIZE_TINY) : Display::return_icon('checkbox_off.png', get_lang('Presence'), null, ICON_SIZE_TINY);
}
} else {
switch ($presence) {
case 1:
echo Display::return_icon('accept.png', get_lang('Attended'));
break;
case 0:
echo Display::return_icon('exclamation.png', get_lang('NotAttended'));
break;
case -1:
//echo Display::return_icon('warning.png',get_lang('NotAttended'));
break;
}
}
echo '</div>';
echo '</td>';
}
} else {
$calendarClass = null;
if (isset($calendar)) {
$calendarClass = "checkboxes_col_".$calendar['id'];
}
echo '<td class="'.$calendarClass.'">';
echo '<div>';
echo '<center>&nbsp;</center>
</div>
</td>';
}
echo '</tr>';
$i++;
}
echo '</tbody></table>';
echo '</div></div>'; ?>
<div class="row">
<div class="col-md-12">
<?php if (!$is_locked_attendance || api_is_platform_admin()) {
if (api_is_allowed_to_edit(null, true)) {
?>
<button type="submit" class="btn btn-primary"><?php echo get_lang('Save'); ?></button>
<?php
}
} ?>
</div>
</div>
<input type="hidden" name="sec_token" value="<?php echo $token; ?>" />
</form>
<?php
} else {
echo Display::return_message(
'<a href="'.api_get_path(WEB_CODE_PATH).'user/user.php?'.api_get_cidreq().'">'.
get_lang('ThereAreNoRegisteredLearnersInsidetheCourse').'</a>',
'warning',
false
);
}
} else {
echo Display::page_header(get_lang('AttendanceSheetReport'));
// View for students?>
<?php if (!empty($users_presence)) {
?>
<div>
<table width="250px;">
<tr>
<td><?php echo get_lang('ToAttend').': '; ?></td>
<td>
<center><div class="attendance-faults-bar" style="background-color:<?php echo !empty($faults['color_bar']) ? $faults['color_bar'] : 'none'; ?>">
<?php echo $faults['faults'].'/'.$faults['total'].' ('.$faults['faults_porcent'].'%)'; ?></div></center>
</td>
</tr>
</table>
</div>
<?php
} ?>
<table class="table table-hover table-striped data_table">
<tr class="row_odd" >
<th><?php echo get_lang('Attendance'); ?></th>
</tr>
<?php
if (!empty($users_presence)) {
$i = 0;
foreach ($users_presence[$user_id] as $presence) {
$duration = !empty($presence['duration']) ? get_lang('Duration').' : '.$presence['duration'] : '';
$signed = false;
if ($allowSignature) {
$attendance = new Attendance();
$isBlocked = $attendance->isCalendarBlocked($presence['calendar_id']);
// if calendar is blocked by admin is it not displayed here.
if ($isBlocked) {
continue;
}
if (!empty($_REQUEST['filter']) && is_numeric($_REQUEST['filter']) && $_REQUEST['filter'] != $presence['calendar_id']) {
continue;
}
$signature = $attendance->getSignature($user_id, $presence['calendar_id']);
$signed = !empty($signature);
}
$class = '';
if ($i % 2 == 0) {
$class = 'row_even';
} else {
$class = 'row_odd';
} ?>
<tr class="<?php echo $class; ?>">
<td>
<?php echo $presence['presence'] ? Display::return_icon('checkbox_on.png', get_lang('Presence'), null, ICON_SIZE_TINY) : Display::return_icon('checkbox_off.png', get_lang('Presence'), null, ICON_SIZE_TINY); ?>
<?php echo "&nbsp; ".$presence['date_time']; ?>
<?php echo "&nbsp; ".$duration; ?>
<?php
if ($allowSignature) {
if ($signed) {
echo '<span class="list-data">
<a id="sign-'.$user_id.'-'.$presence['calendar_id'].'" class="btn btn-primary attendance-sign-view" href="javascript:void(0)">
<em class="fa fa-search"></em> '.get_lang('SignView').'
</a>
</span>';
} else {
if ($presence['presence']) {
echo '<span class="list-data">
<a id="sign-'.$user_id.'-'.$presence['calendar_id'].'" class="btn btn-primary attendance-sign" href="javascript:void(0)">
<em class="fa fa-pencil"></em> '.get_lang('Sign').'
</a>
</span>';
}
}
} ?>
</td>
</tr>
<?php
}
} else {
?>
<tr><td>
<center><?php echo get_lang('YouDoNotHaveDoneAttendances'); ?></center></td>
</tr>
<?php
} ?>
</table>
<?php
}
if ($allowSignature) {
include_once 'attendance_signature.inc.php';
}
if ($allowComment) {
include_once 'attendance_comment.inc.php';
}

View File

@@ -0,0 +1,109 @@
<header id="cm-header">
<!-- Topbar -->
<div class="container">
<div class="row">
<div class="col-xs-12 col-md-3">
<div class="logo">
<a href="<?php echo api_get_path(WEB_PATH); ?>"><?php echo return_logo(); ?></a>
</div>
</div>
<div class="col-xs-12 col-md-9">
<div class="row">
<div class="col-sm-4">
</div>
<div class="col-sm-3">
</div>
<div class="col-sm-5">
<ol class="header-ol">
<?php echo returnNotificationMenu(); ?>
</ol>
</div>
</div>
</div>
</div>
</div>
<!-- Fixed navbar -->
<nav class="navbar navbar-default"></nav>
<div class="nav-tools">
</div>
</header>
<div class="container-fluid">
<h2><?php echo Display::page_header(get_lang('AttendanceSheetReport')); ?></h2>
<h3><?php echo $attendanceName; ?> <span class="label label-default"><?php echo $attendanceCalendar['date']; ?></span></h3>
<div class="well mt-2">
<p><?php echo get_lang('Course').' : '.$courseName; ?></p>
<p><?php echo get_lang('Trainer').' : '.$trainer; ?></p>
</div>
<?php if (!empty($users_in_course)) { ?>
<div class="input-group">
<input type="text" id="search-user" onkeyup="searchUser()" />
</div>
<form method="post" action="index.php?action=attendance_sheet_add&<?php echo api_get_cidreq().$param_filter; ?>&attendance_id=<?php echo $attendance_id; ?>" >
<table id="table-user-calendar" class="table table-hover">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($users_in_course as $user) {
$attendance = new Attendance();
$signature = $attendance->getSignature($user['user_id'], $calendarId);
$signed = !empty($signature);
$isBlocked = $attendance->isCalendarBlocked($calendarId); ?>
<tr>
<td>
<?php
if ($signed) {
echo Display::return_icon('checkbox_on.png', get_lang('Presence'), null, ICON_SIZE_TINY);
} else {
echo Display::return_icon('checkbox_off.png', get_lang('Presence'), null, ICON_SIZE_TINY);
} ?>
</td>
<td><?php echo api_get_person_name($user['firstname'], $user['lastname']); ?></td>
<td>
<?php
if (!$isBlocked) {
if ($signed) {
echo '<div class="list-data">
<span class="item"></span>
<a id="sign-'.$user['user_id'].'-'.$calendarId.'" class="btn btn-primary attendance-sign-view" href="javascript:void(0)">
<em class="fa fa-search"></em> '.get_lang('SignView').'
</a>
</div>';
} else {
echo '<input type="hidden" name="check_presence['.$calendarId.'][]" value="'.$user['user_id'].'" />';
echo '<div class="list-data">
<span class="item"></span>
<a id="sign-'.$user['user_id'].'-'.$calendarId.'" class="btn btn-primary attendance-sign" href="javascript:void(0)">
<em class="fa fa-pencil"></em> '.get_lang('Sign').'
</a>
</div>';
}
} ?>
</td>
</tr>
<?php
} ?>
</tbody>
</table>
</form>
<?php } ?>
</div>
<?php
if ($allowSignature) {
include_once 'attendance_signature.inc.php';
}

View File

@@ -0,0 +1,188 @@
<div id="sign_popup" style="display: none">
<div id="signature_area" class="well">
<canvas width="400px"></canvas>
</div>
<span id="save_controls">
<button id="sign_popup_save" class="btn btn-primary" type="submit">
<em class="fa fa-save"></em> <?php echo get_lang('Save'); ?>
</button>
<button id="sign_popup_clean" class="btn btn-default" type="submit">
<em class="fa fa-eraser"></em> <?php echo get_lang('Clean'); ?>
</button>
</span>
<span id="remove_controls" clase="hidden">
<button id="sign_popup_remove" class="btn btn-danger" type="submit">
<em class="fa fa-remove"></em> <?php echo get_lang('Remove'); ?>
</button>
</span>
<span id="close_controls" style="display: none">
<span id="sign_results"></span>
<hr />
<button id="sign_popup_close" class="btn btn-default" type="submit">
<?php echo get_lang('Close'); ?>
</button>
</span>
<span class="loading" style="display: none"><em class="fa fa-spinner"></em></span>
<input type="hidden" id="sign-selected" />
</div>
<script>
var imageFormat = 'image/png';
var canvas = document.querySelector("#signature_area canvas");
var signaturePad = new SignaturePad(canvas);
var urlAjax = "<?php echo api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?'.api_get_cidreq(); ?>";
var attendance_id = "<?php echo $attendance_id; ?>";
$(function() {
$("#sign_popup_close").on("click", function() {
$("#sign_popup").dialog("close");
$('#loading').hide();
$('#save_controls').show();
$('#close_controls').hide();
$('#signature_area').show();
});
$("#sign_popup_clean").on("click", function() {
signaturePad.clear();
});
$("#sign_popup_remove").on("click", function() {
var selected = $("#sign-selected").val();
$.ajax({
beforeSend: function(result) {
$('#loading').show();
},
type: "POST",
url: urlAjax,
data: "a=remove_attendance_sign&selected="+selected+"&attendance_id="+attendance_id,
success: function(data) {
location.reload();
},
});
});
$("#sign_popup_save").on("click", function() {
if (signaturePad.isEmpty()) {
alert('<?php echo get_lang('ProvideASignatureFirst'); ?>');
return false;
}
var selected = $("#sign-selected").val();
var dataURL = signaturePad.toDataURL(imageFormat);
$.ajax({
beforeSend: function(result) {
$('#loading').show();
},
type: "POST",
url: urlAjax,
data: "a=sign_attendance&selected="+selected+"&file="+dataURL+"&attendance_id="+attendance_id,
success: function(data) {
$('#loading').hide();
$('#save_controls').hide();
$('#close_controls').show();
$('#signature_area').hide();
signaturePad.clear();
if (1 == data) {
$('#sign_results').html('<?php echo get_lang('Saved'); ?>');
} else {
$('#sign_results').html('<?php echo get_lang('Error'); ?>');
}
$('#sign_popup_close').hide();
location.reload();
},
});
});
$(".attendance-sign").on("click", function() {
$("#sign-selected").val($(this).attr("id"));
$("#sign_popup").dialog({
autoOpen: false,
width: 500,
height: 'auto',
close: function(){
}
});
$("#sign_popup").dialog("open");
$("#save_controls").show();
$("#remove_controls").hide();
$('#signature_area').show();
$('#signature_area').html("<canvas width='400px'></canvas>");
canvas = document.querySelector("#signature_area canvas");
signaturePad = new SignaturePad(canvas);
});
$(".attendance-sign-view").on("click", function() {
var selected = $(this).attr("id");
$('#loading').show();
$.ajax({
beforeSend: function(result) {
$('#signature_area').html("<em class='fa fa-spinner'></em>");
},
type: "POST",
url: urlAjax,
data: "a=get_attendance_sign&selected="+selected,
success: function(sign) {
$('#loading').hide();
$('#signature_area').show();
$('#signature_area').html("<img src='"+sign+"' />");
},
});
$("#sign_popup").dialog({
autoOpen: false,
width: 500,
height: 'auto',
close: function(){
}
});
$("#sign-selected").val(selected);
$("#sign_popup").dialog("open");
$("#save_controls").hide();
$("#remove_controls").show();
});
$(".block-calendar").on("click", function(e) {
e.preventDefault();
var urlAjax = $(this).attr("href");
var imgBlocked = $(this).find("img");
var srcImg = imgBlocked.attr("src");
$.ajax({
type: "POST",
url: urlAjax,
success: function(data) {
if (1 == data) {
var newSrcImg = srcImg.replace("eyes.png", "eyes-close.png");
imgBlocked.attr("src", newSrcImg);
imgBlocked.attr("title", "<?php echo get_lang('EnableSignature'); ?>");
} else {
var newSrcImg = srcImg.replace("eyes-close.png", "eyes.png");
imgBlocked.attr("src", newSrcImg);
imgBlocked.attr("title", "<?php echo get_lang('DisableSignature'); ?>");
}
},
});
});
});
function searchUser() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("search-user");
filter = input.value.toUpperCase();
table = document.getElementById("table-user-calendar");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don\'t match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>

View File

@@ -0,0 +1,10 @@
<?php
/* For licensing terms, see /license.txt */
// See AttendanceController::calendarLogins function
echo '<div class="actions">';
echo '<a href="index.php?'.api_get_cidreq().'&action=calendar_list">'.
Display::return_icon('back.png', get_lang('AttendanceCalendar'), '', ICON_SIZE_MEDIUM).'</a>';
echo '</div>';
echo $form;
echo $table;

417
main/attendance/index.php Normal file
View File

@@ -0,0 +1,417 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Template (front controller in MVC pattern) used for dispatching
* to the controllers depend on the current action.
*
* @author Christian Fasanando <christian1827@gmail.com>
* @author Julio Montoya <gugli100@gmail.com> Bug fixing, sql improvements
*
* @package chamilo.attendance
*/
require_once __DIR__.'/../inc/global.inc.php';
require_once 'attendance_controller.php';
require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/fe/exportgradebook.php';
$current_course_tool = TOOL_ATTENDANCE;
// current section
$this_section = SECTION_COURSES;
// protect a course script
api_protect_course_script(true);
// Get actions
$actions = [
'attendance_list',
'attendance_sheet_list',
'attendance_sheet_add',
'attendance_add',
'attendance_edit',
'attendance_delete',
'attendance_delete_select',
'attendance_set_invisible',
'attendance_set_invisible_select',
'attendance_set_visible',
'attendance_set_visible_select',
'attendance_restore',
'attendance_sheet_export_to_pdf',
'attendance_sheet_export_to_xls',
'attendance_sheet_list_no_edit',
'calendar_logins',
'lock_attendance',
'unlock_attendance',
'attendance_sheet_qrcode',
];
$actions_calendar = [
'calendar_list',
'calendar_add',
'calendar_edit',
'calendar_delete',
'calendar_all_delete',
];
$action = 'attendance_list';
$course_id = '';
if (isset($_GET['cidReq'])) {
$course_id = $_GET['cidReq'];
}
if (isset($_GET['action']) &&
(in_array($_GET['action'], $actions) || in_array($_GET['action'], $actions_calendar))
) {
$action = $_GET['action'];
}
if (isset($_GET['isStudentView']) && $_GET['isStudentView'] == 'true') {
$action = 'attendance_list';
}
// get attendance id
$attendance_id = 0;
if (isset($_GET['attendance_id'])) {
$attendance_id = intval($_GET['attendance_id']);
}
// get calendar id
$calendar_id = '';
if (isset($_GET['calendar_id'])) {
$calendar_id = intval($_GET['calendar_id']);
}
// instance attendance object for using like library here
$attendance = new Attendance();
// attendance controller object
$attendanceController = new AttendanceController();
$attendance_data = [];
// get attendance data
if (!empty($attendance_id)) {
// attendance data by id
$attendance_data = $attendance->get_attendance_by_id($attendance_id);
}
$htmlHeadXtra[] = '<script>
$(function() {
$("table th .attendance_lock img").click(function() {
var col_id = this.id;
var col_split = col_id.split("_");
var calendar_id = col_split[2];
var class_img = $(this).attr("class");
if (class_img == "img_unlock") {
//lock
$(".checkbox_head_"+calendar_id).attr("disabled", true);
$(".row_odd td.checkboxes_col_"+calendar_id).css({
"opacity":"1",
"background-color":"#F9F9F9",
"border-left":"none",
"border-right":"none"
});
$(".row_even td.checkboxes_col_"+calendar_id).css({
"opacity":"1","background-color":"#FFF", "border-left":"none","border-right":"none"
});
$(".checkboxes_col_"+calendar_id+" input:checkbox").attr("disabled",true);
$(this).attr("src","'.Display::returnIconPath('lock-closed.png').'");
$(this).attr("title","'.get_lang('DateUnLock').'");
$(this).attr("alt","'.get_lang('DateUnLock').'");
$(this).attr("class","img_lock");
$("#hidden_input_"+calendar_id).attr("value","");
$("#hidden_input_"+calendar_id).attr("disabled",true);
return false;
} else {
//Unlock
$(".checkbox_head_"+calendar_id).attr("disabled", false);
$(".checkbox_head_"+calendar_id).removeAttr("disabled");
$(".row_odd td.checkboxes_col_"+calendar_id).css({
"opacity":"1",
"background-color":"#dcdcdc",
"border-left":"1px #bbb solid",
"border-right":"1px #bbb solid",
"z-index":"1"
});
$(".row_even td.checkboxes_col_"+calendar_id).css({
"opacity":"1",
"background-color":"#eee",
"border-left":"1px #bbb solid",
"border-right":"1px #bbb solid",
"z-index":"1"
});
$(".checkboxes_col_"+calendar_id).mouseover(function() {
//$(".checkbox_head_"+calendar_id).removeAttr("opacity");
//$("row_even td.checkboxes_col_"+calendar_id).css({"opacity":"1","background-color":"red", "border-left":"1px #EEEE00 solid", "border-right":"1px #EEEE00 solid" , "border-bottom":"1px #ccc solid" });
//$("row_odd td.checkboxes_col_"+calendar_id).css({"opacity":"1","background-color":"#FFF", "border-left":"1px #EEEE00 solid", "border-right":"1px #EEEE00 solid" , "border-bottom":"1px #ccc solid" });
});
$(".checkboxes_col_"+calendar_id).mouseout(function() {
// $("row_even td.checkboxes_col_"+calendar_id).css({"opacity":"1","background-color":"#F9F9F9", "border-left":"1px #EEEE00 solid", "border-right":"1px #EEEE00 solid" , "border-bottom":"1px #ccc solid" });
// $("row_odd td.checkboxes_col_"+calendar_id).css({"opacity":"1","background-color":"#FFF", "border-left":"1px #EEEE00 solid", "border-right":"1px #EEEE00 solid" , "border-bottom":"1px #ccc solid" });
});
$(".checkboxes_col_"+calendar_id+" input:checkbox").attr("disabled",false);
$(this).attr("src","'.Display::returnIconPath('lock-open.png').'");
$(this).attr("title","'.get_lang('DateLock').'");
$(this).attr("alt","'.get_lang('DateLock').'");
$(this).attr("class","img_unlock");
$("#hidden_input_"+calendar_id).attr("disabled",false);
$("#hidden_input_"+calendar_id).attr("value",calendar_id);
return false;
}
});
$("table th input:checkbox").click(function() {
var col_id = this.id;
var col_split = col_id.split("_");
var calendar_id = col_split[2];
if (this.checked) {
$(".checkboxes_col_"+calendar_id+" input:checkbox").prop("checked",true);
$(".checkboxes_col_"+calendar_id+"").addClass("row_selected");
} else {
$(".checkboxes_col_"+calendar_id+" input:checkbox").prop("checked",false);
$(".checkboxes_col_"+calendar_id+"").removeClass("row_selected");
}
});
$(".attendance-sheet-content .row_odd, .attendance-sheet-content .row_even").mouseover(function() {
$(".row_odd").css({"background-color":"#F9F9F9"});
$(".row_even").css({"background-color":"#FFF"});
});
$(".attendance-sheet-content .row_odd, .attendance-sheet-content .row_even").mouseout(function() {
$(".row_odd").css({"background-color":"#F9F9F9"});
$(".row_even").css({"background-color":"#FFF"});
});
});
</script>';
$allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
if ($allowSignature) {
$htmlHeadXtra[] = api_get_asset('signature_pad/signature_pad.umd.js');
$htmlHeadXtra[] = '<style>
#search-user {
background-image: url("/main/img/icons/22/sn-search.png");
background-position: 10px 12px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin: 12px 0px;
}
</style>';
}
$student_param = '';
$student_id = null;
if (api_is_drh() && isset($_GET['student_id'])) {
$student_id = intval($_GET['student_id']);
$student_param = '&student_id='.$student_id;
$student_info = api_get_user_info($student_id);
$interbreadcrumb[] = [
'url' => api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?student='.$student_id,
'name' => $student_info['complete_name'],
];
}
if (api_is_in_gradebook()) {
$interbreadcrumb[] = [
'url' => api_get_path(WEB_CODE_PATH).'gradebook/index.php?'.api_get_cidreq(),
'name' => get_lang('ToolGradebook'),
];
}
$interbreadcrumb[] = [
'url' => 'index.php?'.api_get_cidreq().'&action=attendance_list&'.$student_param,
'name' => get_lang('ToolAttendance'),
];
if ($action == 'attendance_add') {
$interbreadcrumb[] = ['url' => '#', 'name' => get_lang('CreateANewAttendance')];
}
if ($action == 'attendance_edit') {
$interbreadcrumb[] = ['url' => '#', 'name' => get_lang('Edit')];
}
if ($action == 'attendance_sheet_list' || $action == 'attendance_sheet_add') {
$interbreadcrumb[] = ['url' => '#', 'name' => $attendance_data['name']];
}
if ($action == 'calendar_list' || $action == 'calendar_edit' || $action == 'calendar_delete' ||
$action == 'calendar_all_delete'
) {
$interbreadcrumb[] = [
'url' => 'index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance_id,
'name' => $attendance_data['name'],
];
$interbreadcrumb[] = ['url' => '#', 'name' => get_lang('AttendanceCalendar')];
}
if ($action == 'calendar_add') {
$interbreadcrumb[] = [
'url' => 'index.php?'.api_get_cidreq().'&action=attendance_sheet_list&attendance_id='.$attendance_id,
'name' => $attendance_data['name'],
];
$interbreadcrumb[] = ['url' => '#', 'name' => get_lang('AddDateAndTime')];
}
$allowToEdit = api_is_allowed_to_edit(null, true);
// Delete selected attendance
if (isset($_POST['action']) && $_POST['action'] == 'attendance_delete_select' && $allowToEdit) {
$attendanceController->attendance_delete($_POST['id']);
}
if (isset($_POST['action']) && $_POST['action'] == 'attendance_set_invisible_select' && $allowToEdit) {
$attendanceController->attendanceSetInvisible($_POST['id']);
}
if (isset($_POST['action']) && $_POST['action'] == 'attendance_set_visible_select' && $allowToEdit) {
$attendanceController->attendanceSetVisible($_POST['id']);
}
switch ($action) {
case 'attendance_sheet_qrcode':
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
$renderer = new \BaconQrCode\Renderer\Image\Png();
$renderer->setHeight(256);
$renderer->setWidth(256);
$writer = new \BaconQrCode\Writer($renderer);
$filter = "";
if (!empty($_REQUEST['filter'])) {
$filter = '&filter='.$_REQUEST['filter'];
}
$attendanceSheetLink = api_get_path(WEB_CODE_PATH).'attendance/index.php?'.api_get_cidreq().'&action=attendance_sheet_list_no_edit&attendance_id='.$attendance_id.$filter;
$filename = "attendanceqrcode".uniqid().".png";
if (!is_dir(api_get_path(SYS_UPLOAD_PATH).'attendance')) {
@mkdir(
api_get_path(SYS_UPLOAD_PATH).'attendance',
api_get_permissions_for_new_directories(),
true
);
}
$writer->writeFile($attendanceSheetLink, api_get_path(SYS_UPLOAD_PATH).'attendance/'.$filename);
echo '<img src="'.api_get_path(WEB_UPLOAD_PATH).'attendance/'.$filename.'" alt="AttendanceQR">';
exit;
case 'attendance_list':
$attendanceController->attendance_list();
break;
case 'attendance_add':
if ($allowToEdit) {
$attendanceController->attendance_add();
} else {
api_not_allowed(true);
}
break;
case 'attendance_edit':
if ($allowToEdit) {
$attendanceController->attendance_edit($attendance_id);
} else {
api_not_allowed(true);
}
break;
case 'attendance_delete':
if ($allowToEdit) {
$attendanceController->attendance_delete($attendance_id);
Display::addFlash(Display::return_message(get_lang('Deleted')));
} else {
api_not_allowed(true);
}
break;
case 'attendance_set_invisible':
if ($allowToEdit) {
$attendanceController->attendanceSetInvisible($attendance_id);
} else {
api_not_allowed(true);
}
break;
case 'attendance_set_visible':
if ($allowToEdit) {
$attendanceController->attendanceSetVisible($attendance_id);
} else {
api_not_allowed(true);
}
break;
/*case 'attendance_restore':
if ($allowToEdit) {
$attendanceController->attendance_restore($attendance_id);
} else {
api_not_allowed(true);
}
break;*/
case 'attendance_sheet_list':
$attendanceController->attendance_sheet(
$action,
$attendance_id,
$student_id,
true
);
break;
case 'attendance_sheet_list_no_edit':
$attendanceController->attendance_sheet(
$action,
$attendance_id,
$student_id,
false
);
break;
case 'attendance_sheet_export_to_pdf':
$attendanceController->attendance_sheet_export_to_pdf(
$action,
$attendance_id,
$student_id,
$course_id
);
break;
case 'attendance_sheet_export_to_xls':
$groupId = isset($_REQUEST['group_id']) ? (int) $_REQUEST['group_id'] : null;
$filter = isset($_REQUEST['filter']) ? $_REQUEST['filter'] : null;
$attendanceController->attendanceSheetExportToXls(
$attendance_id,
(int) $student_id,
(string) $course_id,
$groupId,
$filter
);
break;
case 'attendance_sheet_add':
if ($allowToEdit) {
$attendanceController->attendance_sheet($action, $attendance_id);
} else {
api_not_allowed(true);
}
break;
case 'lock_attendance':
case 'unlock_attendance':
if ($allowToEdit) {
$attendanceController->lock_attendance($action, $attendance_id);
} else {
api_not_allowed(true);
}
break;
case 'calendar_add':
case 'calendar_edit':
case 'calendar_all_delete':
case 'calendar_delete':
if (!$allowToEdit) {
api_not_allowed(true);
}
//no break
case 'calendar_list':
$attendanceController->attendance_calendar(
$action,
$attendance_id,
$calendar_id
);
break;
case 'calendar_logins':
if (api_is_course_admin() || api_is_drh()) {
$attendanceController->getAttendanceBaseInLogin(false, true);
}
break;
default:
$attendanceController->attendance_list();
}

View File

@@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Layout (principal view) used for structuring other views.
*
* @author Christian Fasanando <christian1827@gmail.com>
*
* @package chamilo.attendace
*/
// protect a course script
api_protect_course_script(true);
// Header
$tool = TOOL_ATTENDANCE;
$func = isset($_REQUEST['func']) ? $_REQUEST['func'] : null;
if ('fullscreen' === $func) {
$htmlHeadXtra[] = api_get_css_asset('bootstrap/dist/css/bootstrap.min.css');
Display::display_reduced_header();
} else {
Display::display_header('');
}
// Introduction section
Display::display_introduction_section($tool);
// Tracking
Event::event_access_tool($tool);
// Display
echo $content;
// Footer
if ('fullscreen' === $func) {
Display::display_reduced_footer();
} else {
Display::display_footer();
}

View File

@@ -0,0 +1,85 @@
<?php
/* For licensing terms, see /license.txt */
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
if (!api_get_configuration_value('show_missing_signatures_page') || !api_get_configuration_value('enable_sign_attendance_sheet')) {
api_not_allowed(true);
}
api_block_anonymous_users();
$htmlHeadXtra[] = api_get_asset('signature_pad/signature_pad.umd.js');
$htmlHeadXtra[] = '<style>
#search-user {
background-image: url("/main/img/icons/22/sn-search.png");
background-position: 10px 12px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin: 12px 0px;
}
#main_content ul {
list-style-type: none;
height : 180px;
}
#main_content li {
float : left;
position : relative;
width : 190px;
height : 150px;
border-radius : 10px;
border : 1px solid gray;
background-color : #F9E79F;
margin : 10px;
padding : 10px;
}
#main_content li a{
position : absolute;
bottom : 10px;
left : 10%;
width : 80%;
}
</style>';
$userId = api_get_user_id();
//$courses = CourseManager::get_courses_list_by_user_id($userId, true);
$tbl_attendance_sheet = Database::get_course_table(TABLE_ATTENDANCE_SHEET);
$tbl_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
//$sql = "select * from c_attendance_sheet where user_id = ". $userId . " and presence = 1 and signature IS NULL order by c_id";
$sql = "SELECT cal.c_id as courseId, course.title as courseTitle, cal.date_time as date_time, cal.iid as calendarId
FROM $tbl_attendance_sheet att
INNER JOIN $tbl_attendance_calendar cal
ON cal.id = att.attendance_calendar_id
INNER JOIN $tbl_course course
ON cal.c_id = course.id
WHERE
att.presence = 1 AND
att.signature IS NULL AND
att.user_id = '$userId'
ORDER BY cal.c_id";
$result = Database::query($sql);
$calendars = Database::store_result($result);
$presences = [];
foreach ($calendars as $calendar) {
$presences[$calendar['courseId']]['title'] = $calendar['courseTitle'];
$presences[$calendar['courseId']]['calendars'][$calendar['calendarId']]['buttonToSign'] = "<span class=\"list-data\"><a id=\"sign-".$userId."-".$calendar['calendarId']."-".$calendar['courseId']."\" class=\"btn btn-primary attendance-sign\" href=\"javascript:void(0)\"><em class=\"fa fa-pencil\"></em>".get_lang('Sign')."</a></span>";
$presences[$calendar['courseId']]['calendars'][$calendar['calendarId']]['date_time'] = api_convert_and_format_date($calendar['date_time'], null, date_default_timezone_get());
}
$template = new Template(get_lang('MyMissingSignatures'));
$template->assign('presences', $presences);
$content = $template->fetch($template->get_template('/attendance/my_missing_signatures.tpl'));
$template->assign('content', $content);
$template->display_one_col_template();
include_once 'attendance_signature.inc.php';