2014-12-01 23:55:08 +01:00
// swad_group.c: types of groups and groups
/*
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 .
2020-01-01 14:53:57 +01:00
Copyright ( C ) 1999 - 2020 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 *********************************/
/*****************************************************************************/
2018-10-22 09:51:37 +02:00
# define _GNU_SOURCE // For asprintf
2019-12-29 12:39:00 +01:00
# include <stddef.h> // For NULL
2018-10-22 09:51:37 +02:00
# include <stdio.h> // For asprintf
2014-12-01 23:55:08 +01:00
# include <stdlib.h> // For exit, system, malloc, free, rand, etc.
# include <string.h> // For string functions
# include "swad_action.h"
2020-04-14 17:15:17 +02:00
# include "swad_attendance.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"
2020-05-06 01:43:48 +02:00
# include "swad_exam_event.h"
2018-11-09 20:47:39 +01:00
# include "swad_form.h"
2017-09-07 18:38:18 +02:00
# include "swad_game.h"
2014-12-01 23:55:08 +01:00
# include "swad_global.h"
# include "swad_group.h"
2019-10-23 19:05:05 +02:00
# include "swad_HTML.h"
2019-09-28 02:31:42 +02:00
# include "swad_match.h"
2014-12-01 23:55:08 +01:00
# include "swad_notification.h"
# include "swad_parameter.h"
2020-02-26 00:26:07 +01:00
# include "swad_program.h"
2017-09-17 16:58:09 +02:00
# include "swad_project.h"
2019-03-26 11:53:21 +01:00
# include "swad_setting.h"
2020-04-14 17:15:17 +02:00
# include "swad_survey.h"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-11-21 16:47:07 +01:00
/*************************** Private constants *******************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-05-31 09:37:20 +02:00
# define Grp_GROUP_TYPES_SECTION_ID "grp_types"
2017-05-25 13:43:54 +02:00
# define Grp_NEW_GROUP_TYPE_SECTION_ID "new_grp_type"
# define Grp_GROUPS_SECTION_ID "grps"
2017-05-31 09:37:20 +02:00
# define Grp_NEW_GROUP_SECTION_ID "new_grp"
2017-04-29 15:29:58 +02:00
2017-06-04 18:18:54 +02:00
static const bool Grp_ICanChangeGrps [ Rol_NUM_ROLES ] =
{
2019-11-21 01:27:17 +01:00
[ Rol_UNK ] = false ,
[ Rol_GST ] = false ,
[ Rol_USR ] = false ,
[ Rol_STD ] = true ,
[ Rol_NET ] = false ,
[ Rol_TCH ] = true ,
[ Rol_DEG_ADM ] = false ,
[ Rol_CTR_ADM ] = false ,
[ Rol_INS_ADM ] = false ,
[ Rol_SYS_ADM ] = true ,
2017-06-04 18:18:54 +02:00
} ;
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-11-21 16:47:07 +01:00
/****************************** Private types ********************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*****************************************************************************/
/************* External global variables from others modules *****************/
/*****************************************************************************/
extern struct Globals Gbl ;
/*****************************************************************************/
2019-11-21 16:47:07 +01:00
/************************** Private global variables *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*****************************************************************************/
2019-11-21 16:47:07 +01:00
/***************************** Private prototypes ****************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
static void Grp_ReqEditGroupsInternal ( Ale_AlertType_t AlertTypeGroupTypes , const char * AlertTextGroupTypes ,
Ale_AlertType_t AlertTypeGroups , const char * AlertTextGroups ) ;
2017-04-29 02:20:34 +02:00
static void Grp_ReqEditGroupsInternal0 ( void ) ;
2019-03-09 20:12:44 +01:00
static void Grp_ReqEditGroupsInternal1 ( Ale_AlertType_t AlertTypeGroupTypes ,
const char * AlertTextGroupTypes ) ;
static void Grp_ReqEditGroupsInternal2 ( Ale_AlertType_t AlertTypeGroups ,
const char * AlertTextGroups ) ;
2017-04-28 18:03:30 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_EditGroupTypes ( void ) ;
2020-04-14 17:15:17 +02:00
static void Grp_EditGroups ( const struct Roo_Rooms * Rooms ) ;
2020-04-08 18:18:46 +02:00
static void Grp_PutIconsEditingGroups ( __attribute__ ( ( unused ) ) void * Args ) ;
2017-04-29 20:16:53 +02:00
static void Grp_PutIconToCreateNewGroup ( void ) ;
2017-01-19 20:55:31 +01:00
2017-07-02 18:53:35 +02:00
static void Grp_PutCheckboxAllGrps ( Grp_WhichGroups_t GroupsSelectableByStdsOrNETs ) ;
2017-05-30 19:42:10 +02:00
2018-10-22 10:12:41 +02:00
static void Grp_LockTables ( void ) ;
static void Grp_UnlockTables ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_ConstructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType ) ;
static void Grp_DestructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType ) ;
static void Grp_RemoveUsrFromGroup ( long UsrCod , long GrpCod ) ;
static void Grp_AddUsrToGroup ( struct UsrData * UsrDat , long GrpCod ) ;
2017-04-29 19:32:06 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_ListGroupTypesForEdition ( void ) ;
2020-04-08 18:18:46 +02:00
static void Grp_PutIconsEditingGroupTypes ( __attribute__ ( ( unused ) ) void * Args ) ;
2017-04-29 19:19:55 +02:00
static void Grp_PutIconToViewGroups ( void ) ;
static void Grp_PutIconToCreateNewGroupType ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_WriteHeadingGroupTypes ( void ) ;
2017-04-29 19:32:06 +02:00
2020-04-14 17:15:17 +02:00
static void Grp_ListGroupsForEdition ( const struct Roo_Rooms * Rooms ) ;
2014-12-01 23:55:08 +01:00
static void Grp_WriteHeadingGroups ( void ) ;
2020-05-06 01:43:48 +02:00
static bool Grp_CheckIfAssociatedToGrp ( const char * Table , const char * Field ,
long Cod , long GrpCod ) ;
2020-04-08 18:18:46 +02:00
static void Grp_PutIconToEditGroups ( __attribute__ ( ( unused ) ) void * Args ) ;
2014-12-01 23:55:08 +01:00
static void Grp_ShowWarningToStdsToChangeGrps ( void ) ;
2017-06-04 18:18:54 +02:00
static bool Grp_ListGrpsForChangeMySelection ( struct GroupType * GrpTyp ,
unsigned * NumGrpsThisTypeIBelong ) ;
2014-12-01 23:55:08 +01:00
static void Grp_ListGrpsToAddOrRemUsrs ( struct GroupType * GrpTyp , long UsrCod ) ;
2017-06-23 09:56:01 +02:00
static void Grp_ListGrpsForMultipleSelection ( struct GroupType * GrpTyp ,
2017-07-02 18:53:35 +02:00
Grp_WhichGroups_t GroupsSelectableByStdsOrNETs ) ;
2014-12-01 23:55:08 +01:00
static void Grp_WriteGrpHead ( struct GroupType * GrpTyp ) ;
static void Grp_WriteRowGrp ( struct Group * Grp , bool Highlight ) ;
static void Grp_PutFormToCreateGroupType ( void ) ;
2020-04-14 17:15:17 +02:00
static void Grp_PutFormToCreateGroup ( const struct Roo_Rooms * Rooms ) ;
2014-12-01 23:55:08 +01:00
static unsigned Grp_CountNumGrpsInThisCrsOfType ( long GrpTypCod ) ;
static void Grp_GetDataOfGroupTypeByCod ( struct GroupType * GrpTyp ) ;
2017-03-30 11:20:06 +02:00
static bool Grp_GetMultipleEnrolmentOfAGroupType ( long GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
static long Grp_GetTypeOfGroupOfAGroup ( long GrpCod ) ;
2018-10-31 10:19:01 +01:00
static unsigned long Grp_CountNumUsrsInNoGrpsOfType ( Rol_Role_t Role , long GrpTypCod ) ;
2019-02-18 14:41:46 +01:00
static bool Grp_CheckIfIBelongToGrpsOfType ( long GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
static void Grp_GetLstCodGrpsUsrBelongs ( long CrsCod , long GrpTypCod , long UsrCod ,
struct ListCodGrps * LstGrps ) ;
static bool Grp_CheckIfGrpIsInList ( long GrpCod , struct ListCodGrps * LstGrps ) ;
2015-10-26 20:02:07 +01:00
static bool Grp_CheckIfOpenTimeInTheFuture ( time_t OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
static bool Grp_CheckIfGroupTypeNameExists ( const char * GrpTypName , long GrpTypCod ) ;
static bool Grp_CheckIfGroupNameExists ( long GrpTypCod , const char * GrpName , long GrpCod ) ;
static void Grp_CreateGroupType ( void ) ;
static void Grp_CreateGroup ( void ) ;
2017-04-28 13:10:46 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_AskConfirmRemGrpTypWithGrps ( unsigned NumGrps ) ;
2020-04-08 18:18:46 +02:00
static void Grp_PutParamRemGrpTyp ( void * GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
static void Grp_AskConfirmRemGrp ( void ) ;
2020-04-08 18:18:46 +02:00
static void Grp_PutParamRemGrp ( void * GrpCod ) ;
2014-12-01 23:55:08 +01:00
static void Grp_RemoveGroupTypeCompletely ( void ) ;
static void Grp_RemoveGroupCompletely ( void ) ;
2017-04-28 13:10:46 +02:00
2019-11-08 01:10:32 +01:00
static void Grp_WriteMaxStds ( char Str [ Cns_MAX_DECIMAL_DIGITS_UINT + 1 ] , unsigned MaxStudents ) ;
2014-12-01 23:55:08 +01:00
static long Grp_GetParamGrpTypCod ( void ) ;
static long Grp_GetParamGrpCod ( void ) ;
static void Grp_PutParamGrpTypCod ( long GrpTypCod ) ;
/*****************************************************************************/
/******************* Write the names of the selected groups ******************/
/*****************************************************************************/
void Grp_WriteNamesOfSelectedGrps ( void )
{
extern const char * Txt_Group ;
extern const char * Txt_Groups ;
2017-05-30 21:43:05 +02:00
extern const char * Txt_users_with_no_group ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_and ;
long GrpCod ;
unsigned NumGrpSel ;
struct GroupData GrpDat ;
/***** Show the selected groups *****/
2020-01-11 15:22:02 +01:00
HTM_TxtColonNBSP ( Gbl . Crs . Grps . LstGrpsSel . NumGrps = = 1 ? Txt_Group :
Txt_Groups ) ;
2014-12-01 23:55:08 +01:00
for ( NumGrpSel = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpSel < Gbl . Crs . Grps . LstGrpsSel . NumGrps ;
2014-12-01 23:55:08 +01:00
NumGrpSel + + )
{
2019-04-04 10:45:15 +02:00
if ( ( GrpCod = Gbl . Crs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] ) > = 0 )
2014-12-01 23:55:08 +01:00
{
GrpDat . GrpCod = GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
2019-11-11 10:59:24 +01:00
HTM_TxtF ( " %s %s " , GrpDat . GrpTypName , GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
else // GrpCod < 0 ==> students not belonging to any group of type (-GrpCod)
{
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod = - GrpCod ;
Grp_GetDataOfGroupTypeByCod ( & Gbl . Crs . Grps . GrpTyp ) ;
2019-11-11 10:59:24 +01:00
HTM_TxtF ( " %s (%s) " , Gbl . Crs . Grps . GrpTyp . GrpTypName ,
Txt_users_with_no_group ) ;
2014-12-01 23:55:08 +01:00
}
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . LstGrpsSel . NumGrps > = 2 )
2014-12-01 23:55:08 +01:00
{
2019-04-04 10:45:15 +02:00
if ( NumGrpSel = = Gbl . Crs . Grps . LstGrpsSel . NumGrps - 2 )
2019-11-11 00:15:44 +01:00
HTM_TxtF ( " %s " , Txt_and ) ;
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . LstGrpsSel . NumGrps > = 3 )
if ( NumGrpSel < Gbl . Crs . Grps . LstGrpsSel . NumGrps - 2 )
2019-11-10 16:41:47 +01:00
HTM_Txt ( " , " ) ;
2014-12-01 23:55:08 +01:00
}
}
}
/*****************************************************************************/
/************************** Put forms to edit groups *************************/
/*****************************************************************************/
void Grp_ReqEditGroups ( void )
2017-04-29 20:42:10 +02:00
{
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
Ale_INFO , NULL ) ;
2017-04-29 20:42:10 +02:00
}
2019-03-09 20:12:44 +01:00
static void Grp_ReqEditGroupsInternal ( Ale_AlertType_t AlertTypeGroupTypes ,
const char * AlertTextGroupTypes ,
Ale_AlertType_t AlertTypeGroups ,
const char * AlertTextGroups )
2017-04-28 18:03:30 +02:00
{
2017-04-29 02:20:34 +02:00
Grp_ReqEditGroupsInternal0 ( ) ;
2019-03-09 20:12:44 +01:00
Grp_ReqEditGroupsInternal1 ( AlertTypeGroupTypes , AlertTextGroupTypes ) ;
Grp_ReqEditGroupsInternal2 ( AlertTypeGroups , AlertTextGroups ) ;
2017-04-28 18:03:30 +02:00
}
2017-04-29 02:20:34 +02:00
static void Grp_ReqEditGroupsInternal0 ( void )
2017-04-29 00:23:48 +02:00
{
2017-04-29 02:20:34 +02:00
/***** Start groups types section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin ( Grp_GROUP_TYPES_SECTION_ID ) ;
2017-04-29 00:23:48 +02:00
}
2019-03-09 20:12:44 +01:00
static void Grp_ReqEditGroupsInternal1 ( Ale_AlertType_t AlertTypeGroupTypes ,
const char * AlertTextGroupTypes )
2014-12-01 23:55:08 +01:00
{
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ALL_GROUP_TYPES ) ;
2017-04-29 02:20:34 +02:00
/***** Show optional alert *****/
2019-03-09 20:12:44 +01:00
if ( AlertTextGroupTypes )
if ( AlertTextGroupTypes [ 0 ] )
Ale_ShowAlert ( AlertTypeGroupTypes , AlertTextGroupTypes ) ;
2017-04-28 18:03:30 +02:00
2017-04-29 02:20:34 +02:00
/***** Put form to edit group types *****/
2014-12-01 23:55:08 +01:00
Grp_EditGroupTypes ( ) ;
2017-04-29 02:20:34 +02:00
/***** End groups types section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ( ) ;
2017-04-28 18:03:30 +02:00
2017-04-29 02:20:34 +02:00
/***** Start groups section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin ( Grp_GROUPS_SECTION_ID ) ;
2017-04-29 00:23:48 +02:00
}
2017-04-28 18:03:30 +02:00
2019-03-09 20:12:44 +01:00
static void Grp_ReqEditGroupsInternal2 ( Ale_AlertType_t AlertTypeGroups ,
const char * AlertTextGroups )
2017-04-29 00:23:48 +02:00
{
2020-04-14 17:15:17 +02:00
struct Roo_Rooms Rooms ;
2020-04-14 11:08:23 +02:00
2020-04-14 17:15:17 +02:00
/***** Reset rooms context *****/
Roo_ResetRooms ( & Rooms ) ;
2020-04-14 11:08:23 +02:00
2017-04-29 02:20:34 +02:00
/***** Show optional alert *****/
2019-03-09 20:12:44 +01:00
if ( AlertTextGroups )
if ( AlertTextGroups [ 0 ] )
Ale_ShowAlert ( AlertTypeGroups , AlertTextGroups ) ;
2017-04-29 02:20:34 +02:00
2020-04-14 17:15:17 +02:00
/***** Get list of rooms in this centre *****/
Roo_GetListRooms ( & Rooms , Roo_ONLY_SHRT_NAME ) ;
2020-04-14 11:08:23 +02:00
2017-04-29 02:20:34 +02:00
/***** Put form to edit groups *****/
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTypes . Num ) // If there are group types...
2020-04-14 17:15:17 +02:00
Grp_EditGroups ( & Rooms ) ;
2014-12-01 23:55:08 +01:00
2017-04-29 02:20:34 +02:00
/***** End groups section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ( ) ;
2017-04-29 02:20:34 +02:00
2020-04-14 17:15:17 +02:00
/***** Free list of rooms in this centre *****/
Roo_FreeListRooms ( & Rooms ) ;
2019-01-04 12:53:40 +01:00
2017-04-29 02:20:34 +02:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Put forms to edit group types *********************/
/*****************************************************************************/
static void Grp_EditGroupTypes ( void )
{
2017-04-29 20:16:53 +02:00
extern const char * Hlp_USERS_Groups ;
extern const char * Txt_Types_of_group ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_There_are_no_types_of_group_in_the_course_X ;
2019-10-26 02:19:42 +02:00
/***** Begin box *****/
2020-03-26 02:54:30 +01:00
Box_BoxBegin ( NULL , Txt_Types_of_group ,
2020-04-08 18:18:46 +02:00
Grp_PutIconsEditingGroupTypes , NULL ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE ) ;
2017-04-29 20:16:53 +02:00
2017-05-11 14:47:48 +02:00
/***** Put a form to create a new group type *****/
Grp_PutFormToCreateGroupType ( ) ;
2014-12-01 23:55:08 +01:00
/***** Forms to edit current group types *****/
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTypes . Num ) // Group types found...
2014-12-01 23:55:08 +01:00
Grp_ListGroupTypesForEdition ( ) ;
else // No group types found in this course
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_INFO , Txt_There_are_no_types_of_group_in_the_course_X ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . ShrtName ) ;
2014-12-01 23:55:08 +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
}
/*****************************************************************************/
/**************************** Put forms to edit groups ***********************/
/*****************************************************************************/
2020-04-14 17:15:17 +02:00
static void Grp_EditGroups ( const struct Roo_Rooms * Rooms )
2014-12-01 23:55:08 +01:00
{
2017-04-29 20:16:53 +02:00
extern const char * Hlp_USERS_Groups ;
extern const char * Txt_Groups ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_No_groups_have_been_created_in_the_course_X ;
2019-10-26 02:19:42 +02:00
/***** Begin box *****/
2020-03-26 02:54:30 +01:00
Box_BoxBegin ( NULL , Txt_Groups ,
2020-04-08 18:18:46 +02:00
Grp_PutIconsEditingGroups , NULL ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE ) ;
2017-04-29 20:16:53 +02:00
2017-05-11 14:47:48 +02:00
/***** Put a form to create a new group *****/
2020-04-14 17:15:17 +02:00
Grp_PutFormToCreateGroup ( Rooms ) ;
2017-05-11 14:47:48 +02:00
2014-12-01 23:55:08 +01:00
/***** Forms to edit current groups *****/
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTypes . NumGrpsTotal ) // If there are groups...
2020-04-14 17:15:17 +02:00
Grp_ListGroupsForEdition ( Rooms ) ;
2014-12-01 23:55:08 +01:00
else // There are group types, but there aren't groups
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_INFO , Txt_No_groups_have_been_created_in_the_course_X ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . ShrtName ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End box *****/
2019-10-25 22:48:34 +02:00
Box_BoxEnd ( ) ;
2017-04-29 20:16:53 +02:00
}
/*****************************************************************************/
/**************** Put contextual icons in edition of groups ******************/
/*****************************************************************************/
2020-04-08 18:18:46 +02:00
static void Grp_PutIconsEditingGroups ( __attribute__ ( ( unused ) ) void * Args )
2017-04-29 20:16:53 +02:00
{
2020-04-08 18:18:46 +02:00
/***** Put icon to view groups *****/
Grp_PutIconToViewGroups ( ) ;
2017-04-29 20:16:53 +02:00
2020-04-08 18:18:46 +02:00
/***** Put icon to create a new group *****/
Grp_PutIconToCreateNewGroup ( ) ;
2017-04-29 20:16:53 +02:00
}
static void Grp_PutIconToCreateNewGroup ( void )
{
extern const char * Txt_New_group ;
/***** Put form to create a new group *****/
2020-03-26 02:54:30 +01:00
Ico_PutContextualIconToAdd ( ActReqEdiGrp , Grp_NEW_GROUP_SECTION_ID ,
NULL , NULL ,
2019-01-10 15:26:33 +01:00
Txt_New_group ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** Show form to select one or several groups *******************/
/*****************************************************************************/
2020-03-26 02:54:30 +01:00
void Grp_ShowFormToSelectSeveralGroups ( void ( * FuncParams ) ( void * Args ) , void * Args ,
2017-07-02 18:53:35 +02:00
Grp_WhichGroups_t GroupsSelectableByStdsOrNETs )
2014-12-01 23:55:08 +01:00
{
2016-11-13 20:54:06 +01:00
extern const char * Hlp_USERS_Groups ;
2019-11-19 00:17:23 +01:00
extern const char * The_ClassFormLinkInBoxBold [ The_NUM_THEMES ] ;
2015-04-11 14:27:18 +02:00
extern const char * Txt_Groups ;
2017-05-30 18:24:26 +02:00
extern const char * Txt_Update_users ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpTyp ;
2016-11-25 03:21:02 +01:00
bool ICanEdit ;
2014-12-01 23:55:08 +01:00
2019-04-10 17:46:42 +02:00
/***** Trivial check: if no groups ==> nothing to do *****/
if ( ! Gbl . Crs . Grps . NumGrps )
return ;
2016-11-25 03:21:02 +01:00
2019-10-26 02:19:42 +02:00
/***** Begin box *****/
2019-04-10 17:46:42 +02:00
ICanEdit = ! Gbl . Form . Inside & &
( Gbl . Usrs . Me . Role . Logged = = Rol_TCH | |
Gbl . Usrs . Me . Role . Logged = = Rol_SYS_ADM ) ;
2020-03-26 02:54:30 +01:00
if ( ICanEdit )
Box_BoxBegin ( NULL , Txt_Groups ,
2020-04-08 18:18:46 +02:00
Grp_PutIconToEditGroups , NULL ,
2020-03-26 02:54:30 +01:00
Hlp_USERS_Groups , Box_CLOSABLE ) ;
else
Box_BoxBegin ( NULL , Txt_Groups ,
NULL , NULL ,
Hlp_USERS_Groups , Box_CLOSABLE ) ;
2016-11-25 03:21:02 +01:00
2019-10-20 22:00:28 +02:00
/***** Begin form to update the students listed
2019-04-10 17:46:42 +02:00
depending on the groups selected * * * * */
2019-04-11 14:45:31 +02:00
Frm_StartFormAnchor ( Gbl . Action . Act , // Repeat current action
Usr_USER_LIST_SECTION_ID ) ;
2019-04-10 17:46:42 +02:00
Usr_PutParamsPrefsAboutUsrList ( ) ;
2019-04-11 09:55:35 +02:00
if ( FuncParams )
2020-03-26 02:54:30 +01:00
FuncParams ( Args ) ;
2016-11-25 03:21:02 +01:00
2019-04-10 17:46:42 +02:00
/***** Select all groups *****/
Grp_PutCheckboxAllGrps ( GroupsSelectableByStdsOrNETs ) ;
2016-11-25 03:21:02 +01:00
2019-04-10 17:46:42 +02:00
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
2016-11-25 03:21:02 +01:00
2019-04-10 17:46:42 +02:00
/***** List the groups for each group type *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_BeginWidePadding ( 2 ) ;
2019-04-10 17:46:42 +02:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps )
Grp_ListGrpsForMultipleSelection ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ,
GroupsSelectableByStdsOrNETs ) ;
2019-10-23 19:05:05 +02:00
HTM_TABLE_End ( ) ;
2016-11-25 03:21:02 +01:00
2019-04-10 17:46:42 +02:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
2016-11-25 03:21:02 +01:00
2019-04-10 17:46:42 +02:00
/***** Submit button *****/
2019-10-24 00:04:40 +02:00
HTM_DIV_Begin ( " class= \" CM \" style= \" padding-top:12px; \" " ) ;
2019-11-19 00:17:23 +01:00
HTM_BUTTON_Animated_Begin ( Txt_Update_users ,
The_ClassFormLinkInBoxBold [ Gbl . Prefs . Theme ] ,
Gbl . Action . Act = = ActReqMsgUsr ? " CopyMessageToHiddenFields(); " :
NULL ) ;
2019-04-10 17:46:42 +02:00
Ico_PutCalculateIconWithText ( Txt_Update_users ) ;
2019-11-19 00:17:23 +01:00
HTM_BUTTON_End ( ) ;
2019-10-23 20:07:56 +02:00
HTM_DIV_End ( ) ;
2016-11-25 03:21:02 +01:00
2019-04-10 17:46:42 +02:00
/***** End form *****/
Frm_EndForm ( ) ;
2016-11-25 03:21:02 +01:00
2019-04-10 17:46:42 +02:00
/***** End box *****/
2019-10-25 22:48:34 +02:00
Box_BoxEnd ( ) ;
2014-12-01 23:55:08 +01:00
}
2017-05-30 19:42:10 +02:00
/*****************************************************************************/
/******************* Put checkbox to select all groups ***********************/
/*****************************************************************************/
2017-07-02 18:53:35 +02:00
static void Grp_PutCheckboxAllGrps ( Grp_WhichGroups_t GroupsSelectableByStdsOrNETs )
2017-05-30 19:42:10 +02:00
{
2019-02-22 21:47:50 +01:00
extern const char * The_ClassFormInBox [ The_NUM_THEMES ] ;
2017-05-30 19:42:10 +02:00
extern const char * Txt_All_groups ;
2017-06-06 20:27:46 +02:00
bool ICanSelUnselGroup ;
switch ( Gbl . Usrs . Me . Role . Logged )
{
2017-07-02 18:53:35 +02:00
case Rol_STD :
2017-06-06 20:27:46 +02:00
case Rol_NET :
2017-07-02 18:53:35 +02:00
ICanSelUnselGroup = ( GroupsSelectableByStdsOrNETs = = Grp_ALL_GROUPS ) ;
2017-06-06 20:27:46 +02:00
break ;
case Rol_TCH :
case Rol_DEG_ADM :
case Rol_CTR_ADM :
case Rol_INS_ADM :
case Rol_SYS_ADM :
ICanSelUnselGroup = true ;
break ;
default :
ICanSelUnselGroup = false ;
break ;
}
2017-05-30 19:42:10 +02:00
2019-10-24 00:04:40 +02:00
HTM_DIV_Begin ( " class= \" CONTEXT_OPT \" " ) ;
2019-11-04 20:41:35 +01:00
HTM_LABEL_Begin ( " class= \" %s \" " , The_ClassFormInBox [ Gbl . Prefs . Theme ] ) ;
2020-03-12 13:53:37 +01:00
HTM_INPUT_CHECKBOX ( " AllGroups " , HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-04 20:41:35 +01:00
" value= \" Y \" %s " ,
ICanSelUnselGroup ? ( Gbl . Usrs . ClassPhoto . AllGroups ? " checked= \" checked \" "
" onclick= \" togglecheckChildren(this,'GrpCods') \" " :
" onclick= \" togglecheckChildren(this,'GrpCods') \" " ) :
" disabled= \" disabled \" " ) ;
2019-11-11 10:59:24 +01:00
HTM_TxtF ( " %s " , Txt_All_groups ) ;
2019-11-02 12:59:31 +01:00
HTM_LABEL_End ( ) ;
2019-10-23 20:07:56 +02:00
HTM_DIV_End ( ) ;
2017-05-30 19:42:10 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************ Put parameters with the groups of students selected ************/
/*****************************************************************************/
void Grp_PutParamsCodGrps ( void )
{
2019-11-03 13:19:32 +01:00
extern const char * Par_SEPARATOR_PARAM_MULTIPLE ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpSel ;
2019-11-03 13:19:32 +01:00
size_t MaxLengthGrpCods ;
char * GrpCods ;
2019-11-08 01:10:32 +01:00
char GrpCod [ Cns_MAX_DECIMAL_DIGITS_LONG + 1 ] ;
2014-12-01 23:55:08 +01:00
/***** Write the boolean parameter that indicates if all the groups must be listed *****/
Par_PutHiddenParamChar ( " AllGroups " ,
Gbl . Usrs . ClassPhoto . AllGroups ? ' Y ' :
' N ' ) ;
/***** Write the parameter with the list of group codes to show *****/
if ( ! Gbl . Usrs . ClassPhoto . AllGroups & &
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . LstGrpsSel . NumGrps )
2014-12-01 23:55:08 +01:00
{
2019-11-11 11:20:31 +01:00
MaxLengthGrpCods = Gbl . Crs . Grps . LstGrpsSel . NumGrps * ( Cns_MAX_DECIMAL_DIGITS_LONG + 1 ) - 1 ;
2019-11-03 13:19:32 +01:00
if ( ( GrpCods = ( char * ) malloc ( MaxLengthGrpCods + 1 ) ) = = NULL )
Lay_NotEnoughMemoryExit ( ) ;
2019-11-11 11:20:31 +01:00
GrpCods [ 0 ] = ' \0 ' ;
2019-11-03 13:19:32 +01:00
2014-12-01 23:55:08 +01:00
for ( NumGrpSel = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpSel < Gbl . Crs . Grps . LstGrpsSel . NumGrps ;
2014-12-01 23:55:08 +01:00
NumGrpSel + + )
{
2019-11-03 13:19:32 +01:00
/* Append group code to list */
2014-12-01 23:55:08 +01:00
if ( NumGrpSel )
2019-11-03 13:19:32 +01:00
Str_Concat ( GrpCods , Par_SEPARATOR_PARAM_MULTIPLE , MaxLengthGrpCods ) ;
snprintf ( GrpCod , sizeof ( GrpCod ) ,
" %ld " ,
Gbl . Crs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] ) ;
Str_Concat ( GrpCods , GrpCod , MaxLengthGrpCods ) ;
2014-12-01 23:55:08 +01:00
}
2019-11-03 13:19:32 +01:00
Par_PutHiddenParamString ( NULL , " GrpCods " , GrpCods ) ;
2019-11-06 19:45:20 +01:00
free ( GrpCods ) ;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/**************** Get parameters related to groups selected ******************/
/*****************************************************************************/
void Grp_GetParCodsSeveralGrpsToShowUsrs ( void )
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrp ;
2019-04-04 10:45:15 +02:00
if ( + + Gbl . Crs . Grps . LstGrpsSel . NestedCalls > 1 ) // If list is created yet, there's nothing to do
2014-12-01 23:55:08 +01:00
return ;
/***** Get boolean parameter that indicates if all groups must be listed *****/
2017-01-28 20:32:50 +01:00
Gbl . Usrs . ClassPhoto . AllGroups = Par_GetParToBool ( " AllGroups " ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
/***** Get parameter with list of groups selected *****/
Grp_GetParCodsSeveralGrps ( ) ;
2014-12-01 23:55:08 +01:00
2019-11-08 01:10:32 +01:00
if ( Gbl . Crs . Grps . NumGrps & & // This course has groups and...
2019-04-04 10:45:15 +02:00
! Gbl . Crs . Grps . LstGrpsSel . NumGrps ) // ...I haven't selected any group
2017-01-19 20:55:31 +01:00
{
/***** I I haven't selected any group, show by default the groups I belong to *****/
/* Get list of groups of all types in current course I belong to */
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , - 1L ,
2017-01-19 20:55:31 +01:00
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . NumGrps )
{
/* Allocate space for list of selected groups */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . LstGrpsSel . GrpCods = ( long * ) calloc ( LstGrpsIBelong . NumGrps , sizeof ( long ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2017-01-19 20:55:31 +01:00
/* Fill list of selected groups with list of groups I belong to */
for ( NumGrp = 0 ;
NumGrp < LstGrpsIBelong . NumGrps ;
NumGrp + + )
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . LstGrpsSel . GrpCods [ NumGrp ] = LstGrpsIBelong . GrpCods [ NumGrp ] ;
Gbl . Crs . Grps . LstGrpsSel . NumGrps = LstGrpsIBelong . NumGrps ;
2017-01-19 20:55:31 +01:00
}
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
/* Free list of groups I belong to */
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
2014-12-01 23:55:08 +01:00
}
/***** If no groups selected ==> show all groups *****/
2019-04-04 10:45:15 +02:00
if ( ! Gbl . Crs . Grps . LstGrpsSel . NumGrps )
2014-12-01 23:55:08 +01:00
Gbl . Usrs . ClassPhoto . AllGroups = true ;
}
/*****************************************************************************/
2017-01-19 20:55:31 +01:00
/**************** Get parameter with list of groups selected *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-01-19 20:55:31 +01:00
void Grp_GetParCodsSeveralGrps ( void )
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
char * ParamLstCodGrps ;
2014-12-01 23:55:08 +01:00
const char * Ptr ;
2019-11-08 01:10:32 +01:00
char LongStr [ Cns_MAX_DECIMAL_DIGITS_LONG + 1 ] ;
2014-12-01 23:55:08 +01:00
unsigned NumGrp ;
2019-11-08 01:10:32 +01:00
unsigned long MaxSizeLstGrpCods = ( ( Cns_MAX_DECIMAL_DIGITS_LONG + 1 ) * Gbl . Crs . Grps . NumGrps ) - 1 ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
/***** Reset number of groups selected *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . LstGrpsSel . NumGrps = 0 ;
2014-12-01 23:55:08 +01:00
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . NumGrps ) // If course has groups
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
/***** Allocate memory for the list of group codes selected *****/
if ( ( ParamLstCodGrps = ( char * ) malloc ( MaxSizeLstGrpCods + 1 ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get parameter with list of groups to list *****/
2017-01-19 20:55:31 +01:00
Par_GetParMultiToText ( " GrpCods " , ParamLstCodGrps , MaxSizeLstGrpCods ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
if ( ParamLstCodGrps [ 0 ] )
{
/***** Count number of groups selected from LstCodGrps *****/
for ( Ptr = ParamLstCodGrps , NumGrp = 0 ;
* Ptr ;
NumGrp + + )
2019-11-08 01:10:32 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , Cns_MAX_DECIMAL_DIGITS_LONG ) ;
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . LstGrpsSel . NumGrps = NumGrp ;
2017-01-19 20:55:31 +01:00
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . LstGrpsSel . NumGrps ) // If I have selected groups...
2017-01-19 20:55:31 +01:00
{
/***** Create a list of groups selected from LstCodGrps *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . LstGrpsSel . GrpCods = ( long * ) calloc ( Gbl . Crs . Grps . LstGrpsSel . NumGrps , sizeof ( long ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2017-01-19 20:55:31 +01:00
for ( Ptr = ParamLstCodGrps , NumGrp = 0 ;
* Ptr ;
NumGrp + + )
{
2019-11-08 01:10:32 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , Cns_MAX_DECIMAL_DIGITS_LONG ) ;
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . LstGrpsSel . GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( LongStr ) ;
2017-01-19 20:55:31 +01:00
}
}
}
2014-12-01 23:55:08 +01:00
/***** Free memory used for the list of groups to show *****/
2019-11-06 19:45:20 +01:00
free ( ParamLstCodGrps ) ;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/********* Free memory used for the list of group codes selected *************/
/*****************************************************************************/
void Grp_FreeListCodSelectedGrps ( void )
{
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . LstGrpsSel . NestedCalls > 0 )
if ( - - Gbl . Crs . Grps . LstGrpsSel . NestedCalls = = 0 )
if ( Gbl . Crs . Grps . LstGrpsSel . GrpCods )
2014-12-01 23:55:08 +01:00
{
2019-11-06 19:45:20 +01:00
free ( Gbl . Crs . Grps . LstGrpsSel . GrpCods ) ;
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . LstGrpsSel . GrpCods = NULL ;
Gbl . Crs . Grps . LstGrpsSel . NumGrps = 0 ;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/******************* Change my groups and show form again ********************/
/*****************************************************************************/
void Grp_ChangeMyGrpsAndShowChanges ( void )
{
/***** Change my groups *****/
2017-06-04 18:18:54 +02:00
Grp_ChangeMyGrps ( Cns_VERBOSE ) ;
2014-12-01 23:55:08 +01:00
/***** Show again the table of selection of groups with the changes already made *****/
Grp_ReqRegisterInGrps ( ) ;
}
/*****************************************************************************/
/****************************** Change my groups *****************************/
/*****************************************************************************/
2017-06-04 18:18:54 +02:00
void Grp_ChangeMyGrps ( Cns_QuietOrVerbose_t QuietOrVerbose )
2014-12-01 23:55:08 +01:00
{
extern const char * Txt_The_requested_group_changes_were_successful ;
extern const char * Txt_There_has_been_no_change_in_groups ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsIWant ;
2017-06-20 01:58:16 +02:00
bool MySelectionIsValid ;
2017-06-04 18:18:54 +02:00
bool ChangesMade ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Can I change my groups? *****/
if ( Grp_ICanChangeGrps [ Gbl . Usrs . Me . Role . Logged ] )
{
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Get the group codes which I want to join to *****/
LstGrpsIWant . GrpCods = NULL ; // Initialized to avoid bug reported by Coverity
2017-06-20 01:58:16 +02:00
LstGrpsIWant . NumGrps = 0 ; // Initialized to avoid bug reported by Coverity
2017-06-04 18:18:54 +02:00
Grp_GetLstCodsGrpWanted ( & LstGrpsIWant ) ;
/***** A student can not be enroled in more than one group
if the type of group is of single enrolment * * * * */
// As the form to register in groups of single enrolment...
// ...is a radio-based form and not a checkbox-based form...
// ...this check is made only to avoid problems...
// ...if the student manipulates the form
2017-06-20 01:58:16 +02:00
MySelectionIsValid = Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid ( Gbl . Usrs . Me . Role . Logged , & LstGrpsIWant ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Free list of groups types and groups in this course *****/
// The lists of group types and groups need to be freed here...
// ...in order to get them again when changing my groups atomically
Grp_FreeListGrpTypesAndGrps ( ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Change my groups *****/
if ( MySelectionIsValid )
{
ChangesMade = Grp_ChangeMyGrpsAtomically ( & LstGrpsIWant ) ;
if ( QuietOrVerbose = = Cns_VERBOSE )
{
if ( ChangesMade )
2019-03-09 20:12:44 +01:00
Ale_CreateAlert ( Ale_SUCCESS , NULL ,
Txt_The_requested_group_changes_were_successful ) ;
2017-06-04 18:18:54 +02:00
else
2019-03-09 20:12:44 +01:00
Ale_CreateAlert ( Ale_WARNING , NULL ,
Txt_There_has_been_no_change_in_groups ) ;
2017-06-04 18:18:54 +02:00
}
}
else if ( QuietOrVerbose = = Cns_VERBOSE )
2019-03-09 20:12:44 +01:00
Ale_CreateAlert ( Ale_WARNING , NULL ,
Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Free memory with the list of groups which I want to belong to *****/
Grp_FreeListCodGrp ( & LstGrpsIWant ) ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Change groups of another user ************************/
/*****************************************************************************/
void Grp_ChangeOtherUsrGrps ( void )
{
extern const char * Txt_The_requested_group_changes_were_successful ;
extern const char * Txt_There_has_been_no_change_in_groups ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsUsrWants ;
2017-06-20 01:58:16 +02:00
bool SelectionIsValid ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Can I change another user's groups? *****/
if ( Grp_ICanChangeGrps [ Gbl . Usrs . Me . Role . Logged ] )
{
/***** Get list of groups types and groups in current course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Get the list of groups to which register this user *****/
LstGrpsUsrWants . GrpCods = NULL ; // Initialized to avoid bug reported by Coverity
LstGrpsUsrWants . NumGrps = 0 ; // Initialized to avoid bug reported by Coverity
Grp_GetLstCodsGrpWanted ( & LstGrpsUsrWants ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** A student can not be enroled in more than one group
if the type of group is of single enrolment * * * * */
2017-06-20 01:58:16 +02:00
SelectionIsValid = Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs . Role , & LstGrpsUsrWants ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Free list of groups types and groups in this course *****/
// The lists of group types and groups need to be freed here...
// ...in order to get them again when changing groups atomically
Grp_FreeListGrpTypesAndGrps ( ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Register user in the selected groups *****/
if ( SelectionIsValid )
Grp_ChangeGrpsOtherUsrAtomically ( & LstGrpsUsrWants ) ;
2019-03-09 20:12:44 +01:00
else
Ale_CreateAlert ( Ale_WARNING , NULL ,
Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Free memory with the list of groups to/from which register/remove users *****/
Grp_FreeListCodGrp ( & LstGrpsUsrWants ) ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Change my groups atomically **************************/
/*****************************************************************************/
// Return true if desired changes are made
bool Grp_ChangeMyGrpsAtomically ( struct ListCodGrps * LstGrpsIWant )
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrpTyp ;
unsigned NumGrpIBelong ;
unsigned NumGrpIWant ;
unsigned NumGrpThisType ;
struct GroupType * GrpTyp ;
bool ITryToLeaveAClosedGroup = false ;
bool ITryToRegisterInAClosedGroup = false ;
bool ITryToRegisterInFullGroup = false ;
bool RemoveMeFromThisGrp ;
bool RegisterMeInThisGrp ;
bool ChangesMade = false ;
/***** Lock tables to make the inscription atomic *****/
2018-10-22 10:12:41 +02:00
Grp_LockTables ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** Query in the database the group codes which I belong to *****/
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , - 1L ,
2014-12-01 23:55:08 +01:00
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2017-06-04 18:18:54 +02:00
if ( Gbl . Usrs . Me . Role . Logged = = Rol_STD )
2014-12-01 23:55:08 +01:00
{
/***** Go across the list of groups which I belong to and check if I try to leave a closed group *****/
for ( NumGrpIBelong = 0 ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & ! ITryToLeaveAClosedGroup ;
NumGrpIBelong + + )
{
for ( NumGrpIWant = 0 , RemoveMeFromThisGrp = true ;
NumGrpIWant < LstGrpsIWant - > NumGrps & & RemoveMeFromThisGrp ;
NumGrpIWant + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . GrpCods [ NumGrpIBelong ] = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
RemoveMeFromThisGrp = false ;
if ( RemoveMeFromThisGrp )
/* Check if the group is closed */
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num & & ! ITryToLeaveAClosedGroup ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
GrpTyp = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
2014-12-01 23:55:08 +01:00
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps & & ! ITryToLeaveAClosedGroup ;
NumGrpThisType + + )
2017-01-19 20:55:31 +01:00
if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . GrpCod = = LstGrpsIBelong . GrpCods [ NumGrpIBelong ] )
2014-12-01 23:55:08 +01:00
if ( ! ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . Open ) )
ITryToLeaveAClosedGroup = true ;
}
}
if ( ! ITryToLeaveAClosedGroup )
/***** Go across the list of groups which I want to belong
and check that they are not closed or full * * * * */
for ( NumGrpIWant = 0 ;
NumGrpIWant < LstGrpsIWant - > NumGrps & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpIWant + + )
{
for ( NumGrpIBelong = 0 , RegisterMeInThisGrp = true ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & RegisterMeInThisGrp ;
NumGrpIBelong + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIWant - > GrpCods [ NumGrpIWant ] = = LstGrpsIBelong . GrpCods [ NumGrpIBelong ] )
2014-12-01 23:55:08 +01:00
RegisterMeInThisGrp = false ;
if ( RegisterMeInThisGrp )
/* Check if the group is closed or full */
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num & &
2014-12-01 23:55:08 +01:00
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
GrpTyp = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
2014-12-01 23:55:08 +01:00
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpThisType + + )
2017-01-19 20:55:31 +01:00
if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . GrpCod = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
{
/* Check if the group is closed */
if ( ! ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . Open ) )
ITryToRegisterInAClosedGroup = true ;
/* Check if the group is full */
2017-05-30 21:43:05 +02:00
else if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . NumUsrs [ Rol_STD ] > =
2014-12-01 23:55:08 +01:00
( GrpTyp - > LstGrps [ NumGrpThisType ] ) . MaxStudents )
ITryToRegisterInFullGroup = true ;
}
}
}
}
if ( ! ITryToLeaveAClosedGroup & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup )
{
/***** Go across the list of groups I belong to, removing those groups that are not present in the list of groups I want to belong to *****/
for ( NumGrpIBelong = 0 ;
NumGrpIBelong < LstGrpsIBelong . NumGrps ;
NumGrpIBelong + + )
{
for ( NumGrpIWant = 0 , RemoveMeFromThisGrp = true ;
NumGrpIWant < LstGrpsIWant - > NumGrps & & RemoveMeFromThisGrp ;
NumGrpIWant + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . GrpCods [ NumGrpIBelong ] = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
RemoveMeFromThisGrp = false ;
if ( RemoveMeFromThisGrp )
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( Gbl . Usrs . Me . UsrDat . UsrCod , LstGrpsIBelong . GrpCods [ NumGrpIBelong ] ) ;
2014-12-01 23:55:08 +01:00
}
/***** Go across the list of groups that I want to register in, adding those groups that are not present in the list of groups I belong to *****/
for ( NumGrpIWant = 0 ;
NumGrpIWant < LstGrpsIWant - > NumGrps ;
NumGrpIWant + + )
{
for ( NumGrpIBelong = 0 , RegisterMeInThisGrp = true ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & RegisterMeInThisGrp ;
NumGrpIBelong + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIWant - > GrpCods [ NumGrpIWant ] = = LstGrpsIBelong . GrpCods [ NumGrpIBelong ] )
2014-12-01 23:55:08 +01:00
RegisterMeInThisGrp = false ;
if ( RegisterMeInThisGrp )
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( & Gbl . Usrs . Me . UsrDat , LstGrpsIWant - > GrpCods [ NumGrpIWant ] ) ;
2014-12-01 23:55:08 +01:00
}
ChangesMade = true ;
}
/***** Free memory with the list of groups which I belonged to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
/***** Unlock tables after changes in my groups *****/
2018-10-22 10:12:41 +02:00
Grp_UnlockTables ( ) ;
2014-12-01 23:55:08 +01:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
return ChangesMade ;
}
/*****************************************************************************/
/********************** Change my groups atomically **************************/
/*****************************************************************************/
2017-06-04 18:18:54 +02:00
void Grp_ChangeGrpsOtherUsrAtomically ( struct ListCodGrps * LstGrpsUsrWants )
2014-12-01 23:55:08 +01:00
{
struct ListCodGrps LstGrpsUsrBelongs ;
unsigned NumGrpUsrBelongs ;
unsigned NumGrpUsrWants ;
bool RemoveUsrFromThisGrp ;
bool RegisterUsrInThisGrp ;
2018-10-22 10:12:41 +02:00
/***** Lock tables to make the inscription atomic *****/
2017-06-08 15:32:33 +02:00
if ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs . Role = = Rol_STD )
2018-10-22 10:12:41 +02:00
Grp_LockTables ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** Query in the database the group codes which user belongs to *****/
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , - 1L ,
2014-12-01 23:55:08 +01:00
Gbl . Usrs . Other . UsrDat . UsrCod , & LstGrpsUsrBelongs ) ;
/***** Go across the list of groups user belongs to, removing those groups that are not present in the list of groups user wants to belong to *****/
for ( NumGrpUsrBelongs = 0 ;
NumGrpUsrBelongs < LstGrpsUsrBelongs . NumGrps ;
NumGrpUsrBelongs + + )
{
for ( NumGrpUsrWants = 0 , RemoveUsrFromThisGrp = true ;
NumGrpUsrWants < LstGrpsUsrWants - > NumGrps & & RemoveUsrFromThisGrp ;
NumGrpUsrWants + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] = = LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] )
2014-12-01 23:55:08 +01:00
RemoveUsrFromThisGrp = false ;
if ( RemoveUsrFromThisGrp )
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( Gbl . Usrs . Other . UsrDat . UsrCod , LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] ) ;
2014-12-01 23:55:08 +01:00
}
/***** Go across the list of groups that user wants to register in, adding those groups that are not present in the list of groups user belongs to *****/
for ( NumGrpUsrWants = 0 ;
NumGrpUsrWants < LstGrpsUsrWants - > NumGrps ;
NumGrpUsrWants + + )
{
for ( NumGrpUsrBelongs = 0 , RegisterUsrInThisGrp = true ;
NumGrpUsrBelongs < LstGrpsUsrBelongs . NumGrps & & RegisterUsrInThisGrp ;
NumGrpUsrBelongs + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] = = LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] )
2014-12-01 23:55:08 +01:00
RegisterUsrInThisGrp = false ;
if ( RegisterUsrInThisGrp )
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( & Gbl . Usrs . Other . UsrDat , LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] ) ;
2014-12-01 23:55:08 +01:00
}
2018-10-22 10:12:41 +02:00
/***** Free memory with the list of groups which user belonged to *****/
2014-12-01 23:55:08 +01:00
Grp_FreeListCodGrp ( & LstGrpsUsrBelongs ) ;
2018-10-22 10:12:41 +02:00
/***** Unlock tables after changes in groups *****/
2017-06-08 15:32:33 +02:00
if ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs . Role = = Rol_STD )
2018-10-22 10:12:41 +02:00
Grp_UnlockTables ( ) ;
2014-12-01 23:55:08 +01:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
}
2018-10-22 10:12:41 +02:00
/*****************************************************************************/
/*********** Lock tables to make the registration in groups atomic ***********/
/*****************************************************************************/
static void Grp_LockTables ( void )
{
2018-11-02 22:41:02 +01:00
DB_Query ( " can not lock tables to change user's groups " ,
2019-01-07 17:00:04 +01:00
" LOCK TABLES "
" crs_grp_types WRITE, "
" crs_grp WRITE, "
" crs_grp_usr WRITE, "
" crs_usr READ, "
2020-04-30 01:55:23 +02:00
" crs_usr_last READ, "
2020-04-14 17:15:17 +02:00
" rooms READ " ) ;
2018-10-22 10:12:41 +02:00
Gbl . DB . LockedTables = true ;
}
/*****************************************************************************/
/*********** Unlock tables after changes in registration in groups ***********/
/*****************************************************************************/
static void Grp_UnlockTables ( void )
{
Gbl . DB . LockedTables = false ; // Set to false before the following unlock...
// ...to not retry the unlock if error in unlocking
2018-11-02 22:41:02 +01:00
DB_Query ( " can not unlock tables after changing user's groups " ,
" UNLOCK TABLES " ) ;
2018-10-22 10:12:41 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-06-20 01:58:16 +02:00
/******* Check if not selected more than a group of single enrolment *********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-06-20 01:58:16 +02:00
bool Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid ( Rol_Role_t Role , struct ListCodGrps * LstGrps )
2014-12-01 23:55:08 +01:00
{
struct ListGrpsAlreadySelec * AlreadyExistsGroupOfType ;
unsigned NumCodGrp ;
unsigned NumGrpTyp ;
long GrpTypCod ;
2017-06-20 01:58:16 +02:00
bool MultipleEnrolment ;
bool SelectionValid ;
2014-12-01 23:55:08 +01:00
2017-06-20 01:58:16 +02:00
switch ( Role )
2014-12-01 23:55:08 +01:00
{
2017-06-20 01:58:16 +02:00
case Rol_STD :
if ( LstGrps - > NumGrps < = 1 )
return true ;
/***** Create and initialize list of groups already selected *****/
Grp_ConstructorListGrpAlreadySelec ( & AlreadyExistsGroupOfType ) ;
2017-07-02 18:53:35 +02:00
/***** Go across the list of groups selected
checking if a group of the same type is already selected * * * * */
2017-06-20 01:58:16 +02:00
SelectionValid = true ;
for ( NumCodGrp = 0 ;
SelectionValid & & NumCodGrp < LstGrps - > NumGrps ;
NumCodGrp + + )
{
GrpTypCod = Grp_GetTypeOfGroupOfAGroup ( LstGrps - > GrpCods [ NumCodGrp ] ) ;
MultipleEnrolment = Grp_GetMultipleEnrolmentOfAGroupType ( GrpTypCod ) ;
if ( ! MultipleEnrolment )
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2017-06-20 01:58:16 +02:00
NumGrpTyp + + )
if ( GrpTypCod = = AlreadyExistsGroupOfType [ NumGrpTyp ] . GrpTypCod )
{
if ( AlreadyExistsGroupOfType [ NumGrpTyp ] . AlreadySelected )
SelectionValid = false ;
else
AlreadyExistsGroupOfType [ NumGrpTyp ] . AlreadySelected = true ;
break ;
}
}
2014-12-01 23:55:08 +01:00
2017-06-20 01:58:16 +02:00
/***** Free memory of the list of booleanos that indicates
if a group of each type has been selected * * * * */
Grp_DestructorListGrpAlreadySelec ( & AlreadyExistsGroupOfType ) ;
return SelectionValid ; // Return true if the selection of groups is correct
case Rol_NET :
case Rol_TCH :
return true ;
default :
return false ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Create e inicializar list of groups already selected ************/
/*****************************************************************************/
static void Grp_ConstructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType )
{
unsigned NumGrpTyp ;
/***** Allocate memory to a list of booleanos that indica if already se ha selected a group of cada type *****/
2019-04-04 10:45:15 +02:00
if ( ( * AlreadyExistsGroupOfType = ( struct ListGrpsAlreadySelec * ) calloc ( Gbl . Crs . Grps . GrpTypes . Num , sizeof ( struct ListGrpsAlreadySelec ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Initialize the list *****/
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
( * AlreadyExistsGroupOfType ) [ NumGrpTyp ] . GrpTypCod = Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ;
2014-12-01 23:55:08 +01:00
( * AlreadyExistsGroupOfType ) [ NumGrpTyp ] . AlreadySelected = false ;
}
}
/*****************************************************************************/
/***************** Liberar list of groups already selected *******************/
/*****************************************************************************/
static void Grp_DestructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType )
{
2019-11-06 19:45:20 +01:00
free ( * AlreadyExistsGroupOfType ) ;
2014-12-01 23:55:08 +01:00
* AlreadyExistsGroupOfType = NULL ;
}
/*****************************************************************************/
/******************* Register user in the groups of a list *******************/
/*****************************************************************************/
void Grp_RegisterUsrIntoGroups ( struct UsrData * UsrDat , struct ListCodGrps * LstGrps )
{
extern const char * Txt_THE_USER_X_has_been_removed_from_the_group_of_type_Y_to_which_it_belonged ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_THE_USER_X_has_been_enroled_in_the_group_of_type_Y_Z ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsHeBelongs ;
2016-12-29 22:19:46 +01:00
unsigned NumGrpTyp ;
unsigned NumGrpSel ;
unsigned NumGrpThisType ;
unsigned NumGrpHeBelongs ;
2017-03-30 11:20:06 +02:00
bool MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
bool AlreadyRegisteredInGrp ;
/***** For each existing type of group in the course... *****/
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
MultipleEnrolment = Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
/***** Query in the database the group codes of any group of this type the student belongs to *****/
2016-12-29 22:42:57 +01:00
LstGrpsHeBelongs . NumGrps = 0 ; // Initialized to avoid bug reported by Coverity
2017-01-19 20:55:31 +01:00
LstGrpsHeBelongs . GrpCods = NULL ; // Initialized to avoid bug reported by Coverity
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ,
2014-12-01 23:55:08 +01:00
UsrDat - > UsrCod , & LstGrpsHeBelongs ) ;
/***** For each group selected by me... *****/
for ( NumGrpSel = 0 ;
NumGrpSel < LstGrps - > NumGrps ;
NumGrpSel + + )
{
/* Check if the selected group is of this type */
for ( NumGrpThisType = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpThisType < Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ;
2014-12-01 23:55:08 +01:00
NumGrpThisType + + )
2019-04-04 10:45:15 +02:00
if ( LstGrps - > GrpCods [ NumGrpSel ] = = Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . LstGrps [ NumGrpThisType ] . GrpCod )
2014-12-01 23:55:08 +01:00
{ // The selected group is of this type
AlreadyRegisteredInGrp = false ;
/* For each group of this type to which the user belongs... */
for ( NumGrpHeBelongs = 0 ;
NumGrpHeBelongs < LstGrpsHeBelongs . NumGrps ;
NumGrpHeBelongs + + )
2017-01-19 20:55:31 +01:00
if ( LstGrps - > GrpCods [ NumGrpSel ] = = LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] )
2014-12-01 23:55:08 +01:00
AlreadyRegisteredInGrp = true ;
2017-03-30 11:20:06 +02:00
else if ( ! MultipleEnrolment ) // If the type of group is of single enrolment
2014-12-01 23:55:08 +01:00
{
2017-03-30 11:20:06 +02:00
/* If the enrolment is single and the group to which the user belongs is different from the selected ==>
2014-12-01 23:55:08 +01:00
remove user from the group to which he belongs */
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( UsrDat - > UsrCod , LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] ) ;
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_SUCCESS , Txt_THE_USER_X_has_been_removed_from_the_group_of_type_Y_to_which_it_belonged ,
2019-04-04 10:45:15 +02:00
UsrDat - > FullName , Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
if ( ! AlreadyRegisteredInGrp ) // If the user does not belong to the selected group
{
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( UsrDat , LstGrps - > GrpCods [ NumGrpSel ] ) ;
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_SUCCESS , Txt_THE_USER_X_has_been_enroled_in_the_group_of_type_Y_Z ,
2019-04-04 10:45:15 +02:00
UsrDat - > FullName , Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . LstGrps [ NumGrpThisType ] . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
break ; // Once we know the type of a selected group, it's not necessary to check the rest of types
}
}
/***** Free the list of groups of this type to which the user belonged *****/
Grp_FreeListCodGrp ( & LstGrpsHeBelongs ) ;
}
}
/*****************************************************************************/
/**************** Remove user of the groups indicados in a list **************/
/*****************************************************************************/
// Returns NumGrpsHeIsRemoved
unsigned Grp_RemoveUsrFromGroups ( struct UsrData * UsrDat , struct ListCodGrps * LstGrps )
{
extern const char * Txt_THE_USER_X_has_not_been_removed_from_any_group ;
extern const char * Txt_THE_USER_X_has_been_removed_from_one_group ;
extern const char * Txt_THE_USER_X_has_been_removed_from_Y_groups ;
struct ListCodGrps LstGrpsHeBelongs ;
2017-06-20 14:43:26 +02:00
unsigned NumGrpSel ;
unsigned NumGrpHeBelongs ;
unsigned NumGrpsHeIsRemoved = 0 ;
2014-12-01 23:55:08 +01:00
/***** Query in the database the group codes of any group the user belongs to *****/
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , - 1L ,
2014-12-01 23:55:08 +01:00
UsrDat - > UsrCod , & LstGrpsHeBelongs ) ;
/***** For each group selected by me... *****/
for ( NumGrpSel = 0 ;
NumGrpSel < LstGrps - > NumGrps ;
NumGrpSel + + )
/* For each group to which the user belongs... */
for ( NumGrpHeBelongs = 0 ;
NumGrpHeBelongs < LstGrpsHeBelongs . NumGrps ;
NumGrpHeBelongs + + )
/* If the user belongs to a selected group from which he must be removed */
2017-01-19 20:55:31 +01:00
if ( LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] = = LstGrps - > GrpCods [ NumGrpSel ] )
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( UsrDat - > UsrCod , LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] ) ;
2014-12-01 23:55:08 +01:00
NumGrpsHeIsRemoved + + ;
}
/***** Write message to inform about how many groups the student has been removed from *****/
if ( NumGrpsHeIsRemoved = = 0 )
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_SUCCESS , Txt_THE_USER_X_has_not_been_removed_from_any_group ,
UsrDat - > FullName ) ;
2014-12-01 23:55:08 +01:00
else if ( NumGrpsHeIsRemoved = = 1 )
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_SUCCESS , Txt_THE_USER_X_has_been_removed_from_one_group ,
UsrDat - > FullName ) ;
2014-12-01 23:55:08 +01:00
else // NumGrpsHeIsRemoved > 1
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_SUCCESS , Txt_THE_USER_X_has_been_removed_from_Y_groups ,
UsrDat - > FullName , NumGrpsHeIsRemoved ) ;
2014-12-01 23:55:08 +01:00
/***** Free the list of groups of this type to which the user belonged *****/
Grp_FreeListCodGrp ( & LstGrpsHeBelongs ) ;
return NumGrpsHeIsRemoved ;
}
/*****************************************************************************/
/*************** Remove a user of all the groups of a course *****************/
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
void Grp_RemUsrFromAllGrpsInCrs ( long UsrCod , long CrsCod )
2014-12-01 23:55:08 +01:00
{
2018-10-10 23:56:42 +02:00
bool ItsMe = Usr_ItsMe ( UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove user from all the groups of the course *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove a user from all groups of a course " ,
" DELETE FROM crs_grp_usr "
" WHERE UsrCod=%ld AND GrpCod IN "
" (SELECT crs_grp.GrpCod FROM crs_grp_types,crs_grp "
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod) " ,
UsrCod , CrsCod ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
if ( ItsMe )
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******* Remove a user from all the groups of all the user's courses *********/
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
void Grp_RemUsrFromAllGrps ( long UsrCod )
2014-12-01 23:55:08 +01:00
{
2018-10-10 23:56:42 +02:00
bool ItsMe = Usr_ItsMe ( UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove user from all groups *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove a user from the groups he/she belongs to " ,
" DELETE FROM crs_grp_usr WHERE UsrCod=%ld " ,
UsrCod ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
if ( ItsMe )
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Remove a user from a group ************************/
/*****************************************************************************/
static void Grp_RemoveUsrFromGroup ( long UsrCod , long GrpCod )
{
2018-10-10 23:56:42 +02:00
bool ItsMe = Usr_ItsMe ( UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove user from group *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove a user from a group " ,
" DELETE FROM crs_grp_usr "
" WHERE GrpCod=%ld AND UsrCod=%ld " ,
GrpCod , UsrCod ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
if ( ItsMe )
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Register a user in a group **************************/
/*****************************************************************************/
static void Grp_AddUsrToGroup ( struct UsrData * UsrDat , long GrpCod )
{
/***** Register in group *****/
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ( " can not add a user to a group " ,
" INSERT INTO crs_grp_usr "
" (GrpCod,UsrCod) "
" VALUES "
" (%ld,%ld) " ,
GrpCod , UsrDat - > UsrCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** List current group types for edition *******************/
/*****************************************************************************/
static void Grp_ListGroupTypesForEdition ( void )
{
2017-04-29 20:16:53 +02:00
2014-12-01 23:55:08 +01:00
extern const char * Txt_It_is_optional_to_choose_a_group ;
extern const char * Txt_It_is_mandatory_to_choose_a_group ;
extern const char * Txt_A_student_can_belong_to_several_groups ;
extern const char * Txt_A_student_can_only_belong_to_one_group ;
extern const char * Txt_The_groups_will_automatically_open ;
extern const char * Txt_The_groups_will_not_automatically_open ;
unsigned NumGrpTyp ;
2015-10-26 20:02:07 +01:00
unsigned UniqueId ;
char Id [ 32 ] ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_BeginWidePadding ( 2 ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteHeadingGroupTypes ( ) ;
/***** List group types with forms for edition *****/
2015-10-26 20:02:07 +01:00
for ( NumGrpTyp = 0 , UniqueId = 1 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2015-10-26 20:02:07 +01:00
NumGrpTyp + + , UniqueId + + )
2014-12-01 23:55:08 +01:00
{
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-10-08 23:28:51 +02:00
/* Put icon to remove group type */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActReqRemGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2019-04-04 10:45:15 +02:00
Grp_PutParamGrpTypCod ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-06-11 19:13:28 +02:00
Ico_PutIconRemove ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/* Name of group type */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActRenGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2019-04-04 10:45:15 +02:00
Grp_PutParamGrpTypCod ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2019-11-04 12:25:48 +01:00
HTM_INPUT_TEXT ( " GrpTypName " , Grp_MAX_CHARS_GROUP_TYPE_NAME ,
2020-04-27 03:16:55 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ,
HTM_SUBMIT_ON_CHANGE ,
2019-11-04 12:25:48 +01:00
" size= \" 12 \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/* Is it mandatory to register in any group? */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActChgMdtGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2019-04-04 10:45:15 +02:00
Grp_PutParamGrpTypCod ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
2019-11-05 15:47:35 +01:00
" name= \" MandatoryEnrolment \" "
" style= \" width:150px; \" " ) ;
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_STRING , " N " ,
! Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MandatoryEnrolment , false ,
" %s " , Txt_It_is_optional_to_choose_a_group ) ;
HTM_OPTION ( HTM_Type_STRING , " Y " ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MandatoryEnrolment , false ,
" %s " , Txt_It_is_mandatory_to_choose_a_group ) ;
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/* Is it possible to register in multiple groups? */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActChgMulGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2019-04-04 10:45:15 +02:00
Grp_PutParamGrpTypCod ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
2019-11-05 15:47:35 +01:00
" name= \" MultipleEnrolment \" "
" style= \" width:150px; \" " ) ;
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_STRING , " N " ,
! Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment , false ,
" %s " , Txt_A_student_can_only_belong_to_one_group ) ;
HTM_OPTION ( HTM_Type_STRING , " Y " ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment , false ,
" %s " , Txt_A_student_can_belong_to_several_groups ) ;
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/* Open time */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActChgTimGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2019-04-04 10:45:15 +02:00
Grp_PutParamGrpTypCod ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2019-10-23 19:05:05 +02:00
HTM_TABLE_BeginCenterPadding ( 2 ) ;
HTM_TR_Begin ( NULL ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" style= \" width:16px; \" " ) ;
2019-10-29 21:41:54 +01:00
Ico_PutIcon ( " clock.svg " ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? " CONTEXT_ICO_16x16 " :
" ICO_HIDDEN CONTEXT_ICO_16x16 " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2018-10-18 02:02:32 +02:00
snprintf ( Id , sizeof ( Id ) ,
" open_time_%u " ,
UniqueId ) ;
2015-10-26 20:02:07 +01:00
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( Id ,
" Open " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . OpenTimeUTC ,
2015-10-26 20:02:07 +01:00
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
2016-12-03 20:08:01 +01:00
Dat_FORM_SECONDS_ON ,
2017-02-26 20:09:21 +01:00
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
true ) ; // Submit on change
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
HTM_TABLE_End ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/* Number of groups of this type */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2019-11-10 13:31:47 +01:00
HTM_Unsigned ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
2017-04-29 20:16:53 +02:00
/***** End table *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_End ( ) ;
2014-12-01 23:55:08 +01:00
}
2017-04-29 19:19:55 +02:00
/*****************************************************************************/
/************ Put contextual icons in edition of types of group **************/
/*****************************************************************************/
2020-04-08 18:18:46 +02:00
static void Grp_PutIconsEditingGroupTypes ( __attribute__ ( ( unused ) ) void * Args )
2017-04-29 19:19:55 +02:00
{
2020-04-08 18:18:46 +02:00
/***** Put icon to view groups *****/
Grp_PutIconToViewGroups ( ) ;
2017-04-29 19:19:55 +02:00
2020-04-08 18:18:46 +02:00
/***** Put icon to create a new type of group *****/
Grp_PutIconToCreateNewGroupType ( ) ;
2017-04-29 19:19:55 +02:00
}
static void Grp_PutIconToViewGroups ( void )
{
2020-03-26 02:54:30 +01:00
Ico_PutContextualIconToView ( ActReqSelGrp ,
NULL , NULL ) ;
2017-04-29 19:19:55 +02:00
}
static void Grp_PutIconToCreateNewGroupType ( void )
{
extern const char * Txt_New_type_of_group ;
/***** Put form to create a new type of group *****/
2020-03-26 02:54:30 +01:00
Ico_PutContextualIconToAdd ( ActReqEdiGrp , Grp_NEW_GROUP_TYPE_SECTION_ID ,
NULL , NULL ,
2019-01-10 15:26:33 +01:00
Txt_New_type_of_group ) ;
2017-04-29 19:19:55 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*********************** Write heading of group types ************************/
/*****************************************************************************/
static void Grp_WriteHeadingGroupTypes ( void )
{
extern const char * Txt_Type_of_group ;
extern const char * Txt_eg_Lectures_Practicals ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_Mandatory_enrolment ;
extern const char * Txt_Multiple_enrolment ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Opening_of_groups ;
2020-05-07 14:15:39 +02:00
extern const char * Txt_Number_of_BR_groups ;
2014-12-01 23:55:08 +01:00
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-10-12 00:07:52 +02:00
2019-10-23 19:05:05 +02:00
HTM_TH ( 1 , 1 , " BM " , NULL ) ;
HTM_TH_Begin ( 1 , 1 , " CM " ) ;
2019-11-10 12:36:37 +01:00
HTM_Txt ( Txt_Type_of_group ) ;
2019-11-09 21:08:20 +01:00
HTM_BR ( ) ;
2019-11-11 00:15:44 +01:00
HTM_TxtF ( " (%s) " , Txt_eg_Lectures_Practicals ) ;
2019-10-23 19:05:05 +02:00
HTM_TH_End ( ) ;
HTM_TH ( 1 , 1 , " CM " , Txt_Mandatory_enrolment ) ;
HTM_TH ( 1 , 1 , " CM " , Txt_Multiple_enrolment ) ;
HTM_TH ( 1 , 1 , " CM " , Txt_Opening_of_groups ) ;
2020-05-07 14:15:39 +02:00
HTM_TH ( 1 , 1 , " CM " , Txt_Number_of_BR_groups ) ;
2019-10-12 00:07:52 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** List current groups for edition **********************/
/*****************************************************************************/
2020-04-14 17:15:17 +02:00
static void Grp_ListGroupsForEdition ( const struct Roo_Rooms * Rooms )
2014-12-01 23:55:08 +01:00
{
extern const char * Txt_Group_X_open_click_to_close_it ;
extern const char * Txt_Group_X_closed_click_to_open_it ;
extern const char * Txt_File_zones_of_the_group_X_enabled_click_to_disable_them ;
extern const char * Txt_File_zones_of_the_group_X_disabled_click_to_enable_them ;
2020-04-14 17:15:17 +02:00
extern const char * Txt_No_assigned_room ;
extern const char * Txt_Another_room ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpTyp ;
unsigned NumTipGrpAux ;
unsigned NumGrpThisType ;
2020-04-15 02:17:57 +02:00
unsigned NumRoo ;
2014-12-01 23:55:08 +01:00
struct GroupType * GrpTyp ;
struct GroupType * GrpTypAux ;
struct Group * Grp ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2019-11-08 01:10:32 +01:00
char StrMaxStudents [ Cns_MAX_DECIMAL_DIGITS_UINT + 1 ] ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_BeginWidePadding ( 2 ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteHeadingGroups ( ) ;
/***** List the groups *****/
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
GrpTyp = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
2014-12-01 23:55:08 +01:00
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-10-08 23:28:51 +02:00
/***** Icon to remove group *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActReqRemGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2017-06-11 19:13:28 +02:00
Ico_PutIconRemove ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2019-01-04 22:46:46 +01:00
/***** Icon to open/close group *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( Grp - > Open ? ActCloGrp :
2017-04-29 01:12:35 +02:00
ActOpeGrp ,
2017-05-25 13:43:54 +02:00
Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2019-01-12 19:46:33 +01:00
Ico_PutIconLink ( Grp - > Open ? " unlock.svg " :
2019-01-12 03:00:59 +01:00
" lock.svg " ,
2019-12-30 21:47:07 +01:00
Str_BuildStringStr ( Grp - > Open ? Txt_Group_X_open_click_to_close_it :
Txt_Group_X_closed_click_to_open_it ,
Grp - > GrpName ) ) ;
Str_FreeString ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2019-01-04 22:46:46 +01:00
/***** Icon to activate file zones for this group *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( Grp - > FileZones ? ActDisFilZonGrp :
2017-04-29 01:12:35 +02:00
ActEnaFilZonGrp ,
2017-05-25 13:43:54 +02:00
Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2019-01-12 03:00:59 +01:00
Ico_PutIconLink ( Grp - > FileZones ? " folder-open-green.svg " :
" folder-red.svg " ,
2019-12-30 21:47:07 +01:00
Str_BuildStringStr ( Grp - > FileZones ? Txt_File_zones_of_the_group_X_enabled_click_to_disable_them :
Txt_File_zones_of_the_group_X_disabled_click_to_enable_them ,
Grp - > GrpName ) ) ;
Str_FreeString ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2019-01-04 22:46:46 +01:00
/***** Group type *****/
/* Start selector */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActChgGrpTyp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
2019-11-05 15:47:35 +01:00
" name= \" GrpTypCod \" style= \" width:100px; \" " ) ;
2019-01-04 22:46:46 +01:00
/* Options for group types */
2014-12-01 23:55:08 +01:00
for ( NumTipGrpAux = 0 ;
2019-04-04 10:45:15 +02:00
NumTipGrpAux < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumTipGrpAux + + )
{
2019-04-04 10:45:15 +02:00
GrpTypAux = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumTipGrpAux ] ;
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_LONG , & GrpTypAux - > GrpTypCod ,
GrpTypAux - > GrpTypCod = = GrpTyp - > GrpTypCod , false ,
" %s " , GrpTypAux - > GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
2019-01-04 22:46:46 +01:00
/* End selector */
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2019-01-04 22:46:46 +01:00
/***** Group name *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActRenGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2020-04-27 03:16:55 +02:00
HTM_INPUT_TEXT ( " GrpName " , Grp_MAX_CHARS_GROUP_NAME , Grp - > GrpName ,
HTM_SUBMIT_ON_CHANGE ,
2019-11-04 12:25:48 +01:00
" size= \" 20 \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2020-04-14 17:15:17 +02:00
/***** Room *****/
2019-01-04 22:46:46 +01:00
/* Start selector */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2020-04-14 17:15:17 +02:00
Frm_StartFormAnchor ( ActChgGrpRoo , Grp_GROUPS_SECTION_ID ) ;
2019-01-04 22:46:46 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
2020-04-14 17:15:17 +02:00
" name= \" RooCod \" style= \" width:100px; \" " ) ;
2019-01-04 22:46:46 +01:00
2020-04-14 17:15:17 +02:00
/* Option for no assigned room */
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_STRING , " -1 " ,
2020-04-14 17:15:17 +02:00
Grp - > Room . RooCod < 0 , false ,
" %s " , Txt_No_assigned_room ) ;
2019-01-04 22:46:46 +01:00
2020-04-14 17:15:17 +02:00
/* Option for another room */
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_STRING , " 0 " ,
2020-04-14 17:15:17 +02:00
Grp - > Room . RooCod = = 0 , false ,
" %s " , Txt_Another_room ) ;
2019-01-04 22:46:46 +01:00
2020-04-14 17:15:17 +02:00
/* Options for rooms */
2020-04-15 02:17:57 +02:00
for ( NumRoo = 0 ;
NumRoo < Rooms - > Num ;
NumRoo + + )
HTM_OPTION ( HTM_Type_LONG , & Rooms - > Lst [ NumRoo ] . RooCod ,
Rooms - > Lst [ NumRoo ] . RooCod = = Grp - > Room . RooCod , false ,
" %s " , Rooms - > Lst [ NumRoo ] . ShrtName ) ;
2019-01-04 22:46:46 +01:00
/* End selector */
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2019-01-04 22:46:46 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-01-04 22:46:46 +01:00
/***** Current number of users in this group *****/
2017-05-30 21:43:05 +02:00
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
2019-10-07 15:15:55 +02:00
{
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2019-11-11 10:59:24 +01:00
HTM_Int ( Grp - > NumUsrs [ Role ] ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
}
2017-05-30 21:43:05 +02:00
2019-01-04 22:46:46 +01:00
/***** Maximum number of students of the group (row[3]) *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActChgMaxStdGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2019-11-03 23:59:20 +01:00
Grp_WriteMaxStds ( StrMaxStudents , Grp - > MaxStudents ) ;
2020-04-27 03:16:55 +02:00
HTM_INPUT_TEXT ( " MaxStudents " , Cns_MAX_DECIMAL_DIGITS_UINT , StrMaxStudents ,
HTM_SUBMIT_ON_CHANGE ,
2019-11-04 12:25:48 +01:00
" size= \" 3 \" " ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-08 23:28:51 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
}
2016-11-14 10:05:41 +01:00
/***** End table *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_End ( ) ;
2017-04-29 19:32:06 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************** Write heading of groups **************************/
/*****************************************************************************/
static void Grp_WriteHeadingGroups ( void )
{
extern const char * Txt_Type_BR_of_group ;
extern const char * Txt_Group_name ;
extern const char * Txt_eg_A_B ;
2020-04-14 17:15:17 +02:00
extern const char * Txt_Room ;
2017-05-30 21:43:05 +02:00
extern const char * Txt_ROLES_PLURAL_BRIEF_Abc [ Rol_NUM_ROLES ] ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Max_BR_students ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-10-12 00:07:52 +02:00
2019-10-23 19:05:05 +02:00
HTM_TH ( 1 , 1 , " BM " , NULL ) ;
HTM_TH ( 1 , 1 , " BM " , NULL ) ;
HTM_TH ( 1 , 1 , " BM " , NULL ) ;
HTM_TH ( 1 , 1 , " CM " , Txt_Type_BR_of_group ) ;
HTM_TH_Begin ( 1 , 1 , " CM " ) ;
2019-11-10 12:36:37 +01:00
HTM_Txt ( Txt_Group_name ) ;
2019-11-09 21:08:20 +01:00
HTM_BR ( ) ;
2019-11-11 00:15:44 +01:00
HTM_TxtF ( " (%s) " , Txt_eg_A_B ) ;
2019-10-23 19:05:05 +02:00
HTM_TH_End ( ) ;
2020-04-14 17:15:17 +02:00
HTM_TH ( 1 , 1 , " CM " , Txt_Room ) ;
2017-05-30 21:43:05 +02:00
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
2019-10-23 19:05:05 +02:00
HTM_TH ( 1 , 1 , " CM " , Txt_ROLES_PLURAL_BRIEF_Abc [ Role ] ) ;
HTM_TH ( 1 , 1 , " CM " , Txt_Max_BR_students ) ;
2019-10-12 00:07:52 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2020-05-06 01:43:48 +02:00
/****** List groups of a type to edit ******/
/****** assignments, attendance events, surveys, exam events or matches ******/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2020-05-06 01:43:48 +02:00
void Grp_ListGrpsToEditAsgAttSvyEvtMch ( struct GroupType * GrpTyp , long Cod ,
Grp_WhichIsAssociatedToGrp_t WhichIsAssociatedToGrp )
2014-12-01 23:55:08 +01:00
{
2020-05-06 01:43:48 +02:00
static const struct
{
const char * Table ;
const char * Field ;
} AssociationsToGrps [ Grp_NUM_ASSOCIATIONS_TO_GROUPS ] =
{
[ Grp_ASSIGNMENT ] = { " asg_grp " , " AsgCod " } ,
[ Grp_ATT_EVENT ] = { " att_grp " , " AttCod " } ,
[ Grp_SURVEY ] = { " svy_grp " , " SvyCod " } ,
[ Grp_EXA_EVENT ] = { " exa_groups " , " EvtCod " } ,
[ Grp_MATCH ] = { " mch_groups " , " MchCod " } ,
} ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrpThisType ;
bool IBelongToThisGroup ;
struct Group * Grp ;
2020-05-06 01:43:48 +02:00
bool AssociatedToGrp ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query from the database the groups of this type which I belong to *****/
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , GrpTyp - > GrpTypCod ,
2014-12-01 23:55:08 +01:00
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
2020-05-06 01:43:48 +02:00
if ( Cod > 0 ) // Cod == -1L means new item, assignment, event, survey, exam event or match
AssociatedToGrp = Grp_CheckIfAssociatedToGrp ( AssociationsToGrps [ WhichIsAssociatedToGrp ] . Table ,
AssociationsToGrps [ WhichIsAssociatedToGrp ] . Field ,
Cod , Grp - > GrpCod ) ;
else
AssociatedToGrp = false ;
2019-11-04 20:41:35 +01:00
/* Put checkbox to select the group */
HTM_TR_Begin ( NULL ) ;
if ( IBelongToThisGroup )
HTM_TD_Begin ( " class= \" LM LIGHT_BLUE \" " ) ;
else
HTM_TD_Begin ( " class= \" LM \" " ) ;
2020-03-12 13:53:37 +01:00
HTM_INPUT_CHECKBOX ( " GrpCods " , HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-04 20:41:35 +01:00
" id= \" Grp%ld \" value= \" %ld \" %s%s "
" onclick= \" uncheckParent(this,'WholeCrs') \" " ,
Grp - > GrpCod , Grp - > GrpCod ,
AssociatedToGrp ? " checked= \" checked \" " : " " ,
( IBelongToThisGroup | |
Gbl . Usrs . Me . Role . Logged = = Rol_SYS_ADM ) ? " " : " disabled= \" disabled \" " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free memory with the list of groups which I belongs to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
}
2020-05-06 01:43:48 +02:00
/*****************************************************************************/
/************ Check if an assignment is associated to a group ****************/
/*****************************************************************************/
static bool Grp_CheckIfAssociatedToGrp ( const char * Table , const char * Field ,
long Cod , long GrpCod )
{
/***** Get if an assignment, attendance event, survey, exam event or match
is associated to a given group from database * * * * */
return ( DB_QueryCOUNT ( " can not check if associated to a group " ,
" SELECT COUNT(*) FROM %s "
" WHERE %s=%ld AND GrpCod=%ld " ,
Table , Field , Cod , GrpCod ) ! = 0 ) ;
}
/*****************************************************************************/
/*************** Check if a survey is associated to any group ****************/
/*****************************************************************************/
bool Grp_CheckIfAssociatedToGrps ( const char * Table , const char * Field , long Cod )
{
/***** Get if an assignment, attendance event, survey, exam event or match
is associated to any group from database * * * * */
return ( DB_QueryCOUNT ( " can not check if associated to groups " ,
" SELECT COUNT(*) FROM %s "
" WHERE %s=%ld " ,
Table , Field , Cod ) ! = 0 ) ;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************** Show list of groups to register/remove me *****************/
/*****************************************************************************/
void Grp_ReqRegisterInGrps ( void )
{
2016-03-28 01:02:34 +02:00
/***** Show list of groups to register/remove me *****/
2017-05-22 12:23:08 +02:00
Grp_ShowLstGrpsToChgMyGrps ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Show list of groups to register/remove me *****************/
/*****************************************************************************/
2017-05-22 12:23:08 +02:00
void Grp_ShowLstGrpsToChgMyGrps ( void )
2014-12-01 23:55:08 +01:00
{
2016-11-13 20:54:06 +01:00
extern const char * Hlp_USERS_Groups ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_My_groups ;
2016-03-16 15:00:47 +01:00
extern const char * Txt_Change_my_groups ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_Enrol_in_groups ;
2016-03-28 01:02:34 +02:00
extern const char * Txt_No_groups_have_been_created_in_the_course_X ;
2017-03-01 17:06:24 +01:00
extern const char * Txt_Create_group ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpTyp ;
2017-05-30 11:35:01 +02:00
unsigned NumGrpsThisTypeIBelong ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpsIBelong = 0 ;
2016-03-16 15:00:47 +01:00
bool PutFormToChangeGrps = ! Gbl . Form . Inside ; // Not inside another form (record card)
bool ICanEdit = ! Gbl . Form . Inside & &
2017-06-04 18:18:54 +02:00
( Gbl . Usrs . Me . Role . Logged = = Rol_TCH | |
Gbl . Usrs . Me . Role . Logged = = Rol_SYS_ADM ) ;
bool ICanChangeMyGrps = false ;
2014-12-01 23:55:08 +01:00
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . NumGrps ) // This course has groups
2016-03-28 01:02:34 +02:00
{
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
2014-12-01 23:55:08 +01:00
2016-03-28 01:02:34 +02:00
/***** Show warnings to students *****/
2017-03-30 11:20:06 +02:00
// Students are required to join groups with mandatory enrolment; teachers don't
2017-06-04 18:18:54 +02:00
if ( Gbl . Usrs . Me . Role . Logged = = Rol_STD )
2016-03-28 01:02:34 +02:00
Grp_ShowWarningToStdsToChangeGrps ( ) ;
}
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
if ( ICanEdit )
Box_BoxBegin ( NULL , Txt_My_groups ,
2020-04-08 18:18:46 +02:00
Grp_PutIconToEditGroups , NULL ,
2020-03-26 02:54:30 +01:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE ) ;
else
Box_BoxBegin ( NULL , Txt_My_groups ,
NULL , NULL ,
Hlp_USERS_Groups , Box_NOT_CLOSABLE ) ;
2016-03-16 15:00:47 +01:00
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . NumGrps ) // This course has groups
2016-03-16 15:00:47 +01:00
{
2019-10-20 22:00:28 +02:00
/***** Begin form *****/
2016-03-28 01:02:34 +02:00
if ( PutFormToChangeGrps )
2018-11-09 20:47:39 +01:00
Frm_StartForm ( ActChgGrp ) ;
2016-03-28 01:02:34 +02:00
/***** List the groups the user belongs to for change *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_BeginWidePadding ( 2 ) ;
2016-03-28 01:02:34 +02:00
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2016-03-28 01:02:34 +02:00
NumGrpTyp + + )
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) // If there are groups of this type
2017-05-30 11:35:01 +02:00
{
2019-04-04 10:45:15 +02:00
ICanChangeMyGrps | = Grp_ListGrpsForChangeMySelection ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ,
2017-06-04 18:18:54 +02:00
& NumGrpsThisTypeIBelong ) ;
2017-05-30 11:35:01 +02:00
NumGrpsIBelong + = NumGrpsThisTypeIBelong ;
}
2019-10-23 19:05:05 +02:00
HTM_TABLE_End ( ) ;
2016-03-28 01:02:34 +02:00
/***** End form *****/
if ( PutFormToChangeGrps )
{
2017-06-04 18:18:54 +02:00
if ( ICanChangeMyGrps )
2017-06-11 19:02:40 +02:00
Btn_PutConfirmButton ( NumGrpsIBelong ? Txt_Change_my_groups :
2017-05-30 11:35:01 +02:00
Txt_Enrol_in_groups ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2016-03-28 01:02:34 +02:00
}
}
else // This course has no groups
{
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_INFO , Txt_No_groups_have_been_created_in_the_course_X ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . FullName ) ;
2017-03-01 17:06:24 +01:00
/***** Button to create group *****/
if ( ICanEdit )
{
2018-11-09 20:47:39 +01:00
Frm_StartForm ( ActReqEdiGrp ) ;
2017-06-11 19:02:40 +02:00
Btn_PutConfirmButton ( Txt_Create_group ) ;
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2017-03-01 17:06:24 +01:00
}
2016-03-16 15:00:47 +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
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . NumGrps ) // This course has groups
2016-03-28 01:02:34 +02:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
2016-03-16 15:00:47 +01:00
}
/*****************************************************************************/
/*************************** Put icon to edit groups *************************/
/*****************************************************************************/
2020-04-08 18:18:46 +02:00
static void Grp_PutIconToEditGroups ( __attribute__ ( ( unused ) ) void * Args )
2016-03-16 15:00:47 +01:00
{
2020-04-08 18:18:46 +02:00
Ico_PutContextualIconToEdit ( ActReqEdiGrp , NULL ,
NULL , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Show warnings to students before form to change groups **********/
/*****************************************************************************/
static void Grp_ShowWarningToStdsToChangeGrps ( void )
{
extern const char * Txt_You_have_to_register_compulsorily_at_least_in_one_group_of_type_X ;
extern const char * Txt_You_have_to_register_compulsorily_in_one_group_of_type_X ;
extern const char * Txt_You_can_register_voluntarily_in_one_or_more_groups_of_type_X ;
extern const char * Txt_You_can_register_voluntarily_in_one_group_of_type_X ;
unsigned NumGrpTyp ;
struct GroupType * GrpTyp ;
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
GrpTyp = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
2019-02-18 14:41:46 +01:00
// If there are groups of this type...
if ( GrpTyp - > NumGrps )
// If I don't belong to any group
if ( ! Grp_CheckIfIBelongToGrpsOfType ( GrpTyp - > GrpTypCod ) ) // Fast check (not necesary, but avoid slow check)
// If there is any group of this type available
2019-02-18 17:30:35 +01:00
if ( Grp_GetIfAvailableGrpTyp ( GrpTyp - > GrpTypCod ) ) // Slow check
2014-12-01 23:55:08 +01:00
{
2017-03-30 11:20:06 +02:00
if ( GrpTyp - > MandatoryEnrolment )
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_WARNING , GrpTyp - > MultipleEnrolment ? Txt_You_have_to_register_compulsorily_at_least_in_one_group_of_type_X :
Txt_You_have_to_register_compulsorily_in_one_group_of_type_X ,
GrpTyp - > GrpTypName ) ;
2014-12-01 23:55:08 +01:00
else
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_INFO , GrpTyp - > MultipleEnrolment ? Txt_You_can_register_voluntarily_in_one_or_more_groups_of_type_X :
Txt_You_can_register_voluntarily_in_one_group_of_type_X ,
GrpTyp - > GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
}
}
/*****************************************************************************/
/*************** List the groups of a type to register in ********************/
/*****************************************************************************/
2017-05-30 11:35:01 +02:00
// Returns true if I can change my selection
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
static bool Grp_ListGrpsForChangeMySelection ( struct GroupType * GrpTyp ,
unsigned * NumGrpsThisTypeIBelong )
2014-12-01 23:55:08 +01:00
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrpThisType ;
struct Group * Grp ;
bool IBelongToThisGroup ;
2017-06-20 01:58:16 +02:00
bool IBelongToAClosedGroup ;
bool ICanChangeMySelectionForThisGrpTyp ;
bool ICanChangeMySelectionForThisGrp ;
2019-11-04 18:17:39 +01:00
char StrGrpCod [ 32 ] ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query in the database the group of this type that I belong to *****/
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , GrpTyp - > GrpTypCod ,
2014-12-01 23:55:08 +01:00
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2017-05-30 11:35:01 +02:00
* NumGrpsThisTypeIBelong = LstGrpsIBelong . NumGrps ;
2014-12-01 23:55:08 +01:00
2017-06-20 01:58:16 +02:00
/***** Check if I can change my selection *****/
switch ( Gbl . Usrs . Me . Role . Logged )
{
case Rol_STD :
if ( GrpTyp - > MultipleEnrolment ) // Enrolment is multiple
{
for ( NumGrpThisType = 0 , ICanChangeMySelectionForThisGrpTyp = false ;
NumGrpThisType < GrpTyp - > NumGrps & & ! ICanChangeMySelectionForThisGrpTyp ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
if ( Grp - > Open ) // If group is open
{
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
if ( IBelongToThisGroup ) // I belong to this group
ICanChangeMySelectionForThisGrpTyp = true ; // I can unregister from group
else // I don't belong
if ( Grp - > NumUsrs [ Rol_STD ] < Grp - > MaxStudents ) // Group is not full
ICanChangeMySelectionForThisGrpTyp = true ; // I can register into group
}
}
}
else // Enrolment is single
{
/* Step 1: Check if I belong to a closed group */
for ( NumGrpThisType = 0 , IBelongToAClosedGroup = false ;
NumGrpThisType < GrpTyp - > NumGrps & & ! IBelongToAClosedGroup ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
if ( ! Grp - > Open ) // If group is closed
{
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
if ( IBelongToThisGroup ) // I belong to this group
IBelongToAClosedGroup = true ; // I belong to a closed group
}
}
if ( IBelongToAClosedGroup ) // I belong to a closed group
ICanChangeMySelectionForThisGrpTyp = false ; // I can not unregister
else // I don't belong to a closed group
/* Step 2: Check if I can register in at least one group to which I don't belong */
for ( NumGrpThisType = 0 , ICanChangeMySelectionForThisGrpTyp = false ;
NumGrpThisType < GrpTyp - > NumGrps & & ! ICanChangeMySelectionForThisGrpTyp ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
if ( Grp - > Open & & // If group is open...
Grp - > NumUsrs [ Rol_STD ] < Grp - > MaxStudents ) // ...and not full
{
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
if ( ! IBelongToThisGroup ) // I don't belong to this group
ICanChangeMySelectionForThisGrpTyp = true ; // I can register into this group
}
}
}
break ;
case Rol_TCH :
case Rol_SYS_ADM :
ICanChangeMySelectionForThisGrpTyp = true ; // I can not register/unregister
break ;
default :
ICanChangeMySelectionForThisGrpTyp = false ; // I can not register/unregister
break ;
}
2014-12-01 23:55:08 +01:00
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
2017-06-20 01:58:16 +02:00
/* Selection disabled? */
if ( ICanChangeMySelectionForThisGrpTyp ) // I can change my selection for this group type
2017-05-30 11:35:01 +02:00
{
2017-06-20 01:58:16 +02:00
ICanChangeMySelectionForThisGrp = true ;
if ( Gbl . Usrs . Me . Role . Logged = = Rol_STD )
{
2017-05-30 11:35:01 +02:00
if ( Grp - > Open ) // If group is open
{
2017-06-20 01:58:16 +02:00
if ( ! IBelongToThisGroup & & // I don't belong to group
Grp - > NumUsrs [ Rol_STD ] > = Grp - > MaxStudents ) // Group is full
ICanChangeMySelectionForThisGrp = false ;
2017-05-30 11:35:01 +02:00
}
2017-06-20 01:58:16 +02:00
else // If group is closed
ICanChangeMySelectionForThisGrp = false ;
}
}
else // I can not change my selection for this group type
ICanChangeMySelectionForThisGrp = false ;
2019-11-04 20:41:35 +01:00
/* Put radio item or checkbox to select the group */
HTM_TR_Begin ( NULL ) ;
if ( IBelongToThisGroup )
HTM_TD_Begin ( " class= \" LM LIGHT_BLUE \" " ) ;
else
HTM_TD_Begin ( " class= \" LM \" " ) ;
2019-11-04 18:17:39 +01:00
snprintf ( StrGrpCod , sizeof ( StrGrpCod ) ,
" GrpCod%ld " ,
GrpTyp - > GrpTypCod ) ;
if ( Gbl . Usrs . Me . Role . Logged = = Rol_STD & & // If I am a student
! GrpTyp - > MultipleEnrolment & & // ...and the enrolment is single
GrpTyp - > NumGrps > 1 ) // ...and there are more than one group
{
/* Put a radio item */
if ( GrpTyp - > MandatoryEnrolment )
HTM_INPUT_RADIO ( StrGrpCod , false ,
" id= \" Grp%ld \" value= \" %ld \" %s%s " ,
Grp - > GrpCod , Grp - > GrpCod ,
IBelongToThisGroup ? " checked= \" checked \" " : " " , // Group selected?
ICanChangeMySelectionForThisGrp ? " " :
IBelongToThisGroup ? " readonly " : // I can not unregister (disabled does not work because the value is not submitted)
" disabled= \" disabled \" " ) ; // I can not register
else // If the enrolment is not mandatory, I can select no groups
HTM_INPUT_RADIO ( StrGrpCod , false ,
" id= \" Grp%ld \" value= \" %ld \" %s%s "
" onclick= \" selectUnselectRadio(this,this.form.GrpCod%ld,%u) \" " ,
Grp - > GrpCod , Grp - > GrpCod ,
IBelongToThisGroup ? " checked= \" checked \" " : " " , // Group selected?
ICanChangeMySelectionForThisGrp ? " " :
IBelongToThisGroup ? " readonly " : // I can not unregister (disabled does not work because the value is not submitted)
" disabled= \" disabled \" " , // I can not register
GrpTyp - > GrpTypCod , GrpTyp - > NumGrps ) ;
}
else
/* Put a checkbox item */
2020-03-12 13:53:37 +01:00
HTM_INPUT_CHECKBOX ( StrGrpCod , HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-04 20:41:35 +01:00
" id= \" Grp%ld \" value= \" %ld \" %s%s " ,
Grp - > GrpCod , Grp - > GrpCod ,
IBelongToThisGroup ? " checked= \" checked \" " : " " ,
ICanChangeMySelectionForThisGrp ? " " :
IBelongToThisGroup ? " readonly " : // I can not unregister (disabled does not work because the value is not submitted)
" disabled= \" disabled \" " ) ; // I can not register
2017-06-20 01:58:16 +02:00
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free memory with the list of groups a the that belongs the user *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
2017-06-20 01:58:16 +02:00
return ICanChangeMySelectionForThisGrpTyp ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** Show list of groups to register/remove users ****************/
/*****************************************************************************/
2019-03-08 01:18:31 +01:00
// If UsrCod > 0 ==> mark her/his groups as checked
2014-12-01 23:55:08 +01:00
// If UsrCod <= 0 ==> do not mark any group as checked
void Grp_ShowLstGrpsToChgOtherUsrsGrps ( long UsrCod )
{
2016-11-13 20:54:06 +01:00
extern const char * Hlp_USERS_Groups ;
2015-02-08 18:39:58 +01:00
extern const char * Txt_Groups ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpTyp ;
/***** Get list of groups types and groups in current course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
2019-10-26 02:19:42 +02:00
/***** Begin box and table *****/
2020-03-26 02:54:30 +01:00
Box_BoxTableBegin ( NULL , Txt_Groups ,
NULL , NULL ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE , 0 ) ;
2014-12-01 23:55:08 +01:00
/***** List to select the groups the user belongs to *****/
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps )
Grp_ListGrpsToAddOrRemUsrs ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] , UsrCod ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End table and box *****/
2019-11-25 23:18:08 +01:00
Box_BoxTableEnd ( ) ;
2014-12-01 23:55:08 +01:00
/***** Free list of groups types and groups in current course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
}
/*****************************************************************************/
/*************** List groups of a type to add or remove users ****************/
/*****************************************************************************/
2019-03-08 01:18:31 +01:00
// If UsrCod > 0 ==> mark her/his groups as checked
2014-12-01 23:55:08 +01:00
// If UsrCod <= 0 ==> do not mark any group as checked
static void Grp_ListGrpsToAddOrRemUsrs ( struct GroupType * GrpTyp , long UsrCod )
{
struct ListCodGrps LstGrpsUsrBelongs ;
unsigned NumGrpThisType ;
bool UsrBelongsToThisGroup ;
struct Group * Grp ;
2019-11-04 20:41:35 +01:00
char StrGrpCod [ 32 ] ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
2019-03-08 01:18:31 +01:00
/***** Query the groups of this type which the user belongs to *****/
2014-12-01 23:55:08 +01:00
if ( UsrCod > 0 )
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , GrpTyp - > GrpTypCod ,
2014-12-01 23:55:08 +01:00
Gbl . Usrs . Other . UsrDat . UsrCod , & LstGrpsUsrBelongs ) ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
UsrBelongsToThisGroup = ( UsrCod > 0 ) ? Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsUsrBelongs ) :
false ;
2019-03-09 22:01:06 +01:00
/* Start row */
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-03-09 22:01:06 +01:00
/* Start cell for checkbox */
2014-12-01 23:55:08 +01:00
if ( UsrBelongsToThisGroup )
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM LIGHT_BLUE \" " ) ;
2019-10-08 23:28:51 +02:00
else
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2019-03-09 22:01:06 +01:00
/* Put checkbox to select the group */
// Always checkbox, not radio, because the role in the form may be teacher,
// so if he/she is registered as teacher, he/she can belong to several groups
2019-11-04 20:41:35 +01:00
snprintf ( StrGrpCod , sizeof ( StrGrpCod ) ,
" GrpCod%ld " ,
GrpTyp - > GrpTypCod ) ;
2020-03-12 13:53:37 +01:00
HTM_INPUT_CHECKBOX ( StrGrpCod , HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-07 14:34:03 +01:00
" id= \" Grp%ld \" value= \" %ld \" %s " ,
2019-11-04 20:41:35 +01:00
Grp - > GrpCod , Grp - > GrpCod ,
UsrBelongsToThisGroup ? " checked= \" checked \" " : " " ) ; // I can not register
2019-03-09 22:01:06 +01:00
/* End cell for checkbox */
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2019-03-09 22:01:06 +01:00
/* Write cell for group */
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , UsrBelongsToThisGroup ) ;
2019-03-09 22:01:06 +01:00
/* End row */
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free memory with the lists of groups *****/
if ( UsrCod > 0 )
Grp_FreeListCodGrp ( & LstGrpsUsrBelongs ) ;
}
/*****************************************************************************/
/******* Write a list of groups as checkbox form for unique selection ********/
/*****************************************************************************/
2017-06-23 09:56:01 +02:00
static void Grp_ListGrpsForMultipleSelection ( struct GroupType * GrpTyp ,
2017-07-02 18:53:35 +02:00
Grp_WhichGroups_t GroupsSelectableByStdsOrNETs )
2014-12-01 23:55:08 +01:00
{
2017-05-30 21:43:05 +02:00
extern const char * Txt_users_with_no_group ;
2014-12-01 23:55:08 +01:00
unsigned NumGrpThisType ;
unsigned NumGrpSel ;
struct ListCodGrps LstGrpsIBelong ;
bool IBelongToThisGroup ;
2017-06-06 20:27:46 +02:00
bool ICanSelUnselGroup ;
2019-11-04 20:41:35 +01:00
bool Checked ;
2014-12-01 23:55:08 +01:00
struct Group * Grp ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query from the database the groups of this type which I belong to *****/
2019-04-04 10:45:15 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Hierarchy . Crs . CrsCod , GrpTyp - > GrpTypCod ,
2014-12-01 23:55:08 +01:00
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2017-06-06 20:27:46 +02:00
/***** List the groups of this type *****/
2014-12-01 23:55:08 +01:00
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
2017-06-06 20:27:46 +02:00
/* Pointer to group */
2014-12-01 23:55:08 +01:00
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
2017-06-06 20:27:46 +02:00
/* Check if I belong to his group */
2014-12-01 23:55:08 +01:00
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
2017-06-06 20:27:46 +02:00
/* Check if I can select / unselect this group */
if ( IBelongToThisGroup )
ICanSelUnselGroup = true ;
else
switch ( Gbl . Usrs . Me . Role . Logged )
{
2017-07-02 18:53:35 +02:00
case Rol_STD :
2017-06-06 20:27:46 +02:00
case Rol_NET :
2017-07-02 18:53:35 +02:00
ICanSelUnselGroup = ( GroupsSelectableByStdsOrNETs = = Grp_ALL_GROUPS ) | |
2017-06-23 09:56:01 +02:00
IBelongToThisGroup ;
2017-06-06 20:27:46 +02:00
break ;
case Rol_TCH :
case Rol_DEG_ADM :
case Rol_CTR_ADM :
case Rol_INS_ADM :
case Rol_SYS_ADM :
2017-07-02 18:53:35 +02:00
ICanSelUnselGroup = true ; // GroupsSelectable is ignored
2017-06-06 20:27:46 +02:00
break ;
default :
2017-07-02 18:53:35 +02:00
ICanSelUnselGroup = false ; // GroupsSelectable is ignored
2017-06-06 20:27:46 +02:00
break ;
}
2019-11-04 20:41:35 +01:00
/* This group should be checked? */
2014-12-01 23:55:08 +01:00
if ( Gbl . Usrs . ClassPhoto . AllGroups )
2019-11-04 20:41:35 +01:00
Checked = true ;
2014-12-01 23:55:08 +01:00
else
2019-11-04 20:41:35 +01:00
for ( NumGrpSel = 0 , Checked = false ;
2019-04-04 10:45:15 +02:00
NumGrpSel < Gbl . Crs . Grps . LstGrpsSel . NumGrps ;
2014-12-01 23:55:08 +01:00
NumGrpSel + + )
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] = = Grp - > GrpCod )
2014-12-01 23:55:08 +01:00
{
2019-11-04 20:41:35 +01:00
Checked = true ;
2014-12-01 23:55:08 +01:00
break ;
}
2019-11-04 20:41:35 +01:00
/* Put checkbox to select the group */
HTM_TR_Begin ( NULL ) ;
if ( IBelongToThisGroup )
HTM_TD_Begin ( " class= \" LM LIGHT_BLUE \" " ) ;
2017-06-06 20:27:46 +02:00
else
2019-11-04 20:41:35 +01:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2020-03-12 13:53:37 +01:00
HTM_INPUT_CHECKBOX ( " GrpCods " , HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-04 20:41:35 +01:00
" id= \" Grp%ld \" value= \" %ld \" %s%s " ,
Grp - > GrpCod , Grp - > GrpCod ,
Checked ? " checked= \" checked \" " : " " ,
ICanSelUnselGroup ? " onclick= \" checkParent(this,'AllGroups') \" " :
" disabled= \" disabled \" " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free memory with the list of groups which I belongs to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
/***** Write rows to select the students who don't belong to any group *****/
/* To get the students who don't belong to a type of group, use group code -(GrpTyp->GrpTypCod) */
/* Write checkbox to select the group */
2019-04-10 17:46:42 +02:00
ICanSelUnselGroup = ( Gbl . Usrs . Me . Role . Logged > = Rol_STD ) ;
2017-06-06 20:27:46 +02:00
if ( ICanSelUnselGroup )
{
if ( Gbl . Usrs . ClassPhoto . AllGroups )
2019-11-04 20:41:35 +01:00
Checked = true ;
2017-06-06 20:27:46 +02:00
else
2019-11-04 20:41:35 +01:00
for ( NumGrpSel = 0 , Checked = false ;
2019-04-04 10:45:15 +02:00
NumGrpSel < Gbl . Crs . Grps . LstGrpsSel . NumGrps ;
2017-06-06 20:27:46 +02:00
NumGrpSel + + )
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] = = - ( GrpTyp - > GrpTypCod ) )
2017-06-06 20:27:46 +02:00
{
2019-11-04 20:41:35 +01:00
Checked = true ;
2017-06-06 20:27:46 +02:00
break ;
}
}
2014-12-01 23:55:08 +01:00
else
2019-11-04 20:41:35 +01:00
Checked = false ;
HTM_TR_Begin ( NULL ) ;
HTM_TD_Begin ( " class= \" LM \" " ) ;
2020-03-12 13:53:37 +01:00
HTM_INPUT_CHECKBOX ( " GrpCods " , HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-07 10:24:00 +01:00
" id= \" Grp%ld \" value= \" %ld \" %s "
" onclick= \" checkParent(this,'AllGroups') \" " ,
- GrpTyp - > GrpTypCod , - GrpTyp - > GrpTypCod ,
2019-11-04 20:41:35 +01:00
ICanSelUnselGroup ? ( Checked ? " checked= \" checked \" " : " " ) :
2020-03-12 13:53:37 +01:00
" disabled= \" disabled \" " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/* Column closed/open */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/* Group name = students with no group */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT LM \" " ) ;
2019-11-02 23:40:52 +01:00
HTM_LABEL_Begin ( " for= \" Grp%ld \" " , - GrpTyp - > GrpTypCod ) ;
2019-11-10 12:36:37 +01:00
HTM_Txt ( Txt_users_with_no_group ) ;
2019-11-02 12:59:31 +01:00
HTM_LABEL_End ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2020-04-14 17:15:17 +02:00
/* Room */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT LM \" " ) ;
HTM_TD_End ( ) ;
2019-01-04 23:15:00 +01:00
2014-12-01 23:55:08 +01:00
/* Number of students who don't belong to any group of this type */
2019-12-26 22:29:04 +01:00
for ( Role = Rol_TCH ;
2017-05-30 21:43:05 +02:00
Role > = Rol_STD ;
Role - - )
2019-10-07 15:15:55 +02:00
{
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2019-11-10 16:47:05 +01:00
HTM_UnsignedLong ( Grp_CountNumUsrsInNoGrpsOfType ( Role , GrpTyp - > GrpTypCod ) ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
}
2014-12-01 23:55:08 +01:00
2019-10-05 13:27:58 +02:00
/* Last empty columns for max. students and vacants */
2019-10-23 19:05:05 +02:00
HTM_TD_Empty ( 2 ) ;
2019-10-05 13:27:58 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************** Write a row with the head for list of groups *****************/
/*****************************************************************************/
static void Grp_WriteGrpHead ( struct GroupType * GrpTyp )
{
extern const char * Txt_Opening_of_groups ;
extern const char * Txt_Group ;
2020-04-14 17:15:17 +02:00
extern const char * Txt_Room ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Max_BR_students ;
2017-05-30 21:43:05 +02:00
extern const char * Txt_ROLES_PLURAL_BRIEF_Abc [ Rol_NUM_ROLES ] ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Vacants ;
2015-10-26 20:02:07 +01:00
static unsigned UniqueId = 0 ;
2019-11-01 22:53:39 +01:00
char * Id ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
/***** Name of group type *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
HTM_TD_Begin ( " colspan= \" 9 \" class= \" GRP_TITLE LM \" " ) ;
2019-11-09 21:08:20 +01:00
HTM_BR ( ) ;
2019-11-10 12:36:37 +01:00
HTM_Txt ( GrpTyp - > GrpTypName ) ;
2014-12-01 23:55:08 +01:00
if ( GrpTyp - > MustBeOpened )
{
2015-10-26 20:02:07 +01:00
UniqueId + + ;
2019-11-01 22:53:39 +01:00
if ( asprintf ( & Id , " open_time_%u " , UniqueId ) < 0 )
Lay_NotEnoughMemoryExit ( ) ;
2019-11-09 21:08:20 +01:00
HTM_BR ( ) ;
2020-01-11 15:22:02 +01:00
HTM_TxtColonNBSP ( Txt_Opening_of_groups ) ;
2019-11-07 10:24:00 +01:00
HTM_SPAN_Begin ( " id= \" %s \" " , Id ) ;
HTM_SPAN_End ( ) ;
2019-11-01 23:35:55 +01:00
Dat_WriteLocalDateHMSFromUTC ( Id , GrpTyp - > OpenTimeUTC ,
2019-11-02 12:10:58 +01:00
Gbl . Prefs . DateFormat , Dat_SEPARATOR_COMMA ,
2019-11-02 11:45:41 +01:00
true , true , true , 0x7 ) ;
2019-11-06 19:45:20 +01:00
free ( Id ) ;
2014-12-01 23:55:08 +01:00
}
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Head row with title of each column *****/
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-10-12 00:07:52 +02:00
2019-10-23 19:05:05 +02:00
HTM_TH_Empty ( 2 ) ;
HTM_TH ( 1 , 1 , " LM " , Txt_Group ) ;
2020-04-14 17:15:17 +02:00
HTM_TH ( 1 , 1 , " LM " , Txt_Room ) ;
2017-05-30 21:43:05 +02:00
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
2019-10-23 19:05:05 +02:00
HTM_TH ( 1 , 1 , " CM " , Txt_ROLES_PLURAL_BRIEF_Abc [ Role ] ) ;
HTM_TH ( 1 , 1 , " CM " , Txt_Max_BR_students ) ;
HTM_TH ( 1 , 1 , " CM " , Txt_Vacants ) ;
2019-10-12 00:07:52 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Write a row with the data of a group *********************/
/*****************************************************************************/
static void Grp_WriteRowGrp ( struct Group * Grp , bool Highlight )
{
extern const char * Txt_Group_X_open ;
extern const char * Txt_Group_X_closed ;
int Vacant ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2019-11-08 01:10:32 +01:00
char StrMaxStudents [ Cns_MAX_DECIMAL_DIGITS_UINT + 1 ] ;
2014-12-01 23:55:08 +01:00
/***** Write icon to show if group is open or closed *****/
if ( Highlight )
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM LIGHT_BLUE \" " ) ;
2019-10-08 23:28:51 +02:00
else
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
2019-01-12 19:46:33 +01:00
Ico_PutIconOff ( Grp - > Open ? " unlock.svg " :
" lock.svg " ,
2019-12-30 21:47:07 +01:00
Str_BuildStringStr ( Grp - > Open ? Txt_Group_X_open :
Txt_Group_X_closed ,
Grp - > GrpName ) ) ;
Str_FreeString ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Group name *****/
if ( Highlight )
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM LIGHT_BLUE \" " ) ;
2019-10-08 23:28:51 +02:00
else
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2019-11-02 23:40:52 +01:00
HTM_LABEL_Begin ( " for= \" Grp%ld \" class= \" DAT \" " , Grp - > GrpCod ) ;
2019-11-10 12:36:37 +01:00
HTM_Txt ( Grp - > GrpName ) ;
2019-11-02 12:59:31 +01:00
HTM_LABEL_End ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2020-04-14 17:15:17 +02:00
/***** Room *****/
2019-01-04 23:15:00 +01:00
if ( Highlight )
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT LM LIGHT_BLUE \" " ) ;
2019-10-08 23:28:51 +02:00
else
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT LM \" " ) ;
2020-04-14 17:15:17 +02:00
HTM_Txt ( Grp - > Room . ShrtName ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-01-04 23:15:00 +01:00
2017-05-30 21:43:05 +02:00
/***** Current number of users in this group *****/
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
{
if ( Highlight )
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM LIGHT_BLUE \" " ) ;
2019-10-08 23:28:51 +02:00
else
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2019-11-11 10:59:24 +01:00
HTM_Int ( Grp - > NumUsrs [ Role ] ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2017-05-30 21:43:05 +02:00
}
2014-12-01 23:55:08 +01:00
/***** Max. number of students in this group *****/
if ( Highlight )
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM LIGHT_BLUE \" " ) ;
2019-10-08 23:28:51 +02:00
else
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2019-11-03 23:59:20 +01:00
Grp_WriteMaxStds ( StrMaxStudents , Grp - > MaxStudents ) ;
2019-11-11 10:59:24 +01:00
HTM_TxtF ( " %s " , StrMaxStudents ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Vacants in this group *****/
if ( Highlight )
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM LIGHT_BLUE \" " ) ;
2019-10-08 23:28:51 +02:00
else
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2017-05-30 21:43:05 +02:00
if ( Grp - > MaxStudents < = Grp_MAX_STUDENTS_IN_A_GROUP )
2014-12-01 23:55:08 +01:00
{
2017-05-30 21:43:05 +02:00
Vacant = ( int ) Grp - > MaxStudents - ( int ) Grp - > NumUsrs [ Rol_STD ] ;
2019-11-10 13:31:47 +01:00
HTM_Unsigned ( Vacant > 0 ? ( unsigned ) Vacant :
0 ) ;
2014-12-01 23:55:08 +01:00
}
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Put a form to create a new group type *****************/
/*****************************************************************************/
static void Grp_PutFormToCreateGroupType ( void )
{
extern const char * Txt_New_type_of_group ;
extern const char * Txt_It_is_optional_to_choose_a_group ;
extern const char * Txt_It_is_mandatory_to_choose_a_group ;
extern const char * Txt_A_student_can_belong_to_several_groups ;
extern const char * Txt_A_student_can_only_belong_to_one_group ;
extern const char * Txt_The_groups_will_automatically_open ;
extern const char * Txt_The_groups_will_not_automatically_open ;
extern const char * Txt_Create_type_of_group ;
2019-10-20 22:00:28 +02:00
/***** Begin form *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin ( Grp_NEW_GROUP_TYPE_SECTION_ID ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActNewGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
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_BoxTableBegin ( NULL , Txt_New_type_of_group ,
NULL , NULL ,
2017-06-12 15:03:29 +02:00
NULL , Box_NOT_CLOSABLE , 2 ) ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteHeadingGroupTypes ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-10-08 23:28:51 +02:00
/***** Column to remove group type, disabled here *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Name of group type *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2019-11-04 12:25:48 +01:00
HTM_INPUT_TEXT ( " GrpTypName " , Grp_MAX_CHARS_GROUP_TYPE_NAME ,
2020-04-27 03:16:55 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName , HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-04 09:45:57 +01:00
" size= \" 12 \" required= \" required \" " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Is it mandatory to register in any groups of this type? *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-05 15:47:35 +01:00
" name= \" MandatoryEnrolment \" style= \" width:150px; \" " ) ;
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_STRING , " N " ,
! Gbl . Crs . Grps . GrpTyp . MandatoryEnrolment , false ,
" %s " , Txt_It_is_optional_to_choose_a_group ) ;
HTM_OPTION ( HTM_Type_STRING , " Y " ,
Gbl . Crs . Grps . GrpTyp . MandatoryEnrolment , false ,
" %s " , Txt_It_is_mandatory_to_choose_a_group ) ;
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Is it possible to register in multiple groups of this type? *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-05 15:47:35 +01:00
" name= \" MultipleEnrolment \" style= \" width:150px; \" " ) ;
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_STRING , " N " ,
! Gbl . Crs . Grps . GrpTyp . MultipleEnrolment , false ,
" %s " , Txt_A_student_can_only_belong_to_one_group ) ;
HTM_OPTION ( HTM_Type_STRING , " Y " ,
Gbl . Crs . Grps . GrpTyp . MultipleEnrolment , false ,
" %s " , Txt_A_student_can_belong_to_several_groups ) ;
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Open time *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
HTM_TABLE_BeginPadding ( 2 ) ;
HTM_TR_Begin ( NULL ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" style= \" width:20px; \" " ) ;
2019-10-29 21:41:54 +01:00
Ico_PutIcon ( " clock.svg " ,
Gbl . Crs . Grps . GrpTyp . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ,
Gbl . Crs . Grps . GrpTyp . MustBeOpened ? " CONTEXT_ICO_16x16 " :
" ICO_HIDDEN CONTEXT_ICO_16x16 " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
2015-10-26 20:02:07 +01:00
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( " open_time " ,
" Open " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . OpenTimeUTC ,
2015-10-26 20:02:07 +01:00
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
2016-12-03 20:08:01 +01:00
Dat_FORM_SECONDS_ON ,
2017-02-26 20:09:21 +01:00
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
false ) ; // Don't submit on change
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
HTM_TABLE_End ( ) ;
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Number of groups of this type *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2019-11-10 13:51:07 +01:00
HTM_Unsigned ( 0 ) ; // It's a new group type ==> 0 groups
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End table, send button and end box *****/
2019-11-25 23:18:08 +01:00
Box_BoxTableWithButtonEnd ( Btn_CREATE_BUTTON , Txt_Create_type_of_group ) ;
2014-12-01 23:55:08 +01:00
2015-04-11 23:46:21 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Put a form to create a new group ********************/
/*****************************************************************************/
2020-04-14 17:15:17 +02:00
static void Grp_PutFormToCreateGroup ( const struct Roo_Rooms * Rooms )
2014-12-01 23:55:08 +01:00
{
extern const char * Txt_New_group ;
2015-07-22 11:18:11 +02:00
extern const char * Txt_Group_closed ;
extern const char * Txt_File_zones_disabled ;
2020-04-14 17:15:17 +02:00
extern const char * Txt_No_assigned_room ;
extern const char * Txt_Another_room ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Create_group ;
unsigned NumGrpTyp ;
2020-04-15 02:17:57 +02:00
unsigned NumRoo ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2019-11-08 01:10:32 +01:00
char StrMaxStudents [ Cns_MAX_DECIMAL_DIGITS_UINT + 1 ] ;
2014-12-01 23:55:08 +01:00
2019-10-20 22:00:28 +02:00
/***** Begin form *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin ( Grp_NEW_GROUP_SECTION_ID ) ;
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchor ( ActNewGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
2019-10-26 02:19:42 +02:00
/***** Begin box and table *****/
2020-03-26 02:54:30 +01:00
Box_BoxTableBegin ( NULL , Txt_New_group ,
NULL , NULL ,
2017-06-12 15:03:29 +02:00
NULL , Box_NOT_CLOSABLE , 2 ) ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteHeadingGroups ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-10-08 23:28:51 +02:00
/***** Empty column to remove *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
HTM_TD_End ( ) ;
2019-01-12 19:46:33 +01:00
/***** Disabled icon to open group *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
2019-01-12 19:46:33 +01:00
Ico_PutIconOff ( " lock.svg " , Txt_Group_closed ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-01-12 19:46:33 +01:00
/***** Disabled icon for archive zone *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" BM \" " ) ;
2019-01-12 19:46:33 +01:00
Ico_PutIconOff ( " folder-red.svg " , Txt_File_zones_disabled ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Group type *****/
2019-01-04 22:46:46 +01:00
/* Start selector */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-05 15:47:35 +01:00
" name= \" GrpTypCod \" style= \" width:100px; \" " ) ;
2019-01-04 22:46:46 +01:00
/* Options for group types */
2014-12-01 23:55:08 +01:00
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
2019-11-07 01:13:21 +01:00
HTM_OPTION ( HTM_Type_LONG , & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod = =
Gbl . Crs . Grps . GrpTyp . GrpTypCod , false ,
" %s " , Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ) ;
2019-01-04 22:46:46 +01:00
/* End selector */
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Group name *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2020-04-27 03:16:55 +02:00
HTM_INPUT_TEXT ( " GrpName " , Grp_MAX_CHARS_GROUP_NAME , Gbl . Crs . Grps . GrpName ,
HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-04 09:45:57 +01:00
" size= \" 20 \" required= \" required \" " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2020-04-14 17:15:17 +02:00
/***** Room *****/
2019-01-04 22:46:46 +01:00
/* Start selector */
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2020-04-27 03:16:55 +02:00
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2020-04-14 17:15:17 +02:00
" name= \" RooCod \" style= \" width:100px; \" " ) ;
2019-01-04 22:46:46 +01:00
2020-04-14 17:15:17 +02:00
/* Option for no assigned room */
HTM_OPTION ( HTM_Type_STRING , " -1 " , Gbl . Crs . Grps . RooCod < 0 , false ,
" %s " , Txt_No_assigned_room ) ;
2019-01-04 22:46:46 +01:00
2020-04-14 17:15:17 +02:00
/* Option for another room */
HTM_OPTION ( HTM_Type_STRING , " 0 " , Gbl . Crs . Grps . RooCod = = 0 , false ,
" %s " , Txt_Another_room ) ;
2019-01-04 22:46:46 +01:00
2020-04-14 17:15:17 +02:00
/* Options for rooms */
2020-04-15 02:17:57 +02:00
for ( NumRoo = 0 ;
NumRoo < Rooms - > Num ;
NumRoo + + )
HTM_OPTION ( HTM_Type_LONG , & Rooms - > Lst [ NumRoo ] . RooCod ,
Rooms - > Lst [ NumRoo ] . RooCod = = Gbl . Crs . Grps . RooCod , false ,
" %s " , Rooms - > Lst [ NumRoo ] . ShrtName ) ;
2019-01-04 22:46:46 +01:00
/* End selector */
2019-11-05 08:46:38 +01:00
HTM_SELECT_End ( ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-01-04 12:53:40 +01:00
2017-05-30 21:43:05 +02:00
/***** Current number of users in this group *****/
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
2019-10-07 15:15:55 +02:00
{
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" DAT CM \" " ) ;
2019-11-10 13:51:07 +01:00
HTM_Unsigned ( 0 ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
}
2017-05-30 21:43:05 +02:00
2014-12-01 23:55:08 +01:00
/***** Maximum number of students *****/
2019-10-23 19:05:05 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2019-11-03 23:59:20 +01:00
Grp_WriteMaxStds ( StrMaxStudents , Gbl . Crs . Grps . MaxStudents ) ;
2020-04-27 03:16:55 +02:00
HTM_INPUT_TEXT ( " MaxStudents " , Cns_MAX_DECIMAL_DIGITS_UINT , StrMaxStudents ,
HTM_DONT_SUBMIT_ON_CHANGE ,
2019-11-04 09:45:57 +01:00
" size= \" 3 \" " ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End table, send button and end box *****/
2019-11-25 23:18:08 +01:00
Box_BoxTableWithButtonEnd ( Btn_CREATE_BUTTON , Txt_Create_group ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ( ) ;
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Create a list with current group types in this course ***********/
/*****************************************************************************/
void Grp_GetListGrpTypesInThisCrs ( Grp_WhichGroupTypes_t WhichGroupTypes )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2018-10-31 10:19:01 +01:00
unsigned long NumGrpTyp ;
2014-12-01 23:55:08 +01:00
2019-04-04 10:45:15 +02:00
if ( + + Gbl . Crs . Grps . GrpTypes . NestedCalls > 1 ) // If list is created yet, there's nothing to do
2014-12-01 23:55:08 +01:00
return ;
/***** Open groups of this course that must be opened
if open time is in the past * * * * */
Grp_OpenGroupsAutomatically ( ) ;
/***** Get group types with groups + groups types without groups from database *****/
// The tables in the second part of the UNION requires ALIAS in order to LOCK TABLES when registering in groups
switch ( WhichGroupTypes )
{
case Grp_ONLY_GROUP_TYPES_WITH_GROUPS :
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . Num =
2018-10-31 10:19:01 +01:00
( unsigned ) DB_QuerySELECT ( & mysql_res , " can not get types of group "
" of a course " ,
" SELECT crs_grp_types.GrpTypCod,crs_grp_types.GrpTypName, "
" crs_grp_types.Mandatory,crs_grp_types.Multiple, "
" crs_grp_types.MustBeOpened, "
" UNIX_TIMESTAMP(crs_grp_types.OpenTime), "
" COUNT(crs_grp.GrpCod) "
" FROM crs_grp_types,crs_grp "
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" GROUP BY crs_grp_types.GrpTypCod "
" ORDER BY crs_grp_types.GrpTypName " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod ) ;
2014-12-01 23:55:08 +01:00
break ;
case Grp_ALL_GROUP_TYPES :
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . Num =
2018-10-31 10:19:01 +01:00
( unsigned ) DB_QuerySELECT ( & mysql_res , " can not get types of group "
" of a course " ,
" (SELECT crs_grp_types.GrpTypCod,crs_grp_types.GrpTypName AS GrpTypName, "
" crs_grp_types.Mandatory,crs_grp_types.Multiple, "
" crs_grp_types.MustBeOpened, "
" UNIX_TIMESTAMP(crs_grp_types.OpenTime), "
" COUNT(crs_grp.GrpCod) "
" FROM crs_grp_types,crs_grp "
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" GROUP BY crs_grp_types.GrpTypCod) "
" UNION "
" (SELECT GrpTypCod,GrpTypName, "
" Mandatory,Multiple, "
" MustBeOpened, "
" UNIX_TIMESTAMP(OpenTime), "
" 0 "
" FROM crs_grp_types WHERE CrsCod=%ld "
" AND GrpTypCod NOT IN (SELECT GrpTypCod FROM crs_grp)) "
" ORDER BY GrpTypName " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod ,
Gbl . Hierarchy . Crs . CrsCod ) ;
2014-12-01 23:55:08 +01:00
break ;
}
/***** Get group types *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . NumGrpsTotal = 0 ;
2014-12-01 23:55:08 +01:00
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTypes . Num )
2014-12-01 23:55:08 +01:00
{
/***** Create a list of group types *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes = ( struct GroupType * ) calloc ( Gbl . Crs . Grps . GrpTypes . Num , sizeof ( struct GroupType ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get group types *****/
2018-10-31 10:19:01 +01:00
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2018-10-31 10:19:01 +01:00
NumGrpTyp + + )
2014-12-01 23:55:08 +01:00
{
/* Get next group type */
row = mysql_fetch_row ( mysql_res ) ;
/* Get group type code (row[0]) */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong type of group. " ) ;
/* Get group type name (row[1]) */
2019-04-04 10:45:15 +02:00
Str_Copy ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName , row [ 1 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Is it mandatory to register in any groups of this type? (row[2]) */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MandatoryEnrolment = ( row [ 2 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/* Is it possible to register in multiple groups of this type? (row[3]) */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/* Groups of this type must be opened? (row[4]) */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened = ( row [ 4 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
2015-10-26 20:02:07 +01:00
/* Get open time (row[5] holds the open time UTC) */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . OpenTimeUTC = Dat_GetUNIXTimeFromStr ( row [ 5 ] ) ;
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened & = Grp_CheckIfOpenTimeInTheFuture ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
/* Number of groups of this type (row[6]) */
2019-04-04 10:45:15 +02:00
if ( sscanf ( row [ 6 ] , " %u " , & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ! = 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong number of groups of a type. " ) ;
/* Add number of groups to total number of groups */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . NumGrpsTotal + = Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ;
2014-12-01 23:55:08 +01:00
/* Initialize pointer to the list of groups of this type */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . LstGrps = NULL ;
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/***************** Open automatically groups in this course ******************/
/*****************************************************************************/
void Grp_OpenGroupsAutomatically ( void )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrpTypes ;
unsigned NumGrpTyp ;
long GrpTypCod ;
/***** Find group types to be opened *****/
2018-10-31 10:19:01 +01:00
NumGrpTypes =
( unsigned ) DB_QuerySELECT ( & mysql_res , " can not get the types of group "
" to be opened " ,
" SELECT GrpTypCod FROM crs_grp_types "
" WHERE CrsCod=%ld AND MustBeOpened='Y' "
" AND OpenTime<=NOW() " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod ) ;
2018-10-31 10:19:01 +01:00
2014-12-01 23:55:08 +01:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < NumGrpTypes ;
NumGrpTyp + + )
{
/* Get next group TYPE */
row = mysql_fetch_row ( mysql_res ) ;
if ( ( GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) > 0 )
{
/***** Open all the closed groups in this course the must be opened
and with open time in the past * * * */
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not open groups " ,
" UPDATE crs_grp SET Open='Y' "
" WHERE GrpTypCod=%ld AND Open='N' " ,
GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** To not try to open groups again, set MustBeOpened to false *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update the opening of a type of group " ,
" UPDATE crs_grp_types SET MustBeOpened='N' "
" WHERE GrpTypCod=%ld " ,
GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/********* Create a list with group types and groups in this course **********/
/*****************************************************************************/
void Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_WhichGroupTypes_t WhichGroupTypes )
{
unsigned NumGrpTyp ;
unsigned NumGrp ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
struct GroupType * GrpTyp ;
struct Group * Grp ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
/***** First we get the list of group types *****/
Grp_GetListGrpTypesInThisCrs ( WhichGroupTypes ) ;
/***** Then we get the list of groups for each group type *****/
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
GrpTyp = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
2014-12-01 23:55:08 +01:00
if ( GrpTyp - > NumGrps ) // If there are groups of this type...
{
/***** Query database *****/
if ( ( NumRows = Grp_GetGrpsOfType ( GrpTyp - > GrpTypCod , & mysql_res ) ) > 0 ) // Groups found...
{
// NumRows should be equal to GrpTyp->NumGrps
GrpTyp - > NumGrps = ( unsigned ) NumRows ;
/***** Create list with groups of this type *****/
if ( ( GrpTyp - > LstGrps = ( struct Group * ) calloc ( GrpTyp - > NumGrps , sizeof ( struct Group ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups of this type *****/
for ( NumGrp = 0 ;
NumGrp < GrpTyp - > NumGrps ;
NumGrp + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrp ] ) ;
/* Get next group */
row = mysql_fetch_row ( mysql_res ) ;
/* Get group code (row[0]) */
if ( ( Grp - > GrpCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
/* Get group name (row[1]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( Grp - > GrpName , row [ 1 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
2020-04-14 17:15:17 +02:00
/* Get room code (row[2]) */
Grp - > Room . RooCod = Str_ConvertStrCodToLongCod ( row [ 2 ] ) ;
2017-05-30 21:43:05 +02:00
2020-04-14 17:15:17 +02:00
/* Get room short name (row[3]) */
2019-01-07 17:29:10 +01:00
if ( row [ 3 ] ) // May be NULL because of LEFT JOIN
2020-04-14 17:15:17 +02:00
Str_Copy ( Grp - > Room . ShrtName , row [ 3 ] ,
Roo_MAX_BYTES_SHRT_NAME ) ;
2019-01-07 17:29:10 +01:00
else // NULL
2020-04-14 17:15:17 +02:00
Grp - > Room . ShrtName [ 0 ] = ' \0 ' ;
2019-01-05 11:29:54 +01:00
2017-05-30 21:43:05 +02:00
/* Get number of current users in group */
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
Grp - > NumUsrs [ Role ] = Grp_CountNumUsrsInGrp ( Role , Grp - > GrpCod ) ;
2014-12-01 23:55:08 +01:00
2019-01-05 11:29:54 +01:00
/* Get maximum number of students in group (row[4]) */
Grp - > MaxStudents = Grp_ConvertToNumMaxStdsGrp ( row [ 4 ] ) ;
2014-12-01 23:55:08 +01:00
2019-01-05 11:29:54 +01:00
/* Get whether group is open ('Y') or closed ('N') (row[5]) */
Grp - > Open = ( row [ 5 ] [ 0 ] = = ' Y ' ) ;
2019-01-04 11:59:31 +01:00
2019-01-05 11:29:54 +01:00
/* Get whether group have file zones ('Y') or not ('N') (row[6]) */
Grp - > FileZones = ( row [ 6 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
}
}
2019-01-05 11:29:54 +01:00
else // Error: groups should be found, but really they haven't be found.
// This never should happen.
2014-12-01 23:55:08 +01:00
GrpTyp - > NumGrps = 0 ;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
}
}
/*****************************************************************************/
/********* Free list of groups types and list of groups of each type *********/
/*****************************************************************************/
void Grp_FreeListGrpTypesAndGrps ( void )
{
unsigned NumGrpTyp ;
struct GroupType * GrpTyp ;
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTypes . NestedCalls > 0 )
if ( - - Gbl . Crs . Grps . GrpTypes . NestedCalls = = 0 )
if ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes )
2014-12-01 23:55:08 +01:00
{
/***** Free memory used for each list of groups (one list for each group type) *****/
for ( NumGrpTyp = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
2019-04-04 10:45:15 +02:00
GrpTyp = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
2014-12-01 23:55:08 +01:00
if ( GrpTyp - > LstGrps )
{
2019-11-06 19:45:20 +01:00
free ( GrpTyp - > LstGrps ) ;
2014-12-01 23:55:08 +01:00
GrpTyp - > LstGrps = NULL ;
GrpTyp - > NumGrps = 0 ;
}
}
/***** Free memory used by the list of group types *****/
2019-11-06 19:45:20 +01:00
free ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes ) ;
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes = NULL ;
Gbl . Crs . Grps . GrpTypes . Num = 0 ;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/*********** Query the number of groups that hay in this course **************/
/*****************************************************************************/
unsigned Grp_CountNumGrpsInCurrentCrs ( void )
{
/***** Get number of group in current course from database *****/
2018-11-03 20:52:00 +01:00
return
( unsigned ) DB_QueryCOUNT ( " can not get number of groups in this course " ,
" SELECT COUNT(*) FROM crs_grp_types,crs_grp "
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Count number of groups in a group type *******************/
/*****************************************************************************/
static unsigned Grp_CountNumGrpsInThisCrsOfType ( long GrpTypCod )
{
/***** Get number of groups of a type from database *****/
2018-11-03 20:52:00 +01:00
return
( unsigned ) DB_QueryCOUNT ( " can not get number of groups of a type " ,
" SELECT COUNT(*) FROM crs_grp "
" WHERE GrpTypCod=%ld " ,
GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-01-04 11:59:31 +01:00
/******************** Get groups of a type in this course ********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
unsigned long Grp_GetGrpsOfType ( long GrpTypCod , MYSQL_RES * * mysql_res )
{
/***** Get groups of a type from database *****/
2020-04-14 17:15:17 +02:00
// Don't use INNER JOIN because there are groups without assigned room
2018-10-31 10:19:01 +01:00
return DB_QuerySELECT ( mysql_res , " can not get groups of a type " ,
2019-01-05 11:29:54 +01:00
" SELECT crs_grp.GrpCod, "
" crs_grp.GrpName, "
2020-04-14 17:15:17 +02:00
" crs_grp.RooCod, "
" rooms.ShortName, "
2019-01-05 11:29:54 +01:00
" crs_grp.MaxStudents, "
" crs_grp.Open, "
" crs_grp.FileZones "
2019-01-07 17:00:04 +01:00
" FROM crs_grp "
2020-04-14 17:15:17 +02:00
" LEFT JOIN rooms "
" ON crs_grp.RooCod=rooms.RooCod "
2019-01-05 11:29:54 +01:00
" WHERE crs_grp.GrpTypCod=%ld "
" ORDER BY crs_grp.GrpName " ,
2018-10-31 10:19:01 +01:00
GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Get data of a group type from its code ******************/
/*****************************************************************************/
// GrpTyp->GrpTypCod must have the code of the type of group
static void Grp_GetDataOfGroupTypeByCod ( struct GroupType * GrpTyp )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
/***** Get data of a type of group from database *****/
2019-11-11 11:20:31 +01:00
if ( DB_QuerySELECT ( & mysql_res , " can not get type of group " ,
" SELECT GrpTypName, " // row[0]
" Mandatory, " // row[1]
" Multiple, " // row[2]
" MustBeOpened, " // row[3]
" UNIX_TIMESTAMP(OpenTime) " // row[4]
2018-10-31 10:19:01 +01:00
" FROM crs_grp_types "
" WHERE CrsCod=%ld AND GrpTypCod=%ld " ,
2019-11-11 11:20:31 +01:00
Gbl . Hierarchy . Crs . CrsCod , GrpTyp - > GrpTypCod ) ! = 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Error when getting type of group. " ) ;
/***** Get some data of group type *****/
row = mysql_fetch_row ( mysql_res ) ;
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpTyp - > GrpTypName , row [ 0 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2017-03-30 11:20:06 +02:00
GrpTyp - > MandatoryEnrolment = ( row [ 1 ] [ 0 ] = = ' Y ' ) ;
GrpTyp - > MultipleEnrolment = ( row [ 2 ] [ 0 ] = = ' Y ' ) ;
GrpTyp - > MustBeOpened = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2015-10-26 20:02:07 +01:00
GrpTyp - > OpenTimeUTC = Dat_GetUNIXTimeFromStr ( row [ 4 ] ) ;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/************* Check if a group type has multiple enrolment *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
static bool Grp_GetMultipleEnrolmentOfAGroupType ( long GrpTypCod )
2014-12-01 23:55:08 +01:00
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2017-03-30 11:20:06 +02:00
bool MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
/***** Get data of a type of group from database *****/
2018-10-31 10:19:01 +01:00
if ( DB_QuerySELECT ( & mysql_res , " can not get if type of group "
" has multiple enrolment " ,
" SELECT Multiple FROM crs_grp_types "
" WHERE GrpTypCod=%ld " ,
GrpTypCod ) ! = 1 )
2019-11-11 11:20:31 +01:00
Lay_ShowErrorAndExit ( " Error when getting type of enrolment. " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/***** Get multiple enrolment *****/
2014-12-01 23:55:08 +01:00
row = mysql_fetch_row ( mysql_res ) ;
2017-03-30 11:20:06 +02:00
MultipleEnrolment = ( row [ 0 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
2017-03-30 11:20:06 +02:00
return MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Get data of a group from its code ********************/
/*****************************************************************************/
void Grp_GetDataOfGroupByCod ( struct GroupData * GrpDat )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
2016-12-28 02:40:15 +01:00
/***** Reset values *****/
2019-01-07 17:00:04 +01:00
GrpDat - > GrpTypCod = - 1L ;
GrpDat - > CrsCod = - 1L ;
GrpDat - > GrpTypName [ 0 ] = ' \0 ' ;
GrpDat - > GrpName [ 0 ] = ' \0 ' ;
2020-04-14 17:15:17 +02:00
GrpDat - > Room . RooCod = - 1L ;
GrpDat - > Room . ShrtName [ 0 ] = ' \0 ' ;
2019-01-07 17:00:04 +01:00
GrpDat - > MaxStudents = 0 ;
GrpDat - > Vacant = 0 ;
GrpDat - > Open = false ;
GrpDat - > FileZones = false ;
GrpDat - > MultipleEnrolment = false ;
2016-12-28 02:40:15 +01:00
if ( GrpDat - > GrpCod > 0 )
{
/***** Get data of a group from database *****/
2018-10-31 10:19:01 +01:00
NumRows = DB_QuerySELECT ( & mysql_res , " can not get data of a group " ,
2019-01-07 17:29:10 +01:00
" SELECT crs_grp.GrpTypCod, " // row[0]
" crs_grp_types.CrsCod, " // row[1]
" crs_grp_types.GrpTypName, " // row[2]
" crs_grp_types.Multiple, " // row[3]
" crs_grp.GrpName, " // row[4]
2020-04-14 17:15:17 +02:00
" crs_grp.RooCod, " // row[5]
" rooms.ShortName, " // row[6]
2019-01-07 17:29:10 +01:00
" crs_grp.MaxStudents, " // row[7]
" crs_grp.Open, " // row[8]
" crs_grp.FileZones " // row[9]
2019-01-07 17:00:04 +01:00
" FROM (crs_grp,crs_grp_types) "
2020-04-14 17:15:17 +02:00
" LEFT JOIN rooms "
" ON crs_grp.RooCod=rooms.RooCod "
2018-10-31 10:19:01 +01:00
" WHERE crs_grp.GrpCod=%ld "
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod " ,
GrpDat - > GrpCod ) ;
2016-12-28 02:40:15 +01:00
if ( NumRows = = 1 )
{
/***** Get data of group *****/
row = mysql_fetch_row ( mysql_res ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the code of the group type (row[0]) */
if ( ( GrpDat - > GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < = 0 )
Lay_ShowErrorAndExit ( " Wrong code of type of group. " ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the code of the course (row[1]) */
if ( ( GrpDat - > CrsCod = Str_ConvertStrCodToLongCod ( row [ 1 ] ) ) < = 0 )
Lay_ShowErrorAndExit ( " Wrong code of course. " ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the name of the group type (row[2]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpDat - > GrpTypName , row [ 2 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get whether a student may be in one or multiple groups (row[3]) */
2017-03-30 11:20:06 +02:00
GrpDat - > MultipleEnrolment = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the name of the group (row[4]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpDat - > GrpName , row [ 4 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2015-01-24 19:30:44 +01:00
2019-01-04 11:59:31 +01:00
/* Get the code of the course (row[5]) */
2020-04-14 17:15:17 +02:00
GrpDat - > Room . RooCod = Str_ConvertStrCodToLongCod ( row [ 5 ] ) ;
2019-01-04 11:59:31 +01:00
2020-04-14 17:15:17 +02:00
/* Get the name of the room (row[6]) */
2019-01-07 17:29:10 +01:00
if ( row [ 6 ] ) // May be NULL because of LEFT JOIN
2020-04-14 17:15:17 +02:00
Str_Copy ( GrpDat - > Room . ShrtName , row [ 6 ] ,
Roo_MAX_BYTES_SHRT_NAME ) ;
2019-01-07 17:29:10 +01:00
else // NULL
2020-04-14 17:15:17 +02:00
GrpDat - > Room . ShrtName [ 0 ] = ' \0 ' ;
2019-01-07 17:00:04 +01:00
/* Get maximum number of students (row[7]) */
GrpDat - > MaxStudents = Grp_ConvertToNumMaxStdsGrp ( row [ 7 ] ) ;
2015-01-24 19:30:44 +01:00
2019-01-07 17:00:04 +01:00
/* Get whether group is open or closed (row[8]) */
GrpDat - > Open = ( row [ 8 ] [ 0 ] = = ' Y ' ) ;
2015-01-24 19:30:44 +01:00
2019-01-07 17:00:04 +01:00
/* Get whether group has file zones (row[9]) */
GrpDat - > FileZones = ( row [ 9 ] [ 0 ] = = ' Y ' ) ;
2016-12-28 02:40:15 +01:00
}
2014-12-01 23:55:08 +01:00
2016-12-28 02:40:15 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Get the type of group of a group *********************/
/*****************************************************************************/
static long Grp_GetTypeOfGroupOfAGroup ( long GrpCod )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
long GrpTypCod ;
/***** Get data of a group from database *****/
2018-10-31 10:19:01 +01:00
if ( DB_QuerySELECT ( & mysql_res , " can not get the type of a group " ,
" SELECT GrpTypCod "
" FROM crs_grp "
" WHERE GrpCod=%ld " ,
GrpCod ) ! = 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Error when getting group. " ) ;
/***** Get data of group *****/
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of the group type (row[0]) */
if ( ( GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of type of group. " ) ;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
return GrpTypCod ;
}
/*****************************************************************************/
/******************** Check if a group exists in database ********************/
/*****************************************************************************/
bool Grp_CheckIfGroupExists ( long GrpCod )
{
/***** Get if a group exists from database *****/
2018-11-03 20:52:00 +01:00
return ( DB_QueryCOUNT ( " can not check if a group exists " ,
2018-11-04 20:51:38 +01:00
" SELECT COUNT(*) FROM crs_grp "
" WHERE GrpCod=%ld " ,
2018-11-03 20:52:00 +01:00
GrpCod ) ! = 0 ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Check if a group belongs to a course ********************/
/*****************************************************************************/
bool Grp_CheckIfGroupBelongsToCourse ( long GrpCod , long CrsCod )
{
/***** Get if a group exists from database *****/
2018-11-03 20:52:00 +01:00
return ( DB_QueryCOUNT ( " can not check if a group belongs to a course " ,
" SELECT COUNT(*) FROM crs_grp,crs_grp_types "
" WHERE crs_grp.GrpCod=%ld "
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
" AND crs_grp_types.CrsCod=%ld " ,
GrpCod , CrsCod ) ! = 0 ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
/********************* Count number of users in a group **********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
unsigned Grp_CountNumUsrsInGrp ( Rol_Role_t Role , long GrpCod )
2014-12-01 23:55:08 +01:00
{
/***** Get number of students in a group from database *****/
2018-11-03 20:52:00 +01:00
return
( unsigned ) DB_QueryCOUNT ( " can not get number of users in a group " ,
" SELECT COUNT(*) "
" FROM crs_grp_usr,crs_grp,crs_grp_types,crs_usr "
" WHERE crs_grp_usr.GrpCod=%ld "
" AND crs_grp_usr.GrpCod=crs_grp.GrpCod "
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
" AND crs_usr.Role=%u " ,
GrpCod , ( unsigned ) Role ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
/*** Count # of users of current course not belonging to groups of a type ****/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-31 10:19:01 +01:00
static unsigned long Grp_CountNumUsrsInNoGrpsOfType ( Rol_Role_t Role , long GrpTypCod )
2014-12-01 23:55:08 +01:00
{
2017-05-30 21:43:05 +02:00
/***** Get number of users not belonging to groups of a type ******/
2018-10-31 10:19:01 +01:00
return DB_QueryCOUNT ( " can not get the number of users "
" not belonging to groups of a type " ,
" SELECT COUNT(UsrCod) FROM crs_usr "
" WHERE CrsCod=%ld AND Role=%u "
" AND UsrCod NOT IN "
" (SELECT DISTINCT crs_grp_usr.UsrCod "
" FROM crs_grp,crs_grp_usr "
" WHERE crs_grp.GrpTypCod=%ld "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod) " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod ,
2018-10-31 10:19:01 +01:00
( unsigned ) Role , GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-02-18 14:41:46 +01:00
/********* Check if I belong to any groups of a given type I belong **********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-02-18 14:41:46 +01:00
static bool Grp_CheckIfIBelongToGrpsOfType ( long GrpTypCod )
2014-12-01 23:55:08 +01:00
{
2019-02-18 14:41:46 +01:00
unsigned long NumGrps ;
2014-12-01 23:55:08 +01:00
2017-06-20 01:58:16 +02:00
/***** Get a group which I belong to from database *****/
2019-02-18 14:41:46 +01:00
NumGrps = DB_QueryCOUNT ( " can not check if you belong to a group type " ,
" SELECT COUNT(crs_grp.GrpCod) "
" FROM crs_grp,crs_grp_usr "
" WHERE crs_grp.GrpTypCod=%ld "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=%ld " , // I belong
GrpTypCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
2014-12-01 23:55:08 +01:00
2019-02-18 14:41:46 +01:00
return ( NumGrps ! = 0 ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
/************************ Check if I belong to a group ***********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
// Return true if I belong to group with code GrpCod
void Grp_FlushCacheIBelongToGrp ( void )
{
Gbl . Cache . IBelongToGrp . GrpCod = - 1L ;
Gbl . Cache . IBelongToGrp . IBelong = false ;
}
2014-12-01 23:55:08 +01:00
bool Grp_GetIfIBelongToGrp ( long GrpCod )
{
2017-06-20 14:43:26 +02:00
/***** 1. Fast check: Trivial case *****/
if ( GrpCod < = 0 )
return false ;
/***** 2. Fast check: Is already calculated if I belong to group? *****/
if ( GrpCod = = Gbl . Cache . IBelongToGrp . GrpCod )
return Gbl . Cache . IBelongToGrp . IBelong ;
2014-12-01 23:55:08 +01:00
2017-06-20 14:43:26 +02:00
/***** 3. Slow check: Get if I belong to a group from database *****/
Gbl . Cache . IBelongToGrp . GrpCod = GrpCod ;
2018-11-03 20:52:00 +01:00
Gbl . Cache . IBelongToGrp . IBelong =
( DB_QueryCOUNT ( " can not check if you belong to a group " ,
" SELECT COUNT(*) FROM crs_grp_usr "
" WHERE GrpCod=%ld AND UsrCod=%ld " ,
GrpCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ! = 0 ) ;
2017-06-20 14:43:26 +02:00
return Gbl . Cache . IBelongToGrp . IBelong ;
}
/*****************************************************************************/
/*************** Check if a user belongs to any of my courses ****************/
/*****************************************************************************/
void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( void )
{
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod = - 1L ;
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = false ;
}
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs ( const struct UsrData * UsrDat )
{
2018-10-10 14:03:06 +02:00
bool ItsMe ;
2017-06-20 14:43:26 +02:00
/***** 1. Fast check: Am I logged? *****/
if ( ! Gbl . Usrs . Me . Logged )
return false ;
/***** 2. Fast check: Is it a valid user code? *****/
if ( UsrDat - > UsrCod < = 0 )
return false ;
/***** 3. Fast check: Is it a course selected? *****/
2019-04-04 10:45:15 +02:00
if ( Gbl . Hierarchy . Crs . CrsCod < = 0 )
2017-06-20 14:43:26 +02:00
return false ;
/***** 4. Fast check: Do I belong to the current course? *****/
if ( ! Gbl . Usrs . Me . IBelongToCurrentCrs )
return false ;
/***** 5. Fast check: It's me? *****/
2018-10-10 23:56:42 +02:00
ItsMe = Usr_ItsMe ( UsrDat - > UsrCod ) ;
2018-10-10 14:03:06 +02:00
if ( ItsMe )
2017-06-20 14:43:26 +02:00
return true ;
/***** 6. Fast check: Is already calculated if user shares
any group in the current course with me ? * * * * */
if ( UsrDat - > UsrCod = = Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod )
return Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares ;
/***** 7. Fast / slow check: Does he/she belong to the current course? *****/
if ( ! Usr_CheckIfUsrBelongsToCurrentCrs ( UsrDat ) )
{
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod = UsrDat - > UsrCod ;
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = false ;
return false ;
}
2017-06-23 15:12:49 +02:00
/***** 8. Fast check: Course has groups? *****/
2019-04-04 10:45:15 +02:00
if ( ! Gbl . Crs . Grps . NumGrps )
2017-06-23 15:12:49 +02:00
{
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod = UsrDat - > UsrCod ;
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = true ;
return true ;
}
// Course has groups
/***** 9. Slow check: Get if user shares any group in this course with me from database *****/
2017-06-20 14:43:26 +02:00
/* Check if user shares any group with me */
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod = UsrDat - > UsrCod ;
2018-11-03 20:52:00 +01:00
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares =
( DB_QueryCOUNT ( " can not check if a user shares any group "
" in the current course with you " ,
" SELECT COUNT(*) FROM crs_grp_usr "
" WHERE UsrCod=%ld "
" AND GrpCod IN "
" (SELECT crs_grp_usr.GrpCod "
" FROM crs_grp_usr,crs_grp,crs_grp_types "
" WHERE crs_grp_usr.UsrCod=%ld "
" AND crs_grp_usr.GrpCod=crs_grp.GrpCod "
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
" AND crs_grp_types.CrsCod=%ld) " ,
UsrDat - > UsrCod ,
Gbl . Usrs . Me . UsrDat . UsrCod ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod ) ! = 0 ) ;
2017-06-20 14:43:26 +02:00
return Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-02-18 17:30:35 +01:00
/**** Get if any group in group-type/this-course is open and has vacants *****/
2019-02-18 02:42:15 +01:00
/*****************************************************************************/
2019-02-18 14:41:46 +01:00
// If GrpTypCod > 0 ==> restrict to the given group type, mandatory or not
// If GrpTypCod <= 0 ==> all mandatory group types in the current course
2019-02-18 02:42:15 +01:00
2019-02-18 17:30:35 +01:00
bool Grp_GetIfAvailableGrpTyp ( long GrpTypCod )
2019-02-18 02:42:15 +01:00
{
2019-02-18 09:40:46 +01:00
unsigned NumGrpTypes ;
2019-02-18 14:41:46 +01:00
char * SubQueryGrpTypes ;
if ( GrpTypCod > 0 ) // restrict to the given group type, mandatory or not
{
if ( asprintf ( & SubQueryGrpTypes , " crs_grp_types.GrpTypCod=%ld " ,
GrpTypCod ) < 0 )
Lay_NotEnoughMemoryExit ( ) ;
}
else // all mandatory group types in the current course
{
if ( asprintf ( & SubQueryGrpTypes , " crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.Mandatory='Y' " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod ) < 0 )
2019-02-18 14:41:46 +01:00
Lay_NotEnoughMemoryExit ( ) ;
}
2019-02-18 02:42:15 +01:00
2019-02-18 09:40:46 +01:00
/***** Get the number of types of group in this course
with one or more open groups with vacants , from database * * * * */
NumGrpTypes =
( unsigned ) DB_QueryCOUNT ( " can not check if there has available mandatory group types " ,
" SELECT COUNT(GrpTypCod) FROM "
" ( "
2014-12-01 23:55:08 +01:00
2019-02-18 14:41:46 +01:00
// Available mandatory groups with students
" SELECT GrpTypCod FROM "
" ( "
2019-02-18 09:40:46 +01:00
" SELECT crs_grp_types.GrpTypCod AS GrpTypCod, "
2018-11-03 20:52:00 +01:00
" COUNT(*) AS NumStudents, "
" crs_grp.MaxStudents as MaxStudents "
" FROM crs_grp_types,crs_grp,crs_grp_usr,crs_usr "
2019-02-18 14:41:46 +01:00
" WHERE %s " // Which group types?
2018-11-03 20:52:00 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
2019-02-18 09:40:46 +01:00
" AND crs_grp.Open='Y' " // Open
2019-02-18 14:41:46 +01:00
" AND crs_grp.MaxStudents>0 " // Admits students
2018-11-03 20:52:00 +01:00
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
2019-02-18 14:41:46 +01:00
" AND crs_usr.Role=%u " // Student
2018-11-03 20:52:00 +01:00
" GROUP BY crs_grp.GrpCod "
2019-02-18 09:40:46 +01:00
" HAVING NumStudents<MaxStudents " // Not full
2019-02-18 14:41:46 +01:00
" ) AS available_grp_types_with_stds "
2019-02-18 02:42:15 +01:00
2019-02-18 09:40:46 +01:00
" UNION "
2019-02-18 14:41:46 +01:00
// Available mandatory groups...
" SELECT crs_grp_types.GrpTypCod AS GrpTypCod "
2019-02-18 09:40:46 +01:00
" FROM crs_grp_types,crs_grp "
2019-02-18 14:41:46 +01:00
" WHERE %s " // Which group types?
2018-11-03 20:52:00 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
2019-02-18 09:40:46 +01:00
" AND crs_grp.Open='Y' " // Open
2019-02-18 14:41:46 +01:00
" AND crs_grp.MaxStudents>0 " // Admits students
// ...without students
" AND crs_grp.GrpCod NOT IN "
2019-02-18 09:40:46 +01:00
" (SELECT crs_grp_usr.GrpCod "
" FROM crs_usr,crs_grp_usr "
" WHERE crs_usr.CrsCod=%ld "
2019-02-18 14:41:46 +01:00
" AND crs_usr.Role=%u " // Student
2019-02-18 09:40:46 +01:00
" AND crs_usr.UsrCod=crs_grp_usr.UsrCod) "
2019-02-18 02:42:15 +01:00
2019-02-18 14:41:46 +01:00
" ) AS available_grp_types "
2019-02-18 09:40:46 +01:00
2019-02-18 14:41:46 +01:00
// ...to which I don't belong
" WHERE GrpTypCod NOT IN "
" (SELECT crs_grp_types.GrpTypCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
" WHERE %s " // Which group types?
2018-11-03 20:52:00 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
2019-02-18 17:30:35 +01:00
" AND crs_grp.Open='Y' " // Open
" AND crs_grp.MaxStudents>0 " // Admits students
2018-11-03 20:52:00 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2019-02-18 14:41:46 +01:00
" AND crs_grp_usr.UsrCod=%ld) " , // I belong
2018-11-03 20:52:00 +01:00
2019-02-18 14:41:46 +01:00
SubQueryGrpTypes , ( unsigned ) Rol_STD ,
SubQueryGrpTypes ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod , ( unsigned ) Rol_STD ,
2019-02-18 14:41:46 +01:00
SubQueryGrpTypes , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
2019-02-18 09:40:46 +01:00
2019-02-18 14:41:46 +01:00
/***** Free allocated memory for subquery *****/
2019-11-06 19:45:20 +01:00
free ( SubQueryGrpTypes ) ;
2014-12-01 23:55:08 +01:00
return ( NumGrpTypes ! = 0 ) ;
}
/*****************************************************************************/
/****** Query list of group codes of a type to which a user belongs to *******/
/*****************************************************************************/
// If CrsCod < 0 ==> get the groups from all the user's courses
// If GrpTypCod < 0 ==> get the groups of any type
static void Grp_GetLstCodGrpsUsrBelongs ( long CrsCod , long GrpTypCod ,
long UsrCod , struct ListCodGrps * LstGrps )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrp ;
/***** Get groups which a user belong to from database *****/
if ( CrsCod < 0 ) // Query the groups from all the user's courses
2018-10-31 10:19:01 +01:00
LstGrps - > NumGrps =
( unsigned ) DB_QuerySELECT ( & mysql_res , " can not get the groups "
" which a user belongs to " ,
" SELECT GrpCod "
" FROM crs_grp_usr "
" WHERE UsrCod=%ld " , // Groups will be unordered
UsrCod ) ;
2014-12-01 23:55:08 +01:00
else if ( GrpTypCod < 0 ) // Query the groups of any type in the course
2018-10-31 10:19:01 +01:00
LstGrps - > NumGrps =
( unsigned ) DB_QuerySELECT ( & mysql_res , " can not get the groups "
" which a user belongs to " ,
" SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=%ld "
" ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod , UsrCod ) ;
2014-12-01 23:55:08 +01:00
else // Query only the groups of specified type in the course
2018-10-31 10:19:01 +01:00
LstGrps - > NumGrps =
( unsigned ) DB_QuerySELECT ( & mysql_res , " can not get the groups "
" which a user belongs to " ,
" SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=%ld "
" ORDER BY crs_grp.GrpName " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod , GrpTypCod , UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups the user belongs to *****/
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods = ( long * ) calloc ( LstGrps - > NumGrps , sizeof ( long ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/********** Query list of group codes with file zones I belong to ************/
/*****************************************************************************/
void Grp_GetLstCodGrpsWithFileZonesIBelong ( struct ListCodGrps * LstGrps )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrp ;
/***** Get groups which I belong to from database *****/
2018-10-31 10:19:01 +01:00
LstGrps - > NumGrps =
( unsigned ) DB_QuerySELECT ( & mysql_res , " can not get the groups "
" which you belong to " ,
" SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.FileZones='Y' "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=%ld "
" ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups I belong to *****/
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods = ( long * ) calloc ( LstGrps - > NumGrps , sizeof ( long ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/******** Check if a group is in a list of groups which I belong to **********/
/*****************************************************************************/
static bool Grp_CheckIfGrpIsInList ( long GrpCod , struct ListCodGrps * LstGrps )
{
unsigned NumGrp ;
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
2017-01-19 20:55:31 +01:00
if ( GrpCod = = LstGrps - > GrpCods [ NumGrp ] )
2014-12-01 23:55:08 +01:00
return true ;
return false ;
}
/*****************************************************************************/
/********** Query names of groups of a type which user belongs to ************/
/*****************************************************************************/
void Grp_GetNamesGrpsStdBelongsTo ( long GrpTypCod , long UsrCod , char * GroupNames )
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2017-01-16 01:51:01 +01:00
unsigned long NumRow ;
unsigned long NumRows ;
2018-10-31 10:19:01 +01:00
size_t MaxLength = ( Grp_MAX_BYTES_GROUP_NAME + 2 ) *
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . NumGrpsTotal ;
2014-12-01 23:55:08 +01:00
/***** Get the names of groups which a user belongs to, from database *****/
2018-10-31 10:19:01 +01:00
NumRows = DB_QuerySELECT ( & mysql_res , " can not get the names of groups "
" a user belongs to " ,
" SELECT crs_grp.GrpName "
" FROM crs_grp,crs_grp_usr "
" WHERE crs_grp.GrpTypCod=%ld "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=%ld "
" ORDER BY crs_grp.GrpName " ,
GrpTypCod , UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
GroupNames [ 0 ] = ' \0 ' ;
for ( NumRow = 0 ;
NumRow < NumRows ;
NumRow + + )
{
/* Get next group */
row = mysql_fetch_row ( mysql_res ) ;
/* El group name in row[0] */
if ( NumRow )
2017-01-17 03:33:05 +01:00
Str_Concat ( GroupNames , " , " ,
MaxLength ) ;
Str_Concat ( GroupNames , row [ 0 ] ,
MaxLength ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/****************** Receive form to create a new group type ******************/
/*****************************************************************************/
2020-05-05 21:49:00 +02:00
void Grp_ReceiveFormNewGrpTyp ( void )
2014-12-01 23:55:08 +01:00
{
extern const char * Txt_The_type_of_group_X_already_exists ;
2017-04-29 02:20:34 +02:00
extern const char * Txt_Created_new_type_of_group_X ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_You_must_specify_the_name_of_the_new_type_of_group ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the name of group type */
2019-04-04 10:45:15 +02:00
Par_GetParToText ( " GrpTypName " , Gbl . Crs . Grps . GrpTyp . GrpTypName ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Get whether it is mandatory to regisrer in any group of this type */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MandatoryEnrolment = Par_GetParToBool ( " MandatoryEnrolment " ) ;
2014-12-01 23:55:08 +01:00
/* Get whether it is possible to register in multiple groups of this type */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MultipleEnrolment = Par_GetParToBool ( " MultipleEnrolment " ) ;
2014-12-01 23:55:08 +01:00
/* Get open time */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . OpenTimeUTC = Dat_GetTimeUTCFromForm ( " OpenTimeUTC " ) ;
Gbl . Crs . Grps . GrpTyp . MustBeOpened = Grp_CheckIfOpenTimeInTheFuture ( Gbl . Crs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTyp . GrpTypName [ 0 ] ) // If there's a group type name
2014-12-01 23:55:08 +01:00
{
/***** If name of group type was in database... *****/
2019-04-04 10:45:15 +02:00
if ( Grp_CheckIfGroupTypeNameExists ( Gbl . Crs . Grps . GrpTyp . GrpTypName , - 1L ) )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_group_X_already_exists ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
else // Add new group type to database
2017-04-29 02:20:34 +02:00
{
2014-12-01 23:55:08 +01:00
Grp_CreateGroupType ( ) ;
2017-04-29 02:20:34 +02:00
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_Created_new_type_of_group_X ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2017-04-29 02:20:34 +02:00
}
2014-12-01 23:55:08 +01:00
}
else // If there is not a group type name
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2019-03-09 20:12:44 +01:00
Str_Copy ( AlertTxt , Txt_You_must_specify_the_name_of_the_new_type_of_group ,
sizeof ( AlertTxt ) - 1 ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2019-03-09 20:12:44 +01:00
Grp_ReqEditGroupsInternal ( AlertType , AlertTxt ,
2017-05-11 23:45:46 +02:00
Ale_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************** Check if the open time if in the future ********************/
/*****************************************************************************/
2015-10-26 20:02:07 +01:00
static bool Grp_CheckIfOpenTimeInTheFuture ( time_t OpenTimeUTC )
2014-12-01 23:55:08 +01:00
{
2015-10-26 20:02:07 +01:00
/***** If open time is 0 ==> groups must no be opened *****/
if ( OpenTimeUTC = = ( time_t ) 0 )
2014-12-01 23:55:08 +01:00
return false ;
/***** Is open time in the future? *****/
2015-10-27 19:00:21 +01:00
return ( OpenTimeUTC > Gbl . StartExecutionTimeUTC ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Receive form to create a new group *********************/
/*****************************************************************************/
2020-05-05 21:49:00 +02:00
void Grp_ReceiveFormNewGrp ( void )
2014-12-01 23:55:08 +01:00
{
extern const char * Txt_The_group_X_already_exists ;
2017-04-28 18:03:30 +02:00
extern const char * Txt_Created_new_group_X ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_You_must_specify_the_name_of_the_new_group ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) > 0 ) // Group type valid
2014-12-01 23:55:08 +01:00
{
/* Get group name */
2019-04-04 10:45:15 +02:00
Par_GetParToText ( " GrpName " , Gbl . Crs . Grps . GrpName ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
2020-04-14 17:15:17 +02:00
/* Get room */
Gbl . Crs . Grps . RooCod = Roo_GetParamRooCod ( ) ;
2019-01-04 22:46:46 +01:00
2014-12-01 23:55:08 +01:00
/* Get maximum number of students */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . MaxStudents = ( unsigned )
2017-01-29 21:41:08 +01:00
Par_GetParToUnsignedLong ( " MaxStudents " ,
0 ,
Grp_MAX_STUDENTS_IN_A_GROUP ,
Grp_NUM_STUDENTS_NOT_LIMITED ) ;
2014-12-01 23:55:08 +01:00
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpName [ 0 ] ) // If there's a group name
2014-12-01 23:55:08 +01:00
{
/***** If name of group was in database... *****/
2019-04-04 10:45:15 +02:00
if ( Grp_CheckIfGroupNameExists ( Gbl . Crs . Grps . GrpTyp . GrpTypCod , Gbl . Crs . Grps . GrpName , - 1L ) )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_already_exists ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
else // Add new group to database
2017-04-28 18:03:30 +02:00
{
2014-12-01 23:55:08 +01:00
Grp_CreateGroup ( ) ;
2017-04-28 18:03:30 +02:00
/* Write success message */
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_Created_new_group_X ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpName ) ;
2017-04-28 18:03:30 +02:00
}
2014-12-01 23:55:08 +01:00
}
else // If there is not a group name
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_ERROR ;
2019-03-09 20:12:44 +01:00
Str_Copy ( AlertTxt , Txt_You_must_specify_the_name_of_the_new_group ,
sizeof ( AlertTxt ) - 1 ) ;
2014-12-01 23:55:08 +01:00
}
}
else // Invalid group type
2017-04-28 18:03:30 +02:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_ERROR ;
2019-03-09 20:12:44 +01:00
Str_Copy ( AlertTxt , " Wrong type of group. " ,
sizeof ( AlertTxt ) - 1 ) ;
2017-04-28 18:03:30 +02:00
}
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
AlertType , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Check if name of group type exists **********************/
/*****************************************************************************/
static bool Grp_CheckIfGroupTypeNameExists ( const char * GrpTypName , long GrpTypCod )
{
/***** Get number of group types with a name from database *****/
2018-11-03 20:52:00 +01:00
return ( DB_QueryCOUNT ( " can not check if the name of type of group "
" already existed " ,
" SELECT COUNT(*) FROM crs_grp_types "
" WHERE CrsCod=%ld AND GrpTypName='%s' "
" AND GrpTypCod<>%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod , GrpTypName , GrpTypCod ) ! = 0 ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************ Check if name of group exists **********************/
/*****************************************************************************/
static bool Grp_CheckIfGroupNameExists ( long GrpTypCod , const char * GrpName , long GrpCod )
{
/***** Get number of groups with a type and a name from database *****/
2018-11-03 20:52:00 +01:00
return ( DB_QueryCOUNT ( " can not check if the name of group already existed " ,
" SELECT COUNT(*) FROM crs_grp "
" WHERE GrpTypCod=%ld "
" AND GrpName='%s' "
" AND GrpCod<>%ld " ,
GrpTypCod , GrpName , GrpCod ) ! = 0 ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************** Create a new group type **************************/
/*****************************************************************************/
static void Grp_CreateGroupType ( void )
{
/***** Create a new group type *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod =
2018-11-03 01:45:36 +01:00
DB_QueryINSERTandReturnCode ( " can not create type of group " ,
" INSERT INTO crs_grp_types "
" (CrsCod,GrpTypName,Mandatory,Multiple,MustBeOpened,OpenTime) "
" VALUES "
" (%ld,'%s','%c','%c','%c',FROM_UNIXTIME(%ld)) " ,
2019-04-04 10:45:15 +02:00
Gbl . Hierarchy . Crs . CrsCod , Gbl . Crs . Grps . GrpTyp . GrpTypName ,
Gbl . Crs . Grps . GrpTyp . MandatoryEnrolment ? ' Y ' :
2018-11-03 01:45:36 +01:00
' N ' ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MultipleEnrolment ? ' Y ' :
2018-11-03 01:45:36 +01:00
' N ' ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MustBeOpened ? ' Y ' :
2018-11-03 01:45:36 +01:00
' N ' ,
2019-04-04 10:45:15 +02:00
( long ) Gbl . Crs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************************** Create a new group ****************************/
/*****************************************************************************/
static void Grp_CreateGroup ( void )
{
2017-04-28 18:03:30 +02:00
/***** Create a new group *****/
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ( " can not create group " ,
" INSERT INTO crs_grp "
2020-04-14 17:15:17 +02:00
" (GrpTypCod,GrpName,RooCod,MaxStudents,Open,FileZones) "
2018-11-02 19:37:11 +01:00
" VALUES "
2019-01-04 22:46:46 +01:00
" (%ld,'%s',%ld,%u,'N','N') " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ,
Gbl . Crs . Grps . GrpName ,
2020-04-14 17:15:17 +02:00
Gbl . Crs . Grps . RooCod ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . MaxStudents ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Request removing of a group type **********************/
/*****************************************************************************/
void Grp_ReqRemGroupType ( void )
{
unsigned NumGrps ;
/***** Get the code of the group type *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Check if this group type has groups *****/
2019-04-04 10:45:15 +02:00
if ( ( NumGrps = Grp_CountNumGrpsInThisCrsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ) ) // Group type has groups ==> Ask for confirmation
2014-12-01 23:55:08 +01:00
Grp_AskConfirmRemGrpTypWithGrps ( NumGrps ) ;
else // Group type has no groups ==> remove directly
Grp_RemoveGroupTypeCompletely ( ) ;
}
/*****************************************************************************/
/************************* Request removal of a group ************************/
/*****************************************************************************/
void Grp_ReqRemGroup ( void )
{
/***** Get group code *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Confirm removing *****/
Grp_AskConfirmRemGrp ( ) ;
}
/*****************************************************************************/
/********** Ask for confirmation to remove a group type with groups **********/
/*****************************************************************************/
static void Grp_AskConfirmRemGrpTypWithGrps ( unsigned NumGrps )
{
extern const char * Txt_Do_you_really_want_to_remove_the_type_of_group_X_1_group_ ;
extern const char * Txt_Do_you_really_want_to_remove_the_type_of_group_X_Y_groups_ ;
extern const char * Txt_Remove_type_of_group ;
/***** Get data of the group type from database *****/
2019-04-04 10:45:15 +02:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . Crs . Grps . GrpTyp ) ;
2014-12-01 23:55:08 +01:00
2017-04-29 02:20:34 +02:00
/***** Start section to edit group types *****/
Grp_ReqEditGroupsInternal0 ( ) ;
2017-04-28 14:12:37 +02:00
/***** Show question and button to remove type of group *****/
2014-12-01 23:55:08 +01:00
if ( NumGrps = = 1 )
2019-02-17 01:14:55 +01:00
Ale_ShowAlertAndButton ( ActRemGrpTyp , Grp_GROUP_TYPES_SECTION_ID , NULL ,
2020-04-08 18:18:46 +02:00
Grp_PutParamRemGrpTyp , & Gbl . Crs . Grps . GrpTyp . GrpTypCod ,
2019-02-17 01:14:55 +01:00
Btn_REMOVE_BUTTON , Txt_Remove_type_of_group ,
Ale_QUESTION , Txt_Do_you_really_want_to_remove_the_type_of_group_X_1_group_ ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
else
2019-02-17 01:14:55 +01:00
Ale_ShowAlertAndButton ( ActRemGrpTyp , Grp_GROUP_TYPES_SECTION_ID , NULL ,
2020-04-08 18:18:46 +02:00
Grp_PutParamRemGrpTyp , & Gbl . Crs . Grps . GrpTyp . GrpTypCod ,
2019-02-17 01:14:55 +01:00
Btn_REMOVE_BUTTON , Txt_Remove_type_of_group ,
Ale_QUESTION , Txt_Do_you_really_want_to_remove_the_type_of_group_X_Y_groups_ ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName , NumGrps ) ;
2017-04-28 14:12:37 +02:00
2017-04-29 02:20:34 +02:00
/***** Show the form to edit group types and groups again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal1 ( Ale_INFO , NULL ) ;
Grp_ReqEditGroupsInternal2 ( Ale_INFO , NULL ) ;
2017-04-28 14:12:37 +02:00
}
/*****************************************************************************/
/**************** Put parameter to remove a type of group ********************/
/*****************************************************************************/
2020-04-08 18:18:46 +02:00
static void Grp_PutParamRemGrpTyp ( void * GrpTypCod )
2017-04-28 14:12:37 +02:00
{
2020-04-08 18:18:46 +02:00
if ( GrpTypCod )
Grp_PutParamGrpTypCod ( * ( ( long * ) GrpTypCod ) ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Ask for confirmation to remove a group ******************/
/*****************************************************************************/
static void Grp_AskConfirmRemGrp ( void )
{
extern const char * Txt_Do_you_really_want_to_remove_the_group_X ;
extern const char * Txt_Do_you_really_want_to_remove_the_group_X_1_student_ ;
extern const char * Txt_Do_you_really_want_to_remove_the_group_X_Y_students_ ;
extern const char * Txt_Remove_group ;
struct GroupData GrpDat ;
unsigned NumStds ;
2017-04-28 13:10:46 +02:00
/***** Get name of the group from database *****/
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
2017-04-28 13:10:46 +02:00
/***** Count number of students in group *****/
2019-04-04 10:45:15 +02:00
NumStds = Grp_CountNumUsrsInGrp ( Rol_STD , Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2017-04-29 02:20:34 +02:00
/***** Show the form to edit group types again *****/
Grp_ReqEditGroupsInternal0 ( ) ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal1 ( Ale_INFO , NULL ) ;
2017-04-29 02:20:34 +02:00
2017-04-28 13:10:46 +02:00
/***** Show question and button to remove group *****/
2014-12-01 23:55:08 +01:00
if ( NumStds = = 0 )
2019-02-17 01:14:55 +01:00
Ale_ShowAlertAndButton ( ActRemGrp , Grp_GROUPS_SECTION_ID , NULL ,
2020-04-08 18:18:46 +02:00
Grp_PutParamRemGrp , & Gbl . Crs . Grps . GrpCod ,
2019-02-17 01:14:55 +01:00
Btn_REMOVE_BUTTON , Txt_Remove_group ,
Ale_QUESTION , Txt_Do_you_really_want_to_remove_the_group_X ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
else if ( NumStds = = 1 )
2019-02-17 01:14:55 +01:00
Ale_ShowAlertAndButton ( ActRemGrp , Grp_GROUPS_SECTION_ID , NULL ,
2020-04-08 18:18:46 +02:00
Grp_PutParamRemGrp , & Gbl . Crs . Grps . GrpCod ,
2019-02-17 01:14:55 +01:00
Btn_REMOVE_BUTTON , Txt_Remove_group ,
Ale_QUESTION , Txt_Do_you_really_want_to_remove_the_group_X_1_student_ ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
else
2019-02-17 01:14:55 +01:00
Ale_ShowAlertAndButton ( ActRemGrp , Grp_GROUPS_SECTION_ID , NULL ,
2020-04-08 18:18:46 +02:00
Grp_PutParamRemGrp , & Gbl . Crs . Grps . GrpCod ,
2019-02-17 01:14:55 +01:00
Btn_REMOVE_BUTTON , Txt_Remove_group ,
Ale_QUESTION , Txt_Do_you_really_want_to_remove_the_group_X_Y_students_ ,
GrpDat . GrpName , NumStds ) ;
2017-04-28 13:10:46 +02:00
2017-04-29 02:20:34 +02:00
/***** Show the form to edit groups again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal2 ( Ale_INFO , NULL ) ;
2017-04-28 13:10:46 +02:00
}
/*****************************************************************************/
/*********************** Put parameter to remove a group *********************/
/*****************************************************************************/
2020-04-08 18:18:46 +02:00
static void Grp_PutParamRemGrp ( void * GrpCod )
2017-04-28 13:10:46 +02:00
{
2020-04-08 18:18:46 +02:00
if ( GrpCod )
Grp_PutParamGrpCod ( * ( ( long * ) GrpCod ) ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-04-28 13:10:46 +02:00
/**************************** Remove a group type ****************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_RemoveGroupType ( void )
{
/***** Get param with code of group type *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/***** Remove group type and its groups *****/
Grp_RemoveGroupTypeCompletely ( ) ;
}
/*****************************************************************************/
/******************************* Remove a group ******************************/
/*****************************************************************************/
void Grp_RemoveGroup ( void )
{
/***** Get param with group code *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Remove group *****/
Grp_RemoveGroupCompletely ( ) ;
}
/*****************************************************************************/
2017-04-29 02:20:34 +02:00
/********************* Remove a group type from database *********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Grp_RemoveGroupTypeCompletely ( void )
{
extern const char * Txt_Type_of_group_X_removed ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get name and type of the group from database *****/
2019-04-04 10:45:15 +02:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . Crs . Grps . GrpTyp ) ;
2014-12-01 23:55:08 +01:00
/***** Remove file zones of all the groups of this type *****/
2019-04-04 10:45:15 +02:00
Brw_RemoveZonesOfGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove the associations of assignments to groups of this type *****/
2019-04-04 10:45:15 +02:00
Asg_RemoveGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove the associations of attendance events to groups of this type *****/
2019-04-04 10:45:15 +02:00
Att_RemoveGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
2019-09-27 20:22:32 +02:00
/***** Remove the associations of matches to groups of this type *****/
Mch_RemoveGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove the associations of surveys to groups of this type *****/
2019-04-04 10:45:15 +02:00
Svy_RemoveGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Change all groups of this type in course timetable *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update all groups of a type in course timetable " ,
" UPDATE timetable_crs SET GrpCod=-1 "
" WHERE GrpCod IN "
" (SELECT GrpCod FROM crs_grp WHERE GrpTypCod=%ld) " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove all the students in groups of this type *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove users from all groups of a type " ,
" DELETE FROM crs_grp_usr WHERE GrpCod IN "
" (SELECT GrpCod FROM crs_grp WHERE GrpTypCod=%ld) " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove all the groups of this type *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove groups of a type " ,
" DELETE FROM crs_grp WHERE GrpTypCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove the group type *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove a type of group " ,
" DELETE FROM crs_grp_types WHERE GrpTypCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_Type_of_group_X_removed ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-03-09 20:12:44 +01:00
Grp_ReqEditGroupsInternal ( Ale_SUCCESS , AlertTxt ,
2017-05-11 23:45:46 +02:00
Ale_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******* Remove a group from data base and remove group common zone **********/
/*****************************************************************************/
static void Grp_RemoveGroupCompletely ( void )
{
extern const char * Txt_Group_X_removed ;
struct GroupData GrpDat ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get name and type of the group from database *****/
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Remove file zones of this group *****/
2019-04-04 10:45:15 +02:00
Brw_RemoveGrpZones ( Gbl . Hierarchy . Crs . CrsCod , GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2019-09-27 20:22:32 +02:00
/***** Remove this group from all assignments *****/
2014-12-01 23:55:08 +01:00
Asg_RemoveGroup ( GrpDat . GrpCod ) ;
2019-09-27 20:22:32 +02:00
/***** Remove this group from all attendance events *****/
2014-12-01 23:55:08 +01:00
Att_RemoveGroup ( GrpDat . GrpCod ) ;
2019-09-27 20:22:32 +02:00
/***** Remove this group from all matches *****/
Mch_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Remove this group from all surveys *****/
2014-12-01 23:55:08 +01:00
Svy_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Change this group in course timetable *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update a group in course timetable " ,
" UPDATE timetable_crs SET GrpCod=-1 WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove all the students in this group *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove users from a group " ,
" DELETE FROM crs_grp_usr WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove the group *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ( " can not remove a group " ,
" DELETE FROM crs_grp WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_Group_X_removed ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
Ale_SUCCESS , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************************* Open a group ********************************/
/*****************************************************************************/
void Grp_OpenGroup ( void )
{
extern const char * Txt_The_group_X_is_now_open ;
struct GroupData GrpDat ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get group code *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing open/close status *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not open a group " ,
" UPDATE crs_grp SET Open='Y' WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_is_now_open ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . Open = true ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
Ale_SUCCESS , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************************* Close a group *******************************/
/*****************************************************************************/
void Grp_CloseGroup ( void )
{
extern const char * Txt_The_group_X_is_now_closed ;
struct GroupData GrpDat ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get group code *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing open/close status *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not close a group " ,
" UPDATE crs_grp SET Open='N' WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_is_now_closed ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . Open = false ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
Ale_SUCCESS , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************ Enable file zones of a group ***********************/
/*****************************************************************************/
void Grp_EnableFileZonesGrp ( void )
{
extern const char * Txt_File_zones_of_the_group_X_are_now_enabled ;
struct GroupData GrpDat ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get group code *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing file zones status *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not enable file zones of a group " ,
" UPDATE crs_grp SET FileZones='Y' WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_File_zones_of_the_group_X_are_now_enabled ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . FileZones = true ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
Ale_SUCCESS , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Disable file zones of a group ***********************/
/*****************************************************************************/
void Grp_DisableFileZonesGrp ( void )
{
extern const char * Txt_File_zones_of_the_group_X_are_now_disabled ;
struct GroupData GrpDat ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get group code *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing file zones status *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not disable file zones of a group " ,
" UPDATE crs_grp SET FileZones='N' WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_File_zones_of_the_group_X_are_now_disabled ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . FileZones = false ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
Ale_SUCCESS , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Change the group type of a group ********************/
/*****************************************************************************/
void Grp_ChangeGroupType ( void )
{
extern const char * Txt_The_group_X_already_exists ;
extern const char * Txt_The_type_of_group_of_the_group_X_has_changed ;
long NewGrpTypCod ;
struct GroupData GrpDat ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get group code */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new group type */
NewGrpTypCod = Grp_GetParamGrpTypCod ( ) ;
/* Get from the database the type and the name of the group */
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** If group was in database... *****/
if ( Grp_CheckIfGroupNameExists ( NewGrpTypCod , GrpDat . GrpName , - 1L ) )
{
2018-10-16 21:56:01 +02:00
/* Create warning message */
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_already_exists ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
2018-10-16 21:56:01 +02:00
else // Group is not in database
2014-12-01 23:55:08 +01:00
{
/* Update the table of groups changing old type by new type */
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update the type of a group " ,
" UPDATE crs_grp SET GrpTypCod=%ld WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
NewGrpTypCod , Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/* Create message to show the change made */
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_group_of_the_group_X_has_changed ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod = NewGrpTypCod ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
AlertType , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
2019-01-04 22:46:46 +01:00
/*****************************************************************************/
2020-04-14 17:15:17 +02:00
/************************* Change the room of a group ************************/
2019-01-04 22:46:46 +01:00
/*****************************************************************************/
2020-04-14 17:15:17 +02:00
void Grp_ChangeGroupRoom ( void )
2019-01-04 22:46:46 +01:00
{
2020-04-14 17:15:17 +02:00
extern const char * Txt_The_room_assigned_to_the_group_X_has_changed ;
long NewRooCod ;
2019-01-04 22:46:46 +01:00
struct GroupData GrpDat ;
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2019-01-04 22:46:46 +01:00
/***** Get parameters from form *****/
/* Get group code */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
2019-01-04 22:46:46 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
2020-04-14 17:15:17 +02:00
/* Get the new room */
NewRooCod = Roo_GetParamRooCod ( ) ;
2019-01-04 22:46:46 +01:00
/* Get from the database the name of the group */
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2019-01-04 22:46:46 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
2020-04-14 17:15:17 +02:00
/***** Update the table of groups changing old room by new room *****/
DB_QueryUPDATE ( " can not update the room of a group " ,
" UPDATE crs_grp SET RooCod=%ld WHERE GrpCod=%ld " ,
NewRooCod , Gbl . Crs . Grps . GrpCod ) ;
2019-01-04 22:46:46 +01:00
/* Create message to show the change made */
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2020-04-14 17:15:17 +02:00
Txt_The_room_assigned_to_the_group_X_has_changed ,
2019-01-04 22:46:46 +01:00
GrpDat . GrpName ) ;
/***** Show the form again *****/
2020-04-14 17:15:17 +02:00
Gbl . Crs . Grps . RooCod = NewRooCod ;
2019-01-04 22:46:46 +01:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
AlertType , AlertTxt ) ;
2019-01-04 22:46:46 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************ Change mandatory registration to a group of a type *************/
/*****************************************************************************/
void Grp_ChangeMandatGrpTyp ( void )
{
2017-03-30 11:20:06 +02:00
extern const char * Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ;
extern const char * Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_mandatory ;
extern const char * Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_voluntary ;
bool NewMandatoryEnrolment ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters of the form *****/
/* Get the c<> digo of type of group */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
2017-03-30 11:20:06 +02:00
/* Get the new type of enrolment (mandatory or voluntaria) of this type of group */
NewMandatoryEnrolment = Par_GetParToBool ( " MandatoryEnrolment " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/* Get from the database the name of the type and the old type of enrolment */
2019-04-04 10:45:15 +02:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . Crs . Grps . GrpTyp ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/***** Check if the old type of enrolment match the new
2019-01-02 15:10:51 +01:00
( this happens when return is pressed without changes ) * * * * */
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTyp . MandatoryEnrolment = = NewMandatoryEnrolment )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
else
{
2017-03-30 11:20:06 +02:00
/***** Update of the table of types of group changing the old type of enrolment by the new *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update enrolment type of a type of group " ,
2019-11-06 22:47:12 +01:00
" UPDATE crs_grp_types SET Mandatory='%c' "
" WHERE GrpTypCod=%ld " ,
2018-11-03 12:16:40 +01:00
NewMandatoryEnrolment ? ' Y ' :
' N ' ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
NewMandatoryEnrolment ? Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_mandatory :
Txt_The_enrolment_of_students_into_groups_of_type_X_is_now_voluntary ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MandatoryEnrolment = NewMandatoryEnrolment ;
2019-03-09 20:12:44 +01:00
Grp_ReqEditGroupsInternal ( AlertType , AlertTxt ,
2017-05-11 23:45:46 +02:00
Ale_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/******** Change multiple enrolment to one or more groups of a type *********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_ChangeMultiGrpTyp ( void )
{
2017-03-30 11:20:06 +02:00
extern const char * Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Now_each_student_can_belong_to_multiple_groups_of_type_X ;
extern const char * Txt_Now_each_student_can_only_belong_to_a_group_of_type_X ;
2017-03-30 11:20:06 +02:00
bool NewMultipleEnrolment ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from the form *****/
/* Get the code of type of group */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
2017-03-30 11:20:06 +02:00
/* Get the new type of enrolment (single or multiple) of this type of group */
NewMultipleEnrolment = Par_GetParToBool ( " MultipleEnrolment " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/* Get from the database the name of the type and the old type of enrolment */
2019-04-04 10:45:15 +02:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . Crs . Grps . GrpTyp ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/***** Check if the old type of enrolment match the new one
2014-12-01 23:55:08 +01:00
( this happends when return is pressed without changes ) * * * * */
2019-04-04 10:45:15 +02:00
if ( Gbl . Crs . Grps . GrpTyp . MultipleEnrolment = = NewMultipleEnrolment )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
else
{
2017-03-30 11:20:06 +02:00
/***** Update of the table of types of group changing the old type of enrolment by the new *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update enrolment type of a type of group " ,
" UPDATE crs_grp_types SET Multiple='%c' "
" WHERE GrpTypCod=%ld " ,
NewMultipleEnrolment ? ' Y ' :
' N ' ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
NewMultipleEnrolment ? Txt_Now_each_student_can_belong_to_multiple_groups_of_type_X :
Txt_Now_each_student_can_only_belong_to_a_group_of_type_X ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MultipleEnrolment = NewMultipleEnrolment ;
2019-03-09 20:12:44 +01:00
Grp_ReqEditGroupsInternal ( AlertType , AlertTxt ,
2017-05-11 23:45:46 +02:00
Ale_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Change open time for a type of group *********************/
/*****************************************************************************/
void Grp_ChangeOpenTimeGrpTyp ( void )
{
extern const char * Txt_The_date_time_of_opening_of_groups_has_changed ;
/***** Get the code of type of group *****/
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/***** Get from the database the data of this type of group *****/
2019-04-04 10:45:15 +02:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . Crs . Grps . GrpTyp ) ;
2014-12-01 23:55:08 +01:00
/***** Get open time *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . OpenTimeUTC = Dat_GetTimeUTCFromForm ( " OpenTimeUTC " ) ;
Gbl . Crs . Grps . GrpTyp . MustBeOpened = Grp_CheckIfOpenTimeInTheFuture ( Gbl . Crs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
2016-04-30 17:16:41 +02:00
/***** Update the table of types of group
2017-03-30 11:20:06 +02:00
changing the old open time of enrolment by the new * * * * */
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update enrolment type of a type of group " ,
" UPDATE crs_grp_types "
" SET MustBeOpened='%c',OpenTime=FROM_UNIXTIME(%ld) "
" WHERE GrpTypCod=%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MustBeOpened ? ' Y ' :
2018-11-03 12:16:40 +01:00
' N ' ,
2019-04-04 10:45:15 +02:00
( long ) Gbl . Crs . Grps . GrpTyp . OpenTimeUTC ,
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2019-02-16 16:18:54 +01:00
Ale_ShowAlert ( Ale_SUCCESS , Txt_The_date_time_of_opening_of_groups_has_changed ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-03-09 20:12:44 +01:00
Grp_ReqEditGroupsInternal ( Ale_SUCCESS , NULL ,
2017-05-11 23:45:46 +02:00
Ale_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Change maximum of students in a group *********************/
/*****************************************************************************/
void Grp_ChangeMaxStdsGrp ( void )
{
2019-01-02 22:06:29 +01:00
extern const char * Txt_The_maximum_number_of_students_in_group_X_has_not_changed ;
2019-01-02 15:10:51 +01:00
extern const char * Txt_The_group_X_does_not_have_a_student_limit_now ;
2019-01-02 22:06:29 +01:00
extern const char * Txt_The_maximum_number_of_students_in_group_X_is_now_Y ;
2014-12-01 23:55:08 +01:00
struct GroupData GrpDat ;
unsigned NewMaxStds ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters of the form *****/
/* Get group code */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new maximum number of students of the group */
2017-01-29 21:41:08 +01:00
NewMaxStds = ( unsigned )
Par_GetParToUnsignedLong ( " MaxStudents " ,
0 ,
Grp_MAX_STUDENTS_IN_A_GROUP ,
Grp_NUM_STUDENTS_NOT_LIMITED ) ;
2014-12-01 23:55:08 +01:00
2019-01-02 15:10:51 +01:00
/* Get from the database the type, name, and old maximum of students of the group */
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
2019-01-02 15:10:51 +01:00
/***** Check if the old maximum of students equals the new one
( this happens when return is pressed without changes ) * * * * */
2014-12-01 23:55:08 +01:00
if ( GrpDat . MaxStudents = = NewMaxStds )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2019-01-02 22:06:29 +01:00
Txt_The_maximum_number_of_students_in_group_X_has_not_changed ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/***** Update the table of groups changing the old maximum of students to the new *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update the maximum number of students "
" in a group " ,
" UPDATE crs_grp SET MaxStudents=%u WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
NewMaxStds , Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2017-01-29 12:42:19 +01:00
if ( NewMaxStds > Grp_MAX_STUDENTS_IN_A_GROUP )
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2019-01-02 15:10:51 +01:00
Txt_The_group_X_does_not_have_a_student_limit_now ,
2018-10-16 21:56:01 +02:00
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
else
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2019-01-02 22:06:29 +01:00
Txt_The_maximum_number_of_students_in_group_X_is_now_Y ,
GrpDat . GrpName , NewMaxStds ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . MaxStudents = NewMaxStds ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
AlertType , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-01-02 15:10:51 +01:00
/************* Write the maximum number of students in a group ***************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-11-08 01:10:32 +01:00
static void Grp_WriteMaxStds ( char Str [ Cns_MAX_DECIMAL_DIGITS_UINT + 1 ] , unsigned MaxStudents )
2014-12-01 23:55:08 +01:00
{
2017-05-30 21:43:05 +02:00
if ( MaxStudents < = Grp_MAX_STUDENTS_IN_A_GROUP )
2019-11-08 01:10:32 +01:00
snprintf ( Str , Cns_MAX_DECIMAL_DIGITS_UINT + 1 ,
2019-11-03 23:59:20 +01:00
" %u " ,
MaxStudents ) ;
else
Str [ 0 ] = ' \0 ' ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********* Convert string to maximum number of students in a group ***********/
/*****************************************************************************/
unsigned Grp_ConvertToNumMaxStdsGrp ( const char * StrMaxStudents )
{
unsigned MaxStudents ;
if ( sscanf ( StrMaxStudents , " %u " , & MaxStudents ) ! = 1 )
2017-01-29 12:42:19 +01:00
return Grp_NUM_STUDENTS_NOT_LIMITED ;
2014-12-01 23:55:08 +01:00
else if ( MaxStudents > Grp_MAX_STUDENTS_IN_A_GROUP )
2017-01-29 12:42:19 +01:00
return Grp_NUM_STUDENTS_NOT_LIMITED ;
2014-12-01 23:55:08 +01:00
return MaxStudents ;
}
/*****************************************************************************/
/***************************** Rename a group type ***************************/
/*****************************************************************************/
void Grp_RenameGroupType ( void )
{
2019-12-20 00:30:54 +01:00
extern const char * Txt_You_can_not_leave_the_field_empty ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_The_type_of_group_X_already_exists ;
extern const char * Txt_The_type_of_group_X_has_been_renamed_as_Y ;
extern const char * Txt_The_name_of_the_type_of_group_X_has_not_changed ;
2017-03-07 11:03:05 +01:00
char NewNameGrpTyp [ Grp_MAX_BYTES_GROUP_TYPE_NAME + 1 ] ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the code of the group type */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/* Get the new name for the group type */
2017-03-07 11:03:05 +01:00
Par_GetParToText ( " GrpTypName " , NewNameGrpTyp , Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/***** Get from the database the old name of the group type *****/
2019-04-04 10:45:15 +02:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . Crs . Grps . GrpTyp ) ;
2014-12-01 23:55:08 +01:00
/***** Check if new name is empty *****/
2019-12-20 00:30:54 +01:00
if ( NewNameGrpTyp [ 0 ] )
2014-12-01 23:55:08 +01:00
{
2019-01-02 15:10:51 +01:00
/***** Check if old and new names are the same
( this happens when return is pressed without changes ) * * * * */
2019-04-04 10:45:15 +02:00
if ( strcmp ( Gbl . Crs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ) ) // Different names
2014-12-01 23:55:08 +01:00
{
/***** If group type was in database... *****/
2019-04-04 10:45:15 +02:00
if ( Grp_CheckIfGroupTypeNameExists ( NewNameGrpTyp , Gbl . Crs . Grps . GrpTyp . GrpTypCod ) )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_group_X_already_exists ,
NewNameGrpTyp ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/* Update the table changing old name by new name */
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update the type of a group " ,
" UPDATE crs_grp_types SET GrpTypName='%s' "
" WHERE GrpTypCod=%ld " ,
NewNameGrpTyp ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_group_X_has_been_renamed_as_Y ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ) ;
2014-12-01 23:55:08 +01:00
}
}
else // The same name
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_name_of_the_type_of_group_X_has_not_changed ,
NewNameGrpTyp ) ;
2014-12-01 23:55:08 +01:00
}
}
2019-12-20 00:30:54 +01:00
else
{
AlertType = Ale_WARNING ;
Str_Copy ( AlertTxt , Txt_You_can_not_leave_the_field_empty ,
sizeof ( AlertTxt ) - 1 ) ;
}
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Str_Copy ( Gbl . Crs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2019-03-09 20:12:44 +01:00
Grp_ReqEditGroupsInternal ( AlertType , AlertTxt ,
2017-05-11 23:45:46 +02:00
Ale_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************************* Rename a group ******************************/
/*****************************************************************************/
void Grp_RenameGroup ( void )
{
2019-12-20 00:30:54 +01:00
extern const char * Txt_You_can_not_leave_the_field_empty ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_The_group_X_already_exists ;
extern const char * Txt_The_group_X_has_been_renamed_as_Y ;
extern const char * Txt_The_name_of_the_group_X_has_not_changed ;
struct GroupData GrpDat ;
2017-03-07 11:03:05 +01:00
char NewNameGrp [ Grp_MAX_BYTES_GROUP_NAME + 1 ] ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2019-03-09 20:12:44 +01:00
char AlertTxt [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the code of the group */
2019-04-04 10:45:15 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new name for the group */
2017-03-07 11:03:05 +01:00
Par_GetParToText ( " GrpName " , NewNameGrp , Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
/***** Get from the database the type and the old name of the group *****/
2019-04-04 10:45:15 +02:00
GrpDat . GrpCod = Gbl . Crs . Grps . GrpCod ;
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Check if new name is empty *****/
if ( ! NewNameGrp [ 0 ] )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2019-12-20 00:30:54 +01:00
Str_Copy ( AlertTxt , Txt_You_can_not_leave_the_field_empty ,
sizeof ( AlertTxt ) - 1 ) ;
2014-12-01 23:55:08 +01:00
}
else
{
2019-01-02 15:10:51 +01:00
/***** Check if old and new names are the same
( this happens when return is pressed without changes ) * * * * */
2014-12-01 23:55:08 +01:00
if ( strcmp ( GrpDat . GrpName , NewNameGrp ) ) // Different names
{
/***** If group was in database... *****/
2019-04-04 10:45:15 +02:00
if ( Grp_CheckIfGroupNameExists ( GrpDat . GrpTypCod , NewNameGrp , Gbl . Crs . Grps . GrpCod ) )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_already_exists ,
NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/* Update the table changing old name by new name */
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ( " can not update the name of a group " ,
" UPDATE crs_grp SET GrpName='%s' WHERE GrpCod=%ld " ,
2019-04-04 10:45:15 +02:00
NewNameGrp , Gbl . Crs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_has_been_renamed_as_Y ,
GrpDat . GrpName , NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
}
else // The same name
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2019-03-09 20:12:44 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_name_of_the_group_X_has_not_changed ,
NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
}
/***** Show the form again *****/
2019-04-04 10:45:15 +02:00
Str_Copy ( Gbl . Crs . Grps . GrpName , NewNameGrp ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2019-03-09 20:12:44 +01:00
AlertType , AlertTxt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Get parameter with code of group type *******************/
/*****************************************************************************/
static long Grp_GetParamGrpTypCod ( void )
{
2017-01-28 20:32:50 +01:00
/***** Get code of group type *****/
return Par_GetParToLong ( " GrpTypCod " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Get parameter with group code ***********************/
/*****************************************************************************/
static long Grp_GetParamGrpCod ( void )
{
2017-01-28 20:32:50 +01:00
/***** Get group code *****/
return Par_GetParToLong ( " GrpCod " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Write parameter with code of group type ******************/
/*****************************************************************************/
static void Grp_PutParamGrpTypCod ( long GrpTypCod )
{
2019-11-03 13:19:32 +01:00
Par_PutHiddenParamLong ( NULL , " GrpTypCod " , GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Write parameter with code of group ********************/
/*****************************************************************************/
void Grp_PutParamGrpCod ( long GrpCod )
{
2019-11-03 13:19:32 +01:00
Par_PutHiddenParamLong ( NULL , " GrpCod " , GrpCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************ Get list of group codes selected *******************/
/*****************************************************************************/
void Grp_GetLstCodsGrpWanted ( struct ListCodGrps * LstGrpsWanted )
{
unsigned NumGrpTyp ;
2019-11-08 01:10:32 +01:00
char Param [ 6 + Cns_MAX_DECIMAL_DIGITS_LONG + 1 ] ;
char LongStr [ 1 + Cns_MAX_DECIMAL_DIGITS_LONG + 1 ] ;
2014-12-01 23:55:08 +01:00
char * * LstStrCodGrps ;
const char * Ptr ;
unsigned NumGrpWanted ;
/***** Allocate memory for the strings with group codes in each type *****/
2019-04-04 10:45:15 +02:00
if ( ( LstStrCodGrps = ( char * * ) calloc ( Gbl . Crs . Grps . GrpTypes . Num , sizeof ( char * ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get lists with the groups that I want in each type
in order to count the total number of groups selected * * * * */
for ( NumGrpTyp = 0 , LstGrpsWanted - > NumGrps = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
/***** Allocate memory for the list of group codes of this type *****/
2019-11-08 01:10:32 +01:00
if ( ( LstStrCodGrps [ NumGrpTyp ] = ( char * ) malloc ( ( size_t ) ( ( Cns_MAX_DECIMAL_DIGITS_LONG + 1 ) *
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ) ) = = NULL )
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get the multiple parameter code of group of this type *****/
2018-10-18 02:02:32 +02:00
snprintf ( Param , sizeof ( Param ) ,
" GrpCod%ld " ,
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-01-28 15:58:46 +01:00
Par_GetParMultiToText ( Param , LstStrCodGrps [ NumGrpTyp ] ,
2019-11-08 01:10:32 +01:00
( ( Cns_MAX_DECIMAL_DIGITS_LONG + 1 ) * Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) - 1 ) ;
2014-12-01 23:55:08 +01:00
if ( LstStrCodGrps [ NumGrpTyp ] [ 0 ] )
{
/***** Count the number of groups selected of this type of LstCodGrps[NumGrpTyp] *****/
for ( Ptr = LstStrCodGrps [ NumGrpTyp ] , NumGrpWanted = 0 ;
* Ptr ;
NumGrpWanted + + )
2019-11-08 01:10:32 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , Cns_MAX_DECIMAL_DIGITS_LONG ) ;
2014-12-01 23:55:08 +01:00
/***** Add the number of groups selected of this type to the number of groups selected total *****/
LstGrpsWanted - > NumGrps + = NumGrpWanted ;
}
}
/***** Create the list (argument passed to this function)
with all the groups selected ( of all the types ) * * * * */
if ( LstGrpsWanted - > NumGrps )
{
2017-01-19 20:55:31 +01:00
if ( ( LstGrpsWanted - > GrpCods = ( long * ) calloc ( LstGrpsWanted - > NumGrps , sizeof ( long ) ) ) = = NULL )
2017-03-30 11:20:06 +02:00
Lay_ShowErrorAndExit ( " Not enoguh memory to store codes of groups in which a user wants to be enroled. " ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
for ( NumGrpTyp = 0 , NumGrpWanted = 0 ;
2019-04-04 10:45:15 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . Num ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
/* Add the groups selected of this type to the complete list of groups selected */
for ( Ptr = LstStrCodGrps [ NumGrpTyp ] ;
* Ptr ;
NumGrpWanted + + )
{
2019-11-08 01:10:32 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , Cns_MAX_DECIMAL_DIGITS_LONG ) ;
2017-01-19 20:55:31 +01:00
LstGrpsWanted - > GrpCods [ NumGrpWanted ] = Str_ConvertStrCodToLongCod ( LongStr ) ;
2014-12-01 23:55:08 +01:00
}
/* Free memory used by the list of group codes of this type */
2019-11-06 19:45:20 +01:00
free ( LstStrCodGrps [ NumGrpTyp ] ) ;
2014-12-01 23:55:08 +01:00
}
}
/***** Free memory used by the lists of group codes of each type *****/
2019-11-06 19:45:20 +01:00
free ( LstStrCodGrps ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2016-12-29 22:19:46 +01:00
/************************** Free list of group codes *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_FreeListCodGrp ( struct ListCodGrps * LstGrps )
{
2017-01-19 20:55:31 +01:00
if ( LstGrps - > NumGrps & & LstGrps - > GrpCods )
2019-11-06 19:45:20 +01:00
free ( LstGrps - > GrpCods ) ;
2017-01-19 20:55:31 +01:00
LstGrps - > GrpCods = NULL ;
2016-12-29 22:19:46 +01:00
LstGrps - > NumGrps = 0 ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Put parameter that indicates all groups selected ****************/
/*****************************************************************************/
void Grp_PutParamAllGroups ( void )
{
Par_PutHiddenParamChar ( " AllGroups " , ' Y ' ) ;
}
/*****************************************************************************/
2017-09-29 15:05:23 +02:00
/************* Parameter to show only my groups or all groups ****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2020-03-27 14:56:54 +01:00
void Grp_PutParamWhichGroups ( void * WhichGrps )
2014-12-01 23:55:08 +01:00
{
2020-03-26 02:54:30 +01:00
if ( WhichGrps )
2020-04-08 18:18:46 +02:00
if ( * ( ( Grp_WhichGroups_t * ) WhichGrps ) ! = Grp_WHICH_GROUPS_DEFAULT )
2020-03-26 02:54:30 +01:00
Par_PutHiddenParamUnsigned ( NULL , " WhichGrps " ,
2020-04-08 18:18:46 +02:00
( unsigned ) * ( ( Grp_WhichGroups_t * ) WhichGrps ) ) ;
2014-12-01 23:55:08 +01:00
}
2016-12-04 20:12:56 +01:00
void Grp_PutParamWhichGrpsOnlyMyGrps ( void )
{
2019-11-03 13:19:32 +01:00
Par_PutHiddenParamUnsigned ( NULL , " WhichGrps " , ( unsigned ) Grp_MY_GROUPS ) ;
2016-12-04 20:12:56 +01:00
}
void Grp_PutParamWhichGrpsAllGrps ( void )
{
2019-11-03 13:19:32 +01:00
Par_PutHiddenParamUnsigned ( NULL , " WhichGrps " , ( unsigned ) Grp_ALL_GROUPS ) ;
2016-12-04 20:12:56 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-12-05 01:54:03 +01:00
/***** Show form to choice whether to show only my groups or all groups ******/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2020-03-26 02:54:30 +01:00
void Grp_ShowFormToSelWhichGrps ( Act_Action_t Action ,
void ( * FuncParams ) ( void * Args ) , void * Args )
2016-12-04 23:09:28 +01:00
{
2017-03-21 00:57:11 +01:00
extern const char * Txt_GROUP_WHICH_GROUPS [ 2 ] ;
2016-12-04 23:09:28 +01:00
Grp_WhichGroups_t WhichGrps ;
2020-04-08 18:18:46 +02:00
/***** Start setting selector *****/
Set_StartOneSettingSelector ( ) ;
2019-09-29 17:33:39 +02:00
2020-04-08 18:18:46 +02:00
/***** Put icons to select which groups *****/
for ( WhichGrps = Grp_MY_GROUPS ;
WhichGrps < = Grp_ALL_GROUPS ;
WhichGrps + + )
{
HTM_DIV_Begin ( " class= \" %s \" " ,
WhichGrps = = Gbl . Crs . Grps . WhichGrps ? " PREF_ON " :
" PREF_OFF " ) ;
Frm_StartForm ( Action ) ;
Par_PutHiddenParamUnsigned ( NULL , " WhichGrps " , ( unsigned ) WhichGrps ) ;
if ( FuncParams ) // Extra parameters depending on the action
FuncParams ( Args ) ;
Ico_PutSettingIconLink ( WhichGrps = = Grp_MY_GROUPS ? " mysitemap.png " :
" sitemap.svg " ,
Txt_GROUP_WHICH_GROUPS [ WhichGrps ] ) ;
Frm_EndForm ( ) ;
HTM_DIV_End ( ) ;
2020-03-26 02:54:30 +01:00
}
2020-04-08 18:18:46 +02:00
/***** End setting selector *****/
Set_EndOneSettingSelector ( ) ;
2016-12-04 23:09:28 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-12-03 23:13:49 +01:00
/************* Get whether to show only my groups or all groups **************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2020-03-27 14:56:54 +01:00
Grp_WhichGroups_t Grp_GetParamWhichGroups ( void )
2014-12-01 23:55:08 +01:00
{
2017-04-14 00:27:38 +02:00
static bool AlreadyGot = false ;
2017-01-29 12:42:19 +01:00
Grp_WhichGroups_t WhichGroupsDefault ;
2014-12-01 23:55:08 +01:00
2017-04-14 00:27:38 +02:00
if ( ! AlreadyGot )
2014-12-01 23:55:08 +01:00
{
2017-09-29 15:05:23 +02:00
/***** Get which groups (my groups or all groups) *****/
2017-01-29 12:42:19 +01:00
/* Set default */
switch ( Gbl . Action . Act )
{
2019-09-29 17:33:39 +02:00
case ActSeeCrsTT : // Show course timetable
case ActPrnCrsTT : // Print course timetable
case ActChgCrsTT1stDay : // Change first day of week in course timetable
case ActSeeAsg : // List assignments
2019-09-29 18:24:08 +02:00
case ActSeeAllGam : // List games
2019-09-29 17:33:39 +02:00
case ActSeeAllSvy : // List surveys
case ActSeeAtt : // List attendance
/*
If I belong to this course = = > see only my groups
If I don ' t belong to this course = = > see all groups
*/
WhichGroupsDefault = Gbl . Usrs . Me . IBelongToCurrentCrs ? Grp_MY_GROUPS :
Grp_ALL_GROUPS ;
2017-01-29 12:42:19 +01:00
break ;
2019-09-29 17:33:39 +02:00
case ActSeeMyTT : // Show my timetable
case ActPrnMyTT : // Print my timetable
case ActChgMyTT1stDay : // Change first day of week in my timetable
/* By default, show only my groups */
WhichGroupsDefault = Grp_MY_GROUPS ;
2017-01-29 12:42:19 +01:00
break ;
2019-09-29 17:33:39 +02:00
default : // Control never should enter here
2017-01-29 12:42:19 +01:00
WhichGroupsDefault = Grp_WHICH_GROUPS_DEFAULT ;
break ;
}
/* Get parameter */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . WhichGrps = ( Grp_WhichGroups_t )
2019-09-29 17:33:39 +02:00
Par_GetParToUnsignedLong ( " WhichGrps " ,
0 ,
Grp_NUM_WHICH_GROUPS - 1 ,
( unsigned long ) WhichGroupsDefault ) ;
2017-04-14 00:27:38 +02:00
AlreadyGot = true ;
2014-12-01 23:55:08 +01:00
}
2020-03-26 02:54:30 +01:00
return Gbl . Crs . Grps . WhichGrps ;
2014-12-01 23:55:08 +01:00
}