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 .
2022-09-21 10:46:14 +02:00
Copyright ( C ) 1999 - 2022 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"
2021-05-11 18:22:00 +02:00
# include "swad_assignment_database.h"
2021-05-13 12:50:36 +02:00
# include "swad_attendance_database.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"
2021-04-26 15:27:27 +02:00
# include "swad_error.h"
2021-07-20 13:14:12 +02:00
# include "swad_exam_database.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"
2021-06-17 13:55:45 +02:00
# include "swad_group_database.h"
2019-10-23 19:05:05 +02:00
# include "swad_HTML.h"
2021-09-24 21:49:06 +02:00
# include "swad_match_database.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"
2021-10-20 23:34:45 +02:00
# include "swad_survey_database.h"
2021-06-25 20:05:58 +02:00
# include "swad_timetable.h"
2021-11-03 01:03:51 +01:00
# include "swad_timetable_database.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
/*****************************************************************************/
/************* External global variables from others modules *****************/
/*****************************************************************************/
extern struct Globals Gbl ;
/*****************************************************************************/
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
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 ) ;
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 ) ;
2021-06-17 13:55:45 +02:00
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 void Grp_GetDataOfGroupTypeByCod ( struct GroupType * GrpTyp ) ;
2017-03-30 11:20:06 +02:00
static bool Grp_GetMultipleEnrolmentOfAGroupType ( long GrpTypCod ) ;
2021-06-25 20:05:58 +02:00
static void Grp_GetLstCodGrpsUsrBelongs ( long UsrCod , long GrpTypCod ,
2014-12-01 23:55:08 +01:00
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 ) ;
2017-04-28 13:10:46 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_AskConfirmRemGrpTypWithGrps ( unsigned NumGrps ) ;
static void Grp_AskConfirmRemGrp ( void ) ;
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 ) ;
2020-10-13 22:34:31 +02:00
static void Grp_PutParamGrpTypCod ( void * GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/******************* 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
{
2021-07-08 15:00:17 +02:00
/***** Begin 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
{
2021-06-17 13:26:25 +02:00
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ALL_GROUP_TYPES ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** Show optional alert *****/
if ( AlertTextGroupTypes )
if ( AlertTextGroupTypes [ 0 ] )
Ale_ShowAlert ( AlertTypeGroupTypes , AlertTextGroupTypes ) ;
2017-04-28 18:03:30 +02:00
2021-06-17 13:26:25 +02:00
/***** Put form to edit group types *****/
Grp_EditGroupTypes ( ) ;
2014-12-01 23:55:08 +01:00
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
2021-07-08 15:00:17 +02:00
/***** Begin 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
2021-06-17 13:26:25 +02:00
/***** Reset rooms context *****/
Roo_ResetRooms ( & Rooms ) ;
2020-04-14 11:08:23 +02:00
2021-06-17 13:26:25 +02:00
/***** Show optional alert *****/
if ( AlertTextGroups )
if ( AlertTextGroups [ 0 ] )
Ale_ShowAlert ( AlertTypeGroups , AlertTextGroups ) ;
2017-04-29 02:20:34 +02:00
2021-06-17 13:26:25 +02:00
/***** Get list of rooms in this center *****/
Roo_GetListRooms ( & Rooms , Roo_ONLY_SHRT_NAME ) ;
2020-04-14 11:08:23 +02:00
2021-06-17 13:26:25 +02:00
/***** Put form to edit groups *****/
2021-06-28 12:54:09 +02:00
if ( Gbl . Crs . Grps . GrpTypes . NumGrpTypes ) // If there are group types...
2021-06-17 13:26:25 +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
2021-03-07 21:21:04 +01:00
/***** Free list of rooms in this center *****/
2020-04-14 17:15:17 +02:00
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
2021-06-17 13:26:25 +02:00
/***** Put a form to create a new group type *****/
Grp_PutFormToCreateGroupType ( ) ;
2017-05-11 14:47:48 +02:00
2021-06-17 13:26:25 +02:00
/***** Forms to edit current group types *****/
2021-06-28 12:54:09 +02:00
if ( Gbl . Crs . Grps . GrpTypes . NumGrpTypes ) // Group types found...
2021-06-17 13:26:25 +02:00
Grp_ListGroupTypesForEdition ( ) ;
else // No group types found in this course
Ale_ShowAlert ( Ale_INFO , Txt_There_are_no_types_of_group_in_the_course_X ,
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
2021-06-17 13:26:25 +02:00
/***** Put a form to create a new group *****/
Grp_PutFormToCreateGroup ( Rooms ) ;
2017-05-11 14:47:48 +02:00
2021-06-17 13:26:25 +02:00
/***** Forms to edit current groups *****/
if ( Gbl . Crs . Grps . GrpTypes . NumGrpsTotal ) // If there are groups...
Grp_ListGroupsForEdition ( Rooms ) ;
else // There are group types, but there aren't groups
Ale_ShowAlert ( Ale_INFO , Txt_No_groups_have_been_created_in_the_course_X ,
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 )
{
2022-06-29 18:04:45 +02:00
Ico_PutContextualIconToAdd ( ActReqEdiGrp , Grp_NEW_GROUP_SECTION_ID , NULL , NULL ) ;
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 ;
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 * * * * */
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( Gbl . Action . Act , // Repeat current action
2019-04-11 14:45:31 +02:00
Usr_USER_LIST_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Set_PutParamsPrefsAboutUsrList ( ) ;
if ( FuncParams )
FuncParams ( Args ) ;
2016-11-25 03:21:02 +01:00
2021-12-01 01:43:13 +01:00
/***** Select all groups *****/
Grp_PutCheckboxAllGrps ( GroupsSelectableByStdsOrNETs ) ;
2016-11-25 03:21:02 +01:00
2021-12-01 01:43:13 +01: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
2021-12-01 01:43:13 +01:00
/***** List the groups for each group type *****/
HTM_TABLE_BeginWidePadding ( 2 ) ;
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
NumGrpTyp + + )
if ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps )
Grp_ListGrpsForMultipleSelection ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ,
GroupsSelectableByStdsOrNETs ) ;
HTM_TABLE_End ( ) ;
2016-11-25 03:21:02 +01:00
2021-12-01 01:43:13 +01:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
2016-11-25 03:21:02 +01:00
2021-12-01 01:43:13 +01:00
/***** Submit button *****/
2021-12-29 17:26:48 +01:00
HTM_DIV_Begin ( " class= \" UPD \" " ) ;
2022-04-01 01:06:44 +02:00
HTM_BUTTON_Submit_Begin ( Txt_Update_users ,
" class= \" BT_LINK FORM_IN_%s BOLD \" %s " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ,
2022-04-01 01:06:44 +02:00
Gbl . Action . Act = = ActReqMsgUsr ? " onsubmit= \" CopyMessageToHiddenFields(); \" " :
" " ) ;
2021-12-29 17:26:48 +01:00
Ico_PutIconTextLink ( " recycle.svg " , Ico_BLACK , Txt_Update_users ) ;
2021-12-01 01:43:13 +01:00
HTM_BUTTON_End ( ) ;
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
{
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 \" " ) ;
2022-04-05 01:00:24 +02:00
HTM_LABEL_Begin ( " class= \" FORM_IN_%s \" " , The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_INPUT_CHECKBOX ( " AllGroups " , HTM_DONT_SUBMIT_ON_CHANGE ,
" value= \" Y \" %s " ,
ICanSelUnselGroup ? ( Gbl . Usrs . ClassPhoto . AllGroups ? " checked= \" checked \" "
" onclick= \" togglecheckChildren(this,'GrpCods') \" " :
" onclick= \" togglecheckChildren(this,'GrpCods') \" " ) :
" disabled= \" disabled \" " ) ;
HTM_TxtF ( " %s " , Txt_All_groups ) ;
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
2021-10-30 13:28:48 +02:00
/***** Write the boolean parameter that indicates if all groups must be listed *****/
2014-12-01 23:55:08 +01:00
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 ;
2021-02-15 16:25:55 +01:00
if ( ( GrpCods = malloc ( MaxLengthGrpCods + 1 ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_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 ) ;
2021-02-15 16:25:55 +01:00
snprintf ( GrpCod , sizeof ( GrpCod ) , " %ld " ,
2019-11-03 13:19:32 +01:00
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 */
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Usrs . Me . UsrDat . UsrCod , - 1L ,
& 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 */
2021-02-15 16:25:55 +01:00
if ( ( Gbl . Crs . Grps . LstGrpsSel . GrpCods = calloc ( LstGrpsIBelong . NumGrps ,
sizeof ( * Gbl . Crs . Grps . LstGrpsSel . GrpCods ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_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 *****/
2021-02-15 16:25:55 +01:00
if ( ( ParamLstCodGrps = malloc ( MaxSizeLstGrpCods + 1 ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_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 *****/
2021-02-15 16:25:55 +01:00
if ( ( Gbl . Crs . Grps . LstGrpsSel . GrpCods = calloc ( Gbl . Crs . Grps . LstGrpsSel . NumGrps ,
sizeof ( * Gbl . Crs . Grps . LstGrpsSel . GrpCods ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_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 * * * * */
2021-04-24 15:10:07 +02:00
SelectionIsValid = Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs ,
& 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 *****/
2021-06-17 13:26:25 +02:00
Grp_DB_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 *****/
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Usrs . Me . UsrDat . UsrCod , - 1L ,
& LstGrpsIBelong ) ;
2014-12-01 23:55:08 +01:00
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 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes & &
! 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 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes & &
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 )
2021-06-17 19:39:08 +02:00
Grp_DB_AddUsrToGrp ( Gbl . Usrs . Me . UsrDat . UsrCod ,
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 *****/
2022-07-15 18:15:40 +02:00
DB_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 *****/
2021-04-24 15:10:07 +02:00
if ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs = = Rol_STD )
2021-06-17 13:26:25 +02:00
Grp_DB_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 *****/
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Usrs . Other . UsrDat . UsrCod , - 1L ,
& LstGrpsUsrBelongs ) ;
2014-12-01 23:55:08 +01:00
/***** 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 )
2021-06-17 19:39:08 +02:00
Grp_DB_AddUsrToGrp ( Gbl . Usrs . Other . UsrDat . UsrCod ,
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 *****/
2021-04-24 15:10:07 +02:00
if ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs = = Rol_STD )
2022-07-15 18:15:40 +02:00
DB_UnlockTables ( ) ;
2014-12-01 23:55:08 +01:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
}
/*****************************************************************************/
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 + + )
{
2021-06-17 19:39:08 +02:00
GrpTypCod = Grp_DB_GetGrpTypeFromGrp ( LstGrps - > GrpCods [ NumCodGrp ] ) ;
2017-06-20 01:58:16 +02:00
MultipleEnrolment = Grp_GetMultipleEnrolmentOfAGroupType ( GrpTypCod ) ;
if ( ! MultipleEnrolment )
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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 *****/
2021-06-28 12:54:09 +02:00
if ( ( * AlreadyExistsGroupOfType = calloc ( Gbl . Crs . Grps . GrpTypes . NumGrpTypes ,
2021-02-15 16:25:55 +01:00
sizeof ( * * AlreadyExistsGroupOfType ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Initialize the list *****/
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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 *******************/
/*****************************************************************************/
2022-09-24 18:30:26 +02:00
void Grp_RegisterUsrIntoGroups ( struct Usr_Data * UsrDat , struct ListCodGrps * LstGrps )
2014-12-01 23:55:08 +01:00
{
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 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( UsrDat - > UsrCod , Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ,
& LstGrpsHeBelongs ) ;
2014-12-01 23:55:08 +01:00
/***** 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
{
2021-06-17 19:39:08 +02:00
Grp_DB_AddUsrToGrp ( UsrDat - > UsrCod ,
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
2022-09-24 18:30:26 +02:00
unsigned Grp_RemoveUsrFromGroups ( struct Usr_Data * UsrDat , struct ListCodGrps * LstGrps )
2014-12-01 23:55:08 +01:00
{
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 *****/
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( UsrDat - > UsrCod , - 1L ,
& LstGrpsHeBelongs ) ;
2014-12-01 23:55:08 +01:00
/***** 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 ;
}
/*****************************************************************************/
2021-10-30 13:28:48 +02:00
/***************** Remove a user of all groups of a course *******************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
void Grp_RemUsrFromAllGrpsInCrs ( long UsrCod , long CrsCod )
2014-12-01 23:55:08 +01:00
{
2021-06-17 19:39:08 +02:00
/***** Remove user from all groups in the given course *****/
Grp_DB_RemUsrFromAllGrpsInCrs ( UsrCod , CrsCod ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
2021-06-17 19:39:08 +02:00
if ( Usr_ItsMe ( UsrCod ) )
2017-06-20 14:43:26 +02:00
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2021-10-30 13:28:48 +02:00
/********* Remove a user from all groups of all the user's courses ***********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
void Grp_RemUsrFromAllGrps ( long UsrCod )
2014-12-01 23:55:08 +01:00
{
/***** Remove user from all groups *****/
2021-06-17 19:39:08 +02:00
Grp_DB_RemUsrFromAllGrps ( UsrCod ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
2021-06-17 19:39:08 +02:00
if ( Usr_ItsMe ( UsrCod ) )
2017-06-20 14:43:26 +02:00
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Remove a user from a group ************************/
/*****************************************************************************/
static void Grp_RemoveUsrFromGroup ( long UsrCod , long GrpCod )
{
/***** Remove user from group *****/
2021-06-18 18:39:21 +02:00
Grp_DB_RemoveUsrFromGrp ( UsrCod , GrpCod ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
2021-11-18 22:06:06 +01:00
if ( Usr_ItsMe ( UsrCod ) )
2017-06-20 14:43:26 +02:00
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** List current group types for edition *******************/
/*****************************************************************************/
static void Grp_ListGroupTypesForEdition ( void )
{
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
2021-06-17 13:26:25 +02:00
/***** Begin table *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_BeginWidePadding ( 2 ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** Write heading *****/
Grp_WriteHeadingGroupTypes ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** List group types with forms for edition *****/
for ( NumGrpTyp = 0 , UniqueId = 1 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
2021-06-17 13:26:25 +02:00
NumGrpTyp + + , UniqueId + + )
{
HTM_TR_Begin ( NULL ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/* Put icon to remove group type */
HTM_TD_Begin ( " class= \" BM \" " ) ;
Ico_PutContextualIconToRemove ( ActReqRemGrpTyp , Grp_GROUP_TYPES_SECTION_ID ,
Grp_PutParamGrpTypCod , & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/* Name of group type */
HTM_TD_Begin ( " class= \" LM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActRenGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpTypCod ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2021-06-17 13:26:25 +02:00
HTM_INPUT_TEXT ( " GrpTypName " , Grp_MAX_CHARS_GROUP_TYPE_NAME ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ,
HTM_SUBMIT_ON_CHANGE ,
2022-03-30 00:46:18 +02:00
" size= \" 12 \" class= \" INPUT_%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2021-06-17 13:26:25 +02:00
/* Is it mandatory to register in any group? */
HTM_TD_Begin ( " class= \" CM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActChgMdtGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpTypCod ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2021-06-17 13:26:25 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
" name= \" MandatoryEnrolment \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:150px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02: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 ) ;
HTM_SELECT_End ( ) ;
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2021-06-17 13:26:25 +02:00
/* Is it possible to register in multiple groups? */
HTM_TD_Begin ( " class= \" CM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActChgMulGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpTypCod ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2021-06-17 13:26:25 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
" name= \" MultipleEnrolment \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:150px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02: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 ) ;
HTM_SELECT_End ( ) ;
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2021-06-17 13:26:25 +02:00
/* Open time */
HTM_TD_Begin ( " class= \" LM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActChgTimGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpTypCod ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2021-06-17 13:26:25 +02:00
HTM_TABLE_BeginCenterPadding ( 2 ) ;
HTM_TR_Begin ( NULL ) ;
HTM_TD_Begin ( " class= \" LM \" style= \" width:16px; \" " ) ;
2021-12-22 18:54:43 +01:00
if ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened )
Ico_PutIconOn ( " clock.svg " , Ico_BLACK ,
Txt_The_groups_will_automatically_open ) ;
else
Ico_PutIconOff ( " clock.svg " , Ico_BLACK ,
Txt_The_groups_will_not_automatically_open ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
HTM_TD_Begin ( " class= \" LM \" " ) ;
snprintf ( Id , sizeof ( Id ) , " open_time_%u " , UniqueId ) ;
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( Id ,
" Open " ,
Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . OpenTimeUTC ,
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
Dat_FORM_SECONDS_ON ,
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
true ) ; // Submit on change
HTM_TD_End ( ) ;
HTM_TR_End ( ) ;
HTM_TABLE_End ( ) ;
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/* Number of groups of this type */
2022-04-05 01:00:24 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s \" " , The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_Unsigned ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ;
HTM_TD_End ( ) ;
2019-10-07 15:15:55 +02:00
2021-06-17 13:26:25 +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 )
{
2022-07-19 14:08:49 +02:00
Ico_PutContextualIconToView ( ActReqSelGrp , NULL ,
2020-03-26 02:54:30 +01:00
NULL , NULL ) ;
2017-04-29 19:19:55 +02:00
}
static void Grp_PutIconToCreateNewGroupType ( void )
{
2020-03-26 02:54:30 +01:00
Ico_PutContextualIconToAdd ( ActReqEdiGrp , Grp_NEW_GROUP_TYPE_SECTION_ID ,
2022-06-29 18:04:45 +02:00
NULL , NULL ) ;
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
2022-01-02 15:17:30 +01:00
HTM_TH_Span ( NULL , HTM_HEAD_CENTER , 1 , 1 , " BT " ) ;
HTM_TH_Begin ( HTM_HEAD_CENTER ) ;
2021-06-17 13:26:25 +02:00
HTM_Txt ( Txt_Type_of_group ) ;
HTM_BR ( ) ;
HTM_TxtF ( " (%s) " , Txt_eg_Lectures_Practicals ) ;
HTM_TH_End ( ) ;
2022-01-02 15:17:30 +01:00
HTM_TH ( Txt_Mandatory_enrolment , HTM_HEAD_CENTER ) ;
HTM_TH ( Txt_Multiple_enrolment , HTM_HEAD_CENTER ) ;
HTM_TH ( Txt_Opening_of_groups , HTM_HEAD_CENTER ) ;
HTM_TH ( Txt_Number_of_BR_groups , HTM_HEAD_CENTER ) ;
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
{
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
2021-06-17 13:26:25 +02:00
/***** Begin table *****/
2019-10-23 19:05:05 +02:00
HTM_TABLE_BeginWidePadding ( 2 ) ;
2019-01-04 22:46:46 +01:00
2021-06-17 13:26:25 +02:00
/***** Write heading *****/
Grp_WriteHeadingGroups ( ) ;
2019-01-04 22:46:46 +01:00
2021-06-17 13:26:25 +02:00
/***** List the groups *****/
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
2021-06-17 13:26:25 +02:00
NumGrpTyp + + )
{
GrpTyp = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
HTM_TR_Begin ( NULL ) ;
/***** Icon to remove group *****/
HTM_TD_Begin ( " class= \" BM \" " ) ;
Ico_PutContextualIconToRemove ( ActReqRemGrp , Grp_GROUPS_SECTION_ID ,
Grp_PutParamGrpCod , & Grp - > GrpCod ) ;
HTM_TD_End ( ) ;
/***** Icon to open/close group *****/
HTM_TD_Begin ( " class= \" BM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( Grp - > Open ? ActCloGrp :
2021-06-17 13:26:25 +02:00
ActOpeGrp ,
Grp_GROUPS_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpCod ( & Grp - > GrpCod ) ;
2021-12-30 11:50:29 +01:00
Ico_PutIconLink ( Grp - > Open ? " unlock.svg " :
" lock.svg " ,
Grp - > Open ? Ico_GREEN :
Ico_RED ,
2022-06-30 13:39:57 +02:00
Grp - > Open ? ActCloGrp :
ActOpeGrp ) ;
2021-06-17 13:26:25 +02:00
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
/***** Icon to activate file zones for this group *****/
HTM_TD_Begin ( " class= \" BM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( Grp - > FileZones ? ActDisFilZonGrp :
2021-06-17 13:26:25 +02:00
ActEnaFilZonGrp ,
Grp_GROUPS_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpCod ( & Grp - > GrpCod ) ;
2021-12-30 11:50:29 +01:00
Ico_PutIconLink ( Grp - > FileZones ? " folder-open.svg " :
" folder.svg " ,
Grp - > FileZones ? Ico_GREEN :
Ico_RED ,
2022-06-30 13:39:57 +02:00
Grp - > FileZones ? ActDisFilZonGrp :
ActEnaFilZonGrp ) ;
2021-06-17 13:26:25 +02:00
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
/***** Group type *****/
2021-07-08 15:00:17 +02:00
/* Begin selector */
2021-06-17 13:26:25 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActChgGrpTyp , Grp_GROUPS_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpCod ( & Grp - > GrpCod ) ;
2021-06-17 13:26:25 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
2021-12-18 00:57:27 +01:00
" name= \" GrpTypCod \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:100px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
/* Options for group types */
for ( NumTipGrpAux = 0 ;
2021-06-28 12:54:09 +02:00
NumTipGrpAux < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
2021-06-17 13:26:25 +02:00
NumTipGrpAux + + )
{
GrpTypAux = & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumTipGrpAux ] ;
HTM_OPTION ( HTM_Type_LONG , & GrpTypAux - > GrpTypCod ,
GrpTypAux - > GrpTypCod = = GrpTyp - > GrpTypCod , false ,
" %s " , GrpTypAux - > GrpTypName ) ;
}
/* End selector */
HTM_SELECT_End ( ) ;
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
/***** Group name *****/
HTM_TD_Begin ( " class= \" CM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActRenGrp , Grp_GROUPS_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpCod ( & Grp - > GrpCod ) ;
2021-06-17 13:26:25 +02:00
HTM_INPUT_TEXT ( " GrpName " , Grp_MAX_CHARS_GROUP_NAME , Grp - > GrpName ,
HTM_SUBMIT_ON_CHANGE ,
2022-03-30 00:46:18 +02:00
" size= \" 20 \" class= \" INPUT_%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
/***** Room *****/
2021-07-08 15:00:17 +02:00
/* Begin selector */
2021-06-17 13:26:25 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActChgGrpRoo , Grp_GROUPS_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpCod ( & Grp - > GrpCod ) ;
2021-06-17 13:26:25 +02:00
HTM_SELECT_Begin ( HTM_SUBMIT_ON_CHANGE ,
2021-12-18 00:57:27 +01:00
" name= \" RooCod \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:100px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
/* Option for no assigned room */
HTM_OPTION ( HTM_Type_STRING , " -1 " ,
Grp - > Room . RooCod < 0 , false ,
" %s " , Txt_No_assigned_room ) ;
/* Option for another room */
HTM_OPTION ( HTM_Type_STRING , " 0 " ,
Grp - > Room . RooCod = = 0 , false ,
" %s " , Txt_Another_room ) ;
/* Options for rooms */
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 ) ;
/* End selector */
HTM_SELECT_End ( ) ;
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
/***** Current number of users in this group *****/
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
{
2022-04-05 01:00:24 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s \" " , The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_Int ( Grp - > NumUsrs [ Role ] ) ;
HTM_TD_End ( ) ;
}
2017-05-30 21:43:05 +02:00
2021-06-17 13:26:25 +02:00
/***** Maximum number of students of the group (row[3]) *****/
HTM_TD_Begin ( " class= \" CM \" " ) ;
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActChgMaxStdGrp , Grp_GROUPS_SECTION_ID ) ;
2021-12-01 01:43:13 +01:00
Grp_PutParamGrpCod ( & Grp - > GrpCod ) ;
2021-06-17 13:26:25 +02:00
Grp_WriteMaxStds ( StrMaxStudents , Grp - > MaxStudents ) ;
HTM_INPUT_TEXT ( " MaxStudents " , Cns_MAX_DECIMAL_DIGITS_UINT , StrMaxStudents ,
HTM_SUBMIT_ON_CHANGE ,
2022-03-30 00:46:18 +02:00
" size= \" 3 \" class= \" INPUT_%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
Frm_EndForm ( ) ;
HTM_TD_End ( ) ;
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
2022-01-02 15:17:30 +01:00
HTM_TH_Span ( NULL , HTM_HEAD_CENTER , 1 , 1 , " BT " ) ;
HTM_TH_Span ( NULL , HTM_HEAD_CENTER , 1 , 1 , " BT " ) ;
HTM_TH_Span ( NULL , HTM_HEAD_CENTER , 1 , 1 , " BT " ) ;
HTM_TH ( Txt_Type_BR_of_group , HTM_HEAD_CENTER ) ;
HTM_TH_Begin ( HTM_HEAD_CENTER ) ;
2021-06-17 13:26:25 +02:00
HTM_Txt ( Txt_Group_name ) ;
HTM_BR ( ) ;
HTM_TxtF ( " (%s) " , Txt_eg_A_B ) ;
HTM_TH_End ( ) ;
2022-01-02 15:17:30 +01:00
HTM_TH ( Txt_Room , HTM_HEAD_CENTER ) ;
2021-12-20 22:43:32 +01:00
for ( Role = Rol_TCH ;
2021-06-17 13:26:25 +02:00
Role > = Rol_STD ;
Role - - )
2022-01-02 15:17:30 +01:00
HTM_TH ( Txt_ROLES_PLURAL_BRIEF_Abc [ Role ] , HTM_HEAD_CENTER ) ;
HTM_TH ( Txt_Max_BR_students , HTM_HEAD_CENTER ) ;
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-11-25 01:50:13 +01:00
void Grp_ListGrpsToEditAsgAttSvyEvtMch ( struct GroupType * GrpTyp ,
Grp_WhichIsAssociatedToGrp_t WhichIsAssociatedToGrp ,
long Cod ) // Assignment, attendance event, survey, exam event or match
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 ] =
{
2021-03-20 14:56:50 +01:00
[ Grp_ASSIGNMENT ] = { " asg_groups " , " AsgCod " } ,
[ Grp_ATT_EVENT ] = { " att_groups " , " AttCod " } ,
2021-03-20 15:06:07 +01:00
[ Grp_SURVEY ] = { " svy_groups " , " SvyCod " } ,
2020-05-17 02:28:30 +02:00
[ Grp_EXA_EVENT ] = { " exa_groups " , " SesCod " } ,
2020-05-06 01:43:48 +02:00
[ 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 *****/
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Usrs . Me . UsrDat . UsrCod , GrpTyp - > GrpTypCod ,
& LstGrpsIBelong ) ;
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 ) ;
2020-05-06 01:43:48 +02:00
if ( Cod > 0 ) // Cod == -1L means new item, assignment, event, survey, exam event or match
2021-06-17 13:26:25 +02:00
AssociatedToGrp = Grp_DB_CheckIfAssociatedToGrp ( AssociationsToGrps [ WhichIsAssociatedToGrp ] . Table ,
AssociationsToGrps [ WhichIsAssociatedToGrp ] . Field ,
Cod , Grp - > GrpCod ) ;
2020-05-06 01:43:48 +02:00
else
AssociatedToGrp = false ;
2019-11-04 20:41:35 +01:00
/* Put checkbox to select the group */
HTM_TR_Begin ( NULL ) ;
2021-12-29 20:43:07 +01:00
HTM_TD_Begin ( IBelongToThisGroup ? " class= \" LM BG_HIGHLIGHT \" " :
" class= \" LM \" " ) ;
HTM_INPUT_CHECKBOX ( " GrpCods " , HTM_DONT_SUBMIT_ON_CHANGE ,
" 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 \" " ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
2014-12-01 23:55:08 +01:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free memory with the list of groups which I belongs to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
}
/*****************************************************************************/
/***************** 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 )
2021-03-02 00:54:26 +01:00
Frm_BeginForm ( 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 ) ;
2021-06-17 13:26:25 +02:00
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
2021-06-17 13:26:25 +02:00
NumGrpTyp + + )
if ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) // If there are groups of this type
{
ICanChangeMyGrps | = Grp_ListGrpsForChangeMySelection ( & Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ,
& NumGrpsThisTypeIBelong ) ;
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 )
{
2021-12-01 01:43:13 +01:00
if ( ICanChangeMyGrps )
Btn_PutConfirmButton ( NumGrpsIBelong ? Txt_Change_my_groups :
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 )
{
2021-03-02 00:54:26 +01:00
Frm_BeginForm ( ActReqEdiGrp ) ;
2021-06-17 13:26:25 +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 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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
2021-06-25 20:05:58 +02:00
if ( ! Grp_DB_CheckIfIBelongToGrpsOfType ( GrpTyp - > GrpTypCod ) ) // Fast check (not necesary, but avoid slow check)
2019-02-18 14:41:46 +01:00
// If there is any group of this type available
2021-06-25 20:05:58 +02:00
if ( Grp_DB_CheckIfAvailableGrpTyp ( 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 *****/
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Usrs . Me . UsrDat . UsrCod , GrpTyp - > GrpTypCod ,
& 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 ) ;
2021-12-29 20:43:07 +01:00
HTM_TD_Begin ( IBelongToThisGroup ? " class= \" LM BG_HIGHLIGHT \" " :
" class= \" LM \" " ) ;
2019-11-04 20:41:35 +01:00
2021-12-29 20:43:07 +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 */
HTM_INPUT_CHECKBOX ( StrGrpCod , HTM_DONT_SUBMIT_ON_CHANGE ,
" 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
2021-06-18 18:39:21 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-18 18:39:21 +02:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
2014-12-01 23:55:08 +01:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free 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
2021-06-17 13:26:25 +02:00
/***** List to select the groups the user belongs to *****/
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
2021-06-17 13:26:25 +02:00
NumGrpTyp + + )
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 )
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Usrs . Other . UsrDat . UsrCod , GrpTyp - > GrpTypCod ,
& LstGrpsUsrBelongs ) ;
2014-12-01 23:55:08 +01:00
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
UsrBelongsToThisGroup = ( UsrCod > 0 ) ? Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsUsrBelongs ) :
false ;
2021-07-08 15:00:17 +02:00
/* Begin row */
2019-10-23 19:05:05 +02:00
HTM_TR_Begin ( NULL ) ;
2019-03-09 22:01:06 +01:00
2021-07-08 15:00:17 +02:00
/* Begin cell for checkbox */
2021-12-29 20:43:07 +01:00
HTM_TD_Begin ( UsrBelongsToThisGroup ? " class= \" LM BG_HIGHLIGHT \" " :
" class= \" LM \" " ) ;
2021-12-15 14:02:49 +01:00
2021-12-29 20:43:07 +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
snprintf ( StrGrpCod , sizeof ( StrGrpCod ) , " GrpCod%ld " , GrpTyp - > GrpTypCod ) ;
HTM_INPUT_CHECKBOX ( StrGrpCod , HTM_DONT_SUBMIT_ON_CHANGE ,
" id= \" Grp%ld \" value= \" %ld \" %s " ,
Grp - > GrpCod , Grp - > GrpCod ,
UsrBelongsToThisGroup ? " checked= \" checked \" " :
" " ) ; // I can not register
2019-03-09 22:01:06 +01:00
2021-06-17 13:26:25 +02:00
/* End cell for checkbox */
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/* Write cell for group */
Grp_WriteRowGrp ( Grp , UsrBelongsToThisGroup ) ;
2014-12-01 23:55:08 +01:00
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 *****/
2021-06-25 20:05:58 +02:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . Usrs . Me . UsrDat . UsrCod , GrpTyp - > GrpTypCod ,
& LstGrpsIBelong ) ;
2014-12-01 23:55:08 +01:00
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 ) ;
2021-12-29 20:43:07 +01:00
HTM_TD_Begin ( IBelongToThisGroup ? " class= \" LM BG_HIGHLIGHT \" " :
" class= \" LM \" " ) ;
HTM_INPUT_CHECKBOX ( " GrpCods " , HTM_DONT_SUBMIT_ON_CHANGE ,
" id= \" Grp%ld \" value= \" %ld \" %s%s " ,
Grp - > GrpCod , Grp - > GrpCod ,
Checked ? " checked= \" checked \" " :
" " ,
ICanSelUnselGroup ? " onclick= \" checkParent(this,'AllGroups') \" " :
" disabled= \" disabled \" " ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
2014-12-01 23:55:08 +01:00
2019-10-23 19:05:05 +02:00
HTM_TR_End ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free 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 ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_Begin ( " class= \" LM \" " ) ;
HTM_INPUT_CHECKBOX ( " GrpCods " , HTM_DONT_SUBMIT_ON_CHANGE ,
" id= \" Grp%ld \" value= \" %ld \" %s "
" onclick= \" checkParent(this,'AllGroups') \" " ,
- GrpTyp - > GrpTypCod , - GrpTyp - > GrpTypCod ,
2021-06-24 20:32:25 +02:00
ICanSelUnselGroup ? ( Checked ? " checked= \" checked \" " :
" " ) :
" disabled= \" disabled \" " ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/* Column closed/open */
HTM_TD_Begin ( " class= \" LM \" " ) ;
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/* Group name = students with no group */
2022-04-05 01:00:24 +02:00
HTM_TD_Begin ( " class= \" LM DAT_%s \" " , The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_LABEL_Begin ( " for= \" Grp%ld \" " , - GrpTyp - > GrpTypCod ) ;
HTM_Txt ( Txt_users_with_no_group ) ;
HTM_LABEL_End ( ) ;
HTM_TD_End ( ) ;
2019-01-04 23:15:00 +01:00
2021-06-17 13:26:25 +02:00
/* Room */
2022-04-05 01:00:24 +02:00
HTM_TD_Begin ( " class= \" LM DAT_%s \" " , The_GetSuffix ( ) ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/* Number of students who don't belong to any group of this type */
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
{
2022-04-05 01:00:24 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s \" " , The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_Unsigned ( Grp_DB_CountNumUsrsInNoGrpsOfType ( Role , GrpTyp - > GrpTypCod ) ) ;
HTM_TD_End ( ) ;
}
/* Last empty columns for max. students and vacants */
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 ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_Begin ( " colspan= \" 9 \" class= \" GRP_TITLE LM \" " ) ;
HTM_BR ( ) ;
HTM_Txt ( GrpTyp - > GrpTypName ) ;
if ( GrpTyp - > MustBeOpened )
{
UniqueId + + ;
if ( asprintf ( & Id , " open_time_%u " , UniqueId ) < 0 )
Err_NotEnoughMemoryExit ( ) ;
HTM_BR ( ) ;
HTM_TxtColonNBSP ( Txt_Opening_of_groups ) ;
HTM_SPAN_Begin ( " id= \" %s \" " , Id ) ;
HTM_SPAN_End ( ) ;
Dat_WriteLocalDateHMSFromUTC ( Id , GrpTyp - > OpenTimeUTC ,
Gbl . Prefs . DateFormat , Dat_SEPARATOR_COMMA ,
true , true , true , 0x7 ) ;
free ( Id ) ;
}
HTM_TD_End ( ) ;
2019-10-23 19:05:05 +02:00
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
2021-06-17 13:26:25 +02:00
HTM_TH_Empty ( 2 ) ;
2022-01-02 15:17:30 +01:00
HTM_TH ( Txt_Group , HTM_HEAD_LEFT ) ;
HTM_TH ( Txt_Room , HTM_HEAD_LEFT ) ;
2021-12-20 22:43:32 +01:00
for ( Role = Rol_TCH ;
2021-06-17 13:26:25 +02:00
Role > = Rol_STD ;
Role - - )
2022-01-02 15:17:30 +01:00
HTM_TH ( Txt_ROLES_PLURAL_BRIEF_Abc [ Role ] , HTM_HEAD_CENTER ) ;
HTM_TH ( Txt_Max_BR_students , HTM_HEAD_CENTER ) ;
HTM_TH ( Txt_Vacants , HTM_HEAD_CENTER ) ;
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 ;
2021-12-30 11:50:29 +01:00
char * Title ;
2014-12-01 23:55:08 +01:00
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 *****/
2021-12-29 20:43:07 +01:00
HTM_TD_Begin ( Highlight ? " class= \" BM BG_HIGHLIGHT \" " :
" class= \" BM \" " ) ;
2021-12-30 11:50:29 +01:00
if ( asprintf ( & Title , Grp - > Open ? Txt_Group_X_open :
Txt_Group_X_closed ,
Grp - > GrpName ) < 0 )
Err_NotEnoughMemoryExit ( ) ;
Ico_PutIconOff ( Grp - > Open ? " unlock.svg " :
" lock.svg " ,
Grp - > Open ? Ico_GREEN :
Ico_RED ,
Title ) ;
free ( Title ) ;
2019-10-23 19:05:05 +02:00
HTM_TD_End ( ) ;
2014-12-01 23:55:08 +01:00
/***** Group name *****/
2021-12-29 20:43:07 +01:00
HTM_TD_Begin ( Highlight ? " class= \" LM BG_HIGHLIGHT \" " :
" class= \" LM \" " ) ;
2022-03-29 00:58:40 +02:00
HTM_LABEL_Begin ( " for= \" Grp%ld \" class= \" DAT_%s \" " ,
2022-04-05 01:00:24 +02:00
Grp - > GrpCod , The_GetSuffix ( ) ) ;
2021-12-29 20:43:07 +01:00
HTM_Txt ( Grp - > GrpName ) ;
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 *****/
2022-03-29 00:58:40 +02:00
HTM_TD_Begin ( " class= \" LM DAT_%s%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ,
2022-03-29 00:58:40 +02:00
Highlight ? " BG_HIGHLIGHT " :
" " ) ;
2021-12-29 20:43:07 +01: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 *****/
2021-12-29 20:43:07 +01:00
for ( Role = Rol_TCH ;
2017-05-30 21:43:05 +02:00
Role > = Rol_STD ;
Role - - )
{
2022-03-29 00:58:40 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ,
2022-03-29 00:58:40 +02:00
Highlight ? " BG_HIGHLIGHT " :
" " ) ;
2021-12-29 20:43:07 +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 *****/
2022-03-29 00:58:40 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ,
2022-03-29 00:58:40 +02:00
Highlight ? " BG_HIGHLIGHT " :
" " ) ;
2021-12-29 20:43:07 +01:00
Grp_WriteMaxStds ( StrMaxStudents , Grp - > MaxStudents ) ;
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 *****/
2022-03-29 00:58:40 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ,
2022-03-29 00:58:40 +02:00
Highlight ? " BG_HIGHLIGHT " :
" " ) ;
2021-12-29 20:43:07 +01:00
if ( Grp - > MaxStudents < = Grp_MAX_STUDENTS_IN_A_GROUP )
{
Vacant = ( int ) Grp - > MaxStudents - ( int ) Grp - > NumUsrs [ Rol_STD ] ;
HTM_Unsigned ( Vacant > 0 ? ( unsigned ) Vacant :
0 ) ;
}
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 ;
2021-06-17 13:26:25 +02:00
/***** Begin section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin ( Grp_NEW_GROUP_TYPE_SECTION_ID ) ;
2019-10-08 23:28:51 +02:00
2021-06-17 13:26:25 +02:00
/***** Begin form *****/
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActNewGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2021-06-17 13:26:25 +02:00
/***** Begin box *****/
Box_BoxTableBegin ( NULL , Txt_New_type_of_group ,
NULL , NULL ,
NULL , Box_NOT_CLOSABLE , 2 ) ;
/***** Write heading *****/
Grp_WriteHeadingGroupTypes ( ) ;
HTM_TR_Begin ( NULL ) ;
/***** Column to remove group type, disabled here *****/
HTM_TD_Begin ( " class= \" BM \" " ) ;
HTM_TD_End ( ) ;
/***** Name of group type *****/
HTM_TD_Begin ( " class= \" LM \" " ) ;
HTM_INPUT_TEXT ( " GrpTypName " , Grp_MAX_CHARS_GROUP_TYPE_NAME ,
Gbl . Crs . Grps . GrpTyp . GrpTypName , HTM_DONT_SUBMIT_ON_CHANGE ,
2022-03-30 00:46:18 +02:00
" size= \" 12 \" class= \" INPUT_%s \" "
2022-03-10 00:32:53 +01:00
" required= \" required \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
/***** Is it mandatory to register in any groups of this type? *****/
HTM_TD_Begin ( " class= \" CM \" " ) ;
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2021-12-18 00:57:27 +01:00
" name= \" MandatoryEnrolment \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:150px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02: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 ) ;
HTM_SELECT_End ( ) ;
HTM_TD_End ( ) ;
/***** Is it possible to register in multiple groups of this type? *****/
HTM_TD_Begin ( " class= \" CM \" " ) ;
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2021-12-18 00:57:27 +01:00
" name= \" MultipleEnrolment \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:150px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02: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 ) ;
HTM_SELECT_End ( ) ;
HTM_TD_End ( ) ;
/***** Open time *****/
HTM_TD_Begin ( " class= \" LM \" " ) ;
HTM_TABLE_BeginPadding ( 2 ) ;
HTM_TR_Begin ( NULL ) ;
HTM_TD_Begin ( " class= \" LM \" style= \" width:20px; \" " ) ;
2021-12-22 18:54:43 +01:00
if ( Gbl . Crs . Grps . GrpTyp . MustBeOpened )
Ico_PutIconOn ( " clock.svg " , Ico_BLACK ,
Txt_The_groups_will_automatically_open ) ;
else
Ico_PutIconOff ( " clock.svg " , Ico_BLACK ,
Txt_The_groups_will_not_automatically_open ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
HTM_TD_Begin ( " class= \" LM \" " ) ;
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( " open_time " ,
" Open " ,
Gbl . Crs . Grps . GrpTyp . OpenTimeUTC ,
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
Dat_FORM_SECONDS_ON ,
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
false ) ; // Don't submit on change
HTM_TD_End ( ) ;
HTM_TR_End ( ) ;
HTM_TABLE_End ( ) ;
HTM_TD_End ( ) ;
/***** Number of groups of this type *****/
2022-03-29 00:58:40 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_Unsigned ( 0 ) ; // It's a new group type ==> 0 groups
HTM_TD_End ( ) ;
HTM_TR_End ( ) ;
/***** End table, send button and end box *****/
Box_BoxTableWithButtonEnd ( Btn_CREATE_BUTTON , Txt_Create_type_of_group ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** End form *****/
Frm_EndForm ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** End section *****/
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
2021-06-17 13:26:25 +02:00
/***** Begin section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin ( Grp_NEW_GROUP_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** Begin form *****/
2021-06-29 15:25:42 +02:00
Frm_BeginFormAnchor ( ActNewGrp , Grp_GROUPS_SECTION_ID ) ;
2021-06-17 13:26:25 +02:00
/***** Begin box and table *****/
Box_BoxTableBegin ( NULL , Txt_New_group ,
NULL , NULL ,
NULL , Box_NOT_CLOSABLE , 2 ) ;
/***** Write heading *****/
Grp_WriteHeadingGroups ( ) ;
HTM_TR_Begin ( NULL ) ;
/***** Empty column to remove *****/
HTM_TD_Begin ( " class= \" BM \" " ) ;
HTM_TD_End ( ) ;
/***** Disabled icon to open group *****/
HTM_TD_Begin ( " class= \" BM \" " ) ;
2021-12-22 00:20:06 +01:00
Ico_PutIconOff ( " lock.svg " , Ico_RED , Txt_Group_closed ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
/***** Disabled icon for archive zone *****/
HTM_TD_Begin ( " class= \" BM \" " ) ;
2021-12-22 00:20:06 +01:00
Ico_PutIconOff ( " folder.svg " , Ico_RED , Txt_File_zones_disabled ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
/***** Group type *****/
2021-07-08 15:00:17 +02:00
/* Begin selector */
2021-06-17 13:26:25 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2021-12-18 00:57:27 +01:00
" name= \" GrpTypCod \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:100px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
/* Options for group types */
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
2021-06-17 13:26:25 +02:00
NumGrpTyp + + )
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 ) ;
/* End selector */
HTM_SELECT_End ( ) ;
HTM_TD_End ( ) ;
/***** Group name *****/
HTM_TD_Begin ( " class= \" CM \" " ) ;
HTM_INPUT_TEXT ( " GrpName " , Grp_MAX_CHARS_GROUP_NAME , Gbl . Crs . Grps . GrpName ,
HTM_DONT_SUBMIT_ON_CHANGE ,
2022-03-30 00:46:18 +02:00
" size= \" 20 \" class= \" INPUT_%s \" "
2022-03-10 00:32:53 +01:00
" required= \" required \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
/***** Room *****/
2021-07-08 15:00:17 +02:00
/* Begin selector */
2021-06-17 13:26:25 +02:00
HTM_TD_Begin ( " class= \" CM \" " ) ;
HTM_SELECT_Begin ( HTM_DONT_SUBMIT_ON_CHANGE ,
2021-12-18 00:57:27 +01:00
" name= \" RooCod \" "
2022-03-30 00:46:18 +02:00
" class= \" INPUT_%s \" style= \" width:100px; \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
/* Option for no assigned room */
HTM_OPTION ( HTM_Type_STRING , " -1 " , Gbl . Crs . Grps . RooCod < 0 , false ,
" %s " , Txt_No_assigned_room ) ;
/* Option for another room */
HTM_OPTION ( HTM_Type_STRING , " 0 " , Gbl . Crs . Grps . RooCod = = 0 , false ,
" %s " , Txt_Another_room ) ;
/* Options for rooms */
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 ) ;
/* End selector */
HTM_SELECT_End ( ) ;
HTM_TD_End ( ) ;
/***** Current number of users in this group *****/
2021-12-15 00:47:29 +01:00
for ( Role = Rol_TCH ;
2021-06-17 13:26:25 +02:00
Role > = Rol_STD ;
Role - - )
{
2022-03-29 00:58:40 +02:00
HTM_TD_Begin ( " class= \" CM DAT_%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_Unsigned ( 0 ) ;
HTM_TD_End ( ) ;
}
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** Maximum number of students *****/
HTM_TD_Begin ( " class= \" CM \" " ) ;
Grp_WriteMaxStds ( StrMaxStudents , Gbl . Crs . Grps . MaxStudents ) ;
HTM_INPUT_TEXT ( " MaxStudents " , Cns_MAX_DECIMAL_DIGITS_UINT , StrMaxStudents ,
HTM_DONT_SUBMIT_ON_CHANGE ,
2022-03-30 00:46:18 +02:00
" size= \" 3 \" class= \" INPUT_%s \" " ,
2022-04-05 01:00:24 +02:00
The_GetSuffix ( ) ) ;
2021-06-17 13:26:25 +02:00
HTM_TD_End ( ) ;
2019-01-04 12:53:40 +01:00
2021-06-17 13:26:25 +02:00
HTM_TR_End ( ) ;
2017-05-30 21:43:05 +02:00
2021-06-17 13:26:25 +02:00
/***** End table, send button and end box *****/
Box_BoxTableWithButtonEnd ( Btn_CREATE_BUTTON , Txt_Create_group ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** End form *****/
Frm_EndForm ( ) ;
2014-12-01 23:55:08 +01:00
2021-06-17 13:26:25 +02:00
/***** End section *****/
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 ***********/
/*****************************************************************************/
2021-11-08 19:16:51 +01:00
void Grp_GetListGrpTypesInCurrentCrs ( Grp_WhichGroupTypes_t WhichGroupTypes )
2014-12-01 23:55:08 +01:00
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2018-10-31 10:19:01 +01:00
unsigned long NumGrpTyp ;
2021-11-08 19:16:51 +01:00
static unsigned ( * Grp_DB_GetGrpTypesInCurrentCrs [ Grp_NUM_WHICH_GROUP_TYPES ] ) ( MYSQL_RES * * mysql_res , long CrsCod ) =
2021-06-18 18:39:21 +02:00
{
2021-11-08 19:16:51 +01:00
[ Grp_ONLY_GROUP_TYPES_WITH_GROUPS ] = Grp_DB_GetGrpTypesWithGrpsInCrs ,
[ Grp_ALL_GROUP_TYPES ] = Grp_DB_GetAllGrpTypesInCrs ,
2021-06-18 18:39:21 +02:00
} ;
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 ( ) ;
2021-06-18 18:39:21 +02:00
/***** Get group types from database *****/
2021-11-08 19:16:51 +01:00
Gbl . Crs . Grps . GrpTypes . NumGrpTypes = Grp_DB_GetGrpTypesInCurrentCrs [ WhichGroupTypes ] ( & mysql_res , Gbl . Hierarchy . Crs . CrsCod ) ;
2014-12-01 23:55:08 +01:00
/***** 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
2021-06-28 12:54:09 +02:00
if ( Gbl . Crs . Grps . GrpTypes . NumGrpTypes )
2014-12-01 23:55:08 +01:00
{
/***** Create a list of group types *****/
2021-06-28 12:54:09 +02:00
if ( ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes = calloc ( Gbl . Crs . Grps . GrpTypes . NumGrpTypes ,
2021-02-15 16:25:55 +01:00
sizeof ( * Gbl . Crs . Grps . GrpTypes . LstGrpTypes ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get group types *****/
2018-10-31 10:19:01 +01:00
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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]) */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
/* 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 ] ,
2021-02-15 16:25:55 +01:00
sizeof ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ) - 1 ) ;
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 )
2021-04-26 15:27:27 +02:00
Err_ShowErrorAndExit ( " Wrong number of groups of a type. " ) ;
2014-12-01 23:55:08 +01:00
/* 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 ;
unsigned NumGrpTypes ;
unsigned NumGrpTyp ;
long GrpTypCod ;
/***** Find group types to be opened *****/
2021-06-18 18:39:21 +02:00
NumGrpTypes = Grp_DB_GetGrpTypesInCurrentCrsToBeOpened ( & mysql_res ) ;
2018-10-31 10:19:01 +01:00
2014-12-01 23:55:08 +01:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < NumGrpTypes ;
NumGrpTyp + + )
{
2021-06-18 18:39:21 +02:00
/* Get next group type */
2021-04-04 20:12:31 +02:00
if ( ( GrpTypCod = DB_GetNextCode ( mysql_res ) ) > 0 )
2014-12-01 23:55:08 +01:00
{
2021-10-30 13:28:48 +02:00
/***** Open all closed groups of this type that are closed ****/
2021-06-18 18:39:21 +02:00
Grp_DB_OpenGrpsOfType ( GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** To not try to open groups again, set MustBeOpened to false *****/
2021-06-18 18:39:21 +02:00
Grp_DB_ClearMustBeOpened ( 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 ;
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 *****/
2021-11-08 19:16:51 +01:00
Grp_GetListGrpTypesInCurrentCrs ( WhichGroupTypes ) ;
2014-12-01 23:55:08 +01:00
/***** Then we get the list of groups for each group type *****/
for ( NumGrpTyp = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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 *****/
2021-06-17 13:55:45 +02:00
GrpTyp - > NumGrps = Grp_DB_GetGrpsOfType ( & mysql_res , GrpTyp - > GrpTypCod ) ;
2021-04-16 13:51:12 +02:00
if ( GrpTyp - > NumGrps > 0 ) // Groups found...
2014-12-01 23:55:08 +01:00
{
/***** Create list with groups of this type *****/
2021-04-16 13:51:12 +02:00
if ( ( GrpTyp - > LstGrps = calloc ( ( size_t ) GrpTyp - > NumGrps ,
2021-02-15 16:25:55 +01:00
sizeof ( * GrpTyp - > LstGrps ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_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]) */
2021-04-25 13:24:39 +02:00
if ( ( Grp - > GrpCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/* Get group name (row[1]) */
2021-02-15 16:25:55 +01:00
Str_Copy ( Grp - > GrpName , row [ 1 ] , sizeof ( Grp - > GrpName ) - 1 ) ;
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 ] ,
2021-02-15 16:25:55 +01:00
sizeof ( Grp - > Room . ShrtName ) - 1 ) ;
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 - - )
2021-06-17 13:26:25 +02:00
Grp - > NumUsrs [ Role ] = Grp_DB_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
2021-06-28 12:54:09 +02:00
/* Get whether group is open ('Y') or closed ('N') (row[5]),
and whether group have file zones ( ' Y ' ) or not ( ' N ' ) ( row [ 6 ] ) */
Grp - > Open = ( row [ 5 ] [ 0 ] = = ' Y ' ) ;
2019-01-05 11:29:54 +01:00
Grp - > FileZones = ( row [ 6 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
}
}
/***** 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 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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 ;
2021-06-28 12:54:09 +02:00
Gbl . Crs . Grps . GrpTypes . NumGrpTypes = 0 ;
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 *****/
2021-06-24 20:32:25 +02:00
if ( Grp_DB_GetDataOfGroupTypeByCod ( & mysql_res , GrpTyp - > GrpTypCod ) ! = 1 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get some data of group type *****/
row = mysql_fetch_row ( mysql_res ) ;
2021-02-15 16:25:55 +01:00
Str_Copy ( GrpTyp - > GrpTypName , row [ 0 ] , sizeof ( GrpTyp - > GrpTypName ) - 1 ) ;
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 ' ) ;
2021-06-17 13:26:25 +02: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 *****/
2021-06-24 20:32:25 +02:00
if ( Grp_DB_GetMultipleEnrolmentOfAGroupType ( & mysql_res , GrpTypCod ) ! = 1 )
2021-04-26 15:27:27 +02:00
Err_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 ;
2016-12-28 02:40:15 +01:00
/***** Reset values *****/
2021-06-28 12:54:09 +02:00
GrpDat - > GrpTypCod = - 1L ;
GrpDat - > CrsCod = - 1L ;
GrpDat - > GrpTypName [ 0 ] = ' \0 ' ;
GrpDat - > GrpName [ 0 ] = ' \0 ' ;
GrpDat - > Room . RooCod = - 1L ;
GrpDat - > Room . ShrtName [ 0 ] = ' \0 ' ;
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 *****/
2021-06-24 20:32:25 +02:00
if ( Grp_DB_GetDataOfGroupByCod ( & mysql_res , GrpDat - > GrpCod ) = = 1 )
2016-12-28 02:40:15 +01:00
{
/***** 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 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
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 )
2021-04-26 15:27:27 +02:00
Err_WrongCourseExit ( ) ;
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]) */
2021-02-15 16:25:55 +01:00
Str_Copy ( GrpDat - > GrpTypName , row [ 2 ] , sizeof ( GrpDat - > GrpTypName ) - 1 ) ;
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]) */
2021-02-15 16:25:55 +01:00
Str_Copy ( GrpDat - > GrpName , row [ 4 ] , sizeof ( GrpDat - > GrpName ) - 1 ) ;
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 ] ,
2021-02-15 16:25:55 +01:00
sizeof ( GrpDat - > Room . ShrtName ) - 1 ) ;
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
2021-06-17 13:26:25 +02:00
/* Get whether group is open or closed (row[8]),
and whether group has file zones ( row [ 9 ] ) */
GrpDat - > Open = ( row [ 8 ] [ 0 ] = = ' Y ' ) ;
2019-01-07 17:00:04 +01:00
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
}
/*****************************************************************************/
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 ;
2021-06-24 20:32:25 +02:00
Gbl . Cache . IBelongToGrp . IBelong = Grp_DB_CheckIfIBelongToGrp ( GrpCod ) ;
2017-06-20 14:43:26 +02:00
return Gbl . Cache . IBelongToGrp . IBelong ;
}
/*****************************************************************************/
2021-06-25 20:05:58 +02:00
/***** Check if a user belongs to any of my groups in the current course *****/
2017-06-20 14:43:26 +02:00
/*****************************************************************************/
void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( void )
{
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod = - 1L ;
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = false ;
}
2022-09-24 18:30:26 +02:00
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs ( const struct Usr_Data * UsrDat )
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? *****/
2021-11-18 22:06:06 +01:00
if ( Usr_ItsMe ( UsrDat - > UsrCod ) )
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? *****/
2021-11-03 21:31:16 +01:00
if ( ! Enr_CheckIfUsrBelongsToCurrentCrs ( UsrDat ) )
2017-06-20 14:43:26 +02:00
{
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 ;
2021-06-25 20:05:58 +02:00
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = Grp_DB_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs ( UsrDat - > UsrCod ) ;
2017-06-20 14:43:26 +02:00
return Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****** Query list of group codes of a type to which a user belongs to *******/
/*****************************************************************************/
// If GrpTypCod < 0 ==> get the groups of any type
2021-06-25 20:05:58 +02:00
static void Grp_GetLstCodGrpsUsrBelongs ( long UsrCod , long GrpTypCod ,
struct ListCodGrps * LstGrps )
2014-12-01 23:55:08 +01:00
{
MYSQL_RES * mysql_res ;
unsigned NumGrp ;
/***** Get groups which a user belong to from database *****/
2021-06-25 20:05:58 +02:00
if ( GrpTypCod < 0 ) // Query the groups of any type in the current course
LstGrps - > NumGrps = Grp_DB_GetLstCodGrpsOfAnyTypeInCurrentCrsUsrBelongs ( & mysql_res , UsrCod ) ;
else // Query only the groups of specified type in the current course
LstGrps - > NumGrps = Grp_DB_GetLstCodGrpsOfATypeInCurrentCrsUsrBelongs ( & mysql_res , UsrCod , GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups the user belongs to *****/
2021-02-15 16:25:55 +01:00
if ( ( LstGrps - > GrpCods = calloc ( LstGrps - > NumGrps ,
sizeof ( * LstGrps - > GrpCods ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
/* Get the code of group (row[0]) */
2021-04-25 13:24:39 +02:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = DB_GetNextCode ( mysql_res ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** 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 ;
unsigned NumGrp ;
2021-06-25 20:05:58 +02:00
/***** Get groups with file zones which I belong to from database *****/
LstGrps - > NumGrps = Grp_DB_GetLstCodGrpsWithFileZonesInCurrentCrsIBelong ( & mysql_res ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups I belong to *****/
2021-02-15 16:25:55 +01:00
if ( ( LstGrps - > GrpCods = calloc ( LstGrps - > NumGrps ,
sizeof ( * LstGrps - > GrpCods ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
2021-04-04 20:12:31 +02:00
/* Get the code of group */
2021-04-25 13:24:39 +02:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = DB_GetNextCode ( mysql_res ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
}
/***** 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 ;
2021-06-25 20:05:58 +02:00
2014-12-01 23:55:08 +01:00
return false ;
}
/*****************************************************************************/
/********** Query names of groups of a type which user belongs to ************/
/*****************************************************************************/
2021-06-25 20:05:58 +02:00
void Grp_GetNamesGrpsUsrBelongsTo ( long UsrCod , long GrpTypCod , char * GroupNames )
2014-12-01 23:55:08 +01:00
{
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2021-04-16 13:51:12 +02:00
unsigned NumGrps ;
unsigned NumGrp ;
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 *****/
2021-06-25 20:05:58 +02:00
NumGrps = Grp_DB_GetNamesGrpsUsrBelongsTo ( & mysql_res , UsrCod , GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
GroupNames [ 0 ] = ' \0 ' ;
2021-04-16 13:51:12 +02:00
for ( NumGrp = 0 ;
NumGrp < NumGrps ;
NumGrp + + )
2014-12-01 23:55:08 +01:00
{
/* Get next group */
row = mysql_fetch_row ( mysql_res ) ;
2021-04-16 13:51:12 +02:00
/* Group name is in row[0] */
if ( NumGrp )
2021-02-15 16:25:55 +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 ;
2022-06-18 19:50:40 +02:00
extern const char * Txt_You_must_specify_the_name ;
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
2021-06-28 12:54:09 +02:00
/* Get whether it is mandatory to regisrer in any group of this type
and whether it is possible to register in multiple groups of this type */
2019-04-04 10:45:15 +02:00
Gbl . Crs . Grps . GrpTyp . MandatoryEnrolment = Par_GetParToBool ( " MandatoryEnrolment " ) ;
2021-06-28 12:54:09 +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... *****/
2021-06-17 19:39:08 +02:00
if ( Grp_DB_CheckIfGrpTypNameExistsInCurrentCrs ( 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 ) ,
2021-02-15 16:25:55 +01: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
{
2021-06-17 13:26:25 +02:00
Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_DB_CreateGroupType ( & Gbl . Crs . Grps . GrpTyp ) ;
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 ;
2022-06-18 19:50:40 +02:00
Str_Copy ( AlertTxt , Txt_You_must_specify_the_name ,
2019-03-09 20:12:44 +01:00
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 ;
2022-06-18 19:50:40 +02:00
extern const char * Txt_You_must_specify_the_name ;
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... *****/
2021-06-17 19:39:08 +02:00
if ( Grp_DB_CheckIfGrpNameExistsForGrpTyp ( 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
{
2021-06-17 19:39:08 +02:00
Grp_DB_CreateGroup ( & Gbl . Crs . Grps ) ;
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 ;
2022-06-18 19:50:40 +02:00
Str_Copy ( AlertTxt , Txt_You_must_specify_the_name ,
2019-03-09 20:12:44 +01:00
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
}
/*****************************************************************************/
/********************* Request removing of a group type **********************/
/*****************************************************************************/
void Grp_ReqRemGroupType ( void )
{
unsigned NumGrps ;
/***** Get the code of the group type *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Check if this group type has groups *****/
2021-06-17 13:26:25 +02:00
if ( ( NumGrps = Grp_DB_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 *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** 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
2021-03-02 00:54:26 +01:00
/***** Begin section to edit group types *****/
2017-04-29 02:20:34 +02:00
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-10-13 22:34:31 +02:00
Grp_PutParamGrpTypCod , & 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-10-13 22:34:31 +02:00
Grp_PutParamGrpTypCod , & 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
}
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 *****/
2021-06-17 13:26:25 +02:00
NumStds = Grp_DB_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-10-13 22:34:31 +02:00
Grp_PutParamGrpCod , & 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-10-13 22:34:31 +02:00
Grp_PutParamGrpCod , & 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-10-13 22:34:31 +02:00
Grp_PutParamGrpCod , & 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
}
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 *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Remove group type and its groups *****/
Grp_RemoveGroupTypeCompletely ( ) ;
}
/*****************************************************************************/
/******************************* Remove a group ******************************/
/*****************************************************************************/
void Grp_RemoveGroup ( void )
{
/***** Get param with group code *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** 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
2021-10-30 13:28:48 +02:00
/***** Remove file zones of all 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 *****/
2021-05-11 18:22:00 +02:00
Asg_DB_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 *****/
2021-05-13 12:50:36 +02:00
Att_DB_RemoveGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
2021-07-20 13:14:12 +02:00
/***** Remove the associations of exam sessions to groups of this type *****/
2021-09-09 11:11:08 +02:00
Exa_DB_RemoveAllGrpsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2021-07-20 13:14:12 +02:00
2019-09-27 20:22:32 +02:00
/***** Remove the associations of matches to groups of this type *****/
2021-07-20 13:14:12 +02:00
Mch_DB_RemoveGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2019-09-27 20:22:32 +02:00
2014-12-01 23:55:08 +01:00
/***** Remove the associations of surveys to groups of this type *****/
2021-07-20 13:14:12 +02:00
Svy_DB_RemoveGroupsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
2021-06-25 20:05:58 +02:00
/***** Orphan all groups of this type in course timetable *****/
Tmt_DB_OrphanAllGrpsOfATypeInCrsTimeTable ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
2021-06-28 14:49:50 +02:00
/***** Remove all users from groups of this type *****/
Grp_DB_RemoveUsrsFromGrpsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
2021-10-30 13:28:48 +02:00
/***** Remove all groups of this type *****/
2021-06-28 14:49:50 +02:00
Grp_DB_RemoveGrpsOfType ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove the group type *****/
2021-06-28 14:49:50 +02:00
Grp_DB_RemoveGrpType ( 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 *****/
2021-02-15 16:25:55 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) , 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 *****/
2021-05-11 18:22:00 +02:00
Asg_DB_RemoveGroup ( GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2019-09-27 20:22:32 +02:00
/***** Remove this group from all attendance events *****/
2021-05-13 12:50:36 +02:00
Att_DB_RemoveGroup ( GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2019-09-27 20:22:32 +02:00
/***** Remove this group from all matches *****/
2021-07-20 13:14:12 +02:00
Mch_DB_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Remove this group from all exam sessions *****/
2021-09-24 21:49:06 +02:00
Exa_DB_RemoveGroup ( GrpDat . GrpCod ) ;
2019-09-27 20:22:32 +02:00
/***** Remove this group from all surveys *****/
2021-07-20 13:14:12 +02:00
Svy_DB_RemoveGroup ( GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2021-06-28 14:49:50 +02:00
/***** Orphan this group in course timetable *****/
Tmt_DB_OrphanGrpInCrsTimeTable ( GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2021-06-28 14:49:50 +02:00
/***** Remove all users in this group *****/
Grp_DB_RemoveUsrsFromGrp ( GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove the group *****/
2021-06-28 14:49:50 +02:00
Grp_DB_RemoveGrp ( GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2021-02-15 16:25:55 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) , Txt_Group_X_removed ,
2018-10-16 21:56:01 +02:00
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 *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** 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 *****/
2021-06-28 14:49:50 +02:00
Grp_DB_OpenGrp ( GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2021-02-15 16:25:55 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) , Txt_The_group_X_is_now_open ,
2018-10-16 21:56:01 +02:00
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 *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** 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 *****/
2021-06-28 14:49:50 +02:00
Grp_DB_CloseGrp ( 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 *****/
2021-02-15 16:25:55 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) , Txt_The_group_X_is_now_closed ,
2018-10-16 21:56:01 +02:00
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 *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** 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 *****/
2021-06-28 14:49:50 +02:00
Grp_DB_EnableFileZonesGrp ( 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 ) ,
2021-02-15 16:25:55 +01:00
Txt_File_zones_of_the_group_X_are_now_enabled ,
2018-10-16 21:56:01 +02:00
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 *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** 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 *****/
2021-06-28 14:49:50 +02:00
Grp_DB_DisableFileZonesGrp ( GrpDat . 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 */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/* 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... *****/
2021-06-17 19:39:08 +02:00
if ( Grp_DB_CheckIfGrpNameExistsForGrpTyp ( NewGrpTypCod , GrpDat . GrpName , - 1L ) )
2014-12-01 23:55:08 +01:00
{
2018-10-16 21:56:01 +02:00
/* Create warning message */
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2021-02-15 16:25:55 +01:00
snprintf ( AlertTxt , sizeof ( AlertTxt ) , Txt_The_group_X_already_exists ,
2018-10-16 21:56:01 +02:00
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 */
2021-06-28 14:49:50 +02:00
Grp_DB_ChangeGrpTypOfGrp ( GrpDat . GrpCod , NewGrpTypCod ) ;
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 */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2019-01-04 22:46:46 +01:00
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 *****/
2021-06-29 11:07:08 +02:00
Grp_DB_ChangeRoomOfGrp ( Gbl . Crs . Grps . GrpCod , NewRooCod ) ;
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 */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
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
{
2021-06-29 11:07:08 +02:00
/***** Update of the table of types of group
changing the old type of enrolment by the new * * * * */
Grp_DB_ChangeMandatoryEnrolmentOfAGrpTyp ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ,
NewMandatoryEnrolment ) ;
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 */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
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 *****/
2021-06-29 11:07:08 +02:00
Grp_DB_ChangeMultipleEnrolmentOfAGrpTyp ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ,
NewMultipleEnrolment ) ;
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 *****/
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** 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
2021-06-29 11:07:08 +02:00
changing the old opening time of enrolment by the new * * * * */
Grp_DB_ChangeOpeningTimeOfAGrpTyp ( Gbl . Crs . Grps . GrpTyp . GrpTypCod ,
Gbl . Crs . Grps . GrpTyp . MustBeOpened ,
Gbl . Crs . Grps . GrpTyp . OpenTimeUTC ) ;
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 */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/* 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 *****/
2021-06-29 11:07:08 +02:00
Grp_DB_ChangeMaxStdsOfGrp ( Gbl . Crs . Grps . GrpCod , NewMaxStds ) ;
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 )
2021-02-15 16:25:55 +01:00
snprintf ( Str , Cns_MAX_DECIMAL_DIGITS_UINT + 1 , " %u " , MaxStudents ) ;
2019-11-03 23:59:20 +01:00
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 ;
2022-05-12 22:16:39 +02:00
extern const char * Txt_The_name_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 */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGrpTypExit ( ) ;
2014-12-01 23:55:08 +01:00
/* 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... *****/
2021-06-17 19:39:08 +02:00
if ( Grp_DB_CheckIfGrpTypNameExistsInCurrentCrs ( 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 ) ,
2021-02-15 16:25:55 +01:00
Txt_The_type_of_group_X_already_exists , NewNameGrpTyp ) ;
2014-12-01 23:55:08 +01:00
}
else
{
2021-06-18 18:59:36 +02:00
/***** Update the table changing old name by new name *****/
Grp_DB_RenameGrpTyp ( Gbl . Crs . Grps . GrpTyp . GrpTypCod , NewNameGrpTyp ) ;
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 ) ,
2022-05-12 22:16:39 +02:00
Txt_The_name_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 ,
2021-02-15 16:25:55 +01:00
sizeof ( Gbl . Crs . Grps . GrpTyp . GrpTypName ) - 1 ) ;
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 ;
2022-05-12 22:16:39 +02:00
extern const char * Txt_The_name_X_has_not_changed ;
2014-12-01 23:55:08 +01:00
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 */
2021-04-25 13:24:39 +02:00
if ( ( Gbl . Crs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) < = 0 )
2021-04-26 15:27:27 +02:00
Err_WrongGroupExit ( ) ;
2014-12-01 23:55:08 +01:00
/* 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... *****/
2021-06-17 19:39:08 +02:00
if ( Grp_DB_CheckIfGrpNameExistsForGrpTyp ( 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 ) ,
2021-02-15 16:25:55 +01:00
Txt_The_group_X_already_exists , NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
else
{
2021-06-18 18:59:36 +02:00
/***** Update the table changing old name by new name *****/
Grp_DB_RenameGrp ( Gbl . Crs . Grps . GrpCod , NewNameGrp ) ;
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 ) ,
2022-05-12 22:16:39 +02:00
Txt_The_name_X_has_not_changed , NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
}
/***** Show the form again *****/
2021-02-15 16:25:55 +01:00
Str_Copy ( Gbl . Crs . Grps . GrpName , NewNameGrp , sizeof ( Gbl . Crs . Grps . GrpName ) - 1 ) ;
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 ******************/
/*****************************************************************************/
2020-10-13 22:34:31 +02:00
static void Grp_PutParamGrpTypCod ( void * GrpTypCod )
2014-12-01 23:55:08 +01:00
{
2020-10-13 22:34:31 +02:00
if ( GrpTypCod )
Par_PutHiddenParamLong ( NULL , " GrpTypCod " , * ( ( long * ) GrpTypCod ) ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Write parameter with code of group ********************/
/*****************************************************************************/
2020-10-13 22:34:31 +02:00
void Grp_PutParamGrpCod ( void * GrpCod )
2014-12-01 23:55:08 +01:00
{
2020-10-13 22:34:31 +02:00
if ( GrpCod )
Par_PutHiddenParamLong ( NULL , " GrpCod " , * ( ( long * ) 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 *****/
2021-06-28 12:54:09 +02:00
if ( ( LstStrCodGrps = calloc ( Gbl . Crs . Grps . GrpTypes . NumGrpTypes ,
2021-02-15 16:25:55 +01:00
sizeof ( * LstStrCodGrps ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_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 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
2014-12-01 23:55:08 +01:00
NumGrpTyp + + )
{
/***** Allocate memory for the list of group codes of this type *****/
2021-02-15 16:25:55 +01:00
if ( ( LstStrCodGrps [ NumGrpTyp ] = malloc ( Gbl . Crs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps *
( Cns_MAX_DECIMAL_DIGITS_LONG + 1 ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get the multiple parameter code of group of this type *****/
2021-02-15 16:25:55 +01: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)
2021-10-30 13:28:48 +02:00
with all groups selected ( of all the types ) * * * * */
2014-12-01 23:55:08 +01:00
if ( LstGrpsWanted - > NumGrps )
{
2021-02-15 16:25:55 +01:00
if ( ( LstGrpsWanted - > GrpCods = calloc ( LstGrpsWanted - > NumGrps ,
sizeof ( * LstGrpsWanted - > GrpCods ) ) ) = = NULL )
2021-04-26 15:27:27 +02:00
Err_NotEnoughMemoryExit ( ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
for ( NumGrpTyp = 0 , NumGrpWanted = 0 ;
2021-06-28 12:54:09 +02:00
NumGrpTyp < Gbl . Crs . Grps . GrpTypes . NumGrpTypes ;
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-11-26 00:28:21 +01:00
Par_PutHiddenParamUnsigned ( NULL , " WhichGrps " ,
( 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 ;
2021-07-08 15:00:17 +02:00
/***** Begin setting selector *****/
2021-03-02 16:47:58 +01:00
Set_BeginOneSettingSelector ( ) ;
2019-09-29 17:33:39 +02:00
2021-07-08 15:00:17 +02:00
/***** Put icons to select which groups *****/
for ( WhichGrps = Grp_MY_GROUPS ;
WhichGrps < = Grp_ALL_GROUPS ;
WhichGrps + + )
{
2022-04-25 19:45:05 +02:00
Set_BeginPref ( WhichGrps = = Gbl . Crs . Grps . WhichGrps ) ;
Frm_BeginForm ( 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 " ,
Ico_BLACK , Txt_GROUP_WHICH_GROUPS [ WhichGrps ] ) ;
Frm_EndForm ( ) ;
Set_EndPref ( ) ;
2021-07-08 15:00:17 +02: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
2020-05-15 01:07:46 +02:00
case ActSeeAllExa : // List exams
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
}
2021-05-27 00:30:06 +02:00
/*****************************************************************************/
/************************** Remove groups in a course ************************/
/*****************************************************************************/
void Grp_DB_RemoveCrsGrps ( long CrsCod )
{
2021-06-18 18:59:36 +02:00
/***** Remove all users in groups in the course *****/
2021-06-28 14:49:50 +02:00
Grp_DB_RemoveUsrsFromGrpsOfCrs ( CrsCod ) ;
2021-05-27 00:30:06 +02:00
2021-06-18 18:59:36 +02:00
/***** Remove all groups in the course *****/
Grp_DB_RemoveGrpsInCrs ( CrsCod ) ;
2021-05-27 00:30:06 +02:00
2021-06-18 18:59:36 +02:00
/***** Remove all group types in the course *****/
Grp_DB_RemoveGrpTypesInCrs ( CrsCod ) ;
2021-05-27 00:30:06 +02:00
}