swad-core/swad_attendance.c

3288 lines
110 KiB
C
Raw Normal View History

2014-12-01 23:55:08 +01:00
// swad_attendance.c: control of attendance
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2023 Antonio Ca<EFBFBD>as Vargas
2014-12-01 23:55:08 +01:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************** Headers **********************************/
/*****************************************************************************/
2019-11-01 22:53:39 +01:00
#define _GNU_SOURCE // For asprintf
2014-12-01 23:55:08 +01:00
#include <linux/limits.h> // For PATH_MAX
#include <mysql/mysql.h> // To access MySQL databases
2019-12-29 12:39:00 +01:00
#include <stddef.h> // For NULL
2019-11-01 22:53:39 +01:00
#include <stdio.h> // For asprintf
2014-12-01 23:55:08 +01:00
#include <stdlib.h> // For calloc
#include <string.h> // For string functions
#include "swad_action_list.h"
2014-12-01 23:55:08 +01:00
#include "swad_attendance.h"
#include "swad_attendance_database.h"
#include "swad_autolink.h"
2017-06-10 21:38:10 +02:00
#include "swad_box.h"
2014-12-01 23:55:08 +01:00
#include "swad_database.h"
#include "swad_error.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
#include "swad_group.h"
#include "swad_group_database.h"
#include "swad_hierarchy_level.h"
2019-10-23 19:05:05 +02:00
#include "swad_HTML.h"
2014-12-01 23:55:08 +01:00
#include "swad_ID.h"
#include "swad_pagination.h"
#include "swad_parameter.h"
#include "swad_photo.h"
#include "swad_QR.h"
#include "swad_resource.h"
2019-03-26 11:53:21 +01:00
#include "swad_setting.h"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*************** External global variables from others modules ***************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/****************************** Private constants ****************************/
/*****************************************************************************/
2018-10-18 16:56:07 +02:00
#define Att_ATTENDANCE_TABLE_ID "att_table"
#define Att_ATTENDANCE_DETAILS_ID "att_details"
2018-10-18 11:29:02 +02:00
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/******************************** Private types ******************************/
/*****************************************************************************/
2015-11-13 01:27:44 +01:00
typedef enum
{
2019-11-14 17:53:50 +01:00
Att_VIEW_ONLY_ME, // View only me
Att_VIEW_SEL_USR, // View selected users
Att_PRNT_ONLY_ME, // Print only me
Att_PRNT_SEL_USR, // Print selected users
2015-11-13 01:27:44 +01:00
} Att_TypeOfView_t;
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/****************************** Private prototypes ***************************/
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
static void Att_ResetEvents (struct Att_Events *Events);
static void Att_ShowAllEvents (struct Att_Events *Events);
static void Att_ParsWhichGroupsToShow (void *Events);
static void Att_PutIconsInListOfEvents (void *Events);
static void Att_PutIconToCreateNewEvent (struct Att_Events *Events);
static void Att_PutButtonToCreateNewEvent (struct Att_Events *Events);
static void Att_PutParsToCreateNewEvent (void *Events);
static void Att_PutParsToListUsrsAttendance (void *Events);
2019-12-06 22:49:45 +01:00
static void Att_ShowOneEventRow (struct Att_Events *Events,
bool ShowOnlyThisAttEventComplete);
static void Att_WriteEventAuthor (struct Att_Event *Event);
static Dat_StartEndTime_t Att_GetParAttOrder (void);
2015-04-02 18:39:49 +02:00
static void Att_PutFormsToRemEditOneEvent (struct Att_Events *Events,
const char *Anchor);
static void Att_PutPars (void *Events);
static void Att_GetListEvents (struct Att_Events *Events,
Att_OrderNewestOldest_t OrderNewestOldest);
static void Att_GetEventDataByCodAndCheckCrs (struct Att_Event *Event);
static void Att_ResetEvent (struct Att_Event *Event);
static void Att_FreeListEvents (struct Att_Events *Events);
2020-04-06 16:00:06 +02:00
static void Att_PutParAttCod (void *Events);
2020-04-06 16:00:06 +02:00
static void Att_ShowLstGrpsToEditEvent (long AttCod);
static void Att_CreateGroups (long AttCod);
static void Att_GetAndWriteNamesOfGrpsAssociatedToEvent (struct Att_Event *Event);
2014-12-01 23:55:08 +01:00
2020-04-06 16:00:06 +02:00
static void Att_ShowEvent (struct Att_Events *Events);
static void Att_PutIconsOneEvent (void *Events);
2020-04-06 16:00:06 +02:00
static void Att_ListEventOnlyMeAsStudent (struct Att_Event *Event);
static void Att_ListEventStudents (struct Att_Events *Events);
2019-04-11 23:15:40 +02:00
static void Att_WriteRowUsrToCallTheRoll (unsigned NumUsr,
struct Usr_Data *UsrDat,
2020-04-06 16:00:06 +02:00
struct Att_Event *Event);
static void Att_PutLinkEvent (struct Att_Event *Event,
const char *Title,const char *Txt);
static unsigned Att_GetNumUsrsFromAListWhoAreInEvent (long AttCod,
long LstSelectedUsrCods[],
unsigned NumUsrsInList);
static bool Att_CheckIfUsrIsPresentInEvent (long AttCod,long UsrCod);
static bool Att_CheckIfUsrIsPresentInEventAndGetComments (long AttCod,long UsrCod,
char CommentStd[Cns_MAX_BYTES_TEXT + 1],
char CommentTch[Cns_MAX_BYTES_TEXT + 1]);
2014-12-01 23:55:08 +01:00
2020-04-13 16:39:15 +02:00
static void Att_ReqListOrPrintUsrsAttendanceCrs (void *TypeOfView);
2020-04-06 16:00:06 +02:00
static void Att_ListOrPrintMyAttendanceCrs (Att_TypeOfView_t TypeOfView);
static void Att_GetUsrsAndListOrPrintAttendanceCrs (Att_TypeOfView_t TypeOfView);
static void Att_ListOrPrintUsrsAttendanceCrs (void *TypeOfView);
2015-11-13 01:27:44 +01:00
2020-04-06 16:00:06 +02:00
static void Att_GetListSelectedAttCods (struct Att_Events *Events);
2015-04-02 18:39:49 +02:00
2020-04-06 16:00:06 +02:00
static void Att_PutIconsMyAttList (void *Events);
static void Att_PutFormToPrintMyListPars (void *Events);
2020-04-06 16:00:06 +02:00
static void Att_PutIconsStdsAttList (void *Events);
static void Att_PutParsToPrintStdsList (void *Events);
2015-04-02 18:39:49 +02:00
2020-04-06 16:00:06 +02:00
static void Att_PutButtonToShowDetails (const struct Att_Events *Events);
static void Att_ListEventsToSelect (struct Att_Events *Events,
2020-04-06 16:00:06 +02:00
Att_TypeOfView_t TypeOfView);
2020-04-08 03:41:05 +02:00
static void Att_PutIconToViewAttEvents (__attribute__((unused)) void *Args);
static void Att_PutIconToEditAttEvents (__attribute__((unused)) void *Args);
static void Att_ListUsrsAttendanceTable (struct Att_Events *Events,
2020-04-06 16:00:06 +02:00
Att_TypeOfView_t TypeOfView,
unsigned NumUsrsInList,
2016-03-20 02:08:13 +01:00
long *LstSelectedUsrCods);
static void Att_WriteTableHeadSeveralAttEvents (struct Att_Events *Events);
2020-04-06 16:00:06 +02:00
static void Att_WriteRowUsrSeveralAttEvents (const struct Att_Events *Events,
unsigned NumUsr,struct Usr_Data *UsrDat);
2019-02-13 21:24:54 +01:00
static void Att_PutCheckOrCross (bool Present);
static void Att_ListStdsWithAttEventsDetails (struct Att_Events *Events,
2020-04-06 16:00:06 +02:00
unsigned NumUsrsInList,
2016-11-27 23:08:29 +01:00
long *LstSelectedUsrCods);
static void Att_ListAttEventsForAStd (struct Att_Events *Events,
unsigned NumUsr,struct Usr_Data *UsrDat);
2020-04-06 16:00:06 +02:00
/*****************************************************************************/
/************************** Reset attendance events **************************/
/*****************************************************************************/
static void Att_ResetEvents (struct Att_Events *Events)
{
Events->LstIsRead = false; // List is not read from database
Events->Num = 0; // Number of attendance events
Events->Lst = NULL; // List of attendance events
Events->SelectedOrder = Att_ORDER_DEFAULT;
Events->Event.AttCod = -1L;
2020-04-06 16:00:06 +02:00
Events->ShowDetails = false;
Events->StrAttCodsSelected = NULL;
Events->CurrentPage = 0;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************ List all attendance events *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Att_SeeEvents (void)
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2014-12-01 23:55:08 +01:00
/***** Get parameters *****/
Events.SelectedOrder = Att_GetParAttOrder ();
Grp_GetParWhichGroups ();
Events.CurrentPage = Pag_GetParPagNum (Pag_ATT_EVENTS);
2014-12-01 23:55:08 +01:00
2015-11-13 01:27:44 +01:00
/***** Get list of attendance events *****/
Att_GetListEvents (&Events,Att_NEWEST_FIRST);
2015-11-13 01:27:44 +01:00
/***** Show all attendance events *****/
Att_ShowAllEvents (&Events);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Show all attendance events ************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Att_ShowAllEvents (struct Att_Events *Events)
2014-12-01 23:55:08 +01:00
{
2016-11-13 21:08:14 +01:00
extern const char *Hlp_USERS_Attendance;
2015-01-02 12:57:26 +01:00
extern const char *Txt_Events;
2016-12-15 00:39:52 +01:00
extern const char *Txt_START_END_TIME_HELP[Dat_NUM_START_END_TIME];
extern const char *Txt_START_END_TIME[Dat_NUM_START_END_TIME];
2014-12-01 23:55:08 +01:00
extern const char *Txt_Event;
extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2016-03-20 00:33:27 +01:00
extern const char *Txt_No_events;
struct Pag_Pagination Pagination;
2020-03-27 14:56:54 +01:00
Dat_StartEndTime_t Order;
Grp_WhichGroups_t WhichGroups;
2014-12-01 23:55:08 +01:00
unsigned NumAttEvent;
2017-06-04 18:18:54 +02:00
bool ICanEdit = (Gbl.Usrs.Me.Role.Logged == Rol_TCH ||
Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM);
2014-12-01 23:55:08 +01:00
2016-03-20 00:33:27 +01:00
/***** Compute variables related to pagination *****/
2020-04-06 16:00:06 +02:00
Pagination.NumItems = Events->Num;
Pagination.CurrentPage = (int) Events->CurrentPage;
2016-03-20 00:33:27 +01:00
Pag_CalculatePagination (&Pagination);
2020-04-06 16:00:06 +02:00
Events->CurrentPage = (unsigned) Pagination.CurrentPage;
2015-01-02 12:57:26 +01:00
2019-10-26 02:19:42 +02:00
/***** Begin box *****/
2020-03-26 02:54:30 +01:00
Box_BoxBegin ("100%",Txt_Events,
Att_PutIconsInListOfEvents,Events,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Attendance,Box_NOT_CLOSABLE);
2015-01-02 12:57:26 +01:00
/***** Select whether show only my groups or all groups *****/
if (Gbl.Crs.Grps.NumGrps)
{
Set_BeginSettingsHead ();
Grp_ShowFormToSelWhichGrps (ActSeeAtt,
Att_ParsWhichGroupsToShow,&Events);
Set_EndSettingsHead ();
}
2019-12-06 22:18:05 +01:00
/***** Write links to pages *****/
Pag_WriteLinksToPagesCentered (Pag_ATT_EVENTS,&Pagination,
Events,-1L);
2019-10-11 01:02:51 +02:00
if (Events->Num)
2015-11-13 01:27:44 +01:00
{
/***** Begin table *****/
HTM_TABLE_BeginWideMarginPadding (2);
2019-10-12 19:42:10 +02:00
/***** Table head *****/
HTM_TR_Begin (NULL);
2019-10-11 01:02:51 +02:00
HTM_TH_Span (NULL,HTM_HEAD_CENTER,1,1,"CONTEXT_COL"); // Column for contextual icons
for (Order = (Dat_StartEndTime_t) 0;
Order <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1);
Order++)
{
HTM_TH_Begin (HTM_HEAD_LEFT);
2015-01-02 12:57:26 +01:00
Frm_BeginForm (ActSeeAtt);
WhichGroups = Grp_GetParWhichGroups ();
Grp_PutParWhichGroups (&WhichGroups);
Pag_PutParPagNum (Pag_ATT_EVENTS,Events->CurrentPage);
Par_PutParOrder ((unsigned) Order);
2015-01-02 12:57:26 +01:00
HTM_BUTTON_Submit_Begin (Txt_START_END_TIME_HELP[Order],
"class=\"BT_LINK\"");
if (Order == Events->SelectedOrder)
HTM_U_Begin ();
HTM_Txt (Txt_START_END_TIME[Order]);
if (Order == Events->SelectedOrder)
HTM_U_End ();
HTM_BUTTON_End ();
Frm_EndForm ();
HTM_TH_End ();
}
HTM_TH (Txt_Event ,HTM_HEAD_LEFT );
HTM_TH (Txt_ROLES_PLURAL_Abc[Rol_STD][Usr_SEX_UNKNOWN],HTM_HEAD_RIGHT);
HTM_TR_End ();
/***** Write all attendance events *****/
for (NumAttEvent = Pagination.FirstItemVisible, The_ResetRowColor ();
NumAttEvent <= Pagination.LastItemVisible;
NumAttEvent++, The_ChangeRowColor ())
{
/***** Get data of this attendance event *****/
Events->Event.AttCod = Events->Lst[NumAttEvent - 1].AttCod;
Att_GetEventDataByCodAndCheckCrs (&Events->Event);
Events->Event.NumStdsTotal = Att_DB_GetNumStdsTotalWhoAreInEvent (Events->Event.AttCod);
/***** Show one attendance event *****/
Att_ShowOneEventRow (Events,
false); // Don't show only this event
}
/***** End table *****/
HTM_TABLE_End ();
}
else // No events created
Ale_ShowAlert (Ale_INFO,Txt_No_events);
2016-03-20 00:33:27 +01:00
/***** Write again links to pages *****/
Pag_WriteLinksToPagesCentered (Pag_ATT_EVENTS,&Pagination,
Events,-1L);
2019-12-06 22:18:05 +01:00
/***** Button to create a new attendance event *****/
if (ICanEdit)
Att_PutButtonToCreateNewEvent (Events);
2016-03-20 00:33:27 +01:00
2017-06-12 14:16:33 +02:00
/***** End box *****/
2019-10-25 22:48:34 +02:00
Box_BoxEnd ();
2014-12-01 23:55:08 +01:00
2016-03-20 00:33:27 +01:00
/***** Free list of attendance events *****/
Att_FreeListEvents (Events);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-02-25 15:14:28 +01:00
/***************** Put params to select which groups to show *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Att_ParsWhichGroupsToShow (void *Events)
2016-12-04 23:09:28 +01:00
{
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
Par_PutParOrder ((unsigned) ((struct Att_Events *) Events)->SelectedOrder);
Pag_PutParPagNum (Pag_ATT_EVENTS,((struct Att_Events *) Events)->CurrentPage);
2020-03-26 02:54:30 +01:00
}
2014-12-01 23:55:08 +01:00
}
2018-10-18 08:56:00 +02:00
/*****************************************************************************/
/************* Put contextual icons in list of attendance events *************/
/*****************************************************************************/
static void Att_PutIconsInListOfEvents (void *Events)
2018-10-18 08:56:00 +02:00
{
2020-03-26 02:54:30 +01:00
bool ICanEdit;
2018-10-18 08:56:00 +02:00
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
/***** Put icon to create a new attendance event *****/
ICanEdit = (Gbl.Usrs.Me.Role.Logged == Rol_TCH ||
Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM);
if (ICanEdit)
Att_PutIconToCreateNewEvent ((struct Att_Events *) Events);
2020-03-26 02:54:30 +01:00
/***** Put icon to show attendance list *****/
2020-04-06 16:00:06 +02:00
if (((struct Att_Events *) Events)->Num)
2020-03-26 02:54:30 +01:00
switch (Gbl.Usrs.Me.Role.Logged)
{
case Rol_STD:
Ico_PutContextualIconToShowAttendanceList (ActSeeLstMyAtt,
NULL,NULL);
break;
case Rol_NET:
case Rol_TCH:
case Rol_SYS_ADM:
Ico_PutContextualIconToShowAttendanceList (ActReqLstUsrAtt,
Att_PutParsToListUsrsAttendance,Events);
2020-03-26 02:54:30 +01:00
break;
default:
break;
}
2019-12-06 22:49:45 +01:00
2020-03-26 02:54:30 +01:00
/***** Put icon to print my QR code *****/
QR_PutLinkToPrintQRCode (ActPrnUsrQR,
Usr_PutParMyUsrCodEncrypted,Gbl.Usrs.Me.UsrDat.EnUsrCod);
/***** Put icon to get resource link *****/
if (Rsc_CheckIfICanGetLink ())
Ico_PutContextualIconToGetLink (ActReqLnkAtt,NULL,
Att_PutPars,Events);
2020-03-26 02:54:30 +01:00
}
2018-10-18 08:56:00 +02:00
}
2016-03-20 00:33:27 +01:00
/*****************************************************************************/
/**************** Put icon to create a new attendance event ******************/
/*****************************************************************************/
static void Att_PutIconToCreateNewEvent (struct Att_Events *Events)
2016-03-20 00:33:27 +01:00
{
2019-01-10 15:26:33 +01:00
Ico_PutContextualIconToAdd (ActFrmNewAtt,NULL,
Att_PutParsToCreateNewEvent,Events);
2016-03-20 00:33:27 +01:00
}
/*****************************************************************************/
/**************** Put button to create a new attendance event ****************/
/*****************************************************************************/
static void Att_PutButtonToCreateNewEvent (struct Att_Events *Events)
2016-03-20 00:33:27 +01:00
{
extern const char *Txt_New_event;
/***** Begin form *****/
Frm_BeginForm (ActFrmNewAtt);
Att_PutParsToCreateNewEvent (Events);
/***** Button to create new event *****/
Btn_PutConfirmButton (Txt_New_event);
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-03-20 00:33:27 +01:00
}
/*****************************************************************************/
/************** Put parameters to create a new attendance event **************/
/*****************************************************************************/
static void Att_PutParsToCreateNewEvent (void *Events)
2016-03-20 00:33:27 +01:00
{
2020-03-27 14:56:54 +01:00
Grp_WhichGroups_t WhichGroups;
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
Par_PutParOrder ((unsigned) ((struct Att_Events *) Events)->SelectedOrder);
WhichGroups = Grp_GetParWhichGroups ();
Grp_PutParWhichGroups (&WhichGroups);
Pag_PutParPagNum (Pag_ATT_EVENTS,((struct Att_Events *) Events)->CurrentPage);
2020-03-26 02:54:30 +01:00
}
2016-03-20 00:33:27 +01:00
}
2019-12-06 22:49:45 +01:00
/*****************************************************************************/
/***************** Put parameters to list users attendance *******************/
/*****************************************************************************/
static void Att_PutParsToListUsrsAttendance (void *Events)
2019-12-06 22:49:45 +01:00
{
2020-03-27 14:56:54 +01:00
Grp_WhichGroups_t WhichGroups;
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
Par_PutParOrder ((unsigned) ((struct Att_Events *) Events)->SelectedOrder);
WhichGroups = Grp_GetParWhichGroups ();
Grp_PutParWhichGroups (&WhichGroups);
Pag_PutParPagNum (Pag_ATT_EVENTS,((struct Att_Events *) Events)->CurrentPage);
2020-03-26 02:54:30 +01:00
}
2019-12-06 22:49:45 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************* Show one attendance event *************************/
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
// Only Event->AttCod must be filled
2014-12-01 23:55:08 +01:00
static void Att_ShowOneEventRow (struct Att_Events *Events,
bool ShowOnlyThisAttEventComplete)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_View_event;
2019-04-20 21:11:44 +02:00
char *Anchor = NULL;
2015-10-23 13:20:42 +02:00
static unsigned UniqueId = 0;
2019-11-01 22:53:39 +01:00
char *Id;
2019-09-27 00:46:02 +02:00
Dat_StartEndTime_t StartEndTime;
2019-02-15 21:09:18 +01:00
char Description[Cns_MAX_BYTES_TEXT + 1];
2014-12-01 23:55:08 +01:00
2019-04-20 21:11:44 +02:00
/***** Set anchor string *****/
Frm_SetAnchorStr (Events->Event.AttCod,&Anchor);
2019-04-20 21:11:44 +02:00
2017-05-02 11:39:17 +02:00
/***** Write first row of data of this attendance event *****/
/* Forms to remove/edit this attendance event */
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
if (!ShowOnlyThisAttEventComplete)
{
HTM_TD_Begin ("rowspan=\"2\" class=\"CONTEXT_COL %s\"",
The_GetColorRows ());
Att_PutFormsToRemEditOneEvent (Events,Anchor);
HTM_TD_End ();
}
2017-05-02 11:39:17 +02:00
/* Start/end date/time */
UniqueId++;
for (StartEndTime = (Dat_StartEndTime_t) 0;
StartEndTime <= (Dat_StartEndTime_t) (Dat_NUM_START_END_TIME - 1);
StartEndTime++)
{
if (asprintf (&Id,"att_date_%u_%u",(unsigned) StartEndTime,UniqueId) < 0)
Err_NotEnoughMemoryExit ();
if (ShowOnlyThisAttEventComplete)
HTM_TD_Begin ("id=\"%s\" class=\"LB %s_%s\"",
Id,
Events->Event.Hidden ? (Events->Event.Open ? "DATE_GREEN_LIGHT" :
"DATE_RED_LIGHT") :
(Events->Event.Open ? "DATE_GREEN" :
"DATE_RED"),
The_GetSuffix ());
else
HTM_TD_Begin ("id=\"%s\" class=\"LB %s_%s %s\"",
Id,
Events->Event.Hidden ? (Events->Event.Open ? "DATE_GREEN_LIGHT" :
"DATE_RED_LIGHT") :
(Events->Event.Open ? "DATE_GREEN" :
"DATE_RED"),
The_GetSuffix (),
The_GetColorRows ());
Dat_WriteLocalDateHMSFromUTC (Id,Events->Event.TimeUTC[StartEndTime],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_BREAK,
true,true,true,0x7);
HTM_TD_End ();
free (Id);
}
/* Attendance event title */
2019-10-07 23:02:50 +02:00
if (ShowOnlyThisAttEventComplete)
HTM_TD_Begin ("class=\"LT\"");
2019-10-07 23:02:50 +02:00
else
HTM_TD_Begin ("class=\"LT %s\"",The_GetColorRows ());
HTM_ARTICLE_Begin (Anchor);
Att_PutLinkEvent (&Events->Event,Txt_View_event,Events->Event.Title);
HTM_ARTICLE_End ();
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
/* Number of students in this event */
if (ShowOnlyThisAttEventComplete)
HTM_TD_Begin ("class=\"RT\"");
else
HTM_TD_Begin ("class=\"RT %s\"",The_GetColorRows ());
HTM_SPAN_Begin ("class=\"%s_%s\"",
Events->Event.Hidden ? "ASG_TITLE_LIGHT" :
"ASG_TITLE",
The_GetSuffix ());
HTM_Unsigned (Events->Event.NumStdsTotal);
HTM_SPAN_End ();
HTM_TD_End ();
2019-10-06 12:00:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
/***** Write second row of data of this attendance event *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
/* Author of the attendance event */
if (ShowOnlyThisAttEventComplete)
HTM_TD_Begin ("colspan=\"2\" class=\"LT\"");
else
HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"",The_GetColorRows ());
Att_WriteEventAuthor (&Events->Event);
HTM_TD_End ();
/* Text of the attendance event */
Att_DB_GetEventDescription (Events->Event.AttCod,Description);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Description,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
ALn_InsertLinks (Description,Cns_MAX_BYTES_TEXT,60); // Insert links
if (ShowOnlyThisAttEventComplete)
HTM_TD_Begin ("colspan=\"2\" class=\"LT\"");
else
HTM_TD_Begin ("colspan=\"2\" class=\"LT %s\"",The_GetColorRows ());
if (Gbl.Crs.Grps.NumGrps)
Att_GetAndWriteNamesOfGrpsAssociatedToEvent (&Events->Event);
HTM_DIV_Begin ("class=\"%s_%s\"",
Events->Event.Hidden ? "DAT_LIGHT" :
"DAT",
The_GetSuffix ());
HTM_Txt (Description);
HTM_DIV_End ();
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
2019-04-20 21:11:44 +02:00
/***** Free anchor string *****/
Frm_FreeAnchorStr (Anchor);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Write the author of an attendance event ******************/
/*****************************************************************************/
static void Att_WriteEventAuthor (struct Att_Event *Event)
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
Usr_WriteAuthor1Line (Event->UsrCod,Event->Hidden);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**** Get parameter with the type or order in list of attendance events ******/
/*****************************************************************************/
static Dat_StartEndTime_t Att_GetParAttOrder (void)
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
return (Dat_StartEndTime_t)
Par_GetParUnsignedLong ("Order",
0,
Dat_NUM_START_END_TIME - 1,
(unsigned long) Att_ORDER_DEFAULT);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************** Put a link (form) to edit one attendance event ***************/
/*****************************************************************************/
static void Att_PutFormsToRemEditOneEvent (struct Att_Events *Events,
const char *Anchor)
2014-12-01 23:55:08 +01:00
{
static Act_Action_t ActionHideUnhide[2] =
{
[false] = ActHidAtt, // Visible ==> action to hide
[true ] = ActUnhAtt, // Hidden ==> action to unhide
};
if (Att_CheckIfICanEditEvents ())
{
/***** Icon to remove attendance event *****/
Ico_PutContextualIconToRemove (ActReqRemAtt,NULL,
Att_PutPars,Events);
/***** Icon to hide/unhide attendance event *****/
Ico_PutContextualIconToHideUnhide (ActionHideUnhide,Anchor,
Att_PutPars,Events,
Events->Event.Hidden);
/***** Icon to edit attendance event *****/
Ico_PutContextualIconToEdit (ActEdiOneAtt,NULL,
Att_PutPars,Events);
}
/***** Icon to get resource link *****/
if (Rsc_CheckIfICanGetLink ())
Ico_PutContextualIconToGetLink (ActReqLnkAtt,NULL,
Att_PutPars,Events);
}
2015-12-13 19:37:08 +01:00
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/******************* Check if I can edit calls for exams *********************/
/*****************************************************************************/
2014-12-01 23:55:08 +01:00
bool Att_CheckIfICanEditEvents (void)
{
static const bool ICanEditAttEvents[Rol_NUM_ROLES] =
{
[Rol_TCH ] = true,
[Rol_SYS_ADM] = true,
};
return ICanEditAttEvents[Gbl.Usrs.Me.Role.Logged];
2015-12-13 19:37:08 +01:00
}
/*****************************************************************************/
/***************** Params used to edit an attendance event *******************/
/*****************************************************************************/
static void Att_PutPars (void *Events)
2015-12-13 19:37:08 +01:00
{
2020-03-27 14:56:54 +01:00
Grp_WhichGroups_t WhichGroups;
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
ParCod_PutPar (ParCod_Att,((struct Att_Events *) Events)->Event.AttCod);
Par_PutParOrder ((unsigned) ((struct Att_Events *) Events)->SelectedOrder);
WhichGroups = Grp_GetParWhichGroups ();
Grp_PutParWhichGroups (&WhichGroups);
Pag_PutParPagNum (Pag_ATT_EVENTS,((struct Att_Events *) Events)->CurrentPage);
2020-03-26 02:54:30 +01:00
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************ List all attendance events *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Att_GetListEvents (struct Att_Events *Events,
Att_OrderNewestOldest_t OrderNewestOldest)
2014-12-01 23:55:08 +01:00
{
extern unsigned (*Att_DB_GetListAttEvents[Grp_NUM_WHICH_GROUPS]) (MYSQL_RES **mysql_res,
Dat_StartEndTime_t SelectedOrder,
Att_OrderNewestOldest_t OrderNewestOldest);
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
unsigned NumAttEvent;
2020-04-06 16:00:06 +02:00
if (Events->LstIsRead)
Att_FreeListEvents (Events);
2014-12-01 23:55:08 +01:00
/***** Get list of attendance events from database *****/
Events->Num = Att_DB_GetListAttEvents[Gbl.Crs.Grps.WhichGrps] (&mysql_res,
Events->SelectedOrder,
OrderNewestOldest);
if (Events->Num) // Attendance events found...
2014-12-01 23:55:08 +01:00
{
/***** Create list of attendance events *****/
if ((Events->Lst = calloc ((size_t) Events->Num,
sizeof (*Events->Lst))) == NULL)
Err_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
/***** Get the attendance events codes *****/
for (NumAttEvent = 0;
2020-04-06 16:00:06 +02:00
NumAttEvent < Events->Num;
2014-12-01 23:55:08 +01:00
NumAttEvent++)
{
/* Get next attendance event code */
if ((Events->Lst[NumAttEvent].AttCod = DB_GetNextCode (mysql_res)) < 0)
Err_WrongEventExit ();
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
2020-04-06 16:00:06 +02:00
Events->LstIsRead = true;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********* Get attendance event data using its code and check course *********/
/*****************************************************************************/
static void Att_GetEventDataByCodAndCheckCrs (struct Att_Event *Event)
2014-12-01 23:55:08 +01:00
{
if (Att_GetEventDataByCod (Event))
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
if (Event->CrsCod != Gbl.Hierarchy.Crs.CrsCod)
Err_WrongEventExit ();
2014-12-01 23:55:08 +01:00
}
else // Attendance event not found
Err_WrongEventExit ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************** Get attendance event data using its code *******************/
/*****************************************************************************/
// Returns true if attendance event exists
// This function can be called from web service, so do not display messages
bool Att_GetEventDataByCod (struct Att_Event *Event)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumAttEvents;
2016-12-29 23:33:01 +01:00
bool Found = false;
2014-12-01 23:55:08 +01:00
2016-12-29 23:07:30 +01:00
/***** Reset attendance event data *****/
Att_ResetEvent (Event);
2016-12-29 23:07:30 +01:00
2020-04-06 16:00:06 +02:00
if (Event->AttCod > 0)
2014-12-01 23:55:08 +01:00
{
2016-12-29 23:33:01 +01:00
/***** Build query *****/
NumAttEvents = Att_DB_GetEventDataByCod (&mysql_res,Event->AttCod);
2016-12-29 23:33:01 +01:00
/***** Get data of attendance event from database *****/
if ((Found = (NumAttEvents != 0))) // Attendance event found...
2016-12-29 23:33:01 +01:00
{
/* Get next row from result */
2016-12-29 23:33:01 +01:00
row = mysql_fetch_row (mysql_res);
2014-12-01 23:55:08 +01:00
/* Get attendance event (except Txt) */
Att_GetEventDataFromRow (row,Event);
2016-12-29 23:33:01 +01:00
}
2014-12-01 23:55:08 +01:00
2016-12-29 23:33:01 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
2014-12-01 23:55:08 +01:00
return Found;
}
2016-12-29 23:07:30 +01:00
/*****************************************************************************/
/********************** Clear all attendance event data **********************/
/*****************************************************************************/
static void Att_ResetEvent (struct Att_Event *Event)
2016-12-29 23:07:30 +01:00
{
2020-04-06 16:00:06 +02:00
if (Event->AttCod <= 0) // If > 0 ==> keep values of AttCod and Selected
2017-01-17 14:24:54 +01:00
{
2020-04-06 16:00:06 +02:00
Event->AttCod = -1L;
Event->NumStdsTotal = 0;
2017-01-17 14:24:54 +01:00
}
2020-04-06 16:00:06 +02:00
Event->CrsCod = -1L;
Event->Hidden = false;
Event->UsrCod = -1L;
Event->TimeUTC[Dat_STR_TIME] =
Event->TimeUTC[Dat_END_TIME] = (time_t) 0;
2020-04-06 16:00:06 +02:00
Event->Open = false;
Event->CommentTchVisible = false;
Event->Title[0] = '\0';
}
/*****************************************************************************/
/************************* Get attendance event data *************************/
/*****************************************************************************/
void Att_GetEventDataFromRow (MYSQL_ROW row,struct Att_Event *Event)
{
/***** Get code of attendance event (row[0]) and code of course (row[1]) *****/
Event->AttCod = Str_ConvertStrCodToLongCod (row[0]);
Event->CrsCod = Str_ConvertStrCodToLongCod (row[1]);
/***** Get whether the attendance event is hidden or not (row[2]) *****/
Event->Hidden = (row[2][0] == 'Y');
/***** Get author of the attendance event (row[3]) *****/
Event->UsrCod = Str_ConvertStrCodToLongCod (row[3]);
/***** Get start date (row[4]) and end date (row[5]) in UTC time *****/
Event->TimeUTC[Dat_STR_TIME] = Dat_GetUNIXTimeFromStr (row[4]);
Event->TimeUTC[Dat_END_TIME] = Dat_GetUNIXTimeFromStr (row[5]);
/***** Get whether the attendance event is open or closed (row(6)) *****/
Event->Open = (row[6][0] == '1');
/***** Get whether the attendance event is visible or not (row[7]) *****/
Event->CommentTchVisible = (row[7][0] == 'Y');
/***** Get the title of the attendance event (row[8]) *****/
Str_Copy (Event->Title,row[8],sizeof (Event->Title) - 1);
2016-12-29 23:07:30 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********************** Free list of attendance events ***********************/
/*****************************************************************************/
static void Att_FreeListEvents (struct Att_Events *Events)
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
if (Events->LstIsRead && Events->Lst)
2014-12-01 23:55:08 +01:00
{
/***** Free memory used by the list of attendance events *****/
2020-04-06 16:00:06 +02:00
free (Events->Lst);
Events->Lst = NULL;
Events->Num = 0;
Events->LstIsRead = false;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/********* Ask for confirmation of removing of an attendance event ***********/
/*****************************************************************************/
void Att_AskRemEvent (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Do_you_really_want_to_remove_the_event_X;
extern const char *Txt_Remove_event;
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
2014-12-01 23:55:08 +01:00
2020-04-06 16:00:06 +02:00
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2014-12-01 23:55:08 +01:00
/***** Get parameters *****/
Events.SelectedOrder = Att_GetParAttOrder ();
Grp_GetParWhichGroups ();
Events.CurrentPage = Pag_GetParPagNum (Pag_ATT_EVENTS);
2014-12-01 23:55:08 +01:00
/***** Get attendance event code *****/
Events.Event.AttCod = ParCod_GetAndCheckPar (ParCod_Att);
2014-12-01 23:55:08 +01:00
/***** Get data of the attendance event from database *****/
Att_GetEventDataByCodAndCheckCrs (&Events.Event);
2014-12-01 23:55:08 +01:00
/***** Show question and button to remove event *****/
Ale_ShowAlertAndButton (ActRemAtt,NULL,NULL,
Att_PutPars,&Events,
Btn_REMOVE_BUTTON,Txt_Remove_event,
Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_event_X,
Events.Event.Title);
2014-12-01 23:55:08 +01:00
/***** Show attendance events again *****/
Att_SeeEvents ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2016-09-06 18:29:13 +02:00
/** Get param., remove an attendance event and show attendance events again **/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Att_GetAndRemEvent (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Event_X_removed;
2020-04-06 16:00:06 +02:00
struct Att_Event Event;
2014-12-01 23:55:08 +01:00
/***** Get attendance event code *****/
Event.AttCod = ParCod_GetAndCheckPar (ParCod_Att);
2014-12-01 23:55:08 +01:00
/***** Get data of the attendance event from database *****/
2016-09-06 18:29:13 +02:00
// Inside this function, the course is checked to be the current one
Att_GetEventDataByCodAndCheckCrs (&Event);
2014-12-01 23:55:08 +01:00
2016-09-06 18:29:13 +02:00
/***** Remove the attendance event from database *****/
Att_RemoveEventFromDB (Event.AttCod);
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_SUCCESS,Txt_Event_X_removed,
2020-04-06 16:00:06 +02:00
Event.Title);
2014-12-01 23:55:08 +01:00
/***** Show attendance events again *****/
Att_SeeEvents ();
2014-12-01 23:55:08 +01:00
}
2016-09-06 18:29:13 +02:00
/*****************************************************************************/
/**************** Remove an attendance event from database *******************/
/*****************************************************************************/
void Att_RemoveEventFromDB (long AttCod)
2016-09-06 18:29:13 +02:00
{
/***** Remove users registered in the attendance event *****/
Att_DB_RemoveAllUsrsFromAnEvent (AttCod);
2016-09-06 18:29:13 +02:00
/***** Remove all groups of this attendance event *****/
Att_DB_RemoveGrpsAssociatedToAnEvent (AttCod);
2016-09-06 18:29:13 +02:00
/***** Remove attendance event *****/
Att_DB_RemoveEventFromCurrentCrs (AttCod);
2016-09-06 18:29:13 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************* Hide an attendance event **************************/
/*****************************************************************************/
void Att_HideEvent (void)
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
struct Att_Event Event;
2014-12-01 23:55:08 +01:00
/***** Get attendance event code *****/
Event.AttCod = ParCod_GetAndCheckPar (ParCod_Att);
2014-12-01 23:55:08 +01:00
/***** Get data of the attendance event from database *****/
Att_GetEventDataByCodAndCheckCrs (&Event);
2014-12-01 23:55:08 +01:00
/***** Hide attendance event *****/
Att_DB_HideOrUnhideEvent (Event.AttCod,true);
2014-12-01 23:55:08 +01:00
/***** Show attendance events again *****/
Att_SeeEvents ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************ Unhide an attendance event *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Att_UnhideEvent (void)
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
struct Att_Event Event;
2014-12-01 23:55:08 +01:00
/***** Get attendance event code *****/
Event.AttCod = ParCod_GetAndCheckPar (ParCod_Att);
2014-12-01 23:55:08 +01:00
/***** Get data of the attendance event from database *****/
Att_GetEventDataByCodAndCheckCrs (&Event);
2014-12-01 23:55:08 +01:00
/***** Unhide attendance event *****/
Att_DB_HideOrUnhideEvent (Event.AttCod,false);
2014-12-01 23:55:08 +01:00
/***** Show attendance events again *****/
Att_SeeEvents ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** Put a form to create a new attendance event *****************/
/*****************************************************************************/
void Att_ReqCreatOrEditEvent (void)
2014-12-01 23:55:08 +01:00
{
2016-11-27 23:08:29 +01:00
extern const char *Hlp_USERS_Attendance_new_event;
extern const char *Hlp_USERS_Attendance_edit_event;
2014-12-01 23:55:08 +01:00
extern const char *Txt_New_event;
extern const char *Txt_Edit_event;
2014-12-04 01:19:42 +01:00
extern const char *Txt_Teachers_comment;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Title;
extern const char *Txt_Hidden_MALE_PLURAL;
extern const char *Txt_Visible_MALE_PLURAL;
extern const char *Txt_Description;
extern const char *Txt_Create_event;
2019-02-18 18:27:45 +01:00
extern const char *Txt_Save_changes;
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
2014-12-01 23:55:08 +01:00
bool ItsANewAttEvent;
2020-03-27 14:56:54 +01:00
Grp_WhichGroups_t WhichGroups;
2019-02-15 21:09:18 +01:00
char Description[Cns_MAX_BYTES_TEXT + 1];
2020-02-26 19:35:33 +01:00
static const Dat_SetHMS SetHMS[Dat_NUM_START_END_TIME] =
{
[Dat_STR_TIME] = Dat_HMS_DO_NOT_SET,
[Dat_END_TIME] = Dat_HMS_DO_NOT_SET
2020-02-26 19:35:33 +01:00
};
2014-12-01 23:55:08 +01:00
2020-06-17 22:19:57 +02:00
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2014-12-01 23:55:08 +01:00
/***** Get parameters *****/
Events.SelectedOrder = Att_GetParAttOrder ();
Grp_GetParWhichGroups ();
Events.CurrentPage = Pag_GetParPagNum (Pag_ATT_EVENTS);
2014-12-01 23:55:08 +01:00
/***** Get the code of the attendance event *****/
ItsANewAttEvent = ((Events.Event.AttCod = ParCod_GetPar (ParCod_Att)) <= 0);
2014-12-01 23:55:08 +01:00
/***** Get from the database the data of the attendance event *****/
if (ItsANewAttEvent)
{
2016-12-29 23:07:30 +01:00
/* Reset attendance event data */
Events.Event.AttCod = -1L;
Att_ResetEvent (&Events.Event);
2016-12-29 23:07:30 +01:00
/* Initialize some fields */
Events.Event.CrsCod = Gbl.Hierarchy.Crs.CrsCod;
Events.Event.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Events.Event.TimeUTC[Dat_STR_TIME] = Dat_GetStartExecutionTimeUTC ();
Events.Event.TimeUTC[Dat_END_TIME] = Events.Event.TimeUTC[Dat_STR_TIME] + (2 * 60 * 60); // +2 hours
Events.Event.Open = true;
2014-12-01 23:55:08 +01:00
}
else
{
/* Get data of the attendance event from database */
Att_GetEventDataByCodAndCheckCrs (&Events.Event);
2014-12-01 23:55:08 +01:00
/* Get text of the attendance event from database */
Att_DB_GetEventDescription (Events.Event.AttCod,Description);
2014-12-01 23:55:08 +01:00
}
2019-10-20 22:00:28 +02:00
/***** Begin form *****/
2014-12-01 23:55:08 +01:00
if (ItsANewAttEvent)
Frm_BeginForm (ActNewAtt);
2014-12-01 23:55:08 +01:00
else
{
Frm_BeginForm (ActChgAtt);
ParCod_PutPar (ParCod_Att,Events.Event.AttCod);
2014-12-01 23:55:08 +01:00
}
Par_PutParOrder ((unsigned) Events.SelectedOrder);
WhichGroups = Grp_GetParWhichGroups ();
Grp_PutParWhichGroups (&WhichGroups);
Pag_PutParPagNum (Pag_ATT_EVENTS,Events.CurrentPage);
2014-12-01 23:55:08 +01:00
/***** Begin box and table *****/
if (ItsANewAttEvent)
Box_BoxTableBegin (NULL,Txt_New_event,
NULL,NULL,
Hlp_USERS_Attendance_new_event,Box_NOT_CLOSABLE,2);
else
Box_BoxTableBegin (NULL,
Events.Event.Title[0] ? Events.Event.Title :
Txt_Edit_event,
NULL,NULL,
Hlp_USERS_Attendance_edit_event,Box_NOT_CLOSABLE,2);
2019-10-07 22:28:16 +02:00
/***** Attendance event title *****/
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
/* Label */
Frm_LabelColumn ("RT","Title",Txt_Title);
2019-10-07 22:28:16 +02:00
/* Data */
HTM_TD_Begin ("class=\"LT\"");
HTM_INPUT_TEXT ("Title",Att_MAX_CHARS_ATTENDANCE_EVENT_TITLE,Events.Event.Title,
HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"Title\" class=\"TITLE_DESCRIPTION_WIDTH INPUT_%s\""
" required=\"required\"",
The_GetSuffix ());
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
/***** Assignment start and end dates *****/
Dat_PutFormStartEndClientLocalDateTimes (Events.Event.TimeUTC,
Dat_FORM_SECONDS_ON,
SetHMS);
2019-10-07 22:28:16 +02:00
/***** Visibility of comments *****/
HTM_TR_Begin (NULL);
2019-10-06 12:00:55 +02:00
/* Label */
Frm_LabelColumn ("RT","ComTchVisible",Txt_Teachers_comment);
/* Data */
HTM_TD_Begin ("class=\"LT\"");
HTM_SELECT_Begin (HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"ComTchVisible\" name=\"ComTchVisible\""
" class=\"INPUT_%s\"",
The_GetSuffix ());
HTM_OPTION (HTM_Type_STRING,"N",!Events.Event.CommentTchVisible,false,
"%s",Txt_Hidden_MALE_PLURAL);
HTM_OPTION (HTM_Type_STRING,"Y", Events.Event.CommentTchVisible,false,
"%s",Txt_Visible_MALE_PLURAL);
HTM_SELECT_End ();
HTM_TD_End ();
2019-12-27 21:10:39 +01:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
/***** Attendance event description *****/
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
/* Label */
Frm_LabelColumn ("RT","Txt",Txt_Description);
2019-10-07 22:28:16 +02:00
/* Data */
HTM_TD_Begin ("class=\"LT\"");
HTM_TEXTAREA_Begin ("id=\"Txt\" name=\"Txt\" rows=\"5\""
" class=\"TITLE_DESCRIPTION_WIDTH INPUT_%s\"",
The_GetSuffix ());
if (!ItsANewAttEvent)
HTM_Txt (Description);
HTM_TEXTAREA_End ();
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
/***** Groups *****/
Att_ShowLstGrpsToEditEvent (Events.Event.AttCod);
2014-12-01 23:55:08 +01:00
/***** End table, send button and end box *****/
if (ItsANewAttEvent)
Box_BoxTableWithButtonEnd (Btn_CREATE_BUTTON,Txt_Create_event);
else
Box_BoxTableWithButtonEnd (Btn_CONFIRM_BUTTON,Txt_Save_changes);
2014-12-01 23:55:08 +01:00
2015-04-11 17:33:14 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
/***** Show current attendance events *****/
Att_GetListEvents (&Events,Att_NEWEST_FIRST);
Att_ShowAllEvents (&Events);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************* Show list of groups to edit and attendance event **************/
/*****************************************************************************/
static void Att_ShowLstGrpsToEditEvent (long AttCod)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Groups;
extern const char *Txt_The_whole_course;
unsigned NumGrpTyp;
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
if (Gbl.Crs.Grps.GrpTypes.NumGrpTypes)
2014-12-01 23:55:08 +01:00
{
2019-10-26 02:19:42 +02:00
/***** Begin box and table *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
HTM_TD_Begin ("class=\"RT FORM_IN_%s\"",The_GetSuffix ());
HTM_TxtColon (Txt_Groups);
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
HTM_TD_Begin ("class=\"LT\"");
Box_BoxTableBegin ("100%",NULL,
NULL,NULL,
NULL,Box_NOT_CLOSABLE,0);
/***** First row: checkbox to select the whole course *****/
HTM_TR_Begin (NULL);
HTM_TD_Begin ("colspan=\"7\" class=\"LM DAT_%s\"",
The_GetSuffix ());
HTM_LABEL_Begin (NULL);
HTM_INPUT_CHECKBOX ("WholeCrs",HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"WholeCrs\" value=\"Y\"%s"
" onclick=\"uncheckChildren(this,'GrpCods')\"",
Grp_DB_CheckIfAssociatedToGrps ("att_groups",
"AttCod",
AttCod) ? "" :
" checked=\"checked\"");
HTM_TxtF ("%s&nbsp;%s",Txt_The_whole_course,Gbl.Hierarchy.Crs.ShrtName);
HTM_LABEL_End ();
HTM_TD_End ();
HTM_TR_End ();
/***** List the groups for each group type *****/
for (NumGrpTyp = 0;
NumGrpTyp < Gbl.Crs.Grps.GrpTypes.NumGrpTypes;
NumGrpTyp++)
if (Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].NumGrps)
Grp_ListGrpsToEditAsgAttSvyEvtMch (&Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp],
Grp_ATT_EVENT,AttCod);
/***** End table and box *****/
Box_BoxTableEnd ();
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
}
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ();
}
/*****************************************************************************/
/*************** Receive form to create a new attendance event ***************/
/*****************************************************************************/
void Att_ReceiveFormEvent (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Already_existed_an_event_with_the_title_X;
extern const char *Txt_Created_new_event_X;
extern const char *Txt_The_event_has_been_modified;
2020-04-06 16:00:06 +02:00
struct Att_Event OldAtt;
struct Att_Event ReceivedAtt;
2014-12-01 23:55:08 +01:00
bool ItsANewAttEvent;
2016-09-07 18:02:25 +02:00
bool ReceivedAttEventIsCorrect = true;
2019-02-15 21:09:18 +01:00
char Description[Cns_MAX_BYTES_TEXT + 1];
2014-12-01 23:55:08 +01:00
/***** Get the code of the attendance event *****/
ItsANewAttEvent = ((ReceivedAtt.AttCod = ParCod_GetPar (ParCod_Att)) <= 0);
2014-12-01 23:55:08 +01:00
if (!ItsANewAttEvent)
{
/* Get data of the old (current) attendance event from database */
2016-09-07 18:02:25 +02:00
OldAtt.AttCod = ReceivedAtt.AttCod;
Att_GetEventDataByCodAndCheckCrs (&OldAtt);
2016-09-19 22:03:58 +02:00
ReceivedAtt.Hidden = OldAtt.Hidden;
2014-12-01 23:55:08 +01:00
}
2015-10-23 13:20:42 +02:00
/***** Get start/end date-times *****/
ReceivedAtt.TimeUTC[Dat_STR_TIME] = Dat_GetTimeUTCFromForm (Dat_STR_TIME);
ReceivedAtt.TimeUTC[Dat_END_TIME] = Dat_GetTimeUTCFromForm (Dat_END_TIME);
2014-12-01 23:55:08 +01:00
/***** Get boolean parameter that indicates if teacher's comments are visible by students *****/
ReceivedAtt.CommentTchVisible = Par_GetParBool ("ComTchVisible");
2014-12-01 23:55:08 +01:00
/***** Get attendance event title *****/
Par_GetParText ("Title",ReceivedAtt.Title,Att_MAX_BYTES_ATTENDANCE_EVENT_TITLE);
2014-12-01 23:55:08 +01:00
2019-02-15 21:09:18 +01:00
/***** Get attendance event description *****/
Par_GetParHTML ("Txt",Description,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous)
2014-12-01 23:55:08 +01:00
/***** Adjust dates *****/
if (ReceivedAtt.TimeUTC[Dat_STR_TIME] == 0)
ReceivedAtt.TimeUTC[Dat_STR_TIME] = Dat_GetStartExecutionTimeUTC ();
if (ReceivedAtt.TimeUTC[Dat_END_TIME] == 0)
ReceivedAtt.TimeUTC[Dat_END_TIME] = ReceivedAtt.TimeUTC[Dat_STR_TIME] + 2 * 60 * 60; // +2 hours // TODO: 2 * 60 * 60 should be in a #define in swad_config.h
2014-12-01 23:55:08 +01:00
/***** Check if title is correct *****/
2016-09-07 18:02:25 +02:00
if (ReceivedAtt.Title[0]) // If there's an attendance event title
2014-12-01 23:55:08 +01:00
{
/* If title of attendance event was in database... */
if (Att_DB_CheckIfSimilarEventExists ("Title",ReceivedAtt.Title,ReceivedAtt.AttCod))
2014-12-01 23:55:08 +01:00
{
2016-09-07 18:02:25 +02:00
ReceivedAttEventIsCorrect = false;
2019-02-15 23:38:44 +01:00
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_WARNING,Txt_Already_existed_an_event_with_the_title_X,
2019-02-15 23:38:44 +01:00
ReceivedAtt.Title);
2014-12-01 23:55:08 +01:00
}
}
else // If there is not an attendance event title
{
2016-09-07 18:02:25 +02:00
ReceivedAttEventIsCorrect = false;
Ale_ShowAlertYouMustSpecifyTheTitle ();
2014-12-01 23:55:08 +01:00
}
/***** Create a new attendance event or update an existing one *****/
2016-09-07 18:02:25 +02:00
if (ReceivedAttEventIsCorrect)
2014-12-01 23:55:08 +01:00
{
/* Get groups for this attendance events */
2017-01-19 20:55:31 +01:00
Grp_GetParCodsSeveralGrps ();
2014-12-01 23:55:08 +01:00
if (ItsANewAttEvent)
{
2016-09-07 18:02:25 +02:00
ReceivedAtt.Hidden = false; // New attendance events are visible by default
Att_CreateEvent (&ReceivedAtt,Description); // Add new attendance event to database
2014-12-01 23:55:08 +01:00
/***** Write success message *****/
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_SUCCESS,Txt_Created_new_event_X,
2019-02-15 23:38:44 +01:00
ReceivedAtt.Title);
2014-12-01 23:55:08 +01:00
}
else
{
Att_UpdateEvent (&ReceivedAtt,Description);
2014-12-01 23:55:08 +01:00
/***** Write success message *****/
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_SUCCESS,Txt_The_event_has_been_modified);
2014-12-01 23:55:08 +01:00
}
/* Free memory for list of selected groups */
Grp_FreeListCodSelectedGrps ();
}
else
Att_ReqCreatOrEditEvent ();
2014-12-01 23:55:08 +01:00
/***** Show attendance events again *****/
Att_SeeEvents ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Create a new attendance event *************************/
/*****************************************************************************/
void Att_CreateEvent (struct Att_Event *Event,const char *Description)
2014-12-01 23:55:08 +01:00
{
/***** Create a new attendance event *****/
Event->AttCod = Att_DB_CreateEvent (Event,Description);
2014-12-01 23:55:08 +01:00
/***** Create groups *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
Att_CreateGroups (Event->AttCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Update an existing attendance event **********************/
/*****************************************************************************/
void Att_UpdateEvent (struct Att_Event *Event,const char *Description)
2014-12-01 23:55:08 +01:00
{
/***** Update the data of the attendance event *****/
Att_DB_UpdateEvent (Event,Description);
2014-12-01 23:55:08 +01:00
/***** Update groups *****/
/* Remove old groups */
Att_DB_RemoveGrpsAssociatedToAnEvent (Event->AttCod);
2014-12-01 23:55:08 +01:00
/* Create new groups */
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
Att_CreateGroups (Event->AttCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Create groups of an attendance event **********************/
/*****************************************************************************/
static void Att_CreateGroups (long AttCod)
2014-12-01 23:55:08 +01:00
{
unsigned NumGrp;
2014-12-01 23:55:08 +01:00
/***** Create groups of the attendance event *****/
for (NumGrp = 0;
NumGrp < Gbl.Crs.Grps.LstGrpsSel.NumGrps;
NumGrp++)
Att_DB_CreateGroup (AttCod,Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrp]);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****** Get and write the names of the groups of an attendance event *********/
/*****************************************************************************/
static void Att_GetAndWriteNamesOfGrpsAssociatedToEvent (struct Att_Event *Event)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Group;
extern const char *Txt_Groups;
extern const char *Txt_and;
extern const char *Txt_The_whole_course;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumGrps;
unsigned NumGrp;
2014-12-01 23:55:08 +01:00
/***** Get groups associated to an attendance event from database *****/
NumGrps = Att_DB_GetGroupsAssociatedToEvent (&mysql_res,Event->AttCod);
2014-12-01 23:55:08 +01:00
/***** Begin container *****/
HTM_DIV_Begin ("class=\"%s_%s\"",
Event->Hidden ? "ASG_GRP_LIGHT" :
"ASG_GRP",
The_GetSuffix ());
2016-09-06 18:29:13 +02:00
/***** Write heading *****/
HTM_TxtColonNBSP (NumGrps == 1 ? Txt_Group :
Txt_Groups);
2016-09-06 18:29:13 +02:00
/***** Write groups *****/
if (NumGrps) // Groups found...
{
/* Get and write the group types and names */
for (NumGrp = 0;
NumGrp < NumGrps;
NumGrp++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
2016-09-06 18:29:13 +02:00
/* Write group type name (row[0]) and group name (row[1]) */
HTM_TxtF ("%s&nbsp;%s",row[0],row[1]);
2016-09-06 18:29:13 +02:00
/* Write the name of the room (row[2]) */
if (row[2]) // May be NULL because of LEFT JOIN
if (row[2][0])
HTM_TxtF ("&nbsp;(%s)",row[2]);
2016-09-06 18:29:13 +02:00
/* Write separator */
if (NumGrps >= 2)
{
if (NumGrp == NumGrps - 2)
HTM_TxtF (" %s ",Txt_and);
if (NumGrps >= 3)
if (NumGrp < NumGrps - 2)
HTM_Txt (", ");
}
}
}
else
HTM_TxtF ("%s&nbsp;%s",
Txt_The_whole_course,Gbl.Hierarchy.Crs.ShrtName);
2016-09-06 18:29:13 +02:00
/***** End container *****/
HTM_DIV_End ();
2016-09-06 18:29:13 +02:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
2016-09-06 18:29:13 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************** Remove all attendance events of a course ******************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Att_RemoveCrsEvents (long CrsCod)
2014-12-01 23:55:08 +01:00
{
/***** Remove students *****/
Att_DB_RemoveUsrsFromCrsEvents (CrsCod);
2014-12-01 23:55:08 +01:00
/***** Remove groups *****/
Att_DB_RemoveGrpsAssociatedToCrsEvents (CrsCod);
2014-12-01 23:55:08 +01:00
/***** Remove attendance events *****/
Att_DB_RemoveCrsEvents (CrsCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Get number of attendance events ***********************/
/*****************************************************************************/
// Returns the number of attendance events
// in this location (all the platform, the current degree or the current course)
2014-12-01 23:55:08 +01:00
unsigned Att_GetNumEvents (HieLvl_Level_t Scope,unsigned *NumNotif)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumAttEvents;
/***** Set default values *****/
NumAttEvents = 0;
*NumNotif = 0;
2014-12-01 23:55:08 +01:00
/***** Get number of attendance events from database *****/
if (Att_DB_GetNumEvents (&mysql_res,Scope))
2014-12-01 23:55:08 +01:00
{
/***** Get number of attendance events *****/
row = mysql_fetch_row (mysql_res);
if (sscanf (row[0],"%u",&NumAttEvents) != 1)
Err_ShowErrorAndExit ("Error when getting number of attendance events.");
2014-12-01 23:55:08 +01:00
/***** Get number of notifications by email *****/
if (row[1])
if (sscanf (row[1],"%u",NumNotif) != 1)
Err_ShowErrorAndExit ("Error when getting number of notifications of attendance events.");
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumAttEvents;
}
/*****************************************************************************/
/************************ Show one attendance event **************************/
/*****************************************************************************/
void Att_SeeOneEvent (void)
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2014-12-01 23:55:08 +01:00
/***** Get attendance event code *****/
Events.Event.AttCod = ParCod_GetAndCheckPar (ParCod_Att);
2020-04-06 16:00:06 +02:00
/***** Show event *****/
Att_ShowEvent (&Events);
}
static void Att_ShowEvent (struct Att_Events *Events)
{
extern const char *Hlp_USERS_Attendance;
extern const char *Txt_Event;
2014-12-01 23:55:08 +01:00
/***** Get parameters *****/
Events->SelectedOrder = Att_GetParAttOrder ();
Grp_GetParWhichGroups ();
Events->CurrentPage = Pag_GetParPagNum (Pag_ATT_EVENTS);
2014-12-01 23:55:08 +01:00
/***** Get data of this attendance event *****/
Att_GetEventDataByCodAndCheckCrs (&Events->Event);
Events->Event.NumStdsTotal = Att_DB_GetNumStdsTotalWhoAreInEvent (Events->Event.AttCod);
/***** Show attendance event inside a box *****/
2020-03-26 02:54:30 +01:00
Box_BoxTableBegin (NULL,Txt_Event,
Att_PutIconsOneEvent,Events,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Attendance,Box_NOT_CLOSABLE,2);
Att_ShowOneEventRow (Events,
true); // Show only this event
2019-11-25 23:18:08 +01:00
Box_BoxTableEnd ();
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
switch (Gbl.Usrs.Me.Role.Logged)
2014-12-01 23:55:08 +01:00
{
2017-05-18 19:13:41 +02:00
case Rol_STD:
Att_ListEventOnlyMeAsStudent (&Events->Event);
2014-12-01 23:55:08 +01:00
break;
2017-05-21 21:23:13 +02:00
case Rol_NET:
2017-05-18 19:13:41 +02:00
case Rol_TCH:
2015-04-07 21:44:24 +02:00
case Rol_SYS_ADM:
2014-12-01 23:55:08 +01:00
/***** Show list of students *****/
Att_ListEventStudents (Events);
2014-12-01 23:55:08 +01:00
break;
default:
break;
}
}
/*****************************************************************************/
/*************** Put contextual icons in an attendance event *****************/
/*****************************************************************************/
static void Att_PutIconsOneEvent (void *Events)
{
char *Anchor = NULL;
/***** Set anchor string *****/
Frm_SetAnchorStr (((struct Att_Events *) Events)->Event.AttCod,&Anchor);
/***** Put icons to edit resource link *****/
Att_PutFormsToRemEditOneEvent ((struct Att_Events *) Events,Anchor);
/***** Free anchor string *****/
Frm_FreeAnchorStr (Anchor);
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*********************** List me as student in one event *********************/
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
// Event must be filled before calling this function
2014-12-01 23:55:08 +01:00
static void Att_ListEventOnlyMeAsStudent (struct Att_Event *Event)
2014-12-01 23:55:08 +01:00
{
2016-11-13 21:08:14 +01:00
extern const char *Hlp_USERS_Attendance;
2019-02-18 18:27:45 +01:00
extern const char *Txt_Attendance;
2014-12-04 01:19:42 +01:00
extern const char *Txt_Student_comment;
extern const char *Txt_Teachers_comment;
2015-03-12 14:45:40 +01:00
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2019-02-18 18:27:45 +01:00
extern const char *Txt_Save_changes;
2014-12-01 23:55:08 +01:00
2019-03-26 11:53:21 +01:00
/***** Get my setting about photos in users' list for current course *****/
Set_GetMyPrefAboutListWithPhotosFromDB ();
2014-12-01 23:55:08 +01:00
2019-02-18 18:27:45 +01:00
/***** List students (only me) *****/
2019-10-26 02:19:42 +02:00
/* Begin box */
2020-03-26 02:54:30 +01:00
Box_BoxBegin (NULL,Txt_Attendance,
NULL,NULL,
2019-02-18 18:27:45 +01:00
Hlp_USERS_Attendance,Box_NOT_CLOSABLE);
/***** Begin form *****/
if (Event->Open)
{
Frm_BeginForm (ActRecAttMe);
ParCod_PutPar (ParCod_Att,Event->AttCod);
}
/***** List students (only me) *****/
/* Begin table */
HTM_TABLE_BeginWideMarginPadding (2);
2019-02-18 18:27:45 +01:00
/* Header */
HTM_TR_Begin (NULL);
2019-10-11 01:02:51 +02:00
HTM_TH_Empty (3);
if (Gbl.Usrs.Listing.WithPhotos)
HTM_TH_Empty (1);
HTM_TH_Span (Txt_ROLES_SINGUL_Abc[Rol_STD][Usr_SEX_UNKNOWN],HTM_HEAD_LEFT,1,2,NULL);
HTM_TH (Txt_Student_comment ,HTM_HEAD_LEFT);
HTM_TH (Txt_Teachers_comment ,HTM_HEAD_LEFT);
2019-10-11 01:02:51 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
/* List of students (only me) */
Att_WriteRowUsrToCallTheRoll (1,&Gbl.Usrs.Me.UsrDat,Event);
2014-12-01 23:55:08 +01:00
/* End table */
HTM_TABLE_End ();
2014-12-01 23:55:08 +01:00
/* Send button */
if (Event->Open)
{
Btn_PutConfirmButton (Txt_Save_changes);
Frm_EndForm ();
}
2019-02-18 18:27:45 +01:00
/* End box */
2019-10-25 22:48:34 +02:00
Box_BoxEnd ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** List students who attended to one event *********************/
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
// Event must be filled before calling this function
2014-12-01 23:55:08 +01:00
static void Att_ListEventStudents (struct Att_Events *Events)
2014-12-01 23:55:08 +01:00
{
2016-11-13 21:08:14 +01:00
extern const char *Hlp_USERS_Attendance;
2015-04-11 17:33:14 +02:00
extern const char *Txt_Attendance;
2014-12-04 01:19:42 +01:00
extern const char *Txt_Student_comment;
extern const char *Txt_Teachers_comment;
2015-03-12 14:45:40 +01:00
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2019-02-18 18:27:45 +01:00
extern const char *Txt_Save_changes;
2019-04-11 23:15:40 +02:00
unsigned NumUsr;
struct Usr_Data UsrDat;
2014-12-01 23:55:08 +01:00
2016-11-25 03:21:02 +01:00
/***** Get groups to show ******/
Grp_GetParCodsSeveralGrpsToShowUsrs ();
2014-12-01 23:55:08 +01:00
/***** Get and order list of students in this course *****/
Usr_GetListUsrs (HieLvl_CRS,Rol_STD);
2014-12-01 23:55:08 +01:00
2019-10-26 02:19:42 +02:00
/***** Begin box *****/
2020-03-26 02:54:30 +01:00
Box_BoxBegin (NULL,Txt_Attendance,
NULL,NULL,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Attendance,Box_NOT_CLOSABLE);
2016-11-25 03:21:02 +01:00
/***** Form to select groups *****/
Grp_ShowFormToSelectSeveralGroups (Att_PutParAttCod,Events,Grp_MY_GROUPS);
2017-05-25 11:04:38 +02:00
/***** Begin section with user list *****/
HTM_SECTION_Begin (Usr_USER_LIST_SECTION_ID);
2016-11-25 03:21:02 +01:00
if (Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs)
{
/***** Get my preference about photos in users' list for current course *****/
Set_GetMyPrefAboutListWithPhotosFromDB ();
2014-12-01 23:55:08 +01:00
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
2014-12-01 23:55:08 +01:00
/* Begin form */
Frm_BeginForm (ActRecAttStd);
ParCod_PutPar (ParCod_Att,Events->Event.AttCod);
Grp_PutParsCodGrps ();
2014-12-01 23:55:08 +01:00
/* Begin table */
HTM_TABLE_BeginWideMarginPadding (2);
2017-05-01 12:36:24 +02:00
/* Header */
HTM_TR_Begin (NULL);
2019-10-11 01:02:51 +02:00
HTM_TH_Empty (3);
if (Gbl.Usrs.Listing.WithPhotos)
HTM_TH_Empty (1);
HTM_TH_Span (Txt_ROLES_SINGUL_Abc[Rol_STD][Usr_SEX_UNKNOWN],HTM_HEAD_LEFT,1,2,NULL);
HTM_TH (Txt_Student_comment ,HTM_HEAD_LEFT);
HTM_TH (Txt_Teachers_comment ,HTM_HEAD_LEFT);
2019-10-11 01:02:51 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
/* List of students */
for (NumUsr = 0;
NumUsr < Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs;
NumUsr++)
{
/* Copy user's basic data from list */
Usr_CopyBasicUsrDataFromList (&UsrDat,&Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr]);
2016-07-26 02:41:31 +02:00
/* Get list of user's IDs */
ID_GetListIDsFromUsrCod (&UsrDat);
2016-07-26 02:41:31 +02:00
Att_WriteRowUsrToCallTheRoll (NumUsr + 1,&UsrDat,&Events->Event);
}
2014-12-01 23:55:08 +01:00
/* End table */
HTM_TABLE_End ();
2016-11-25 03:21:02 +01:00
/* Send button */
Btn_PutConfirmButton (Txt_Save_changes);
2014-12-01 23:55:08 +01:00
/***** End form *****/
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
else // Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs == 0
/***** Show warning indicating no students found *****/
Usr_ShowWarningNoUsersFound (Rol_STD);
2014-12-01 23:55:08 +01:00
/***** End section with user list *****/
HTM_SECTION_End ();
2017-05-25 11:04:38 +02:00
2017-06-12 14:16:33 +02:00
/***** End box *****/
2019-10-25 22:48:34 +02:00
Box_BoxEnd ();
2016-11-25 03:21:02 +01:00
2014-12-01 23:55:08 +01:00
/***** Free memory for students list *****/
2017-05-18 19:13:41 +02:00
Usr_FreeUsrsList (Rol_STD);
2014-12-01 23:55:08 +01:00
/***** Free memory for list of selected groups *****/
Grp_FreeListCodSelectedGrps ();
}
/*****************************************************************************/
/************** Write parameter with code of attendance event ****************/
/*****************************************************************************/
static void Att_PutParAttCod (void *Events)
{
if (Events)
ParCod_PutPar (ParCod_Att,((struct Att_Events *) Events)->Event.AttCod);
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-04-11 23:15:40 +02:00
/************** Write a row of a table with the data of a user ***************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-04-11 23:15:40 +02:00
static void Att_WriteRowUsrToCallTheRoll (unsigned NumUsr,
struct Usr_Data *UsrDat,
2020-04-06 16:00:06 +02:00
struct Att_Event *Event)
2014-12-01 23:55:08 +01:00
{
static const char *ClassPhoto[PhoSha_NUM_SHAPES] =
{
[PhoSha_SHAPE_CIRCLE ] = "PHOTOC45x60",
[PhoSha_SHAPE_ELLIPSE ] = "PHOTOE45x60",
[PhoSha_SHAPE_OVAL ] = "PHOTOO45x60",
[PhoSha_SHAPE_RECTANGLE] = "PHOTOR45x60",
};
2014-12-01 23:55:08 +01:00
bool Present;
2017-01-28 15:58:46 +01:00
char CommentStd[Cns_MAX_BYTES_TEXT + 1];
char CommentTch[Cns_MAX_BYTES_TEXT + 1];
2017-05-20 12:04:12 +02:00
bool ICanChangeStdAttendance;
bool ICanEditStdComment;
bool ICanEditTchComment;
/***** Set who can edit *****/
2017-06-04 18:18:54 +02:00
switch (Gbl.Usrs.Me.Role.Logged)
2017-05-20 12:04:12 +02:00
{
case Rol_STD:
// A student can see only her/his attendance
if (!Usr_ItsMe (UsrDat->UsrCod))
Err_ShowErrorAndExit ("Wrong call.");
2017-05-20 12:04:12 +02:00
ICanChangeStdAttendance = false;
2020-04-06 16:00:06 +02:00
ICanEditStdComment = Event->Open; // Attendance event is open
2017-05-20 12:04:12 +02:00
ICanEditTchComment = false;
break;
case Rol_TCH:
ICanChangeStdAttendance = true;
ICanEditStdComment = false;
ICanEditTchComment = true;
break;
case Rol_SYS_ADM:
ICanChangeStdAttendance = true;
ICanEditStdComment = false;
ICanEditTchComment = false;
break;
default:
ICanChangeStdAttendance = false;
ICanEditStdComment = false;
ICanEditTchComment = false;
break;
}
2014-12-01 23:55:08 +01:00
2019-02-13 21:24:54 +01:00
/***** Check if this student is already present in the current event *****/
Present = Att_CheckIfUsrIsPresentInEventAndGetComments (Event->AttCod,UsrDat->UsrCod,CommentStd,CommentTch);
2014-12-01 23:55:08 +01:00
/***** Begin table row *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
/***** Icon to show if the user is already present *****/
HTM_TD_Begin ("class=\"BT %s\"",The_GetColorRows ());
HTM_LABEL_Begin ("for=\"Std%u\"",NumUsr);
Att_PutCheckOrCross (Present);
HTM_LABEL_End ();
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
/***** Checkbox to select user *****/
HTM_TD_Begin ("class=\"CT %s\"",The_GetColorRows ());
HTM_INPUT_CHECKBOX ("UsrCodStd",HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"Std%u\" value=\"%s\"%s%s",
NumUsr,UsrDat->EnUsrCod,
Present ? " checked=\"checked\"" : "",
ICanChangeStdAttendance ? "" :
" disabled=\"disabled\"");
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
/***** Write number of student in the list *****/
HTM_TD_Begin ("class=\"RT %s_%s %s\"",
UsrDat->Accepted ? "DAT_STRONG" :
"DAT",
The_GetSuffix (),
The_GetColorRows ());
HTM_Unsigned (NumUsr);
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
/***** Show student's photo *****/
if (Gbl.Usrs.Listing.WithPhotos)
{
HTM_TD_Begin ("class=\"%s LT\"",The_GetColorRows ());
Pho_ShowUsrPhotoIfAllowed (UsrDat,
ClassPhoto[Gbl.Prefs.PhotoShape],Pho_ZOOM);
HTM_TD_End ();
}
/***** Write user's ID ******/
HTM_TD_Begin ("class=\"LT %s_%s %s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix (),
The_GetColorRows ());
ID_WriteUsrIDs (UsrDat,NULL);
HTM_TD_End ();
/***** Write student's name *****/
HTM_TD_Begin ("class=\"LT %s_%s %s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix (),
The_GetColorRows ());
HTM_Txt (UsrDat->Surname1);
if (UsrDat->Surname2[0])
HTM_TxtF ("&nbsp;%s",UsrDat->Surname2);
HTM_TxtF (", %s",UsrDat->FrstName);
HTM_TD_End ();
/***** Student's comment: write form or text */
HTM_TD_Begin ("class=\"LT %s_%s %s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix (),
The_GetColorRows ());
if (ICanEditStdComment) // Show with form
{
HTM_TEXTAREA_Begin ("name=\"CommentStd%s\" cols=\"40\" rows=\"3\""
" class=\"INPUT_%s\"",
UsrDat->EnUsrCod,
The_GetSuffix ());
HTM_Txt (CommentStd);
HTM_TEXTAREA_End ();
}
else // Show without form
{
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
CommentStd,Cns_MAX_BYTES_TEXT,false);
HTM_Txt (CommentStd);
}
HTM_TD_End ();
/***** Teacher's comment: write form, text or nothing */
HTM_TD_Begin ("class=\"LT %s_%s %s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix (),
The_GetColorRows ());
if (ICanEditTchComment) // Show with form
{
HTM_TEXTAREA_Begin ("name=\"CommentTch%s\" cols=\"40\" rows=\"3\""
" class=\"INPUT_%s\"",
UsrDat->EnUsrCod,
The_GetSuffix ());
HTM_Txt (CommentTch);
HTM_TEXTAREA_End ();
}
else if (Event->CommentTchVisible) // Show without form
{
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
CommentTch,Cns_MAX_BYTES_TEXT,false);
HTM_Txt (CommentTch);
}
HTM_TD_End ();
/***** End table row *****/
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
The_ChangeRowColor ();
2014-12-01 23:55:08 +01:00
}
2018-12-03 19:49:54 +01:00
/*****************************************************************************/
/**************** Put link to view one attendance event **********************/
/*****************************************************************************/
static void Att_PutLinkEvent (struct Att_Event *Event,
const char *Title,const char *Txt)
2018-12-03 19:49:54 +01:00
{
/***** Begin form *****/
Frm_BeginForm (ActSeeOneAtt);
ParCod_PutPar (ParCod_Att,Event->AttCod);
Att_PutParsCodGrps (Event->AttCod);
/***** Link to view attendance event *****/
HTM_BUTTON_Submit_Begin (Title,"class=\"LT BT_LINK %s_%s\"",
Event->Hidden ? "ASG_TITLE_LIGHT" :
"ASG_TITLE",
The_GetSuffix ());
HTM_Txt (Txt);
HTM_BUTTON_End ();
/***** End form *****/
2018-12-03 19:49:54 +01:00
Frm_EndForm ();
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/****** Put parameters with the default groups in an attendance event ********/
/*****************************************************************************/
void Att_PutParsCodGrps (long AttCod)
2014-12-01 23:55:08 +01:00
{
2019-11-03 13:19:32 +01:00
extern const char *Par_SEPARATOR_PARAM_MULTIPLE;
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumGrp;
unsigned NumGrps;
2019-11-03 13:19:32 +01:00
size_t MaxLengthGrpCods;
char *GrpCods;
2014-12-01 23:55:08 +01:00
/***** Get groups associated to an attendance event from database *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.NumGrps)
NumGrps = Att_DB_GetGrpCodsAssociatedToEvent (&mysql_res,AttCod);
2014-12-01 23:55:08 +01:00
else
NumGrps = 0;
/***** Get groups *****/
if (NumGrps) // Groups found...
{
2019-11-03 13:19:32 +01:00
MaxLengthGrpCods = NumGrps * (1 + 20) - 1;
if ((GrpCods = malloc (MaxLengthGrpCods + 1)) == NULL)
Err_NotEnoughMemoryExit ();
2019-11-08 01:10:32 +01:00
GrpCods[0] = '\0';
2014-12-01 23:55:08 +01:00
2014-12-08 01:30:47 +01:00
/* Get groups */
2014-12-01 23:55:08 +01:00
for (NumGrp = 0;
NumGrp < NumGrps;
NumGrp++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
2019-11-03 13:19:32 +01:00
/* Append group code to list */
2014-12-01 23:55:08 +01:00
if (NumGrp)
2019-11-03 13:19:32 +01:00
Str_Concat (GrpCods,Par_SEPARATOR_PARAM_MULTIPLE,MaxLengthGrpCods);
Str_Concat (GrpCods,row[0],MaxLengthGrpCods);
2014-12-01 23:55:08 +01:00
}
Par_PutParString (NULL,"GrpCods",GrpCods);
2019-11-06 19:45:20 +01:00
free (GrpCods);
2014-12-01 23:55:08 +01:00
}
else
/***** Write the boolean parameter that indicates
if all groups should be listed *****/
Par_PutParChar ("AllGroups",'Y');
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.NumGrps)
2014-12-01 23:55:08 +01:00
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/*************** Save me as students who attended to an event ****************/
/*****************************************************************************/
void Att_RegisterMeAsStdInEvent (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Your_comment_has_been_updated;
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
2014-12-01 23:55:08 +01:00
bool Present;
char *ParName;
2017-01-28 15:58:46 +01:00
char CommentStd[Cns_MAX_BYTES_TEXT + 1];
char CommentTch[Cns_MAX_BYTES_TEXT + 1];
2014-12-01 23:55:08 +01:00
2020-04-06 16:00:06 +02:00
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2014-12-01 23:55:08 +01:00
/***** Get attendance event code *****/
Events.Event.AttCod = ParCod_GetAndCheckPar (ParCod_Att);
Att_GetEventDataByCodAndCheckCrs (&Events.Event); // This checks that event belong to current course
2014-12-01 23:55:08 +01:00
if (Events.Event.Open)
2014-12-01 23:55:08 +01:00
{
/***** Get comments for this student *****/
Present = Att_CheckIfUsrIsPresentInEventAndGetComments (Events.Event.AttCod,Gbl.Usrs.Me.UsrDat.UsrCod,
2018-10-10 23:56:42 +02:00
CommentStd,CommentTch);
if (asprintf (&ParName,"CommentStd%s",Gbl.Usrs.Me.UsrDat.EnUsrCod) < 0)
Err_NotEnoughMemoryExit ();
Par_GetParHTML (ParName,CommentStd,Cns_MAX_BYTES_TEXT);
free (ParName);
2014-12-01 23:55:08 +01:00
if (Present ||
CommentStd[0] ||
CommentTch[0])
/***** Register student *****/
Att_DB_RegUsrInEventChangingComments (Events.Event.AttCod,Gbl.Usrs.Me.UsrDat.UsrCod,
Present,CommentStd,CommentTch);
2014-12-01 23:55:08 +01:00
else
/***** Remove student *****/
Att_DB_RemoveUsrFromEvent (Events.Event.AttCod,Gbl.Usrs.Me.UsrDat.UsrCod);
2014-12-01 23:55:08 +01:00
/***** Write final message *****/
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_SUCCESS,Txt_Your_comment_has_been_updated);
2014-12-01 23:55:08 +01:00
}
/***** Show the attendance event again *****/
2020-04-06 16:00:06 +02:00
Att_ShowEvent (&Events);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Save students who attended to an event ********************/
/*****************************************************************************/
/* Algorithm:
2017-05-18 19:13:41 +02:00
1. Get list of students in the groups selected: Gbl.Usrs.LstUsrs[Rol_STD]
2014-12-01 23:55:08 +01:00
2. Mark all students in the groups selected setting Remove=true
2019-03-11 13:33:34 +01:00
3. Get list of students marked as present by me: Gbl.Usrs.Selected.List[Rol_STD]
4. Loop over the list Gbl.Usrs.Selected.List[Rol_STD],
2014-12-01 23:55:08 +01:00
that holds the list of the students marked as present,
2017-05-18 19:13:41 +02:00
marking the students in Gbl.Usrs.LstUsrs[Rol_STD].Lst as Remove=false
5. Delete from att_users all students marked as Remove=true
6. Replace (insert without duplicated) into att_users all students marked as Remove=false
2014-12-01 23:55:08 +01:00
*/
void Att_RegisterStudentsInEvent (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Presents;
extern const char *Txt_Absents;
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
2019-04-11 23:15:40 +02:00
unsigned NumUsr;
2014-12-01 23:55:08 +01:00
const char *Ptr;
bool Present;
char *ParName;
2014-12-01 23:55:08 +01:00
unsigned NumStdsPresent;
unsigned NumStdsAbsent;
struct Usr_Data UsrData;
2017-01-28 15:58:46 +01:00
char CommentStd[Cns_MAX_BYTES_TEXT + 1];
char CommentTch[Cns_MAX_BYTES_TEXT + 1];
2014-12-01 23:55:08 +01:00
2020-04-06 16:00:06 +02:00
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2014-12-01 23:55:08 +01:00
/***** Get attendance event code *****/
Events.Event.AttCod = ParCod_GetAndCheckPar (ParCod_Att);
Att_GetEventDataByCodAndCheckCrs (&Events.Event); // This checks that event belong to current course
2014-12-01 23:55:08 +01:00
/***** Get groups selected *****/
Grp_GetParCodsSeveralGrpsToShowUsrs ();
2017-05-18 19:13:41 +02:00
/***** 1. Get list of students in the groups selected: Gbl.Usrs.LstUsrs[Rol_STD] *****/
2014-12-01 23:55:08 +01:00
/* Get list of students in the groups selected */
Usr_GetListUsrs (HieLvl_CRS,Rol_STD);
2014-12-01 23:55:08 +01:00
2017-05-18 19:13:41 +02:00
if (Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs) // If there are students in the groups selected...
2014-12-01 23:55:08 +01:00
{
/***** 2. Mark all students in the groups selected setting Remove=true *****/
2019-04-11 23:15:40 +02:00
for (NumUsr = 0;
NumUsr < Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs;
NumUsr++)
Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].Remove = true;
2014-12-01 23:55:08 +01:00
2019-03-11 13:33:34 +01:00
/***** 3. Get list of students marked as present by me: Gbl.Usrs.Selected.List[Rol_STD] *****/
2019-11-15 03:34:48 +01:00
Usr_GetListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected);
2014-12-01 23:55:08 +01:00
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrData);
2019-03-11 13:33:34 +01:00
/***** 4. Loop over the list Gbl.Usrs.Selected.List[Rol_STD],
2014-12-01 23:55:08 +01:00
that holds the list of the students marked as present,
2017-05-18 19:13:41 +02:00
marking the students in Gbl.Usrs.LstUsrs[Rol_STD].Lst as Remove=false *****/
2019-03-11 13:33:34 +01:00
Ptr = Gbl.Usrs.Selected.List[Rol_STD];
2014-12-01 23:55:08 +01:00
while (*Ptr)
{
Par_GetNextStrUntilSeparParMult (&Ptr,UsrData.EnUsrCod,
2017-03-13 14:22:36 +01:00
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
2014-12-01 23:55:08 +01:00
Usr_GetUsrCodFromEncryptedUsrCod (&UsrData);
2016-07-26 02:41:31 +02:00
if (UsrData.UsrCod > 0) // Student exists in database
2014-12-01 23:55:08 +01:00
/***** Mark student to not be removed *****/
2019-04-11 23:15:40 +02:00
for (NumUsr = 0;
NumUsr < Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs;
NumUsr++)
if (Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].UsrCod == UsrData.UsrCod)
2014-12-01 23:55:08 +01:00
{
2019-04-11 23:15:40 +02:00
Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].Remove = false;
2014-12-01 23:55:08 +01:00
break; // Found! Exit loop
}
}
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrData);
/***** Free memory *****/
2016-07-04 14:03:04 +02:00
/* Free memory used by list of selected students' codes */
2019-11-15 03:34:48 +01:00
Usr_FreeListsSelectedEncryptedUsrsCods (&Gbl.Usrs.Selected);
2014-12-01 23:55:08 +01:00
// 5. Delete from att_users all students marked as Remove=true
// 6. Replace (insert without duplicated) into att_users all students marked as Remove=false
2019-04-11 23:15:40 +02:00
for (NumUsr = 0, NumStdsAbsent = NumStdsPresent = 0;
NumUsr < Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs;
NumUsr++)
2014-12-01 23:55:08 +01:00
{
/***** Get comments for this student *****/
Att_CheckIfUsrIsPresentInEventAndGetComments (Events.Event.AttCod,
Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].UsrCod,
CommentStd,
CommentTch);
if (asprintf (&ParName,"CommentTch%s",
Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].EnUsrCod) < 0)
Err_NotEnoughMemoryExit ();
Par_GetParHTML (ParName,CommentTch,Cns_MAX_BYTES_TEXT);
free (ParName);
2014-12-01 23:55:08 +01:00
2019-04-11 23:15:40 +02:00
Present = !Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].Remove;
2014-12-01 23:55:08 +01:00
if (Present ||
CommentStd[0] ||
CommentTch[0])
/***** Register student *****/
Att_DB_RegUsrInEventChangingComments (Events.Event.AttCod,Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].UsrCod,
Present,CommentStd,CommentTch);
2014-12-01 23:55:08 +01:00
else
/***** Remove student *****/
Att_DB_RemoveUsrFromEvent (Events.Event.AttCod,Gbl.Usrs.LstUsrs[Rol_STD].Lst[NumUsr].UsrCod);
2014-12-01 23:55:08 +01:00
if (Present)
NumStdsPresent++;
else
NumStdsAbsent++;
}
/***** Free memory for students list *****/
2017-05-18 19:13:41 +02:00
Usr_FreeUsrsList (Rol_STD);
2014-12-01 23:55:08 +01:00
/***** Write final message *****/
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_INFO,"%s: %u<br />"
2019-02-15 23:38:44 +01:00
"%s: %u",
Txt_Presents,NumStdsPresent,
Txt_Absents ,NumStdsAbsent );
2014-12-01 23:55:08 +01:00
}
2017-05-18 19:13:41 +02:00
else // Gbl.Usrs.LstUsrs[Rol_STD].NumUsrs == 0
2017-02-09 19:27:18 +01:00
/***** Show warning indicating no students found *****/
2017-05-18 19:13:41 +02:00
Usr_ShowWarningNoUsersFound (Rol_STD);
2014-12-01 23:55:08 +01:00
/***** Show the attendance event again *****/
2020-04-06 16:00:06 +02:00
Att_ShowEvent (&Events);
2014-12-01 23:55:08 +01:00
/***** Free memory for list of groups selected *****/
Grp_FreeListCodSelectedGrps ();
}
/*****************************************************************************/
2019-11-13 21:31:06 +01:00
/********* Get number of users from a list who attended to an event **********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static unsigned Att_GetNumUsrsFromAListWhoAreInEvent (long AttCod,
long LstSelectedUsrCods[],
unsigned NumUsrsInList)
2014-12-01 23:55:08 +01:00
{
2019-11-14 02:29:18 +01:00
char *SubQueryUsrs;
2019-11-13 21:31:06 +01:00
unsigned NumUsrsInAttEvent;
2014-12-01 23:55:08 +01:00
2019-04-11 23:15:40 +02:00
if (NumUsrsInList)
2014-12-01 23:55:08 +01:00
{
2019-11-13 21:31:06 +01:00
/***** Create subquery string *****/
Usr_CreateSubqueryUsrCods (LstSelectedUsrCods,NumUsrsInList,
2019-11-14 02:29:18 +01:00
&SubQueryUsrs);
2014-12-01 23:55:08 +01:00
/***** Get number of users from list in attendance event from database ****/
NumUsrsInAttEvent = Att_DB_GetNumStdsFromListWhoAreInEvent (AttCod,SubQueryUsrs);
2018-11-04 21:28:11 +01:00
/***** Free memory for subquery string *****/
2019-11-14 02:29:18 +01:00
Usr_FreeSubqueryUsrCods (SubQueryUsrs);
2014-12-01 23:55:08 +01:00
}
2019-11-13 21:31:06 +01:00
else
NumUsrsInAttEvent = 0;
return NumUsrsInAttEvent;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Check if a student attended to an event *******************/
/*****************************************************************************/
static bool Att_CheckIfUsrIsPresentInEvent (long AttCod,long UsrCod)
2014-12-01 23:55:08 +01:00
{
bool Present;
Att_DB_CheckIfUsrIsInTableAttUsr (AttCod,UsrCod,&Present);
2014-12-01 23:55:08 +01:00
return Present;
}
/*****************************************************************************/
/***************** Check if a student attended to an event *******************/
/*****************************************************************************/
static bool Att_CheckIfUsrIsPresentInEventAndGetComments (long AttCod,long UsrCod,
2017-01-17 03:10:43 +01:00
char CommentStd[Cns_MAX_BYTES_TEXT + 1],
char CommentTch[Cns_MAX_BYTES_TEXT + 1])
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
bool Present;
/***** Check if a students is registered in an event in database *****/
if (Att_DB_GetPresentAndComments (&mysql_res,AttCod,UsrCod))
2014-12-01 23:55:08 +01:00
{
/* Get row */
row = mysql_fetch_row (mysql_res);
/* Get if present (row[0]) */
2016-09-07 18:48:10 +02:00
Present = (row[0][0] == 'Y');
2014-12-01 23:55:08 +01:00
/* Get student's (row[1]) and teacher's (row[2]) comment */
Str_Copy (CommentStd,row[1],Cns_MAX_BYTES_TEXT);
Str_Copy (CommentTch,row[2],Cns_MAX_BYTES_TEXT);
2014-12-01 23:55:08 +01:00
}
else // User is not present
{
Present = false;
CommentStd[0] =
CommentTch[0] = '\0';
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return Present;
}
/*****************************************************************************/
2019-04-11 23:15:40 +02:00
/********** Request listing attendance of users to several events ************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2020-04-13 16:39:15 +02:00
void Att_ReqListUsrsAttendanceCrs (void)
{
Att_TypeOfView_t TypeOfView = Att_VIEW_SEL_USR;
Att_ReqListOrPrintUsrsAttendanceCrs (&TypeOfView);
}
static void Att_ReqListOrPrintUsrsAttendanceCrs (void *TypeOfView)
2014-12-01 23:55:08 +01:00
{
2016-11-27 23:08:29 +01:00
extern const char *Hlp_USERS_Attendance_attendance_list;
2019-04-11 23:15:40 +02:00
extern const char *Txt_Attendance_list;
2019-03-12 10:28:50 +01:00
extern const char *Txt_View_attendance;
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
2020-04-08 18:18:46 +02:00
switch (*((Att_TypeOfView_t *) TypeOfView))
2020-04-08 03:06:45 +02:00
{
case Att_VIEW_SEL_USR:
case Att_PRNT_SEL_USR:
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
/***** Get list of attendance events *****/
Att_GetListEvents (&Events,Att_OLDEST_FIRST);
2020-04-08 03:06:45 +02:00
/***** List users to select some of them *****/
Usr_PutFormToSelectUsrsToGoToAct (&Gbl.Usrs.Selected,
ActSeeLstUsrAtt,
NULL,NULL,
Txt_Attendance_list,
Hlp_USERS_Attendance_attendance_list,
Txt_View_attendance,
false); // Do not put form with date range
/***** Free list of attendance events *****/
Att_FreeListEvents (&Events);
2020-04-08 03:06:45 +02:00
break;
default:
Err_WrongTypeExit ();
2020-04-08 03:06:45 +02:00
break;
}
2015-11-13 01:27:44 +01:00
}
/*****************************************************************************/
/********** List my attendance (I am a student) to several events ************/
/*****************************************************************************/
2019-11-14 17:53:50 +01:00
void Att_ListMyAttendanceCrs (void)
2015-11-13 01:27:44 +01:00
{
2020-04-06 16:00:06 +02:00
Att_ListOrPrintMyAttendanceCrs (Att_VIEW_ONLY_ME);
2015-11-13 01:27:44 +01:00
}
2019-11-14 17:53:50 +01:00
void Att_PrintMyAttendanceCrs (void)
2015-11-13 01:27:44 +01:00
{
2020-04-06 16:00:06 +02:00
Att_ListOrPrintMyAttendanceCrs (Att_PRNT_ONLY_ME);
2015-11-13 01:27:44 +01:00
}
2020-04-06 16:00:06 +02:00
static void Att_ListOrPrintMyAttendanceCrs (Att_TypeOfView_t TypeOfView)
2015-11-13 01:27:44 +01:00
{
2018-10-18 09:59:38 +02:00
extern const char *Hlp_USERS_Attendance_attendance_list;
extern const char *Txt_Attendance;
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
2015-11-13 01:27:44 +01:00
unsigned NumAttEvent;
2020-04-08 03:06:45 +02:00
switch (TypeOfView)
{
case Att_VIEW_ONLY_ME:
case Att_PRNT_ONLY_ME:
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2020-04-06 16:00:06 +02:00
2020-04-08 03:06:45 +02:00
/***** Get list of attendance events *****/
Att_GetListEvents (&Events,Att_OLDEST_FIRST);
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Get boolean parameter that indicates if details must be shown *****/
Events.ShowDetails = Par_GetParBool ("ShowDetails");
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Get list of groups selected ******/
Grp_GetParCodsSeveralGrpsToShowUsrs ();
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Get number of students in each event *****/
for (NumAttEvent = 0;
NumAttEvent < Events.Num;
NumAttEvent++)
/* Get number of students in this event */
Events.Lst[NumAttEvent].NumStdsFromList =
Att_GetNumUsrsFromAListWhoAreInEvent (Events.Lst[NumAttEvent].AttCod,
2020-04-08 03:06:45 +02:00
&Gbl.Usrs.Me.UsrDat.UsrCod,1);
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Get list of attendance events selected *****/
Att_GetListSelectedAttCods (&Events);
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Begin box *****/
switch (TypeOfView)
{
case Att_VIEW_ONLY_ME:
Box_BoxBegin (NULL,Txt_Attendance,
2020-04-08 13:40:21 +02:00
Att_PutIconsMyAttList,&Events,
2020-04-08 03:06:45 +02:00
Hlp_USERS_Attendance_attendance_list,Box_NOT_CLOSABLE);
break;
case Att_PRNT_ONLY_ME:
Box_BoxBegin (NULL,Txt_Attendance,
NULL,NULL,
NULL,Box_NOT_CLOSABLE);
break;
default:
Err_WrongTypeExit ();
2020-04-08 03:06:45 +02:00
break;
}
2018-10-18 09:59:38 +02:00
2020-04-08 03:06:45 +02:00
/***** List events to select *****/
Att_ListEventsToSelect (&Events,TypeOfView);
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Get my preference about photos in users' list for current course *****/
Set_GetMyPrefAboutListWithPhotosFromDB ();
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Show table with attendances for every student in list *****/
Att_ListUsrsAttendanceTable (&Events,TypeOfView,1,&Gbl.Usrs.Me.UsrDat.UsrCod);
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Show details or put button to show details *****/
if (Events.ShowDetails)
Att_ListStdsWithAttEventsDetails (&Events,1,&Gbl.Usrs.Me.UsrDat.UsrCod);
2018-10-18 09:59:38 +02:00
2020-04-08 03:06:45 +02:00
/***** End box *****/
Box_BoxEnd ();
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Free memory for list of attendance events selected *****/
free (Events.StrAttCodsSelected);
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Free list of groups selected *****/
Grp_FreeListCodSelectedGrps ();
2015-11-13 01:27:44 +01:00
2020-04-08 03:06:45 +02:00
/***** Free list of attendance events *****/
Att_FreeListEvents (&Events);
2020-04-08 03:06:45 +02:00
break;
default:
Err_WrongTypeExit ();
2020-04-08 03:06:45 +02:00
break;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-04-11 23:15:40 +02:00
/*************** List attendance of users to several events ******************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-11-14 17:53:50 +01:00
void Att_ListUsrsAttendanceCrs (void)
{
2020-04-06 16:00:06 +02:00
Att_GetUsrsAndListOrPrintAttendanceCrs (Att_VIEW_SEL_USR);
2019-11-14 17:53:50 +01:00
}
void Att_PrintUsrsAttendanceCrs (void)
2015-11-13 01:27:44 +01:00
{
2020-04-06 16:00:06 +02:00
Att_GetUsrsAndListOrPrintAttendanceCrs (Att_PRNT_SEL_USR);
2015-11-13 01:27:44 +01:00
}
2020-04-06 16:00:06 +02:00
static void Att_GetUsrsAndListOrPrintAttendanceCrs (Att_TypeOfView_t TypeOfView)
2015-11-13 01:27:44 +01:00
{
2019-11-15 03:34:48 +01:00
Usr_GetSelectedUsrsAndGoToAct (&Gbl.Usrs.Selected,
2020-04-06 16:00:06 +02:00
Att_ListOrPrintUsrsAttendanceCrs,&TypeOfView,
2020-04-13 16:39:15 +02:00
Att_ReqListOrPrintUsrsAttendanceCrs,&TypeOfView);
2015-11-13 01:27:44 +01:00
}
2020-04-06 16:00:06 +02:00
static void Att_ListOrPrintUsrsAttendanceCrs (void *TypeOfView)
2014-12-01 23:55:08 +01:00
{
2018-10-18 09:59:38 +02:00
extern const char *Hlp_USERS_Attendance_attendance_list;
2019-04-11 23:15:40 +02:00
extern const char *Txt_Attendance_list;
2020-04-06 16:00:06 +02:00
struct Att_Events Events;
2019-04-11 23:15:40 +02:00
unsigned NumUsrsInList;
2014-12-01 23:55:08 +01:00
long *LstSelectedUsrCods;
2014-12-06 02:21:34 +01:00
unsigned NumAttEvent;
2014-12-01 23:55:08 +01:00
2020-04-08 18:18:46 +02:00
switch (*((Att_TypeOfView_t *) TypeOfView))
2014-12-01 23:55:08 +01:00
{
2020-04-08 03:06:45 +02:00
case Att_VIEW_SEL_USR:
case Att_PRNT_SEL_USR:
/***** Reset attendance events *****/
Att_ResetEvents (&Events);
2014-12-06 02:21:34 +01:00
2020-04-08 03:06:45 +02:00
/***** Get parameters *****/
/* Get boolean parameter that indicates if details must be shown */
Events.ShowDetails = Par_GetParBool ("ShowDetails");
2019-11-14 17:53:50 +01:00
2020-04-08 03:06:45 +02:00
/* Get list of groups selected */
Grp_GetParCodsSeveralGrpsToShowUsrs ();
2014-12-01 23:55:08 +01:00
2020-04-08 03:06:45 +02:00
/***** Count number of valid users in list of encrypted user codes *****/
NumUsrsInList = Usr_CountNumUsrsInListOfSelectedEncryptedUsrCods (&Gbl.Usrs.Selected);
2014-12-08 01:30:47 +01:00
2020-04-08 03:06:45 +02:00
if (NumUsrsInList)
{
/***** Get list of students selected to show their attendances *****/
Usr_GetListSelectedUsrCods (&Gbl.Usrs.Selected,NumUsrsInList,&LstSelectedUsrCods);
/***** Get list of attendance events *****/
Att_GetListEvents (&Events,Att_OLDEST_FIRST);
2020-04-08 03:06:45 +02:00
/***** Get number of students in each event *****/
for (NumAttEvent = 0;
NumAttEvent < Events.Num;
NumAttEvent++)
/* Get number of students in this event */
Events.Lst[NumAttEvent].NumStdsFromList =
Att_GetNumUsrsFromAListWhoAreInEvent (Events.Lst[NumAttEvent].AttCod,
2020-04-08 03:06:45 +02:00
LstSelectedUsrCods,NumUsrsInList);
/***** Get list of attendance events selected *****/
Att_GetListSelectedAttCods (&Events);
/***** Begin box *****/
2020-04-08 18:18:46 +02:00
switch (*((Att_TypeOfView_t *) TypeOfView))
2020-04-08 03:06:45 +02:00
{
case Att_VIEW_SEL_USR:
Box_BoxBegin (NULL,Txt_Attendance_list,
Att_PutIconsStdsAttList,&Events,
Hlp_USERS_Attendance_attendance_list,Box_NOT_CLOSABLE);
break;
case Att_PRNT_SEL_USR:
Box_BoxBegin (NULL,Txt_Attendance_list,
NULL,NULL,
NULL,Box_NOT_CLOSABLE);
break;
default:
Err_WrongTypeExit ();
2020-04-08 03:06:45 +02:00
}
2018-10-18 09:59:38 +02:00
2020-04-08 03:06:45 +02:00
/***** List events to select *****/
2020-04-08 18:18:46 +02:00
Att_ListEventsToSelect (&Events,*((Att_TypeOfView_t *) TypeOfView));
2014-12-01 23:55:08 +01:00
2020-04-08 03:06:45 +02:00
/***** Get my preference about photos in users' list for current course *****/
Set_GetMyPrefAboutListWithPhotosFromDB ();
2014-12-01 23:55:08 +01:00
2020-04-08 03:06:45 +02:00
/***** Show table with attendances for every student in list *****/
2020-04-08 18:18:46 +02:00
Att_ListUsrsAttendanceTable (&Events,*((Att_TypeOfView_t *) TypeOfView),
NumUsrsInList,LstSelectedUsrCods);
2014-12-01 23:55:08 +01:00
2020-04-08 03:06:45 +02:00
/***** Show details or put button to show details *****/
if (Events.ShowDetails)
Att_ListStdsWithAttEventsDetails (&Events,NumUsrsInList,LstSelectedUsrCods);
2018-10-18 09:59:38 +02:00
2020-04-08 03:06:45 +02:00
/***** End box *****/
Box_BoxEnd ();
2014-12-08 14:29:11 +01:00
2020-04-08 03:06:45 +02:00
/***** Free memory for list of attendance events selected *****/
free (Events.StrAttCodsSelected);
2014-12-01 23:55:08 +01:00
2020-04-08 03:06:45 +02:00
/***** Free list of attendance events *****/
Att_FreeListEvents (&Events);
2019-11-14 17:53:50 +01:00
2020-04-08 03:06:45 +02:00
/***** Free list of user codes *****/
Usr_FreeListSelectedUsrCods (LstSelectedUsrCods);
}
2014-12-01 23:55:08 +01:00
2020-04-08 03:06:45 +02:00
/***** Free list of groups selected *****/
Grp_FreeListCodSelectedGrps ();
break;
default:
Err_WrongTypeExit ();
2020-04-08 03:06:45 +02:00
break;
}
2014-12-01 23:55:08 +01:00
}
2014-12-07 02:04:30 +01:00
/*****************************************************************************/
/****************** Get list of attendance events selected *******************/
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
static void Att_GetListSelectedAttCods (struct Att_Events *Events)
2014-12-07 02:04:30 +01:00
{
2020-02-17 12:00:39 +01:00
size_t MaxSizeListAttCodsSelected;
2014-12-07 02:04:30 +01:00
unsigned NumAttEvent;
const char *Ptr;
long AttCod;
2019-11-08 01:10:32 +01:00
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2014-12-08 01:30:47 +01:00
MYSQL_RES *mysql_res;
unsigned NumGrpsInThisEvent;
unsigned NumGrpInThisEvent;
long GrpCodInThisEvent;
unsigned NumGrpSel;
2014-12-07 02:04:30 +01:00
/***** Allocate memory for list of attendance events selected *****/
2020-04-06 16:00:06 +02:00
MaxSizeListAttCodsSelected = (size_t) Events->Num * (Cns_MAX_DECIMAL_DIGITS_LONG + 1);
if ((Events->StrAttCodsSelected = malloc (MaxSizeListAttCodsSelected + 1)) == NULL)
Err_NotEnoughMemoryExit ();
2014-12-07 02:04:30 +01:00
/***** Get parameter multiple with list of attendance events selected *****/
2020-04-06 16:00:06 +02:00
Par_GetParMultiToText ("AttCods",Events->StrAttCodsSelected,MaxSizeListAttCodsSelected);
2014-12-07 02:04:30 +01:00
2014-12-08 01:30:47 +01:00
/***** Set which attendance events will be shown as selected (checkboxes on) *****/
2020-04-06 16:00:06 +02:00
if (Events->StrAttCodsSelected[0]) // There are events selected
2014-12-08 01:30:47 +01:00
{
/* Reset selection */
for (NumAttEvent = 0;
2020-04-06 16:00:06 +02:00
NumAttEvent < Events->Num;
2014-12-08 01:30:47 +01:00
NumAttEvent++)
2020-04-06 16:00:06 +02:00
Events->Lst[NumAttEvent].Selected = false;
2014-12-07 02:04:30 +01:00
2014-12-08 01:30:47 +01:00
/* Set some events as selected */
2020-04-06 16:00:06 +02:00
for (Ptr = Events->StrAttCodsSelected;
2014-12-07 02:04:30 +01:00
*Ptr;
2020-02-17 12:00:39 +01:00
)
2014-12-07 02:04:30 +01:00
{
/* Get next attendance event selected */
Par_GetNextStrUntilSeparParMult (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2014-12-07 02:04:30 +01:00
AttCod = Str_ConvertStrCodToLongCod (LongStr);
2014-12-08 01:30:47 +01:00
/* Set each event in *StrAttCodsSelected as selected */
2014-12-07 02:04:30 +01:00
for (NumAttEvent = 0;
2020-04-06 16:00:06 +02:00
NumAttEvent < Events->Num;
2014-12-07 02:04:30 +01:00
NumAttEvent++)
2020-04-06 16:00:06 +02:00
if (Events->Lst[NumAttEvent].AttCod == AttCod)
2019-11-25 23:18:08 +01:00
{
2020-04-06 16:00:06 +02:00
Events->Lst[NumAttEvent].Selected = true;
2019-11-25 23:18:08 +01:00
break;
}
2014-12-07 02:04:30 +01:00
}
2014-12-08 01:30:47 +01:00
}
else // No events selected
{
/***** Set which events will be marked as selected by default *****/
2019-04-04 10:45:15 +02:00
if (!Gbl.Crs.Grps.NumGrps || // Course has no groups
2014-12-08 01:30:47 +01:00
Gbl.Usrs.ClassPhoto.AllGroups) // All groups selected
/* Set all events as selected */
for (NumAttEvent = 0;
2020-04-06 16:00:06 +02:00
NumAttEvent < Events->Num;
2014-12-08 01:30:47 +01:00
NumAttEvent++)
2020-04-06 16:00:06 +02:00
Events->Lst[NumAttEvent].Selected = true;
2014-12-08 01:30:47 +01:00
else // Course has groups and not all of them are selected
for (NumAttEvent = 0;
2020-04-06 16:00:06 +02:00
NumAttEvent < Events->Num;
2014-12-08 01:30:47 +01:00
NumAttEvent++)
{
/* Reset selection */
2020-04-06 16:00:06 +02:00
Events->Lst[NumAttEvent].Selected = false;
2014-12-07 02:04:30 +01:00
2014-12-08 01:30:47 +01:00
/* Set this event as selected? */
2020-04-06 16:00:06 +02:00
if (Events->Lst[NumAttEvent].NumStdsFromList) // Some students attended to this event
Events->Lst[NumAttEvent].Selected = true;
2014-12-08 01:30:47 +01:00
else // No students attended to this event
{
/***** Get groups associated to an attendance event from database *****/
if ((NumGrpsInThisEvent = Att_DB_GetGrpCodsAssociatedToEvent (&mysql_res,
Events->Lst[NumAttEvent].AttCod))) // This event is associated to groups
2014-12-08 01:30:47 +01:00
/* Get groups associated to this event */
for (NumGrpInThisEvent = 0;
NumGrpInThisEvent < NumGrpsInThisEvent &&
2020-04-06 16:00:06 +02:00
!Events->Lst[NumAttEvent].Selected;
2014-12-08 01:30:47 +01:00
NumGrpInThisEvent++)
{
/* Get next group associated to this event */
if ((GrpCodInThisEvent = DB_GetNextCode (mysql_res)) > 0)
2014-12-08 01:30:47 +01:00
/* Check if this group is selected */
for (NumGrpSel = 0;
2019-04-04 10:45:15 +02:00
NumGrpSel < Gbl.Crs.Grps.LstGrpsSel.NumGrps &&
2020-04-06 16:00:06 +02:00
!Events->Lst[NumAttEvent].Selected;
2014-12-08 01:30:47 +01:00
NumGrpSel++)
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrpSel] == GrpCodInThisEvent)
2020-04-06 16:00:06 +02:00
Events->Lst[NumAttEvent].Selected = true;
2014-12-08 01:30:47 +01:00
}
else // This event is not associated to groups
2020-04-06 16:00:06 +02:00
Events->Lst[NumAttEvent].Selected = true;
2014-12-08 01:30:47 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
}
}
2014-12-07 02:04:30 +01:00
}
2014-12-08 14:29:11 +01:00
/*****************************************************************************/
2018-10-18 11:10:04 +02:00
/******* Put contextual icons when listing my assistance (as student) ********/
2014-12-08 14:29:11 +01:00
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
static void Att_PutIconsMyAttList (void *Events)
2014-12-08 14:29:11 +01:00
{
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
/***** Put icon to print my assistance (as student) to several events *****/
Ico_PutContextualIconToPrint (ActPrnLstMyAtt,
Att_PutFormToPrintMyListPars,Events);
2018-10-18 11:10:04 +02:00
2020-03-26 02:54:30 +01:00
/***** Put icon to print my QR code *****/
QR_PutLinkToPrintQRCode (ActPrnUsrQR,
Usr_PutParMyUsrCodEncrypted,Gbl.Usrs.Me.UsrDat.EnUsrCod);
2020-03-26 02:54:30 +01:00
}
2015-04-02 18:39:49 +02:00
}
static void Att_PutFormToPrintMyListPars (void *Events)
2015-11-13 01:27:44 +01:00
{
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
2020-04-06 16:00:06 +02:00
if (((struct Att_Events *) Events)->ShowDetails)
Par_PutParChar ("ShowDetails",'Y');
2020-04-06 16:00:06 +02:00
if (((struct Att_Events *) Events)->StrAttCodsSelected)
if (((struct Att_Events *) Events)->StrAttCodsSelected[0])
Par_PutParString (NULL,"AttCods",((struct Att_Events *) Events)->StrAttCodsSelected);
2020-03-26 02:54:30 +01:00
}
2015-11-13 01:27:44 +01:00
}
/*****************************************************************************/
2016-03-20 02:08:13 +01:00
/******** Put icon to print assistance of students to several events *********/
2015-11-13 01:27:44 +01:00
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
static void Att_PutIconsStdsAttList (void *Events)
2015-11-13 01:27:44 +01:00
{
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
/***** Put icon to print assistance of students to several events *****/
Ico_PutContextualIconToPrint (ActPrnLstUsrAtt,
Att_PutParsToPrintStdsList,Events);
2018-10-18 11:10:04 +02:00
2020-03-26 02:54:30 +01:00
/***** Put icon to print my QR code *****/
QR_PutLinkToPrintQRCode (ActPrnUsrQR,
Usr_PutParMyUsrCodEncrypted,Gbl.Usrs.Me.UsrDat.EnUsrCod);
2020-03-26 02:54:30 +01:00
}
2015-11-13 01:27:44 +01:00
}
static void Att_PutParsToPrintStdsList (void *Events)
2015-04-02 18:39:49 +02:00
{
2020-04-06 16:00:06 +02:00
if (Events)
2020-03-26 02:54:30 +01:00
{
2020-04-06 16:00:06 +02:00
if (((struct Att_Events *) Events)->ShowDetails)
Par_PutParChar ("ShowDetails",'Y');
Grp_PutParsCodGrps ();
Usr_PutParSelectedUsrsCods (&Gbl.Usrs.Selected);
2020-04-06 16:00:06 +02:00
if (((struct Att_Events *) Events)->StrAttCodsSelected)
if (((struct Att_Events *) Events)->StrAttCodsSelected[0])
Par_PutParString (NULL,"AttCods",((struct Att_Events *) Events)->StrAttCodsSelected);
2020-03-26 02:54:30 +01:00
}
2014-12-08 14:29:11 +01:00
}
/*****************************************************************************/
/**** Put a link (form) to list assistance of students to several events *****/
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
static void Att_PutButtonToShowDetails (const struct Att_Events *Events)
2014-12-08 14:29:11 +01:00
{
extern const char *Txt_Show_more_details;
/***** Button to show more details *****/
/* Begin form */
Frm_BeginFormAnchor (Gbl.Action.Act,Att_ATTENDANCE_DETAILS_ID);
Par_PutParChar ("ShowDetails",'Y');
Grp_PutParsCodGrps ();
Usr_PutParSelectedUsrsCods (&Gbl.Usrs.Selected);
if (Events->StrAttCodsSelected)
if (Events->StrAttCodsSelected[0])
Par_PutParString (NULL,"AttCods",Events->StrAttCodsSelected);
/* Button */
Btn_PutConfirmButton (Txt_Show_more_details);
/* End form */
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-08 14:29:11 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********** Write list of those attendance events that have students *********/
/*****************************************************************************/
static void Att_ListEventsToSelect (struct Att_Events *Events,
2020-04-06 16:00:06 +02:00
Att_TypeOfView_t TypeOfView)
2014-12-01 23:55:08 +01:00
{
2014-12-04 01:19:42 +01:00
extern const char *Txt_Events;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Event;
extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2014-12-08 01:30:47 +01:00
extern const char *Txt_Update_attendance;
2015-10-24 20:46:11 +02:00
unsigned UniqueId;
2019-11-01 22:53:39 +01:00
char *Id;
2014-12-01 23:55:08 +01:00
unsigned NumAttEvent;
2020-04-06 16:00:06 +02:00
bool NormalView = (TypeOfView == Att_VIEW_ONLY_ME ||
TypeOfView == Att_VIEW_SEL_USR);
2018-10-18 09:59:38 +02:00
2019-10-26 02:19:42 +02:00
/***** Begin box *****/
2020-04-06 16:00:06 +02:00
switch (TypeOfView)
2020-03-26 02:54:30 +01:00
{
case Att_VIEW_ONLY_ME:
Box_BoxBegin (NULL,Txt_Events,
2020-04-08 03:41:05 +02:00
Att_PutIconToViewAttEvents,NULL,
2020-03-26 02:54:30 +01:00
NULL,Box_NOT_CLOSABLE);
break;
case Att_VIEW_SEL_USR:
Box_BoxBegin (NULL,Txt_Events,
2020-04-08 03:41:05 +02:00
Att_PutIconToEditAttEvents,NULL,
2020-03-26 02:54:30 +01:00
NULL,Box_NOT_CLOSABLE);
break;
case Att_PRNT_ONLY_ME:
case Att_PRNT_SEL_USR:
Box_BoxBegin (NULL,Txt_Events,
NULL,NULL,
NULL,Box_NOT_CLOSABLE);
break;
}
2014-12-01 23:55:08 +01:00
/***** Begin form to update the attendance
depending on the events selected *****/
if (NormalView)
{
Frm_BeginFormAnchor (Gbl.Action.Act,Att_ATTENDANCE_TABLE_ID);
Grp_PutParsCodGrps ();
Usr_PutParSelectedUsrsCods (&Gbl.Usrs.Selected);
}
2014-12-01 23:55:08 +01:00
/***** Begin table *****/
HTM_TABLE_BeginWidePadding (2);
2014-12-01 23:55:08 +01:00
/***** Heading row *****/
HTM_TR_Begin (NULL);
HTM_TH_Span (Txt_Event ,HTM_HEAD_LEFT ,1,4,NULL);
HTM_TH (Txt_ROLES_PLURAL_Abc[Rol_STD][Usr_SEX_UNKNOWN],HTM_HEAD_RIGHT);
HTM_TR_End ();
2019-10-07 22:28:16 +02:00
/***** List the events *****/
for (NumAttEvent = 0, UniqueId = 1;
NumAttEvent < Events->Num;
NumAttEvent++, UniqueId++, The_ChangeRowColor ())
{
/* Get data of the attendance event from database */
Events->Event.AttCod = Events->Lst[NumAttEvent].AttCod;
Att_GetEventDataByCodAndCheckCrs (&Events->Event);
Events->Event.NumStdsTotal = Att_DB_GetNumStdsTotalWhoAreInEvent (Events->Event.AttCod);
2019-10-07 22:28:16 +02:00
/* Write a row for this event */
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
HTM_TD_Begin ("class=\"CT DAT_%s %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_INPUT_CHECKBOX ("AttCods",HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"Event%u\" value=\"%ld\"%s",
NumAttEvent,Events->Event.AttCod,
Events->Lst[NumAttEvent].Selected ? " checked=\"checked\"" :
"");
HTM_TD_End ();
HTM_TD_Begin ("class=\"RT DAT_%s %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_LABEL_Begin ("for=\"Event%u\"",NumAttEvent);
HTM_TxtF ("%u:",NumAttEvent + 1);
HTM_LABEL_End ();
HTM_TD_End ();
HTM_TD_Begin ("class=\"LT DAT_%s %s\"",
The_GetSuffix (),
The_GetColorRows ());
if (asprintf (&Id,"att_date_start_%u",UniqueId) < 0)
Err_NotEnoughMemoryExit ();
HTM_LABEL_Begin ("for=\"Event%u\"",NumAttEvent);
HTM_SPAN_Begin ("id=\"%s\"",Id);
HTM_SPAN_End ();
HTM_LABEL_End ();
Dat_WriteLocalDateHMSFromUTC (Id,Events->Event.TimeUTC[Dat_STR_TIME],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA,
true,true,true,0x7);
free (Id);
HTM_TD_End ();
HTM_TD_Begin ("class=\"LT DAT_%s %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_Txt (Events->Event.Title);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RT DAT_%s %s\"",
The_GetSuffix (),
The_GetColorRows ());
HTM_Unsigned (Events->Event.NumStdsTotal);
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
HTM_TR_End ();
}
2014-12-07 02:04:30 +01:00
/***** End table *****/
HTM_TABLE_End ();
2014-12-08 14:29:11 +01:00
/***** Put button to refresh *****/
if (NormalView)
{
HTM_DIV_Begin ("class=\"UPD\"");
HTM_BUTTON_Submit_Begin (Txt_Update_attendance,
"class=\"BT_LINK FORM_IN_%s BOLD\"",
The_GetSuffix ());
Ico_PutIconTextLink ("recycle.svg",Ico_BLACK,Txt_Update_attendance);
HTM_BUTTON_End ();
HTM_DIV_End ();
}
/***** End form *****/
if (NormalView)
Frm_EndForm ();
2018-10-18 09:59:38 +02:00
/***** End box *****/
2019-10-25 22:48:34 +02:00
Box_BoxEnd ();
2018-10-18 09:59:38 +02:00
}
/*****************************************************************************/
2020-03-26 02:54:30 +01:00
/*********** Put icon to list (without edition) attendance events ************/
2018-10-18 09:59:38 +02:00
/*****************************************************************************/
2020-04-08 03:41:05 +02:00
static void Att_PutIconToViewAttEvents (__attribute__((unused)) void *Args)
2018-10-18 09:59:38 +02:00
{
Ico_PutContextualIconToView (ActSeeAtt,NULL,
2020-04-08 03:41:05 +02:00
NULL,NULL);
2014-12-05 02:33:47 +01:00
}
/*****************************************************************************/
2020-03-26 02:54:30 +01:00
/************ Put icon to list (with edition) attendance events **************/
2018-10-18 11:10:04 +02:00
/*****************************************************************************/
2020-04-08 03:41:05 +02:00
static void Att_PutIconToEditAttEvents (__attribute__((unused)) void *Args)
2018-10-18 11:10:04 +02:00
{
2020-04-08 03:41:05 +02:00
Ico_PutContextualIconToEdit (ActSeeAtt,NULL,
NULL,NULL);
2018-10-18 11:10:04 +02:00
}
/*****************************************************************************/
2019-04-11 23:15:40 +02:00
/************ Show table with attendances for every user in list *************/
2014-12-05 02:33:47 +01:00
/*****************************************************************************/
static void Att_ListUsrsAttendanceTable (struct Att_Events *Events,
2020-04-06 16:00:06 +02:00
Att_TypeOfView_t TypeOfView,
unsigned NumUsrsInList,
2016-03-20 02:08:13 +01:00
long *LstSelectedUsrCods)
2014-12-05 02:33:47 +01:00
{
2019-04-11 23:15:40 +02:00
extern const char *Txt_Number_of_users;
struct Usr_Data UsrDat;
2019-04-11 23:15:40 +02:00
unsigned NumUsr;
2014-12-05 02:33:47 +01:00
unsigned NumAttEvent;
2014-12-06 02:21:34 +01:00
unsigned Total;
2020-04-06 16:00:06 +02:00
bool PutButtonShowDetails = (TypeOfView == Att_VIEW_ONLY_ME ||
TypeOfView == Att_VIEW_SEL_USR) &&
!Events->ShowDetails;
2014-12-05 02:33:47 +01:00
2014-12-06 02:21:34 +01:00
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
2014-12-05 02:33:47 +01:00
/***** Begin section with attendance table *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin (Att_ATTENDANCE_TABLE_ID);
2018-10-18 11:29:02 +02:00
/***** Begin table *****/
HTM_TABLE_BeginCenterPadding (2);
2014-12-08 14:29:11 +01:00
/***** Heading row *****/
Att_WriteTableHeadSeveralAttEvents (Events);
2014-12-05 02:33:47 +01:00
/***** List the users *****/
for (NumUsr = 0;
NumUsr < NumUsrsInList;
NumUsr++)
2017-06-09 15:04:02 +02:00
{
UsrDat.UsrCod = LstSelectedUsrCods[NumUsr];
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat, // Get from the database the data of the student
Usr_DONT_GET_PREFS,
Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
if (Usr_CheckIfICanViewAtt (&UsrDat))
{
UsrDat.Accepted = Enr_CheckIfUsrHasAcceptedInCurrentCrs (&UsrDat);
Att_WriteRowUsrSeveralAttEvents (Events,NumUsr,&UsrDat);
}
2017-06-09 15:04:02 +02:00
}
2014-12-05 02:33:47 +01:00
/***** Last row with the total of users present in each event *****/
if (NumUsrsInList > 1)
{
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
HTM_TD_Begin ("colspan=\"%u\" class=\"RM DAT_STRONG_%s LINE_TOP\"",
Gbl.Usrs.Listing.WithPhotos ? 4 :
3,
The_GetSuffix ());
HTM_TxtColon (Txt_Number_of_users);
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
for (NumAttEvent = 0, Total = 0;
NumAttEvent < Events->Num;
NumAttEvent++)
if (Events->Lst[NumAttEvent].Selected)
{
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP\"",
The_GetSuffix ());
HTM_Unsigned (Events->Lst[NumAttEvent].NumStdsFromList);
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
Total += Events->Lst[NumAttEvent].NumStdsFromList;
}
2019-10-07 22:28:16 +02:00
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP\"",
The_GetSuffix ());
HTM_Unsigned (Total);
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
HTM_TR_End ();
}
2014-12-01 23:55:08 +01:00
/***** End table *****/
HTM_TABLE_End ();
2016-03-20 02:08:13 +01:00
/***** Button to show more details *****/
if (PutButtonShowDetails)
Att_PutButtonToShowDetails (Events);
2015-04-11 17:33:14 +02:00
2018-10-18 11:29:02 +02:00
/***** End section with attendance table *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ();
2018-10-18 11:29:02 +02:00
2014-12-06 02:21:34 +01:00
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/* Write table heading for listing of students in several attendance events **/
/*****************************************************************************/
static void Att_WriteTableHeadSeveralAttEvents (struct Att_Events *Events)
2014-12-01 23:55:08 +01:00
{
2015-03-12 14:45:40 +01:00
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2014-12-01 23:55:08 +01:00
extern const char *Txt_Attendance;
unsigned NumAttEvent;
2019-11-08 01:10:32 +01:00
char StrNumAttEvent[Cns_MAX_DECIMAL_DIGITS_UINT + 1];
2014-12-01 23:55:08 +01:00
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-11 01:02:51 +02:00
HTM_TH_Span (Txt_ROLES_SINGUL_Abc[Rol_USR][Usr_SEX_UNKNOWN],HTM_HEAD_LEFT,
1,Gbl.Usrs.Listing.WithPhotos ? 4 :
3,NULL);
2014-12-01 23:55:08 +01:00
for (NumAttEvent = 0;
NumAttEvent < Events->Num;
NumAttEvent++)
if (Events->Lst[NumAttEvent].Selected)
{
/***** Get data of this attendance event *****/
Events->Event.AttCod = Events->Lst[NumAttEvent].AttCod;
Att_GetEventDataByCodAndCheckCrs (&Events->Event);
/***** Put link to this attendance event *****/
HTM_TH_Begin (HTM_HEAD_CENTER);
snprintf (StrNumAttEvent,sizeof (StrNumAttEvent),"%u",NumAttEvent + 1);
Att_PutLinkEvent (&Events->Event,
Events->Event.Title,
StrNumAttEvent);
HTM_TH_End ();
}
2014-12-01 23:55:08 +01:00
HTM_TH (Txt_Attendance ,HTM_HEAD_RIGHT);
2019-10-11 01:02:51 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-04-11 23:15:40 +02:00
/************** Write a row of a table with the data of a user ***************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2020-04-06 16:00:06 +02:00
static void Att_WriteRowUsrSeveralAttEvents (const struct Att_Events *Events,
unsigned NumUsr,struct Usr_Data *UsrDat)
2014-12-01 23:55:08 +01:00
{
static const char *ClassPhoto[PhoSha_NUM_SHAPES] =
{
[PhoSha_SHAPE_CIRCLE ] = "PHOTOC21x28",
[PhoSha_SHAPE_ELLIPSE ] = "PHOTOE21x28",
[PhoSha_SHAPE_OVAL ] = "PHOTOO21x28",
[PhoSha_SHAPE_RECTANGLE] = "PHOTOR21x28",
};
2014-12-01 23:55:08 +01:00
unsigned NumAttEvent;
bool Present;
unsigned NumTimesPresent;
2019-04-11 23:15:40 +02:00
/***** Write number of user in the list *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
HTM_TD_Begin ("class=\"RM %s_%s %s\"",
UsrDat->Accepted ? "DAT_STRONG" :
"DAT",
The_GetSuffix (),
The_GetColorRows ());
HTM_Unsigned (NumUsr + 1);
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
/***** Show user's photo *****/
if (Gbl.Usrs.Listing.WithPhotos)
2014-12-01 23:55:08 +01:00
{
HTM_TD_Begin ("class=\"LM %s\"",The_GetColorRows ());
Pho_ShowUsrPhotoIfAllowed (UsrDat,
ClassPhoto[Gbl.Prefs.PhotoShape],Pho_ZOOM);
2019-10-23 19:05:05 +02:00
HTM_TD_End ();
2014-12-01 23:55:08 +01:00
}
/***** Write user's ID ******/
HTM_TD_Begin ("class=\"LM %s_%s %s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix (),
The_GetColorRows ());
ID_WriteUsrIDs (UsrDat,NULL);
HTM_TD_End ();
/***** Write user's name *****/
HTM_TD_Begin ("class=\"LM %s_%s %s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix (),
The_GetColorRows ());
HTM_Txt (UsrDat->Surname1);
if (UsrDat->Surname2[0])
HTM_TxtF ("&nbsp;%s",UsrDat->Surname2);
HTM_TxtF (", %s",UsrDat->FrstName);
HTM_TD_End ();
/***** Check/cross to show if the user is present/absent *****/
for (NumAttEvent = 0, NumTimesPresent = 0;
NumAttEvent < Events->Num;
NumAttEvent++)
if (Events->Lst[NumAttEvent].Selected)
{
/* Check if this student is already registered in the current event */
// Here it is not necessary to get comments
Present = Att_CheckIfUsrIsPresentInEvent (Events->Lst[NumAttEvent].AttCod,
UsrDat->UsrCod);
/* Write check or cross */
HTM_TD_Begin ("class=\"BM %s\"",The_GetColorRows ());
Att_PutCheckOrCross (Present);
HTM_TD_End ();
if (Present)
NumTimesPresent++;
}
/***** Last column with the number of times this user is present *****/
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
HTM_Unsigned (NumTimesPresent);
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-01 23:55:08 +01:00
The_ChangeRowColor ();
2014-12-01 23:55:08 +01:00
}
2014-12-06 02:21:34 +01:00
2019-02-13 21:24:54 +01:00
/*****************************************************************************/
/*********************** Put check or cross character ************************/
/*****************************************************************************/
static void Att_PutCheckOrCross (bool Present)
{
extern const char *Txt_Present;
extern const char *Txt_Absent;
if (Present)
2019-10-24 00:04:40 +02:00
{
HTM_DIV_Begin ("class=\"ATT_CHECK ATT_CHECK_%s\" title=\"%s\"",
The_GetSuffix (),Txt_Present);
HTM_Txt ("&check;");
2019-10-24 00:04:40 +02:00
}
2019-02-13 21:24:54 +01:00
else
2019-10-24 00:04:40 +02:00
{
HTM_DIV_Begin ("class=\"ATT_CROSS ATT_CROSS_%s\" title=\"%s\"",
The_GetSuffix (),Txt_Absent);
HTM_Txt ("&cross;");
2019-10-24 00:04:40 +02:00
}
2019-10-23 20:07:56 +02:00
HTM_DIV_End ();
2019-02-13 21:24:54 +01:00
}
2014-12-06 02:21:34 +01:00
/*****************************************************************************/
/**************** List the students with details and comments ****************/
/*****************************************************************************/
static void Att_ListStdsWithAttEventsDetails (struct Att_Events *Events,
2020-04-06 16:00:06 +02:00
unsigned NumUsrsInList,
2016-11-27 23:08:29 +01:00
long *LstSelectedUsrCods)
2014-12-06 02:21:34 +01:00
{
extern const char *Txt_Details;
struct Usr_Data UsrDat;
2019-04-11 23:15:40 +02:00
unsigned NumUsr;
2014-12-06 02:21:34 +01:00
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Begin section with attendance details *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin (Att_ATTENDANCE_DETAILS_ID);
2018-10-18 16:56:07 +02:00
/***** Begin box and table *****/
Box_BoxTableBegin (NULL,Txt_Details,
NULL,NULL,
NULL,Box_NOT_CLOSABLE,2);
/***** List students with attendance details *****/
for (NumUsr = 0;
NumUsr < NumUsrsInList;
NumUsr++)
2017-06-09 15:04:02 +02:00
{
UsrDat.UsrCod = LstSelectedUsrCods[NumUsr];
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat, // Get from the database the data of the student
Usr_DONT_GET_PREFS,
Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
if (Usr_CheckIfICanViewAtt (&UsrDat))
{
UsrDat.Accepted = Enr_CheckIfUsrHasAcceptedInCurrentCrs (&UsrDat);
Att_ListAttEventsForAStd (Events,NumUsr,&UsrDat);
}
2017-06-09 15:04:02 +02:00
}
2014-12-06 02:21:34 +01:00
/***** End table and box *****/
Box_BoxTableEnd ();
2014-12-06 02:21:34 +01:00
2018-10-18 16:56:07 +02:00
/***** End section with attendance details *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ();
2018-10-18 16:56:07 +02:00
2014-12-06 02:21:34 +01:00
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
/*****************************************************************************/
/*************** Write list of attendance events for a student ***************/
/*****************************************************************************/
static void Att_ListAttEventsForAStd (struct Att_Events *Events,
unsigned NumUsr,struct Usr_Data *UsrDat)
2014-12-06 02:21:34 +01:00
{
extern const char *Txt_Student_comment;
extern const char *Txt_Teachers_comment;
static const char *ClassPhoto[PhoSha_NUM_SHAPES] =
{
[PhoSha_SHAPE_CIRCLE ] = "PHOTOC21x28",
[PhoSha_SHAPE_ELLIPSE ] = "PHOTOE21x28",
[PhoSha_SHAPE_OVAL ] = "PHOTOO21x28",
[PhoSha_SHAPE_RECTANGLE] = "PHOTOR21x28",
};
2014-12-06 02:21:34 +01:00
unsigned NumAttEvent;
2015-10-24 20:46:11 +02:00
unsigned UniqueId;
2019-11-01 22:53:39 +01:00
char *Id;
2014-12-06 02:21:34 +01:00
bool Present;
2015-11-13 01:27:44 +01:00
bool ShowCommentStd;
bool ShowCommentTch;
2017-01-17 03:10:43 +01:00
char CommentStd[Cns_MAX_BYTES_TEXT + 1];
char CommentTch[Cns_MAX_BYTES_TEXT + 1];
2014-12-06 02:21:34 +01:00
/***** Write number of student in the list *****/
2019-04-11 23:15:40 +02:00
NumUsr++;
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-07 22:28:16 +02:00
HTM_TD_Begin ("class=\"RM %s_%s %s\"",
UsrDat->Accepted ? "DAT_STRONG" :
"DAT",
The_GetSuffix (),
The_GetColorRows ());
HTM_TxtF ("%u:",NumUsr);
HTM_TD_End ();
/***** Show student's photo *****/
HTM_TD_Begin ("colspan=\"2\" class=\"RM %s\"",
The_GetColorRows ());
Pho_ShowUsrPhotoIfAllowed (UsrDat,
ClassPhoto[Gbl.Prefs.PhotoShape],Pho_ZOOM);
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
HTM_TD_Begin ("class=\"LM %s\"",The_GetColorRows ());
HTM_TABLE_Begin (NULL);
HTM_TR_Begin (NULL);
/***** Write user's ID ******/
HTM_TD_Begin ("class=\"LM %s_%s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix ());
ID_WriteUsrIDs (UsrDat,NULL);
HTM_TD_End ();
/***** Write student's name *****/
HTM_TD_Begin ("class=\"LM %s_%s\"",
UsrDat->Accepted ? "DAT_SMALL_STRONG" :
"DAT_SMALL",
The_GetSuffix ());
HTM_Txt (UsrDat->Surname1);
if (UsrDat->Surname2[0])
HTM_TxtF ("&nbsp;%s",UsrDat->Surname2);
HTM_TxtF (", %s",UsrDat->FrstName);
HTM_TD_End ();
HTM_TR_End ();
HTM_TABLE_End ();
HTM_TD_End ();
2019-10-07 22:28:16 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-06 02:21:34 +01:00
/***** List the events with students *****/
2015-10-24 20:46:11 +02:00
for (NumAttEvent = 0, UniqueId = 1;
2020-04-06 16:00:06 +02:00
NumAttEvent < Events->Num;
2015-10-24 20:46:11 +02:00
NumAttEvent++, UniqueId++)
2020-04-06 16:00:06 +02:00
if (Events->Lst[NumAttEvent].Selected)
2014-12-06 02:21:34 +01:00
{
/***** Get data of the attendance event from database *****/
Events->Event.AttCod = Events->Lst[NumAttEvent].AttCod;
Att_GetEventDataByCodAndCheckCrs (&Events->Event);
Events->Event.NumStdsTotal = Att_DB_GetNumStdsTotalWhoAreInEvent (Events->Event.AttCod);
2014-12-06 02:21:34 +01:00
/***** Get comments for this student *****/
Present = Att_CheckIfUsrIsPresentInEventAndGetComments (Events->Event.AttCod,UsrDat->UsrCod,CommentStd,CommentTch);
2015-11-13 01:27:44 +01:00
ShowCommentStd = CommentStd[0];
ShowCommentTch = CommentTch[0] &&
2017-06-04 18:18:54 +02:00
(Gbl.Usrs.Me.Role.Logged == Rol_TCH ||
Events->Event.CommentTchVisible);
2014-12-06 02:21:34 +01:00
/***** Write a row for this event *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-06 12:00:55 +02:00
HTM_TD_ColouredEmpty (1);
2019-10-06 12:00:55 +02:00
HTM_TD_Begin ("class=\"RT %s_%s %s\"",
Present ? "DAT_GREEN" :
"DAT_RED",
The_GetSuffix (),
The_GetColorRows ());
HTM_TxtF ("%u:",NumAttEvent + 1);
HTM_TD_End ();
2019-10-06 12:00:55 +02:00
HTM_TD_Begin ("class=\"BT %s\"",The_GetColorRows ());
Att_PutCheckOrCross (Present);
HTM_TD_End ();
2019-10-06 12:00:55 +02:00
HTM_TD_Begin ("class=\"LT DAT_%s %s\"",
The_GetSuffix (),
The_GetColorRows ());
if (asprintf (&Id,"att_date_start_%u_%u",NumUsr,UniqueId) < 0)
Err_NotEnoughMemoryExit ();
HTM_SPAN_Begin ("id=\"%s\"",Id);
HTM_SPAN_End ();
HTM_BR ();
HTM_Txt (Events->Event.Title);
Dat_WriteLocalDateHMSFromUTC (Id,Events->Event.TimeUTC[Dat_STR_TIME],
Gbl.Prefs.DateFormat,Dat_SEPARATOR_COMMA,
true,true,true,0x7);
free (Id);
HTM_TD_End ();
2019-10-06 12:00:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-06 02:21:34 +01:00
/***** Write comments for this student *****/
2015-11-13 01:27:44 +01:00
if (ShowCommentStd || ShowCommentTch)
2014-12-06 02:21:34 +01:00
{
2019-10-23 19:05:05 +02:00
HTM_TR_Begin (NULL);
2019-10-06 12:00:55 +02:00
HTM_TD_ColouredEmpty (2);
HTM_TD_Begin ("class=\"BT %s\"",The_GetColorRows ());
HTM_TD_End ();
HTM_TD_Begin ("class=\"LM DAT_%s %s\"",
The_GetSuffix (),The_GetColorRows ());
HTM_DL_Begin ();
if (ShowCommentStd)
{
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
CommentStd,Cns_MAX_BYTES_TEXT,false);
HTM_DT_Begin ();
HTM_TxtColon (Txt_Student_comment);
HTM_DT_End ();
HTM_DD_Begin ();
HTM_Txt (CommentStd);
HTM_DD_End ();
}
if (ShowCommentTch)
{
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
CommentTch,Cns_MAX_BYTES_TEXT,false);
HTM_DT_Begin ();
HTM_TxtColon (Txt_Teachers_comment);
HTM_DT_End ();
HTM_DD_Begin ();
HTM_Txt (CommentTch);
HTM_DD_End ();
}
HTM_DL_End ();
HTM_TD_End ();
2019-10-06 12:00:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ();
2014-12-06 02:21:34 +01:00
}
}
The_ChangeRowColor ();
2014-12-06 02:21:34 +01:00
}